@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,395 @@
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 { i18next, localize } from '@operato/i18n'
8
+ import { ScrollbarStyles } from '@operato/styles'
9
+ import { isMobileDevice } from '@operato/utils'
10
+ import { client, CustomAlert, gqlContext } from '@things-factory/shell'
11
+
12
+ class ProductCombinationSettingsPopup extends localize(i18next)(LitElement) {
13
+ static get properties() {
14
+ return {
15
+ record: Object,
16
+ marketplace: Object,
17
+ productSetId: String,
18
+ searchFields: Array,
19
+ productConfig: Object,
20
+ productCombinationSettingConfig: Object,
21
+ productCombinationSettingData: Object
22
+ }
23
+ }
24
+
25
+ static get styles() {
26
+ return [
27
+ ScrollbarStyles,
28
+ css`
29
+ :host {
30
+ display: flex;
31
+ flex-direction: column;
32
+ overflow: hidden;
33
+ }
34
+ search-form {
35
+ overflow: visible;
36
+ }
37
+ ox-grist {
38
+ flex: 1;
39
+ }
40
+ .grist-container {
41
+ display: flex;
42
+ overflow: auto;
43
+ flex: 1;
44
+ }
45
+ .grist-column {
46
+ overflow: hidden;
47
+ display: flex;
48
+ flex: 1;
49
+ flex-direction: column;
50
+ }
51
+ .button-container {
52
+ padding: 10px 0 12px 0;
53
+ text-align: center;
54
+ }
55
+ [danger] {
56
+ --mdc-theme-primary: var(--mdc-danger-button-primary-color);
57
+ }
58
+ .header {
59
+ display: grid;
60
+ grid-template-columns: repeat(24, 1fr);
61
+ grid-gap: var(--form-grid-gap);
62
+ grid-auto-rows: minmax(24px, auto);
63
+ max-width: var(--form-multi-column-max-width);
64
+ margin-top: var(--form-margin);
65
+ margin-left: var(--form-margin);
66
+ margin-right: var(--form-margin);
67
+ }
68
+ .header legend {
69
+ grid-column: span 24;
70
+ text-transform: capitalize;
71
+
72
+ padding: var(--legend-padding);
73
+ font: var(--legend-font);
74
+ color: var(--legend-text-color);
75
+ border-bottom: var(--legend-border-bottom);
76
+ }
77
+ `
78
+ ]
79
+ }
80
+
81
+ get searchForm() {
82
+ return this.shadowRoot.querySelector('#search-form')
83
+ }
84
+
85
+ get productListGrist() {
86
+ return this.shadowRoot.querySelector('ox-grist#product_list_grist')
87
+ }
88
+
89
+ get productCombinationSettingGrist() {
90
+ return this.shadowRoot.querySelector('ox-grist#product_combination_setting_grist')
91
+ }
92
+
93
+ render() {
94
+ return html`
95
+ <div class="grist-container">
96
+ <div class="grist-column">
97
+ <search-form
98
+ id="search-form"
99
+ .fields=${this.searchFields}
100
+ @submit=${e => this.productListGrist.fetch()}
101
+ ></search-form>
102
+
103
+ <ox-grist
104
+ id="product_list_grist"
105
+ .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
106
+ .config=${this.productConfig}
107
+ .fetchHandler=${this._fetchMyBizplaceProducts.bind(this)}
108
+ >
109
+ </ox-grist>
110
+
111
+ <div class="header">
112
+ <legend>${i18next.t('title.linked_products')}</legend>
113
+ </div>
114
+
115
+ <ox-grist
116
+ id="product_combination_setting_grist"
117
+ .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
118
+ .config=${this.productCombinationSettingConfig}
119
+ .data=${this.productCombinationSettingData}
120
+ ></ox-grist>
121
+ </div>
122
+ </div>
123
+
124
+ <div class="button-container">
125
+ <mwc-button
126
+ @click=${this.linkProductCombination}
127
+ raised
128
+ label="${i18next.t('button.link_product')}"
129
+ ></mwc-button>
130
+ </div>
131
+ `
132
+ }
133
+
134
+ async updated(changedProps) {
135
+ if (changedProps.has('record')) this.productCombinationSettingData = await this._fetchProductCombinationLink()
136
+ }
137
+
138
+ async firstUpdated() {
139
+ this.searchFields = [
140
+ {
141
+ label: i18next.t('field.product_info'),
142
+ name: 'product_info',
143
+ props: { searchOper: 'i_like' }
144
+ },
145
+ {
146
+ label: i18next.t('field.type'),
147
+ name: 'type',
148
+ props: {
149
+ searchOper: 'i_like'
150
+ }
151
+ }
152
+ ]
153
+
154
+ const _productColumns = [
155
+ {
156
+ type: 'string',
157
+ name: 'productSku',
158
+ header: i18next.t('field.sku'),
159
+ sortable: false,
160
+ record: { editable: false },
161
+ width: 150
162
+ },
163
+ {
164
+ type: 'string',
165
+ name: 'gtin',
166
+ header: i18next.t('field.gtin'),
167
+ sortable: false,
168
+ record: { editable: false },
169
+ width: 150
170
+ },
171
+ {
172
+ type: 'string',
173
+ name: 'productName',
174
+ header: i18next.t('field.name'),
175
+ sortable: true,
176
+ record: { editable: false, align: 'left' },
177
+ width: 220
178
+ },
179
+ {
180
+ type: 'string',
181
+ name: 'packingType',
182
+ header: i18next.t('field.packing_type'),
183
+ record: { editable: false },
184
+ width: 120
185
+ }
186
+ ]
187
+
188
+ this.productConfig = {
189
+ rows: {
190
+ selectable: { multiple: true },
191
+ appendable: false
192
+ },
193
+ columns: [
194
+ { type: 'gutter', gutterName: 'sequence' },
195
+ {
196
+ type: 'gutter',
197
+ gutterName: 'button',
198
+ icon: 'add',
199
+ handlers: {
200
+ click: (_columns, _data, _column, record, _rowIndex) => {
201
+ if (record) this.addProductLink(record)
202
+ }
203
+ }
204
+ },
205
+ ..._productColumns
206
+ ]
207
+ }
208
+
209
+ this.productCombinationSettingConfig = {
210
+ pagination: { infinite: true },
211
+ rows: { appendable: false },
212
+ columns: [
213
+ { type: 'gutter', gutterName: 'sequence' },
214
+ {
215
+ type: 'gutter',
216
+ gutterName: 'button',
217
+ icon: 'clear',
218
+ handlers: {
219
+ click: (_columns, _data, _column, record, _rowIndex) => {
220
+ if (record) this.removeProductLink(_data.records, _rowIndex)
221
+ }
222
+ }
223
+ },
224
+ {
225
+ type: 'string',
226
+ name: 'id', //id of product combination setting
227
+ hidden: true
228
+ },
229
+ {
230
+ type: 'number',
231
+ name: 'qty',
232
+ header: i18next.t('field.qty'),
233
+ record: { editable: true, align: 'left' },
234
+ width: 120
235
+ },
236
+ ..._productColumns
237
+ ]
238
+ }
239
+
240
+ this.productCombinationSettingData = await this._fetchProductCombinationLink()
241
+ }
242
+
243
+ async _fetchMyBizplaceProducts({ page, limit, sorters = [] }) {
244
+ return await this._fetchProducts({ page, limit, sorters, filters: [...this.searchForm.queryFilters] })
245
+ }
246
+
247
+ async _fetchProductCombinationLink() {
248
+ return await this._fetchProducts({ page: 1, limit: 1000, combinationId: true })
249
+ }
250
+
251
+ async _fetchProducts({ page, limit, sorters = [], filters = [], combinationId = false }) {
252
+ filters.push({
253
+ name: 'productCombinationId',
254
+ operator: combinationId ? 'eq' : 'noteq',
255
+ value: this.record?.id || ''
256
+ })
257
+ const response = await client.query({
258
+ query: gql`
259
+ query productCombinationSets($filters: [Filter], $pagination: Pagination, $sortings: [Sorting]) {
260
+ productCombinationSets(filters: $filters, pagination: $pagination, sortings: $sortings) {
261
+ items {
262
+ id
263
+ productId
264
+ productName
265
+ productSku
266
+ productDescription
267
+ productType
268
+ qty
269
+ productDetailId
270
+ gtin
271
+ packingType
272
+ packingSize
273
+ }
274
+ total
275
+ }
276
+ }
277
+ `,
278
+ variables: {
279
+ filters,
280
+ pagination: { page, limit },
281
+ sortings: sorters
282
+ },
283
+ context: gqlContext()
284
+ })
285
+ if (!response.errors) {
286
+ return {
287
+ records: response.data.productCombinationSets.items || [],
288
+ total: response.data.productCombinationSets.total || 0
289
+ }
290
+ }
291
+ }
292
+
293
+ addProductLink(record) {
294
+ if (
295
+ this.productCombinationSettingData.records.findIndex(
296
+ x => x.productId === record.productId && x.productDetailId === record.productDetailId
297
+ ) < 0
298
+ ) {
299
+ // set qty to null because it is new item to be linked
300
+ record.qty = null
301
+ this.productCombinationSettingData = {
302
+ ...this.productCombinationSettingData,
303
+ records: [...this.productCombinationSettingGrist.dirtyData.records, record]
304
+ }
305
+ } else {
306
+ this._showToast({ level: 'error', message: i18next.t('text.existing_item_found') })
307
+ }
308
+ }
309
+
310
+ removeProductLink(records, index) {
311
+ records.splice(index, 1)
312
+
313
+ this.productCombinationSettingData = {
314
+ ...this.productCombinationSettingData,
315
+ records
316
+ }
317
+ }
318
+
319
+ async linkProductCombination() {
320
+ try {
321
+ let patches = this.productCombinationSettingGrist.dirtyData.records.map(record => {
322
+ const qty = record.qty
323
+ if (!qty || qty <= 0) {
324
+ throw new Error(i18next.t('text.invalid_qty_for_item_number', { number: record.__seq__ }))
325
+ }
326
+ return {
327
+ // only existing product combination will have id
328
+ id: record.id || '',
329
+ product: { id: record.productId } || {},
330
+ productDetail: { id: record.productDetailId } || {},
331
+ qty
332
+ }
333
+ })
334
+ const productCombinationId = this.record?.id
335
+ if (productCombinationId && patches) {
336
+ const response = await client.query({
337
+ query: gql`
338
+ mutation linkProductCombination(
339
+ $productCombinationId: String!
340
+ $patches: [ProductCombinationSettingPatch]!
341
+ ) {
342
+ linkProductCombination(productCombinationId: $productCombinationId, patches: $patches) {
343
+ id
344
+ productId
345
+ productSku
346
+ productName
347
+ productDescription
348
+ productType
349
+ qty
350
+ productDetailId
351
+ gtin
352
+ packingType
353
+ packingSize
354
+ }
355
+ }
356
+ `,
357
+ variables: {
358
+ productCombinationId,
359
+ patches
360
+ },
361
+ context: gqlContext()
362
+ })
363
+ if (!response.errors) {
364
+ this.productCombinationSettingData = await this._fetchProductCombinationLink()
365
+ await CustomAlert({
366
+ type: 'success',
367
+ title: i18next.t('text.success'),
368
+ text: ''
369
+ })
370
+ }
371
+ } else {
372
+ CustomAlert({
373
+ title: i18next.t('text.nothing_changed'),
374
+ text: i18next.t('text.there_is_nothing_to_save')
375
+ })
376
+ }
377
+ } catch (error) {
378
+ this._showToast(error)
379
+ }
380
+ }
381
+
382
+ _showToast({ type, level, message }) {
383
+ document.dispatchEvent(
384
+ new CustomEvent('notify', {
385
+ detail: {
386
+ type,
387
+ level,
388
+ message
389
+ }
390
+ })
391
+ )
392
+ }
393
+ }
394
+
395
+ window.customElements.define('product-combination-settings-popup', ProductCombinationSettingsPopup)