@things-factory/dataset 5.0.0-alpha.9 → 5.0.0-zeta.1

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 (105) hide show
  1. package/README.md +9 -0
  2. package/assets/data-samples.jpg +0 -0
  3. package/client/bootstrap.js +21 -1
  4. package/client/pages/{data-entry-form.js → data-entry/data-entry-form.js} +15 -3
  5. package/client/pages/data-entry/data-entry-list-page.js +390 -0
  6. package/client/pages/data-ooc/data-ooc-list-page.js +416 -0
  7. package/client/pages/data-ooc/data-ooc-view.js +183 -0
  8. package/client/pages/data-report/data-report-embed-page.js +113 -0
  9. package/client/pages/data-report/data-report-list-page.js +432 -0
  10. package/client/pages/data-report/jasper-report-oocs-page.js +122 -0
  11. package/client/pages/data-report/jasper-report-samples-crosstab-page.js +122 -0
  12. package/client/pages/data-report/jasper-report-samples-page.js +122 -0
  13. package/client/pages/data-sample/data-sample-list-page.js +372 -0
  14. package/client/pages/data-sample/data-sample-view.js +98 -0
  15. package/client/pages/{data-sensor.js → data-sensor/data-sensor-list-page.js} +43 -68
  16. package/client/pages/{data-item-list.js → data-set/data-item-list.js} +36 -11
  17. package/client/pages/{data-set-importer.js → data-set/data-set-importer.js} +0 -0
  18. package/client/pages/data-set/data-set-list-page.js +739 -0
  19. package/client/route.js +34 -6
  20. package/config/config.development.js +13 -0
  21. package/config/config.production.js +1 -0
  22. package/dist-server/controllers/create-data-sample.js +133 -0
  23. package/dist-server/controllers/create-data-sample.js.map +1 -0
  24. package/dist-server/controllers/data-use-case.js +57 -0
  25. package/dist-server/controllers/data-use-case.js.map +1 -0
  26. package/dist-server/controllers/index.js +18 -0
  27. package/dist-server/controllers/index.js.map +1 -1
  28. package/dist-server/controllers/jasper-report.js +156 -0
  29. package/dist-server/controllers/jasper-report.js.map +1 -0
  30. package/dist-server/index.js +1 -0
  31. package/dist-server/index.js.map +1 -1
  32. package/dist-server/routes.js +13 -24
  33. package/dist-server/routes.js.map +1 -1
  34. package/dist-server/service/data-item/data-item-query.js +6 -2
  35. package/dist-server/service/data-item/data-item-query.js.map +1 -1
  36. package/dist-server/service/data-item/data-item-type.js +15 -7
  37. package/dist-server/service/data-item/data-item-type.js.map +1 -1
  38. package/dist-server/service/data-item/data-item.js +17 -3
  39. package/dist-server/service/data-item/data-item.js.map +1 -1
  40. package/dist-server/service/data-ooc/data-ooc-mutation.js +92 -0
  41. package/dist-server/service/data-ooc/data-ooc-mutation.js.map +1 -0
  42. package/dist-server/service/data-ooc/data-ooc-query.js +120 -0
  43. package/dist-server/service/data-ooc/data-ooc-query.js.map +1 -0
  44. package/dist-server/service/data-ooc/data-ooc-subscription.js +65 -0
  45. package/dist-server/service/data-ooc/data-ooc-subscription.js.map +1 -0
  46. package/dist-server/service/data-ooc/data-ooc-type.js +107 -0
  47. package/dist-server/service/data-ooc/data-ooc-type.js.map +1 -0
  48. package/dist-server/service/data-ooc/data-ooc.js +237 -0
  49. package/dist-server/service/data-ooc/data-ooc.js.map +1 -0
  50. package/dist-server/service/data-ooc/index.js +10 -0
  51. package/dist-server/service/data-ooc/index.js.map +1 -0
  52. package/dist-server/service/data-sample/data-sample-mutation.js +2 -138
  53. package/dist-server/service/data-sample/data-sample-mutation.js.map +1 -1
  54. package/dist-server/service/data-sample/data-sample-query.js +7 -2
  55. package/dist-server/service/data-sample/data-sample-query.js.map +1 -1
  56. package/dist-server/service/data-sample/data-sample-type.js +12 -42
  57. package/dist-server/service/data-sample/data-sample-type.js.map +1 -1
  58. package/dist-server/service/data-sample/data-sample.js +34 -3
  59. package/dist-server/service/data-sample/data-sample.js.map +1 -1
  60. package/dist-server/service/data-sensor/data-sensor-query.js +7 -2
  61. package/dist-server/service/data-sensor/data-sensor-query.js.map +1 -1
  62. package/dist-server/service/data-set/data-set-mutation.js +40 -14
  63. package/dist-server/service/data-set/data-set-mutation.js.map +1 -1
  64. package/dist-server/service/data-set/data-set-query.js +190 -3
  65. package/dist-server/service/data-set/data-set-query.js.map +1 -1
  66. package/dist-server/service/data-set/data-set-type.js +84 -3
  67. package/dist-server/service/data-set/data-set-type.js.map +1 -1
  68. package/dist-server/service/data-set/data-set.js +110 -15
  69. package/dist-server/service/data-set/data-set.js.map +1 -1
  70. package/dist-server/service/index.js +6 -2
  71. package/dist-server/service/index.js.map +1 -1
  72. package/package.json +19 -13
  73. package/server/controllers/create-data-sample.ts +177 -0
  74. package/server/controllers/data-use-case.ts +85 -0
  75. package/server/controllers/index.ts +2 -0
  76. package/server/controllers/jasper-report.ts +170 -0
  77. package/server/index.ts +1 -0
  78. package/server/routes.ts +21 -31
  79. package/server/service/data-item/data-item-query.ts +8 -3
  80. package/server/service/data-item/data-item-type.ts +10 -6
  81. package/server/service/data-item/data-item.ts +15 -4
  82. package/server/service/data-ooc/data-ooc-mutation.ts +150 -0
  83. package/server/service/data-ooc/data-ooc-query.ts +69 -0
  84. package/server/service/data-ooc/data-ooc-subscription.ts +51 -0
  85. package/server/service/data-ooc/data-ooc-type.ts +68 -0
  86. package/server/service/data-ooc/data-ooc.ts +204 -0
  87. package/server/service/data-ooc/index.ts +7 -0
  88. package/server/service/data-sample/data-sample-mutation.ts +3 -168
  89. package/server/service/data-sample/data-sample-query.ts +9 -3
  90. package/server/service/data-sample/data-sample-type.ts +7 -28
  91. package/server/service/data-sample/data-sample.ts +33 -3
  92. package/server/service/data-sensor/data-sensor-query.ts +9 -3
  93. package/server/service/data-set/data-set-mutation.ts +53 -14
  94. package/server/service/data-set/data-set-query.ts +161 -4
  95. package/server/service/data-set/data-set-type.ts +65 -4
  96. package/server/service/data-set/data-set.ts +100 -12
  97. package/server/service/index.ts +6 -2
  98. package/things-factory.config.js +35 -7
  99. package/translations/en.json +46 -3
  100. package/translations/ko.json +45 -3
  101. package/translations/ms.json +44 -3
  102. package/translations/zh.json +44 -3
  103. package/client/pages/data-sample.js +0 -307
  104. package/client/pages/data-set.js +0 -457
  105. package/yarn-error.log +0 -23244
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # dataset
2
+ ## Architecture for data-samples
3
+ ![Architecture for data-samples](./assets/data-samples.jpg)
4
+ ## Partition Keys
5
+ At the early stage, partition keys are desinged for dynamic partitioning for Athena. But It will be required so many AWS Glue crawlers also by each 'data-sets'.
6
+
7
+ Partition keys are related for S3 request limitations.
8
+ > __3,500 PUT/COPY/POST/DELETE or 5,500 GET/HEAD requests per second per prefix in a bucket__
9
+ - https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance.html
Binary file
@@ -1 +1,21 @@
1
- export default function bootstrap() {}
1
+ import '@operato/app/filter-renderer.js' /* register resource-object filter renderer */
2
+
3
+ import {
4
+ OxGristRendererJson5,
5
+ registerEditor as registerGristEditor,
6
+ registerRenderer as registerGristRenderer
7
+ } from '@operato/data-grist'
8
+
9
+ import { OxGristEditorCode } from '@operato/app/grist-editor/ox-grist-editor-code.js'
10
+ import { OxGristEditorDataItemSpec } from '@operato/dataset/grist-editor'
11
+ import { OxGristEditorPartitionKeys } from '@operato/app/grist-editor/ox-grist-editor-partition-keys.js'
12
+
13
+ export default function bootstrap() {
14
+ registerGristEditor('data-item-spec', OxGristEditorDataItemSpec)
15
+ registerGristRenderer('data-item-spec', OxGristRendererJson5)
16
+
17
+ registerGristEditor('script', OxGristEditorCode)
18
+
19
+ registerGristEditor('partition-keys', OxGristEditorPartitionKeys)
20
+ registerGristRenderer('partition-keys', OxGristRendererJson5)
21
+ }
@@ -1,9 +1,11 @@
1
+ import '@operato/dataset/ox-data-entry-form.js'
2
+
1
3
  import gql from 'graphql-tag'
2
4
  import { css, html, LitElement } from 'lit'
3
5
 
4
6
  import { client } from '@operato/graphql'
5
7
  import { i18next, localize } from '@operato/i18n'
6
- import '@operato/dataset/ox-data-entry-form.js'
8
+ import { ScrollbarStyles } from '@operato/styles'
7
9
 
8
10
  class DataEntryForm extends localize(i18next)(LitElement) {
9
11
  static get properties() {
@@ -14,6 +16,7 @@ class DataEntryForm extends localize(i18next)(LitElement) {
14
16
 
15
17
  static get styles() {
16
18
  return [
19
+ ScrollbarStyles,
17
20
  css`
18
21
  :host {
19
22
  display: flex;
@@ -24,7 +27,8 @@ class DataEntryForm extends localize(i18next)(LitElement) {
24
27
 
25
28
  ox-data-entry-form {
26
29
  flex: 1;
27
- margin: 10px;
30
+ padding: 10px;
31
+ overflow: auto;
28
32
  }
29
33
 
30
34
  .button-container {
@@ -52,7 +56,9 @@ class DataEntryForm extends localize(i18next)(LitElement) {
52
56
  async _updateDataItems() {
53
57
  const data = this.entryForm.buildValue()
54
58
  const dataSample = {
55
- dataSetId: this.dataSet.id,
59
+ dataSet: {
60
+ id: this.dataSet.id
61
+ },
56
62
  data
57
63
  }
58
64
 
@@ -69,6 +75,12 @@ class DataEntryForm extends localize(i18next)(LitElement) {
69
75
  dataSample
70
76
  }
71
77
  })
78
+
79
+ if (!response.errors) {
80
+ document.dispatchEvent(
81
+ new CustomEvent('notify', { detail: { message: i18next.t('text.data sample created successfully') } })
82
+ )
83
+ }
72
84
  }
73
85
  }
74
86
 
@@ -0,0 +1,390 @@
1
+ import '@operato/data-grist'
2
+ import './data-entry-form'
3
+ import '@operato/board/ox-board-viewer.js'
4
+
5
+ import gql from 'graphql-tag'
6
+ import { css, html } from 'lit'
7
+ import { connect } from 'pwa-helpers/connect-mixin'
8
+
9
+ import { getRenderer } from '@operato/data-grist'
10
+ import { OxDataUseCase } from '@operato/dataset'
11
+ import { client } from '@operato/graphql'
12
+ import { i18next, localize } from '@operato/i18n'
13
+ import { openPopup } from '@operato/layout'
14
+ import { navigate, PageView, store } from '@operato/shell'
15
+ import { CommonGristStyles, ScrollbarStyles } from '@operato/styles'
16
+ import { provider } from '@things-factory/board-ui'
17
+
18
+ const USECASE_OPTIONS = () => {
19
+ return ['', ...OxDataUseCase.getUseCaseNames()].map(name => {
20
+ return {
21
+ display: name,
22
+ value: name
23
+ }
24
+ })
25
+ }
26
+
27
+ const showEntryView = async (columns, data, column, record, rowIndex) => {
28
+ const { name, entryType, entryView } = record
29
+ const title = `${name} - ${i18next.t('title.data-entry-form')}`
30
+
31
+ switch (entryType) {
32
+ case 'generated':
33
+ openPopup(html` <data-entry-form .dataSet=${record} style="background-color: white;"></data-entry-form> `, {
34
+ closable: true,
35
+ backdrop: true,
36
+ size: 'large',
37
+ title
38
+ })
39
+ break
40
+
41
+ case 'board':
42
+ const board = {
43
+ id: entryView
44
+ }
45
+ openPopup(
46
+ html`
47
+ <ox-board-viewer
48
+ style="background-color: white;"
49
+ .board=${board}
50
+ .provider=${provider}
51
+ hide-fullscreen
52
+ hide-navigation
53
+ ></ox-board-viewer>
54
+ `,
55
+ {
56
+ closable: true,
57
+ backdrop: true,
58
+ size: 'large',
59
+ title
60
+ }
61
+ )
62
+
63
+ // navigate(`board-viewer/${entryView}?interactive=true&title=${title}`)
64
+ break
65
+
66
+ case 'page':
67
+ navigate(entryView)
68
+ break
69
+
70
+ case 'external':
71
+ window.open(entryView, '_blank')
72
+ break
73
+ }
74
+ }
75
+
76
+ export class DataEntryListPage extends connect(store)(localize(i18next)(PageView)) {
77
+ static get properties() {
78
+ return {
79
+ active: String,
80
+ gristConfig: Object,
81
+ filters: Object,
82
+ sorters: Object,
83
+ mode: String
84
+ }
85
+ }
86
+
87
+ static get styles() {
88
+ return [
89
+ ScrollbarStyles,
90
+ CommonGristStyles,
91
+ css`
92
+ :host {
93
+ display: flex;
94
+
95
+ width: 100%;
96
+
97
+ --grid-record-emphasized-background-color: red;
98
+ --grid-record-emphasized-color: yellow;
99
+ }
100
+ `
101
+ ]
102
+ }
103
+
104
+ get context() {
105
+ return {
106
+ title: i18next.t('title.data-entry list'),
107
+ help: 'dataset/data-entry-list'
108
+ }
109
+ }
110
+
111
+ render() {
112
+ const mode = 'CARD'
113
+
114
+ return html`
115
+ <ox-grist
116
+ .mode=${mode}
117
+ .config=${this.gristConfig}
118
+ .filters=${this.filters}
119
+ .orders=${this.orders}
120
+ .fetchHandler=${this.fetchHandler.bind(this)}
121
+ >
122
+ <div slot="headroom">
123
+ <div id="filters">
124
+ <ox-filters-form></ox-filters-form>
125
+ </div>
126
+
127
+ <div id="sorters">
128
+ Sort
129
+ <mwc-icon
130
+ @click=${e => {
131
+ const target = e.currentTarget
132
+ this.renderRoot.querySelector('#sorter-control').open({
133
+ right: 0,
134
+ top: target.offsetTop + target.offsetHeight
135
+ })
136
+ }}
137
+ >expand_more</mwc-icon
138
+ >
139
+ <ox-popup id="sorter-control">
140
+ <ox-sorters-control> </ox-sorters-control>
141
+ </ox-popup>
142
+ </div>
143
+ </div>
144
+ </ox-grist>
145
+ `
146
+ }
147
+
148
+ get grist() {
149
+ return this.renderRoot.querySelector('ox-grist')
150
+ }
151
+
152
+ async pageInitialized(lifecycle) {
153
+ this.gristConfig = {
154
+ list: {
155
+ thumbnail: 'entryView',
156
+ fields: ['name', 'description'],
157
+ details: ['schedule', 'type', 'useCase', 'latestCollectedAt', 'prevSchedule', 'nextSchedule']
158
+ },
159
+ columns: [
160
+ {
161
+ type: 'gutter',
162
+ gutterName: 'button',
163
+ icon: 'fact_check',
164
+ handlers: {
165
+ click: showEntryView
166
+ }
167
+ },
168
+ {
169
+ type: 'string',
170
+ name: 'name',
171
+ header: i18next.t('field.name'),
172
+ record: {
173
+ editable: false
174
+ },
175
+ filter: 'search',
176
+ sortable: true,
177
+ width: 150
178
+ },
179
+ {
180
+ type: 'string',
181
+ name: 'description',
182
+ header: i18next.t('field.description'),
183
+ record: {
184
+ editable: false
185
+ },
186
+ filter: 'search',
187
+ width: 200
188
+ },
189
+ {
190
+ type: 'select',
191
+ name: 'type',
192
+ label: true,
193
+ header: i18next.t('field.type'),
194
+ record: {
195
+ editable: false,
196
+ options: [
197
+ {},
198
+ {
199
+ display: i18next.t('text.manually collected'),
200
+ value: 'manual'
201
+ },
202
+ {
203
+ display: i18next.t('text.automatically collected'),
204
+ value: 'automatic'
205
+ }
206
+ ]
207
+ },
208
+ sortable: true,
209
+ filter: true,
210
+ width: 60
211
+ },
212
+ {
213
+ type: 'select',
214
+ name: 'useCase',
215
+ label: true,
216
+ header: i18next.t('field.use-case'),
217
+ record: {
218
+ editable: false,
219
+ options: USECASE_OPTIONS
220
+ },
221
+ sortable: true,
222
+ filter: {
223
+ operator: 'eq',
224
+ options: USECASE_OPTIONS /* in case select options type is a function, filter should have its own options */
225
+ },
226
+ width: 80
227
+ },
228
+ {
229
+ type: 'crontab',
230
+ name: 'schedule',
231
+ label: true,
232
+ header: i18next.t('field.schedule'),
233
+ record: {
234
+ editable: false
235
+ },
236
+ width: 80,
237
+ label: true
238
+ },
239
+ {
240
+ type: 'resource-object',
241
+ name: 'entryRole',
242
+ header: i18next.t('field.entry-role'),
243
+ record: {
244
+ editable: false
245
+ },
246
+ width: 120
247
+ },
248
+ {
249
+ type: 'resource-object',
250
+ name: 'supervisoryRole',
251
+ header: i18next.t('field.supervisory-role'),
252
+ record: {
253
+ editable: false
254
+ },
255
+ width: 120
256
+ },
257
+ {
258
+ type: 'datetime',
259
+ name: 'latestCollectedAt',
260
+ label: true,
261
+ header: i18next.t('field.latest-collected-at'),
262
+ record: {
263
+ editable: false
264
+ },
265
+ width: 180
266
+ },
267
+ {
268
+ type: 'datetime',
269
+ name: 'prevSchedule',
270
+ label: true,
271
+ header: i18next.t('field.prev-schedule'),
272
+ record: {
273
+ editable: false
274
+ },
275
+ width: 180
276
+ },
277
+ {
278
+ type: 'datetime',
279
+ name: 'nextSchedule',
280
+ label: true,
281
+ header: i18next.t('field.next-schedule'),
282
+ record: {
283
+ editable: false
284
+ },
285
+ width: 180
286
+ },
287
+ {
288
+ type: 'string',
289
+ name: 'entryView',
290
+ hidden: true,
291
+ record: {
292
+ editable: false,
293
+ renderer: function (value, column, record, rowIndex, field) {
294
+ const type = record.entryType !== 'board' ? 'string' : 'image'
295
+ value = record.entryType !== 'board' ? value : record.entryBoard?.thumbnail
296
+
297
+ return getRenderer(type)(value, column, record, rowIndex, field)
298
+ }
299
+ }
300
+ }
301
+ ],
302
+ rows: {
303
+ selectable: {
304
+ multiple: false
305
+ },
306
+ handlers: {
307
+ click: showEntryView
308
+ },
309
+ classifier: function (record, rowIndex) {}
310
+ },
311
+ sorters: [
312
+ {
313
+ name: 'name'
314
+ }
315
+ ]
316
+ }
317
+ }
318
+
319
+ async fetchHandler({ page, limit, sortings = [], filters = [] }) {
320
+ const response = await client.query({
321
+ query: gql`
322
+ query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
323
+ responses: dataSetsForEntry(filters: $filters, pagination: $pagination, sortings: $sortings) {
324
+ items {
325
+ id
326
+ name
327
+ description
328
+ partitionKeys
329
+ active
330
+ type
331
+ useCase
332
+ schedule
333
+ timezone
334
+ entryRole {
335
+ id
336
+ name
337
+ }
338
+ supervisoryRole {
339
+ id
340
+ name
341
+ }
342
+ entryType
343
+ entryView
344
+ entryBoard {
345
+ thumbnail
346
+ }
347
+ monitorType
348
+ monitorView
349
+ updater {
350
+ id
351
+ name
352
+ }
353
+ reportType
354
+ reportView
355
+ updatedAt
356
+ dataItems {
357
+ name
358
+ description
359
+ sequence
360
+ active
361
+ tag
362
+ type
363
+ unit
364
+ options
365
+ quota
366
+ spec
367
+ }
368
+ latestCollectedAt
369
+ nextSchedule
370
+ prevSchedule
371
+ }
372
+ total
373
+ }
374
+ }
375
+ `,
376
+ variables: {
377
+ filters,
378
+ pagination: { page, limit },
379
+ sortings
380
+ }
381
+ })
382
+
383
+ return {
384
+ total: response.data.responses.total || 0,
385
+ records: response.data.responses.items || []
386
+ }
387
+ }
388
+ }
389
+
390
+ window.customElements.define('data-entry-list-page', DataEntryListPage)