@things-factory/worklist 6.0.24 → 6.0.26

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.
Files changed (131) hide show
  1. package/client/activity-summary-generator.ts +132 -0
  2. package/client/bootstrap.ts +37 -0
  3. package/client/components/activity-starter-form.ts +89 -3
  4. package/client/index.ts +1 -0
  5. package/client/pages/activity-approval/activity-approval-page.ts +5 -50
  6. package/client/pages/activity-thread/activity-thread-page.ts +5 -44
  7. package/client/pages/installable-activity/installable-activity-list-page.ts +400 -0
  8. package/client/pages/installable-activity/installable-activity-model-item-list.ts +18 -0
  9. package/client/pages/todo/draft-list-page.ts +9 -0
  10. package/client/route.ts +4 -0
  11. package/client/templates/activity-approval-context-template.ts +67 -0
  12. package/client/templates/activity-thread-context-template.ts +62 -0
  13. package/dist-client/activity-summary-generator.d.ts +2 -0
  14. package/dist-client/activity-summary-generator.js +114 -0
  15. package/dist-client/activity-summary-generator.js.map +1 -0
  16. package/dist-client/bootstrap.d.ts +2 -0
  17. package/dist-client/bootstrap.js +35 -0
  18. package/dist-client/bootstrap.js.map +1 -1
  19. package/dist-client/components/activity-starter-form.d.ts +1 -0
  20. package/dist-client/components/activity-starter-form.js +66 -4
  21. package/dist-client/components/activity-starter-form.js.map +1 -1
  22. package/dist-client/index.d.ts +1 -0
  23. package/dist-client/index.js +1 -0
  24. package/dist-client/index.js.map +1 -1
  25. package/dist-client/pages/activity-approval/activity-approval-page.d.ts +1 -0
  26. package/dist-client/pages/activity-approval/activity-approval-page.js +4 -48
  27. package/dist-client/pages/activity-approval/activity-approval-page.js.map +1 -1
  28. package/dist-client/pages/activity-thread/activity-thread-page.d.ts +1 -0
  29. package/dist-client/pages/activity-thread/activity-thread-page.js +4 -42
  30. package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
  31. package/dist-client/pages/installable-activity/installable-activity-list-page.d.ts +45 -0
  32. package/dist-client/pages/installable-activity/installable-activity-list-page.js +404 -0
  33. package/dist-client/pages/installable-activity/installable-activity-list-page.js.map +1 -0
  34. package/dist-client/pages/installable-activity/installable-activity-model-item-list.d.ts +1 -0
  35. package/dist-client/pages/installable-activity/installable-activity-model-item-list.js +20 -0
  36. package/dist-client/pages/installable-activity/installable-activity-model-item-list.js.map +1 -0
  37. package/dist-client/pages/installed-activity/installed-activity-list-page.d.ts +45 -0
  38. package/dist-client/pages/installed-activity/installed-activity-list-page.js +412 -0
  39. package/dist-client/pages/installed-activity/installed-activity-list-page.js.map +1 -0
  40. package/dist-client/pages/installed-activity/installed-activity-model-item-list.d.ts +1 -0
  41. package/dist-client/pages/installed-activity/installed-activity-model-item-list.js +20 -0
  42. package/dist-client/pages/installed-activity/installed-activity-model-item-list.js.map +1 -0
  43. package/dist-client/pages/todo/draft-list-page.js +9 -0
  44. package/dist-client/pages/todo/draft-list-page.js.map +1 -1
  45. package/dist-client/route.d.ts +1 -1
  46. package/dist-client/route.js +3 -0
  47. package/dist-client/route.js.map +1 -1
  48. package/dist-client/templates/activity-approval-context-template.d.ts +2 -0
  49. package/dist-client/templates/activity-approval-context-template.js +62 -0
  50. package/dist-client/templates/activity-approval-context-template.js.map +1 -0
  51. package/dist-client/templates/activity-context-template.d.ts +2 -0
  52. package/dist-client/templates/activity-context-template.js +62 -0
  53. package/dist-client/templates/activity-context-template.js.map +1 -0
  54. package/dist-client/templates/activity-thread-context-template.d.ts +2 -0
  55. package/dist-client/templates/activity-thread-context-template.js +57 -0
  56. package/dist-client/templates/activity-thread-context-template.js.map +1 -0
  57. package/dist-client/tsconfig.tsbuildinfo +1 -1
  58. package/dist-server/controllers/activity-installation-controller.js +17 -0
  59. package/dist-server/controllers/activity-installation-controller.js.map +1 -0
  60. package/dist-server/controllers/activity-instance/post.js +3 -6
  61. package/dist-server/controllers/activity-instance/post.js.map +1 -1
  62. package/dist-server/controllers/activity-thread/submit.js.map +1 -1
  63. package/dist-server/controllers/call-webhook.js +4 -2
  64. package/dist-server/controllers/call-webhook.js.map +1 -1
  65. package/dist-server/controllers/common.js +44 -4
  66. package/dist-server/controllers/common.js.map +1 -1
  67. package/dist-server/controllers/index.js +4 -0
  68. package/dist-server/controllers/index.js.map +1 -1
  69. package/dist-server/index.js +1 -1
  70. package/dist-server/index.js.map +1 -1
  71. package/dist-server/service/activity/activity-model-type.js +1 -1
  72. package/dist-server/service/activity/activity-model-type.js.map +1 -1
  73. package/dist-server/service/activity/activity-query.js +1 -0
  74. package/dist-server/service/activity/activity-query.js.map +1 -1
  75. package/dist-server/service/activity-approval/event-subscriber.js +20 -6
  76. package/dist-server/service/activity-approval/event-subscriber.js.map +1 -1
  77. package/dist-server/service/activity-instance/activity-instance-query.js +40 -0
  78. package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
  79. package/dist-server/service/activity-instance/activity-instance-type.js +13 -1
  80. package/dist-server/service/activity-instance/activity-instance-type.js.map +1 -1
  81. package/dist-server/service/activity-instance/activity-instance.js +25 -1
  82. package/dist-server/service/activity-instance/activity-instance.js.map +1 -1
  83. package/dist-server/service/index.js +4 -0
  84. package/dist-server/service/index.js.map +1 -1
  85. package/dist-server/service/installable-activity/index.js +10 -0
  86. package/dist-server/service/installable-activity/index.js.map +1 -0
  87. package/dist-server/service/installable-activity/installable-activity-mutation.js +60 -0
  88. package/dist-server/service/installable-activity/installable-activity-mutation.js.map +1 -0
  89. package/dist-server/service/installable-activity/installable-activity-query.js +48 -0
  90. package/dist-server/service/installable-activity/installable-activity-query.js.map +1 -0
  91. package/dist-server/service/installable-activity/installable-activity-type.js +21 -0
  92. package/dist-server/service/installable-activity/installable-activity-type.js.map +1 -0
  93. package/dist-server/service/installable-activity/installable-activity.js +70 -0
  94. package/dist-server/service/installable-activity/installable-activity.js.map +1 -0
  95. package/dist-server/service/installed-activity/index.js +10 -0
  96. package/dist-server/service/installed-activity/index.js.map +1 -0
  97. package/dist-server/service/installed-activity/installed-activity-mutation.js +60 -0
  98. package/dist-server/service/installed-activity/installed-activity-mutation.js.map +1 -0
  99. package/dist-server/service/installed-activity/installed-activity-query.js +48 -0
  100. package/dist-server/service/installed-activity/installed-activity-query.js.map +1 -0
  101. package/dist-server/service/installed-activity/installed-activity-type.js +21 -0
  102. package/dist-server/service/installed-activity/installed-activity-type.js.map +1 -0
  103. package/dist-server/service/installed-activity/installed-activity.js +70 -0
  104. package/dist-server/service/installed-activity/installed-activity.js.map +1 -0
  105. package/dist-server/tsconfig.tsbuildinfo +1 -1
  106. package/package.json +7 -7
  107. package/server/controllers/activity-installation-controller.ts +17 -0
  108. package/server/controllers/activity-instance/post.ts +9 -9
  109. package/server/controllers/activity-thread/submit.ts +1 -1
  110. package/server/controllers/call-webhook.ts +5 -2
  111. package/server/controllers/common.ts +41 -5
  112. package/server/controllers/index.ts +1 -0
  113. package/server/index.ts +1 -1
  114. package/server/service/activity/activity-model-type.ts +3 -3
  115. package/server/service/activity/activity-query.ts +2 -1
  116. package/server/service/activity-approval/event-subscriber.ts +19 -7
  117. package/server/service/activity-instance/activity-instance-query.ts +44 -1
  118. package/server/service/activity-instance/activity-instance-type.ts +12 -4
  119. package/server/service/activity-instance/activity-instance.ts +17 -1
  120. package/server/service/index.ts +7 -0
  121. package/server/service/installable-activity/index.ts +7 -0
  122. package/server/service/installable-activity/installable-activity-mutation.ts +61 -0
  123. package/server/service/installable-activity/installable-activity-query.ts +36 -0
  124. package/server/service/installable-activity/installable-activity-type.ts +12 -0
  125. package/server/service/installable-activity/installable-activity.ts +49 -0
  126. package/things-factory.config.js +1 -0
  127. package/translations/en.json +3 -0
  128. package/translations/ko.json +3 -0
  129. package/translations/ms.json +3 -0
  130. package/translations/zh.json +3 -0
  131. package/server/controllers/activity-extension-controller.ts +0 -12
@@ -0,0 +1,400 @@
1
+ import '@operato/data-grist'
2
+ import './installable-activity-model-item-list.js'
3
+ import gql from 'graphql-tag'
4
+ import { css, html } from 'lit'
5
+ import { customElement, property, query } from 'lit/decorators.js'
6
+ import { connect } from 'pwa-helpers/connect-mixin.js'
7
+
8
+ import { DataGrist, getEditor, getRenderer } from '@operato/data-grist'
9
+ import { client } from '@operato/graphql'
10
+ import { i18next, localize } from '@operato/i18n'
11
+ import { notify, openPopup } from '@operato/layout'
12
+ import { PageView, store } from '@operato/shell'
13
+ import { CommonButtonStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'
14
+ import { isMobileDevice } from '@operato/utils'
15
+
16
+ import { ActivityTypes, ActivityUITypes } from '../../types.js'
17
+
18
+ @customElement('installable-activity-list-page')
19
+ export class ActivityTemplateListPage extends connect(store)(localize(i18next)(PageView)) {
20
+ static styles = [
21
+ ScrollbarStyles,
22
+ CommonGristStyles,
23
+ css`
24
+ :host {
25
+ display: flex;
26
+
27
+ width: 100%;
28
+
29
+ --grid-record-emphasized-background-color: red;
30
+ --grid-record-emphasized-color: yellow;
31
+ }
32
+ `
33
+ ]
34
+
35
+ @property({ type: Object }) gristConfig: any
36
+ @property({ type: String }) mode?: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'
37
+
38
+ get context() {
39
+ return {
40
+ search: {
41
+ handler: (search: string) => {
42
+ this.grist.searchText = search
43
+ },
44
+ placeholder: i18next.t('title.installable activity list'),
45
+ value: this.grist.searchText
46
+ },
47
+ filter: {
48
+ handler: () => {
49
+ this.grist.toggleHeadroom()
50
+ }
51
+ },
52
+ help: 'worklist/installable-activity',
53
+ actions: []
54
+ }
55
+ }
56
+
57
+ @query('#sorter-control') sorterControl?: any
58
+ @query('ox-grist') grist!: DataGrist
59
+
60
+ render() {
61
+ const mode = this.mode
62
+
63
+ return html`
64
+ <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
65
+ <div slot="headroom">
66
+ <div id="filters">
67
+ <ox-filters-form autofocus without-search></ox-filters-form>
68
+ </div>
69
+
70
+ <div id="sorters">
71
+ Sort
72
+ <mwc-icon
73
+ @click=${e => {
74
+ const target = e.currentTarget
75
+ this.sorterControl.open({
76
+ right: 0,
77
+ top: target.offsetTop + target.offsetHeight
78
+ })
79
+ }}
80
+ >expand_more</mwc-icon
81
+ >
82
+ <ox-popup id="sorter-control">
83
+ <ox-sorters-control> </ox-sorters-control>
84
+ </ox-popup>
85
+ </div>
86
+
87
+ <div id="modes">
88
+ <mwc-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</mwc-icon>
89
+ <mwc-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>format_list_bulleted</mwc-icon>
90
+ <mwc-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</mwc-icon>
91
+ </div>
92
+ </div>
93
+ </ox-grist>
94
+ `
95
+ }
96
+
97
+ async pageInitialized(lifecycle) {
98
+ this.gristConfig = {
99
+ list: {
100
+ thumbnail: 'thumbnail',
101
+ fields: ['name', 'description'],
102
+ details: ['provider', 'release']
103
+ },
104
+ columns: [
105
+ { type: 'gutter', gutterName: 'sequence' },
106
+ { type: 'gutter', gutterName: 'row-selector', multiple: true },
107
+ {
108
+ type: 'gutter',
109
+ gutterName: 'button',
110
+ icon: 'reorder',
111
+ handlers: {
112
+ click: (columns, data, column, record, rowIndex) => {
113
+ const popup = openPopup(
114
+ html`
115
+ <installable-activity-model-item-list .activity=${record}></installable-activity-model-item-list>
116
+ `,
117
+ {
118
+ backdrop: true,
119
+ help: 'worklist/activity-model-item-list',
120
+ size: 'large',
121
+ title: i18next.t('title.activity model item list')
122
+ }
123
+ )
124
+ popup.onclosed = () => {
125
+ this.grist?.fetch()
126
+ }
127
+ }
128
+ }
129
+ },
130
+ {
131
+ type: 'gutter',
132
+ gutterName: 'button',
133
+ name: 'state',
134
+ icon: record => (record && record.active ? 'pause' : 'play_arrow'),
135
+ handlers: {
136
+ click: (columns, data, column, record, rowIndex) => {
137
+ if (record.active) {
138
+ this.deactivate(record)
139
+ } else {
140
+ this.activate(record)
141
+ }
142
+ }
143
+ }
144
+ },
145
+ {
146
+ type: 'string',
147
+ name: 'name',
148
+ header: i18next.t('field.name'),
149
+ record: {
150
+ editable: false
151
+ },
152
+ filter: 'search',
153
+ sortable: true,
154
+ width: 150
155
+ },
156
+ {
157
+ type: 'string',
158
+ name: 'description',
159
+ header: i18next.t('field.description'),
160
+ record: {
161
+ editable: false
162
+ },
163
+ filter: 'search',
164
+ width: 200
165
+ },
166
+ {
167
+ type: 'string',
168
+ name: 'release',
169
+ header: i18next.t('field.release'),
170
+ record: {
171
+ editable: false
172
+ },
173
+ filter: 'search',
174
+ sortable: true,
175
+ width: 150
176
+ },
177
+ {
178
+ type: 'string',
179
+ name: 'provider',
180
+ header: i18next.t('field.provider'),
181
+ record: {
182
+ editable: false
183
+ },
184
+ filter: 'search',
185
+ sortable: true,
186
+ width: 150
187
+ },
188
+ {
189
+ type: 'select',
190
+ name: 'activityType',
191
+ label: true,
192
+ header: i18next.t('field.activity-type'),
193
+ record: {
194
+ editable: false,
195
+ options: ActivityTypes
196
+ },
197
+ sortable: true,
198
+ // filter: true,
199
+ width: 60
200
+ },
201
+ {
202
+ type: 'image',
203
+ name: 'thumbnail',
204
+ header: i18next.t('field.thumbnail'),
205
+ record: { editable: false },
206
+ width: 120
207
+ },
208
+ {
209
+ type: 'select',
210
+ name: 'uiType',
211
+ label: true,
212
+ header: i18next.t('field.ui-type'),
213
+ record: {
214
+ editable: false,
215
+ options: ActivityUITypes
216
+ },
217
+ width: 80
218
+ },
219
+ {
220
+ type: 'string',
221
+ name: 'uiSource',
222
+ header: i18next.t('field.ui-source'),
223
+ record: {
224
+ editable: false,
225
+ renderer: function (value, column, record, rowIndex, field) {
226
+ var type = record.uiType !== 'board' ? 'script' : 'board'
227
+ return getRenderer(type)(value, column, record, rowIndex, field)
228
+ }
229
+ },
230
+ width: 140
231
+ },
232
+ {
233
+ type: 'select',
234
+ name: 'reportType',
235
+ label: true,
236
+ header: i18next.t('field.report-type'),
237
+ record: {
238
+ editable: false,
239
+ options: ActivityUITypes
240
+ },
241
+ width: 80
242
+ },
243
+ {
244
+ type: 'string',
245
+ name: 'reportSource',
246
+ header: i18next.t('field.report-source'),
247
+ record: {
248
+ editable: false,
249
+ editor: function (value, column, record, rowIndex, field) {
250
+ var type = record.reportType !== 'board' ? 'script' : 'board'
251
+ return getEditor(type)(value, column, record, rowIndex, field)
252
+ },
253
+ renderer: function (value, column, record, rowIndex, field) {
254
+ var type = record.reportType !== 'board' ? 'script' : 'board'
255
+ return getRenderer(type)(value, column, record, rowIndex, field)
256
+ }
257
+ },
258
+ width: 140
259
+ },
260
+ {
261
+ type: 'checkbox',
262
+ name: 'startable',
263
+ label: true,
264
+ header: i18next.t('field.startable'),
265
+ record: {
266
+ editable: false
267
+ },
268
+ // filter: true,
269
+ sortable: true,
270
+ width: 60
271
+ },
272
+ {
273
+ type: 'checkbox',
274
+ name: 'active',
275
+ label: true,
276
+ header: i18next.t('field.active'),
277
+ record: {
278
+ editable: false,
279
+ renderer: function (value, column, record, rowIndex, field) {
280
+ var type = record.reportType !== 'board' ? 'script' : 'board'
281
+ return getRenderer(type)(value, column, record, rowIndex, field)
282
+ }
283
+ },
284
+ // filter: true,
285
+ sortable: true,
286
+ width: 60
287
+ }
288
+ ],
289
+ rows: {
290
+ selectable: false,
291
+ appendable: false
292
+ },
293
+ sorters: [
294
+ {
295
+ name: 'name'
296
+ }
297
+ ]
298
+ }
299
+ }
300
+
301
+ async pageUpdated(changes, lifecycle) {
302
+ if (this.active) {
303
+ }
304
+ }
305
+
306
+ async fetchHandler({ page, limit, sortings = [], filters = [] }) {
307
+ const response = await client.query({
308
+ query: gql`
309
+ query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
310
+ responses: installableActivities(filters: $filters, pagination: $pagination, sortings: $sortings) {
311
+ items {
312
+ activity {
313
+ id
314
+ state
315
+ }
316
+ name
317
+ description
318
+ provider
319
+ release
320
+ activityType
321
+ startable
322
+ model {
323
+ name
324
+ description
325
+ active
326
+ tag
327
+ inout
328
+ type
329
+ unit
330
+ options
331
+ quantifier
332
+ spec
333
+ }
334
+ thumbnail
335
+ uiType
336
+ uiSource
337
+ reportType
338
+ reportSource
339
+ }
340
+ total
341
+ }
342
+ }
343
+ `,
344
+ variables: {
345
+ filters,
346
+ pagination: { page, limit },
347
+ sortings
348
+ }
349
+ })
350
+
351
+ if (!response.data) {
352
+ return
353
+ }
354
+
355
+ const { total, items: records } = response.data?.responses
356
+
357
+ for (var item of records) {
358
+ item.active = item.activity && item.activity.state == 'released'
359
+ }
360
+
361
+ return {
362
+ total,
363
+ records
364
+ }
365
+ }
366
+
367
+ async activate(record) {
368
+ await client.mutate({
369
+ mutation: gql`
370
+ mutation ($name: String!) {
371
+ activateInstallableActivity(name: $name) {
372
+ name
373
+ }
374
+ }
375
+ `,
376
+ variables: {
377
+ name: record.name
378
+ }
379
+ })
380
+
381
+ this.grist?.fetch()
382
+ }
383
+
384
+ async deactivate(record) {
385
+ await client.mutate({
386
+ mutation: gql`
387
+ mutation ($name: String!) {
388
+ deactivateInstallableActivity(name: $name) {
389
+ name
390
+ }
391
+ }
392
+ `,
393
+ variables: {
394
+ name: record.name
395
+ }
396
+ })
397
+
398
+ this.grist?.fetch()
399
+ }
400
+ }
@@ -0,0 +1,18 @@
1
+ import { html } from 'lit'
2
+ import { customElement } from 'lit/decorators.js'
3
+
4
+ import { isMobileDevice } from '@operato/utils'
5
+ import { ActivityModelItemList } from '../activity/activity-model-item-list'
6
+
7
+ @customElement('installable-activity-model-item-list')
8
+ class InstallableActivityModelItemList extends ActivityModelItemList {
9
+ render() {
10
+ return html`
11
+ <ox-grist
12
+ .mode=${isMobileDevice() ? 'CARD' : 'GRID'}
13
+ .config=${this.gristConfig}
14
+ .fetchHandler=${this.fetchHandler.bind(this)}
15
+ ></ox-grist>
16
+ `
17
+ }
18
+ }
@@ -301,6 +301,15 @@ export class DraftListPage extends connect(store)(localize(i18next)(PageView)) {
301
301
  id
302
302
  }
303
303
  activityType
304
+ assignees {
305
+ type
306
+ assignee {
307
+ id
308
+ name
309
+ description
310
+ controlNo
311
+ }
312
+ }
304
313
  approvalLine {
305
314
  type
306
315
  approver {
package/client/route.ts CHANGED
@@ -75,5 +75,9 @@ export default function route(page: string) {
75
75
  case 'activity-approval-list':
76
76
  import('./pages/activity-approval/activity-approval-list-page')
77
77
  return page
78
+
79
+ case 'installable-activity-list':
80
+ import('./pages/installable-activity/installable-activity-list-page')
81
+ return page
78
82
  }
79
83
  }
@@ -0,0 +1,67 @@
1
+ import '@material/mwc-icon'
2
+
3
+ import { html, css, LitElement } from 'lit'
4
+ import { customElement, state } from 'lit/decorators.js'
5
+
6
+ import { connect } from 'pwa-helpers/connect-mixin'
7
+
8
+ import { ContextToolbarOverlayStyle } from '@operato/context/ox-context-toolbar-overlay-style.js'
9
+ import { store } from '@operato/shell'
10
+ import { i18next } from '@operato/i18n'
11
+
12
+ import '@things-factory/organization/dist-client/component/approval-line-view.js'
13
+
14
+ const formatter = new Intl.DateTimeFormat(navigator.language, { dateStyle: 'full', timeStyle: 'short' })
15
+
16
+ @customElement('activity-approval-context-template')
17
+ class ActivityApprovalContextTemplate extends connect(store)(LitElement) {
18
+ static styles = [
19
+ ContextToolbarOverlayStyle,
20
+ css`
21
+ :host {
22
+ background-color: white;
23
+
24
+ width: 100%;
25
+ padding: 5px;
26
+ overflow: auto;
27
+ }
28
+ `
29
+ ]
30
+
31
+ @state() private context
32
+
33
+ render() {
34
+ const activityApproval = this.context.activityApproval || {}
35
+
36
+ const { round, order, approver, createdAt, activityThread } = activityApproval || {}
37
+ const { state, dueAt, assignedAt, assignee, activityInstance } = activityThread || {}
38
+ const { name, description, thumbnail, approvalLine } = activityInstance || {}
39
+
40
+ return html`
41
+ <div>
42
+ <div>name: ${name}</div>
43
+ <div>description: ${description}</div>
44
+ <div>state: ${state}</div>
45
+ <div>round: ${round}</div>
46
+ <div>order: ${order}</div>
47
+ <div>assigned at: ${assignedAt && formatter.format(new Date(assignedAt))}</div>
48
+ <div>due at: ${dueAt && formatter.format(new Date(dueAt))}</div>
49
+ <div>assignee: ${assignee?.name}</div>
50
+ <div>approver: ${approver?.name}</div>
51
+ <div>waited since: ${createdAt && formatter.format(new Date(createdAt))}</div>
52
+ </div>
53
+ <div>
54
+ <div approval-line>
55
+ ${approvalLine
56
+ ? html` <approval-line-view .model=${approvalLine} .current=${order}></approval-line-view> `
57
+ : html``}
58
+ </div>
59
+ <img src=${thumbnail} />
60
+ </div>
61
+ `
62
+ }
63
+
64
+ stateChanged(state) {
65
+ this.context = state.route.context
66
+ }
67
+ }
@@ -0,0 +1,62 @@
1
+ import '@material/mwc-icon'
2
+
3
+ import { html, css, LitElement } from 'lit'
4
+ import { customElement, state } from 'lit/decorators.js'
5
+
6
+ import { connect } from 'pwa-helpers/connect-mixin'
7
+
8
+ import { ContextToolbarOverlayStyle } from '@operato/context/ox-context-toolbar-overlay-style.js'
9
+ import { store } from '@operato/shell'
10
+ import { i18next } from '@operato/i18n'
11
+
12
+ import '@things-factory/organization/dist-client/component/approval-line-view.js'
13
+
14
+ const formatter = new Intl.DateTimeFormat(navigator.language, { dateStyle: 'full', timeStyle: 'short' })
15
+
16
+ @customElement('activity-thread-context-template')
17
+ class ActivityThreadContextTemplate extends connect(store)(LitElement) {
18
+ static styles = [
19
+ ContextToolbarOverlayStyle,
20
+ css`
21
+ :host {
22
+ background-color: white;
23
+
24
+ width: 100%;
25
+ padding: 5px;
26
+ overflow: auto;
27
+ }
28
+ `
29
+ ]
30
+
31
+ @state() private context
32
+
33
+ render() {
34
+ const activityThread = this.context.activityThread || {}
35
+
36
+ const { state, round, dueAt, assignedAt, assignee, activityInstance } = activityThread || {}
37
+ const { name, description, thumbnail, approvalLine } = activityInstance || {}
38
+
39
+ return html`
40
+ <div>
41
+ <div>name: ${name}</div>
42
+ <div>description: ${description}</div>
43
+ <div>state: ${state}</div>
44
+ <div>round: ${round}</div>
45
+ <div>assigned at: ${assignedAt && formatter.format(new Date(assignedAt))}</div>
46
+ <div>due at: ${dueAt && formatter.format(new Date(dueAt))}</div>
47
+ <div>assignee: ${assignee?.name}</div>
48
+ </div>
49
+
50
+ <div>
51
+ <div approval-line>
52
+ ${approvalLine ? html` <approval-line-view .model=${approvalLine}></approval-line-view> ` : html``}
53
+ </div>
54
+ <img src=${thumbnail} />
55
+ </div>
56
+ `
57
+ }
58
+
59
+ stateChanged(state) {
60
+ this.context = state.route.context
61
+ }
62
+ }
@@ -0,0 +1,2 @@
1
+ export declare function generateActivitySummary(name: string): AsyncGenerator<any, void, unknown>;
2
+ export declare function startSubscribeActivitySummary(): Promise<void>;
@@ -0,0 +1,114 @@
1
+ import { __asyncGenerator, __await } from "tslib";
2
+ import debounce from 'lodash-es/debounce';
3
+ import gql from 'graphql-tag';
4
+ import { client, subscribe } from '@operato/graphql';
5
+ import { AsyncLock } from '@operato/utils';
6
+ async function subscribeActivityInstance() {
7
+ return await subscribe({
8
+ query: gql `
9
+ subscription {
10
+ activityInstance {
11
+ name
12
+ }
13
+ }
14
+ `
15
+ }, {
16
+ next: async ({ data }) => {
17
+ if (data) {
18
+ fetchActivitySummary();
19
+ }
20
+ }
21
+ });
22
+ }
23
+ async function subscribeActivityThread() {
24
+ return await subscribe({
25
+ query: gql `
26
+ subscription {
27
+ activityThread {
28
+ transaction
29
+ }
30
+ }
31
+ `
32
+ }, {
33
+ next: async ({ data }) => {
34
+ if (data) {
35
+ fetchActivitySummary();
36
+ }
37
+ }
38
+ });
39
+ }
40
+ async function subscribeActivityApproval() {
41
+ return await subscribe({
42
+ query: gql `
43
+ subscription {
44
+ activityApproval {
45
+ judgment
46
+ }
47
+ }
48
+ `
49
+ }, {
50
+ next: async ({ data }) => {
51
+ if (data) {
52
+ fetchActivitySummary();
53
+ }
54
+ }
55
+ });
56
+ }
57
+ var summary = {};
58
+ var generatorLocks = {
59
+ numberOfToDos: new AsyncLock(true),
60
+ numberOfApprovalWaitings: new AsyncLock(true),
61
+ numberOfPicks: new AsyncLock(true),
62
+ numberOfDrafts: new AsyncLock(true)
63
+ };
64
+ const fetchActivitySummary = debounce(async () => {
65
+ var _a, _b, _c, _d;
66
+ const response = await client.query({
67
+ query: gql `
68
+ query {
69
+ activitySummary {
70
+ numberOfToDos
71
+ numberOfApprovalWaitings
72
+ numberOfPicks
73
+ numberOfDrafts
74
+ }
75
+ }
76
+ `
77
+ });
78
+ if (response.data) {
79
+ const { numberOfToDos, numberOfApprovalWaitings, numberOfPicks, numberOfDrafts } = response.data.activitySummary;
80
+ summary['numberOfToDos'] = numberOfToDos;
81
+ summary['numberOfApprovalWaitings'] = numberOfApprovalWaitings;
82
+ summary['numberOfPicks'] = numberOfPicks;
83
+ summary['numberOfDrafts'] = numberOfDrafts;
84
+ (_a = generatorLocks['numberOfToDos']) === null || _a === void 0 ? void 0 : _a.unlock(numberOfToDos);
85
+ (_b = generatorLocks['numberOfApprovalWaitings']) === null || _b === void 0 ? void 0 : _b.unlock(numberOfApprovalWaitings);
86
+ (_c = generatorLocks['numberOfPicks']) === null || _c === void 0 ? void 0 : _c.unlock(numberOfPicks);
87
+ (_d = generatorLocks['numberOfDrafts']) === null || _d === void 0 ? void 0 : _d.unlock(numberOfDrafts);
88
+ }
89
+ }, 1000);
90
+ export function generateActivitySummary(name) {
91
+ var _a;
92
+ return __asyncGenerator(this, arguments, function* generateActivitySummary_1() {
93
+ /* 1. 앞에 사용되었던 generator가 종료될 기회를 준다. */
94
+ (_a = generatorLocks[name]) === null || _a === void 0 ? void 0 : _a.unlock();
95
+ /* 2. 마지막 값을 일단 yield 한다. */
96
+ yield yield __await(summary[name]);
97
+ while (true) {
98
+ generatorLocks[name].lock();
99
+ let badge = yield __await(generatorLocks[name].promise);
100
+ if (badge === undefined) {
101
+ /* 새로운 generator가 생성된 경우이면, 기존 generator는 종료한다. */
102
+ return yield __await(void 0);
103
+ }
104
+ yield yield __await(badge);
105
+ }
106
+ });
107
+ }
108
+ export async function startSubscribeActivitySummary() {
109
+ await subscribeActivityInstance();
110
+ await subscribeActivityThread();
111
+ await subscribeActivityApproval();
112
+ fetchActivitySummary();
113
+ }
114
+ //# sourceMappingURL=activity-summary-generator.js.map