From ec3e08ceddefdc28ae1f261f2b867fe5d8adb18e Mon Sep 17 00:00:00 2001 From: dawn Date: Fri, 11 Sep 2026 02:06:55 +0300 Subject: [PATCH] web: create custom labels from repo settings Signed-off-by: dawn --- web/src/lib/api/labels.ts | 40 ++++- .../[repo]/settings/labels/new/+page.svelte | 154 ++++++++++-------- .../[repo]/settings/labels/new/+page.ts | 6 + 3 files changed, 133 insertions(+), 67 deletions(-) create mode 100644 web/src/routes/[handle]/[repo]/settings/labels/new/+page.ts diff --git a/web/src/lib/api/labels.ts b/web/src/lib/api/labels.ts index 508d2f52f..cdcd16241 100644 --- a/web/src/lib/api/labels.ts +++ b/web/src/lib/api/labels.ts @@ -1,10 +1,17 @@ -import type { ResourceUri } from "@atcute/lexicons/syntax"; +import type { Nsid, ResourceUri } from "@atcute/lexicons/syntax"; +import { now as tidNow } from "@atcute/tid"; +import type { OAuthUserAgent } from "@atcute/oauth-browser-client"; import type { BobbinContext, XrpcRequestInit } from "$lib/api/client"; import type * as ShTangledLabelDefinition from "$lib/api/lexicons/types/sh/tangled/label/definition"; import { collect } from "$lib/api/pagination"; +import { createRecord, deleteRecord, type WrittenRecord } from "$lib/api/write"; export type LabelDefinition = ShTangledLabelDefinition.Main; +const LABEL_DEFINITION_COLLECTION = "sh.tangled.label.definition" as Nsid; +const ISSUE_SCOPE = "sh.tangled.repo.issue" as Nsid; +const PULL_SCOPE = "sh.tangled.repo.pull" as Nsid; + export const DEFAULT_LABEL_OWNER = "did:plc:wshs7t2adsemcrrd4snkeqli"; export const DEFAULT_LABELS = [ `at://${DEFAULT_LABEL_OWNER}/sh.tangled.label.definition/wontfix`, @@ -34,3 +41,34 @@ export const listLabelDefinitions = async ( }; export const isBasicLabel = (label: LabelDefinition): boolean => label.valueType.type === "null"; + +export interface CustomLabelInput { + name: string; + color: string; + issues: boolean; + pulls: boolean; + keyValue: boolean; +} + +export const createLabelDefinition = ( + agent: OAuthUserAgent, + input: CustomLabelInput +): Promise => + createRecord( + agent, + LABEL_DEFINITION_COLLECTION, + { + $type: "sh.tangled.label.definition", + name: input.name, + color: input.color, + scope: [...(input.issues ? [ISSUE_SCOPE] : []), ...(input.pulls ? [PULL_SCOPE] : [])], + valueType: input.keyValue + ? { type: "string", format: "any" } + : { type: "null", format: "any" }, + createdAt: new Date().toISOString() as never + }, + tidNow() + ); + +export const deleteLabelDefinition = (agent: OAuthUserAgent, uri: string): Promise => + deleteRecord(agent, LABEL_DEFINITION_COLLECTION, uri.slice(uri.lastIndexOf("/") + 1)); diff --git a/web/src/routes/[handle]/[repo]/settings/labels/new/+page.svelte b/web/src/routes/[handle]/[repo]/settings/labels/new/+page.svelte index 863bc8e23..5b7ae7ddf 100644 --- a/web/src/routes/[handle]/[repo]/settings/labels/new/+page.svelte +++ b/web/src/routes/[handle]/[repo]/settings/labels/new/+page.svelte @@ -1,13 +1,15 @@ - - {#snippet skeleton()} - - {/snippet} - - {@const repo = await data.repo} - {@const back = `/${repo.ownerHandle}/${repo.name}/settings`} - - - -
- Basic - Key-value -
-
+ + + + + +
+ Basic + Key-value +
+
- - - + + + - -
- Issues - Pull requests -
-
+ +
+ Issues + Pull requests +
+
- -
- {#each COLORS as swatch (swatch)} - - {/each} -
-
-
+ +
+ {#each COLORS as swatch (swatch)} + + {/each} +
+
+
- - - - -
-
+ + + + + diff --git a/web/src/routes/[handle]/[repo]/settings/labels/new/+page.ts b/web/src/routes/[handle]/[repo]/settings/labels/new/+page.ts new file mode 100644 index 000000000..a308e5542 --- /dev/null +++ b/web/src/routes/[handle]/[repo]/settings/labels/new/+page.ts @@ -0,0 +1,6 @@ +import { requireRepoAdmin } from "$lib/api/access"; +import type { PageLoad } from "./$types"; + +export const load: PageLoad = async (event) => { + requireRepoAdmin((await event.parent()).access); +}; -- 2.51.2