@things-factory/dataset 5.0.0-alpha.2 → 5.0.0-alpha.20
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 +12 -0
- package/assets/data-samples.jpg +0 -0
- package/client/bootstrap.js +16 -1
- package/client/pages/data-entry-form.js +84 -0
- package/client/pages/data-item-list.js +58 -16
- package/client/pages/data-ooc-view.js +182 -0
- package/client/pages/data-ooc.js +469 -0
- package/client/pages/data-sample-view.js +97 -0
- package/client/pages/data-sample.js +130 -55
- package/client/pages/data-sensor.js +8 -18
- package/client/pages/data-set.js +126 -25
- package/client/route.js +4 -0
- package/dist-server/controllers/create-data-sample.js +122 -0
- package/dist-server/controllers/create-data-sample.js.map +1 -0
- package/dist-server/controllers/data-use-case.js +57 -0
- package/dist-server/controllers/data-use-case.js.map +1 -0
- package/dist-server/controllers/index.js +17 -0
- package/dist-server/controllers/index.js.map +1 -1
- package/dist-server/index.js +2 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/routes.js +9 -24
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/data-item/data-item-mutation.js +5 -1
- package/dist-server/service/data-item/data-item-mutation.js.map +1 -1
- package/dist-server/service/data-item/data-item-type.js +14 -5
- package/dist-server/service/data-item/data-item-type.js.map +1 -1
- package/dist-server/service/data-item/data-item.js +20 -7
- package/dist-server/service/data-item/data-item.js.map +1 -1
- package/dist-server/service/data-ooc/data-ooc-mutation.js +92 -0
- package/dist-server/service/data-ooc/data-ooc-mutation.js.map +1 -0
- package/dist-server/service/data-ooc/data-ooc-query.js +115 -0
- package/dist-server/service/data-ooc/data-ooc-query.js.map +1 -0
- package/dist-server/service/data-ooc/data-ooc-subscription.js +65 -0
- package/dist-server/service/data-ooc/data-ooc-subscription.js.map +1 -0
- package/dist-server/service/data-ooc/data-ooc-type.js +99 -0
- package/dist-server/service/data-ooc/data-ooc-type.js.map +1 -0
- package/dist-server/service/data-ooc/data-ooc.js +227 -0
- package/dist-server/service/data-ooc/data-ooc.js.map +1 -0
- package/dist-server/service/data-ooc/index.js +10 -0
- package/dist-server/service/data-ooc/index.js.map +1 -0
- package/dist-server/service/data-sample/data-sample-mutation.js +3 -105
- package/dist-server/service/data-sample/data-sample-mutation.js.map +1 -1
- package/dist-server/service/data-sample/data-sample-type.js +6 -43
- package/dist-server/service/data-sample/data-sample-type.js.map +1 -1
- package/dist-server/service/data-sample/data-sample.js +33 -12
- package/dist-server/service/data-sample/data-sample.js.map +1 -1
- package/dist-server/service/data-set/data-set-mutation.js +1 -2
- package/dist-server/service/data-set/data-set-mutation.js.map +1 -1
- package/dist-server/service/data-set/data-set-query.js +12 -0
- package/dist-server/service/data-set/data-set-query.js.map +1 -1
- package/dist-server/service/data-set/data-set-type.js +19 -2
- package/dist-server/service/data-set/data-set-type.js.map +1 -1
- package/dist-server/service/data-set/data-set.js +22 -10
- package/dist-server/service/data-set/data-set.js.map +1 -1
- package/dist-server/service/data-spec/data-spec-manager.js +20 -0
- package/dist-server/service/data-spec/data-spec-manager.js.map +1 -0
- package/dist-server/service/data-spec/data-spec-query.js +48 -0
- package/dist-server/service/data-spec/data-spec-query.js.map +1 -0
- package/dist-server/service/data-spec/data-spec.js +78 -0
- package/dist-server/service/data-spec/data-spec.js.map +1 -0
- package/dist-server/service/data-spec/index.js +8 -0
- package/dist-server/service/data-spec/index.js.map +1 -0
- package/dist-server/service/index.js +12 -4
- package/dist-server/service/index.js.map +1 -1
- package/package.json +15 -12
- package/server/controllers/create-data-sample.ts +161 -0
- package/server/controllers/data-use-case.ts +85 -0
- package/server/controllers/index.ts +1 -0
- package/server/index.ts +3 -0
- package/server/routes.ts +18 -32
- package/server/service/data-item/data-item-mutation.ts +6 -1
- package/server/service/data-item/data-item-type.ts +11 -7
- package/server/service/data-item/data-item.ts +16 -6
- package/server/service/data-ooc/data-ooc-mutation.ts +150 -0
- package/server/service/data-ooc/data-ooc-query.ts +63 -0
- package/server/service/data-ooc/data-ooc-subscription.ts +51 -0
- package/server/service/data-ooc/data-ooc-type.ts +62 -0
- package/server/service/data-ooc/data-ooc.ts +195 -0
- package/server/service/data-ooc/index.ts +7 -0
- package/server/service/data-sample/data-sample-mutation.ts +6 -128
- package/server/service/data-sample/data-sample-type.ts +4 -32
- package/server/service/data-sample/data-sample.ts +31 -10
- package/server/service/data-set/data-set-mutation.ts +1 -4
- package/server/service/data-set/data-set-query.ts +8 -1
- package/server/service/data-set/data-set-type.ts +17 -6
- package/server/service/data-set/data-set.ts +18 -8
- package/server/service/data-spec/data-spec-manager.ts +21 -0
- package/server/service/data-spec/data-spec-query.ts +21 -0
- package/server/service/data-spec/data-spec.ts +44 -0
- package/server/service/data-spec/index.ts +5 -0
- package/server/service/index.ts +16 -8
- package/things-factory.config.js +4 -0
- package/translations/en.json +20 -1
- package/translations/ko.json +21 -2
- package/translations/ms.json +20 -1
- package/translations/zh.json +20 -1
package/README.md
ADDED
@@ -0,0 +1,12 @@
|
|
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. Look at the below picture for understanding.
|
7
|
+
|
8
|
+

|
9
|
+
|
10
|
+
These tasks are related for S3 request limitations.
|
11
|
+
> __3,500 PUT/COPY/POST/DELETE or 5,500 GET/HEAD requests per second per prefix in a bucket__
|
12
|
+
- https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance.html
|
Binary file
|
package/client/bootstrap.js
CHANGED
@@ -1 +1,16 @@
|
|
1
|
-
|
1
|
+
import {
|
2
|
+
OxGristRendererJson5,
|
3
|
+
registerEditor as registerGristEditor,
|
4
|
+
registerRenderer as registerGristRenderer
|
5
|
+
} from '@operato/data-grist'
|
6
|
+
|
7
|
+
import { OxGristEditorDataItemSpec } from '@operato/dataset/grist-editor'
|
8
|
+
import { OxGristEditorPartitionKeys } from '@operato/app/grist-editor/ox-grist-editor-partition-keys.js'
|
9
|
+
|
10
|
+
export default function bootstrap() {
|
11
|
+
registerGristEditor('data-item-spec', OxGristEditorDataItemSpec)
|
12
|
+
registerGristRenderer('data-item-spec', OxGristRendererJson5)
|
13
|
+
|
14
|
+
registerGristEditor('partition-keys', OxGristEditorPartitionKeys)
|
15
|
+
registerGristRenderer('partition-keys', OxGristRendererJson5)
|
16
|
+
}
|
@@ -0,0 +1,84 @@
|
|
1
|
+
import '@operato/dataset/ox-data-entry-form.js'
|
2
|
+
|
3
|
+
import { LitElement, css, html } from 'lit'
|
4
|
+
import { i18next, localize } from '@operato/i18n'
|
5
|
+
|
6
|
+
import { client } from '@operato/graphql'
|
7
|
+
import gql from 'graphql-tag'
|
8
|
+
|
9
|
+
class DataEntryForm extends localize(i18next)(LitElement) {
|
10
|
+
static get properties() {
|
11
|
+
return {
|
12
|
+
dataSet: Object
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
static get styles() {
|
17
|
+
return [
|
18
|
+
css`
|
19
|
+
:host {
|
20
|
+
display: flex;
|
21
|
+
flex-direction: column;
|
22
|
+
|
23
|
+
background-color: #fff;
|
24
|
+
}
|
25
|
+
|
26
|
+
ox-data-entry-form {
|
27
|
+
flex: 1;
|
28
|
+
margin: 10px;
|
29
|
+
}
|
30
|
+
|
31
|
+
.button-container {
|
32
|
+
display: flex;
|
33
|
+
margin-left: auto;
|
34
|
+
padding: var(--padding-default);
|
35
|
+
}
|
36
|
+
`
|
37
|
+
]
|
38
|
+
}
|
39
|
+
|
40
|
+
get entryForm() {
|
41
|
+
return this.renderRoot.querySelector('ox-data-entry-form')
|
42
|
+
}
|
43
|
+
|
44
|
+
render() {
|
45
|
+
return html`
|
46
|
+
<ox-data-entry-form .dataSet=${this.dataSet}></ox-data-entry-form>
|
47
|
+
<div class="button-container">
|
48
|
+
<mwc-button raised @click=${this._updateDataItems.bind(this)}>${i18next.t('button.save')}</mwc-button>
|
49
|
+
</div>
|
50
|
+
`
|
51
|
+
}
|
52
|
+
|
53
|
+
async _updateDataItems() {
|
54
|
+
const data = this.entryForm.buildValue()
|
55
|
+
const dataSample = {
|
56
|
+
dataSet: {
|
57
|
+
id: this.dataSet.id
|
58
|
+
},
|
59
|
+
data
|
60
|
+
}
|
61
|
+
|
62
|
+
const response = await client.mutate({
|
63
|
+
mutation: gql`
|
64
|
+
mutation ($dataSample: NewDataSample!) {
|
65
|
+
createDataSample(dataSample: $dataSample) {
|
66
|
+
id
|
67
|
+
collectedAt
|
68
|
+
}
|
69
|
+
}
|
70
|
+
`,
|
71
|
+
variables: {
|
72
|
+
dataSample
|
73
|
+
}
|
74
|
+
})
|
75
|
+
|
76
|
+
if (!response.errors) {
|
77
|
+
document.dispatchEvent(
|
78
|
+
new CustomEvent('notify', { detail: { message: i18next.t('text.data sample created successfully') } })
|
79
|
+
)
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
window.customElements.define('data-entry-form', DataEntryForm)
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import
|
2
|
-
import {
|
1
|
+
import { LitElement, css, html } from 'lit'
|
2
|
+
import { i18next, localize } from '@operato/i18n'
|
3
3
|
|
4
4
|
import { client } from '@operato/graphql'
|
5
|
-
import
|
5
|
+
import gql from 'graphql-tag'
|
6
6
|
import { isMobileDevice } from '@operato/utils'
|
7
7
|
|
8
8
|
class DataItemList extends localize(i18next)(LitElement) {
|
@@ -33,9 +33,6 @@ class DataItemList extends localize(i18next)(LitElement) {
|
|
33
33
|
padding: var(--padding-default);
|
34
34
|
}
|
35
35
|
|
36
|
-
form {
|
37
|
-
position: relative;
|
38
|
-
}
|
39
36
|
[danger] {
|
40
37
|
--mdc-theme-primary: var(--mdc-danger-button-primary-color);
|
41
38
|
}
|
@@ -46,7 +43,7 @@ class DataItemList extends localize(i18next)(LitElement) {
|
|
46
43
|
]
|
47
44
|
}
|
48
45
|
|
49
|
-
get
|
46
|
+
get grist() {
|
50
47
|
return this.renderRoot.querySelector('ox-grist')
|
51
48
|
}
|
52
49
|
|
@@ -64,8 +61,6 @@ class DataItemList extends localize(i18next)(LitElement) {
|
|
64
61
|
`
|
65
62
|
}
|
66
63
|
|
67
|
-
async updated(changedProps) {}
|
68
|
-
|
69
64
|
async firstUpdated() {
|
70
65
|
this.gristConfig = {
|
71
66
|
list: { fields: ['name', 'description', 'active'] },
|
@@ -149,7 +144,44 @@ class DataItemList extends localize(i18next)(LitElement) {
|
|
149
144
|
name: 'type',
|
150
145
|
header: i18next.t('field.type'),
|
151
146
|
record: {
|
152
|
-
options: ['number', 'text', 'select', 'boolean'],
|
147
|
+
options: ['', 'number', 'text', 'select', 'boolean', 'file'],
|
148
|
+
editable: true
|
149
|
+
},
|
150
|
+
width: 120
|
151
|
+
},
|
152
|
+
{
|
153
|
+
type: 'parameters',
|
154
|
+
name: 'options',
|
155
|
+
header: i18next.t('field.options'),
|
156
|
+
record: {
|
157
|
+
editable: true,
|
158
|
+
renderer: 'json5',
|
159
|
+
options: async (value, column, record, row, field) => {
|
160
|
+
return {
|
161
|
+
name: record.type,
|
162
|
+
help: '',
|
163
|
+
spec:
|
164
|
+
record.type === 'select'
|
165
|
+
? [
|
166
|
+
{
|
167
|
+
type: 'options' /* property-editor type */,
|
168
|
+
name: 'options',
|
169
|
+
label: 'options'
|
170
|
+
}
|
171
|
+
]
|
172
|
+
: [],
|
173
|
+
context: this.grist,
|
174
|
+
objectified: true
|
175
|
+
}
|
176
|
+
}
|
177
|
+
},
|
178
|
+
width: 120
|
179
|
+
},
|
180
|
+
{
|
181
|
+
type: 'string',
|
182
|
+
name: 'unit',
|
183
|
+
header: i18next.t('field.unit'),
|
184
|
+
record: {
|
153
185
|
editable: true
|
154
186
|
},
|
155
187
|
width: 120
|
@@ -164,11 +196,16 @@ class DataItemList extends localize(i18next)(LitElement) {
|
|
164
196
|
width: 60
|
165
197
|
},
|
166
198
|
{
|
167
|
-
type: '
|
199
|
+
type: 'data-item-spec',
|
168
200
|
name: 'spec',
|
169
201
|
header: i18next.t('field.spec'),
|
170
202
|
record: {
|
171
|
-
editable: true
|
203
|
+
editable: true,
|
204
|
+
options: {
|
205
|
+
name: '',
|
206
|
+
help: '',
|
207
|
+
objectified: true /* prevent from stringifying */
|
208
|
+
}
|
172
209
|
},
|
173
210
|
width: 200
|
174
211
|
}
|
@@ -207,7 +244,10 @@ class DataItemList extends localize(i18next)(LitElement) {
|
|
207
244
|
description
|
208
245
|
sequence
|
209
246
|
active
|
247
|
+
tag
|
210
248
|
type
|
249
|
+
options
|
250
|
+
unit
|
211
251
|
quota
|
212
252
|
spec
|
213
253
|
}
|
@@ -224,7 +264,7 @@ class DataItemList extends localize(i18next)(LitElement) {
|
|
224
264
|
}
|
225
265
|
|
226
266
|
async _updateDataItems() {
|
227
|
-
let patches = this.
|
267
|
+
let patches = this.grist._data.records
|
228
268
|
if (patches && patches.length) {
|
229
269
|
patches = patches.map(patch => {
|
230
270
|
var patchField = {}
|
@@ -250,14 +290,16 @@ class DataItemList extends localize(i18next)(LitElement) {
|
|
250
290
|
}
|
251
291
|
})
|
252
292
|
|
253
|
-
if (!response.errors)
|
293
|
+
if (!response.errors) {
|
294
|
+
this.grist.fetch()
|
295
|
+
}
|
254
296
|
}
|
255
297
|
}
|
256
298
|
|
257
299
|
async _deleteDataItems() {
|
258
300
|
if (!confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) return
|
259
301
|
|
260
|
-
const ids = this.
|
302
|
+
const ids = this.grist.selected.map(record => record.id)
|
261
303
|
if (!(ids && ids.length > 0)) return
|
262
304
|
|
263
305
|
const response = await client.mutate({
|
@@ -273,7 +315,7 @@ class DataItemList extends localize(i18next)(LitElement) {
|
|
273
315
|
|
274
316
|
if (response.errors) return
|
275
317
|
|
276
|
-
this.
|
318
|
+
this.grist.fetch()
|
277
319
|
await document.dispatchEvent(
|
278
320
|
new CustomEvent('notify', {
|
279
321
|
detail: {
|
@@ -0,0 +1,182 @@
|
|
1
|
+
import '@operato/dataset/ox-data-ooc-view.js'
|
2
|
+
|
3
|
+
import { LitElement, css, html } from 'lit'
|
4
|
+
import { i18next, localize } from '@operato/i18n'
|
5
|
+
|
6
|
+
import { ScrollbarStyles } from '@operato/styles'
|
7
|
+
import { client } from '@operato/graphql'
|
8
|
+
import gql from 'graphql-tag'
|
9
|
+
|
10
|
+
class DataOocView extends localize(i18next)(LitElement) {
|
11
|
+
static get styles() {
|
12
|
+
return [
|
13
|
+
ScrollbarStyles,
|
14
|
+
css`
|
15
|
+
:host {
|
16
|
+
display: flex;
|
17
|
+
flex-direction: column;
|
18
|
+
|
19
|
+
background-color: #fff;
|
20
|
+
}
|
21
|
+
|
22
|
+
div[content] {
|
23
|
+
flex: 1;
|
24
|
+
|
25
|
+
display: flex;
|
26
|
+
overflow: auto;
|
27
|
+
}
|
28
|
+
|
29
|
+
ox-data-ooc-view {
|
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);
|
54
|
+
}
|
55
|
+
|
56
|
+
.button-container {
|
57
|
+
display: flex;
|
58
|
+
margin-left: auto;
|
59
|
+
padding: var(--padding-default);
|
60
|
+
}
|
61
|
+
`
|
62
|
+
]
|
63
|
+
}
|
64
|
+
|
65
|
+
static get properties() {
|
66
|
+
return {
|
67
|
+
dataSet: Object,
|
68
|
+
dataOoc: Object
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
get sampleView() {
|
73
|
+
return this.renderRoot.querySelector('ox-data-ooc-view')
|
74
|
+
}
|
75
|
+
|
76
|
+
render() {
|
77
|
+
const state = this.dataOoc.state
|
78
|
+
|
79
|
+
return html`
|
80
|
+
<div content>
|
81
|
+
<ox-data-ooc-view .dataSet=${this.dataSet} .dataOoc=${this.dataOoc}></ox-data-ooc-view>
|
82
|
+
</div>
|
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
|
+
|
93
|
+
<div class="button-container">
|
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``}
|
103
|
+
</div>
|
104
|
+
`
|
105
|
+
}
|
106
|
+
|
107
|
+
updated(changes) {
|
108
|
+
if (changes.has('dataOoc')) {
|
109
|
+
this.fetchDataSet()
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
async fetchDataSet() {
|
114
|
+
const id = this.dataOoc?.dataSet?.id
|
115
|
+
|
116
|
+
if (id) {
|
117
|
+
const response = await client.query({
|
118
|
+
query: gql`
|
119
|
+
query ($id: String!) {
|
120
|
+
dataSet(id: $id) {
|
121
|
+
id
|
122
|
+
name
|
123
|
+
description
|
124
|
+
useCase
|
125
|
+
dataItems {
|
126
|
+
id
|
127
|
+
name
|
128
|
+
description
|
129
|
+
active
|
130
|
+
unit
|
131
|
+
tag
|
132
|
+
type
|
133
|
+
spec
|
134
|
+
}
|
135
|
+
}
|
136
|
+
}
|
137
|
+
`,
|
138
|
+
variables: {
|
139
|
+
id: this.dataOoc.dataSet.id
|
140
|
+
}
|
141
|
+
})
|
142
|
+
|
143
|
+
this.dataSet = response.data.dataSet
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
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
|
+
}
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
window.customElements.define('data-ooc-view', DataOocView)
|