Skip to content

g1t/apps/web/app/routes/repo/notifications.ts

40 lines2,196 bytesCodeBlame
1/**
2 * What a person hears of from one repository: subscribing to one of its
3 * issues or pull requests (`intent` subscribe, unsubscribe, ignore or
4 * default, with its `number`), and watching it (`intent` watch, with
5 * `level` and, for custom, the `event` kinds). Posted by the sidebar's
6 * Notifications box and the header's Watch menu (components/notifications.tsx).
7 * Only someone who can read the repository may choose.
8 */
9import { data } from "react-router";
10
11import type { Route } from "./+types/notifications";
12import { subscriptionFromForm, watchFromForm } from "../../lib/inbox";
13import { inbox, repos } from "../../lib/services.server";
14import { assertSameOrigin, requireUser } from "../../lib/session.server";
15
16export async function action({ request, params, context }: Route.ActionArgs) {
17 assertSameOrigin(request);
18 const user = requireUser(context, request);
19 const form = await request.formData();
20 const repo = await repos.get({ namespace: params.owner, name: params.repo }, user);
21 if (!repo.ok) return data({ error: "That repository could not be found." }, { status: 404 });
22 const path = `${repo.value.namespace}/${repo.value.name}`;
23 try {
24 if (form.get("intent") === "watch") {
25 const watch = watchFromForm(form);
26 if (!watch) return data({ error: "Choose how to watch it." }, { status: 400 });
27 // Participating is the default: no choice to keep.
28 const level = watch.level === "participating" ? null : watch.level;
29 return { error: null, watching: await inbox.watch(user.username, repo.value.id, path, level, watch.events) };
30 }
31 const choice = subscriptionFromForm(form);
32 const number = Number(form.get("number"));
33 if (!choice || !Number.isInteger(number) || number < 1) return data({ error: "Nothing to do." }, { status: 400 });
34 const subscription = await inbox.subscribe(user, { repoId: repo.value.id, number }, choice.subscribed, choice.ignored);
35 if (!subscription) return data({ error: "That issue or pull request could not be found." }, { status: 404 });
36 return { error: null, subscription };
37 } catch {
38 return data({ error: "That did not save. Try again in a moment." }, { status: 503 });
39 }
40}