@things-factory/reference-app 5.0.0-zeta.8 → 5.0.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 (67) hide show
  1. package/client/bootstrap.js +21 -11
  2. package/client/components/ocr-viewpart.js +1 -1
  3. package/client/editors/id-editor.js +1 -1
  4. package/client/editors/id-selector.js +1 -1
  5. package/client/menu.js +10 -5
  6. package/client/pages/data-entry/data-entry-form.js +117 -0
  7. package/client/pages/data-entry/data-entry-generator-popup.js +110 -0
  8. package/client/pages/data-set/data-item-list.js +277 -0
  9. package/client/pages/data-set/data-set-importer.js +103 -0
  10. package/client/pages/data-set/data-set-list-page.js +738 -0
  11. package/client/pages/ocr-page.js +1 -1
  12. package/client/pages/operation/operation-api.js +85 -0
  13. package/client/pages/operation/operation-master.js +432 -0
  14. package/client/pages/pending-job-page.js +1 -1
  15. package/client/pages/product/product-api.js +150 -0
  16. package/client/pages/product/product-master.js +888 -0
  17. package/client/pages/product-combination-settings-popup.js +395 -0
  18. package/client/pages/product-combinations-popup.js +372 -0
  19. package/client/pages/product-details-popup.js +744 -0
  20. package/client/pages/upload-page.js +1 -1
  21. package/client/route.js +12 -0
  22. package/config/config.development.js +1 -1
  23. package/config.development.js +21 -0
  24. package/db.sqlite +0 -0
  25. package/dist-server/constants/index.js +18 -0
  26. package/dist-server/constants/index.js.map +1 -0
  27. package/dist-server/constants/type-constants.js +26 -0
  28. package/dist-server/constants/type-constants.js.map +1 -0
  29. package/dist-server/controllers/create-data-sample-mockup.js +236 -0
  30. package/dist-server/controllers/create-data-sample-mockup.js.map +1 -0
  31. package/dist-server/controllers/index.js +17 -0
  32. package/dist-server/controllers/index.js.map +1 -1
  33. package/dist-server/service/data-sample-mockup/data-sample-mockup-mutation.js +40 -0
  34. package/dist-server/service/data-sample-mockup/data-sample-mockup-mutation.js.map +1 -0
  35. package/dist-server/service/data-sample-mockup/data-sample-mockup-type.js +28 -0
  36. package/dist-server/service/data-sample-mockup/data-sample-mockup-type.js.map +1 -0
  37. package/dist-server/service/data-sample-mockup/index.js +7 -0
  38. package/dist-server/service/data-sample-mockup/index.js.map +1 -0
  39. package/dist-server/service/index.js +5 -2
  40. package/dist-server/service/index.js.map +1 -1
  41. package/dist-server/service/reference/reference-mutation.js +6 -3
  42. package/dist-server/service/reference/reference-mutation.js.map +1 -1
  43. package/dist-server/service/reference/reference-query.js +7 -4
  44. package/dist-server/service/reference/reference-query.js.map +1 -1
  45. package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +4 -14
  46. package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +19 -69
  47. package/logs/application-2022-07-22-10.log +26 -0
  48. package/logs/connections-2022-07-12-00.log +0 -0
  49. package/logs/connections-2022-07-14-14.log +0 -0
  50. package/logs/connections-2022-07-14-15.log +0 -0
  51. package/logs/connections-2022-07-14-16.log +0 -0
  52. package/logs/connections-2022-07-14-17.log +0 -0
  53. package/logs/connections-2022-07-22-10.log +0 -0
  54. package/package.json +58 -56
  55. package/server/constants/index.ts +1 -0
  56. package/server/constants/type-constants.ts +24 -0
  57. package/server/controllers/create-data-sample-mockup.ts +268 -0
  58. package/server/controllers/index.ts +1 -0
  59. package/server/service/data-sample-mockup/data-sample-mockup-mutation.ts +18 -0
  60. package/server/service/data-sample-mockup/data-sample-mockup-type.ts +10 -0
  61. package/server/service/data-sample-mockup/index.ts +4 -0
  62. package/server/service/index.ts +5 -2
  63. package/server/service/reference/reference-mutation.ts +5 -3
  64. package/server/service/reference/reference-query.ts +8 -7
  65. package/things-factory.config.js +8 -0
  66. package/translations/en.json +6 -1
  67. package/translations/ko.json +7 -1
@@ -0,0 +1,888 @@
1
+ import '@material/mwc-icon'
2
+ import '@things-factory/form-ui'
3
+ import '@things-factory/import-ui'
4
+ import '@operato/data-grist/ox-grist.js'
5
+ import '@operato/data-grist/ox-filters-form.js'
6
+ import '@operato/data-grist/ox-sorters-control.js'
7
+ import '@operato/data-grist/ox-record-creator.js'
8
+ import '../product-details-popup'
9
+
10
+ import { css, html } from 'lit'
11
+
12
+ import { i18next, localize } from '@operato/i18n'
13
+ import { openPopup } from '@operato/layout'
14
+ import { CommonButtonStyles, CommonGristStyles } from '@operato/styles'
15
+ import { isMobileDevice } from '@operato/utils'
16
+ import { getCodeByName } from '@things-factory/code-base'
17
+ import { CustomAlert, PageView } from '@things-factory/shell'
18
+
19
+ import { createProduct, deleteProducts, fetchProducts, saveProducts } from './product-api'
20
+
21
+ class ProductMaster extends localize(i18next)(PageView) {
22
+ static get styles() {
23
+ return [
24
+ CommonGristStyles,
25
+ css`
26
+ :host {
27
+ display: flex;
28
+
29
+ width: 100%;
30
+
31
+ --grid-record-emphasized-background-color: red;
32
+ --grid-record-emphasized-color: yellow;
33
+ }
34
+ `
35
+ ]
36
+ }
37
+
38
+ constructor() {
39
+ super()
40
+ this.mode = isMobileDevice() ? 'LIST' : 'GRID'
41
+ }
42
+
43
+ static get properties() {
44
+ return {
45
+ config: Object,
46
+ data: Object,
47
+ mode: String,
48
+ importHandler: Object
49
+ }
50
+ }
51
+
52
+ render() {
53
+ let mode = this.mode
54
+
55
+ return html`
56
+ <ox-grist .config=${this.config} .mode=${mode} auto-fetch .fetchHandler=${this.fetchHandler.bind(this)}>
57
+ <div slot="headroom">
58
+ <div id="filters">
59
+ <ox-filters-form autofocus></ox-filters-form>
60
+ </div>
61
+
62
+ <div id="sorters">
63
+ Sort
64
+ <mwc-icon
65
+ @click=${e => {
66
+ const target = e.currentTarget
67
+ this.renderRoot.querySelector('#sorter-control').open({
68
+ right: 0,
69
+ top: target.offsetTop + target.offsetHeight
70
+ })
71
+ }}
72
+ >expand_more</mwc-icon
73
+ >
74
+ <ox-popup id="sorter-control">
75
+ <ox-sorters-control> </ox-sorters-control>
76
+ </ox-popup>
77
+ </div>
78
+
79
+ <div id="modes">
80
+ <mwc-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</mwc-icon>
81
+ <mwc-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</mwc-icon>
82
+ </div>
83
+
84
+ <ox-record-creator id="add" .callback=${this.productCreationCallback.bind(this)}>
85
+ <button><mwc-icon>add</mwc-icon></button>
86
+ </ox-record-creator>
87
+ </div>
88
+ </ox-grist>
89
+ `
90
+ }
91
+
92
+ get context() {
93
+ return {
94
+ title: i18next.t('title.product'),
95
+ help: 'operato-fnb/products',
96
+ actions: [
97
+ {
98
+ title: i18next.t('button.save'),
99
+ action: this._saveProducts.bind(this),
100
+ ...CommonButtonStyles.save
101
+ },
102
+ {
103
+ title: i18next.t('button.delete'),
104
+ action: this._deleteProducts.bind(this),
105
+ ...CommonButtonStyles.delete
106
+ }
107
+ ],
108
+ exportable: {
109
+ name: i18next.t('title.product'),
110
+ data: this._exportableData.bind(this)
111
+ },
112
+ importable: {
113
+ handler: this._importableData.bind(this)
114
+ },
115
+ help: 'master/product-master'
116
+ }
117
+ }
118
+
119
+ async pageInitialized() {
120
+ const [productType, packingType, uom, weightUnit, lengthUnit] = await Promise.all([
121
+ getCodeByName('PRODUCT_TYPES'),
122
+ getCodeByName('PACKING_TYPES'),
123
+ getCodeByName('UOM'),
124
+ getCodeByName('WEIGHT_UNITS'),
125
+ getCodeByName('LENGTH_UNITS')
126
+ ])
127
+
128
+ this.config = {
129
+ list: {
130
+ thumbnail: 'thumbnail',
131
+ fields: ['name', 'description'],
132
+ details: ['sku', 'type', 'packingType', 'primaryUnit', 'primaryValue']
133
+ },
134
+ rows: {
135
+ selectable: {
136
+ multiple: true
137
+ },
138
+ handlers: {
139
+ click: 'select-row-toggle'
140
+ },
141
+ classifier: function (record, rowIndex) {}
142
+ },
143
+ columns: [
144
+ { type: 'gutter', gutterName: 'dirty' },
145
+ { type: 'gutter', gutterName: 'sequence' },
146
+ { type: 'gutter', gutterName: 'row-selector', multiple: true },
147
+ {
148
+ type: 'string',
149
+ name: 'id',
150
+ header: i18next.t('field.id'),
151
+ hidden: true,
152
+ record: { editable: false },
153
+ imex: { header: i18next.t('field.id'), key: 'id', width: 100, type: 'string' },
154
+ width: 70
155
+ },
156
+ {
157
+ type: 'gutter',
158
+ gutterName: 'button',
159
+ icon: 'drive_file_rename_outline',
160
+ handlers: {
161
+ click: 'record-view'
162
+ }
163
+ },
164
+ {
165
+ type: 'string',
166
+ name: 'sku',
167
+ record: { editable: true, mandatory: true },
168
+ imex: { header: i18next.t('field.product_code'), key: 'sku', width: 30, type: 'string' },
169
+ header: i18next.t('field.product_code'),
170
+ label: true,
171
+ filter: 'search',
172
+ sortable: true,
173
+ width: 100
174
+ },
175
+ {
176
+ type: 'string',
177
+ name: 'name',
178
+ record: { editable: true, mandatory: true },
179
+ imex: { header: i18next.t('field.product_name'), key: 'name', width: 30, type: 'string' },
180
+ header: i18next.t('field.product_name'),
181
+ filter: 'search',
182
+ sortable: true,
183
+ width: 180
184
+ },
185
+ {
186
+ type: 'string',
187
+ name: 'description',
188
+ record: { editable: true },
189
+ imex: { header: i18next.t('field.description'), key: 'description', width: 50, type: 'string' },
190
+ header: i18next.t('field.description'),
191
+ width: 250
192
+ },
193
+ {
194
+ type: 'select',
195
+ name: 'type',
196
+ header: i18next.t('field.type'),
197
+ label: true,
198
+ record: {
199
+ editable: true,
200
+ mandatory: true,
201
+ options: ['', ...Object.keys(productType).map(key => productType[key].description)]
202
+ },
203
+ filter: true,
204
+ imex: {
205
+ header: i18next.t('field.type'),
206
+ key: 'type',
207
+ width: 50,
208
+ type: 'array',
209
+ arrData: productType.map(productType => {
210
+ return {
211
+ name: productType.name,
212
+ id: productType.name
213
+ }
214
+ })
215
+ },
216
+ sortable: true,
217
+ width: 100
218
+ },
219
+ {
220
+ type: 'object',
221
+ name: 'routing',
222
+ header: i18next.t('field.routing'),
223
+ record: { editable: true, options: { queryName: 'routings' }, mandatory: true },
224
+ width: 180
225
+ },
226
+ {
227
+ type: 'string',
228
+ name: 'auxUnit1',
229
+ record: { editable: true, align: 'right', format: '##0.###' },
230
+ imex: { header: i18next.t('field.primary_value'), key: 'auxUnit1', width: 20, type: 'string' },
231
+ header: i18next.t('field.primary_value'),
232
+ width: 100
233
+ },
234
+ {
235
+ type: 'float',
236
+ name: 'uomValue',
237
+ record: { editable: true, mandatory: true, align: 'right', format: '##0.###' },
238
+ imex: { header: i18next.t('field.uom_value'), key: 'uomValue', width: 15, type: 'float' },
239
+ header: i18next.t('field.uom_value'),
240
+ width: 60
241
+ },
242
+ {
243
+ type: 'select',
244
+ name: 'uom',
245
+ record: {
246
+ editable: true,
247
+ mandatory: true,
248
+ options: ['', ...Object.keys(uom).map(key => uom[key].name)]
249
+ },
250
+ imex: {
251
+ header: i18next.t('field.uom'),
252
+ key: 'uom',
253
+ width: 10,
254
+ type: 'array',
255
+ arrData: uom.map(uom => {
256
+ return {
257
+ name: uom.name,
258
+ id: uom.name
259
+ }
260
+ })
261
+ },
262
+ header: i18next.t('field.uom'),
263
+ width: 80
264
+ },
265
+ {
266
+ type: 'select',
267
+ name: 'packingType',
268
+ header: i18next.t('field.packing_type'),
269
+ label: true,
270
+ record: {
271
+ editable: true,
272
+ mandatory: true,
273
+ options: ['', ...Object.keys(packingType).map(key => packingType[key].name)]
274
+ },
275
+ imex: {
276
+ header: i18next.t('field.packing_type'),
277
+ key: 'packingType',
278
+ width: 50,
279
+ type: 'array',
280
+ arrData: packingType.map(packingType => {
281
+ return {
282
+ name: packingType.name,
283
+ id: packingType.name
284
+ }
285
+ })
286
+ },
287
+ width: 80
288
+ },
289
+ {
290
+ type: 'string',
291
+ name: 'brand',
292
+ record: { editable: true },
293
+ imex: { header: i18next.t('field.brand'), key: 'brand', width: 40, type: 'string' },
294
+ header: i18next.t('field.brand'),
295
+ width: 150,
296
+ hidden: true
297
+ },
298
+ {
299
+ type: 'string',
300
+ name: 'subBrand',
301
+ record: { editable: true },
302
+ imex: { header: i18next.t('field.sub_brand'), key: 'subBrand', width: 30, type: 'string' },
303
+ header: i18next.t('field.sub_brand'),
304
+ width: 200,
305
+ hidden: true
306
+ },
307
+ {
308
+ type: 'string',
309
+ name: 'inventoryAccountCode',
310
+ header: i18next.t('field.inventory_account_code'),
311
+ record: { editable: true },
312
+ imex: {
313
+ header: i18next.t('field.inventory_account_code'),
314
+ key: 'inventoryAccountCode',
315
+ width: 30,
316
+ type: 'string'
317
+ },
318
+ width: 200,
319
+ hidden: true
320
+ },
321
+ {
322
+ type: 'string',
323
+ name: 'cogsAccountCode',
324
+ header: i18next.t('field.cogs_account_code'),
325
+ record: { editable: true },
326
+ imex: { header: i18next.t('field.cogs_account_code'), key: 'cogsAccountCode', width: 30, type: 'string' },
327
+ width: 200,
328
+ hidden: true
329
+ },
330
+ {
331
+ type: 'float',
332
+ name: 'bufferQty',
333
+ record: { editable: true, align: 'left', options: { min: 0 } },
334
+ imex: { header: i18next.t('field.buffer_qty'), key: 'bufferQty', width: 20, type: 'float' },
335
+ header: i18next.t('field.buffer_qty'),
336
+ width: 120,
337
+ hidden: true
338
+ },
339
+ {
340
+ type: 'float',
341
+ name: 'minQty',
342
+ record: { editable: true, align: 'left', options: { min: 0 } },
343
+ imex: { header: i18next.t('field.min_qty'), key: 'minQty', width: 20, type: 'float' },
344
+ header: i18next.t('field.min_qty'),
345
+ width: 120,
346
+ hidden: true
347
+ },
348
+ {
349
+ type: 'float',
350
+ name: 'maxQty',
351
+ record: { editable: true, align: 'left', options: { min: 0 } },
352
+ imex: { header: i18next.t('field.max_qty'), key: 'maxQty', width: 20, type: 'float' },
353
+ header: i18next.t('field.max_qty'),
354
+ width: 120,
355
+ hidden: true
356
+ },
357
+ {
358
+ type: 'integer',
359
+ name: 'expirationPeriod',
360
+ record: { editable: true },
361
+ imex: { header: i18next.t('field.expiration_period'), key: 'expirationPeriod', width: 30, type: 'integer' },
362
+ header: i18next.t('field.expiration_period'),
363
+ width: 140
364
+ },
365
+ {
366
+ type: 'boolean',
367
+ name: 'isRequiredCheckExpiry',
368
+ header: i18next.t('field.required_checking_expiry'),
369
+ record: { editable: true, align: 'center' },
370
+ width: 120,
371
+ hidden: true
372
+ },
373
+ {
374
+ type: 'object',
375
+ name: 'productRef',
376
+ record: {
377
+ editable: true,
378
+ options: {
379
+ queryName: 'myBizplaceProducts',
380
+ nameField: 'name',
381
+ descriptionField: 'description',
382
+ select: [
383
+ { name: 'id', hidden: true },
384
+ { name: 'sku', header: i18next.t('field.sku') },
385
+ { name: 'name', header: i18next.t('field.name') },
386
+ { name: 'description', header: i18next.t('field.description') },
387
+ { name: 'packingType', header: i18next.t('field.packing_type') },
388
+ { name: 'uom', header: i18next.t('field.uom') },
389
+ { name: 'uomValue', header: i18next.t('field.uom_value') }
390
+ ],
391
+ list: { fields: ['sku', 'name', 'description', 'packingType'] }
392
+ }
393
+ },
394
+ imex: {
395
+ header: i18next.t('field.product_ref'),
396
+ key: 'productRef.name',
397
+ width: 30,
398
+ type: 'array',
399
+ arrData: []
400
+ },
401
+ header: i18next.t('field.product_ref'),
402
+ width: 230,
403
+ hidden: true
404
+ },
405
+ {
406
+ type: 'object',
407
+ name: 'parentProductRef',
408
+ record: {
409
+ editable: true,
410
+ options: {
411
+ queryName: 'myBizplaceProducts',
412
+ nameField: 'name',
413
+ descriptionField: 'description',
414
+ select: [
415
+ { name: 'id', hidden: true },
416
+ { name: 'sku', header: i18next.t('field.sku') },
417
+ { name: 'name', header: i18next.t('field.name') },
418
+ { name: 'description', header: i18next.t('field.description') },
419
+ { name: 'packingType', header: i18next.t('field.packing_type') },
420
+ { name: 'primaryUnit', header: i18next.t('field.uom') },
421
+ { name: 'primaryValue', header: i18next.t('field.uom_value') }
422
+ ],
423
+ list: { fields: ['sku', 'name', 'description', 'packingType'] }
424
+ }
425
+ },
426
+ header: i18next.t('field.parent_product_ref'),
427
+ width: 230,
428
+ hidden: true
429
+ },
430
+ {
431
+ type: 'float',
432
+ name: 'bundleQty',
433
+ record: { editable: true },
434
+ header: i18next.t('field.bundle_qty'),
435
+ width: 80,
436
+ hidden: true
437
+ },
438
+ {
439
+ type: 'string',
440
+ name: 'gtin',
441
+ record: { editable: true, mandatory: true },
442
+ imex: { header: i18next.t('field.gtin'), key: 'gtin', width: 20, type: 'string' },
443
+ header: i18next.t('field.gtin'),
444
+ width: 120,
445
+ hidden: true
446
+ },
447
+ {
448
+ type: 'string',
449
+ name: 'refCode',
450
+ record: { editable: true },
451
+ imex: { header: i18next.t('field.ref_code'), key: 'refCode', width: 20, type: 'string' },
452
+ header: i18next.t('field.ref_code'),
453
+ width: 120,
454
+ hidden: true
455
+ },
456
+ {
457
+ type: 'select',
458
+ name: 'weightUnit',
459
+ record: {
460
+ editable: true,
461
+ mandatory: true,
462
+ options: ['', ...Object.keys(weightUnit).map(key => weightUnit[key].name)]
463
+ },
464
+ imex: {
465
+ header: i18next.t('field.weight_unit'),
466
+ key: 'weightUnit',
467
+ width: 20,
468
+ type: 'array',
469
+ arrData: weightUnit.map(weightUnit => {
470
+ return {
471
+ name: weightUnit.name,
472
+ id: weightUnit.name
473
+ }
474
+ })
475
+ },
476
+ header: i18next.t('field.weight_unit'),
477
+ width: 100,
478
+ hidden: true
479
+ },
480
+ {
481
+ type: 'float',
482
+ name: 'grossWeight',
483
+ record: { editable: true, mandatory: true },
484
+ imex: { header: i18next.t('field.gross_weight'), key: 'grossWeight', width: 20, type: 'float' },
485
+ header: i18next.t('field.gross_weight'),
486
+ width: 160,
487
+ hidden: true
488
+ },
489
+ {
490
+ type: 'float',
491
+ name: 'nettWeight',
492
+ record: { editable: true, mandatory: true },
493
+ imex: { header: i18next.t('field.nett_weight'), key: 'nettWeight', width: 20, type: 'float' },
494
+ header: i18next.t('field.nett_weight'),
495
+ width: 160,
496
+ hidden: true
497
+ },
498
+ {
499
+ type: 'float',
500
+ name: 'density',
501
+ record: { editable: true },
502
+ imex: { header: i18next.t('field.density'), key: 'density', width: 10, type: 'float' },
503
+ header: i18next.t('field.density'),
504
+ width: 100,
505
+ hidden: true
506
+ },
507
+ {
508
+ type: 'string',
509
+ name: 'lengthUnit',
510
+ record: {
511
+ editable: true,
512
+ mandatory: true,
513
+ options: ['', ...Object.keys(lengthUnit).map(key => lengthUnit[key].name)]
514
+ },
515
+ imex: {
516
+ header: i18next.t('field.length_unit'),
517
+ key: 'lengthUnit',
518
+ width: 20,
519
+ type: 'array',
520
+ arrData: lengthUnit.map(lengthUnit => {
521
+ return {
522
+ name: lengthUnit.name,
523
+ id: lengthUnit.name
524
+ }
525
+ })
526
+ },
527
+ header: i18next.t('field.length_unit'),
528
+ width: 100,
529
+ hidden: true
530
+ },
531
+ {
532
+ type: 'float',
533
+ name: 'width',
534
+ record: { editable: true, mandatory: true },
535
+ imex: { header: i18next.t('field.width'), key: 'width', width: 15, type: 'float' },
536
+ header: i18next.t('field.width'),
537
+ width: 80,
538
+ hidden: true
539
+ },
540
+ {
541
+ type: 'float',
542
+ name: 'depth',
543
+ record: { editable: true, mandatory: true },
544
+ imex: { header: i18next.t('field.depth'), key: 'depth', width: 15, type: 'float' },
545
+ header: i18next.t('field.depth'),
546
+ width: 80,
547
+ hidden: true
548
+ },
549
+ {
550
+ type: 'float',
551
+ name: 'height',
552
+ record: { editable: true, mandatory: true },
553
+ imex: { header: i18next.t('field.height'), key: 'height', width: 15, type: 'float' },
554
+ header: i18next.t('field.height'),
555
+ width: 80,
556
+ hidden: true
557
+ },
558
+ {
559
+ type: 'float',
560
+ name: 'volume',
561
+ record: { editable: true, mandatory: true },
562
+ imex: { header: i18next.t('field.volume'), key: 'volume', width: 15, type: 'float' },
563
+ header: i18next.t('field.volume'),
564
+ width: 100,
565
+ hidden: true
566
+ },
567
+ {
568
+ type: 'float',
569
+ name: 'volumeSize',
570
+ record: { editable: true },
571
+ imex: { header: i18next.t('field.volume_size'), key: 'volumeSize', width: 20, type: 'float' },
572
+ header: i18next.t('field.volume_size'),
573
+ width: 160,
574
+ hidden: true
575
+ },
576
+ {
577
+ type: 'string',
578
+ name: 'auxValue1',
579
+ record: { editable: true },
580
+ imex: { header: `${i18next.t('field.aux_value')} 1`, key: 'auxValue1', width: 20, type: 'string' },
581
+ header: `${i18next.t('field.aux_value')} 1`,
582
+ width: 100,
583
+ hidden: true
584
+ },
585
+ {
586
+ type: 'string',
587
+ name: 'auxUnit2',
588
+ record: { editable: true },
589
+ imex: { header: `${i18next.t('field.aux_unit')} 2`, key: 'auxUnit2', width: 20, type: 'string' },
590
+ header: `${i18next.t('field.aux_unit')} 2`,
591
+ width: 100,
592
+ hidden: true
593
+ },
594
+ {
595
+ type: 'string',
596
+ name: 'auxValue2',
597
+ record: { editable: true },
598
+ imex: { header: `${i18next.t('field.aux_value')} 2`, key: 'auxValue2', width: 20, type: 'string' },
599
+ header: `${i18next.t('field.aux_value')} 2`,
600
+ width: 100,
601
+ hidden: true
602
+ },
603
+ {
604
+ type: 'string',
605
+ name: 'auxUnit3',
606
+ record: { editable: true },
607
+ imex: { header: `${i18next.t('field.aux_unit')} 3`, key: 'auxUnit3', width: 20, type: 'string' },
608
+ header: `${i18next.t('field.aux_unit')} 3`,
609
+ width: 100,
610
+ hidden: true
611
+ },
612
+ {
613
+ type: 'string',
614
+ name: 'auxValue3',
615
+ record: { editable: true },
616
+ imex: { header: `${i18next.t('field.aux_value')} 3`, key: 'auxValue3', width: 20, type: 'string' },
617
+ header: `${i18next.t('field.aux_value')} 3`,
618
+ width: 100,
619
+ hidden: true
620
+ },
621
+ {
622
+ type: 'string',
623
+ name: 'auxUnit4',
624
+ record: { editable: true },
625
+ imex: { header: `${i18next.t('field.aux_unit')} 4`, key: 'auxUnit4', width: 20, type: 'string' },
626
+ header: `${i18next.t('field.aux_unit')} 4`,
627
+ width: 100,
628
+ hidden: true
629
+ },
630
+ {
631
+ type: 'string',
632
+ name: 'auxValue4',
633
+ record: { editable: true },
634
+ imex: { header: `${i18next.t('field.aux_value')} 4`, key: 'auxValue4', width: 20, type: 'string' },
635
+ header: `${i18next.t('field.aux_value')} 4`,
636
+ width: 100,
637
+ hidden: true
638
+ },
639
+ {
640
+ type: 'string',
641
+ name: 'auxUnit5',
642
+ record: { editable: true },
643
+ imex: { header: `${i18next.t('field.aux_unit')} 5`, key: 'auxUnit5', width: 20, type: 'string' },
644
+ header: `${i18next.t('field.aux_unit')} 5`,
645
+ width: 100,
646
+ hidden: true
647
+ },
648
+ {
649
+ type: 'string',
650
+ name: 'auxValue5',
651
+ record: { editable: true },
652
+ imex: { header: `${i18next.t('field.aux_value')} 5`, key: 'auxValue5', width: 20, type: 'string' },
653
+ header: `${i18next.t('field.aux_value')} 5`,
654
+ width: 100,
655
+ hidden: true
656
+ },
657
+ {
658
+ type: 'object',
659
+ name: 'updater',
660
+ header: i18next.t('field.updater'),
661
+ width: 80
662
+ },
663
+ {
664
+ type: 'datetime',
665
+ name: 'updatedAt',
666
+ header: i18next.t('field.updated_at'),
667
+ sortable: true,
668
+ width: 180
669
+ },
670
+ {
671
+ type: 'image',
672
+ name: 'thumbnail',
673
+ header: i18next.t('field.thumbnail'),
674
+ record: { editable: true },
675
+ width: 70
676
+ }
677
+ ],
678
+ sorters: [
679
+ {
680
+ name: 'name',
681
+ desc: false
682
+ }
683
+ ]
684
+ }
685
+ }
686
+
687
+ async pageUpdated(changes, lifecycle) {
688
+ if (this.active) {
689
+ this.grist.fetch()
690
+ }
691
+ }
692
+
693
+ get grist() {
694
+ return this.renderRoot.querySelector('ox-grist')
695
+ }
696
+
697
+ _importableData(records) {
698
+ setTimeout(() => {
699
+ openPopup(
700
+ html`
701
+ <import-pop-up
702
+ .records=${records}
703
+ .config=${{
704
+ rows: this.config.rows,
705
+ columns: [...this.config.columns.filter(column => !!column.imex)]
706
+ }}
707
+ .importHandler=${this.importHandler.bind(this)}
708
+ ></import-pop-up>
709
+ `,
710
+ {
711
+ backdrop: true,
712
+ size: 'large',
713
+ title: i18next.t('title.import')
714
+ }
715
+ )
716
+ }, 500)
717
+ }
718
+
719
+ async fetchHandler() {
720
+ const response = await fetchProducts(...arguments)
721
+
722
+ return {
723
+ total: response.total || 0,
724
+ records: response.records || []
725
+ }
726
+ }
727
+
728
+ async importHandler(patches) {
729
+ const response = await saveProducts(patches)
730
+
731
+ if (!response.errors) {
732
+ history.back()
733
+ this.grist.fetch()
734
+ document.dispatchEvent(
735
+ new CustomEvent('notify', {
736
+ detail: {
737
+ message: i18next.t('text.data_imported_successfully')
738
+ }
739
+ })
740
+ )
741
+ }
742
+ }
743
+
744
+ async productCreationCallback(product) {
745
+ try {
746
+ const response = await createProduct(product)
747
+
748
+ if (!response.errors) {
749
+ this.grist.fetch()
750
+ document.dispatchEvent(
751
+ new CustomEvent('notify', {
752
+ detail: {
753
+ message: i18next.t('text.data_created_successfully')
754
+ }
755
+ })
756
+ )
757
+ }
758
+
759
+ return true
760
+ } catch (ex) {
761
+ console.error(ex)
762
+ document.dispatchEvent(
763
+ new CustomEvent('notify', {
764
+ detail: {
765
+ type: 'error',
766
+ message: i18next.t('text.error')
767
+ }
768
+ })
769
+ )
770
+ return false
771
+ }
772
+ }
773
+
774
+ async _saveProducts() {
775
+ let patches = this.grist.exportPatchList({ flagName: 'cuFlag' })
776
+ if (patches && patches.length) {
777
+ const response = await saveProducts(patches)
778
+
779
+ if (!response.errors) {
780
+ this.grist.fetch()
781
+ document.dispatchEvent(
782
+ new CustomEvent('notify', {
783
+ detail: {
784
+ message: i18next.t('text.data_updated_successfully')
785
+ }
786
+ })
787
+ )
788
+ }
789
+ }
790
+ }
791
+
792
+ async _deleteProducts() {
793
+ CustomAlert({
794
+ title: i18next.t('text.are_you_sure'),
795
+ text: i18next.t('text.you_wont_be_able_to_revert_this'),
796
+ type: 'warning',
797
+ confirmButton: { text: i18next.t('button.delete'), color: '#22a6a7' },
798
+ cancelButton: { text: 'cancel', color: '#cfcfcf' },
799
+ callback: async result => {
800
+ if (result.value) {
801
+ const ids = this.grist.selected.map(record => record.id)
802
+ if (ids && ids.length > 0) {
803
+ const response = await deleteProducts(ids)
804
+
805
+ if (!response.errors) {
806
+ this.grist.fetch()
807
+ document.dispatchEvent(
808
+ new CustomEvent('notify', {
809
+ detail: {
810
+ message: i18next.t('text.data_deleted_successfully')
811
+ }
812
+ })
813
+ )
814
+ }
815
+ }
816
+ }
817
+ }
818
+ })
819
+ }
820
+
821
+ get _columns() {
822
+ return this.config.columns
823
+ }
824
+
825
+ _exportableData() {
826
+ let records = []
827
+ if (this.grist.selected && this.grist.selected.length > 0) {
828
+ records = this.grist.selected
829
+ } else {
830
+ records = this.grist.data.records
831
+ }
832
+
833
+ var headerSetting = this.grist.compiledConfig.columns
834
+ .filter(column => column.type !== 'gutter' && !!column.imex)
835
+ .map(column => {
836
+ return column.imex
837
+ })
838
+
839
+ var data = records.map(item => {
840
+ return {
841
+ id: item.id,
842
+ ...this._columns
843
+ .filter(column => column.type !== 'gutter' && !!column.imex)
844
+ .reduce((record, column) => {
845
+ record[column.imex.key] = column.imex.key
846
+ .split('.')
847
+ .reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
848
+ return record
849
+ }, {})
850
+ }
851
+ })
852
+
853
+ return { header: headerSetting, data: data }
854
+ }
855
+
856
+ _validate(data) {
857
+ let errors = []
858
+ data = data.map(itm => {
859
+ if (_.isEmpty(itm.sku) || '') {
860
+ if (!errors.find(err => err.type == 'sku')) errors.push({ type: 'sku', value: 'Product SKU is required' })
861
+ }
862
+ if (_.isEmpty(itm.name) || '') {
863
+ if (!errors.find(err => err.type == 'name')) errors.push({ type: 'name', value: 'Product name is required' })
864
+ }
865
+ if (_.isEmpty(itm.type) || '') {
866
+ if (!errors.find(err => err.type == 'type')) errors.push({ type: 'type', value: 'Product type is required' })
867
+ }
868
+ if (_.isEmpty(itm.packingType) || '') {
869
+ if (!errors.find(err => err.type == 'packingType'))
870
+ errors.push({ type: 'packingType', value: 'Packing type is required' })
871
+ }
872
+ if (_.isEmpty(itm.uom) || '') {
873
+ if (!errors.find(err => err.type == 'uom')) errors.push({ type: 'uom', value: 'UOM is required' })
874
+ }
875
+ if (!_.isNumber(itm.uomValue) || _.isNaN(itm.uomValue) || '' || itm?.uomValue < 0) {
876
+ if (!errors.find(err => err.type == 'uomValue'))
877
+ errors.push({ type: 'uomValue', value: 'UOM Value is required' })
878
+ }
879
+ return itm
880
+ })
881
+
882
+ if (errors.length > 0) {
883
+ throw new Error(errors.map(itm => itm.value).join(', '))
884
+ }
885
+ }
886
+ }
887
+
888
+ window.customElements.define('product-master', ProductMaster)