Skip to content

Commit

Permalink
Tags (#13)
Browse files Browse the repository at this point in the history
* prefer function to const

* adding create tag and tag list

* using lucide icons vs feather

* more tests

* fix build
  • Loading branch information
Charlie ⚡️ committed Oct 18, 2022
1 parent 8fb639c commit dc72df1
Show file tree
Hide file tree
Showing 57 changed files with 938 additions and 446 deletions.
1 change: 1 addition & 0 deletions apps/graphql/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ model User {
updatedAt DateTime @updatedAt @map("updated_at")
feeds Feed[]
tags Tag[]
refreshInterval Int @default(60) @map("refresh_interval")
@@map("users")
}
11 changes: 11 additions & 0 deletions apps/graphql/src/__generated__.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export type Mutation = {
markAsRead: Entry;
refreshFeed: Array<Entry>;
removeFeed: Feed;
removeTag: Tag;
updateFeed: Feed;
};

Expand Down Expand Up @@ -92,6 +93,10 @@ export type MutationRemoveFeedArgs = {
id: Scalars["ID"];
};

export type MutationRemoveTagArgs = {
id: Scalars["ID"];
};

export type MutationUpdateFeedArgs = {
fields?: InputMaybe<UpdateFeedInput>;
id: Scalars["ID"];
Expand Down Expand Up @@ -329,6 +334,12 @@ export type MutationResolvers<
ContextType,
RequireFields<MutationRemoveFeedArgs, "id">
>;
removeTag?: Resolver<
ResolversTypes["Tag"],
ParentType,
ContextType,
RequireFields<MutationRemoveTagArgs, "id">
>;
updateFeed?: Resolver<
ResolversTypes["Feed"],
ParentType,
Expand Down
8 changes: 3 additions & 5 deletions apps/graphql/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Fastify from "fastify";
import mercurius, { type MercuriusOptions } from "mercurius";
import mercurius from "mercurius";
import { schema } from "./schema";
import { context } from "./context";
import { RecommendedKeyArray } from "./recommendations";
Expand All @@ -13,13 +13,11 @@ export const createApp = () => {
});
});

const options: MercuriusOptions = {
app.register(mercurius, {
schema,
graphiql: true,
context: () => context,
};

app.register(mercurius, options);
});

return app;
};
48 changes: 29 additions & 19 deletions apps/graphql/src/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { Feed } from "@prisma/client";
/**
* TODO:
* - recently read
* - tags
* - me
**/
const query: QueryResolvers<Context> = {
Expand Down Expand Up @@ -77,7 +76,6 @@ const query: QueryResolvers<Context> = {

/**
* TODO:
* - create, read, update, delete tags
* - login
* - register user
**/
Expand All @@ -104,6 +102,22 @@ const mutation: MutationResolvers<Context> = {
throw new Error(err);
}
},
async addTag(_parent, { name }, { prisma }) {
try {
const tag = await prisma.tag.create({
data: {
title: name,
},
});

return {
id: tag.id,
title: tag.title,
};
} catch (error: any) {
throw new Error(error);
}
},
async removeFeed(_parent, { id }, { prisma }) {
await prisma.entry.deleteMany({
where: {
Expand All @@ -117,6 +131,19 @@ const mutation: MutationResolvers<Context> = {
});
return feed;
},

async removeTag(_parent, { id }, { prisma }) {
const tag = await prisma.tag.delete({
where: {
id,
},
});

return {
id: tag.id,
title: tag.title,
};
},
async refreshFeed(_parent, { id }, { prisma, rss }) {
const feed = await prisma.feed.findUnique({
where: {
Expand Down Expand Up @@ -226,23 +253,6 @@ const mutation: MutationResolvers<Context> = {
throw new Error(error);
}
},

async addTag(_parent, { name }, { prisma }) {
try {
const tag = await prisma.tag.create({
data: {
title: name,
},
});

return {
id: tag.id,
title: tag.title,
};
} catch (error: any) {
throw new Error(error);
}
},
};

export const resolvers: Resolvers<Context> = {
Expand Down
1 change: 1 addition & 0 deletions apps/graphql/src/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type Mutation {
addFeed(url: String!): Feed!
addTag(name: String!): Tag!
removeFeed(id: ID!): Feed!
removeTag(id: ID!): Tag!
refreshFeed(id: ID!): [Entry!]!
markAsFavorite(id: ID!, favorite: Boolean!): Entry!
markAsRead(id: ID!): Entry!
Expand Down
2 changes: 1 addition & 1 deletion apps/graphql/test/errors.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SDKError } from "../src/errors";

describe("Errors", () => {
it("error contains message", () => {
test("error contains message", () => {
const error = new SDKError("Service unavailable", 503);
expect(error).toBeInstanceOf(SDKError);
expect(error.name).toBe("SDKError");
Expand Down
2 changes: 1 addition & 1 deletion apps/graphql/test/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { createMercuriusTestClient } from "mercurius-integration-testing";
describe("Integration", () => {
const client = createMercuriusTestClient(createApp());

it("can create feeds", async () => {
test("can create feeds", async () => {
const createFeed = await client.query(
gql`
mutation CreateFeed($url: String!) {
Expand Down
4 changes: 2 additions & 2 deletions apps/graphql/test/rss.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ export const getFixtureAsString = async (filePath: string) => {
const parser = new RSSKit();

describe("RSS", () => {
it("can parse a string", async () => {
test("can parse a string", async () => {
const feed = await getFixtureAsString("guardian.rss");
const output = await parser.parse(feed);

expect(output.title).toBe("The Guardian");
expect(output.items.length).toEqual(90);
});

it("can parse a podcast RSS feed", async () => {
test("can parse a podcast RSS feed", async () => {
const feed = await getFixtureAsString("serial.rss");
const output = await parser.parse(feed);
expect(output.title).toBe("Serial");
Expand Down
9 changes: 4 additions & 5 deletions apps/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,24 @@
"build": "next build",
"start": "next start",
"test": "jest --verbose",
"test:ci": "jest --verbose --ci --runInBand --no-cache",
"types": "tsc --noEmit --pretty"
},
"dependencies": {
"@headlessui/react": "^1.7.2",
"@headlessui/react": "^1.7.3",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/typography": "^0.5.7",
"autoprefixer": "^10.4.7",
"date-fns": "^2.29.2",
"autoprefixer": "^10.4.12",
"date-fns": "^2.29.3",
"fathom-client": "^3.5.0",
"graphql-request": "^5.0.0",
"graphql-tag": "^2.12.6",
"lucide-react": "^0.91.0",
"next": "^12.3.1",
"postcss": "^8.4.14",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-fast-compare": "^3.2.0",
"react-icons": "^4.4.0",
"sharp": "^0.31.0",
"swr": "^1.3.0",
"tailwindcss": "^3.1.8",
Expand Down
45 changes: 22 additions & 23 deletions apps/ui/src/components/add-feed.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useCallback, useState } from "react";
import { FiPlus } from "react-icons/fi";
import { Plus } from "lucide-react";

import { addFeed } from "../lib/graphql";

Expand All @@ -12,7 +12,7 @@ interface AddFeedFormProps {
onSelect?(selectedFeed: unknown): void | Promise<void>;
}

export const AddFeedForm = (props: AddFeedFormProps) => {
export function AddFeedForm(props: AddFeedFormProps) {
const [url, setUrl] = useState("");

const handleSubmit: React.FormEventHandler = useCallback(
Expand All @@ -38,28 +38,27 @@ export const AddFeedForm = (props: AddFeedFormProps) => {
);

return (
<div>
<form onSubmit={handleSubmit}>
<Label htmlFor="url">
<Input
name="url"
id="url"
data-testid="add-feed-url"
value={url}
onChange={handleChange}
/>
<TextLabel>URL</TextLabel>
</Label>
<form onSubmit={handleSubmit}>
<Label htmlFor="url">
<TextLabel>URL</TextLabel>

<div className="mt-8 flex justify-end">
<SuperButton type="submit">Submit</SuperButton>
</div>
</form>
</div>
<Input
name="url"
id="url"
data-testid="add-feed-url"
value={url}
onChange={handleChange}
/>
</Label>

<div className="mt-8 flex justify-end">
<SuperButton type="submit">Submit</SuperButton>
</div>
</form>
);
};
}

export const AddFeed = () => {
export function AddFeed() {
const [isOpen, setOpen] = useState(false);
const handleSubmit = useCallback((url: string) => {
addFeed(url);
Expand All @@ -68,7 +67,7 @@ export const AddFeed = () => {
return (
<>
<Button onClick={() => setOpen(true)} aria-label="Add Feed" className="block">
<FiPlus size={24} />
<Plus size={24} />
</Button>
<Dialog isOpen={isOpen} onClose={() => setOpen(false)} title="Add Feed">
<div className="mt-2 mb-8 text-sm opacity-50">
Expand All @@ -78,4 +77,4 @@ export const AddFeed = () => {
</Dialog>
</>
);
};
}
4 changes: 2 additions & 2 deletions apps/ui/src/components/app-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ interface AppHeaderProps {
children?: React.ReactNode;
}

export const AppHeader = (props: AppHeaderProps) => {
export function AppHeader(props: AppHeaderProps) {
return (
<header className="w-full border-b border-zinc-200 px-4 dark:border-zinc-700">
<div className="flex items-center justify-between">
Expand All @@ -24,4 +24,4 @@ export const AppHeader = (props: AppHeaderProps) => {
`}</style>
</header>
);
};
}
Loading

1 comment on commit dc72df1

@vercel
Copy link

@vercel vercel bot commented on dc72df1 Oct 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.