@things-factory/menu-ui 8.0.0 → 9.0.0-beta.3

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 (56) hide show
  1. package/dist-client/apptools/favorite-tool.d.ts +28 -0
  2. package/dist-client/apptools/favorite-tool.js +139 -0
  3. package/dist-client/apptools/favorite-tool.js.map +1 -0
  4. package/dist-client/bootstrap.d.ts +4 -0
  5. package/dist-client/bootstrap.js +52 -0
  6. package/dist-client/bootstrap.js.map +1 -0
  7. package/dist-client/components/child-menus-selector.d.ts +1 -0
  8. package/dist-client/components/child-menus-selector.js +146 -0
  9. package/dist-client/components/child-menus-selector.js.map +1 -0
  10. package/dist-client/components/role-select-popup.d.ts +1 -0
  11. package/dist-client/components/role-select-popup.js +180 -0
  12. package/dist-client/components/role-select-popup.js.map +1 -0
  13. package/dist-client/index.js +2 -0
  14. package/dist-client/index.js.map +1 -0
  15. package/dist-client/pages/menu-list-page.d.ts +2 -0
  16. package/dist-client/pages/menu-list-page.js +204 -0
  17. package/dist-client/pages/menu-list-page.js.map +1 -0
  18. package/dist-client/pages/menu-management-detail.d.ts +2 -0
  19. package/dist-client/pages/menu-management-detail.js +376 -0
  20. package/dist-client/pages/menu-management-detail.js.map +1 -0
  21. package/dist-client/pages/menu-management.d.ts +3 -0
  22. package/dist-client/pages/menu-management.js +280 -0
  23. package/dist-client/pages/menu-management.js.map +1 -0
  24. package/dist-client/pages/role-menus-management.d.ts +4 -0
  25. package/dist-client/pages/role-menus-management.js +215 -0
  26. package/dist-client/pages/role-menus-management.js.map +1 -0
  27. package/dist-client/route.d.ts +1 -0
  28. package/dist-client/route.js +14 -0
  29. package/dist-client/route.js.map +1 -0
  30. package/dist-client/tsconfig.tsbuildinfo +1 -0
  31. package/dist-client/viewparts/menu-bar.d.ts +12 -0
  32. package/dist-client/viewparts/menu-bar.js +108 -0
  33. package/dist-client/viewparts/menu-bar.js.map +1 -0
  34. package/dist-client/viewparts/menu-tile-list.d.ts +13 -0
  35. package/dist-client/viewparts/menu-tile-list.js +234 -0
  36. package/dist-client/viewparts/menu-tile-list.js.map +1 -0
  37. package/dist-client/viewparts/menu-tree-bar.d.ts +28 -0
  38. package/dist-client/viewparts/menu-tree-bar.js +307 -0
  39. package/dist-client/viewparts/menu-tree-bar.js.map +1 -0
  40. package/package.json +21 -18
  41. package/things-factory.config.js +5 -14
  42. package/client/apptools/favorite-tool.js +0 -130
  43. package/client/bootstrap.js +0 -57
  44. package/client/components/child-menus-selector.js +0 -150
  45. package/client/components/role-select-popup.js +0 -179
  46. package/client/pages/menu-list-page.js +0 -200
  47. package/client/pages/menu-management-detail.js +0 -384
  48. package/client/pages/menu-management.js +0 -294
  49. package/client/pages/role-menus-management.js +0 -215
  50. package/client/route.js +0 -15
  51. package/client/viewparts/menu-bar.js +0 -114
  52. package/client/viewparts/menu-tile-list.js +0 -222
  53. package/client/viewparts/menu-tree-bar.js +0 -295
  54. package/server/index.ts +0 -0
  55. /package/{client/index.js → dist-client/index.d.ts} +0 -0
  56. /package/{client → dist-client}/themes/menu-theme.css +0 -0
@@ -1,200 +0,0 @@
1
- import '../viewparts/menu-bar'
2
- import '../viewparts/menu-tile-list'
3
-
4
- import gql from 'graphql-tag'
5
- import { css, html } from 'lit'
6
- import { connect } from 'pwa-helpers/connect-mixin.js'
7
-
8
- import { client, navigate, PageView, store } from '@things-factory/shell'
9
- import { ScrollbarStyles } from '@operato/styles'
10
- import { pulltorefresh, swipe } from '@things-factory/utils'
11
-
12
- class MenuListPage extends connect(store)(PageView) {
13
- static get styles() {
14
- return [
15
- ScrollbarStyles,
16
- css`
17
- :host {
18
- display: flex;
19
- flex-direction: column;
20
-
21
- overflow: hidden;
22
- }
23
-
24
- menu-bar {
25
- z-index: 1;
26
- }
27
-
28
- menu-tile-list {
29
- flex: 1;
30
- overflow-y: auto;
31
- }
32
- `
33
- ]
34
- }
35
-
36
- static get properties() {
37
- return {
38
- menuId: String,
39
- menus: Array,
40
- routingTypes: Object,
41
- favorites: Array,
42
- user: Object,
43
- showSpinner: Boolean
44
- }
45
- }
46
-
47
- render() {
48
- return html`
49
- <menu-bar .menus=${this.menus} .menuId=${this.menuId}></menu-bar>
50
-
51
- <menu-tile-list
52
- .menus=${this.menus}
53
- .routingTypes=${this.routingTypes}
54
- .menuId=${this.menuId}
55
- .favorites=${this.favorites}
56
- .showSpinner=${this.showSpinner}
57
- ></menu-tile-list>
58
- `
59
- }
60
-
61
- get context() {
62
- return {
63
- title: 'Menu'
64
- }
65
- }
66
-
67
- async fetchMenus() {
68
- const response = await client.query({
69
- query: gql`
70
- query {
71
- userMenus {
72
- id
73
- name
74
- role {
75
- id
76
- name
77
- description
78
- }
79
- children {
80
- id
81
- name
82
- routingType
83
- idField
84
- titleField
85
- resourceName
86
- resourceUrl
87
- template
88
- role {
89
- id
90
- name
91
- description
92
- }
93
- }
94
- }
95
- }
96
- `
97
- })
98
-
99
- return response.data.userMenus
100
- }
101
-
102
- async updated(changes) {
103
- if (changes.has('user')) {
104
- if (this.user && this.user.email) {
105
- this.refresh()
106
- }
107
- }
108
- }
109
-
110
- stateChanged(state) {
111
- this.page = state.route.page
112
- this.routingTypes = state.menu.routingTypes
113
- this.menuId = state.route.resourceId
114
- this.favorites = state.favorite.favorites
115
- this.user = state.auth.user
116
-
117
- var provider = state.menu.provider
118
- this.getMenus = typeof provider === 'function' ? provider.bind(this) : this.fetchMenus
119
- }
120
-
121
- async refresh() {
122
- this.showSpinner = true
123
- this.menus = await this.getMenus()
124
- this.showSpinner = false
125
- }
126
-
127
- async firstUpdated() {
128
- var list = this.shadowRoot.querySelector('menu-tile-list')
129
-
130
- pulltorefresh({
131
- container: this.shadowRoot,
132
- scrollable: list,
133
- refresh: () => {
134
- return this.refresh()
135
- }
136
- })
137
-
138
- swipe({
139
- container: this.shadowRoot.querySelector('menu-tile-list'),
140
- animates: {
141
- dragging: async (d, opts) => {
142
- var currentIndex = Number(this.menuId)
143
- var isHome = this.menuId === '' || this.menuId === undefined
144
-
145
- if ((d > 0 && isHome) || (d < 0 && currentIndex >= this.menus.length - 1)) {
146
- /* TODO blocked gesture */
147
- return false
148
- }
149
-
150
- list.style.transform = `translate3d(${d}px, 0, 0)`
151
- },
152
- aborting: async opts => {
153
- list.style.transition = 'transform 0.3s'
154
- list.style.transform = `translate3d(0, 0, 0)`
155
-
156
- setTimeout(() => {
157
- list.style.transition = ''
158
- }, 300)
159
- },
160
- swiping: async (d, opts) => {
161
- var currentIndex = Number(this.menuId)
162
- var isHome = this.menuId === '' || this.menuId === undefined
163
-
164
- if ((d > 0 && isHome) || (d < 0 && currentIndex >= this.menus.length - 1)) {
165
- list.style.transform = `translate3d(0, 0, 0)`
166
-
167
- return
168
- }
169
-
170
- list.style.transition = 'transform 0.3s'
171
- list.style.transform = `translate3d(${d < 0 ? '-100%' : '100%'}, 0, 0)`
172
-
173
- setTimeout(() => {
174
- if (isHome) {
175
- navigate(`${this.page}/0`)
176
- } else if (d > 0 && currentIndex == 0) {
177
- navigate(`${this.page}`)
178
- } else {
179
- navigate(`${this.page}/${currentIndex + (d < 0 ? 1 : -1)}`)
180
- }
181
-
182
- list.style.transition = ''
183
- list.style.transform = `translate3d(${d < 0 ? '100%' : '-100%'}, 0, 0)`
184
-
185
- requestAnimationFrame(() => {
186
- list.style.transition = 'transform 0.3s'
187
- list.style.transform = `translate3d(0, 0, 0)`
188
- })
189
- }, 300)
190
- }
191
- }
192
- })
193
-
194
- await this.updateComplete
195
-
196
- this.refresh()
197
- }
198
- }
199
-
200
- window.customElements.define('menu-list-page', MenuListPage)
@@ -1,384 +0,0 @@
1
- import '@things-factory/form-ui'
2
- import '@operato/data-grist'
3
-
4
- import gql from 'graphql-tag'
5
- import { css, html, LitElement } from 'lit'
6
-
7
- import { getEditor, getRenderer } from '@operato/data-grist'
8
- import { i18next, localize } from '@operato/i18n'
9
- import { client } from '@operato/graphql'
10
- import { ScrollbarStyles } from '@operato/styles'
11
- import { gqlBuilder, isMobileDevice } from '@things-factory/utils'
12
-
13
- import { OxPrompt } from '@operato/popup/ox-prompt.js'
14
-
15
- class MenuManagementDetail extends localize(i18next)(LitElement) {
16
- static get styles() {
17
- return [
18
- ScrollbarStyles,
19
- css`
20
- :host {
21
- display: flex;
22
- flex-direction: column;
23
- overflow: hidden;
24
- background-color: var(--md-sys-color-surface);
25
- }
26
- search-form {
27
- overflow: visible;
28
- }
29
- .grist {
30
- display: flex;
31
- flex-direction: column;
32
- flex: 1;
33
- overflow-y: auto;
34
- }
35
- ox-grist {
36
- overflow-y: hidden;
37
- flex: 1;
38
- }
39
- .button-container {
40
- padding: 10px 0 12px 0;
41
- text-align: center;
42
- }
43
- .button-container > button {
44
- background-color: var(--button-background-color);
45
- border: var(--button-border);
46
- border-radius: var(--button-border-radius);
47
- margin: var(--button-margin);
48
- padding: var(--button-padding);
49
- color: var(--button-color);
50
- font: var(--button-font);
51
- text-transform: var(--button-text-transform);
52
- }
53
- .button-container > button:hover,
54
- .button-container > button:active {
55
- background-color: var(--button-background-focus-color);
56
- }
57
- `
58
- ]
59
- }
60
-
61
- static get properties() {
62
- return {
63
- menuId: String,
64
- searchFields: Object,
65
- config: Object
66
- }
67
- }
68
-
69
- render() {
70
- return html`
71
- <search-form .fields=${this.searchFields} @submit=${e => this.dataGrist.fetch()}></search-form>
72
-
73
- <div class="grist">
74
- <ox-grist
75
- .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
76
- .config=${this.config}
77
- .fetchHandler=${this.fetchHandler.bind(this)}
78
- ></ox-grist>
79
- </div>
80
-
81
- <div class="button-container">
82
- <button @click=${this.save}>${i18next.t('button.save')}</button>
83
- <button @click=${this.delete}>${i18next.t('button.delete')}</button>
84
- </div>
85
- `
86
- }
87
-
88
- get searchForm() {
89
- return this.shadowRoot.querySelector('search-form')
90
- }
91
-
92
- get dataGrist() {
93
- return this.shadowRoot.querySelector('ox-grist')
94
- }
95
-
96
- firstUpdated() {
97
- this.searchFields = [
98
- {
99
- name: 'name',
100
- label: i18next.t('field.name'),
101
- type: 'text',
102
- props: { searchOper: 'i_like' }
103
- },
104
- {
105
- name: 'description',
106
- label: i18next.t('field.description'),
107
- type: 'text',
108
- props: { searchOper: 'i_like' }
109
- },
110
- {
111
- name: 'template',
112
- label: i18next.t('field.template'),
113
- type: 'text',
114
- props: { searchOper: 'i_like' }
115
- },
116
- {
117
- name: 'category',
118
- label: i18next.t('field.category'),
119
- type: 'text',
120
- props: { searchOper: 'i_like' }
121
- },
122
- {
123
- name: 'resourceUrl',
124
- label: i18next.t('field.resource_url'),
125
- type: 'text',
126
- props: { searchOper: 'i_like' }
127
- },
128
- {
129
- name: 'hiddenFlag',
130
- label: i18next.t('field.hidden_flag'),
131
- type: 'checkbox',
132
- props: { searchOper: 'eq' },
133
- attrs: ['indeterminate']
134
- }
135
- ]
136
-
137
- this.config = {
138
- rows: { selectable: { multiple: true } },
139
- pagination: { infinite: true },
140
- columns: [
141
- { type: 'gutter', gutterName: 'dirty' },
142
- { type: 'gutter', gutterName: 'sequence' },
143
- { type: 'gutter', gutterName: 'row-selector', multiple: true },
144
- {
145
- type: 'string',
146
- name: 'name',
147
- header: i18next.t('field.name'),
148
- record: { editable: true, align: 'left' },
149
- sortable: true,
150
- width: 150
151
- },
152
- {
153
- type: 'integer',
154
- name: 'rank',
155
- header: i18next.t('field.rank'),
156
- record: { editable: true },
157
- sortable: true,
158
- width: 80
159
- },
160
- {
161
- type: 'select',
162
- name: 'resourceType',
163
- header: i18next.t('field.type'),
164
- record: {
165
- editable: true,
166
- options: ['', 'board']
167
- },
168
- width: 80
169
- },
170
- {
171
- type: 'string',
172
- name: 'resourceId',
173
- header: i18next.t('field.value'),
174
- record: {
175
- editable: true,
176
- editor: function (value, column, record, rowIndex, field) {
177
- const type = record.resourceType || 'string'
178
- if (value && type !== 'board') {
179
- delete record.resourceId
180
- value = ''
181
- }
182
- return getEditor(type)(value, column, record, rowIndex, field)
183
- },
184
- renderer: function (value, column, record, rowIndex, field) {
185
- const type = record.resourceType || 'string'
186
- if (value && type !== 'board') {
187
- delete record.resourceId
188
- value = ''
189
- }
190
- return getRenderer(type)(value, column, record, rowIndex, field)
191
- }
192
- },
193
- width: 140
194
- },
195
- {
196
- type: 'string',
197
- name: 'description',
198
- header: i18next.t('field.description'),
199
- record: { editable: true, align: 'left' },
200
- sortable: true,
201
- width: 200
202
- },
203
- {
204
- type: 'string',
205
- name: 'template',
206
- header: i18next.t('field.template'),
207
- record: { editable: true, align: 'left' },
208
- sortable: true,
209
- width: 160
210
- },
211
- {
212
- type: 'string',
213
- name: 'resourceUrl',
214
- header: i18next.t('field.resource_url'),
215
- record: { editable: true, align: 'left' },
216
- sortable: true,
217
- width: 160
218
- },
219
- {
220
- type: 'boolean',
221
- name: 'hiddenFlag',
222
- header: i18next.t('field.hidden_flag'),
223
- record: { editable: true },
224
- sortable: true,
225
- width: 80
226
- },
227
- {
228
- type: 'resource-object',
229
- name: 'role',
230
- label: true,
231
- header: i18next.t('field.required role'),
232
- record: {
233
- editable: true,
234
- options: {
235
- title: i18next.t('title.lookup role'),
236
- queryName: 'roles'
237
- }
238
- },
239
- width: 200
240
- },
241
- {
242
- type: 'datetime',
243
- name: 'updatedAt',
244
- header: i18next.t('field.updated_at'),
245
- record: { editable: false },
246
- sortable: true,
247
- width: 150
248
- },
249
- {
250
- type: 'object',
251
- name: 'updater',
252
- header: i18next.t('field.updater'),
253
- record: { editable: false },
254
- sortable: true,
255
- width: 150
256
- }
257
- ]
258
- }
259
- }
260
-
261
- async fetchHandler({ page, limit, sorters = [{ name: 'rank' }, { name: 'name' }] }) {
262
- const response = await client.query({
263
- query: gql`
264
- query {
265
- menus(${gqlBuilder.buildArgs({
266
- filters: [...this.searchForm.queryFilters, { name: 'parentId', operator: 'eq', value: this.menuId }],
267
- pagination: { page, limit },
268
- sortings: sorters
269
- })}) {
270
- items {
271
- id
272
- name
273
- rank
274
- description
275
- category
276
- template
277
- resourceUrl
278
- resourceType
279
- resourceId
280
- hiddenFlag
281
- role {
282
- id
283
- name
284
- description
285
- }
286
- updatedAt
287
- updater{
288
- id
289
- name
290
- description
291
- }
292
- }
293
- total
294
- }
295
- }
296
- `
297
- })
298
-
299
- return {
300
- total: response.data.menus.total || 0,
301
- records: response.data.menus.items || []
302
- }
303
- }
304
-
305
- async save() {
306
- const patches = this.getPatches()
307
- if (patches && patches.length) {
308
- const response = await client.query({
309
- query: gql`
310
- mutation {
311
- updateMultipleMenu(${gqlBuilder.buildArgs({
312
- patches
313
- })}) {
314
- name
315
- }
316
- }
317
- `
318
- })
319
-
320
- if (!response.errors) this.dataGrist.fetch()
321
- } else {
322
- OxPrompt.open({
323
- title: i18next.t('text.nothing_changed'),
324
- text: i18next.t('text.there_is_nothing_to_save')
325
- })
326
- }
327
- }
328
-
329
- async delete() {
330
- const ids = this.dataGrist.selected.map(record => record.id)
331
- if (ids && ids.length > 0) {
332
- if (
333
- await OxPrompt.open({
334
- type: 'warning',
335
- title: i18next.t('button.delete'),
336
- text: i18next.t('text.are_you_sure'),
337
- confirmButton: { text: i18next.t('button.delete') },
338
- cancelButton: { text: i18next.t('button.cancel') }
339
- })
340
- ) {
341
- const response = await client.query({
342
- query: gql`
343
- mutation {
344
- deleteMenus(${gqlBuilder.buildArgs({ ids })})
345
- }
346
- `
347
- })
348
-
349
- if (!response.errors) {
350
- this.dataGrist.fetch()
351
- }
352
- }
353
- } else {
354
- OxPrompt.open({
355
- title: i18next.t('text.nothing_selected'),
356
- text: i18next.t('text.there_is_nothing_to_delete')
357
- })
358
- }
359
- }
360
-
361
- getPatches() {
362
- let patches = this.dataGrist.dirtyRecords
363
- if (patches && patches.length) {
364
- patches = patches.map(menu => {
365
- let patchField = menu.id ? { id: menu.id } : {}
366
- patchField = { ...patchField, routingType: menu.routingType, menuType: menu.menuType }
367
- const dirtyFields = menu.__dirtyfields__
368
- for (let key in dirtyFields) {
369
- patchField[key] = dirtyFields[key].after
370
- }
371
- patchField.parent = { id: this.menuId }
372
- patchField.routingType = patchField.routingType || 'STATIC'
373
- patchField.menuType = patchField.menuType || 'SCREEN'
374
- patchField.cuFlag = menu.__dirty__
375
-
376
- return patchField
377
- })
378
- }
379
-
380
- return patches
381
- }
382
- }
383
-
384
- customElements.define('menu-management-detail', MenuManagementDetail)