@openlettermarketing/olc-react-sdk 2.1.5 → 2.1.6-beta.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.
- package/build/index.js +77 -77
- package/build/index.js.map +1 -1
- package/build/types/src/assets/images/modal-icons/warning.d.ts +3 -0
- package/build/types/src/components/GenericUIBlocks/Dialog/V2/index.d.ts +1 -0
- package/build/types/src/components/TopNavigation/FieldValidationModal/index.d.ts +11 -0
- package/build/types/src/utils/message.d.ts +7 -0
- package/build/types/src/utils/template-builder.d.ts +16 -0
- package/build/types/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/assets/images/modal-icons/warning.tsx +15 -0
- package/src/components/CreateTemplate/V2/index.tsx +3 -1
- package/src/components/GenericUIBlocks/Dialog/V2/index.tsx +4 -2
- package/src/components/GenericUIBlocks/Dialog/V2/styles.scss +4 -0
- package/src/components/SidePanel/CustomQRCode/index.tsx +7 -7
- package/src/components/TopNavigation/FieldValidationModal/index.tsx +73 -0
- package/src/components/TopNavigation/FieldValidationModal/styles.scss +39 -0
- package/src/components/TopNavigation/index.tsx +44 -0
- package/src/utils/message.ts +8 -1
- package/src/utils/template-builder.ts +64 -1
- package/version.js +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { InvalidField } from '../../../utils/template-builder';
|
|
3
|
+
import './styles.scss';
|
|
4
|
+
interface FieldValidationModalProps {
|
|
5
|
+
open: boolean;
|
|
6
|
+
invalidFields: InvalidField[];
|
|
7
|
+
currentTheme?: string | null | undefined;
|
|
8
|
+
handleClose: () => void;
|
|
9
|
+
}
|
|
10
|
+
declare const FieldValidationModal: React.FC<FieldValidationModalProps>;
|
|
11
|
+
export default FieldValidationModal;
|
|
@@ -136,6 +136,13 @@ export declare const MESSAGES: {
|
|
|
136
136
|
readonly DOWNLOAD_ENVELOPE_BUTTON: "Download Envelope Proof";
|
|
137
137
|
readonly CANCEL_BUTTON: "Cancel";
|
|
138
138
|
readonly SUBMIT_BUTTON: "Save";
|
|
139
|
+
readonly FIELD_VALIDATION: {
|
|
140
|
+
readonly TITLE: "Invalid Fields";
|
|
141
|
+
readonly HEADING: "Please fix the following field errors";
|
|
142
|
+
readonly DESCRIPTION: (fieldNames: string) => string;
|
|
143
|
+
readonly INVALID_FORMAT: "is incorrect";
|
|
144
|
+
readonly NOT_UPPERCASE: "is incorrect";
|
|
145
|
+
};
|
|
139
146
|
};
|
|
140
147
|
readonly QR_CODE_MODAL: {
|
|
141
148
|
readonly CREATE_TITLE: "Create New QR Code";
|
|
@@ -72,3 +72,19 @@ export declare const extractCustomRistrictedBoxColor: (jsonData: any) => null;
|
|
|
72
72
|
export declare const validateGSV: (pages: any) => boolean;
|
|
73
73
|
export declare const validateEmoji: (pages: any) => boolean;
|
|
74
74
|
export declare const isValidQR: (pages: any) => boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Interface for invalid field validation results
|
|
77
|
+
*/
|
|
78
|
+
export interface InvalidField {
|
|
79
|
+
field: string;
|
|
80
|
+
issue: 'INVALID_FORMAT' | 'NOT_UPPERCASE';
|
|
81
|
+
pageIndex: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validates template fields for correct format and capitalization
|
|
85
|
+
* Returns array of invalid fields found in the template
|
|
86
|
+
*
|
|
87
|
+
* @param pages - Template pages array from store.toJSON()
|
|
88
|
+
* @returns Array of objects containing invalid fields and their issues
|
|
89
|
+
*/
|
|
90
|
+
export declare const validateTemplateFields: (pages: any) => InvalidField[];
|
package/build/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION: "2.1.
|
|
1
|
+
export const SDK_VERSION: "2.1.6-beta.1";
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const WarningIcon = (props: any) => {
|
|
4
|
+
const { fill = 'var(--primary-color)' } = props;
|
|
5
|
+
|
|
6
|
+
return (
|
|
7
|
+
<svg width="34" height="34" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
8
|
+
<path d="M24 4L4 44H44L24 4Z" stroke={fill} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
9
|
+
<path d="M24 18V28" stroke={fill} strokeWidth="2" strokeLinecap="round"/>
|
|
10
|
+
<circle cx="24" cy="36" r="2" fill={fill}/>
|
|
11
|
+
</svg>
|
|
12
|
+
);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default WarningIcon;
|
|
@@ -407,7 +407,9 @@ const CreateTemplateV2: React.FC<CreateTemplateV2Props> = ({
|
|
|
407
407
|
<div className='size-selection-container'>
|
|
408
408
|
<Typography style={descriptionStyles}>Design Format</Typography>
|
|
409
409
|
<div className='radio-buttons-container'>
|
|
410
|
-
{product?.size
|
|
410
|
+
{product?.size
|
|
411
|
+
?.filter((type: any) => !restrictedSet.has(String(type.id)))
|
|
412
|
+
.map((type: any) => (
|
|
411
413
|
<label key={type.id} className={`radio-button-wrapper ${selectedRPLType === type.id ? 'selected' : ''}`}>
|
|
412
414
|
<input type="radio" name="postcardSize" value={type.id} checked={selectedRPLType === type.id} onChange={() => handleRealPennedLetter(type, product)} className="radio-input" />
|
|
413
415
|
<span className="radio-button"></span>
|
|
@@ -27,6 +27,7 @@ interface DialogProps {
|
|
|
27
27
|
isGallery?: boolean;
|
|
28
28
|
currentTheme?: string | null | undefined;
|
|
29
29
|
isQRCode?: boolean;
|
|
30
|
+
hideButtons?: boolean;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
const buttonStyles: CSSProperties = {
|
|
@@ -80,7 +81,8 @@ const DialogV2: React.FC<DialogProps> = ({
|
|
|
80
81
|
children = [],
|
|
81
82
|
isGallery = false,
|
|
82
83
|
currentTheme = "default",
|
|
83
|
-
isQRCode = false
|
|
84
|
+
isQRCode = false,
|
|
85
|
+
hideButtons = false
|
|
84
86
|
}) => {
|
|
85
87
|
const contentAdjust = submitText.length > 6 ? "fit-content" : "100px";
|
|
86
88
|
|
|
@@ -204,7 +206,7 @@ const DialogV2: React.FC<DialogProps> = ({
|
|
|
204
206
|
)}
|
|
205
207
|
{children}
|
|
206
208
|
<div className="confirm-modal-footer">
|
|
207
|
-
{!isGallery &&
|
|
209
|
+
{!isGallery && !hideButtons &&
|
|
208
210
|
<>
|
|
209
211
|
<button onClick={onSubmit} disabled={loading}>
|
|
210
212
|
{loading ? <CircularProgress style={progressStyles} /> : submitText}
|
|
@@ -625,11 +625,11 @@ const CustomQRCode = {
|
|
|
625
625
|
const handleEditQRCode = async (qrCode: any) => {
|
|
626
626
|
setIsEditing(true);
|
|
627
627
|
setSelectedQR(qrCode);
|
|
628
|
-
dispatch(setQrUrl(qrCode.url));
|
|
629
|
-
dispatch(setUtmSource(qrCode.
|
|
630
|
-
dispatch(setUtmMedium(qrCode.
|
|
631
|
-
dispatch(setUtmCampaignName(qrCode.utm_campaign_name
|
|
632
|
-
dispatch(setCustomUtms(qrCode.custom_utms
|
|
628
|
+
dispatch(setQrUrl(qrCode.url ?? ''));
|
|
629
|
+
dispatch(setUtmSource(qrCode.utm_source ?? ''));
|
|
630
|
+
dispatch(setUtmMedium(qrCode.utm_medium ?? ''));
|
|
631
|
+
dispatch(setUtmCampaignName(qrCode.utm_campaign_name ?? ''));
|
|
632
|
+
dispatch(setCustomUtms(qrCode.custom_utms ?? {}));
|
|
633
633
|
|
|
634
634
|
handleDialogChange('qr-modal');
|
|
635
635
|
setIsActionsOpen(null);
|
|
@@ -678,8 +678,8 @@ const CustomQRCode = {
|
|
|
678
678
|
name: utmCampaignName,
|
|
679
679
|
url: url,
|
|
680
680
|
qrImagePath: uploadedFile,
|
|
681
|
-
utm_source: utmSource,
|
|
682
|
-
utm_medium: utmMedium,
|
|
681
|
+
utm_source: utmSource || null,
|
|
682
|
+
utm_medium: utmMedium || null,
|
|
683
683
|
utm_campaign_name: utmCampaignName,
|
|
684
684
|
custom_utms: customUtms,
|
|
685
685
|
},
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
// Utils
|
|
4
|
+
import { MESSAGES } from '../../../utils/message';
|
|
5
|
+
|
|
6
|
+
// Components
|
|
7
|
+
import Dialog from '../../GenericUIBlocks/Dialog';
|
|
8
|
+
import DialogV2 from '../../GenericUIBlocks/Dialog/V2';
|
|
9
|
+
|
|
10
|
+
// Icons
|
|
11
|
+
import Warning from '../../../assets/images/modal-icons/warning';
|
|
12
|
+
|
|
13
|
+
// Types
|
|
14
|
+
import { InvalidField } from '../../../utils/template-builder';
|
|
15
|
+
|
|
16
|
+
// Styles
|
|
17
|
+
import './styles.scss';
|
|
18
|
+
|
|
19
|
+
interface FieldValidationModalProps {
|
|
20
|
+
open: boolean;
|
|
21
|
+
invalidFields: InvalidField[];
|
|
22
|
+
currentTheme?: string | null | undefined;
|
|
23
|
+
handleClose: () => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const modalStyles = {
|
|
27
|
+
maxWidth: '600px',
|
|
28
|
+
minHeight: '300px',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const modalStylesV2 = {
|
|
32
|
+
maxWidth: '600px',
|
|
33
|
+
minHeight: '300px',
|
|
34
|
+
padding: '40px',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const FieldValidationModal: React.FC<FieldValidationModalProps> = ({
|
|
38
|
+
open,
|
|
39
|
+
invalidFields,
|
|
40
|
+
currentTheme,
|
|
41
|
+
handleClose,
|
|
42
|
+
}) => {
|
|
43
|
+
// Build the description with all field names (reversed so UI order matches template order)
|
|
44
|
+
const fieldNames = [...invalidFields].reverse().map(item => `"${item.field}"`).join(', ');
|
|
45
|
+
const description = MESSAGES.TEMPLATE.FIELD_VALIDATION.DESCRIPTION(fieldNames);
|
|
46
|
+
|
|
47
|
+
return currentTheme === 'v2' ? (
|
|
48
|
+
<DialogV2
|
|
49
|
+
icon={<Warning fill="var(--primary-color)" />}
|
|
50
|
+
customStyles={modalStylesV2}
|
|
51
|
+
open={open}
|
|
52
|
+
handleClose={handleClose}
|
|
53
|
+
title={MESSAGES.TEMPLATE.FIELD_VALIDATION.TITLE}
|
|
54
|
+
subHeading=""
|
|
55
|
+
description={description}
|
|
56
|
+
currentTheme="v2"
|
|
57
|
+
isGallery={false}
|
|
58
|
+
hideButtons={true}
|
|
59
|
+
/>
|
|
60
|
+
) : (
|
|
61
|
+
<Dialog
|
|
62
|
+
icon={<Warning fill="var(--primary-color)" />}
|
|
63
|
+
customStyles={modalStyles}
|
|
64
|
+
open={open}
|
|
65
|
+
handleClose={handleClose}
|
|
66
|
+
title={MESSAGES.TEMPLATE.FIELD_VALIDATION.TITLE}
|
|
67
|
+
subHeading=""
|
|
68
|
+
description={description}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default FieldValidationModal;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
.field-validation-content {
|
|
2
|
+
margin-top: 20px;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.field-validation-list {
|
|
6
|
+
max-height: 300px;
|
|
7
|
+
overflow-y: auto;
|
|
8
|
+
padding: 10px;
|
|
9
|
+
background-color: #f9f9f9;
|
|
10
|
+
border-radius: 4px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.field-validation-item {
|
|
14
|
+
margin-bottom: 15px;
|
|
15
|
+
padding: 12px;
|
|
16
|
+
background-color: #fff;
|
|
17
|
+
border-left: 3px solid #ff9800;
|
|
18
|
+
border-radius: 4px;
|
|
19
|
+
|
|
20
|
+
.field-name {
|
|
21
|
+
font-weight: 600;
|
|
22
|
+
color: #333;
|
|
23
|
+
margin-bottom: 5px;
|
|
24
|
+
font-family: 'Courier New', monospace;
|
|
25
|
+
font-size: 14px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.field-error {
|
|
29
|
+
color: #666;
|
|
30
|
+
font-size: 13px;
|
|
31
|
+
margin-bottom: 4px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.field-location {
|
|
35
|
+
color: #999;
|
|
36
|
+
font-size: 12px;
|
|
37
|
+
font-style: italic;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -20,6 +20,7 @@ import { searchAndAdvanceChange } from '../../redux/actions/templateActions';
|
|
|
20
20
|
import SaveTemplateModel from './SaveTemplateModel';
|
|
21
21
|
import ConfirmNavigateDialog from './ConfirmNavigateDialog';
|
|
22
22
|
import EditTemplateNameModel from './EditTemplateNameModel';
|
|
23
|
+
import FieldValidationModal from './FieldValidationModal';
|
|
23
24
|
|
|
24
25
|
// Utils
|
|
25
26
|
import {
|
|
@@ -31,6 +32,8 @@ import {
|
|
|
31
32
|
removeBracketsFromRPL,
|
|
32
33
|
validateEmoji,
|
|
33
34
|
validateGSV,
|
|
35
|
+
validateTemplateFields,
|
|
36
|
+
InvalidField,
|
|
34
37
|
} from '../../utils/template-builder';
|
|
35
38
|
import { addSafetyBordersToNonWindowProfessioanl } from '../../utils/templateSafetyBorders/professional';
|
|
36
39
|
import { addIdentifierAreaToProfessionalNonWindow } from '../../utils/templateIdentifierArea/professional';
|
|
@@ -142,6 +145,7 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
|
|
|
142
145
|
const [downloadingProof, setDownloaingProof] = useState<boolean>(false);
|
|
143
146
|
const [downloadingEnvelope, setDownloaingEnvelope] = useState<boolean>(false);
|
|
144
147
|
const [templateTitle, setTemplateTitle] = useState('');
|
|
148
|
+
const [invalidFields, setInvalidFields] = useState<InvalidField[]>([]);
|
|
145
149
|
|
|
146
150
|
const { id } = useParams<{ id: string }>();
|
|
147
151
|
|
|
@@ -447,6 +451,19 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
|
|
|
447
451
|
return;
|
|
448
452
|
}
|
|
449
453
|
|
|
454
|
+
// Validate fields FIRST - before other validations
|
|
455
|
+
const fieldValidationResult = validateTemplateFields(jsonData.pages);
|
|
456
|
+
|
|
457
|
+
if (fieldValidationResult.length > 0) {
|
|
458
|
+
setInvalidFields(fieldValidationResult);
|
|
459
|
+
setIsShowModel((prev) => ({
|
|
460
|
+
...prev,
|
|
461
|
+
open: true,
|
|
462
|
+
model: 'field-validation'
|
|
463
|
+
}));
|
|
464
|
+
return; // Stop save process
|
|
465
|
+
}
|
|
466
|
+
|
|
450
467
|
const hasEmoji = validateEmoji(jsonData.pages);
|
|
451
468
|
|
|
452
469
|
if (hasEmoji) {
|
|
@@ -576,6 +593,24 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
|
|
|
576
593
|
model: string = '',
|
|
577
594
|
loading: string | null = null
|
|
578
595
|
) => {
|
|
596
|
+
// If trying to open save modal, validate fields first
|
|
597
|
+
if (model === 'save' && templateType === 'json') {
|
|
598
|
+
const jsonData = store.toJSON();
|
|
599
|
+
const fieldValidationResult = validateTemplateFields(jsonData.pages);
|
|
600
|
+
|
|
601
|
+
if (fieldValidationResult.length > 0) {
|
|
602
|
+
// Show validation modal instead of save modal
|
|
603
|
+
setInvalidFields(fieldValidationResult);
|
|
604
|
+
setIsShowModel({
|
|
605
|
+
open: true,
|
|
606
|
+
model: 'field-validation',
|
|
607
|
+
loading: false
|
|
608
|
+
});
|
|
609
|
+
return; // Don't open save modal
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// If validation passed or not save modal, proceed normally
|
|
579
614
|
setIsShowModel((prev) => ({
|
|
580
615
|
...prev,
|
|
581
616
|
open: !prev.open,
|
|
@@ -913,6 +948,15 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
|
|
|
913
948
|
currentTheme={currentTheme}
|
|
914
949
|
/>
|
|
915
950
|
)}
|
|
951
|
+
{/* Field Validation Modal */}
|
|
952
|
+
{isShowModel.open && isShowModel.model === 'field-validation' && (
|
|
953
|
+
<FieldValidationModal
|
|
954
|
+
open={isShowModel.open}
|
|
955
|
+
invalidFields={invalidFields}
|
|
956
|
+
currentTheme={currentTheme}
|
|
957
|
+
handleClose={() => handleChangeModel()}
|
|
958
|
+
/>
|
|
959
|
+
)}
|
|
916
960
|
{/* Duplicate Template Modal */}
|
|
917
961
|
<DuplicateTemplateModal
|
|
918
962
|
open={isShowModel.open && isShowModel.model === 'duplicate'}
|
package/src/utils/message.ts
CHANGED
|
@@ -142,7 +142,14 @@ export const MESSAGES = {
|
|
|
142
142
|
DOWNLOAD_PROOF_BUTTON: "Download Mailer Proof",
|
|
143
143
|
DOWNLOAD_ENVELOPE_BUTTON: "Download Envelope Proof",
|
|
144
144
|
CANCEL_BUTTON: "Cancel",
|
|
145
|
-
SUBMIT_BUTTON: "Save"
|
|
145
|
+
SUBMIT_BUTTON: "Save",
|
|
146
|
+
FIELD_VALIDATION: {
|
|
147
|
+
TITLE: "Invalid Fields",
|
|
148
|
+
HEADING: "Please fix the following field errors",
|
|
149
|
+
DESCRIPTION: (fieldNames: string) => `Following fields ${fieldNames} are incorrect to proceed further. You need to fix those`,
|
|
150
|
+
INVALID_FORMAT: "is incorrect",
|
|
151
|
+
NOT_UPPERCASE: "is incorrect",
|
|
152
|
+
},
|
|
146
153
|
},
|
|
147
154
|
QR_CODE_MODAL: {
|
|
148
155
|
CREATE_TITLE: "Create New QR Code",
|
|
@@ -325,4 +325,67 @@ export const isValidQR = (pages: any) => {
|
|
|
325
325
|
}
|
|
326
326
|
}
|
|
327
327
|
return true;
|
|
328
|
-
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Interface for invalid field validation results
|
|
332
|
+
*/
|
|
333
|
+
export interface InvalidField {
|
|
334
|
+
field: string;
|
|
335
|
+
issue: 'INVALID_FORMAT' | 'NOT_UPPERCASE';
|
|
336
|
+
pageIndex: number;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Validates template fields for correct format and capitalization
|
|
341
|
+
* Returns array of invalid fields found in the template
|
|
342
|
+
*
|
|
343
|
+
* @param pages - Template pages array from store.toJSON()
|
|
344
|
+
* @returns Array of objects containing invalid fields and their issues
|
|
345
|
+
*/
|
|
346
|
+
export const validateTemplateFields = (pages: any): InvalidField[] => {
|
|
347
|
+
const invalidFields: InvalidField[] = [];
|
|
348
|
+
|
|
349
|
+
pages.forEach((page: any, pageIndex: number) => {
|
|
350
|
+
page.children?.forEach((child: any) => {
|
|
351
|
+
if (child.type === 'text' && child.text) {
|
|
352
|
+
const text = child.text;
|
|
353
|
+
|
|
354
|
+
// Find all potential field tokens/fields in the text.
|
|
355
|
+
// A tokentokens/fields is any sequence that contains at least one brace character.
|
|
356
|
+
const tokens = text.split(/\s+/);
|
|
357
|
+
|
|
358
|
+
tokens.forEach((token: string) => {
|
|
359
|
+
if (!token) return;
|
|
360
|
+
|
|
361
|
+
// Only process tokens that contain at least one brace
|
|
362
|
+
if (!token.includes('{') && !token.includes('}')) return;
|
|
363
|
+
|
|
364
|
+
// Valid format: must be EXACTLY {{UPPERCASE_CONTENT}} with no extra chars
|
|
365
|
+
const isValidFormat = /^\{\{[A-Z0-9._]+\}\}$/.test(token);
|
|
366
|
+
|
|
367
|
+
if (!isValidFormat) {
|
|
368
|
+
const content = token.replace(/^\{+|\}+$/g, '');
|
|
369
|
+
const isDoubleBrace = /^\{\{.+\}\}$/.test(token);
|
|
370
|
+
const hasOnlyValidChars = /^[A-Za-z0-9._]+$/.test(content);
|
|
371
|
+
|
|
372
|
+
if (isDoubleBrace && hasOnlyValidChars && content !== content.toUpperCase()) {
|
|
373
|
+
// Double brace but lowercase content
|
|
374
|
+
invalidFields.push({ field: token, issue: 'NOT_UPPERCASE', pageIndex });
|
|
375
|
+
} else {
|
|
376
|
+
// Any other invalid format
|
|
377
|
+
invalidFields.push({ field: token, issue: 'INVALID_FORMAT', pageIndex });
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// Remove duplicates
|
|
386
|
+
const uniqueFields = invalidFields.filter((item: InvalidField, index: number, self: InvalidField[]) =>
|
|
387
|
+
index === self.findIndex((t: InvalidField) => t.field === item.field && t.issue === item.issue)
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
return uniqueFields;
|
|
391
|
+
};
|
package/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = '2.1.
|
|
1
|
+
export const SDK_VERSION = '2.1.6-beta.1';
|