@things-factory/worklist 6.0.24 → 6.0.25

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 (108) hide show
  1. package/client/activity-summary-generator.ts +132 -0
  2. package/client/components/activity-starter-form.ts +89 -3
  3. package/client/index.ts +1 -0
  4. package/client/pages/installable-activity/installable-activity-list-page.ts +410 -0
  5. package/client/pages/installable-activity/installable-activity-model-item-list.ts +18 -0
  6. package/client/pages/todo/draft-list-page.ts +9 -0
  7. package/client/route.ts +4 -0
  8. package/dist-client/activity-summary-generator.d.ts +2 -0
  9. package/dist-client/activity-summary-generator.js +114 -0
  10. package/dist-client/activity-summary-generator.js.map +1 -0
  11. package/dist-client/components/activity-starter-form.d.ts +1 -0
  12. package/dist-client/components/activity-starter-form.js +66 -4
  13. package/dist-client/components/activity-starter-form.js.map +1 -1
  14. package/dist-client/index.d.ts +1 -0
  15. package/dist-client/index.js +1 -0
  16. package/dist-client/index.js.map +1 -1
  17. package/dist-client/pages/installable-activity/installable-activity-list-page.d.ts +45 -0
  18. package/dist-client/pages/installable-activity/installable-activity-list-page.js +414 -0
  19. package/dist-client/pages/installable-activity/installable-activity-list-page.js.map +1 -0
  20. package/dist-client/pages/installable-activity/installable-activity-model-item-list.d.ts +1 -0
  21. package/dist-client/pages/installable-activity/installable-activity-model-item-list.js +20 -0
  22. package/dist-client/pages/installable-activity/installable-activity-model-item-list.js.map +1 -0
  23. package/dist-client/pages/installed-activity/installed-activity-list-page.d.ts +45 -0
  24. package/dist-client/pages/installed-activity/installed-activity-list-page.js +412 -0
  25. package/dist-client/pages/installed-activity/installed-activity-list-page.js.map +1 -0
  26. package/dist-client/pages/installed-activity/installed-activity-model-item-list.d.ts +1 -0
  27. package/dist-client/pages/installed-activity/installed-activity-model-item-list.js +20 -0
  28. package/dist-client/pages/installed-activity/installed-activity-model-item-list.js.map +1 -0
  29. package/dist-client/pages/todo/draft-list-page.js +9 -0
  30. package/dist-client/pages/todo/draft-list-page.js.map +1 -1
  31. package/dist-client/route.d.ts +1 -1
  32. package/dist-client/route.js +3 -0
  33. package/dist-client/route.js.map +1 -1
  34. package/dist-client/tsconfig.tsbuildinfo +1 -1
  35. package/dist-server/controllers/activity-installation-controller.js +17 -0
  36. package/dist-server/controllers/activity-installation-controller.js.map +1 -0
  37. package/dist-server/controllers/activity-instance/post.js +3 -6
  38. package/dist-server/controllers/activity-instance/post.js.map +1 -1
  39. package/dist-server/controllers/activity-thread/submit.js.map +1 -1
  40. package/dist-server/controllers/call-webhook.js +4 -2
  41. package/dist-server/controllers/call-webhook.js.map +1 -1
  42. package/dist-server/controllers/common.js +44 -4
  43. package/dist-server/controllers/common.js.map +1 -1
  44. package/dist-server/controllers/index.js +4 -0
  45. package/dist-server/controllers/index.js.map +1 -1
  46. package/dist-server/index.js +1 -1
  47. package/dist-server/index.js.map +1 -1
  48. package/dist-server/service/activity/activity-model-type.js +1 -1
  49. package/dist-server/service/activity/activity-model-type.js.map +1 -1
  50. package/dist-server/service/activity/activity-query.js +1 -0
  51. package/dist-server/service/activity/activity-query.js.map +1 -1
  52. package/dist-server/service/activity-approval/event-subscriber.js +20 -6
  53. package/dist-server/service/activity-approval/event-subscriber.js.map +1 -1
  54. package/dist-server/service/activity-instance/activity-instance-query.js +40 -0
  55. package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
  56. package/dist-server/service/activity-instance/activity-instance-type.js +13 -1
  57. package/dist-server/service/activity-instance/activity-instance-type.js.map +1 -1
  58. package/dist-server/service/activity-instance/activity-instance.js +25 -1
  59. package/dist-server/service/activity-instance/activity-instance.js.map +1 -1
  60. package/dist-server/service/index.js +4 -0
  61. package/dist-server/service/index.js.map +1 -1
  62. package/dist-server/service/installable-activity/index.js +10 -0
  63. package/dist-server/service/installable-activity/index.js.map +1 -0
  64. package/dist-server/service/installable-activity/installable-activity-mutation.js +60 -0
  65. package/dist-server/service/installable-activity/installable-activity-mutation.js.map +1 -0
  66. package/dist-server/service/installable-activity/installable-activity-query.js +48 -0
  67. package/dist-server/service/installable-activity/installable-activity-query.js.map +1 -0
  68. package/dist-server/service/installable-activity/installable-activity-type.js +21 -0
  69. package/dist-server/service/installable-activity/installable-activity-type.js.map +1 -0
  70. package/dist-server/service/installable-activity/installable-activity.js +70 -0
  71. package/dist-server/service/installable-activity/installable-activity.js.map +1 -0
  72. package/dist-server/service/installed-activity/index.js +10 -0
  73. package/dist-server/service/installed-activity/index.js.map +1 -0
  74. package/dist-server/service/installed-activity/installed-activity-mutation.js +60 -0
  75. package/dist-server/service/installed-activity/installed-activity-mutation.js.map +1 -0
  76. package/dist-server/service/installed-activity/installed-activity-query.js +48 -0
  77. package/dist-server/service/installed-activity/installed-activity-query.js.map +1 -0
  78. package/dist-server/service/installed-activity/installed-activity-type.js +21 -0
  79. package/dist-server/service/installed-activity/installed-activity-type.js.map +1 -0
  80. package/dist-server/service/installed-activity/installed-activity.js +70 -0
  81. package/dist-server/service/installed-activity/installed-activity.js.map +1 -0
  82. package/dist-server/tsconfig.tsbuildinfo +1 -1
  83. package/package.json +7 -7
  84. package/server/controllers/activity-installation-controller.ts +17 -0
  85. package/server/controllers/activity-instance/post.ts +9 -9
  86. package/server/controllers/activity-thread/submit.ts +1 -1
  87. package/server/controllers/call-webhook.ts +5 -2
  88. package/server/controllers/common.ts +41 -5
  89. package/server/controllers/index.ts +1 -0
  90. package/server/index.ts +1 -1
  91. package/server/service/activity/activity-model-type.ts +3 -3
  92. package/server/service/activity/activity-query.ts +2 -1
  93. package/server/service/activity-approval/event-subscriber.ts +19 -7
  94. package/server/service/activity-instance/activity-instance-query.ts +44 -1
  95. package/server/service/activity-instance/activity-instance-type.ts +12 -4
  96. package/server/service/activity-instance/activity-instance.ts +17 -1
  97. package/server/service/index.ts +7 -0
  98. package/server/service/installable-activity/index.ts +7 -0
  99. package/server/service/installable-activity/installable-activity-mutation.ts +61 -0
  100. package/server/service/installable-activity/installable-activity-query.ts +36 -0
  101. package/server/service/installable-activity/installable-activity-type.ts +12 -0
  102. package/server/service/installable-activity/installable-activity.ts +49 -0
  103. package/things-factory.config.js +1 -0
  104. package/translations/en.json +2 -0
  105. package/translations/ko.json +2 -0
  106. package/translations/ms.json +2 -0
  107. package/translations/zh.json +2 -0
  108. package/server/controllers/activity-extension-controller.ts +0 -12
@@ -0,0 +1,132 @@
1
+ import debounce from 'lodash-es/debounce'
2
+ import gql from 'graphql-tag'
3
+ import { client, subscribe } from '@operato/graphql'
4
+ import { AsyncLock } from '@operato/utils'
5
+
6
+ async function subscribeActivityInstance() {
7
+ return await subscribe(
8
+ {
9
+ query: gql`
10
+ subscription {
11
+ activityInstance {
12
+ name
13
+ }
14
+ }
15
+ `
16
+ },
17
+ {
18
+ next: async ({ data }) => {
19
+ if (data) {
20
+ fetchActivitySummary()
21
+ }
22
+ }
23
+ }
24
+ )
25
+ }
26
+
27
+ async function subscribeActivityThread() {
28
+ return await subscribe(
29
+ {
30
+ query: gql`
31
+ subscription {
32
+ activityThread {
33
+ transaction
34
+ }
35
+ }
36
+ `
37
+ },
38
+ {
39
+ next: async ({ data }) => {
40
+ if (data) {
41
+ fetchActivitySummary()
42
+ }
43
+ }
44
+ }
45
+ )
46
+ }
47
+
48
+ async function subscribeActivityApproval() {
49
+ return await subscribe(
50
+ {
51
+ query: gql`
52
+ subscription {
53
+ activityApproval {
54
+ judgment
55
+ }
56
+ }
57
+ `
58
+ },
59
+ {
60
+ next: async ({ data }) => {
61
+ if (data) {
62
+ fetchActivitySummary()
63
+ }
64
+ }
65
+ }
66
+ )
67
+ }
68
+
69
+ var summary = {}
70
+ var generatorLocks = {
71
+ numberOfToDos: new AsyncLock(true),
72
+ numberOfApprovalWaitings: new AsyncLock(true),
73
+ numberOfPicks: new AsyncLock(true),
74
+ numberOfDrafts: new AsyncLock(true)
75
+ }
76
+
77
+ const fetchActivitySummary = debounce(async () => {
78
+ const response = await client.query({
79
+ query: gql`
80
+ query {
81
+ activitySummary {
82
+ numberOfToDos
83
+ numberOfApprovalWaitings
84
+ numberOfPicks
85
+ numberOfDrafts
86
+ }
87
+ }
88
+ `
89
+ })
90
+
91
+ if (response.data) {
92
+ const { numberOfToDos, numberOfApprovalWaitings, numberOfPicks, numberOfDrafts } = response.data.activitySummary
93
+
94
+ summary['numberOfToDos'] = numberOfToDos
95
+ summary['numberOfApprovalWaitings'] = numberOfApprovalWaitings
96
+ summary['numberOfPicks'] = numberOfPicks
97
+ summary['numberOfDrafts'] = numberOfDrafts
98
+
99
+ generatorLocks['numberOfToDos']?.unlock(numberOfToDos)
100
+ generatorLocks['numberOfApprovalWaitings']?.unlock(numberOfApprovalWaitings)
101
+ generatorLocks['numberOfPicks']?.unlock(numberOfPicks)
102
+ generatorLocks['numberOfDrafts']?.unlock(numberOfDrafts)
103
+ }
104
+ }, 1000)
105
+
106
+ export async function* generateActivitySummary(name: string) {
107
+ /* 1. 앞에 사용되었던 generator가 종료될 기회를 준다. */
108
+ generatorLocks[name]?.unlock()
109
+
110
+ /* 2. 마지막 값을 일단 yield 한다. */
111
+ yield summary[name]
112
+
113
+ while (true) {
114
+ generatorLocks[name].lock()
115
+
116
+ let badge = await generatorLocks[name].promise
117
+ if (badge === undefined) {
118
+ /* 새로운 generator가 생성된 경우이면, 기존 generator는 종료한다. */
119
+ return
120
+ }
121
+
122
+ yield badge
123
+ }
124
+ }
125
+
126
+ export async function startSubscribeActivitySummary() {
127
+ await subscribeActivityInstance()
128
+ await subscribeActivityThread()
129
+ await subscribeActivityApproval()
130
+
131
+ fetchActivitySummary()
132
+ }
@@ -77,6 +77,7 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
77
77
  input,
78
78
  state,
79
79
  approvalLine,
80
+ assignees,
80
81
  threadsMin = 0,
81
82
  threadsMax = 0
82
83
  } = this.activityInstance || {}
@@ -123,6 +124,19 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
123
124
  />
124
125
  </section>
125
126
 
127
+ <section>
128
+ <label>Assignees</label>
129
+ ${assignees
130
+ ? html`
131
+ <assignees-view
132
+ .value=${assignees}
133
+ @click=${this.onClickAssignees.bind(this)}
134
+ @change=${e => (this.activityInstance.assignees = e.currentTarget.value)}
135
+ ></assignees-view>
136
+ `
137
+ : html`<mwc-icon-button icon="group_add" @click=${this.onClickAssignees.bind(this)}></mwc-icon-button>`}
138
+ </section>
139
+
126
140
  <section>
127
141
  <label>Approval Line</label>
128
142
  ${approvalLine
@@ -130,6 +144,7 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
130
144
  <approval-line-view
131
145
  .model=${approvalLine}
132
146
  @click=${this.onClickApprovalLine.bind(this)}
147
+ @change=${e => (this.activityInstance.approvalLine = e.currentTarget.value)}
133
148
  ></approval-line-view>
134
149
  `
135
150
  : html`<mwc-icon-button icon="group_add" @click=${this.onClickApprovalLine.bind(this)}></mwc-icon-button>`}
@@ -230,6 +245,15 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
230
245
  description
231
246
  input
232
247
  state
248
+ assignees {
249
+ type
250
+ assignee {
251
+ id
252
+ name
253
+ description
254
+ controlNo
255
+ }
256
+ }
233
257
  approvalLine {
234
258
  type
235
259
  approver {
@@ -260,7 +284,16 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
260
284
  }
261
285
 
262
286
  async updateActivityInstance() {
263
- const { id, name, description, input, threadsMin = 0, threadsMax = 0, approvalLine } = this.activityInstance
287
+ const {
288
+ id,
289
+ name,
290
+ description,
291
+ input,
292
+ threadsMin = 0,
293
+ threadsMax = 0,
294
+ assignees,
295
+ approvalLine
296
+ } = this.activityInstance
264
297
 
265
298
  const patch = {
266
299
  name: name || this.activity.name,
@@ -268,6 +301,7 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
268
301
  input,
269
302
  threadsMin,
270
303
  threadsMax,
304
+ assignees,
271
305
  approvalLine
272
306
  }
273
307
 
@@ -280,6 +314,15 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
280
314
  description
281
315
  input
282
316
  state
317
+ assignees {
318
+ type
319
+ assignee {
320
+ id
321
+ name
322
+ description
323
+ controlNo
324
+ }
325
+ }
283
326
  approvalLine {
284
327
  type
285
328
  approver {
@@ -311,7 +354,16 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
311
354
  }
312
355
 
313
356
  async postActivityInstance() {
314
- const { id, name, description, input, threadsMin = 0, threadsMax = 0 } = this.activityInstance
357
+ const {
358
+ id,
359
+ name,
360
+ description,
361
+ input,
362
+ threadsMin = 0,
363
+ threadsMax = 0,
364
+ assignees,
365
+ approvalLine
366
+ } = this.activityInstance
315
367
 
316
368
  const activityInstance = {
317
369
  id,
@@ -319,7 +371,9 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
319
371
  description: description || this.activity.description,
320
372
  threadsMin,
321
373
  threadsMax,
322
- input
374
+ input,
375
+ assignees,
376
+ approvalLine
323
377
  }
324
378
 
325
379
  const response = await client.mutate({
@@ -331,6 +385,15 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
331
385
  description
332
386
  input
333
387
  state
388
+ assignees {
389
+ type
390
+ assignee {
391
+ id
392
+ name
393
+ description
394
+ controlNo
395
+ }
396
+ }
334
397
  approvalLine {
335
398
  type
336
399
  approver {
@@ -360,6 +423,29 @@ export class ActivityStarterForm extends localize(i18next)(LitElement) {
360
423
  }
361
424
  }
362
425
 
426
+ onClickAssignees() {
427
+ const { assignees } = this.activityInstance || {}
428
+
429
+ const popup = openPopup(
430
+ html`
431
+ <assignees-editor-popup
432
+ .value=${assignees}
433
+ .confirmCallback=${value => {
434
+ this.activityInstance.assignees = value
435
+ this.requestUpdate()
436
+ }}
437
+ ></assignees-editor-popup>
438
+ `,
439
+ {
440
+ backdrop: true,
441
+ help: 'organization/assignees-editor',
442
+ size: 'large',
443
+ title: i18next.t('title.assignee list')
444
+ }
445
+ )
446
+ popup.onclosed = () => {}
447
+ }
448
+
363
449
  onClickApprovalLine() {
364
450
  const { approvalLine } = this.activityInstance || {}
365
451
 
package/client/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './pages/activity/activity-page.js'
2
+ export * from './activity-summary-generator'
@@ -0,0 +1,410 @@
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: ['visibility', 'updatedAt']
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: 'version',
169
+ header: i18next.t('field.version'),
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
+ type: 'resource-object',
290
+ name: 'updater',
291
+ header: i18next.t('field.updater'),
292
+ record: {
293
+ editable: false
294
+ },
295
+ sortable: true,
296
+ width: 120
297
+ }
298
+ ],
299
+ rows: {
300
+ selectable: false,
301
+ appendable: false
302
+ },
303
+ sorters: [
304
+ {
305
+ name: 'name'
306
+ }
307
+ ]
308
+ }
309
+ }
310
+
311
+ async pageUpdated(changes, lifecycle) {
312
+ if (this.active) {
313
+ }
314
+ }
315
+
316
+ async fetchHandler({ page, limit, sortings = [], filters = [] }) {
317
+ const response = await client.query({
318
+ query: gql`
319
+ query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
320
+ responses: installableActivities(filters: $filters, pagination: $pagination, sortings: $sortings) {
321
+ items {
322
+ activity {
323
+ id
324
+ state
325
+ }
326
+ name
327
+ description
328
+ provider
329
+ release
330
+ activityType
331
+ startable
332
+ model {
333
+ name
334
+ description
335
+ active
336
+ tag
337
+ inout
338
+ type
339
+ unit
340
+ options
341
+ quantifier
342
+ spec
343
+ }
344
+ thumbnail
345
+ uiType
346
+ uiSource
347
+ reportType
348
+ reportSource
349
+ }
350
+ total
351
+ }
352
+ }
353
+ `,
354
+ variables: {
355
+ filters,
356
+ pagination: { page, limit },
357
+ sortings
358
+ }
359
+ })
360
+
361
+ if (!response.data) {
362
+ return
363
+ }
364
+
365
+ const { total, items: records } = response.data?.responses
366
+
367
+ for (var item of records) {
368
+ item.active = item.activity && item.activity.state == 'released'
369
+ }
370
+
371
+ return {
372
+ total,
373
+ records
374
+ }
375
+ }
376
+
377
+ async activate(record) {
378
+ await client.mutate({
379
+ mutation: gql`
380
+ mutation ($name: String!) {
381
+ activateInstallableActivity(name: $name) {
382
+ name
383
+ }
384
+ }
385
+ `,
386
+ variables: {
387
+ name: record.name
388
+ }
389
+ })
390
+
391
+ this.grist?.fetch()
392
+ }
393
+
394
+ async deactivate(record) {
395
+ await client.mutate({
396
+ mutation: gql`
397
+ mutation ($name: String!) {
398
+ deactivateInstallableActivity(name: $name) {
399
+ name
400
+ }
401
+ }
402
+ `,
403
+ variables: {
404
+ name: record.name
405
+ }
406
+ })
407
+
408
+ this.grist?.fetch()
409
+ }
410
+ }