@operato/dataset 2.0.0-alpha.2 → 2.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/CHANGELOG.md +162 -0
- package/demo/favicon.ico +0 -0
- package/demo/index.html +338 -0
- package/demo/ox-data-ooc-brief-view-test.html +338 -0
- package/dist/src/ox-data-entry-view.js +2 -1
- package/dist/src/ox-data-entry-view.js.map +1 -1
- package/dist/src/ox-data-ooc-badge.d.ts +9 -0
- package/dist/src/ox-data-ooc-badge.js +66 -0
- package/dist/src/ox-data-ooc-badge.js.map +1 -0
- package/dist/src/ox-data-ooc-brief-view.d.ts +2 -0
- package/dist/src/ox-data-ooc-brief-view.js +8 -110
- package/dist/src/ox-data-ooc-brief-view.js.map +1 -1
- package/dist/src/ox-data-ooc-correction-part.d.ts +9 -0
- package/dist/src/ox-data-ooc-correction-part.js +99 -0
- package/dist/src/ox-data-ooc-correction-part.js.map +1 -0
- package/dist/src/ox-data-ooc-history.d.ts +10 -0
- package/dist/src/ox-data-ooc-history.js +72 -0
- package/dist/src/ox-data-ooc-history.js.map +1 -0
- package/dist/src/ox-data-ooc-view.d.ts +1 -0
- package/dist/src/ox-data-ooc-view.js +6 -89
- package/dist/src/ox-data-ooc-view.js.map +1 -1
- package/dist/src/ox-data-sample-subgroup-view.js +1 -1
- package/dist/src/ox-data-sample-subgroup-view.js.map +1 -1
- package/dist/src/ox-data-sample-view.js +41 -30
- package/dist/src/ox-data-sample-view.js.map +1 -1
- package/dist/src/ox-data-summary-view.js +1 -1
- package/dist/src/ox-data-summary-view.js.map +1 -1
- package/dist/src/types.d.ts +57 -9
- package/dist/src/types.js.map +1 -1
- package/dist/src/usecase/spc/index.d.ts +1 -0
- package/dist/src/usecase/spc/index.js +8 -0
- package/dist/src/usecase/spc/index.js.map +1 -0
- package/dist/src/usecase/spc/ox-data-use-case-spc.d.ts +7 -0
- package/dist/src/usecase/spc/ox-data-use-case-spc.js +102 -0
- package/dist/src/usecase/spc/ox-data-use-case-spc.js.map +1 -0
- package/dist/src/usecase/spc/ox-input-spc-limits.d.ts +44 -0
- package/dist/src/usecase/spc/ox-input-spc-limits.js +193 -0
- package/dist/src/usecase/spc/ox-input-spc-limits.js.map +1 -0
- package/dist/src/usecase/spc/ox-property-editor-spc-limits.d.ts +6 -0
- package/dist/src/usecase/spc/ox-property-editor-spc-limits.js +24 -0
- package/dist/src/usecase/spc/ox-property-editor-spc-limits.js.map +1 -0
- package/dist/stories/ox-data-ooc-view.stories.js +2 -0
- package/dist/stories/ox-data-ooc-view.stories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +24 -9
- package/src/ox-data-entry-view.ts +2 -1
- package/src/ox-data-ooc-badge.ts +64 -0
- package/src/ox-data-ooc-brief-view.ts +9 -120
- package/src/ox-data-ooc-correction-part.ts +107 -0
- package/src/ox-data-ooc-history.ts +74 -0
- package/src/ox-data-ooc-view.ts +6 -91
- package/src/ox-data-sample-subgroup-view.ts +1 -1
- package/src/ox-data-sample-view.ts +41 -30
- package/src/ox-data-summary-view.ts +1 -1
- package/src/types.ts +76 -27
- package/src/usecase/spc/index.ts +10 -0
- package/src/usecase/spc/ox-data-use-case-spc.ts +147 -0
- package/src/usecase/spc/ox-input-spc-limits.ts +182 -0
- package/src/usecase/spc/ox-property-editor-spc-limits.ts +23 -0
- package/stories/ox-data-ooc-view.stories.ts +2 -0
- package/themes/grist-theme.css +1 -1
- package/translations/en.json +1 -0
- package/translations/ko.json +1 -0
- package/translations/ms.json +142 -70
- package/translations/zh.json +146 -75
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '@operato/input/ox-input-file.js'
|
|
2
2
|
import './ox-data-sample-subgroup-view.js'
|
|
3
3
|
|
|
4
|
-
import { css, html, LitElement } from 'lit'
|
|
4
|
+
import { css, html, LitElement, nothing } from 'lit'
|
|
5
5
|
import { customElement, property } from 'lit/decorators.js'
|
|
6
6
|
|
|
7
7
|
import { i18next } from '@operato/i18n'
|
|
@@ -58,6 +58,7 @@ export class OxDataSampleView extends LitElement {
|
|
|
58
58
|
font: var(--th-font);
|
|
59
59
|
color: var(--th-color);
|
|
60
60
|
text-align: left;
|
|
61
|
+
white-space: nowrap;
|
|
61
62
|
}
|
|
62
63
|
th[item] {
|
|
63
64
|
min-width: 100px;
|
|
@@ -94,6 +95,12 @@ export class OxDataSampleView extends LitElement {
|
|
|
94
95
|
pre {
|
|
95
96
|
tab-size: 2;
|
|
96
97
|
}
|
|
98
|
+
|
|
99
|
+
@media print {
|
|
100
|
+
:host {
|
|
101
|
+
display: block;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
97
104
|
`
|
|
98
105
|
|
|
99
106
|
@property({ type: Object }) dataSample?: DataSample
|
|
@@ -128,36 +135,40 @@ export class OxDataSampleView extends LitElement {
|
|
|
128
135
|
</p>
|
|
129
136
|
|
|
130
137
|
<form>
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
138
|
+
${nonGroupDataItems.length > 0
|
|
139
|
+
? html`
|
|
140
|
+
<table>
|
|
141
|
+
<tr>
|
|
142
|
+
<th item>${i18next.t('field.item')}</th>
|
|
143
|
+
<th>${i18next.t('field.description')}</th>
|
|
144
|
+
<th>${i18next.t('field.finalizing-function')}</th>
|
|
145
|
+
<th>${i18next.t('field.unit')}</th>
|
|
146
|
+
<th value>${i18next.t('field.value')}</th>
|
|
147
|
+
<th>${i18next.t('field.spec')}</th>
|
|
148
|
+
<th>${i18next.t('field.ooc')}</th>
|
|
149
|
+
<th>${i18next.t('field.oos')}</th>
|
|
150
|
+
</tr>
|
|
151
|
+
${nonGroupDataItems.map(dataItem => {
|
|
152
|
+
const { name = '', tag = '', description = '', stat, unit = '', spec = {}, type } = dataItem
|
|
153
|
+
const value = data[tag]
|
|
154
|
+
const { ooc, oos } = judgment?.[tag] || {}
|
|
155
|
+
|
|
156
|
+
return html`
|
|
157
|
+
<tr ?ooc=${ooc} ?oos=${oos}>
|
|
158
|
+
<td name>${name}</td>
|
|
159
|
+
<td>${description}</td>
|
|
160
|
+
<td>${stat}</td>
|
|
161
|
+
<td>${unit}</td>
|
|
162
|
+
<td>${this.buildValue(type, value)}</td>
|
|
163
|
+
<td><pre>${this.buildSpec(useCaseNames, spec)}</pre></td>
|
|
164
|
+
<td>${ooc ? html`<mwc-icon>done</mwc-icon>` : ''}</td>
|
|
165
|
+
<td>${oos ? html`<mwc-icon>done</mwc-icon>` : ''}</td>
|
|
166
|
+
</tr>
|
|
167
|
+
`
|
|
168
|
+
})}
|
|
169
|
+
</table>
|
|
158
170
|
`
|
|
159
|
-
}
|
|
160
|
-
</table>
|
|
171
|
+
: nothing}
|
|
161
172
|
${Object.keys(dataItemSubgroups).map(subgroup => {
|
|
162
173
|
return html`
|
|
163
174
|
<ox-data-sample-subgroup-view
|
|
@@ -116,7 +116,7 @@ export class OxDataSummaryView extends LitElement {
|
|
|
116
116
|
<tr>
|
|
117
117
|
<th item>${i18next.t('field.item')}</th>
|
|
118
118
|
<th>${i18next.t('field.description')}</th>
|
|
119
|
-
<th>${i18next.t('field.
|
|
119
|
+
<th>${i18next.t('field.finalizing-function')}</th>
|
|
120
120
|
<th>${i18next.t('field.unit')}</th>
|
|
121
121
|
<th value>${i18next.t('field.value')}</th>
|
|
122
122
|
<th>${i18next.t('field.spec')}</th>
|
package/src/types.ts
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Represents a selectable option with a text label and a value.
|
|
3
|
+
*/
|
|
4
|
+
export type SelectOption = {
|
|
5
|
+
text: string
|
|
6
|
+
value: string
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* An array of selectable options.
|
|
10
|
+
*/
|
|
2
11
|
export type SelectOptions = SelectOption[]
|
|
12
|
+
/**
|
|
13
|
+
* Defines the options and additional properties for a type.
|
|
14
|
+
*/
|
|
3
15
|
export type TypeOptions = {
|
|
4
16
|
options?: SelectOptions
|
|
5
17
|
[prop: string]: any
|
|
6
18
|
}
|
|
7
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Describes the structure and properties of a data item.
|
|
21
|
+
*/
|
|
8
22
|
export type DataItem = {
|
|
9
23
|
name: string
|
|
10
24
|
description: string
|
|
@@ -24,7 +38,9 @@ export type DataItem = {
|
|
|
24
38
|
}
|
|
25
39
|
}
|
|
26
40
|
}
|
|
27
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Defines the structure of a dataset, including its name, description, type, use case, and data items.
|
|
43
|
+
*/
|
|
28
44
|
export type DataSet = {
|
|
29
45
|
name: string
|
|
30
46
|
description: string
|
|
@@ -32,59 +48,82 @@ export type DataSet = {
|
|
|
32
48
|
useCase: string
|
|
33
49
|
active: boolean
|
|
34
50
|
dataItems: DataItem[]
|
|
35
|
-
spec: {
|
|
51
|
+
spec: {
|
|
52
|
+
[dataItem: string]: {
|
|
53
|
+
[useCase: string]: any
|
|
54
|
+
}
|
|
55
|
+
}
|
|
36
56
|
}
|
|
37
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Describes the definition of a data specification, including its type, label, name, and optional properties.
|
|
59
|
+
*/
|
|
38
60
|
export type DataSpecDefinition = {
|
|
39
61
|
type: string
|
|
40
62
|
label: string
|
|
41
63
|
name: string
|
|
42
|
-
property?: {
|
|
64
|
+
property?: {
|
|
65
|
+
[option: string]: any
|
|
66
|
+
}
|
|
43
67
|
}
|
|
44
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Describes a use case definition, including its name, description, help text, and specifications.
|
|
70
|
+
*/
|
|
45
71
|
export type UseCaseDefinition = {
|
|
46
72
|
name: string
|
|
47
73
|
description: string
|
|
48
74
|
help: string
|
|
49
75
|
specs: DataSpecDefinition[]
|
|
50
76
|
}
|
|
51
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Represents the limits for a data specification.
|
|
79
|
+
*/
|
|
52
80
|
export type DataSpecLimit = {
|
|
53
81
|
[limit: string]: number | string | string[] | boolean
|
|
54
82
|
}
|
|
55
|
-
|
|
83
|
+
/**
|
|
84
|
+
* A set of data specification limits, keyed by use case.
|
|
85
|
+
*/
|
|
56
86
|
export type DataSpecLimitSet = {
|
|
57
87
|
[useCase: string]: DataSpecLimit
|
|
58
88
|
}
|
|
59
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Represents a collection of data, keyed by a tag.
|
|
91
|
+
*/
|
|
60
92
|
export type DataCollection = {
|
|
61
93
|
[tag: string]: any
|
|
62
94
|
}
|
|
63
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Represents a judgment on data, indicating if it is out of control or out of specification.
|
|
97
|
+
*/
|
|
64
98
|
export type Judgment = {
|
|
65
99
|
[tag: string]: {
|
|
66
100
|
ooc: boolean
|
|
67
101
|
oos: boolean
|
|
68
102
|
}
|
|
69
103
|
}
|
|
70
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Describes a data sample, including its name, description, use case, and associated data and judgments.
|
|
106
|
+
*/
|
|
71
107
|
export type DataSample = {
|
|
72
|
-
name
|
|
73
|
-
description
|
|
74
|
-
useCase
|
|
108
|
+
name?: string
|
|
109
|
+
description?: string
|
|
110
|
+
useCase?: string
|
|
75
111
|
data?: DataCollection
|
|
76
112
|
judgment?: Judgment
|
|
77
113
|
dataItems?: DataItem[]
|
|
78
|
-
quota
|
|
79
|
-
workDate
|
|
80
|
-
workShift
|
|
81
|
-
collectedAt
|
|
114
|
+
quota?: number
|
|
115
|
+
workDate?: string
|
|
116
|
+
workShift?: string
|
|
117
|
+
collectedAt?: Date
|
|
118
|
+
reviewActivityInstance?: any
|
|
119
|
+
dataOoc?: DataOoc
|
|
82
120
|
}
|
|
83
|
-
|
|
84
121
|
export type DataOocState = 'ISSUED' | 'REVIEWED' | 'CORRECTED'
|
|
85
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Extends DataSample with additional fields specific to an out of control state, including state, corrective actions, and review history.
|
|
124
|
+
*/
|
|
86
125
|
export type DataOoc = DataSample & {
|
|
87
|
-
state
|
|
126
|
+
state?: DataOocState
|
|
88
127
|
correctiveInstruction?: string
|
|
89
128
|
correctiveAction?: string
|
|
90
129
|
reviewer?: {
|
|
@@ -97,7 +136,7 @@ export type DataOoc = DataSample & {
|
|
|
97
136
|
name: string
|
|
98
137
|
}
|
|
99
138
|
correctedAt?: Date
|
|
100
|
-
history
|
|
139
|
+
history?: {
|
|
101
140
|
user: {
|
|
102
141
|
id: string
|
|
103
142
|
name: string
|
|
@@ -106,8 +145,11 @@ export type DataOoc = DataSample & {
|
|
|
106
145
|
comment: string
|
|
107
146
|
timestamp: number
|
|
108
147
|
}[]
|
|
148
|
+
resolveActivityInstance?: any
|
|
109
149
|
}
|
|
110
|
-
|
|
150
|
+
/**
|
|
151
|
+
* Describes a summary of data, including its name, description, relevant data items, and key metrics.
|
|
152
|
+
*/
|
|
111
153
|
export type DataSummary = {
|
|
112
154
|
name: string
|
|
113
155
|
description: string
|
|
@@ -123,7 +165,14 @@ export type DataSummary = {
|
|
|
123
165
|
countOoc?: number
|
|
124
166
|
countOos?: number
|
|
125
167
|
useCase?: string
|
|
126
|
-
summary?: {
|
|
168
|
+
summary?: {
|
|
169
|
+
[key: string]: any
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Represents the result of an evaluation, indicating if data is out of specification or out of control.
|
|
174
|
+
*/
|
|
175
|
+
export type EvaluationResult = {
|
|
176
|
+
oos: boolean
|
|
177
|
+
ooc: boolean
|
|
127
178
|
}
|
|
128
|
-
|
|
129
|
-
export type EvaluationResult = { oos: boolean; ooc: boolean }
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/* Here, only the common module of client and server is imported/exported. Be careful not to use a module dedicated to client or server. */
|
|
2
|
+
|
|
3
|
+
import { OxDataUseCase } from '../ox-data-use-case'
|
|
4
|
+
import { OxDataUseCaseSPC } from './ox-data-use-case-spc'
|
|
5
|
+
|
|
6
|
+
// OxPropertyEditor.register({
|
|
7
|
+
// 'spc-limits': 'ox-property-editor-spc-limits'
|
|
8
|
+
// })
|
|
9
|
+
|
|
10
|
+
OxDataUseCase.registerUseCase('SPC', new OxDataUseCaseSPC())
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import i18next from 'i18next' // Since this is a common module, @operato/i18n was deliberately avoided.
|
|
2
|
+
|
|
3
|
+
import { DataItem, EvaluationResult, UseCaseDefinition } from '../../types'
|
|
4
|
+
import { OxDataUseCase } from '../ox-data-use-case.js'
|
|
5
|
+
|
|
6
|
+
export class OxDataUseCaseSPC extends OxDataUseCase {
|
|
7
|
+
getSpecification(dataItem: DataItem): UseCaseDefinition {
|
|
8
|
+
return {
|
|
9
|
+
name: 'SPC',
|
|
10
|
+
description: 'Critical Control Point Data Spec',
|
|
11
|
+
help: '',
|
|
12
|
+
specs: [
|
|
13
|
+
{
|
|
14
|
+
type: 'spc-limits' /* A value which seperates acceptability from unacceptability */,
|
|
15
|
+
label: 'critical-limits',
|
|
16
|
+
name: 'criticalLimits',
|
|
17
|
+
property: dataItem
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: 'spc-limits',
|
|
21
|
+
label: 'target-limits',
|
|
22
|
+
name: 'targetLimits',
|
|
23
|
+
property: dataItem
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
evaluate(spec: any, values: any | any[]): EvaluationResult | undefined {
|
|
30
|
+
if (!spec || typeof values === 'undefined') {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!(values instanceof Array)) {
|
|
35
|
+
values = [values]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const {
|
|
39
|
+
minimum: criticalMinimum,
|
|
40
|
+
maximum: criticalMaximum,
|
|
41
|
+
acceptables: criticalAcceptables
|
|
42
|
+
} = spec['criticalLimits'] || {}
|
|
43
|
+
|
|
44
|
+
const {
|
|
45
|
+
minimum: targetMinimum,
|
|
46
|
+
maximum: targetMaximum,
|
|
47
|
+
acceptables: targetAcceptables
|
|
48
|
+
} = spec['targetLimits'] || {}
|
|
49
|
+
|
|
50
|
+
var oos = false
|
|
51
|
+
var ooc = false
|
|
52
|
+
|
|
53
|
+
for (let i = 0; i < values.length; i++) {
|
|
54
|
+
const value = values[i]
|
|
55
|
+
|
|
56
|
+
if (criticalMinimum != null && value < criticalMinimum) {
|
|
57
|
+
oos = true
|
|
58
|
+
break
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (criticalMaximum != null && value > criticalMaximum) {
|
|
62
|
+
oos = true
|
|
63
|
+
break
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (criticalAcceptables != null && !criticalAcceptables.includes(value)) {
|
|
67
|
+
oos = true
|
|
68
|
+
break
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (let i = 0; i < values.length; i++) {
|
|
73
|
+
const value = values[i]
|
|
74
|
+
|
|
75
|
+
if (targetMinimum != null && value < targetMinimum) {
|
|
76
|
+
ooc = true
|
|
77
|
+
break
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (targetMaximum != null && value > targetMaximum) {
|
|
81
|
+
ooc = true
|
|
82
|
+
break
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (targetAcceptables != null && !targetAcceptables.includes(value)) {
|
|
86
|
+
ooc = true
|
|
87
|
+
break
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { oos, ooc }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
elaborateUseCaseSpec(limits: any): string | undefined {
|
|
95
|
+
if (!limits) {
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
var text = ''
|
|
100
|
+
|
|
101
|
+
const {
|
|
102
|
+
minimum: criticalMinimum,
|
|
103
|
+
maximum: criticalMaximum,
|
|
104
|
+
acceptables: criticalAcceptables
|
|
105
|
+
} = limits['criticalLimits'] || {}
|
|
106
|
+
|
|
107
|
+
if (criticalMinimum != null || criticalMaximum != null || criticalAcceptables != null) {
|
|
108
|
+
text += `${i18next.t('label.critical-limits')}\n`
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (criticalMinimum != null) {
|
|
112
|
+
text += `\t${i18next.t('label.minimum value')} : ${criticalMinimum}\n`
|
|
113
|
+
}
|
|
114
|
+
if (criticalMaximum != null) {
|
|
115
|
+
text += `\t${i18next.t('label.maximum value')} : ${criticalMaximum}\n`
|
|
116
|
+
}
|
|
117
|
+
if (criticalAcceptables != null) {
|
|
118
|
+
text += `\t${i18next.t('label.acceptables')} : ${
|
|
119
|
+
criticalAcceptables instanceof Array ? criticalAcceptables.join(', ') : criticalAcceptables
|
|
120
|
+
}\n`
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const {
|
|
124
|
+
minimum: targetMinimum,
|
|
125
|
+
maximum: targetMaximum,
|
|
126
|
+
acceptables: targetAcceptables
|
|
127
|
+
} = limits['targetLimits'] || {}
|
|
128
|
+
|
|
129
|
+
if (targetMinimum != null || targetMaximum != null || targetAcceptables != null) {
|
|
130
|
+
text += `${i18next.t('label.target-limits')}\n`
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (targetMinimum != null) {
|
|
134
|
+
text += `\t${i18next.t('label.minimum value')} : ${targetMinimum}\n`
|
|
135
|
+
}
|
|
136
|
+
if (targetMaximum != null) {
|
|
137
|
+
text += `\t${i18next.t('label.maximum value')} : ${targetMaximum}\n`
|
|
138
|
+
}
|
|
139
|
+
if (targetAcceptables != null) {
|
|
140
|
+
text += `\t${i18next.t('label.acceptables')} : ${
|
|
141
|
+
targetAcceptables instanceof Array ? targetAcceptables.join(', ') : targetAcceptables
|
|
142
|
+
}\n`
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return text
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright © HatioLab Inc. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { css, html, LitElement } from 'lit'
|
|
6
|
+
import { customElement, property, query, queryAll } from 'lit/decorators.js'
|
|
7
|
+
|
|
8
|
+
import { i18next } from '@operato/i18n'
|
|
9
|
+
|
|
10
|
+
export enum DataItemType {
|
|
11
|
+
number = 'number',
|
|
12
|
+
text = 'text',
|
|
13
|
+
boolean = 'boolean',
|
|
14
|
+
select = 'select',
|
|
15
|
+
file = 'file'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type SpcLimitValue = {
|
|
19
|
+
minimum?: number
|
|
20
|
+
maximum?: number
|
|
21
|
+
acceptables?: string[] | boolean[]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
element for SPC limits
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
|
|
29
|
+
<ox-input-spc-limits
|
|
30
|
+
.value=${value}
|
|
31
|
+
.type=${type}>
|
|
32
|
+
</ox-input-spc-limits>
|
|
33
|
+
*/
|
|
34
|
+
@customElement('ox-input-spc-limits')
|
|
35
|
+
export class OxInputSpcLimits extends LitElement {
|
|
36
|
+
static styles = css`
|
|
37
|
+
:host {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
align-content: center;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
label {
|
|
44
|
+
margin: 0 var(--margin-default) var(--margin-default) 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
label div > * {
|
|
48
|
+
vertical-align: middle;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
button {
|
|
52
|
+
width: 20px;
|
|
53
|
+
text-align: center;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
div[name],
|
|
57
|
+
input[type='checkbox'] + span {
|
|
58
|
+
display: inline-block;
|
|
59
|
+
font: var(--label-font);
|
|
60
|
+
color: var(--label-color);
|
|
61
|
+
text-align: right;
|
|
62
|
+
}
|
|
63
|
+
input,
|
|
64
|
+
select {
|
|
65
|
+
border: var(--input-field-border);
|
|
66
|
+
border-radius: var(--input-field-border-radius);
|
|
67
|
+
padding: var(--input-field-padding);
|
|
68
|
+
font: var(--input-field-font);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
input[type='checkbox'] {
|
|
72
|
+
width: initial;
|
|
73
|
+
}
|
|
74
|
+
input[checked] + span {
|
|
75
|
+
font-weight: bold;
|
|
76
|
+
}
|
|
77
|
+
[unit],
|
|
78
|
+
[value] {
|
|
79
|
+
display: inline-block;
|
|
80
|
+
opacity: 0.7;
|
|
81
|
+
font: var(--form-sublabel-font);
|
|
82
|
+
}
|
|
83
|
+
[properties] {
|
|
84
|
+
font: var(--input-field-font);
|
|
85
|
+
color: var(--label-color);
|
|
86
|
+
}
|
|
87
|
+
`
|
|
88
|
+
|
|
89
|
+
@property({ type: Object }) value: SpcLimitValue = {}
|
|
90
|
+
@property({ type: String }) type: DataItemType = DataItemType.number
|
|
91
|
+
@property({ type: String }) unit?: string
|
|
92
|
+
@property({ type: Object }) options: { options?: { text: string; value: string }[] } = {}
|
|
93
|
+
|
|
94
|
+
@query('[name=minimum]') minimum!: HTMLInputElement
|
|
95
|
+
@query('[name=maximum]') maximum!: HTMLInputElement
|
|
96
|
+
@queryAll('[type=checkbox]:checked') checkedAll!: NodeListOf<HTMLInputElement>
|
|
97
|
+
|
|
98
|
+
firstUpdated() {
|
|
99
|
+
this.renderRoot.addEventListener('change', this.onChange.bind(this))
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
render() {
|
|
103
|
+
const { minimum, maximum, acceptables = [] } = this.value || {}
|
|
104
|
+
|
|
105
|
+
return html`
|
|
106
|
+
<div>
|
|
107
|
+
${this.type === DataItemType.number
|
|
108
|
+
? html`
|
|
109
|
+
<label>
|
|
110
|
+
<div name>${i18next.t('text.minimum value')}</div>
|
|
111
|
+
<input type="number" name="minimum" .value=${String(minimum)} />
|
|
112
|
+
<div unit>${this.unit}</div>
|
|
113
|
+
</select>
|
|
114
|
+
</label>
|
|
115
|
+
<label>
|
|
116
|
+
<div name>${i18next.t('text.maximum value')}</div>
|
|
117
|
+
<input type="number" name="maximum" .value=${String(maximum)} />
|
|
118
|
+
<div unit>${this.unit}</div>
|
|
119
|
+
</label>
|
|
120
|
+
`
|
|
121
|
+
: this.type === DataItemType.select
|
|
122
|
+
? html`
|
|
123
|
+
<!-- <div>Acceptables</div> -->
|
|
124
|
+
${this.options?.options?.map(
|
|
125
|
+
option => html`
|
|
126
|
+
<div>
|
|
127
|
+
<input
|
|
128
|
+
type="checkbox"
|
|
129
|
+
data-value=${option.value}
|
|
130
|
+
?checked=${(acceptables as string[]).includes(option.value)}
|
|
131
|
+
/>
|
|
132
|
+
<span>${option.text}</span>
|
|
133
|
+
<span value>(${option.value})</span>
|
|
134
|
+
</div>
|
|
135
|
+
`
|
|
136
|
+
)}
|
|
137
|
+
`
|
|
138
|
+
: this.type === DataItemType.boolean
|
|
139
|
+
? html`
|
|
140
|
+
<div>
|
|
141
|
+
<input type="checkbox" data-value=${true} ?checked=${(acceptables as boolean[]).includes(true)} />
|
|
142
|
+
<span value>true</span>
|
|
143
|
+
</div>
|
|
144
|
+
<div>
|
|
145
|
+
<input type="checkbox" data-value=${false} ?checked=${(acceptables as boolean[]).includes(false)} />
|
|
146
|
+
<span value>false</span>
|
|
147
|
+
</div>
|
|
148
|
+
`
|
|
149
|
+
: html` <div properties>${i18next.t('text.no properties to set')}</div> `}
|
|
150
|
+
</div>
|
|
151
|
+
`
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private onChange(e: Event) {
|
|
155
|
+
if (this.type === DataItemType.number) {
|
|
156
|
+
this.value = {
|
|
157
|
+
minimum: this.minimum.valueAsNumber,
|
|
158
|
+
maximum: this.maximum.valueAsNumber
|
|
159
|
+
}
|
|
160
|
+
} else if (this.type === DataItemType.select) {
|
|
161
|
+
this.value = {
|
|
162
|
+
acceptables: Array.from(this.checkedAll).map(checked => {
|
|
163
|
+
const x = checked.getAttribute('data-value')!
|
|
164
|
+
console.log(x)
|
|
165
|
+
return x
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
} else if (this.type === DataItemType.boolean) {
|
|
169
|
+
this.value = {
|
|
170
|
+
acceptables: Array.from(this.checkedAll).map(checked => {
|
|
171
|
+
const x = checked.getAttribute('data-value')! === 'true'
|
|
172
|
+
console.log(x)
|
|
173
|
+
return x
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
this.value = {}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import './ox-input-spc-limits.js'
|
|
2
|
+
|
|
3
|
+
import { html, TemplateResult } from 'lit'
|
|
4
|
+
import { customElement } from 'lit/decorators.js'
|
|
5
|
+
|
|
6
|
+
import { OxPropertyEditor, PropertySpec } from '@operato/property-editor'
|
|
7
|
+
|
|
8
|
+
@customElement('ox-property-editor-spc-limits')
|
|
9
|
+
export class OxPropertyEditorSpcLimits extends OxPropertyEditor {
|
|
10
|
+
editorTemplate(value: any, spec: PropertySpec): TemplateResult {
|
|
11
|
+
const { type, options, unit } = spec.property || {}
|
|
12
|
+
|
|
13
|
+
return html`
|
|
14
|
+
<ox-input-spc-limits
|
|
15
|
+
id="editor"
|
|
16
|
+
.value=${value}
|
|
17
|
+
.type=${type}
|
|
18
|
+
.unit=${unit}
|
|
19
|
+
.options=${options}
|
|
20
|
+
></ox-input-spc-limits>
|
|
21
|
+
`
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -144,6 +144,7 @@ var dataOoc = {
|
|
|
144
144
|
name: 'Data Sample Name',
|
|
145
145
|
description: 'Data Sample이 어쩌구 저쩌구 그래서 중요합니다. 당연히 그래야죠.',
|
|
146
146
|
useCase: 'CCP',
|
|
147
|
+
state: 'REVIEWED',
|
|
147
148
|
judgment: {
|
|
148
149
|
temp: {
|
|
149
150
|
ooc: true,
|
|
@@ -247,6 +248,7 @@ var dataOoc = {
|
|
|
247
248
|
name: 'shnam'
|
|
248
249
|
},
|
|
249
250
|
state: 'CORRECTED',
|
|
251
|
+
comment: '전량 폐기하였습니다',
|
|
250
252
|
timestamp: Date.now()
|
|
251
253
|
}
|
|
252
254
|
]
|
package/themes/grist-theme.css
CHANGED
|
@@ -37,7 +37,7 @@ body {
|
|
|
37
37
|
|
|
38
38
|
--grid-record-background-color: var(--theme-white-color);
|
|
39
39
|
--grid-record-odd-background-color: #f9f7f5;
|
|
40
|
-
--grid-record-padding:
|
|
40
|
+
--grid-record-padding: 0 5px 0 5px;
|
|
41
41
|
--grid-record-color: var(--secondary-color);
|
|
42
42
|
--grid-record-color-hover: var(--primary-color);
|
|
43
43
|
--grid-record-wide-fontsize: var(--fontsize-small);
|
package/translations/en.json
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"field.entry-role": "entry role",
|
|
18
18
|
"field.entry-type": "entry type",
|
|
19
19
|
"field.entry-view": "entry view",
|
|
20
|
+
"field.finalizing-function": "finalizing func.",
|
|
20
21
|
"field.hidden": "hidden",
|
|
21
22
|
"field.item": "item",
|
|
22
23
|
"field.latest-collected-at": "latest collected at",
|