@capillarytech/creatives-library 8.0.246-alpha.0 → 8.0.246
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/assets/Android.png +0 -0
- package/assets/iOS.png +0 -0
- package/constants/unified.js +1 -2
- package/initialReducer.js +0 -2
- package/package.json +1 -1
- package/services/api.js +0 -10
- package/services/tests/api.test.js +0 -18
- package/utils/common.js +0 -5
- package/utils/commonUtils.js +5 -28
- package/utils/tests/commonUtil.test.js +0 -224
- package/utils/transformTemplateConfig.js +10 -0
- package/v2Components/CapDeviceContent/index.js +56 -61
- package/v2Components/CapTagList/index.js +1 -6
- package/v2Components/CapTagListWithInput/index.js +1 -5
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +0 -5
- package/v2Components/ErrorInfoNote/index.js +72 -447
- package/v2Components/ErrorInfoNote/messages.js +0 -22
- package/v2Components/ErrorInfoNote/style.scss +4 -280
- package/v2Components/FormBuilder/tests/index.test.js +4 -13
- package/v2Components/HtmlEditor/HTMLEditor.js +94 -642
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +133 -1135
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +16 -27
- package/v2Components/HtmlEditor/_htmlEditor.scss +45 -108
- package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +101 -13
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +139 -148
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +1 -2
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +0 -9
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +0 -22
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +7 -4
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +45 -35
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +3 -1
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +6 -7
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +6 -3
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +13 -11
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +152 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +31 -49
- package/v2Components/HtmlEditor/constants.js +20 -29
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +16 -373
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +2 -5
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +146 -88
- package/v2Components/HtmlEditor/hooks/useValidation.js +45 -150
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +85 -95
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +102 -134
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +25 -23
- package/v2Components/HtmlEditor/utils/validationAdapter.js +41 -66
- package/v2Components/MobilePushPreviewV2/index.js +7 -32
- package/v2Components/TemplatePreview/_templatePreview.scss +24 -44
- package/v2Components/TemplatePreview/index.js +32 -47
- package/v2Components/TemplatePreview/messages.js +0 -4
- package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +0 -1
- package/v2Components/TestAndPreviewSlidebox/index.js +25 -31
- package/v2Containers/BeeEditor/index.js +90 -172
- package/v2Containers/CreativesContainer/SlideBoxContent.js +51 -128
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +12 -113
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +1 -2
- package/v2Containers/CreativesContainer/constants.js +0 -1
- package/v2Containers/CreativesContainer/index.js +46 -238
- package/v2Containers/CreativesContainer/messages.js +0 -8
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +2 -11
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +50 -38
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +0 -91
- package/v2Containers/Email/actions.js +0 -7
- package/v2Containers/Email/constants.js +1 -5
- package/v2Containers/Email/index.js +30 -229
- package/v2Containers/Email/messages.js +0 -32
- package/v2Containers/Email/reducer.js +1 -12
- package/v2Containers/Email/sagas.js +7 -61
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +0 -2
- package/v2Containers/Email/tests/sagas.test.js +1 -1
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +15 -210
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +74 -40
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +67 -2
- package/v2Containers/EmailWrapper/constants.js +0 -2
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +77 -629
- package/v2Containers/EmailWrapper/index.js +23 -103
- package/v2Containers/EmailWrapper/messages.js +1 -61
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +214 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +77 -509
- package/v2Containers/InApp/actions.js +0 -7
- package/v2Containers/InApp/constants.js +4 -20
- package/v2Containers/InApp/index.js +357 -801
- package/v2Containers/InApp/index.scss +3 -4
- package/v2Containers/InApp/messages.js +3 -7
- package/v2Containers/InApp/reducer.js +3 -21
- package/v2Containers/InApp/sagas.js +9 -29
- package/v2Containers/InApp/selectors.js +5 -25
- package/v2Containers/InApp/tests/index.test.js +50 -154
- package/v2Containers/InApp/tests/reducer.test.js +0 -34
- package/v2Containers/InApp/tests/sagas.test.js +9 -61
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +0 -3
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +0 -2
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +0 -2
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +0 -9
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +0 -12
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +0 -4
- package/v2Containers/TagList/index.js +19 -62
- package/v2Containers/Templates/_templates.scss +1 -60
- package/v2Containers/Templates/index.js +4 -89
- package/v2Containers/Templates/messages.js +0 -4
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +0 -35
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +0 -874
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +0 -254
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +0 -363
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +0 -51
- package/v2Components/HtmlEditor/hooks/__tests__/useValidation.apiErrors.test.js +0 -630
- package/v2Containers/BeePopupEditor/constants.js +0 -10
- package/v2Containers/BeePopupEditor/index.js +0 -193
- package/v2Containers/BeePopupEditor/tests/index.test.js +0 -627
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +0 -1317
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +0 -1605
- package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +0 -520
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +0 -643
- package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +0 -376
- package/v2Containers/InApp/__tests__/sagas.test.js +0 -363
- package/v2Containers/InApp/tests/selectors.test.js +0 -612
- package/v2Containers/InAppWrapper/components/InAppWrapperView.js +0 -162
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +0 -267
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +0 -9
- package/v2Containers/InAppWrapper/constants.js +0 -16
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +0 -473
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +0 -198
- package/v2Containers/InAppWrapper/index.js +0 -148
- package/v2Containers/InAppWrapper/messages.js +0 -49
- package/v2Containers/InappAdvance/index.js +0 -1099
- package/v2Containers/InappAdvance/index.scss +0 -10
- package/v2Containers/InappAdvance/tests/index.test.js +0 -448
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ValidationTabs Styles
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
@import '~@capillarytech/cap-ui-library/styles/_variables.scss';
|
|
6
|
-
|
|
7
|
-
.validation-tabs {
|
|
8
|
-
overflow-y: hidden;
|
|
9
|
-
width: 100%;
|
|
10
|
-
background-color: $CAP_COLOR_05; // Light pink background
|
|
11
|
-
border-radius: 0.25rem;
|
|
12
|
-
padding: 1rem 1rem;
|
|
13
|
-
box-sizing: border-box;
|
|
14
|
-
|
|
15
|
-
&__header {
|
|
16
|
-
display: flex;
|
|
17
|
-
align-items: flex-start;
|
|
18
|
-
justify-content: space-between;
|
|
19
|
-
width: 100%;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
&__tabs {
|
|
23
|
-
flex: 1;
|
|
24
|
-
|
|
25
|
-
// Override CapTab styles for proper spacing
|
|
26
|
-
.cap-tab-v2 {
|
|
27
|
-
.ant-tabs-nav {
|
|
28
|
-
margin-bottom: 0;
|
|
29
|
-
|
|
30
|
-
&::before {
|
|
31
|
-
border-bottom: none;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
.ant-tabs-tab {
|
|
36
|
-
padding: 0.5rem 0.75rem; // Add horizontal padding for spacing
|
|
37
|
-
margin-right: 0; // Remove margin, use padding instead
|
|
38
|
-
color: $CAP_G03;
|
|
39
|
-
font-size: 0.875rem;
|
|
40
|
-
font-weight: 500;
|
|
41
|
-
|
|
42
|
-
& + .ant-tabs-tab {
|
|
43
|
-
margin-left: 1.5rem; // Add space between tabs
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
&:hover {
|
|
47
|
-
color: $CAP_COLOR_05;
|
|
48
|
-
background: transparent;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
&.ant-tabs-tab-active {
|
|
52
|
-
.ant-tabs-tab-btn {
|
|
53
|
-
color: $CAP_COLOR_05;
|
|
54
|
-
font-weight: 600;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.ant-tabs-ink-bar {
|
|
60
|
-
background-color: $CAP_COLOR_05;
|
|
61
|
-
height: 0.125rem;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.ant-tabs-content-holder {
|
|
65
|
-
padding-top: 0.25rem; // Reduced from 0.5rem
|
|
66
|
-
padding-bottom: 0; // No bottom padding
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
&__tab-label {
|
|
72
|
-
display: flex;
|
|
73
|
-
align-items: center;
|
|
74
|
-
gap: 0.25rem;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
&__tab-count {
|
|
78
|
-
color: inherit;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
&__actions {
|
|
82
|
-
display: flex;
|
|
83
|
-
align-items: center;
|
|
84
|
-
gap: 0.5rem;
|
|
85
|
-
flex-shrink: 0;
|
|
86
|
-
padding-top: 0.5rem;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
&__close {
|
|
90
|
-
display: flex;
|
|
91
|
-
align-items: center;
|
|
92
|
-
justify-content: center;
|
|
93
|
-
width: 1.5rem;
|
|
94
|
-
height: 1.5rem;
|
|
95
|
-
padding: 0;
|
|
96
|
-
background: transparent;
|
|
97
|
-
border: none;
|
|
98
|
-
border-radius: 0.25rem;
|
|
99
|
-
cursor: pointer;
|
|
100
|
-
color: $CAP_G03;
|
|
101
|
-
transition: all 0.2s ease;
|
|
102
|
-
|
|
103
|
-
&:hover {
|
|
104
|
-
background-color: rgba($CAP_COLOR_05, 0.1);
|
|
105
|
-
color: $CAP_COLOR_05;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
.cap-icon-v2 {
|
|
109
|
-
font-size: 0.875rem;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
&__content {
|
|
114
|
-
max-height: 15rem; // Limit height for many errors
|
|
115
|
-
overflow-y: auto;
|
|
116
|
-
padding-right: 0.25rem;
|
|
117
|
-
padding-bottom: 0; // Remove bottom padding completely
|
|
118
|
-
|
|
119
|
-
// Custom scrollbar
|
|
120
|
-
&::-webkit-scrollbar {
|
|
121
|
-
width: 0.375rem;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
&::-webkit-scrollbar-track {
|
|
125
|
-
background: transparent;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
&::-webkit-scrollbar-thumb {
|
|
129
|
-
background-color: $CAP_G06;
|
|
130
|
-
border-radius: 0.1875rem;
|
|
131
|
-
|
|
132
|
-
&:hover {
|
|
133
|
-
background-color: $CAP_G04;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
&__item {
|
|
139
|
-
display: flex;
|
|
140
|
-
align-items: flex-start;
|
|
141
|
-
gap: 0.5rem;
|
|
142
|
-
padding: 0.25rem 0; // Reduced from 0.375rem
|
|
143
|
-
border-bottom: 1px solid rgba($CAP_G06, 0.3);
|
|
144
|
-
|
|
145
|
-
&:last-child {
|
|
146
|
-
border-bottom: none;
|
|
147
|
-
padding-bottom: 0.25rem; // Minimal padding on last item
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
&--error {
|
|
151
|
-
.validation-tabs__icon--error {
|
|
152
|
-
color: $CAP_RED;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
&--warning {
|
|
157
|
-
.validation-tabs__icon--warning {
|
|
158
|
-
color: $CAP_YELLOW;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
&__item-icon {
|
|
164
|
-
flex-shrink: 0;
|
|
165
|
-
display: flex;
|
|
166
|
-
align-items: center;
|
|
167
|
-
padding-top: 0.125rem;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
&__icon {
|
|
171
|
-
font-size: 0.875rem;
|
|
172
|
-
|
|
173
|
-
&--error {
|
|
174
|
-
color: $CAP_RED;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
&--warning {
|
|
178
|
-
color: $CAP_YELLOW;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
&__item-content {
|
|
183
|
-
flex: 1;
|
|
184
|
-
display: flex;
|
|
185
|
-
flex-wrap: wrap;
|
|
186
|
-
align-items: baseline;
|
|
187
|
-
gap: 0.25rem;
|
|
188
|
-
font-size: 0.75rem;
|
|
189
|
-
line-height: 1.4;
|
|
190
|
-
color: $CAP_G01;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
&__item-message {
|
|
194
|
-
color: $CAP_G01;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
&__item-location {
|
|
198
|
-
color: $CAP_G03;
|
|
199
|
-
white-space: nowrap;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
&__item-rule {
|
|
203
|
-
color: $CAP_G04;
|
|
204
|
-
font-family: monospace;
|
|
205
|
-
font-size: 0.6875rem;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
&__item-navigate {
|
|
209
|
-
flex-shrink: 0;
|
|
210
|
-
display: flex;
|
|
211
|
-
align-items: center;
|
|
212
|
-
justify-content: center;
|
|
213
|
-
width: 1.25rem;
|
|
214
|
-
height: 1.25rem;
|
|
215
|
-
padding: 0;
|
|
216
|
-
background: transparent;
|
|
217
|
-
border: none;
|
|
218
|
-
border-radius: 0.25rem;
|
|
219
|
-
cursor: pointer;
|
|
220
|
-
color: $CAP_G04;
|
|
221
|
-
transition: all 0.2s ease;
|
|
222
|
-
|
|
223
|
-
&:hover {
|
|
224
|
-
background-color: rgba($CAP_G01, 0.1);
|
|
225
|
-
color: $CAP_G01;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
.anticon {
|
|
229
|
-
font-size: 0.75rem;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Responsive adjustments
|
|
235
|
-
@media (max-width: 768px) {
|
|
236
|
-
.validation-tabs {
|
|
237
|
-
padding: 0.375rem 0.5rem;
|
|
238
|
-
|
|
239
|
-
&__tabs {
|
|
240
|
-
.ant-tabs-tab {
|
|
241
|
-
margin-right: 1rem;
|
|
242
|
-
font-size: 0.8125rem;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
&__content {
|
|
247
|
-
max-height: 10rem;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
&__item-content {
|
|
251
|
-
font-size: 0.6875rem;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
@@ -1,363 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ValidationTabs Component
|
|
3
|
-
*
|
|
4
|
-
* Displays validation errors in a tabbed interface with 3 categories:
|
|
5
|
-
* - HTML issues: General HTML/CSS validation errors and warnings
|
|
6
|
-
* - Label issues: Tag syntax errors (open/close tags, attributes, brackets)
|
|
7
|
-
* - Liquid issues: Liquid expression errors (only when liquid feature enabled)
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import React, { useState, useMemo } from 'react';
|
|
11
|
-
import PropTypes from 'prop-types';
|
|
12
|
-
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
|
13
|
-
|
|
14
|
-
// Cap UI Library
|
|
15
|
-
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
16
|
-
import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
|
|
17
|
-
import CapTab from '@capillarytech/cap-ui-library/CapTab';
|
|
18
|
-
import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
|
|
19
|
-
|
|
20
|
-
// Messages
|
|
21
|
-
import messages from './messages';
|
|
22
|
-
|
|
23
|
-
// Styles
|
|
24
|
-
import './_validationTabs.scss';
|
|
25
|
-
|
|
26
|
-
// Constants for issue sources
|
|
27
|
-
const ISSUE_SOURCES = {
|
|
28
|
-
HTMLHINT: 'htmlhint',
|
|
29
|
-
CSS_VALIDATOR: 'css-validator',
|
|
30
|
-
CUSTOM: 'custom',
|
|
31
|
-
SECURITY: 'security',
|
|
32
|
-
LIQUID: 'liquid-validator',
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
// Label issue patterns - syntax errors related to tags
|
|
36
|
-
const LABEL_ISSUE_PATTERNS = [
|
|
37
|
-
'tag must be paired',
|
|
38
|
-
'open tag match failed',
|
|
39
|
-
'closed tag match failed',
|
|
40
|
-
'unclosed',
|
|
41
|
-
'missing required',
|
|
42
|
-
'tag-pair',
|
|
43
|
-
'attr-value-not-empty',
|
|
44
|
-
'attr-no-duplication',
|
|
45
|
-
'tag-self-close',
|
|
46
|
-
'spec-char-escape',
|
|
47
|
-
'tagname-lowercase',
|
|
48
|
-
'attr-lowercase',
|
|
49
|
-
'id-unique',
|
|
50
|
-
'src-not-empty',
|
|
51
|
-
'alt-require',
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Categorize issues into HTML, Label, and Liquid categories
|
|
56
|
-
*/
|
|
57
|
-
const categorizeIssues = (allIssues) => {
|
|
58
|
-
const htmlIssues = [];
|
|
59
|
-
const labelIssues = [];
|
|
60
|
-
const liquidIssues = [];
|
|
61
|
-
|
|
62
|
-
allIssues.forEach((issue) => {
|
|
63
|
-
const { source, rule, message } = issue;
|
|
64
|
-
const messageLower = (message || '').toLowerCase();
|
|
65
|
-
const ruleLower = (rule || '').toLowerCase();
|
|
66
|
-
|
|
67
|
-
// Check if it's a Liquid issue - ONLY by source, not by message content
|
|
68
|
-
// This prevents false positives where HTML errors mention liquid syntax
|
|
69
|
-
if (source === ISSUE_SOURCES.LIQUID) {
|
|
70
|
-
liquidIssues.push(issue);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Check if it's a Label (tag syntax) issue
|
|
75
|
-
const isLabelIssue = LABEL_ISSUE_PATTERNS.some(
|
|
76
|
-
(pattern) => messageLower.includes(pattern.toLowerCase())
|
|
77
|
-
|| ruleLower.includes(pattern.toLowerCase()),
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
if (isLabelIssue) {
|
|
81
|
-
labelIssues.push(issue);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Default to HTML issues
|
|
86
|
-
htmlIssues.push(issue);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
return { htmlIssues, labelIssues, liquidIssues };
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Get icon based on severity
|
|
94
|
-
*/
|
|
95
|
-
const getSeverityIcon = (severity) => {
|
|
96
|
-
if (severity === 'warning') {
|
|
97
|
-
return <CapIcon type="alert-warning" className="validation-tabs__icon validation-tabs__icon--warning" />;
|
|
98
|
-
}
|
|
99
|
-
return <CapIcon type="warning-circle" className="validation-tabs__icon validation-tabs__icon--error" />;
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* ValidationTabContent - Renders the content for each tab
|
|
104
|
-
*/
|
|
105
|
-
const ValidationTabContent = ({
|
|
106
|
-
issues,
|
|
107
|
-
onErrorClick,
|
|
108
|
-
}) => {
|
|
109
|
-
if (!issues || issues.length === 0) {
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const handleNavigateClick = (issue, e) => {
|
|
114
|
-
e.stopPropagation();
|
|
115
|
-
if (onErrorClick) {
|
|
116
|
-
// Always call onErrorClick to acknowledge the error (enables buttons)
|
|
117
|
-
// If line number exists, navigate to it; otherwise just acknowledge and focus editor
|
|
118
|
-
onErrorClick({
|
|
119
|
-
line: issue.line || 1, // Default to line 1 if no line number (for API errors)
|
|
120
|
-
column: issue.column || 1,
|
|
121
|
-
message: issue.message,
|
|
122
|
-
severity: issue.severity,
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
return (
|
|
128
|
-
<div className="validation-tabs__content">
|
|
129
|
-
{issues.map((issue, index) => {
|
|
130
|
-
const {
|
|
131
|
-
severity, message, line, column,
|
|
132
|
-
} = issue;
|
|
133
|
-
const key = `${message}-${line}-${column}-${index}`;
|
|
134
|
-
|
|
135
|
-
return (
|
|
136
|
-
<div
|
|
137
|
-
key={key}
|
|
138
|
-
className={`validation-tabs__item validation-tabs__item--${severity || 'error'}`}
|
|
139
|
-
>
|
|
140
|
-
<div className="validation-tabs__item-icon">
|
|
141
|
-
{getSeverityIcon(severity)}
|
|
142
|
-
</div>
|
|
143
|
-
<div className="validation-tabs__item-content">
|
|
144
|
-
<span className="validation-tabs__item-message">
|
|
145
|
-
{message}
|
|
146
|
-
</span>
|
|
147
|
-
{line && (
|
|
148
|
-
<span className="validation-tabs__item-location">
|
|
149
|
-
<FormattedMessage
|
|
150
|
-
{...messages.lineChar}
|
|
151
|
-
values={{ line, char: column || 1 }}
|
|
152
|
-
/>
|
|
153
|
-
</span>
|
|
154
|
-
)}
|
|
155
|
-
</div>
|
|
156
|
-
{/* Always show redirection icon for errors (even API errors without line numbers) */}
|
|
157
|
-
{/* Clicking it acknowledges the error and enables buttons */}
|
|
158
|
-
<CapTooltip title={line ? `Line ${line}, Char ${column || 1}` : 'Click to acknowledge error and focus editor'}>
|
|
159
|
-
<button
|
|
160
|
-
type="button"
|
|
161
|
-
className="validation-tabs__item-navigate"
|
|
162
|
-
onClick={(e) => handleNavigateClick(issue, e)}
|
|
163
|
-
aria-label={line ? `Line ${line}, Char ${column || 1}` : 'Acknowledge error'}
|
|
164
|
-
>
|
|
165
|
-
<CapIcon type="redirection" />
|
|
166
|
-
</button>
|
|
167
|
-
</CapTooltip>
|
|
168
|
-
</div>
|
|
169
|
-
);
|
|
170
|
-
})}
|
|
171
|
-
</div>
|
|
172
|
-
);
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
ValidationTabContent.propTypes = {
|
|
176
|
-
issues: PropTypes.array,
|
|
177
|
-
onErrorClick: PropTypes.func,
|
|
178
|
-
intl: intlShape.isRequired,
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
ValidationTabContent.defaultProps = {
|
|
182
|
-
issues: [],
|
|
183
|
-
onErrorClick: null,
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* ValidationTabs Component
|
|
188
|
-
*/
|
|
189
|
-
const ValidationTabs = ({
|
|
190
|
-
intl,
|
|
191
|
-
validation,
|
|
192
|
-
onErrorClick,
|
|
193
|
-
onClose,
|
|
194
|
-
isLiquidEnabled,
|
|
195
|
-
className,
|
|
196
|
-
}) => {
|
|
197
|
-
const [activeKey, setActiveKey] = useState(null);
|
|
198
|
-
|
|
199
|
-
// Categorize issues
|
|
200
|
-
const { htmlIssues, labelIssues, liquidIssues } = useMemo(() => {
|
|
201
|
-
if (!validation) {
|
|
202
|
-
return { htmlIssues: [], labelIssues: [], liquidIssues: [] };
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Get all issues from validation
|
|
206
|
-
const allIssues = validation.getAllIssues ? validation.getAllIssues() : [];
|
|
207
|
-
const categorized = categorizeIssues(allIssues);
|
|
208
|
-
return categorized;
|
|
209
|
-
}, [validation]);
|
|
210
|
-
|
|
211
|
-
// Calculate counts
|
|
212
|
-
const htmlCount = htmlIssues.length;
|
|
213
|
-
const labelCount = labelIssues.length;
|
|
214
|
-
const liquidCount = liquidIssues.length;
|
|
215
|
-
const totalCount = htmlCount + labelCount + (isLiquidEnabled ? liquidCount : 0);
|
|
216
|
-
|
|
217
|
-
// Set default active key when issues change
|
|
218
|
-
useMemo(() => {
|
|
219
|
-
if (htmlCount > 0 && !activeKey) {
|
|
220
|
-
setActiveKey('html');
|
|
221
|
-
} else if (labelCount > 0 && !activeKey) {
|
|
222
|
-
setActiveKey('label');
|
|
223
|
-
} else if (liquidCount > 0 && isLiquidEnabled && !activeKey) {
|
|
224
|
-
setActiveKey('liquid');
|
|
225
|
-
}
|
|
226
|
-
}, [htmlCount, labelCount, liquidCount, isLiquidEnabled, activeKey]);
|
|
227
|
-
|
|
228
|
-
// Don't render if no issues
|
|
229
|
-
if (totalCount === 0) {
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Build tab panes (CapTab uses 'panes' with 'tab' and 'content' properties)
|
|
234
|
-
const tabPanes = [];
|
|
235
|
-
|
|
236
|
-
if (htmlCount > 0) {
|
|
237
|
-
tabPanes.push({
|
|
238
|
-
key: 'html',
|
|
239
|
-
tab: (
|
|
240
|
-
<CapTooltip title={`${intl.formatMessage(messages.htmlIssues)} (${htmlCount})`}>
|
|
241
|
-
<span className="validation-tabs__tab-label">
|
|
242
|
-
<FormattedMessage {...messages.htmlIssues} />
|
|
243
|
-
<span className="validation-tabs__tab-count">
|
|
244
|
-
(
|
|
245
|
-
{htmlCount}
|
|
246
|
-
)
|
|
247
|
-
</span>
|
|
248
|
-
</span>
|
|
249
|
-
</CapTooltip>
|
|
250
|
-
),
|
|
251
|
-
content: (
|
|
252
|
-
<ValidationTabContent
|
|
253
|
-
issues={htmlIssues}
|
|
254
|
-
onErrorClick={onErrorClick}
|
|
255
|
-
intl={intl}
|
|
256
|
-
/>
|
|
257
|
-
),
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (labelCount > 0) {
|
|
262
|
-
tabPanes.push({
|
|
263
|
-
key: 'label',
|
|
264
|
-
tab: (
|
|
265
|
-
<CapTooltip title={`${intl.formatMessage(messages.labelIssues)} (${labelCount})`}>
|
|
266
|
-
<span className="validation-tabs__tab-label">
|
|
267
|
-
<FormattedMessage {...messages.labelIssues} />
|
|
268
|
-
<span className="validation-tabs__tab-count">
|
|
269
|
-
(
|
|
270
|
-
{labelCount}
|
|
271
|
-
)
|
|
272
|
-
</span>
|
|
273
|
-
</span>
|
|
274
|
-
</CapTooltip>
|
|
275
|
-
),
|
|
276
|
-
content: (
|
|
277
|
-
<ValidationTabContent
|
|
278
|
-
issues={labelIssues}
|
|
279
|
-
onErrorClick={onErrorClick}
|
|
280
|
-
intl={intl}
|
|
281
|
-
/>
|
|
282
|
-
),
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (isLiquidEnabled && liquidCount > 0) {
|
|
287
|
-
tabPanes.push({
|
|
288
|
-
key: 'liquid',
|
|
289
|
-
tab: (
|
|
290
|
-
<CapTooltip title={`${intl.formatMessage(messages.liquidIssues)} (${liquidCount})`}>
|
|
291
|
-
<span className="validation-tabs__tab-label">
|
|
292
|
-
<FormattedMessage {...messages.liquidIssues} />
|
|
293
|
-
<span className="validation-tabs__tab-count">
|
|
294
|
-
(
|
|
295
|
-
{liquidCount}
|
|
296
|
-
)
|
|
297
|
-
</span>
|
|
298
|
-
</span>
|
|
299
|
-
</CapTooltip>
|
|
300
|
-
),
|
|
301
|
-
content: (
|
|
302
|
-
<ValidationTabContent
|
|
303
|
-
issues={liquidIssues}
|
|
304
|
-
onErrorClick={onErrorClick}
|
|
305
|
-
intl={intl}
|
|
306
|
-
/>
|
|
307
|
-
),
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// Handle close
|
|
312
|
-
const handleClose = () => {
|
|
313
|
-
if (onClose) {
|
|
314
|
-
onClose();
|
|
315
|
-
}
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
return (
|
|
319
|
-
<div className={`validation-tabs ${className || ''}`}>
|
|
320
|
-
<CapRow className="validation-tabs__header">
|
|
321
|
-
<CapTab
|
|
322
|
-
activeKey={activeKey || (tabPanes[0]?.key)}
|
|
323
|
-
onChange={setActiveKey}
|
|
324
|
-
panes={tabPanes}
|
|
325
|
-
className="validation-tabs__tabs"
|
|
326
|
-
/>
|
|
327
|
-
<CapRow className="validation-tabs__actions">
|
|
328
|
-
<CapTooltip title={intl.formatMessage(messages.closePanel)}>
|
|
329
|
-
<button
|
|
330
|
-
type="button"
|
|
331
|
-
className="validation-tabs__close"
|
|
332
|
-
onClick={handleClose}
|
|
333
|
-
aria-label={intl.formatMessage(messages.closePanel)}
|
|
334
|
-
>
|
|
335
|
-
<CapIcon type="close" />
|
|
336
|
-
</button>
|
|
337
|
-
</CapTooltip>
|
|
338
|
-
</CapRow>
|
|
339
|
-
</CapRow>
|
|
340
|
-
</div>
|
|
341
|
-
);
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
ValidationTabs.propTypes = {
|
|
345
|
-
intl: intlShape.isRequired,
|
|
346
|
-
validation: PropTypes.shape({
|
|
347
|
-
getAllIssues: PropTypes.func,
|
|
348
|
-
}),
|
|
349
|
-
onErrorClick: PropTypes.func,
|
|
350
|
-
onClose: PropTypes.func,
|
|
351
|
-
isLiquidEnabled: PropTypes.bool,
|
|
352
|
-
className: PropTypes.string,
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
ValidationTabs.defaultProps = {
|
|
356
|
-
validation: null,
|
|
357
|
-
onErrorClick: null,
|
|
358
|
-
onClose: null,
|
|
359
|
-
isLiquidEnabled: false,
|
|
360
|
-
className: '',
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
export default injectIntl(ValidationTabs);
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ValidationTabs Messages
|
|
3
|
-
*
|
|
4
|
-
* Internationalization messages for the ValidationTabs component
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { defineMessages } from 'react-intl';
|
|
8
|
-
|
|
9
|
-
const scope = 'app.components.HtmlEditor.ValidationTabs';
|
|
10
|
-
|
|
11
|
-
export default defineMessages({
|
|
12
|
-
// Tab labels
|
|
13
|
-
htmlIssues: {
|
|
14
|
-
id: `${scope}.htmlIssues`,
|
|
15
|
-
defaultMessage: 'HTML issues',
|
|
16
|
-
},
|
|
17
|
-
labelIssues: {
|
|
18
|
-
id: `${scope}.labelIssues`,
|
|
19
|
-
defaultMessage: 'Label issues',
|
|
20
|
-
},
|
|
21
|
-
liquidIssues: {
|
|
22
|
-
id: `${scope}.liquidIssues`,
|
|
23
|
-
defaultMessage: 'Liquid issues',
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
// Error item labels
|
|
27
|
-
syntaxError: {
|
|
28
|
-
id: `${scope}.syntaxError`,
|
|
29
|
-
defaultMessage: 'Syntax Error',
|
|
30
|
-
},
|
|
31
|
-
lineChar: {
|
|
32
|
-
id: `${scope}.lineChar`,
|
|
33
|
-
defaultMessage: 'Line {line}, Char {char}.',
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
// Tooltips
|
|
37
|
-
navigateToError: {
|
|
38
|
-
id: `${scope}.navigateToError`,
|
|
39
|
-
defaultMessage: 'Go to error location',
|
|
40
|
-
},
|
|
41
|
-
closePanel: {
|
|
42
|
-
id: `${scope}.closePanel`,
|
|
43
|
-
defaultMessage: 'Close validation panel',
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
// Liquid documentation
|
|
47
|
-
liquidDocumentation: {
|
|
48
|
-
id: `${scope}.liquidDocumentation`,
|
|
49
|
-
defaultMessage: 'Liquid documentation',
|
|
50
|
-
},
|
|
51
|
-
});
|