@deskwork/studio 0.10.1 → 0.11.0
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/dist/lib/editorial-skills-catalogue.d.ts +15 -1
- package/dist/lib/editorial-skills-catalogue.d.ts.map +1 -1
- package/dist/lib/editorial-skills-catalogue.js +66 -59
- package/dist/lib/editorial-skills-catalogue.js.map +1 -1
- package/dist/lib/entry-resolver.d.ts +22 -0
- package/dist/lib/entry-resolver.d.ts.map +1 -0
- package/dist/lib/entry-resolver.js +42 -0
- package/dist/lib/entry-resolver.js.map +1 -0
- package/dist/lib/stage-affordances.d.ts +31 -0
- package/dist/lib/stage-affordances.d.ts.map +1 -0
- package/dist/lib/stage-affordances.js +37 -0
- package/dist/lib/stage-affordances.js.map +1 -0
- package/dist/pages/dashboard/affordances.d.ts +41 -0
- package/dist/pages/dashboard/affordances.d.ts.map +1 -0
- package/dist/pages/dashboard/affordances.js +87 -0
- package/dist/pages/dashboard/affordances.js.map +1 -0
- package/dist/pages/dashboard/affordances.ts +95 -0
- package/dist/pages/dashboard/data.d.ts +24 -0
- package/dist/pages/dashboard/data.d.ts.map +1 -0
- package/dist/pages/dashboard/data.js +49 -0
- package/dist/pages/dashboard/data.js.map +1 -0
- package/dist/pages/dashboard/data.ts +56 -0
- package/dist/pages/dashboard/header.d.ts +13 -0
- package/dist/pages/dashboard/header.d.ts.map +1 -0
- package/dist/pages/dashboard/header.js +70 -0
- package/dist/pages/dashboard/header.js.map +1 -0
- package/dist/pages/dashboard/header.ts +80 -0
- package/dist/pages/dashboard/section.d.ts +37 -0
- package/dist/pages/dashboard/section.d.ts.map +1 -0
- package/dist/pages/dashboard/section.js +117 -0
- package/dist/pages/dashboard/section.js.map +1 -0
- package/dist/pages/dashboard/section.ts +132 -0
- package/dist/pages/dashboard.d.ts +30 -21
- package/dist/pages/dashboard.d.ts.map +1 -1
- package/dist/pages/dashboard.js +34 -799
- package/dist/pages/dashboard.js.map +1 -1
- package/dist/pages/dashboard.ts +44 -980
- package/dist/pages/entry-review.d.ts +25 -0
- package/dist/pages/entry-review.d.ts.map +1 -0
- package/dist/pages/entry-review.js +148 -0
- package/dist/pages/entry-review.js.map +1 -0
- package/dist/pages/entry-review.ts +185 -0
- package/dist/pages/help.d.ts +10 -5
- package/dist/pages/help.d.ts.map +1 -1
- package/dist/pages/help.js +113 -99
- package/dist/pages/help.js.map +1 -1
- package/dist/pages/help.ts +113 -99
- package/dist/pages/index.d.ts +13 -1
- package/dist/pages/index.d.ts.map +1 -1
- package/dist/pages/index.js +39 -24
- package/dist/pages/index.js.map +1 -1
- package/dist/pages/index.ts +43 -27
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +23 -3
- package/dist/server.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-stage section renderer.
|
|
3
|
+
*
|
|
4
|
+
* Pipeline-redesign Task 34. Each of the eight stage sections renders
|
|
5
|
+
* with a section heading (stage name + entry count) and either a list
|
|
6
|
+
* of rows or an empty-state placeholder. Per-row HTML carries the
|
|
7
|
+
* sidecar-derived state inline (iteration count + reviewState badge)
|
|
8
|
+
* so an operator can see at a glance where each entry sits without
|
|
9
|
+
* opening it.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { html, unsafe, type RawHtml } from '../html.ts';
|
|
13
|
+
import type { Entry, Stage } from '@deskwork/core/schema/entry';
|
|
14
|
+
import {
|
|
15
|
+
iterationForCurrentStage,
|
|
16
|
+
renderReviewStateBadge,
|
|
17
|
+
renderRowActions,
|
|
18
|
+
} from './affordances.ts';
|
|
19
|
+
|
|
20
|
+
const STAGE_ORNAMENTS: Record<Stage, string> = {
|
|
21
|
+
Ideas: '◇',
|
|
22
|
+
Planned: '§',
|
|
23
|
+
Outlining: '⊹',
|
|
24
|
+
Drafting: '✎',
|
|
25
|
+
Final: '※',
|
|
26
|
+
Published: '✓',
|
|
27
|
+
Blocked: '⊘',
|
|
28
|
+
Cancelled: '✗',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const STAGE_EMPTY_MESSAGES: Record<Stage, string> = {
|
|
32
|
+
Ideas: 'No open ideas. Run /deskwork:add to capture one.',
|
|
33
|
+
Planned: 'Nothing planned. /deskwork:approve <slug> to graduate an idea.',
|
|
34
|
+
Outlining: 'Nothing in outlining.',
|
|
35
|
+
Drafting: 'No posts in drafting.',
|
|
36
|
+
Final: 'Nothing in final review.',
|
|
37
|
+
Published: 'No published posts yet.',
|
|
38
|
+
Blocked: 'Nothing blocked.',
|
|
39
|
+
Cancelled: 'No cancelled entries.',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Render one entry as a single dashboard row. Carries inline:
|
|
44
|
+
* - slug (linked to the review surface)
|
|
45
|
+
* - title
|
|
46
|
+
* - iteration count for the entry's currentStage
|
|
47
|
+
* - reviewState badge (or an em-dash placeholder)
|
|
48
|
+
* - updatedAt timestamp
|
|
49
|
+
* - per-stage action buttons
|
|
50
|
+
*/
|
|
51
|
+
export function renderRow(entry: Entry, index: number): RawHtml {
|
|
52
|
+
const iteration = iterationForCurrentStage(entry);
|
|
53
|
+
const reviewLink = `/dev/editorial-review/${entry.uuid}`;
|
|
54
|
+
const search = [entry.slug, entry.title, entry.keywords.join(' ')].join(' ').toLowerCase();
|
|
55
|
+
// Hierarchical entries (slugs containing `/`) get a visual indent
|
|
56
|
+
// marker the CSS layer reads. Storage stays flat; this is display-only.
|
|
57
|
+
const depth = entry.slug.split('/').length - 1;
|
|
58
|
+
const depthAttrs =
|
|
59
|
+
depth > 0
|
|
60
|
+
? unsafe(html` data-depth="${depth}" style="--er-row-depth: ${depth}"`)
|
|
61
|
+
: '';
|
|
62
|
+
|
|
63
|
+
return unsafe(html`
|
|
64
|
+
<div class="er-calendar-row-wrap" data-row-wrap data-search="${search}"${depthAttrs}>
|
|
65
|
+
<div class="er-calendar-row" data-stage="${entry.currentStage}"
|
|
66
|
+
data-uuid="${entry.uuid}" data-slug="${entry.slug}" data-search="${search}">
|
|
67
|
+
<span class="er-row-num">№ ${String(index + 1).padStart(2, '0')}</span>
|
|
68
|
+
<div class="er-calendar-body">
|
|
69
|
+
<span class="er-row-slug"><a href="${reviewLink}"
|
|
70
|
+
title="open the review surface">${entry.slug}</a></span>
|
|
71
|
+
<span class="er-calendar-title">${entry.title}</span>
|
|
72
|
+
<span class="er-calendar-meta er-calendar-meta-iteration"
|
|
73
|
+
data-iteration="${iteration}">iteration: ${iteration}</span>
|
|
74
|
+
<span class="er-calendar-meta er-calendar-meta-updated"
|
|
75
|
+
title="${entry.updatedAt}">${formatDate(entry.updatedAt)}</span>
|
|
76
|
+
</div>
|
|
77
|
+
<span class="er-calendar-status">${renderReviewStateBadge(entry.reviewState)}</span>
|
|
78
|
+
${renderRowActions(entry)}
|
|
79
|
+
</div>
|
|
80
|
+
</div>`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Render one full stage section: heading + ornaments + count + rows.
|
|
85
|
+
* Empty stages render the placeholder message — keeping the section
|
|
86
|
+
* visible (rather than collapsing it) so the operator sees that the
|
|
87
|
+
* stage exists and is currently empty.
|
|
88
|
+
*/
|
|
89
|
+
export function renderStageSection(stage: Stage, entries: readonly Entry[]): RawHtml {
|
|
90
|
+
const body =
|
|
91
|
+
entries.length === 0
|
|
92
|
+
? unsafe(html`<div class="er-empty" data-empty-stage="${stage}"
|
|
93
|
+
style="padding: 1rem 0.25rem; font-size: 0.95rem;">
|
|
94
|
+
${STAGE_EMPTY_MESSAGES[stage]}
|
|
95
|
+
</div>`)
|
|
96
|
+
: unsafe(entries.map((e, i) => renderRow(e, i).__raw).join(''));
|
|
97
|
+
|
|
98
|
+
return unsafe(html`
|
|
99
|
+
<section class="er-section" id="stage-${stage.toLowerCase()}" data-stage-section="${stage}">
|
|
100
|
+
<h2 class="er-section-head">
|
|
101
|
+
<span>${stage}</span>
|
|
102
|
+
<span class="ornament">${STAGE_ORNAMENTS[stage]}</span>
|
|
103
|
+
<span class="count">№ ${entries.length}</span>
|
|
104
|
+
</h2>
|
|
105
|
+
${body}
|
|
106
|
+
</section>`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Render the reserved Distribution placeholder. Stays a separate
|
|
111
|
+
* sibling of the stage sections — distribution records (shortform
|
|
112
|
+
* cross-posts) are tracked under their own model and the dashboard
|
|
113
|
+
* surfaces only a placeholder here until that integration lands.
|
|
114
|
+
*/
|
|
115
|
+
export function renderDistributionPlaceholder(): RawHtml {
|
|
116
|
+
return unsafe(html`
|
|
117
|
+
<section class="er-section" id="stage-distribution" data-stage-section="Distribution">
|
|
118
|
+
<h2 class="er-section-head">
|
|
119
|
+
<span>Distribution</span>
|
|
120
|
+
<span class="ornament">⌘</span>
|
|
121
|
+
</h2>
|
|
122
|
+
<div class="er-empty" style="padding: 1rem 0.25rem; font-size: 0.95rem;">
|
|
123
|
+
Reserved for shortform DistributionRecords — separate model.
|
|
124
|
+
</div>
|
|
125
|
+
</section>`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function formatDate(iso: string): string {
|
|
129
|
+
// Trim to YYYY-MM-DD for compact display. Full timestamp is on the
|
|
130
|
+
// <span title="...">.
|
|
131
|
+
return iso.slice(0, 10);
|
|
132
|
+
}
|
|
@@ -1,32 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Studio dashboard page — `/dev/editorial-studio`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Pipeline-redesign Task 34. The dashboard renders eight stage
|
|
5
|
+
* sections — Ideas → Planned → Outlining → Drafting → Final →
|
|
6
|
+
* Published, plus Blocked and Cancelled — backed by sidecar reads
|
|
7
|
+
* under `<projectRoot>/.deskwork/entries/*.json`. Each row carries
|
|
8
|
+
* the entry's iteration count for its current stage and a
|
|
9
|
+
* reviewState badge so an operator can see at a glance where each
|
|
10
|
+
* entry sits without opening it.
|
|
9
11
|
*
|
|
10
|
-
*
|
|
11
|
-
* (
|
|
12
|
-
*
|
|
12
|
+
* Replaces the legacy calendar.md + workflow store rendering. The
|
|
13
|
+
* scaffold (folio, masthead, filter strip, layout) is preserved so
|
|
14
|
+
* existing CSS keeps working.
|
|
13
15
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* The renderer's data flow:
|
|
17
|
+
* 1. loadDashboardData reads every sidecar and groups by stage.
|
|
18
|
+
* 2. Each of the eight stages renders via `renderStageSection`.
|
|
19
|
+
* 3. The Distribution placeholder pins beneath the stage sections.
|
|
20
|
+
*
|
|
21
|
+
* The legacy export `renderDashboard` stays — server.ts wires it as
|
|
22
|
+
* the page handler. The `getIndex` parameter is preserved for
|
|
23
|
+
* signature compatibility with the override resolver in server.ts;
|
|
24
|
+
* the new dashboard does not currently consume it (sidecars are the
|
|
25
|
+
* data source, not the on-disk content tree).
|
|
20
26
|
*/
|
|
21
|
-
import type { ContentIndex } from '@deskwork/core/content-index';
|
|
22
27
|
import type { StudioContext } from '../routes/api.ts';
|
|
28
|
+
import type { ContentIndex } from '@deskwork/core/content-index';
|
|
23
29
|
/**
|
|
24
|
-
* Per-request content-index getter.
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* dashboard falls back to the slug-template path.
|
|
30
|
+
* Per-request content-index getter. Preserved for compatibility with
|
|
31
|
+
* `runTemplateOverride` in server.ts — the override resolver calls
|
|
32
|
+
* the dashboard with `(ctx, getIndex)` and we keep the signature
|
|
33
|
+
* symmetric. Sidecar-driven rendering does not consume it directly.
|
|
29
34
|
*/
|
|
30
35
|
export type DashboardIndexGetter = (site: string) => ContentIndex;
|
|
31
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Render the studio dashboard. Async because sidecar reads hit disk;
|
|
38
|
+
* the route handler in server.ts awaits the result before sending it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function renderDashboard(ctx: StudioContext, getIndex?: DashboardIndexGetter): Promise<string>;
|
|
32
41
|
//# sourceMappingURL=dashboard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/pages/dashboard.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/pages/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAUtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,YAAY,CAAC;AAElE;;;GAGG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,aAAa,EAClB,QAAQ,CAAC,EAAE,oBAAoB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAsCjB"}
|