@operato/dataset 1.0.0-beta.38 → 1.0.0-beta.40

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 (94) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/src/grist-editor/ox-grist-editor-data-item-spec.js +1 -1
  3. package/dist/src/grist-editor/ox-grist-editor-data-item-spec.js.map +1 -1
  4. package/dist/src/grist-editor/ox-popup-data-item-spec.js +3 -2
  5. package/dist/src/grist-editor/ox-popup-data-item-spec.js.map +1 -1
  6. package/dist/src/index.d.ts +1 -5
  7. package/dist/src/index.js +1 -5
  8. package/dist/src/index.js.map +1 -1
  9. package/dist/src/ox-data-item-spec.d.ts +2 -2
  10. package/dist/src/ox-data-item-spec.js +1 -1
  11. package/dist/src/ox-data-item-spec.js.map +1 -1
  12. package/dist/src/ox-data-ooc-view.js +1 -1
  13. package/dist/src/ox-data-ooc-view.js.map +1 -1
  14. package/dist/src/ox-data-sample-view.d.ts +1 -2
  15. package/dist/src/ox-data-sample-view.js +25 -31
  16. package/dist/src/ox-data-sample-view.js.map +1 -1
  17. package/dist/src/types.d.ts +18 -6
  18. package/dist/src/types.js.map +1 -1
  19. package/dist/src/usecase/ccp/index.d.ts +1 -0
  20. package/dist/src/usecase/ccp/index.js +8 -0
  21. package/dist/src/usecase/ccp/index.js.map +1 -0
  22. package/dist/src/usecase/ccp/ox-data-use-case-ccp.d.ts +7 -0
  23. package/dist/src/usecase/ccp/ox-data-use-case-ccp.js +102 -0
  24. package/dist/src/usecase/ccp/ox-data-use-case-ccp.js.map +1 -0
  25. package/dist/src/usecase/ccp/ox-input-ccp-limits.d.ts +44 -0
  26. package/dist/src/usecase/ccp/ox-input-ccp-limits.js +171 -0
  27. package/dist/src/usecase/ccp/ox-input-ccp-limits.js.map +1 -0
  28. package/dist/src/usecase/ccp/ox-property-editor-ccp-limits.d.ts +5 -0
  29. package/dist/src/usecase/ccp/ox-property-editor-ccp-limits.js +24 -0
  30. package/dist/src/usecase/ccp/ox-property-editor-ccp-limits.js.map +1 -0
  31. package/dist/src/{ox-data-use-case.d.ts → usecase/ox-data-use-case.d.ts} +5 -5
  32. package/dist/src/{ox-data-use-case.js → usecase/ox-data-use-case.js} +23 -34
  33. package/dist/src/usecase/ox-data-use-case.js.map +1 -0
  34. package/dist/src/usecase/qc/index.d.ts +1 -0
  35. package/dist/src/usecase/qc/index.js +8 -0
  36. package/dist/src/usecase/qc/index.js.map +1 -0
  37. package/dist/src/usecase/qc/ox-data-use-case-qc.d.ts +7 -0
  38. package/dist/src/usecase/qc/ox-data-use-case-qc.js +55 -0
  39. package/dist/src/usecase/qc/ox-data-use-case-qc.js.map +1 -0
  40. package/dist/src/usecase/qc/ox-input-qc-limits.d.ts +44 -0
  41. package/dist/src/usecase/qc/ox-input-qc-limits.js +171 -0
  42. package/dist/src/usecase/qc/ox-input-qc-limits.js.map +1 -0
  43. package/dist/src/usecase/qc/ox-property-editor-qc-limits.d.ts +5 -0
  44. package/dist/src/usecase/qc/ox-property-editor-qc-limits.js +24 -0
  45. package/dist/src/usecase/qc/ox-property-editor-qc-limits.js.map +1 -0
  46. package/dist/stories/ox-data-entry-form.stories.d.ts +19 -0
  47. package/dist/stories/ox-data-entry-form.stories.js +152 -0
  48. package/dist/stories/ox-data-entry-form.stories.js.map +1 -0
  49. package/dist/stories/ox-data-item-spec.stories.d.ts +26 -0
  50. package/dist/stories/ox-data-item-spec.stories.js +102 -0
  51. package/dist/stories/ox-data-item-spec.stories.js.map +1 -0
  52. package/dist/stories/ox-data-ooc-view.stories.d.ts +19 -0
  53. package/dist/stories/ox-data-ooc-view.stories.js +242 -0
  54. package/dist/stories/ox-data-ooc-view.stories.js.map +1 -0
  55. package/dist/stories/ox-data-sample-view.stories.d.ts +19 -0
  56. package/dist/stories/ox-data-sample-view.stories.js +213 -0
  57. package/dist/stories/ox-data-sample-view.stories.js.map +1 -0
  58. package/dist/stories/ox-grist-editor-data-item-spec.stories.d.ts +27 -0
  59. package/dist/stories/ox-grist-editor-data-item-spec.stories.js +389 -0
  60. package/dist/stories/ox-grist-editor-data-item-spec.stories.js.map +1 -0
  61. package/dist/tsconfig.tsbuildinfo +1 -1
  62. package/package.json +18 -12
  63. package/src/grist-editor/ox-grist-editor-data-item-spec.ts +1 -1
  64. package/src/grist-editor/ox-popup-data-item-spec.ts +3 -2
  65. package/src/index.ts +1 -5
  66. package/src/ox-data-item-spec.ts +3 -3
  67. package/src/ox-data-ooc-view.ts +1 -1
  68. package/src/ox-data-sample-view.ts +28 -31
  69. package/src/types.ts +23 -6
  70. package/src/usecase/ccp/index.ts +10 -0
  71. package/src/usecase/ccp/ox-data-use-case-ccp.ts +147 -0
  72. package/src/usecase/ccp/ox-input-ccp-limits.ts +161 -0
  73. package/src/usecase/ccp/ox-property-editor-ccp-limits.ts +23 -0
  74. package/src/{ox-data-use-case.ts → usecase/ox-data-use-case.ts} +28 -40
  75. package/src/usecase/qc/index.ts +10 -0
  76. package/src/usecase/qc/ox-data-use-case-qc.ts +72 -0
  77. package/src/usecase/qc/ox-input-qc-limits.ts +161 -0
  78. package/src/usecase/qc/ox-property-editor-qc-limits.ts +23 -0
  79. package/stories/ox-data-entry-form.stories.ts +165 -0
  80. package/stories/ox-data-item-spec.stories.ts +121 -0
  81. package/stories/ox-data-ooc-view.stories.ts +256 -0
  82. package/stories/ox-data-sample-view.stories.ts +227 -0
  83. package/stories/ox-grist-editor-data-item-spec.stories.ts +409 -0
  84. package/translations/en.json +26 -8
  85. package/translations/ko.json +25 -7
  86. package/translations/ms.json +26 -8
  87. package/translations/zh.json +25 -7
  88. package/demo/index.html +0 -28
  89. package/demo/ox-data-entry-form.html +0 -118
  90. package/demo/ox-data-item-spec.html +0 -152
  91. package/demo/ox-data-ooc-view.html +0 -185
  92. package/demo/ox-data-sample-view.html +0 -150
  93. package/demo/ox-grist-editor-data-item-spec.html +0 -476
  94. package/dist/src/ox-data-use-case.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { DataItem, DataItemSpecSet, DataSet, EvaluationResult } from './types'
1
+ import { DataItem, DataSet, DataSpecLimitSet, EvaluationResult, UseCaseDefinition } from '../types'
2
2
 
3
3
  export abstract class OxDataUseCase {
4
4
  static registry: { [name: string]: OxDataUseCase } = {}
@@ -19,39 +19,35 @@ export abstract class OxDataUseCase {
19
19
  return OxDataUseCase.registry[name]
20
20
  }
21
21
 
22
- public static elaborateDataItemSpec(dataSet: DataSet, dataItem: DataItem): string {
23
- if (!dataSet.useCase) {
24
- return ''
25
- }
22
+ public static elaborateDataItemSpec(spec: DataSpecLimitSet): string {
23
+ const useCaseNames = Object.keys(spec || {})
26
24
 
27
- const useCaseNames = dataSet.useCase.split(',').map(useCaseName => useCaseName.trim())
28
- const useCases = useCaseNames.map(useCaseName => OxDataUseCase.getUseCase(useCaseName)).filter(useCase => !!useCase)
25
+ var texts: string[] = []
29
26
 
30
- var texts = []
31
-
32
- for (let j = 0; j < useCases.length; j++) {
33
- const useCase = useCases[j]
27
+ useCaseNames.forEach(useCaseName => {
28
+ const useCase = OxDataUseCase.getUseCase(useCaseName)
34
29
  if (!useCase) {
35
- continue
30
+ return
36
31
  }
37
32
 
38
- const specs = dataItem.spec?.[dataSet.useCase]
39
- if (!specs) {
40
- continue
33
+ const limits = spec?.[useCaseName]
34
+ if (!limits) {
35
+ return
41
36
  }
42
37
 
43
- const result = useCase.elaborateUseCaseSpec(dataItem.spec)
38
+ const result = useCase.elaborateUseCaseSpec(limits)
44
39
  if (!result) {
45
- continue
40
+ return
46
41
  }
47
42
 
43
+ texts.push(`[ ${useCaseName} ]`)
48
44
  texts.push(result)
49
- }
45
+ })
50
46
 
51
47
  return texts.join('\n')
52
48
  }
53
49
 
54
- public static evaluate(dataSet: DataSet, dataItems: DataItem[], data: any): EvaluationResult | undefined {
50
+ public static evaluate(dataSet: DataSet, dataItems: DataItem[], data: any): EvaluationResult {
55
51
  var ooc = false
56
52
  var oos = false
57
53
 
@@ -86,7 +82,7 @@ export abstract class OxDataUseCase {
86
82
  continue
87
83
  }
88
84
 
89
- const result = useCase?.evaluate(specs, values)
85
+ const result = useCase!.evaluate(specs, values)
90
86
 
91
87
  if (result) {
92
88
  ooc ||= result.ooc
@@ -98,22 +94,10 @@ export abstract class OxDataUseCase {
98
94
  return { ooc, oos }
99
95
  }
100
96
 
101
- public static evaluateItem(dataSet: DataSet, dataItem: DataItem, values: any | any[]): EvaluationResult | undefined {
97
+ public static evaluateItem(spec: DataSpecLimitSet, values: any | any[]): EvaluationResult | undefined {
102
98
  var ooc = false
103
99
  var oos = false
104
100
 
105
- if (!dataSet.useCase) {
106
- return { ooc, oos }
107
- }
108
-
109
- const useCaseNames = dataSet.useCase.split(',').map(useCaseName => useCaseName.trim())
110
- const useCases = useCaseNames.map(useCaseName => OxDataUseCase.getUseCase(useCaseName)).filter(useCase => !!useCase)
111
-
112
- const { active, tag } = dataItem
113
- if (!active || !tag) {
114
- return
115
- }
116
-
117
101
  if (typeof values === 'undefined') {
118
102
  return // TODO what if in case no value ?
119
103
  }
@@ -122,26 +106,30 @@ export abstract class OxDataUseCase {
122
106
  values = [values]
123
107
  }
124
108
 
125
- for (let j = 0; j < useCases.length; j++) {
126
- const useCase = useCases[j]
109
+ const useCaseNames = Object.keys(spec || {})
110
+
111
+ if (useCaseNames.length === 0) {
112
+ return { ooc, oos }
113
+ }
127
114
 
128
- const specs = dataItem.spec?.[dataSet.useCase]
129
- if (!specs) {
115
+ useCaseNames.forEach(useCaseName => {
116
+ const useCase = OxDataUseCase.getUseCase(useCaseName)
117
+ if (!useCase) {
130
118
  return
131
119
  }
132
120
 
133
- const result = useCase?.evaluate(specs, values)
121
+ const result = useCase?.evaluate(spec[useCaseName], values)
134
122
 
135
123
  if (result) {
136
124
  ooc ||= result.ooc
137
125
  oos ||= result.oos
138
126
  }
139
- }
127
+ })
140
128
 
141
129
  return { ooc, oos }
142
130
  }
143
131
 
144
132
  public abstract evaluate(specs: any, values: any[]): EvaluationResult | undefined
145
133
  public abstract elaborateUseCaseSpec(spec: any): string | undefined
146
- public abstract getSpecification(dataItem: DataItem): DataItemSpecSet
134
+ public abstract getSpecification(dataItem: DataItem): UseCaseDefinition
147
135
  }
@@ -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.js'
4
+ import { OxDataUseCaseQC } from './ox-data-use-case-qc.js'
5
+
6
+ // OxPropertyEditor.register({
7
+ // 'qc-limits': 'ox-property-editor-qc-limits'
8
+ // })
9
+
10
+ OxDataUseCase.registerUseCase('QC', new OxDataUseCaseQC())
@@ -0,0 +1,72 @@
1
+ import i18next from 'i18next' // Since this is a common module, @operato/i18n was deliberately avoided.
2
+
3
+ import { DataItem, EvaluationResult, UseCaseDefinition } from '../../types.js'
4
+ import { OxDataUseCase } from '../ox-data-use-case.js'
5
+
6
+ export class OxDataUseCaseQC implements OxDataUseCase {
7
+ getSpecification(dataItem: DataItem): UseCaseDefinition {
8
+ return {
9
+ name: 'QC',
10
+ description: 'Quality Control Data Spec',
11
+ help: '',
12
+ specs: [
13
+ {
14
+ type: 'qc-limits' /* 'A value which seperates acceptability from unacceptability' */,
15
+ label: 'pass-limits',
16
+ name: 'passLimits',
17
+ property: dataItem
18
+ }
19
+ ]
20
+ }
21
+ }
22
+
23
+ evaluate(spec: any, values: any[]): EvaluationResult {
24
+ const { minimum, maximum, acceptables } = spec['passLimits']
25
+
26
+ for (let i = 0; i < values.length; i++) {
27
+ const value = values[i]
28
+
29
+ if (typeof minimum !== 'undefined' && value < minimum) {
30
+ return { oos: true, ooc: true }
31
+ }
32
+
33
+ if (typeof maximum !== 'undefined' && value > maximum) {
34
+ return { oos: true, ooc: true }
35
+ }
36
+
37
+ if (typeof acceptables !== 'undefined' && !acceptables.includes(value)) {
38
+ return { oos: true, ooc: true }
39
+ }
40
+ }
41
+
42
+ return { oos: false, ooc: false }
43
+ }
44
+
45
+ elaborateUseCaseSpec(limits: any): string | undefined {
46
+ if (!limits) {
47
+ return
48
+ }
49
+
50
+ var text = ''
51
+
52
+ const { minimum, maximum, acceptables } = limits['passLimits'] || {}
53
+
54
+ if (minimum !== undefined || maximum !== undefined || acceptables !== undefined) {
55
+ text += `${i18next.t('label.pass-limits')}\n`
56
+ }
57
+
58
+ if (minimum !== undefined) {
59
+ text += `\t${i18next.t('label.minimum value')} : ${minimum}\n`
60
+ }
61
+ if (maximum !== undefined) {
62
+ text += `\t${i18next.t('label.maximum value')} : ${maximum}\n`
63
+ }
64
+ if (acceptables !== undefined) {
65
+ text += `\t${i18next.t('label.acceptables')} : ${
66
+ acceptables instanceof Array ? acceptables.join(', ') : acceptables
67
+ }\n`
68
+ }
69
+
70
+ return text
71
+ }
72
+ }
@@ -0,0 +1,161 @@
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 QcLimitValue = {
19
+ minimum?: number
20
+ maximum?: number
21
+ acceptables?: string[]
22
+ }
23
+
24
+ /**
25
+ element for QC limits
26
+
27
+ Example:
28
+
29
+ <ox-input-qc-limits
30
+ .value=${value}
31
+ .type=${type}>
32
+ </ox-input-qc-limits>
33
+ */
34
+ @customElement('ox-input-qc-limits')
35
+ export class OxInputQcLimits 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: QcLimitValue = {}
90
+ @property({ type: String }) type: DataItemType = DataItemType.number
91
+ @property({ type: String }) unit?: string
92
+ @property({ type: Array }) 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=${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=${maximum} />
118
+ <div unit>${this.unit}</div>
119
+ </label>
120
+ </div>
121
+ `
122
+ : this.type === DataItemType.select
123
+ ? html`
124
+ <!-- <div>Acceptables</div> -->
125
+ ${this.options?.options?.map(
126
+ option => html`
127
+ <div>
128
+ <input type="checkbox" data-value=${option.value} ?checked=${acceptables.includes(option.value)} />
129
+ <span>${option.text}</span>
130
+ <span value>(${option.value})</span>
131
+ </div>
132
+ `
133
+ )}
134
+ </div>
135
+ `
136
+ : html` <div properties>${i18next.t('text.no properties to set')}</div> `}
137
+ </div>
138
+ `
139
+ }
140
+
141
+ private onChange(e: Event) {
142
+ if (this.type === DataItemType.number) {
143
+ this.value = {
144
+ minimum: this.minimum.valueAsNumber,
145
+ maximum: this.maximum.valueAsNumber
146
+ }
147
+ } else if (this.type === DataItemType.select) {
148
+ this.value = {
149
+ acceptables: Array.from(this.checkedAll).map(checked => {
150
+ const x = checked.getAttribute('data-value')!
151
+ console.log(x)
152
+ return x
153
+ })
154
+ }
155
+ } else {
156
+ this.value = {}
157
+ }
158
+
159
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
160
+ }
161
+ }
@@ -0,0 +1,23 @@
1
+ import './ox-input-qc-limits.js'
2
+
3
+ import { html } from 'lit'
4
+ import { customElement } from 'lit/decorators.js'
5
+
6
+ import { OxPropertyEditor } from '@operato/property-editor'
7
+
8
+ @customElement('ox-property-editor-qc-limits')
9
+ export class OxPropertyEditorQcLimits extends OxPropertyEditor {
10
+ editorTemplate() {
11
+ const { type, options, unit } = this.property || {}
12
+
13
+ return html`
14
+ <ox-input-qc-limits
15
+ id="editor"
16
+ .value=${this.value}
17
+ .type=${type}
18
+ .unit=${unit}
19
+ .options=${options}
20
+ ></ox-input-qc-limits>
21
+ `
22
+ }
23
+ }
@@ -0,0 +1,165 @@
1
+ import '@operato/i18n'
2
+ import '../src/ox-data-entry-form.js'
3
+ import '../src/usecase/ccp' /* register usecase CCP */
4
+ import '@material/mwc-icon'
5
+
6
+ import { html, TemplateResult } from 'lit'
7
+
8
+ export default {
9
+ title: 'ox-data-entry-form',
10
+ component: 'ox-data-entry-form',
11
+ argTypes: {}
12
+ }
13
+
14
+ interface Story<T> {
15
+ (args: T): TemplateResult
16
+ args?: Partial<T>
17
+ argTypes?: Record<string, unknown>
18
+ }
19
+
20
+ interface ArgTypes {}
21
+
22
+ const dataSet = {
23
+ name: 'sample',
24
+ description: 'sample description',
25
+ useCase: 'CCP',
26
+ dataItems: [
27
+ {
28
+ name: '창고 온도',
29
+ description: '창고 온도는 섭씨 0도 이하로 유지되어야 합니다.',
30
+ sequence: 1,
31
+ tag: 'temp',
32
+ type: 'number',
33
+ quota: 1,
34
+ active: true,
35
+ unit: '℃',
36
+ spec: {
37
+ CCP: {
38
+ criticalLimits: {
39
+ minimum: 100,
40
+ maximum: 200
41
+ },
42
+ targetLimits: {
43
+ minimum: 120,
44
+ maximum: 180
45
+ }
46
+ }
47
+ }
48
+ },
49
+ {
50
+ name: '창고 습도',
51
+ description: '창고 습도는 30% 이하로 유지되어야 합니다.',
52
+ sequence: 2,
53
+ tag: 'humid',
54
+ type: 'number',
55
+ quota: 5,
56
+ active: true,
57
+ unit: '%',
58
+ spec: {
59
+ CCP: {
60
+ criticalLimits: {
61
+ minimum: 10,
62
+ maximum: 50
63
+ },
64
+ targetLimits: {
65
+ minimum: 20,
66
+ maximum: 40
67
+ }
68
+ }
69
+ }
70
+ },
71
+ {
72
+ name: '육안 검사',
73
+ description: '육안 검사는 포장전 30분 내로 실행되어야 합니다.',
74
+ sequence: 3,
75
+ tag: 'inspection',
76
+ type: 'boolean',
77
+ quota: 3,
78
+ active: true,
79
+ spec: {
80
+ CCP: {
81
+ criticalLimits: {
82
+ acceptables: true
83
+ },
84
+ targetLimits: {
85
+ acceptables: true
86
+ }
87
+ }
88
+ }
89
+ },
90
+ {
91
+ name: '품평',
92
+ description: '품평은 최우수/우수/보통/미달을 포함하여 간단히 평가.',
93
+ sequence: 4,
94
+ tag: 'evaluation',
95
+ type: 'select',
96
+ options: {
97
+ options: [
98
+ { text: '최우수', value: '최우수' },
99
+ { text: '우수', value: '우수' },
100
+ { text: '보통', value: '보통' },
101
+ { text: '미달', value: '미달' }
102
+ ]
103
+ },
104
+ quota: 3,
105
+ active: true,
106
+ spec: {
107
+ CCP: {
108
+ criticalLimits: {
109
+ acceptables: ['최우수', '우수', '보통']
110
+ },
111
+ targetLimits: {
112
+ acceptables: ['최우수', '우수']
113
+ }
114
+ }
115
+ }
116
+ },
117
+ {
118
+ name: '코멘트',
119
+ description: '특이사항을 기록함.',
120
+ sequence: 4,
121
+ tag: 'comment',
122
+ type: 'string',
123
+ quota: 1,
124
+ active: true
125
+ },
126
+ {
127
+ name: '첨부파일',
128
+ description: '참조 첨부 파일.',
129
+ sequence: 4,
130
+ tag: 'attachment',
131
+ type: 'file',
132
+ quota: 1,
133
+ active: true
134
+ }
135
+ ]
136
+ }
137
+ var value = {
138
+ temp: 1000,
139
+ humid: [20, 23, 21, 26, 27],
140
+ inspection: [true, false, true],
141
+ evaluation: ['최우수', '보통', '우수'],
142
+ comment: '이것이 코멘트입니다.'
143
+ }
144
+
145
+ const Template: Story<ArgTypes> = ({}: ArgTypes) =>
146
+ html`
147
+ <link href="/themes/app-theme.css" rel="stylesheet" />
148
+ <link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
149
+ <style>
150
+ body {
151
+ }
152
+ </style>
153
+
154
+ <ox-data-entry-form
155
+ .dataSet=${dataSet}
156
+ .value=${value}
157
+ @change=${(e: CustomEvent) => {
158
+ value = e.detail
159
+ console.log('change', value)
160
+ }}
161
+ ></ox-data-entry-form>
162
+ `
163
+
164
+ export const Regular = Template.bind({})
165
+ Regular.args = {}
@@ -0,0 +1,121 @@
1
+ import '@operato/i18n'
2
+ import '@material/mwc-icon'
3
+ import '@operato/property-editor/ox-property-editor-checkbox.js'
4
+ import '@operato/property-editor/ox-property-editor-number.js'
5
+ import '@operato/property-editor/ox-property-editor-string.js'
6
+ import '@operato/property-editor/ox-properties-dynamic-view.js'
7
+ import '../src/ox-data-item-spec.js'
8
+ import '../src/usecase/ccp' /* register usecase CCP */
9
+ import '../src/usecase/qc' /* register usecase QC */
10
+ import '../src/usecase/ccp/ox-property-editor-ccp-limits.js'
11
+ import '../src/usecase/qc/ox-property-editor-qc-limits.js'
12
+
13
+ import { html, TemplateResult } from 'lit'
14
+
15
+ import { OxPropertyEditor } from '@operato/property-editor'
16
+
17
+ OxPropertyEditor.register({
18
+ number: 'ox-property-editor-number',
19
+ string: 'ox-property-editor-string',
20
+ boolean: 'ox-property-editor-checkbox',
21
+ 'ccp-limits': 'ox-property-editor-ccp-limits',
22
+ 'qc-limits': 'ox-property-editor-qc-limits'
23
+ })
24
+
25
+ export default {
26
+ title: 'ox-data-item-spec',
27
+ component: 'ox-data-item-spec',
28
+ argTypes: {}
29
+ }
30
+
31
+ interface Story<T> {
32
+ (args: T): TemplateResult
33
+ args?: Partial<T>
34
+ argTypes?: Record<string, unknown>
35
+ }
36
+
37
+ interface ArgTypes {}
38
+
39
+ const dataItemA = {
40
+ name: '창고 온도',
41
+ description: '창고 온도는 섭씨 0도 이하로 유지되어야 합니다.',
42
+ sequence: 1,
43
+ tag: 'temp',
44
+ unit: '℃',
45
+ type: 'number',
46
+ quota: 1
47
+ }
48
+
49
+ const dataItemB = {
50
+ name: '품평',
51
+ description: '품평은 최우수/우수/보통/미달을 포함하여 간단히 평가.',
52
+ sequence: 4,
53
+ tag: 'evaluation',
54
+ type: 'select',
55
+ options: {
56
+ options: [
57
+ { text: '최우수', value: '최우수' },
58
+ { text: '우수', value: '우수' },
59
+ { text: '보통', value: '보통' },
60
+ { text: '미달', value: '미달' }
61
+ ]
62
+ },
63
+ quota: 3
64
+ }
65
+
66
+ const dataItemC = {
67
+ name: '코멘트',
68
+ description: '특이사항을 기록함.',
69
+ sequence: 4,
70
+ tag: 'comment',
71
+ type: 'string',
72
+ quota: 1
73
+ }
74
+
75
+ var specA = {
76
+ CCP: {
77
+ criticalLimits: {
78
+ minimum: 100,
79
+ maximum: 200
80
+ },
81
+ targetLimits: {
82
+ minimum: 120,
83
+ maximum: 180
84
+ }
85
+ },
86
+ QC: {
87
+ passLimits: {
88
+ minimum: 320,
89
+ maximum: 440
90
+ }
91
+ }
92
+ }
93
+
94
+ var specB = {
95
+ CCP: { accpetables: ['최우수', '우수'] },
96
+ QC: { accpetables: ['최우수', '우수'] }
97
+ }
98
+
99
+ const Template: Story<ArgTypes> = ({}: ArgTypes) =>
100
+ html`
101
+ <link href="/themes/app-theme.css" rel="stylesheet" />
102
+ <link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
103
+ <style>
104
+ body {
105
+ }
106
+ </style>
107
+
108
+ <script type="module"></script>
109
+
110
+ <ox-data-item-spec
111
+ .dataItem=${dataItemA}
112
+ .value=${specA}
113
+ @change=${(e: CustomEvent) => {
114
+ specA = e.detail
115
+ console.log('change', specA)
116
+ }}
117
+ ></ox-data-item-spec>
118
+ `
119
+
120
+ export const Regular = Template.bind({})
121
+ Regular.args = {}