@capillarytech/creatives-library 7.17.214 → 7.17.216
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/utils/tagValidations.js +11 -3
- package/utils/tests/tagValidations.test.js +14 -3
- package/v2Components/FormBuilder/index.js +13 -1
- package/v2Containers/BeeEditor/index.js +3 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +47 -26
- package/v2Containers/CreativesContainer/index.js +3 -0
- package/v2Containers/Email/index.js +1 -0
- package/v2Containers/EmailWrapper/index.js +3 -0
- package/v2Containers/MobilePush/Create/index.js +2 -0
- package/v2Containers/MobilePush/Edit/index.js +2 -0
- package/v2Containers/MobilepushWrapper/index.js +3 -1
- package/v2Containers/Sms/Create/index.js +2 -0
- package/v2Containers/Sms/Edit/index.js +2 -0
- package/v2Containers/SmsTrai/Edit/index.js +3 -0
- package/v2Containers/SmsWrapper/index.js +2 -0
- package/v2Containers/TagList/index.js +27 -2
- package/v2Containers/TagList/messages.js +4 -0
- package/v2Containers/TagList/tests/TagList.test.js +19 -8
- package/v2Containers/TagList/tests/mockdata.js +59 -1
- package/v2Containers/Viber/index.js +2 -0
- package/v2Containers/Whatsapp/index.js +4 -1
- package/v2Containers/Zalo/index.js +3 -0
- package/containers/App/index.js +0 -52
- package/entry.js +0 -2
- package/hoc/withReactRouterV3Compatibility.js +0 -66
- package/initialReducer.js +0 -34
- package/mfe-exposed-components.js +0 -8
- package/utils/checkStore.js +0 -21
- package/utils/customAuthWrapper.js +0 -62
- package/utils/customConnectedAuthWrapper.js +0 -26
- package/utils/history.js +0 -8
- package/utils/injectReducer.js +0 -2
- package/utils/injectSaga.js +0 -2
- package/v2Components/NavigationBar/saga.js +0 -18
- package/v2Components/RenderRoute/RenderRoute.js +0 -11
- package/v2Components/RenderRoute/index.js +0 -1
package/package.json
CHANGED
package/utils/tagValidations.js
CHANGED
|
@@ -17,10 +17,11 @@ const SUBTAGS = 'subtags';
|
|
|
17
17
|
* @param {Object} response - The response object to check.
|
|
18
18
|
* @param {Object} tagObject - The tagLookupMap.
|
|
19
19
|
*/
|
|
20
|
-
export const checkSupport = (response = {}, tagObject = {}) => {
|
|
20
|
+
export const checkSupport = (response = {}, tagObject = {}, eventContextTags = []) => {
|
|
21
21
|
const supportedList = [];
|
|
22
22
|
// Verifies the presence of the tag in the 'Add Labels' section.
|
|
23
|
-
|
|
23
|
+
// Incase of journey event context the tags won't be available in the tagObject(tagLookupMap).
|
|
24
|
+
const checkNameInTagObjectOrEventContext = (name) => !!tagObject[name] || eventContextTags?.some((tag) => tag?.tagName === name);
|
|
24
25
|
|
|
25
26
|
// Verify if childTag is a valid sub-tag of parentTag from the 'Add Labels' section or if it's unsupported.
|
|
26
27
|
const checkSubtags = (parentTag, childName) => {
|
|
@@ -47,7 +48,7 @@ export const checkSupport = (response = {}, tagObject = {}) => {
|
|
|
47
48
|
|
|
48
49
|
//Checks if the tag is present in the Add Label Section
|
|
49
50
|
for (const item of response?.data || []) {
|
|
50
|
-
if (
|
|
51
|
+
if (checkNameInTagObjectOrEventContext(item?.name)) {
|
|
51
52
|
supportedList?.push(item?.name);
|
|
52
53
|
}
|
|
53
54
|
//Repeat the process for subtags
|
|
@@ -93,6 +94,7 @@ export const validateTags = ({
|
|
|
93
94
|
injectedTagsParams,
|
|
94
95
|
location,
|
|
95
96
|
tagModule,
|
|
97
|
+
eventContextTags,
|
|
96
98
|
}) => {
|
|
97
99
|
const tags = tagsParam;
|
|
98
100
|
const injectedTags = transformInjectedTags(injectedTagsParams);
|
|
@@ -145,6 +147,12 @@ export const validateTags = ({
|
|
|
145
147
|
}
|
|
146
148
|
}
|
|
147
149
|
}
|
|
150
|
+
// Journey Event Context Tags support
|
|
151
|
+
eventContextTags?.forEach((tag) => {
|
|
152
|
+
if (tagValue === tag?.tagName) {
|
|
153
|
+
ifSupported = true;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
148
156
|
ifSupported = ifSupported || checkIfSupportedTag(tagValue, injectedTags);
|
|
149
157
|
if (!ifSupported) {
|
|
150
158
|
response.unsupportedTags.push(tagValue);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import '@testing-library/jest-dom';
|
|
3
3
|
import { checkSupport, extractNames, getTagMapValue, preprocessHtml, validateIfTagClosed,validateTags} from '../tagValidations';
|
|
4
|
+
import { eventContextTags } from '../../v2Containers/TagList/tests/mockdata';
|
|
4
5
|
|
|
5
6
|
describe("check if curly brackets are balanced", () => {
|
|
6
7
|
it("test for balanced curly brackets", () => {
|
|
@@ -50,7 +51,7 @@ describe("validateTags", () => {
|
|
|
50
51
|
},
|
|
51
52
|
];
|
|
52
53
|
it("should return valid response when all tags are present", () => {
|
|
53
|
-
const content = "Hello {{tag1}}, {{tag2}}, {{tag3}}";
|
|
54
|
+
const content = "Hello {{tag1}}, {{tag2}}, {{tag3}} {{lifetimePurchases}}";
|
|
54
55
|
|
|
55
56
|
const injectedTagsParams = [];
|
|
56
57
|
const location = { query: { module: "DEFAULT" } };
|
|
@@ -62,6 +63,7 @@ describe("validateTags", () => {
|
|
|
62
63
|
injectedTagsParams,
|
|
63
64
|
location,
|
|
64
65
|
tagModule,
|
|
66
|
+
eventContextTags,
|
|
65
67
|
});
|
|
66
68
|
|
|
67
69
|
expect(result.valid).toEqual(true);
|
|
@@ -96,7 +98,7 @@ describe("validateTags", () => {
|
|
|
96
98
|
});
|
|
97
99
|
|
|
98
100
|
it("should return invalid response when an unsupported tag is present", () => {
|
|
99
|
-
const content = "Hello {{tag1}}, {{tag2}}, {{tag3}}";
|
|
101
|
+
const content = "Hello {{tag1}}, {{tag2}}, {{tag3}} {{missingEventContextTags}}";
|
|
100
102
|
const tagsParam = [
|
|
101
103
|
{
|
|
102
104
|
definition: {
|
|
@@ -125,7 +127,7 @@ describe("validateTags", () => {
|
|
|
125
127
|
|
|
126
128
|
expect(result.valid).toEqual(true);
|
|
127
129
|
expect(result.missingTags).toEqual([]);
|
|
128
|
-
expect(result.unsupportedTags).toEqual(["tag3"]);
|
|
130
|
+
expect(result.unsupportedTags).toEqual(["tag3", "missingEventContextTags"]);
|
|
129
131
|
expect(result.isBraceError).toEqual(false);
|
|
130
132
|
});
|
|
131
133
|
|
|
@@ -272,6 +274,15 @@ describe("checkSupport", () => {
|
|
|
272
274
|
expect(result).toEqual([]);
|
|
273
275
|
});
|
|
274
276
|
|
|
277
|
+
it("should return event context tags even if tagObject is empty", () => {
|
|
278
|
+
const response = {
|
|
279
|
+
data: [{ name: "tag1" }, { name: "lifetimePurchases" }],
|
|
280
|
+
};
|
|
281
|
+
const tagObject = {};
|
|
282
|
+
const result = checkSupport(response, tagObject, eventContextTags);
|
|
283
|
+
expect(result).toEqual(['lifetimePurchases']);
|
|
284
|
+
});
|
|
285
|
+
|
|
275
286
|
it("should return an array of supported tags", () => {
|
|
276
287
|
const response = {
|
|
277
288
|
data: [{ name: "tag1" }, { name: "tag2" }, { name: "tag3" }],
|
|
@@ -1120,7 +1120,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1120
1120
|
// Extracts the supported liquid tags from the given content.
|
|
1121
1121
|
const supportedLiquidTags = checkSupport(
|
|
1122
1122
|
result,
|
|
1123
|
-
this.props?.metaEntities?.tagLookupMap
|
|
1123
|
+
this.props?.metaEntities?.tagLookupMap,
|
|
1124
|
+
this.props?.eventContextTags
|
|
1124
1125
|
);
|
|
1125
1126
|
const unsupportedLiquidTags = extractedLiquidTags?.filter(
|
|
1126
1127
|
(tag) => !supportedLiquidTags?.includes(tag) && !this.skipTags(tag)
|
|
@@ -1283,6 +1284,14 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1283
1284
|
}
|
|
1284
1285
|
}
|
|
1285
1286
|
}
|
|
1287
|
+
|
|
1288
|
+
// Event Context Tags support
|
|
1289
|
+
this.props?.eventContextTags?.forEach((tag) => {
|
|
1290
|
+
if (tagValue === tag?.tagName) {
|
|
1291
|
+
ifSupported = true;
|
|
1292
|
+
}
|
|
1293
|
+
});
|
|
1294
|
+
|
|
1286
1295
|
ifSupported = ifSupported || this.checkIfSupportedTag(tagValue, injectedTags);
|
|
1287
1296
|
if (!ifSupported && !this.liquidFlow) {
|
|
1288
1297
|
response.unsupportedTags.push(tagValue);
|
|
@@ -2610,6 +2619,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2610
2619
|
id={val.id}
|
|
2611
2620
|
userLocale={this.props.userLocale}
|
|
2612
2621
|
selectedOfferDetails={this.props.selectedOfferDetails}
|
|
2622
|
+
eventContextTags={this.props?.eventContextTags}
|
|
2613
2623
|
/>
|
|
2614
2624
|
</CapColumn>
|
|
2615
2625
|
);
|
|
@@ -3231,6 +3241,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3231
3241
|
userLocale={this.state.translationLang}
|
|
3232
3242
|
selectedOfferDetails={this.props.selectedOfferDetails}
|
|
3233
3243
|
channel={channel}
|
|
3244
|
+
eventContextTags={this.props?.eventContextTags}
|
|
3234
3245
|
/>
|
|
3235
3246
|
</CapColumn>
|
|
3236
3247
|
);
|
|
@@ -3505,6 +3516,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3505
3516
|
saveBeeData={this.props.saveBeeData}
|
|
3506
3517
|
onContextChange={this.props.onContextChange}
|
|
3507
3518
|
moduleFilterEnabled={isModuleFilterEnabled}
|
|
3519
|
+
eventContextTags={this.props?.eventContextTags}
|
|
3508
3520
|
/>
|
|
3509
3521
|
</CapColumn>
|
|
3510
3522
|
);
|
|
@@ -48,6 +48,7 @@ function BeeEditor(props) {
|
|
|
48
48
|
actions,
|
|
49
49
|
BEESelect,
|
|
50
50
|
currentOrgDetails,
|
|
51
|
+
eventContextTags,
|
|
51
52
|
} = props;
|
|
52
53
|
const { saveRowRequest } = BEESelect;
|
|
53
54
|
const {formatMessage} = intl;
|
|
@@ -280,6 +281,7 @@ function BeeEditor(props) {
|
|
|
280
281
|
className: "bee-editor-tag-list",
|
|
281
282
|
}}
|
|
282
283
|
onContextChange={onContextChange}
|
|
284
|
+
eventContextTags={eventContextTags}
|
|
283
285
|
/>
|
|
284
286
|
<CapModal
|
|
285
287
|
className="custom-row-modal"
|
|
@@ -323,6 +325,7 @@ BeeEditor.propTypes = {
|
|
|
323
325
|
injectedTags: PropTypes.object,
|
|
324
326
|
onContextChange: PropTypes.func,
|
|
325
327
|
userLocale: PropTypes.string,
|
|
328
|
+
eventContextTags: PropTypes.array,
|
|
326
329
|
};
|
|
327
330
|
|
|
328
331
|
const mapStateToProps = () => createStructuredSelector({
|
|
@@ -156,6 +156,7 @@ export function SlideBoxContent(props) {
|
|
|
156
156
|
showLiquidErrorInFooter,
|
|
157
157
|
creativesMode,
|
|
158
158
|
hostName = '',
|
|
159
|
+
eventContextTags,
|
|
159
160
|
} = props;
|
|
160
161
|
const type = (messageDetails.type || '').toLowerCase(); // type is context in get tags values : outbound | dvs | referral | loyalty | coupons
|
|
161
162
|
const query = { type: !isFullMode && 'embedded', module: isFullMode ? 'default' : 'library', isEditFromCampaigns: (templateData || {}).isEditFromCampaigns};
|
|
@@ -396,6 +397,7 @@ export function SlideBoxContent(props) {
|
|
|
396
397
|
onCreateComplete,
|
|
397
398
|
selectedOfferDetails,
|
|
398
399
|
getFormData,
|
|
400
|
+
eventContextTags,
|
|
399
401
|
};
|
|
400
402
|
|
|
401
403
|
return (
|
|
@@ -430,6 +432,7 @@ export function SlideBoxContent(props) {
|
|
|
430
432
|
smsRegister={smsRegister}
|
|
431
433
|
enableNewChannels={enableNewChannels}
|
|
432
434
|
hideTestAndPreviewBtn={hideTestAndPreviewBtn}
|
|
435
|
+
eventContextTags={eventContextTags}
|
|
433
436
|
/>
|
|
434
437
|
)}
|
|
435
438
|
{isPreview && (
|
|
@@ -509,6 +512,7 @@ export function SlideBoxContent(props) {
|
|
|
509
512
|
handleClose={handleClose}
|
|
510
513
|
onCreateComplete={onCreateComplete}
|
|
511
514
|
smsRegister={smsRegister}
|
|
515
|
+
eventContextTags={eventContextTags}
|
|
512
516
|
/>
|
|
513
517
|
)}
|
|
514
518
|
{isEditFTP && (
|
|
@@ -545,6 +549,7 @@ export function SlideBoxContent(props) {
|
|
|
545
549
|
search: '',
|
|
546
550
|
}}
|
|
547
551
|
hostName={hostName}
|
|
552
|
+
eventContextTags={eventContextTags}
|
|
548
553
|
/>
|
|
549
554
|
}
|
|
550
555
|
{
|
|
@@ -575,6 +580,7 @@ export function SlideBoxContent(props) {
|
|
|
575
580
|
onCreateComplete={onCreateComplete}
|
|
576
581
|
smsRegister={smsRegister}
|
|
577
582
|
onShowTemplates={onShowTemplates}
|
|
583
|
+
eventContextTags={eventContextTags}
|
|
578
584
|
/>
|
|
579
585
|
)}
|
|
580
586
|
|
|
@@ -606,6 +612,7 @@ export function SlideBoxContent(props) {
|
|
|
606
612
|
getCmsTemplatesInProgress={getCmsTemplatesInProgress}
|
|
607
613
|
moduleType={moduleType}
|
|
608
614
|
showLiquidErrorInFooter={showLiquidErrorInFooter}
|
|
615
|
+
eventContextTags={eventContextTags}
|
|
609
616
|
/>
|
|
610
617
|
)}
|
|
611
618
|
{(isEditEmailWithId || isEmailEditWithContent) && (
|
|
@@ -634,6 +641,7 @@ export function SlideBoxContent(props) {
|
|
|
634
641
|
onTestContentClicked={onTestContentClicked}
|
|
635
642
|
moduleType={moduleType}
|
|
636
643
|
showLiquidErrorInFooter={showLiquidErrorInFooter}
|
|
644
|
+
eventContextTags={eventContextTags}
|
|
637
645
|
/>
|
|
638
646
|
)}
|
|
639
647
|
{isEditMPush &&
|
|
@@ -659,35 +667,38 @@ export function SlideBoxContent(props) {
|
|
|
659
667
|
type={type}
|
|
660
668
|
hideTestAndPreviewBtn={hideTestAndPreviewBtn}
|
|
661
669
|
creativesMode={creativesMode}
|
|
670
|
+
eventContextTags={eventContextTags}
|
|
662
671
|
/>
|
|
663
672
|
}
|
|
664
673
|
{isCreateMPush &&
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
674
|
+
<MobilepushWrapper
|
|
675
|
+
key="creatives-mobilepush-wrapper"
|
|
676
|
+
date={new Date().getMilliseconds()}
|
|
677
|
+
setIsLoadingContent={setIsLoadingContent}
|
|
678
|
+
onMobilepushModeChange={onMobilepushModeChange}
|
|
679
|
+
mobilePushCreateMode={mobilePushCreateMode}
|
|
680
|
+
isGetFormData={isGetFormData}
|
|
681
|
+
getFormData={getFormData}
|
|
682
|
+
templateData={templateData}
|
|
683
|
+
type={type}
|
|
684
|
+
step={templateStep}
|
|
685
|
+
showNextStep={onCreateNextStep}
|
|
686
|
+
isFullMode={isFullMode}
|
|
687
|
+
onEnterTemplateName={onEnterTemplateName}
|
|
688
|
+
onRemoveTemplateName={onRemoveTemplateName}
|
|
689
|
+
cap={cap}
|
|
690
|
+
onResetStep={onResetStep}
|
|
691
|
+
showTemplateName={showTemplateName}
|
|
692
|
+
query={query}
|
|
693
|
+
forwardedTags={forwardedTags}
|
|
694
|
+
onValidationFail={onValidationFail}
|
|
695
|
+
selectedOfferDetails={selectedOfferDetails}
|
|
696
|
+
onPreviewContentClicked={onPreviewContentClicked}
|
|
697
|
+
hideTestAndPreviewBtn={hideTestAndPreviewBtn}
|
|
698
|
+
onTestContentClicked={onTestContentClicked}
|
|
699
|
+
eventContextTags={eventContextTags}
|
|
700
|
+
/>
|
|
701
|
+
}
|
|
691
702
|
{
|
|
692
703
|
isCreateFacebook && (
|
|
693
704
|
<Facebook
|
|
@@ -704,6 +715,7 @@ export function SlideBoxContent(props) {
|
|
|
704
715
|
fbAdManager={fbAdManager}
|
|
705
716
|
onSelectTemplate={onSelectTemplate}
|
|
706
717
|
orgUnitId={orgUnitId}
|
|
718
|
+
eventContextTags={eventContextTags}
|
|
707
719
|
/>
|
|
708
720
|
)
|
|
709
721
|
}
|
|
@@ -723,6 +735,7 @@ export function SlideBoxContent(props) {
|
|
|
723
735
|
getFormSubscriptionData={getFormData}
|
|
724
736
|
fbAdManager={fbAdManager}
|
|
725
737
|
onSelectTemplate={onSelectTemplate}
|
|
738
|
+
eventContextTags={eventContextTags}
|
|
726
739
|
/>
|
|
727
740
|
)
|
|
728
741
|
}
|
|
@@ -744,6 +757,7 @@ export function SlideBoxContent(props) {
|
|
|
744
757
|
selectedAccount={selectedAccount}
|
|
745
758
|
handleClose={handleClose}
|
|
746
759
|
selectedOfferDetails={selectedOfferDetails}
|
|
760
|
+
eventContextTags={eventContextTags}
|
|
747
761
|
/>
|
|
748
762
|
)
|
|
749
763
|
}
|
|
@@ -762,6 +776,7 @@ export function SlideBoxContent(props) {
|
|
|
762
776
|
createNew
|
|
763
777
|
handleClose={handleClose}
|
|
764
778
|
selectedOfferDetails={selectedOfferDetails}
|
|
779
|
+
eventContextTags={eventContextTags}
|
|
765
780
|
/>
|
|
766
781
|
)
|
|
767
782
|
}
|
|
@@ -776,6 +791,7 @@ export function SlideBoxContent(props) {
|
|
|
776
791
|
onShowTemplates={onShowTemplates}
|
|
777
792
|
templateData={templateData}
|
|
778
793
|
selectedOfferDetails={selectedOfferDetails}
|
|
794
|
+
eventContextTags={eventContextTags}
|
|
779
795
|
createNew/>
|
|
780
796
|
)}
|
|
781
797
|
|
|
@@ -792,11 +808,13 @@ export function SlideBoxContent(props) {
|
|
|
792
808
|
onShowTemplates={onShowTemplates}
|
|
793
809
|
templateData={templateData}
|
|
794
810
|
selectedOfferDetails={selectedOfferDetails}
|
|
811
|
+
eventContextTags={eventContextTags}
|
|
795
812
|
createNew/> }
|
|
796
813
|
|
|
797
814
|
{isCreateWhatsapp && (<Whatsapp
|
|
798
815
|
isFullMode={isFullMode}
|
|
799
816
|
onCreateComplete={onCreateComplete}
|
|
817
|
+
eventContextTags={eventContextTags}
|
|
800
818
|
handleClose={handleClose}/>
|
|
801
819
|
)}
|
|
802
820
|
|
|
@@ -807,6 +825,7 @@ export function SlideBoxContent(props) {
|
|
|
807
825
|
getDefaultTags={type}
|
|
808
826
|
forwardedTags={forwardedTags}
|
|
809
827
|
selectedOfferDetails={selectedOfferDetails}
|
|
828
|
+
eventContextTags={eventContextTags}
|
|
810
829
|
params={{
|
|
811
830
|
id: templateData._id,
|
|
812
831
|
}}
|
|
@@ -830,6 +849,7 @@ export function SlideBoxContent(props) {
|
|
|
830
849
|
isGetFormData={isGetFormData}
|
|
831
850
|
templateData={templateData}
|
|
832
851
|
getDefaultTags={type}
|
|
852
|
+
eventContextTags={eventContextTags}
|
|
833
853
|
/>
|
|
834
854
|
)}
|
|
835
855
|
|
|
@@ -841,6 +861,7 @@ export function SlideBoxContent(props) {
|
|
|
841
861
|
forwardedTags={forwardedTags}
|
|
842
862
|
onCreateComplete={onCreateComplete}
|
|
843
863
|
selectedOfferDetails={selectedOfferDetails}
|
|
864
|
+
eventContextTags={eventContextTags}
|
|
844
865
|
params={{
|
|
845
866
|
id: templateData._id,
|
|
846
867
|
}}
|
|
@@ -1213,6 +1213,7 @@ export class Creatives extends React.Component {
|
|
|
1213
1213
|
editor,
|
|
1214
1214
|
smsRegister,
|
|
1215
1215
|
enableNewChannels,
|
|
1216
|
+
eventContextTags,
|
|
1216
1217
|
} = this.props;
|
|
1217
1218
|
const mapTemplateCreate =
|
|
1218
1219
|
slidBoxContent === "createTemplate" &&
|
|
@@ -1314,6 +1315,7 @@ export class Creatives extends React.Component {
|
|
|
1314
1315
|
showLiquidErrorInFooter={this.showLiquidErrorInFooter}
|
|
1315
1316
|
creativesMode={creativesMode} // An existing prop that we're using here. Required to ensure correct account details in Edit or Preview in case of Embedded mode.
|
|
1316
1317
|
hostName={this.props?.hostName || ''}
|
|
1318
|
+
eventContextTags={eventContextTags}
|
|
1317
1319
|
/>
|
|
1318
1320
|
}
|
|
1319
1321
|
footer={this.shouldShowFooter() &&
|
|
@@ -1373,6 +1375,7 @@ Creatives.propTypes = {
|
|
|
1373
1375
|
strategy: PropTypes.string,
|
|
1374
1376
|
orgUnitId: PropTypes.number,
|
|
1375
1377
|
hostName: PropTypes.string,
|
|
1378
|
+
eventContextTags: PropTypes.array,
|
|
1376
1379
|
};
|
|
1377
1380
|
const mapStatesToProps = () => createStructuredSelector({
|
|
1378
1381
|
isLoading: isLoadingSelector(),
|
|
@@ -2733,6 +2733,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2733
2733
|
isEmailLoading={isLoading}
|
|
2734
2734
|
moduleType={moduleType}
|
|
2735
2735
|
showLiquidErrorInFooter={this.props.showLiquidErrorInFooter}
|
|
2736
|
+
eventContextTags={this.props?.eventContextTags}
|
|
2736
2737
|
/> : ''}
|
|
2737
2738
|
</Col>
|
|
2738
2739
|
</Row>
|
|
@@ -215,6 +215,7 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
|
|
|
215
215
|
currentOrgDetails,
|
|
216
216
|
moduleType,
|
|
217
217
|
showLiquidErrorInFooter,
|
|
218
|
+
eventContextTags,
|
|
218
219
|
} = this.props;
|
|
219
220
|
const {
|
|
220
221
|
templateName,
|
|
@@ -287,6 +288,7 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
|
|
|
287
288
|
onTestContentClicked={onTestContentClicked}
|
|
288
289
|
editor={editor}
|
|
289
290
|
moduleType={moduleType}
|
|
291
|
+
eventContextTags={eventContextTags}
|
|
290
292
|
/>}
|
|
291
293
|
{!isShowEmailCreate && (
|
|
292
294
|
<CmsTemplatesComponent
|
|
@@ -332,6 +334,7 @@ EmailWrapper.propTypes = {
|
|
|
332
334
|
moduleType: PropTypes.string,
|
|
333
335
|
onEnterTemplateName: PropTypes.func,
|
|
334
336
|
onRemoveTemplateName: PropTypes.func,
|
|
337
|
+
eventContextTags: PropTypes.array,
|
|
335
338
|
};
|
|
336
339
|
|
|
337
340
|
const mapStateToProps = createStructuredSelector({
|
|
@@ -1804,6 +1804,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
1804
1804
|
templateData={this.props.templateData}
|
|
1805
1805
|
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
1806
1806
|
isFullMode={this.props.isFullMode}
|
|
1807
|
+
eventContextTags={this.props?.eventContextTags}
|
|
1807
1808
|
/>
|
|
1808
1809
|
</CapColumn>
|
|
1809
1810
|
{this.props.iosCtasData && this.state.showIosCtaTable &&
|
|
@@ -1895,6 +1896,7 @@ Create.propTypes = {
|
|
|
1895
1896
|
getFormLibraryData: PropTypes.func,
|
|
1896
1897
|
onPreviewContentClicked: PropTypes.func,
|
|
1897
1898
|
onTestContentClicked: PropTypes.func,
|
|
1899
|
+
eventContextTags: PropTypes.array,
|
|
1898
1900
|
};
|
|
1899
1901
|
|
|
1900
1902
|
const mapStateToProps = createStructuredSelector({
|
|
@@ -1951,6 +1951,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1951
1951
|
templateData={this.props.templateData}
|
|
1952
1952
|
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
1953
1953
|
isFullMode={this.props.isFullMode}
|
|
1954
|
+
eventContextTags={this.props?.eventContextTags}
|
|
1954
1955
|
/>}
|
|
1955
1956
|
</CapColumn>
|
|
1956
1957
|
{this.props.iosCtasData && this.state.showIosCtaTable &&
|
|
@@ -2046,6 +2047,7 @@ Edit.propTypes = {
|
|
|
2046
2047
|
onPreviewContentClicked: PropTypes.func,
|
|
2047
2048
|
onTestContentClicked: PropTypes.func,
|
|
2048
2049
|
creativesMode: PropTypes.string,
|
|
2050
|
+
eventContextTags: PropTypes.array,
|
|
2049
2051
|
};
|
|
2050
2052
|
|
|
2051
2053
|
const mapStateToProps = createStructuredSelector({
|
|
@@ -72,7 +72,7 @@ export class MobilepushWrapper extends React.Component { // eslint-disable-line
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
render() {
|
|
75
|
-
const {mobilePushCreateMode, step, getFormData, setIsLoadingContent, isGetFormData, query, isFullMode, showTemplateName, type, onValidationFail, onPreviewContentClicked, onTestContentClicked, templateData} = this.props;
|
|
75
|
+
const {mobilePushCreateMode, step, getFormData, setIsLoadingContent, isGetFormData, query, isFullMode, showTemplateName, type, onValidationFail, onPreviewContentClicked, onTestContentClicked, templateData, eventContextTags = []} = this.props;
|
|
76
76
|
const {templateName} = this.state;
|
|
77
77
|
const isShowMobilepushCreate = !isEmpty(mobilePushCreateMode);
|
|
78
78
|
return (
|
|
@@ -119,6 +119,7 @@ export class MobilepushWrapper extends React.Component { // eslint-disable-line
|
|
|
119
119
|
onTestContentClicked={onTestContentClicked}
|
|
120
120
|
templateData={templateData}
|
|
121
121
|
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
122
|
+
eventContextTags={eventContextTags}
|
|
122
123
|
/>
|
|
123
124
|
|
|
124
125
|
|
|
@@ -144,6 +145,7 @@ MobilepushWrapper.propTypes = {
|
|
|
144
145
|
showTemplateName: PropTypes.func,
|
|
145
146
|
type: PropTypes.string,
|
|
146
147
|
onValidationFail: PropTypes.func,
|
|
148
|
+
eventContextTags: PropTypes.array,
|
|
147
149
|
};
|
|
148
150
|
|
|
149
151
|
|
|
@@ -989,6 +989,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
989
989
|
selectedOfferDetails={this.props.selectedOfferDetails}
|
|
990
990
|
onTestContentClicked={this.props.onTestContentClicked}
|
|
991
991
|
onPreviewContentClicked={this.props.onPreviewContentClicked}
|
|
992
|
+
eventContextTags={this.props?.eventContextTags}
|
|
992
993
|
/>
|
|
993
994
|
</CapColumn>
|
|
994
995
|
</CapRow>
|
|
@@ -1015,6 +1016,7 @@ Create.propTypes = {
|
|
|
1015
1016
|
getFormSubscriptionData: PropTypes.func,
|
|
1016
1017
|
isLoadingMetaEntities: PropTypes.bool,
|
|
1017
1018
|
selectedOfferDetails: PropTypes.array,
|
|
1019
|
+
eventContextTags: PropTypes.array,
|
|
1018
1020
|
};
|
|
1019
1021
|
|
|
1020
1022
|
const mapStateToProps = createStructuredSelector({
|
|
@@ -987,6 +987,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
987
987
|
selectedOfferDetails={this.props.selectedOfferDetails}
|
|
988
988
|
onPreviewContentClicked={this.props.onPreviewContentClicked}
|
|
989
989
|
onTestContentClicked={this.props.onTestContentClicked}
|
|
990
|
+
eventContextTags={this.props?.eventContextTags}
|
|
990
991
|
/>
|
|
991
992
|
</CapColumn>
|
|
992
993
|
</CapRow>
|
|
@@ -1016,6 +1017,7 @@ Edit.propTypes = {
|
|
|
1016
1017
|
// route: PropTypes.object,
|
|
1017
1018
|
injectedTags: PropTypes.object,
|
|
1018
1019
|
selectedOfferDetails: PropTypes.array,
|
|
1020
|
+
eventContextTags: PropTypes.array,
|
|
1019
1021
|
};
|
|
1020
1022
|
|
|
1021
1023
|
const mapStateToProps = createStructuredSelector({
|
|
@@ -71,6 +71,7 @@ export const SmsTraiEdit = (props) => {
|
|
|
71
71
|
getFormSubscriptionData,
|
|
72
72
|
templateData = {},
|
|
73
73
|
selectedOfferDetails,
|
|
74
|
+
eventContextTags,
|
|
74
75
|
} = props || {};
|
|
75
76
|
const { formatMessage } = intl;
|
|
76
77
|
const [loading, updateLoading] = useState(true);
|
|
@@ -226,6 +227,7 @@ export const SmsTraiEdit = (props) => {
|
|
|
226
227
|
injectedTagsParams: injectedTags,
|
|
227
228
|
location,
|
|
228
229
|
tagModule: getDefaultTags,
|
|
230
|
+
eventContextTags,
|
|
229
231
|
}) || {};
|
|
230
232
|
updateIsTagValidationError(
|
|
231
233
|
tagValidationResponse.unsupportedTags.length > 0,
|
|
@@ -569,6 +571,7 @@ export const SmsTraiEdit = (props) => {
|
|
|
569
571
|
injectedTags={injectedTags || {}}
|
|
570
572
|
hidePopover={disablehandler()}
|
|
571
573
|
selectedOfferDetails={selectedOfferDetails}
|
|
574
|
+
eventContextTags={eventContextTags}
|
|
572
575
|
/>
|
|
573
576
|
}
|
|
574
577
|
/>
|
|
@@ -29,6 +29,7 @@ const SmsWrapper = (props) => {
|
|
|
29
29
|
handleClose,
|
|
30
30
|
smsRegister,
|
|
31
31
|
onShowTemplates,
|
|
32
|
+
eventContextTags,
|
|
32
33
|
} = props;
|
|
33
34
|
|
|
34
35
|
const smsProps = {
|
|
@@ -44,6 +45,7 @@ const SmsWrapper = (props) => {
|
|
|
44
45
|
selectedOfferDetails,
|
|
45
46
|
onPreviewContentClicked,
|
|
46
47
|
onTestContentClicked,
|
|
48
|
+
eventContextTags,
|
|
47
49
|
};
|
|
48
50
|
const isTraiDlt = isTraiDLTEnable(isFullMode, smsRegister);
|
|
49
51
|
return <>
|
|
@@ -22,6 +22,7 @@ import './_tagList.scss';
|
|
|
22
22
|
import { selectCurrentOrgDetails, makeSelectFetchingSchemaError } from '../Cap/selectors';
|
|
23
23
|
import { injectIntl } from 'react-intl';
|
|
24
24
|
import { scope } from './messages';
|
|
25
|
+
import messages from './messages';
|
|
25
26
|
import { handleInjectedData, hasGiftVoucherFeature, hasPromoFeature, hasBadgesFeature, transformBadgeTags } from '../../utils/common';
|
|
26
27
|
import { GIFT_VOUCHER_RELATED_TAGS, PROMO_ENGINE_RELATED_TAGS, BADGES_RELATED_TAGS, BADGES_ENROLL, BADGES_ISSUE } from '../../containers/App/constants';
|
|
27
28
|
|
|
@@ -83,7 +84,9 @@ export class TagList extends React.Component { // eslint-disable-line react/pref
|
|
|
83
84
|
generateTags = (props) => {
|
|
84
85
|
let tags = {};
|
|
85
86
|
let injectedTags = {};
|
|
86
|
-
const
|
|
87
|
+
const eventContextTagsObj = {};
|
|
88
|
+
|
|
89
|
+
const {selectedOfferDetails, eventContextTags } = props;
|
|
87
90
|
if (props.injectedTags && !_.isEmpty(props.injectedTags)) {
|
|
88
91
|
const formattedInjectedTags = handleInjectedData(
|
|
89
92
|
props.injectedTags,
|
|
@@ -101,7 +104,27 @@ export class TagList extends React.Component { // eslint-disable-line react/pref
|
|
|
101
104
|
this.transformCouponTags(selectedOfferDetails, tags);
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
|
-
|
|
107
|
+
if (eventContextTags?.length) {
|
|
108
|
+
const TAG_HEADER_MSG_LABEL = this.props.intl.formatMessage(messages.tagsBasedOnEntryTriggerEvent);
|
|
109
|
+
eventContextTagsObj.EventContextTags = {
|
|
110
|
+
name: TAG_HEADER_MSG_LABEL,
|
|
111
|
+
desc: TAG_HEADER_MSG_LABEL,
|
|
112
|
+
resolved: true,
|
|
113
|
+
'tag-header': true,
|
|
114
|
+
subtags: {},
|
|
115
|
+
};
|
|
116
|
+
// Journey event context tags also should be displayed in the Add Labels.
|
|
117
|
+
eventContextTags.forEach((tag) => {
|
|
118
|
+
if (tag?.tagName) {
|
|
119
|
+
eventContextTagsObj.EventContextTags.subtags[tag?.tagName] = {
|
|
120
|
+
name: tag?.tagName,
|
|
121
|
+
desc: tag?.tagName,
|
|
122
|
+
resolved: true
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
this.setState({tags: _.merge( {}, tags, injectedTags, eventContextTagsObj )});
|
|
105
128
|
}
|
|
106
129
|
populateTags(tagsList) {
|
|
107
130
|
const mainTags = {};
|
|
@@ -299,6 +322,7 @@ export class TagList extends React.Component { // eslint-disable-line react/pref
|
|
|
299
322
|
TagList.defaultProps = {
|
|
300
323
|
isNewVersionFlow: false,
|
|
301
324
|
userLocale: 'en',
|
|
325
|
+
eventContextTags: [],
|
|
302
326
|
};
|
|
303
327
|
|
|
304
328
|
TagList.propTypes = {
|
|
@@ -318,6 +342,7 @@ TagList.propTypes = {
|
|
|
318
342
|
channel: PropTypes.string,
|
|
319
343
|
disabled: PropTypes.bool,
|
|
320
344
|
fetchingSchemaError: PropTypes.bool,
|
|
345
|
+
eventContextTags: PropTypes.array,
|
|
321
346
|
};
|
|
322
347
|
|
|
323
348
|
const mapStateToProps = createStructuredSelector({
|
|
@@ -11,4 +11,8 @@ export default defineMessages({
|
|
|
11
11
|
id: `${scope}.header`,
|
|
12
12
|
defaultMessage: 'This is TagList container !',
|
|
13
13
|
},
|
|
14
|
+
tagsBasedOnEntryTriggerEvent: {
|
|
15
|
+
id: `${scope}.tagsBasedOnEntryTriggerEvent`,
|
|
16
|
+
defaultMessage: 'Tags based on entry trigger event',
|
|
17
|
+
},
|
|
14
18
|
});
|
|
@@ -4,9 +4,10 @@ import configureStore from "../../../store";
|
|
|
4
4
|
import { injectIntl } from "react-intl";
|
|
5
5
|
import { fireEvent } from "@testing-library/react";
|
|
6
6
|
import { TagList } from '../index';
|
|
7
|
-
import { TagListData } from './mockdata';
|
|
7
|
+
import { TagListData, eventContextTags } from './mockdata';
|
|
8
8
|
import { Provider } from 'react-redux';
|
|
9
9
|
import { screen, render } from '../../../utils/test-utils';
|
|
10
|
+
const { getByText } = screen;
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
const initializeTagList = (props) => {
|
|
@@ -26,16 +27,26 @@ const initializeTagList = (props) => {
|
|
|
26
27
|
);
|
|
27
28
|
};
|
|
28
29
|
|
|
30
|
+
const addLabelBtnAssertion = () => {
|
|
31
|
+
const addLabelButton = screen.getByRole('button', {
|
|
32
|
+
name: /add label/i
|
|
33
|
+
});
|
|
34
|
+
expect(addLabelButton).toBeInTheDocument();
|
|
35
|
+
fireEvent.click(addLabelButton);
|
|
36
|
+
};
|
|
29
37
|
|
|
30
38
|
describe("TagList test : UNIT", () => {
|
|
31
39
|
it("should render the TagList component with default props amd addLabel Button", async () => {
|
|
32
40
|
initializeTagList();
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
addLabelBtnAssertion();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should render event context tags correctly from generateTags', () => {
|
|
45
|
+
initializeTagList({eventContextTags});
|
|
46
|
+
addLabelBtnAssertion();
|
|
47
|
+
const EVENT_CONTEXT_TAG_HEADER = getByText('Tags based on entry trigger event');
|
|
48
|
+
expect(EVENT_CONTEXT_TAG_HEADER).toBeInTheDocument();
|
|
49
|
+
fireEvent.click(EVENT_CONTEXT_TAG_HEADER);
|
|
50
|
+
expect(getByText('lifetimePurchases')).toBeInTheDocument();
|
|
40
51
|
});
|
|
41
52
|
});
|
|
@@ -105,4 +105,62 @@ export const TagListData = {
|
|
|
105
105
|
"actions": {},
|
|
106
106
|
"globalActions": {},
|
|
107
107
|
"isNewVersionFlow": false,
|
|
108
|
-
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const eventContextTags = [
|
|
111
|
+
{
|
|
112
|
+
"profileId": "BEHAVIOURAL_EVENT_PROFILE",
|
|
113
|
+
"method": "getEventData",
|
|
114
|
+
"field": "butterfly",
|
|
115
|
+
"params": null,
|
|
116
|
+
"returnType": {
|
|
117
|
+
"isList": false,
|
|
118
|
+
"typeInfo": {
|
|
119
|
+
"type": "DOUBLE",
|
|
120
|
+
"typeId": null
|
|
121
|
+
},
|
|
122
|
+
"list": false
|
|
123
|
+
},
|
|
124
|
+
"factId": "getEventData_butterfly",
|
|
125
|
+
"tagName": "(butterfly)",
|
|
126
|
+
"isTaggable": true,
|
|
127
|
+
"uniqueId": "yW_DH7vjKk__BEHAVIOURAL__monsoon",
|
|
128
|
+
"isDynamicFact": true
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"profileId": "BEHAVIOURAL_EVENT_PROFILE",
|
|
132
|
+
"method": "getEventData",
|
|
133
|
+
"field": "raindrops",
|
|
134
|
+
"params": null,
|
|
135
|
+
"returnType": {
|
|
136
|
+
"isList": false,
|
|
137
|
+
"typeInfo": {
|
|
138
|
+
"type": "DOUBLE",
|
|
139
|
+
"typeId": null
|
|
140
|
+
},
|
|
141
|
+
"list": false
|
|
142
|
+
},
|
|
143
|
+
"factId": "getEventData_raindrops",
|
|
144
|
+
"tagName": "",
|
|
145
|
+
"isTaggable": true,
|
|
146
|
+
"uniqueId": "yW_DH7vjKk__BEHAVIOURAL__monsoon",
|
|
147
|
+
"isDynamicFact": true
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"factId": "5LFP9e",
|
|
151
|
+
"profileId": "CUSTOMER_PROFILE",
|
|
152
|
+
"params": [],
|
|
153
|
+
"returnType": {
|
|
154
|
+
"isList": false,
|
|
155
|
+
"typeInfo": {
|
|
156
|
+
"type": "DOUBLE",
|
|
157
|
+
"typeId": null
|
|
158
|
+
},
|
|
159
|
+
"list": false
|
|
160
|
+
},
|
|
161
|
+
"tagName": "lifetimePurchases",
|
|
162
|
+
"isTaggable": true,
|
|
163
|
+
"uniqueId": "yW_DH7vjKk__BEHAVIOURAL__monsoon",
|
|
164
|
+
"isDynamicFact": false
|
|
165
|
+
}
|
|
166
|
+
];
|
|
@@ -71,6 +71,7 @@ export const Viber = (props) => {
|
|
|
71
71
|
viberData = {},
|
|
72
72
|
selectedOfferDetails = [],
|
|
73
73
|
currentOrgDetails,
|
|
74
|
+
eventContextTags,
|
|
74
75
|
} = props || {};
|
|
75
76
|
|
|
76
77
|
const { formatMessage } = intl;
|
|
@@ -270,6 +271,7 @@ export const Viber = (props) => {
|
|
|
270
271
|
id={"viber_tags"}
|
|
271
272
|
userLocale={localStorage.getItem("jlocale") || "en"}
|
|
272
273
|
selectedOfferDetails={selectedOfferDetails}
|
|
274
|
+
eventContextTags={eventContextTags}
|
|
273
275
|
/>
|
|
274
276
|
</CapColumn>
|
|
275
277
|
<div className="viber-textarea-wrapper">
|
|
@@ -128,7 +128,8 @@ export const Whatsapp = (props) => {
|
|
|
128
128
|
loadingTags,
|
|
129
129
|
getFormData,
|
|
130
130
|
selectedOfferDetails,
|
|
131
|
-
currentOrgDetails
|
|
131
|
+
currentOrgDetails,
|
|
132
|
+
eventContextTags,
|
|
132
133
|
} = props || {};
|
|
133
134
|
const { formatMessage } = intl;
|
|
134
135
|
const { TextArea } = CapInput;
|
|
@@ -501,6 +502,7 @@ export const Whatsapp = (props) => {
|
|
|
501
502
|
injectedTagsParams: injectedTags,
|
|
502
503
|
location,
|
|
503
504
|
tagModule: getDefaultTags,
|
|
505
|
+
eventContextTags,
|
|
504
506
|
}) || {};
|
|
505
507
|
const unsupportedTagsLengthCheck =
|
|
506
508
|
validationResponse?.unsupportedTags?.length > 0;
|
|
@@ -2051,6 +2053,7 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
|
|
|
2051
2053
|
onContextChange={handleOnTagsContextChange}
|
|
2052
2054
|
injectedTags={injectedTags || {}}
|
|
2053
2055
|
selectedOfferDetails={selectedOfferDetails}
|
|
2056
|
+
eventContextTags={eventContextTags}
|
|
2054
2057
|
/>
|
|
2055
2058
|
)
|
|
2056
2059
|
}
|
|
@@ -66,6 +66,7 @@ export const Zalo = (props) => {
|
|
|
66
66
|
getFormData,
|
|
67
67
|
selectedOfferDetails,
|
|
68
68
|
hostName: zaloHostName = '',
|
|
69
|
+
eventContextTags,
|
|
69
70
|
} = props || {};
|
|
70
71
|
const {hostName = zaloHostName || ''} = senderDetails;
|
|
71
72
|
const { formatMessage } = intl;
|
|
@@ -256,6 +257,7 @@ export const Zalo = (props) => {
|
|
|
256
257
|
injectedTagsParams: injectedTags,
|
|
257
258
|
location,
|
|
258
259
|
tagModule: getDefaultTags,
|
|
260
|
+
eventContextTags,
|
|
259
261
|
}) || {};
|
|
260
262
|
const { unsupportedTags = [], isBraceError } = tagValidationResponse;
|
|
261
263
|
let tagError = '';
|
|
@@ -445,6 +447,7 @@ export const Zalo = (props) => {
|
|
|
445
447
|
injectedTags={injectedTags || {}}
|
|
446
448
|
selectedOfferDetails={selectedOfferDetails}
|
|
447
449
|
disabled={isFullMode}
|
|
450
|
+
eventContextTags={eventContextTags}
|
|
448
451
|
/>
|
|
449
452
|
}
|
|
450
453
|
/>
|
package/containers/App/index.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* App.js
|
|
4
|
-
*
|
|
5
|
-
* This component is the skeleton around the actual pages, and should only
|
|
6
|
-
* contain code that should be seen on all pages. (e.g. navigation bar)
|
|
7
|
-
*
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import React, { useEffect } from 'react'; // eslint-disable-line no-unused-vars
|
|
11
|
-
import { Switch } from 'react-router';
|
|
12
|
-
import { ConnectedRouter } from 'connected-react-router/immutable';
|
|
13
|
-
import history from 'utils/history';
|
|
14
|
-
|
|
15
|
-
import Cap from '../Cap';
|
|
16
|
-
import CapV2 from '../../v2Containers/Cap';
|
|
17
|
-
import Login from '../Login';
|
|
18
|
-
import NotFoundPage from '../NotFoundPage';
|
|
19
|
-
|
|
20
|
-
import GlobalStyle from '../../global-styles';
|
|
21
|
-
import config from '../../config/app';
|
|
22
|
-
import withReactRouterV3Compatibility from '../../hoc/withReactRouterV3Compatibility';
|
|
23
|
-
import RenderRoute from '../../v2Components/RenderRoute';
|
|
24
|
-
import { updateCharCount } from '../../utils/smsCharCountV2';
|
|
25
|
-
|
|
26
|
-
const loginUrl =
|
|
27
|
-
process.env.NODE_ENV === 'production'
|
|
28
|
-
? `${config.production.login_url}`
|
|
29
|
-
: `${config.development.login_url}`;
|
|
30
|
-
|
|
31
|
-
// const Protected = userIsAuthenticatedRedir(Cap);
|
|
32
|
-
const v3CompatibleCap = withReactRouterV3Compatibility(Cap);
|
|
33
|
-
const v3CompatibleCapV2 = withReactRouterV3Compatibility(CapV2);
|
|
34
|
-
|
|
35
|
-
export default function App() {
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
updateCharCount("", false);
|
|
38
|
-
});
|
|
39
|
-
return (
|
|
40
|
-
<div>
|
|
41
|
-
<ConnectedRouter history={history}>
|
|
42
|
-
<Switch>
|
|
43
|
-
<RenderRoute exact path={loginUrl} component={Login} />
|
|
44
|
-
<RenderRoute path="/v2" component={v3CompatibleCapV2} key="/v2" />
|
|
45
|
-
<RenderRoute path="/" component={v3CompatibleCap} key="/" />
|
|
46
|
-
<RenderRoute component={NotFoundPage} />
|
|
47
|
-
</Switch>
|
|
48
|
-
</ConnectedRouter>
|
|
49
|
-
<GlobalStyle />
|
|
50
|
-
</div>
|
|
51
|
-
);
|
|
52
|
-
}
|
package/entry.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { compose } from 'redux';
|
|
4
|
-
import { withRouter } from 'react-router-dom';
|
|
5
|
-
import componentRoutes from '../routes';
|
|
6
|
-
|
|
7
|
-
function findRoute(routes, path) {
|
|
8
|
-
let match;
|
|
9
|
-
for (let i = 0; i < routes.length; i++) {
|
|
10
|
-
const route = routes[i];
|
|
11
|
-
if (route?.path === path) {
|
|
12
|
-
match = route;
|
|
13
|
-
break;
|
|
14
|
-
}
|
|
15
|
-
if (route?.routes) {
|
|
16
|
-
match = findRoute(route.routes, path);
|
|
17
|
-
if (match) {
|
|
18
|
-
break;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return match;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function getParamsObject(params = []) {
|
|
26
|
-
const paramsObject = {};
|
|
27
|
-
params.forEach((value, key) => {
|
|
28
|
-
if (paramsObject[key]) {
|
|
29
|
-
// If the key already exists, convert the value to an array (to handle multiple values for the same key)
|
|
30
|
-
paramsObject[key] = Array.isArray(paramsObject[key])
|
|
31
|
-
? [...paramsObject[key], value]
|
|
32
|
-
: [paramsObject[key], value];
|
|
33
|
-
} else {
|
|
34
|
-
paramsObject[key] = value;
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
return paramsObject;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function withReactRouterV3Compatibility(Component) {
|
|
41
|
-
const EnhancedComponent = (props) => {
|
|
42
|
-
const { history = {}, location = {}, match = {} } = props;
|
|
43
|
-
const matchedRoute = findRoute(componentRoutes, match.path);
|
|
44
|
-
const newProps = {
|
|
45
|
-
...props,
|
|
46
|
-
router: history,
|
|
47
|
-
params: match.params,
|
|
48
|
-
route: matchedRoute,
|
|
49
|
-
location: {
|
|
50
|
-
...location,
|
|
51
|
-
query: getParamsObject(new URLSearchParams(location.search)),
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
return <Component {...newProps} />;
|
|
55
|
-
};
|
|
56
|
-
EnhancedComponent.propTypes = {
|
|
57
|
-
router: PropTypes.object,
|
|
58
|
-
params: PropTypes.object,
|
|
59
|
-
route: PropTypes.object,
|
|
60
|
-
};
|
|
61
|
-
return compose(
|
|
62
|
-
withRouter,
|
|
63
|
-
)(EnhancedComponent);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export default withReactRouterV3Compatibility;
|
package/initialReducer.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import languageProviderReducer from 'v2Containers/LanguageProvider/reducer';
|
|
2
|
-
import beeEditorReducer from 'v2Containers/BeeEditor/reducer';
|
|
3
|
-
import CapFacebookPreviewReducer from 'v2Containers/CapFacebookPreview/reducer';
|
|
4
|
-
|
|
5
|
-
import capReducer from 'containers/Cap/reducer';
|
|
6
|
-
import appReducer from 'containers/App/reducer';
|
|
7
|
-
import createSmsReducer from 'containers/Sms/Create/reducer';
|
|
8
|
-
import editSmsReducer from 'containers/Sms/Edit/reducer';
|
|
9
|
-
import templateReducer from 'containers/Templates/reducer';
|
|
10
|
-
import tagsReducer from 'containers/TagList/reducer';
|
|
11
|
-
import emailReducer from 'containers/Email/reducer';
|
|
12
|
-
import ebillReducer from 'containers/Ebill/reducer';
|
|
13
|
-
import ftpReducer from 'v2Containers/FTP/reducer';
|
|
14
|
-
import galleryReducer from './v2Containers/Assets/Gallery/reducer';
|
|
15
|
-
import CapCollapsibleLeftNavigationReducer from '@capillarytech/cap-ui-library/CapCollapsibleLeftNavigation/reducer';
|
|
16
|
-
import { AIRA_REDUCER_DOMAIN, askAiraReducer } from '@capillarytech/cap-ui-library/CapAskAira';
|
|
17
|
-
|
|
18
|
-
export const initialReducer = {
|
|
19
|
-
language: languageProviderReducer,
|
|
20
|
-
cap: capReducer,
|
|
21
|
-
app: appReducer,
|
|
22
|
-
create: createSmsReducer,
|
|
23
|
-
edit: editSmsReducer,
|
|
24
|
-
templates: templateReducer,
|
|
25
|
-
tagList: tagsReducer,
|
|
26
|
-
email: emailReducer,
|
|
27
|
-
ebill: ebillReducer,
|
|
28
|
-
beeEditor: beeEditorReducer,
|
|
29
|
-
facebookPreview: CapFacebookPreviewReducer,
|
|
30
|
-
FTP: ftpReducer,
|
|
31
|
-
[AIRA_REDUCER_DOMAIN]: askAiraReducer,
|
|
32
|
-
gallery: galleryReducer,
|
|
33
|
-
navigationConfig: CapCollapsibleLeftNavigationReducer,
|
|
34
|
-
};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
// This file is used to expose the components of the MFE to the host application
|
|
2
|
-
// Contents of this file are used in webpack config's ModuleFederationPlugin.
|
|
3
|
-
//
|
|
4
|
-
module.exports = {
|
|
5
|
-
// which exposes
|
|
6
|
-
// ADD MFE COMPONENT YOU WANT TO EXPORT example:
|
|
7
|
-
// './Home': './app/components/pages/Home',
|
|
8
|
-
};
|
package/utils/checkStore.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { conformsTo, isFunction, isObject } from 'lodash';
|
|
2
|
-
import invariant from 'invariant';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Validate the shape of redux store
|
|
6
|
-
*/
|
|
7
|
-
export default function checkStore(store) {
|
|
8
|
-
const shape = {
|
|
9
|
-
dispatch: isFunction,
|
|
10
|
-
subscribe: isFunction,
|
|
11
|
-
getState: isFunction,
|
|
12
|
-
replaceReducer: isFunction,
|
|
13
|
-
runSaga: isFunction,
|
|
14
|
-
injectedReducers: isObject,
|
|
15
|
-
injectedSagas: isObject,
|
|
16
|
-
};
|
|
17
|
-
invariant(
|
|
18
|
-
conformsTo(store, shape),
|
|
19
|
-
'(app/utils...) injectors: Expected a valid redux store',
|
|
20
|
-
);
|
|
21
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-unused-vars */
|
|
2
|
-
/* eslint-disable react/no-multi-comp */
|
|
3
|
-
/* eslint-disable react/prefer-stateless-function */
|
|
4
|
-
import React, { Component } from 'react';
|
|
5
|
-
import PropTypes from 'prop-types';
|
|
6
|
-
import hoistStatics from 'hoist-non-react-statics';
|
|
7
|
-
|
|
8
|
-
const AuthenticatingComponentWithRef = React.forwardRef((props, ref) => (
|
|
9
|
-
<div ref={ref} />
|
|
10
|
-
));
|
|
11
|
-
const FailureComponentWithRef = React.forwardRef((props, ref) => (
|
|
12
|
-
<div ref={ref} />
|
|
13
|
-
));
|
|
14
|
-
const defaults = {
|
|
15
|
-
AuthenticatingComponent: AuthenticatingComponentWithRef, // dont render anything while authenticating
|
|
16
|
-
FailureComponent: FailureComponentWithRef, // dont render anything on failure of the predicate
|
|
17
|
-
wrapperDisplayName: 'AuthWrapper',
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export default args => {
|
|
21
|
-
const { AuthenticatingComponent, FailureComponent, wrapperDisplayName } = {
|
|
22
|
-
...defaults,
|
|
23
|
-
...args,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// Wraps the component that needs the auth enforcement
|
|
27
|
-
return function wrapComponent(DecoratedComponent) {
|
|
28
|
-
const displayName =
|
|
29
|
-
DecoratedComponent.displayName || DecoratedComponent.name || 'Component';
|
|
30
|
-
|
|
31
|
-
class UserAuthWrapper extends Component {
|
|
32
|
-
static displayName = `${wrapperDisplayName}(${displayName})`;
|
|
33
|
-
|
|
34
|
-
static propTypes = {
|
|
35
|
-
isAuthenticated: PropTypes.bool,
|
|
36
|
-
isAuthenticating: PropTypes.bool,
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
static defaultProps = {
|
|
40
|
-
isAuthenticating: false,
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
render() {
|
|
44
|
-
const { isAuthenticated, isAuthenticating, forwardedRef } = this.props;
|
|
45
|
-
if (isAuthenticated) {
|
|
46
|
-
return <DecoratedComponent {...this.props} ref={forwardedRef} />;
|
|
47
|
-
}
|
|
48
|
-
if (isAuthenticating) {
|
|
49
|
-
return <AuthenticatingComponent {...this.props} ref={forwardedRef} />;
|
|
50
|
-
}
|
|
51
|
-
return <FailureComponent {...this.props} ref={forwardedRef} />;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** forwardRef from HOC to the Wrapped Component */
|
|
56
|
-
const UserAuthWrapperWithRef = React.forwardRef((props, ref) => (
|
|
57
|
-
<UserAuthWrapper {...props} forwardedRef={ref} />
|
|
58
|
-
));
|
|
59
|
-
|
|
60
|
-
return hoistStatics(UserAuthWrapperWithRef, DecoratedComponent);
|
|
61
|
-
};
|
|
62
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { connect } from 'react-redux';
|
|
2
|
-
|
|
3
|
-
import authWrapper from './customAuthWrapper';
|
|
4
|
-
|
|
5
|
-
const connectedDefaults = {
|
|
6
|
-
authenticatingSelector: () => false,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export default args => {
|
|
10
|
-
const { authenticatedSelector, authenticatingSelector } = {
|
|
11
|
-
...connectedDefaults,
|
|
12
|
-
...args,
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/** Passed withRef option set to true for forwarding Ref to Wrapped Component */
|
|
16
|
-
return DecoratedComponent =>
|
|
17
|
-
connect(
|
|
18
|
-
(state, ownProps) => ({
|
|
19
|
-
isAuthenticated: authenticatedSelector(state, ownProps),
|
|
20
|
-
isAuthenticating: authenticatingSelector(state, ownProps),
|
|
21
|
-
}),
|
|
22
|
-
null,
|
|
23
|
-
null,
|
|
24
|
-
{ withRef: true },
|
|
25
|
-
)(authWrapper(args)(DecoratedComponent));
|
|
26
|
-
};
|
package/utils/history.js
DELETED
package/utils/injectReducer.js
DELETED
package/utils/injectSaga.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { all } from 'redux-saga/effects';
|
|
2
|
-
import CapCollapsibleLeftNavigationSagas from '@capillarytech/cap-ui-library/CapCollapsibleLeftNavigation/saga';
|
|
3
|
-
import { analyticsBotSaga } from '@capillarytech/cap-ui-library/CapAskAira';
|
|
4
|
-
|
|
5
|
-
export default [
|
|
6
|
-
{
|
|
7
|
-
key: 'navigation',
|
|
8
|
-
saga: function* navigationConfigSaga() {
|
|
9
|
-
yield all(CapCollapsibleLeftNavigationSagas.map(saga => saga.call()));
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
key: 'analyticsBotSaga',
|
|
14
|
-
saga: function* analyticsBotSagaFn() {
|
|
15
|
-
yield all(analyticsBotSaga.map(saga => saga.call()));
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
];
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Route } from 'react-router-dom';
|
|
3
|
-
|
|
4
|
-
const RenderRoute = ({ Component: ComponentToRender, ...rest }) => (
|
|
5
|
-
<Route
|
|
6
|
-
{...rest}
|
|
7
|
-
render={props => <ComponentToRender {...props} />}
|
|
8
|
-
/>
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
export default RenderRoute;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from './RenderRoute';
|