@skillcdn/console 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/api.d.ts +4 -4
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +4 -4
- package/dist/api.js.map +1 -1
- package/dist/cli/cli.d.ts +5 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +290 -46
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/credentials.d.ts +5 -0
- package/dist/cli/credentials.d.ts.map +1 -1
- package/dist/cli/credentials.js +2 -0
- package/dist/cli/credentials.js.map +1 -1
- package/dist/cli/directory.d.ts +7 -0
- package/dist/cli/directory.d.ts.map +1 -1
- package/dist/cli/directory.js +7 -0
- package/dist/cli/directory.js.map +1 -1
- package/dist/cli/format.d.ts +10 -1
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +76 -20
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +42 -23
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.js +1 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/client.d.ts +39 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +24 -3
- package/dist/client.js.map +1 -1
- package/dist/compat.d.ts +28 -6
- package/dist/compat.d.ts.map +1 -1
- package/dist/compat.js +55 -14
- package/dist/compat.js.map +1 -1
- package/dist/components/board.d.ts.map +1 -1
- package/dist/components/board.js +6 -4
- package/dist/components/board.js.map +1 -1
- package/dist/components/calendar.d.ts +18 -8
- package/dist/components/calendar.d.ts.map +1 -1
- package/dist/components/calendar.js +39 -27
- package/dist/components/calendar.js.map +1 -1
- package/dist/components/event-feed.d.ts.map +1 -1
- package/dist/components/event-feed.js +2 -0
- package/dist/components/event-feed.js.map +1 -1
- package/dist/components/pack-connect.d.ts +23 -0
- package/dist/components/pack-connect.d.ts.map +1 -0
- package/dist/components/pack-connect.js +86 -0
- package/dist/components/pack-connect.js.map +1 -0
- package/dist/components/pack-token.d.ts +27 -0
- package/dist/components/pack-token.d.ts.map +1 -0
- package/dist/components/pack-token.js +11 -0
- package/dist/components/pack-token.js.map +1 -0
- package/dist/components/picker.d.ts +39 -0
- package/dist/components/picker.d.ts.map +1 -0
- package/dist/components/picker.js +155 -0
- package/dist/components/picker.js.map +1 -0
- package/dist/components/projects.d.ts +13 -0
- package/dist/components/projects.d.ts.map +1 -1
- package/dist/components/projects.js +37 -5
- package/dist/components/projects.js.map +1 -1
- package/dist/components/task-form.d.ts +18 -4
- package/dist/components/task-form.d.ts.map +1 -1
- package/dist/components/task-form.js +56 -13
- package/dist/components/task-form.js.map +1 -1
- package/dist/components/task-list.js +2 -2
- package/dist/components/task-list.js.map +1 -1
- package/dist/components/task-view.d.ts +7 -1
- package/dist/components/task-view.d.ts.map +1 -1
- package/dist/components/task-view.js +6 -5
- package/dist/components/task-view.js.map +1 -1
- package/dist/components/ui.d.ts +7 -0
- package/dist/components/ui.d.ts.map +1 -1
- package/dist/components/ui.js +11 -0
- package/dist/components/ui.js.map +1 -1
- package/dist/components/work.d.ts +3 -1
- package/dist/components/work.d.ts.map +1 -1
- package/dist/components/work.js +6 -4
- package/dist/components/work.js.map +1 -1
- package/dist/components/workspace.d.ts +46 -0
- package/dist/components/workspace.d.ts.map +1 -0
- package/dist/components/workspace.js +124 -0
- package/dist/components/workspace.js.map +1 -0
- package/dist/console.css +319 -11
- package/dist/console.d.ts.map +1 -1
- package/dist/console.js +83 -24
- package/dist/console.js.map +1 -1
- package/dist/data.d.ts +26 -1
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +59 -1
- package/dist/data.js.map +1 -1
- package/dist/dates.d.ts +12 -2
- package/dist/dates.d.ts.map +1 -1
- package/dist/dates.js +20 -2
- package/dist/dates.js.map +1 -1
- package/dist/i18n/en.d.ts +64 -3
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +81 -16
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/ko.d.ts.map +1 -1
- package/dist/i18n/ko.js +77 -16
- package/dist/i18n/ko.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/limits.d.ts +2 -0
- package/dist/limits.d.ts.map +1 -1
- package/dist/limits.js +2 -0
- package/dist/limits.js.map +1 -1
- package/dist/router.d.ts +4 -4
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +11 -2
- package/dist/router.js.map +1 -1
- package/dist/routes.d.ts +4 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +4 -0
- package/dist/routes.js.map +1 -1
- package/dist/schemas.d.ts +194 -13
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +121 -21
- package/dist/schemas.js.map +1 -1
- package/dist/vocabulary.d.ts +21 -1
- package/dist/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary.js +18 -0
- package/dist/vocabulary.js.map +1 -1
- package/docs/specs/cli.md +25 -20
- package/docs/specs/rest.md +42 -19
- package/package.json +2 -2
- package/skills/building-a-console/SKILL.md +6 -6
- package/skills/building-a-console/references/the-look-from-a-website.md +39 -0
- package/skills/deploying-a-console/SKILL.md +9 -8
- package/skills/deploying-a-console/references/resources.md +1 -1
- package/skills/working-the-board/SKILL.md +5 -5
- package/skills/working-the-board/references/setting-up.md +1 -1
- package/skills/working-the-board/references/terms.md +3 -1
- package/skills/working-the-board/references/the-sentence.md +1 -1
- package/src/api.ts +21 -0
- package/src/cli/cli.ts +384 -51
- package/src/cli/credentials.ts +7 -0
- package/src/cli/directory.ts +9 -0
- package/src/cli/format.ts +83 -20
- package/src/cli/help.ts +50 -23
- package/src/cli/main.ts +1 -0
- package/src/client.ts +107 -10
- package/src/compat.ts +63 -14
- package/src/components/board.tsx +10 -4
- package/src/components/calendar.tsx +76 -34
- package/src/components/event-feed.tsx +2 -0
- package/src/components/pack-connect.tsx +179 -0
- package/src/components/pack-token.tsx +74 -0
- package/src/components/picker.tsx +297 -0
- package/src/components/projects.tsx +108 -9
- package/src/components/task-form.tsx +149 -63
- package/src/components/task-list.tsx +2 -2
- package/src/components/task-view.tsx +23 -9
- package/src/components/ui.tsx +25 -0
- package/src/components/work.tsx +10 -5
- package/src/components/workspace.tsx +298 -0
- package/src/console.tsx +202 -32
- package/src/data.ts +101 -1
- package/src/dates.ts +23 -2
- package/src/i18n/en.ts +92 -16
- package/src/i18n/ko.ts +84 -16
- package/src/index.ts +32 -1
- package/src/limits.ts +2 -0
- package/src/router.ts +17 -5
- package/src/routes.ts +4 -0
- package/src/schemas.ts +140 -19
- package/src/styles/console.css +319 -11
- package/src/vocabulary.ts +28 -0
package/src/schemas.ts
CHANGED
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
MAX_TOKEN_DAYS,
|
|
40
40
|
MAX_TOKEN_NAME_LENGTH,
|
|
41
41
|
MAX_URL_LENGTH,
|
|
42
|
+
MAX_WORKERS,
|
|
42
43
|
MIN_OPTIONS,
|
|
43
44
|
} from "./limits.js";
|
|
44
45
|
import { hasForbiddenCodePoint } from "./text.js";
|
|
@@ -50,6 +51,8 @@ import {
|
|
|
50
51
|
GOAL_STATES,
|
|
51
52
|
LINK_SOURCES,
|
|
52
53
|
MEMBERSHIP_SOURCES,
|
|
54
|
+
PACK_CONNECT_ENDINGS,
|
|
55
|
+
PEOPLE_VISIBILITIES,
|
|
53
56
|
PERSON_ROLES,
|
|
54
57
|
PERSON_STATUSES,
|
|
55
58
|
PROJECT_ICON_TYPES,
|
|
@@ -63,6 +66,7 @@ import {
|
|
|
63
66
|
SKILLS_STATUSES,
|
|
64
67
|
TASK_PRIORITIES,
|
|
65
68
|
TASK_STATES,
|
|
69
|
+
WEEK_STARTS,
|
|
66
70
|
} from "./vocabulary.js";
|
|
67
71
|
|
|
68
72
|
/** A line of text a person wrote: trimmed, bounded, and free of characters that hide. */
|
|
@@ -166,6 +170,18 @@ export const restProviderSchema = z.object({
|
|
|
166
170
|
});
|
|
167
171
|
export type RestProvider = z.infer<typeof restProviderSchema>;
|
|
168
172
|
|
|
173
|
+
/**
|
|
174
|
+
* A time zone's name as the IANA database spells one (`Asia/Seoul`, `UTC`): its shape here; the
|
|
175
|
+
* server knows which names are zones.
|
|
176
|
+
*/
|
|
177
|
+
export const timeZoneName = z
|
|
178
|
+
.string()
|
|
179
|
+
.check(
|
|
180
|
+
z.minLength(1),
|
|
181
|
+
z.maxLength(64),
|
|
182
|
+
z.regex(/^[A-Za-z0-9_+-]+(?:\/[A-Za-z0-9_+-]+)*$/, "must be a time zone name"),
|
|
183
|
+
);
|
|
184
|
+
|
|
169
185
|
/** A language tag as a browser sends one (`en`, `ko-KR`): what the pages speak, by the person's choice. */
|
|
170
186
|
const languageTag = z
|
|
171
187
|
.string()
|
|
@@ -178,22 +194,67 @@ const languageTag = z
|
|
|
178
194
|
export const restMePatchSchema = z.object({ language: z.nullable(languageTag) });
|
|
179
195
|
export type RestMePatch = z.infer<typeof restMePatchSchema>;
|
|
180
196
|
|
|
197
|
+
/**
|
|
198
|
+
* The workspace as `GET /api/v1/me` describes it, and as `PATCH /api/v1/workspace` answers: what
|
|
199
|
+
* the board is called, what the deployment's configuration says of it, and the settings an
|
|
200
|
+
* administrator keeps on the Settings page (ADR-0035).
|
|
201
|
+
*/
|
|
202
|
+
export const restWorkspaceSchema = z.object({
|
|
203
|
+
name: z.string(),
|
|
204
|
+
/** The most days a token may be good for here, or `null` when a person chooses. */
|
|
205
|
+
tokenDaysAtMost: z.nullable(z.int().check(z.positive())),
|
|
206
|
+
/**
|
|
207
|
+
* The organization's skills: the origin of the SkillCDN deployment they are read through,
|
|
208
|
+
* and the address a project without one of its own reads, canonical, or `null` for none.
|
|
209
|
+
*/
|
|
210
|
+
skills: z.object({
|
|
211
|
+
source: z.string(),
|
|
212
|
+
address: z.nullable(z.string()),
|
|
213
|
+
/**
|
|
214
|
+
* The SkillCDN token the organization's pack is read with, by a project that names no
|
|
215
|
+
* address and holds no token of its own (ADR-0036): when it was set, never the token; `null`
|
|
216
|
+
* for none. Optional, so that a console older than it still answers.
|
|
217
|
+
*/
|
|
218
|
+
packToken: z.optional(z.nullable(z.object({ setAt: instant }))),
|
|
219
|
+
}),
|
|
220
|
+
/**
|
|
221
|
+
* Who sees whom on the People page (ADR-0035): everyone, or the people one shares a project
|
|
222
|
+
* with. Read as optional, so that a console older than this setting still answers; `everyone`
|
|
223
|
+
* then, which is what it does.
|
|
224
|
+
*/
|
|
225
|
+
peopleVisibility: z.optional(z.enum(PEOPLE_VISIBILITIES)),
|
|
226
|
+
/** The day the calendars begin a week on: the language's, Monday or Sunday. Optional as above; `auto` then. */
|
|
227
|
+
weekStart: z.optional(z.enum(WEEK_STARTS)),
|
|
228
|
+
/**
|
|
229
|
+
* The workspace's time zone, an IANA name, in which the command prints moments; `null` for
|
|
230
|
+
* none, when they stay as the API gives them, in UTC. Optional as above; none then.
|
|
231
|
+
*/
|
|
232
|
+
timeZone: z.optional(z.nullable(timeZoneName)),
|
|
233
|
+
});
|
|
234
|
+
export type RestWorkspace = z.infer<typeof restWorkspaceSchema>;
|
|
235
|
+
|
|
236
|
+
/** What `PATCH /api/v1/workspace` is sent, by an administrator: the settings to change, at least one. */
|
|
237
|
+
export const restWorkspacePatchSchema = z
|
|
238
|
+
.object({
|
|
239
|
+
peopleVisibility: z.optional(z.enum(PEOPLE_VISIBILITIES)),
|
|
240
|
+
weekStart: z.optional(z.enum(WEEK_STARTS)),
|
|
241
|
+
/** A zone's name, or `null` for none. */
|
|
242
|
+
timeZone: z.optional(z.nullable(timeZoneName)),
|
|
243
|
+
})
|
|
244
|
+
.check(
|
|
245
|
+
z.refine((patch) => Object.values(patch).some((value) => value !== undefined), {
|
|
246
|
+
message: "names nothing to change",
|
|
247
|
+
}),
|
|
248
|
+
);
|
|
249
|
+
export type RestWorkspacePatch = z.infer<typeof restWorkspacePatchSchema>;
|
|
250
|
+
|
|
181
251
|
/**
|
|
182
252
|
* `GET /api/v1/me`: the workspace, who the session cookie says is signed in (or `null`), the
|
|
183
253
|
* language they chose (or `null`), and the identity providers people sign in through, none
|
|
184
254
|
* where nobody can.
|
|
185
255
|
*/
|
|
186
256
|
export const restMeSchema = z.object({
|
|
187
|
-
workspace:
|
|
188
|
-
name: z.string(),
|
|
189
|
-
/** The most days a token may be good for here, or `null` when a person chooses. */
|
|
190
|
-
tokenDaysAtMost: z.nullable(z.int().check(z.positive())),
|
|
191
|
-
/**
|
|
192
|
-
* The organization's skills: the origin of the SkillCDN deployment they are read through,
|
|
193
|
-
* and the address a project without one of its own reads, canonical, or `null` for none.
|
|
194
|
-
*/
|
|
195
|
-
skills: z.object({ source: z.string(), address: z.nullable(z.string()) }),
|
|
196
|
-
}),
|
|
257
|
+
workspace: restWorkspaceSchema,
|
|
197
258
|
person: z.nullable(restPersonSchema),
|
|
198
259
|
/**
|
|
199
260
|
* What the token asking is called by its person, when a token asks: how a console of a
|
|
@@ -329,15 +390,25 @@ export const restProjectPatchSchema = z.object({
|
|
|
329
390
|
});
|
|
330
391
|
export type RestProjectPatch = z.infer<typeof restProjectPatchSchema>;
|
|
331
392
|
|
|
332
|
-
/**
|
|
393
|
+
/**
|
|
394
|
+
* A member of a project, with what they are in it: a person listed in it, or, in a project open
|
|
395
|
+
* to the workspace, anyone of the workspace, who is a member of it without a listing (ADR-0035).
|
|
396
|
+
*/
|
|
333
397
|
export const restMemberSchema = z.object({
|
|
334
398
|
person: restPersonSchema,
|
|
399
|
+
/** What they are in it: an owner as listed or as an administrator, else a member. */
|
|
335
400
|
role: z.enum(PROJECT_ROLES),
|
|
401
|
+
/** Since when: the listing's day, or, for a member without one, the later of the project's making and their joining. */
|
|
336
402
|
addedAt: instant,
|
|
403
|
+
/**
|
|
404
|
+
* Whether a listing holds them in the project. Read as optional, so that a console older than
|
|
405
|
+
* this field still answers; everyone it lists is listed.
|
|
406
|
+
*/
|
|
407
|
+
listed: z.optional(z.boolean()),
|
|
337
408
|
});
|
|
338
409
|
export type RestMember = z.infer<typeof restMemberSchema>;
|
|
339
410
|
|
|
340
|
-
/** `GET /api/v1/projects/<key>/members`:
|
|
411
|
+
/** `GET /api/v1/projects/<key>/members`: the members, by login; everyone of the workspace in a project open to it. */
|
|
341
412
|
export const restMembersSchema = z.object({ items: z.array(restMemberSchema) });
|
|
342
413
|
export type RestMembers = z.infer<typeof restMembersSchema>;
|
|
343
414
|
|
|
@@ -410,8 +481,10 @@ export const restTaskSchema = z.object({
|
|
|
410
481
|
body: z.string(),
|
|
411
482
|
state: z.enum(TASK_STATES),
|
|
412
483
|
priority: z.enum(TASK_PRIORITIES),
|
|
484
|
+
/** Whose task it is: one person, whoever wrote it. */
|
|
413
485
|
owner: restPersonSchema,
|
|
414
|
-
|
|
486
|
+
/** The people at work on it (ADR-0037), in the order they came to it; `[]` while nobody is. */
|
|
487
|
+
workers: z.array(restPersonSchema),
|
|
415
488
|
/** The task this one is part of, or `null`. */
|
|
416
489
|
parentId: z.nullable(uuid),
|
|
417
490
|
/** The category the task is sorted into, as the workspace keeps it, or `null`. */
|
|
@@ -460,7 +533,8 @@ export const restTaskInputSchema = z.object({
|
|
|
460
533
|
body: z.optional(body),
|
|
461
534
|
state: z.optional(z.enum(TASK_STATES)),
|
|
462
535
|
priority: z.optional(z.enum(TASK_PRIORITIES)),
|
|
463
|
-
|
|
536
|
+
/** The people to be at work on it, each one who may work in the project, in place of those there were; `[]` for nobody. */
|
|
537
|
+
workerIds: z.optional(z.array(uuid).check(z.maxLength(MAX_WORKERS))),
|
|
464
538
|
parentId: z.optional(z.nullable(uuid)),
|
|
465
539
|
/** The key of a category of the workspace, or `null` for none. */
|
|
466
540
|
category: z.optional(z.nullable(categoryKey)),
|
|
@@ -479,7 +553,7 @@ export const restTaskPatchSchema = z.object({
|
|
|
479
553
|
body: z.optional(body),
|
|
480
554
|
state: z.optional(z.enum(TASK_STATES)),
|
|
481
555
|
priority: z.optional(z.enum(TASK_PRIORITIES)),
|
|
482
|
-
|
|
556
|
+
workerIds: z.optional(z.array(uuid).check(z.maxLength(MAX_WORKERS))),
|
|
483
557
|
parentId: z.optional(z.nullable(uuid)),
|
|
484
558
|
category: z.optional(z.nullable(categoryKey)),
|
|
485
559
|
goalId: z.optional(z.nullable(uuid)),
|
|
@@ -526,8 +600,8 @@ export const restGoalSchema = z.object({
|
|
|
526
600
|
});
|
|
527
601
|
export type RestGoal = z.infer<typeof restGoalSchema>;
|
|
528
602
|
|
|
529
|
-
/** `GET /api/v1/projects/<key>/goals`: the roadmap, the active goals first. */
|
|
530
|
-
export const restGoalsSchema = z.object({ items: z.array(restGoalSchema) });
|
|
603
|
+
/** `GET /api/v1/projects/<key>/goals`: a page of the roadmap, the active goals first, and whether there is more after it. */
|
|
604
|
+
export const restGoalsSchema = z.object({ items: z.array(restGoalSchema), more: z.boolean() });
|
|
531
605
|
export type RestGoals = z.infer<typeof restGoalsSchema>;
|
|
532
606
|
|
|
533
607
|
/** What `POST /api/v1/projects/<key>/goals` is sent: the title, and the rest with defaults. */
|
|
@@ -616,8 +690,8 @@ const projectRef = z.object({
|
|
|
616
690
|
|
|
617
691
|
/**
|
|
618
692
|
* `GET /api/v1/work`: what is on the asker's plate across the projects they may see (ADR-0019):
|
|
619
|
-
* the open tasks
|
|
620
|
-
* project; and, for the week on the plate, `closed`, the tasks
|
|
693
|
+
* the open tasks they work on, and the decisions that wait for a person, each with its
|
|
694
|
+
* project; and, for the week on the plate, `closed`, the tasks they work on that are done
|
|
621
695
|
* or dropped and not yet put away. Left out by a console older than it.
|
|
622
696
|
*/
|
|
623
697
|
export const restWorkSchema = z.object({
|
|
@@ -991,6 +1065,53 @@ export const restPackTokenInputSchema = z.object({
|
|
|
991
1065
|
});
|
|
992
1066
|
export type RestPackTokenInput = z.infer<typeof restPackTokenInputSchema>;
|
|
993
1067
|
|
|
1068
|
+
/**
|
|
1069
|
+
* `POST .../pack-token/connect` (ADR-0036): what the person is shown, as the deployment said it,
|
|
1070
|
+
* the code and the page to approve it on, until when, and how often the console asks again. The
|
|
1071
|
+
* secret the console claims the token with stays with the console.
|
|
1072
|
+
*/
|
|
1073
|
+
export const restPackConnectStartedSchema = z.object({
|
|
1074
|
+
code: z.string(),
|
|
1075
|
+
url: z.string(),
|
|
1076
|
+
expiresAt: instant,
|
|
1077
|
+
intervalSeconds: z.int().check(z.positive()),
|
|
1078
|
+
});
|
|
1079
|
+
export type RestPackConnectStarted = z.infer<typeof restPackConnectStartedSchema>;
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* `GET .../pack-token/connect`: how the connection stands. Nothing asked; waiting for the
|
|
1083
|
+
* person, with what they were shown; connected, the token kept and the project as it stands; or
|
|
1084
|
+
* ended short of a token, and why.
|
|
1085
|
+
*/
|
|
1086
|
+
const packConnectNone = z.object({ status: z.literal("none") });
|
|
1087
|
+
const packConnectPending = z.object({
|
|
1088
|
+
status: z.literal("pending"),
|
|
1089
|
+
code: z.string(),
|
|
1090
|
+
url: z.string(),
|
|
1091
|
+
expiresAt: instant,
|
|
1092
|
+
intervalSeconds: z.int().check(z.positive()),
|
|
1093
|
+
});
|
|
1094
|
+
const packConnectEnded = z.object({
|
|
1095
|
+
status: z.literal("ended"),
|
|
1096
|
+
reason: z.enum(PACK_CONNECT_ENDINGS),
|
|
1097
|
+
});
|
|
1098
|
+
export const restPackConnectSchema = z.union([
|
|
1099
|
+
packConnectNone,
|
|
1100
|
+
packConnectPending,
|
|
1101
|
+
z.object({ status: z.literal("connected"), project: restProjectSchema }),
|
|
1102
|
+
packConnectEnded,
|
|
1103
|
+
]);
|
|
1104
|
+
export type RestPackConnect = z.infer<typeof restPackConnectSchema>;
|
|
1105
|
+
|
|
1106
|
+
/** `GET /api/v1/workspace/pack-token/connect`: the same, for the workspace's token, with the workspace as it stands once connected. */
|
|
1107
|
+
export const restWorkspacePackConnectSchema = z.union([
|
|
1108
|
+
packConnectNone,
|
|
1109
|
+
packConnectPending,
|
|
1110
|
+
z.object({ status: z.literal("connected"), workspace: restWorkspaceSchema }),
|
|
1111
|
+
packConnectEnded,
|
|
1112
|
+
]);
|
|
1113
|
+
export type RestWorkspacePackConnect = z.infer<typeof restWorkspacePackConnectSchema>;
|
|
1114
|
+
|
|
994
1115
|
/** `GET .../skills/one?path=&cursor=`: a page of a skill's context, as the pack answers `load_skill` (`RestSkill` of `@skillcdn/core`); `read` is `null` unless `ready`. */
|
|
995
1116
|
export const restSkillLoadSchema = z.object({
|
|
996
1117
|
...packEnvelope,
|
package/src/styles/console.css
CHANGED
|
@@ -1177,6 +1177,7 @@ table {
|
|
|
1177
1177
|
display: grid;
|
|
1178
1178
|
grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
|
|
1179
1179
|
gap: var(--sc-space-4);
|
|
1180
|
+
align-items: start;
|
|
1180
1181
|
}
|
|
1181
1182
|
|
|
1182
1183
|
.sc-input {
|
|
@@ -1237,6 +1238,150 @@ table {
|
|
|
1237
1238
|
justify-self: start;
|
|
1238
1239
|
}
|
|
1239
1240
|
|
|
1241
|
+
/* The workers of a task on its form: each a chip with the way to take them off, and the way to add one. */
|
|
1242
|
+
.sc-chips {
|
|
1243
|
+
display: flex;
|
|
1244
|
+
flex-wrap: wrap;
|
|
1245
|
+
align-items: center;
|
|
1246
|
+
gap: var(--sc-space-2);
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
.sc-chip {
|
|
1250
|
+
display: inline-flex;
|
|
1251
|
+
align-items: center;
|
|
1252
|
+
gap: var(--sc-space-1);
|
|
1253
|
+
min-height: var(--sc-control-size);
|
|
1254
|
+
padding: 0 var(--sc-space-1) 0 var(--sc-space-2);
|
|
1255
|
+
border: var(--sc-border);
|
|
1256
|
+
border-radius: var(--sc-radius-md);
|
|
1257
|
+
background: var(--sc-color-bg-inset);
|
|
1258
|
+
font-size: var(--sc-text-sm);
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
.sc-chip-remove,
|
|
1262
|
+
.sc-picker-clear {
|
|
1263
|
+
display: inline-grid;
|
|
1264
|
+
flex: none;
|
|
1265
|
+
place-items: center;
|
|
1266
|
+
width: 1.5rem;
|
|
1267
|
+
height: 1.5rem;
|
|
1268
|
+
border: 0;
|
|
1269
|
+
border-radius: var(--sc-radius-sm);
|
|
1270
|
+
background: transparent;
|
|
1271
|
+
color: var(--sc-color-text-muted);
|
|
1272
|
+
font-size: var(--sc-text-md);
|
|
1273
|
+
line-height: 1;
|
|
1274
|
+
cursor: pointer;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
.sc-chip-remove:hover:not(:disabled),
|
|
1278
|
+
.sc-picker-clear:hover:not(:disabled) {
|
|
1279
|
+
background: var(--sc-color-bg-raised);
|
|
1280
|
+
color: var(--sc-color-text);
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
.sc-chip-remove:focus-visible,
|
|
1284
|
+
.sc-picker-clear:focus-visible {
|
|
1285
|
+
outline: var(--sc-focus-ring);
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
.sc-chips .sc-chip-add {
|
|
1289
|
+
width: auto;
|
|
1290
|
+
min-width: 10rem;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
/* A picker: the field that searches a listing, its page of results under it, and the choice in its place. */
|
|
1294
|
+
.sc-picker {
|
|
1295
|
+
position: relative;
|
|
1296
|
+
min-width: 0;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
.sc-picker-chosen {
|
|
1300
|
+
display: flex;
|
|
1301
|
+
align-items: center;
|
|
1302
|
+
gap: var(--sc-space-2);
|
|
1303
|
+
min-height: var(--sc-control-size);
|
|
1304
|
+
padding: var(--sc-space-1) var(--sc-space-1) var(--sc-space-1) var(--sc-space-3);
|
|
1305
|
+
border: 1px solid var(--sc-color-border-strong);
|
|
1306
|
+
border-radius: var(--sc-radius-md);
|
|
1307
|
+
background: var(--sc-color-field);
|
|
1308
|
+
font-size: var(--sc-text-sm);
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
.sc-picker-value {
|
|
1312
|
+
flex: 1;
|
|
1313
|
+
min-width: 0;
|
|
1314
|
+
overflow: hidden;
|
|
1315
|
+
text-overflow: ellipsis;
|
|
1316
|
+
white-space: nowrap;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
.sc-picker-list {
|
|
1320
|
+
position: absolute;
|
|
1321
|
+
z-index: 40;
|
|
1322
|
+
top: calc(100% + var(--sc-space-1));
|
|
1323
|
+
right: 0;
|
|
1324
|
+
left: 0;
|
|
1325
|
+
max-height: 18rem;
|
|
1326
|
+
margin: 0;
|
|
1327
|
+
padding: var(--sc-space-1);
|
|
1328
|
+
overflow-y: auto;
|
|
1329
|
+
list-style: none;
|
|
1330
|
+
border: var(--sc-border);
|
|
1331
|
+
border-radius: var(--sc-radius-md);
|
|
1332
|
+
background: var(--sc-color-bg-inset);
|
|
1333
|
+
box-shadow: var(--sc-shadow-stage);
|
|
1334
|
+
font-size: var(--sc-text-sm);
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
/* Where the window has no room below the field, and more above, the list stands above it. */
|
|
1338
|
+
.sc-picker-list-above {
|
|
1339
|
+
top: auto;
|
|
1340
|
+
bottom: calc(100% + var(--sc-space-1));
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
.sc-picker-option {
|
|
1344
|
+
padding: var(--sc-space-2);
|
|
1345
|
+
overflow: hidden;
|
|
1346
|
+
border-radius: var(--sc-radius-sm);
|
|
1347
|
+
text-overflow: ellipsis;
|
|
1348
|
+
white-space: nowrap;
|
|
1349
|
+
cursor: pointer;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
.sc-picker-option-active {
|
|
1353
|
+
background: var(--sc-color-bg-raised);
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
.sc-picker-note {
|
|
1357
|
+
padding: var(--sc-space-2);
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
/* The workers of a task on a card or a row: pictures side by side, and how many more. */
|
|
1361
|
+
.sc-workers {
|
|
1362
|
+
display: inline-flex;
|
|
1363
|
+
align-items: center;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
.sc-workers > * + * {
|
|
1367
|
+
margin-left: -0.375rem;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
.sc-workers-more {
|
|
1371
|
+
margin-inline: var(--sc-space-1);
|
|
1372
|
+
color: var(--sc-color-text-muted);
|
|
1373
|
+
font-size: var(--sc-text-xs);
|
|
1374
|
+
font-weight: var(--sc-weight-medium);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
.sc-worker-list {
|
|
1378
|
+
display: grid;
|
|
1379
|
+
gap: var(--sc-space-1);
|
|
1380
|
+
margin: 0;
|
|
1381
|
+
padding: 0;
|
|
1382
|
+
list-style: none;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1240
1385
|
.sc-form-actions {
|
|
1241
1386
|
display: flex;
|
|
1242
1387
|
flex-wrap: wrap;
|
|
@@ -2905,8 +3050,10 @@ table {
|
|
|
2905
3050
|
white-space: nowrap;
|
|
2906
3051
|
}
|
|
2907
3052
|
|
|
2908
|
-
/*
|
|
2909
|
-
|
|
3053
|
+
/* The task under the pointer is lit a little by its colour, in every piece of its bar and in
|
|
3054
|
+
every week it crosses, never one piece alone; by its colour and not by a filter, which would
|
|
3055
|
+
light the card within it too. */
|
|
3056
|
+
.sc-calendar-bar-pointed {
|
|
2910
3057
|
background: color-mix(in srgb, var(--sc-category-fill), white 12%);
|
|
2911
3058
|
}
|
|
2912
3059
|
|
|
@@ -2924,6 +3071,18 @@ table {
|
|
|
2924
3071
|
border-end-end-radius: var(--sc-radius-full);
|
|
2925
3072
|
}
|
|
2926
3073
|
|
|
3074
|
+
/* The title of a bar with more days in the week runs along the bar as far as its days reach,
|
|
3075
|
+
less the room of its end, instead of stopping at the first day's edge: above every piece,
|
|
3076
|
+
the one under the pointer included, and under the cards; the pointer goes through it to the
|
|
3077
|
+
piece of the day beneath. The days are the first piece's own custom property. */
|
|
3078
|
+
.sc-calendar-task-title-spanning {
|
|
3079
|
+
position: relative;
|
|
3080
|
+
z-index: 25;
|
|
3081
|
+
flex: none;
|
|
3082
|
+
max-width: calc(var(--sc-span, 1) * 100% - 2.25rem);
|
|
3083
|
+
pointer-events: none;
|
|
3084
|
+
}
|
|
3085
|
+
|
|
2927
3086
|
.sc-calendar-bar.sc-calendar-late {
|
|
2928
3087
|
border-color: color-mix(in srgb, var(--sc-color-danger) 70%, transparent);
|
|
2929
3088
|
color: var(--sc-color-danger);
|
|
@@ -3364,18 +3523,12 @@ table {
|
|
|
3364
3523
|
position: relative;
|
|
3365
3524
|
}
|
|
3366
3525
|
|
|
3367
|
-
/* The
|
|
3368
|
-
.
|
|
3369
|
-
.sc-calendar-task:focus-visible,
|
|
3370
|
-
.sc-calendar-bar:hover,
|
|
3371
|
-
.sc-calendar-bar:focus-visible {
|
|
3372
|
-
z-index: 20;
|
|
3373
|
-
}
|
|
3374
|
-
|
|
3526
|
+
/* The card rises above its neighbours and above a title running along a bar; the item under the
|
|
3527
|
+
pointer itself stays in its layer, so that nothing of it covers such a title. */
|
|
3375
3528
|
.sc-task-tip {
|
|
3376
3529
|
position: absolute;
|
|
3377
3530
|
left: 0;
|
|
3378
|
-
z-index:
|
|
3531
|
+
z-index: 30;
|
|
3379
3532
|
width: max-content;
|
|
3380
3533
|
max-width: 20rem;
|
|
3381
3534
|
padding: var(--sc-space-2) var(--sc-space-3);
|
|
@@ -4130,3 +4283,158 @@ table {
|
|
|
4130
4283
|
.sc-goal-view-list {
|
|
4131
4284
|
display: block;
|
|
4132
4285
|
}
|
|
4286
|
+
|
|
4287
|
+
/* The workspace's settings (ADR-0035): each setting a row, its name beside its value; on the form,
|
|
4288
|
+
its name and its hint beside a control of a bounded width, so that a short choice is not a
|
|
4289
|
+
field as wide as the page. */
|
|
4290
|
+
.sc-settings-list {
|
|
4291
|
+
display: grid;
|
|
4292
|
+
margin: 0;
|
|
4293
|
+
font-size: var(--sc-text-sm);
|
|
4294
|
+
}
|
|
4295
|
+
|
|
4296
|
+
.sc-settings-item {
|
|
4297
|
+
display: grid;
|
|
4298
|
+
grid-template-columns: minmax(8rem, 14rem) minmax(0, 1fr);
|
|
4299
|
+
gap: var(--sc-space-1) var(--sc-space-5);
|
|
4300
|
+
padding: var(--sc-space-3) 0;
|
|
4301
|
+
border-top: var(--sc-border);
|
|
4302
|
+
}
|
|
4303
|
+
|
|
4304
|
+
.sc-settings-item:first-child {
|
|
4305
|
+
padding-top: 0;
|
|
4306
|
+
border-top: 0;
|
|
4307
|
+
}
|
|
4308
|
+
|
|
4309
|
+
.sc-settings-item:last-child {
|
|
4310
|
+
padding-bottom: 0;
|
|
4311
|
+
}
|
|
4312
|
+
|
|
4313
|
+
.sc-settings-item dt {
|
|
4314
|
+
color: var(--sc-color-text-muted);
|
|
4315
|
+
}
|
|
4316
|
+
|
|
4317
|
+
.sc-settings-item dd {
|
|
4318
|
+
margin: 0;
|
|
4319
|
+
}
|
|
4320
|
+
|
|
4321
|
+
.sc-settings-note {
|
|
4322
|
+
margin-left: var(--sc-space-3);
|
|
4323
|
+
color: var(--sc-color-text-muted);
|
|
4324
|
+
}
|
|
4325
|
+
|
|
4326
|
+
.sc-settings-form {
|
|
4327
|
+
gap: 0;
|
|
4328
|
+
}
|
|
4329
|
+
|
|
4330
|
+
.sc-settings-row {
|
|
4331
|
+
display: grid;
|
|
4332
|
+
grid-template-columns: minmax(0, 1fr) minmax(14rem, 20rem);
|
|
4333
|
+
gap: var(--sc-space-3) var(--sc-space-6);
|
|
4334
|
+
align-items: start;
|
|
4335
|
+
padding: var(--sc-space-4) 0;
|
|
4336
|
+
border-top: var(--sc-border);
|
|
4337
|
+
}
|
|
4338
|
+
|
|
4339
|
+
.sc-settings-row:first-child {
|
|
4340
|
+
padding-top: 0;
|
|
4341
|
+
border-top: 0;
|
|
4342
|
+
}
|
|
4343
|
+
|
|
4344
|
+
.sc-settings-label {
|
|
4345
|
+
display: block;
|
|
4346
|
+
font-weight: var(--sc-weight-medium);
|
|
4347
|
+
}
|
|
4348
|
+
|
|
4349
|
+
.sc-settings-hint {
|
|
4350
|
+
max-width: var(--sc-width-prose);
|
|
4351
|
+
margin: var(--sc-space-1) 0 0;
|
|
4352
|
+
color: var(--sc-color-text-muted);
|
|
4353
|
+
font-size: var(--sc-text-sm);
|
|
4354
|
+
}
|
|
4355
|
+
|
|
4356
|
+
.sc-settings-control {
|
|
4357
|
+
display: grid;
|
|
4358
|
+
justify-items: start;
|
|
4359
|
+
gap: var(--sc-space-2);
|
|
4360
|
+
}
|
|
4361
|
+
|
|
4362
|
+
.sc-settings-control .sc-input {
|
|
4363
|
+
width: 100%;
|
|
4364
|
+
}
|
|
4365
|
+
|
|
4366
|
+
.sc-settings-form .sc-form-actions {
|
|
4367
|
+
padding-top: var(--sc-space-4);
|
|
4368
|
+
border-top: var(--sc-border);
|
|
4369
|
+
}
|
|
4370
|
+
|
|
4371
|
+
@media (max-width: 40rem) {
|
|
4372
|
+
.sc-settings-item,
|
|
4373
|
+
.sc-settings-row {
|
|
4374
|
+
grid-template-columns: minmax(0, 1fr);
|
|
4375
|
+
}
|
|
4376
|
+
}
|
|
4377
|
+
|
|
4378
|
+
/* The pack token (ADR-0028, ADR-0036): what it is for first, then the two ways to one side by
|
|
4379
|
+
side, each a card with its words before its controls, and the code shown large while the
|
|
4380
|
+
page waits for the approval. */
|
|
4381
|
+
.sc-pack-intro {
|
|
4382
|
+
max-width: var(--sc-width-prose);
|
|
4383
|
+
margin: 0 0 var(--sc-space-5);
|
|
4384
|
+
color: var(--sc-color-text-muted);
|
|
4385
|
+
font-size: var(--sc-text-sm);
|
|
4386
|
+
}
|
|
4387
|
+
|
|
4388
|
+
.sc-pack-ways {
|
|
4389
|
+
display: grid;
|
|
4390
|
+
grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
|
|
4391
|
+
gap: var(--sc-space-4);
|
|
4392
|
+
}
|
|
4393
|
+
|
|
4394
|
+
.sc-pack-way {
|
|
4395
|
+
display: grid;
|
|
4396
|
+
align-content: start;
|
|
4397
|
+
gap: var(--sc-space-3);
|
|
4398
|
+
padding: var(--sc-space-4);
|
|
4399
|
+
border: var(--sc-border);
|
|
4400
|
+
border-radius: var(--sc-radius-lg);
|
|
4401
|
+
background: var(--sc-color-sheet);
|
|
4402
|
+
}
|
|
4403
|
+
|
|
4404
|
+
.sc-pack-way-title {
|
|
4405
|
+
font-size: var(--sc-text-md);
|
|
4406
|
+
font-weight: var(--sc-weight-medium);
|
|
4407
|
+
}
|
|
4408
|
+
|
|
4409
|
+
.sc-pack-way .sc-field-hint {
|
|
4410
|
+
margin-top: 0;
|
|
4411
|
+
}
|
|
4412
|
+
|
|
4413
|
+
.sc-pack-connect {
|
|
4414
|
+
display: grid;
|
|
4415
|
+
gap: var(--sc-space-3);
|
|
4416
|
+
}
|
|
4417
|
+
|
|
4418
|
+
.sc-pack-connect-code {
|
|
4419
|
+
display: flex;
|
|
4420
|
+
flex-wrap: wrap;
|
|
4421
|
+
align-items: baseline;
|
|
4422
|
+
gap: var(--sc-space-3);
|
|
4423
|
+
}
|
|
4424
|
+
|
|
4425
|
+
.sc-pack-code {
|
|
4426
|
+
font-size: var(--sc-text-xl);
|
|
4427
|
+
letter-spacing: 0.12em;
|
|
4428
|
+
}
|
|
4429
|
+
|
|
4430
|
+
.sc-pack-connect-waiting {
|
|
4431
|
+
display: flex;
|
|
4432
|
+
align-items: center;
|
|
4433
|
+
gap: var(--sc-space-2);
|
|
4434
|
+
color: var(--sc-color-text-muted);
|
|
4435
|
+
font-size: var(--sc-text-sm);
|
|
4436
|
+
}
|
|
4437
|
+
|
|
4438
|
+
.sc-pack-actions {
|
|
4439
|
+
margin-top: var(--sc-space-5);
|
|
4440
|
+
}
|
package/src/vocabulary.ts
CHANGED
|
@@ -30,6 +30,9 @@ export const GOAL_STATES = ["planned", "active", "done", "dropped"] as const;
|
|
|
30
30
|
|
|
31
31
|
export type GoalState = (typeof GOAL_STATES)[number];
|
|
32
32
|
|
|
33
|
+
/** The states a goal is still open in: planned, or being worked towards. */
|
|
34
|
+
export const OPEN_GOAL_STATES: readonly GoalState[] = ["planned", "active"];
|
|
35
|
+
|
|
33
36
|
/**
|
|
34
37
|
* The colours a category, or a project's mark, may be shown in: names, so that a custom console
|
|
35
38
|
* paints them in its own tokens and no value a person typed reaches a stylesheet.
|
|
@@ -97,6 +100,30 @@ export const PROJECT_VISIBILITIES = ["workspace", "private"] as const;
|
|
|
97
100
|
|
|
98
101
|
export type ProjectVisibility = (typeof PROJECT_VISIBILITIES)[number];
|
|
99
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Who sees whom on the People page and in the pickers (ADR-0035): everyone of the workspace,
|
|
105
|
+
* or only the people one shares a project with; an administrator always sees everyone.
|
|
106
|
+
*/
|
|
107
|
+
export const PEOPLE_VISIBILITIES = ["everyone", "shared_projects"] as const;
|
|
108
|
+
|
|
109
|
+
export type PeopleVisibility = (typeof PEOPLE_VISIBILITIES)[number];
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The day the calendars begin a week on (ADR-0035): as the language of the pages has it, or
|
|
113
|
+
* Monday, or Sunday, for the whole workspace.
|
|
114
|
+
*/
|
|
115
|
+
export const WEEK_STARTS = ["auto", "monday", "sunday"] as const;
|
|
116
|
+
|
|
117
|
+
export type WeekStart = (typeof WEEK_STARTS)[number];
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* How a private pack's connection ended short of a token (ADR-0036): the code expired before
|
|
121
|
+
* anyone approved, the person declined at the deployment, or the deployment refused the request.
|
|
122
|
+
*/
|
|
123
|
+
export const PACK_CONNECT_ENDINGS = ["expired", "declined", "refused"] as const;
|
|
124
|
+
|
|
125
|
+
export type PackConnectEnding = (typeof PACK_CONNECT_ENDINGS)[number];
|
|
126
|
+
|
|
100
127
|
/** What a run is doing: at work, waiting for a person's decision, or over in one of three ways. */
|
|
101
128
|
export const RUN_STATUSES = ["running", "waiting", "finished", "failed", "abandoned"] as const;
|
|
102
129
|
|
|
@@ -153,6 +180,7 @@ export const EVENT_KINDS = [
|
|
|
153
180
|
"person.unlisted",
|
|
154
181
|
"person.deactivated",
|
|
155
182
|
"person.reactivated",
|
|
183
|
+
"workspace.updated",
|
|
156
184
|
"category.created",
|
|
157
185
|
"category.updated",
|
|
158
186
|
"category.removed",
|