@things-factory/ai-dashboard 10.1.255 → 10.1.257
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/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
|
@@ -7,15 +7,17 @@ import '@material/web/button/filled-button.js'
|
|
|
7
7
|
import '@material/web/button/text-button.js'
|
|
8
8
|
import '@operato/popup/ox-popup-actions.js'
|
|
9
9
|
|
|
10
|
+
import gql from 'graphql-tag'
|
|
10
11
|
import { LitElement, css, html, nothing } from 'lit'
|
|
11
12
|
import { customElement, property, state } from 'lit/decorators.js'
|
|
12
13
|
|
|
14
|
+
import { QueryController } from '@operato/graphql'
|
|
13
15
|
import { i18next, localize } from '@operato/i18n'
|
|
14
16
|
import { notify, openPopup } from '@operato/layout'
|
|
15
17
|
import { CommonPopupStyles, PopupBodyStyles } from '@operato/styles'
|
|
16
18
|
import { askAssistant } from '@things-factory/ai-assistant/dist-client/index.js'
|
|
17
19
|
|
|
18
|
-
import { cardApi, dashboardChanged, type CardItem, type CardShare } from '../utils/card-api.js'
|
|
20
|
+
import { cardApi, dashboardChanged, type CardItem, type CardShare, type CardVersion, type ShareOptions } from '../utils/card-api.js'
|
|
19
21
|
import { cardSelection } from '../utils/card-words.js'
|
|
20
22
|
|
|
21
23
|
const t = (key: string, options: Record<string, unknown> = {}) => String(i18next.t(key, options))
|
|
@@ -270,20 +272,31 @@ export class CardRenameForm extends localize(i18next)(LitElement) {
|
|
|
270
272
|
export class CardShareForm extends localize(i18next)(LitElement) {
|
|
271
273
|
static styles = [CommonPopupStyles, PopupBodyStyles, FormStyles]
|
|
272
274
|
@property({ attribute: false }) card!: CardItem
|
|
273
|
-
@state() private options?: Awaited<ReturnType<typeof cardApi.shareOptions>>
|
|
274
275
|
@state() private shares: CardShare[] = []
|
|
275
|
-
@state() private found: { id: string; name: string; note?: string }[] = []
|
|
276
276
|
@state() private search = ''
|
|
277
|
+
/** The name the people are found by - the typed text once typing pauses. */
|
|
278
|
+
@state() private findBy = ''
|
|
277
279
|
private searching?: ReturnType<typeof setTimeout>
|
|
278
280
|
|
|
279
|
-
|
|
281
|
+
private optionsRead = new QueryController(
|
|
282
|
+
this,
|
|
283
|
+
gql`query { dashboardShareOptions { domainId domainName departments { id name } peopleAvailable roles { id name note } } }`
|
|
284
|
+
)
|
|
285
|
+
private peopleRead = new QueryController(this, gql`query ($text: String!) { dashboardSharePeople(text: $text) { id name note } }`, {
|
|
286
|
+
variables: () => (this.findBy ? { text: this.findBy } : undefined)
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
private get options(): ShareOptions | undefined {
|
|
290
|
+
return this.optionsRead.data?.dashboardShareOptions
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private get found(): { id: string; name: string; note?: string }[] {
|
|
294
|
+
return this.peopleRead.data?.dashboardSharePeople ?? []
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
connectedCallback() {
|
|
280
298
|
super.connectedCallback()
|
|
281
299
|
this.shares = [...(this.card?.shares ?? [])].map(({ scope, targetId, targetName }) => ({ scope, targetId, targetName }))
|
|
282
|
-
try {
|
|
283
|
-
this.options = await cardApi.shareOptions()
|
|
284
|
-
} catch (error: any) {
|
|
285
|
-
notify({ level: 'error', message: error?.message ?? String(error) })
|
|
286
|
-
}
|
|
287
300
|
}
|
|
288
301
|
|
|
289
302
|
private has(scope: string, id: string) {
|
|
@@ -297,13 +310,7 @@ export class CardShareForm extends localize(i18next)(LitElement) {
|
|
|
297
310
|
private find(text: string) {
|
|
298
311
|
this.search = text
|
|
299
312
|
clearTimeout(this.searching)
|
|
300
|
-
this.searching = setTimeout(
|
|
301
|
-
try {
|
|
302
|
-
this.found = text.trim() ? await cardApi.people(text.trim()) : []
|
|
303
|
-
} catch {
|
|
304
|
-
this.found = []
|
|
305
|
-
}
|
|
306
|
-
}, 250)
|
|
313
|
+
this.searching = setTimeout(() => (this.findBy = text.trim()), 250)
|
|
307
314
|
}
|
|
308
315
|
|
|
309
316
|
render() {
|
|
@@ -381,15 +388,15 @@ export class CardShareForm extends localize(i18next)(LitElement) {
|
|
|
381
388
|
export class CardVersions extends localize(i18next)(LitElement) {
|
|
382
389
|
static styles = [CommonPopupStyles, PopupBodyStyles, FormStyles]
|
|
383
390
|
@property({ attribute: false }) card!: CardItem
|
|
384
|
-
@state() private versions?: Awaited<ReturnType<typeof cardApi.versions>>
|
|
385
391
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
392
|
+
private versionsRead = new QueryController(
|
|
393
|
+
this,
|
|
394
|
+
gql`query ($id: String!) { dashboardCardVersions(id: $id) { version name definition creatorName createdAt } }`,
|
|
395
|
+
{ variables: () => (this.card ? { id: this.card.id } : undefined) }
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
private get versions(): CardVersion[] | undefined {
|
|
399
|
+
return this.versionsRead.data?.dashboardCardVersions
|
|
393
400
|
}
|
|
394
401
|
|
|
395
402
|
render() {
|
|
@@ -6,15 +6,17 @@ import '@material/web/icon/icon.js'
|
|
|
6
6
|
import '@material/web/button/filled-tonal-button.js'
|
|
7
7
|
import '@material/web/button/text-button.js'
|
|
8
8
|
|
|
9
|
+
import gql from 'graphql-tag'
|
|
9
10
|
import { LitElement, css, html, nothing } from 'lit'
|
|
10
11
|
import { customElement, state } from 'lit/decorators.js'
|
|
11
12
|
|
|
13
|
+
import { QueryController } from '@operato/graphql'
|
|
12
14
|
import { i18next, localize } from '@operato/i18n'
|
|
13
15
|
import { ScrollbarStyles } from '@operato/styles'
|
|
14
16
|
import { notify } from '@operato/layout'
|
|
15
17
|
import { OxPrompt } from '@operato/popup/ox-prompt.js'
|
|
16
18
|
|
|
17
|
-
import { cardApi, DASHBOARD_CHANGED, dashboardChanged, type CardItem } from '../utils/card-api.js'
|
|
19
|
+
import { cardApi, CARD_FIELDS, DASHBOARD_CHANGED, dashboardChanged, type CardItem } from '../utils/card-api.js'
|
|
18
20
|
import { ownershipLine, viewIcon } from '../utils/card-words.js'
|
|
19
21
|
import { openCardRename, openCardShare, openCardVersions } from './card-dialogs.js'
|
|
20
22
|
|
|
@@ -179,15 +181,28 @@ export class CardLibrary extends localize(i18next)(LitElement) {
|
|
|
179
181
|
]
|
|
180
182
|
|
|
181
183
|
@state() private which: 'mine' | 'shared' = 'mine'
|
|
182
|
-
@state() private cards?: CardItem[]
|
|
183
|
-
@state() private error?: string
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
/* The tab's cards (ADR-0190); a change told from elsewhere reads them again. */
|
|
186
|
+
private library = new QueryController(
|
|
187
|
+
this,
|
|
188
|
+
gql`query ($which: String!) { dashboardCards(which: $which) { ${CARD_FIELDS} } }`,
|
|
189
|
+
{ variables: () => ({ which: this.which }) }
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
private get cards(): CardItem[] | undefined {
|
|
193
|
+
return this.library.data?.dashboardCards
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private get error(): string | undefined {
|
|
197
|
+
const error = this.library.error as any
|
|
198
|
+
return error ? (error.message ?? String(error)) : undefined
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
private onChanged = () => this.library.refetch()
|
|
186
202
|
|
|
187
203
|
connectedCallback() {
|
|
188
204
|
super.connectedCallback()
|
|
189
205
|
window.addEventListener(DASHBOARD_CHANGED, this.onChanged)
|
|
190
|
-
this.load()
|
|
191
206
|
}
|
|
192
207
|
|
|
193
208
|
disconnectedCallback() {
|
|
@@ -195,19 +210,8 @@ export class CardLibrary extends localize(i18next)(LitElement) {
|
|
|
195
210
|
super.disconnectedCallback()
|
|
196
211
|
}
|
|
197
212
|
|
|
198
|
-
private async load() {
|
|
199
|
-
try {
|
|
200
|
-
this.cards = await cardApi.library(this.which)
|
|
201
|
-
this.error = undefined
|
|
202
|
-
} catch (error: any) {
|
|
203
|
-
this.error = error?.message ?? String(error)
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
213
|
private show(which: 'mine' | 'shared') {
|
|
208
214
|
this.which = which
|
|
209
|
-
this.cards = undefined
|
|
210
|
-
this.load()
|
|
211
215
|
}
|
|
212
216
|
|
|
213
217
|
render() {
|
|
@@ -7,13 +7,15 @@ import '@material/web/icon/icon.js'
|
|
|
7
7
|
import '@things-factory/ai-assistant/dist-client/index.js'
|
|
8
8
|
|
|
9
9
|
import { LitElement, css, html, nothing } from 'lit'
|
|
10
|
-
import { customElement, property
|
|
10
|
+
import { customElement, property } from 'lit/decorators.js'
|
|
11
11
|
|
|
12
|
+
import gql from 'graphql-tag'
|
|
13
|
+
import { QueryController } from '@operato/graphql'
|
|
12
14
|
import { i18next, localize } from '@operato/i18n'
|
|
13
15
|
import '@operato/popup/ox-popup-menu.js'
|
|
14
16
|
import { OxPopupMenu } from '@operato/popup/ox-popup-menu.js'
|
|
15
17
|
|
|
16
|
-
import {
|
|
18
|
+
import { type CardItem, type CardRun } from '../utils/card-api.js'
|
|
17
19
|
import { drawsNothing, issueLine, ownershipLine, partialLine, readLine, viewIcon } from '../utils/card-words.js'
|
|
18
20
|
|
|
19
21
|
const t = (key: string, options: Record<string, unknown> = {}) => String(i18next.t(key, options))
|
|
@@ -280,36 +282,39 @@ export class AiDashboardCard extends localize(i18next)(LitElement) {
|
|
|
280
282
|
@property({ type: Boolean }) first = false
|
|
281
283
|
@property({ type: Boolean }) last = false
|
|
282
284
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
/* The card drawn from the data - the server runs its definition as the viewer (ADR-0190). */
|
|
286
|
+
private cardRun = new QueryController(
|
|
287
|
+
this,
|
|
288
|
+
gql`
|
|
289
|
+
query ($id: String!) {
|
|
290
|
+
dashboardCardRun(id: $id)
|
|
291
|
+
}
|
|
292
|
+
`,
|
|
293
|
+
{ variables: () => (this.card ? { id: this.card.id } : undefined) }
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
private get run(): CardRun | undefined {
|
|
297
|
+
return this.cardRun.data?.dashboardCardRun
|
|
298
|
+
}
|
|
287
299
|
|
|
288
|
-
private
|
|
300
|
+
private get failed() {
|
|
301
|
+
const error = this.cardRun.error as any
|
|
302
|
+
return error ? (error.message ?? String(error)) : undefined
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
private get loading() {
|
|
306
|
+
return this.cardRun.loading
|
|
307
|
+
}
|
|
289
308
|
|
|
290
309
|
updated(changes: Map<string, unknown>) {
|
|
291
|
-
/* A new card
|
|
292
|
-
const
|
|
293
|
-
if (
|
|
310
|
+
/* A new version of the same card is read again; a new card is read by its own variables. */
|
|
311
|
+
const old = changes.get('card') as CardItem | undefined
|
|
312
|
+
if (old && this.card && old.id === this.card.id && old.version !== this.card.version) this.refresh()
|
|
294
313
|
}
|
|
295
314
|
|
|
296
|
-
/** Draws the card again from the data
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const key = `${this.card.id}@${this.card.version}`
|
|
300
|
-
this.readingFor = key
|
|
301
|
-
this.loading = true
|
|
302
|
-
this.failed = undefined
|
|
303
|
-
try {
|
|
304
|
-
const run = await cardApi.run(this.card.id)
|
|
305
|
-
if (this.readingFor !== key) return
|
|
306
|
-
this.run = run
|
|
307
|
-
this.readAt = new Date()
|
|
308
|
-
} catch (error: any) {
|
|
309
|
-
if (this.readingFor === key) this.failed = error?.message ?? String(error)
|
|
310
|
-
} finally {
|
|
311
|
-
if (this.readingFor === key) this.loading = false
|
|
312
|
-
}
|
|
315
|
+
/** Draws the card again from the data. */
|
|
316
|
+
refresh() {
|
|
317
|
+
return this.cardRun.refetch()
|
|
313
318
|
}
|
|
314
319
|
|
|
315
320
|
private act(action: CardAction) {
|
|
@@ -384,7 +389,7 @@ export class AiDashboardCard extends localize(i18next)(LitElement) {
|
|
|
384
389
|
private renderFooter() {
|
|
385
390
|
const partial = partialLine(this.run!, t)
|
|
386
391
|
return html`<footer>
|
|
387
|
-
<span>${readLine(this.run!, this.
|
|
392
|
+
<span>${readLine(this.run!, this.cardRun.answeredAt ?? new Date(), t, i18next.language)}</span>
|
|
388
393
|
${partial ? html`<span class="partial"><md-icon>warning</md-icon>${partial}</span>` : nothing}
|
|
389
394
|
</footer>`
|
|
390
395
|
}
|
|
@@ -6,12 +6,14 @@
|
|
|
6
6
|
import '@material/web/icon/icon.js'
|
|
7
7
|
import '@things-factory/ai-assistant/dist-client/index.js'
|
|
8
8
|
|
|
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'
|
|
11
12
|
|
|
13
|
+
import { QueryController } from '@operato/graphql'
|
|
12
14
|
import { i18next, localize } from '@operato/i18n'
|
|
13
15
|
|
|
14
|
-
import {
|
|
16
|
+
import { type CardRun } from '../utils/card-api.js'
|
|
15
17
|
import { drawsNothing, issueLine, partialLine } from '../utils/card-words.js'
|
|
16
18
|
|
|
17
19
|
const t = (key: string, options: Record<string, unknown> = {}) => String(i18next.t(key, options))
|
|
@@ -59,23 +61,20 @@ export class ProposalPreview extends localize(i18next)(LitElement) {
|
|
|
59
61
|
@property({ attribute: false }) sessionId?: string
|
|
60
62
|
@property({ attribute: false }) proposalKey?: string
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
/* The proposal run as the viewer, for the proposal shown (ADR-0190). */
|
|
65
|
+
private preview = new QueryController(
|
|
66
|
+
this,
|
|
67
|
+
gql`query ($s: String!, $k: String!) { dashboardCardProposalPreview(sessionId: $s, proposalKey: $k) }`,
|
|
68
|
+
{ variables: () => (this.sessionId && this.proposalKey ? { s: this.sessionId, k: this.proposalKey } : undefined) }
|
|
69
|
+
)
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (key && key !== this.readFor) this.read(key)
|
|
71
|
+
private get run(): CardRun | undefined {
|
|
72
|
+
return this.preview.data?.dashboardCardProposalPreview
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
private
|
|
72
|
-
this.
|
|
73
|
-
|
|
74
|
-
const run = await cardApi.preview(this.sessionId!, this.proposalKey!)
|
|
75
|
-
if (this.readFor === key) this.run = run
|
|
76
|
-
} catch (error: any) {
|
|
77
|
-
if (this.readFor === key) this.failed = error?.message ?? String(error)
|
|
78
|
-
}
|
|
75
|
+
private get failed(): string | undefined {
|
|
76
|
+
const error = this.preview.error as any
|
|
77
|
+
return error ? (error.message ?? String(error)) : undefined
|
|
79
78
|
}
|
|
80
79
|
|
|
81
80
|
render() {
|
|
@@ -9,16 +9,18 @@ import '@material/web/icon/icon.js'
|
|
|
9
9
|
import '../components/dashboard-card.js'
|
|
10
10
|
import '../components/card-library.js'
|
|
11
11
|
|
|
12
|
+
import gql from 'graphql-tag'
|
|
12
13
|
import { css, html, nothing } from 'lit'
|
|
13
14
|
import { customElement, state } from 'lit/decorators.js'
|
|
14
15
|
|
|
16
|
+
import { MutationController, QueryController } from '@operato/graphql'
|
|
15
17
|
import { i18next, localize } from '@operato/i18n'
|
|
16
18
|
import { notify, openPopup } from '@operato/layout'
|
|
17
19
|
import { PageView } from '@operato/shell'
|
|
18
20
|
import { DocumentPageStyles, ScrollbarStyles } from '@operato/styles'
|
|
19
21
|
import { askAssistant } from '@things-factory/ai-assistant/dist-client/index.js'
|
|
20
22
|
|
|
21
|
-
import { cardApi, DASHBOARD_CHANGED, dashboardChanged, type CardItem, type PlaceItem } from '../utils/card-api.js'
|
|
23
|
+
import { cardApi, CARD_FIELDS, DASHBOARD_CHANGED, dashboardChanged, type CardItem, type PlaceItem } from '../utils/card-api.js'
|
|
22
24
|
import { movedPlaces } from '../utils/card-words.js'
|
|
23
25
|
import { dashboardExamples } from '../utils/examples.js'
|
|
24
26
|
import { openCardAiPrompt, openCardRename, openCardShare, openCardVersions } from '../components/card-dialogs.js'
|
|
@@ -199,12 +201,33 @@ export class MyDashboardPage extends localize(i18next)(PageView) {
|
|
|
199
201
|
`
|
|
200
202
|
]
|
|
201
203
|
|
|
202
|
-
@state() private places: PlaceItem[] = []
|
|
203
|
-
@state() private loaded = false
|
|
204
|
-
@state() private error?: string
|
|
205
204
|
@state() private editing = false
|
|
205
|
+
/** The places as moved here, shown while the move is being saved. */
|
|
206
|
+
@state() private arranged?: PlaceItem[]
|
|
207
|
+
|
|
208
|
+
/* A page refresh, or a change told from elsewhere, reads the board again. */
|
|
209
|
+
private board = new QueryController(this, gql`query { myDashboard { id order width height card { ${CARD_FIELDS} } } }`)
|
|
210
|
+
private arranging = new MutationController(this, gql`mutation ($places: [DashboardPlaceInput!]!) { arrangeDashboard(places: $places) }`, {
|
|
211
|
+
refetch: () => [this.board]
|
|
212
|
+
})
|
|
213
|
+
private unplacing = new MutationController(this, gql`mutation ($id: String!) { removeDashboardPlace(id: $id) }`, {
|
|
214
|
+
refetch: () => [this.board]
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
private get places(): PlaceItem[] {
|
|
218
|
+
return (this.arranging.pending && this.arranged) || this.board.data?.myDashboard || []
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private get loaded() {
|
|
222
|
+
return !!this.board.answeredAt
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
private get error(): string | undefined {
|
|
226
|
+
const error = this.board.error as any
|
|
227
|
+
return error ? (error.message ?? String(error)) : undefined
|
|
228
|
+
}
|
|
206
229
|
|
|
207
|
-
private onChanged = () => this.
|
|
230
|
+
private onChanged = () => this.board.refetch()
|
|
208
231
|
|
|
209
232
|
get context() {
|
|
210
233
|
return {
|
|
@@ -233,22 +256,6 @@ export class MyDashboardPage extends localize(i18next)(PageView) {
|
|
|
233
256
|
if (changes.has('editing')) this.updateContext()
|
|
234
257
|
}
|
|
235
258
|
|
|
236
|
-
/* Not awaited: the shell sets the tab's title only after this returns. */
|
|
237
|
-
async pageUpdated(changes: any) {
|
|
238
|
-
if ((this as any).active && changes.active) this.load()
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
private async load() {
|
|
242
|
-
try {
|
|
243
|
-
this.places = await cardApi.myDashboard()
|
|
244
|
-
this.error = undefined
|
|
245
|
-
} catch (error: any) {
|
|
246
|
-
this.error = error?.message ?? String(error)
|
|
247
|
-
} finally {
|
|
248
|
-
this.loaded = true
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
259
|
render() {
|
|
253
260
|
return html`<div class="page">
|
|
254
261
|
${this.error
|
|
@@ -319,15 +326,10 @@ export class MyDashboardPage extends localize(i18next)(PageView) {
|
|
|
319
326
|
return this.places.find(one => one.card.id === card.id)
|
|
320
327
|
}
|
|
321
328
|
|
|
329
|
+
/* The board shows the move at once; a failed one goes back to the board read. */
|
|
322
330
|
private async arrange(next: PlaceItem[]) {
|
|
323
|
-
|
|
324
|
-
this.places
|
|
325
|
-
try {
|
|
326
|
-
await cardApi.arrange(next.map(({ id, order, width, height }) => ({ id, order, width, height })))
|
|
327
|
-
} catch (error: any) {
|
|
328
|
-
this.places = before
|
|
329
|
-
notify({ level: 'error', message: error?.message ?? String(error) })
|
|
330
|
-
}
|
|
331
|
+
this.arranged = next
|
|
332
|
+
await this.arranging.run({ places: next.map(({ id, order, width, height }) => ({ id, order, width, height })) })
|
|
331
333
|
}
|
|
332
334
|
|
|
333
335
|
private async onCardAction(event: CustomEvent) {
|
|
@@ -349,9 +351,8 @@ export class MyDashboardPage extends localize(i18next)(PageView) {
|
|
|
349
351
|
return dashboardChanged()
|
|
350
352
|
case 'unplace':
|
|
351
353
|
if (!place) return
|
|
352
|
-
await
|
|
353
|
-
|
|
354
|
-
return this.load()
|
|
354
|
+
if (await this.unplacing.run({ id: place.id })) notify({ level: 'info', message: t('ai-dashboard.text.unplaced', { name: card.name }) })
|
|
355
|
+
return
|
|
355
356
|
case 'left':
|
|
356
357
|
case 'right':
|
|
357
358
|
return place && this.arrange(movedPlaces(this.places, place.id, action === 'left' ? -1 : 1))
|
package/client/utils/card-api.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* The
|
|
3
|
-
* conversation's card read the same fields.
|
|
2
|
+
* The dashboard's changes (server: card-resolver.ts), and the card fields the screens read - one place, so the page,
|
|
3
|
+
* the library and the conversation's card read the same fields. Each screen declares its own reads (ADR-0190).
|
|
4
4
|
*/
|
|
5
5
|
import gql from 'graphql-tag'
|
|
6
6
|
|
|
@@ -50,56 +50,45 @@ export interface CardRun {
|
|
|
50
50
|
source?: { key: string; labelKey?: string }
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
export interface ShareOptions {
|
|
54
|
+
domainId: string
|
|
55
|
+
domainName: string
|
|
56
|
+
departments: { id: string; name: string }[]
|
|
57
|
+
peopleAvailable: boolean
|
|
58
|
+
roles: { id: string; name: string; note?: string | null }[]
|
|
59
|
+
}
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
export interface CardVersion {
|
|
62
|
+
version: number
|
|
63
|
+
name: string
|
|
64
|
+
definition: any
|
|
65
|
+
creatorName?: string
|
|
66
|
+
createdAt?: string
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const CARD_FIELDS = `id name description version definition access ownerName copiedFromId placed shares { scope targetId targetName } updatedAt`
|
|
70
|
+
|
|
71
|
+
async function ask<T>(document: string, variables: Record<string, unknown> = {}): Promise<T> {
|
|
72
|
+
const response: any = await client.mutate({ mutation: gql(document), variables })
|
|
59
73
|
if (response.errors?.length) throw new Error(response.errors[0].message)
|
|
60
74
|
return response.data
|
|
61
75
|
}
|
|
62
76
|
|
|
63
77
|
export const cardApi = {
|
|
64
|
-
myDashboard: async () => (await ask<any>(`query { myDashboard { id order width height card { ${CARD_FIELDS} } } }`)).myDashboard as PlaceItem[],
|
|
65
|
-
library: async (which: 'mine' | 'shared') => (await ask<any>(`query ($which: String!) { dashboardCards(which: $which) { ${CARD_FIELDS} } }`, { which })).dashboardCards as CardItem[],
|
|
66
|
-
run: async (id: string) => (await ask<any>(`query ($id: String!) { dashboardCardRun(id: $id) }`, { id })).dashboardCardRun as CardRun,
|
|
67
|
-
preview: async (sessionId: string, proposalKey: string) =>
|
|
68
|
-
(await ask<any>(`query ($s: String!, $k: String!) { dashboardCardProposalPreview(sessionId: $s, proposalKey: $k) }`, { s: sessionId, k: proposalKey })).dashboardCardProposalPreview as CardRun,
|
|
69
|
-
versions: async (id: string) =>
|
|
70
|
-
(await ask<any>(`query ($id: String!) { dashboardCardVersions(id: $id) { version name definition creatorName createdAt } }`, { id })).dashboardCardVersions as {
|
|
71
|
-
version: number
|
|
72
|
-
name: string
|
|
73
|
-
definition: any
|
|
74
|
-
creatorName?: string
|
|
75
|
-
createdAt?: string
|
|
76
|
-
}[],
|
|
77
|
-
shareOptions: async () =>
|
|
78
|
-
(await ask<any>(`query { dashboardShareOptions { domainId domainName departments { id name } peopleAvailable roles { id name note } } }`)).dashboardShareOptions as {
|
|
79
|
-
domainId: string
|
|
80
|
-
domainName: string
|
|
81
|
-
departments: { id: string; name: string }[]
|
|
82
|
-
peopleAvailable: boolean
|
|
83
|
-
roles: { id: string; name: string; note?: string | null }[]
|
|
84
|
-
},
|
|
85
|
-
people: async (text: string) => (await ask<any>(`query ($text: String!) { dashboardSharePeople(text: $text) { id name note } }`, { text })).dashboardSharePeople as { id: string; name: string; note?: string }[],
|
|
86
78
|
saveProposal: async (sessionId: string, proposalKey: string) =>
|
|
87
|
-
(await ask<any>(`mutation ($s: String!, $k: String!) { saveDashboardCardProposal(sessionId: $s, proposalKey: $k) }`, { s: sessionId, k: proposalKey }
|
|
79
|
+
(await ask<any>(`mutation ($s: String!, $k: String!) { saveDashboardCardProposal(sessionId: $s, proposalKey: $k) }`, { s: sessionId, k: proposalKey })).saveDashboardCardProposal as {
|
|
88
80
|
cardId: string
|
|
89
81
|
version: number
|
|
90
82
|
placeId: string
|
|
91
83
|
again?: boolean
|
|
92
84
|
},
|
|
93
|
-
rename: async (id: string, name: string) => (await ask<any>(`mutation ($id: String!, $name: String!) { renameDashboardCard(id: $id, name: $name) { id } }`, { id, name }
|
|
94
|
-
restore: async (id: string, version: number) => (await ask<any>(`mutation ($id: String!, $v: Int!) { restoreDashboardCardVersion(id: $id, version: $v) { id } }`, { id, v: version }
|
|
95
|
-
copy: async (id: string) => (await ask<any>(`mutation ($id: String!) { copyDashboardCard(id: $id) { id } }`, { id }
|
|
96
|
-
remove: async (id: string) => (await ask<any>(`mutation ($id: String!) { deleteDashboardCard(id: $id) }`, { id }
|
|
85
|
+
rename: async (id: string, name: string) => (await ask<any>(`mutation ($id: String!, $name: String!) { renameDashboardCard(id: $id, name: $name) { id } }`, { id, name })).renameDashboardCard,
|
|
86
|
+
restore: async (id: string, version: number) => (await ask<any>(`mutation ($id: String!, $v: Int!) { restoreDashboardCardVersion(id: $id, version: $v) { id } }`, { id, v: version })).restoreDashboardCardVersion,
|
|
87
|
+
copy: async (id: string) => (await ask<any>(`mutation ($id: String!) { copyDashboardCard(id: $id) { id } }`, { id })).copyDashboardCard,
|
|
88
|
+
remove: async (id: string) => (await ask<any>(`mutation ($id: String!) { deleteDashboardCard(id: $id) }`, { id })).deleteDashboardCard,
|
|
97
89
|
share: async (id: string, shares: CardShare[]) =>
|
|
98
|
-
(await ask<any>(`mutation ($id: String!, $shares: [DashboardCardShareInput!]!) { shareDashboardCard(id: $id, shares: $shares) { ${CARD_FIELDS} } }`, { id, shares }
|
|
99
|
-
place: async (cardId: string) => (await ask<any>(`mutation ($id: String!) { placeDashboardCard(cardId: $id) { id } }`, { id: cardId }
|
|
100
|
-
unplace: async (id: string) => (await ask<any>(`mutation ($id: String!) { removeDashboardPlace(id: $id) }`, { id }, true)).removeDashboardPlace,
|
|
101
|
-
arrange: async (places: { id: string; order: number; width: number; height: number }[]) =>
|
|
102
|
-
(await ask<any>(`mutation ($places: [DashboardPlaceInput!]!) { arrangeDashboard(places: $places) }`, { places }, true)).arrangeDashboard
|
|
90
|
+
(await ask<any>(`mutation ($id: String!, $shares: [DashboardCardShareInput!]!) { shareDashboardCard(id: $id, shares: $shares) { ${CARD_FIELDS} } }`, { id, shares })).shareDashboardCard as CardItem,
|
|
91
|
+
place: async (cardId: string) => (await ask<any>(`mutation ($id: String!) { placeDashboardCard(cardId: $id) { id } }`, { id: cardId })).placeDashboardCard
|
|
103
92
|
}
|
|
104
93
|
|
|
105
94
|
/** Told when a card is saved, copied, placed or removed elsewhere - an open dashboard reads itself again. */
|
|
@@ -30,12 +30,16 @@ declare const CardShareForm_base: (new (...args: any[]) => LitElement) & typeof
|
|
|
30
30
|
export declare class CardShareForm extends CardShareForm_base {
|
|
31
31
|
static styles: import("lit").CSSResult[];
|
|
32
32
|
card: CardItem;
|
|
33
|
-
private options?;
|
|
34
33
|
private shares;
|
|
35
|
-
private found;
|
|
36
34
|
private search;
|
|
35
|
+
/** The name the people are found by - the typed text once typing pauses. */
|
|
36
|
+
private findBy;
|
|
37
37
|
private searching?;
|
|
38
|
-
|
|
38
|
+
private optionsRead;
|
|
39
|
+
private peopleRead;
|
|
40
|
+
private get options();
|
|
41
|
+
private get found();
|
|
42
|
+
connectedCallback(): void;
|
|
39
43
|
private has;
|
|
40
44
|
private toggle;
|
|
41
45
|
private find;
|
|
@@ -48,8 +52,8 @@ declare const CardVersions_base: (new (...args: any[]) => LitElement) & typeof L
|
|
|
48
52
|
export declare class CardVersions extends CardVersions_base {
|
|
49
53
|
static styles: import("lit").CSSResult[];
|
|
50
54
|
card: CardItem;
|
|
51
|
-
private
|
|
52
|
-
|
|
55
|
+
private versionsRead;
|
|
56
|
+
private get versions();
|
|
53
57
|
render(): import("lit-html").TemplateResult<1>;
|
|
54
58
|
private restore;
|
|
55
59
|
}
|
|
@@ -7,8 +7,10 @@ import '@material/web/icon/icon.js';
|
|
|
7
7
|
import '@material/web/button/filled-button.js';
|
|
8
8
|
import '@material/web/button/text-button.js';
|
|
9
9
|
import '@operato/popup/ox-popup-actions.js';
|
|
10
|
+
import gql from 'graphql-tag';
|
|
10
11
|
import { LitElement, css, html, nothing } from 'lit';
|
|
11
12
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
13
|
+
import { QueryController } from '@operato/graphql';
|
|
12
14
|
import { i18next, localize } from '@operato/i18n';
|
|
13
15
|
import { notify, openPopup } from '@operato/layout';
|
|
14
16
|
import { CommonPopupStyles, PopupBodyStyles } from '@operato/styles';
|
|
@@ -284,19 +286,24 @@ let CardShareForm = class CardShareForm extends localize(i18next)(LitElement) {
|
|
|
284
286
|
constructor() {
|
|
285
287
|
super(...arguments);
|
|
286
288
|
this.shares = [];
|
|
287
|
-
this.found = [];
|
|
288
289
|
this.search = '';
|
|
290
|
+
/** The name the people are found by - the typed text once typing pauses. */
|
|
291
|
+
this.findBy = '';
|
|
292
|
+
this.optionsRead = new QueryController(this, gql `query { dashboardShareOptions { domainId domainName departments { id name } peopleAvailable roles { id name note } } }`);
|
|
293
|
+
this.peopleRead = new QueryController(this, gql `query ($text: String!) { dashboardSharePeople(text: $text) { id name note } }`, {
|
|
294
|
+
variables: () => (this.findBy ? { text: this.findBy } : undefined)
|
|
295
|
+
});
|
|
289
296
|
}
|
|
290
297
|
static { this.styles = [CommonPopupStyles, PopupBodyStyles, FormStyles]; }
|
|
291
|
-
|
|
298
|
+
get options() {
|
|
299
|
+
return this.optionsRead.data?.dashboardShareOptions;
|
|
300
|
+
}
|
|
301
|
+
get found() {
|
|
302
|
+
return this.peopleRead.data?.dashboardSharePeople ?? [];
|
|
303
|
+
}
|
|
304
|
+
connectedCallback() {
|
|
292
305
|
super.connectedCallback();
|
|
293
306
|
this.shares = [...(this.card?.shares ?? [])].map(({ scope, targetId, targetName }) => ({ scope, targetId, targetName }));
|
|
294
|
-
try {
|
|
295
|
-
this.options = await cardApi.shareOptions();
|
|
296
|
-
}
|
|
297
|
-
catch (error) {
|
|
298
|
-
notify({ level: 'error', message: error?.message ?? String(error) });
|
|
299
|
-
}
|
|
300
307
|
}
|
|
301
308
|
has(scope, id) {
|
|
302
309
|
return this.shares.some(one => one.scope === scope && one.targetId === id);
|
|
@@ -307,14 +314,7 @@ let CardShareForm = class CardShareForm extends localize(i18next)(LitElement) {
|
|
|
307
314
|
find(text) {
|
|
308
315
|
this.search = text;
|
|
309
316
|
clearTimeout(this.searching);
|
|
310
|
-
this.searching = setTimeout(
|
|
311
|
-
try {
|
|
312
|
-
this.found = text.trim() ? await cardApi.people(text.trim()) : [];
|
|
313
|
-
}
|
|
314
|
-
catch {
|
|
315
|
-
this.found = [];
|
|
316
|
-
}
|
|
317
|
-
}, 250);
|
|
317
|
+
this.searching = setTimeout(() => (this.findBy = text.trim()), 250);
|
|
318
318
|
}
|
|
319
319
|
render() {
|
|
320
320
|
const options = this.options;
|
|
@@ -384,37 +384,31 @@ __decorate([
|
|
|
384
384
|
property({ attribute: false }),
|
|
385
385
|
__metadata("design:type", Object)
|
|
386
386
|
], CardShareForm.prototype, "card", void 0);
|
|
387
|
-
__decorate([
|
|
388
|
-
state(),
|
|
389
|
-
__metadata("design:type", Object)
|
|
390
|
-
], CardShareForm.prototype, "options", void 0);
|
|
391
387
|
__decorate([
|
|
392
388
|
state(),
|
|
393
389
|
__metadata("design:type", Array)
|
|
394
390
|
], CardShareForm.prototype, "shares", void 0);
|
|
395
391
|
__decorate([
|
|
396
392
|
state(),
|
|
397
|
-
__metadata("design:type",
|
|
398
|
-
], CardShareForm.prototype, "
|
|
393
|
+
__metadata("design:type", Object)
|
|
394
|
+
], CardShareForm.prototype, "search", void 0);
|
|
399
395
|
__decorate([
|
|
400
396
|
state(),
|
|
401
397
|
__metadata("design:type", Object)
|
|
402
|
-
], CardShareForm.prototype, "
|
|
398
|
+
], CardShareForm.prototype, "findBy", void 0);
|
|
403
399
|
CardShareForm = __decorate([
|
|
404
400
|
customElement('ai-dashboard-card-share-form')
|
|
405
401
|
], CardShareForm);
|
|
406
402
|
export { CardShareForm };
|
|
407
403
|
/** One's own card's versions, newest first - an earlier one comes back as a new version. */
|
|
408
404
|
let CardVersions = class CardVersions extends localize(i18next)(LitElement) {
|
|
405
|
+
constructor() {
|
|
406
|
+
super(...arguments);
|
|
407
|
+
this.versionsRead = new QueryController(this, gql `query ($id: String!) { dashboardCardVersions(id: $id) { version name definition creatorName createdAt } }`, { variables: () => (this.card ? { id: this.card.id } : undefined) });
|
|
408
|
+
}
|
|
409
409
|
static { this.styles = [CommonPopupStyles, PopupBodyStyles, FormStyles]; }
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
try {
|
|
413
|
-
this.versions = await cardApi.versions(this.card.id);
|
|
414
|
-
}
|
|
415
|
-
catch (error) {
|
|
416
|
-
notify({ level: 'error', message: error?.message ?? String(error) });
|
|
417
|
-
}
|
|
410
|
+
get versions() {
|
|
411
|
+
return this.versionsRead.data?.dashboardCardVersions;
|
|
418
412
|
}
|
|
419
413
|
render() {
|
|
420
414
|
const view = (definition) => t(`ai-dashboard.view.${definition?.view?.kind ?? 'table'}`);
|
|
@@ -447,10 +441,6 @@ __decorate([
|
|
|
447
441
|
property({ attribute: false }),
|
|
448
442
|
__metadata("design:type", Object)
|
|
449
443
|
], CardVersions.prototype, "card", void 0);
|
|
450
|
-
__decorate([
|
|
451
|
-
state(),
|
|
452
|
-
__metadata("design:type", Object)
|
|
453
|
-
], CardVersions.prototype, "versions", void 0);
|
|
454
444
|
CardVersions = __decorate([
|
|
455
445
|
customElement('ai-dashboard-card-versions')
|
|
456
446
|
], CardVersions);
|