@things-factory/biz-ui 4.3.701 → 4.3.723
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.
- package/client/components/contact-points-popup.js +15 -1
- package/client/pages/contact-point-list.js +187 -3
- package/package.json +10 -10
- package/translations/en.json +2 -1
- package/translations/ja.json +1 -0
- package/translations/ko.json +1 -0
- package/translations/ms.json +1 -0
- package/translations/zh.json +1 -0
|
@@ -105,7 +105,7 @@ class ContactPointsPopup extends localize(i18next)(LitElement) {
|
|
|
105
105
|
firstUpdated() {
|
|
106
106
|
this.config = {
|
|
107
107
|
list: {
|
|
108
|
-
fields: ['companyName', 'accountNo', 'email', 'name', 'description']
|
|
108
|
+
fields: ['companyName', 'accountNo', 'email', 'name', 'description', 'country', 'releaseShelfLife']
|
|
109
109
|
},
|
|
110
110
|
pagination: { pages: [10, 20, 50, 100] },
|
|
111
111
|
rows: {
|
|
@@ -154,6 +154,18 @@ class ContactPointsPopup extends localize(i18next)(LitElement) {
|
|
|
154
154
|
header: i18next.t('field.billing_address'),
|
|
155
155
|
width: 350
|
|
156
156
|
},
|
|
157
|
+
{
|
|
158
|
+
type: 'string',
|
|
159
|
+
name: 'country',
|
|
160
|
+
header: i18next.t('field.country'),
|
|
161
|
+
width: 350
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
type: 'number',
|
|
165
|
+
name: 'releaseShelfLife',
|
|
166
|
+
header: i18next.t('field.release_shelf_life'),
|
|
167
|
+
width: 350
|
|
168
|
+
},
|
|
157
169
|
{
|
|
158
170
|
type: 'string',
|
|
159
171
|
name: 'phone',
|
|
@@ -234,8 +246,10 @@ class ContactPointsPopup extends localize(i18next)(LitElement) {
|
|
|
234
246
|
address
|
|
235
247
|
address2
|
|
236
248
|
postCode
|
|
249
|
+
country
|
|
237
250
|
city
|
|
238
251
|
state
|
|
252
|
+
releaseShelfLife
|
|
239
253
|
billingAddress
|
|
240
254
|
}
|
|
241
255
|
total
|
|
@@ -51,6 +51,7 @@ export class ContactPointList extends localize(i18next)(PageView) {
|
|
|
51
51
|
.config=${this.config}
|
|
52
52
|
.data=${this.data}
|
|
53
53
|
.fetchHandler="${this.fetchHandler.bind(this)}"
|
|
54
|
+
@field-change=${this._onFieldChange.bind(this)}
|
|
54
55
|
></data-grist>
|
|
55
56
|
`
|
|
56
57
|
}
|
|
@@ -81,12 +82,20 @@ export class ContactPointList extends localize(i18next)(PageView) {
|
|
|
81
82
|
rows: this.config.rows,
|
|
82
83
|
columns: [...this.config.columns.filter(column => column.imex !== undefined)]
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
+
// Normalize records to handle Excel object values (e.g., hyperlinks for email) and numeric fields
|
|
86
|
+
const normalizedRecords = records.map(record => {
|
|
87
|
+
let normalized = this._normalizeStringFields(record)
|
|
88
|
+
normalized = this._normalizeNumericFields(normalized)
|
|
89
|
+
return normalized
|
|
90
|
+
})
|
|
91
|
+
openImportPopUp(normalizedRecords, config, async patches => {
|
|
85
92
|
try {
|
|
86
93
|
patches = patches.map(patch => {
|
|
87
94
|
if (!patch?.id) delete patch.id
|
|
88
|
-
|
|
89
|
-
|
|
95
|
+
// Normalize both string fields (for hyperlinks) and numeric fields (for GraphQL types)
|
|
96
|
+
let normalized = this._normalizeStringFields(patch)
|
|
97
|
+
normalized = this._normalizeNumericFields(normalized)
|
|
98
|
+
return normalized
|
|
90
99
|
})
|
|
91
100
|
await this._validateImport(patches)
|
|
92
101
|
await this._saveContactPoints(patches)
|
|
@@ -302,6 +311,14 @@ export class ContactPointList extends localize(i18next)(PageView) {
|
|
|
302
311
|
header: i18next.t('field.contact_point_state'),
|
|
303
312
|
width: 150
|
|
304
313
|
},
|
|
314
|
+
{
|
|
315
|
+
type: 'string',
|
|
316
|
+
name: 'country',
|
|
317
|
+
record: { editable: true },
|
|
318
|
+
imex: { header: i18next.t('field.country'), key: 'country', width: 40, type: 'string' },
|
|
319
|
+
header: i18next.t('field.country'),
|
|
320
|
+
width: 150
|
|
321
|
+
},
|
|
305
322
|
{
|
|
306
323
|
type: 'string',
|
|
307
324
|
name: 'billingAddress',
|
|
@@ -315,6 +332,25 @@ export class ContactPointList extends localize(i18next)(PageView) {
|
|
|
315
332
|
header: i18next.t('field.contact_point_billing_address'),
|
|
316
333
|
width: 300
|
|
317
334
|
},
|
|
335
|
+
{
|
|
336
|
+
type: 'number',
|
|
337
|
+
name: 'releaseShelfLife',
|
|
338
|
+
record: {
|
|
339
|
+
editable: true,
|
|
340
|
+
validation: (after, before, record, column) => {
|
|
341
|
+
const validation = this._validateReleaseShelfLife(after, true)
|
|
342
|
+
return validation.valid
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
header: i18next.t('field.release_shelf_life'),
|
|
346
|
+
imex: {
|
|
347
|
+
header: i18next.t('field.release_shelf_life'),
|
|
348
|
+
key: 'releaseShelfLife',
|
|
349
|
+
width: 40,
|
|
350
|
+
type: 'number'
|
|
351
|
+
},
|
|
352
|
+
width: 150
|
|
353
|
+
},
|
|
318
354
|
{
|
|
319
355
|
name: 'type',
|
|
320
356
|
record: { editable: true },
|
|
@@ -357,6 +393,131 @@ export class ContactPointList extends localize(i18next)(PageView) {
|
|
|
357
393
|
}
|
|
358
394
|
}
|
|
359
395
|
|
|
396
|
+
/**
|
|
397
|
+
* Validates releaseShelfLife value
|
|
398
|
+
* @param {any} value - The value to validate
|
|
399
|
+
* @param {boolean} allowEmpty - Whether to allow empty/null/undefined values (default: true)
|
|
400
|
+
* @returns {{valid: boolean, error?: string}} - Validation result with optional error message
|
|
401
|
+
*/
|
|
402
|
+
_validateReleaseShelfLife(value, allowEmpty = true) {
|
|
403
|
+
// Allow empty/null values if allowed
|
|
404
|
+
if (allowEmpty && (value === null || value === undefined || value === '')) {
|
|
405
|
+
return { valid: true }
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// If not allowed and empty, return error
|
|
409
|
+
if (!allowEmpty && (value === null || value === undefined || value === '')) {
|
|
410
|
+
return { valid: false, error: i18next.t('field.release_shelf_life') + ' is required' }
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const numValue = Number(value)
|
|
414
|
+
|
|
415
|
+
// Check if it's a valid number
|
|
416
|
+
if (isNaN(numValue)) {
|
|
417
|
+
return { valid: false, error: i18next.t('field.release_shelf_life') + ' must be a valid number' }
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Check if it's negative
|
|
421
|
+
if (numValue < 0) {
|
|
422
|
+
return { valid: false, error: i18next.t('field.release_shelf_life') + ' cannot be negative' }
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Check if it's an integer (no decimals)
|
|
426
|
+
if (!Number.isInteger(numValue)) {
|
|
427
|
+
return { valid: false, error: i18next.t('field.release_shelf_life') + ' must be an integer (no decimal values)' }
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return { valid: true }
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
_onFieldChange(e) {
|
|
434
|
+
const { after, before, column, record, row } = e.detail
|
|
435
|
+
|
|
436
|
+
// Handle releaseShelfLife validation (redundant with column validation, but kept for user feedback)
|
|
437
|
+
if (column.name === 'releaseShelfLife') {
|
|
438
|
+
const validation = this._validateReleaseShelfLife(after, true)
|
|
439
|
+
if (!validation.valid) {
|
|
440
|
+
// Revert to previous value
|
|
441
|
+
this.dataGrist._data.records[row][column.name] = before
|
|
442
|
+
this.data = {
|
|
443
|
+
...this.dataGrist._data
|
|
444
|
+
}
|
|
445
|
+
// Show error message
|
|
446
|
+
this.showToast(validation.error)
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
_normalizeStringFields(record) {
|
|
452
|
+
// Normalize object values to strings (e.g., Excel hyperlinks for email fields)
|
|
453
|
+
// ExcelJS may return email cells as objects like { text: 'email@example.com', hyperlink: 'mailto:...' }
|
|
454
|
+
const normalized = { ...record }
|
|
455
|
+
const stringFields = [
|
|
456
|
+
'email',
|
|
457
|
+
'name',
|
|
458
|
+
'companyName',
|
|
459
|
+
'description',
|
|
460
|
+
'fax',
|
|
461
|
+
'phone',
|
|
462
|
+
'accountNo',
|
|
463
|
+
'address',
|
|
464
|
+
'address2',
|
|
465
|
+
'postCode',
|
|
466
|
+
'city',
|
|
467
|
+
'state',
|
|
468
|
+
'country',
|
|
469
|
+
'billingAddress',
|
|
470
|
+
'type'
|
|
471
|
+
]
|
|
472
|
+
stringFields.forEach(field => {
|
|
473
|
+
if (normalized[field] && typeof normalized[field] === 'object' && !Array.isArray(normalized[field])) {
|
|
474
|
+
// Handle ExcelJS hyperlink objects
|
|
475
|
+
if (normalized[field].text !== undefined) {
|
|
476
|
+
normalized[field] = normalized[field].text
|
|
477
|
+
} else {
|
|
478
|
+
// Fallback: try to stringify or use empty string
|
|
479
|
+
normalized[field] = normalized[field].toString ? normalized[field].toString() : ''
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
})
|
|
483
|
+
return normalized
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
_normalizeNumericFields(record) {
|
|
487
|
+
// Normalize numeric fields - convert string numbers to integers/floats
|
|
488
|
+
// GraphQL requires integers to be actual numbers, not strings
|
|
489
|
+
const normalized = { ...record }
|
|
490
|
+
|
|
491
|
+
// releaseShelfLife must be an integer
|
|
492
|
+
// Explicitly check for 0 as a valid value (both number 0 and string "0")
|
|
493
|
+
const releaseShelfLifeValue = normalized.releaseShelfLife
|
|
494
|
+
|
|
495
|
+
if (releaseShelfLifeValue === 0 || releaseShelfLifeValue === '0') {
|
|
496
|
+
// 0 is a valid value, ensure it's stored as integer 0
|
|
497
|
+
normalized.releaseShelfLife = 0
|
|
498
|
+
} else if (releaseShelfLifeValue !== null && releaseShelfLifeValue !== undefined && releaseShelfLifeValue !== '') {
|
|
499
|
+
if (typeof releaseShelfLifeValue === 'string') {
|
|
500
|
+
const numValue = Number(releaseShelfLifeValue)
|
|
501
|
+
if (!isNaN(numValue)) {
|
|
502
|
+
normalized.releaseShelfLife = Number.isInteger(numValue) ? numValue : Math.floor(numValue)
|
|
503
|
+
} else {
|
|
504
|
+
// Invalid number string, set to default 0
|
|
505
|
+
normalized.releaseShelfLife = 0
|
|
506
|
+
}
|
|
507
|
+
} else if (typeof releaseShelfLifeValue === 'number') {
|
|
508
|
+
// Ensure it's an integer
|
|
509
|
+
normalized.releaseShelfLife = Number.isInteger(releaseShelfLifeValue)
|
|
510
|
+
? releaseShelfLifeValue
|
|
511
|
+
: Math.floor(releaseShelfLifeValue)
|
|
512
|
+
}
|
|
513
|
+
} else {
|
|
514
|
+
// Empty/null values should default to 0
|
|
515
|
+
normalized.releaseShelfLife = 0
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return normalized
|
|
519
|
+
}
|
|
520
|
+
|
|
360
521
|
async fetchPartnersBizplaces() {
|
|
361
522
|
const response = await client.query({
|
|
362
523
|
query: gql`
|
|
@@ -402,9 +563,11 @@ export class ContactPointList extends localize(i18next)(PageView) {
|
|
|
402
563
|
state
|
|
403
564
|
city
|
|
404
565
|
postCode
|
|
566
|
+
country
|
|
405
567
|
billingAddress
|
|
406
568
|
description
|
|
407
569
|
type
|
|
570
|
+
releaseShelfLife
|
|
408
571
|
updatedAt
|
|
409
572
|
bizplace {
|
|
410
573
|
id
|
|
@@ -472,6 +635,19 @@ export class ContactPointList extends localize(i18next)(PageView) {
|
|
|
472
635
|
if (!errors.find(err => err.type == 'customerName'))
|
|
473
636
|
errors.push({ type: 'customerName', value: 'customer name is required' })
|
|
474
637
|
}
|
|
638
|
+
|
|
639
|
+
// Validate releaseShelfLife: must be non-negative integer
|
|
640
|
+
const releaseShelfLifeValidation = this._validateReleaseShelfLife(itm.releaseShelfLife, true)
|
|
641
|
+
if (!releaseShelfLifeValidation.valid) {
|
|
642
|
+
itm.error = true
|
|
643
|
+
if (!errors.find(err => err.type == 'releaseShelfLife')) {
|
|
644
|
+
errors.push({
|
|
645
|
+
type: 'releaseShelfLife',
|
|
646
|
+
value: releaseShelfLifeValidation.error
|
|
647
|
+
})
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
475
651
|
return itm
|
|
476
652
|
})
|
|
477
653
|
|
|
@@ -562,6 +738,14 @@ export class ContactPointList extends localize(i18next)(PageView) {
|
|
|
562
738
|
throw new Error(i18next.t('text.contact_type_does_not_exist'))
|
|
563
739
|
}
|
|
564
740
|
|
|
741
|
+
// Validate releaseShelfLife: must be non-negative integer
|
|
742
|
+
const releaseShelfLifeValidation = this._validateReleaseShelfLife(item.releaseShelfLife, true)
|
|
743
|
+
if (!releaseShelfLifeValidation.valid) {
|
|
744
|
+
if (!errors.find(error => error.type == 'releaseShelfLife')) {
|
|
745
|
+
errors.push({ type: 'releaseShelfLife', value: releaseShelfLifeValidation.error })
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
565
749
|
return item
|
|
566
750
|
})
|
|
567
751
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/biz-ui",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.723",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
"migration:create": "node ../../node_modules/typeorm/cli.js migration:create -d ./server/migrations"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@things-factory/biz-base": "^4.3.
|
|
27
|
-
"@things-factory/code-base": "^4.3.
|
|
28
|
-
"@things-factory/form-ui": "^4.3.
|
|
29
|
-
"@things-factory/grist-ui": "^4.3.
|
|
30
|
-
"@things-factory/i18n-base": "^4.3.
|
|
31
|
-
"@things-factory/import-ui": "^4.3.
|
|
32
|
-
"@things-factory/layout-base": "^4.3.
|
|
33
|
-
"@things-factory/shell": "^4.3.
|
|
26
|
+
"@things-factory/biz-base": "^4.3.723",
|
|
27
|
+
"@things-factory/code-base": "^4.3.723",
|
|
28
|
+
"@things-factory/form-ui": "^4.3.723",
|
|
29
|
+
"@things-factory/grist-ui": "^4.3.723",
|
|
30
|
+
"@things-factory/i18n-base": "^4.3.723",
|
|
31
|
+
"@things-factory/import-ui": "^4.3.723",
|
|
32
|
+
"@things-factory/layout-base": "^4.3.723",
|
|
33
|
+
"@things-factory/shell": "^4.3.723"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "34bf57aa5628280fc483602659df898706e14638"
|
|
36
36
|
}
|
package/translations/en.json
CHANGED
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
"field.billing_address": "billing address",
|
|
6
6
|
"field.company_name": "company name",
|
|
7
7
|
"field.other_company": "other company",
|
|
8
|
+
"field.release_shelf_life": "release shelf life",
|
|
8
9
|
"title.contact_points": "contact points",
|
|
9
10
|
"title.select_supplier": "select supplier",
|
|
10
11
|
"text.bizplace_is_not_selected": "customer is not selected",
|
|
11
12
|
"label.account_no": "account no",
|
|
12
13
|
"text.invalid_form": "invalid form",
|
|
13
|
-
|
|
14
|
+
|
|
14
15
|
"field.contact_point_customer_name": "Customer Name",
|
|
15
16
|
"field.contact_point_company_name": "Company Name",
|
|
16
17
|
"field.contact_point_other_company_name": "Other Company",
|
package/translations/ja.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"field.billing_address": "[jp]billing address",
|
|
6
6
|
"field.company_name": "[jp]company name",
|
|
7
7
|
"field.other_company": "[jp]other company",
|
|
8
|
+
"field.release_shelf_life": "[jp]release shelf life",
|
|
8
9
|
"title.contact_points": "[jp]contact points",
|
|
9
10
|
"title.select_supplier": "[jp]select supplier",
|
|
10
11
|
"text.bizplace_is_not_selected": "[jp]customer is not selected",
|
package/translations/ko.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"field.billing_address": "[ko]billing address",
|
|
6
6
|
"field.company_name": "[ko]company name",
|
|
7
7
|
"field.other_company": "[ko]other company",
|
|
8
|
+
"field.release_shelf_life": "[ko]release shelf life",
|
|
8
9
|
"title.contact_points": "[ko]contact points",
|
|
9
10
|
"title.select_supplier": "[ko]select supplier",
|
|
10
11
|
"text.bizplace_is_not_selected": "[ko]customer is not selected",
|
package/translations/ms.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"field.billing_address": "[ms]billing address",
|
|
6
6
|
"field.company_name": "[ms]company name",
|
|
7
7
|
"field.other_company": "[ms]other company",
|
|
8
|
+
"field.release_shelf_life": "[ms]release shelf life",
|
|
8
9
|
"title.contact_points": "[ms]contact points",
|
|
9
10
|
"title.select_supplier": "[ms]select supplier",
|
|
10
11
|
"text.bizplace_is_not_selected": "[ms]customer is not selected",
|
package/translations/zh.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"field.billing_address": "[zh]billing address",
|
|
6
6
|
"field.company_name": "[zh]company name",
|
|
7
7
|
"field.other_company": "[zh]other company",
|
|
8
|
+
"field.release_shelf_life": "[zh]release shelf life",
|
|
8
9
|
"title.contact_points": "[zh]contact points",
|
|
9
10
|
"title.select_supplier": "[zh]select supplier",
|
|
10
11
|
"text.bizplace_is_not_selected": "[zh]customer is not selected",
|