@things-factory/ai-dashboard 10.1.256 → 10.1.258
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/card-dialogs.ts +31 -24
- package/client/components/card-library.ts +20 -16
- package/client/components/dashboard-card.ts +33 -28
- package/client/components/proposal-preview.ts +15 -16
- package/client/pages/my-dashboard-page.ts +33 -32
- package/client/utils/card-api.ts +28 -39
- package/dist-client/components/card-dialogs.d.ts +9 -5
- package/dist-client/components/card-dialogs.js +25 -35
- package/dist-client/components/card-dialogs.js.map +1 -1
- package/dist-client/components/card-library.d.ts +3 -3
- package/dist-client/components/card-library.js +13 -22
- package/dist-client/components/card-library.js.map +1 -1
- package/dist-client/components/dashboard-card.d.ts +5 -6
- package/dist-client/components/dashboard-card.js +26 -46
- package/dist-client/components/dashboard-card.js.map +1 -1
- package/dist-client/components/proposal-preview.d.ts +3 -5
- package/dist-client/components/proposal-preview.js +13 -25
- package/dist-client/components/proposal-preview.js.map +1 -1
- package/dist-client/pages/my-dashboard-page.d.ts +8 -5
- package/dist-client/pages/my-dashboard-page.js +31 -44
- package/dist-client/pages/my-dashboard-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/card-api.d.ts +20 -35
- package/dist-client/utils/card-api.js +12 -23
- package/dist-client/utils/card-api.js.map +1 -1
- package/package.json +9 -9
|
@@ -6,13 +6,19 @@ import { __decorate, __metadata } from "tslib";
|
|
|
6
6
|
*/
|
|
7
7
|
import '@material/web/icon/icon.js';
|
|
8
8
|
import '@things-factory/ai-assistant/dist-client/index.js';
|
|
9
|
+
import gql from 'graphql-tag';
|
|
9
10
|
import { LitElement, css, html, nothing } from 'lit';
|
|
10
|
-
import { customElement, property
|
|
11
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
12
|
+
import { QueryController } from '@operato/graphql';
|
|
11
13
|
import { i18next, localize } from '@operato/i18n';
|
|
12
|
-
import { cardApi } from '../utils/card-api.js';
|
|
13
14
|
import { drawsNothing, issueLine, partialLine } from '../utils/card-words.js';
|
|
14
15
|
const t = (key, options = {}) => String(i18next.t(key, options));
|
|
15
16
|
let ProposalPreview = class ProposalPreview extends localize(i18next)(LitElement) {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
/* The proposal run as the viewer, for the proposal shown (ADR-0190). */
|
|
20
|
+
this.preview = new QueryController(this, gql `query ($s: String!, $k: String!) { dashboardCardProposalPreview(sessionId: $s, proposalKey: $k) }`, { variables: () => (this.sessionId && this.proposalKey ? { s: this.sessionId, k: this.proposalKey } : undefined) });
|
|
21
|
+
}
|
|
16
22
|
static { this.styles = css `
|
|
17
23
|
:host {
|
|
18
24
|
display: block;
|
|
@@ -49,22 +55,12 @@ let ProposalPreview = class ProposalPreview extends localize(i18next)(LitElement
|
|
|
49
55
|
color: var(--ui-warn, #b26a00);
|
|
50
56
|
}
|
|
51
57
|
`; }
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (key && key !== this.readFor)
|
|
55
|
-
this.read(key);
|
|
58
|
+
get run() {
|
|
59
|
+
return this.preview.data?.dashboardCardProposalPreview;
|
|
56
60
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const run = await cardApi.preview(this.sessionId, this.proposalKey);
|
|
61
|
-
if (this.readFor === key)
|
|
62
|
-
this.run = run;
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
if (this.readFor === key)
|
|
66
|
-
this.failed = error?.message ?? String(error);
|
|
67
|
-
}
|
|
61
|
+
get failed() {
|
|
62
|
+
const error = this.preview.error;
|
|
63
|
+
return error ? (error.message ?? String(error)) : undefined;
|
|
68
64
|
}
|
|
69
65
|
render() {
|
|
70
66
|
if (this.failed)
|
|
@@ -96,14 +92,6 @@ __decorate([
|
|
|
96
92
|
property({ attribute: false }),
|
|
97
93
|
__metadata("design:type", String)
|
|
98
94
|
], ProposalPreview.prototype, "proposalKey", void 0);
|
|
99
|
-
__decorate([
|
|
100
|
-
state(),
|
|
101
|
-
__metadata("design:type", Object)
|
|
102
|
-
], ProposalPreview.prototype, "run", void 0);
|
|
103
|
-
__decorate([
|
|
104
|
-
state(),
|
|
105
|
-
__metadata("design:type", String)
|
|
106
|
-
], ProposalPreview.prototype, "failed", void 0);
|
|
107
95
|
ProposalPreview = __decorate([
|
|
108
96
|
customElement('ai-dashboard-proposal-preview')
|
|
109
97
|
], ProposalPreview);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposal-preview.js","sourceRoot":"","sources":["../../client/components/proposal-preview.ts"],"names":[],"mappings":";AAAA;;;;GAIG;AACH,OAAO,4BAA4B,CAAA;AACnC,OAAO,mDAAmD,CAAA;AAE1D,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"proposal-preview.js","sourceRoot":"","sources":["../../client/components/proposal-preview.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The preview under a card the conversation offers (ADR-0160 decisions 6, 9). The proposal holds the definition only;\n * the preview asks the server to run it as whoever is looking at the conversation, so a value is never kept in the\n * conversation and nobody sees data their own doors do not open.\n */\nimport '@material/web/icon/icon.js'\nimport '@things-factory/ai-assistant/dist-client/index.js'\n\nimport gql from 'graphql-tag'\nimport { LitElement, css, html, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { QueryController } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\n\nimport { type CardRun } from '../utils/card-api.js'\nimport { drawsNothing, issueLine, partialLine } from '../utils/card-words.js'\n\nconst t = (key: string, options: Record<string, unknown> = {}) => String(i18next.t(key, options))\n\n@customElement('ai-dashboard-proposal-preview')\nexport class ProposalPreview extends localize(i18next)(LitElement) {\n static styles = css`\n :host {\n display: block;\n margin: 4px 0 8px;\n }\n\n .frame {\n padding: 10px 12px 8px;\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 .waiting,\n .note {\n font-size: 12px;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n .note {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-top: 6px;\n --md-icon-size: 14px;\n }\n\n .issue {\n font-size: 12px;\n color: var(--md-sys-color-error);\n }\n\n .partial {\n color: var(--ui-warn, #b26a00);\n }\n `\n\n @property({ attribute: false }) proposal: any\n @property({ attribute: false }) sessionId?: string\n @property({ attribute: false }) proposalKey?: string\n\n /* The proposal run as the viewer, for the proposal shown (ADR-0190). */\n private preview = new QueryController(\n this,\n gql`query ($s: String!, $k: String!) { dashboardCardProposalPreview(sessionId: $s, proposalKey: $k) }`,\n { variables: () => (this.sessionId && this.proposalKey ? { s: this.sessionId, k: this.proposalKey } : undefined) }\n )\n\n private get run(): CardRun | undefined {\n return this.preview.data?.dashboardCardProposalPreview\n }\n\n private get failed(): string | undefined {\n const error = this.preview.error as any\n return error ? (error.message ?? String(error)) : undefined\n }\n\n render() {\n if (this.failed) return html`<div class=\"frame issue\">${this.failed}</div>`\n if (!this.run) return html`<div class=\"frame waiting\">${t('ai-dashboard.preview.reading')}</div>`\n const issue = issueLine(this.run, t)\n const partial = partialLine(this.run, t)\n return html`<div class=\"frame\">\n ${issue\n ? html`<div class=\"issue\">${issue.text}</div>`\n : drawsNothing(this.run)\n ? html`<div class=\"waiting\">${t('ai-dashboard.card.nothing')}</div>`\n : html`<ox-assistant-workspace-view compact .workspace=${{ name: this.proposalKey, title: this.proposal?.card?.name ?? '', blocks: [this.run.block] }}></ox-assistant-workspace-view>`}\n ${partial ? html`<div class=\"note partial\"><md-icon>warning</md-icon>${partial}</div>` : nothing}\n <div class=\"note\"><md-icon>bolt</md-icon>${t('ai-dashboard.preview.note', { day: this.run.asOf })}</div>\n </div>`\n }\n}\n"]}
|
|
@@ -5,10 +5,15 @@ import { PageView } from '@operato/shell';
|
|
|
5
5
|
declare const MyDashboardPage_base: (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
|
|
6
6
|
export declare class MyDashboardPage extends MyDashboardPage_base {
|
|
7
7
|
static styles: import("lit").CSSResult[];
|
|
8
|
-
private places;
|
|
9
|
-
private loaded;
|
|
10
|
-
private error?;
|
|
11
8
|
private editing;
|
|
9
|
+
/** The places as moved here, shown while the move is being saved. */
|
|
10
|
+
private arranged?;
|
|
11
|
+
private board;
|
|
12
|
+
private arranging;
|
|
13
|
+
private unplacing;
|
|
14
|
+
private get places();
|
|
15
|
+
private get loaded();
|
|
16
|
+
private get error();
|
|
12
17
|
private onChanged;
|
|
13
18
|
get context(): {
|
|
14
19
|
title: string;
|
|
@@ -30,8 +35,6 @@ export declare class MyDashboardPage extends MyDashboardPage_base {
|
|
|
30
35
|
connectedCallback(): void;
|
|
31
36
|
disconnectedCallback(): void;
|
|
32
37
|
updated(changes: Map<string, unknown>): void;
|
|
33
|
-
pageUpdated(changes: any): Promise<void>;
|
|
34
|
-
private load;
|
|
35
38
|
render(): import("lit-html").TemplateResult<1>;
|
|
36
39
|
private renderBoard;
|
|
37
40
|
private renderEmpty;
|
|
@@ -9,14 +9,16 @@ import { __decorate, __metadata } from "tslib";
|
|
|
9
9
|
import '@material/web/icon/icon.js';
|
|
10
10
|
import '../components/dashboard-card.js';
|
|
11
11
|
import '../components/card-library.js';
|
|
12
|
+
import gql from 'graphql-tag';
|
|
12
13
|
import { css, html, nothing } from 'lit';
|
|
13
14
|
import { customElement, state } from 'lit/decorators.js';
|
|
15
|
+
import { MutationController, QueryController } from '@operato/graphql';
|
|
14
16
|
import { i18next, localize } from '@operato/i18n';
|
|
15
17
|
import { notify, openPopup } from '@operato/layout';
|
|
16
18
|
import { PageView } from '@operato/shell';
|
|
17
19
|
import { DocumentPageStyles, ScrollbarStyles } from '@operato/styles';
|
|
18
20
|
import { askAssistant } from '@things-factory/ai-assistant/dist-client/index.js';
|
|
19
|
-
import { cardApi, DASHBOARD_CHANGED, dashboardChanged } from '../utils/card-api.js';
|
|
21
|
+
import { cardApi, CARD_FIELDS, DASHBOARD_CHANGED, dashboardChanged } from '../utils/card-api.js';
|
|
20
22
|
import { movedPlaces } from '../utils/card-words.js';
|
|
21
23
|
import { dashboardExamples } from '../utils/examples.js';
|
|
22
24
|
import { openCardAiPrompt, openCardRename, openCardShare, openCardVersions } from '../components/card-dialogs.js';
|
|
@@ -24,10 +26,16 @@ const t = (key, options = {}) => String(i18next.t(key, options));
|
|
|
24
26
|
let MyDashboardPage = class MyDashboardPage extends localize(i18next)(PageView) {
|
|
25
27
|
constructor() {
|
|
26
28
|
super(...arguments);
|
|
27
|
-
this.places = [];
|
|
28
|
-
this.loaded = false;
|
|
29
29
|
this.editing = false;
|
|
30
|
-
|
|
30
|
+
/* A page refresh, or a change told from elsewhere, reads the board again. */
|
|
31
|
+
this.board = new QueryController(this, gql `query { myDashboard { id order width height card { ${CARD_FIELDS} } } }`);
|
|
32
|
+
this.arranging = new MutationController(this, gql `mutation ($places: [DashboardPlaceInput!]!) { arrangeDashboard(places: $places) }`, {
|
|
33
|
+
refetch: () => [this.board]
|
|
34
|
+
});
|
|
35
|
+
this.unplacing = new MutationController(this, gql `mutation ($id: String!) { removeDashboardPlace(id: $id) }`, {
|
|
36
|
+
refetch: () => [this.board]
|
|
37
|
+
});
|
|
38
|
+
this.onChanged = () => this.board.refetch();
|
|
31
39
|
}
|
|
32
40
|
static { this.styles = [
|
|
33
41
|
DocumentPageStyles,
|
|
@@ -198,6 +206,16 @@ let MyDashboardPage = class MyDashboardPage extends localize(i18next)(PageView)
|
|
|
198
206
|
}
|
|
199
207
|
`
|
|
200
208
|
]; }
|
|
209
|
+
get places() {
|
|
210
|
+
return (this.arranging.pending && this.arranged) || this.board.data?.myDashboard || [];
|
|
211
|
+
}
|
|
212
|
+
get loaded() {
|
|
213
|
+
return !!this.board.answeredAt;
|
|
214
|
+
}
|
|
215
|
+
get error() {
|
|
216
|
+
const error = this.board.error;
|
|
217
|
+
return error ? (error.message ?? String(error)) : undefined;
|
|
218
|
+
}
|
|
201
219
|
get context() {
|
|
202
220
|
return {
|
|
203
221
|
title: t('ai-dashboard.title'),
|
|
@@ -222,23 +240,6 @@ let MyDashboardPage = class MyDashboardPage extends localize(i18next)(PageView)
|
|
|
222
240
|
if (changes.has('editing'))
|
|
223
241
|
this.updateContext();
|
|
224
242
|
}
|
|
225
|
-
/* Not awaited: the shell sets the tab's title only after this returns. */
|
|
226
|
-
async pageUpdated(changes) {
|
|
227
|
-
if (this.active && changes.active)
|
|
228
|
-
this.load();
|
|
229
|
-
}
|
|
230
|
-
async load() {
|
|
231
|
-
try {
|
|
232
|
-
this.places = await cardApi.myDashboard();
|
|
233
|
-
this.error = undefined;
|
|
234
|
-
}
|
|
235
|
-
catch (error) {
|
|
236
|
-
this.error = error?.message ?? String(error);
|
|
237
|
-
}
|
|
238
|
-
finally {
|
|
239
|
-
this.loaded = true;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
243
|
render() {
|
|
243
244
|
return html `<div class="page">
|
|
244
245
|
${this.error
|
|
@@ -300,16 +301,10 @@ let MyDashboardPage = class MyDashboardPage extends localize(i18next)(PageView)
|
|
|
300
301
|
placeOf(card) {
|
|
301
302
|
return this.places.find(one => one.card.id === card.id);
|
|
302
303
|
}
|
|
304
|
+
/* The board shows the move at once; a failed one goes back to the board read. */
|
|
303
305
|
async arrange(next) {
|
|
304
|
-
|
|
305
|
-
this.places
|
|
306
|
-
try {
|
|
307
|
-
await cardApi.arrange(next.map(({ id, order, width, height }) => ({ id, order, width, height })));
|
|
308
|
-
}
|
|
309
|
-
catch (error) {
|
|
310
|
-
this.places = before;
|
|
311
|
-
notify({ level: 'error', message: error?.message ?? String(error) });
|
|
312
|
-
}
|
|
306
|
+
this.arranged = next;
|
|
307
|
+
await this.arranging.run({ places: next.map(({ id, order, width, height }) => ({ id, order, width, height })) });
|
|
313
308
|
}
|
|
314
309
|
async onCardAction(event) {
|
|
315
310
|
const { action, card } = event.detail;
|
|
@@ -331,9 +326,9 @@ let MyDashboardPage = class MyDashboardPage extends localize(i18next)(PageView)
|
|
|
331
326
|
case 'unplace':
|
|
332
327
|
if (!place)
|
|
333
328
|
return;
|
|
334
|
-
await
|
|
335
|
-
|
|
336
|
-
return
|
|
329
|
+
if (await this.unplacing.run({ id: place.id }))
|
|
330
|
+
notify({ level: 'info', message: t('ai-dashboard.text.unplaced', { name: card.name }) });
|
|
331
|
+
return;
|
|
337
332
|
case 'left':
|
|
338
333
|
case 'right':
|
|
339
334
|
return place && this.arrange(movedPlaces(this.places, place.id, action === 'left' ? -1 : 1));
|
|
@@ -354,22 +349,14 @@ let MyDashboardPage = class MyDashboardPage extends localize(i18next)(PageView)
|
|
|
354
349
|
}
|
|
355
350
|
}
|
|
356
351
|
};
|
|
357
|
-
__decorate([
|
|
358
|
-
state(),
|
|
359
|
-
__metadata("design:type", Array)
|
|
360
|
-
], MyDashboardPage.prototype, "places", void 0);
|
|
361
352
|
__decorate([
|
|
362
353
|
state(),
|
|
363
354
|
__metadata("design:type", Object)
|
|
364
|
-
], MyDashboardPage.prototype, "
|
|
365
|
-
__decorate([
|
|
366
|
-
state(),
|
|
367
|
-
__metadata("design:type", String)
|
|
368
|
-
], MyDashboardPage.prototype, "error", void 0);
|
|
355
|
+
], MyDashboardPage.prototype, "editing", void 0);
|
|
369
356
|
__decorate([
|
|
370
357
|
state(),
|
|
371
|
-
__metadata("design:type",
|
|
372
|
-
], MyDashboardPage.prototype, "
|
|
358
|
+
__metadata("design:type", Array)
|
|
359
|
+
], MyDashboardPage.prototype, "arranged", void 0);
|
|
373
360
|
MyDashboardPage = __decorate([
|
|
374
361
|
customElement('my-dashboard-page')
|
|
375
362
|
], MyDashboardPage);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"my-dashboard-page.js","sourceRoot":"","sources":["../../client/pages/my-dashboard-page.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * 나의 대시보드 - the cards a person placed, drawn from the data as them (ADR-0160 decision 8).\n *\n * Cards are made in the AI conversation beside the page (its card tool is in front here) and saved by pressing the\n * card there; the library holds one's own cards and those shared with one. The page asks no model: each card asks\n * the server to run its definition, each on its own, so a slow card waits in its place.\n */\nimport '@material/web/icon/icon.js'\nimport '../components/dashboard-card.js'\nimport '../components/card-library.js'\n\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { notify, openPopup } from '@operato/layout'\nimport { PageView } from '@operato/shell'\nimport { DocumentPageStyles, ScrollbarStyles } from '@operato/styles'\nimport { askAssistant } from '@things-factory/ai-assistant/dist-client/index.js'\n\nimport { cardApi, DASHBOARD_CHANGED, dashboardChanged, type CardItem, type PlaceItem } from '../utils/card-api.js'\nimport { movedPlaces } from '../utils/card-words.js'\nimport { dashboardExamples } from '../utils/examples.js'\nimport { openCardAiPrompt, openCardRename, openCardShare, openCardVersions } from '../components/card-dialogs.js'\nimport type { CardAction } from '../components/dashboard-card.js'\n\nconst t = (key: string, options: Record<string, unknown> = {}) => String(i18next.t(key, options))\n\n\n@customElement('my-dashboard-page')\nexport class MyDashboardPage extends localize(i18next)(PageView) {\n static styles = [\n DocumentPageStyles,\n ScrollbarStyles,\n css`\n .page {\n gap: var(--spacing-large, 16px);\n }\n\n .lead {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px 16px;\n }\n\n .lead p {\n flex: 1;\n min-width: 240px;\n margin: 0;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n\n .chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 999px;\n background: var(--ui-accent-wash, color-mix(in srgb, var(--md-sys-color-primary) 12%, transparent));\n color: var(--ui-accent, var(--md-sys-color-primary));\n font-size: var(--ui-t-small, 12px);\n font-weight: 600;\n --md-icon-size: 16px;\n }\n\n .board {\n container-type: inline-size;\n }\n\n .grid {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n grid-auto-rows: minmax(250px, auto);\n grid-auto-flow: dense;\n gap: 16px;\n }\n\n .grid > * {\n grid-column: span var(--w, 2);\n grid-row: span var(--h, 1);\n }\n\n @container (max-width: 1100px) {\n .grid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .grid > .w3,\n .grid > .w4 {\n --w: 2;\n }\n }\n\n @container (max-width: 640px) {\n .grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .grid > * {\n --w: 1 !important;\n }\n }\n\n .empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 14px;\n max-width: 640px;\n margin: 6vh auto 0;\n padding: 36px 28px;\n border: 1px dashed var(--ui-line, var(--md-sys-color-outline-variant));\n border-radius: 16px;\n background: radial-gradient(120% 100% at 50% 0%, var(--ui-accent-wash, color-mix(in srgb, var(--md-sys-color-primary) 10%, transparent)) 0%, transparent 70%);\n text-align: center;\n }\n\n .empty .mark {\n display: grid;\n place-items: center;\n width: 56px;\n height: 56px;\n border-radius: 16px;\n background: var(--ui-accent, var(--md-sys-color-primary));\n color: var(--ui-on-accent, var(--md-sys-color-on-primary));\n --md-icon-size: 30px;\n box-shadow: 0 10px 24px -12px var(--ui-accent, var(--md-sys-color-primary));\n }\n\n .empty h2 {\n margin: 4px 0 0;\n font-size: var(--ui-t-page, 18px);\n font-weight: 650;\n }\n\n .empty p {\n margin: 0;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n\n .examples {\n display: flex;\n flex-direction: column;\n gap: 8px;\n width: 100%;\n margin-top: 6px;\n }\n\n .examples button,\n .empty .library {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n border: 1px solid var(--ui-line, var(--md-sys-color-outline-variant));\n border-radius: 10px;\n background: var(--ui-panel, var(--md-sys-color-surface-container-lowest));\n color: var(--ui-ink, var(--md-sys-color-on-surface));\n font: inherit;\n text-align: start;\n cursor: pointer;\n transition:\n border-color 0.15s ease,\n transform 0.15s ease;\n --md-icon-size: 18px;\n }\n\n .examples button md-icon {\n color: var(--ui-accent, var(--md-sys-color-primary));\n }\n\n .examples button:hover,\n .examples button:focus-visible,\n .empty .library:hover {\n border-color: var(--ui-accent, var(--md-sys-color-primary));\n transform: translateY(-1px);\n outline: none;\n }\n\n .empty .library {\n justify-content: center;\n border-style: dashed;\n background: transparent;\n }\n\n .notice {\n margin: 0;\n padding: 12px 14px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--ui-crit, #c62828) 8%, transparent);\n }\n\n .note {\n margin: 0;\n font-size: var(--ui-t-small, 12px);\n color: var(--ui-faint, var(--md-sys-color-on-surface-variant));\n }\n `\n ]\n\n @state() private places: PlaceItem[] = []\n @state() private loaded = false\n @state() private error?: string\n @state() private editing = false\n\n private onChanged = () => this.load()\n\n get context() {\n return {\n title: t('ai-dashboard.title'),\n frame: 'document',\n actions: [\n { title: t(this.editing ? 'ai-dashboard.button.done' : 'ai-dashboard.button.arrange'), action: () => (this.editing = !this.editing), icon: this.editing ? 'check' : 'dashboard_customize' },\n { title: t('ai-dashboard.button.library'), action: () => this.openLibrary(), icon: 'collections_bookmark' },\n { title: t('ai-dashboard.button.make'), action: () => this.make(), icon: 'auto_awesome', emphasis: { raised: true } }\n ]\n }\n }\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener(DASHBOARD_CHANGED, this.onChanged)\n }\n\n disconnectedCallback() {\n window.removeEventListener(DASHBOARD_CHANGED, this.onChanged)\n super.disconnectedCallback()\n }\n\n updated(changes: Map<string, unknown>) {\n /* The action bar follows the mode - its words say what pressing it does now. */\n if (changes.has('editing')) this.updateContext()\n }\n\n /* Not awaited: the shell sets the tab's title only after this returns. */\n async pageUpdated(changes: any) {\n if ((this as any).active && changes.active) this.load()\n }\n\n private async load() {\n try {\n this.places = await cardApi.myDashboard()\n this.error = undefined\n } catch (error: any) {\n this.error = error?.message ?? String(error)\n } finally {\n this.loaded = true\n }\n }\n\n render() {\n return html`<div class=\"page\">\n ${this.error\n ? html`<p class=\"notice\">${this.error}</p>`\n : this.loaded && !this.places.length\n ? this.renderEmpty()\n : this.places.length\n ? this.renderBoard()\n : nothing}\n </div>`\n }\n\n private renderBoard() {\n const sorted = [...this.places].sort((a, b) => a.order - b.order)\n return html`<div class=\"lead\">\n <p>${t('ai-dashboard.page.lead')}</p>\n ${this.editing ? html`<span class=\"chip\"><md-icon>dashboard_customize</md-icon>${t('ai-dashboard.page.arranging')}</span>` : nothing}\n </div>\n <div class=\"board\">\n <div class=\"grid\" @card-action=${(event: CustomEvent) => this.onCardAction(event)}>\n ${sorted.map(\n (place, i) => html`<ai-dashboard-card\n class=\"w${place.width} h${place.height}\"\n style=\"--w: ${place.width}; --h: ${place.height}\"\n data-place=${place.id}\n .card=${place.card}\n .width=${place.width}\n .height=${place.height}\n ?editing=${this.editing}\n ?first=${i === 0}\n ?last=${i === sorted.length - 1}\n ></ai-dashboard-card>`\n )}\n </div>\n </div>\n <p class=\"note\">${t('ai-dashboard.page.no-tokens')}</p>`\n }\n\n private renderEmpty() {\n return html`<div class=\"empty\">\n <span class=\"mark\"><md-icon>auto_awesome</md-icon></span>\n <h2>${t('ai-dashboard.page.empty-title')}</h2>\n <p>${t('ai-dashboard.page.empty-text')}</p>\n ${dashboardExamples().length\n ? html`<div class=\"examples\">\n ${dashboardExamples().map(key => html`<button @click=${() => this.askFor(t(key))}><md-icon>chat_bubble</md-icon><span>${t(key)}</span></button>`)}\n </div>`\n : nothing}\n <button class=\"library\" @click=${() => this.openLibrary()}><md-icon>collections_bookmark</md-icon>${t('ai-dashboard.page.from-library')}</button>\n <p class=\"note\">${t('ai-dashboard.page.no-tokens')}</p>\n </div>`\n }\n\n /** Sends a request to the conversation beside the page - this screen's, where the card tool is in front. */\n private async askFor(ask: string) {\n await askAssistant({ ask, continueCurrent: true })\n }\n\n private make() {\n askAssistant({ draft: t('ai-dashboard.page.make-draft'), continueCurrent: true })\n }\n\n private openLibrary() {\n openPopup(html`<ai-dashboard-card-library></ai-dashboard-card-library>`, { backdrop: true, size: 'large', title: t('ai-dashboard.library.title') })\n }\n\n private placeOf(card: CardItem) {\n return this.places.find(one => one.card.id === card.id)\n }\n\n private async arrange(next: PlaceItem[]) {\n const before = this.places\n this.places = next\n try {\n await cardApi.arrange(next.map(({ id, order, width, height }) => ({ id, order, width, height })))\n } catch (error: any) {\n this.places = before\n notify({ level: 'error', message: error?.message ?? String(error) })\n }\n }\n\n private async onCardAction(event: CustomEvent) {\n const { action, card } = event.detail as { action: CardAction; card: CardItem }\n const place = this.placeOf(card)\n try {\n switch (action) {\n case 'ai':\n return openCardAiPrompt(card)\n case 'rename':\n return openCardRename(card)\n case 'share':\n return openCardShare(card)\n case 'versions':\n return openCardVersions(card)\n case 'copy':\n await cardApi.copy(card.id)\n notify({ level: 'info', message: t('ai-dashboard.text.copied', { name: card.name }) })\n return dashboardChanged()\n case 'unplace':\n if (!place) return\n await cardApi.unplace(place.id)\n notify({ level: 'info', message: t('ai-dashboard.text.unplaced', { name: card.name }) })\n return this.load()\n case 'left':\n case 'right':\n return place && this.arrange(movedPlaces(this.places, place.id, action === 'left' ? -1 : 1))\n case 'wider':\n case 'narrower':\n case 'taller':\n case 'shorter': {\n if (!place) return\n const width = Math.min(4, Math.max(1, place.width + (action === 'wider' ? 1 : action === 'narrower' ? -1 : 0)))\n const height = Math.min(2, Math.max(1, place.height + (action === 'taller' ? 1 : action === 'shorter' ? -1 : 0)))\n return this.arrange(this.places.map(one => (one.id === place.id ? { ...one, width, height } : one)))\n }\n }\n } catch (error: any) {\n notify({ level: 'error', message: error?.message ?? String(error) })\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"my-dashboard-page.js","sourceRoot":"","sources":["../../client/pages/my-dashboard-page.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * 나의 대시보드 - the cards a person placed, drawn from the data as them (ADR-0160 decision 8).\n *\n * Cards are made in the AI conversation beside the page (its card tool is in front here) and saved by pressing the\n * card there; the library holds one's own cards and those shared with one. The page asks no model: each card asks\n * the server to run its definition, each on its own, so a slow card waits in its place.\n */\nimport '@material/web/icon/icon.js'\nimport '../components/dashboard-card.js'\nimport '../components/card-library.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { MutationController, QueryController } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify, openPopup } from '@operato/layout'\nimport { PageView } from '@operato/shell'\nimport { DocumentPageStyles, ScrollbarStyles } from '@operato/styles'\nimport { askAssistant } from '@things-factory/ai-assistant/dist-client/index.js'\n\nimport { cardApi, CARD_FIELDS, DASHBOARD_CHANGED, dashboardChanged, type CardItem, type PlaceItem } from '../utils/card-api.js'\nimport { movedPlaces } from '../utils/card-words.js'\nimport { dashboardExamples } from '../utils/examples.js'\nimport { openCardAiPrompt, openCardRename, openCardShare, openCardVersions } from '../components/card-dialogs.js'\nimport type { CardAction } from '../components/dashboard-card.js'\n\nconst t = (key: string, options: Record<string, unknown> = {}) => String(i18next.t(key, options))\n\n\n@customElement('my-dashboard-page')\nexport class MyDashboardPage extends localize(i18next)(PageView) {\n static styles = [\n DocumentPageStyles,\n ScrollbarStyles,\n css`\n .page {\n gap: var(--spacing-large, 16px);\n }\n\n .lead {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px 16px;\n }\n\n .lead p {\n flex: 1;\n min-width: 240px;\n margin: 0;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n\n .chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 999px;\n background: var(--ui-accent-wash, color-mix(in srgb, var(--md-sys-color-primary) 12%, transparent));\n color: var(--ui-accent, var(--md-sys-color-primary));\n font-size: var(--ui-t-small, 12px);\n font-weight: 600;\n --md-icon-size: 16px;\n }\n\n .board {\n container-type: inline-size;\n }\n\n .grid {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n grid-auto-rows: minmax(250px, auto);\n grid-auto-flow: dense;\n gap: 16px;\n }\n\n .grid > * {\n grid-column: span var(--w, 2);\n grid-row: span var(--h, 1);\n }\n\n @container (max-width: 1100px) {\n .grid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .grid > .w3,\n .grid > .w4 {\n --w: 2;\n }\n }\n\n @container (max-width: 640px) {\n .grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .grid > * {\n --w: 1 !important;\n }\n }\n\n .empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 14px;\n max-width: 640px;\n margin: 6vh auto 0;\n padding: 36px 28px;\n border: 1px dashed var(--ui-line, var(--md-sys-color-outline-variant));\n border-radius: 16px;\n background: radial-gradient(120% 100% at 50% 0%, var(--ui-accent-wash, color-mix(in srgb, var(--md-sys-color-primary) 10%, transparent)) 0%, transparent 70%);\n text-align: center;\n }\n\n .empty .mark {\n display: grid;\n place-items: center;\n width: 56px;\n height: 56px;\n border-radius: 16px;\n background: var(--ui-accent, var(--md-sys-color-primary));\n color: var(--ui-on-accent, var(--md-sys-color-on-primary));\n --md-icon-size: 30px;\n box-shadow: 0 10px 24px -12px var(--ui-accent, var(--md-sys-color-primary));\n }\n\n .empty h2 {\n margin: 4px 0 0;\n font-size: var(--ui-t-page, 18px);\n font-weight: 650;\n }\n\n .empty p {\n margin: 0;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n\n .examples {\n display: flex;\n flex-direction: column;\n gap: 8px;\n width: 100%;\n margin-top: 6px;\n }\n\n .examples button,\n .empty .library {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n border: 1px solid var(--ui-line, var(--md-sys-color-outline-variant));\n border-radius: 10px;\n background: var(--ui-panel, var(--md-sys-color-surface-container-lowest));\n color: var(--ui-ink, var(--md-sys-color-on-surface));\n font: inherit;\n text-align: start;\n cursor: pointer;\n transition:\n border-color 0.15s ease,\n transform 0.15s ease;\n --md-icon-size: 18px;\n }\n\n .examples button md-icon {\n color: var(--ui-accent, var(--md-sys-color-primary));\n }\n\n .examples button:hover,\n .examples button:focus-visible,\n .empty .library:hover {\n border-color: var(--ui-accent, var(--md-sys-color-primary));\n transform: translateY(-1px);\n outline: none;\n }\n\n .empty .library {\n justify-content: center;\n border-style: dashed;\n background: transparent;\n }\n\n .notice {\n margin: 0;\n padding: 12px 14px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--ui-crit, #c62828) 8%, transparent);\n }\n\n .note {\n margin: 0;\n font-size: var(--ui-t-small, 12px);\n color: var(--ui-faint, var(--md-sys-color-on-surface-variant));\n }\n `\n ]\n\n @state() private editing = false\n /** The places as moved here, shown while the move is being saved. */\n @state() private arranged?: PlaceItem[]\n\n /* A page refresh, or a change told from elsewhere, reads the board again. */\n private board = new QueryController(this, gql`query { myDashboard { id order width height card { ${CARD_FIELDS} } } }`)\n private arranging = new MutationController(this, gql`mutation ($places: [DashboardPlaceInput!]!) { arrangeDashboard(places: $places) }`, {\n refetch: () => [this.board]\n })\n private unplacing = new MutationController(this, gql`mutation ($id: String!) { removeDashboardPlace(id: $id) }`, {\n refetch: () => [this.board]\n })\n\n private get places(): PlaceItem[] {\n return (this.arranging.pending && this.arranged) || this.board.data?.myDashboard || []\n }\n\n private get loaded() {\n return !!this.board.answeredAt\n }\n\n private get error(): string | undefined {\n const error = this.board.error as any\n return error ? (error.message ?? String(error)) : undefined\n }\n\n private onChanged = () => this.board.refetch()\n\n get context() {\n return {\n title: t('ai-dashboard.title'),\n frame: 'document',\n actions: [\n { title: t(this.editing ? 'ai-dashboard.button.done' : 'ai-dashboard.button.arrange'), action: () => (this.editing = !this.editing), icon: this.editing ? 'check' : 'dashboard_customize' },\n { title: t('ai-dashboard.button.library'), action: () => this.openLibrary(), icon: 'collections_bookmark' },\n { title: t('ai-dashboard.button.make'), action: () => this.make(), icon: 'auto_awesome', emphasis: { raised: true } }\n ]\n }\n }\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener(DASHBOARD_CHANGED, this.onChanged)\n }\n\n disconnectedCallback() {\n window.removeEventListener(DASHBOARD_CHANGED, this.onChanged)\n super.disconnectedCallback()\n }\n\n updated(changes: Map<string, unknown>) {\n /* The action bar follows the mode - its words say what pressing it does now. */\n if (changes.has('editing')) this.updateContext()\n }\n\n render() {\n return html`<div class=\"page\">\n ${this.error\n ? html`<p class=\"notice\">${this.error}</p>`\n : this.loaded && !this.places.length\n ? this.renderEmpty()\n : this.places.length\n ? this.renderBoard()\n : nothing}\n </div>`\n }\n\n private renderBoard() {\n const sorted = [...this.places].sort((a, b) => a.order - b.order)\n return html`<div class=\"lead\">\n <p>${t('ai-dashboard.page.lead')}</p>\n ${this.editing ? html`<span class=\"chip\"><md-icon>dashboard_customize</md-icon>${t('ai-dashboard.page.arranging')}</span>` : nothing}\n </div>\n <div class=\"board\">\n <div class=\"grid\" @card-action=${(event: CustomEvent) => this.onCardAction(event)}>\n ${sorted.map(\n (place, i) => html`<ai-dashboard-card\n class=\"w${place.width} h${place.height}\"\n style=\"--w: ${place.width}; --h: ${place.height}\"\n data-place=${place.id}\n .card=${place.card}\n .width=${place.width}\n .height=${place.height}\n ?editing=${this.editing}\n ?first=${i === 0}\n ?last=${i === sorted.length - 1}\n ></ai-dashboard-card>`\n )}\n </div>\n </div>\n <p class=\"note\">${t('ai-dashboard.page.no-tokens')}</p>`\n }\n\n private renderEmpty() {\n return html`<div class=\"empty\">\n <span class=\"mark\"><md-icon>auto_awesome</md-icon></span>\n <h2>${t('ai-dashboard.page.empty-title')}</h2>\n <p>${t('ai-dashboard.page.empty-text')}</p>\n ${dashboardExamples().length\n ? html`<div class=\"examples\">\n ${dashboardExamples().map(key => html`<button @click=${() => this.askFor(t(key))}><md-icon>chat_bubble</md-icon><span>${t(key)}</span></button>`)}\n </div>`\n : nothing}\n <button class=\"library\" @click=${() => this.openLibrary()}><md-icon>collections_bookmark</md-icon>${t('ai-dashboard.page.from-library')}</button>\n <p class=\"note\">${t('ai-dashboard.page.no-tokens')}</p>\n </div>`\n }\n\n /** Sends a request to the conversation beside the page - this screen's, where the card tool is in front. */\n private async askFor(ask: string) {\n await askAssistant({ ask, continueCurrent: true })\n }\n\n private make() {\n askAssistant({ draft: t('ai-dashboard.page.make-draft'), continueCurrent: true })\n }\n\n private openLibrary() {\n openPopup(html`<ai-dashboard-card-library></ai-dashboard-card-library>`, { backdrop: true, size: 'large', title: t('ai-dashboard.library.title') })\n }\n\n private placeOf(card: CardItem) {\n return this.places.find(one => one.card.id === card.id)\n }\n\n /* The board shows the move at once; a failed one goes back to the board read. */\n private async arrange(next: PlaceItem[]) {\n this.arranged = next\n await this.arranging.run({ places: next.map(({ id, order, width, height }) => ({ id, order, width, height })) })\n }\n\n private async onCardAction(event: CustomEvent) {\n const { action, card } = event.detail as { action: CardAction; card: CardItem }\n const place = this.placeOf(card)\n try {\n switch (action) {\n case 'ai':\n return openCardAiPrompt(card)\n case 'rename':\n return openCardRename(card)\n case 'share':\n return openCardShare(card)\n case 'versions':\n return openCardVersions(card)\n case 'copy':\n await cardApi.copy(card.id)\n notify({ level: 'info', message: t('ai-dashboard.text.copied', { name: card.name }) })\n return dashboardChanged()\n case 'unplace':\n if (!place) return\n if (await this.unplacing.run({ id: place.id })) notify({ level: 'info', message: t('ai-dashboard.text.unplaced', { name: card.name }) })\n return\n case 'left':\n case 'right':\n return place && this.arrange(movedPlaces(this.places, place.id, action === 'left' ? -1 : 1))\n case 'wider':\n case 'narrower':\n case 'taller':\n case 'shorter': {\n if (!place) return\n const width = Math.min(4, Math.max(1, place.width + (action === 'wider' ? 1 : action === 'narrower' ? -1 : 0)))\n const height = Math.min(2, Math.max(1, place.height + (action === 'taller' ? 1 : action === 'shorter' ? -1 : 0)))\n return this.arrange(this.places.map(one => (one.id === place.id ? { ...one, width, height } : one)))\n }\n }\n } catch (error: any) {\n notify({ level: 'error', message: error?.message ?? String(error) })\n }\n }\n}\n"]}
|