@capillarytech/creatives-library 8.0.353-alpha.2 → 8.0.353-alpha.4
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/package.json
CHANGED
|
@@ -79,6 +79,69 @@ const errorMessageForTags = {
|
|
|
79
79
|
TAG_BRACKET_COUNT_MISMATCH_ERROR: 'tagBracketCountMismatchError'
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
+
// Isolated input for EMAIL template-name: only this tiny component re-renders on each keystroke.
|
|
83
|
+
// formData is updated only on blur (onCommit), eliminating all re-renders during typing.
|
|
84
|
+
class HighFreqInput extends React.Component {
|
|
85
|
+
constructor(props) {
|
|
86
|
+
super(props);
|
|
87
|
+
this.state = { localValue: props.value || '' };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
componentDidUpdate(prevProps) {
|
|
91
|
+
if (prevProps.value !== this.props.value && this.state.localValue !== this.props.value) {
|
|
92
|
+
this.setState({ localValue: this.props.value || '' });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
handleChange = (e) => {
|
|
97
|
+
this.setState({ localValue: e.target.value });
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
handleBlur = (e) => {
|
|
101
|
+
this.props.onCommit(this.state.localValue);
|
|
102
|
+
if (this.props.onBlur) this.props.onBlur(e);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
render() {
|
|
106
|
+
const { value: _v, onCommit: _oc, onBlur: _ob, ...rest } = this.props;
|
|
107
|
+
return <CapInput {...rest} value={this.state.localValue} onChange={this.handleChange} onBlur={this.handleBlur} />;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Isolated wrapper for EMAIL template-subject: blur-only commit, same as HighFreqInput.
|
|
112
|
+
class HighFreqTagInput extends React.Component {
|
|
113
|
+
constructor(props) {
|
|
114
|
+
super(props);
|
|
115
|
+
this.state = { localInputValue: props.inputValue || '' };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
componentDidUpdate(prevProps) {
|
|
119
|
+
if (prevProps.inputValue !== this.props.inputValue && this.state.localInputValue !== this.props.inputValue) {
|
|
120
|
+
this.setState({ localInputValue: this.props.inputValue || '' });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
handleInputChange = (e) => {
|
|
125
|
+
this.setState({ localInputValue: e.target.value });
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
handleBlur = () => {
|
|
129
|
+
this.props.onCommit(this.state.localInputValue);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
render() {
|
|
133
|
+
const { inputValue: _iv, onCommit: _oc, inputOnChange: _ic, ...rest } = this.props;
|
|
134
|
+
return (
|
|
135
|
+
<CapTagListWithInput
|
|
136
|
+
{...rest}
|
|
137
|
+
inputValue={this.state.localInputValue}
|
|
138
|
+
inputOnChange={this.handleInputChange}
|
|
139
|
+
inputProps={{ ...(this.props.inputProps || {}), onBlur: this.handleBlur }}
|
|
140
|
+
/>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
82
145
|
class FormBuilder extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
83
146
|
constructor(props) {
|
|
84
147
|
super(props);
|
|
@@ -352,6 +415,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
352
415
|
this.setState({tabCount: nextProps.tabCount});
|
|
353
416
|
}
|
|
354
417
|
if (nextProps.startValidation && nextProps.startValidation !== false && this.props.startValidation !== nextProps.startValidation) {
|
|
418
|
+
if (this.debouncedUpdateFormData) this.debouncedUpdateFormData.flush();
|
|
355
419
|
this.setState({checkValidation: true});
|
|
356
420
|
this.validateForm(null, null, true, true, () => {
|
|
357
421
|
//triggering the saveFormData or onSubmit when validation sets isFormValid to TRUE
|
|
@@ -382,12 +446,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
382
446
|
this.setState({formData: nextProps.formData, tabCount: nextProps.tabCount});
|
|
383
447
|
// this.resetTabKeys(nextProps.formData, nextProps.tabCount);
|
|
384
448
|
} else if (this.props.schema && this.props.schema.channel && this.props.schema.channel.toUpperCase() === 'EMAIL') {
|
|
385
|
-
|
|
386
|
-
// already updated them via updateFieldValueImmediately, so overwriting here
|
|
387
|
-
// would cause a redundant full re-render ~300ms after every keystroke.
|
|
388
|
-
if (!this._isOnlyHighFreqUpdate(nextProps.formData, this.state.formData)) {
|
|
389
|
-
this.setState({formData: nextProps.formData});
|
|
390
|
-
}
|
|
449
|
+
this.setState({formData: nextProps.formData});
|
|
391
450
|
}
|
|
392
451
|
|
|
393
452
|
if (this.state.usingTabContainer && this.state.tabKey === '') {
|
|
@@ -428,24 +487,14 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
428
487
|
( !this.state.usingTabContainer || (this.state.usingTabContainer && nextProps.tabKey !== ''))
|
|
429
488
|
&& !_.isEqual(nextProps.formData, this.state.formData) &&
|
|
430
489
|
!_.isEqual(nextProps.formData, this.props.formData)) {
|
|
431
|
-
//
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
if (!isEmailHighFreqOnly) {
|
|
440
|
-
// Don't run validation if we're in Test & Preview mode
|
|
441
|
-
if (!nextProps.isTestAndPreviewMode) {
|
|
442
|
-
this.setState({formData: nextProps.formData, tabKey: nextProps.tabKey}, () => {
|
|
443
|
-
this.validateForm();
|
|
444
|
-
});
|
|
445
|
-
} else {
|
|
446
|
-
// Just update formData without validation
|
|
447
|
-
this.setState({formData: nextProps.formData, tabKey: nextProps.tabKey});
|
|
448
|
-
}
|
|
490
|
+
// Don't run validation if we're in Test & Preview mode
|
|
491
|
+
if (!nextProps.isTestAndPreviewMode) {
|
|
492
|
+
this.setState({formData: nextProps.formData, tabKey: nextProps.tabKey}, () => {
|
|
493
|
+
this.validateForm();
|
|
494
|
+
});
|
|
495
|
+
} else {
|
|
496
|
+
// Just update formData without validation
|
|
497
|
+
this.setState({formData: nextProps.formData, tabKey: nextProps.tabKey});
|
|
449
498
|
}
|
|
450
499
|
//this.resetTabKeys(nextProps.formData, nextProps.tabCount);
|
|
451
500
|
} else if ((_.isEmpty(this.props.formData) || !this.props.formData) && _.isEmpty(this.state.formData)) {
|
|
@@ -463,16 +512,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
463
512
|
this.setState({currentTab: nextProps.currentTab});
|
|
464
513
|
}
|
|
465
514
|
|
|
466
|
-
|
|
467
|
-
// and the setState + validateForm cascade triggered by every debounced keystroke.
|
|
468
|
-
const isEmailHighFreqOnly = (
|
|
469
|
-
!_.isEmpty(nextProps.formData) &&
|
|
470
|
-
this.props.schema &&
|
|
471
|
-
this.props.schema.channel &&
|
|
472
|
-
this.props.schema.channel.toUpperCase() === 'EMAIL' &&
|
|
473
|
-
this._isOnlyHighFreqUpdate(nextProps.formData, this.state.formData)
|
|
474
|
-
);
|
|
475
|
-
if (!isEmailHighFreqOnly && !_.isEmpty(nextProps.formData) && !_.isEqual(this.state.formData, nextProps.formData)) {
|
|
515
|
+
if (!_.isEmpty(nextProps.formData) && !_.isEqual(this.state.formData, nextProps.formData)) {
|
|
476
516
|
if (nextProps.isNewVersionFlow) {
|
|
477
517
|
const tabKey = (this.state.tabKey !== nextProps.formData[nextProps.currentTab - 1].tabKey) ? nextProps.formData[nextProps.currentTab - 1].tabKey : this.state.tabKey;
|
|
478
518
|
|
|
@@ -2205,20 +2245,6 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2205
2245
|
this.debouncedUpdateFormData(data, val, event, true);
|
|
2206
2246
|
}
|
|
2207
2247
|
|
|
2208
|
-
// Returns true when the only differences between newData and currentData are
|
|
2209
|
-
// the high-frequency standalone fields (template-name / template-subject).
|
|
2210
|
-
// Uses reference equality for all other keys — safe because shallow spreads in
|
|
2211
|
-
// optimizedFormDataUpdate and updateFieldValueImmediately preserve nested refs.
|
|
2212
|
-
_isOnlyHighFreqUpdate(newData, currentData) {
|
|
2213
|
-
if (!newData || !currentData) return false;
|
|
2214
|
-
// isTemplateNameEdited is set alongside template-name by performTemplateNameUpdate
|
|
2215
|
-
// and treated as a high-freq field so it doesn't break the reference equality check.
|
|
2216
|
-
const HIGH_FREQ_FIELDS = ['template-name', 'template-subject', 'isTemplateNameEdited'];
|
|
2217
|
-
return Object.keys(newData).every(
|
|
2218
|
-
key => HIGH_FREQ_FIELDS.includes(key) || newData[key] === currentData[key]
|
|
2219
|
-
);
|
|
2220
|
-
}
|
|
2221
|
-
|
|
2222
2248
|
// Update field value immediately for UI feedback
|
|
2223
2249
|
updateFieldValueImmediately(data, val) {
|
|
2224
2250
|
const currentFormData = this.state.formData;
|
|
@@ -3448,40 +3474,62 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3448
3474
|
? formatMessage(messages.personalizationTagsErrorMessage)
|
|
3449
3475
|
: (errorType === TAG_BRACKET_COUNT_MISMATCH_ERROR ? formatMessage(globalMessages.unbalanacedCurlyBraces) : (val.errorMessage && ifError ? val.errorMessage : ''));
|
|
3450
3476
|
if (styling === 'semantic') {
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3477
|
+
const isEmailStandaloneHighFreq = val.standalone && this.props.schema?.channel?.toUpperCase() === 'EMAIL';
|
|
3478
|
+
if (isEmailStandaloneHighFreq) {
|
|
3479
|
+
columns.push(
|
|
3480
|
+
<CapColumn key={val.id} span={val.width} offset={val.offset} style={val.style || {}}>
|
|
3481
|
+
<HighFreqInput
|
|
3482
|
+
id={val.id}
|
|
3483
|
+
errorMessage={errorMessageText}
|
|
3484
|
+
label={val.label}
|
|
3485
|
+
inductiveText={val.inductiveText}
|
|
3486
|
+
className={`input-primary chart-name-input${ifError ? ' error' : ''}`}
|
|
3487
|
+
style={val.style ? val.style : {}}
|
|
3488
|
+
placeholder={val.placeholder}
|
|
3489
|
+
onCommit={(newValue) => this.performFormDataUpdate(newValue, val)}
|
|
3490
|
+
onBlur={(e) => this.handleFieldBlur(e, val)}
|
|
3491
|
+
value={value || ""}
|
|
3492
|
+
disabled={val.disabled}
|
|
3493
|
+
size={val.size || "default"}
|
|
3494
|
+
/>
|
|
3495
|
+
</CapColumn>
|
|
3496
|
+
);
|
|
3497
|
+
} else {
|
|
3498
|
+
columns.push(
|
|
3499
|
+
<CapColumn key={val.id} span={val.width} offset={val.offset} style={val.style || {}}>
|
|
3500
|
+
<CapInput
|
|
3501
|
+
id={val.id}
|
|
3502
|
+
errorMessage={errorMessageText}
|
|
3503
|
+
label={val.label}
|
|
3504
|
+
inductiveText={val.inductiveText}
|
|
3505
|
+
className={`input-primary chart-name-input${ifError ? ' error' : ''}`}
|
|
3506
|
+
// fluid={val.fluid}
|
|
3507
|
+
style={val.style ? val.style : {}}
|
|
3508
|
+
placeholder={val.placeholder}
|
|
3509
|
+
onChange={(e) => this.updateFormData(e.target.value, val)}
|
|
3510
|
+
onBlur={(e) => this.handleFieldBlur(e, val)}
|
|
3511
|
+
value={value || ""}
|
|
3512
|
+
defaultValue={isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id]}
|
|
3513
|
+
disabled={val.disabled}
|
|
3514
|
+
size={val.size || "default"}
|
|
3515
|
+
/>
|
|
3516
|
+
{this.props.schema?.channel === EMAIL &&
|
|
3517
|
+
!aiContentBotDisabled && (
|
|
3518
|
+
<CapAskAira.ContentGenerationBot
|
|
3519
|
+
text={value || ""}
|
|
3520
|
+
setText={this.handleSetText.bind(this, val)}
|
|
3521
|
+
iconPlacement="float-br"
|
|
3522
|
+
iconSize="1.6rem"
|
|
3523
|
+
rootStyle={{
|
|
3524
|
+
bottom: "0.2rem",
|
|
3525
|
+
right: "0.2rem",
|
|
3526
|
+
left: "auto",
|
|
3527
|
+
}}
|
|
3528
|
+
/>
|
|
3529
|
+
)}
|
|
3530
|
+
</CapColumn>
|
|
3531
|
+
);
|
|
3532
|
+
}
|
|
3485
3533
|
}
|
|
3486
3534
|
break;
|
|
3487
3535
|
|
|
@@ -3722,37 +3770,48 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3722
3770
|
isBEEAppEnableForCapTagList === false ||
|
|
3723
3771
|
channelForCapTagList !== 'EMAIL'
|
|
3724
3772
|
) {
|
|
3773
|
+
const isEmailStandaloneSubject = val.standalone && channelForCapTagList === 'EMAIL' && val.id === 'template-subject';
|
|
3774
|
+
const tagListProps = {
|
|
3775
|
+
key: `input-${val.id}`,
|
|
3776
|
+
inputId: val.id,
|
|
3777
|
+
inputValue: this.state.formData[val.id] || '',
|
|
3778
|
+
inputPlaceholder: val.placeholder || '',
|
|
3779
|
+
inputErrorMessage: val.errorMessage && ifError ? val.errorMessage : '',
|
|
3780
|
+
inputRequired: val.required || false,
|
|
3781
|
+
inputDisabled: val.disabled || false,
|
|
3782
|
+
headingText: val.label || '',
|
|
3783
|
+
headingStyle: val.headingStyle || { marginTop: '3%', marginRight: '79%' },
|
|
3784
|
+
headingType: "h4",
|
|
3785
|
+
onTagSelect: (data) => this.callChildEvent(data, val, 'onTagSelect'),
|
|
3786
|
+
onContextChange: this.props.onContextChange,
|
|
3787
|
+
location: this.props.location,
|
|
3788
|
+
tags: this.props.tags ? this.props.tags : [],
|
|
3789
|
+
injectedTags: this.props.injectedTags ? this.props.injectedTags : {},
|
|
3790
|
+
className: val.className ? val.className : '',
|
|
3791
|
+
userLocale: this.state.translationLang,
|
|
3792
|
+
selectedOfferDetails: this.props.selectedOfferDetails,
|
|
3793
|
+
eventContextTags: this.props?.eventContextTags,
|
|
3794
|
+
waitEventContextTags: this.props?.waitEventContextTags,
|
|
3795
|
+
moduleFilterEnabled: moduleFilterEnabledForCapTagList,
|
|
3796
|
+
containerStyle: val.style || {},
|
|
3797
|
+
inputProps: val.inputProps || {},
|
|
3798
|
+
showInput: val.showInput !== false,
|
|
3799
|
+
showTagList: val.showTagList !== false,
|
|
3800
|
+
restrictPersonalization: this.props.restrictPersonalization,
|
|
3801
|
+
};
|
|
3725
3802
|
columns.push(
|
|
3726
3803
|
<CapColumn key={`input-${val.id}`} offset={val.offset} span={val.width ? val.width : ''} style={val.style ? val.style : {marginBottom: '16px'}}>
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
headingType="h4"
|
|
3739
|
-
onTagSelect={(data) => this.callChildEvent(data, val, 'onTagSelect')}
|
|
3740
|
-
onContextChange={this.props.onContextChange}
|
|
3741
|
-
location={this.props.location}
|
|
3742
|
-
tags={this.props.tags ? this.props.tags : []}
|
|
3743
|
-
injectedTags={this.props.injectedTags ? this.props.injectedTags : {}}
|
|
3744
|
-
className={val.className ? val.className : ''}
|
|
3745
|
-
userLocale={this.state.translationLang}
|
|
3746
|
-
selectedOfferDetails={this.props.selectedOfferDetails}
|
|
3747
|
-
eventContextTags={this.props?.eventContextTags}
|
|
3748
|
-
waitEventContextTags={this.props?.waitEventContextTags}
|
|
3749
|
-
moduleFilterEnabled={moduleFilterEnabledForCapTagList}
|
|
3750
|
-
containerStyle={val.style || {}}
|
|
3751
|
-
inputProps={val.inputProps || {}}
|
|
3752
|
-
showInput={val.showInput !== false}
|
|
3753
|
-
showTagList={val.showTagList !== false}
|
|
3754
|
-
restrictPersonalization={this.props.restrictPersonalization}
|
|
3755
|
-
/>
|
|
3804
|
+
{isEmailStandaloneSubject ? (
|
|
3805
|
+
<HighFreqTagInput
|
|
3806
|
+
{...tagListProps}
|
|
3807
|
+
onCommit={(newValue) => this.performFormDataUpdate(newValue, val)}
|
|
3808
|
+
/>
|
|
3809
|
+
) : (
|
|
3810
|
+
<CapTagListWithInput
|
|
3811
|
+
{...tagListProps}
|
|
3812
|
+
inputOnChange={(e) => this.updateFormData(e.target.value, val)}
|
|
3813
|
+
/>
|
|
3814
|
+
)}
|
|
3756
3815
|
</CapColumn>
|
|
3757
3816
|
);
|
|
3758
3817
|
}
|
|
@@ -24,16 +24,21 @@ class TemplateNameInputField extends React.Component {
|
|
|
24
24
|
handleChange = (ev) => {
|
|
25
25
|
const { value } = ev.currentTarget;
|
|
26
26
|
this.setState({ localValue: value });
|
|
27
|
-
this.props.onChange(value);
|
|
27
|
+
if (this.props.onChange) this.props.onChange(value);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
handleBlur = () => {
|
|
31
|
+
if (this.props.onBlur) this.props.onBlur(this.state.localValue);
|
|
28
32
|
};
|
|
29
33
|
|
|
30
34
|
render() {
|
|
31
|
-
const { onChange: _onChange, initialValue: _initialValue, ...rest } = this.props;
|
|
35
|
+
const { onChange: _onChange, initialValue: _initialValue, onBlur: _ob, ...rest } = this.props;
|
|
32
36
|
return (
|
|
33
37
|
<CapInput
|
|
34
38
|
{...rest}
|
|
35
39
|
value={this.state.localValue}
|
|
36
40
|
onChange={this.handleChange}
|
|
41
|
+
onBlur={this.handleBlur}
|
|
37
42
|
/>
|
|
38
43
|
);
|
|
39
44
|
}
|
|
@@ -230,10 +235,7 @@ export class Creatives extends React.Component {
|
|
|
230
235
|
// Performance optimized template name update
|
|
231
236
|
performTemplateNameUpdate = (value, formData, onFormDataChange) => {
|
|
232
237
|
const isEmptyTemplateName = !value.trim();
|
|
233
|
-
|
|
234
|
-
// standalone field changed, enabling the fast-path cache in getFormDataForBuilder
|
|
235
|
-
// and skipping the expensive FormBuilder re-render + validateForm cascade.
|
|
236
|
-
const newFormData = { ...formData, 'template-name': value, 'isTemplateNameEdited': true, _highFreqField: 'template-name' };
|
|
238
|
+
const newFormData = { ...formData, 'template-name': value, 'isTemplateNameEdited': true };
|
|
237
239
|
|
|
238
240
|
this.setState({ isTemplateNameEmpty: isEmptyTemplateName });
|
|
239
241
|
onFormDataChange(newFormData);
|
|
@@ -1799,17 +1801,15 @@ export class Creatives extends React.Component {
|
|
|
1799
1801
|
<TemplateNameInputField
|
|
1800
1802
|
initialValue={name}
|
|
1801
1803
|
suffix={<span />}
|
|
1802
|
-
onBlur={() => {
|
|
1803
|
-
this.
|
|
1804
|
-
|
|
1805
|
-
});
|
|
1804
|
+
onBlur={(committedValue) => {
|
|
1805
|
+
this.performTemplateNameUpdate(committedValue, formData, onFormDataChange);
|
|
1806
|
+
this.setState({ isEditName: false });
|
|
1806
1807
|
}}
|
|
1807
1808
|
onChange={(value) => {
|
|
1808
1809
|
const isEmptyTemplateName = !value.trim();
|
|
1809
1810
|
if (this.state.isTemplateNameEmpty !== isEmptyTemplateName) {
|
|
1810
1811
|
this.setState({ isTemplateNameEmpty: isEmptyTemplateName });
|
|
1811
1812
|
}
|
|
1812
|
-
this.debouncedTemplateNameUpdate(value, formData, onFormDataChange);
|
|
1813
1813
|
}}
|
|
1814
1814
|
/>
|
|
1815
1815
|
)
|
|
@@ -795,15 +795,9 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
795
795
|
delete window?.[CREATIVES_S3_ASSET_FILESIZES];
|
|
796
796
|
}
|
|
797
797
|
|
|
798
|
-
|
|
799
|
-
// CreativesContainer.performTemplateNameUpdate passes _highFreqField on the formData object.
|
|
800
|
-
// Both paths set _highFreqUpdate so getFormDataForBuilder can use the fast-path cache.
|
|
801
|
-
onFormDataChange = (updatedFormData, tabCount, currentTab, val) => {
|
|
798
|
+
onFormDataChange = (updatedFormData, tabCount, currentTab) => {
|
|
802
799
|
// this.transformFormData(formData);
|
|
803
800
|
const formData = {...updatedFormData};
|
|
804
|
-
// Consume and clean up the CC-path signal before storing in state
|
|
805
|
-
const highFreqField = (val && val.id) || updatedFormData._highFreqField;
|
|
806
|
-
delete formData._highFreqField;
|
|
807
801
|
|
|
808
802
|
const {defaultData = {}, isFullMode, showTemplateName} = this.props;
|
|
809
803
|
const templateName = formData['template-name'];
|
|
@@ -816,10 +810,6 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
816
810
|
formData['template-name'] = templateName;
|
|
817
811
|
}
|
|
818
812
|
|
|
819
|
-
// Must be set before setState so getFormDataForBuilder reads it during the triggered re-render.
|
|
820
|
-
const HIGH_FREQ_FIELDS = ['template-name', 'template-subject'];
|
|
821
|
-
this._highFreqUpdate = !!(highFreqField && HIGH_FREQ_FIELDS.includes(highFreqField));
|
|
822
|
-
|
|
823
813
|
this.setState({formData, tabCount, isSchemaChanged: false}, () => {
|
|
824
814
|
if (this.props.isFullMode && showTemplateName) {
|
|
825
815
|
showTemplateName({formData, onFormDataChange: this.onFormDataChange});
|
|
@@ -831,27 +821,6 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
831
821
|
//this.resetCkEditorInstance(currentTab, formData);
|
|
832
822
|
}
|
|
833
823
|
|
|
834
|
-
// Returns a formData object safe to pass to FormBuilder.
|
|
835
|
-
// For high-frequency field updates (template-name / template-subject) patches only
|
|
836
|
-
// those fields into the existing cache, avoiding an expensive _.cloneDeep of the
|
|
837
|
-
// entire email formData (HTML content, tabs, language variants) on every keystroke.
|
|
838
|
-
// All other operations (tab changes, language add/delete, etc.) still get a full clone.
|
|
839
|
-
getFormDataForBuilder = () => {
|
|
840
|
-
const formData = this.state.formData;
|
|
841
|
-
if (this._highFreqUpdate && this._formDataBuilderCache) {
|
|
842
|
-
this._formDataBuilderCache = {
|
|
843
|
-
...this._formDataBuilderCache,
|
|
844
|
-
'template-name': formData['template-name'],
|
|
845
|
-
'template-subject': formData['template-subject'],
|
|
846
|
-
'isTemplateNameEdited': formData['isTemplateNameEdited'],
|
|
847
|
-
};
|
|
848
|
-
} else {
|
|
849
|
-
this._formDataBuilderCache = _.cloneDeep(formData);
|
|
850
|
-
}
|
|
851
|
-
this._highFreqUpdate = false;
|
|
852
|
-
return this._formDataBuilderCache;
|
|
853
|
-
}
|
|
854
|
-
|
|
855
824
|
onChange = (evt) => {
|
|
856
825
|
const {isFullMode, showTemplateName} = this.props;
|
|
857
826
|
const formData = _.cloneDeep(this.state.formData);
|
|
@@ -3160,7 +3129,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
3160
3129
|
onChange={this.onFormDataChange}
|
|
3161
3130
|
currentTab={this.state.currentTab}
|
|
3162
3131
|
parent={this}
|
|
3163
|
-
formData={this.
|
|
3132
|
+
formData={_.cloneDeep(this.state.formData)}
|
|
3164
3133
|
location={this.props.location}
|
|
3165
3134
|
tabKey={this.state.tabKey}
|
|
3166
3135
|
tags={tags}
|