@things-factory/organization 6.2.103 → 6.2.111

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 (36) hide show
  1. package/client/pages/department/department-list-page.ts +308 -196
  2. package/client/pages/department/department-tree-page.ts +153 -403
  3. package/client/route.ts +4 -4
  4. package/client/types/department.ts +0 -8
  5. package/dist-client/pages/department/department-list-page.d.ts +12 -20
  6. package/dist-client/pages/department/department-list-page.js +308 -182
  7. package/dist-client/pages/department/department-list-page.js.map +1 -1
  8. package/dist-client/pages/department/department-tree-page.d.ts +10 -12
  9. package/dist-client/pages/department/department-tree-page.js +142 -382
  10. package/dist-client/pages/department/department-tree-page.js.map +1 -1
  11. package/dist-client/route.d.ts +1 -1
  12. package/dist-client/route.js +3 -3
  13. package/dist-client/route.js.map +1 -1
  14. package/dist-client/tsconfig.tsbuildinfo +1 -1
  15. package/dist-client/types/department.d.ts +0 -6
  16. package/dist-client/types/department.js +0 -5
  17. package/dist-client/types/department.js.map +1 -1
  18. package/dist-server/service/department/department-history.js +4 -15
  19. package/dist-server/service/department/department-history.js.map +1 -1
  20. package/dist-server/service/department/department-query.js +15 -10
  21. package/dist-server/service/department/department-query.js.map +1 -1
  22. package/dist-server/service/department/department-type.js +0 -8
  23. package/dist-server/service/department/department-type.js.map +1 -1
  24. package/dist-server/service/department/department.js +1 -15
  25. package/dist-server/service/department/department.js.map +1 -1
  26. package/dist-server/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +2 -2
  28. package/server/service/department/department-history.ts +7 -31
  29. package/server/service/department/department-query.ts +13 -10
  30. package/server/service/department/department-type.ts +1 -7
  31. package/server/service/department/department.ts +0 -15
  32. package/translations/en.json +1 -0
  33. package/translations/ja.json +1 -0
  34. package/translations/ko.json +1 -0
  35. package/translations/ms.json +1 -0
  36. package/translations/zh.json +1 -0
@@ -8,8 +8,6 @@ import { customElement, property, query, state } from 'lit/decorators.js'
8
8
  import { ScopedElementsMixin } from '@open-wc/scoped-elements'
9
9
  import { client } from '@operato/graphql'
10
10
  import { i18next, localize } from '@operato/i18n'
11
- import { isMobileDevice } from '@operato/utils'
12
- import { DataGrist, FetchOption, GristRecord } from '@operato/data-grist'
13
11
 
14
12
  import { connect } from 'pwa-helpers/connect-mixin'
15
13
  import gql from 'graphql-tag'
@@ -20,7 +18,7 @@ import { Department } from '../../types/department'
20
18
  import { DepartmentView } from '../../component/department-view'
21
19
 
22
20
  const departmentFragment = gql`
23
- fragment Department_department on Department {
21
+ fragment departmentFragment on Department {
24
22
  id
25
23
  controlNo
26
24
  name
@@ -34,7 +32,6 @@ const departmentFragment = gql`
34
32
  email
35
33
  }
36
34
  active
37
- state
38
35
  picture
39
36
 
40
37
  updater {
@@ -48,21 +45,26 @@ const departmentFragment = gql`
48
45
  @customElement('department-tree-page')
49
46
  export class DepartmentTreePage extends connect(store)(localize(i18next)(ScopedElementsMixin(PageView))) {
50
47
  static styles = [
51
- ScrollbarStyles,
52
48
  CommonHeaderStyles,
49
+ ScrollbarStyles,
53
50
  css`
54
51
  :host {
55
52
  display: flex;
53
+ flex-direction: column;
56
54
 
57
55
  width: 100%;
56
+ overflow: auto;
57
+ }
58
58
 
59
- --grid-record-emphasized-background-color: #8b0000;
60
- --grid-record-emphasized-color: #ff6b6b;
59
+ ox-tree-vertical {
60
+ flex: 1;
61
61
  }
62
62
 
63
- ox-grist {
64
- overflow-y: auto;
63
+ department-view {
65
64
  flex: 1;
65
+
66
+ max-width: 500px;
67
+ align-self: center;
66
68
  }
67
69
  `
68
70
  ]
@@ -76,7 +78,7 @@ export class DepartmentTreePage extends connect(store)(localize(i18next)(ScopedE
76
78
  @state() root?: Department
77
79
  @state() selected?: Department
78
80
 
79
- @query('ox-grist') private grist!: DataGrist
81
+ @query('department-view') departmentView!: DepartmentView
80
82
 
81
83
  get context() {
82
84
  return {
@@ -88,10 +90,17 @@ export class DepartmentTreePage extends connect(store)(localize(i18next)(ScopedE
88
90
  title: i18next.t('button.add'),
89
91
  action: this.create.bind(this)
90
92
  },
93
+ this.selected
94
+ ? {
95
+ icon: 'save',
96
+ title: i18next.t('button.save'),
97
+ action: this.save.bind(this)
98
+ }
99
+ : null,
91
100
  {
92
- icon: 'save',
93
- title: i18next.t('button.save'),
94
- action: this.save.bind(this)
101
+ icon: 'refresh',
102
+ title: i18next.t('button.reset'),
103
+ action: this.reset.bind(this)
95
104
  },
96
105
  {
97
106
  icon: 'delete',
@@ -110,74 +119,117 @@ export class DepartmentTreePage extends connect(store)(localize(i18next)(ScopedE
110
119
  }
111
120
  }
112
121
 
113
- @property({ type: Object }) gristConfig: any
114
-
115
122
  render() {
116
- const mode = isMobileDevice() ? 'CARD' : 'GRID'
117
-
118
123
  return html`
119
- <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
120
- <div slot="headroom" class="header">
121
- <div class="title">
122
- <mwc-icon>summarize</mwc-icon>
123
- ${i18next.t('title.department list')}
124
- </div>
125
-
126
- <div class="filters">
127
- <ox-filters-form class="filter" autofocus without-search></ox-filters-form>
128
- </div>
129
-
130
- <ox-context-page-toolbar class="actions" .context=${this.context}></ox-context-page-toolbar>
124
+ <div class="header">
125
+ <div class="title">
126
+ <mwc-icon>summarize</mwc-icon>
127
+ ${i18next.t('title.department list')}
131
128
  </div>
132
- </ox-grist>
129
+
130
+ <ox-context-page-toolbar class="actions" .context=${this.context}></ox-context-page-toolbar>
131
+ </div>
132
+
133
+ <ox-tree-vertical .data=${this.root} .selected=${this.selected} @select=${this.onSelect.bind(this)} label-property="name"></ox-tree-vertical>
134
+
135
+ <department-view .department=${this.selected}></department-view>
133
136
  `
134
137
  }
135
138
 
136
- async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {
137
- const response = await client.query({
138
- query: gql`
139
- query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
140
- responses: departmentRoot {
141
- ...Department_department
142
- children(filters: $filters, pagination: $pagination, sortings: $sortings) {
143
- ...Department_department
144
- children(filters: $filters, pagination: $pagination, sortings: $sortings) {
145
- ...Department_department
146
- children(filters: $filters, pagination: $pagination, sortings: $sortings) {
147
- ...Department_department
148
- children(filters: $filters, pagination: $pagination, sortings: $sortings) {
149
- ...Department_department
150
- children(filters: $filters, pagination: $pagination, sortings: $sortings) {
151
- ...Department_department
152
- children(filters: $filters, pagination: $pagination, sortings: $sortings) {
153
- ...Department_department
154
- children(filters: $filters, pagination: $pagination, sortings: $sortings) {
155
- ...Department_department
156
- }
157
- }
158
- }
159
- }
160
- }
161
- }
162
- }
139
+ onSelect(e: CustomEvent) {
140
+ this.selected = e.detail as Department
141
+ this.updateContext()
142
+ }
143
+
144
+ reset() {
145
+ this.departmentView.department = {}
146
+ }
147
+
148
+ async create() {
149
+ const { id: parentId } = this.selected || {}
150
+ const { controlNo, name, description, picture, active, manager } = this.departmentView.department
151
+
152
+ var department = {
153
+ controlNo,
154
+ name,
155
+ description,
156
+ manager,
157
+ active
158
+ } as any
159
+
160
+ if (picture instanceof File) {
161
+ department.picture = picture
162
+ }
163
+
164
+ if (parentId) {
165
+ department.parent = { id: parentId }
166
+ }
167
+
168
+ const response = await client.mutate({
169
+ mutation: gql`
170
+ mutation ($department: NewDepartment!) {
171
+ createDepartment(department: $department) {
172
+ ...departmentFragment
163
173
  }
164
174
  }
165
175
 
166
176
  ${departmentFragment}
167
177
  `,
168
178
  variables: {
169
- filters,
170
- pagination: { page, limit },
171
- sortings
179
+ department
180
+ },
181
+ context: {
182
+ hasUpload: true
172
183
  }
173
184
  })
174
185
 
175
- const root = response.data.responses
186
+ this.selected = response.data.createDepartment
187
+ this.updateContext()
176
188
 
177
- return {
178
- total: 1, //response.data.responses.total || 0,
179
- records: [root]
189
+ await this.fetch()
190
+ }
191
+
192
+ async save() {
193
+ const { id, controlNo, name, description, picture, active, manager } = this.departmentView.department
194
+
195
+ if (!id) {
196
+ alert('Please select department first.')
180
197
  }
198
+
199
+ var patch = {
200
+ controlNo,
201
+ name,
202
+ description,
203
+ active,
204
+ manager
205
+ } as any
206
+
207
+ if (picture instanceof File) {
208
+ patch.picture = picture
209
+ }
210
+
211
+ const response = await client.mutate({
212
+ mutation: gql`
213
+ mutation ($id: String!, $patch: DepartmentPatch!) {
214
+ updateDepartment(id: $id, patch: $patch) {
215
+ ...departmentFragment
216
+ }
217
+ }
218
+
219
+ ${departmentFragment}
220
+ `,
221
+ variables: {
222
+ id,
223
+ patch
224
+ },
225
+ context: {
226
+ hasUpload: true
227
+ }
228
+ })
229
+
230
+ this.selected = response.data.updateDepartment
231
+
232
+ this.fetch()
181
233
  }
182
234
 
183
235
  async delete() {
@@ -207,182 +259,12 @@ export class DepartmentTreePage extends connect(store)(localize(i18next)(ScopedE
207
259
  this.selected = {}
208
260
  this.updateContext()
209
261
 
210
- await this.grist.fetch()
262
+ await this.fetch()
211
263
  }
212
264
  }
213
265
 
214
266
  async pageInitialized(lifecycle: any) {
215
- this.gristConfig = {
216
- pagination: { pages: [50, 100, 200] },
217
- list: {
218
- thumbnail: 'profile',
219
- fields: ['controlNo', 'name'],
220
- details: ['email', 'manager', 'updatedAt']
221
- },
222
- columns: [
223
- {
224
- type: 'gutter',
225
- gutterName: 'dirty',
226
- fixed: true
227
- },
228
- {
229
- type: 'tree',
230
- name: 'name',
231
- label: true,
232
- header: i18next.t('label.name'),
233
- record: {
234
- editable: true,
235
- options: {
236
- selectable: true
237
- }
238
- },
239
- filter: 'search',
240
- sortable: true,
241
- width: 200,
242
- fixed: true,
243
- handlers: {
244
- contextmenu: 'contextmenu-tree-mutation'
245
- }
246
- },
247
- { name: 'id', hidden: true },
248
- {
249
- type: 'string',
250
- name: 'controlNo',
251
- header: i18next.t('label.control-no'),
252
- record: {
253
- editable: true
254
- },
255
- filter: 'search',
256
- sortable: true,
257
- width: 110
258
- },
259
- {
260
- type: 'string',
261
- name: 'description',
262
- header: i18next.t('label.description'),
263
- record: {
264
- editable: true
265
- },
266
- filter: 'search',
267
- sortable: true,
268
- width: 110
269
- },
270
- {
271
- type: 'string',
272
- name: 'state',
273
- header: i18next.t('label.state'),
274
- record: {
275
- editable: true
276
- },
277
- sortable: true,
278
- width: 110
279
- },
280
- {
281
- type: 'resource-object',
282
- name: 'manager',
283
- header: i18next.t('label.manager'),
284
- record: {
285
- editable: true,
286
- options: {
287
- title: i18next.t('title.employee list'),
288
- queryName: 'employees',
289
- pagination: { pages: [50, 100, 200] },
290
- basicArgs: {
291
- filters: [
292
- {
293
- name: 'active',
294
- operator: 'eq',
295
- value: true
296
- }
297
- ]
298
- },
299
- list: { fields: ['controlNo', 'name', 'email'] },
300
- columns: [
301
- { name: 'id', hidden: true },
302
- {
303
- name: 'controlNo',
304
- width: 120,
305
- header: { renderer: () => i18next.t('field.control-no') },
306
- filter: 'search',
307
- sortable: true
308
- },
309
- {
310
- name: 'name',
311
- width: 120,
312
- header: { renderer: () => i18next.t('field.name') },
313
- filter: 'search',
314
- sortable: true
315
- },
316
- {
317
- name: 'email',
318
- width: 150,
319
- header: { renderer: () => i18next.t('label.email') },
320
- filter: 'search',
321
- sortable: true
322
- }
323
- ],
324
- valueField: 'id',
325
- nameField: 'name',
326
- descriptionField: 'controlNo'
327
- }
328
- },
329
- sortable: true,
330
- width: 120
331
- },
332
- {
333
- type: 'checkbox',
334
- name: 'active',
335
- label: true,
336
- header: i18next.t('field.active'),
337
- width: 70,
338
- record: {
339
- align: 'center',
340
- editable: true
341
- },
342
- filter: true,
343
- sortable: true
344
- },
345
- {
346
- type: 'resource-object',
347
- name: 'updater',
348
- header: i18next.t('field.updater'),
349
- width: 90,
350
- sortable: false
351
- },
352
- {
353
- type: 'datetime',
354
- name: 'updatedAt',
355
- header: i18next.t('field.updated_at'),
356
- width: 180,
357
- sortable: true
358
- },
359
- {
360
- type: 'image',
361
- name: 'picture',
362
- record: {
363
- renderer: function (value, column, record, rowIndex, field) {
364
- return html`<ox-pfp-view style="height:90%; width: unset; aspect-ratio: 1 / 1;" .profile=${record.picture} .name=${record.name}></ox-pfp-view>`
365
- }
366
- },
367
- hidden: true
368
- }
369
- ],
370
- rows: {
371
- appendable: false,
372
- selectable: {
373
- multiple: true
374
- }
375
- },
376
- sorters: [
377
- {
378
- name: 'controlNo'
379
- }
380
- ],
381
- tree: {
382
- childrenProperty: 'children',
383
- expanded: () => true
384
- }
385
- }
267
+ this.fetch()
386
268
  }
387
269
 
388
270
  async pageUpdated(changes: any, lifecycle: any) {
@@ -391,177 +273,45 @@ export class DepartmentTreePage extends connect(store)(localize(i18next)(ScopedE
391
273
  }
392
274
  }
393
275
 
394
- async create() {
395
- // const { id: parentId } = this.selected || {}
396
- // const { controlNo, name, description, state, picture, active, manager } = this.grist.department
397
-
398
- // var department = {
399
- // controlNo,
400
- // name,
401
- // description,
402
- // state,
403
- // manager,
404
- // active
405
- // } as any
406
-
407
- // if (picture instanceof File) {
408
- // department.picture = picture
409
- // }
410
-
411
- // if (parentId) {
412
- // department.parent = { id: parentId }
413
- // }
414
-
415
- // const response = await client.mutate({
416
- // mutation: gql`
417
- // mutation ($department: NewDepartment!) {
418
- // createDepartment(department: $department) {
419
- // ...Department_department
420
- // }
421
- // }
422
-
423
- // ${departmentFragment}
424
- // `,
425
- // variables: {
426
- // department
427
- // },
428
- // context: {
429
- // hasUpload: true
430
- // }
431
- // })
432
-
433
- // this.selected = response.data.createDepartment
434
- // this.updateContext()
435
-
436
- await this.grist.fetch()
437
- }
438
-
439
- // async _deleteDataSet() {
440
- // if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {
441
- // const ids = this.grist.selected.map(record => record.id)
442
- // if (ids && ids.length > 0) {
443
- // const response = await client.mutate({
444
- // mutation: gql`
445
- // mutation ($ids: [String!]!) {
446
- // deleteDataSets(ids: $ids)
447
- // }
448
- // `,
449
- // variables: {
450
- // ids
451
- // }
452
- // })
453
-
454
- // if (!response.errors) {
455
- // this.grist.fetch()
456
- // notify({
457
- // message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })
458
- // })
459
- // }
460
- // }
461
- // }
462
- // }
463
-
464
- // async _copyDataSet() {
465
- // var selected = this.grist.selected
466
- // if (selected.length == 0) return
467
-
468
- // if (!confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.copy') }))) return
469
- // var response = await client.mutate({
470
- // mutation: gql`
471
- // mutation ($ids: [String!]!) {
472
- // copyDataSets(ids: $ids) {
473
- // id
474
- // }
475
- // }
476
- // `,
477
- // variables: {
478
- // ids: selected.map(r => r.id)
479
- // }
480
- // })
481
-
482
- // if (!response.errors) {
483
- // this.grist.fetch()
484
- // }
485
- // }
486
-
487
- // async save() {
488
- // const { id, controlNo, name, description, state, picture, active, manager } = this.departmentView.department
489
-
490
- // if (!id) {
491
- // alert('Please select department first.')
492
- // }
493
-
494
- // var patch = {
495
- // controlNo,
496
- // name,
497
- // description,
498
- // state,
499
- // active,
500
- // manager
501
- // } as any
502
-
503
- // if (picture instanceof File) {
504
- // patch.picture = picture
505
- // }
506
-
507
- // const response = await client.mutate({
508
- // mutation: gql`
509
- // mutation ($id: String!, $patch: DepartmentPatch!) {
510
- // updateDepartment(id: $id, patch: $patch) {
511
- // ...Department_department
512
- // }
513
- // }
514
-
515
- // ${departmentFragment}
516
- // `,
517
- // variables: {
518
- // id,
519
- // patch
520
- // },
521
- // context: {
522
- // hasUpload: true
523
- // }
524
- // })
525
-
526
- // this.selected = response.data.updateDepartment
527
-
528
- // this.fetch()
529
- // }
530
-
531
- async save() {
532
- let patches = this.grist.dirtyRecords
533
- if (patches && patches.length) {
534
- patches = patches.map(patch => {
535
- let patchField: any = patch.id ? { id: patch.id } : {}
536
- const dirtyFields = patch.__dirtyfields__
537
- for (let key in dirtyFields) {
538
- patchField[key] = dirtyFields[key].after
539
- }
540
- patchField.cuFlag = patch.__dirty__
541
-
542
- return patchField
543
- })
544
-
545
- const response = await client.mutate({
546
- mutation: gql`
547
- mutation ($patches: [DepartmentPatch!]!) {
548
- updateMultipleDepartment(patches: $patches) {
549
- name
276
+ async fetch() {
277
+ const response = await client.query({
278
+ query: gql`
279
+ query {
280
+ responses: departmentRoots {
281
+ total
282
+ items {
283
+ ...departmentFragment
284
+ children {
285
+ ...departmentFragment
286
+ children {
287
+ ...departmentFragment
288
+ children {
289
+ ...departmentFragment
290
+ children {
291
+ ...departmentFragment
292
+ children {
293
+ ...departmentFragment
294
+ children {
295
+ ...departmentFragment
296
+ children {
297
+ ...departmentFragment
298
+ }
299
+ }
300
+ }
301
+ }
302
+ }
303
+ }
304
+ }
550
305
  }
551
306
  }
552
- `,
553
- variables: {
554
- patches
555
- },
556
- context: {
557
- hasUpload: true
558
307
  }
559
- })
560
308
 
561
- if (!response.errors) {
562
- this.grist.fetch()
563
- }
564
- }
309
+ ${departmentFragment}
310
+ `
311
+ })
312
+ const { items: records, total } = response.data.responses
313
+
314
+ this.root = records[0]
565
315
  }
566
316
 
567
317
  async exportHandler() {}
package/client/route.ts CHANGED
@@ -4,14 +4,14 @@ export default function route(page: string) {
4
4
  import('./pages/employee/employee-list-page')
5
5
  return page
6
6
 
7
- case 'department-list':
8
- import('./pages/department/department-list-page')
9
- return page
10
-
11
7
  case 'department-tree':
12
8
  import('./pages/department/department-tree-page')
13
9
  return page
14
10
 
11
+ case 'department-list':
12
+ import('./pages/department/department-list-page')
13
+ return page
14
+
15
15
  case 'employees-by-department':
16
16
  import('./pages/employee/employees-by-department')
17
17
  return page
@@ -1,11 +1,6 @@
1
1
  import { Domain, User } from '@operato/shell'
2
2
  import { Employee } from './employee'
3
3
 
4
- export enum DepartmentStatus {
5
- STATUS_A = 'STATUS_A',
6
- STATUS_B = 'STATUS_B'
7
- }
8
-
9
4
  export class Department {
10
5
  readonly id?: string
11
6
 
@@ -20,9 +15,6 @@ export class Department {
20
15
 
21
16
  manager?: Employee
22
17
 
23
- active?: boolean
24
- state?: DepartmentStatus
25
-
26
18
  extension?: string
27
19
  picture?: string
28
20