@operato/board 0.2.48 → 0.2.52

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 (127) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/assets/images/components/audio.png +0 -0
  3. package/assets/images/components/both-arrow.png +0 -0
  4. package/assets/images/components/color-image.png +0 -0
  5. package/assets/images/components/container.png +0 -0
  6. package/assets/images/components/dash.png +0 -0
  7. package/assets/images/components/donut.png +0 -0
  8. package/assets/images/components/ellipse.png +0 -0
  9. package/assets/images/components/forklift.png +0 -0
  10. package/assets/images/components/gif-image.png +0 -0
  11. package/assets/images/components/global-reference.png +0 -0
  12. package/assets/images/components/gray-image.png +0 -0
  13. package/assets/images/components/humidity-sensor.png +0 -0
  14. package/assets/images/components/info-window.png +0 -0
  15. package/assets/images/components/line.png +0 -0
  16. package/assets/images/components/local-reference.png +0 -0
  17. package/assets/images/components/person.png +0 -0
  18. package/assets/images/components/polygon.png +0 -0
  19. package/assets/images/components/polyline.png +0 -0
  20. package/assets/images/components/popup.png +0 -0
  21. package/assets/images/components/rect.png +0 -0
  22. package/assets/images/components/single-arrow.png +0 -0
  23. package/assets/images/components/star.png +0 -0
  24. package/assets/images/components/text.png +0 -0
  25. package/assets/images/components/triangle.png +0 -0
  26. package/assets/images/icon-vtoolbar.png +0 -0
  27. package/custom-elements.json +1900 -743
  28. package/dist/src/component/3d.d.ts +2 -0
  29. package/dist/src/component/3d.js +27 -0
  30. package/dist/src/component/3d.js.map +1 -0
  31. package/dist/src/component/chart-and-gauge.d.ts +2 -0
  32. package/dist/src/component/chart-and-gauge.js +26 -0
  33. package/dist/src/component/chart-and-gauge.js.map +1 -0
  34. package/dist/src/component/container.d.ts +2 -0
  35. package/dist/src/component/container.js +60 -0
  36. package/dist/src/component/container.js.map +1 -0
  37. package/dist/src/component/data-source.d.ts +2 -0
  38. package/dist/src/component/data-source.js +28 -0
  39. package/dist/src/component/data-source.js.map +1 -0
  40. package/dist/src/component/etc.d.ts +2 -0
  41. package/dist/src/component/etc.js +82 -0
  42. package/dist/src/component/etc.js.map +1 -0
  43. package/dist/src/component/form.d.ts +2 -0
  44. package/dist/src/component/form.js +40 -0
  45. package/dist/src/component/form.js.map +1 -0
  46. package/dist/src/component/index.d.ts +12 -0
  47. package/dist/src/component/index.js +13 -0
  48. package/dist/src/component/index.js.map +1 -0
  49. package/dist/src/component/iot.d.ts +2 -0
  50. package/dist/src/component/iot.js +50 -0
  51. package/dist/src/component/iot.js.map +1 -0
  52. package/dist/src/component/line.d.ts +2 -0
  53. package/dist/src/component/line.js +130 -0
  54. package/dist/src/component/line.js.map +1 -0
  55. package/dist/src/component/register-default-groups.d.ts +1 -0
  56. package/dist/src/component/register-default-groups.js +28 -0
  57. package/dist/src/component/register-default-groups.js.map +1 -0
  58. package/dist/src/component/shape.d.ts +2 -0
  59. package/dist/src/component/shape.js +152 -0
  60. package/dist/src/component/shape.js.map +1 -0
  61. package/dist/src/component/table.d.ts +2 -0
  62. package/dist/src/component/table.js +26 -0
  63. package/dist/src/component/table.js.map +1 -0
  64. package/dist/src/component/text-and-media.d.ts +2 -0
  65. package/dist/src/component/text-and-media.js +122 -0
  66. package/dist/src/component/text-and-media.js.map +1 -0
  67. package/dist/src/component/warehouse.d.ts +2 -0
  68. package/dist/src/component/warehouse.js +24 -0
  69. package/dist/src/component/warehouse.js.map +1 -0
  70. package/dist/src/graphql/board.d.ts +6 -0
  71. package/dist/src/graphql/board.js +130 -0
  72. package/dist/src/graphql/board.js.map +1 -0
  73. package/dist/src/graphql/favorite-board.d.ts +1 -0
  74. package/dist/src/graphql/favorite-board.js +23 -0
  75. package/dist/src/graphql/favorite-board.js.map +1 -0
  76. package/dist/src/graphql/group.d.ts +7 -0
  77. package/dist/src/graphql/group.js +125 -0
  78. package/dist/src/graphql/group.js.map +1 -0
  79. package/dist/src/graphql/index.d.ts +4 -0
  80. package/dist/src/graphql/index.js +5 -0
  81. package/dist/src/graphql/index.js.map +1 -0
  82. package/dist/src/graphql/play-group.d.ts +8 -0
  83. package/dist/src/graphql/play-group.js +173 -0
  84. package/dist/src/graphql/play-group.js.map +1 -0
  85. package/dist/src/modeller/component-toolbar/component-detail.d.ts +1 -1
  86. package/dist/src/modeller/component-toolbar/component-detail.js +6 -6
  87. package/dist/src/modeller/component-toolbar/component-detail.js.map +1 -1
  88. package/dist/src/modeller/component-toolbar/component-menu.js +1 -2
  89. package/dist/src/modeller/component-toolbar/component-menu.js.map +1 -1
  90. package/dist/src/modeller/component-toolbar/component-toolbar.js +26 -65
  91. package/dist/src/modeller/component-toolbar/component-toolbar.js.map +1 -1
  92. package/dist/src/ox-board-list.d.ts +2 -0
  93. package/dist/src/ox-board-list.js +427 -0
  94. package/dist/src/ox-board-list.js.map +1 -0
  95. package/dist/src/ox-board-modeller.d.ts +6 -1
  96. package/dist/src/ox-board-modeller.js +35 -3
  97. package/dist/src/ox-board-modeller.js.map +1 -1
  98. package/dist/src/types.d.ts +30 -0
  99. package/dist/src/types.js.map +1 -1
  100. package/dist/tsconfig.tsbuildinfo +1 -1
  101. package/package.json +12 -6
  102. package/src/component/3d.ts +29 -0
  103. package/src/component/chart-and-gauge.ts +28 -0
  104. package/src/component/container.ts +62 -0
  105. package/src/component/data-source.ts +30 -0
  106. package/src/component/etc.ts +87 -0
  107. package/src/component/form.ts +42 -0
  108. package/src/component/index.ts +12 -0
  109. package/src/component/iot.ts +52 -0
  110. package/src/component/line.ts +132 -0
  111. package/src/component/register-default-groups.ts +28 -0
  112. package/src/component/shape.ts +154 -0
  113. package/src/component/table.ts +28 -0
  114. package/src/component/text-and-media.ts +124 -0
  115. package/src/component/warehouse.ts +26 -0
  116. package/src/graphql/board.ts +144 -0
  117. package/src/graphql/favorite-board.ts +25 -0
  118. package/src/graphql/group.ts +138 -0
  119. package/src/graphql/index.ts +4 -0
  120. package/src/graphql/play-group.ts +189 -0
  121. package/src/modeller/component-toolbar/component-detail.ts +7 -7
  122. package/src/modeller/component-toolbar/component-menu.ts +2 -5
  123. package/src/modeller/component-toolbar/component-toolbar.ts +35 -67
  124. package/src/ox-board-list.ts +459 -0
  125. package/src/ox-board-modeller.ts +44 -5
  126. package/src/types.ts +48 -0
  127. package/yarn-error.log +0 -18355
@@ -4,10 +4,11 @@
4
4
 
5
5
  import './component-menu'
6
6
 
7
- import { css, html, LitElement, PropertyValues } from 'lit'
7
+ import { LitElement, PropertyValues, css, html } from 'lit'
8
+ import { SCENE_MODE, Scene } from '@hatiolab/things-scene'
8
9
  import { customElement, property, query, queryAll } from 'lit/decorators.js'
9
10
 
10
- import { Scene, SCENE_MODE } from '@hatiolab/things-scene'
11
+ import { ComponentGroup } from '../../types'
11
12
 
12
13
  @customElement('component-toolbar')
13
14
  class ComponentToolbar extends LitElement {
@@ -22,7 +23,7 @@ class ComponentToolbar extends LitElement {
22
23
  background-color: var(--component-toolbar-background-color);
23
24
  }
24
25
 
25
- span {
26
+ img {
26
27
  display: flex;
27
28
  flex-direction: row;
28
29
 
@@ -32,65 +33,8 @@ class ComponentToolbar extends LitElement {
32
33
 
33
34
  border-bottom: var(--component-toolbar-border);
34
35
  margin: 0;
35
- background: url(/assets/images/icon-vtoolbar.png) -1px 0 no-repeat;
36
- }
37
-
38
- span[data-group='line'] {
39
- background-position: 50% -186px;
40
- }
41
-
42
- span[data-group='shape'] {
43
- background-position: 0px -284px;
44
- }
45
-
46
- span[data-group='textAndMedia'] {
47
- background-position: 50% -385px;
48
- }
49
-
50
- span[data-group='chartAndGauge'] {
51
- background-position: 50% -488px;
52
- }
53
-
54
- span[data-group='table'] {
55
- background-position: 50% -585px;
56
- }
57
-
58
- span[data-group='container'] {
59
- background-position: 50% -685px;
60
- }
61
-
62
- span[data-group='dataSource'] {
63
- background-position: 50% -888px;
64
- }
65
-
66
- span[data-group='IoT'] {
67
- background-position: -3px -788px;
68
- }
69
-
70
- span[data-group='3D'] {
71
- background-position: 50% -992px;
72
- }
73
-
74
- span[data-group='warehouse'] {
75
- background-position: -2px -1089px;
76
- }
77
-
78
- span[data-group='form'] {
79
- background-position: -2px -1287px;
80
- }
81
-
82
- span[data-group='etc'] {
83
- background-position: -1px -1189px;
84
- }
85
-
86
- .pressed {
87
- background-position: 0 15px;
88
- }
89
-
90
- .pressed[pressed],
91
- .pressed[active] {
92
- background-position: -3px -88px;
93
- background-color: #beb9b3;
36
+ padding: 6px;
37
+ box-sizing: border-box;
94
38
  }
95
39
 
96
40
  component-menu {
@@ -107,15 +51,29 @@ class ComponentToolbar extends LitElement {
107
51
  `
108
52
  ]
109
53
 
110
- @property({ type: Array }) componentGroupList: any[] = []
54
+ @property({ type: Array }) componentGroupList: ComponentGroup[] = []
111
55
  @property({ type: String }) group?: string | null
112
56
  @property({ type: Object }) scene!: Scene
113
57
  @property({ type: Number }) mode: SCENE_MODE = SCENE_MODE.VIEW
114
58
 
115
59
  @query('component-menu') private menu!: HTMLElement
116
- @queryAll('[data-group]') groups!: NodeListOf<HTMLElement>
60
+ @queryAll('[data-group]') private groups!: NodeListOf<HTMLElement>
61
+
62
+ private icons: { [name: string]: string } = {}
117
63
 
118
64
  updated(changes: PropertyValues<this>) {
65
+ if (changes.has('componentGroupList')) {
66
+ const color = getComputedStyle(this, null).getPropertyValue('--primary-color')
67
+
68
+ this.icons = (this.componentGroupList || [])
69
+ .filter(group => group.templates?.length > 0)
70
+ .reduce((sum, group: ComponentGroup) => {
71
+ sum[group.name] =
72
+ 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(group.icon.replace(/{{strokeColor}}/g, color))
73
+ return sum
74
+ }, {} as { [name: string]: string })
75
+ }
76
+
119
77
  if (changes.has('group')) {
120
78
  this.groups.forEach(group => {
121
79
  group.getAttribute('data-group') === this.group
@@ -128,10 +86,20 @@ class ComponentToolbar extends LitElement {
128
86
  }
129
87
 
130
88
  render() {
89
+ const componentList = this.componentGroupList || []
90
+
131
91
  return html`
132
- ${this.componentGroupList
92
+ ${componentList
133
93
  .filter(group => group.templates?.length > 0)
134
- .map(item => html` <span data-group=${item.name} @click=${(e: MouseEvent) => this._onClickGroup(e)}> </span> `)}
94
+ .map(
95
+ group => html`
96
+ <img
97
+ data-group=${group.name}
98
+ @click=${(e: MouseEvent) => this._onClickGroup(e)}
99
+ .src=${this.icons[group.name]}
100
+ />
101
+ `
102
+ )}
135
103
 
136
104
  <component-menu
137
105
  tabindex="-1"
@@ -140,7 +108,7 @@ class ComponentToolbar extends LitElement {
140
108
  }}
141
109
  .scene=${this.scene}
142
110
  .group=${this.group}
143
- .groups=${this.componentGroupList}
111
+ .groups=${componentList}
144
112
  hidden
145
113
  >
146
114
  </component-menu>
@@ -0,0 +1,459 @@
1
+ import '@operato/popup'
2
+ import '@operato/data-grist'
3
+
4
+ import { Board, BoardGroup } from './types'
5
+ import { ColumnConfig, GristData, GristRecord, SortersConfig } from '@operato/data-grist/dist/src/types'
6
+ import { LitElement, css, html } from 'lit'
7
+ import { createBoard, fetchBoardList } from './graphql/board'
8
+ import { customElement, property, query, state } from 'lit/decorators'
9
+
10
+ import { DataGrist } from '@operato/data-grist'
11
+ import { OxPopup } from '@operato/popup'
12
+ import { fetchFavoriteBoardList } from './graphql/favorite-board'
13
+ import { fetchGroupList } from './graphql/group'
14
+
15
+ @customElement('ox-board-list')
16
+ class BoardList 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(--status-success-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.onCreateBoard()}>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.getBoards({ 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 fetchGroupList()).groups.items
343
+
344
+ if (this.groups) {
345
+ await this.refreshBoards()
346
+ }
347
+ }
348
+
349
+ async getBoards({
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.getFavoriteBoards({
356
+ page,
357
+ limit
358
+ })
359
+
360
+ var listParam = {
361
+ filters: this.groupId
362
+ ? [
363
+ {
364
+ name: 'group_id',
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 fetchBoardList(listParam)).boards
378
+ }
379
+
380
+ async getFavoriteBoards({ page = 1, limit = 30 } = {}) {
381
+ var listParam = {
382
+ pagination: {
383
+ page,
384
+ limit
385
+ }
386
+ }
387
+
388
+ return (await fetchFavoriteBoardList(listParam)).favoriteBoards
389
+ }
390
+
391
+ async refreshBoards() {
392
+ if (!this.groups) {
393
+ await this.refresh()
394
+ return
395
+ }
396
+
397
+ this.grist.fetch()
398
+ }
399
+
400
+ async onCreateBoard() {
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 board: Board = {
414
+ name,
415
+ description,
416
+ groupId,
417
+ model: {
418
+ width: 1200,
419
+ height: 800
420
+ }
421
+ }
422
+
423
+ const { createBoard: created } = await createBoard(board)
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
+ }
@@ -6,18 +6,20 @@ import './modeller/edit-toolbar'
6
6
  import '@hatiolab/things-scene'
7
7
  import './ox-board-viewer'
8
8
 
9
- import { saveAs } from 'file-saver'
10
- import { css, html, LitElement } from 'lit'
9
+ import { ComponentGroup, ComponentTemplate } from './types'
10
+ import { LitElement, css, html } from 'lit'
11
+ import { Model, SCENE_MODE, Scene } from '@hatiolab/things-scene'
11
12
  import { customElement, property, query } from 'lit/decorators.js'
12
13
 
13
- import { Scene, SCENE_MODE } from '@hatiolab/things-scene'
14
- import { OxPopup } from '@operato/popup'
15
-
16
14
  import { EditToolbar } from './modeller/edit-toolbar'
15
+ import { OxPopup } from '@operato/popup'
16
+ import { saveAs } from 'file-saver'
17
17
  import { togglefullscreen } from './utils/fullscreen'
18
18
 
19
19
  const isMacOS = navigator.userAgent.indexOf('Mac') != -1
20
20
 
21
+ var Registry: ComponentGroup[] = []
22
+
21
23
  @customElement('ox-board-modeller')
22
24
  export class BoardModeller extends LitElement {
23
25
  static styles = [
@@ -93,6 +95,43 @@ export class BoardModeller extends LitElement {
93
95
  `
94
96
  ]
95
97
 
98
+ static registerGroup(group: ComponentGroup) {
99
+ var found = Registry.find(inRegisterGroup => inRegisterGroup.name == group.name)
100
+
101
+ if (found) {
102
+ found = {
103
+ ...found,
104
+ ...group
105
+ }
106
+ } else {
107
+ Registry.push(group)
108
+ }
109
+ }
110
+
111
+ static registerTemplate(templates: ComponentTemplate[]): void {
112
+ templates &&
113
+ templates.forEach(template => {
114
+ var group = Registry.find(group => group.name == template.group)
115
+
116
+ if (!group) {
117
+ console.warn('Invalid group', group, template)
118
+ return
119
+ }
120
+
121
+ if (!group.templates.find(inGroupTemplate => inGroupTemplate.type == template.type)) {
122
+ group.templates.push(template)
123
+ }
124
+ })
125
+ }
126
+
127
+ static get groups(): ComponentGroup[] {
128
+ return Registry
129
+ }
130
+
131
+ static getGroup(name: string) {
132
+ return Registry.find(group => group.name === name)
133
+ }
134
+
96
135
  @property({ type: String }) boardName: string = ''
97
136
  @property({ type: Object }) model: any = null
98
137
  @property({ type: String }) baseUrl: string = ''