@things-factory/operato-wms 4.3.767 → 4.3.770

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 (46) hide show
  1. package/client/pages/bulk-operation/validate-gan-popup.js +2 -2
  2. package/client/pages/components/list-view/product-list-view.js +28 -3
  3. package/client/pages/components/mobile-condition-of-goods-listing.js +342 -0
  4. package/client/pages/components/unloading-worksheet-information-popup.js +299 -0
  5. package/client/pages/constants/order.js +7 -0
  6. package/client/pages/inbound/condition-of-goods-popup.js +646 -0
  7. package/client/pages/inbound/putaway/putaway-product.js +35 -6
  8. package/client/pages/inbound/unload-product-landing-page.js +282 -0
  9. package/client/pages/inbound/unload-product.js +707 -175
  10. package/client/pages/inbound/unloaded-inventories-popup.js +3 -0
  11. package/client/pages/inventory/inventory-adjustment-approval.js +28 -1
  12. package/client/pages/inventory/inventory-adjustment.js +77 -44
  13. package/client/pages/inventory/inventory-by-product-detail.js +15 -0
  14. package/client/pages/inventory/inventory-history.js +18 -0
  15. package/client/pages/inventory/onhand-inventory.js +14 -0
  16. package/client/pages/order/arrival-notice/create-arrival-notice.js +209 -206
  17. package/client/pages/order/arrival-notice/duplicate-arrival-notice.js +132 -129
  18. package/client/pages/order/arrival-notice/edit-product-popup.js +97 -92
  19. package/client/pages/order/release-order/b2b/b2b-order-list.js +99 -0
  20. package/client/pages/order/release-order/packing-label-history-popup.js +378 -0
  21. package/client/pages/order/release-order/preview-print-packing-list.js +533 -0
  22. package/client/pages/order/release-order/print-quantity-popup.js +118 -0
  23. package/client/pages/outbound/loading-v2/loading-execution-base.js +29 -0
  24. package/client/pages/outbound/loading-v2/loading-execution.js +579 -2
  25. package/client/pages/outbound/loading-v2/loading-package-info-popup.js +182 -0
  26. package/client/pages/outbound/loading-v2/loading.js +18 -0
  27. package/client/pages/report/inbound-order-details-report.js +26 -1
  28. package/client/route.js +17 -0
  29. package/dist-server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.js +9 -1
  30. package/dist-server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.js.map +1 -1
  31. package/dist-server/graphql/resolvers/outbound/loading-worksheet-v2.js +11 -5
  32. package/dist-server/graphql/resolvers/outbound/loading-worksheet-v2.js.map +1 -1
  33. package/dist-server/graphql/resolvers/reports/inbound-order-details-report.js +2 -1
  34. package/dist-server/graphql/resolvers/reports/inbound-order-details-report.js.map +1 -1
  35. package/dist-server/graphql/types/reports/inbound-order-details-report.js +1 -0
  36. package/dist-server/graphql/types/reports/inbound-order-details-report.js.map +1 -1
  37. package/package.json +15 -15
  38. package/server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.ts +9 -1
  39. package/server/graphql/resolvers/outbound/loading-worksheet-v2.ts +13 -1
  40. package/server/graphql/resolvers/reports/inbound-order-details-report.ts +2 -1
  41. package/server/graphql/types/reports/inbound-order-details-report.ts +1 -0
  42. package/things-factory.config.js +8 -0
  43. package/translations/en.json +45 -1
  44. package/translations/ko.json +40 -0
  45. package/translations/ms.json +40 -0
  46. package/translations/zh.json +40 -0
@@ -0,0 +1,646 @@
1
+ import '@things-factory/grist-ui'
2
+
3
+ import gql from 'graphql-tag'
4
+ import { css, html, LitElement } from 'lit-element'
5
+ import { connect } from 'pwa-helpers/connect-mixin'
6
+
7
+ import { MultiColumnFormStyles } from '@things-factory/form-ui'
8
+ import { i18next, localize } from '@things-factory/i18n-base'
9
+ import { client, store, CustomAlert } from '@things-factory/shell'
10
+ import { isMobileDevice } from '@things-factory/utils'
11
+ import { CONDITION_OF_GOODS } from '../constants'
12
+ import '../components/mobile-condition-of-goods-listing'
13
+ import { showToast } from '../../util'
14
+ class ConditionOfGoodsPopup extends connect(store)(localize(i18next)(LitElement)) {
15
+ static get properties() {
16
+ return {
17
+ config: Object,
18
+ mobileConfig: Object,
19
+ unloadedInventories: Array,
20
+ worksheetDetailNames: Array,
21
+ _productInfoFilter: String,
22
+ _conditionFilter: String,
23
+ _isExecuting: Boolean
24
+ }
25
+ }
26
+
27
+ constructor() {
28
+ super()
29
+ this._isExecuting = false
30
+ this._productInfoFilter = ''
31
+ this._conditionFilter = ''
32
+ this.unloadedInventories = []
33
+ this.worksheetDetailNames = []
34
+ this.config = null
35
+ this._closeTimeoutId = null
36
+ }
37
+
38
+ disconnectedCallback() {
39
+ if (this._closeTimeoutId) {
40
+ clearTimeout(this._closeTimeoutId)
41
+ this._closeTimeoutId = null
42
+ }
43
+ super.disconnectedCallback()
44
+ }
45
+
46
+ static get styles() {
47
+ return [
48
+ MultiColumnFormStyles,
49
+ css`
50
+ .button-container {
51
+ padding: var(--button-container-padding);
52
+ margin: var(--button-container-margin);
53
+ text-align: var(--button-container-align);
54
+ background-color: var(--button-container-background);
55
+ height: var(--button-container-height);
56
+ display: flex;
57
+ gap: 10px;
58
+ justify-content: flex-end;
59
+ }
60
+
61
+ @media (max-width: 767px) {
62
+ mobile-condition-of-goods-listing {
63
+ padding-bottom: 40px;
64
+ }
65
+
66
+ .button-container {
67
+ background-color: var(--theme-white-color, white);
68
+ position: fixed;
69
+ bottom: 0;
70
+ left: 0;
71
+ right: 0;
72
+ z-index: 1000;
73
+ margin: 0;
74
+ padding: 0;
75
+ justify-content: flex-end;
76
+ align-items: flex-end;
77
+ height: 40px !important;
78
+ gap: 0;
79
+ }
80
+
81
+ .button-container mwc-button {
82
+ margin-bottom: 0 !important;
83
+ }
84
+ }
85
+
86
+ .button-container button {
87
+ background-color: var(--button-container-button-background-color);
88
+ border-radius: var(--button-container-button-border-radius);
89
+ height: var(--button-container-button-height);
90
+ border: var(--button-container-button-border);
91
+ margin: var(--button-container-button-margin);
92
+ padding: var(--button-padding);
93
+ color: var(--theme-white-color);
94
+ font: var(--button-font);
95
+ text-transform: var(--button-text-transform);
96
+ min-width: 100px;
97
+ }
98
+ .button-container button:hover,
99
+ .button-container button:active {
100
+ background-color: var(--button-background-focus-color);
101
+ }
102
+ .button-container button.secondary {
103
+ background-color: var(--button-secondary-background-color, #757575);
104
+ }
105
+ .button-container button.secondary:hover,
106
+ .button-container button.secondary:active {
107
+ background-color: var(--button-secondary-background-focus-color, #616161);
108
+ }
109
+ data-grist {
110
+ overflow-y: hidden;
111
+ flex: 1;
112
+ --grid-record-odd-background-color: var(--theme-white-color);
113
+ --data-list-background-color: var(--theme-white-color);
114
+ }
115
+ .grist {
116
+ display: flex;
117
+ flex-direction: column;
118
+ flex: 1;
119
+ overflow-y: auto;
120
+ }
121
+ data-listing {
122
+ flex: 1;
123
+ overflow: hidden;
124
+ }
125
+ :host {
126
+ padding: 10px;
127
+ display: flex;
128
+ flex-direction: column;
129
+ overflow: hidden;
130
+ background-color: white;
131
+ --data-list-label-text-transform: capitalize;
132
+ }
133
+ .filter-section {
134
+ background-color: var(--form-section-background-color, #f5f5f5);
135
+ padding: 15px;
136
+ margin-bottom: 10px;
137
+ border-radius: 4px;
138
+ }
139
+ .filter-section fieldset {
140
+ margin-bottom: 10px;
141
+ }
142
+ .filter-section fieldset:last-child {
143
+ margin-bottom: 0;
144
+ }
145
+ select {
146
+ width: 100%;
147
+ padding: 8px;
148
+ border: 1px solid #ccc;
149
+ border-radius: 4px;
150
+ font-size: 14px;
151
+ box-sizing: border-box;
152
+ }
153
+ input[type='text'] {
154
+ width: 100%;
155
+ padding: 8px;
156
+ border: 1px solid #ccc;
157
+ border-radius: 4px;
158
+ font-size: 14px;
159
+ box-sizing: border-box;
160
+ }
161
+ @media screen and (max-width: 460px) {
162
+ .single-column-form {
163
+ max-width: 100%;
164
+ grid-gap: 5px;
165
+ border-bottom: 1px solid #017E7F;
166
+ }
167
+ .single-column-form fieldset {
168
+ display: contents;
169
+ border: none;
170
+ margin: 0;
171
+ padding: 0;
172
+ }
173
+ .single-column-form label {
174
+ font-weight: bold !important;
175
+ text-transform: capitalize !important;
176
+ }
177
+ .single-column-form input[type='text'],
178
+ .single-column-form select {
179
+ width: 100%;
180
+ box-sizing: border-box;
181
+ max-width: 100%;
182
+ margin-bottom: 10px;
183
+ }
184
+ }
185
+ `
186
+ ]
187
+ }
188
+
189
+ get dataGrist() {
190
+ return this.shadowRoot.querySelector('data-grist')
191
+ }
192
+
193
+ get dataListing() {
194
+ return this.shadowRoot.querySelector('mobile-condition-of-goods-listing')
195
+ }
196
+
197
+ get currentDataComponent() {
198
+ return isMobileDevice() ? this.dataListing : this.dataGrist
199
+ }
200
+
201
+ get productInfoInput() {
202
+ return this.shadowRoot.querySelector('input[name=productInfo]')
203
+ }
204
+
205
+ get conditionFilterSelect() {
206
+ return this.shadowRoot.querySelector('select[name=conditionFilter]')
207
+ }
208
+
209
+ firstUpdated() {
210
+ this._setupGristConfig()
211
+ this.updateComplete.then(() => {
212
+ const component = this.currentDataComponent
213
+ if (component && this.worksheetDetailNames && this.worksheetDetailNames.length > 0) {
214
+ if (isMobileDevice() && this.dataListing) {
215
+ this.dataListing.fetch()
216
+ } else if (!isMobileDevice() && this.dataGrist) {
217
+ this.dataGrist.fetch()
218
+ }
219
+ }
220
+ })
221
+ }
222
+
223
+ updated(changedProperties) {
224
+ if (changedProperties.has('worksheetDetailNames')) {
225
+ const component = this.currentDataComponent
226
+ if (component && this.worksheetDetailNames && this.worksheetDetailNames.length > 0) {
227
+ if (isMobileDevice() && this.dataListing) {
228
+ this.dataListing.fetch()
229
+ } else if (!isMobileDevice() && this.dataGrist) {
230
+ this.dataGrist.fetch()
231
+ }
232
+ }
233
+ }
234
+ }
235
+
236
+ _onFieldChange(e) {
237
+ // Handle field changes from data-listing component
238
+ // This is called when selection box values change
239
+ // The data is already updated in the component, we just need to track changes
240
+ }
241
+
242
+ _setupGristConfig() {
243
+ this.config = {
244
+ pagination: { limit: 50, pages: [20, 50, 100, 200, 500] },
245
+ rows: { selectable: { multiple: false }, appendable: false },
246
+ list: {
247
+ fields: ['palletId', 'cartonId', 'sku', 'productName', 'qty', 'conditionOfGoods']
248
+ },
249
+ columns: [
250
+ { type: 'gutter', gutterName: 'sequence' },
251
+ {
252
+ type: 'string',
253
+ name: 'palletId',
254
+ label: true,
255
+ header: i18next.t('field.lot_id'),
256
+ width: 150
257
+ },
258
+ {
259
+ type: 'string',
260
+ name: 'cartonId',
261
+ label: true,
262
+ header: i18next.t('field.carton_id'),
263
+ width: 150
264
+ },
265
+ {
266
+ type: 'string',
267
+ name: 'sku',
268
+ label: true,
269
+ header: i18next.t('field.sku'),
270
+ width: 120
271
+ },
272
+ {
273
+ type: 'string',
274
+ name: 'productName',
275
+ label: true,
276
+ header: i18next.t('field.product_name'),
277
+ width: 250
278
+ },
279
+ {
280
+ type: 'float',
281
+ name: 'qty',
282
+ label: true,
283
+ header: i18next.t('field.actual_pack_qty'),
284
+ width: 120
285
+ },
286
+ {
287
+ type: 'select',
288
+ name: 'conditionOfGoods',
289
+ label: true,
290
+ header: i18next.t('field.condition'),
291
+ width: 150,
292
+ record: {
293
+ editable: true,
294
+ options: Object.keys(CONDITION_OF_GOODS).map(key => ({
295
+ value: CONDITION_OF_GOODS[key].value,
296
+ display: i18next.t(`label.${CONDITION_OF_GOODS[key].name}`)
297
+ }))
298
+ }
299
+ }
300
+ ]
301
+ }
302
+
303
+ this.mobileConfig = {
304
+ columns: [
305
+ {
306
+ type: 'text',
307
+ header: i18next.t('field.lot_id'),
308
+ field: 'palletId',
309
+ color: '#007E7F'
310
+ },
311
+ {
312
+ type: 'text',
313
+ header: i18next.t('field.carton_id'),
314
+ field: 'cartonId',
315
+ color: '#007E7F'
316
+ },
317
+ {
318
+ type: 'text',
319
+ header: i18next.t('field.sku'),
320
+ field: 'sku',
321
+ color: '#007E7F'
322
+ },
323
+ {
324
+ type: 'text',
325
+ header: i18next.t('field.product_name'),
326
+ field: 'productName'
327
+ },
328
+ {
329
+ type: 'text',
330
+ header: i18next.t('field.actual_pack_qty'),
331
+ field: 'qty'
332
+ },
333
+ {
334
+ type: 'selectionBox',
335
+ header: i18next.t('field.condition'),
336
+ field: 'conditionOfGoods',
337
+ options: Object.keys(CONDITION_OF_GOODS).map(key => ({
338
+ value: CONDITION_OF_GOODS[key].value,
339
+ label: i18next.t(`label.${CONDITION_OF_GOODS[key].name}`)
340
+ }))
341
+ }
342
+ ]
343
+ }
344
+ }
345
+
346
+ async fetchHandler({ page, limit }) {
347
+ try {
348
+ const worksheetDetailNames = this._getWorksheetDetailNames()
349
+
350
+ if (!worksheetDetailNames || worksheetDetailNames.length === 0) {
351
+ return {
352
+ total: 0,
353
+ records: []
354
+ }
355
+ }
356
+
357
+ const response = await client.query({
358
+ query: gql`
359
+ query unloadedInventories($worksheetDetailNames: [String]!) {
360
+ unloadedInventories(worksheetDetailNames: $worksheetDetailNames) {
361
+ id
362
+ batchId
363
+ packingType
364
+ packingSize
365
+ batchIdRef
366
+ palletId
367
+ cartonId
368
+ qty
369
+ expirationDate
370
+ manufactureDate
371
+ status
372
+ product {
373
+ id
374
+ name
375
+ sku
376
+ }
377
+ conditionOfGoods
378
+ }
379
+ }
380
+ `,
381
+ variables: {
382
+ worksheetDetailNames
383
+ },
384
+ })
385
+
386
+ if (response.errors) {
387
+ throw new Error(response.errors[0]?.message || i18next.t('text.error_occurred'))
388
+ }
389
+
390
+ const allInventories = response.data?.unloadedInventories || []
391
+
392
+ // Apply filters
393
+ let filtered = this._applyFilters(allInventories)
394
+
395
+ // Transform to records format
396
+ const allRecords = filtered.map(inventory => ({
397
+ id: inventory.id,
398
+ palletId: inventory.palletId || '',
399
+ cartonId: inventory.cartonId || '',
400
+ sku: inventory.product?.sku || '',
401
+ productName: inventory.product?.name || '',
402
+ qty: inventory.qty || 0,
403
+ conditionOfGoods: inventory.conditionOfGoods || CONDITION_OF_GOODS.GOOD.value
404
+ }))
405
+
406
+ // Apply pagination
407
+ const startIndex = (page - 1) * limit
408
+ const endIndex = startIndex + limit
409
+ const records = allRecords.slice(startIndex, endIndex)
410
+
411
+ return {
412
+ total: allRecords.length,
413
+ records
414
+ }
415
+ } catch (e) {
416
+ showToast({ message: e.message || i18next.t('text.error_occurred'), type: 'error' })
417
+ return {
418
+ total: 0,
419
+ records: []
420
+ }
421
+ }
422
+ }
423
+
424
+ _getWorksheetDetailNames() {
425
+ return this.worksheetDetailNames || []
426
+ }
427
+
428
+ _onProductInfoFilterChange(e) {
429
+ this._productInfoFilter = e.target.value
430
+ }
431
+
432
+ _onProductInfoFilterKeyPress(e) {
433
+ if (e.keyCode === 13) {
434
+ e.preventDefault()
435
+ if (isMobileDevice() && this.dataListing) {
436
+ this.dataListing.fetch()
437
+ } else if (!isMobileDevice() && this.dataGrist) {
438
+ this.dataGrist.fetch()
439
+ }
440
+ }
441
+ }
442
+
443
+ _onConditionFilterChange(e) {
444
+ this._conditionFilter = e.target.value
445
+ if (isMobileDevice() && this.dataListing) {
446
+ this.dataListing.fetch()
447
+ } else if (!isMobileDevice() && this.dataGrist) {
448
+ this.dataGrist.fetch()
449
+ }
450
+ }
451
+
452
+ _applyFilters(inventories) {
453
+ let filtered = inventories || []
454
+
455
+ // Apply product info filter (search by SKU or product name)
456
+ if (this._productInfoFilter && this._productInfoFilter.trim() !== '') {
457
+ const searchTerm = this._productInfoFilter.toLowerCase().trim()
458
+ filtered = filtered.filter(
459
+ inventory =>
460
+ (inventory.product?.sku && inventory.product.sku.toLowerCase().includes(searchTerm)) ||
461
+ (inventory.product?.name && inventory.product.name.toLowerCase().includes(searchTerm))
462
+ )
463
+ }
464
+
465
+ // Apply condition filter
466
+ if (this._conditionFilter && this._conditionFilter !== '') {
467
+ filtered = filtered.filter(inventory => {
468
+ const condition = inventory.conditionOfGoods || CONDITION_OF_GOODS.GOOD.value
469
+ return condition === this._conditionFilter
470
+ })
471
+ }
472
+
473
+ return filtered
474
+ }
475
+
476
+ _closePopup() {
477
+ history.back()
478
+ }
479
+
480
+ async _confirmChanges() {
481
+ try {
482
+ if (this._isExecuting) return
483
+
484
+ const result = await CustomAlert({
485
+ type: 'info',
486
+ title: 'Proceed with Goods Condition changes ?',
487
+ confirmButton: { text: i18next.t('button.confirm') },
488
+ cancelButton: { text: i18next.t('button.cancel') },
489
+ invertButton: true
490
+ })
491
+
492
+ if (!result.value) {
493
+ return
494
+ }
495
+
496
+ this._isExecuting = true
497
+
498
+ const component = this.currentDataComponent
499
+ if (!component) {
500
+ this._isExecuting = false
501
+ showToast({ message: i18next.t('text.error_occurred'), type: 'error' })
502
+ return
503
+ }
504
+
505
+ // Show spinner for both mobile and web before processing
506
+ component.showSpinner()
507
+
508
+ // Get patches based on device type
509
+ let rawPatches = []
510
+ if (isMobileDevice()) {
511
+ rawPatches = component.getChangedRecords() || []
512
+ } else {
513
+ rawPatches = component.exportPatchList({})
514
+ }
515
+
516
+ // Check if patches is empty - handle cleanup and return
517
+ if (!rawPatches || rawPatches.length === 0) {
518
+ component.hideSpinner()
519
+ this._isExecuting = false
520
+ showToast({ message: i18next.t('text.nothing_changed'), type: 'info' })
521
+ return
522
+ }
523
+
524
+ // Normalize patches to inventoryPatches format (id + conditionOfGoods)
525
+ const inventoryPatches = rawPatches.map(patch => ({
526
+ id: patch.id,
527
+ conditionOfGoods: patch.conditionOfGoods || CONDITION_OF_GOODS.GOOD.value
528
+ }))
529
+
530
+ const response = await client.mutate({
531
+ mutation: gql`
532
+ mutation updateInventoryCondition($patches: [InventoryPatch!]!) {
533
+ updateInventoryCondition(patches: $patches) {
534
+ id
535
+ conditionOfGoods
536
+ }
537
+ }
538
+ `,
539
+ variables: { patches: inventoryPatches }
540
+ })
541
+
542
+ if (response.errors) {
543
+ throw new Error(response.errors[0]?.message || i18next.t('text.error_occurred'))
544
+ }
545
+
546
+ this.dispatchEvent(
547
+ new CustomEvent('condition-updated', {
548
+ bubbles: true,
549
+ composed: true,
550
+ detail: { changes: inventoryPatches }
551
+ })
552
+ )
553
+
554
+ if (component) {
555
+ component.hideSpinner()
556
+ }
557
+ this._closeTimeoutId = setTimeout(() => {
558
+ this._closeTimeoutId = null
559
+ this._closePopup()
560
+ }, 50)
561
+ } catch (e) {
562
+ showToast({ message: e.message || i18next.t('text.error_occurred'), type: 'error' })
563
+ const component = this.currentDataComponent
564
+ if (component) {
565
+ component.hideSpinner()
566
+ }
567
+ } finally {
568
+ this._isExecuting = false
569
+ }
570
+ }
571
+
572
+
573
+ render() {
574
+ const isMobileDeviceCheck = isMobileDevice()
575
+
576
+ return html`
577
+ <form id="info-form" class="${isMobileDeviceCheck ? 'single-column-form' : 'multi-column-form'}">
578
+ <fieldset>
579
+ <label>${i18next.t('label.product_info')}</label>
580
+ <input
581
+ type="text"
582
+ name="productInfo"
583
+ .value="${this._productInfoFilter}"
584
+ @input="${this._onProductInfoFilterChange.bind(this)}"
585
+ @keypress="${this._onProductInfoFilterKeyPress.bind(this)}"
586
+ />
587
+ </fieldset>
588
+ <fieldset>
589
+ <label>${i18next.t('label.condition')}</label>
590
+ <select name="conditionFilter" .value="${this._conditionFilter}" @change="${this._onConditionFilterChange.bind(this)}">
591
+ <option value="">All</option>
592
+ ${Object.keys(CONDITION_OF_GOODS).map(
593
+ key => html`
594
+ <option value="${CONDITION_OF_GOODS[key].value}">${i18next.t(`label.${CONDITION_OF_GOODS[key].name}`)}</option>
595
+ `
596
+ )}
597
+ </select>
598
+ </fieldset>
599
+ </form>
600
+
601
+ ${!isMobileDeviceCheck
602
+ ? html`
603
+ <div class="grist">
604
+ ${this.config
605
+ ? html`
606
+ <data-grist
607
+ id="grist"
608
+ .mode=${'GRID'}
609
+ .config=${this.config}
610
+ .fetchHandler="${this.fetchHandler.bind(this)}"
611
+ ></data-grist>
612
+ `
613
+ : html`<div>Loading...</div>`}
614
+ </div>
615
+ `
616
+ : html`
617
+ <mobile-condition-of-goods-listing
618
+ .config="${this.mobileConfig}"
619
+ .fetchHandler="${this.fetchHandler.bind(this)}"
620
+ @field-change="${this._onFieldChange.bind(this)}"
621
+ ></mobile-condition-of-goods-listing>
622
+ `}
623
+
624
+ <div class="button-container">
625
+ <mwc-button
626
+ outlined
627
+ class="secondary"
628
+ @click="${this._closePopup.bind(this)}"
629
+ label="${i18next.t('button.close')}"
630
+ icon="close"
631
+ ?disabled=${this._isExecuting}
632
+ ></mwc-button>
633
+ <mwc-button
634
+ raised
635
+ @click="${this._confirmChanges.bind(this)}"
636
+ label="${i18next.t('button.confirm')}"
637
+ icon="check"
638
+ ?disabled=${this._isExecuting}
639
+ ></mwc-button>
640
+ </div>
641
+ `
642
+ }
643
+ }
644
+
645
+ window.customElements.define('condition-of-goods-popup', ConditionOfGoodsPopup)
646
+