@skillcdn/console 0.1.18 → 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 +1 -1
- package/SKILLCDN.md +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +1 -1
- package/dist/api.js.map +1 -1
- package/dist/cli/cli.d.ts +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +353 -39
- 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 +10 -1
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +106 -2
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +42 -20
- package/dist/cli/help.js.map +1 -1
- package/dist/client.d.ts +21 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +14 -1
- package/dist/client.js.map +1 -1
- 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/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 +17 -1
- package/dist/components/goals.d.ts.map +1 -1
- package/dist/components/goals.js +34 -9
- 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/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/console.css +282 -3
- package/dist/console.d.ts.map +1 -1
- package/dist/console.js +124 -10
- 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 +47 -2
- package/dist/data.js.map +1 -1
- package/dist/i18n/en.d.ts +52 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +50 -2
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/ko.d.ts.map +1 -1
- package/dist/i18n/ko.js +50 -2
- package/dist/i18n/ko.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +25 -6
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +38 -7
- 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 +158 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +78 -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 +17 -9
- package/docs/specs/rest.md +22 -4
- package/package.json +1 -1
- package/skills/working-the-board/SKILL.md +10 -4
- package/src/api.ts +13 -0
- package/src/cli/cli.ts +441 -42
- package/src/cli/credentials.ts +276 -14
- package/src/cli/directory.ts +43 -6
- package/src/cli/format.ts +138 -2
- package/src/cli/help.ts +44 -20
- package/src/client.ts +60 -0
- package/src/components/board.tsx +154 -8
- package/src/components/comments.tsx +20 -10
- package/src/components/event-feed.tsx +4 -0
- package/src/components/goals.tsx +173 -106
- package/src/components/markdown.tsx +19 -0
- package/src/components/pictures.tsx +389 -0
- package/src/components/projects.tsx +68 -0
- package/src/components/task-view.tsx +43 -2
- package/src/console.tsx +259 -4
- package/src/data.ts +72 -1
- package/src/i18n/en.ts +53 -2
- package/src/i18n/ko.ts +53 -2
- package/src/index.ts +27 -0
- package/src/router.ts +57 -9
- package/src/rules.ts +5 -5
- package/src/schemas.ts +97 -0
- package/src/styles/console.css +282 -3
- package/src/vocabulary.ts +3 -0
package/dist/console.css
CHANGED
|
@@ -2166,16 +2166,110 @@ table {
|
|
|
2166
2166
|
font-size: var(--sc-text-sm);
|
|
2167
2167
|
}
|
|
2168
2168
|
|
|
2169
|
-
/* A picture in a comment is
|
|
2170
|
-
|
|
2169
|
+
/* A picture in a comment is a thumbnail, no taller than a few lines, that opens large over the
|
|
2170
|
+
page; a picture that only comes over https stays where it is, as small. */
|
|
2171
|
+
.sc-picture-thumb {
|
|
2172
|
+
display: inline-block;
|
|
2173
|
+
padding: 0;
|
|
2174
|
+
border: 0;
|
|
2175
|
+
border-radius: var(--sc-radius-md);
|
|
2176
|
+
background: none;
|
|
2177
|
+
line-height: 0;
|
|
2178
|
+
cursor: zoom-in;
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
.sc-picture-thumb:focus-visible {
|
|
2182
|
+
outline: 2px solid var(--sc-color-accent);
|
|
2183
|
+
outline-offset: 2px;
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
.sc-picture-thumb img,
|
|
2171
2187
|
.sc-comment .sc-prose img {
|
|
2172
2188
|
display: block;
|
|
2189
|
+
width: auto;
|
|
2173
2190
|
max-width: 100%;
|
|
2174
|
-
|
|
2191
|
+
height: auto;
|
|
2192
|
+
max-height: 10rem;
|
|
2175
2193
|
border: var(--sc-border);
|
|
2176
2194
|
border-radius: var(--sc-radius-md);
|
|
2177
2195
|
}
|
|
2178
2196
|
|
|
2197
|
+
.sc-prose .sc-picture-thumb {
|
|
2198
|
+
margin: var(--sc-space-2) 0;
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
/* The picture large, over the page: a bar with its name and the ways to zoom and to close, the
|
|
2202
|
+
stage it moves on, and a hint. The page under it is dimmed and does not scroll. */
|
|
2203
|
+
.sc-overlay {
|
|
2204
|
+
position: fixed;
|
|
2205
|
+
z-index: 100;
|
|
2206
|
+
display: grid;
|
|
2207
|
+
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
2208
|
+
inset: 0;
|
|
2209
|
+
background: color-mix(in srgb, var(--sc-color-bg) 90%, transparent);
|
|
2210
|
+
backdrop-filter: blur(12px);
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
.sc-overlay-bar {
|
|
2214
|
+
display: flex;
|
|
2215
|
+
align-items: center;
|
|
2216
|
+
justify-content: space-between;
|
|
2217
|
+
gap: var(--sc-space-3);
|
|
2218
|
+
padding: var(--sc-space-3) var(--sc-space-4);
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
.sc-overlay-name {
|
|
2222
|
+
min-width: 0;
|
|
2223
|
+
overflow: hidden;
|
|
2224
|
+
color: var(--sc-color-text);
|
|
2225
|
+
font-size: var(--sc-text-sm);
|
|
2226
|
+
text-overflow: ellipsis;
|
|
2227
|
+
white-space: nowrap;
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
.sc-overlay-actions {
|
|
2231
|
+
display: flex;
|
|
2232
|
+
flex-shrink: 0;
|
|
2233
|
+
gap: var(--sc-space-1);
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
.sc-overlay-stage {
|
|
2237
|
+
position: relative;
|
|
2238
|
+
display: grid;
|
|
2239
|
+
place-items: center;
|
|
2240
|
+
overflow: hidden;
|
|
2241
|
+
cursor: grab;
|
|
2242
|
+
touch-action: none;
|
|
2243
|
+
user-select: none;
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
.sc-overlay-stage[data-dragging="true"] {
|
|
2247
|
+
cursor: grabbing;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
.sc-overlay-picture {
|
|
2251
|
+
width: auto;
|
|
2252
|
+
max-width: 100%;
|
|
2253
|
+
height: auto;
|
|
2254
|
+
max-height: 100%;
|
|
2255
|
+
transform-origin: center center;
|
|
2256
|
+
will-change: transform;
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
.sc-overlay-hint {
|
|
2260
|
+
margin: 0;
|
|
2261
|
+
padding: var(--sc-space-2) var(--sc-space-4) var(--sc-space-3);
|
|
2262
|
+
color: var(--sc-color-text-muted);
|
|
2263
|
+
font-size: var(--sc-text-xs);
|
|
2264
|
+
text-align: center;
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
@media (max-width: 40rem) {
|
|
2268
|
+
.sc-overlay-hint {
|
|
2269
|
+
display: none;
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2179
2273
|
.sc-comment-files {
|
|
2180
2274
|
display: grid;
|
|
2181
2275
|
gap: var(--sc-space-2);
|
|
@@ -3680,3 +3774,188 @@ table {
|
|
|
3680
3774
|
grid-template-columns: minmax(6rem, 8rem) minmax(16rem, 1fr);
|
|
3681
3775
|
}
|
|
3682
3776
|
}
|
|
3777
|
+
|
|
3778
|
+
/* A card is dragged to another column by its grip, which shows on the card under the pointer
|
|
3779
|
+
and always to a finger; the column under the dragged card says it would take it, and a ghost
|
|
3780
|
+
of the card follows the pointer. The keyboard keeps the select. */
|
|
3781
|
+
.sc-card {
|
|
3782
|
+
position: relative;
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
.sc-card-grip {
|
|
3786
|
+
position: absolute;
|
|
3787
|
+
top: var(--sc-space-1);
|
|
3788
|
+
right: var(--sc-space-1);
|
|
3789
|
+
display: inline-flex;
|
|
3790
|
+
align-items: center;
|
|
3791
|
+
justify-content: center;
|
|
3792
|
+
width: 1.5rem;
|
|
3793
|
+
height: 1.5rem;
|
|
3794
|
+
padding: 0;
|
|
3795
|
+
border: 0;
|
|
3796
|
+
border-radius: var(--sc-radius-sm);
|
|
3797
|
+
background: none;
|
|
3798
|
+
color: var(--sc-color-text-faint);
|
|
3799
|
+
font-size: var(--sc-text-sm);
|
|
3800
|
+
letter-spacing: -0.15em;
|
|
3801
|
+
cursor: grab;
|
|
3802
|
+
opacity: 0;
|
|
3803
|
+
touch-action: none;
|
|
3804
|
+
transition: opacity var(--sc-transition);
|
|
3805
|
+
}
|
|
3806
|
+
|
|
3807
|
+
.sc-card:hover .sc-card-grip,
|
|
3808
|
+
.sc-card:focus-within .sc-card-grip,
|
|
3809
|
+
.sc-card.sc-card-dragging .sc-card-grip {
|
|
3810
|
+
opacity: 1;
|
|
3811
|
+
}
|
|
3812
|
+
|
|
3813
|
+
@media (pointer: coarse) {
|
|
3814
|
+
.sc-card-grip {
|
|
3815
|
+
opacity: 1;
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
|
|
3819
|
+
.sc-card:has(.sc-card-grip) .sc-card-title {
|
|
3820
|
+
padding-right: 1.75rem;
|
|
3821
|
+
}
|
|
3822
|
+
|
|
3823
|
+
.sc-card-dragging {
|
|
3824
|
+
opacity: 0.5;
|
|
3825
|
+
}
|
|
3826
|
+
|
|
3827
|
+
.sc-board-dragging {
|
|
3828
|
+
user-select: none;
|
|
3829
|
+
}
|
|
3830
|
+
|
|
3831
|
+
.sc-column-over {
|
|
3832
|
+
outline: 2px solid var(--sc-color-accent);
|
|
3833
|
+
outline-offset: -2px;
|
|
3834
|
+
}
|
|
3835
|
+
|
|
3836
|
+
.sc-drag-ghost {
|
|
3837
|
+
position: fixed;
|
|
3838
|
+
top: 0;
|
|
3839
|
+
left: 0;
|
|
3840
|
+
z-index: 50;
|
|
3841
|
+
max-width: 18rem;
|
|
3842
|
+
padding: var(--sc-space-2) var(--sc-space-3);
|
|
3843
|
+
border: 1px solid var(--sc-color-accent);
|
|
3844
|
+
border-radius: var(--sc-radius-lg);
|
|
3845
|
+
background: var(--sc-color-bg-raised);
|
|
3846
|
+
box-shadow: var(--sc-glow);
|
|
3847
|
+
color: var(--sc-color-text);
|
|
3848
|
+
font-size: var(--sc-text-sm);
|
|
3849
|
+
pointer-events: none;
|
|
3850
|
+
}
|
|
3851
|
+
|
|
3852
|
+
/* A goal's page reads as the board does: the facts in a row at its head, then a switch between
|
|
3853
|
+
the views of its tasks, then the view, which takes the rest of the height as the board does. */
|
|
3854
|
+
.sc-goal-page {
|
|
3855
|
+
display: flex;
|
|
3856
|
+
flex: 1 1 0;
|
|
3857
|
+
flex-direction: column;
|
|
3858
|
+
gap: var(--sc-space-4);
|
|
3859
|
+
min-height: 0;
|
|
3860
|
+
}
|
|
3861
|
+
|
|
3862
|
+
.sc-goal-header {
|
|
3863
|
+
display: grid;
|
|
3864
|
+
gap: var(--sc-space-3);
|
|
3865
|
+
}
|
|
3866
|
+
|
|
3867
|
+
.sc-goal-progress {
|
|
3868
|
+
display: grid;
|
|
3869
|
+
grid-template-columns: minmax(0, 20rem) auto;
|
|
3870
|
+
align-items: center;
|
|
3871
|
+
gap: var(--sc-space-3);
|
|
3872
|
+
font-size: var(--sc-text-sm);
|
|
3873
|
+
}
|
|
3874
|
+
|
|
3875
|
+
.sc-facts-row {
|
|
3876
|
+
display: flex;
|
|
3877
|
+
flex-wrap: wrap;
|
|
3878
|
+
align-items: center;
|
|
3879
|
+
gap: var(--sc-space-2) var(--sc-space-5);
|
|
3880
|
+
margin: 0;
|
|
3881
|
+
font-size: var(--sc-text-sm);
|
|
3882
|
+
}
|
|
3883
|
+
|
|
3884
|
+
.sc-facts-row > div {
|
|
3885
|
+
display: flex;
|
|
3886
|
+
align-items: center;
|
|
3887
|
+
gap: var(--sc-space-2);
|
|
3888
|
+
}
|
|
3889
|
+
|
|
3890
|
+
.sc-facts-row dt {
|
|
3891
|
+
color: var(--sc-color-text-muted);
|
|
3892
|
+
}
|
|
3893
|
+
|
|
3894
|
+
.sc-facts-row dd {
|
|
3895
|
+
margin: 0;
|
|
3896
|
+
}
|
|
3897
|
+
|
|
3898
|
+
.sc-goal-about-summary {
|
|
3899
|
+
color: var(--sc-color-text-muted);
|
|
3900
|
+
font-size: var(--sc-text-sm);
|
|
3901
|
+
cursor: pointer;
|
|
3902
|
+
}
|
|
3903
|
+
|
|
3904
|
+
.sc-goal-about .sc-prose {
|
|
3905
|
+
max-width: var(--sc-width-prose);
|
|
3906
|
+
margin-top: var(--sc-space-3);
|
|
3907
|
+
}
|
|
3908
|
+
|
|
3909
|
+
.sc-views {
|
|
3910
|
+
display: flex;
|
|
3911
|
+
flex-wrap: wrap;
|
|
3912
|
+
gap: var(--sc-space-1);
|
|
3913
|
+
}
|
|
3914
|
+
|
|
3915
|
+
.sc-view {
|
|
3916
|
+
padding: var(--sc-space-1) var(--sc-space-3);
|
|
3917
|
+
border-radius: var(--sc-radius-full);
|
|
3918
|
+
color: var(--sc-color-text-muted);
|
|
3919
|
+
font-size: var(--sc-text-sm);
|
|
3920
|
+
text-decoration: none;
|
|
3921
|
+
}
|
|
3922
|
+
|
|
3923
|
+
.sc-view:hover {
|
|
3924
|
+
background: var(--sc-color-bg-inset);
|
|
3925
|
+
color: var(--sc-color-text);
|
|
3926
|
+
}
|
|
3927
|
+
|
|
3928
|
+
.sc-view-current {
|
|
3929
|
+
background: var(--sc-color-bg-inset);
|
|
3930
|
+
color: var(--sc-color-text);
|
|
3931
|
+
font-weight: var(--sc-weight-medium);
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3934
|
+
.sc-goal-tasks-view {
|
|
3935
|
+
display: flex;
|
|
3936
|
+
flex: 1 1 0;
|
|
3937
|
+
flex-direction: column;
|
|
3938
|
+
min-height: 0;
|
|
3939
|
+
}
|
|
3940
|
+
|
|
3941
|
+
.sc-goal-view-list {
|
|
3942
|
+
display: block;
|
|
3943
|
+
}
|
|
3944
|
+
|
|
3945
|
+
/* The done and dropped columns lead to the archive (ADR-0029), beside their count. */
|
|
3946
|
+
.sc-column-meta {
|
|
3947
|
+
display: inline-flex;
|
|
3948
|
+
align-items: center;
|
|
3949
|
+
gap: var(--sc-space-2);
|
|
3950
|
+
}
|
|
3951
|
+
|
|
3952
|
+
.sc-column-archive {
|
|
3953
|
+
color: var(--sc-color-text-muted);
|
|
3954
|
+
font-size: var(--sc-text-xs);
|
|
3955
|
+
text-decoration: none;
|
|
3956
|
+
}
|
|
3957
|
+
|
|
3958
|
+
.sc-column-archive:hover {
|
|
3959
|
+
color: var(--sc-color-text);
|
|
3960
|
+
text-decoration: underline;
|
|
3961
|
+
}
|
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,EACL,KAAK,aAAa,EAClB,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AAEf,OAAO,EAEL,KAAK,aAAa,EAYlB,KAAK,WAAW,EAajB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAuB,KAAK,UAAU,EAAsB,MAAM,uBAAuB,CAAC;AACjG,OAAO,EAAY,KAAK,aAAa,EAAY,MAAM,0BAA0B,CAAC;AAClF,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAGlF,OAAO,EAA8B,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACnG,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAsB,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../src/console.tsx"],"names":[],"mappings":"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"}
|
package/dist/console.js
CHANGED
|
@@ -9,9 +9,10 @@ import { ConnectWords } from "./components/connect.js";
|
|
|
9
9
|
import { DecisionForm } from "./components/decision-form.js";
|
|
10
10
|
import { DecisionCard, DecisionList } from "./components/decision-list.js";
|
|
11
11
|
import { EventFeed } from "./components/event-feed.js";
|
|
12
|
-
import { GoalForm, GoalList, GoalView } from "./components/goals.js";
|
|
12
|
+
import { GoalForm, GoalList, GoalView, goalMonth } from "./components/goals.js";
|
|
13
|
+
import { PAGE_SIZE } from "./components/paged.js";
|
|
13
14
|
import { ListingForm, PeopleList } from "./components/people.js";
|
|
14
|
-
import { MemberList, ProjectForm, ProjectList, ProjectMark, } from "./components/projects.js";
|
|
15
|
+
import { MemberList, PackTokenForm, ProjectForm, ProjectList, ProjectMark, } from "./components/projects.js";
|
|
15
16
|
import { GoalTimeline } from "./components/roadmap.js";
|
|
16
17
|
import { RulesForm, RulesView } from "./components/rules.js";
|
|
17
18
|
import { isPlainClick, Shell, } from "./components/shell.js";
|
|
@@ -21,7 +22,7 @@ import { TaskForm } from "./components/task-form.js";
|
|
|
21
22
|
import { TaskList } from "./components/task-list.js";
|
|
22
23
|
import { TaskView } from "./components/task-view.js";
|
|
23
24
|
import { NewToken, TokenForm, TokenList } from "./components/tokens.js";
|
|
24
|
-
import { Button, Callout, CategoryBadge, EmptyState, personName, Spinner, } from "./components/ui.js";
|
|
25
|
+
import { Button, Callout, CategoryBadge, EmptyState, personName, Spinner, StateBadge, Time, } from "./components/ui.js";
|
|
25
26
|
import { WorkList } from "./components/work.js";
|
|
26
27
|
import { ConnectPage } from "./connect-page.js";
|
|
27
28
|
import { useConsoleData } from "./data.js";
|
|
@@ -199,13 +200,85 @@ function ProjectsPage(props) {
|
|
|
199
200
|
navigation.replace(projectHref(made.key));
|
|
200
201
|
}), onCancel: () => navigation.back(PATHS.projects) }) })), _jsx(components.ProjectList, { projects: data.projects, projectHref: href, onOpen: (project) => navigation.go(href(project)), empty: _jsx(EmptyState, { title: words.empty.title, body: words.empty.body, action: _jsx(LinkButton, { href: PATHS.newProject, children: words.newProject }) }) })] }));
|
|
201
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* The archive of the board (ADR-0029): the tasks put away, newest first, a page at a time from
|
|
205
|
+
* the server, each brought back from here by whoever may work in the project.
|
|
206
|
+
*/
|
|
207
|
+
function ArchivePage(props) {
|
|
208
|
+
const words = useWords();
|
|
209
|
+
const { project, data } = props;
|
|
210
|
+
const key = project.key;
|
|
211
|
+
const { busy, error, act } = useAction();
|
|
212
|
+
const [items, setItems] = useState([]);
|
|
213
|
+
const [more, setMore] = useState(false);
|
|
214
|
+
const [loaded, setLoaded] = useState(false);
|
|
215
|
+
const { archivedTasks } = data.actions;
|
|
216
|
+
const feedLength = data.events.length;
|
|
217
|
+
// The first page, read again whenever the project's feed grows: something was put away or brought back.
|
|
218
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: the feed's length is what triggers the read
|
|
219
|
+
useEffect(() => {
|
|
220
|
+
const controller = new AbortController();
|
|
221
|
+
archivedTasks({ limit: PAGE_SIZE, offset: 0 }, controller.signal)
|
|
222
|
+
.then((page) => {
|
|
223
|
+
if (!controller.signal.aborted) {
|
|
224
|
+
setItems(page.items);
|
|
225
|
+
setMore(page.more);
|
|
226
|
+
setLoaded(true);
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
.catch(() => undefined);
|
|
230
|
+
return () => controller.abort();
|
|
231
|
+
}, [archivedTasks, feedLength]);
|
|
232
|
+
const onMore = () => void archivedTasks({ limit: PAGE_SIZE, offset: items.length })
|
|
233
|
+
.then((page) => {
|
|
234
|
+
setItems((current) => [...current, ...page.items]);
|
|
235
|
+
setMore(page.more);
|
|
236
|
+
})
|
|
237
|
+
.catch(() => undefined);
|
|
238
|
+
const archive = words.archive;
|
|
239
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sc-page-head", children: [_jsx("h1", { className: "sc-page-title", children: archive.title }), _jsx(LinkButton, { href: projectHref(key), children: words.nav.board })] }), _jsx("p", { className: "sc-lead", children: archive.lead }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), !loaded ? (_jsx(Spinner, { label: archive.loading })) : items.length === 0 ? (_jsx(EmptyState, { title: archive.empty.title, body: archive.empty.body })) : (_jsxs(_Fragment, { children: [_jsx("ul", { className: "sc-task-rows", "aria-label": archive.title, children: items.map((task) => (_jsxs("li", { className: "sc-task-row", children: [_jsxs("a", { className: "sc-task-row-title", href: taskHref(key, task.number), children: [_jsxs("span", { className: "sc-card-number", children: ["#", task.number] }), " ", task.title] }), _jsxs("span", { className: "sc-task-row-meta", children: [_jsx(StateBadge, { state: task.state }), task.archivedAt !== null && (_jsxs("span", { className: "sc-muted", children: [archive.since, " ", _jsx(Time, { iso: task.archivedAt })] })), _jsx(Button, { size: "sm", variant: "ghost", disabled: busy, onClick: () => void act(async () => {
|
|
240
|
+
await data.actions.restoreTask(task.id);
|
|
241
|
+
setItems((current) => current.filter((candidate) => candidate.id !== task.id));
|
|
242
|
+
}), children: archive.restore })] })] }, task.id))) }), more && (_jsx("div", { className: "sc-show-more", children: _jsx(Button, { variant: "secondary", size: "sm", onClick: onMore, children: archive.more }) }))] }))] }));
|
|
243
|
+
}
|
|
202
244
|
function TaskPage(props) {
|
|
203
245
|
const words = useWords();
|
|
204
246
|
const { route, project, data, components, navigation, busy, error, act } = props;
|
|
205
247
|
const key = project.key;
|
|
206
|
-
const
|
|
248
|
+
const current = route.number === undefined
|
|
207
249
|
? data.tasks.find((candidate) => candidate.id === route.id)
|
|
208
250
|
: data.tasks.find((candidate) => candidate.number === route.number);
|
|
251
|
+
// A task put away is not among the board's (ADR-0029): it is asked for by itself.
|
|
252
|
+
const [fetched, setFetched] = useState(undefined);
|
|
253
|
+
const [missing, setMissing] = useState(undefined);
|
|
254
|
+
const { fetchTask } = data.actions;
|
|
255
|
+
const wanted = current === undefined && data.projectLoaded
|
|
256
|
+
? route.number === undefined
|
|
257
|
+
? route.id
|
|
258
|
+
: String(route.number)
|
|
259
|
+
: undefined;
|
|
260
|
+
useEffect(() => {
|
|
261
|
+
if (wanted === undefined) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const controller = new AbortController();
|
|
265
|
+
fetchTask(wanted, controller.signal)
|
|
266
|
+
.then((found) => {
|
|
267
|
+
if (!controller.signal.aborted) {
|
|
268
|
+
setFetched(found);
|
|
269
|
+
}
|
|
270
|
+
})
|
|
271
|
+
.catch(() => {
|
|
272
|
+
if (!controller.signal.aborted) {
|
|
273
|
+
setMissing(wanted);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
return () => controller.abort();
|
|
277
|
+
}, [wanted, fetchTask]);
|
|
278
|
+
const task = current ??
|
|
279
|
+
(fetched !== undefined && (fetched.id === route.id || fetched.number === route.number)
|
|
280
|
+
? fetched
|
|
281
|
+
: undefined);
|
|
209
282
|
const [history, setHistory] = useState(undefined);
|
|
210
283
|
const [comments, setComments] = useState(undefined);
|
|
211
284
|
const { taskHistory, taskComments } = data.actions;
|
|
@@ -242,6 +315,9 @@ function TaskPage(props) {
|
|
|
242
315
|
return () => controller.abort();
|
|
243
316
|
}, [taskId, taskHistory, taskComments, feedLength]);
|
|
244
317
|
if (task === undefined) {
|
|
318
|
+
if (wanted !== undefined && missing !== wanted) {
|
|
319
|
+
return _jsx(Spinner, { label: words.common.loading });
|
|
320
|
+
}
|
|
245
321
|
return (_jsx(EmptyState, { title: words.task.noSuch.title, body: words.task.noSuch.body, action: _jsx(LinkButton, { href: projectHref(key), children: words.nav.board }) }));
|
|
246
322
|
}
|
|
247
323
|
const here = taskHref(key, task.number);
|
|
@@ -251,7 +327,12 @@ function TaskPage(props) {
|
|
|
251
327
|
}), onMove: (target, state) => void act(() => data.actions.updateTask(target.id, { state })), onRaiseDecision: (input) => void act(async () => {
|
|
252
328
|
await data.actions.raiseDecision(input);
|
|
253
329
|
navigation.replace(here);
|
|
254
|
-
}), 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)),
|
|
330
|
+
}), 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)), onArchive: (target) => void act(async () => {
|
|
331
|
+
await data.actions.archiveTask(target.id);
|
|
332
|
+
navigation.go(projectHref(key, "archive"));
|
|
333
|
+
}), onRestore: (target) => void act(async () => {
|
|
334
|
+
setFetched(await data.actions.restoreTask(target.id));
|
|
335
|
+
}), onComment: (draft) => void act(async () => {
|
|
255
336
|
await data.actions.comment(task.id, {
|
|
256
337
|
body: draft.body,
|
|
257
338
|
files: draft.files.map((file) => ({
|
|
@@ -278,7 +359,7 @@ function ProjectPage(props) {
|
|
|
278
359
|
if (route.name === "board") {
|
|
279
360
|
const me = data.me?.person ?? undefined;
|
|
280
361
|
const shown = filterTasks(data.tasks, route.filter, me);
|
|
281
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sc-page-head", children: [_jsx("h1", { className: "sc-page-title", children: project.name }), _jsx(LinkButton, { href: newTaskHref(key), variant: "primary", children: words.board.writeTask })] }), project.description.length > 0 && _jsx("p", { className: "sc-lead", children: project.description }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), data.tasks.length > 0 && (_jsx(BoardFilters, { filter: route.filter, categories: data.categories, goals: data.goals, people: data.people.filter(inWorkspace), me: me, shown: shown.length, total: data.tasks.length, onChange: (filter) => navigation.replace(boardHref(key, filter)) })), _jsx(components.Board, { tasks: shown, taskHref: href, onOpen: (task) => navigation.go(href(task)), onMove: onMove, empty: data.tasks.length === 0 ? (_jsx(EmptyState, { title: words.board.empty.title, body: words.board.empty.body, action: _jsx(LinkButton, { href: newTaskHref(key), children: words.board.writeTask }) })) : undefined })] }));
|
|
362
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sc-page-head", children: [_jsx("h1", { className: "sc-page-title", children: project.name }), _jsx(LinkButton, { href: newTaskHref(key), variant: "primary", children: words.board.writeTask })] }), project.description.length > 0 && _jsx("p", { className: "sc-lead", children: project.description }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), data.tasks.length > 0 && (_jsx(BoardFilters, { filter: route.filter, categories: data.categories, goals: data.goals, people: data.people.filter(inWorkspace), me: me, shown: shown.length, total: data.tasks.length, onChange: (filter) => navigation.replace(boardHref(key, filter)) })), _jsx(components.Board, { tasks: shown, taskHref: href, onOpen: (task) => navigation.go(href(task)), onMove: onMove, archiveHref: projectHref(key, "archive"), empty: data.tasks.length === 0 ? (_jsx(EmptyState, { title: words.board.empty.title, body: words.board.empty.body, action: _jsx(LinkButton, { href: newTaskHref(key), children: words.board.writeTask }) })) : undefined })] }));
|
|
282
363
|
}
|
|
283
364
|
if (route.name === "new-task") {
|
|
284
365
|
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "sc-page-head", children: _jsx("h1", { className: "sc-page-title", children: words.task.newTitle }) }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), _jsx("section", { className: "sc-panel sc-panel-form", "aria-label": words.task.newAria, children: _jsx(TaskForm, { people: data.people.filter(inWorkspace), parents: data.tasks, categories: data.categories, goals: data.goals, busy: busy, onSubmit: (input) => void act(async () => {
|
|
@@ -327,9 +408,24 @@ function ProjectPage(props) {
|
|
|
327
408
|
navigation.replace(here);
|
|
328
409
|
}), onCancel: () => navigation.back(here) }) })] }));
|
|
329
410
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
411
|
+
const now = today();
|
|
412
|
+
const towards = data.tasks.filter((task) => task.goalId === goal.id);
|
|
413
|
+
const month = route.month ?? goalMonth(goal, now);
|
|
414
|
+
const viewHref = (view) => goalHref(key, goal.id, { view });
|
|
415
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sc-page-head", children: [_jsx("h1", { className: "sc-page-title", children: roadmap.one }), _jsx(LinkButton, { href: projectHref(key, "roadmap"), children: roadmap.all })] }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), _jsx(GoalView, { goal: goal, tasks: data.tasks, taskHref: href, docHref: toDoc, today: now, editHref: owner ? goalHref(key, goal.id, { form: "edit" }) : undefined, onMove: owner
|
|
416
|
+
? (target, state) => void act(async () => {
|
|
417
|
+
await data.actions.updateGoal(target.id, { state });
|
|
418
|
+
// A goal closed takes its done and dropped tasks to the archive, if the person says so (ADR-0029).
|
|
419
|
+
const closed = towards.filter((task) => !OPEN_TASK_STATES.includes(task.state)).length;
|
|
420
|
+
if ((state === "done" || state === "dropped") &&
|
|
421
|
+
closed > 0 &&
|
|
422
|
+
window.confirm(roadmap.archiveAsk(closed))) {
|
|
423
|
+
await data.actions.archiveGoalTasks(target.id);
|
|
424
|
+
}
|
|
425
|
+
})
|
|
426
|
+
: undefined, onArchiveTasks: owner && towards.some((task) => !OPEN_TASK_STATES.includes(task.state))
|
|
427
|
+
? () => void act(() => data.actions.archiveGoalTasks(goal.id))
|
|
428
|
+
: undefined, busy: busy, view: route.view, viewHref: viewHref, board: _jsx(components.Board, { tasks: towards, taskHref: href, onOpen: (task) => navigation.go(href(task)), onMove: onMove, today: now, archiveHref: projectHref(key, "archive"), empty: towards.length === 0 ? _jsx("p", { className: "sc-muted", children: roadmap.noTasks }) : undefined }), calendar: _jsx(components.Calendar, { tasks: towards, month: month, today: now, categories: data.categories, goals: [goal], taskHref: href, goalHref: (target) => goalHref(key, target.id), monthHref: (wanted) => goalHref(key, goal.id, { view: "calendar", month: wanted }) }) })] }));
|
|
333
429
|
}
|
|
334
430
|
if (route.name === "docs") {
|
|
335
431
|
return (_jsx(DocsPage, { project: project, path: route.path, view: route.view, data: data, navigation: navigation }));
|
|
@@ -347,6 +443,9 @@ function ProjectPage(props) {
|
|
|
347
443
|
const decision = data.decisions.find((candidate) => candidate.id === route.id);
|
|
348
444
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sc-page-head", children: [_jsx("h1", { className: "sc-page-title", children: words.decisions.one }), _jsx(LinkButton, { href: projectHref(key, "decisions"), children: words.decisions.all })] }), error !== undefined && _jsx(Callout, { tone: "danger", children: error }), decision === undefined ? (_jsx(EmptyState, { title: words.decisions.noSuch.title, body: words.decisions.noSuch.body })) : (_jsx(DecisionCard, { decision: decision, task: decision.taskId === null ? undefined : tasksById.get(decision.taskId), taskHref: href, docHref: toDoc, onAnswer: onAnswer, onUpdate: onUpdate, busy: busy }))] }));
|
|
349
445
|
}
|
|
446
|
+
if (route.name === "archive") {
|
|
447
|
+
return _jsx(ArchivePage, { project: project, data: data });
|
|
448
|
+
}
|
|
350
449
|
if (route.name === "feed") {
|
|
351
450
|
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "sc-page-head", children: _jsx("h1", { className: "sc-page-title", children: words.feed.title }) }), _jsx(components.EventFeed, { events: data.events, href: (event) => {
|
|
352
451
|
const task = event.taskId === null ? undefined : tasksById.get(event.taskId);
|
|
@@ -443,7 +542,21 @@ function ProjectSettingsPage(props) {
|
|
|
443
542
|
navigation.replace(here);
|
|
444
543
|
}), onCancel: () => navigation.back(here) })) })] }));
|
|
445
544
|
}
|
|
446
|
-
|
|
545
|
+
if (route.form === "pack-token") {
|
|
546
|
+
if (!owner) {
|
|
547
|
+
return _jsx(NothingHere, {});
|
|
548
|
+
}
|
|
549
|
+
return (_jsxs(_Fragment, { children: [head, error !== undefined && _jsx(Callout, { tone: "danger", children: error }), _jsx("section", { className: "sc-panel sc-panel-form", "aria-label": words.projects.packToken.aria, children: _jsx(PackTokenForm, { set: project.packToken !== null, busy: busy, onSubmit: (token) => void act(async () => {
|
|
550
|
+
await data.actions.setPackToken(token);
|
|
551
|
+
navigation.replace(here);
|
|
552
|
+
}), onRemove: project.packToken === null
|
|
553
|
+
? undefined
|
|
554
|
+
: () => void act(async () => {
|
|
555
|
+
await data.actions.removePackToken();
|
|
556
|
+
navigation.replace(here);
|
|
557
|
+
}), onCancel: () => navigation.back(here) }) })] }));
|
|
558
|
+
}
|
|
559
|
+
return (_jsxs(_Fragment, { children: [head, error !== undefined && _jsx(Callout, { tone: "danger", children: error }), _jsx("section", { className: "sc-panel", "aria-label": settings.aria, children: _jsxs("dl", { className: "sc-facts sc-facts-plain", children: [_jsxs("div", { children: [_jsx("dt", { children: form.name }), _jsx("dd", { children: project.name })] }), _jsxs("div", { children: [_jsx("dt", { children: form.key }), _jsx("dd", { children: _jsx("code", { className: "sc-project-key", children: project.key }) })] }), _jsxs("div", { children: [_jsx("dt", { children: form.whoIsMember }), _jsx("dd", { children: words.vocabulary.visibility[project.visibility] })] }), _jsxs("div", { children: [_jsx("dt", { children: form.skillsAddress }), _jsx("dd", { children: project.skillsAddress !== null ? (_jsxs("code", { children: [skills?.source ?? "", project.skillsAddress] })) : skills?.address != null ? (settings.organizationsSkills(skills.address)) : (settings.noSkills) })] }), _jsxs("div", { children: [_jsx("dt", { children: settings.packToken }), _jsxs("dd", { children: [project.packToken === null ? (_jsx("span", { className: "sc-muted", children: settings.packTokenNone })) : (_jsxs(_Fragment, { children: [settings.packTokenSet, " ", _jsx(Time, { iso: project.packToken.setAt })] })), owner && (_jsxs(_Fragment, { children: [" ", _jsx("a", { href: projectSettingsHref(key, "pack-token"), children: settings.packTokenEdit })] }))] })] }), _jsxs("div", { children: [_jsx("dt", { children: form.symbol }), _jsx("dd", { children: _jsx(ProjectMark, { project: project, size: "sm" }) })] }), project.description.length > 0 && (_jsxs("div", { className: "sc-facts-wide", children: [_jsx("dt", { children: form.description }), _jsx("dd", { children: project.description })] }))] }) }), _jsxs("section", { className: "sc-panel", "aria-label": words.rules.projectRules, children: [_jsx("h2", { className: "sc-section-title", children: words.rules.projectRules }), rules === undefined ? (_jsx(Spinner, { label: words.rules.loading })) : (_jsx(RulesView, { rules: rules.project, scope: "project", docHref: (path) => docHref(key, path), editHref: owner ? projectSettingsHref(key, "rules") : undefined, onArchive: owner
|
|
447
560
|
? () => void act(async () => {
|
|
448
561
|
await data.actions.archiveDocument(RULES_PATH);
|
|
449
562
|
setRules(await data.actions.projectRules());
|
|
@@ -846,6 +959,7 @@ export function createConsole(config = {}) {
|
|
|
846
959
|
current: candidate.tag === pack.tag,
|
|
847
960
|
})), onLanguage: (tag) => void data.actions.updateMe({ language: tag }).catch(() => undefined), person: data.me.person, live: projectKey === undefined ? undefined : data.live, wide: route.name === "board" ||
|
|
848
961
|
route.name === "calendar" ||
|
|
962
|
+
(route.name === "goal" && route.form === undefined) ||
|
|
849
963
|
(route.name === "custom" &&
|
|
850
964
|
pages.some((candidate) => candidate.key === route.page && candidate.wide === true)), onNavigate: (href) => navigation.go(href), onSignOut: viaToken ? undefined : () => void data.actions.signOut(), children: page }));
|
|
851
965
|
}
|