Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

36 linesCodeBlameRaw
1// The forms of the workspace's milestones pages, under Work: create, edit,
2// close or reopen, delete. Each needs the Write role in the workspace,
3// which work checks again.
4
5import { needs } from "@g1t/contracts";
6
7import type { MilestoneResult } from "../components/milestones";
8import { work } from "./services.server";
9import { assertSameOrigin, requireUser } from "./session.server";
10import { canItem } from "./work-access";
11
12type Context = Parameters<typeof requireUser>[0];
13
14export async function milestoneAction(request: Request, params: { owner?: string }, context: Context): Promise<MilestoneResult> {
15 assertSameOrigin(request);
16 const user = requireUser(context, request);
17 const form = await request.formData();
18 const intent = String(form.get("intent") ?? "");
19 const number = Number(form.get("number")) || undefined;
20 const workspace = (params.owner ?? "").toLowerCase();
21 if (!canItem(user, workspace, null, "manage_labels")) return { intent, number, error: needs("manage_labels") };
22 const text = (key: string) => (form.has(key) ? String(form.get(key) ?? "") : undefined);
23 if (intent === "delete") {
24 const deleted = await work.deleteMilestone(user, workspace, number ?? 0);
25 return deleted.ok ? { intent, number } : { intent, number, error: deleted.error.message };
26 }
27 const state = form.get("state");
28 const saved = await work.saveMilestone(user, workspace, {
29 number: intent === "create" ? undefined : number,
30 title: text("title"),
31 description: text("description"),
32 dueOn: text("dueOn"),
33 state: state === "open" || state === "closed" ? state : undefined,
34 });
35 return saved.ok ? { intent, number: saved.value.number } : { intent, number, error: saved.error.message };
36}