@operato/process 1.1.1

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 (197) hide show
  1. package/.storybook/main.js +3 -0
  2. package/.storybook/server.mjs +8 -0
  3. package/CHANGELOG.md +1824 -0
  4. package/LICENSE +21 -0
  5. package/README.md +95 -0
  6. package/demo/index-modeller.html +101 -0
  7. package/demo/index-viewer.html +101 -0
  8. package/demo/index.html +101 -0
  9. package/dist/src/data-storage/data-storage.d.ts +8 -0
  10. package/dist/src/data-storage/data-storage.js +28 -0
  11. package/dist/src/data-storage/data-storage.js.map +1 -0
  12. package/dist/src/graphql/data-subscription.d.ts +5 -0
  13. package/dist/src/graphql/data-subscription.js +24 -0
  14. package/dist/src/graphql/data-subscription.js.map +1 -0
  15. package/dist/src/graphql/favorite-process.d.ts +1 -0
  16. package/dist/src/graphql/favorite-process.js +23 -0
  17. package/dist/src/graphql/favorite-process.js.map +1 -0
  18. package/dist/src/graphql/index.d.ts +3 -0
  19. package/dist/src/graphql/index.js +4 -0
  20. package/dist/src/graphql/index.js.map +1 -0
  21. package/dist/src/graphql/process-group.d.ts +7 -0
  22. package/dist/src/graphql/process-group.js +125 -0
  23. package/dist/src/graphql/process-group.js.map +1 -0
  24. package/dist/src/graphql/process.d.ts +6 -0
  25. package/dist/src/graphql/process.js +130 -0
  26. package/dist/src/graphql/process.js.map +1 -0
  27. package/dist/src/graphql/scenario.d.ts +6 -0
  28. package/dist/src/graphql/scenario.js +69 -0
  29. package/dist/src/graphql/scenario.js.map +1 -0
  30. package/dist/src/index.d.ts +5 -0
  31. package/dist/src/index.js +6 -0
  32. package/dist/src/index.js.map +1 -0
  33. package/dist/src/modeller/component-toolbar/component-detail.d.ts +12 -0
  34. package/dist/src/modeller/component-toolbar/component-detail.js +58 -0
  35. package/dist/src/modeller/component-toolbar/component-detail.js.map +1 -0
  36. package/dist/src/modeller/component-toolbar/component-menu.d.ts +24 -0
  37. package/dist/src/modeller/component-toolbar/component-menu.js +190 -0
  38. package/dist/src/modeller/component-toolbar/component-menu.js.map +1 -0
  39. package/dist/src/modeller/component-toolbar/component-toolbar.d.ts +28 -0
  40. package/dist/src/modeller/component-toolbar/component-toolbar.js +168 -0
  41. package/dist/src/modeller/component-toolbar/component-toolbar.js.map +1 -0
  42. package/dist/src/modeller/component-toolbar/mode-icons.d.ts +2 -0
  43. package/dist/src/modeller/component-toolbar/mode-icons.js +86 -0
  44. package/dist/src/modeller/component-toolbar/mode-icons.js.map +1 -0
  45. package/dist/src/modeller/edit-toolbar-style.d.ts +4 -0
  46. package/dist/src/modeller/edit-toolbar-style.js +227 -0
  47. package/dist/src/modeller/edit-toolbar-style.js.map +1 -0
  48. package/dist/src/modeller/edit-toolbar.d.ts +61 -0
  49. package/dist/src/modeller/edit-toolbar.js +641 -0
  50. package/dist/src/modeller/edit-toolbar.js.map +1 -0
  51. package/dist/src/modeller/property-sidebar/abstract-property.d.ts +10 -0
  52. package/dist/src/modeller/property-sidebar/abstract-property.js +55 -0
  53. package/dist/src/modeller/property-sidebar/abstract-property.js.map +1 -0
  54. package/dist/src/modeller/property-sidebar/effects/effects-shared-style.d.ts +4 -0
  55. package/dist/src/modeller/property-sidebar/effects/effects-shared-style.js +61 -0
  56. package/dist/src/modeller/property-sidebar/effects/effects-shared-style.js.map +1 -0
  57. package/dist/src/modeller/property-sidebar/effects/effects.d.ts +20 -0
  58. package/dist/src/modeller/property-sidebar/effects/effects.js +42 -0
  59. package/dist/src/modeller/property-sidebar/effects/effects.js.map +1 -0
  60. package/dist/src/modeller/property-sidebar/effects/property-shadow.d.ts +23 -0
  61. package/dist/src/modeller/property-sidebar/effects/property-shadow.js +103 -0
  62. package/dist/src/modeller/property-sidebar/effects/property-shadow.js.map +1 -0
  63. package/dist/src/modeller/property-sidebar/effects/value-converter.d.ts +1 -0
  64. package/dist/src/modeller/property-sidebar/effects/value-converter.js +21 -0
  65. package/dist/src/modeller/property-sidebar/effects/value-converter.js.map +1 -0
  66. package/dist/src/modeller/property-sidebar/inspector/inspector.d.ts +29 -0
  67. package/dist/src/modeller/property-sidebar/inspector/inspector.js +318 -0
  68. package/dist/src/modeller/property-sidebar/inspector/inspector.js.map +1 -0
  69. package/dist/src/modeller/property-sidebar/property-shared-style.d.ts +4 -0
  70. package/dist/src/modeller/property-sidebar/property-shared-style.js +135 -0
  71. package/dist/src/modeller/property-sidebar/property-shared-style.js.map +1 -0
  72. package/dist/src/modeller/property-sidebar/property-sidebar.d.ts +43 -0
  73. package/dist/src/modeller/property-sidebar/property-sidebar.js +309 -0
  74. package/dist/src/modeller/property-sidebar/property-sidebar.js.map +1 -0
  75. package/dist/src/modeller/property-sidebar/shapes/box-padding-editor-styles.d.ts +1 -0
  76. package/dist/src/modeller/property-sidebar/shapes/box-padding-editor-styles.js +94 -0
  77. package/dist/src/modeller/property-sidebar/shapes/box-padding-editor-styles.js.map +1 -0
  78. package/dist/src/modeller/property-sidebar/shapes/shapes.d.ts +28 -0
  79. package/dist/src/modeller/property-sidebar/shapes/shapes.js +321 -0
  80. package/dist/src/modeller/property-sidebar/shapes/shapes.js.map +1 -0
  81. package/dist/src/modeller/property-sidebar/specifics/specific-properties-builder.d.ts +16 -0
  82. package/dist/src/modeller/property-sidebar/specifics/specific-properties-builder.js +132 -0
  83. package/dist/src/modeller/property-sidebar/specifics/specific-properties-builder.js.map +1 -0
  84. package/dist/src/modeller/property-sidebar/specifics/specifics.d.ts +25 -0
  85. package/dist/src/modeller/property-sidebar/specifics/specifics.js +81 -0
  86. package/dist/src/modeller/property-sidebar/specifics/specifics.js.map +1 -0
  87. package/dist/src/modeller/property-sidebar/styles/styles.d.ts +21 -0
  88. package/dist/src/modeller/property-sidebar/styles/styles.js +559 -0
  89. package/dist/src/modeller/property-sidebar/styles/styles.js.map +1 -0
  90. package/dist/src/modeller/scene-viewer/scene-handler.d.ts +11 -0
  91. package/dist/src/modeller/scene-viewer/scene-handler.js +32 -0
  92. package/dist/src/modeller/scene-viewer/scene-handler.js.map +1 -0
  93. package/dist/src/modeller/scene-viewer/scene-layer.d.ts +10 -0
  94. package/dist/src/modeller/scene-viewer/scene-layer.js +38 -0
  95. package/dist/src/modeller/scene-viewer/scene-layer.js.map +1 -0
  96. package/dist/src/modeller/scene-viewer/scene-property.d.ts +6 -0
  97. package/dist/src/modeller/scene-viewer/scene-property.js +15 -0
  98. package/dist/src/modeller/scene-viewer/scene-property.js.map +1 -0
  99. package/dist/src/modeller/scene-viewer/scene-viewer.d.ts +38 -0
  100. package/dist/src/modeller/scene-viewer/scene-viewer.js +243 -0
  101. package/dist/src/modeller/scene-viewer/scene-viewer.js.map +1 -0
  102. package/dist/src/ox-process-list.d.ts +2 -0
  103. package/dist/src/ox-process-list.js +427 -0
  104. package/dist/src/ox-process-list.js.map +1 -0
  105. package/dist/src/ox-process-modeller.d.ts +58 -0
  106. package/dist/src/ox-process-modeller.js +396 -0
  107. package/dist/src/ox-process-modeller.js.map +1 -0
  108. package/dist/src/ox-process-viewer.d.ts +51 -0
  109. package/dist/src/ox-process-viewer.js +512 -0
  110. package/dist/src/ox-process-viewer.js.map +1 -0
  111. package/dist/src/types.d.ts +37 -0
  112. package/dist/src/types.js +2 -0
  113. package/dist/src/types.js.map +1 -0
  114. package/dist/stories/index.stories.d.ts +33 -0
  115. package/dist/stories/index.stories.js +33 -0
  116. package/dist/stories/index.stories.js.map +1 -0
  117. package/dist/tsconfig.tsbuildinfo +1 -0
  118. package/icons/components/audio.png +0 -0
  119. package/icons/components/both-arrow.png +0 -0
  120. package/icons/components/color-image.png +0 -0
  121. package/icons/components/container.png +0 -0
  122. package/icons/components/dash.png +0 -0
  123. package/icons/components/donut.png +0 -0
  124. package/icons/components/ellipse.png +0 -0
  125. package/icons/components/forklift.png +0 -0
  126. package/icons/components/gif-image.png +0 -0
  127. package/icons/components/global-reference.png +0 -0
  128. package/icons/components/gray-image.png +0 -0
  129. package/icons/components/humidity-sensor.png +0 -0
  130. package/icons/components/info-window.png +0 -0
  131. package/icons/components/line.png +0 -0
  132. package/icons/components/local-reference.png +0 -0
  133. package/icons/components/no-image.png +0 -0
  134. package/icons/components/ortholine.png +0 -0
  135. package/icons/components/person.png +0 -0
  136. package/icons/components/polygon.png +0 -0
  137. package/icons/components/polyline.png +0 -0
  138. package/icons/components/popup.png +0 -0
  139. package/icons/components/rect.png +0 -0
  140. package/icons/components/single-arrow.png +0 -0
  141. package/icons/components/star.png +0 -0
  142. package/icons/components/streamline.png +0 -0
  143. package/icons/components/text.png +0 -0
  144. package/icons/components/triangle.png +0 -0
  145. package/icons/icon-collapse-active.png +0 -0
  146. package/icons/icon-collapse.png +0 -0
  147. package/icons/icon-fullscreen.png +0 -0
  148. package/icons/icon-htoolbar.png +0 -0
  149. package/icons/icon-properties-arrow-type.png +0 -0
  150. package/icons/icon-properties-gradient-direction.png +0 -0
  151. package/icons/icon-properties-label.png +0 -0
  152. package/icons/icon-properties-line-type.png +0 -0
  153. package/icons/icon-properties-padding.png +0 -0
  154. package/icons/icon-properties-ratio.png +0 -0
  155. package/icons/icon-properties-table.png +0 -0
  156. package/icons/icon-properties.png +0 -0
  157. package/icons/icon-shell-inspector.png +0 -0
  158. package/package.json +115 -0
  159. package/src/data-storage/data-storage.ts +47 -0
  160. package/src/graphql/data-subscription.ts +30 -0
  161. package/src/graphql/favorite-process.ts +25 -0
  162. package/src/graphql/index.ts +3 -0
  163. package/src/graphql/process-group.ts +138 -0
  164. package/src/graphql/process.ts +144 -0
  165. package/src/graphql/scenario.ts +79 -0
  166. package/src/index.ts +7 -0
  167. package/src/modeller/component-toolbar/component-detail.ts +58 -0
  168. package/src/modeller/component-toolbar/component-menu.ts +187 -0
  169. package/src/modeller/component-toolbar/component-toolbar.ts +173 -0
  170. package/src/modeller/component-toolbar/mode-icons.ts +86 -0
  171. package/src/modeller/edit-toolbar-style.ts +228 -0
  172. package/src/modeller/edit-toolbar.ts +641 -0
  173. package/src/modeller/property-sidebar/abstract-property.ts +69 -0
  174. package/src/modeller/property-sidebar/effects/effects-shared-style.ts +62 -0
  175. package/src/modeller/property-sidebar/effects/effects.ts +47 -0
  176. package/src/modeller/property-sidebar/effects/property-shadow.ts +114 -0
  177. package/src/modeller/property-sidebar/effects/value-converter.ts +23 -0
  178. package/src/modeller/property-sidebar/inspector/inspector.ts +361 -0
  179. package/src/modeller/property-sidebar/property-shared-style.ts +136 -0
  180. package/src/modeller/property-sidebar/property-sidebar.ts +308 -0
  181. package/src/modeller/property-sidebar/shapes/box-padding-editor-styles.ts +94 -0
  182. package/src/modeller/property-sidebar/shapes/shapes.ts +326 -0
  183. package/src/modeller/property-sidebar/specifics/specific-properties-builder.ts +144 -0
  184. package/src/modeller/property-sidebar/specifics/specifics.ts +77 -0
  185. package/src/modeller/property-sidebar/styles/styles.ts +577 -0
  186. package/src/modeller/scene-viewer/scene-handler.ts +39 -0
  187. package/src/modeller/scene-viewer/scene-layer.ts +41 -0
  188. package/src/modeller/scene-viewer/scene-property.ts +9 -0
  189. package/src/modeller/scene-viewer/scene-viewer.ts +249 -0
  190. package/src/ox-process-list.ts +459 -0
  191. package/src/ox-process-modeller.ts +396 -0
  192. package/src/ox-process-viewer.ts +555 -0
  193. package/src/types.ts +68 -0
  194. package/stories/index.stories.ts +52 -0
  195. package/tsconfig.json +23 -0
  196. package/web-dev-server.config.mjs +30 -0
  197. package/web-test-runner.config.mjs +29 -0
@@ -0,0 +1,249 @@
1
+ import './scene-layer'
2
+ import './scene-handler'
3
+
4
+ import { css, html, LitElement, PropertyValues } from 'lit'
5
+ import { property } from 'lit/decorators.js'
6
+
7
+ import { Component, create as createScene, FITMODE, Model, Properties, Scene, SCENE_MODE } from '@hatiolab/things-scene'
8
+
9
+ import SceneLayer from './scene-layer'
10
+
11
+ export default class SceneViewer extends LitElement {
12
+ static styles = css`
13
+ :host {
14
+ outline: none;
15
+ }
16
+ `
17
+
18
+ @property({ type: Object }) scene: Scene | null = null
19
+ @property({ type: Object }) model?: Model
20
+ /* Scene Mode - mode 0 : view mode, mode 1 : edit mode, mode 2 : shift mode */
21
+ @property({ type: Number }) mode: SCENE_MODE = SCENE_MODE.VIEW
22
+ @property({ type: Number }) screenSize: number = 13.3
23
+ @property({ type: Object }) variables: Properties = {}
24
+ @property({ type: Object }) data: any
25
+ /*
26
+ * 캔바스에 모델을 어떻게 적절하게 보여줄 것인지를 설정한다.
27
+ *
28
+ * @none 가로, 세로 스케일을 1로 고정하고, {0, 0}좌표로 translate시킨다.
29
+ * @both 캔바스에 모델을 꼭 채우도록 가로, 세로 스케일을 조정하고, {0, 0}좌표로 translate시킨다.
30
+ * @width 캔바스의 폭에 모델의 폭을 일치하도록 가로, 세로 스케일을 동일하게 조정하고, {0, 0}좌표로 translate시킨다.
31
+ * @height 캔바스의 높이에 모델의 높이를 일치하도록 가로, 세로 스케일을 동일하게 조정하고, {0, 0}좌표로 translate시킨다.
32
+ * @center 가로, 세로 스케일을 1로 고정하고 모델이 화면의 중앙에 위치하도록 translate시킨다.
33
+ * @ratio 모델의 모든 부분이 캔바스에 최대 크기로 표현될 수 있도록 가로, 세로 동일한 스케일로 조정하고, {0, 0}좌표로 translate시킨다.
34
+ */
35
+ @property({ type: String }) fit: FITMODE = 'none'
36
+ @property({ type: Array }) selected: Component[] = []
37
+ @property({ type: Boolean }) disposeWhenDetached: boolean = false
38
+ @property({ type: String }) baseUrl: string = ''
39
+ @property({ type: Object }) provider: any
40
+ @property({ type: String }) name: string = 'noname'
41
+ @property({ type: Boolean }) enableInspector: boolean = true
42
+ @property({ type: Boolean }) showInspector: boolean = false
43
+
44
+ private lastOffsetWidth?: number
45
+
46
+ disconnectedCallback() {
47
+ super.disconnectedCallback()
48
+
49
+ if (this.scene && this.disposeWhenDetached) {
50
+ this._disposeScene()
51
+ }
52
+ }
53
+
54
+ render() {
55
+ return html` <slot></slot> `
56
+ }
57
+
58
+ updated(change: PropertyValues<this>) {
59
+ change.has('model') && this._onModelChanged(this.model)
60
+ change.has('mode') && this._onModeChanged(this.mode)
61
+ change.has('screenSize') && this._onDisplayChanged(this.screenSize)
62
+ change.has('data') && this._onDataChanged(this.data)
63
+ change.has('baseUrl') && this._onBaseUrlChanged(this.baseUrl)
64
+ }
65
+
66
+ _setScene(scene: Scene | null) {
67
+ this.scene = scene
68
+ this.dispatchEvent(
69
+ new CustomEvent('scene-changed', {
70
+ bubbles: true,
71
+ composed: true,
72
+ detail: { value: scene }
73
+ })
74
+ )
75
+ }
76
+
77
+ _setMode(mode: SCENE_MODE) {
78
+ this.mode = mode
79
+ this.dispatchEvent(
80
+ new CustomEvent('mode-changed', {
81
+ bubbles: true,
82
+ composed: true,
83
+ detail: { value: mode }
84
+ })
85
+ )
86
+ }
87
+
88
+ _setVariables(variables: Properties) {
89
+ this.variables = variables
90
+ this.dispatchEvent(
91
+ new CustomEvent('variables-changed', {
92
+ bubbles: true,
93
+ composed: true,
94
+ detail: { value: variables }
95
+ })
96
+ )
97
+ }
98
+
99
+ _setSelected(selected: Component[]) {
100
+ this.selected = selected
101
+ this.dispatchEvent(
102
+ new CustomEvent('selected-changed', {
103
+ bubbles: true,
104
+ composed: true,
105
+ detail: { value: selected }
106
+ })
107
+ )
108
+ }
109
+
110
+ _disposeScene() {
111
+ if (this.scene) {
112
+ this.scene.off('selected', this._onSelectedChanged, this)
113
+ this.scene.off('mode', this._onSceneModeChanged, this)
114
+
115
+ if (this.provider) {
116
+ this.scene.release && this.scene.release()
117
+ } else {
118
+ this.scene.dispose()
119
+ }
120
+
121
+ this._setScene(null)
122
+ this._setSelected([])
123
+ }
124
+ }
125
+
126
+ resize(force: boolean) {
127
+ if (typeof this.scene == 'object') {
128
+ if (force || this.fit === 'both' || Math.abs(this.offsetWidth - (this.lastOffsetWidth || 0)) >= 1) {
129
+ requestAnimationFrame(() => {
130
+ if (this.scene) {
131
+ this.scene.resize()
132
+ this.scene.fit(this.fit)
133
+ }
134
+ })
135
+ }
136
+
137
+ this.lastOffsetWidth = this.offsetWidth
138
+ }
139
+ }
140
+
141
+ _onModelChanged(model?: Model) {
142
+ this._disposeScene()
143
+
144
+ if (!model) {
145
+ return
146
+ }
147
+
148
+ const layers = Array.from(this.querySelectorAll('scene-layer')).map(layer => (layer as SceneLayer).getModel())
149
+
150
+ const handlers = Array.from(this.querySelectorAll('scene-handler')).map(handler => handler.getAttribute('type'))
151
+
152
+ this._setScene(
153
+ createScene({
154
+ target: this,
155
+ model: JSON.parse(JSON.stringify(model)),
156
+ layers,
157
+ handlers,
158
+ mode: this.mode,
159
+ refProvider: this.provider
160
+ })
161
+ )
162
+
163
+ if (this.provider) {
164
+ this.provider.add(this.name, this.scene)
165
+ }
166
+
167
+ this.scene!.screen = this.screenSize
168
+
169
+ /* 이 컴포넌트의 폭이 값을 가지고 있으면 - 화면상에 자리를 잡고 보여지고 있음을 의미한다.
170
+ * 이 때는 정상적으로 그려주고,
171
+ * 그렇지 않으면, 다음 Resize Handling시에 처리하도록 한다.
172
+ */
173
+ this.resize(true)
174
+
175
+ this._setVariables(model.variables || this.scene!.variables)
176
+
177
+ this.scene!.on('selected', this._onSelectedChanged, this)
178
+ this.scene!.on('mode', this._onSceneModeChanged, this)
179
+
180
+ this._onModeChanged(this.mode)
181
+ this._onDisplayChanged(this.screenSize)
182
+ this._onBaseUrlChanged(this.baseUrl)
183
+ }
184
+
185
+ _onDisplayChanged(screenSize: string | number) {
186
+ if (!this.scene) {
187
+ return
188
+ }
189
+
190
+ if (screenSize) {
191
+ this.scene.screen = parseFloat(String(screenSize))
192
+ }
193
+ }
194
+
195
+ _onModeChanged(mode: SCENE_MODE) {
196
+ if (!this.scene) {
197
+ return
198
+ }
199
+ this.scene.mode = Number(mode)
200
+ }
201
+
202
+ _onDataChanged(data: any) {
203
+ if (!this.scene || !data) {
204
+ return
205
+ }
206
+
207
+ this.scene.data = data
208
+ }
209
+
210
+ _onSelectedChanged(after: Component[]) {
211
+ /*
212
+ scene 컴포넌트의 속성을 속성 에디터(input box등)에서 변경하다가,
213
+ scene의 다른 컴포넌트를 클릭해서 포커스(선택) 컴포넌트를 변경하게되면,
214
+ 속성 에디터(input box등)의 value change 이벤트의 처리와 충돌(레이스)하게된다.
215
+
216
+ 기대하는 순서는 먼저 속성 에디터의 value change 이벤트를 처리한 후에,
217
+ selected 이벤트를 처리할 수 있도록 requestAnimationFrame으로 한 프레임을 지연하도록 하였다.
218
+ */
219
+ requestAnimationFrame(() => {
220
+ this._setSelected(after)
221
+ })
222
+ }
223
+
224
+ _onSceneModeChanged(after: SCENE_MODE) {
225
+ if (!this.scene) {
226
+ return
227
+ }
228
+
229
+ if (this.mode !== after) {
230
+ this._setMode(after)
231
+ }
232
+
233
+ if (after === 2) {
234
+ this.style.cursor = 'all-scroll'
235
+ } else if (after === 3) {
236
+ this.style.cursor = 'crosshair'
237
+ } else {
238
+ this.style.cursor = 'default'
239
+ }
240
+ }
241
+
242
+ _onBaseUrlChanged(after: string) {
243
+ if (!this.scene) {
244
+ return
245
+ }
246
+
247
+ this.scene.baseUrl = after
248
+ }
249
+ }
@@ -0,0 +1,459 @@
1
+ import '@operato/popup/ox-popup.js'
2
+ import '@operato/data-grist'
3
+
4
+ import { css, html, LitElement } from 'lit'
5
+ import { customElement, property, query, state } from 'lit/decorators.js'
6
+
7
+ import { ColumnConfig, DataGrist, GristData, GristRecord, SortersConfig } from '@operato/data-grist'
8
+ import { OxPopup } from '@operato/popup'
9
+
10
+ import { createProcess, fetchProcessList } from './graphql/process'
11
+ import { fetchFavoriteProcessList } from './graphql/favorite-process'
12
+ import { fetchProcessGroupList } from './graphql/process-group'
13
+ import { Process } from './types'
14
+
15
+ @customElement('ox-process-list')
16
+ class ProcessList extends LitElement {
17
+ static styles = css`
18
+ :host {
19
+ display: flex;
20
+
21
+ width: 100%;
22
+
23
+ --grid-record-emphasized-background-color: red;
24
+ --grid-record-emphasized-color: yellow;
25
+ }
26
+
27
+ ox-grist {
28
+ flex: 1;
29
+ overflow-y: auto;
30
+
31
+ --grid-record-emphasized-background-color: red;
32
+ --grid-record-emphasized-color: yellow;
33
+ }
34
+
35
+ #headroom {
36
+ display: flex;
37
+ flex-direction: row;
38
+ align-items: center;
39
+ padding: var(--padding-default) var(--padding-wide);
40
+ border-top: 2px solid rgba(0, 0, 0, 0.2);
41
+ background-color: var(--theme-white-color);
42
+ box-shadow: var(--box-shadow);
43
+ }
44
+
45
+ #filters {
46
+ flex: 1;
47
+ --mdc-icon-size: 20px;
48
+ }
49
+ #mode {
50
+ width: 100px;
51
+ }
52
+ #add {
53
+ width: 50px;
54
+ text-align: right;
55
+ }
56
+
57
+ #modes > * {
58
+ padding: var(--padding-narrow);
59
+ font-size: 1em;
60
+ opacity: 0.5;
61
+ color: var(--primary-text-color);
62
+ cursor: pointer;
63
+ }
64
+
65
+ #modes > mwc-icon[active] {
66
+ border-radius: 9px;
67
+ background-color: rgba(var(--primary-color-rgb), 0.05);
68
+ opacity: 1;
69
+ color: var(--secondary-text-color);
70
+ cursor: default;
71
+ }
72
+ #modes > mwc-icon:hover {
73
+ opacity: 1;
74
+ color: var(--secondary-text-color);
75
+ }
76
+
77
+ #add button {
78
+ background-color: var(--primary-color);
79
+ border: 0;
80
+ border-radius: 50%;
81
+ padding: 5px;
82
+ width: 36px;
83
+ height: 36px;
84
+ cursor: pointer;
85
+ }
86
+ #add button:hover {
87
+ background-color: var(--focus-background-color);
88
+ box-shadow: var(--box-shadow);
89
+ }
90
+ #add button mwc-icon {
91
+ font-size: 2em;
92
+ color: var(--theme-white-color);
93
+ }
94
+
95
+ #filters {
96
+ position: relative;
97
+ }
98
+ #filters [type='text'] {
99
+ background-color: transparent;
100
+ border: 0;
101
+ border-bottom: var(--border-dark-color);
102
+ padding: var(--padding-narrow) var(--padding-narrow) 7px 25px;
103
+ font-size: var(--fontsize-large);
104
+ }
105
+ #filters [type='text']:focus {
106
+ outline: none;
107
+ }
108
+ #filters mwc-icon {
109
+ position: absolute;
110
+ top: 3px;
111
+ color: var(--secondary-color);
112
+ }
113
+ #filters * {
114
+ margin-right: var(--margin-default);
115
+ }
116
+
117
+ oops-spinner {
118
+ display: none;
119
+ position: absolute;
120
+ left: 50%;
121
+ top: 50%;
122
+ transform: translate(-50%, -50%);
123
+ }
124
+
125
+ oops-spinner[show] {
126
+ display: block;
127
+ }
128
+
129
+ @media only screen and (max-width: 460px) {
130
+ #modes {
131
+ display: none;
132
+ }
133
+ }
134
+ `
135
+
136
+ @property({ type: Boolean }) creatable: boolean = false
137
+ @property({ type: Object }) config: any
138
+ @property({ type: Object }) data: any
139
+ @property({ type: String }) mode: 'GRID' | 'LIST' | 'CARD' = 'CARD'
140
+ @property({ type: String }) groupId?: string
141
+ @property({ type: Array }) groups: any[] = []
142
+ @property({ type: Array }) favorites: any[] = []
143
+
144
+ @state() _showSpinner: boolean = false
145
+
146
+ @query('ox-grist') grist!: DataGrist
147
+
148
+ render() {
149
+ const mode = this.mode || 'CARD'
150
+
151
+ return html`
152
+ <ox-grist .config=${this.config} .mode=${mode} auto-fetch .fetchHandler=${this.fetchHandler.bind(this)}>
153
+ <div slot="headroom" id="headroom">
154
+ <div id="filters">
155
+ <mwc-icon>search</mwc-icon>
156
+ <input type="text" />
157
+
158
+ <select
159
+ @change=${(e: Event) => {
160
+ this.groupId = (e.currentTarget as HTMLInputElement).value
161
+ this.requestUpdate()
162
+ }}
163
+ >
164
+ <option value="">*</option>
165
+ ${this.groups.map(
166
+ group =>
167
+ html` <option value=${group.id} ?selected=${group.id === this.groupId}>${group.description}</option> `
168
+ )}
169
+ </select>
170
+ </div>
171
+
172
+ <div id="modes">
173
+ <mwc-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</mwc-icon>
174
+ <mwc-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>format_list_bulleted</mwc-icon>
175
+ <mwc-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</mwc-icon>
176
+ </div>
177
+
178
+ ${this.creatable
179
+ ? html`
180
+ <div id="add">
181
+ <button><mwc-icon @click=${() => this.onCreateProcess()}>add</mwc-icon></button>
182
+ </div>
183
+ `
184
+ : undefined}
185
+ </div>
186
+ </ox-grist>
187
+
188
+ <oops-spinner ?show=${this._showSpinner}></oops-spinner>
189
+ `
190
+ }
191
+
192
+ async fetchHandler({ page, limit, sorters = [] }: { page: number; limit: number; sorters: SortersConfig }) {
193
+ this._showSpinner = true
194
+
195
+ const { items: records, total } = await this.getProcesses({ page, limit, sorters })
196
+
197
+ this._showSpinner = false
198
+
199
+ return {
200
+ total,
201
+ records
202
+ }
203
+ }
204
+
205
+ get gristConfig() {
206
+ return {
207
+ list: {
208
+ thumbnail: function (record: GristRecord, rowIndex: number) {
209
+ return html` <img src=${record.thumbnail} style="width: 100%; height: 100%;" /> `
210
+ },
211
+ fields: ['name', 'description'],
212
+ details: ['updatedAt']
213
+ },
214
+ columns: [
215
+ {
216
+ type: 'gutter',
217
+ gutterName: 'dirty'
218
+ },
219
+ {
220
+ type: 'gutter',
221
+ gutterName: 'sequence'
222
+ },
223
+ {
224
+ type: 'gutter',
225
+ gutterName: 'button',
226
+ icon: 'star_border',
227
+ handlers: {
228
+ click: (
229
+ columns: ColumnConfig[],
230
+ data: GristData,
231
+ column: ColumnConfig,
232
+ record: GristRecord,
233
+ rowIndex: number
234
+ ): void => {}
235
+ }
236
+ },
237
+ {
238
+ type: 'gutter',
239
+ gutterName: 'button',
240
+ icon: 'drive_file_rename_outline',
241
+ handlers: {
242
+ click: (
243
+ columns: ColumnConfig[],
244
+ data: GristData,
245
+ column: ColumnConfig,
246
+ record: GristRecord,
247
+ rowIndex: number
248
+ ): void => {}
249
+ }
250
+ },
251
+ {
252
+ type: 'string',
253
+ name: 'id',
254
+ hidden: true
255
+ },
256
+ {
257
+ type: 'string',
258
+ name: 'name',
259
+ header: 'name',
260
+ record: {
261
+ editable: true,
262
+ align: 'left'
263
+ },
264
+ width: 200,
265
+ sortable: true
266
+ },
267
+ {
268
+ type: 'string',
269
+ name: 'description',
270
+ header: 'description',
271
+ record: {
272
+ editable: true,
273
+ align: 'left'
274
+ },
275
+ width: 200,
276
+ handlers: {
277
+ dblclick: (
278
+ columns: ColumnConfig[],
279
+ data: GristData,
280
+ column: ColumnConfig,
281
+ record: GristRecord,
282
+ rowIndex: number
283
+ ): void => {
284
+ alert(`${column.name} ${record[column.name]}, row : ${rowIndex}`)
285
+ }
286
+ }
287
+ },
288
+ {
289
+ type: 'boolean',
290
+ name: 'active',
291
+ header: 'active',
292
+ record: {
293
+ editable: true
294
+ },
295
+ sortable: true,
296
+ width: 60
297
+ },
298
+ {
299
+ type: 'datetime',
300
+ name: 'updatedAt',
301
+ header: 'updated at',
302
+ record: {
303
+ editable: true
304
+ },
305
+ sortable: true,
306
+ width: 180
307
+ },
308
+ {
309
+ type: 'datetime',
310
+ name: 'createdAt',
311
+ header: 'created at',
312
+ record: {
313
+ editable: true
314
+ },
315
+ sortable: true,
316
+ width: 180
317
+ }
318
+ ],
319
+ rows: {
320
+ selectable: {
321
+ multiple: true
322
+ },
323
+ handlers: {},
324
+ classifier: function (
325
+ record: GristRecord,
326
+ rowIndex: number
327
+ ): { emphasized?: boolean | string | string[]; [key: string]: any } | void {}
328
+ },
329
+ sorters: [
330
+ {
331
+ name: 'name',
332
+ desc: false
333
+ }
334
+ ],
335
+ pagination: {
336
+ pages: [20, 30, 50, 100, 200]
337
+ }
338
+ }
339
+ }
340
+
341
+ async refresh() {
342
+ this.groups = (await fetchProcessGroupList()).processGroups.items
343
+
344
+ if (this.groups) {
345
+ await this.refreshProcesses()
346
+ }
347
+ }
348
+
349
+ async getProcesses({
350
+ page = 1,
351
+ limit = 30,
352
+ sorters = []
353
+ }: { page?: number; limit?: number; sorters?: SortersConfig } = {}) {
354
+ if (this.groupId && this.groupId == 'favor')
355
+ return await this.getFavoriteProcesses({
356
+ page,
357
+ limit
358
+ })
359
+
360
+ var listParam = {
361
+ filters: this.groupId
362
+ ? [
363
+ {
364
+ name: 'groupId',
365
+ operator: 'eq',
366
+ value: this.groupId
367
+ }
368
+ ]
369
+ : [],
370
+ sortings: sorters,
371
+ pagination: {
372
+ page,
373
+ limit
374
+ }
375
+ }
376
+
377
+ return (await fetchProcessList(listParam)).processes
378
+ }
379
+
380
+ async getFavoriteProcesses({ page = 1, limit = 30 } = {}) {
381
+ var listParam = {
382
+ pagination: {
383
+ page,
384
+ limit
385
+ }
386
+ }
387
+
388
+ return (await fetchFavoriteProcessList(listParam)).favoriteProcesses
389
+ }
390
+
391
+ async refreshProcesses() {
392
+ if (!this.groups) {
393
+ await this.refresh()
394
+ return
395
+ }
396
+
397
+ this.grist.fetch()
398
+ }
399
+
400
+ async onCreateProcess() {
401
+ /*
402
+ * 기존 설정된 이미지가 선택된 상태가 되게 하기 위해서는 selector에 value를 전달해줄 필요가 있음.
403
+ * 주의. value는 object일 수도 있고, string일 수도 있다.
404
+ * string인 경우에는 해당 보드의 id로 해석한다.
405
+ */
406
+ var template = html`
407
+ <process-creation-popup
408
+ .defaultGroup=${this.groupId}
409
+ .groups=${this.groups}
410
+ @create-process=${async (e: CustomEvent) => {
411
+ try {
412
+ var { name, description, groupId } = e.detail
413
+ var process: Process = {
414
+ name,
415
+ description,
416
+ groupId,
417
+ model: {
418
+ width: 1200,
419
+ height: 800
420
+ }
421
+ }
422
+
423
+ const { createProcess: created } = await createProcess(process)
424
+
425
+ // this.popup && this.popup.close()
426
+
427
+ // await sleep(100)
428
+
429
+ this.notify('info', 'new process created')
430
+ } catch (ex: Error | any) {
431
+ console.error(ex)
432
+ this.notify('error', ex, ex)
433
+ }
434
+ }}
435
+ ></process-creation-popup>
436
+ `
437
+
438
+ OxPopup.open({
439
+ template,
440
+ parent: this.renderRoot as Element
441
+ })
442
+
443
+ requestAnimationFrame(() => {
444
+ dispatchEvent(new Event('resize'))
445
+ })
446
+ }
447
+
448
+ notify(level: 'warn' | 'error' | 'info', message: any, ex?: Error) {
449
+ document.dispatchEvent(
450
+ new CustomEvent('notify', {
451
+ detail: {
452
+ level,
453
+ message,
454
+ ex
455
+ }
456
+ })
457
+ )
458
+ }
459
+ }