@capillarytech/creatives-library 8.0.282 → 8.0.284
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
|
@@ -55,19 +55,26 @@ export const CapWhatsappCarouselButton = (props) => {
|
|
|
55
55
|
const invalidVarRegex = /{{(.*?)}}/g;
|
|
56
56
|
|
|
57
57
|
const handleButtonType = ({ target: { value } }, buttonIndex) => {
|
|
58
|
-
const cloneCarouselData = cloneDeep(carouselData);
|
|
59
58
|
const dataMap = {
|
|
60
59
|
[PHONE_NUMBER]: INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
|
|
61
60
|
[URL]: INITIAL_CAROUSEL_URL_DATA,
|
|
62
61
|
[QUICK_REPLY]: INITIAL_CAROUSEL_QUICK_REPLY_DATA,
|
|
63
62
|
};
|
|
63
|
+
const initialData = dataMap[value];
|
|
64
|
+
const newButtonData = initialData ? cloneDeep(initialData) : {};
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
setCarouselData(
|
|
67
|
+
carouselData.map((item, index) =>
|
|
68
|
+
index === carouselIndex
|
|
69
|
+
? {
|
|
70
|
+
...item,
|
|
71
|
+
buttons: item.buttons.map((btn, i) =>
|
|
72
|
+
i === buttonIndex ? newButtonData : btn
|
|
73
|
+
),
|
|
74
|
+
}
|
|
75
|
+
: item
|
|
76
|
+
)
|
|
77
|
+
);
|
|
71
78
|
};
|
|
72
79
|
|
|
73
80
|
const onValueChange = (buttonIndex, fields = []) => {
|
|
@@ -148,17 +155,28 @@ export const CapWhatsappCarouselButton = (props) => {
|
|
|
148
155
|
};
|
|
149
156
|
|
|
150
157
|
const handleDeleteButton = (buttonIndex) => {
|
|
151
|
-
setCarouselData((prevData) =>
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
setCarouselData((prevData) =>
|
|
159
|
+
prevData.map((carousel, index) =>
|
|
160
|
+
index === carouselIndex
|
|
161
|
+
? {
|
|
162
|
+
...carousel,
|
|
163
|
+
buttons: carousel.buttons.filter((_, i) => i !== buttonIndex),
|
|
164
|
+
}
|
|
165
|
+
: carousel
|
|
166
|
+
)
|
|
167
|
+
);
|
|
155
168
|
};
|
|
156
169
|
|
|
157
170
|
const addCarouselButton = () => {
|
|
158
171
|
setCarouselData(
|
|
159
|
-
carouselData.map((item, index) =>
|
|
160
|
-
|
|
161
|
-
|
|
172
|
+
carouselData.map((item, index) =>
|
|
173
|
+
index === carouselIndex
|
|
174
|
+
? {
|
|
175
|
+
...item,
|
|
176
|
+
buttons: [...buttonData, cloneDeep(INITIAL_CAROUSEL_PHONE_NUMBER_DATA)],
|
|
177
|
+
}
|
|
178
|
+
: item
|
|
179
|
+
)
|
|
162
180
|
);
|
|
163
181
|
};
|
|
164
182
|
|
|
@@ -3,9 +3,10 @@ import { injectIntl } from 'react-intl';
|
|
|
3
3
|
import '@testing-library/jest-dom';
|
|
4
4
|
import { render, screen, fireEvent } from '../../../utils/test-utils';
|
|
5
5
|
import { CapWhatsappCarouselButton } from '../index';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
7
|
INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
|
|
8
|
-
INITIAL_CAROUSEL_URL_DATA
|
|
8
|
+
INITIAL_CAROUSEL_URL_DATA,
|
|
9
|
+
URL,
|
|
9
10
|
} from '../constant';
|
|
10
11
|
import { HOST_TWILIO } from "../../../v2Containers/Whatsapp/constants";
|
|
11
12
|
|
|
@@ -234,4 +235,121 @@ describe('CapWhatsappCarouselButton', () => {
|
|
|
234
235
|
})
|
|
235
236
|
]));
|
|
236
237
|
});
|
|
238
|
+
|
|
239
|
+
describe('carousel-scoped updates (only current card is updated)', () => {
|
|
240
|
+
it('handleButtonType only updates the carousel at carouselIndex', () => {
|
|
241
|
+
const card0 = {
|
|
242
|
+
bodyText: '',
|
|
243
|
+
buttons: [{ ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA, text: 'Card 0' }],
|
|
244
|
+
};
|
|
245
|
+
const card1 = {
|
|
246
|
+
bodyText: '',
|
|
247
|
+
buttons: [{ ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA, text: 'Card 1' }],
|
|
248
|
+
};
|
|
249
|
+
const carouselData = [card0, card1];
|
|
250
|
+
|
|
251
|
+
initializeComponent(carouselData, false, HOST_TWILIO, 0);
|
|
252
|
+
|
|
253
|
+
const radios = screen.getAllByRole('radio');
|
|
254
|
+
const urlRadio = radios.find((r) => r.value === URL) || radios[1];
|
|
255
|
+
if (urlRadio) fireEvent.click(urlRadio);
|
|
256
|
+
|
|
257
|
+
expect(setCarouselData).toHaveBeenCalledWith(expect.any(Array));
|
|
258
|
+
const updated = setCarouselData.mock.calls[0][0];
|
|
259
|
+
expect(updated).toHaveLength(2);
|
|
260
|
+
expect(updated[0].buttons[0]).toMatchObject(INITIAL_CAROUSEL_URL_DATA);
|
|
261
|
+
expect(updated[1]).toEqual(card1);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('handleDeleteButton only removes button from the carousel at carouselIndex', () => {
|
|
265
|
+
const card0 = {
|
|
266
|
+
bodyText: '',
|
|
267
|
+
buttons: [
|
|
268
|
+
{ ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA, text: 'A', isSaved: true },
|
|
269
|
+
{ ...INITIAL_CAROUSEL_URL_DATA, text: 'B', isSaved: true },
|
|
270
|
+
],
|
|
271
|
+
};
|
|
272
|
+
const card1 = {
|
|
273
|
+
bodyText: '',
|
|
274
|
+
buttons: [
|
|
275
|
+
{ ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA, text: 'C', isSaved: true },
|
|
276
|
+
{ ...INITIAL_CAROUSEL_URL_DATA, text: 'D', isSaved: true },
|
|
277
|
+
],
|
|
278
|
+
};
|
|
279
|
+
const carouselData = [card0, card1];
|
|
280
|
+
|
|
281
|
+
const { container } = initializeComponent(carouselData, false, HOST_TWILIO, 0);
|
|
282
|
+
|
|
283
|
+
const deleteIconBtns = container.querySelectorAll('.whatsapp-carousel-delete-icon-btn');
|
|
284
|
+
expect(deleteIconBtns.length).toBeGreaterThanOrEqual(2);
|
|
285
|
+
fireEvent.click(deleteIconBtns[1]);
|
|
286
|
+
|
|
287
|
+
expect(setCarouselData).toHaveBeenCalledTimes(1);
|
|
288
|
+
const setter = setCarouselData.mock.calls[0][0];
|
|
289
|
+
expect(typeof setter).toBe('function');
|
|
290
|
+
const result = setter(carouselData);
|
|
291
|
+
expect(result[0].buttons).toHaveLength(1);
|
|
292
|
+
expect(result[0].buttons[0].text).toBe('A');
|
|
293
|
+
expect(result[1].buttons).toHaveLength(2);
|
|
294
|
+
expect(result[1].buttons[0].text).toBe('C');
|
|
295
|
+
expect(result[1].buttons[1].text).toBe('D');
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('addCarouselButton only adds button to the carousel at carouselIndex', () => {
|
|
299
|
+
const card0 = {
|
|
300
|
+
bodyText: '',
|
|
301
|
+
buttons: [{
|
|
302
|
+
...INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
|
|
303
|
+
text: 'Call us',
|
|
304
|
+
phone_number: '9112345678',
|
|
305
|
+
isSaved: true,
|
|
306
|
+
}],
|
|
307
|
+
};
|
|
308
|
+
const card1 = {
|
|
309
|
+
bodyText: '',
|
|
310
|
+
buttons: [{ ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA, text: 'Other' }],
|
|
311
|
+
};
|
|
312
|
+
const carouselData = [card0, card1];
|
|
313
|
+
|
|
314
|
+
initializeComponent(carouselData, false, HOST_TWILIO, 0);
|
|
315
|
+
|
|
316
|
+
const addButton = screen.getByRole('button', { name: /add button/i });
|
|
317
|
+
fireEvent.click(addButton);
|
|
318
|
+
|
|
319
|
+
expect(setCarouselData).toHaveBeenCalledWith(expect.any(Array));
|
|
320
|
+
const updated = setCarouselData.mock.calls[0][0];
|
|
321
|
+
expect(updated).toHaveLength(2);
|
|
322
|
+
expect(updated[0].buttons).toHaveLength(2);
|
|
323
|
+
expect(updated[0].buttons[0].text).toBe('Call us');
|
|
324
|
+
expect(updated[0].buttons[1]).toMatchObject(INITIAL_CAROUSEL_PHONE_NUMBER_DATA);
|
|
325
|
+
expect(updated[0].buttons[1]).not.toBe(INITIAL_CAROUSEL_PHONE_NUMBER_DATA);
|
|
326
|
+
expect(updated[1]).toEqual(card1);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it('addCarouselButton adds a new button object (clone) so state is not shared', () => {
|
|
330
|
+
const carouselData = [{
|
|
331
|
+
bodyText: '',
|
|
332
|
+
buttons: [{
|
|
333
|
+
...INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
|
|
334
|
+
text: 'Saved',
|
|
335
|
+
isSaved: true,
|
|
336
|
+
}],
|
|
337
|
+
}];
|
|
338
|
+
|
|
339
|
+
initializeComponent(carouselData, false, HOST_TWILIO, 0);
|
|
340
|
+
|
|
341
|
+
const addButton = screen.getByRole('button', { name: /add button/i });
|
|
342
|
+
fireEvent.click(addButton);
|
|
343
|
+
|
|
344
|
+
const updated = setCarouselData.mock.calls[0][0];
|
|
345
|
+
const addedButton = updated[0].buttons[1];
|
|
346
|
+
expect(addedButton).toMatchObject({
|
|
347
|
+
buttonType: 'PHONE_NUMBER',
|
|
348
|
+
text: '',
|
|
349
|
+
phone_number: '',
|
|
350
|
+
isSaved: false,
|
|
351
|
+
});
|
|
352
|
+
expect(addedButton).not.toBe(INITIAL_CAROUSEL_PHONE_NUMBER_DATA);
|
|
353
|
+
});
|
|
354
|
+
});
|
|
237
355
|
});
|
|
@@ -47,6 +47,17 @@ import TestAndPreviewSlidebox from '../../../v2Components/TestAndPreviewSlidebox
|
|
|
47
47
|
const PrefixWrapper = styled.div`
|
|
48
48
|
margin-right: 16px;
|
|
49
49
|
`;
|
|
50
|
+
|
|
51
|
+
const safeParseDeeplinkConfig = (value) => {
|
|
52
|
+
if (!value || typeof value !== 'string') return [];
|
|
53
|
+
try {
|
|
54
|
+
const parsed = JSON.parse(value);
|
|
55
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
56
|
+
} catch {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
50
61
|
export class Edit extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
51
62
|
constructor(props) {
|
|
52
63
|
super(props);
|
|
@@ -96,11 +107,12 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
96
107
|
if (!_.isEmpty(this.state.schema)) {
|
|
97
108
|
this.injectEvents(this.state.schema);
|
|
98
109
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
110
|
+
const templateId = get(this, "props.params.id");
|
|
111
|
+
const hasTemplateData = !_.isEmpty(this.props.templateData);
|
|
112
|
+
if (this.props.location?.query && (templateId || hasTemplateData)) {
|
|
113
|
+
if (templateId && templateId !== 'temp') {
|
|
102
114
|
this.props.actions.getTemplateDetails(templateId);
|
|
103
|
-
} else {
|
|
115
|
+
} else if (hasTemplateData) {
|
|
104
116
|
this.props.actions.setTemplateDetails(this.props.templateData);
|
|
105
117
|
}
|
|
106
118
|
}
|
|
@@ -176,7 +188,9 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
176
188
|
this.props.actions.getMobilepushTemplatesList('mobilepush', params);
|
|
177
189
|
}
|
|
178
190
|
if (nextProps.metaEntities && nextProps.metaEntities.layouts && nextProps.metaEntities.layouts.length > 0 && _.isEmpty(this.state.fullSchema)) {
|
|
179
|
-
|
|
191
|
+
const definition = nextProps.metaEntities.layouts[0].definition;
|
|
192
|
+
const initialSchema = definition?.textSchema || definition?.imageSchema || {};
|
|
193
|
+
this.setState({fullSchema: definition, schema: initialSchema}, () => {
|
|
180
194
|
// Use this.props (latest) in callback to avoid race: templateDetails may have arrived by now
|
|
181
195
|
const latestSelectedAccount = this.getSelectedWeChatAccountFromProps(this.props);
|
|
182
196
|
this.handleEditSchemaOnPropsChange(this.props, latestSelectedAccount);
|
|
@@ -240,7 +254,10 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
240
254
|
newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action2`] = get(templateCta, 'ctaTemplateDetails[1].buttonText');
|
|
241
255
|
}
|
|
242
256
|
}
|
|
243
|
-
|
|
257
|
+
const newAccount = newFormData["mobilepush-accounts"];
|
|
258
|
+
const currentAccount = this.state.formData["mobilepush-accounts"];
|
|
259
|
+
const isExplicitAccountChange = newAccount !== undefined && newAccount !== currentAccount;
|
|
260
|
+
if (isExplicitAccountChange) {
|
|
244
261
|
this.setMobilePushAccountOptions(this.props.Edit.weCrmAccounts, newFormData["mobilepush-accounts"]);
|
|
245
262
|
delete newFormData['mobilepush-template'];
|
|
246
263
|
delete newFormData['template-name'];
|
|
@@ -250,6 +267,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
250
267
|
if (!_.isEmpty(newFormData[1])) {
|
|
251
268
|
delete newFormData[1];
|
|
252
269
|
}
|
|
270
|
+
} else if (newAccount === undefined && currentAccount !== undefined) {
|
|
271
|
+
newFormData["mobilepush-accounts"] = currentAccount;
|
|
253
272
|
}
|
|
254
273
|
if (this.state.isSchemaChanged) {
|
|
255
274
|
this.setState({isSchemaChanged: false});
|
|
@@ -281,7 +300,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
281
300
|
if (isEmbeddedEditOrPreview(queryType, mode)) {
|
|
282
301
|
selectedWeChatAccount = !_.isEmpty(editSelectedWeChatAccount)
|
|
283
302
|
? editSelectedWeChatAccount
|
|
284
|
-
: templateSelectedWeChatAccount;
|
|
303
|
+
: (templateSelectedWeChatAccount || {});
|
|
285
304
|
} else if (!_.isEmpty(templateSelectedWeChatAccount)) {
|
|
286
305
|
selectedWeChatAccount = templateSelectedWeChatAccount;
|
|
287
306
|
}
|
|
@@ -295,8 +314,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
295
314
|
const inputFields = get(schema, `containers[0].panes[${tabIndex - 1}].sections[0].childSections[0].childSections[0].inputFields`);
|
|
296
315
|
const id = field.id;
|
|
297
316
|
const fieldIndex = findIndex(inputFields, {identifier: id});
|
|
298
|
-
const ck = selectedWeChatAccount
|
|
299
|
-
const deepLinkOptions = _.map(
|
|
317
|
+
const ck = selectedWeChatAccount?.configs ? !!selectedWeChatAccount.configs.deeplink : false;
|
|
318
|
+
const deepLinkOptions = _.map(safeParseDeeplinkConfig(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (link) => ({label: link.name, value: link.link, title: link.link }) );
|
|
300
319
|
// let inputId = deeplinkValue && deeplinkValue.toLowerCase() === "deeplink" ? `${id}-select` : `${id}-text`;
|
|
301
320
|
// if (field.id === "cta-deeplink-secondary-cta-1" && (tabIndex > 1 || this.state.currentTab > 1)) {
|
|
302
321
|
// inputId = `${inputId}${tabIndex || this.state.currentTab}`;
|
|
@@ -667,8 +686,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
667
686
|
|
|
668
687
|
getLinkName = (link) => {
|
|
669
688
|
const selectedWeChatAccount = this.getWeChatAccount();
|
|
670
|
-
const ck = selectedWeChatAccount
|
|
671
|
-
const deepLinkOptions = _.filter(
|
|
689
|
+
const ck = selectedWeChatAccount?.configs ? !!selectedWeChatAccount.configs.deeplink : false;
|
|
690
|
+
const deepLinkOptions = _.filter(safeParseDeeplinkConfig(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (l) => l.link === link);
|
|
672
691
|
if (deepLinkOptions[0]) {
|
|
673
692
|
return deepLinkOptions[0].name;
|
|
674
693
|
}
|
|
@@ -766,6 +785,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
766
785
|
|
|
767
786
|
|
|
768
787
|
setEditState(data, schema) {
|
|
788
|
+
if (!data?.versions?.base || typeof data.versions.base !== 'object') return;
|
|
769
789
|
const tabCount = Object.keys(data.versions.base).length;
|
|
770
790
|
const formData = {};
|
|
771
791
|
if (this.props.location.query.type === 'embedded' && this.props.location.query.module === "loyalty") {
|
|
@@ -1114,8 +1134,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1114
1134
|
const currentTab = tab || this.state.currentTab;
|
|
1115
1135
|
const schema = inputSchema ? _.cloneDeep(inputSchema) : _.cloneDeep(this.state.schema);
|
|
1116
1136
|
const selectedWeChatAccount = this.getWeChatAccount();
|
|
1117
|
-
const ck = selectedWeChatAccount
|
|
1118
|
-
const deepLinkOptions = _.map(
|
|
1137
|
+
const ck = selectedWeChatAccount?.configs ? !!selectedWeChatAccount.configs.deeplink : false;
|
|
1138
|
+
const deepLinkOptions = _.map(safeParseDeeplinkConfig(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (link) => ({label: link.name, value: link.link, title: link.link }) );
|
|
1119
1139
|
|
|
1120
1140
|
const inputFields = get(schema, `containers[0].panes[${currentTab - 1}].sections[0].childSections[0].childSections[0].inputFields`);
|
|
1121
1141
|
forEach(inputFields, (inputField, fieldIndex) => {
|
|
@@ -1266,8 +1286,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1266
1286
|
delete formData[self.state.currentTab - 1][`${id.replace('-delete', '')}`];
|
|
1267
1287
|
}
|
|
1268
1288
|
if (child.inputFields[fieldIndex] && child.inputFields[fieldIndex].id === "cta-deeplink-select-section") {
|
|
1269
|
-
const ck = selectedWeChatAccount
|
|
1270
|
-
const configkeys = selectedWeChatAccount ? _.filter(
|
|
1289
|
+
const ck = selectedWeChatAccount?.configs ? !!selectedWeChatAccount.configs.deeplink : false;
|
|
1290
|
+
const configkeys = selectedWeChatAccount ? _.filter(safeParseDeeplinkConfig(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (dl) => dl.link === selectedDeeplink) : [];
|
|
1271
1291
|
if (configkeys.length) {
|
|
1272
1292
|
const options = configkeys[0].keys;
|
|
1273
1293
|
_.forEach(options, (opt) => {
|
|
@@ -1378,8 +1398,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1378
1398
|
delete formData[self.state.currentTab - 1][`cta-deeplink-${id.replace('delete', 'text')}`];
|
|
1379
1399
|
}
|
|
1380
1400
|
if (child.inputFields[fieldIndex] && child.inputFields[fieldIndex].id === "cta-deeplink-select-section") {
|
|
1381
|
-
const ck = selectedWeChatAccount
|
|
1382
|
-
const configkeys = selectedWeChatAccount ? _.filter(
|
|
1401
|
+
const ck = selectedWeChatAccount?.configs ? !!selectedWeChatAccount.configs.deeplink : false;
|
|
1402
|
+
const configkeys = selectedWeChatAccount ? _.filter(safeParseDeeplinkConfig(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (dl) => dl.link === selectedDeeplink) : [];
|
|
1383
1403
|
|
|
1384
1404
|
if (configkeys.length) {
|
|
1385
1405
|
const options = configkeys[0].keys;
|
|
@@ -1732,8 +1752,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1732
1752
|
const {id} = field;
|
|
1733
1753
|
const fieldIndex = findIndex(inputFields, {identifier: id});
|
|
1734
1754
|
const formDataKey = id.replace("-show-keys", "");
|
|
1735
|
-
const ck = selectedWeChatAccount
|
|
1736
|
-
let keys = selectedWeChatAccount ? _.filter(
|
|
1755
|
+
const ck = selectedWeChatAccount?.configs ? !!selectedWeChatAccount.configs.deeplink : false;
|
|
1756
|
+
let keys = selectedWeChatAccount ? _.filter(safeParseDeeplinkConfig(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (dl) => dl.link === formData[currentTab - 1][formDataKey]) : [];
|
|
1737
1757
|
if (keys[0]) {
|
|
1738
1758
|
keys = keys[0].keys;
|
|
1739
1759
|
}
|
|
@@ -1763,7 +1783,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1763
1783
|
inputFields.splice(fieldIndex + index + 1, 0, row);
|
|
1764
1784
|
});
|
|
1765
1785
|
if (!tabIndex) { // removes the existing selected options keys so that newly selected options keys can be added.
|
|
1766
|
-
const configkeys = _.filter(
|
|
1786
|
+
const configkeys = _.filter(safeParseDeeplinkConfig(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (dl) => dl.link === this.state.formData[currentTab - 1][field.id]);
|
|
1767
1787
|
if (configkeys.length) {
|
|
1768
1788
|
const options = configkeys[0].keys;
|
|
1769
1789
|
inputFields = inputFields.slice(0, fieldIndex + 1).concat(inputFields.slice(fieldIndex + options.length + 1, inputFields.length));
|
|
@@ -1782,8 +1802,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1782
1802
|
const selectedWeChatAccount = this.getWeChatAccount();
|
|
1783
1803
|
const id = field.id;
|
|
1784
1804
|
const schema = inputSchema ? _.cloneDeep(inputSchema) : _.cloneDeep(this.state.schema);
|
|
1785
|
-
const ck = selectedWeChatAccount
|
|
1786
|
-
const deepLinkOptions = selectedWeChatAccount ? _.map(
|
|
1805
|
+
const ck = selectedWeChatAccount?.configs ? !!selectedWeChatAccount.configs.deeplink : false;
|
|
1806
|
+
const deepLinkOptions = selectedWeChatAccount ? _.map(safeParseDeeplinkConfig(ck ? selectedWeChatAccount?.configs?.deeplink : '[]'), (link) => ({label: link.name, value: link.link, title: link.link }) ) : [];
|
|
1787
1807
|
// const eventsMap = _.cloneDeep(this.state.eventsMap);
|
|
1788
1808
|
const tabIndex = currentTab || this.state.currentTab;
|
|
1789
1809
|
const inputFields = get(schema, `containers[0].panes[${tabIndex - 1}].sections[0].childSections[0].childSections[0].inputFields`);
|
|
@@ -1813,8 +1833,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1813
1833
|
const formDataCopy = cloneDeep(formData);
|
|
1814
1834
|
const schema = inputSchema ? _.cloneDeep(inputSchema) : _.cloneDeep(this.state.schema);
|
|
1815
1835
|
const selectedWeChatAccount = this.getWeChatAccount();
|
|
1816
|
-
const ck = selectedWeChatAccount
|
|
1817
|
-
const deepLinkOptions = selectedWeChatAccount ? _.map(
|
|
1836
|
+
const ck = selectedWeChatAccount?.configs ? !!selectedWeChatAccount.configs.deeplink : false;
|
|
1837
|
+
const deepLinkOptions = selectedWeChatAccount ? _.map(safeParseDeeplinkConfig(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (link) => ({label: link.name, value: link.link, title: link.link }) ) : [];
|
|
1818
1838
|
const inputFields = get(schema, `containers[0].panes[${tabIndex - 1}].sections[0].childSections[0].childSections[0].inputFields`);
|
|
1819
1839
|
const fieldIndex = findIndex(inputFields, {identifier: id});
|
|
1820
1840
|
let newInputFields;
|
|
@@ -2030,48 +2050,94 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2030
2050
|
}
|
|
2031
2051
|
|
|
2032
2052
|
handleEditSchemaOnPropsChange = (nextProps, selectedWeChatAccount) => {
|
|
2053
|
+
const templateDetails = nextProps.templateDetails || nextProps.templateData;
|
|
2033
2054
|
const queryType = String(get(this.props, 'location.query.type', ''))?.toLowerCase();
|
|
2034
2055
|
const isEmbeddedLibrary = queryType === EMBEDDED && !nextProps.isFullMode;
|
|
2035
2056
|
const canSetAccountFromTemplate =
|
|
2036
|
-
!selectedWeChatAccount &&
|
|
2037
|
-
|
|
2057
|
+
(_.isEmpty(selectedWeChatAccount) || !selectedWeChatAccount?.configs) &&
|
|
2058
|
+
templateDetails?.definition?.accountId &&
|
|
2038
2059
|
nextProps.Edit?.weCrmAccounts?.length > 0;
|
|
2060
|
+
const hasAccountOrEmbedded =
|
|
2061
|
+
!_.isEmpty(selectedWeChatAccount) ||
|
|
2062
|
+
isEmbeddedLibrary ||
|
|
2063
|
+
canSetAccountFromTemplate ||
|
|
2064
|
+
!nextProps.isFullMode ||
|
|
2065
|
+
queryType === EMBEDDED;
|
|
2066
|
+
const hasTemplateDetails = !_.isEmpty(templateDetails);
|
|
2067
|
+
const hasEditData = !_.isEmpty(this.state.editData);
|
|
2068
|
+
const hasFullSchema = !_.isEmpty(this.state.fullSchema);
|
|
2069
|
+
const locationCheck = (this.props.location.query.type !== 'embedded' || this.props.isFullMode === false || queryType === EMBEDDED);
|
|
2039
2070
|
const canPopulateForm =
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2071
|
+
hasTemplateDetails &&
|
|
2072
|
+
!hasEditData &&
|
|
2073
|
+
hasFullSchema &&
|
|
2074
|
+
locationCheck &&
|
|
2075
|
+
hasAccountOrEmbedded;
|
|
2045
2076
|
if (canPopulateForm) {
|
|
2046
2077
|
this.props = nextProps;
|
|
2047
2078
|
if (canSetAccountFromTemplate) {
|
|
2048
|
-
this.setMobilePushAccountOptions(nextProps.Edit.weCrmAccounts,
|
|
2079
|
+
this.setMobilePushAccountOptions(nextProps.Edit.weCrmAccounts, templateDetails.definition.accountId);
|
|
2049
2080
|
}
|
|
2050
|
-
const mode =
|
|
2081
|
+
const mode = templateDetails.definition ? templateDetails.definition.mode : templateDetails.mode;
|
|
2051
2082
|
const schema = mode === "text" ? this.state.fullSchema?.textSchema : this.state.fullSchema?.imageSchema;
|
|
2052
|
-
|
|
2053
|
-
const
|
|
2083
|
+
if (!schema) return;
|
|
2084
|
+
const configs = nextProps.Templates?.selectedWeChatAccount?.configs || {};
|
|
2085
|
+
const hasExplicitConfigs = !_.isEmpty(configs) && ('android' in configs || 'ios' in configs);
|
|
2086
|
+
const isAndroidSupported = hasExplicitConfigs ? configs.android === '1' : true;
|
|
2087
|
+
const isIosSupported = hasExplicitConfigs ? configs.ios === '1' : true;
|
|
2054
2088
|
if (!isAndroidSupported) {
|
|
2055
2089
|
const androidField = get(schema, "containers[0].panes[0]");
|
|
2056
|
-
androidField
|
|
2057
|
-
|
|
2058
|
-
|
|
2090
|
+
if (androidField) {
|
|
2091
|
+
androidField.isSupported = false;
|
|
2092
|
+
this.setState({currentTab: 2});
|
|
2093
|
+
set(schema, "containers[0].panes[0]", androidField);
|
|
2094
|
+
}
|
|
2059
2095
|
}
|
|
2060
2096
|
if (!isIosSupported) {
|
|
2061
2097
|
const iosField = get(schema, "containers[0].panes[1]");
|
|
2062
|
-
iosField
|
|
2063
|
-
|
|
2064
|
-
|
|
2098
|
+
if (iosField) {
|
|
2099
|
+
iosField.isSupported = false;
|
|
2100
|
+
set(schema, "containers[0].panes[1]", iosField);
|
|
2101
|
+
}
|
|
2065
2102
|
}
|
|
2066
|
-
this.
|
|
2067
|
-
|
|
2103
|
+
const dataToUse = this.normalizeTemplateDataForEdit(templateDetails);
|
|
2104
|
+
if (dataToUse?.versions?.base) {
|
|
2105
|
+
this.setEditState(dataToUse, schema);
|
|
2106
|
+
this.getTags();
|
|
2107
|
+
} else {
|
|
2108
|
+
console.warn('[MobliPushEdit] Skipped setEditState - dataToUse.versions.base missing', { dataToUse });
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
};
|
|
2112
|
+
|
|
2113
|
+
normalizeTemplateDataForEdit = (data) => {
|
|
2114
|
+
if (!data) return null;
|
|
2115
|
+
if (data.versions?.base) return data;
|
|
2116
|
+
if (data.content?.versions?.base) {
|
|
2117
|
+
return { ...data, versions: data.content.versions };
|
|
2068
2118
|
}
|
|
2119
|
+
const baseContent = data.content || {};
|
|
2120
|
+
if (baseContent.ANDROID || baseContent.IOS) {
|
|
2121
|
+
return {
|
|
2122
|
+
...data,
|
|
2123
|
+
versions: { base: baseContent },
|
|
2124
|
+
name: data.name || data.templateName || '',
|
|
2125
|
+
definition: data.definition || {},
|
|
2126
|
+
mode: data.mode || data.definition?.mode || 'text',
|
|
2127
|
+
};
|
|
2128
|
+
}
|
|
2129
|
+
return data;
|
|
2069
2130
|
}
|
|
2070
2131
|
|
|
2071
2132
|
render() {
|
|
2133
|
+
const queryType = String(get(this.props, 'location.query.type', ''))?.toLowerCase();
|
|
2134
|
+
const isEmbeddedOrLibrary = queryType === 'embedded' || this.props.isFullMode === false;
|
|
2135
|
+
const hasFormContent = !_.isEmpty(this.state.formData) && !_.isEmpty(this.state.schema);
|
|
2136
|
+
const showFormBuilder = !this.props.isLoadingMetaEntities || hasFormContent;
|
|
2072
2137
|
const schema = this.state.schema;
|
|
2073
2138
|
const loadingContentEdit = this.state.loadingContentEdit || (this.props.location.query.module === 'dvs' && _.isEmpty(this.state.schema));
|
|
2074
|
-
const
|
|
2139
|
+
const metaEntitiesBlockSpinner = hasFormContent;
|
|
2140
|
+
const spinning = get(this.props, "Edit.fetchingWeCrmAccounts") || (!metaEntitiesBlockSpinner && this.props.isLoadingMetaEntities) || loadingContentEdit || this.props.Edit.fetchingDefaultTemplates || this.props.Edit.assetUploading || this.state.loading || (this.props.Edit && (("getTemplateDetailsInProgress" in this.props.Edit && this.props.Edit.getTemplateDetailsInProgress) || ("editTemplateInProgress" in this.props.Edit && this.props.Edit.editTemplateInProgress)));
|
|
2075
2141
|
let tags = this.props.metaEntities && this.props.metaEntities.tags ? this.props.metaEntities.tags.standard : [];
|
|
2076
2142
|
if (this.props.supportedTags) {
|
|
2077
2143
|
tags = this.props.supportedTags;
|
|
@@ -2081,7 +2147,11 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2081
2147
|
<CapSpin spinning={spinning}>
|
|
2082
2148
|
<CapRow>
|
|
2083
2149
|
<CapColumn>
|
|
2084
|
-
{
|
|
2150
|
+
{(() => {
|
|
2151
|
+
if (isEmbeddedOrLibrary && !showFormBuilder && hasFormContent) {
|
|
2152
|
+
console.warn('[MobliPushEdit] FormBuilder HIDDEN (isLoadingMetaEntities=true) but formData+schema exist');
|
|
2153
|
+
}
|
|
2154
|
+
return showFormBuilder && <FormBuilder
|
|
2085
2155
|
channel={MOBILE_PUSH}
|
|
2086
2156
|
schema={schema}
|
|
2087
2157
|
showLiquidErrorInFooter={this.props.showLiquidErrorInFooter}
|
|
@@ -2116,7 +2186,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2116
2186
|
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
2117
2187
|
isFullMode={this.props.isFullMode}
|
|
2118
2188
|
eventContextTags={this.props?.eventContextTags}
|
|
2119
|
-
|
|
2189
|
+
/>;
|
|
2190
|
+
})()}
|
|
2120
2191
|
</CapColumn>
|
|
2121
2192
|
{this.props.iosCtasData && this.state.showIosCtaTable &&
|
|
2122
2193
|
<CapSlideBox
|
|
@@ -2055,11 +2055,11 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
|
|
|
2055
2055
|
const buttonArray = firstCarouselButtonData.map((button) => {
|
|
2056
2056
|
switch (button?.buttonType) {
|
|
2057
2057
|
case PHONE_NUMBER:
|
|
2058
|
-
return INITIAL_CAROUSEL_PHONE_NUMBER_DATA;
|
|
2058
|
+
return cloneDeep(INITIAL_CAROUSEL_PHONE_NUMBER_DATA);
|
|
2059
2059
|
case QUICK_REPLY:
|
|
2060
|
-
return INITIAL_CAROUSEL_QUICK_REPLY_DATA;
|
|
2060
|
+
return cloneDeep(INITIAL_CAROUSEL_QUICK_REPLY_DATA);
|
|
2061
2061
|
default:
|
|
2062
|
-
return INITIAL_CAROUSEL_URL_DATA;
|
|
2062
|
+
return cloneDeep(INITIAL_CAROUSEL_URL_DATA);
|
|
2063
2063
|
}
|
|
2064
2064
|
});
|
|
2065
2065
|
const newCard = cloneDeep(CAROUSEL_INITIAL_DATA[0]);
|