@things-factory/dataset 8.0.0-beta.9 → 8.0.2

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 (134) hide show
  1. package/client/activities/activity-data-collect-edit.ts +105 -0
  2. package/client/activities/activity-data-collect-view.ts +91 -0
  3. package/client/activities/activity-data-review-edit.ts +278 -0
  4. package/client/activities/activity-data-review-view.ts +226 -0
  5. package/client/activities/activity-ooc-resolve-edit.ts +195 -0
  6. package/client/activities/activity-ooc-resolve-view.ts +143 -0
  7. package/client/activities/activity-ooc-review-edit.ts +173 -0
  8. package/client/activities/activity-ooc-review-view.ts +129 -0
  9. package/client/bootstrap.ts +35 -0
  10. package/client/components/data-entry-form.ts +109 -0
  11. package/client/index.ts +1 -0
  12. package/client/pages/data-archive/data-archive-list-page.ts +277 -0
  13. package/client/pages/data-archive/data-archive-request-popup.ts +177 -0
  14. package/client/pages/data-entry/data-entry-list-page.ts +464 -0
  15. package/client/pages/data-key-set/data-key-item-list.ts +183 -0
  16. package/client/pages/data-key-set/data-key-set-importer.ts +89 -0
  17. package/client/pages/data-key-set/data-key-set-list-page.ts +413 -0
  18. package/client/pages/data-ooc/data-ooc-list-page.ts +549 -0
  19. package/client/pages/data-ooc/data-ooc-page.ts +164 -0
  20. package/client/pages/data-ooc/data-ooc-view.ts +236 -0
  21. package/client/pages/data-ooc/data-oocs-page.ts +200 -0
  22. package/client/pages/data-report/data-report-embed-page.ts +108 -0
  23. package/client/pages/data-report/data-report-list-page.ts +454 -0
  24. package/client/pages/data-report/data-report-samples-page.ts +174 -0
  25. package/client/pages/data-report/jasper-report-oocs-page.ts +110 -0
  26. package/client/pages/data-report/jasper-report-samples-crosstab-page.ts +110 -0
  27. package/client/pages/data-report/jasper-report-samples-page.ts +110 -0
  28. package/client/pages/data-sample/data-sample-list-page.ts +442 -0
  29. package/client/pages/data-sample/data-sample-page.ts +55 -0
  30. package/client/pages/data-sample/data-sample-search-page.ts +424 -0
  31. package/client/pages/data-sample/data-sample-view.ts +292 -0
  32. package/client/pages/data-sample/data-samples-page.ts +249 -0
  33. package/client/pages/data-sensor/data-sensor-list-page.ts +456 -0
  34. package/client/pages/data-set/data-item-list.ts +304 -0
  35. package/client/pages/data-set/data-set-importer.ts +89 -0
  36. package/client/pages/data-set/data-set-list-page.ts +1078 -0
  37. package/client/pages/data-summary/data-summary-list-page.ts +363 -0
  38. package/client/pages/data-summary/data-summary-period-page.ts +439 -0
  39. package/client/pages/data-summary/data-summary-search-page.ts +426 -0
  40. package/client/pages/data-summary/data-summary-view.ts +133 -0
  41. package/client/route.ts +91 -0
  42. package/client/tsconfig.json +13 -0
  43. package/dist-client/activities/activity-data-review-edit.js +19 -10
  44. package/dist-client/activities/activity-data-review-edit.js.map +1 -1
  45. package/dist-client/activities/activity-data-review-view.js +80 -0
  46. package/dist-client/activities/activity-data-review-view.js.map +1 -1
  47. package/dist-client/pages/data-entry/data-entry-list-page.js +2 -2
  48. package/dist-client/pages/data-entry/data-entry-list-page.js.map +1 -1
  49. package/dist-client/tsconfig.tsbuildinfo +1 -1
  50. package/dist-server/controllers/create-data-ooc.js +2 -0
  51. package/dist-server/controllers/create-data-ooc.js.map +1 -1
  52. package/dist-server/service/data-archive/index.d.ts +1 -1
  53. package/dist-server/service/data-ooc/index.d.ts +1 -1
  54. package/dist-server/service/data-sample/data-sample-query.d.ts +1 -1
  55. package/dist-server/service/data-sample/data-sample-query.js +3 -3
  56. package/dist-server/service/data-sample/data-sample-query.js.map +1 -1
  57. package/dist-server/service/data-sample/index.d.ts +1 -1
  58. package/dist-server/service/data-set/index.d.ts +1 -1
  59. package/dist-server/service/index.d.ts +2 -2
  60. package/dist-server/tsconfig.tsbuildinfo +1 -1
  61. package/package.json +26 -26
  62. package/server/activities/activity-data-collect.ts +100 -0
  63. package/server/activities/activity-data-review.ts +109 -0
  64. package/server/activities/activity-ooc-resolve.ts +123 -0
  65. package/server/activities/activity-ooc-review.ts +95 -0
  66. package/server/activities/index.ts +11 -0
  67. package/server/controllers/create-data-ooc.ts +80 -0
  68. package/server/controllers/create-data-sample.ts +323 -0
  69. package/server/controllers/data-use-case.ts +98 -0
  70. package/server/controllers/finalize-data-collection.ts +388 -0
  71. package/server/controllers/index.ts +6 -0
  72. package/server/controllers/issue-data-collection-task.ts +70 -0
  73. package/server/controllers/issue-ooc-resolve.ts +58 -0
  74. package/server/controllers/issue-ooc-review.ts +52 -0
  75. package/server/controllers/jasper-report.ts +186 -0
  76. package/server/controllers/query-data-summary-by-period.ts +178 -0
  77. package/server/controllers/shiny-report.ts +54 -0
  78. package/server/engine/index.ts +1 -0
  79. package/server/engine/task/create-data-sample.ts +100 -0
  80. package/server/engine/task/index.ts +2 -0
  81. package/server/engine/task/issue-collect-data.ts +45 -0
  82. package/server/index.ts +8 -0
  83. package/server/routes.ts +188 -0
  84. package/server/service/data-archive/data-archive-mutation.ts +273 -0
  85. package/server/service/data-archive/data-archive-query.ts +58 -0
  86. package/server/service/data-archive/data-archive-type.ts +48 -0
  87. package/server/service/data-archive/data-archive.ts +69 -0
  88. package/server/service/data-archive/index.ts +6 -0
  89. package/server/service/data-key-set/data-key-item-type.ts +31 -0
  90. package/server/service/data-key-set/data-key-set-mutation.ts +201 -0
  91. package/server/service/data-key-set/data-key-set-query.ts +68 -0
  92. package/server/service/data-key-set/data-key-set-type.ts +70 -0
  93. package/server/service/data-key-set/data-key-set.ts +86 -0
  94. package/server/service/data-key-set/index.ts +6 -0
  95. package/server/service/data-ooc/data-ooc-mutation.ts +154 -0
  96. package/server/service/data-ooc/data-ooc-query.ts +106 -0
  97. package/server/service/data-ooc/data-ooc-subscription.ts +48 -0
  98. package/server/service/data-ooc/data-ooc-type.ts +71 -0
  99. package/server/service/data-ooc/data-ooc.ts +259 -0
  100. package/server/service/data-ooc/index.ts +7 -0
  101. package/server/service/data-sample/data-sample-mutation.ts +18 -0
  102. package/server/service/data-sample/data-sample-query.ts +215 -0
  103. package/server/service/data-sample/data-sample-type.ts +47 -0
  104. package/server/service/data-sample/data-sample.ts +193 -0
  105. package/server/service/data-sample/index.ts +6 -0
  106. package/server/service/data-sensor/data-sensor-mutation.ts +116 -0
  107. package/server/service/data-sensor/data-sensor-query.ts +76 -0
  108. package/server/service/data-sensor/data-sensor-type.ts +104 -0
  109. package/server/service/data-sensor/data-sensor.ts +126 -0
  110. package/server/service/data-sensor/index.ts +6 -0
  111. package/server/service/data-set/data-item-type.ts +155 -0
  112. package/server/service/data-set/data-set-mutation.ts +552 -0
  113. package/server/service/data-set/data-set-query.ts +461 -0
  114. package/server/service/data-set/data-set-type.ts +204 -0
  115. package/server/service/data-set/data-set.ts +326 -0
  116. package/server/service/data-set/index.ts +6 -0
  117. package/server/service/data-set-history/data-set-history-query.ts +126 -0
  118. package/server/service/data-set-history/data-set-history-type.ts +12 -0
  119. package/server/service/data-set-history/data-set-history.ts +217 -0
  120. package/server/service/data-set-history/event-subscriber.ts +17 -0
  121. package/server/service/data-set-history/index.ts +7 -0
  122. package/server/service/data-spec/data-spec-manager.ts +21 -0
  123. package/server/service/data-spec/data-spec-query.ts +21 -0
  124. package/server/service/data-spec/data-spec.ts +45 -0
  125. package/server/service/data-spec/index.ts +5 -0
  126. package/server/service/data-summary/data-summary-mutation.ts +45 -0
  127. package/server/service/data-summary/data-summary-query.ts +179 -0
  128. package/server/service/data-summary/data-summary-type.ts +86 -0
  129. package/server/service/data-summary/data-summary.ts +170 -0
  130. package/server/service/data-summary/index.ts +7 -0
  131. package/server/service/index.ts +57 -0
  132. package/server/tsconfig.json +10 -0
  133. package/server/utils/config-resolver.ts +29 -0
  134. package/server/utils/index.ts +1 -0
@@ -0,0 +1,424 @@
1
+ import '@material/web/icon/icon.js'
2
+ import '@operato/data-grist'
3
+ import '@operato/context/ox-context-page-toolbar.js'
4
+ import './data-sample-view.js'
5
+
6
+ import gql from 'graphql-tag'
7
+ import { css, html } from 'lit'
8
+ import { customElement, property, query, state } from 'lit/decorators.js'
9
+ import { connect } from 'pwa-helpers/connect-mixin'
10
+ import moment from '@operato/moment-timezone-es'
11
+
12
+ import { DataGrist, FetchOption, GristRecord } from '@operato/data-grist'
13
+ import { client } from '@operato/graphql'
14
+ import { i18next, localize } from '@operato/i18n'
15
+ import { openPopup } from '@operato/layout'
16
+ import { PageView, store } from '@operato/shell'
17
+ import { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles'
18
+ import { isMobileDevice } from '@operato/utils'
19
+ import { GhostPrint } from '@operato/ghost-print'
20
+
21
+ @customElement('data-sample-search-page')
22
+ export class DataSampleSearchPage extends connect(store)(localize(i18next)(PageView)) {
23
+ static styles = [
24
+ ScrollbarStyles,
25
+ CommonHeaderStyles,
26
+ css`
27
+ :host {
28
+ display: flex;
29
+ flex-direction: column;
30
+
31
+ overflow: hidden;
32
+ }
33
+
34
+ ox-grist {
35
+ overflow-y: auto;
36
+ flex: 1;
37
+ }
38
+
39
+ .header {
40
+ grid-template-areas: 'filters actions';
41
+ }
42
+ `
43
+ ]
44
+
45
+ @state() dataSetId?: string
46
+ @state() dataSet: any
47
+ @state() dataKeySet: any
48
+
49
+ @state() gristConfig: any
50
+ @state() mode: 'CARD' | 'GRID' | 'LIST' = isMobileDevice() ? 'CARD' : 'GRID'
51
+
52
+ @query('ox-grist') private grist!: DataGrist
53
+
54
+ get context() {
55
+ return {
56
+ title: i18next.t('title.data-sample search'),
57
+ search: {
58
+ handler: (search: string) => {
59
+ this.grist.searchText = search
60
+ },
61
+ value: this.grist?.searchText || ''
62
+ },
63
+ filter: {
64
+ handler: () => {
65
+ this.grist.toggleHeadroom()
66
+ }
67
+ },
68
+ help: 'dataset/data-sample-search',
69
+ actions: [
70
+ {
71
+ title: i18next.t('button.print'),
72
+ action: this.printSamples.bind(this),
73
+ icon: 'print'
74
+ }
75
+ ],
76
+ // exportable: {
77
+ // name: i18next.t('title.data-sample search'),
78
+ // data: this._exportableData.bind(this)
79
+ // },
80
+ toolbar: false
81
+ }
82
+ }
83
+
84
+ render() {
85
+ const mode = this.mode || (isMobileDevice() ? 'LIST' : 'GRID')
86
+
87
+ return html`
88
+ <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
89
+ <div slot="headroom" class="header">
90
+ <div class="filters">
91
+ <ox-filters-form class="filter" autofocus without-search></ox-filters-form>
92
+ </div>
93
+
94
+ <ox-context-page-toolbar class="actions" .context=${this.context}></ox-context-page-toolbar>
95
+ </div>
96
+ </ox-grist>
97
+ `
98
+ }
99
+
100
+ pageUpdated(changes, lifecycle) {
101
+ if (this.active) {
102
+ this.dataSetId = lifecycle.resourceId
103
+ return
104
+ }
105
+ }
106
+
107
+ async updated(changes) {
108
+ if (changes.has('dataSetId')) {
109
+ const response = await client.query({
110
+ query: gql`
111
+ query ($id: String!) {
112
+ dataSet(id: $id) {
113
+ id
114
+ name
115
+ description
116
+ dataKeySet {
117
+ id
118
+ name
119
+ description
120
+ dataKeyItems {
121
+ name
122
+ description
123
+ dataKey
124
+ tKey
125
+ }
126
+ }
127
+ }
128
+ }
129
+ `,
130
+ variables: {
131
+ id: this.dataSetId
132
+ }
133
+ })
134
+
135
+ this.dataSet = response.data.dataSet
136
+ this.dataKeySet = this.dataSet.dataKeySet
137
+
138
+ this.refreshGristConfig()
139
+ }
140
+ }
141
+
142
+ getDataKeyColumns() {
143
+ return (
144
+ this.dataKeySet?.dataKeyItems.map((item, index) => {
145
+ return {
146
+ type: 'string',
147
+ name: `key0${index + 1}`,
148
+ header: i18next.t(item.tKey),
149
+ record: {
150
+ editable: false
151
+ },
152
+ sortable: true,
153
+ filter: 'i_like',
154
+ width: 120,
155
+ imex: true
156
+ }
157
+ }) || []
158
+ )
159
+ }
160
+
161
+ refreshGristConfig() {
162
+ const yesterday = moment().subtract(1, 'day').format('YYYY-MM-DD')
163
+ const today = moment().format('YYYY-MM-DD')
164
+
165
+ this.gristConfig = {
166
+ list: { fields: ['dataSet', 'data', 'updater', 'updatedAt'] },
167
+ columns: [
168
+ { type: 'gutter', gutterName: 'sequence', fixed: true },
169
+ { type: 'gutter', gutterName: 'row-selector', fixed: true, multiple: true },
170
+ {
171
+ type: 'gutter',
172
+ gutterName: 'button',
173
+ fixed: true,
174
+ icon: 'assignment',
175
+ iconOnly: false,
176
+ title: i18next.t('button.detail'),
177
+ width: 72
178
+ },
179
+ {
180
+ type: 'string',
181
+ name: 'name',
182
+ fixed: true,
183
+ label: true,
184
+ header: i18next.t('field.name'),
185
+ record: {
186
+ editable: false
187
+ },
188
+ filter: 'search',
189
+ sortable: true,
190
+ width: 120,
191
+ imex: true
192
+ },
193
+ {
194
+ type: 'string',
195
+ name: 'description',
196
+ label: true,
197
+ header: i18next.t('field.description'),
198
+ record: {
199
+ editable: false
200
+ },
201
+ filter: 'search',
202
+ width: 150,
203
+ imex: true
204
+ },
205
+ ...this.getDataKeyColumns(),
206
+ {
207
+ type: 'checkbox',
208
+ name: 'ooc',
209
+ header: i18next.t('field.ooc'),
210
+ record: {
211
+ editable: false
212
+ },
213
+ width: 30
214
+ },
215
+ {
216
+ type: 'checkbox',
217
+ name: 'oos',
218
+ header: i18next.t('field.oos'),
219
+ record: {
220
+ editable: false
221
+ },
222
+ width: 30
223
+ },
224
+ {
225
+ type: 'json5',
226
+ name: 'data',
227
+ header: i18next.t('field.data'),
228
+ record: {
229
+ editable: false
230
+ },
231
+ hidden: true,
232
+ imex: true
233
+ },
234
+ {
235
+ type: 'string',
236
+ name: 'workDate',
237
+ header: i18next.t('field.work-date'),
238
+ sortable: true,
239
+ filter: {
240
+ type: 'date',
241
+ operator: 'between',
242
+ value: [yesterday, today]
243
+ },
244
+ width: 80,
245
+ imex: true
246
+ },
247
+ {
248
+ type: 'string',
249
+ name: 'workShift',
250
+ header: i18next.t('field.work-shift'),
251
+ sortable: true,
252
+ width: 40,
253
+ imex: true
254
+ },
255
+ {
256
+ type: 'datetime',
257
+ name: 'collectedAt',
258
+ header: i18next.t('field.collected-at'),
259
+ sortable: true,
260
+ width: 180,
261
+ imex: true
262
+ },
263
+ {
264
+ type: 'resource-object',
265
+ name: 'updater',
266
+ header: i18next.t('field.updater'),
267
+ sortable: true,
268
+ width: 120,
269
+ imex: true
270
+ },
271
+ {
272
+ type: 'datetime',
273
+ name: 'updatedAt',
274
+ header: i18next.t('field.updated_at'),
275
+ sortable: true,
276
+ width: 180,
277
+ imex: true
278
+ }
279
+ ],
280
+ rows: {
281
+ appendable: false,
282
+ selectable: {
283
+ multiple: true
284
+ },
285
+ classifier: function (record, rowIndex) {
286
+ var emphasized
287
+ if (record['oos']) {
288
+ emphasized = ['#8B0000', 'white']
289
+ } else if (record['ooc']) {
290
+ emphasized = ['#FF6B6B', 'white']
291
+ }
292
+
293
+ return {
294
+ emphasized
295
+ }
296
+ },
297
+ handlers: {
298
+ click: (columns, data, column, record, rowIndex) => {
299
+ openPopup(
300
+ html`
301
+ <data-sample-view data-sample-id=${record.id} style="background-color: white;"></data-sample-view>
302
+ `,
303
+ {
304
+ backdrop: true,
305
+ size: 'large',
306
+ title: i18next.t('title.data-sample view')
307
+ }
308
+ )
309
+ }
310
+ }
311
+ },
312
+ sorters: [
313
+ {
314
+ name: 'collectedAt',
315
+ desc: true
316
+ }
317
+ ]
318
+ }
319
+ }
320
+
321
+ async fetchHandler({ page, limit, sortings = [], filters = [] }: FetchOption) {
322
+ if (!this.dataSetId) {
323
+ return { records: [], total: 0 }
324
+ }
325
+
326
+ const response = await client.query({
327
+ query: gql`
328
+ query ($dataSetId: String!, $filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
329
+ responses: dataSamplesByDataSet(
330
+ dataSetId: $dataSetId
331
+ filters: $filters
332
+ pagination: $pagination
333
+ sortings: $sortings
334
+ ) {
335
+ items {
336
+ id
337
+ name
338
+ description
339
+ useCase
340
+ key01
341
+ key02
342
+ key03
343
+ key04
344
+ key05
345
+ data
346
+ ooc
347
+ oos
348
+ judgment
349
+ workDate
350
+ workShift
351
+ updater {
352
+ id
353
+ name
354
+ }
355
+ updatedAt
356
+ collectedAt
357
+ }
358
+ total
359
+ }
360
+ }
361
+ `,
362
+ variables: {
363
+ dataSetId: this.dataSetId,
364
+ filters,
365
+ pagination: { page, limit },
366
+ sortings
367
+ }
368
+ })
369
+
370
+ return {
371
+ total: response.data.responses.total || 0,
372
+ records: response.data.responses.items || []
373
+ }
374
+ }
375
+
376
+ _exportableData() {
377
+ let records = [] as GristRecord[]
378
+ if (this.grist.selected && this.grist.selected.length > 0) {
379
+ records = this.grist.selected
380
+ } else {
381
+ records = this.grist.data.records
382
+ }
383
+
384
+ var headerSetting = this.grist.compiledConfig.columns
385
+ .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
386
+ .map(column => {
387
+ return column.imex === true
388
+ ? {
389
+ header: column.header.renderer(column),
390
+ key: column.name,
391
+ width: column.width,
392
+ type: column.type
393
+ }
394
+ : column.imex
395
+ })
396
+
397
+ var data = records.map(item => {
398
+ return {
399
+ id: item.id,
400
+ ...this.gristConfig.columns
401
+ .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
402
+ .reduce((record, column) => {
403
+ const key = column.imex === true ? column.name : column.imex.key
404
+ record[key] = key
405
+ .split('.')
406
+ .reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
407
+ return record
408
+ }, {})
409
+ }
410
+ })
411
+
412
+ return { header: headerSetting, data: data }
413
+ }
414
+
415
+ printSamples() {
416
+ const selected = this.grist.selected
417
+ const ids = selected.map(record => record.id).join('|')
418
+
419
+ GhostPrint.print({
420
+ src: `./data-samples?ids=${ids}`
421
+ // pending: 200 * selected.length
422
+ })
423
+ }
424
+ }
@@ -0,0 +1,292 @@
1
+ import '@material/web/icon/icon.js'
2
+ import '@material/web/fab/fab.js'
3
+ import '@operato/dataset/ox-data-sample-view.js'
4
+ import '@operato/dataset/ox-data-ooc-brief-view.js'
5
+ import '@things-factory/worklist/dist-client/components/activity-thread-timeline.js'
6
+
7
+ import gql from 'graphql-tag'
8
+ import { css, html, LitElement, nothing } from 'lit'
9
+ import { customElement, property, state } from 'lit/decorators.js'
10
+
11
+ import { client } from '@operato/graphql'
12
+ import { i18next, localize } from '@operato/i18n'
13
+ import { ScrollbarStyles } from '@operato/styles'
14
+ import { DataSample } from '@operato/dataset'
15
+ import { GhostPrint } from '@operato/ghost-print'
16
+
17
+ @customElement('data-sample-view')
18
+ export class DataSampleView extends localize(i18next)(LitElement) {
19
+ static styles = [
20
+ ScrollbarStyles,
21
+ css`
22
+ :host {
23
+ position: relative;
24
+ display: block;
25
+ overflow: auto;
26
+ background-color: var(--md-sys-color-surface);
27
+ }
28
+
29
+ ox-data-sample-view,
30
+ ox-data-ooc-brief-view {
31
+ padding: var(--spacing-large);
32
+ }
33
+
34
+ activity-thread-timeline {
35
+ margin: var(--spacing-medium);
36
+ }
37
+
38
+ md-fab {
39
+ position: fixed;
40
+ bottom: 15px;
41
+ right: 16px;
42
+ text-decoration: auto;
43
+ opacity: 0.5;
44
+ }
45
+
46
+ @media print {
47
+ md-fab {
48
+ display: none;
49
+ }
50
+ }
51
+ `
52
+ ]
53
+
54
+ @property({
55
+ type: String,
56
+ attribute: 'data-sample-id'
57
+ })
58
+ dataSampleId?: string
59
+
60
+ @state() dataSample?: DataSample
61
+
62
+ private printHandler = this.handlePrint.bind(this)
63
+
64
+ render() {
65
+ const dataSample = this.dataSample
66
+
67
+ if (!dataSample) {
68
+ return nothing
69
+ }
70
+
71
+ if (dataSample.dataOoc) {
72
+ var reviewActivityThread = dataSample.dataOoc.reviewActivityInstance?.activityThreads?.[0]
73
+ var resolveActivityThread = dataSample.dataOoc.resolveActivityInstance?.activityThreads?.[0]
74
+ } else {
75
+ var reviewActivityThread = dataSample?.reviewActivityInstance?.activityThreads?.[0]
76
+ }
77
+
78
+ return html`
79
+ ${!dataSample?.dataOoc
80
+ ? html` <ox-data-sample-view .dataSample=${dataSample}></ox-data-sample-view> `
81
+ : html` <ox-data-ooc-brief-view .dataOoc=${dataSample!.dataOoc}></ox-data-ooc-brief-view>`}
82
+ ${reviewActivityThread
83
+ ? html`
84
+ <activity-thread-timeline
85
+ subtitle=${String(
86
+ i18next.t(dataSample?.dataOoc ? 'label.ooc review timeline' : 'label.datasample review timeline')
87
+ )}
88
+ .activityThread=${reviewActivityThread}
89
+ short-form
90
+ ></activity-thread-timeline>
91
+ `
92
+ : nothing}
93
+ ${resolveActivityThread
94
+ ? html`
95
+ <activity-thread-timeline
96
+ subtitle=${String(i18next.t('label.ooc resolve timeline'))}
97
+ .activityThread=${resolveActivityThread}
98
+ short-form
99
+ ></activity-thread-timeline>
100
+ `
101
+ : nothing}
102
+
103
+ <md-fab
104
+ title="print"
105
+ @click=${() =>
106
+ GhostPrint.print({
107
+ src: `./data-sample/${this.dataSampleId}`
108
+ })}
109
+ >
110
+ <md-icon slot="icon">print</md-icon>
111
+ </md-fab>
112
+ `
113
+ }
114
+
115
+ updated(changes) {
116
+ if (changes.has('dataSampleId')) {
117
+ this.fetchDataSample()
118
+ }
119
+ }
120
+
121
+ async fetchDataSample() {
122
+ const id = this.dataSampleId
123
+
124
+ const response = await client.query({
125
+ query: gql`
126
+ query ($id: String!) {
127
+ dataSample(id: $id) {
128
+ id
129
+ name
130
+ description
131
+ useCase
132
+ key01
133
+ key02
134
+ key03
135
+ key04
136
+ key05
137
+ data
138
+ ooc
139
+ oos
140
+ updatedAt
141
+ collectedAt
142
+ updater {
143
+ id
144
+ name
145
+ }
146
+ dataSet {
147
+ id
148
+ name
149
+ description
150
+ }
151
+ dataItems {
152
+ name
153
+ description
154
+ active
155
+ hidden
156
+ tag
157
+ group
158
+ type
159
+ unit
160
+ options
161
+ quota
162
+ spec
163
+ stat
164
+ }
165
+ judgment
166
+ workDate
167
+ workShift
168
+ reviewActivityInstance {
169
+ ...ActivityInstanceFragment
170
+ }
171
+ dataOoc {
172
+ name
173
+ description
174
+ useCase
175
+ dataSet {
176
+ id
177
+ name
178
+ }
179
+ key01
180
+ key02
181
+ key03
182
+ key04
183
+ key05
184
+ partitionKeys
185
+ dataItems {
186
+ name
187
+ description
188
+ active
189
+ hidden
190
+ tag
191
+ group
192
+ type
193
+ unit
194
+ options
195
+ quota
196
+ spec
197
+ }
198
+ data
199
+ rawData
200
+ judgment
201
+ ooc
202
+ oos
203
+ state
204
+ history
205
+ workDate
206
+ workShift
207
+ correctiveInstruction
208
+ correctiveAction
209
+ reviewedAt
210
+ reviewer {
211
+ id
212
+ name
213
+ }
214
+ correctedAt
215
+ corrector {
216
+ id
217
+ name
218
+ }
219
+ updater {
220
+ id
221
+ name
222
+ }
223
+ updatedAt
224
+ collectedAt
225
+
226
+ reviewActivityInstance {
227
+ ...ActivityInstanceFragment
228
+ }
229
+ resolveActivityInstance {
230
+ ...ActivityInstanceFragment
231
+ }
232
+ }
233
+ }
234
+ }
235
+
236
+ fragment ActivityInstanceFragment on ActivityInstance {
237
+ activityThreads {
238
+ assignee {
239
+ name
240
+ }
241
+ output
242
+ activityApprovals {
243
+ judgment
244
+ approver {
245
+ name
246
+ }
247
+ comment
248
+ createdAt
249
+ updatedAt
250
+ terminatedAt
251
+ }
252
+ activityThreadHistories {
253
+ transaction
254
+ reason
255
+ updater {
256
+ name
257
+ }
258
+ updatedAt
259
+ state
260
+ output
261
+ }
262
+ }
263
+ }
264
+ `,
265
+ variables: {
266
+ id
267
+ }
268
+ })
269
+
270
+ this.dataSample = response.data.dataSample
271
+ }
272
+
273
+ handlePrint(event) {
274
+ if ((event.ctrlKey || event.metaKey) && event.key === 'p') {
275
+ event.preventDefault()
276
+
277
+ GhostPrint.print({
278
+ src: `./data-sample/${this.dataSampleId}`
279
+ })
280
+ }
281
+ }
282
+
283
+ connectedCallback(): void {
284
+ super.connectedCallback()
285
+ window.addEventListener('keydown', this.printHandler)
286
+ }
287
+
288
+ disconnectedCallback(): void {
289
+ super.disconnectedCallback()
290
+ window.removeEventListener('keydown', this.printHandler)
291
+ }
292
+ }