@skillcdn/console 0.1.17 → 0.1.19
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/SKILLCDN.md +1 -1
- package/dist/api.d.ts +3 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +2 -1
- package/dist/api.js.map +1 -1
- package/dist/cli/cli.d.ts +11 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +496 -51
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/credentials.d.ts +102 -3
- package/dist/cli/credentials.d.ts.map +1 -1
- package/dist/cli/credentials.js +177 -8
- package/dist/cli/credentials.js.map +1 -1
- package/dist/cli/directory.d.ts +6 -0
- package/dist/cli/directory.d.ts.map +1 -1
- package/dist/cli/directory.js +37 -6
- package/dist/cli/directory.js.map +1 -1
- package/dist/cli/format.d.ts +11 -2
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +114 -5
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +49 -25
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/install.d.ts +21 -0
- package/dist/cli/install.d.ts.map +1 -0
- package/dist/cli/install.js +87 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/main.js +22 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/notices.d.ts +13 -0
- package/dist/cli/notices.d.ts.map +1 -0
- package/dist/cli/notices.js +31 -0
- package/dist/cli/notices.js.map +1 -0
- package/dist/client.d.ts +36 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +22 -4
- package/dist/client.js.map +1 -1
- package/dist/compat.d.ts +66 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +115 -0
- package/dist/compat.js.map +1 -0
- package/dist/components/board.d.ts +9 -1
- package/dist/components/board.d.ts.map +1 -1
- package/dist/components/board.js +82 -5
- package/dist/components/board.js.map +1 -1
- package/dist/components/calendar.d.ts +3 -1
- package/dist/components/calendar.d.ts.map +1 -1
- package/dist/components/calendar.js +21 -2
- package/dist/components/calendar.js.map +1 -1
- package/dist/components/comments.d.ts.map +1 -1
- package/dist/components/comments.js +12 -4
- package/dist/components/comments.js.map +1 -1
- package/dist/components/event-feed.d.ts.map +1 -1
- package/dist/components/event-feed.js +4 -0
- package/dist/components/event-feed.js.map +1 -1
- package/dist/components/goals.d.ts +20 -2
- package/dist/components/goals.d.ts.map +1 -1
- package/dist/components/goals.js +50 -13
- package/dist/components/goals.js.map +1 -1
- package/dist/components/markdown.d.ts +6 -0
- package/dist/components/markdown.d.ts.map +1 -1
- package/dist/components/markdown.js +7 -0
- package/dist/components/markdown.js.map +1 -1
- package/dist/components/pictures.d.ts +68 -0
- package/dist/components/pictures.d.ts.map +1 -0
- package/dist/components/pictures.js +213 -0
- package/dist/components/pictures.js.map +1 -0
- package/dist/components/projects.d.ts +12 -0
- package/dist/components/projects.d.ts.map +1 -1
- package/dist/components/projects.js +15 -0
- package/dist/components/projects.js.map +1 -1
- package/dist/components/roadmap.d.ts +37 -0
- package/dist/components/roadmap.d.ts.map +1 -0
- package/dist/components/roadmap.js +76 -0
- package/dist/components/roadmap.js.map +1 -0
- package/dist/components/task-view.d.ts +3 -0
- package/dist/components/task-view.d.ts.map +1 -1
- package/dist/components/task-view.js +6 -4
- package/dist/components/task-view.js.map +1 -1
- package/dist/components/tokens.d.ts +2 -0
- package/dist/components/tokens.d.ts.map +1 -1
- package/dist/components/tokens.js +13 -3
- package/dist/components/tokens.js.map +1 -1
- package/dist/console.css +486 -3
- package/dist/console.d.ts.map +1 -1
- package/dist/console.js +132 -17
- package/dist/console.js.map +1 -1
- package/dist/data.d.ts +16 -1
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +48 -3
- package/dist/data.js.map +1 -1
- package/dist/i18n/en.d.ts +76 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +74 -2
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/ko.d.ts.map +1 -1
- package/dist/i18n/ko.js +74 -2
- package/dist/i18n/ko.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +31 -7
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +48 -8
- package/dist/router.js.map +1 -1
- package/dist/rules.js +5 -5
- package/dist/rules.js.map +1 -1
- package/dist/schemas.d.ts +200 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +96 -0
- package/dist/schemas.js.map +1 -1
- package/dist/vocabulary.d.ts +2 -2
- package/dist/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary.js +3 -0
- package/dist/vocabulary.js.map +1 -1
- package/docs/specs/cli.md +26 -15
- package/docs/specs/rest.md +31 -9
- package/package.json +3 -2
- package/skills/working-the-board/SKILL.md +11 -4
- package/src/api.ts +36 -0
- package/src/cli/cli.ts +616 -54
- package/src/cli/credentials.ts +276 -14
- package/src/cli/directory.ts +43 -6
- package/src/cli/format.ts +146 -5
- package/src/cli/help.ts +51 -25
- package/src/cli/install.ts +111 -0
- package/src/cli/main.ts +23 -3
- package/src/cli/notices.ts +48 -0
- package/src/client.ts +91 -6
- package/src/compat.ts +173 -0
- package/src/components/board.tsx +154 -8
- package/src/components/calendar.tsx +41 -1
- package/src/components/comments.tsx +20 -10
- package/src/components/event-feed.tsx +4 -0
- package/src/components/goals.tsx +234 -88
- package/src/components/markdown.tsx +19 -0
- package/src/components/pictures.tsx +389 -0
- package/src/components/projects.tsx +68 -0
- package/src/components/roadmap.tsx +242 -0
- package/src/components/task-view.tsx +43 -2
- package/src/components/tokens.tsx +38 -1
- package/src/console.tsx +278 -4
- package/src/data.ts +73 -2
- package/src/i18n/en.ts +77 -2
- package/src/i18n/ko.ts +77 -2
- package/src/index.ts +35 -0
- package/src/router.ts +70 -11
- package/src/rules.ts +5 -5
- package/src/schemas.ts +117 -0
- package/src/styles/console.css +486 -3
- package/src/vocabulary.ts +3 -0
package/src/data.ts
CHANGED
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
type DocumentFilter,
|
|
7
7
|
EVENT_KINDS,
|
|
8
8
|
type FileUpload,
|
|
9
|
+
LIST_LIMIT,
|
|
10
|
+
type ProjectClient,
|
|
9
11
|
type RestAnswerInput,
|
|
10
12
|
type RestCategory,
|
|
11
13
|
type RestCategoryInput,
|
|
@@ -44,6 +46,7 @@ import {
|
|
|
44
46
|
type RestTask,
|
|
45
47
|
type RestTaskInput,
|
|
46
48
|
type RestTaskPatch,
|
|
49
|
+
type RestTasks,
|
|
47
50
|
type RestToken,
|
|
48
51
|
type RestTokenCreated,
|
|
49
52
|
type RestTokenInput,
|
|
@@ -74,11 +77,26 @@ export interface ConsoleActions {
|
|
|
74
77
|
/** Sets the image for the mark of the project the page is on, or takes it away; for an owner. */
|
|
75
78
|
setProjectIcon(input: FileUpload): Promise<RestProject>;
|
|
76
79
|
removeProjectIcon(): Promise<RestProject>;
|
|
80
|
+
/** Sets the pack token of the project the page is on, or takes it away; for an owner (ADR-0028). */
|
|
81
|
+
setPackToken(token: string): Promise<RestProject>;
|
|
82
|
+
removePackToken(): Promise<RestProject>;
|
|
77
83
|
addMember(input: RestMemberInput): Promise<RestMember>;
|
|
78
84
|
updateMember(personId: string, patch: RestMemberPatch): Promise<RestMember>;
|
|
79
85
|
removeMember(personId: string): Promise<void>;
|
|
80
86
|
createTask(input: RestTaskInput): Promise<RestTask>;
|
|
81
87
|
updateTask(id: string, patch: RestTaskPatch): Promise<RestTask>;
|
|
88
|
+
/** One task by its id or its number, asked for by itself: a task put away is not among the board's. */
|
|
89
|
+
fetchTask(ref: string, signal?: AbortSignal): Promise<RestTask>;
|
|
90
|
+
/** Puts a done or dropped task away, or brings one back (ADR-0029). */
|
|
91
|
+
archiveTask(id: string): Promise<RestTask>;
|
|
92
|
+
restoreTask(id: string): Promise<RestTask>;
|
|
93
|
+
/** Puts every done or dropped task of a goal away; for an owner. Answers how many went. */
|
|
94
|
+
archiveGoalTasks(goalId: string): Promise<number>;
|
|
95
|
+
/** A page of the tasks put away, newest first. */
|
|
96
|
+
archivedTasks(
|
|
97
|
+
page: { readonly limit: number; readonly offset: number },
|
|
98
|
+
signal?: AbortSignal,
|
|
99
|
+
): Promise<RestTasks>;
|
|
82
100
|
raiseDecision(input: RestDecisionInput): Promise<RestDecision>;
|
|
83
101
|
answerDecision(id: string, input: RestAnswerInput): Promise<RestDecision>;
|
|
84
102
|
/** Grows a decision's record: its context, or what followed. */
|
|
@@ -201,6 +219,32 @@ async function readFeed(
|
|
|
201
219
|
return events.slice(-FEED_KEEP);
|
|
202
220
|
}
|
|
203
221
|
|
|
222
|
+
/** How many pages of the current tasks are read before the board is shown as it stands. */
|
|
223
|
+
const TASKS_MAX_PAGES = 20;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* The current tasks of a project, whole: page after page while the server says there is more,
|
|
227
|
+
* so that a board past one page loses nothing without a word; the tasks put away are not among
|
|
228
|
+
* them (ADR-0029).
|
|
229
|
+
*/
|
|
230
|
+
async function readTasks(
|
|
231
|
+
scope: ProjectClient,
|
|
232
|
+
signal: AbortSignal | undefined,
|
|
233
|
+
): Promise<{ readonly items: RestTask[] }> {
|
|
234
|
+
const items: RestTask[] = [];
|
|
235
|
+
for (let page = 0; page < TASKS_MAX_PAGES; page += 1) {
|
|
236
|
+
const result = await scope.tasks(
|
|
237
|
+
{ archived: false, limit: LIST_LIMIT, offset: page * LIST_LIMIT },
|
|
238
|
+
signal,
|
|
239
|
+
);
|
|
240
|
+
items.push(...result.items);
|
|
241
|
+
if (!result.more) {
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return { items };
|
|
246
|
+
}
|
|
247
|
+
|
|
204
248
|
const wordsOf = (failure: unknown, fallback: string): string =>
|
|
205
249
|
failure instanceof ApiError ? failure.message : fallback;
|
|
206
250
|
|
|
@@ -265,9 +309,9 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
|
|
|
265
309
|
const [nextProject, nextTasks, nextDecisions, nextGoals, nextRuns, nextMembers] =
|
|
266
310
|
await Promise.all([
|
|
267
311
|
scope.get(signal),
|
|
268
|
-
scope
|
|
312
|
+
readTasks(scope, signal),
|
|
269
313
|
scope.decisions(undefined, signal),
|
|
270
|
-
scope.goals(signal),
|
|
314
|
+
scope.goals({}, signal),
|
|
271
315
|
scope.runs(undefined, signal),
|
|
272
316
|
scope.members(signal),
|
|
273
317
|
]);
|
|
@@ -454,6 +498,16 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
|
|
|
454
498
|
await refreshWorkspace();
|
|
455
499
|
return changed;
|
|
456
500
|
},
|
|
501
|
+
async setPackToken(token) {
|
|
502
|
+
const changed = await scope().setPackToken({ token });
|
|
503
|
+
setProject(changed);
|
|
504
|
+
return changed;
|
|
505
|
+
},
|
|
506
|
+
async removePackToken() {
|
|
507
|
+
const changed = await scope().removePackToken();
|
|
508
|
+
setProject(changed);
|
|
509
|
+
return changed;
|
|
510
|
+
},
|
|
457
511
|
async addMember(input) {
|
|
458
512
|
const member = await scope().addMember(input);
|
|
459
513
|
await refreshProject();
|
|
@@ -478,6 +532,23 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
|
|
|
478
532
|
setTasks((current) => current.map((candidate) => (candidate.id === id ? task : candidate)));
|
|
479
533
|
return task;
|
|
480
534
|
},
|
|
535
|
+
fetchTask: (ref, signal) => scope().task(ref, signal),
|
|
536
|
+
async archiveTask(id) {
|
|
537
|
+
const task = await scope().archiveTask(id);
|
|
538
|
+
setTasks((current) => current.filter((candidate) => candidate.id !== id));
|
|
539
|
+
return task;
|
|
540
|
+
},
|
|
541
|
+
async restoreTask(id) {
|
|
542
|
+
const task = await scope().restoreTask(id);
|
|
543
|
+
setTasks((current) => [task, ...current.filter((candidate) => candidate.id !== id)]);
|
|
544
|
+
return task;
|
|
545
|
+
},
|
|
546
|
+
async archiveGoalTasks(goalId) {
|
|
547
|
+
const { archived } = await scope().archiveTasksOfGoal(goalId);
|
|
548
|
+
await refreshProject();
|
|
549
|
+
return archived;
|
|
550
|
+
},
|
|
551
|
+
archivedTasks: (page, signal) => scope().tasks({ archived: true, ...page }, signal),
|
|
481
552
|
async raiseDecision(input) {
|
|
482
553
|
const decision = await scope().raiseDecision(input);
|
|
483
554
|
await refreshProject();
|
package/src/i18n/en.ts
CHANGED
|
@@ -194,12 +194,24 @@ export const en = {
|
|
|
194
194
|
private: "The administrators own it until an owner is listed.",
|
|
195
195
|
},
|
|
196
196
|
},
|
|
197
|
+
packToken: {
|
|
198
|
+
aria: "The pack token",
|
|
199
|
+
label: "Token",
|
|
200
|
+
hint: "A token a person made at SkillCDN for the pack's repository, on their account page there. The console keeps it sealed, reads the pack with it for whoever may see the project, and shows it to nobody.",
|
|
201
|
+
placeholder: "scdn_repo_…",
|
|
202
|
+
set: "Set the token",
|
|
203
|
+
remove: "Remove the token",
|
|
204
|
+
},
|
|
197
205
|
settings: {
|
|
198
206
|
title: "Settings",
|
|
199
207
|
aria: "Project settings",
|
|
200
208
|
edit: "Edit the project",
|
|
201
209
|
organizationsSkills: (address: string) => `The organization's: ${address}`,
|
|
202
210
|
noSkills: "None: the console names no address for the organization's.",
|
|
211
|
+
packToken: "Pack token",
|
|
212
|
+
packTokenNone: "None: a public pack needs none, and a private one is not read.",
|
|
213
|
+
packTokenSet: "Set",
|
|
214
|
+
packTokenEdit: "Change it",
|
|
203
215
|
},
|
|
204
216
|
},
|
|
205
217
|
|
|
@@ -210,6 +222,8 @@ export const en = {
|
|
|
210
222
|
body: "Write the first task: what is to be done, and for whom.",
|
|
211
223
|
},
|
|
212
224
|
moveTo: "Move to",
|
|
225
|
+
grip: "Drag to another column",
|
|
226
|
+
archive: "Archive",
|
|
213
227
|
decisions: (n: number) => count(n, "decision", "decisions"),
|
|
214
228
|
decisionsTitle: "Decisions waiting for a person",
|
|
215
229
|
filters: {
|
|
@@ -265,6 +279,10 @@ export const en = {
|
|
|
265
279
|
: "",
|
|
266
280
|
started: "Started",
|
|
267
281
|
done: "Done",
|
|
282
|
+
archived: "Put away",
|
|
283
|
+
archivedAt: "Put away",
|
|
284
|
+
archive: "Put away",
|
|
285
|
+
restore: "Bring back",
|
|
268
286
|
form: {
|
|
269
287
|
title: "Title",
|
|
270
288
|
titlePlaceholder: "What is to be done, in plain words that stand on their own.",
|
|
@@ -385,16 +403,39 @@ export const en = {
|
|
|
385
403
|
inProgress: (n: number) => `${n} in progress`,
|
|
386
404
|
noTasks: "No task works towards it yet.",
|
|
387
405
|
tasks: "Tasks",
|
|
406
|
+
category: "Category",
|
|
407
|
+
noCategory: "No category",
|
|
408
|
+
starts: "Starts",
|
|
409
|
+
noStart: "No start day",
|
|
388
410
|
target: "Target",
|
|
389
411
|
noTarget: "No target day",
|
|
390
412
|
setBy: "Set by",
|
|
391
413
|
state: "State",
|
|
392
414
|
nothingMore: "Nothing more was written about it.",
|
|
415
|
+
about: "What reaching it means",
|
|
416
|
+
archiveTasks: "Put the done tasks away",
|
|
417
|
+
archiveAsk: (n: number) =>
|
|
418
|
+
`Put the ${count(n, "task", "tasks")} done or dropped under this goal away as well?`,
|
|
419
|
+
view: "View",
|
|
420
|
+
views: { board: "Board", list: "List", calendar: "Calendar" },
|
|
421
|
+
timeline: {
|
|
422
|
+
title: "The months",
|
|
423
|
+
legend: "Category colours",
|
|
424
|
+
earlier: "A month earlier",
|
|
425
|
+
later: "A month later",
|
|
426
|
+
thisMonth: "This month",
|
|
427
|
+
today: "Today",
|
|
428
|
+
nothing: "No goal is planned in these months.",
|
|
429
|
+
noDays: "No day set",
|
|
430
|
+
},
|
|
393
431
|
form: {
|
|
394
432
|
title: "Title",
|
|
395
433
|
body: "What reaching it means",
|
|
396
434
|
bodyPlaceholder: "What is true once the goal is reached, in Markdown.",
|
|
397
435
|
state: "State",
|
|
436
|
+
category: "Category",
|
|
437
|
+
noCategory: "No category",
|
|
438
|
+
startsOn: "Start day",
|
|
398
439
|
dueOn: "Target day",
|
|
399
440
|
set: "Set the goal",
|
|
400
441
|
},
|
|
@@ -538,6 +579,8 @@ export const en = {
|
|
|
538
579
|
taskUpdated: (fields: string, task: string) => `changed ${fields} of ${task}`,
|
|
539
580
|
taskCommented: (task: string, excerpt: string | undefined) =>
|
|
540
581
|
`commented on ${task}${excerpt === undefined || excerpt === "" ? "" : `: ${excerpt}`}`,
|
|
582
|
+
taskArchived: (task: string) => `put ${task} away`,
|
|
583
|
+
taskRestored: (task: string) => `brought ${task} back`,
|
|
541
584
|
decisionRaised: (question: string) => `asked: ${question}`,
|
|
542
585
|
decisionAnswered: (question: string, option: string) => `answered "${question}": ${option}`,
|
|
543
586
|
decisionUpdated: (fields: string, question: string) =>
|
|
@@ -558,6 +601,19 @@ export const en = {
|
|
|
558
601
|
},
|
|
559
602
|
},
|
|
560
603
|
|
|
604
|
+
archive: {
|
|
605
|
+
title: "Archive",
|
|
606
|
+
lead: "Tasks done or dropped and put away: out of the board, the lists and the calendar, each still open by its number. Brought back from here.",
|
|
607
|
+
loading: "Loading the archive",
|
|
608
|
+
empty: {
|
|
609
|
+
title: "Nothing is put away",
|
|
610
|
+
body: "A task done or dropped is put away from its page, with its goal, or by the console after a while.",
|
|
611
|
+
},
|
|
612
|
+
since: "put away",
|
|
613
|
+
restore: "Bring back",
|
|
614
|
+
more: "Show more",
|
|
615
|
+
},
|
|
616
|
+
|
|
561
617
|
runs: {
|
|
562
618
|
for: "for",
|
|
563
619
|
since: "since",
|
|
@@ -584,6 +640,16 @@ export const en = {
|
|
|
584
640
|
picture: (name: string) => `The picture ${name}`,
|
|
585
641
|
label: (name: string) => `A comment by ${name}`,
|
|
586
642
|
},
|
|
643
|
+
pictures: {
|
|
644
|
+
open: (name: string) => `Open the picture ${name}`,
|
|
645
|
+
label: (name: string) => `The picture ${name}, large`,
|
|
646
|
+
close: "Close",
|
|
647
|
+
zoomIn: "Zoom in",
|
|
648
|
+
zoomOut: "Zoom out",
|
|
649
|
+
fit: "Fit to the screen",
|
|
650
|
+
file: "Open the file itself",
|
|
651
|
+
hint: "Zoom with the wheel, the buttons or two fingers; drag to move; Escape closes.",
|
|
652
|
+
},
|
|
587
653
|
|
|
588
654
|
skills: {
|
|
589
655
|
loading: "Loading the skills",
|
|
@@ -595,13 +661,15 @@ export const en = {
|
|
|
595
661
|
servedBy: "Served by",
|
|
596
662
|
at: "at",
|
|
597
663
|
connect:
|
|
598
|
-
"An agent reads these through its own MCP connection to this address, which a person makes once:",
|
|
664
|
+
"An agent reads these with the console command (console skill <path>), or through its own MCP connection to this address, which a person makes once:",
|
|
599
665
|
connectLink: "how, on the address's page at SkillCDN",
|
|
600
666
|
status: {
|
|
601
667
|
indexing: "SkillCDN is still indexing the repository. Look again in a moment.",
|
|
602
668
|
failed: "SkillCDN could not index the repository. What it found is on the address's page.",
|
|
603
669
|
not_found:
|
|
604
|
-
"SkillCDN does not serve this address, or
|
|
670
|
+
"SkillCDN does not serve this address to the console: there is nothing there, or the pack is private and the project holds no pack token for it (Settings).",
|
|
671
|
+
token_invalid:
|
|
672
|
+
"The pack token the project holds no longer works at SkillCDN: it expired, was removed, or its maker lost the repository. An owner sets a new one on the Settings page.",
|
|
605
673
|
unavailable: "SkillCDN could not be reached. The skills are as they were; look again later.",
|
|
606
674
|
},
|
|
607
675
|
none: {
|
|
@@ -734,6 +802,13 @@ export const en = {
|
|
|
734
802
|
goodUntil: "Good until",
|
|
735
803
|
notActive: "Not active yet",
|
|
736
804
|
lastActive: "Last active",
|
|
805
|
+
command: (version: string) => `console ${version}`,
|
|
806
|
+
commandVerdict: {
|
|
807
|
+
behind: "an update is available",
|
|
808
|
+
ahead: "newer than this console",
|
|
809
|
+
outdated: "must be updated",
|
|
810
|
+
too_new: "too new for this console",
|
|
811
|
+
},
|
|
737
812
|
disconnect: "Disconnect",
|
|
738
813
|
form: {
|
|
739
814
|
name: "Name",
|
package/src/i18n/ko.ts
CHANGED
|
@@ -163,12 +163,24 @@ export const ko: Messages = {
|
|
|
163
163
|
private: "소유자가 지정될 때까지 관리자가 소유합니다.",
|
|
164
164
|
},
|
|
165
165
|
},
|
|
166
|
+
packToken: {
|
|
167
|
+
aria: "팩 토큰",
|
|
168
|
+
label: "토큰",
|
|
169
|
+
hint: "사람이 SkillCDN 계정 페이지에서 팩의 저장소에 대해 만든 토큰입니다. 콘솔이 봉인해 보관하고, 프로젝트를 볼 수 있는 사람을 위해 팩을 읽는 데 쓰며, 누구에게도 보여 주지 않습니다.",
|
|
170
|
+
placeholder: "scdn_repo_…",
|
|
171
|
+
set: "토큰 넣기",
|
|
172
|
+
remove: "토큰 빼기",
|
|
173
|
+
},
|
|
166
174
|
settings: {
|
|
167
175
|
title: "설정",
|
|
168
176
|
aria: "프로젝트 설정",
|
|
169
177
|
edit: "프로젝트 편집",
|
|
170
178
|
organizationsSkills: (address) => `조직의 스킬: ${address}`,
|
|
171
179
|
noSkills: "없음: 콘솔에 조직의 주소가 없습니다.",
|
|
180
|
+
packToken: "팩 토큰",
|
|
181
|
+
packTokenNone: "없음: 공개 팩은 필요 없고, 비공개 팩은 읽히지 않습니다.",
|
|
182
|
+
packTokenSet: "설정됨",
|
|
183
|
+
packTokenEdit: "바꾸기",
|
|
172
184
|
},
|
|
173
185
|
},
|
|
174
186
|
|
|
@@ -179,6 +191,8 @@ export const ko: Messages = {
|
|
|
179
191
|
body: "첫 작업을 쓰세요. 무엇을, 누구를 위해 할지.",
|
|
180
192
|
},
|
|
181
193
|
moveTo: "이동",
|
|
194
|
+
grip: "끌어서 다른 열로",
|
|
195
|
+
archive: "보관함",
|
|
182
196
|
decisions: (n) => `결정 ${n}건`,
|
|
183
197
|
decisionsTitle: "사람을 기다리는 결정",
|
|
184
198
|
filters: {
|
|
@@ -234,6 +248,10 @@ export const ko: Messages = {
|
|
|
234
248
|
: "",
|
|
235
249
|
started: "시작",
|
|
236
250
|
done: "완료",
|
|
251
|
+
archived: "보관됨",
|
|
252
|
+
archivedAt: "보관",
|
|
253
|
+
archive: "보관하기",
|
|
254
|
+
restore: "되살리기",
|
|
237
255
|
form: {
|
|
238
256
|
title: "제목",
|
|
239
257
|
titlePlaceholder: "무엇을 할지, 제목만 보고도 알 수 있게.",
|
|
@@ -354,16 +372,38 @@ export const ko: Messages = {
|
|
|
354
372
|
inProgress: (n) => `${n}개 진행 중`,
|
|
355
373
|
noTasks: "아직 이 목표를 향한 작업이 없습니다.",
|
|
356
374
|
tasks: "작업",
|
|
375
|
+
category: "카테고리",
|
|
376
|
+
noCategory: "카테고리 없음",
|
|
377
|
+
starts: "시작일",
|
|
378
|
+
noStart: "시작일 없음",
|
|
357
379
|
target: "목표일",
|
|
358
380
|
noTarget: "목표일 없음",
|
|
359
381
|
setBy: "세운 사람",
|
|
360
382
|
state: "상태",
|
|
361
383
|
nothingMore: "더 적힌 내용이 없습니다.",
|
|
384
|
+
about: "이루면 무엇이 달라지나",
|
|
385
|
+
archiveTasks: "완료 작업 모두 보관",
|
|
386
|
+
archiveAsk: (n) => `이 목표의 완료·폐기 작업 ${n}건도 함께 보관할까요?`,
|
|
387
|
+
view: "보기",
|
|
388
|
+
views: { board: "보드", list: "목록", calendar: "캘린더" },
|
|
389
|
+
timeline: {
|
|
390
|
+
title: "달별 로드맵",
|
|
391
|
+
legend: "카테고리 색",
|
|
392
|
+
earlier: "한 달 앞으로",
|
|
393
|
+
later: "한 달 뒤로",
|
|
394
|
+
thisMonth: "이번 달",
|
|
395
|
+
today: "오늘",
|
|
396
|
+
nothing: "이 기간에 잡힌 목표가 없습니다.",
|
|
397
|
+
noDays: "날짜 없음",
|
|
398
|
+
},
|
|
362
399
|
form: {
|
|
363
400
|
title: "제목",
|
|
364
401
|
body: "달성의 의미",
|
|
365
402
|
bodyPlaceholder: "목표를 이루면 무엇이 참이 되는지, Markdown으로.",
|
|
366
403
|
state: "상태",
|
|
404
|
+
category: "카테고리",
|
|
405
|
+
noCategory: "카테고리 없음",
|
|
406
|
+
startsOn: "시작일",
|
|
367
407
|
dueOn: "목표일",
|
|
368
408
|
set: "목표 세우기",
|
|
369
409
|
},
|
|
@@ -504,6 +544,8 @@ export const ko: Messages = {
|
|
|
504
544
|
taskUpdated: (fields, task) => `${task}의 ${fields}을(를) 바꿨습니다`,
|
|
505
545
|
taskCommented: (task, excerpt) =>
|
|
506
546
|
`${task}에 댓글을 남겼습니다${excerpt === undefined || excerpt === "" ? "" : `: ${excerpt}`}`,
|
|
547
|
+
taskArchived: (task) => `${task}을(를) 보관했습니다`,
|
|
548
|
+
taskRestored: (task) => `${task}을(를) 되살렸습니다`,
|
|
507
549
|
decisionRaised: (question) => `질문했습니다: ${question}`,
|
|
508
550
|
decisionAnswered: (question, option) => `"${question}"에 답했습니다: ${option}`,
|
|
509
551
|
decisionUpdated: (fields, question) => `결정 "${question}"의 ${fields}을(를) 썼습니다`,
|
|
@@ -523,6 +565,19 @@ export const ko: Messages = {
|
|
|
523
565
|
},
|
|
524
566
|
},
|
|
525
567
|
|
|
568
|
+
archive: {
|
|
569
|
+
title: "보관함",
|
|
570
|
+
lead: "완료·폐기된 뒤 보관된 작업입니다. 보드·목록·캘린더에서는 빠지고, 번호로는 여전히 열립니다. 여기서 되살립니다.",
|
|
571
|
+
loading: "보관함을 불러오는 중",
|
|
572
|
+
empty: {
|
|
573
|
+
title: "보관된 작업이 없습니다",
|
|
574
|
+
body: "완료·폐기된 작업은 작업 페이지에서, 목표를 닫을 때 함께, 또는 일정 기간 뒤 콘솔이 보관합니다.",
|
|
575
|
+
},
|
|
576
|
+
since: "보관",
|
|
577
|
+
restore: "되살리기",
|
|
578
|
+
more: "더 보기",
|
|
579
|
+
},
|
|
580
|
+
|
|
526
581
|
runs: {
|
|
527
582
|
for: "대신:",
|
|
528
583
|
since: "시작",
|
|
@@ -549,6 +604,16 @@ export const ko: Messages = {
|
|
|
549
604
|
picture: (name) => `그림 ${name}`,
|
|
550
605
|
label: (name) => `${name}의 댓글`,
|
|
551
606
|
},
|
|
607
|
+
pictures: {
|
|
608
|
+
open: (name) => `그림 ${name} 크게 보기`,
|
|
609
|
+
label: (name) => `그림 ${name}, 크게`,
|
|
610
|
+
close: "닫기",
|
|
611
|
+
zoomIn: "확대",
|
|
612
|
+
zoomOut: "축소",
|
|
613
|
+
fit: "화면에 맞추기",
|
|
614
|
+
file: "파일 자체 열기",
|
|
615
|
+
hint: "휠·버튼·두 손가락으로 확대와 축소, 끌어서 이동, Esc로 닫기.",
|
|
616
|
+
},
|
|
552
617
|
|
|
553
618
|
skills: {
|
|
554
619
|
loading: "스킬을 불러오는 중",
|
|
@@ -559,13 +624,16 @@ export const ko: Messages = {
|
|
|
559
624
|
},
|
|
560
625
|
servedBy: "제공:",
|
|
561
626
|
at: "주소:",
|
|
562
|
-
connect:
|
|
627
|
+
connect:
|
|
628
|
+
"에이전트는 콘솔 명령(console skill <경로>)으로, 또는 이 주소에 자기 MCP 연결로 스킬을 받습니다. MCP 연결은 사람이 한 번 해 줍니다:",
|
|
563
629
|
connectLink: "SkillCDN 페이지의 연결 안내",
|
|
564
630
|
status: {
|
|
565
631
|
indexing: "SkillCDN이 아직 저장소를 색인하고 있습니다. 잠시 후 다시 보세요.",
|
|
566
632
|
failed: "SkillCDN이 저장소를 색인하지 못했습니다. 찾은 내용은 주소의 페이지에 있습니다.",
|
|
567
633
|
not_found:
|
|
568
|
-
"SkillCDN이 이 주소를 제공하지
|
|
634
|
+
"SkillCDN이 이 주소를 콘솔에 제공하지 않습니다. 그곳에 아무것도 없거나, 비공개 팩인데 프로젝트에 팩 토큰이 없습니다(설정).",
|
|
635
|
+
token_invalid:
|
|
636
|
+
"프로젝트가 가진 팩 토큰이 SkillCDN에서 더 이상 통하지 않습니다. 만료되었거나 지워졌거나, 만든 사람이 저장소 권한을 잃었습니다. 소유자가 설정 페이지에서 새로 넣습니다.",
|
|
569
637
|
unavailable:
|
|
570
638
|
"SkillCDN에 연결할 수 없습니다. 스킬은 이전 상태 그대로입니다. 나중에 다시 보세요.",
|
|
571
639
|
},
|
|
@@ -698,6 +766,13 @@ export const ko: Messages = {
|
|
|
698
766
|
goodUntil: "만료",
|
|
699
767
|
notActive: "아직 활동 없음",
|
|
700
768
|
lastActive: "마지막 활동",
|
|
769
|
+
command: (version) => `console ${version}`,
|
|
770
|
+
commandVerdict: {
|
|
771
|
+
behind: "업데이트할 수 있음",
|
|
772
|
+
ahead: "이 콘솔보다 새 버전",
|
|
773
|
+
outdated: "업데이트 필요",
|
|
774
|
+
too_new: "이 콘솔에는 너무 새 버전",
|
|
775
|
+
},
|
|
701
776
|
disconnect: "연결 끊기",
|
|
702
777
|
form: {
|
|
703
778
|
name: "이름",
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ export {
|
|
|
10
10
|
type BoardFiltersProps,
|
|
11
11
|
type BoardProps,
|
|
12
12
|
byDue,
|
|
13
|
+
columnStateOf,
|
|
13
14
|
filterTasks,
|
|
14
15
|
TaskCard,
|
|
15
16
|
} from "./components/board.js";
|
|
@@ -78,6 +79,7 @@ export {
|
|
|
78
79
|
type GoalListProps,
|
|
79
80
|
GoalView,
|
|
80
81
|
type GoalViewProps,
|
|
82
|
+
goalMonth,
|
|
81
83
|
} from "./components/goals.js";
|
|
82
84
|
export { Markdown, type MarkdownProps } from "./components/markdown.js";
|
|
83
85
|
export { PAGE_SIZE, ShowMore, usePaged } from "./components/paged.js";
|
|
@@ -87,10 +89,32 @@ export {
|
|
|
87
89
|
PeopleList,
|
|
88
90
|
type PeopleListProps,
|
|
89
91
|
} from "./components/people.js";
|
|
92
|
+
export {
|
|
93
|
+
clampScale,
|
|
94
|
+
FITTED,
|
|
95
|
+
Lightbox,
|
|
96
|
+
type LightboxProps,
|
|
97
|
+
MAX_SCALE,
|
|
98
|
+
MIN_SCALE,
|
|
99
|
+
type Picture,
|
|
100
|
+
PictureOverlay,
|
|
101
|
+
type PictureOverlayProps,
|
|
102
|
+
type PictureState,
|
|
103
|
+
PictureThumb,
|
|
104
|
+
type PictureThumbProps,
|
|
105
|
+
type PictureView,
|
|
106
|
+
panBy,
|
|
107
|
+
usePicture,
|
|
108
|
+
wheelFactor,
|
|
109
|
+
ZOOM_STEP,
|
|
110
|
+
zoomAround,
|
|
111
|
+
} from "./components/pictures.js";
|
|
90
112
|
export {
|
|
91
113
|
keyOf,
|
|
92
114
|
MemberList,
|
|
93
115
|
type MemberListProps,
|
|
116
|
+
PackTokenForm,
|
|
117
|
+
type PackTokenFormProps,
|
|
94
118
|
PROJECT_ROLE_LABELS,
|
|
95
119
|
ProjectForm,
|
|
96
120
|
type ProjectFormProps,
|
|
@@ -100,6 +124,13 @@ export {
|
|
|
100
124
|
ProjectRoleBadge,
|
|
101
125
|
VISIBILITY_LABELS,
|
|
102
126
|
} from "./components/projects.js";
|
|
127
|
+
export {
|
|
128
|
+
DEFAULT_TIMELINE_MONTHS,
|
|
129
|
+
GoalTimeline,
|
|
130
|
+
type GoalTimelineProps,
|
|
131
|
+
type TimelineBar,
|
|
132
|
+
timelineBars,
|
|
133
|
+
} from "./components/roadmap.js";
|
|
103
134
|
export {
|
|
104
135
|
RulesForm,
|
|
105
136
|
type RulesFormProps,
|
|
@@ -216,6 +247,9 @@ export {
|
|
|
216
247
|
type DocsView,
|
|
217
248
|
decisionHref,
|
|
218
249
|
docHref,
|
|
250
|
+
GOAL_TASK_VIEWS,
|
|
251
|
+
type GoalPageOptions,
|
|
252
|
+
type GoalTaskView,
|
|
219
253
|
goalHref,
|
|
220
254
|
matchRoute,
|
|
221
255
|
movedFrom,
|
|
@@ -230,6 +264,7 @@ export {
|
|
|
230
264
|
projectHref,
|
|
231
265
|
projectSettingsHref,
|
|
232
266
|
type Route,
|
|
267
|
+
roadmapHref,
|
|
233
268
|
settingsHref,
|
|
234
269
|
signInFailureOf,
|
|
235
270
|
type TaskFormKind,
|
package/src/router.ts
CHANGED
|
@@ -59,22 +59,28 @@ export type Route =
|
|
|
59
59
|
readonly month: string | undefined;
|
|
60
60
|
readonly filter: BoardFilter;
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
/** The roadmap of a project: the months shown from the one named, or from this one. */
|
|
63
|
+
| { readonly name: "roadmap"; readonly project: string; readonly from: string | undefined }
|
|
63
64
|
| { readonly name: "new-goal"; readonly project: string }
|
|
65
|
+
/** One goal: its tasks as a board, a list or a calendar (on a month, or this one), or its form. */
|
|
64
66
|
| {
|
|
65
67
|
readonly name: "goal";
|
|
66
68
|
readonly project: string;
|
|
67
69
|
readonly id: string;
|
|
68
70
|
readonly form: "edit" | undefined;
|
|
71
|
+
readonly view: GoalTaskView;
|
|
72
|
+
readonly month: string | undefined;
|
|
69
73
|
}
|
|
70
74
|
| { readonly name: "feed"; readonly project: string }
|
|
75
|
+
/** The archive of a project's board (ADR-0029): the tasks put away, read a page at a time. */
|
|
76
|
+
| { readonly name: "archive"; readonly project: string }
|
|
71
77
|
| { readonly name: "skills"; readonly project: string }
|
|
72
78
|
| { readonly name: "members"; readonly project: string }
|
|
73
79
|
/** A project's settings, read; or one of its forms open: the project's own, or its rules (ADR-0023). */
|
|
74
80
|
| {
|
|
75
81
|
readonly name: "settings";
|
|
76
82
|
readonly project: string;
|
|
77
|
-
readonly form: "edit" | "rules" | undefined;
|
|
83
|
+
readonly form: "edit" | "rules" | "pack-token" | undefined;
|
|
78
84
|
}
|
|
79
85
|
/** The workspace's settings: its rules, its categories, its skills; or the form the rules are written on. */
|
|
80
86
|
| { readonly name: "workspace-settings"; readonly form: "rules" | undefined }
|
|
@@ -110,6 +116,7 @@ export type Route =
|
|
|
110
116
|
export type ProjectPage =
|
|
111
117
|
| "docs"
|
|
112
118
|
| "decisions"
|
|
119
|
+
| "archive"
|
|
113
120
|
| "calendar"
|
|
114
121
|
| "roadmap"
|
|
115
122
|
| "feed"
|
|
@@ -150,6 +157,7 @@ const CODE_TEXT = /^[A-Za-z0-9-]{1,16}$/;
|
|
|
150
157
|
/** The pages of a project that take nothing after their name. */
|
|
151
158
|
const PLAIN_PAGES: readonly Exclude<ProjectPage, "docs" | "calendar" | "roadmap" | "settings">[] = [
|
|
152
159
|
"decisions",
|
|
160
|
+
"archive",
|
|
153
161
|
"feed",
|
|
154
162
|
"skills",
|
|
155
163
|
"members",
|
|
@@ -330,9 +338,23 @@ export function matchRoute(pathname: string, search = ""): Route {
|
|
|
330
338
|
if (third === "new") {
|
|
331
339
|
return { name: "new-goal", project };
|
|
332
340
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
341
|
+
if (!UUID.test(third)) {
|
|
342
|
+
return NOT_FOUND;
|
|
343
|
+
}
|
|
344
|
+
const named = params.get("view");
|
|
345
|
+
const view = named === null ? "board" : isGoalTaskView(named) ? named : undefined;
|
|
346
|
+
const month = params.get("month");
|
|
347
|
+
if (view === undefined || (month !== null && !isMonth(month))) {
|
|
348
|
+
return NOT_FOUND;
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
name: "goal",
|
|
352
|
+
project,
|
|
353
|
+
id: third,
|
|
354
|
+
form: params.has("edit") ? "edit" : undefined,
|
|
355
|
+
view,
|
|
356
|
+
month: month ?? undefined,
|
|
357
|
+
};
|
|
336
358
|
}
|
|
337
359
|
if (third !== undefined) {
|
|
338
360
|
return NOT_FOUND;
|
|
@@ -345,13 +367,23 @@ export function matchRoute(pathname: string, search = ""): Route {
|
|
|
345
367
|
return { name: "calendar", project, month: month ?? undefined, filter: boardFilterOf(params) };
|
|
346
368
|
}
|
|
347
369
|
if (page === "roadmap") {
|
|
348
|
-
|
|
370
|
+
const from = params.get("from");
|
|
371
|
+
if (from !== null && !isMonth(from)) {
|
|
372
|
+
return NOT_FOUND;
|
|
373
|
+
}
|
|
374
|
+
return { name: "roadmap", project, from: from ?? undefined };
|
|
349
375
|
}
|
|
350
376
|
if (page === "settings") {
|
|
351
377
|
return {
|
|
352
378
|
name: "settings",
|
|
353
379
|
project,
|
|
354
|
-
form: params.has("edit")
|
|
380
|
+
form: params.has("edit")
|
|
381
|
+
? "edit"
|
|
382
|
+
: params.has("rules")
|
|
383
|
+
? "rules"
|
|
384
|
+
: params.has("pack-token")
|
|
385
|
+
? "pack-token"
|
|
386
|
+
: undefined,
|
|
355
387
|
};
|
|
356
388
|
}
|
|
357
389
|
const found = PLAIN_PAGES.find((candidate) => candidate === page);
|
|
@@ -381,7 +413,7 @@ export function projectHref(key: string, page?: ProjectPage): string {
|
|
|
381
413
|
}
|
|
382
414
|
|
|
383
415
|
/** Where a project's settings are read, or one of their forms is open: the project's own, or its rules. */
|
|
384
|
-
export function projectSettingsHref(key: string, form?: "edit" | "rules"): string {
|
|
416
|
+
export function projectSettingsHref(key: string, form?: "edit" | "rules" | "pack-token"): string {
|
|
385
417
|
const base = projectHref(key, "settings");
|
|
386
418
|
return form === undefined ? base : `${base}?${form}`;
|
|
387
419
|
}
|
|
@@ -455,14 +487,41 @@ export function customPageHref(page: string, project?: string): string {
|
|
|
455
487
|
}
|
|
456
488
|
|
|
457
489
|
/** Where a goal is set: the form. */
|
|
490
|
+
/** Where a project's roadmap is, from a month on, or from this one when none is named. */
|
|
491
|
+
export function roadmapHref(key: string, from?: string): string {
|
|
492
|
+
const base = projectHref(key, "roadmap");
|
|
493
|
+
return from === undefined ? base : `${base}?from=${from}`;
|
|
494
|
+
}
|
|
495
|
+
|
|
458
496
|
export function newGoalHref(key: string): string {
|
|
459
497
|
return `${PATHS.project}/${key}/roadmap/new`;
|
|
460
498
|
}
|
|
461
499
|
|
|
462
|
-
/**
|
|
463
|
-
export
|
|
500
|
+
/** The views of a goal's tasks: the board of them, the list by state, or the calendar. */
|
|
501
|
+
export const GOAL_TASK_VIEWS = ["board", "list", "calendar"] as const;
|
|
502
|
+
export type GoalTaskView = (typeof GOAL_TASK_VIEWS)[number];
|
|
503
|
+
|
|
504
|
+
function isGoalTaskView(value: string): value is GoalTaskView {
|
|
505
|
+
return (GOAL_TASK_VIEWS as readonly string[]).includes(value);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/** What a goal's address may say besides the goal: its form, the view of its tasks, the calendar's month. */
|
|
509
|
+
export interface GoalPageOptions {
|
|
510
|
+
readonly form?: "edit" | undefined;
|
|
511
|
+
/** The board is the view an address without one shows. */
|
|
512
|
+
readonly view?: GoalTaskView | undefined;
|
|
513
|
+
readonly month?: string | undefined;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/** Where one goal is read, in a view of its tasks, or changed. */
|
|
517
|
+
export function goalHref(key: string, id: string, options: GoalPageOptions = {}): string {
|
|
464
518
|
const base = `${PATHS.project}/${key}/roadmap/${id}`;
|
|
465
|
-
|
|
519
|
+
const parts = [
|
|
520
|
+
...(options.form === undefined ? [] : [options.form]),
|
|
521
|
+
...(options.view === undefined || options.view === "board" ? [] : [`view=${options.view}`]),
|
|
522
|
+
...(options.month === undefined ? [] : [`month=${options.month}`]),
|
|
523
|
+
];
|
|
524
|
+
return parts.length === 0 ? base : `${base}?${parts.join("&")}`;
|
|
466
525
|
}
|
|
467
526
|
|
|
468
527
|
/**
|