@things-factory/ai-assistant 10.1.99 → 10.1.101
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/client/components/entry-review.ts +19 -4
- package/client/components/workspace-view.ts +6 -1
- package/client/utils/entry-proposal.ts +12 -2
- package/dist-client/components/entry-review.d.ts +1 -1
- package/dist-client/components/entry-review.js +21 -5
- package/dist-client/components/entry-review.js.map +1 -1
- package/dist-client/components/workspace-view.d.ts +1 -1
- package/dist-client/components/workspace-view.js +7 -2
- package/dist-client/components/workspace-view.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/entry-proposal.d.ts +2 -0
- package/dist-client/utils/entry-proposal.js +11 -1
- package/dist-client/utils/entry-proposal.js.map +1 -1
- package/dist-server/service/data-entry/entry-apply.js +27 -1
- package/dist-server/service/data-entry/entry-apply.js.map +1 -1
- package/dist-server/service/data-entry/entry-target.d.ts +69 -6
- package/dist-server/service/data-entry/entry-target.js +159 -12
- package/dist-server/service/data-entry/entry-target.js.map +1 -1
- package/dist-server/service/data-entry/entry-tools.d.ts +13 -1
- package/dist-server/service/data-entry/entry-tools.js +27 -10
- package/dist-server/service/data-entry/entry-tools.js.map +1 -1
- package/dist-server/service/data-entry/entry-update.js +3 -3
- package/dist-server/service/data-entry/entry-update.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/server/service/data-entry/data-entry-update.test.ts +107 -1
- package/server/service/data-entry/data-entry.test.ts +41 -4
- package/server/service/data-entry/entry-apply.ts +26 -3
- package/server/service/data-entry/entry-target.ts +190 -17
- package/server/service/data-entry/entry-tools.ts +29 -10
- package/server/service/data-entry/entry-update.ts +4 -3
- package/test/entry-proposal.test.ts +11 -0
- package/translations/en.json +9 -1
- package/translations/ja.json +9 -1
- package/translations/ko.json +9 -1
- package/translations/ms.json +9 -1
- package/translations/zh.json +9 -1
|
@@ -11,6 +11,7 @@ import { LitElement, css, html, nothing } from 'lit'
|
|
|
11
11
|
import { customElement, property } from 'lit/decorators.js'
|
|
12
12
|
|
|
13
13
|
import { i18next } from '@operato/i18n'
|
|
14
|
+
import { ScrollbarStyles } from '@operato/styles'
|
|
14
15
|
|
|
15
16
|
import { entryCellIssues, entryIssueKey, type EntryIssueView, type EntryRowView, type EntryTotalView } from '../utils/entry-proposal.js'
|
|
16
17
|
|
|
@@ -25,6 +26,12 @@ function issueText(issue: EntryIssueView): string {
|
|
|
25
26
|
return String(i18next.t(entryIssueKey(issue), { defaultValue: issue.code, ...params }))
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
/** Where a row came from, in the screen's words - "said in the conversation" is the framework's, never the model's English. */
|
|
30
|
+
function sourceText(source: { attachmentId?: string; where?: string; person?: boolean }): string {
|
|
31
|
+
if (source.person) return t('source-person', 'said in the conversation')
|
|
32
|
+
return source.where || source.attachmentId || ''
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
/** An enum value in the person's words when the target names its key - the code only when it does not. */
|
|
29
36
|
function valueOf(column: { valueKeyPrefix?: string }, value: unknown): string {
|
|
30
37
|
if (column.valueKeyPrefix && typeof value === 'string' && value) return String(i18next.t(`${column.valueKeyPrefix}${value.toLowerCase()}`, { defaultValue: value }))
|
|
@@ -33,6 +40,8 @@ function valueOf(column: { valueKeyPrefix?: string }, value: unknown): string {
|
|
|
33
40
|
|
|
34
41
|
function shown(value: unknown): string {
|
|
35
42
|
if (value === undefined || value === null) return ''
|
|
43
|
+
/* A reference: the record's name the server found, or the text that found none. */
|
|
44
|
+
if (typeof value === 'object') return String((value as any).label ?? (value as any).text ?? (value as any).id ?? '')
|
|
36
45
|
if (typeof value === 'number') return value.toLocaleString(i18next.language || undefined)
|
|
37
46
|
if (typeof value === 'boolean') return value ? '✓' : '—'
|
|
38
47
|
return String(value)
|
|
@@ -40,7 +49,10 @@ function shown(value: unknown): string {
|
|
|
40
49
|
|
|
41
50
|
@customElement('ox-assistant-entry-review')
|
|
42
51
|
export class AssistantEntryReview extends LitElement {
|
|
43
|
-
|
|
52
|
+
/* The inner scroll areas wear the standard scrollbar, as the dock does. */
|
|
53
|
+
static styles = [
|
|
54
|
+
ScrollbarStyles,
|
|
55
|
+
css`
|
|
44
56
|
:host {
|
|
45
57
|
display: block;
|
|
46
58
|
margin: 4px 0 2px;
|
|
@@ -169,6 +181,7 @@ export class AssistantEntryReview extends LitElement {
|
|
|
169
181
|
color: var(--md-sys-color-on-surface-variant);
|
|
170
182
|
}
|
|
171
183
|
`
|
|
184
|
+
]
|
|
172
185
|
|
|
173
186
|
@property({ attribute: false }) proposal: any
|
|
174
187
|
|
|
@@ -184,7 +197,7 @@ export class AssistantEntryReview extends LitElement {
|
|
|
184
197
|
<span>${t('total', '{field} total {sum}', { field: name(total.field), sum: shown(total.all) })}</span>
|
|
185
198
|
${total.ready !== total.all ? html`<span>${t('total-ready', 'entered {sum}', { sum: shown(total.ready) })}</span>` : nothing}
|
|
186
199
|
${total.declared !== undefined
|
|
187
|
-
? html`<span>${t('total-declared', 'the material says {sum}', { sum: shown(total.declared) })}${total.declaredFound === false ? ` (${t('total-not-found', 'not found in the file')})` : ''}</span>
|
|
200
|
+
? html`<span>${total.declaredBy === 'file' ? t('total-declared-file', "the file's total line {sum}", { sum: shown(total.declared) }) : t('total-declared', 'the material says {sum}', { sum: shown(total.declared) })}${total.declaredFound === false ? ` (${t('total-not-found', 'not found in the file')})` : ''}</span>
|
|
188
201
|
${total.difference
|
|
189
202
|
? html`<span class="differs">${t('total-differs', 'differs by {sum}', { sum: shown(total.difference) })}</span>`
|
|
190
203
|
: html`<span class="matches"><md-icon>task_alt</md-icon> ${t('total-matches', 'matches')}</span>`}`
|
|
@@ -251,7 +264,9 @@ export class AssistantEntryReview extends LitElement {
|
|
|
251
264
|
const counts = p.counts ?? {}
|
|
252
265
|
return html`
|
|
253
266
|
<div class="summary" role="status">
|
|
267
|
+
${counts.groups ? html`<span>${t('groups', '{count} records', { count: counts.groups })}</span>` : nothing}
|
|
254
268
|
<span>${t('rows', '{count} rows', { count: counts.rows ?? rows.length })}</span>
|
|
269
|
+
${counts.groups && counts.groupsReady !== counts.groups ? html`<span class="blocked">${t('groups-kept-out', '{count} records kept out whole', { count: counts.groups - counts.groupsReady })}</span>` : nothing}
|
|
255
270
|
<span>${t('ready', '{count} ready', { count: counts.ready ?? 0 })}</span>
|
|
256
271
|
${counts.blocked ? html`<span class="blocked">${t('blocked', '{count} will not be entered', { count: counts.blocked })}</span>` : nothing}
|
|
257
272
|
${counts.cut ? html`<span class="blocked">${t('cut', '{count} left out over the limit', { count: counts.cut })}</span>` : nothing}
|
|
@@ -286,9 +301,9 @@ export class AssistantEntryReview extends LitElement {
|
|
|
286
301
|
${text || (issues.some(issue => issue.code === 'required') ? html`<span class="missing">${t('missing', 'missing')}</span>` : '')}
|
|
287
302
|
</td>`
|
|
288
303
|
})}
|
|
289
|
-
<td class="source" title=${(row.sources ?? []).map(
|
|
304
|
+
<td class="source" title=${(row.sources ?? []).map(sourceText).join(' · ')}>
|
|
290
305
|
${row.evidence ? html`<span class="verified" title=${t('evidence', 'found on line {line} of the file', { line: row.evidence.line })}><md-icon>task_alt</md-icon></span> ` : nothing}
|
|
291
|
-
${(row.sources ?? []).map(
|
|
306
|
+
${(row.sources ?? []).map(sourceText).join(' · ')}
|
|
292
307
|
${whole
|
|
293
308
|
.filter(issue => issue.code !== 'no-source')
|
|
294
309
|
.map(issue => html`<span class="row-issue ${issue.blocking ? 'blocking' : ''}">${issueText(issue)}</span>`)}
|
|
@@ -12,6 +12,7 @@ import { customElement, property, state } from 'lit/decorators.js'
|
|
|
12
12
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
|
|
13
13
|
|
|
14
14
|
import { i18next } from '@operato/i18n'
|
|
15
|
+
import { ScrollbarStyles } from '@operato/styles'
|
|
15
16
|
|
|
16
17
|
import { renderMarkdown } from './markdown.js'
|
|
17
18
|
import { sortRows, tableCsv, type WorkspaceBlockView, type WorkspaceView } from '../utils/workspace.js'
|
|
@@ -36,7 +37,10 @@ function ticksFor(max: number): number[] {
|
|
|
36
37
|
|
|
37
38
|
@customElement('ox-assistant-workspace-view')
|
|
38
39
|
export class AssistantWorkspaceView extends LitElement {
|
|
39
|
-
|
|
40
|
+
/* The inner scroll areas wear the standard scrollbar, as the dock does. */
|
|
41
|
+
static styles = [
|
|
42
|
+
ScrollbarStyles,
|
|
43
|
+
css`
|
|
40
44
|
:host {
|
|
41
45
|
display: block;
|
|
42
46
|
color: var(--md-sys-color-on-surface);
|
|
@@ -243,6 +247,7 @@ export class AssistantWorkspaceView extends LitElement {
|
|
|
243
247
|
margin-top: 0;
|
|
244
248
|
}
|
|
245
249
|
`
|
|
250
|
+
]
|
|
246
251
|
|
|
247
252
|
@property({ attribute: false }) workspace?: WorkspaceView
|
|
248
253
|
|
|
@@ -18,7 +18,7 @@ export interface EntryIssueView {
|
|
|
18
18
|
export interface EntryRowView {
|
|
19
19
|
index: number
|
|
20
20
|
values: Record<string, unknown>
|
|
21
|
-
sources: { attachmentId?: string; where?: string }[]
|
|
21
|
+
sources: { attachmentId?: string; where?: string; person?: boolean }[]
|
|
22
22
|
issues: EntryIssueView[]
|
|
23
23
|
/** The server found this row's numbers and dates together on this line of the cited file. */
|
|
24
24
|
evidence?: { attachmentId: string; line: number }
|
|
@@ -31,6 +31,7 @@ export interface EntryTotalView {
|
|
|
31
31
|
declared?: number
|
|
32
32
|
declaredFound?: boolean
|
|
33
33
|
difference?: number
|
|
34
|
+
declaredBy?: 'model' | 'file'
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export interface EntryRowResult {
|
|
@@ -52,7 +53,16 @@ export function isEntryProposal(proposal: any): boolean {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export function entryReadyCount(proposal: any): number {
|
|
55
|
-
|
|
56
|
+
const rows: EntryRowView[] = proposal?.rows ?? []
|
|
57
|
+
const blocked = (row: EntryRowView) => row.issues?.some(issue => issue.blocking)
|
|
58
|
+
if (!proposal?.groupBy) return rows.filter(row => !blocked(row)).length
|
|
59
|
+
/* Lines of one record go in together - a record with a line kept out is kept out whole, and its lines do not count. */
|
|
60
|
+
const keyOf = (row: EntryRowView) => {
|
|
61
|
+
const value: any = row.values?.[proposal.groupBy]
|
|
62
|
+
return value === undefined || value === null || value === '' ? `row-${row.index}` : String(typeof value === 'object' ? value.id ?? value.text : value)
|
|
63
|
+
}
|
|
64
|
+
const out = new Set(rows.filter(blocked).map(keyOf))
|
|
65
|
+
return rows.filter(row => !out.has(keyOf(row))).length
|
|
56
66
|
}
|
|
57
67
|
|
|
58
68
|
/** The i18n key of an issue - the target's own, or the framework's by code. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '@material/web/icon/icon.js';
|
|
2
2
|
import { LitElement } from 'lit';
|
|
3
3
|
export declare class AssistantEntryReview extends LitElement {
|
|
4
|
-
static styles: import("lit").CSSResult;
|
|
4
|
+
static styles: import("lit").CSSResult[];
|
|
5
5
|
proposal: any;
|
|
6
6
|
/** The sum of each totalled field, beside the total the material prints - a missing row shows here without reading every row. */
|
|
7
7
|
private renderTotals;
|
|
@@ -10,6 +10,7 @@ import '@material/web/icon/icon.js';
|
|
|
10
10
|
import { LitElement, css, html, nothing } from 'lit';
|
|
11
11
|
import { customElement, property } from 'lit/decorators.js';
|
|
12
12
|
import { i18next } from '@operato/i18n';
|
|
13
|
+
import { ScrollbarStyles } from '@operato/styles';
|
|
13
14
|
import { entryCellIssues, entryIssueKey } from '../utils/entry-proposal.js';
|
|
14
15
|
const SHOWN = 50;
|
|
15
16
|
const t = (key, defaultValue, options = {}) => i18next.t(`ai-assistant.entry.${key}`, { defaultValue, ...options });
|
|
@@ -19,6 +20,12 @@ function issueText(issue) {
|
|
|
19
20
|
params.values = params.values.join(', ');
|
|
20
21
|
return String(i18next.t(entryIssueKey(issue), { defaultValue: issue.code, ...params }));
|
|
21
22
|
}
|
|
23
|
+
/** Where a row came from, in the screen's words - "said in the conversation" is the framework's, never the model's English. */
|
|
24
|
+
function sourceText(source) {
|
|
25
|
+
if (source.person)
|
|
26
|
+
return t('source-person', 'said in the conversation');
|
|
27
|
+
return source.where || source.attachmentId || '';
|
|
28
|
+
}
|
|
22
29
|
/** An enum value in the person's words when the target names its key - the code only when it does not. */
|
|
23
30
|
function valueOf(column, value) {
|
|
24
31
|
if (column.valueKeyPrefix && typeof value === 'string' && value)
|
|
@@ -28,6 +35,9 @@ function valueOf(column, value) {
|
|
|
28
35
|
function shown(value) {
|
|
29
36
|
if (value === undefined || value === null)
|
|
30
37
|
return '';
|
|
38
|
+
/* A reference: the record's name the server found, or the text that found none. */
|
|
39
|
+
if (typeof value === 'object')
|
|
40
|
+
return String(value.label ?? value.text ?? value.id ?? '');
|
|
31
41
|
if (typeof value === 'number')
|
|
32
42
|
return value.toLocaleString(i18next.language || undefined);
|
|
33
43
|
if (typeof value === 'boolean')
|
|
@@ -35,7 +45,10 @@ function shown(value) {
|
|
|
35
45
|
return String(value);
|
|
36
46
|
}
|
|
37
47
|
let AssistantEntryReview = class AssistantEntryReview extends LitElement {
|
|
38
|
-
|
|
48
|
+
/* The inner scroll areas wear the standard scrollbar, as the dock does. */
|
|
49
|
+
static { this.styles = [
|
|
50
|
+
ScrollbarStyles,
|
|
51
|
+
css `
|
|
39
52
|
:host {
|
|
40
53
|
display: block;
|
|
41
54
|
margin: 4px 0 2px;
|
|
@@ -163,7 +176,8 @@ let AssistantEntryReview = class AssistantEntryReview extends LitElement {
|
|
|
163
176
|
margin-top: 4px;
|
|
164
177
|
color: var(--md-sys-color-on-surface-variant);
|
|
165
178
|
}
|
|
166
|
-
|
|
179
|
+
`
|
|
180
|
+
]; }
|
|
167
181
|
/** The sum of each totalled field, beside the total the material prints - a missing row shows here without reading every row. */
|
|
168
182
|
renderTotals(totals, columns) {
|
|
169
183
|
if (!totals.length)
|
|
@@ -177,7 +191,7 @@ let AssistantEntryReview = class AssistantEntryReview extends LitElement {
|
|
|
177
191
|
<span>${t('total', '{field} total {sum}', { field: name(total.field), sum: shown(total.all) })}</span>
|
|
178
192
|
${total.ready !== total.all ? html `<span>${t('total-ready', 'entered {sum}', { sum: shown(total.ready) })}</span>` : nothing}
|
|
179
193
|
${total.declared !== undefined
|
|
180
|
-
? html `<span>${t('total-declared', 'the material says {sum}', { sum: shown(total.declared) })}${total.declaredFound === false ? ` (${t('total-not-found', 'not found in the file')})` : ''}</span>
|
|
194
|
+
? html `<span>${total.declaredBy === 'file' ? t('total-declared-file', "the file's total line {sum}", { sum: shown(total.declared) }) : t('total-declared', 'the material says {sum}', { sum: shown(total.declared) })}${total.declaredFound === false ? ` (${t('total-not-found', 'not found in the file')})` : ''}</span>
|
|
181
195
|
${total.difference
|
|
182
196
|
? html `<span class="differs">${t('total-differs', 'differs by {sum}', { sum: shown(total.difference) })}</span>`
|
|
183
197
|
: html `<span class="matches"><md-icon>task_alt</md-icon> ${t('total-matches', 'matches')}</span>`}`
|
|
@@ -242,7 +256,9 @@ let AssistantEntryReview = class AssistantEntryReview extends LitElement {
|
|
|
242
256
|
const counts = p.counts ?? {};
|
|
243
257
|
return html `
|
|
244
258
|
<div class="summary" role="status">
|
|
259
|
+
${counts.groups ? html `<span>${t('groups', '{count} records', { count: counts.groups })}</span>` : nothing}
|
|
245
260
|
<span>${t('rows', '{count} rows', { count: counts.rows ?? rows.length })}</span>
|
|
261
|
+
${counts.groups && counts.groupsReady !== counts.groups ? html `<span class="blocked">${t('groups-kept-out', '{count} records kept out whole', { count: counts.groups - counts.groupsReady })}</span>` : nothing}
|
|
246
262
|
<span>${t('ready', '{count} ready', { count: counts.ready ?? 0 })}</span>
|
|
247
263
|
${counts.blocked ? html `<span class="blocked">${t('blocked', '{count} will not be entered', { count: counts.blocked })}</span>` : nothing}
|
|
248
264
|
${counts.cut ? html `<span class="blocked">${t('cut', '{count} left out over the limit', { count: counts.cut })}</span>` : nothing}
|
|
@@ -277,9 +293,9 @@ let AssistantEntryReview = class AssistantEntryReview extends LitElement {
|
|
|
277
293
|
${text || (issues.some(issue => issue.code === 'required') ? html `<span class="missing">${t('missing', 'missing')}</span>` : '')}
|
|
278
294
|
</td>`;
|
|
279
295
|
})}
|
|
280
|
-
<td class="source" title=${(row.sources ?? []).map(
|
|
296
|
+
<td class="source" title=${(row.sources ?? []).map(sourceText).join(' · ')}>
|
|
281
297
|
${row.evidence ? html `<span class="verified" title=${t('evidence', 'found on line {line} of the file', { line: row.evidence.line })}><md-icon>task_alt</md-icon></span> ` : nothing}
|
|
282
|
-
${(row.sources ?? []).map(
|
|
298
|
+
${(row.sources ?? []).map(sourceText).join(' · ')}
|
|
283
299
|
${whole
|
|
284
300
|
.filter(issue => issue.code !== 'no-source')
|
|
285
301
|
.map(issue => html `<span class="row-issue ${issue.blocking ? 'blocking' : ''}">${issueText(issue)}</span>`)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry-review.js","sourceRoot":"","sources":["../../client/components/entry-review.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The rows of a data entry proposal, as the person reviews them (operato-application/design/ai/data-entry.md §5).\n *\n * Read-only on purpose: a correction is said in the conversation (\"row 2 is 12,000\", \"drop the last one\")\n * and the model proposes again. What is wrong in a cell is marked on the cell - blocking in the error\n * colour, a note in the outline - and where each row came from is on the row.\n */\nimport '@material/web/icon/icon.js'\n\nimport { LitElement, css, html, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\n\nimport { entryCellIssues, entryIssueKey, type EntryIssueView, type EntryRowView, type EntryTotalView } from '../utils/entry-proposal.js'\n\nconst SHOWN = 50\n\nconst t = (key: string, defaultValue: string, options: Record<string, unknown> = {}) =>\n i18next.t(`ai-assistant.entry.${key}`, { defaultValue, ...options })\n\nfunction issueText(issue: EntryIssueView): string {\n const params = { ...(issue.params ?? {}) } as any\n if (Array.isArray(params.values)) params.values = params.values.join(', ')\n return String(i18next.t(entryIssueKey(issue), { defaultValue: issue.code, ...params }))\n}\n\n/** An enum value in the person's words when the target names its key - the code only when it does not. */\nfunction valueOf(column: { valueKeyPrefix?: string }, value: unknown): string {\n if (column.valueKeyPrefix && typeof value === 'string' && value) return String(i18next.t(`${column.valueKeyPrefix}${value.toLowerCase()}`, { defaultValue: value }))\n return shown(value)\n}\n\nfunction shown(value: unknown): string {\n if (value === undefined || value === null) return ''\n if (typeof value === 'number') return value.toLocaleString(i18next.language || undefined)\n if (typeof value === 'boolean') return value ? '✓' : '—'\n return String(value)\n}\n\n@customElement('ox-assistant-entry-review')\nexport class AssistantEntryReview extends LitElement {\n static styles = css`\n :host {\n display: block;\n margin: 4px 0 2px;\n font-size: 12px;\n color: var(--md-sys-color-on-surface);\n }\n\n .summary {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 10px;\n margin-bottom: 6px;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n .summary .blocked {\n color: var(--md-sys-color-error);\n font-weight: 600;\n }\n\n .scroll {\n max-height: 320px;\n overflow: auto;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n\n table {\n width: 100%;\n border-collapse: collapse;\n }\n\n th,\n td {\n padding: 4px 6px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n text-align: start;\n vertical-align: top;\n white-space: nowrap;\n }\n\n th {\n position: sticky;\n top: 0;\n background: var(--md-sys-color-surface-container);\n font-weight: 600;\n }\n\n td.num {\n text-align: end;\n font-variant-numeric: tabular-nums;\n }\n\n tr.blocked td {\n background: color-mix(in srgb, var(--md-sys-color-error) 6%, transparent);\n }\n\n td.bad {\n color: var(--md-sys-color-error);\n text-decoration: underline wavy var(--md-sys-color-error);\n text-underline-offset: 3px;\n }\n\n td.note {\n text-decoration: underline dotted var(--md-sys-color-outline);\n text-underline-offset: 3px;\n }\n\n .before {\n color: var(--md-sys-color-on-surface-variant);\n text-decoration: line-through;\n }\n\n .missing {\n color: var(--md-sys-color-error);\n font-style: italic;\n }\n\n .source {\n color: var(--md-sys-color-on-surface-variant);\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .row-issue {\n display: block;\n color: var(--md-sys-color-on-surface-variant);\n white-space: normal;\n }\n\n .row-issue.blocking {\n color: var(--md-sys-color-error);\n }\n\n .verified {\n color: var(--md-sys-color-primary);\n }\n\n .verified md-icon,\n .totals md-icon {\n --md-icon-size: 14px;\n vertical-align: -2px;\n }\n\n .totals {\n display: flex;\n flex-wrap: wrap;\n gap: 2px 12px;\n margin: 6px 0 0;\n font-variant-numeric: tabular-nums;\n }\n\n .totals .differs {\n color: var(--md-sys-color-error);\n font-weight: 600;\n }\n\n .totals .matches {\n color: var(--md-sys-color-primary);\n }\n\n .more,\n .check-failed {\n margin-top: 4px;\n color: var(--md-sys-color-on-surface-variant);\n }\n `\n\n @property({ attribute: false }) proposal: any\n\n /** The sum of each totalled field, beside the total the material prints - a missing row shows here without reading every row. */\n private renderTotals(totals: EntryTotalView[], columns: { name: string; labelKey?: string }[]) {\n if (!totals.length) return nothing\n const name = (field: string) => {\n const column = columns.find(one => one.name === field)\n return column?.labelKey ? i18next.t(column.labelKey) : field\n }\n return html`<div class=\"totals\" role=\"status\">\n ${totals.map(total => html`\n <span>${t('total', '{field} total {sum}', { field: name(total.field), sum: shown(total.all) })}</span>\n ${total.ready !== total.all ? html`<span>${t('total-ready', 'entered {sum}', { sum: shown(total.ready) })}</span>` : nothing}\n ${total.declared !== undefined\n ? html`<span>${t('total-declared', 'the material says {sum}', { sum: shown(total.declared) })}${total.declaredFound === false ? ` (${t('total-not-found', 'not found in the file')})` : ''}</span>\n ${total.difference\n ? html`<span class=\"differs\">${t('total-differs', 'differs by {sum}', { sum: shown(total.difference) })}</span>`\n : html`<span class=\"matches\"><md-icon>task_alt</md-icon> ${t('total-matches', 'matches')}</span>`}`\n : nothing}\n `)}\n </div>`\n }\n\n /**\n * A 수정안 - each record by its name, each changing field as what it holds now and what it becomes, and how the\n * record was picked. The \"now\" is the server's reading, never the model's memory.\n */\n private renderChanges(p: any) {\n const columns: { name: string; type: string; labelKey?: string; valueKeyPrefix?: string }[] = p.columns ?? []\n const rows: any[] = p.rows ?? []\n const counts = p.counts ?? {}\n const via = (row: any) =>\n row.via === 'current' ? t('via-current', 'the record on screen') : row.via === 'selected' ? t('via-selected', 'selected on screen') : t('via-id', 'found in the conversation')\n return html`\n <div class=\"summary\" role=\"status\">\n <span>${t('changes', '{count} records', { count: counts.rows ?? rows.length })}</span>\n <span>${t('ready', '{count} ready', { count: counts.ready ?? 0 })}</span>\n ${counts.blocked ? html`<span class=\"blocked\">${t('not-changed', '{count} will not be changed', { count: counts.blocked })}</span>` : nothing}\n </div>\n <div class=\"scroll\">\n <table>\n <thead>\n <tr>\n <th>#</th>\n <th>${t('record', 'record')}</th>\n ${columns.map(column => html`<th>${column.labelKey ? i18next.t(column.labelKey) : column.name}</th>`)}\n <th>${t('picked', 'picked')}</th>\n </tr>\n </thead>\n <tbody>\n ${rows.slice(0, SHOWN).map(row => {\n const blocked = (row.issues ?? []).some((issue: EntryIssueView) => issue.blocking)\n const whole = entryCellIssues(row)\n return html`<tr class=${blocked ? 'blocked' : ''}>\n <td class=\"num\">${row.index + 1}</td>\n <td>${row.label || row.id}${whole.map(issue => html`<span class=\"row-issue ${issue.blocking ? 'blocking' : ''}\">${issueText(issue)}</span>`)}</td>\n ${columns.map(column => {\n const issues = entryCellIssues(row, column.name)\n const bad = issues.some(issue => issue.blocking)\n const changes = column.name in (row.values ?? {})\n return html`<td class=\"${column.type === 'number' || column.type === 'integer' ? 'num' : ''} ${bad ? 'bad' : issues.length ? 'note' : ''}\" title=${issues.map(issueText).join('\\n')}>\n ${changes ? html`<span class=\"before\">${valueOf(column, row.before?.[column.name]) || '—'}</span> → <strong>${valueOf(column, row.values[column.name]) || '—'}</strong>` : ''}\n </td>`\n })}\n <td class=\"source\">${via(row)}</td>\n </tr>`\n })}\n </tbody>\n </table>\n </div>\n `\n }\n\n render() {\n const p = this.proposal ?? {}\n if (p.op === 'update') return this.renderChanges(p)\n const columns: { name: string; type: string; required?: boolean; labelKey?: string; valueKeyPrefix?: string }[] = p.columns ?? []\n const rows: EntryRowView[] = p.rows ?? []\n const counts = p.counts ?? {}\n return html`\n <div class=\"summary\" role=\"status\">\n <span>${t('rows', '{count} rows', { count: counts.rows ?? rows.length })}</span>\n <span>${t('ready', '{count} ready', { count: counts.ready ?? 0 })}</span>\n ${counts.blocked ? html`<span class=\"blocked\">${t('blocked', '{count} will not be entered', { count: counts.blocked })}</span>` : nothing}\n ${counts.cut ? html`<span class=\"blocked\">${t('cut', '{count} left out over the limit', { count: counts.cut })}</span>` : nothing}\n ${counts.verified ? html`<span class=\"verified\"><md-icon>task_alt</md-icon> ${t('verified', '{count} found in their file', { count: counts.verified })}</span>` : nothing}\n ${counts.unmatched ? html`<span class=\"blocked\">${t('unmatched', '{count} with a value their file does not have', { count: counts.unmatched })}</span>` : nothing}\n </div>\n <div class=\"scroll\">\n <table>\n <thead>\n <tr>\n <th>#</th>\n ${columns.map(column => html`<th>${column.labelKey ? i18next.t(column.labelKey) : column.name}${column.required ? ' *' : ''}</th>`)}\n <th>${t('source', 'from')}</th>\n </tr>\n </thead>\n <tbody>\n ${rows.slice(0, SHOWN).map(row => {\n const blocked = (row.issues ?? []).some(issue => issue.blocking)\n const whole = entryCellIssues(row)\n return html`\n <tr class=${blocked ? 'blocked' : ''}>\n <td class=\"num\">${row.index + 1}</td>\n ${columns.map(column => {\n const issues = entryCellIssues(row, column.name)\n const bad = issues.some(issue => issue.blocking)\n const value = row.values?.[column.name]\n const text = valueOf(column, value)\n return html`<td\n class=\"${column.type === 'number' || column.type === 'integer' ? 'num' : ''} ${bad ? 'bad' : issues.length ? 'note' : ''}\"\n title=${issues.map(issueText).join('\\n')}\n >\n ${text || (issues.some(issue => issue.code === 'required') ? html`<span class=\"missing\">${t('missing', 'missing')}</span>` : '')}\n </td>`\n })}\n <td class=\"source\" title=${(row.sources ?? []).map(source => source.where || source.attachmentId).join(' · ')}>\n ${row.evidence ? html`<span class=\"verified\" title=${t('evidence', 'found on line {line} of the file', { line: row.evidence.line })}><md-icon>task_alt</md-icon></span> ` : nothing}\n ${(row.sources ?? []).map(source => source.where || source.attachmentId).join(' · ')}\n ${whole\n .filter(issue => issue.code !== 'no-source')\n .map(issue => html`<span class=\"row-issue ${issue.blocking ? 'blocking' : ''}\">${issueText(issue)}</span>`)}\n ${whole.some(issue => issue.code === 'no-source') ? html`<span class=\"row-issue\">${issueText({ code: 'no-source', blocking: false })}</span>` : nothing}\n </td>\n </tr>\n `\n })}\n </tbody>\n </table>\n </div>\n ${this.renderTotals(p.totals ?? [], columns)}\n ${rows.length > SHOWN ? html`<div class=\"more\">${t('more-rows', '{count} more rows are not shown - they are entered too.', { count: rows.length - SHOWN })}</div>` : nothing}\n ${p.checkFailed ? html`<div class=\"check-failed\">${t('check-failed', 'the application could not check these rows; they are checked again when entered.')}</div>` : nothing}\n `\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"entry-review.js","sourceRoot":"","sources":["../../client/components/entry-review.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The rows of a data entry proposal, as the person reviews them (operato-application/design/ai/data-entry.md §5).\n *\n * Read-only on purpose: a correction is said in the conversation (\"row 2 is 12,000\", \"drop the last one\")\n * and the model proposes again. What is wrong in a cell is marked on the cell - blocking in the error\n * colour, a note in the outline - and where each row came from is on the row.\n */\nimport '@material/web/icon/icon.js'\n\nimport { LitElement, css, html, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { entryCellIssues, entryIssueKey, type EntryIssueView, type EntryRowView, type EntryTotalView } from '../utils/entry-proposal.js'\n\nconst SHOWN = 50\n\nconst t = (key: string, defaultValue: string, options: Record<string, unknown> = {}) =>\n i18next.t(`ai-assistant.entry.${key}`, { defaultValue, ...options })\n\nfunction issueText(issue: EntryIssueView): string {\n const params = { ...(issue.params ?? {}) } as any\n if (Array.isArray(params.values)) params.values = params.values.join(', ')\n return String(i18next.t(entryIssueKey(issue), { defaultValue: issue.code, ...params }))\n}\n\n/** Where a row came from, in the screen's words - \"said in the conversation\" is the framework's, never the model's English. */\nfunction sourceText(source: { attachmentId?: string; where?: string; person?: boolean }): string {\n if (source.person) return t('source-person', 'said in the conversation')\n return source.where || source.attachmentId || ''\n}\n\n/** An enum value in the person's words when the target names its key - the code only when it does not. */\nfunction valueOf(column: { valueKeyPrefix?: string }, value: unknown): string {\n if (column.valueKeyPrefix && typeof value === 'string' && value) return String(i18next.t(`${column.valueKeyPrefix}${value.toLowerCase()}`, { defaultValue: value }))\n return shown(value)\n}\n\nfunction shown(value: unknown): string {\n if (value === undefined || value === null) return ''\n /* A reference: the record's name the server found, or the text that found none. */\n if (typeof value === 'object') return String((value as any).label ?? (value as any).text ?? (value as any).id ?? '')\n if (typeof value === 'number') return value.toLocaleString(i18next.language || undefined)\n if (typeof value === 'boolean') return value ? '✓' : '—'\n return String(value)\n}\n\n@customElement('ox-assistant-entry-review')\nexport class AssistantEntryReview extends LitElement {\n /* The inner scroll areas wear the standard scrollbar, as the dock does. */\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n margin: 4px 0 2px;\n font-size: 12px;\n color: var(--md-sys-color-on-surface);\n }\n\n .summary {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 10px;\n margin-bottom: 6px;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n .summary .blocked {\n color: var(--md-sys-color-error);\n font-weight: 600;\n }\n\n .scroll {\n max-height: 320px;\n overflow: auto;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n\n table {\n width: 100%;\n border-collapse: collapse;\n }\n\n th,\n td {\n padding: 4px 6px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n text-align: start;\n vertical-align: top;\n white-space: nowrap;\n }\n\n th {\n position: sticky;\n top: 0;\n background: var(--md-sys-color-surface-container);\n font-weight: 600;\n }\n\n td.num {\n text-align: end;\n font-variant-numeric: tabular-nums;\n }\n\n tr.blocked td {\n background: color-mix(in srgb, var(--md-sys-color-error) 6%, transparent);\n }\n\n td.bad {\n color: var(--md-sys-color-error);\n text-decoration: underline wavy var(--md-sys-color-error);\n text-underline-offset: 3px;\n }\n\n td.note {\n text-decoration: underline dotted var(--md-sys-color-outline);\n text-underline-offset: 3px;\n }\n\n .before {\n color: var(--md-sys-color-on-surface-variant);\n text-decoration: line-through;\n }\n\n .missing {\n color: var(--md-sys-color-error);\n font-style: italic;\n }\n\n .source {\n color: var(--md-sys-color-on-surface-variant);\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .row-issue {\n display: block;\n color: var(--md-sys-color-on-surface-variant);\n white-space: normal;\n }\n\n .row-issue.blocking {\n color: var(--md-sys-color-error);\n }\n\n .verified {\n color: var(--md-sys-color-primary);\n }\n\n .verified md-icon,\n .totals md-icon {\n --md-icon-size: 14px;\n vertical-align: -2px;\n }\n\n .totals {\n display: flex;\n flex-wrap: wrap;\n gap: 2px 12px;\n margin: 6px 0 0;\n font-variant-numeric: tabular-nums;\n }\n\n .totals .differs {\n color: var(--md-sys-color-error);\n font-weight: 600;\n }\n\n .totals .matches {\n color: var(--md-sys-color-primary);\n }\n\n .more,\n .check-failed {\n margin-top: 4px;\n color: var(--md-sys-color-on-surface-variant);\n }\n `\n ]\n\n @property({ attribute: false }) proposal: any\n\n /** The sum of each totalled field, beside the total the material prints - a missing row shows here without reading every row. */\n private renderTotals(totals: EntryTotalView[], columns: { name: string; labelKey?: string }[]) {\n if (!totals.length) return nothing\n const name = (field: string) => {\n const column = columns.find(one => one.name === field)\n return column?.labelKey ? i18next.t(column.labelKey) : field\n }\n return html`<div class=\"totals\" role=\"status\">\n ${totals.map(total => html`\n <span>${t('total', '{field} total {sum}', { field: name(total.field), sum: shown(total.all) })}</span>\n ${total.ready !== total.all ? html`<span>${t('total-ready', 'entered {sum}', { sum: shown(total.ready) })}</span>` : nothing}\n ${total.declared !== undefined\n ? html`<span>${total.declaredBy === 'file' ? t('total-declared-file', \"the file's total line {sum}\", { sum: shown(total.declared) }) : t('total-declared', 'the material says {sum}', { sum: shown(total.declared) })}${total.declaredFound === false ? ` (${t('total-not-found', 'not found in the file')})` : ''}</span>\n ${total.difference\n ? html`<span class=\"differs\">${t('total-differs', 'differs by {sum}', { sum: shown(total.difference) })}</span>`\n : html`<span class=\"matches\"><md-icon>task_alt</md-icon> ${t('total-matches', 'matches')}</span>`}`\n : nothing}\n `)}\n </div>`\n }\n\n /**\n * A 수정안 - each record by its name, each changing field as what it holds now and what it becomes, and how the\n * record was picked. The \"now\" is the server's reading, never the model's memory.\n */\n private renderChanges(p: any) {\n const columns: { name: string; type: string; labelKey?: string; valueKeyPrefix?: string }[] = p.columns ?? []\n const rows: any[] = p.rows ?? []\n const counts = p.counts ?? {}\n const via = (row: any) =>\n row.via === 'current' ? t('via-current', 'the record on screen') : row.via === 'selected' ? t('via-selected', 'selected on screen') : t('via-id', 'found in the conversation')\n return html`\n <div class=\"summary\" role=\"status\">\n <span>${t('changes', '{count} records', { count: counts.rows ?? rows.length })}</span>\n <span>${t('ready', '{count} ready', { count: counts.ready ?? 0 })}</span>\n ${counts.blocked ? html`<span class=\"blocked\">${t('not-changed', '{count} will not be changed', { count: counts.blocked })}</span>` : nothing}\n </div>\n <div class=\"scroll\">\n <table>\n <thead>\n <tr>\n <th>#</th>\n <th>${t('record', 'record')}</th>\n ${columns.map(column => html`<th>${column.labelKey ? i18next.t(column.labelKey) : column.name}</th>`)}\n <th>${t('picked', 'picked')}</th>\n </tr>\n </thead>\n <tbody>\n ${rows.slice(0, SHOWN).map(row => {\n const blocked = (row.issues ?? []).some((issue: EntryIssueView) => issue.blocking)\n const whole = entryCellIssues(row)\n return html`<tr class=${blocked ? 'blocked' : ''}>\n <td class=\"num\">${row.index + 1}</td>\n <td>${row.label || row.id}${whole.map(issue => html`<span class=\"row-issue ${issue.blocking ? 'blocking' : ''}\">${issueText(issue)}</span>`)}</td>\n ${columns.map(column => {\n const issues = entryCellIssues(row, column.name)\n const bad = issues.some(issue => issue.blocking)\n const changes = column.name in (row.values ?? {})\n return html`<td class=\"${column.type === 'number' || column.type === 'integer' ? 'num' : ''} ${bad ? 'bad' : issues.length ? 'note' : ''}\" title=${issues.map(issueText).join('\\n')}>\n ${changes ? html`<span class=\"before\">${valueOf(column, row.before?.[column.name]) || '—'}</span> → <strong>${valueOf(column, row.values[column.name]) || '—'}</strong>` : ''}\n </td>`\n })}\n <td class=\"source\">${via(row)}</td>\n </tr>`\n })}\n </tbody>\n </table>\n </div>\n `\n }\n\n render() {\n const p = this.proposal ?? {}\n if (p.op === 'update') return this.renderChanges(p)\n const columns: { name: string; type: string; required?: boolean; labelKey?: string; valueKeyPrefix?: string }[] = p.columns ?? []\n const rows: EntryRowView[] = p.rows ?? []\n const counts = p.counts ?? {}\n return html`\n <div class=\"summary\" role=\"status\">\n ${counts.groups ? html`<span>${t('groups', '{count} records', { count: counts.groups })}</span>` : nothing}\n <span>${t('rows', '{count} rows', { count: counts.rows ?? rows.length })}</span>\n ${counts.groups && counts.groupsReady !== counts.groups ? html`<span class=\"blocked\">${t('groups-kept-out', '{count} records kept out whole', { count: counts.groups - counts.groupsReady })}</span>` : nothing}\n <span>${t('ready', '{count} ready', { count: counts.ready ?? 0 })}</span>\n ${counts.blocked ? html`<span class=\"blocked\">${t('blocked', '{count} will not be entered', { count: counts.blocked })}</span>` : nothing}\n ${counts.cut ? html`<span class=\"blocked\">${t('cut', '{count} left out over the limit', { count: counts.cut })}</span>` : nothing}\n ${counts.verified ? html`<span class=\"verified\"><md-icon>task_alt</md-icon> ${t('verified', '{count} found in their file', { count: counts.verified })}</span>` : nothing}\n ${counts.unmatched ? html`<span class=\"blocked\">${t('unmatched', '{count} with a value their file does not have', { count: counts.unmatched })}</span>` : nothing}\n </div>\n <div class=\"scroll\">\n <table>\n <thead>\n <tr>\n <th>#</th>\n ${columns.map(column => html`<th>${column.labelKey ? i18next.t(column.labelKey) : column.name}${column.required ? ' *' : ''}</th>`)}\n <th>${t('source', 'from')}</th>\n </tr>\n </thead>\n <tbody>\n ${rows.slice(0, SHOWN).map(row => {\n const blocked = (row.issues ?? []).some(issue => issue.blocking)\n const whole = entryCellIssues(row)\n return html`\n <tr class=${blocked ? 'blocked' : ''}>\n <td class=\"num\">${row.index + 1}</td>\n ${columns.map(column => {\n const issues = entryCellIssues(row, column.name)\n const bad = issues.some(issue => issue.blocking)\n const value = row.values?.[column.name]\n const text = valueOf(column, value)\n return html`<td\n class=\"${column.type === 'number' || column.type === 'integer' ? 'num' : ''} ${bad ? 'bad' : issues.length ? 'note' : ''}\"\n title=${issues.map(issueText).join('\\n')}\n >\n ${text || (issues.some(issue => issue.code === 'required') ? html`<span class=\"missing\">${t('missing', 'missing')}</span>` : '')}\n </td>`\n })}\n <td class=\"source\" title=${(row.sources ?? []).map(sourceText).join(' · ')}>\n ${row.evidence ? html`<span class=\"verified\" title=${t('evidence', 'found on line {line} of the file', { line: row.evidence.line })}><md-icon>task_alt</md-icon></span> ` : nothing}\n ${(row.sources ?? []).map(sourceText).join(' · ')}\n ${whole\n .filter(issue => issue.code !== 'no-source')\n .map(issue => html`<span class=\"row-issue ${issue.blocking ? 'blocking' : ''}\">${issueText(issue)}</span>`)}\n ${whole.some(issue => issue.code === 'no-source') ? html`<span class=\"row-issue\">${issueText({ code: 'no-source', blocking: false })}</span>` : nothing}\n </td>\n </tr>\n `\n })}\n </tbody>\n </table>\n </div>\n ${this.renderTotals(p.totals ?? [], columns)}\n ${rows.length > SHOWN ? html`<div class=\"more\">${t('more-rows', '{count} more rows are not shown - they are entered too.', { count: rows.length - SHOWN })}</div>` : nothing}\n ${p.checkFailed ? html`<div class=\"check-failed\">${t('check-failed', 'the application could not check these rows; they are checked again when entered.')}</div>` : nothing}\n `\n }\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import '@material/web/icon/icon.js';
|
|
|
2
2
|
import { LitElement, type TemplateResult } from 'lit';
|
|
3
3
|
import { type WorkspaceView } from '../utils/workspace.js';
|
|
4
4
|
export declare class AssistantWorkspaceView extends LitElement {
|
|
5
|
-
static styles: import("lit").CSSResult;
|
|
5
|
+
static styles: import("lit").CSSResult[];
|
|
6
6
|
workspace?: WorkspaceView;
|
|
7
7
|
private sorts;
|
|
8
8
|
private asTable;
|
|
@@ -11,6 +11,7 @@ import { LitElement, css, html, nothing, svg } from 'lit';
|
|
|
11
11
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
12
12
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
|
13
13
|
import { i18next } from '@operato/i18n';
|
|
14
|
+
import { ScrollbarStyles } from '@operato/styles';
|
|
14
15
|
import { renderMarkdown } from './markdown.js';
|
|
15
16
|
import { sortRows, tableCsv } from '../utils/workspace.js';
|
|
16
17
|
const LIGHT = ['#2a78d6', '#eb6834', '#1baf7a', '#eda100', '#e87ba4', '#008300', '#4a3aa7', '#e34948'];
|
|
@@ -33,7 +34,10 @@ let AssistantWorkspaceView = class AssistantWorkspaceView extends LitElement {
|
|
|
33
34
|
this.asTable = new Set();
|
|
34
35
|
this.dark = false;
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
/* The inner scroll areas wear the standard scrollbar, as the dock does. */
|
|
38
|
+
static { this.styles = [
|
|
39
|
+
ScrollbarStyles,
|
|
40
|
+
css `
|
|
37
41
|
:host {
|
|
38
42
|
display: block;
|
|
39
43
|
color: var(--md-sys-color-on-surface);
|
|
@@ -239,7 +243,8 @@ let AssistantWorkspaceView = class AssistantWorkspaceView extends LitElement {
|
|
|
239
243
|
.markdown :first-child {
|
|
240
244
|
margin-top: 0;
|
|
241
245
|
}
|
|
242
|
-
|
|
246
|
+
`
|
|
247
|
+
]; }
|
|
243
248
|
connectedCallback() {
|
|
244
249
|
super.connectedCallback();
|
|
245
250
|
this.dark = document.body.classList.contains('dark');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-view.js","sourceRoot":"","sources":["../../client/components/workspace-view.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The blocks of an AI 작업판, drawn (operato-application/design/ai/workspace.md §3).\n *\n * Every kind is drawn here - the model writes no HTML. Charts use the eight validated categorical colours in\n * a fixed order (dataviz reference palette, light and dark each checked); three of the light ones sit under\n * 3:1 against the surface, so every chart carries its legend (two series or more) and a table view.\n */\nimport '@material/web/icon/icon.js'\n\nimport { LitElement, css, html, nothing, svg, type TemplateResult } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\n\nimport { i18next } from '@operato/i18n'\n\nimport { renderMarkdown } from './markdown.js'\nimport { sortRows, tableCsv, type WorkspaceBlockView, type WorkspaceView } from '../utils/workspace.js'\n\nconst LIGHT = ['#2a78d6', '#eb6834', '#1baf7a', '#eda100', '#e87ba4', '#008300', '#4a3aa7', '#e34948']\nconst DARK = ['#3987e5', '#d95926', '#199e70', '#c98500', '#d55181', '#008300', '#9085e9', '#e66767']\n\nconst t = (key: string, defaultValue: string, options: Record<string, unknown> = {}) =>\n String(i18next.t(`ai-assistant.workspace.${key}`, { defaultValue, ...options }))\n\nconst shown = (value: unknown) =>\n value === null || value === undefined ? '' : typeof value === 'number' ? value.toLocaleString(i18next.language || undefined) : String(value)\n\n/** Four round steps from zero to above the largest value. */\nfunction ticksFor(max: number): number[] {\n if (!(max > 0)) return [0, 1]\n const raw = max / 4\n const power = 10 ** Math.floor(Math.log10(raw))\n const step = [1, 2, 2.5, 5, 10].map(one => one * power).find(one => one >= raw) ?? raw\n return Array.from({ length: Math.ceil(max / step) + 1 }, (_, i) => Math.round(i * step * 1e6) / 1e6)\n}\n\n@customElement('ox-assistant-workspace-view')\nexport class AssistantWorkspaceView extends LitElement {\n static styles = css`\n :host {\n display: block;\n color: var(--md-sys-color-on-surface);\n font-size: 14px;\n line-height: 1.5;\n }\n\n section {\n margin: 0 0 20px;\n }\n\n h1,\n h2,\n h3 {\n margin: 24px 0 8px;\n line-height: 1.3;\n }\n\n h1 {\n font-size: 22px;\n }\n\n h2 {\n font-size: 18px;\n }\n\n h3 {\n font-size: 15px;\n }\n\n .metrics {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));\n gap: 10px;\n }\n\n .metric {\n padding: 12px 14px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 10px;\n background: var(--md-sys-color-surface-container-lowest);\n }\n\n .metric .label {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n }\n\n .metric .value {\n font-size: 22px;\n font-weight: 650;\n font-variant-numeric: tabular-nums;\n }\n\n .metric .note {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n }\n\n .bar {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n }\n\n .bar .caption {\n flex: 1;\n }\n\n .bar button {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n\n .bar md-icon {\n --md-icon-size: 16px;\n }\n\n .scroll {\n max-height: 560px;\n overflow: auto;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n }\n\n table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n }\n\n th,\n td {\n padding: 6px 10px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n text-align: start;\n white-space: nowrap;\n }\n\n th {\n position: sticky;\n top: 0;\n background: var(--md-sys-color-surface-container);\n font-weight: 600;\n }\n\n th button {\n border: 0;\n padding: 0;\n background: none;\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n\n td.num,\n th.num {\n text-align: end;\n font-variant-numeric: tabular-nums;\n }\n\n .chart svg {\n width: 100%;\n height: auto;\n display: block;\n }\n\n .chart .grid {\n stroke: var(--md-sys-color-outline-variant);\n stroke-width: 1;\n }\n\n .chart .tick {\n fill: var(--md-sys-color-on-surface-variant);\n font-size: 11px;\n }\n\n .legend {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 14px;\n margin-top: 6px;\n font-size: 12px;\n }\n\n .legend .swatch {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin-inline-end: 5px;\n border-radius: 3px;\n vertical-align: -1px;\n }\n\n .steps {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n .steps li {\n display: flex;\n gap: 8px;\n padding: 4px 0;\n }\n\n .steps md-icon {\n --md-icon-size: 18px;\n }\n\n .steps .done md-icon {\n color: var(--md-sys-color-primary);\n }\n\n .steps .failed md-icon {\n color: var(--md-sys-color-error);\n }\n\n .steps .note {\n display: block;\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n }\n\n .unreadable,\n .cut {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n font-style: italic;\n }\n\n .markdown :first-child {\n margin-top: 0;\n }\n `\n\n @property({ attribute: false }) workspace?: WorkspaceView\n\n @state() private sorts: Record<number, { column: string; direction: 'asc' | 'desc' }> = {}\n @state() private asTable = new Set<number>()\n @state() private dark = false\n\n private themeWatch?: MutationObserver\n\n connectedCallback() {\n super.connectedCallback()\n this.dark = document.body.classList.contains('dark')\n this.themeWatch = new MutationObserver(() => (this.dark = document.body.classList.contains('dark')))\n this.themeWatch.observe(document.body, { attributes: true, attributeFilter: ['class'] })\n }\n\n disconnectedCallback() {\n this.themeWatch?.disconnect()\n super.disconnectedCallback()\n }\n\n render() {\n const blocks = this.workspace?.blocks ?? []\n return html`${blocks.map((block, i) => this.block(block, i))}`\n }\n\n private block(block: WorkspaceBlockView, i: number): TemplateResult {\n switch (block.kind) {\n case 'heading':\n return block.level === 1 ? html`<h1>${block.text}</h1>` : block.level === 3 ? html`<h3>${block.text}</h3>` : html`<h2>${block.text}</h2>`\n case 'text':\n return html`<section class=\"markdown\">${unsafeHTML(renderMarkdown(block.markdown))}</section>`\n case 'metrics':\n return html`<section class=\"metrics\">\n ${(block.items ?? []).map(\n (one: any) => html`<div class=\"metric\">\n <div class=\"label\">${one.label}</div>\n <div class=\"value\">${shown(one.value)}${one.unit ? html` <small>${one.unit}</small>` : nothing}</div>\n ${one.note ? html`<div class=\"note\">${one.note}</div>` : nothing}\n </div>`\n )}\n </section>`\n case 'table':\n return this.table(block, i)\n case 'chart':\n return this.chart(block, i)\n case 'steps':\n return html`<section>\n <ol class=\"steps\">\n ${(block.items ?? []).map(\n (one: any) => html`<li class=${one.state}>\n <md-icon>${{ done: 'check_circle', doing: 'progress_activity', failed: 'error', todo: 'radio_button_unchecked' }[one.state as string] ?? 'radio_button_unchecked'}</md-icon>\n <span>${one.label}${one.note ? html`<span class=\"note\">${one.note}</span>` : nothing}</span>\n </li>`\n )}\n </ol>\n </section>`\n default:\n return html`<section class=\"unreadable\">${t('unreadable', 'a block that cannot be drawn ({reason})', { reason: block.reason ?? block.kind })}</section>`\n }\n }\n\n private table(block: WorkspaceBlockView, i: number): TemplateResult {\n const columns: { name: string; label?: string; type?: string }[] = block.columns ?? []\n const sort = this.sorts[i]\n const rows = sort ? sortRows(block.rows ?? [], sort.column, sort.direction, i18next.language) : block.rows ?? []\n const toggle = (column: string) =>\n (this.sorts = { ...this.sorts, [i]: { column, direction: sort?.column === column && sort.direction === 'asc' ? 'desc' : 'asc' } })\n return html`<section>\n <div class=\"bar\">\n <span class=\"caption\">${block.caption ?? ''} · ${t('rows', '{count} rows', { count: rows.length })}</span>\n <button @click=${() => this.download(block.caption || this.workspace?.title || 'table', columns, rows)}>\n <md-icon>download</md-icon>${t('csv', 'CSV')}\n </button>\n </div>\n ${this.tableOf(columns, rows, sort, toggle)}\n ${block.cut ? html`<div class=\"cut\">${t('cut', '{count} more rows were left out over the limit.', { count: block.cut })}</div>` : nothing}\n </section>`\n }\n\n private tableOf(columns: { name: string; label?: string; type?: string }[], rows: Record<string, any>[], sort?: { column: string; direction: string }, toggle?: (column: string) => void) {\n return html`<div class=\"scroll\">\n <table>\n <thead>\n <tr>\n ${columns.map(\n column => html`<th class=${column.type === 'number' ? 'num' : ''} aria-sort=${sort?.column === column.name ? (sort.direction === 'asc' ? 'ascending' : 'descending') : 'none'}>\n ${toggle\n ? html`<button @click=${() => toggle(column.name)}>${column.label || column.name}${sort?.column === column.name ? (sort.direction === 'asc' ? ' ▲' : ' ▼') : ''}</button>`\n : column.label || column.name}\n </th>`\n )}\n </tr>\n </thead>\n <tbody>\n ${rows.map(row => html`<tr>${columns.map(column => html`<td class=${column.type === 'number' || typeof row[column.name] === 'number' ? 'num' : ''}>${shown(row[column.name])}</td>`)}</tr>`)}\n </tbody>\n </table>\n </div>`\n }\n\n private chart(block: WorkspaceBlockView, i: number): TemplateResult {\n const colours = this.dark ? DARK : LIGHT\n const x: string[] = block.x ?? []\n const series: { name: string; other?: boolean; values: (number | null)[] }[] = block.series ?? []\n const name = (one: { name: string; other?: boolean }) => (one.other ? t('other', 'other') : one.name)\n const showingTable = this.asTable.has(i)\n const flip = () => {\n const next = new Set(this.asTable)\n next.has(i) ? next.delete(i) : next.add(i)\n this.asTable = next\n }\n\n const bar = html`<div class=\"bar\">\n <span class=\"caption\">${block.caption ?? ''}${block.unit ? ` (${block.unit})` : ''}</span>\n <button @click=${flip}><md-icon>${showingTable ? 'bar_chart' : 'table_rows'}</md-icon>${showingTable ? t('as-chart', 'chart') : t('as-table', 'table')}</button>\n </div>`\n\n if (showingTable) {\n const columns = [{ name: '_x', label: '' }, ...series.map((one, s) => ({ name: `s${s}`, label: name(one), type: 'number' }))]\n const rows = x.map((label, j) => Object.fromEntries([['_x', label], ...series.map((one, s) => [`s${s}`, one.values[j]])]))\n return html`<section class=\"chart\">${bar}${this.tableOf(columns, rows)}</section>`\n }\n\n const W = 640\n const H = 240\n const left = 56\n const bottom = 28\n const plotW = W - left - 8\n const plotH = H - bottom - 10\n const values = series.flatMap(one => one.values).filter((v): v is number => typeof v === 'number')\n const min = Math.min(0, ...values)\n const ticks = ticksFor(Math.max(...values, 0) - min).map(tick => tick + min)\n const top = ticks[ticks.length - 1] || 1\n const y = (v: number) => 10 + plotH - ((v - min) / (top - min || 1)) * plotH\n const band = plotW / Math.max(1, x.length)\n const everyNth = Math.max(1, Math.ceil(x.length / 12))\n\n const marks =\n block.chart === 'line'\n ? series.map((one, s) => {\n const points = one.values.map((v, j) => (typeof v === 'number' ? [left + band * (j + 0.5), y(v)] : null))\n const path = points.reduce((d, p, j) => (p ? `${d}${d && points[j - 1] ? 'L' : 'M'}${p[0]},${p[1]}` : d), '')\n return svg`<path d=${path} fill=\"none\" stroke=${colours[s % 8]} stroke-width=\"2\" stroke-linejoin=\"round\" stroke-linecap=\"round\"></path>\n ${points.map((p, j) =>\n p ? svg`<circle cx=${p[0]} cy=${p[1]} r=\"4\" fill=${colours[s % 8]} stroke=\"var(--md-sys-color-surface)\" stroke-width=\"2\"><title>${name(one)} · ${x[j]}: ${shown(one.values[j])}</title></circle>` : nothing\n )}`\n })\n : series.map((one, s) => {\n const inner = band * 0.7\n const width = Math.max(2, inner / series.length - 2)\n return one.values.map((v, j) => {\n if (typeof v !== 'number') return nothing\n const x0 = left + band * j + (band - inner) / 2 + s * (width + 2)\n const y0 = Math.min(y(v), y(0))\n const h = Math.max(1, Math.abs(y(v) - y(0)))\n return svg`<rect x=${x0} y=${y0} width=${width} height=${h} rx=\"3\" fill=${colours[s % 8]}><title>${name(one)} · ${x[j]}: ${shown(v)}</title></rect>`\n })\n })\n\n return html`<section class=\"chart\" role=\"img\" aria-label=${block.caption || series.map(name).join(', ')}>\n ${bar}\n <svg viewBox=\"0 0 ${W} ${H}\">\n ${ticks.map(tick => svg`<line class=\"grid\" x1=${left} x2=${W - 8} y1=${y(tick)} y2=${y(tick)}></line><text class=\"tick\" x=${left - 6} y=${y(tick) + 4} text-anchor=\"end\">${shown(tick)}</text>`)}\n ${marks}\n ${x.map((label, j) => (j % everyNth ? nothing : svg`<text class=\"tick\" x=${left + band * (j + 0.5)} y=${H - 8} text-anchor=\"middle\">${label}</text>`))}\n </svg>\n ${series.length > 1\n ? html`<div class=\"legend\">${series.map((one, s) => html`<span><span class=\"swatch\" style=\"background:${colours[s % 8]}\"></span>${name(one)}</span>`)}</div>`\n : nothing}\n </section>`\n }\n\n private download(title: string, columns: { name: string; label?: string }[], rows: Record<string, any>[]) {\n const blob = new Blob([tableCsv(columns, rows)], { type: 'text/csv;charset=utf-8' })\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = `${title.replace(/[\\\\/:*?\"<>|]+/g, '-').slice(0, 80)}.csv`\n link.click()\n setTimeout(() => URL.revokeObjectURL(url), 1000)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workspace-view.js","sourceRoot":"","sources":["../../client/components/workspace-view.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The blocks of an AI 작업판, drawn (operato-application/design/ai/workspace.md §3).\n *\n * Every kind is drawn here - the model writes no HTML. Charts use the eight validated categorical colours in\n * a fixed order (dataviz reference palette, light and dark each checked); three of the light ones sit under\n * 3:1 against the surface, so every chart carries its legend (two series or more) and a table view.\n */\nimport '@material/web/icon/icon.js'\n\nimport { LitElement, css, html, nothing, svg, type TemplateResult } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\n\nimport { i18next } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { renderMarkdown } from './markdown.js'\nimport { sortRows, tableCsv, type WorkspaceBlockView, type WorkspaceView } from '../utils/workspace.js'\n\nconst LIGHT = ['#2a78d6', '#eb6834', '#1baf7a', '#eda100', '#e87ba4', '#008300', '#4a3aa7', '#e34948']\nconst DARK = ['#3987e5', '#d95926', '#199e70', '#c98500', '#d55181', '#008300', '#9085e9', '#e66767']\n\nconst t = (key: string, defaultValue: string, options: Record<string, unknown> = {}) =>\n String(i18next.t(`ai-assistant.workspace.${key}`, { defaultValue, ...options }))\n\nconst shown = (value: unknown) =>\n value === null || value === undefined ? '' : typeof value === 'number' ? value.toLocaleString(i18next.language || undefined) : String(value)\n\n/** Four round steps from zero to above the largest value. */\nfunction ticksFor(max: number): number[] {\n if (!(max > 0)) return [0, 1]\n const raw = max / 4\n const power = 10 ** Math.floor(Math.log10(raw))\n const step = [1, 2, 2.5, 5, 10].map(one => one * power).find(one => one >= raw) ?? raw\n return Array.from({ length: Math.ceil(max / step) + 1 }, (_, i) => Math.round(i * step * 1e6) / 1e6)\n}\n\n@customElement('ox-assistant-workspace-view')\nexport class AssistantWorkspaceView extends LitElement {\n /* The inner scroll areas wear the standard scrollbar, as the dock does. */\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n color: var(--md-sys-color-on-surface);\n font-size: 14px;\n line-height: 1.5;\n }\n\n section {\n margin: 0 0 20px;\n }\n\n h1,\n h2,\n h3 {\n margin: 24px 0 8px;\n line-height: 1.3;\n }\n\n h1 {\n font-size: 22px;\n }\n\n h2 {\n font-size: 18px;\n }\n\n h3 {\n font-size: 15px;\n }\n\n .metrics {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));\n gap: 10px;\n }\n\n .metric {\n padding: 12px 14px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 10px;\n background: var(--md-sys-color-surface-container-lowest);\n }\n\n .metric .label {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n }\n\n .metric .value {\n font-size: 22px;\n font-weight: 650;\n font-variant-numeric: tabular-nums;\n }\n\n .metric .note {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n }\n\n .bar {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n }\n\n .bar .caption {\n flex: 1;\n }\n\n .bar button {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n\n .bar md-icon {\n --md-icon-size: 16px;\n }\n\n .scroll {\n max-height: 560px;\n overflow: auto;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n }\n\n table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n }\n\n th,\n td {\n padding: 6px 10px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n text-align: start;\n white-space: nowrap;\n }\n\n th {\n position: sticky;\n top: 0;\n background: var(--md-sys-color-surface-container);\n font-weight: 600;\n }\n\n th button {\n border: 0;\n padding: 0;\n background: none;\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n\n td.num,\n th.num {\n text-align: end;\n font-variant-numeric: tabular-nums;\n }\n\n .chart svg {\n width: 100%;\n height: auto;\n display: block;\n }\n\n .chart .grid {\n stroke: var(--md-sys-color-outline-variant);\n stroke-width: 1;\n }\n\n .chart .tick {\n fill: var(--md-sys-color-on-surface-variant);\n font-size: 11px;\n }\n\n .legend {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 14px;\n margin-top: 6px;\n font-size: 12px;\n }\n\n .legend .swatch {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin-inline-end: 5px;\n border-radius: 3px;\n vertical-align: -1px;\n }\n\n .steps {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n .steps li {\n display: flex;\n gap: 8px;\n padding: 4px 0;\n }\n\n .steps md-icon {\n --md-icon-size: 18px;\n }\n\n .steps .done md-icon {\n color: var(--md-sys-color-primary);\n }\n\n .steps .failed md-icon {\n color: var(--md-sys-color-error);\n }\n\n .steps .note {\n display: block;\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n }\n\n .unreadable,\n .cut {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n font-style: italic;\n }\n\n .markdown :first-child {\n margin-top: 0;\n }\n `\n ]\n\n @property({ attribute: false }) workspace?: WorkspaceView\n\n @state() private sorts: Record<number, { column: string; direction: 'asc' | 'desc' }> = {}\n @state() private asTable = new Set<number>()\n @state() private dark = false\n\n private themeWatch?: MutationObserver\n\n connectedCallback() {\n super.connectedCallback()\n this.dark = document.body.classList.contains('dark')\n this.themeWatch = new MutationObserver(() => (this.dark = document.body.classList.contains('dark')))\n this.themeWatch.observe(document.body, { attributes: true, attributeFilter: ['class'] })\n }\n\n disconnectedCallback() {\n this.themeWatch?.disconnect()\n super.disconnectedCallback()\n }\n\n render() {\n const blocks = this.workspace?.blocks ?? []\n return html`${blocks.map((block, i) => this.block(block, i))}`\n }\n\n private block(block: WorkspaceBlockView, i: number): TemplateResult {\n switch (block.kind) {\n case 'heading':\n return block.level === 1 ? html`<h1>${block.text}</h1>` : block.level === 3 ? html`<h3>${block.text}</h3>` : html`<h2>${block.text}</h2>`\n case 'text':\n return html`<section class=\"markdown\">${unsafeHTML(renderMarkdown(block.markdown))}</section>`\n case 'metrics':\n return html`<section class=\"metrics\">\n ${(block.items ?? []).map(\n (one: any) => html`<div class=\"metric\">\n <div class=\"label\">${one.label}</div>\n <div class=\"value\">${shown(one.value)}${one.unit ? html` <small>${one.unit}</small>` : nothing}</div>\n ${one.note ? html`<div class=\"note\">${one.note}</div>` : nothing}\n </div>`\n )}\n </section>`\n case 'table':\n return this.table(block, i)\n case 'chart':\n return this.chart(block, i)\n case 'steps':\n return html`<section>\n <ol class=\"steps\">\n ${(block.items ?? []).map(\n (one: any) => html`<li class=${one.state}>\n <md-icon>${{ done: 'check_circle', doing: 'progress_activity', failed: 'error', todo: 'radio_button_unchecked' }[one.state as string] ?? 'radio_button_unchecked'}</md-icon>\n <span>${one.label}${one.note ? html`<span class=\"note\">${one.note}</span>` : nothing}</span>\n </li>`\n )}\n </ol>\n </section>`\n default:\n return html`<section class=\"unreadable\">${t('unreadable', 'a block that cannot be drawn ({reason})', { reason: block.reason ?? block.kind })}</section>`\n }\n }\n\n private table(block: WorkspaceBlockView, i: number): TemplateResult {\n const columns: { name: string; label?: string; type?: string }[] = block.columns ?? []\n const sort = this.sorts[i]\n const rows = sort ? sortRows(block.rows ?? [], sort.column, sort.direction, i18next.language) : block.rows ?? []\n const toggle = (column: string) =>\n (this.sorts = { ...this.sorts, [i]: { column, direction: sort?.column === column && sort.direction === 'asc' ? 'desc' : 'asc' } })\n return html`<section>\n <div class=\"bar\">\n <span class=\"caption\">${block.caption ?? ''} · ${t('rows', '{count} rows', { count: rows.length })}</span>\n <button @click=${() => this.download(block.caption || this.workspace?.title || 'table', columns, rows)}>\n <md-icon>download</md-icon>${t('csv', 'CSV')}\n </button>\n </div>\n ${this.tableOf(columns, rows, sort, toggle)}\n ${block.cut ? html`<div class=\"cut\">${t('cut', '{count} more rows were left out over the limit.', { count: block.cut })}</div>` : nothing}\n </section>`\n }\n\n private tableOf(columns: { name: string; label?: string; type?: string }[], rows: Record<string, any>[], sort?: { column: string; direction: string }, toggle?: (column: string) => void) {\n return html`<div class=\"scroll\">\n <table>\n <thead>\n <tr>\n ${columns.map(\n column => html`<th class=${column.type === 'number' ? 'num' : ''} aria-sort=${sort?.column === column.name ? (sort.direction === 'asc' ? 'ascending' : 'descending') : 'none'}>\n ${toggle\n ? html`<button @click=${() => toggle(column.name)}>${column.label || column.name}${sort?.column === column.name ? (sort.direction === 'asc' ? ' ▲' : ' ▼') : ''}</button>`\n : column.label || column.name}\n </th>`\n )}\n </tr>\n </thead>\n <tbody>\n ${rows.map(row => html`<tr>${columns.map(column => html`<td class=${column.type === 'number' || typeof row[column.name] === 'number' ? 'num' : ''}>${shown(row[column.name])}</td>`)}</tr>`)}\n </tbody>\n </table>\n </div>`\n }\n\n private chart(block: WorkspaceBlockView, i: number): TemplateResult {\n const colours = this.dark ? DARK : LIGHT\n const x: string[] = block.x ?? []\n const series: { name: string; other?: boolean; values: (number | null)[] }[] = block.series ?? []\n const name = (one: { name: string; other?: boolean }) => (one.other ? t('other', 'other') : one.name)\n const showingTable = this.asTable.has(i)\n const flip = () => {\n const next = new Set(this.asTable)\n next.has(i) ? next.delete(i) : next.add(i)\n this.asTable = next\n }\n\n const bar = html`<div class=\"bar\">\n <span class=\"caption\">${block.caption ?? ''}${block.unit ? ` (${block.unit})` : ''}</span>\n <button @click=${flip}><md-icon>${showingTable ? 'bar_chart' : 'table_rows'}</md-icon>${showingTable ? t('as-chart', 'chart') : t('as-table', 'table')}</button>\n </div>`\n\n if (showingTable) {\n const columns = [{ name: '_x', label: '' }, ...series.map((one, s) => ({ name: `s${s}`, label: name(one), type: 'number' }))]\n const rows = x.map((label, j) => Object.fromEntries([['_x', label], ...series.map((one, s) => [`s${s}`, one.values[j]])]))\n return html`<section class=\"chart\">${bar}${this.tableOf(columns, rows)}</section>`\n }\n\n const W = 640\n const H = 240\n const left = 56\n const bottom = 28\n const plotW = W - left - 8\n const plotH = H - bottom - 10\n const values = series.flatMap(one => one.values).filter((v): v is number => typeof v === 'number')\n const min = Math.min(0, ...values)\n const ticks = ticksFor(Math.max(...values, 0) - min).map(tick => tick + min)\n const top = ticks[ticks.length - 1] || 1\n const y = (v: number) => 10 + plotH - ((v - min) / (top - min || 1)) * plotH\n const band = plotW / Math.max(1, x.length)\n const everyNth = Math.max(1, Math.ceil(x.length / 12))\n\n const marks =\n block.chart === 'line'\n ? series.map((one, s) => {\n const points = one.values.map((v, j) => (typeof v === 'number' ? [left + band * (j + 0.5), y(v)] : null))\n const path = points.reduce((d, p, j) => (p ? `${d}${d && points[j - 1] ? 'L' : 'M'}${p[0]},${p[1]}` : d), '')\n return svg`<path d=${path} fill=\"none\" stroke=${colours[s % 8]} stroke-width=\"2\" stroke-linejoin=\"round\" stroke-linecap=\"round\"></path>\n ${points.map((p, j) =>\n p ? svg`<circle cx=${p[0]} cy=${p[1]} r=\"4\" fill=${colours[s % 8]} stroke=\"var(--md-sys-color-surface)\" stroke-width=\"2\"><title>${name(one)} · ${x[j]}: ${shown(one.values[j])}</title></circle>` : nothing\n )}`\n })\n : series.map((one, s) => {\n const inner = band * 0.7\n const width = Math.max(2, inner / series.length - 2)\n return one.values.map((v, j) => {\n if (typeof v !== 'number') return nothing\n const x0 = left + band * j + (band - inner) / 2 + s * (width + 2)\n const y0 = Math.min(y(v), y(0))\n const h = Math.max(1, Math.abs(y(v) - y(0)))\n return svg`<rect x=${x0} y=${y0} width=${width} height=${h} rx=\"3\" fill=${colours[s % 8]}><title>${name(one)} · ${x[j]}: ${shown(v)}</title></rect>`\n })\n })\n\n return html`<section class=\"chart\" role=\"img\" aria-label=${block.caption || series.map(name).join(', ')}>\n ${bar}\n <svg viewBox=\"0 0 ${W} ${H}\">\n ${ticks.map(tick => svg`<line class=\"grid\" x1=${left} x2=${W - 8} y1=${y(tick)} y2=${y(tick)}></line><text class=\"tick\" x=${left - 6} y=${y(tick) + 4} text-anchor=\"end\">${shown(tick)}</text>`)}\n ${marks}\n ${x.map((label, j) => (j % everyNth ? nothing : svg`<text class=\"tick\" x=${left + band * (j + 0.5)} y=${H - 8} text-anchor=\"middle\">${label}</text>`))}\n </svg>\n ${series.length > 1\n ? html`<div class=\"legend\">${series.map((one, s) => html`<span><span class=\"swatch\" style=\"background:${colours[s % 8]}\"></span>${name(one)}</span>`)}</div>`\n : nothing}\n </section>`\n }\n\n private download(title: string, columns: { name: string; label?: string }[], rows: Record<string, any>[]) {\n const blob = new Blob([tableCsv(columns, rows)], { type: 'text/csv;charset=utf-8' })\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = `${title.replace(/[\\\\/:*?\"<>|]+/g, '-').slice(0, 80)}.csv`\n link.click()\n setTimeout(() => URL.revokeObjectURL(url), 1000)\n }\n}\n"]}
|