@skillcdn/console 0.1.1 → 0.1.3
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 +15 -10
- package/dist/api.d.ts +6 -5
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +5 -4
- package/dist/api.js.map +1 -1
- package/dist/cli/cli.d.ts +3 -0
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +251 -44
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/directory.d.ts +14 -0
- package/dist/cli/directory.d.ts.map +1 -0
- package/dist/cli/directory.js +46 -0
- package/dist/cli/directory.js.map +1 -0
- package/dist/cli/format.d.ts +15 -3
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +84 -6
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +78 -9
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.js +2 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/client.d.ts +69 -10
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +71 -33
- package/dist/client.js.map +1 -1
- package/dist/components/decision-list.d.ts +7 -1
- package/dist/components/decision-list.d.ts.map +1 -1
- package/dist/components/decision-list.js +21 -4
- package/dist/components/decision-list.js.map +1 -1
- package/dist/components/documents.d.ts +85 -0
- package/dist/components/documents.d.ts.map +1 -0
- package/dist/components/documents.js +103 -0
- package/dist/components/documents.js.map +1 -0
- package/dist/components/event-feed.d.ts.map +1 -1
- package/dist/components/event-feed.js +46 -14
- package/dist/components/event-feed.js.map +1 -1
- package/dist/components/markdown.d.ts +5 -2
- package/dist/components/markdown.d.ts.map +1 -1
- package/dist/components/markdown.js +8 -1
- package/dist/components/markdown.js.map +1 -1
- package/dist/components/projects.d.ts +41 -0
- package/dist/components/projects.d.ts.map +1 -0
- package/dist/components/projects.js +81 -0
- package/dist/components/projects.js.map +1 -0
- package/dist/components/runs.d.ts +5 -2
- package/dist/components/runs.d.ts.map +1 -1
- package/dist/components/runs.js +4 -4
- package/dist/components/runs.js.map +1 -1
- package/dist/components/shell.d.ts +5 -0
- package/dist/components/shell.d.ts.map +1 -1
- package/dist/components/shell.js +1 -1
- package/dist/components/shell.js.map +1 -1
- package/dist/components/task-view.d.ts +9 -1
- package/dist/components/task-view.d.ts.map +1 -1
- package/dist/components/task-view.js +3 -2
- package/dist/components/task-view.js.map +1 -1
- package/dist/console.css +253 -1
- package/dist/console.d.ts +3 -0
- package/dist/console.d.ts.map +1 -1
- package/dist/console.js +156 -58
- package/dist/console.js.map +1 -1
- package/dist/data.d.ts +44 -10
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +215 -81
- package/dist/data.js.map +1 -1
- package/dist/docs-page.d.ts +11 -0
- package/dist/docs-page.d.ts.map +1 -0
- package/dist/docs-page.js +146 -0
- package/dist/docs-page.js.map +1 -0
- package/dist/documents.d.ts +19 -0
- package/dist/documents.d.ts.map +1 -0
- package/dist/documents.js +64 -0
- package/dist/documents.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/limits.d.ts +17 -0
- package/dist/limits.d.ts.map +1 -1
- package/dist/limits.js +17 -0
- package/dist/limits.js.map +1 -1
- package/dist/router.d.ts +28 -7
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +52 -23
- package/dist/router.js.map +1 -1
- package/dist/routes.d.ts +16 -12
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +31 -11
- package/dist/routes.js.map +1 -1
- package/dist/schemas.d.ts +414 -28
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +204 -27
- package/dist/schemas.js.map +1 -1
- package/dist/use-action.d.ts +8 -0
- package/dist/use-action.d.ts.map +1 -0
- package/dist/use-action.js +30 -0
- package/dist/use-action.js.map +1 -0
- package/dist/vocabulary.d.ts +10 -1
- package/dist/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary.js +16 -0
- package/dist/vocabulary.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-view.js","sourceRoot":"","sources":["../../src/components/task-view.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"task-view.js","sourceRoot":"","sources":["../../src/components/task-view.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAcjC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAoC5F,MAAM,UAAU,QAAQ,CAAC,KAAoB;IAC3C,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACvB,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,MAAM,GACV,IAAI,CAAC,QAAQ,KAAK,IAAI;QACpB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;IACnF,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;IAChF,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAErF,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CACL,eAAK,SAAS,EAAC,SAAS,aACtB,cAAI,SAAS,EAAC,eAAe,aAC3B,gBAAM,SAAS,EAAC,gBAAgB,kBAAG,IAAI,CAAC,MAAM,IAAQ,OAAE,IAAI,CAAC,KAAK,IAC/D,EACL,KAAC,QAAQ,IACP,MAAM,EAAE,KAAK,CAAC,MAAM,EACpB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,KAAK,CAAC,KAAK,EACpB,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;wBAClB,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;wBAC5B,UAAU,CAAC,KAAK,CAAC,CAAC;oBACpB,CAAC,EACD,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,GACjC,IACE,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,eAAK,SAAS,EAAC,SAAS,aACtB,kBAAQ,SAAS,EAAC,gBAAgB,aAC/B,MAAM,KAAK,SAAS,IAAI,CACvB,aAAG,SAAS,EAAC,gBAAgB,wBACnB,GAAG,EACX,aAAG,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,kBAC3B,MAAM,CAAC,MAAM,OAAG,MAAM,CAAC,KAAK,IAC5B,IACF,CACL,EACD,cAAI,SAAS,EAAC,eAAe,aAC3B,gBAAM,SAAS,EAAC,gBAAgB,kBAAG,IAAI,CAAC,MAAM,IAAQ,OAAE,IAAI,CAAC,KAAK,IAC/D,EACL,eAAK,SAAS,EAAC,gBAAgB,aAC7B,KAAC,UAAU,IAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAI,EACjC,KAAC,aAAa,IAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,GAAI,IACtC,IACC,EACT,cAAI,SAAS,EAAC,UAAU,aACtB,0BACE,iCAAc,EACd,uBACE,KAAC,UAAU,IAAC,MAAM,EAAE,IAAI,CAAC,KAAK,GAAI,GAC/B,IACD,EACN,0BACE,oCAAiB,EACjB,uBACG,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,CACxB,eAAM,SAAS,EAAC,UAAU,uBAAc,CACzC,CAAC,CAAC,CAAC,CACF,KAAC,UAAU,IAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,GAAI,CACtC,GACE,IACD,EACN,0BACE,mCAAgB,EAChB,uBACE,KAAC,IAAI,IAAC,GAAG,EAAE,IAAI,CAAC,SAAS,GAAI,GAC1B,IACD,EACN,0BACE,mCAAgB,EAChB,uBACE,KAAC,IAAI,IAAC,GAAG,EAAE,IAAI,CAAC,SAAS,GAAI,GAC1B,IACD,IACH,EACL,eAAK,SAAS,EAAC,iBAAiB,aAC9B,iBAAO,SAAS,EAAC,0BAA0B,aACzC,eAAM,SAAS,EAAC,gBAAgB,sBAAa,EAC7C,iBACE,SAAS,EAAC,UAAU,EACpB,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,QAAQ,EAAE,KAAK,CAAC,IAAI,KAAK,IAAI,EAC7B,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAkB,CAAC,YAEvE,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAC1B,iBAAoB,KAAK,EAAE,KAAK,YAC7B,YAAY,CAAC,KAAK,CAAC,IADT,KAAK,CAET,CACV,CAAC,GACK,IACH,EACR,KAAC,MAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,qBAAe,EACtD,KAAC,MAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,iCAE/C,IACL,EACL,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,CAC5B,YAAG,SAAS,EAAC,eAAe,EAAC,IAAI,EAAC,OAAO,YACtC,KAAK,CAAC,KAAK,GACV,CACL,EACA,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACtB,KAAC,QAAQ,IAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,GAAI,CACxD,CAAC,CAAC,CAAC,CACF,YAAG,SAAS,EAAC,UAAU,mDAAuC,CAC/D,EACA,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CACxB,mBAAS,SAAS,EAAC,iBAAiB,gBAAY,OAAO,aACrD,aAAI,SAAS,EAAC,kBAAkB,sBAAW,EAC3C,aAAI,SAAS,EAAC,cAAc,YACzB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACxB,uBACE,YAAG,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,8BAA8B,YAClE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,GACrB,IAHG,IAAI,CAAC,GAAG,CAIZ,CACN,CAAC,GACC,IACG,CACX,EACA,MAAM,IAAI,CACT,mBAAS,SAAS,EAAC,iBAAiB,gBAAY,kBAAkB,aAChE,aAAI,SAAS,EAAC,kBAAkB,iCAAsB,EACtD,KAAC,YAAY,IACX,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,MAAM,EAAE,IAAI,CAAC,EAAE,EACf,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;4BAClB,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;4BAC7B,SAAS,CAAC,KAAK,CAAC,CAAC;wBACnB,CAAC,EACD,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,GAChC,IACM,CACX,EACA,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAClB,mBAAS,SAAS,EAAC,iBAAiB,gBAAY,MAAM,aACpD,aAAI,SAAS,EAAC,kBAAkB,+BAAoB,EACpD,KAAC,OAAO,IACN,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,KAAK,CAAC,YAAY,EAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,SAAS,EAAE,KAAK,CAAC,YAAY,EAC7B,IAAI,EAAE,KAAK,CAAC,IAAI,GAChB,IACM,CACX,EACA,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CACnB,mBAAS,SAAS,EAAC,iBAAiB,gBAAY,WAAW,aACzD,aAAI,SAAS,EAAC,kBAAkB,0BAAe,EAC9C,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CACvB,KAAC,YAAY,IAEX,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC3E,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,QAAQ,EAAE,KAAK,CAAC,gBAAgB,EAChC,IAAI,EAAE,KAAK,CAAC,IAAI,IANX,QAAQ,CAAC,EAAE,CAOhB,CACH,CAAC,IACM,CACX,EACA,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAC1D,mBAAS,SAAS,EAAC,iBAAiB,gBAAY,SAAS,aACvD,aAAI,SAAS,EAAC,kBAAkB,8BAAmB,EACnD,KAAC,SAAS,IAAC,MAAM,EAAE,KAAK,CAAC,OAAO,GAAI,IAC5B,CACX,EACA,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CACtB,mBAAS,SAAS,EAAC,iBAAiB,gBAAY,UAAU,aACxD,aAAI,SAAS,EAAC,kBAAkB,2BAAgB,EAChD,aAAI,SAAS,EAAC,aAAa,YACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACzB,yBACE,aAAG,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,aAC9B,gBAAM,SAAS,EAAC,gBAAgB,kBAAG,OAAO,CAAC,MAAM,IAAQ,OAAE,OAAO,CAAC,KAAK,IACtE,EAAC,GAAG,EACR,KAAC,UAAU,IAAC,KAAK,EAAE,OAAO,CAAC,KAAK,GAAI,KAJ7B,OAAO,CAAC,EAAE,CAKd,CACN,CAAC,GACC,IACG,CACX,IACG,CACP,CAAC;AACJ,CAAC"}
|
package/dist/console.css
CHANGED
|
@@ -244,8 +244,30 @@ svg {
|
|
|
244
244
|
white-space: nowrap;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
.sc-crumb {
|
|
248
|
+
display: inline-flex;
|
|
249
|
+
align-items: center;
|
|
250
|
+
gap: var(--sc-space-2);
|
|
251
|
+
min-width: 0;
|
|
252
|
+
white-space: nowrap;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.sc-crumb-separator {
|
|
256
|
+
color: var(--sc-color-text-faint);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.sc-crumb-link {
|
|
260
|
+
overflow: hidden;
|
|
261
|
+
max-width: 14rem;
|
|
262
|
+
color: var(--sc-color-text);
|
|
263
|
+
font-weight: var(--sc-weight-medium);
|
|
264
|
+
text-decoration: none;
|
|
265
|
+
text-overflow: ellipsis;
|
|
266
|
+
}
|
|
267
|
+
|
|
247
268
|
.sc-nav {
|
|
248
269
|
display: flex;
|
|
270
|
+
flex-wrap: wrap;
|
|
249
271
|
gap: var(--sc-space-1);
|
|
250
272
|
}
|
|
251
273
|
|
|
@@ -1259,7 +1281,75 @@ svg {
|
|
|
1259
1281
|
font-size: var(--sc-text-sm);
|
|
1260
1282
|
}
|
|
1261
1283
|
|
|
1262
|
-
/*
|
|
1284
|
+
/* Projects: what a person may see, each with what they are in it and what waits in it. */
|
|
1285
|
+
|
|
1286
|
+
.sc-projects {
|
|
1287
|
+
display: grid;
|
|
1288
|
+
gap: var(--sc-space-3);
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
.sc-project {
|
|
1292
|
+
padding: var(--sc-space-4);
|
|
1293
|
+
border: var(--sc-border);
|
|
1294
|
+
border-radius: var(--sc-radius-md);
|
|
1295
|
+
background: var(--sc-color-bg-subtle);
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
.sc-project-head {
|
|
1299
|
+
display: flex;
|
|
1300
|
+
flex-wrap: wrap;
|
|
1301
|
+
align-items: center;
|
|
1302
|
+
gap: var(--sc-space-3);
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
.sc-project-name {
|
|
1306
|
+
color: var(--sc-color-text);
|
|
1307
|
+
font-size: var(--sc-text-lg);
|
|
1308
|
+
font-weight: var(--sc-weight-bold);
|
|
1309
|
+
text-decoration: none;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
.sc-project-name:hover {
|
|
1313
|
+
text-decoration: underline;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
.sc-project-key {
|
|
1317
|
+
color: var(--sc-color-text-muted);
|
|
1318
|
+
font-size: var(--sc-text-sm);
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
.sc-project-description {
|
|
1322
|
+
margin: var(--sc-space-2) 0 0;
|
|
1323
|
+
color: var(--sc-color-text-muted);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
.sc-project-meta {
|
|
1327
|
+
display: flex;
|
|
1328
|
+
flex-wrap: wrap;
|
|
1329
|
+
gap: var(--sc-space-2);
|
|
1330
|
+
margin: var(--sc-space-2) 0 0;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
.sc-project-meta:empty {
|
|
1334
|
+
display: none;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
.sc-members {
|
|
1338
|
+
display: grid;
|
|
1339
|
+
gap: var(--sc-space-4);
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
.sc-member-form .sc-field-row {
|
|
1343
|
+
align-items: end;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
.sc-feed-agent {
|
|
1347
|
+
margin-left: var(--sc-space-2);
|
|
1348
|
+
color: var(--sc-color-text-muted);
|
|
1349
|
+
font-size: var(--sc-text-sm);
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
/* Skills: the project's, or the organization's, as SkillCDN serves them at the address. */
|
|
1263
1353
|
|
|
1264
1354
|
.sc-skills {
|
|
1265
1355
|
display: grid;
|
|
@@ -1380,3 +1470,165 @@ svg {
|
|
|
1380
1470
|
white-space: pre-wrap;
|
|
1381
1471
|
word-break: break-all;
|
|
1382
1472
|
}
|
|
1473
|
+
|
|
1474
|
+
/* Documents: a folder's pages, one page with its versions, its links both ways and its files. */
|
|
1475
|
+
|
|
1476
|
+
.sc-doc-crumbs {
|
|
1477
|
+
margin-bottom: var(--sc-space-3);
|
|
1478
|
+
color: var(--sc-color-text-muted);
|
|
1479
|
+
font-size: var(--sc-text-sm);
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
.sc-doc-crumbs a {
|
|
1483
|
+
color: var(--sc-color-text-muted);
|
|
1484
|
+
text-decoration: none;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
.sc-doc-crumbs a:hover {
|
|
1488
|
+
color: var(--sc-color-accent);
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
.sc-doc-search {
|
|
1492
|
+
display: flex;
|
|
1493
|
+
gap: var(--sc-space-2);
|
|
1494
|
+
margin-bottom: var(--sc-space-4);
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
.sc-doc-search .sc-input {
|
|
1498
|
+
flex: 1;
|
|
1499
|
+
max-width: 32rem;
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
.sc-folder {
|
|
1503
|
+
display: grid;
|
|
1504
|
+
gap: var(--sc-space-3);
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
.sc-folders {
|
|
1508
|
+
display: flex;
|
|
1509
|
+
flex-wrap: wrap;
|
|
1510
|
+
gap: var(--sc-space-2);
|
|
1511
|
+
margin: 0;
|
|
1512
|
+
padding: 0;
|
|
1513
|
+
list-style: none;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
.sc-folder-link {
|
|
1517
|
+
display: inline-block;
|
|
1518
|
+
padding: var(--sc-space-1) var(--sc-space-3);
|
|
1519
|
+
border: var(--sc-border);
|
|
1520
|
+
border-radius: var(--sc-radius-md);
|
|
1521
|
+
background: var(--sc-color-bg-subtle);
|
|
1522
|
+
color: var(--sc-color-text);
|
|
1523
|
+
font-family: var(--sc-font-mono);
|
|
1524
|
+
font-size: var(--sc-text-sm);
|
|
1525
|
+
text-decoration: none;
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
.sc-folder-link:hover {
|
|
1529
|
+
border-color: var(--sc-color-border-strong);
|
|
1530
|
+
color: var(--sc-color-accent);
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
.sc-docs {
|
|
1534
|
+
display: grid;
|
|
1535
|
+
gap: var(--sc-space-2);
|
|
1536
|
+
margin: 0;
|
|
1537
|
+
padding: 0;
|
|
1538
|
+
list-style: none;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
.sc-doc-row {
|
|
1542
|
+
display: flex;
|
|
1543
|
+
flex-wrap: wrap;
|
|
1544
|
+
align-items: baseline;
|
|
1545
|
+
gap: var(--sc-space-2) var(--sc-space-3);
|
|
1546
|
+
padding: var(--sc-space-3) var(--sc-space-4);
|
|
1547
|
+
border: var(--sc-border);
|
|
1548
|
+
border-radius: var(--sc-radius-md);
|
|
1549
|
+
background: var(--sc-color-bg-subtle);
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
.sc-doc-title {
|
|
1553
|
+
color: var(--sc-color-text);
|
|
1554
|
+
font-weight: var(--sc-weight-medium);
|
|
1555
|
+
text-decoration: none;
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
.sc-doc-title:hover {
|
|
1559
|
+
color: var(--sc-color-accent);
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
.sc-doc-meta {
|
|
1563
|
+
color: var(--sc-color-text-muted);
|
|
1564
|
+
font-size: var(--sc-text-sm);
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
.sc-doc-path {
|
|
1568
|
+
font-family: var(--sc-font-mono);
|
|
1569
|
+
font-size: var(--sc-text-xs);
|
|
1570
|
+
color: var(--sc-color-text-faint);
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
.sc-doc-editor {
|
|
1574
|
+
min-height: 20rem;
|
|
1575
|
+
font-family: var(--sc-font-mono);
|
|
1576
|
+
font-size: var(--sc-text-sm);
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
.sc-doc-notice {
|
|
1580
|
+
margin-bottom: var(--sc-space-4);
|
|
1581
|
+
padding: var(--sc-space-3) var(--sc-space-4);
|
|
1582
|
+
border: var(--sc-border);
|
|
1583
|
+
border-radius: var(--sc-radius-md);
|
|
1584
|
+
background: var(--sc-color-bg-inset);
|
|
1585
|
+
color: var(--sc-color-text-muted);
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
.sc-doc-archived .sc-prose {
|
|
1589
|
+
opacity: 0.85;
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
.sc-doc-attach {
|
|
1593
|
+
display: flex;
|
|
1594
|
+
flex-wrap: wrap;
|
|
1595
|
+
gap: var(--sc-space-2);
|
|
1596
|
+
margin-top: var(--sc-space-3);
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
.sc-versions {
|
|
1600
|
+
margin: 0;
|
|
1601
|
+
padding: 0;
|
|
1602
|
+
list-style: none;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
.sc-version + .sc-version {
|
|
1606
|
+
margin-top: var(--sc-space-2);
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
.sc-version-number {
|
|
1610
|
+
display: inline-block;
|
|
1611
|
+
min-width: 2.5rem;
|
|
1612
|
+
font-family: var(--sc-font-mono);
|
|
1613
|
+
font-size: var(--sc-text-sm);
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
/* A decision as a record: its context, its answer, and what followed. */
|
|
1617
|
+
|
|
1618
|
+
.sc-decision-section {
|
|
1619
|
+
margin-top: var(--sc-space-3);
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
.sc-decision-label {
|
|
1623
|
+
margin: 0 0 var(--sc-space-1);
|
|
1624
|
+
color: var(--sc-color-text-faint);
|
|
1625
|
+
font-size: var(--sc-text-xs);
|
|
1626
|
+
font-weight: var(--sc-weight-medium);
|
|
1627
|
+
letter-spacing: 0.04em;
|
|
1628
|
+
text-transform: uppercase;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
.sc-outcome-form {
|
|
1632
|
+
display: grid;
|
|
1633
|
+
gap: var(--sc-space-2);
|
|
1634
|
+
}
|
package/dist/console.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { type BoardProps } from "./components/board.js";
|
|
|
4
4
|
import { type DecisionListProps } from "./components/decision-list.js";
|
|
5
5
|
import { type EventFeedProps } from "./components/event-feed.js";
|
|
6
6
|
import { type PeopleListProps } from "./components/people.js";
|
|
7
|
+
import { type MemberListProps, type ProjectListProps } from "./components/projects.js";
|
|
7
8
|
import { type ShellProps } from "./components/shell.js";
|
|
8
9
|
import { type SignInProps } from "./components/sign-in.js";
|
|
9
10
|
import { type SkillListProps } from "./components/skills.js";
|
|
@@ -20,6 +21,8 @@ export interface ConsoleComponents {
|
|
|
20
21
|
readonly TokenList: ComponentType<TokenListProps>;
|
|
21
22
|
readonly PeopleList: ComponentType<PeopleListProps>;
|
|
22
23
|
readonly SkillList: ComponentType<SkillListProps>;
|
|
24
|
+
readonly ProjectList: ComponentType<ProjectListProps>;
|
|
25
|
+
readonly MemberList: ComponentType<MemberListProps>;
|
|
23
26
|
}
|
|
24
27
|
export declare const DEFAULT_COMPONENTS: ConsoleComponents;
|
|
25
28
|
export interface ConsoleConfig {
|
package/dist/console.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../src/console.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAyD,MAAM,OAAO,CAAC;AAElG,OAAO,
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../src/console.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAyD,MAAM,OAAO,CAAC;AAElG,OAAO,EACL,KAAK,aAAa,EAanB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACrF,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAEL,KAAK,eAAe,EAGpB,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExE,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAkC,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAqB7F,8FAA8F;AAC9F,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACxD,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAClD,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IACpD,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAClD,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACtD,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;CACrD;AAED,eAAO,MAAM,kBAAkB,EAAE,iBAYhC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,+FAA+F;IAC/F,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,SAAS,CAAC;IAC7D,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAC7C;AAED,MAAM,WAAW,UAAU;IACzB,sEAAsE;IACtE,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;IAC3E,mFAAmF;IACnF,KAAK,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,IAAI,CAAC;CACvC;AAifD,wBAAgB,aAAa,CAAC,MAAM,GAAE,aAAkB,GAAG,UAAU,CAoKpE"}
|
package/dist/console.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { StrictMode, useCallback, useEffect, useMemo, useState } from "react";
|
|
3
3
|
import { createRoot } from "react-dom/client";
|
|
4
|
-
import {
|
|
4
|
+
import { createClient, } from "./api.js";
|
|
5
5
|
import { Board } from "./components/board.js";
|
|
6
6
|
import { DecisionForm } from "./components/decision-form.js";
|
|
7
7
|
import { DecisionList } from "./components/decision-list.js";
|
|
8
8
|
import { EventFeed } from "./components/event-feed.js";
|
|
9
9
|
import { PeopleList } from "./components/people.js";
|
|
10
|
+
import { MemberList, ProjectForm, ProjectList, } from "./components/projects.js";
|
|
10
11
|
import { Shell } from "./components/shell.js";
|
|
11
12
|
import { SignIn } from "./components/sign-in.js";
|
|
12
13
|
import { SkillList } from "./components/skills.js";
|
|
@@ -15,7 +16,10 @@ import { TaskView } from "./components/task-view.js";
|
|
|
15
16
|
import { NewToken, TokenForm, TokenList } from "./components/tokens.js";
|
|
16
17
|
import { Button, Callout, EmptyState, Spinner } from "./components/ui.js";
|
|
17
18
|
import { useConsoleData } from "./data.js";
|
|
18
|
-
import {
|
|
19
|
+
import { DocsPage } from "./docs-page.js";
|
|
20
|
+
import { docHref, matchRoute, PATHS, projectHref, signInFailureOf, taskHref, withoutSignInParam, } from "./router.js";
|
|
21
|
+
import { projectPath } from "./routes.js";
|
|
22
|
+
import { useAction } from "./use-action.js";
|
|
19
23
|
export const DEFAULT_COMPONENTS = {
|
|
20
24
|
Shell,
|
|
21
25
|
Board,
|
|
@@ -26,6 +30,8 @@ export const DEFAULT_COMPONENTS = {
|
|
|
26
30
|
TokenList,
|
|
27
31
|
PeopleList,
|
|
28
32
|
SkillList,
|
|
33
|
+
ProjectList,
|
|
34
|
+
MemberList,
|
|
29
35
|
};
|
|
30
36
|
/** The browser's location, as the app reads it; a given path while rendering elsewhere. */
|
|
31
37
|
function useLocation(initialPath) {
|
|
@@ -53,42 +59,51 @@ function useLocation(initialPath) {
|
|
|
53
59
|
}, [read]);
|
|
54
60
|
return { location, navigate };
|
|
55
61
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
62
|
+
/** The key of the project a route is on, or nothing. */
|
|
63
|
+
const projectOf = (route) => "project" in route ? route.project : undefined;
|
|
64
|
+
function ProjectsPage(props) {
|
|
65
|
+
const { data, components, navigate } = props;
|
|
66
|
+
const [making, setMaking] = useState(false);
|
|
67
|
+
const { busy, error, act } = useAction();
|
|
68
|
+
const href = (project) => projectHref(project.key);
|
|
69
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sc-page-head", children: [_jsx("h1", { className: "sc-page-title", children: "Projects" }), _jsx(Button, { variant: "primary", onClick: () => setMaking(true), disabled: making, children: "New project" })] }), _jsx("p", { className: "sc-lead", children: "A project holds its board, its skills and its people. What you may see and change is decided per project: an owner configures it, a member works on it." }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), making && (_jsx("section", { className: "sc-panel", "aria-label": "New project", children: _jsx(ProjectForm, { busy: busy, onSubmit: (input) => void act(async () => {
|
|
70
|
+
const made = await data.actions.createProject(input);
|
|
71
|
+
setMaking(false);
|
|
72
|
+
navigate(projectHref(made.key));
|
|
73
|
+
}), onCancel: () => setMaking(false) }) })), _jsx(components.ProjectList, { projects: data.projects, projectHref: href, onOpen: (project) => navigate(href(project)), empty: _jsx(EmptyState, { title: "No projects yet", body: "Make the first one: what it is for, and who is in it. Or ask an owner to add you to theirs.", action: _jsx(Button, { onClick: () => setMaking(true), children: "New project" }) }) })] }));
|
|
61
74
|
}
|
|
62
|
-
function
|
|
63
|
-
const {
|
|
75
|
+
function TaskPage(props) {
|
|
76
|
+
const { project, task, data, components, busy, error, act } = props;
|
|
77
|
+
const [history, setHistory] = useState(undefined);
|
|
78
|
+
const { taskHistory } = data.actions;
|
|
79
|
+
// Everything that happened to the task, asked for again whenever the project's feed grows.
|
|
80
|
+
const feedLength = data.events.length;
|
|
81
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: the feed's length is the trigger
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
const controller = new AbortController();
|
|
84
|
+
taskHistory(task.id, controller.signal)
|
|
85
|
+
.then((events) => {
|
|
86
|
+
if (!controller.signal.aborted) {
|
|
87
|
+
setHistory(events);
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
.catch(() => undefined);
|
|
91
|
+
return () => controller.abort();
|
|
92
|
+
}, [task.id, taskHistory, feedLength]);
|
|
93
|
+
return (_jsx(components.TaskView, { task: task, people: data.people, tasks: data.tasks, decisions: data.decisions, runs: data.runs, history: history, taskHref: (candidate) => taskHref(project.key, candidate.id), decisionHref: () => projectHref(project.key, "decisions"), fileHref: (artifact) => projectPath(project.key, "files", artifact.id), docHref: (path) => docHref(project.key, path), busy: busy, error: error, onChange: (target, patch) => void act(() => data.actions.updateTask(target.id, patch)), onMove: (target, state) => void act(() => data.actions.updateTask(target.id, { state })), onRaiseDecision: (input) => void act(() => data.actions.raiseDecision(input)), onAnswer: (decision, input) => void act(() => data.actions.answerDecision(decision.id, input)), onUpdateDecision: (decision, patch) => void act(() => data.actions.updateDecision(decision.id, patch)), onAbandonRun: (run) => void act(() => data.actions.abandonRun(run.id)) }));
|
|
94
|
+
}
|
|
95
|
+
function ProjectPage(props) {
|
|
96
|
+
const { route, project, data, components, navigate } = props;
|
|
64
97
|
const [writing, setWriting] = useState(false);
|
|
65
98
|
const [asking, setAsking] = useState(false);
|
|
66
|
-
const
|
|
67
|
-
const [fresh, setFresh] = useState(undefined);
|
|
68
|
-
const [busy, setBusy] = useState(false);
|
|
69
|
-
const [error, setError] = useState(undefined);
|
|
99
|
+
const { busy, error, act } = useAction();
|
|
70
100
|
const tasksById = useMemo(() => new Map(data.tasks.map((task) => [task.id, task])), [data.tasks]);
|
|
71
|
-
const href = (task) => taskHref(task.id);
|
|
72
|
-
|
|
73
|
-
const act = async (work) => {
|
|
74
|
-
setBusy(true);
|
|
75
|
-
setError(undefined);
|
|
76
|
-
try {
|
|
77
|
-
await work();
|
|
78
|
-
}
|
|
79
|
-
catch (failure) {
|
|
80
|
-
setError(errorWords(failure));
|
|
81
|
-
}
|
|
82
|
-
finally {
|
|
83
|
-
setBusy(false);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
101
|
+
const href = (task) => taskHref(project.key, task.id);
|
|
102
|
+
const owner = project.role === "owner";
|
|
86
103
|
const onMove = (task, state) => void act(() => data.actions.updateTask(task.id, { state }));
|
|
87
|
-
const onChange = (task, patch) => void act(() => data.actions.updateTask(task.id, patch));
|
|
88
104
|
const onAnswer = (decision, input) => void act(() => data.actions.answerDecision(decision.id, input));
|
|
89
|
-
const onRaise = (input) => void act(() => data.actions.raiseDecision(input));
|
|
90
105
|
if (route.name === "board") {
|
|
91
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sc-page-head", children: [_jsx("h1", { className: "sc-page-title", children:
|
|
106
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sc-page-head", children: [_jsx("h1", { className: "sc-page-title", children: project.name }), _jsx(Button, { variant: "primary", onClick: () => setWriting(true), disabled: writing, children: "Write a task" })] }), project.description.length > 0 && _jsx("p", { className: "sc-lead", children: project.description }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), writing && (_jsx("section", { className: "sc-panel", "aria-label": "Write a task", children: _jsx(TaskForm, { people: data.people, parents: data.tasks, busy: busy, onSubmit: (input) => void act(async () => {
|
|
92
107
|
await data.actions.createTask(input);
|
|
93
108
|
setWriting(false);
|
|
94
109
|
}), onCancel: () => setWriting(false) }) })), _jsx(components.Board, { tasks: data.tasks, taskHref: href, onOpen: (task) => navigate(href(task)), onMove: onMove, empty: data.tasks.length === 0 ? (_jsx(EmptyState, { title: "Nothing on the board yet", body: "Write the first task: what is to be done, and for whom.", action: _jsx(Button, { onClick: () => setWriting(true), children: "Write a task" }) })) : undefined })] }));
|
|
@@ -96,26 +111,58 @@ function Page(props) {
|
|
|
96
111
|
if (route.name === "task") {
|
|
97
112
|
const task = tasksById.get(route.id);
|
|
98
113
|
if (task === undefined) {
|
|
99
|
-
return (_jsx(EmptyState, { title: "No such task", body: "It may
|
|
114
|
+
return (_jsx(EmptyState, { title: "No such task", body: "It may belong to another project, or the link is wrong." }));
|
|
100
115
|
}
|
|
101
|
-
return (_jsx(
|
|
116
|
+
return (_jsx(TaskPage, { project: project, task: task, data: data, components: components, busy: busy, error: error, act: act }));
|
|
117
|
+
}
|
|
118
|
+
if (route.name === "docs") {
|
|
119
|
+
return _jsx(DocsPage, { project: project, path: route.path, data: data, navigate: navigate });
|
|
102
120
|
}
|
|
103
121
|
if (route.name === "decisions") {
|
|
104
122
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sc-page-head", children: [_jsx("h1", { className: "sc-page-title", children: "Decisions" }), _jsx(Button, { variant: "primary", onClick: () => setAsking(true), disabled: asking, children: "Raise a decision" })] }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), asking && (_jsx("section", { className: "sc-panel", "aria-label": "Raise a decision", children: _jsx(DecisionForm, { tasks: data.tasks, busy: busy, onSubmit: (input) => void act(async () => {
|
|
105
123
|
await data.actions.raiseDecision(input);
|
|
106
124
|
setAsking(false);
|
|
107
|
-
}), onCancel: () => setAsking(false) }) })), _jsx(components.DecisionList, { decisions: data.decisions, tasks: tasksById, taskHref: href, onAnswer: onAnswer, busy: busy, empty: _jsx(EmptyState, { title: "Nothing waits for a person", body: "A decision raised from a task, or from here, shows up on this page." }) })] }));
|
|
125
|
+
}), onCancel: () => setAsking(false) }) })), _jsx(components.DecisionList, { decisions: data.decisions, tasks: tasksById, taskHref: href, docHref: (path) => docHref(project.key, path), onAnswer: onAnswer, onUpdate: (decision, patch) => void act(() => data.actions.updateDecision(decision.id, patch)), busy: busy, empty: _jsx(EmptyState, { title: "Nothing waits for a person", body: "A decision raised from a task, or from here, shows up on this page." }) })] }));
|
|
108
126
|
}
|
|
109
127
|
if (route.name === "feed") {
|
|
110
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "sc-page-head", children: _jsx("h1", { className: "sc-page-title", children: "What happened" }) }), _jsx(components.EventFeed, { events: data.events, href: (event) =>
|
|
128
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "sc-page-head", children: _jsx("h1", { className: "sc-page-title", children: "What happened" }) }), _jsx(components.EventFeed, { events: data.events, href: (event) => event.taskId !== null
|
|
129
|
+
? taskHref(project.key, event.taskId)
|
|
130
|
+
: event.data.path !== undefined
|
|
131
|
+
? docHref(project.key, event.data.path)
|
|
132
|
+
: undefined, empty: _jsx(EmptyState, { title: "Nothing happened yet" }) })] }));
|
|
111
133
|
}
|
|
112
134
|
if (route.name === "skills") {
|
|
113
135
|
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "sc-page-head", children: _jsx("h1", { className: "sc-page-title", children: "Skills" }) }), _jsx(components.SkillList, { skills: data.skills })] }));
|
|
114
136
|
}
|
|
137
|
+
if (route.name === "members") {
|
|
138
|
+
const me = data.me?.person ?? undefined;
|
|
139
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "sc-page-head", children: _jsx("h1", { className: "sc-page-title", children: "Members" }) }), _jsxs("p", { className: "sc-lead", children: [project.visibility === "workspace"
|
|
140
|
+
? "Everyone of the workspace is a member of this project; those listed here are its owners and the people named besides. "
|
|
141
|
+
: "Only those listed here are in this project. ", "An owner configures the project; a member works on it. A workspace administrator is an owner of every project."] }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), _jsx(components.MemberList, { members: data.members, people: data.people, me: me, busy: busy, onAdd: owner ? (input) => void act(() => data.actions.addMember(input)) : undefined, onChangeRole: owner
|
|
142
|
+
? (member, role) => void act(() => data.actions.updateMember(member.person.id, { role }))
|
|
143
|
+
: undefined, onRemove: owner
|
|
144
|
+
? (member) => void act(() => data.actions.removeMember(member.person.id))
|
|
145
|
+
: undefined, empty: _jsx(EmptyState, { title: "Nobody is listed", body: project.visibility === "workspace"
|
|
146
|
+
? "Everyone of the workspace is in; the administrators own it."
|
|
147
|
+
: "The administrators own it until an owner is listed." }) })] }));
|
|
148
|
+
}
|
|
149
|
+
if (route.name === "settings") {
|
|
150
|
+
if (!owner) {
|
|
151
|
+
return (_jsx(EmptyState, { title: "Only an owner may change the project", body: "Ask one of its owners, or a workspace administrator." }));
|
|
152
|
+
}
|
|
153
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "sc-page-head", children: _jsx("h1", { className: "sc-page-title", children: "Settings" }) }), _jsxs("p", { className: "sc-lead", children: ["The key, ", _jsx("code", { children: project.key }), ", is what paths and the command say, and does not change. The skills address names a repository served by SkillCDN; empty, the organization's skills are shown."] }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), _jsx("section", { className: "sc-panel", "aria-label": "Project settings", children: _jsx(ProjectForm, { project: project, busy: busy, onSubmit: (input) => void act(() => data.actions.updateProject(input)) }) })] }));
|
|
154
|
+
}
|
|
155
|
+
return _jsx(EmptyState, { title: "There is nothing at this address" });
|
|
156
|
+
}
|
|
157
|
+
function WorkspacePage(props) {
|
|
158
|
+
const { route, data, components } = props;
|
|
159
|
+
const [making, setMaking] = useState(false);
|
|
160
|
+
const [fresh, setFresh] = useState(undefined);
|
|
161
|
+
const { busy, error, act } = useAction();
|
|
115
162
|
if (route.name === "people") {
|
|
116
163
|
const me = data.me?.person ?? undefined;
|
|
117
164
|
const administrator = me?.role === "admin";
|
|
118
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "sc-page-head", children: _jsx("h1", { className: "sc-page-title", children: "People" }) }), _jsx("p", { className: "sc-lead", children: "Everyone who has signed in. An administrator configures the
|
|
165
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "sc-page-head", children: _jsx("h1", { className: "sc-page-title", children: "People" }) }), _jsx("p", { className: "sc-lead", children: "Everyone who has signed in. An administrator configures the workspace and says what each person is; a member works in the projects they are in. What a person may do, their agents may do." }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), _jsx(components.PeopleList, { people: data.people, me: me, busy: busy, onChangeRole: administrator
|
|
119
166
|
? (person, role) => void act(() => data.actions.updatePerson(person.id, { role }))
|
|
120
167
|
: undefined })] }));
|
|
121
168
|
}
|
|
@@ -124,7 +171,7 @@ function Page(props) {
|
|
|
124
171
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sc-page-head", children: [_jsx("h1", { className: "sc-page-title", children: "Tokens" }), _jsx(Button, { variant: "primary", onClick: () => setMaking(true), disabled: making, children: "Make a token" })] }), _jsx("p", { className: "sc-lead", children: "A token lets an agent, a script or a console of your own act as you on this board: what you may do, it may do. Make one per agent, name it after where it runs, and remove it when that is over." }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), fresh !== undefined && (_jsx(NewToken, { token: fresh.token, secret: fresh.secret, onDone: () => setFresh(undefined) })), making && (_jsx("section", { className: "sc-panel", "aria-label": "Make a token", children: _jsx(TokenForm, { busy: busy, onSubmit: (input) => void act(async () => {
|
|
125
172
|
setFresh(await data.actions.createToken(input));
|
|
126
173
|
setMaking(false);
|
|
127
|
-
}), onCancel: () => setMaking(false) }) })), _jsx(components.TokenList, { tokens: data.tokens, busy: busy, onRevoke: (token) => void act(() => data.actions.revokeToken(token.id)), empty: _jsx(EmptyState, { title: "No tokens yet", body: "Make one for your agent, and it can work on this board as you." }) }), _jsxs("section", { className: "sc-panel sc-connect", "aria-label": "Connecting an agent", children: [_jsx("h2", { className: "sc-section-title", children: "Connecting an agent" }), _jsxs("p", { children: ["An agent works this board with the ", _jsx("code", { children: "console" }), " command, which comes with the", " ", _jsx("code", { children: "@skillcdn/console" }), " package. Install the package where the agent runs,
|
|
174
|
+
}), onCancel: () => setMaking(false) }) })), _jsx(components.TokenList, { tokens: data.tokens, busy: busy, onRevoke: (token) => void act(() => data.actions.revokeToken(token.id)), empty: _jsx(EmptyState, { title: "No tokens yet", body: "Make one for your agent, and it can work on this board as you." }) }), _jsxs("section", { className: "sc-panel sc-connect", "aria-label": "Connecting an agent", children: [_jsx("h2", { className: "sc-section-title", children: "Connecting an agent" }), _jsxs("p", { children: ["An agent works this board with the ", _jsx("code", { children: "console" }), " command, which comes with the", " ", _jsx("code", { children: "@skillcdn/console" }), " package. Install the package where the agent runs, sign the command in with a token made here, and say which project the directory works in:"] }), _jsxs("pre", { className: "sc-code", children: ["npm install -g @skillcdn/console", "\n", "console login --url ", origin, "\n", "console use ", "<project key>"] }), _jsxs("p", { children: ["It asks for the token and keeps it in your home directory, and your agent is you from then on: ", _jsx("code", { children: "console take" }), " starts work on a task, ", _jsx("code", { children: "console report" }), ",", " ", _jsx("code", { children: "console hand-in" }), " and ", _jsx("code", { children: "console ask" }), " say how it goes, and", " ", _jsx("code", { children: "console finish" }), " ends the run. ", _jsx("code", { children: "console help" }), " says the rest."] })] })] }));
|
|
128
175
|
}
|
|
129
176
|
return _jsx(EmptyState, { title: "There is nothing at this address" });
|
|
130
177
|
}
|
|
@@ -134,40 +181,91 @@ export function createConsole(config = {}) {
|
|
|
134
181
|
const fallbackTitle = config.title ?? "Console";
|
|
135
182
|
function App(props) {
|
|
136
183
|
const { location, navigate } = useLocation(props.initialPath);
|
|
137
|
-
const data = useConsoleData(client);
|
|
138
184
|
const route = useMemo(() => matchRoute(location.pathname), [location.pathname]);
|
|
185
|
+
const projectKey = projectOf(route);
|
|
186
|
+
const data = useConsoleData(client, projectKey);
|
|
139
187
|
const failure = signInFailureOf(location.search);
|
|
140
188
|
const title = data.me?.workspace.name ?? fallbackTitle;
|
|
141
189
|
useEffect(() => {
|
|
142
190
|
if (typeof document !== "undefined") {
|
|
143
|
-
document.title = title
|
|
191
|
+
document.title = data.project === undefined ? title : `${data.project.name} · ${title}`;
|
|
144
192
|
}
|
|
145
|
-
}, [title]);
|
|
193
|
+
}, [title, data.project]);
|
|
146
194
|
if (data.me === undefined) {
|
|
147
195
|
return (_jsx("div", { className: "sc-loading", children: data.error === undefined ? (_jsx(Spinner, { label: "Loading" })) : (_jsx(Callout, { tone: "danger", title: "The console could not be reached", action: _jsx(Button, { onClick: data.reload, children: "Try again" }), children: data.error })) }));
|
|
148
196
|
}
|
|
149
197
|
if (data.me.person === null) {
|
|
150
198
|
return (_jsx(components.SignIn, { title: title, providers: data.me.signIn, returnTo: withoutSignInParam(location.pathname, location.search), failure: failure }));
|
|
151
199
|
}
|
|
200
|
+
const project = data.project;
|
|
152
201
|
const waiting = data.decisions.filter((decision) => decision.answer === null).length;
|
|
153
|
-
const nav =
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
202
|
+
const nav = projectKey === undefined
|
|
203
|
+
? [{ href: PATHS.projects, label: "Projects", current: route.name === "projects" }]
|
|
204
|
+
: [
|
|
205
|
+
{
|
|
206
|
+
href: projectHref(projectKey),
|
|
207
|
+
label: "Board",
|
|
208
|
+
current: route.name === "board" || route.name === "task",
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
href: projectHref(projectKey, "docs"),
|
|
212
|
+
label: "Docs",
|
|
213
|
+
current: route.name === "docs",
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
href: projectHref(projectKey, "decisions"),
|
|
217
|
+
label: "Decisions",
|
|
218
|
+
current: route.name === "decisions",
|
|
219
|
+
count: waiting,
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
href: projectHref(projectKey, "feed"),
|
|
223
|
+
label: "Feed",
|
|
224
|
+
current: route.name === "feed",
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
href: projectHref(projectKey, "skills"),
|
|
228
|
+
label: "Skills",
|
|
229
|
+
current: route.name === "skills",
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
href: projectHref(projectKey, "members"),
|
|
233
|
+
label: "Members",
|
|
234
|
+
current: route.name === "members",
|
|
235
|
+
},
|
|
236
|
+
...(project?.role === "owner"
|
|
237
|
+
? [
|
|
238
|
+
{
|
|
239
|
+
href: projectHref(projectKey, "settings"),
|
|
240
|
+
label: "Settings",
|
|
241
|
+
current: route.name === "settings",
|
|
242
|
+
},
|
|
243
|
+
]
|
|
244
|
+
: []),
|
|
245
|
+
];
|
|
246
|
+
nav.push({ href: PATHS.people, label: "People", current: route.name === "people" }, { href: PATHS.tokens, label: "Tokens", current: route.name === "tokens" });
|
|
247
|
+
let page;
|
|
248
|
+
if (!data.loaded) {
|
|
249
|
+
page = (_jsx("div", { className: "sc-loading", children: _jsx(Spinner, { label: "Loading the workspace" }) }));
|
|
250
|
+
}
|
|
251
|
+
else if (route.name === "projects") {
|
|
252
|
+
page = _jsx(ProjectsPage, { data: data, components: components, navigate: navigate });
|
|
253
|
+
}
|
|
254
|
+
else if (projectKey === undefined) {
|
|
255
|
+
page = _jsx(WorkspacePage, { route: route, data: data, components: components });
|
|
256
|
+
}
|
|
257
|
+
else if (data.projectError !== undefined) {
|
|
258
|
+
page = (_jsx(EmptyState, { title: "No such project", body: "It may not exist, or it is not yours to see. The projects you may work in are on the front page.", action: _jsx(Button, { onClick: () => navigate(PATHS.projects), children: "Projects" }) }));
|
|
259
|
+
}
|
|
260
|
+
else if (!data.projectLoaded || project === undefined) {
|
|
261
|
+
page = (_jsx("div", { className: "sc-loading", children: _jsx(Spinner, { label: "Loading the project" }) }));
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
page = (_jsx(ProjectPage, { route: route, project: project, data: data, components: components, navigate: navigate }));
|
|
265
|
+
}
|
|
266
|
+
return (_jsx(components.Shell, { title: title, project: projectKey === undefined
|
|
267
|
+
? undefined
|
|
268
|
+
: { name: project?.name ?? projectKey, href: projectHref(projectKey) }, nav: nav, person: data.me.person, live: projectKey === undefined ? undefined : data.live, onNavigate: (href) => navigate(href), onSignOut: () => void data.actions.signOut(), children: page }));
|
|
171
269
|
}
|
|
172
270
|
return {
|
|
173
271
|
App,
|