@capillarytech/creatives-library 6.8.4 → 6.8.6
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/app.js +1 -0
- package/config/app.js +1 -1
- package/package.json +1 -1
- package/utils/tagValidations.js +137 -0
- package/v2Components/TemplatePreview/assets/images/WECHAT_5x.png +0 -0
- package/v2Containers/Line/Container/ImageMap/index.js +4 -1
- package/v2Containers/Line/Container/Text/index.js +19 -4
- package/v2Containers/Line/Container/Text/messages.js +4 -0
package/app.js
CHANGED
package/config/app.js
CHANGED
|
@@ -14,7 +14,7 @@ const config = {
|
|
|
14
14
|
accountConfig: (strs, accountId) => `${window.location.origin}/org/config/AccountAdd?q=a&channelId=2&accountId=${accountId}&edit=1`,
|
|
15
15
|
},
|
|
16
16
|
development: {
|
|
17
|
-
api_endpoint: '
|
|
17
|
+
api_endpoint: 'http://localhost:2022/arya/api/v1/creatives',
|
|
18
18
|
campaigns_api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/campaigns',
|
|
19
19
|
auth_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/auth',
|
|
20
20
|
arya_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1',
|
package/package.json
CHANGED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is to maintain the tag validations
|
|
3
|
+
* across the forms used in creatives, very
|
|
4
|
+
* similar to the FormBuilder component.
|
|
5
|
+
* The motive is to chizzling out the dependency from
|
|
6
|
+
* FormBuilder component into meaningful blocks
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import lodashForEach from 'lodash/forEach';
|
|
10
|
+
import lodashCloneDeep from 'lodash/cloneDeep';
|
|
11
|
+
|
|
12
|
+
const DEFAULT = 'default';
|
|
13
|
+
const SUBTAGS = 'subtags';
|
|
14
|
+
|
|
15
|
+
export const validateTags = ({
|
|
16
|
+
content,
|
|
17
|
+
tagsParam,
|
|
18
|
+
injectedTagsParams,
|
|
19
|
+
location,
|
|
20
|
+
tagModule,
|
|
21
|
+
}) => {
|
|
22
|
+
const tags = tagsParam;
|
|
23
|
+
const injectedTags = transformInjectedTags(injectedTagsParams);
|
|
24
|
+
let currentModule = location.query.module ? location.query.module : DEFAULT;
|
|
25
|
+
if (tagModule) {
|
|
26
|
+
currentModule = tagModule;
|
|
27
|
+
}
|
|
28
|
+
const response = {
|
|
29
|
+
valid: true,
|
|
30
|
+
missingTags: [],
|
|
31
|
+
unsupportedTags: [],
|
|
32
|
+
};
|
|
33
|
+
if(tags && tags.length) {
|
|
34
|
+
lodashForEach(tags, ({
|
|
35
|
+
definition: {
|
|
36
|
+
supportedModules,
|
|
37
|
+
value,
|
|
38
|
+
},
|
|
39
|
+
}) => {
|
|
40
|
+
lodashForEach(supportedModules, (module) => {
|
|
41
|
+
if (module.mandatory && (currentModule === module.context)) {
|
|
42
|
+
if (content.indexOf(`{{${value}}}`) === -1) {
|
|
43
|
+
response.valid = false;
|
|
44
|
+
response.missingTags.push(value);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
const regex = /{{[(A-Z\w+(\s\w+)*$\(\)@!#$%^&*~.,/\\]+}}/g;
|
|
50
|
+
let match = regex.exec(content);
|
|
51
|
+
while (match !== null) {
|
|
52
|
+
const tagValue = match[0].substring(indexOfEnd(match[0], '{{'), match[0].indexOf('}}'));
|
|
53
|
+
match = regex.exec(content);
|
|
54
|
+
let ifSupported = false;
|
|
55
|
+
lodashForEach(tags, (tag) => {
|
|
56
|
+
if (tag.definition.value === tagValue) {
|
|
57
|
+
ifSupported = true;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const ifSkipped = skipTags(tagValue);
|
|
61
|
+
if (ifSkipped) {
|
|
62
|
+
ifSupported = true;
|
|
63
|
+
let isUnsubscribeSkipped = tagValue.indexOf("unsubscribe") != -1 ;
|
|
64
|
+
if (isUnsubscribeSkipped) {
|
|
65
|
+
const missingTagIndex = response.missingTags.indexOf("unsubscribe");
|
|
66
|
+
if(missingTagIndex != -1) { //skip regex tags for mandatory tags also
|
|
67
|
+
response.missingTags.splice(missingTagIndex, 1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
ifSupported = ifSupported || checkIfSupportedTag(tagValue, injectedTags);
|
|
72
|
+
if (!ifSupported) {
|
|
73
|
+
response.unsupportedTags.push(tagValue);
|
|
74
|
+
response.valid = false;
|
|
75
|
+
}
|
|
76
|
+
if (response.unsupportedTags.length == 0 && response.missingTags.length == 0 ) {
|
|
77
|
+
response.valid = true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return response;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const checkIfSupportedTag = (checkingTag, injectedTags) => {
|
|
85
|
+
let result = false;
|
|
86
|
+
lodashForEach(injectedTags, (tag, key) => {
|
|
87
|
+
if (tag.subtags && checkIfSupportedTag(checkingTag, tag.subtags)) {
|
|
88
|
+
result = true;
|
|
89
|
+
} else if (checkingTag === key) {
|
|
90
|
+
result = true;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const indexOfEnd = (targetString, string) => {
|
|
98
|
+
let io = targetString.indexOf(string);
|
|
99
|
+
return io == -1 ? -1 : io + string.length;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const skipTags = (tag) => {
|
|
103
|
+
const regexGroups = ["dynamic_expiry_date_after_\\d+_days.FORMAT_\\d", "unsubscribe\\(#[a-zA-Z\\d]{6}\\)","Link_to_[a-zA-z]","SURVEY.*.TOKEN","^[A-Za-z].*\\([\\d]*\\)"];
|
|
104
|
+
let skipped = false;
|
|
105
|
+
lodashForEach(regexGroups, (group) => {
|
|
106
|
+
const groupRegex = new RegExp(group, "g");
|
|
107
|
+
let match = groupRegex.exec(tag);
|
|
108
|
+
if (match !== null ) {
|
|
109
|
+
skipped = true;
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
});
|
|
114
|
+
return skipped;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const transformInjectedTags = (tags) => {
|
|
118
|
+
lodashForEach(tags, (tag) => {
|
|
119
|
+
const temp = tag;
|
|
120
|
+
let subKey = '';
|
|
121
|
+
Object.keys(tag).map( (k) => {
|
|
122
|
+
if (k.indexOf(SUBTAGS) !== -1) {
|
|
123
|
+
subKey = k;
|
|
124
|
+
}
|
|
125
|
+
return true;
|
|
126
|
+
});
|
|
127
|
+
if (subKey !== '') {
|
|
128
|
+
temp['tag-header'] = true;
|
|
129
|
+
if (subKey !== SUBTAGS) {
|
|
130
|
+
temp.subtags =lodashCloneDeep(temp[subKey]);
|
|
131
|
+
delete temp[subKey];
|
|
132
|
+
}
|
|
133
|
+
temp.subtags = transformInjectedTags(temp.subtags);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return tags;
|
|
137
|
+
}
|
|
Binary file
|
|
@@ -166,6 +166,9 @@ export const LineImageMap = ({
|
|
|
166
166
|
const validWidth = width === LINE_ASSET_WIDTH;
|
|
167
167
|
const isCustom = assetType === CUSTOM_ASSET_TYPE;
|
|
168
168
|
const validHeight = isCustom ? ( LINE_CUSTOM_ASSET_HEIGHT_MIN <= height && height <= LINE_CUSTOM_ASSET_HEIGHT_MAX) : height === LINE_ASSET_HEIGHT;
|
|
169
|
+
if (isCustom) {
|
|
170
|
+
data.fileParams.assetType = CUSTOM_ASSET_TYPE;
|
|
171
|
+
}
|
|
169
172
|
if (incorrectFile || !validWidth || !validHeight) {
|
|
170
173
|
updateImageErrorMessage(formatMessage(messages.lineImageMapIncorrectSize));
|
|
171
174
|
} else {
|
|
@@ -177,7 +180,7 @@ export const LineImageMap = ({
|
|
|
177
180
|
});
|
|
178
181
|
actions.uploadAsset(
|
|
179
182
|
data.file,
|
|
180
|
-
|
|
183
|
+
data.type,
|
|
181
184
|
data.fileParams,
|
|
182
185
|
);
|
|
183
186
|
}
|
|
@@ -15,6 +15,8 @@ import messages from './messages';
|
|
|
15
15
|
import style from './style';
|
|
16
16
|
import withStyles from '../../../../hoc/withStyles';
|
|
17
17
|
|
|
18
|
+
import { validateTags } from '../../../../utils/tagValidations';
|
|
19
|
+
|
|
18
20
|
const { TextArea } = CapInput;
|
|
19
21
|
const {CapCustomCardList} = CapCustomCard;
|
|
20
22
|
|
|
@@ -71,7 +73,7 @@ export const LineText = ({
|
|
|
71
73
|
useEffect(() => {
|
|
72
74
|
if (messageContent && (isFullMode ? messageTitle : true)) {
|
|
73
75
|
updateMessageState({
|
|
74
|
-
isError: (messageContent.length > charLimit) || (!messageContent || !(isFullMode ? messageTitle : true) || (errorMessageTextarea
|
|
76
|
+
isError: (messageContent.length > charLimit) || (!messageContent || !(isFullMode ? messageTitle : true) || (errorMessageTextarea || errorMessageTitle)),
|
|
75
77
|
messageContent,
|
|
76
78
|
messageTitle,
|
|
77
79
|
index,
|
|
@@ -116,10 +118,19 @@ export const LineText = ({
|
|
|
116
118
|
|
|
117
119
|
const updateTextContentError = (value) => {
|
|
118
120
|
let errorMessage = false;
|
|
121
|
+
const { valid } = validateTags({
|
|
122
|
+
content: value,
|
|
123
|
+
tagsParam: tags,
|
|
124
|
+
injectedTagsParams: injectedTags,
|
|
125
|
+
location,
|
|
126
|
+
tagModule: 'outbound',
|
|
127
|
+
}) || {};
|
|
119
128
|
if (value === '') {
|
|
120
129
|
errorMessage = formatMessage(messages.emptyTitleErrorMessage);
|
|
121
130
|
} else if (value.length > charLimit) {
|
|
122
131
|
errorMessage = formatMessage(messages.limitExceededContentErrorMessage);
|
|
132
|
+
} else if (!valid && !isFullMode) {
|
|
133
|
+
errorMessage = formatMessage(messages.invalidTagError);
|
|
123
134
|
}
|
|
124
135
|
updateErrorMessageTextArea(errorMessage);
|
|
125
136
|
}
|
|
@@ -128,7 +139,7 @@ export const LineText = ({
|
|
|
128
139
|
updateTextMessageContent(value);
|
|
129
140
|
updateTextContentError(value);
|
|
130
141
|
updateMessageState({
|
|
131
|
-
isError: (value.length > charLimit) || (!value || !(isFullMode ? messageTitle : true) || (!value
|
|
142
|
+
isError: (value.length > charLimit) || (!value || !(isFullMode ? messageTitle : true) || (!value || errorMessageTitle)),
|
|
132
143
|
messageContent: value,
|
|
133
144
|
messageTitle,
|
|
134
145
|
index,
|
|
@@ -149,7 +160,7 @@ export const LineText = ({
|
|
|
149
160
|
updateTextMessageTitle(value);
|
|
150
161
|
updateTextTitleError(value);
|
|
151
162
|
updateMessageState({
|
|
152
|
-
isError: (messageContent.length > charLimit) || (!messageContent || !(isFullMode ? value : true) || (!value
|
|
163
|
+
isError: (messageContent.length > charLimit) || (!messageContent || !(isFullMode ? value : true) || (!value || errorMessageTextarea)),
|
|
153
164
|
messageContent,
|
|
154
165
|
messageTitle: value,
|
|
155
166
|
index,
|
|
@@ -158,7 +169,11 @@ export const LineText = ({
|
|
|
158
169
|
});
|
|
159
170
|
}
|
|
160
171
|
|
|
161
|
-
const onTagSelect = (data) =>
|
|
172
|
+
const onTagSelect = (data) => {
|
|
173
|
+
const messageData = `${messageContent}{{${data}}}`;
|
|
174
|
+
updateTextMessageContent(messageData);
|
|
175
|
+
updateTextContentError(messageData);
|
|
176
|
+
}
|
|
162
177
|
|
|
163
178
|
const setNewContent = () => updateCreateNew(true);
|
|
164
179
|
|