@skillcdn/console 0.1.13 → 0.1.15

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.
Files changed (170) hide show
  1. package/README.md +5 -4
  2. package/SKILLCDN.md +2 -0
  3. package/dist/agent-name.d.ts +3 -0
  4. package/dist/agent-name.d.ts.map +1 -0
  5. package/dist/agent-name.js +9 -0
  6. package/dist/agent-name.js.map +1 -0
  7. package/dist/api.d.ts +6 -4
  8. package/dist/api.d.ts.map +1 -1
  9. package/dist/api.js +6 -4
  10. package/dist/api.js.map +1 -1
  11. package/dist/cli/cli.d.ts +2 -0
  12. package/dist/cli/cli.d.ts.map +1 -1
  13. package/dist/cli/cli.js +215 -22
  14. package/dist/cli/cli.js.map +1 -1
  15. package/dist/cli/format.d.ts +14 -4
  16. package/dist/cli/format.d.ts.map +1 -1
  17. package/dist/cli/format.js +59 -10
  18. package/dist/cli/format.js.map +1 -1
  19. package/dist/cli/help.d.ts.map +1 -1
  20. package/dist/cli/help.js +27 -11
  21. package/dist/cli/help.js.map +1 -1
  22. package/dist/cli/main.js +5 -0
  23. package/dist/cli/main.js.map +1 -1
  24. package/dist/client.d.ts +20 -2
  25. package/dist/client.d.ts.map +1 -1
  26. package/dist/client.js +11 -2
  27. package/dist/client.js.map +1 -1
  28. package/dist/components/calendar.d.ts +15 -0
  29. package/dist/components/calendar.d.ts.map +1 -1
  30. package/dist/components/calendar.js +78 -41
  31. package/dist/components/calendar.js.map +1 -1
  32. package/dist/components/connect.d.ts +4 -1
  33. package/dist/components/connect.d.ts.map +1 -1
  34. package/dist/components/connect.js +7 -3
  35. package/dist/components/connect.js.map +1 -1
  36. package/dist/components/decision-list.d.ts.map +1 -1
  37. package/dist/components/decision-list.js +3 -3
  38. package/dist/components/decision-list.js.map +1 -1
  39. package/dist/components/documents.d.ts +5 -0
  40. package/dist/components/documents.d.ts.map +1 -1
  41. package/dist/components/documents.js +3 -2
  42. package/dist/components/documents.js.map +1 -1
  43. package/dist/components/event-feed.d.ts +1 -1
  44. package/dist/components/event-feed.d.ts.map +1 -1
  45. package/dist/components/event-feed.js +10 -1
  46. package/dist/components/event-feed.js.map +1 -1
  47. package/dist/components/people.d.ts +24 -1
  48. package/dist/components/people.d.ts.map +1 -1
  49. package/dist/components/people.js +35 -3
  50. package/dist/components/people.js.map +1 -1
  51. package/dist/components/projects.d.ts +6 -0
  52. package/dist/components/projects.d.ts.map +1 -1
  53. package/dist/components/projects.js +3 -3
  54. package/dist/components/projects.js.map +1 -1
  55. package/dist/components/rules.d.ts +40 -0
  56. package/dist/components/rules.d.ts.map +1 -0
  57. package/dist/components/rules.js +46 -0
  58. package/dist/components/rules.js.map +1 -0
  59. package/dist/components/runs.d.ts +1 -1
  60. package/dist/components/runs.d.ts.map +1 -1
  61. package/dist/components/runs.js +2 -1
  62. package/dist/components/runs.js.map +1 -1
  63. package/dist/components/skills.d.ts.map +1 -1
  64. package/dist/components/skills.js +5 -1
  65. package/dist/components/skills.js.map +1 -1
  66. package/dist/components/tokens.d.ts.map +1 -1
  67. package/dist/components/tokens.js +2 -9
  68. package/dist/components/tokens.js.map +1 -1
  69. package/dist/components/ui.d.ts +7 -2
  70. package/dist/components/ui.d.ts.map +1 -1
  71. package/dist/components/ui.js +13 -0
  72. package/dist/components/ui.js.map +1 -1
  73. package/dist/components/work.d.ts +9 -1
  74. package/dist/components/work.d.ts.map +1 -1
  75. package/dist/components/work.js +8 -3
  76. package/dist/components/work.js.map +1 -1
  77. package/dist/connect-page.d.ts.map +1 -1
  78. package/dist/connect-page.js +1 -1
  79. package/dist/connect-page.js.map +1 -1
  80. package/dist/console.css +253 -13
  81. package/dist/console.d.ts.map +1 -1
  82. package/dist/console.js +203 -49
  83. package/dist/console.js.map +1 -1
  84. package/dist/data.d.ts +19 -2
  85. package/dist/data.d.ts.map +1 -1
  86. package/dist/data.js +27 -1
  87. package/dist/data.js.map +1 -1
  88. package/dist/dates.d.ts +4 -0
  89. package/dist/dates.d.ts.map +1 -1
  90. package/dist/dates.js +26 -0
  91. package/dist/dates.js.map +1 -1
  92. package/dist/i18n/en.d.ts +90 -28
  93. package/dist/i18n/en.d.ts.map +1 -1
  94. package/dist/i18n/en.js +89 -31
  95. package/dist/i18n/en.js.map +1 -1
  96. package/dist/i18n/ko.d.ts.map +1 -1
  97. package/dist/i18n/ko.js +89 -31
  98. package/dist/i18n/ko.js.map +1 -1
  99. package/dist/index.d.ts +6 -5
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +6 -5
  102. package/dist/index.js.map +1 -1
  103. package/dist/limits.d.ts +4 -0
  104. package/dist/limits.d.ts.map +1 -1
  105. package/dist/limits.js +4 -0
  106. package/dist/limits.js.map +1 -1
  107. package/dist/router.d.ts +34 -2
  108. package/dist/router.d.ts.map +1 -1
  109. package/dist/router.js +55 -7
  110. package/dist/router.js.map +1 -1
  111. package/dist/routes.d.ts +14 -4
  112. package/dist/routes.d.ts.map +1 -1
  113. package/dist/routes.js +17 -2
  114. package/dist/routes.js.map +1 -1
  115. package/dist/rules.d.ts +28 -0
  116. package/dist/rules.d.ts.map +1 -0
  117. package/dist/rules.js +102 -0
  118. package/dist/rules.js.map +1 -0
  119. package/dist/schemas.d.ts +652 -4
  120. package/dist/schemas.d.ts.map +1 -1
  121. package/dist/schemas.js +96 -6
  122. package/dist/schemas.js.map +1 -1
  123. package/dist/vocabulary.d.ts +21 -1
  124. package/dist/vocabulary.d.ts.map +1 -1
  125. package/dist/vocabulary.js +21 -0
  126. package/dist/vocabulary.js.map +1 -1
  127. package/docs/specs/cli.md +13 -9
  128. package/docs/specs/rest.md +32 -8
  129. package/package.json +1 -1
  130. package/skills/building-a-console/SKILL.md +1 -1
  131. package/skills/deploying-a-console/SKILL.md +5 -5
  132. package/skills/deploying-a-console/assets/secrets.example.json +2 -1
  133. package/skills/deploying-a-console/references/access.md +10 -6
  134. package/skills/deploying-a-console/references/resources.md +10 -7
  135. package/skills/working-the-board/SKILL.md +10 -9
  136. package/skills/working-the-board/references/project-rules.md +36 -0
  137. package/src/agent-name.ts +9 -0
  138. package/src/api.ts +37 -0
  139. package/src/cli/cli.ts +253 -24
  140. package/src/cli/format.ts +74 -10
  141. package/src/cli/help.ts +30 -10
  142. package/src/cli/main.ts +5 -0
  143. package/src/client.ts +47 -1
  144. package/src/components/calendar.tsx +242 -101
  145. package/src/components/connect.tsx +12 -6
  146. package/src/components/decision-list.tsx +2 -2
  147. package/src/components/documents.tsx +7 -3
  148. package/src/components/event-feed.tsx +16 -3
  149. package/src/components/people.tsx +244 -35
  150. package/src/components/projects.tsx +31 -8
  151. package/src/components/rules.tsx +167 -0
  152. package/src/components/runs.tsx +4 -2
  153. package/src/components/skills.tsx +22 -11
  154. package/src/components/tokens.tsx +2 -14
  155. package/src/components/ui.tsx +25 -2
  156. package/src/components/work.tsx +69 -43
  157. package/src/connect-page.tsx +0 -1
  158. package/src/console.tsx +531 -67
  159. package/src/data.ts +52 -2
  160. package/src/dates.ts +28 -0
  161. package/src/i18n/en.ts +99 -38
  162. package/src/i18n/ko.ts +95 -38
  163. package/src/index.ts +21 -1
  164. package/src/limits.ts +4 -0
  165. package/src/router.ts +77 -12
  166. package/src/routes.ts +23 -3
  167. package/src/rules.ts +109 -0
  168. package/src/schemas.ts +121 -4
  169. package/src/styles/console.css +253 -13
  170. package/src/vocabulary.ts +30 -0
@@ -6,7 +6,7 @@ import {
6
6
  type RestTokenInput,
7
7
  } from "../api.js";
8
8
  import { useWords } from "../i18n/index.js";
9
- import { Button, Callout, Time } from "./ui.js";
9
+ import { Button, Callout, CopyButton, Time } from "./ui.js";
10
10
 
11
11
  // The tokens a person holds for their agents, scripts and consoles of their own, shown as the
12
12
  // agents that hold them: the list, the way to make one by hand, and the one just made, whose
@@ -180,16 +180,6 @@ export interface NewTokenProps {
180
180
  export function NewToken(props: NewTokenProps) {
181
181
  const words = useWords();
182
182
  const fresh = words.agents.fresh;
183
- const [copied, setCopied] = useState(false);
184
- const copy = () => {
185
- if (typeof navigator === "undefined" || navigator.clipboard === undefined) {
186
- return;
187
- }
188
- void navigator.clipboard.writeText(props.secret).then(
189
- () => setCopied(true),
190
- () => setCopied(false),
191
- );
192
- };
193
183
  return (
194
184
  <Callout
195
185
  tone="warning"
@@ -203,9 +193,7 @@ export function NewToken(props: NewTokenProps) {
203
193
  <p>{fresh.copyNow}</p>
204
194
  <p className="sc-secret">
205
195
  <code className="sc-secret-value">{props.secret}</code>
206
- <Button size="sm" onClick={copy}>
207
- {copied ? fresh.copied : fresh.copy}
208
- </Button>
196
+ <CopyButton text={props.secret} size="sm" />
209
197
  </p>
210
198
  <p>
211
199
  {fresh.useIt}{" "}
@@ -1,4 +1,4 @@
1
- import type { ButtonHTMLAttributes, ReactNode } from "react";
1
+ import { type ButtonHTMLAttributes, type ReactNode, useState } from "react";
2
2
  import {
3
3
  type CategoryColor,
4
4
  type GoalState,
@@ -87,7 +87,10 @@ export function personName(person: {
87
87
  * A person's picture as the git host serves it: loaded lazily, without a referrer, and gone as
88
88
  * a whole when there is none or it cannot be loaded, leaving the initial of the name instead.
89
89
  */
90
- export function Avatar(props: { readonly person: RestPerson; readonly size?: "sm" | "md" | "lg" }) {
90
+ export function Avatar(props: {
91
+ readonly person: RestPerson;
92
+ readonly size?: "xs" | "sm" | "md" | "lg";
93
+ }) {
91
94
  const size = props.size ?? "md";
92
95
  const initial = personName(props.person).slice(0, 1).toUpperCase();
93
96
  if (props.person.avatar === null) {
@@ -112,6 +115,26 @@ export function Avatar(props: { readonly person: RestPerson; readonly size?: "sm
112
115
  );
113
116
  }
114
117
 
118
+ /** Puts a text on the clipboard, where the browser offers one, and says so once it is there. */
119
+ export function CopyButton(props: { readonly text: string; readonly size?: "md" | "sm" }) {
120
+ const words = useWords().common;
121
+ const [copied, setCopied] = useState(false);
122
+ const copy = () => {
123
+ if (typeof navigator === "undefined" || navigator.clipboard === undefined) {
124
+ return;
125
+ }
126
+ void navigator.clipboard.writeText(props.text).then(
127
+ () => setCopied(true),
128
+ () => setCopied(false),
129
+ );
130
+ };
131
+ return (
132
+ <Button size={props.size ?? "md"} onClick={copy}>
133
+ {copied ? words.copied : words.copy}
134
+ </Button>
135
+ );
136
+ }
137
+
115
138
  /** A person, as a picture and their name, wherever one is named; the login is there on hover. */
116
139
  export function PersonChip(props: { readonly person: RestPerson; readonly size?: "sm" | "md" }) {
117
140
  return (
@@ -1,20 +1,30 @@
1
1
  import type { RestTask, RestWork } from "../api.js";
2
2
  import { addDays, today as todayOf } from "../dates.js";
3
3
  import { useWords } from "../i18n/index.js";
4
+ import { Week } from "./calendar.js";
4
5
  import { ProjectMark } from "./projects.js";
5
6
  import { TaskList } from "./task-list.js";
6
7
  import { PersonChip, Time } from "./ui.js";
7
8
 
8
- // What is on a person's plate (ADR-0019), across the projects they may see: the open tasks
9
- // assigned to them, by when they are due, and the decisions that wait for a person. Takes its
10
- // data as props and nothing from the network.
9
+ // What is on a person's plate (ADR-0019), across the projects they may see: the week at the
10
+ // top, with the open tasks assigned to them on its days; below, the same tasks by when they
11
+ // are due, and the decisions that wait for a person. Takes its data as props and nothing from
12
+ // the network; the week shown is the address's (ADR-0010).
11
13
 
12
14
  export interface WorkListProps {
13
- readonly work: RestWork;
15
+ /** The tasks on the plate; and the decisions waiting on the person's own plate, left out on another's. */
16
+ readonly work: {
17
+ readonly tasks: RestWork["tasks"];
18
+ readonly decisions?: RestWork["decisions"] | undefined;
19
+ };
14
20
  /** The day to count from; the browser's today when left out. */
15
21
  readonly today?: string | undefined;
22
+ /** A day of the week shown at the top; today's week when left out. */
23
+ readonly week?: string | undefined;
16
24
  readonly taskHref: (projectKey: string, task: RestTask) => string;
17
25
  readonly decisionHref: (projectKey: string, decisionId: string) => string;
26
+ /** Where the page is with the week of a day at the top. */
27
+ readonly weekHref: (day: string) => string;
18
28
  }
19
29
 
20
30
  export function WorkList(props: WorkListProps) {
@@ -25,6 +35,10 @@ export function WorkList(props: WorkListProps) {
25
35
  const { tasks, decisions } = props.work;
26
36
  const projectOf = new Map(tasks.map((item) => [item.task.id, item.project]));
27
37
  const hrefOf = (task: RestTask) => props.taskHref(projectOf.get(task.id)?.key ?? "", task);
38
+ const markOf = (task: RestTask) => {
39
+ const project = projectOf.get(task.id);
40
+ return project === undefined ? undefined : <ProjectMark project={project} size="sm" />;
41
+ };
28
42
  const nameOf = (task: RestTask) => {
29
43
  const project = projectOf.get(task.id);
30
44
  return project === undefined ? undefined : (
@@ -45,49 +59,61 @@ export function WorkList(props: WorkListProps) {
45
59
  }
46
60
  return (
47
61
  <div className="sc-work">
48
- {groups
49
- .filter((group) => group.tasks.length > 0)
50
- .map((group) => (
51
- <section key={group.title} className="sc-task-section" aria-label={group.title}>
62
+ <Week
63
+ tasks={tasks.map((item) => item.task)}
64
+ day={props.week}
65
+ today={now}
66
+ taskHref={hrefOf}
67
+ weekHref={props.weekHref}
68
+ markOf={markOf}
69
+ />
70
+ <div className="sc-work-lists">
71
+ {groups
72
+ .filter((group) => group.tasks.length > 0)
73
+ .map((group) => (
74
+ <section key={group.title} className="sc-task-section" aria-label={group.title}>
75
+ <h2 className="sc-section-title">
76
+ {group.title} <span className="sc-column-count">{group.tasks.length}</span>
77
+ </h2>
78
+ <TaskList
79
+ tasks={group.tasks}
80
+ taskHref={hrefOf}
81
+ projectOf={nameOf}
82
+ showState
83
+ today={now}
84
+ />
85
+ </section>
86
+ ))}
87
+ {decisions !== undefined && (
88
+ <section className="sc-task-section" aria-label={work.decisions}>
52
89
  <h2 className="sc-section-title">
53
- {group.title} <span className="sc-column-count">{group.tasks.length}</span>
90
+ {work.decisions} <span className="sc-column-count">{decisions.length}</span>
54
91
  </h2>
55
- <TaskList
56
- tasks={group.tasks}
57
- taskHref={hrefOf}
58
- projectOf={nameOf}
59
- showState
60
- today={now}
61
- />
92
+ {decisions.length === 0 ? (
93
+ <p className="sc-muted">{work.noDecisions}</p>
94
+ ) : (
95
+ <ol className="sc-decision-log">
96
+ {decisions.map(({ project, decision }) => (
97
+ <li key={decision.id} className="sc-decision-row">
98
+ <a
99
+ className="sc-decision-row-question"
100
+ href={props.decisionHref(project.key, decision.id)}
101
+ >
102
+ {decision.question}
103
+ </a>
104
+ <span className="sc-task-row-project">
105
+ <ProjectMark project={project} size="sm" /> {work.inProject(project.name)}
106
+ </span>
107
+ <span className="sc-decision-row-meta">
108
+ <PersonChip person={decision.raisedBy} /> <Time iso={decision.createdAt} />
109
+ </span>
110
+ </li>
111
+ ))}
112
+ </ol>
113
+ )}
62
114
  </section>
63
- ))}
64
- <section className="sc-task-section" aria-label={work.decisions}>
65
- <h2 className="sc-section-title">
66
- {work.decisions} <span className="sc-column-count">{decisions.length}</span>
67
- </h2>
68
- {decisions.length === 0 ? (
69
- <p className="sc-muted">{work.noDecisions}</p>
70
- ) : (
71
- <ol className="sc-decision-log">
72
- {decisions.map(({ project, decision }) => (
73
- <li key={decision.id} className="sc-decision-row">
74
- <a
75
- className="sc-decision-row-question"
76
- href={props.decisionHref(project.key, decision.id)}
77
- >
78
- {decision.question}
79
- </a>
80
- <span className="sc-task-row-project">
81
- <ProjectMark project={project} size="sm" /> {work.inProject(project.name)}
82
- </span>
83
- <span className="sc-decision-row-meta">
84
- <PersonChip person={decision.raisedBy} /> <Time iso={decision.createdAt} />
85
- </span>
86
- </li>
87
- ))}
88
- </ol>
89
115
  )}
90
- </section>
116
+ </div>
91
117
  </div>
92
118
  );
93
119
  }
@@ -70,7 +70,6 @@ export function ConnectPage(props: ConnectPageProps) {
70
70
  );
71
71
  const ask = (
72
72
  <>
73
- <p className="sc-lead">{words.lead}</p>
74
73
  <section className="sc-panel" aria-label={words.aria}>
75
74
  <ConnectCodeForm busy={busy} onSubmit={(typed) => navigation.go(connectHref(typed))} />
76
75
  </section>