cozy-ui-plus 4.0.0 → 4.2.0
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/CHANGELOG.md +14 -0
- package/dist/Contacts/AddModal/ContactForm/FieldInput.js +3 -7
- package/dist/Contacts/AddModal/ContactForm/FieldInputArray.js +3 -5
- package/dist/Contacts/AddModal/ContactForm/FieldInputLayout.js +2 -4
- package/dist/Contacts/AddModal/ContactForm/FieldInputWrapper.js +1 -1
- package/dist/Contacts/AddModal/ContactForm/contactToFormValues.js +75 -90
- package/dist/Contacts/AddModal/ContactForm/helpers.js +104 -34
- package/dist/Contacts/AddModal/ContactForm/index.js +7 -2
- package/dist/Contacts/AddModal/ContactForm/locales/index.js +4 -4
- package/dist/src/Contacts/AddModal/ContactForm/FieldInput.d.ts +2 -6
- package/dist/src/Contacts/AddModal/ContactForm/FieldInputArray.d.ts +2 -6
- package/dist/src/Contacts/AddModal/ContactForm/helpers.d.ts +5 -2
- package/package.json +2 -2
- package/src/Contacts/AddModal/ContactForm/FieldInput.jsx +3 -7
- package/src/Contacts/AddModal/ContactForm/FieldInputArray.jsx +7 -4
- package/src/Contacts/AddModal/ContactForm/FieldInputLayout.jsx +3 -3
- package/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx +1 -1
- package/src/Contacts/AddModal/ContactForm/contactToFormValues.js +79 -94
- package/src/Contacts/AddModal/ContactForm/contactToFormValues.spec.js +0 -23
- package/src/Contacts/AddModal/ContactForm/helpers.js +77 -17
- package/src/Contacts/AddModal/ContactForm/helpers.spec.js +344 -1
- package/src/Contacts/AddModal/ContactForm/index.jsx +24 -10
- package/src/Contacts/AddModal/ContactForm/locales/en.json +1 -1
- package/src/Contacts/AddModal/ContactForm/locales/fr.json +1 -1
- package/src/Contacts/AddModal/ContactForm/locales/ru.json +1 -1
- package/src/Contacts/AddModal/ContactForm/locales/vi.json +1 -1
|
@@ -7,7 +7,10 @@ import {
|
|
|
7
7
|
makeImppValues,
|
|
8
8
|
makeCustomLabel,
|
|
9
9
|
makeFields,
|
|
10
|
-
makeInitialCustomValue
|
|
10
|
+
makeInitialCustomValue,
|
|
11
|
+
hasNoValues,
|
|
12
|
+
getFirstValueIfArray,
|
|
13
|
+
validateFields
|
|
11
14
|
} from './helpers'
|
|
12
15
|
import { locales } from './locales'
|
|
13
16
|
|
|
@@ -388,4 +391,344 @@ describe('makeFields', () => {
|
|
|
388
391
|
|
|
389
392
|
expect(res).toStrictEqual(defaultFields)
|
|
390
393
|
})
|
|
394
|
+
|
|
395
|
+
it('should replace default fields values by custom fields', () => {
|
|
396
|
+
const defaultFields = [
|
|
397
|
+
{ name: 'firstname', type: 'text', layout: 'accordion' },
|
|
398
|
+
{ name: 'lastname' }
|
|
399
|
+
]
|
|
400
|
+
const customFields = [
|
|
401
|
+
{ name: 'firstname', isSecondary: true, layout: 'array' }
|
|
402
|
+
]
|
|
403
|
+
|
|
404
|
+
const res = makeFields(customFields, defaultFields)
|
|
405
|
+
|
|
406
|
+
expect(res).toStrictEqual([
|
|
407
|
+
{ name: 'firstname', type: 'text', isSecondary: true, layout: 'array' },
|
|
408
|
+
{ name: 'lastname' }
|
|
409
|
+
])
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
it('should replace default fields values and add custom fields at custom position', () => {
|
|
413
|
+
const defaultFields = [
|
|
414
|
+
{ name: 'firstname', type: 'text', layout: 'accordion' },
|
|
415
|
+
{ name: 'lastname' }
|
|
416
|
+
]
|
|
417
|
+
const customFields = [
|
|
418
|
+
{ name: 'firstname', isSecondary: true, layout: 'array', position: 1 }
|
|
419
|
+
]
|
|
420
|
+
|
|
421
|
+
const res = makeFields(customFields, defaultFields)
|
|
422
|
+
|
|
423
|
+
expect(res).toStrictEqual([
|
|
424
|
+
{ name: 'lastname' },
|
|
425
|
+
{
|
|
426
|
+
name: 'firstname',
|
|
427
|
+
type: 'text',
|
|
428
|
+
isSecondary: true,
|
|
429
|
+
layout: 'array',
|
|
430
|
+
position: 1
|
|
431
|
+
}
|
|
432
|
+
])
|
|
433
|
+
})
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
describe('hasNoValues', () => {
|
|
437
|
+
it('should return true when all fields have no values', () => {
|
|
438
|
+
const values = {}
|
|
439
|
+
const fields = [{ name: 'firstname' }, { name: 'lastname' }]
|
|
440
|
+
|
|
441
|
+
const res = hasNoValues(values, fields)
|
|
442
|
+
|
|
443
|
+
expect(res).toBe(true)
|
|
444
|
+
})
|
|
445
|
+
|
|
446
|
+
it('should return true when all field values are undefined', () => {
|
|
447
|
+
const values = { firstname: undefined, lastname: undefined }
|
|
448
|
+
const fields = [{ name: 'firstname' }, { name: 'lastname' }]
|
|
449
|
+
|
|
450
|
+
const res = hasNoValues(values, fields)
|
|
451
|
+
|
|
452
|
+
expect(res).toBe(true)
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
it('should return true when all field values are null', () => {
|
|
456
|
+
const values = { firstname: null, lastname: null }
|
|
457
|
+
const fields = [{ name: 'firstname' }, { name: 'lastname' }]
|
|
458
|
+
|
|
459
|
+
const res = hasNoValues(values, fields)
|
|
460
|
+
|
|
461
|
+
expect(res).toBe(true)
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
it('should return true when all field values are empty strings', () => {
|
|
465
|
+
const values = { firstname: '', lastname: '' }
|
|
466
|
+
const fields = [{ name: 'firstname' }, { name: 'lastname' }]
|
|
467
|
+
|
|
468
|
+
const res = hasNoValues(values, fields)
|
|
469
|
+
|
|
470
|
+
expect(res).toBe(true)
|
|
471
|
+
})
|
|
472
|
+
|
|
473
|
+
it('should return true when all field values are empty arrays', () => {
|
|
474
|
+
const values = { email: [], phone: [] }
|
|
475
|
+
const fields = [{ name: 'email' }, { name: 'phone' }]
|
|
476
|
+
|
|
477
|
+
const res = hasNoValues(values, fields)
|
|
478
|
+
|
|
479
|
+
expect(res).toBe(true)
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
it('should return false when at least one field has a value', () => {
|
|
483
|
+
const values = { firstname: 'John', lastname: undefined }
|
|
484
|
+
const fields = [{ name: 'firstname' }, { name: 'lastname' }]
|
|
485
|
+
|
|
486
|
+
const res = hasNoValues(values, fields)
|
|
487
|
+
|
|
488
|
+
expect(res).toBe(false)
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
it('should return false when at least one field has a non-empty string', () => {
|
|
492
|
+
const values = { firstname: '', lastname: 'Doe' }
|
|
493
|
+
const fields = [{ name: 'firstname' }, { name: 'lastname' }]
|
|
494
|
+
|
|
495
|
+
const res = hasNoValues(values, fields)
|
|
496
|
+
|
|
497
|
+
expect(res).toBe(false)
|
|
498
|
+
})
|
|
499
|
+
|
|
500
|
+
it('should return false when at least one field has a non-empty array', () => {
|
|
501
|
+
const values = { email: [{ address: 'john.doe@cozycloud.cc' }], phone: [] }
|
|
502
|
+
const fields = [{ name: 'email' }, { name: 'phone' }]
|
|
503
|
+
|
|
504
|
+
const res = hasNoValues(values, fields)
|
|
505
|
+
|
|
506
|
+
expect(res).toBe(false)
|
|
507
|
+
})
|
|
508
|
+
|
|
509
|
+
it('should return true for nested field paths with no values', () => {
|
|
510
|
+
const values = { phone: [{ number: undefined }] }
|
|
511
|
+
const fields = [{ name: 'phone[0].number' }]
|
|
512
|
+
|
|
513
|
+
const res = hasNoValues(values, fields)
|
|
514
|
+
|
|
515
|
+
expect(res).toBe(true)
|
|
516
|
+
})
|
|
517
|
+
|
|
518
|
+
it('should handle mixed array and non-array values', () => {
|
|
519
|
+
const values = { firstname: 'John', lastname: ['Doe'] }
|
|
520
|
+
const fields = [{ name: 'firstname' }, { name: 'lastname' }]
|
|
521
|
+
|
|
522
|
+
const res = hasNoValues(values, fields)
|
|
523
|
+
|
|
524
|
+
expect(res).toBe(false)
|
|
525
|
+
})
|
|
526
|
+
|
|
527
|
+
it('should return true when fields array is empty', () => {
|
|
528
|
+
const values = { firstname: 'John', lastname: 'Doe' }
|
|
529
|
+
const fields = []
|
|
530
|
+
|
|
531
|
+
const res = hasNoValues(values, fields)
|
|
532
|
+
|
|
533
|
+
expect(res).toBe(true)
|
|
534
|
+
})
|
|
535
|
+
})
|
|
536
|
+
|
|
537
|
+
describe('getFirstValueIfArray', () => {
|
|
538
|
+
it('should return the first value of arrays', () => {
|
|
539
|
+
const values = {
|
|
540
|
+
phone: [{ phone: '123' }, { phone: '456' }],
|
|
541
|
+
email: [{ email: 'test@example.com' }],
|
|
542
|
+
name: 'John'
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const res = getFirstValueIfArray(values)
|
|
546
|
+
|
|
547
|
+
expect(res).toEqual({
|
|
548
|
+
phone: { phone: '123' },
|
|
549
|
+
email: { email: 'test@example.com' },
|
|
550
|
+
name: 'John'
|
|
551
|
+
})
|
|
552
|
+
})
|
|
553
|
+
|
|
554
|
+
it('should return undefined for empty arrays', () => {
|
|
555
|
+
const values = {
|
|
556
|
+
phone: [],
|
|
557
|
+
email: [{ email: 'test@example.com' }]
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
const res = getFirstValueIfArray(values)
|
|
561
|
+
|
|
562
|
+
expect(res).toEqual({
|
|
563
|
+
phone: undefined,
|
|
564
|
+
email: { email: 'test@example.com' }
|
|
565
|
+
})
|
|
566
|
+
})
|
|
567
|
+
|
|
568
|
+
it('should not mutate the original object', () => {
|
|
569
|
+
const values = {
|
|
570
|
+
phone: [{ phone: '123' }, { phone: '456' }],
|
|
571
|
+
name: 'John'
|
|
572
|
+
}
|
|
573
|
+
const originalValues = JSON.parse(JSON.stringify(values))
|
|
574
|
+
|
|
575
|
+
getFirstValueIfArray(values)
|
|
576
|
+
|
|
577
|
+
expect(values).toEqual(originalValues)
|
|
578
|
+
})
|
|
579
|
+
|
|
580
|
+
it('should handle non-array values', () => {
|
|
581
|
+
const values = {
|
|
582
|
+
name: 'John',
|
|
583
|
+
age: 30,
|
|
584
|
+
active: true,
|
|
585
|
+
address: null
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const res = getFirstValueIfArray(values)
|
|
589
|
+
|
|
590
|
+
expect(res).toEqual({
|
|
591
|
+
name: 'John',
|
|
592
|
+
age: 30,
|
|
593
|
+
active: true,
|
|
594
|
+
address: null
|
|
595
|
+
})
|
|
596
|
+
})
|
|
597
|
+
|
|
598
|
+
it('should handle mixed array and non-array values', () => {
|
|
599
|
+
const values = {
|
|
600
|
+
phone: [{ phone: '123' }],
|
|
601
|
+
name: 'John',
|
|
602
|
+
email: []
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const res = getFirstValueIfArray(values)
|
|
606
|
+
|
|
607
|
+
expect(res).toEqual({
|
|
608
|
+
phone: { phone: '123' },
|
|
609
|
+
name: 'John',
|
|
610
|
+
email: undefined
|
|
611
|
+
})
|
|
612
|
+
})
|
|
613
|
+
|
|
614
|
+
it('should return empty object for empty input', () => {
|
|
615
|
+
const values = {}
|
|
616
|
+
|
|
617
|
+
const res = getFirstValueIfArray(values)
|
|
618
|
+
|
|
619
|
+
expect(res).toEqual({})
|
|
620
|
+
})
|
|
621
|
+
})
|
|
622
|
+
|
|
623
|
+
describe('validateFields', () => {
|
|
624
|
+
it('should return errors for required fields that are empty (non-array fields)', () => {
|
|
625
|
+
const values = {
|
|
626
|
+
name: '',
|
|
627
|
+
email: undefined
|
|
628
|
+
}
|
|
629
|
+
const fields = [
|
|
630
|
+
{ name: 'name', required: true },
|
|
631
|
+
{ name: 'email', required: true },
|
|
632
|
+
{ name: 'phone', required: false }
|
|
633
|
+
]
|
|
634
|
+
|
|
635
|
+
const res = validateFields(values, fields, t)
|
|
636
|
+
|
|
637
|
+
expect(res).toEqual({
|
|
638
|
+
name: 'All required fields must be filled in',
|
|
639
|
+
email: 'All required fields must be filled in'
|
|
640
|
+
})
|
|
641
|
+
})
|
|
642
|
+
|
|
643
|
+
it('should return errors for required array fields that are empty', () => {
|
|
644
|
+
const values = {
|
|
645
|
+
phone: []
|
|
646
|
+
}
|
|
647
|
+
const fields = [{ name: 'phone', required: true, layout: 'array' }]
|
|
648
|
+
|
|
649
|
+
const res = validateFields(values, fields, t)
|
|
650
|
+
|
|
651
|
+
expect(res).toEqual({
|
|
652
|
+
phone: [
|
|
653
|
+
{
|
|
654
|
+
phone: 'All required fields must be filled in'
|
|
655
|
+
}
|
|
656
|
+
]
|
|
657
|
+
})
|
|
658
|
+
})
|
|
659
|
+
|
|
660
|
+
it('should not return errors for required array fields with valid first element', () => {
|
|
661
|
+
const values = {
|
|
662
|
+
phone: [{ phone: '123456789' }]
|
|
663
|
+
}
|
|
664
|
+
const fields = [{ name: 'phone', required: true, layout: 'array' }]
|
|
665
|
+
|
|
666
|
+
const res = validateFields(values, fields, t)
|
|
667
|
+
|
|
668
|
+
expect(res).toEqual({})
|
|
669
|
+
})
|
|
670
|
+
|
|
671
|
+
it('should not return errors for non-required fields', () => {
|
|
672
|
+
const values = {
|
|
673
|
+
name: '',
|
|
674
|
+
phone: []
|
|
675
|
+
}
|
|
676
|
+
const fields = [
|
|
677
|
+
{ name: 'name', required: false },
|
|
678
|
+
{ name: 'phone', required: false, layout: 'array' }
|
|
679
|
+
]
|
|
680
|
+
|
|
681
|
+
const res = validateFields(values, fields, t)
|
|
682
|
+
|
|
683
|
+
expect(res).toEqual({})
|
|
684
|
+
})
|
|
685
|
+
|
|
686
|
+
it('should handle mixed array and non-array required fields', () => {
|
|
687
|
+
const values = {
|
|
688
|
+
name: '',
|
|
689
|
+
phone: []
|
|
690
|
+
}
|
|
691
|
+
const fields = [
|
|
692
|
+
{ name: 'name', required: true },
|
|
693
|
+
{ name: 'phone', required: true, layout: 'array' }
|
|
694
|
+
]
|
|
695
|
+
|
|
696
|
+
const res = validateFields(values, fields, t)
|
|
697
|
+
|
|
698
|
+
expect(res).toEqual({
|
|
699
|
+
name: 'All required fields must be filled in',
|
|
700
|
+
phone: [
|
|
701
|
+
{
|
|
702
|
+
phone: 'All required fields must be filled in'
|
|
703
|
+
}
|
|
704
|
+
]
|
|
705
|
+
})
|
|
706
|
+
})
|
|
707
|
+
|
|
708
|
+
it('should use getFirstValueIfArray to check only first element of arrays', () => {
|
|
709
|
+
const values = {
|
|
710
|
+
phone: [{ phone: '123' }, {}]
|
|
711
|
+
}
|
|
712
|
+
const fields = [{ name: 'phone', required: true, layout: 'array' }]
|
|
713
|
+
|
|
714
|
+
const res = validateFields(values, fields, t)
|
|
715
|
+
|
|
716
|
+
// Should not return error because first element has phone value
|
|
717
|
+
expect(res).toEqual({})
|
|
718
|
+
})
|
|
719
|
+
|
|
720
|
+
it('should return empty errors object when no required fields are empty', () => {
|
|
721
|
+
const values = {
|
|
722
|
+
name: 'John',
|
|
723
|
+
phone: [{ phone: '123456789' }]
|
|
724
|
+
}
|
|
725
|
+
const fields = [
|
|
726
|
+
{ name: 'name', required: true },
|
|
727
|
+
{ name: 'phone', required: true, layout: 'array' }
|
|
728
|
+
]
|
|
729
|
+
|
|
730
|
+
const res = validateFields(values, fields, t)
|
|
731
|
+
|
|
732
|
+
expect(res).toEqual({})
|
|
733
|
+
})
|
|
391
734
|
})
|
|
@@ -10,7 +10,12 @@ import FieldInputLayout from './FieldInputLayout'
|
|
|
10
10
|
import contactToFormValues from './contactToFormValues'
|
|
11
11
|
import { fields as defaultFields } from './fieldsConfig'
|
|
12
12
|
import formValuesToContact from './formValuesToContact'
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
validateFields,
|
|
15
|
+
makeFields,
|
|
16
|
+
hasNoValues,
|
|
17
|
+
initializationFieldValues
|
|
18
|
+
} from './helpers'
|
|
14
19
|
import { locales } from './locales'
|
|
15
20
|
// import { fullContactPropTypes } from '../../ContactPropTypes' // !!
|
|
16
21
|
|
|
@@ -50,14 +55,23 @@ const ContactForm = ({ contacts, contact, customFieldsProps, onSubmit }) => {
|
|
|
50
55
|
return (
|
|
51
56
|
<Form
|
|
52
57
|
mutators={{ ...arrayMutators }}
|
|
53
|
-
initialValues={
|
|
54
|
-
contact
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
initialValues={
|
|
59
|
+
!contact
|
|
60
|
+
? initializationFieldValues(_fields)
|
|
61
|
+
: contactToFormValues({
|
|
62
|
+
contact,
|
|
63
|
+
makeCustomContactValues,
|
|
64
|
+
t
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
validate={values => validateFields(values, _fields, t)}
|
|
68
|
+
onSubmit={formValues => {
|
|
69
|
+
// avoid creating an empty contact
|
|
70
|
+
if (hasNoValues(formValues, _fields)) {
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return onSubmit(
|
|
61
75
|
formValuesToContact({
|
|
62
76
|
formValues,
|
|
63
77
|
oldContact: contact,
|
|
@@ -65,7 +79,7 @@ const ContactForm = ({ contacts, contact, customFieldsProps, onSubmit }) => {
|
|
|
65
79
|
t
|
|
66
80
|
})
|
|
67
81
|
)
|
|
68
|
-
}
|
|
82
|
+
}}
|
|
69
83
|
render={({ handleSubmit, valid, submitFailed, errors }) => {
|
|
70
84
|
setSubmitContactForm(handleSubmit)
|
|
71
85
|
return (
|