@capillarytech/creatives-library 9.0.11-beta.1 → 9.0.12
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 +1 -1
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +7 -0
- package/v2Containers/Ebill/index.js +31 -7
- package/v2Containers/MobilePushNew/components/MediaUploaders.js +3 -3
- package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +1 -2
- package/v2Containers/Templates/index.js +1 -1
package/package.json
CHANGED
|
@@ -16,6 +16,7 @@ import { isTraiDLTEnable } from '../../utils/common';
|
|
|
16
16
|
import { formatString } from '../../utils/Formatter';
|
|
17
17
|
import {
|
|
18
18
|
CAP_SPACE_12,
|
|
19
|
+
ICON_SIZE_M,
|
|
19
20
|
} from '@capillarytech/cap-ui-library/styled/variables';
|
|
20
21
|
import { WHATSAPP_HELP_DOC_LINK, JOURNEY } from './constants';
|
|
21
22
|
|
|
@@ -23,8 +24,14 @@ const { CapLabelInline } = CapLabel;
|
|
|
23
24
|
const StyledLabel = styled(CapLabelInline)`
|
|
24
25
|
margin-right: ${CAP_SPACE_12};
|
|
25
26
|
`;
|
|
27
|
+
// CapIcons.BackIcon renders an <svg width="1em" height="1em">, so its size follows
|
|
28
|
+
// the inherited font-size. Pin it to the medium icon size (24px) and center it so
|
|
29
|
+
// the back arrow matches the header title instead of collapsing to a tiny glyph.
|
|
26
30
|
const PrefixWrapper = styled.div`
|
|
27
31
|
margin-right: 16px;
|
|
32
|
+
display: inline-flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
font-size: ${ICON_SIZE_M};
|
|
28
35
|
`;
|
|
29
36
|
const renderData = (type, value, channel) => (
|
|
30
37
|
<StyledLabel className={channel?.toLowerCase() === ZALO ? 'zalo-template-name-spacing' : ''} type={type}>
|
|
@@ -39,6 +39,7 @@ export class Ebill extends React.Component { // eslint-disable-line react/prefer
|
|
|
39
39
|
currentTab: 1,
|
|
40
40
|
isEdit: false,
|
|
41
41
|
loading: false,
|
|
42
|
+
isSaving: false,
|
|
42
43
|
isFormValid: true,
|
|
43
44
|
injectedTags: {},
|
|
44
45
|
checkValidation: false,
|
|
@@ -570,26 +571,33 @@ export class Ebill extends React.Component { // eslint-disable-line react/prefer
|
|
|
570
571
|
},
|
|
571
572
|
};
|
|
572
573
|
this.isTagLoaded = false;
|
|
574
|
+
this.isSubmitting = false;
|
|
573
575
|
}
|
|
574
576
|
|
|
575
577
|
componentWillMount() {
|
|
578
|
+
// NOTE: API dispatches must NOT live here. componentWillMount runs in React's
|
|
579
|
+
// render phase, which React 18 (createRoot/concurrent) may execute more than
|
|
580
|
+
// once per commit — causing every dispatched request to fire twice. All
|
|
581
|
+
// side-effects are in componentDidMount (commit phase, runs exactly once).
|
|
576
582
|
if (this.props.params.id) {
|
|
577
|
-
this.props.actions.getTemplateDetails(this.props.params.id, 'ebill');
|
|
578
583
|
this.setState({isEdit: true});
|
|
579
584
|
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
componentDidMount() {
|
|
588
|
+
if (this.props.params.id) {
|
|
589
|
+
this.props.actions.getTemplateDetails(this.props.params.id, 'ebill');
|
|
590
|
+
}
|
|
580
591
|
|
|
581
592
|
if (!_.isEmpty(this.props.Templates.edmTemplate) && this.props.Templates.edmTemplate.versions.base.is_drag_drop) {
|
|
582
593
|
this.props.actions.getCmsData('edm', this.props.Templates.edmTemplate.versions.base.drag_drop_id);
|
|
583
594
|
}
|
|
584
|
-
}
|
|
585
595
|
|
|
586
|
-
componentDidMount() {
|
|
587
596
|
const query = {
|
|
588
597
|
layout: 'EBILL',
|
|
589
598
|
type: 'LAYOUT',
|
|
590
599
|
};
|
|
591
600
|
this.props.globalActions.fetchSchemaForEntity(query);
|
|
592
|
-
|
|
593
601
|
}
|
|
594
602
|
|
|
595
603
|
componentWillReceiveProps(nextProps) {
|
|
@@ -609,7 +617,7 @@ export class Ebill extends React.Component { // eslint-disable-line react/prefer
|
|
|
609
617
|
this.setEditState(nextProps.Ebill.templateDetails);
|
|
610
618
|
}
|
|
611
619
|
|
|
612
|
-
if (nextProps.Ebill.createResponse && nextProps.Ebill.createResponse.templateId) {
|
|
620
|
+
if (nextProps.Ebill.createResponse && nextProps.Ebill.createResponse.templateId && !_.isEqual(nextProps.Ebill.createResponse, this.props.Ebill.createResponse)) {
|
|
613
621
|
let message;
|
|
614
622
|
if (this.state.isEdit) {
|
|
615
623
|
message = getMessageObject('success', this.props.intl.formatMessage(messages.ebillEditSuccess), true);
|
|
@@ -618,6 +626,8 @@ export class Ebill extends React.Component { // eslint-disable-line react/prefer
|
|
|
618
626
|
}
|
|
619
627
|
this.props.globalActions.addMessageToQueue(message);
|
|
620
628
|
this.props.actions.clearCRUDResponse();
|
|
629
|
+
this.isSubmitting = false;
|
|
630
|
+
this.setState({ isSaving: false });
|
|
621
631
|
const module = this.props.location.query.module ? this.props.location.query.module : 'default';
|
|
622
632
|
const type = this.props.location.query.type;
|
|
623
633
|
this.props.router.push({
|
|
@@ -629,6 +639,8 @@ export class Ebill extends React.Component { // eslint-disable-line react/prefer
|
|
|
629
639
|
if (nextProps.Ebill.createTemplateError && !_.isEqual(nextProps.Ebill.createTemplateError, this.props.Ebill.createTemplateError)) {
|
|
630
640
|
const message = getMessageObject('error', (nextProps.Ebill.createTemplateErrorMessage && nextProps.Ebill.createTemplateErrorMessage !== '') ? nextProps.Ebill.createTemplateErrorMessage : this.props.intl.formatMessage(messages.somethingWentWrong), true);
|
|
631
641
|
this.props.globalActions.addMessageToQueue(message);
|
|
642
|
+
this.isSubmitting = false;
|
|
643
|
+
this.setState({ isSaving: false });
|
|
632
644
|
}
|
|
633
645
|
|
|
634
646
|
|
|
@@ -773,11 +785,23 @@ export class Ebill extends React.Component { // eslint-disable-line react/prefer
|
|
|
773
785
|
saveFormData = (formData) => {
|
|
774
786
|
//Logic to save in db etc
|
|
775
787
|
// const isValidated = this.validateFormData(formData);
|
|
776
|
-
//
|
|
788
|
+
//
|
|
777
789
|
// if (!isValidated) {
|
|
778
790
|
// return;
|
|
779
791
|
// }
|
|
780
|
-
|
|
792
|
+
|
|
793
|
+
// Guard against duplicate submissions. Uses a synchronous instance flag
|
|
794
|
+
// (NOT React state) because setState is async — two onSubmit invocations in
|
|
795
|
+
// the same tick would both read a stale `false` and each dispatch a
|
|
796
|
+
// createTemplate, firing POST /templates/EBILL twice. The instance flag
|
|
797
|
+
// flips synchronously, so the second call is dropped immediately.
|
|
798
|
+
// Reset once the create/update response or error is received in componentWillReceiveProps.
|
|
799
|
+
if (this.isSubmitting) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
this.isSubmitting = true;
|
|
803
|
+
this.setState({ isSaving: true });
|
|
804
|
+
|
|
781
805
|
const obj = {};
|
|
782
806
|
obj.versions = {
|
|
783
807
|
base: {},
|
|
@@ -378,8 +378,8 @@ const MediaUploaders = ({
|
|
|
378
378
|
})));
|
|
379
379
|
};
|
|
380
380
|
|
|
381
|
-
const onTabChange = (
|
|
382
|
-
setCarouselActiveTabIndex(
|
|
381
|
+
const onTabChange = (key) => {
|
|
382
|
+
setCarouselActiveTabIndex(Number(key));
|
|
383
383
|
};
|
|
384
384
|
|
|
385
385
|
const addCarouselCard = () => {
|
|
@@ -765,7 +765,7 @@ const MediaUploaders = ({
|
|
|
765
765
|
const getTabPanes = () => {
|
|
766
766
|
const currentData = getCurrentCarouselData();
|
|
767
767
|
return currentData?.map((data, index) => ({
|
|
768
|
-
key: index,
|
|
768
|
+
key: String(index),
|
|
769
769
|
tab: index + 1,
|
|
770
770
|
content: (
|
|
771
771
|
<CapCard
|
|
@@ -2146,8 +2146,7 @@ describe('MediaUploaders', () => {
|
|
|
2146
2146
|
const secondTabButton = screen.getByText('Tab 2');
|
|
2147
2147
|
fireEvent.click(secondTabButton);
|
|
2148
2148
|
|
|
2149
|
-
|
|
2150
|
-
expect(setCarouselActiveTabIndex).toHaveBeenCalledWith('1');
|
|
2149
|
+
expect(setCarouselActiveTabIndex).toHaveBeenCalledWith(1);
|
|
2151
2150
|
});
|
|
2152
2151
|
|
|
2153
2152
|
it('should handle carousel card add operation', () => {
|
|
@@ -646,7 +646,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
646
646
|
}
|
|
647
647
|
|
|
648
648
|
|
|
649
|
-
if (selectedChannel === "ebill" && nextProps.CreateEbill && nextProps.CreateEbill.createResponse && nextProps.CreateEbill.createResponse.templateId && nextProps.CreateEbill.createResponse.templateId !== '') {
|
|
649
|
+
if (selectedChannel === "ebill" && nextProps.CreateEbill && nextProps.CreateEbill.createResponse && nextProps.CreateEbill.createResponse.templateId && nextProps.CreateEbill.createResponse.templateId !== '' && !isEqual(nextProps.CreateEbill.createResponse, this.props.CreateEbill && this.props.CreateEbill.createResponse)) {
|
|
650
650
|
const message = `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`;
|
|
651
651
|
CapNotification.success({key: 'duplicateSucess', message});
|
|
652
652
|
this.getAllTemplates({params, resetPage: true});
|