@things-factory/dataset 5.0.0-alpha.19 → 5.0.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # dataset
2
+ ## partition keys
3
+ 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'.
4
+ Now partition keys are fixed with some cases. Default is daily dataset, which has S3 Key like 'domain={domain}/datasetid={datasetid}/year=2022/month=3/day=25'. It will be set default with empty value in 'data-sets'.
5
+
6
+ In another case, it is necessary to divide by hours or minutes and store them. This datetime item must be included in the S3 key. It will be required a new Glue Crawler and a Glue Catalog Table. For example if you need to separate directory hourly, you should add "%H" for 'hour' to partition_keys for this. and also should add a new crawler. And it would be needed a column to know it is daily or hourly or minutely for reporting client side. It's not developed yet.
7
+ Look at the below picture for understanding.
8
+
9
+ ![Architecture for partitioning](./assets/data-samples.jpg)
10
+
11
+ These tasks are related for S3 request limitations.
12
+ > __3,500 PUT/COPY/POST/DELETE or 5,500 GET/HEAD requests per second per prefix in a bucket__
13
+ - https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance.html
Binary file
@@ -290,7 +290,9 @@ class DataItemList extends localize(i18next)(LitElement) {
290
290
  }
291
291
  })
292
292
 
293
- if (!response.errors) this.grist.fetch()
293
+ if (!response.errors) {
294
+ this.grist.fetch()
295
+ }
294
296
  }
295
297
  }
296
298
 
@@ -1,4 +1,4 @@
1
- import '@operato/dataset/ox-data-sample-view.js'
1
+ import '@operato/dataset/ox-data-ooc-view.js'
2
2
 
3
3
  import { LitElement, css, html } from 'lit'
4
4
  import { i18next, localize } from '@operato/i18n'
@@ -8,13 +8,6 @@ import { client } from '@operato/graphql'
8
8
  import gql from 'graphql-tag'
9
9
 
10
10
  class DataOocView extends localize(i18next)(LitElement) {
11
- static get properties() {
12
- return {
13
- dataSet: Object,
14
- dataSample: Object
15
- }
16
- }
17
-
18
11
  static get styles() {
19
12
  return [
20
13
  ScrollbarStyles,
@@ -30,11 +23,34 @@ class DataOocView extends localize(i18next)(LitElement) {
30
23
  flex: 1;
31
24
 
32
25
  display: flex;
33
- overflow: scroll;
26
+ overflow: auto;
34
27
  }
35
28
 
36
- ox-data-sample-view {
29
+ ox-data-ooc-view {
37
30
  flex: 1;
31
+ padding: var(--padding-wide);
32
+ }
33
+
34
+ label[comment] {
35
+ display: flex;
36
+ flex-direction: column;
37
+
38
+ padding: var(--padding-wide);
39
+ }
40
+
41
+ label[comment] div {
42
+ display: flex;
43
+ }
44
+
45
+ mwc-icon {
46
+ color: var(--status-danger-color);
47
+ }
48
+
49
+ textarea {
50
+ border: var(--input-field-border);
51
+ border-radius: var(--input-border-radius);
52
+ padding: var(--input-field-padding);
53
+ font: var(--input-field-font);
38
54
  }
39
55
 
40
56
  .button-container {
@@ -46,30 +62,56 @@ class DataOocView extends localize(i18next)(LitElement) {
46
62
  ]
47
63
  }
48
64
 
65
+ static get properties() {
66
+ return {
67
+ dataSet: Object,
68
+ dataOoc: Object
69
+ }
70
+ }
71
+
49
72
  get sampleView() {
50
- return this.renderRoot.querySelector('ox-data-sample-view')
73
+ return this.renderRoot.querySelector('ox-data-ooc-view')
51
74
  }
52
75
 
53
76
  render() {
77
+ const state = this.dataOoc.state
78
+
54
79
  return html`
55
80
  <div content>
56
- <ox-data-sample-view .dataSet=${this.dataSet} .dataSample=${this.dataSample}></ox-data-sample-view>
81
+ <ox-data-ooc-view .dataSet=${this.dataSet} .dataOoc=${this.dataOoc}></ox-data-ooc-view>
57
82
  </div>
58
83
 
84
+ ${state === 'CREATED' || state === 'REVIEWED'
85
+ ? html`
86
+ <label comment>
87
+ <div><mwc-icon>build_circle</mwc-icon> <span>correction activity</span></div>
88
+ <textarea placeholder="조치 내용을 입력해주세요."></textarea>
89
+ </label>
90
+ `
91
+ : html``}
92
+
59
93
  <div class="button-container">
60
- <mwc-button raised @click=${this._updateDataSample.bind(this)}>${i18next.t('button.save')}</mwc-button>
94
+ ${state === 'CREATED'
95
+ ? html`<mwc-button raised @click=${() => this._processOoc('REVIEWED')}
96
+ >${i18next.t('button.reviewed')}</mwc-button
97
+ >`
98
+ : state === 'REVIEWED'
99
+ ? html`<mwc-button raised @click=${() => this._processOoc('CORRECTED')}
100
+ >${i18next.t('button.corrected')}</mwc-button
101
+ >`
102
+ : html``}
61
103
  </div>
62
104
  `
63
105
  }
64
106
 
65
107
  updated(changes) {
66
- if (changes.has('dataSample')) {
108
+ if (changes.has('dataOoc')) {
67
109
  this.fetchDataSet()
68
110
  }
69
111
  }
70
112
 
71
113
  async fetchDataSet() {
72
- const id = this.dataSample?.dataSet?.id
114
+ const id = this.dataOoc?.dataSet?.id
73
115
 
74
116
  if (id) {
75
117
  const response = await client.query({
@@ -94,7 +136,7 @@ class DataOocView extends localize(i18next)(LitElement) {
94
136
  }
95
137
  `,
96
138
  variables: {
97
- id: this.dataSample.dataSet.id
139
+ id: this.dataOoc.dataSet.id
98
140
  }
99
141
  })
100
142
 
@@ -102,32 +144,38 @@ class DataOocView extends localize(i18next)(LitElement) {
102
144
  }
103
145
  }
104
146
 
105
- async _updateDataSample() {
106
- // const data = this.sampleView.buildValue()
107
- // const dataSample = {
108
- // dataSet: {
109
- // id: this.dataSet.id
110
- // },
111
- // data
112
- // }
113
- // const response = await client.mutate({
114
- // mutation: gql`
115
- // mutation ($dataSample: NewDataSample!) {
116
- // createDataSample(dataSample: $dataSample) {
117
- // id
118
- // collectedAt
119
- // }
120
- // }
121
- // `,
122
- // variables: {
123
- // dataSample
124
- // }
125
- // })
126
- // if (!response.errors) {
127
- // document.dispatchEvent(
128
- // new CustomEvent('notify', { detail: { message: i18next.t('text.data sample created successfully') } })
129
- // )
130
- // }
147
+ async _processOoc(state) {
148
+ const commentTextArea = this.renderRoot.querySelector('textarea')
149
+ const comment = commentTextArea && commentTextArea.value
150
+ if (!comment || !comment.trim()) {
151
+ commentTextArea.focus()
152
+ return
153
+ }
154
+
155
+ const patch = {
156
+ state,
157
+ correctiveAction: comment
158
+ }
159
+
160
+ const response = await client.mutate({
161
+ mutation: gql`
162
+ mutation ($id: String!, $patch: DataOocPatch!) {
163
+ updateDataOoc(id: $id, patch: $patch) {
164
+ id
165
+ }
166
+ }
167
+ `,
168
+ variables: {
169
+ id: this.dataOoc.id,
170
+ patch
171
+ }
172
+ })
173
+
174
+ if (!response.errors) {
175
+ document.dispatchEvent(
176
+ new CustomEvent('notify', { detail: { message: i18next.t('text.data ooc updated successfully') } })
177
+ )
178
+ }
131
179
  }
132
180
  }
133
181
 
@@ -56,11 +56,11 @@ export class DataOoc extends connect(store)(localize(i18next)(PageView)) {
56
56
  title: i18next.t('title.data-ooc list'),
57
57
  help: 'integration/ui/data-ooc',
58
58
  actions: [
59
- {
60
- title: i18next.t('button.save'),
61
- action: this._updateDataOoc.bind(this),
62
- ...CommonButtonStyles.save
63
- }
59
+ // {
60
+ // title: i18next.t('button.save'),
61
+ // action: this._updateDataOoc.bind(this),
62
+ // ...CommonButtonStyles.save
63
+ // }
64
64
  ],
65
65
  exportable: {
66
66
  name: i18next.t('title.data-ooc list'),
@@ -124,14 +124,17 @@ export class DataOoc extends connect(store)(localize(i18next)(PageView)) {
124
124
  icon: 'assignment_turned_in',
125
125
  handlers: {
126
126
  click: (columns, data, column, record, rowIndex) => {
127
- openPopup(
128
- html` <data-ooc-view .dataSample=${record} style="background-color: white;"></data-ooc-view> `,
127
+ const popup = openPopup(
128
+ html` <data-ooc-view .dataOoc=${record} style="background-color: white;"></data-ooc-view> `,
129
129
  {
130
130
  backdrop: true,
131
131
  size: 'large',
132
132
  title: i18next.t('title.data-ooc view')
133
133
  }
134
134
  )
135
+ popup.onclosed = () => {
136
+ this.grist.fetch()
137
+ }
135
138
  }
136
139
  }
137
140
  },
@@ -160,6 +163,12 @@ export class DataOoc extends connect(store)(localize(i18next)(PageView)) {
160
163
  width: 150,
161
164
  imex: true
162
165
  },
166
+ {
167
+ type: 'string',
168
+ name: 'history',
169
+ hidden: true,
170
+ imex: true
171
+ },
163
172
  {
164
173
  type: 'checkbox',
165
174
  name: 'ooc',
@@ -179,14 +188,16 @@ export class DataOoc extends connect(store)(localize(i18next)(PageView)) {
179
188
  width: 30
180
189
  },
181
190
  {
182
- type: 'string',
191
+ type: 'select',
183
192
  name: 'state',
184
193
  label: true,
185
194
  header: i18next.t('field.state'),
186
195
  record: {
187
- editable: false
196
+ editable: false,
197
+ options: ['', 'CREATED', 'REVIEWED', 'CORRECTED']
188
198
  },
189
- width: 150,
199
+ width: 100,
200
+ filter: true,
190
201
  imex: true
191
202
  },
192
203
  {
@@ -211,17 +222,6 @@ export class DataOoc extends connect(store)(localize(i18next)(PageView)) {
211
222
  width: 120,
212
223
  imex: true
213
224
  },
214
- {
215
- type: 'resource-object',
216
- name: 'dataSample',
217
- header: i18next.t('field.data-sample'),
218
- record: {
219
- editable: false
220
- },
221
- sortable: true,
222
- width: 120,
223
- imex: true
224
- },
225
225
  {
226
226
  type: 'json5',
227
227
  name: 'partitionKeys',
@@ -338,6 +338,7 @@ export class DataOoc extends connect(store)(localize(i18next)(PageView)) {
338
338
  spec
339
339
  ooc
340
340
  oos
341
+ history
341
342
  correctiveAction
342
343
  correctedAt
343
344
  corrector {
@@ -368,62 +369,62 @@ export class DataOoc extends connect(store)(localize(i18next)(PageView)) {
368
369
  }
369
370
  }
370
371
 
371
- async _updateDataOoc() {
372
- let patches = this.grist.dirtyRecords
373
- if (patches && patches.length) {
374
- patches = patches.map(patch => {
375
- let patchField = patch.id ? { id: patch.id } : {}
376
- const dirtyFields = patch.__dirtyfields__
377
- for (let key in dirtyFields) {
378
- patchField[key] = dirtyFields[key].after
379
- }
380
- this._setDefaultFieldsValue(patchField)
381
- patchField.cuFlag = patch.__dirty__
382
-
383
- return patchField
384
- })
385
-
386
- const response = await client.mutate({
387
- mutation: gql`
388
- mutation ($patches: [DataOocPatch!]!) {
389
- updateMultipleDataOoc(patches: $patches) {
390
- name
391
- }
392
- }
393
- `,
394
- variables: {
395
- patches
396
- }
397
- })
398
-
399
- if (!response.errors) this.grist.fetch()
400
- }
401
- }
402
-
403
- async _deleteDataOoc() {
404
- if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {
405
- const ids = this.grist.selected.map(record => record.id)
406
- if (ids && ids.length > 0) {
407
- const response = await client.mutate({
408
- mutation: gql`
409
- mutation ($ids: [String!]!) {
410
- deleteDataOocs(ids: $ids)
411
- }
412
- `,
413
- variables: {
414
- ids
415
- }
416
- })
417
-
418
- if (!response.errors) {
419
- this.grist.fetch()
420
- notify({
421
- message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })
422
- })
423
- }
424
- }
425
- }
426
- }
372
+ // async _updateDataOoc() {
373
+ // let patches = this.grist.dirtyRecords
374
+ // if (patches && patches.length) {
375
+ // patches = patches.map(patch => {
376
+ // let patchField = patch.id ? { id: patch.id } : {}
377
+ // const dirtyFields = patch.__dirtyfields__
378
+ // for (let key in dirtyFields) {
379
+ // patchField[key] = dirtyFields[key].after
380
+ // }
381
+ // this._setDefaultFieldsValue(patchField)
382
+ // patchField.cuFlag = patch.__dirty__
383
+
384
+ // return patchField
385
+ // })
386
+
387
+ // const response = await client.mutate({
388
+ // mutation: gql`
389
+ // mutation ($patches: [DataOocPatch!]!) {
390
+ // updateMultipleDataOoc(patches: $patches) {
391
+ // name
392
+ // }
393
+ // }
394
+ // `,
395
+ // variables: {
396
+ // patches
397
+ // }
398
+ // })
399
+
400
+ // if (!response.errors) this.grist.fetch()
401
+ // }
402
+ // }
403
+
404
+ // async _deleteDataOoc() {
405
+ // if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {
406
+ // const ids = this.grist.selected.map(record => record.id)
407
+ // if (ids && ids.length > 0) {
408
+ // const response = await client.mutate({
409
+ // mutation: gql`
410
+ // mutation ($ids: [String!]!) {
411
+ // deleteDataOocs(ids: $ids)
412
+ // }
413
+ // `,
414
+ // variables: {
415
+ // ids
416
+ // }
417
+ // })
418
+
419
+ // if (!response.errors) {
420
+ // this.grist.fetch()
421
+ // notify({
422
+ // message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })
423
+ // })
424
+ // }
425
+ // }
426
+ // }
427
+ // }
427
428
 
428
429
  _exportableData() {
429
430
  let records = []
@@ -30,11 +30,12 @@ class DataSampleView extends localize(i18next)(LitElement) {
30
30
  flex: 1;
31
31
 
32
32
  display: flex;
33
- overflow: scroll;
33
+ overflow: auto;
34
34
  }
35
35
 
36
36
  ox-data-sample-view {
37
37
  flex: 1;
38
+ padding: var(--padding-wide);
38
39
  }
39
40
  `
40
41
  ]
@@ -153,6 +153,7 @@ export class DataSensor extends connect(store)(localize(i18next)(PageView)) {
153
153
  editable: true
154
154
  },
155
155
  sortable: true,
156
+ filter: true,
156
157
  width: 60
157
158
  },
158
159
  {
@@ -176,6 +177,7 @@ export class DataSensor extends connect(store)(localize(i18next)(PageView)) {
176
177
  editable: true
177
178
  },
178
179
  sortable: true,
180
+ filter: 'search',
179
181
  width: 150
180
182
  },
181
183
  {