@things-factory/ops-master 10.0.18

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 (181) hide show
  1. package/.dockerignore +31 -0
  2. package/dist-client/index.d.ts +1 -0
  3. package/dist-client/index.js +2 -0
  4. package/dist-client/index.js.map +1 -0
  5. package/dist-client/pages/master-axes.d.ts +33 -0
  6. package/dist-client/pages/master-axes.js +176 -0
  7. package/dist-client/pages/master-axes.js.map +1 -0
  8. package/dist-client/pages/master-list.d.ts +68 -0
  9. package/dist-client/pages/master-list.js +267 -0
  10. package/dist-client/pages/master-list.js.map +1 -0
  11. package/dist-client/route.d.ts +1 -0
  12. package/dist-client/route.js +8 -0
  13. package/dist-client/route.js.map +1 -0
  14. package/dist-client/tsconfig.tsbuildinfo +1 -0
  15. package/dist-server/index.d.ts +1 -0
  16. package/dist-server/index.js +5 -0
  17. package/dist-server/index.js.map +1 -0
  18. package/dist-server/service/asset/asset-lifecycle.d.ts +83 -0
  19. package/dist-server/service/asset/asset-lifecycle.js +99 -0
  20. package/dist-server/service/asset/asset-lifecycle.js.map +1 -0
  21. package/dist-server/service/asset/asset-master-resolver.d.ts +44 -0
  22. package/dist-server/service/asset/asset-master-resolver.js +140 -0
  23. package/dist-server/service/asset/asset-master-resolver.js.map +1 -0
  24. package/dist-server/service/asset/asset-master.d.ts +21 -0
  25. package/dist-server/service/asset/asset-master.js +25 -0
  26. package/dist-server/service/asset/asset-master.js.map +1 -0
  27. package/dist-server/service/asset/asset-query.d.ts +8 -0
  28. package/dist-server/service/asset/asset-query.js +50 -0
  29. package/dist-server/service/asset/asset-query.js.map +1 -0
  30. package/dist-server/service/asset/index.d.ts +6 -0
  31. package/dist-server/service/asset/index.js +10 -0
  32. package/dist-server/service/asset/index.js.map +1 -0
  33. package/dist-server/service/asset/physical-asset-class.d.ts +34 -0
  34. package/dist-server/service/asset/physical-asset-class.js +104 -0
  35. package/dist-server/service/asset/physical-asset-class.js.map +1 -0
  36. package/dist-server/service/asset/physical-asset.d.ts +53 -0
  37. package/dist-server/service/asset/physical-asset.js +123 -0
  38. package/dist-server/service/asset/physical-asset.js.map +1 -0
  39. package/dist-server/service/equipment/equipment-class.d.ts +34 -0
  40. package/dist-server/service/equipment/equipment-class.js +104 -0
  41. package/dist-server/service/equipment/equipment-class.js.map +1 -0
  42. package/dist-server/service/equipment/equipment-master-resolver.d.ts +60 -0
  43. package/dist-server/service/equipment/equipment-master-resolver.js +200 -0
  44. package/dist-server/service/equipment/equipment-master-resolver.js.map +1 -0
  45. package/dist-server/service/equipment/equipment-master.d.ts +29 -0
  46. package/dist-server/service/equipment/equipment-master.js +36 -0
  47. package/dist-server/service/equipment/equipment-master.js.map +1 -0
  48. package/dist-server/service/equipment/equipment-query.d.ts +8 -0
  49. package/dist-server/service/equipment/equipment-query.js +50 -0
  50. package/dist-server/service/equipment/equipment-query.js.map +1 -0
  51. package/dist-server/service/equipment/equipment.d.ts +45 -0
  52. package/dist-server/service/equipment/equipment.js +133 -0
  53. package/dist-server/service/equipment/equipment.js.map +1 -0
  54. package/dist-server/service/equipment/index.d.ts +8 -0
  55. package/dist-server/service/equipment/index.js +12 -0
  56. package/dist-server/service/equipment/index.js.map +1 -0
  57. package/dist-server/service/equipment/state-period-rules.d.ts +76 -0
  58. package/dist-server/service/equipment/state-period-rules.js +88 -0
  59. package/dist-server/service/equipment/state-period-rules.js.map +1 -0
  60. package/dist-server/service/equipment/stop-reason-query.d.ts +11 -0
  61. package/dist-server/service/equipment/stop-reason-query.js +39 -0
  62. package/dist-server/service/equipment/stop-reason-query.js.map +1 -0
  63. package/dist-server/service/equipment/stop-reason.d.ts +58 -0
  64. package/dist-server/service/equipment/stop-reason.js +114 -0
  65. package/dist-server/service/equipment/stop-reason.js.map +1 -0
  66. package/dist-server/service/index.d.ts +46 -0
  67. package/dist-server/service/index.js +80 -0
  68. package/dist-server/service/index.js.map +1 -0
  69. package/dist-server/service/location/index.d.ts +5 -0
  70. package/dist-server/service/location/index.js +9 -0
  71. package/dist-server/service/location/index.js.map +1 -0
  72. package/dist-server/service/location/location-master-resolver.d.ts +28 -0
  73. package/dist-server/service/location/location-master-resolver.js +80 -0
  74. package/dist-server/service/location/location-master-resolver.js.map +1 -0
  75. package/dist-server/service/location/location-master.d.ts +24 -0
  76. package/dist-server/service/location/location-master.js +27 -0
  77. package/dist-server/service/location/location-master.js.map +1 -0
  78. package/dist-server/service/location/location-query.d.ts +7 -0
  79. package/dist-server/service/location/location-query.js +41 -0
  80. package/dist-server/service/location/location-query.js.map +1 -0
  81. package/dist-server/service/location/operational-location.d.ts +52 -0
  82. package/dist-server/service/location/operational-location.js +132 -0
  83. package/dist-server/service/location/operational-location.js.map +1 -0
  84. package/dist-server/service/master-axis.d.ts +29 -0
  85. package/dist-server/service/master-axis.js +39 -0
  86. package/dist-server/service/master-axis.js.map +1 -0
  87. package/dist-server/service/master-crud.d.ts +44 -0
  88. package/dist-server/service/master-crud.js +73 -0
  89. package/dist-server/service/master-crud.js.map +1 -0
  90. package/dist-server/service/master-list.d.ts +12 -0
  91. package/dist-server/service/master-list.js +24 -0
  92. package/dist-server/service/master-list.js.map +1 -0
  93. package/dist-server/service/material/index.d.ts +6 -0
  94. package/dist-server/service/material/index.js +10 -0
  95. package/dist-server/service/material/index.js.map +1 -0
  96. package/dist-server/service/material/material-class.d.ts +34 -0
  97. package/dist-server/service/material/material-class.js +104 -0
  98. package/dist-server/service/material/material-class.js.map +1 -0
  99. package/dist-server/service/material/material-definition.d.ts +42 -0
  100. package/dist-server/service/material/material-definition.js +112 -0
  101. package/dist-server/service/material/material-definition.js.map +1 -0
  102. package/dist-server/service/material/material-master-resolver.d.ts +44 -0
  103. package/dist-server/service/material/material-master-resolver.js +140 -0
  104. package/dist-server/service/material/material-master-resolver.js.map +1 -0
  105. package/dist-server/service/material/material-master.d.ts +9 -0
  106. package/dist-server/service/material/material-master.js +24 -0
  107. package/dist-server/service/material/material-master.js.map +1 -0
  108. package/dist-server/service/material/material-query.d.ts +8 -0
  109. package/dist-server/service/material/material-query.js +50 -0
  110. package/dist-server/service/material/material-query.js.map +1 -0
  111. package/dist-server/service/operation/index.d.ts +5 -0
  112. package/dist-server/service/operation/index.js +9 -0
  113. package/dist-server/service/operation/index.js.map +1 -0
  114. package/dist-server/service/operation/operation-definition.d.ts +52 -0
  115. package/dist-server/service/operation/operation-definition.js +142 -0
  116. package/dist-server/service/operation/operation-definition.js.map +1 -0
  117. package/dist-server/service/operation/operation-master-resolver.d.ts +28 -0
  118. package/dist-server/service/operation/operation-master-resolver.js +80 -0
  119. package/dist-server/service/operation/operation-master-resolver.js.map +1 -0
  120. package/dist-server/service/operation/operation-master.d.ts +21 -0
  121. package/dist-server/service/operation/operation-master.js +28 -0
  122. package/dist-server/service/operation/operation-master.js.map +1 -0
  123. package/dist-server/service/operation/operation-query.d.ts +7 -0
  124. package/dist-server/service/operation/operation-query.js +41 -0
  125. package/dist-server/service/operation/operation-query.js.map +1 -0
  126. package/dist-server/service/personnel/index.d.ts +6 -0
  127. package/dist-server/service/personnel/index.js +10 -0
  128. package/dist-server/service/personnel/index.js.map +1 -0
  129. package/dist-server/service/personnel/person.d.ts +51 -0
  130. package/dist-server/service/personnel/person.js +119 -0
  131. package/dist-server/service/personnel/person.js.map +1 -0
  132. package/dist-server/service/personnel/personnel-class.d.ts +54 -0
  133. package/dist-server/service/personnel/personnel-class.js +114 -0
  134. package/dist-server/service/personnel/personnel-class.js.map +1 -0
  135. package/dist-server/service/personnel/personnel-master-resolver.d.ts +44 -0
  136. package/dist-server/service/personnel/personnel-master-resolver.js +140 -0
  137. package/dist-server/service/personnel/personnel-master-resolver.js.map +1 -0
  138. package/dist-server/service/personnel/personnel-master.d.ts +39 -0
  139. package/dist-server/service/personnel/personnel-master.js +34 -0
  140. package/dist-server/service/personnel/personnel-master.js.map +1 -0
  141. package/dist-server/service/personnel/personnel-query.d.ts +21 -0
  142. package/dist-server/service/personnel/personnel-query.js +57 -0
  143. package/dist-server/service/personnel/personnel-query.js.map +1 -0
  144. package/dist-server/service/personnel/qualification.d.ts +97 -0
  145. package/dist-server/service/personnel/qualification.js +122 -0
  146. package/dist-server/service/personnel/qualification.js.map +1 -0
  147. package/dist-server/service/resource/resource-class.d.ts +25 -0
  148. package/dist-server/service/resource/resource-class.js +29 -0
  149. package/dist-server/service/resource/resource-class.js.map +1 -0
  150. package/dist-server/service/status/axis-stamp.d.ts +16 -0
  151. package/dist-server/service/status/axis-stamp.js +22 -0
  152. package/dist-server/service/status/axis-stamp.js.map +1 -0
  153. package/dist-server/service/status/index.d.ts +3 -0
  154. package/dist-server/service/status/index.js +7 -0
  155. package/dist-server/service/status/index.js.map +1 -0
  156. package/dist-server/service/status/master-status.d.ts +45 -0
  157. package/dist-server/service/status/master-status.js +129 -0
  158. package/dist-server/service/status/master-status.js.map +1 -0
  159. package/dist-server/service/test-spec/index.d.ts +5 -0
  160. package/dist-server/service/test-spec/index.js +9 -0
  161. package/dist-server/service/test-spec/index.js.map +1 -0
  162. package/dist-server/service/test-spec/test-spec-master-resolver.d.ts +28 -0
  163. package/dist-server/service/test-spec/test-spec-master-resolver.js +80 -0
  164. package/dist-server/service/test-spec/test-spec-master-resolver.js.map +1 -0
  165. package/dist-server/service/test-spec/test-spec-master.d.ts +6 -0
  166. package/dist-server/service/test-spec/test-spec-master.js +18 -0
  167. package/dist-server/service/test-spec/test-spec-master.js.map +1 -0
  168. package/dist-server/service/test-spec/test-spec-query.d.ts +7 -0
  169. package/dist-server/service/test-spec/test-spec-query.js +41 -0
  170. package/dist-server/service/test-spec/test-spec-query.js.map +1 -0
  171. package/dist-server/service/test-spec/test-specification.d.ts +41 -0
  172. package/dist-server/service/test-spec/test-specification.js +106 -0
  173. package/dist-server/service/test-spec/test-specification.js.map +1 -0
  174. package/dist-server/tsconfig.tsbuildinfo +1 -0
  175. package/package.json +50 -0
  176. package/things-factory.config.js +12 -0
  177. package/translations/en.json +53 -0
  178. package/translations/ja.json +1 -0
  179. package/translations/ko.json +53 -0
  180. package/translations/ms.json +1 -0
  181. package/translations/zh.json +1 -0
package/.dockerignore ADDED
@@ -0,0 +1,31 @@
1
+ node_modules/
2
+ client/
3
+ server/
4
+ dist-client/
5
+ installer/
6
+ attachments/
7
+ cache/
8
+ logs/
9
+ Dockerfile*
10
+ docker-compose.yml
11
+ db.sqlite
12
+ db*.sqlite
13
+ license.json
14
+ config.development.js
15
+ config.production.js
16
+ !config/config.development.js
17
+ !config/config.production.js
18
+ \_index.html
19
+
20
+ npm-debug.log
21
+ yarn-error.log
22
+
23
+ .env
24
+ .env.local
25
+ .env.production
26
+ .git/
27
+ .gitignore
28
+ .dockerignore
29
+ .vscode/
30
+ .idea/
31
+ .DS_Store
@@ -0,0 +1 @@
1
+ export * from './pages/master-list';
@@ -0,0 +1,2 @@
1
+ export * from './pages/master-list';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA","sourcesContent":["export * from './pages/master-list'\n"]}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 마스터 열두 축의 **화면 쪽 선언** — 축마다 다른 것만 적는다.
3
+ *
4
+ * ── 왜 화면이 하나인가 ─────────────────────────────────────────────────────
5
+ * 열두 축의 화면이 하는 일이 같다: 목록을 보이고, 그리드에서 고치고, 저장한다. 화면을 열둘 만들면
6
+ * 규칙 하나를 고칠 때 열두 곳을 고쳐야 하고, 한 곳을 빠뜨리면 그 축만 다르게 동작한다.
7
+ *
8
+ * ── 왜 서버의 축 표와 따로 두나 ────────────────────────────────────────────
9
+ * 서버가 아는 것은 「어느 표에서 읽나 · 무엇으로 찾나」이고, 화면이 아는 것은 「어느 칸을 어떤 모양으로
10
+ * 보이나」다. 서로 다른 물음이라 한 표에 담으면 양쪽 다 지저분해진다. 축의 이름(`key`)만 같게 둔다.
11
+ */
12
+ export type ColumnType = 'string' | 'number' | 'boolean' | 'date' | 'json' | 'list';
13
+ export interface AxisColumn {
14
+ name: string;
15
+ /** 화면 문구 키. `field.<이것>`. */
16
+ label: string;
17
+ type: ColumnType;
18
+ width?: number;
19
+ /** 고칠 수 없는 칸. 자동으로 붙는 값이 여기 온다. */
20
+ readonly?: boolean;
21
+ }
22
+ export interface MasterAxisView {
23
+ key: string;
24
+ /** GraphQL 조회 이름 — 서버가 낸 그대로. */
25
+ query: string;
26
+ /** GraphQL 저장 이름. */
27
+ mutation: string;
28
+ /** 제목 문구 키. `title.<이것>`. */
29
+ title: string;
30
+ columns: AxisColumn[];
31
+ }
32
+ export declare const MASTER_AXIS_VIEWS: readonly MasterAxisView[];
33
+ export declare function masterAxisViewOf(key: string): MasterAxisView | undefined;
@@ -0,0 +1,176 @@
1
+ /**
2
+ * 마스터 열두 축의 **화면 쪽 선언** — 축마다 다른 것만 적는다.
3
+ *
4
+ * ── 왜 화면이 하나인가 ─────────────────────────────────────────────────────
5
+ * 열두 축의 화면이 하는 일이 같다: 목록을 보이고, 그리드에서 고치고, 저장한다. 화면을 열둘 만들면
6
+ * 규칙 하나를 고칠 때 열두 곳을 고쳐야 하고, 한 곳을 빠뜨리면 그 축만 다르게 동작한다.
7
+ *
8
+ * ── 왜 서버의 축 표와 따로 두나 ────────────────────────────────────────────
9
+ * 서버가 아는 것은 「어느 표에서 읽나 · 무엇으로 찾나」이고, 화면이 아는 것은 「어느 칸을 어떤 모양으로
10
+ * 보이나」다. 서로 다른 물음이라 한 표에 담으면 양쪽 다 지저분해진다. 축의 이름(`key`)만 같게 둔다.
11
+ */
12
+ /** 열두 축이 공통으로 갖는 끝 칸들 — ISA-95 유효 기간. */
13
+ const EFFECTIVE = [
14
+ { name: 'effectiveStart', label: 'effective-start', type: 'date', width: 150 },
15
+ { name: 'effectiveEnd', label: 'effective-end', type: 'date', width: 150 }
16
+ ];
17
+ /** 이름과 설명은 열두 축이 모두 갖는다. */
18
+ const IDENTITY = [
19
+ { name: 'name', label: 'name', type: 'string', width: 160 },
20
+ { name: 'description', label: 'description', type: 'string', width: 200 }
21
+ ];
22
+ export const MASTER_AXIS_VIEWS = [
23
+ {
24
+ key: 'personnelClass',
25
+ query: 'personnelClasses',
26
+ mutation: 'updateMultiplePersonnelClass',
27
+ title: 'personnel-class',
28
+ columns: [
29
+ ...IDENTITY,
30
+ { name: 'baseIds', label: 'base-classes', type: 'list', width: 180 },
31
+ /* 이 등급이 요구하는 검사. 자격 인터록이 이 칸을 읽는다 — 비어 있으면 아무 검사도 요구하지 않는다. */
32
+ { name: 'testSpecificationIds', label: 'required-tests', type: 'list', width: 200 },
33
+ ...EFFECTIVE
34
+ ]
35
+ },
36
+ {
37
+ key: 'person',
38
+ query: 'persons',
39
+ mutation: 'updateMultiplePerson',
40
+ title: 'person',
41
+ columns: [
42
+ ...IDENTITY,
43
+ { name: 'personnelClassIds', label: 'personnel-classes', type: 'list', width: 200 },
44
+ { name: 'homeLocation', label: 'home-location', type: 'string', width: 140 },
45
+ { name: 'workCalendar', label: 'work-calendar', type: 'json', width: 200 },
46
+ { name: 'testResults', label: 'test-results', type: 'json', width: 200 },
47
+ ...EFFECTIVE
48
+ ]
49
+ },
50
+ {
51
+ key: 'equipmentClass',
52
+ query: 'equipmentClasses',
53
+ mutation: 'updateMultipleEquipmentClass',
54
+ title: 'equipment-class',
55
+ columns: [...IDENTITY, { name: 'baseIds', label: 'base-classes', type: 'list', width: 180 }, ...EFFECTIVE]
56
+ },
57
+ {
58
+ key: 'equipment',
59
+ query: 'equipmentList',
60
+ mutation: 'updateMultipleEquipment',
61
+ title: 'equipment',
62
+ columns: [
63
+ ...IDENTITY,
64
+ { name: 'equipmentClassIds', label: 'equipment-classes', type: 'list', width: 200 },
65
+ { name: 'identity', label: 'identity', type: 'string', width: 200 },
66
+ { name: 'homeLocation', label: 'home-location', type: 'string', width: 140 },
67
+ /* 계획 조업 시간의 바탕. 비어 있으면 OEE 의 가동률이 「모름」이 된다. */
68
+ { name: 'workCalendar', label: 'work-calendar', type: 'json', width: 200 },
69
+ ...EFFECTIVE
70
+ ]
71
+ },
72
+ {
73
+ key: 'stopReason',
74
+ query: 'stopReasonList',
75
+ mutation: 'updateMultipleStopReason',
76
+ title: 'stop-reason',
77
+ columns: [
78
+ ...IDENTITY,
79
+ /* 어느 상태의 사유인가. 이 칸이 가동률을 깎느냐 마느냐를 가른다. */
80
+ { name: 'status', label: 'state', type: 'string', width: 130 },
81
+ { name: 'parentName', label: 'parent-reason', type: 'string', width: 150 },
82
+ { name: 'detailRequired', label: 'detail-required', type: 'boolean', width: 110 },
83
+ ...EFFECTIVE
84
+ ]
85
+ },
86
+ {
87
+ key: 'physicalAssetClass',
88
+ query: 'physicalAssetClasses',
89
+ mutation: 'updateMultiplePhysicalAssetClass',
90
+ title: 'asset-class',
91
+ columns: [
92
+ ...IDENTITY,
93
+ { name: 'baseIds', label: 'base-classes', type: 'list', width: 180 },
94
+ { name: 'testSpecificationIds', label: 'required-tests', type: 'list', width: 200 },
95
+ ...EFFECTIVE
96
+ ]
97
+ },
98
+ {
99
+ key: 'physicalAsset',
100
+ query: 'physicalAssets',
101
+ mutation: 'updateMultiplePhysicalAsset',
102
+ title: 'asset',
103
+ columns: [
104
+ ...IDENTITY,
105
+ { name: 'assetClassIds', label: 'asset-classes', type: 'list', width: 180 },
106
+ { name: 'identity', label: 'grai', type: 'string', width: 200 },
107
+ /* 정격 사용 횟수. 비어 있으면 횟수로 막지 않는다. */
108
+ { name: 'cycleLimit', label: 'cycle-limit', type: 'number', width: 110 },
109
+ { name: 'testResults', label: 'calibrations', type: 'json', width: 200 },
110
+ ...EFFECTIVE
111
+ ]
112
+ },
113
+ {
114
+ key: 'materialClass',
115
+ query: 'materialClasses',
116
+ mutation: 'updateMultipleMaterialClass',
117
+ title: 'material-class',
118
+ columns: [...IDENTITY, { name: 'baseIds', label: 'base-classes', type: 'list', width: 180 }, ...EFFECTIVE]
119
+ },
120
+ {
121
+ key: 'materialDefinition',
122
+ query: 'materialDefinitions',
123
+ mutation: 'updateMultipleMaterialDefinition',
124
+ title: 'material',
125
+ columns: [
126
+ ...IDENTITY,
127
+ { name: 'materialClassIds', label: 'material-classes', type: 'list', width: 180 },
128
+ { name: 'identity', label: 'gtin', type: 'string', width: 200 },
129
+ { name: 'uom', label: 'uom', type: 'string', width: 90 },
130
+ { name: 'locationType', label: 'location-type', type: 'string', width: 140 },
131
+ ...EFFECTIVE
132
+ ]
133
+ },
134
+ {
135
+ key: 'operationalLocation',
136
+ query: 'operationalLocations',
137
+ mutation: 'updateMultipleOperationalLocation',
138
+ title: 'location',
139
+ columns: [
140
+ ...IDENTITY,
141
+ { name: 'equipmentLevel', label: 'equipment-level', type: 'string', width: 140 },
142
+ { name: 'parentName', label: 'parent-location', type: 'string', width: 150 },
143
+ { name: 'identity', label: 'sgln', type: 'string', width: 200 },
144
+ ...EFFECTIVE
145
+ ]
146
+ },
147
+ {
148
+ key: 'operationDefinition',
149
+ query: 'operationDefinitions',
150
+ mutation: 'updateMultipleOperationDefinition',
151
+ title: 'operation',
152
+ columns: [
153
+ ...IDENTITY,
154
+ { name: 'intent', label: 'intent', type: 'string', width: 110 },
155
+ { name: 'locationType', label: 'location-type', type: 'string', width: 140 },
156
+ { name: 'resourceType', label: 'resource-type', type: 'string', width: 140 },
157
+ /* 품목당 표준 시간. 없으면 OEE 의 성능률이 「모름」이 된다. ISO 8601 기간 표기다. */
158
+ { name: 'duration', label: 'duration', type: 'string', width: 110 },
159
+ /* 요구 인원. 자격 인터록이 이 칸을 읽는다. */
160
+ { name: 'personnelSpecification', label: 'personnel-spec', type: 'json', width: 200 },
161
+ { name: 'bizStep', label: 'biz-step', type: 'string', width: 200 },
162
+ ...EFFECTIVE
163
+ ]
164
+ },
165
+ {
166
+ key: 'testSpecification',
167
+ query: 'testSpecifications',
168
+ mutation: 'updateMultipleTestSpecification',
169
+ title: 'test-specification',
170
+ columns: [...IDENTITY, ...EFFECTIVE]
171
+ }
172
+ ];
173
+ export function masterAxisViewOf(key) {
174
+ return MASTER_AXIS_VIEWS.find(axis => axis.key === key);
175
+ }
176
+ //# sourceMappingURL=master-axes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"master-axes.js","sourceRoot":"","sources":["../../client/pages/master-axes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAyBH,yCAAyC;AACzC,MAAM,SAAS,GAAiB;IAC9B,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;IAC9E,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;CAC3E,CAAA;AAED,4BAA4B;AAC5B,MAAM,QAAQ,GAAiB;IAC7B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;IAC3D,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;CAC1E,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAA8B;IAC1D;QACE,GAAG,EAAE,gBAAgB;QACrB,KAAK,EAAE,kBAAkB;QACzB,QAAQ,EAAE,8BAA8B;QACxC,KAAK,EAAE,iBAAiB;QACxB,OAAO,EAAE;YACP,GAAG,QAAQ;YACX,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YACpE,+DAA+D;YAC/D,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YACnF,GAAG,SAAS;SACb;KACF;IACD;QACE,GAAG,EAAE,QAAQ;QACb,KAAK,EAAE,SAAS;QAChB,QAAQ,EAAE,sBAAsB;QAChC,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE;YACP,GAAG,QAAQ;YACX,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YACnF,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC5E,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YAC1E,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YACxE,GAAG,SAAS;SACb;KACF;IACD;QACE,GAAG,EAAE,gBAAgB;QACrB,KAAK,EAAE,kBAAkB;QACzB,QAAQ,EAAE,8BAA8B;QACxC,KAAK,EAAE,iBAAiB;QACxB,OAAO,EAAE,CAAC,GAAG,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,GAAG,SAAS,CAAC;KAC3G;IACD;QACE,GAAG,EAAE,WAAW;QAChB,KAAK,EAAE,eAAe;QACtB,QAAQ,EAAE,yBAAyB;QACnC,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE;YACP,GAAG,QAAQ;YACX,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YACnF,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YACnE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC5E,+CAA+C;YAC/C,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YAC1E,GAAG,SAAS;SACb;KACF;IACD;QACE,GAAG,EAAE,YAAY;QACjB,KAAK,EAAE,gBAAgB;QACvB,QAAQ,EAAE,0BAA0B;QACpC,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE;YACP,GAAG,QAAQ;YACX,0CAA0C;YAC1C,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC9D,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC1E,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;YACjF,GAAG,SAAS;SACb;KACF;IACD;QACE,GAAG,EAAE,oBAAoB;QACzB,KAAK,EAAE,sBAAsB;QAC7B,QAAQ,EAAE,kCAAkC;QAC5C,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE;YACP,GAAG,QAAQ;YACX,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YACpE,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YACnF,GAAG,SAAS;SACb;KACF;IACD;QACE,GAAG,EAAE,eAAe;QACpB,KAAK,EAAE,gBAAgB;QACvB,QAAQ,EAAE,6BAA6B;QACvC,KAAK,EAAE,OAAO;QACd,OAAO,EAAE;YACP,GAAG,QAAQ;YACX,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YAC3E,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC/D,kCAAkC;YAClC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YACxE,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YACxE,GAAG,SAAS;SACb;KACF;IACD;QACE,GAAG,EAAE,eAAe;QACpB,KAAK,EAAE,iBAAiB;QACxB,QAAQ,EAAE,6BAA6B;QACvC,KAAK,EAAE,gBAAgB;QACvB,OAAO,EAAE,CAAC,GAAG,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,GAAG,SAAS,CAAC;KAC3G;IACD;QACE,GAAG,EAAE,oBAAoB;QACzB,KAAK,EAAE,qBAAqB;QAC5B,QAAQ,EAAE,kCAAkC;QAC5C,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE;YACP,GAAG,QAAQ;YACX,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YACjF,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC/D,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;YACxD,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC5E,GAAG,SAAS;SACb;KACF;IACD;QACE,GAAG,EAAE,qBAAqB;QAC1B,KAAK,EAAE,sBAAsB;QAC7B,QAAQ,EAAE,mCAAmC;QAC7C,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE;YACP,GAAG,QAAQ;YACX,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAChF,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC5E,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC/D,GAAG,SAAS;SACb;KACF;IACD;QACE,GAAG,EAAE,qBAAqB;QAC1B,KAAK,EAAE,sBAAsB;QAC7B,QAAQ,EAAE,mCAAmC;QAC7C,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE;YACP,GAAG,QAAQ;YACX,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC/D,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC5E,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAC5E,0DAA0D;YAC1D,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YACnE,8BAA8B;YAC9B,EAAE,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;YACrF,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;YAClE,GAAG,SAAS;SACb;KACF;IACD;QACE,GAAG,EAAE,mBAAmB;QACxB,KAAK,EAAE,oBAAoB;QAC3B,QAAQ,EAAE,iCAAiC;QAC3C,KAAK,EAAE,oBAAoB;QAC3B,OAAO,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,SAAS,CAAC;KACrC;CACF,CAAA;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,CAAA;AACzD,CAAC","sourcesContent":["/**\n * 마스터 열두 축의 **화면 쪽 선언** — 축마다 다른 것만 적는다.\n *\n * ── 왜 화면이 하나인가 ─────────────────────────────────────────────────────\n * 열두 축의 화면이 하는 일이 같다: 목록을 보이고, 그리드에서 고치고, 저장한다. 화면을 열둘 만들면\n * 규칙 하나를 고칠 때 열두 곳을 고쳐야 하고, 한 곳을 빠뜨리면 그 축만 다르게 동작한다.\n *\n * ── 왜 서버의 축 표와 따로 두나 ────────────────────────────────────────────\n * 서버가 아는 것은 「어느 표에서 읽나 · 무엇으로 찾나」이고, 화면이 아는 것은 「어느 칸을 어떤 모양으로\n * 보이나」다. 서로 다른 물음이라 한 표에 담으면 양쪽 다 지저분해진다. 축의 이름(`key`)만 같게 둔다.\n */\n\nexport type ColumnType = 'string' | 'number' | 'boolean' | 'date' | 'json' | 'list'\n\nexport interface AxisColumn {\n name: string\n /** 화면 문구 키. `field.<이것>`. */\n label: string\n type: ColumnType\n width?: number\n /** 고칠 수 없는 칸. 자동으로 붙는 값이 여기 온다. */\n readonly?: boolean\n}\n\nexport interface MasterAxisView {\n key: string\n /** GraphQL 조회 이름 — 서버가 낸 그대로. */\n query: string\n /** GraphQL 저장 이름. */\n mutation: string\n /** 제목 문구 키. `title.<이것>`. */\n title: string\n columns: AxisColumn[]\n}\n\n/** 열두 축이 공통으로 갖는 끝 칸들 — ISA-95 유효 기간. */\nconst EFFECTIVE: AxisColumn[] = [\n { name: 'effectiveStart', label: 'effective-start', type: 'date', width: 150 },\n { name: 'effectiveEnd', label: 'effective-end', type: 'date', width: 150 }\n]\n\n/** 이름과 설명은 열두 축이 모두 갖는다. */\nconst IDENTITY: AxisColumn[] = [\n { name: 'name', label: 'name', type: 'string', width: 160 },\n { name: 'description', label: 'description', type: 'string', width: 200 }\n]\n\nexport const MASTER_AXIS_VIEWS: readonly MasterAxisView[] = [\n {\n key: 'personnelClass',\n query: 'personnelClasses',\n mutation: 'updateMultiplePersonnelClass',\n title: 'personnel-class',\n columns: [\n ...IDENTITY,\n { name: 'baseIds', label: 'base-classes', type: 'list', width: 180 },\n /* 이 등급이 요구하는 검사. 자격 인터록이 이 칸을 읽는다 — 비어 있으면 아무 검사도 요구하지 않는다. */\n { name: 'testSpecificationIds', label: 'required-tests', type: 'list', width: 200 },\n ...EFFECTIVE\n ]\n },\n {\n key: 'person',\n query: 'persons',\n mutation: 'updateMultiplePerson',\n title: 'person',\n columns: [\n ...IDENTITY,\n { name: 'personnelClassIds', label: 'personnel-classes', type: 'list', width: 200 },\n { name: 'homeLocation', label: 'home-location', type: 'string', width: 140 },\n { name: 'workCalendar', label: 'work-calendar', type: 'json', width: 200 },\n { name: 'testResults', label: 'test-results', type: 'json', width: 200 },\n ...EFFECTIVE\n ]\n },\n {\n key: 'equipmentClass',\n query: 'equipmentClasses',\n mutation: 'updateMultipleEquipmentClass',\n title: 'equipment-class',\n columns: [...IDENTITY, { name: 'baseIds', label: 'base-classes', type: 'list', width: 180 }, ...EFFECTIVE]\n },\n {\n key: 'equipment',\n query: 'equipmentList',\n mutation: 'updateMultipleEquipment',\n title: 'equipment',\n columns: [\n ...IDENTITY,\n { name: 'equipmentClassIds', label: 'equipment-classes', type: 'list', width: 200 },\n { name: 'identity', label: 'identity', type: 'string', width: 200 },\n { name: 'homeLocation', label: 'home-location', type: 'string', width: 140 },\n /* 계획 조업 시간의 바탕. 비어 있으면 OEE 의 가동률이 「모름」이 된다. */\n { name: 'workCalendar', label: 'work-calendar', type: 'json', width: 200 },\n ...EFFECTIVE\n ]\n },\n {\n key: 'stopReason',\n query: 'stopReasonList',\n mutation: 'updateMultipleStopReason',\n title: 'stop-reason',\n columns: [\n ...IDENTITY,\n /* 어느 상태의 사유인가. 이 칸이 가동률을 깎느냐 마느냐를 가른다. */\n { name: 'status', label: 'state', type: 'string', width: 130 },\n { name: 'parentName', label: 'parent-reason', type: 'string', width: 150 },\n { name: 'detailRequired', label: 'detail-required', type: 'boolean', width: 110 },\n ...EFFECTIVE\n ]\n },\n {\n key: 'physicalAssetClass',\n query: 'physicalAssetClasses',\n mutation: 'updateMultiplePhysicalAssetClass',\n title: 'asset-class',\n columns: [\n ...IDENTITY,\n { name: 'baseIds', label: 'base-classes', type: 'list', width: 180 },\n { name: 'testSpecificationIds', label: 'required-tests', type: 'list', width: 200 },\n ...EFFECTIVE\n ]\n },\n {\n key: 'physicalAsset',\n query: 'physicalAssets',\n mutation: 'updateMultiplePhysicalAsset',\n title: 'asset',\n columns: [\n ...IDENTITY,\n { name: 'assetClassIds', label: 'asset-classes', type: 'list', width: 180 },\n { name: 'identity', label: 'grai', type: 'string', width: 200 },\n /* 정격 사용 횟수. 비어 있으면 횟수로 막지 않는다. */\n { name: 'cycleLimit', label: 'cycle-limit', type: 'number', width: 110 },\n { name: 'testResults', label: 'calibrations', type: 'json', width: 200 },\n ...EFFECTIVE\n ]\n },\n {\n key: 'materialClass',\n query: 'materialClasses',\n mutation: 'updateMultipleMaterialClass',\n title: 'material-class',\n columns: [...IDENTITY, { name: 'baseIds', label: 'base-classes', type: 'list', width: 180 }, ...EFFECTIVE]\n },\n {\n key: 'materialDefinition',\n query: 'materialDefinitions',\n mutation: 'updateMultipleMaterialDefinition',\n title: 'material',\n columns: [\n ...IDENTITY,\n { name: 'materialClassIds', label: 'material-classes', type: 'list', width: 180 },\n { name: 'identity', label: 'gtin', type: 'string', width: 200 },\n { name: 'uom', label: 'uom', type: 'string', width: 90 },\n { name: 'locationType', label: 'location-type', type: 'string', width: 140 },\n ...EFFECTIVE\n ]\n },\n {\n key: 'operationalLocation',\n query: 'operationalLocations',\n mutation: 'updateMultipleOperationalLocation',\n title: 'location',\n columns: [\n ...IDENTITY,\n { name: 'equipmentLevel', label: 'equipment-level', type: 'string', width: 140 },\n { name: 'parentName', label: 'parent-location', type: 'string', width: 150 },\n { name: 'identity', label: 'sgln', type: 'string', width: 200 },\n ...EFFECTIVE\n ]\n },\n {\n key: 'operationDefinition',\n query: 'operationDefinitions',\n mutation: 'updateMultipleOperationDefinition',\n title: 'operation',\n columns: [\n ...IDENTITY,\n { name: 'intent', label: 'intent', type: 'string', width: 110 },\n { name: 'locationType', label: 'location-type', type: 'string', width: 140 },\n { name: 'resourceType', label: 'resource-type', type: 'string', width: 140 },\n /* 품목당 표준 시간. 없으면 OEE 의 성능률이 「모름」이 된다. ISO 8601 기간 표기다. */\n { name: 'duration', label: 'duration', type: 'string', width: 110 },\n /* 요구 인원. 자격 인터록이 이 칸을 읽는다. */\n { name: 'personnelSpecification', label: 'personnel-spec', type: 'json', width: 200 },\n { name: 'bizStep', label: 'biz-step', type: 'string', width: 200 },\n ...EFFECTIVE\n ]\n },\n {\n key: 'testSpecification',\n query: 'testSpecifications',\n mutation: 'updateMultipleTestSpecification',\n title: 'test-specification',\n columns: [...IDENTITY, ...EFFECTIVE]\n }\n]\n\nexport function masterAxisViewOf(key: string): MasterAxisView | undefined {\n return MASTER_AXIS_VIEWS.find(axis => axis.key === key)\n}\n"]}
@@ -0,0 +1,68 @@
1
+ import '@material/web/icon/icon.js';
2
+ import '@operato/data-grist/ox-grist.js';
3
+ import '@operato/data-grist/ox-filters-form.js';
4
+ import '@operato/context/ox-context-page-toolbar.js';
5
+ import { FetchOption } from '@operato/data-grist';
6
+ import { PageView } from '@operato/shell';
7
+ declare const OpsMasterList_base: (new (...args: any[]) => {
8
+ __preferenceProviders: {
9
+ [element: string]: import("@operato/p13n").PagePreferenceProvider;
10
+ };
11
+ getPagePreferenceProvider(element: string): import("@operato/p13n").PagePreferenceProvider | undefined;
12
+ }) & (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
13
+ /**
14
+ * 마스터 화면 하나가 **열두 축을 다 맡는다.**
15
+ *
16
+ * 축은 주소의 질의로 받는다(`ops-master-list?axis=person`). 메뉴가 축마다 한 줄씩 걸고, 화면은 그
17
+ * 하나다 — 규칙을 고칠 때 한 곳만 고치면 열두 축이 함께 바뀐다.
18
+ *
19
+ * ── 마스터는 그리드에서 고친다 ─────────────────────────────────────────────
20
+ * 업무 기록(실적 · 검사 · 처분)은 조회 전용이다. 일어난 일을 나중에 고치면 「그때 무엇이 있었나」가
21
+ * 사라진다. 마스터는 **선언**이라 다르다 — 지금의 규정이 무엇인지가 답이고, 규정은 바뀐다.
22
+ *
23
+ * ── 없앨 때 지우지 않는다 ──────────────────────────────────────────────────
24
+ * 지운 행은 서버가 유효 기간의 끝을 채워 오늘부터 유효하지 않게 만든다. 실제로 지우면 그것을 가리키던
25
+ * 지난 실적이 가리킬 것을 잃는다. 화면은 그 사실을 말해 준다 — 지운 줄 알았는데 목록에 남아 있으면
26
+ * 사용자가 저장이 안 된 것으로 읽는다.
27
+ */
28
+ export declare class OpsMasterList extends OpsMasterList_base {
29
+ static styles: import("lit").CSSResult[];
30
+ active: boolean;
31
+ gristConfig: any;
32
+ mode: 'CARD' | 'LIST' | 'GRID';
33
+ private axis?;
34
+ private total?;
35
+ private loaded;
36
+ private grist;
37
+ get context(): {
38
+ title: string;
39
+ search: {
40
+ handler: (search: string) => void;
41
+ value: string;
42
+ };
43
+ filter: {
44
+ handler: () => void;
45
+ };
46
+ actions: {
47
+ title: string;
48
+ action: () => Promise<void>;
49
+ icon: string;
50
+ }[];
51
+ exportable: {
52
+ name: string;
53
+ data: () => any[];
54
+ };
55
+ };
56
+ render(): import("lit-html").TemplateResult<1>;
57
+ private scaleNotice;
58
+ /** 주소가 바뀌면 축이 바뀐다. 셸이 이 훅으로 알려 준다. */
59
+ pageUpdated(changes: any, lifecycle: any): Promise<void>;
60
+ private configOf;
61
+ private columnOf;
62
+ fetchHandler({ page, limit, sortings, filters }: FetchOption): Promise<{
63
+ total: any;
64
+ records: any;
65
+ }>;
66
+ private save;
67
+ }
68
+ export {};
@@ -0,0 +1,267 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import '@material/web/icon/icon.js';
3
+ import '@operato/data-grist/ox-grist.js';
4
+ import '@operato/data-grist/ox-filters-form.js';
5
+ import '@operato/context/ox-context-page-toolbar.js';
6
+ import gql from 'graphql-tag';
7
+ import { css, html } from 'lit';
8
+ import { customElement, property, query, state } from 'lit/decorators.js';
9
+ import { DataGrist } from '@operato/data-grist';
10
+ import { client } from '@operato/graphql';
11
+ import { i18next, localize } from '@operato/i18n';
12
+ import { notify } from '@operato/layout';
13
+ import { p13n } from '@operato/p13n';
14
+ import { PageView } from '@operato/shell';
15
+ import { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles } from '@operato/styles';
16
+ import { isMobileDevice } from '@operato/utils';
17
+ import { MASTER_AXIS_VIEWS, masterAxisViewOf } from './master-axes';
18
+ /**
19
+ * 마스터 화면 하나가 **열두 축을 다 맡는다.**
20
+ *
21
+ * 축은 주소의 질의로 받는다(`ops-master-list?axis=person`). 메뉴가 축마다 한 줄씩 걸고, 화면은 그
22
+ * 하나다 — 규칙을 고칠 때 한 곳만 고치면 열두 축이 함께 바뀐다.
23
+ *
24
+ * ── 마스터는 그리드에서 고친다 ─────────────────────────────────────────────
25
+ * 업무 기록(실적 · 검사 · 처분)은 조회 전용이다. 일어난 일을 나중에 고치면 「그때 무엇이 있었나」가
26
+ * 사라진다. 마스터는 **선언**이라 다르다 — 지금의 규정이 무엇인지가 답이고, 규정은 바뀐다.
27
+ *
28
+ * ── 없앨 때 지우지 않는다 ──────────────────────────────────────────────────
29
+ * 지운 행은 서버가 유효 기간의 끝을 채워 오늘부터 유효하지 않게 만든다. 실제로 지우면 그것을 가리키던
30
+ * 지난 실적이 가리킬 것을 잃는다. 화면은 그 사실을 말해 준다 — 지운 줄 알았는데 목록에 남아 있으면
31
+ * 사용자가 저장이 안 된 것으로 읽는다.
32
+ */
33
+ let OpsMasterList = class OpsMasterList extends p13n(localize(i18next)(PageView)) {
34
+ constructor() {
35
+ super(...arguments);
36
+ this.active = false;
37
+ this.mode = isMobileDevice() ? 'CARD' : 'GRID';
38
+ this.loaded = 0;
39
+ }
40
+ static { this.styles = [
41
+ CommonGristStyles,
42
+ CommonHeaderStyles,
43
+ ScrollbarStyles,
44
+ css `
45
+ :host {
46
+ display: flex;
47
+ flex-direction: column;
48
+ overflow: hidden;
49
+ }
50
+
51
+ ox-grist {
52
+ overflow-y: auto;
53
+ flex: 1;
54
+ }
55
+
56
+ .scale {
57
+ padding: var(--spacing-small) var(--spacing-large);
58
+ color: var(--md-sys-color-on-surface-variant);
59
+ font-size: 0.85rem;
60
+ }
61
+
62
+ .scale[data-capped] {
63
+ color: var(--status-warning-color);
64
+ }
65
+ `
66
+ ]; }
67
+ get context() {
68
+ return {
69
+ title: this.axis ? i18next.t(`title.${this.axis.title}`) : i18next.t('title.master'),
70
+ search: {
71
+ handler: (search) => {
72
+ this.grist.searchText = search;
73
+ },
74
+ value: this.grist?.searchText || ''
75
+ },
76
+ filter: {
77
+ handler: () => {
78
+ this.grist.toggleHeadroom();
79
+ }
80
+ },
81
+ actions: [
82
+ {
83
+ title: i18next.t('button.save'),
84
+ action: this.save.bind(this),
85
+ icon: 'save'
86
+ }
87
+ ],
88
+ exportable: {
89
+ name: this.axis ? i18next.t(`title.${this.axis.title}`) : i18next.t('title.master'),
90
+ data: () => this.grist.exportRecords()
91
+ }
92
+ };
93
+ }
94
+ render() {
95
+ if (!this.axis) {
96
+ /* 어느 축인지 모르면 빈 그리드를 보이지 않는다 — 빈 목록과 「축을 못 찾았다」가 구별되지 않는다. */
97
+ return html `<div class="scale">${i18next.t('text.master-axis-unknown')}</div>`;
98
+ }
99
+ return html `
100
+ <ox-grist .mode=${this.mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
101
+ <div slot="headroom" class="header">
102
+ <div class="title">${i18next.t(`title.${this.axis.title}`)}</div>
103
+ <ox-context-page-toolbar class="actions" .context=${this.context}></ox-context-page-toolbar>
104
+ </div>
105
+ </ox-grist>
106
+
107
+ ${this.scaleNotice()}
108
+ `;
109
+ }
110
+ scaleNotice() {
111
+ if (this.total === undefined) {
112
+ return html `<div class="scale">${i18next.t('text.loaded-count', { loaded: this.loaded })}</div>`;
113
+ }
114
+ const capped = this.loaded < this.total;
115
+ return html `
116
+ <div class="scale" ?data-capped=${capped}>
117
+ ${capped
118
+ ? i18next.t('text.loaded-of-total-more', { loaded: this.loaded, total: this.total })
119
+ : i18next.t('text.loaded-of-total', { loaded: this.loaded, total: this.total })}
120
+ </div>
121
+ `;
122
+ }
123
+ /** 주소가 바뀌면 축이 바뀐다. 셸이 이 훅으로 알려 준다. */
124
+ async pageUpdated(changes, lifecycle) {
125
+ const key = new URLSearchParams(lifecycle?.params ?? location.search).get('axis') ?? MASTER_AXIS_VIEWS[0].key;
126
+ const axis = masterAxisViewOf(key);
127
+ if (axis?.key === this.axis?.key) {
128
+ return;
129
+ }
130
+ this.axis = axis;
131
+ this.total = undefined;
132
+ this.loaded = 0;
133
+ if (axis) {
134
+ this.gristConfig = this.configOf(axis);
135
+ await this.updateComplete;
136
+ this.grist?.fetch();
137
+ }
138
+ }
139
+ configOf(axis) {
140
+ return {
141
+ list: { fields: ['name', 'description'], details: [] },
142
+ columns: [
143
+ { type: 'gutter', gutterName: 'sequence' },
144
+ { type: 'gutter', gutterName: 'row-selector', multiple: true },
145
+ ...axis.columns.map(column => this.columnOf(column))
146
+ ],
147
+ /* 새 행을 만들 수 있다 — 마스터를 채우는 것이 이 화면의 일이다. */
148
+ rows: { appendable: true, selectable: { multiple: true } },
149
+ sorters: [{ name: 'name', desc: false }]
150
+ };
151
+ }
152
+ columnOf(column) {
153
+ const header = i18next.t(`field.${column.label}`);
154
+ const editable = !column.readonly;
155
+ switch (column.type) {
156
+ case 'number':
157
+ return { type: 'float', name: column.name, header, record: { editable }, sortable: true, width: column.width };
158
+ case 'boolean':
159
+ return { type: 'boolean', name: column.name, header, record: { editable }, width: column.width };
160
+ case 'date':
161
+ return { type: 'datetime', name: column.name, header, record: { editable }, sortable: true, width: column.width };
162
+ /*
163
+ * 목록과 JSON 은 **글자로 고친다.** 전용 편집기를 만들면 축마다 다른 편집기가 생기고, 그 편집기가
164
+ * 모르는 칸이 들어오면 값이 오류 보고 없이 사라진다. 지금은 있는 그대로 보이고 그대로 고친다.
165
+ */
166
+ case 'list':
167
+ case 'json':
168
+ return { type: 'string', name: column.name, header, record: { editable }, width: column.width };
169
+ default:
170
+ return {
171
+ type: 'string',
172
+ name: column.name,
173
+ header,
174
+ record: { editable },
175
+ filter: 'search',
176
+ sortable: true,
177
+ width: column.width
178
+ };
179
+ }
180
+ }
181
+ async fetchHandler({ page = 1, limit = 50, sortings = [], filters = [] }) {
182
+ if (!this.axis) {
183
+ return { total: 0, records: [] };
184
+ }
185
+ const fields = this.axis.columns.map(column => column.name).join('\n');
186
+ const response = await client.query({
187
+ query: gql `
188
+ query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
189
+ ${this.axis.query}(filters: $filters, pagination: $pagination, sortings: $sortings) {
190
+ items {
191
+ id
192
+ ${fields}
193
+ }
194
+ total
195
+ }
196
+ }
197
+ `,
198
+ variables: { filters, pagination: { page, limit }, sortings },
199
+ fetchPolicy: 'no-cache'
200
+ });
201
+ const payload = response.data?.[this.axis.query];
202
+ const items = payload?.items ?? [];
203
+ const total = payload?.total;
204
+ this.loaded = items.length;
205
+ this.total = typeof total === 'number' ? total : undefined;
206
+ return { total: total ?? 0, records: items };
207
+ }
208
+ async save() {
209
+ if (!this.axis) {
210
+ return;
211
+ }
212
+ const patches = this.grist.dirtyRecords;
213
+ if (!patches?.length) {
214
+ notify({ message: i18next.t('text.nothing-changed'), level: 'info' });
215
+ return;
216
+ }
217
+ await client.mutate({
218
+ mutation: gql `
219
+ mutation ($patches: [ScalarObject!]!) {
220
+ ${this.axis.mutation}(patches: $patches) {
221
+ id
222
+ name
223
+ }
224
+ }
225
+ `,
226
+ variables: { patches }
227
+ });
228
+ /* 지운 행은 사라지지 않고 유효 기간의 끝이 채워진다. 말해 주지 않으면 저장이 안 된 것으로 읽는다. */
229
+ if (patches.some((patch) => String(patch.cuFlag).toUpperCase() === '-')) {
230
+ notify({ message: i18next.t('text.retired-not-deleted'), level: 'info' });
231
+ }
232
+ this.grist.fetch();
233
+ }
234
+ };
235
+ __decorate([
236
+ property({ type: Boolean }),
237
+ __metadata("design:type", Boolean)
238
+ ], OpsMasterList.prototype, "active", void 0);
239
+ __decorate([
240
+ property({ type: Object }),
241
+ __metadata("design:type", Object)
242
+ ], OpsMasterList.prototype, "gristConfig", void 0);
243
+ __decorate([
244
+ property({ type: String }),
245
+ __metadata("design:type", String)
246
+ ], OpsMasterList.prototype, "mode", void 0);
247
+ __decorate([
248
+ state(),
249
+ __metadata("design:type", Object)
250
+ ], OpsMasterList.prototype, "axis", void 0);
251
+ __decorate([
252
+ state(),
253
+ __metadata("design:type", Number)
254
+ ], OpsMasterList.prototype, "total", void 0);
255
+ __decorate([
256
+ state(),
257
+ __metadata("design:type", Object)
258
+ ], OpsMasterList.prototype, "loaded", void 0);
259
+ __decorate([
260
+ query('ox-grist'),
261
+ __metadata("design:type", DataGrist)
262
+ ], OpsMasterList.prototype, "grist", void 0);
263
+ OpsMasterList = __decorate([
264
+ customElement('ops-master-list')
265
+ ], OpsMasterList);
266
+ export { OpsMasterList };
267
+ //# sourceMappingURL=master-list.js.map