@capillarytech/creatives-library 9.0.15 → 9.0.16-beta.0
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/AppRoot.js +80 -0
- package/app.js +5 -3
- package/entry.js +67 -1
- package/mfe-exposed-components.js +2 -4
- package/package.json +2 -2
- package/services/api.js +1 -1
- package/styles/containers/layout/_layoutPage.scss +8 -6
- package/utils/getDataLayer.js +15 -0
- package/utils/gtmTrackers/gtmEvents/creativeDetails.js +2 -1
- package/utils/mfeDetect.js +1 -0
- package/v2Components/NavigationBar/index.js +9 -7
- package/v2Components/NavigationBar/mfeModuleHeader.config.js +16 -0
- package/v2Components/Pagination/_pagination.scss +2 -0
- package/v2Containers/Cap/constants.js +1 -0
- package/v2Containers/Cap/index.js +47 -21
- package/v2Containers/Cap/sagas.js +19 -0
- package/v2Containers/Templates/_templates.scss +2 -3
- package/v2Containers/Templates/index.js +1 -0
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +10 -4
- package/v2Containers/TemplatesV2/index.js +21 -1
- package/v2Containers/Whatsapp/index.js +5 -1
package/AppRoot.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React, { useMemo, useEffect, useRef } from 'react';
|
|
2
|
+
import { Provider } from 'react-redux';
|
|
3
|
+
import { configureStore } from '@capillarytech/vulcan-react-sdk/utils';
|
|
4
|
+
import { createBrowserHistory } from 'history';
|
|
5
|
+
import ConfigProvider from 'antd/lib/config-provider';
|
|
6
|
+
import { getCapThemeConfig, loadCapUI } from '@capillarytech/cap-ui-library/utils';
|
|
7
|
+
|
|
8
|
+
import LanguageProvider from 'v2Containers/LanguageProvider';
|
|
9
|
+
import App from './containers/App';
|
|
10
|
+
import './styles/main.scss';
|
|
11
|
+
import { initialReducer } from './initialReducer';
|
|
12
|
+
import { translationMessages } from './i18n';
|
|
13
|
+
import initialState from './initialState';
|
|
14
|
+
import pathConfig from './config/path';
|
|
15
|
+
import { isMFEMode } from './utils/mfeDetect';
|
|
16
|
+
import { MFEEventBus } from '@capillarytech/cap-ui-utils';
|
|
17
|
+
import appConfig from '../app-config';
|
|
18
|
+
|
|
19
|
+
// Module-scope SDK init — MUST run before configureStore.
|
|
20
|
+
loadCapUI();
|
|
21
|
+
|
|
22
|
+
const AppRoot = ({ basename: _basename = '/creatives/ui', history: hostHistory }) => {
|
|
23
|
+
const { store, history } = useMemo(() => {
|
|
24
|
+
const hist =
|
|
25
|
+
hostHistory ||
|
|
26
|
+
createBrowserHistory({ basename: pathConfig.publicPath });
|
|
27
|
+
const st = configureStore(initialState, initialReducer, hist);
|
|
28
|
+
return { store: st, history: hist };
|
|
29
|
+
}, [hostHistory]);
|
|
30
|
+
|
|
31
|
+
const fcpReported = useRef(false);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (isMFEMode() && !fcpReported.current) {
|
|
34
|
+
fcpReported.current = true;
|
|
35
|
+
requestAnimationFrame(() => {
|
|
36
|
+
MFEEventBus.emit('mfe:segment', {
|
|
37
|
+
action: 'stop',
|
|
38
|
+
appId: appConfig.appName,
|
|
39
|
+
type: 'fcp',
|
|
40
|
+
timestamp: performance.now(),
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (!isMFEMode()) {
|
|
48
|
+
const { startStandalone } = require('locize');
|
|
49
|
+
startStandalone();
|
|
50
|
+
}
|
|
51
|
+
}, []);
|
|
52
|
+
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (isMFEMode()) {
|
|
55
|
+
MFEEventBus.emit('gtm:init', {
|
|
56
|
+
appId: appConfig.appName,
|
|
57
|
+
containerId: appConfig.gtm.trackingId,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}, []);
|
|
61
|
+
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
const unsub = MFEEventBus.on('creatives:navigate', ({ path }) => {
|
|
64
|
+
if (path) history.push(path);
|
|
65
|
+
});
|
|
66
|
+
return unsub;
|
|
67
|
+
}, [history]);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<Provider store={store}>
|
|
71
|
+
<LanguageProvider messages={translationMessages}>
|
|
72
|
+
<ConfigProvider theme={getCapThemeConfig()}>
|
|
73
|
+
<App history={history} />
|
|
74
|
+
</ConfigProvider>
|
|
75
|
+
</LanguageProvider>
|
|
76
|
+
</Provider>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default AppRoot;
|
package/app.js
CHANGED
|
@@ -33,9 +33,11 @@ import { getCapThemeConfig, loadCapUI } from '@capillarytech/cap-ui-library/util
|
|
|
33
33
|
loadCapUI();
|
|
34
34
|
|
|
35
35
|
try {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
if (!window.MFE_HOST) {
|
|
37
|
+
const { setupNewrelicWebVitals } = require('./newRelic/utils');
|
|
38
|
+
// Setup New Relic WebVitals tracking
|
|
39
|
+
setupNewrelicWebVitals();
|
|
40
|
+
}
|
|
39
41
|
} catch (error) {
|
|
40
42
|
Bugsnag.notify(error);
|
|
41
43
|
}
|
package/entry.js
CHANGED
|
@@ -1,2 +1,68 @@
|
|
|
1
1
|
import { publicPath } from './config/path';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
function normalizeTrailingSlash(url) {
|
|
4
|
+
if (!url) return url;
|
|
5
|
+
return url.endsWith('/') ? url : `${url}/`;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getCreativesRemoteEntryScript() {
|
|
9
|
+
if (typeof document === 'undefined') return null;
|
|
10
|
+
const all = Array.from(
|
|
11
|
+
document.querySelectorAll('script[src*="remoteEntry"]'),
|
|
12
|
+
);
|
|
13
|
+
const match =
|
|
14
|
+
all.find(s => /cap-creatives-ui/i.test(s.src)) || all[all.length - 1];
|
|
15
|
+
return match;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getRemoteEntryOrigin() {
|
|
19
|
+
const el = getCreativesRemoteEntryScript();
|
|
20
|
+
if (!el || !el.src) return '';
|
|
21
|
+
try {
|
|
22
|
+
return new URL(el.src, window.location.href).origin;
|
|
23
|
+
} catch (e) {
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getRemoteEntryBaseUrl() {
|
|
29
|
+
const el = getCreativesRemoteEntryScript();
|
|
30
|
+
if (!el || !el.src) return '';
|
|
31
|
+
try {
|
|
32
|
+
const u = new URL(el.src, window.location.href);
|
|
33
|
+
const dir = u.pathname.replace(/\/[^/]+\.js(\?.*)?$/, '/');
|
|
34
|
+
return normalizeTrailingSlash(`${u.origin}${dir}`);
|
|
35
|
+
} catch (e) {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function resolveWebpackPublicPath() {
|
|
41
|
+
const envPath = process.env.MFE_PUBLIC_PATH;
|
|
42
|
+
|
|
43
|
+
if (envPath && envPath.length > 0) {
|
|
44
|
+
if (/^https?:\/\//i.test(envPath)) {
|
|
45
|
+
return normalizeTrailingSlash(envPath);
|
|
46
|
+
}
|
|
47
|
+
const origin = getRemoteEntryOrigin();
|
|
48
|
+
if (origin) {
|
|
49
|
+
const p = envPath.startsWith('/') ? envPath : `/${envPath}`;
|
|
50
|
+
return normalizeTrailingSlash(new URL(p, origin).href);
|
|
51
|
+
}
|
|
52
|
+
return normalizeTrailingSlash(
|
|
53
|
+
`${window.location.origin}${envPath.startsWith('/') ? '' : '/'}${envPath}`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const fromRemote = getRemoteEntryBaseUrl();
|
|
58
|
+
if (fromRemote) {
|
|
59
|
+
return fromRemote;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const origin = new URL(
|
|
63
|
+
((document || {}).currentScript || {}).src || window.location,
|
|
64
|
+
).origin;
|
|
65
|
+
return `${origin}${publicPath}/`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
__webpack_public_path__ = resolveWebpackPublicPath();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capillarytech/creatives-library",
|
|
3
3
|
"author": "meharaj",
|
|
4
|
-
"version": "9.0.
|
|
4
|
+
"version": "9.0.16-beta.0",
|
|
5
5
|
"description": "Capillary creatives ui",
|
|
6
6
|
"main": "./index.js",
|
|
7
7
|
"module": "./index.es.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"@babel/polyfill": "7.4.3",
|
|
17
17
|
"@bugsnag/js": "^7.2.1",
|
|
18
18
|
"@bugsnag/plugin-react": "7.2.1",
|
|
19
|
-
"@capillarytech/cap-ui-utils": "3.0.
|
|
19
|
+
"@capillarytech/cap-ui-utils": "3.0.20",
|
|
20
20
|
"@capillarytech/vulcan-react-sdk": "3.0.1",
|
|
21
21
|
"@codemirror/autocomplete": "^6.19.0",
|
|
22
22
|
"@codemirror/lang-css": "^6.3.1",
|
package/services/api.js
CHANGED
|
@@ -679,7 +679,7 @@ export const getSupportVideosConfig = () => {
|
|
|
679
679
|
};
|
|
680
680
|
|
|
681
681
|
export const getNavigationConfigApi = async () => {
|
|
682
|
-
const url = `${ARYA_ENDPOINT}/
|
|
682
|
+
const url = `${ARYA_ENDPOINT}/mfe_navigations`;
|
|
683
683
|
return request(url, getAPICallObject('GET'));
|
|
684
684
|
};
|
|
685
685
|
|
|
@@ -79,7 +79,6 @@
|
|
|
79
79
|
flex: 1;
|
|
80
80
|
height: calc(100vh - 50px);
|
|
81
81
|
overflow: auto;
|
|
82
|
-
padding: 8px 16px 0;
|
|
83
82
|
color: #333333;
|
|
84
83
|
}
|
|
85
84
|
|
|
@@ -154,16 +153,19 @@
|
|
|
154
153
|
}
|
|
155
154
|
|
|
156
155
|
.cap-loader-box {
|
|
157
|
-
position:
|
|
156
|
+
position: absolute;
|
|
158
157
|
top: 0;
|
|
158
|
+
left: 0;
|
|
159
159
|
width: 100%;
|
|
160
|
-
height:
|
|
161
|
-
background:
|
|
162
|
-
|
|
160
|
+
min-height: calc(100vh - 48px);
|
|
161
|
+
background: #ffffff;
|
|
162
|
+
display: flex;
|
|
163
|
+
align-items: center;
|
|
164
|
+
justify-content: center;
|
|
163
165
|
|
|
164
166
|
.loader-image {
|
|
165
167
|
width: 80px;
|
|
166
|
-
|
|
168
|
+
height: auto;
|
|
167
169
|
}
|
|
168
170
|
}
|
|
169
171
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isMFEMode } from './mfeDetect';
|
|
2
|
+
import appConfig from '../../app-config';
|
|
3
|
+
|
|
4
|
+
const getDataLayerName = () => {
|
|
5
|
+
if (isMFEMode()) {
|
|
6
|
+
return `dataLayer_${appConfig.appName.replace(/-/g, '_')}`;
|
|
7
|
+
}
|
|
8
|
+
return 'dataLayer';
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const getDataLayer = () => {
|
|
12
|
+
const name = getDataLayerName();
|
|
13
|
+
window[name] = window[name] || [];
|
|
14
|
+
return window[name];
|
|
15
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CREATIVES } from "../../../v2Containers/App/constants";
|
|
2
|
+
import { getDataLayer } from '../../getDataLayer';
|
|
2
3
|
|
|
3
4
|
const creativeDetails = ({
|
|
4
5
|
name,
|
|
@@ -23,7 +24,7 @@ const creativeDetails = ({
|
|
|
23
24
|
videoAdded,
|
|
24
25
|
stickersAdded
|
|
25
26
|
};
|
|
26
|
-
|
|
27
|
+
getDataLayer().push({
|
|
27
28
|
creativeDetails: parsedObj,
|
|
28
29
|
event: 'creativeDetails',
|
|
29
30
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const isMFEMode = () => Boolean(window.MFE_HOST);
|
|
@@ -12,8 +12,10 @@ import { loadItem } from 'services/localStorageApi';
|
|
|
12
12
|
import { intlShape, injectIntl } from 'react-intl';
|
|
13
13
|
import { withRouter } from 'react-router-dom';
|
|
14
14
|
import { get } from 'lodash';
|
|
15
|
-
import CapNavigation from '@capillarytech/cap-ui-library/
|
|
15
|
+
import CapNavigation from '@capillarytech/cap-ui-library/CapNavigationSPA';
|
|
16
16
|
import { CAP_WHITE } from '@capillarytech/cap-ui-library/styled/variables';
|
|
17
|
+
import { MFEModuleHeader } from '@capillarytech/cap-ui-utils';
|
|
18
|
+
import { MFE_MODULE_HEADER } from './mfeModuleHeader.config';
|
|
17
19
|
import injectSaga from '../../utils/injectSaga';
|
|
18
20
|
import sagas from './saga';
|
|
19
21
|
import messages from './messages';
|
|
@@ -30,12 +32,11 @@ import { CapLeftNavigatioOpenCss, CapLeftNavigationCss } from './style';
|
|
|
30
32
|
import { EMBEDDED } from './constants';
|
|
31
33
|
|
|
32
34
|
const CapWrapper = styled.div`
|
|
33
|
-
position: absolute;
|
|
34
35
|
padding: 0;
|
|
35
36
|
background-color: ${CAP_WHITE};
|
|
36
37
|
width: 100%;
|
|
37
38
|
display: flex;
|
|
38
|
-
|
|
39
|
+
|
|
39
40
|
|
|
40
41
|
.sidebar-container {
|
|
41
42
|
margin-right: 10px;
|
|
@@ -46,10 +47,8 @@ const CapWrapper = styled.div`
|
|
|
46
47
|
`;
|
|
47
48
|
|
|
48
49
|
const ComponentWrapper = styled.div`
|
|
49
|
-
max-width: 1140px;
|
|
50
|
-
margin: 0 auto;
|
|
51
50
|
width: 100%;
|
|
52
|
-
padding:
|
|
51
|
+
padding: 0;
|
|
53
52
|
`;
|
|
54
53
|
|
|
55
54
|
export class NavigationBar extends React.Component {
|
|
@@ -58,6 +57,7 @@ export class NavigationBar extends React.Component {
|
|
|
58
57
|
this.state = this.initializeSelectedProduct();
|
|
59
58
|
}
|
|
60
59
|
|
|
60
|
+
|
|
61
61
|
initializeSelectedProduct = () => {
|
|
62
62
|
const { location, intl: { formatMessage } } = this.props;
|
|
63
63
|
const { pathname } = location;
|
|
@@ -179,6 +179,7 @@ export class NavigationBar extends React.Component {
|
|
|
179
179
|
const topbarIcons = this.getTopbarIcons(showDocumentationBot);
|
|
180
180
|
const headerOverideCss = leftNavbarExpandedProp ? CapLeftNavigatioOpenCss : CapLeftNavigationCss;
|
|
181
181
|
return (
|
|
182
|
+
<>
|
|
182
183
|
<CapNavigation
|
|
183
184
|
className="creatives-main-container"
|
|
184
185
|
showContent
|
|
@@ -212,7 +213,8 @@ export class NavigationBar extends React.Component {
|
|
|
212
213
|
</CapWrapper>
|
|
213
214
|
</div>
|
|
214
215
|
</CapNavigation>
|
|
215
|
-
|
|
216
|
+
<MFEModuleHeader history={this.props.history} {...MFE_MODULE_HEADER} />
|
|
217
|
+
</>
|
|
216
218
|
);
|
|
217
219
|
}
|
|
218
220
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Static, module-specific config for the shared MFE module-header wrapper
|
|
2
|
+
// (MFEModuleHeader). Runtime values (history) are supplied in NavigationBar.
|
|
3
|
+
export const MFE_MODULE_HEADER = {
|
|
4
|
+
header: {
|
|
5
|
+
name: 'Creatives',
|
|
6
|
+
description: 'Store your creative templates for all your channels',
|
|
7
|
+
showBorder: false,
|
|
8
|
+
showSettings: false,
|
|
9
|
+
},
|
|
10
|
+
landingRoutes: [
|
|
11
|
+
'/creatives/ui/v2/',
|
|
12
|
+
'/creatives/ui/v2',
|
|
13
|
+
'/v2/',
|
|
14
|
+
'/v2'
|
|
15
|
+
],
|
|
16
|
+
};
|
|
@@ -56,6 +56,7 @@ export const SUCCESS = 'SUCCESS';
|
|
|
56
56
|
export const FAILURE = 'FAILURE';
|
|
57
57
|
|
|
58
58
|
export const ENABLE_PRODUCT_SUPPORT_VIDEOS = 'ENABLE_PRODUCT_SUPPORT_VIDEOS';
|
|
59
|
+
export const ENABLE_NEW_LEFT_NAVIGATION = 'ENABLE_NEW_LEFT_NAVIGATION';
|
|
59
60
|
export const DEFAULT = 'default';
|
|
60
61
|
export const DEFAULT_MODULE = 'creatives';
|
|
61
62
|
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
REQUEST,
|
|
31
31
|
DEFAULT,
|
|
32
32
|
ENABLE_PRODUCT_SUPPORT_VIDEOS,
|
|
33
|
+
ENABLE_NEW_LEFT_NAVIGATION,
|
|
33
34
|
CAMPAIGN_SETTINGS_URL,
|
|
34
35
|
} from './constants';
|
|
35
36
|
import './_cap.scss';
|
|
@@ -53,7 +54,8 @@ import { v2ViberSagas } from '../Viber/sagas';
|
|
|
53
54
|
import { v2FacebookSagas } from '../Facebook/sagas';
|
|
54
55
|
import createReducer from '../Line/Container/reducer';
|
|
55
56
|
import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
|
|
56
|
-
|
|
57
|
+
import { getDataLayer } from '../../utils/getDataLayer';
|
|
58
|
+
const gtm = getDataLayer();
|
|
57
59
|
const {
|
|
58
60
|
logNewTab,
|
|
59
61
|
utilsGetOrgNameFromId,
|
|
@@ -72,18 +74,19 @@ const CapWrapper = styled.div`
|
|
|
72
74
|
min-height: 100%;
|
|
73
75
|
padding: 0;
|
|
74
76
|
flex-direction: column;
|
|
77
|
+
position: relative;
|
|
75
78
|
`;
|
|
76
79
|
GA.initialize({ accessKey: GTM_TRACKING_ID, trackUIError: true, trackLoadPerformance: 'creatives' });
|
|
77
80
|
|
|
78
81
|
const MainWrapper = styled.div`
|
|
79
82
|
position: relative;
|
|
80
|
-
min-height:
|
|
81
|
-
top:
|
|
83
|
+
min-height: 100%;
|
|
84
|
+
top: 0;
|
|
82
85
|
`;
|
|
83
86
|
|
|
84
87
|
const ContentWrapper = styled.div`
|
|
85
88
|
&& {
|
|
86
|
-
margin-left:
|
|
89
|
+
margin-left: 0;
|
|
87
90
|
}
|
|
88
91
|
`;
|
|
89
92
|
|
|
@@ -500,6 +503,8 @@ export class Cap extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
500
503
|
const type = this.props.location.query.type;
|
|
501
504
|
const toastMessages = this.props.Global.messages;
|
|
502
505
|
const { isCreativesAccessible, showOrgChangeModal, showRefreshModal } = this.state;
|
|
506
|
+
const { accessibleFeatures = [] } = currentOrgDetails;
|
|
507
|
+
const isLatestLeftNavigationEnabled = accessibleFeatures.includes(ENABLE_NEW_LEFT_NAVIGATION);
|
|
503
508
|
return (
|
|
504
509
|
<CapWrapper>
|
|
505
510
|
{ this.props.loader.localeLoading || this.props.Global.fetching_userdata ?
|
|
@@ -537,26 +542,47 @@ export class Cap extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
537
542
|
campaignOrgV2Status={currentOrgDetails.org_campaign_v2_status}
|
|
538
543
|
handleLeftNavBarExpanded={this.handleLeftNavBarExpanded}
|
|
539
544
|
leftNavbarExpandedProp={this.state.leftNavbarExpanded}
|
|
540
|
-
/>) : ''}
|
|
541
|
-
<MainWrapper className="main">
|
|
542
545
|
|
|
543
|
-
<ContentWrapper
|
|
544
|
-
className={`main-content ${this.state.leftNavbarExpanded ? "contet-width-collapse" : "content-width-expanded"}`}
|
|
545
|
-
leftNavbarExpanded={this.state.leftNavbarExpanded}
|
|
546
546
|
>
|
|
547
|
-
<
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
547
|
+
<MainWrapper isLatestLeftNavigationEnabled={isLatestLeftNavigationEnabled} className="main">
|
|
548
|
+
<ContentWrapper
|
|
549
|
+
className={`main-content ${this.state.leftNavbarExpanded ? "contet-width-collapse" : "content-width-expanded"}`}
|
|
550
|
+
isLatestLeftNavigationEnabled={isLatestLeftNavigationEnabled}
|
|
551
|
+
leftNavbarExpanded={this.state.leftNavbarExpanded}
|
|
552
|
+
>
|
|
553
|
+
<Switch>
|
|
554
|
+
{componentRoutes.map(routeProps => {
|
|
555
|
+
return (
|
|
556
|
+
<RenderRoute
|
|
557
|
+
{...routeProps}
|
|
558
|
+
key={routeProps.path}
|
|
559
|
+
isLoggedIn={isLoggedIn}
|
|
560
|
+
/>
|
|
561
|
+
)}
|
|
562
|
+
)}
|
|
563
|
+
</Switch>
|
|
564
|
+
</ContentWrapper>
|
|
565
|
+
</MainWrapper>
|
|
566
|
+
</NavigationBar>) : (
|
|
567
|
+
<MainWrapper isLatestLeftNavigationEnabled={isLatestLeftNavigationEnabled} className="main">
|
|
568
|
+
<ContentWrapper
|
|
569
|
+
className={`main-content ${this.state.leftNavbarExpanded ? "contet-width-collapse" : "content-width-expanded"}`}
|
|
570
|
+
isLatestLeftNavigationEnabled={isLatestLeftNavigationEnabled}
|
|
571
|
+
leftNavbarExpanded={this.state.leftNavbarExpanded}
|
|
572
|
+
>
|
|
573
|
+
<Switch>
|
|
574
|
+
{componentRoutes.map(routeProps => {
|
|
575
|
+
return (
|
|
576
|
+
<RenderRoute
|
|
577
|
+
{...routeProps}
|
|
578
|
+
key={routeProps.path}
|
|
579
|
+
isLoggedIn={isLoggedIn}
|
|
580
|
+
/>
|
|
581
|
+
)}
|
|
555
582
|
)}
|
|
556
|
-
|
|
557
|
-
</
|
|
558
|
-
</
|
|
559
|
-
</MainWrapper>
|
|
583
|
+
</Switch>
|
|
584
|
+
</ContentWrapper>
|
|
585
|
+
</MainWrapper>)}
|
|
560
586
|
</div>
|
|
561
587
|
{(toastMessages && toastMessages.length > 0) &&
|
|
562
588
|
toastMessages.map((message) => {
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
// import { normalize } from 'normalizr';
|
|
8
8
|
import * as Api from '../../services/api';
|
|
9
9
|
import * as LocalStorage from '../../services/localStorageApi';
|
|
10
|
+
import { isMFEMode } from '../../utils/mfeDetect';
|
|
10
11
|
import * as types from './constants';
|
|
11
12
|
import config from '../../config/app';
|
|
12
13
|
//import pathConfig from '../../config/path';
|
|
@@ -82,6 +83,24 @@ export function* logoutFlow() {
|
|
|
82
83
|
|
|
83
84
|
export function* fetchUserInfo(option) {
|
|
84
85
|
try {
|
|
86
|
+
if (isMFEMode()) {
|
|
87
|
+
const userData = LocalStorage.loadItem('user');
|
|
88
|
+
const currentOrgId = LocalStorage.loadItem('orgID');
|
|
89
|
+
const storedOrgDetails = LocalStorage.loadItem('currentOrgDetails');
|
|
90
|
+
const currentOrgDetails = {
|
|
91
|
+
...(storedOrgDetails || {}),
|
|
92
|
+
accessibleFeatures: window.capAuth?.accessibleFeatures || [],
|
|
93
|
+
};
|
|
94
|
+
yield put({
|
|
95
|
+
type: types.GET_USER_DATA_SUCCESS,
|
|
96
|
+
userData: userData || {},
|
|
97
|
+
currentOrgId,
|
|
98
|
+
currentOrgDetails,
|
|
99
|
+
});
|
|
100
|
+
if (option.callback) option.callback(userData, currentOrgDetails);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
85
104
|
const result = yield call(Api.getUserData);
|
|
86
105
|
if (result?.isError || result?.status === 401) {
|
|
87
106
|
yield call(LocalStorage.clearItem, 'user');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@import '~@capillarytech/cap-ui-library/styles/_variables.scss';
|
|
2
2
|
|
|
3
3
|
.ant-tabs-content{
|
|
4
|
-
margin-top: $
|
|
4
|
+
margin-top: $CAP_SPACE_08;
|
|
5
5
|
.ant-tabs-tabpane-active{
|
|
6
6
|
padding: unset;
|
|
7
7
|
}
|
|
@@ -1174,7 +1174,7 @@
|
|
|
1174
1174
|
display: flex;
|
|
1175
1175
|
align-items: baseline;
|
|
1176
1176
|
justify-content: space-between;
|
|
1177
|
-
width:
|
|
1177
|
+
width: 100%;
|
|
1178
1178
|
}
|
|
1179
1179
|
|
|
1180
1180
|
.filter-row-content {
|
|
@@ -1243,7 +1243,6 @@
|
|
|
1243
1243
|
justify-content: space-between;
|
|
1244
1244
|
align-items: center;
|
|
1245
1245
|
gap: $CAP_SPACE_08;
|
|
1246
|
-
margin-right: $CAP_SPACE_32;
|
|
1247
1246
|
}
|
|
1248
1247
|
|
|
1249
1248
|
.template-listing-more-btn {
|
|
@@ -4561,6 +4561,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
4561
4561
|
<CapButton
|
|
4562
4562
|
className={`create-new-${channelLowerCase} margin-l-8 margin-b-12`}
|
|
4563
4563
|
type={"primary"}
|
|
4564
|
+
isAddBtn
|
|
4564
4565
|
disabled={this.isCreateDisabled()}
|
|
4565
4566
|
onClick={this.createTemplate}
|
|
4566
4567
|
>
|
|
@@ -10,10 +10,10 @@ export default css`
|
|
|
10
10
|
|
|
11
11
|
.component-wrapper {
|
|
12
12
|
${(props) => props.isFullMode ? `
|
|
13
|
-
max-width:
|
|
14
|
-
margin: 0
|
|
13
|
+
max-width: 100%;
|
|
14
|
+
margin: 0;
|
|
15
15
|
width: 100%;
|
|
16
|
-
padding: 0
|
|
16
|
+
padding: 0;
|
|
17
17
|
/* Only main channel tabs content, not HTML Editor validation panel tabs */
|
|
18
18
|
> .cap-tab-v2 > .ant-tabs-content-holder > .ant-tabs-content,
|
|
19
19
|
> .cap-tab-v2 > .ant-tabs-content {
|
|
@@ -26,6 +26,12 @@ export default css`
|
|
|
26
26
|
`;
|
|
27
27
|
|
|
28
28
|
export const CapTabStyle = css`
|
|
29
|
-
${(props) => props.isFullMode ? `margin-top: ${CAP_SPACE_24}
|
|
29
|
+
${(props) => props.isFullMode ? `margin-top: ${CAP_SPACE_24};` : ``
|
|
30
|
+
}
|
|
31
|
+
.ant-tabs-nav-list {
|
|
32
|
+
gap: 2rem;
|
|
33
|
+
}
|
|
34
|
+
.ant-tabs-tab + .ant-tabs-tab {
|
|
35
|
+
margin: 0 !important;
|
|
30
36
|
}
|
|
31
37
|
`;
|
|
@@ -46,6 +46,9 @@ import {
|
|
|
46
46
|
NORMALIZED_CHANNEL_ALIASES,
|
|
47
47
|
SMS,
|
|
48
48
|
} from "../CreativesContainer/constants";
|
|
49
|
+
import { MFEEventBus } from '@capillarytech/cap-ui-utils';
|
|
50
|
+
import { isMFEMode } from '../../utils/mfeDetect';
|
|
51
|
+
import appConfig from '../../../app-config';
|
|
49
52
|
|
|
50
53
|
const {CapCustomCardList} = CapCustomCard;
|
|
51
54
|
|
|
@@ -53,6 +56,7 @@ const StyledCapTab = withStyles(CapTab, CapTabStyle);
|
|
|
53
56
|
export class TemplatesV2 extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
54
57
|
constructor(props) {
|
|
55
58
|
super(props);
|
|
59
|
+
this.lcpReported = false;
|
|
56
60
|
let defaultChannel = get(this, 'props.channel') || get(this, 'props.params.channel') || 'sms';
|
|
57
61
|
if (defaultChannel === LOYALTY) {
|
|
58
62
|
defaultChannel = 'sms';
|
|
@@ -221,6 +225,23 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
221
225
|
}
|
|
222
226
|
}
|
|
223
227
|
|
|
228
|
+
componentDidUpdate(prevProps) {
|
|
229
|
+
if (
|
|
230
|
+
isMFEMode() &&
|
|
231
|
+
!this.lcpReported &&
|
|
232
|
+
!this.props.Templates.getAllTemplatesInProgress &&
|
|
233
|
+
prevProps.Templates.getAllTemplatesInProgress
|
|
234
|
+
) {
|
|
235
|
+
this.lcpReported = true;
|
|
236
|
+
MFEEventBus.emit('mfe:segment', {
|
|
237
|
+
action: 'stop',
|
|
238
|
+
appId: appConfig.appName,
|
|
239
|
+
type: 'lcp',
|
|
240
|
+
timestamp: performance.now(),
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
224
245
|
componentWillReceiveProps(nextProps) {
|
|
225
246
|
if (this.props.channel !== nextProps.channel) {
|
|
226
247
|
const panes = this.setChannelContent(nextProps.channel, this.state.panes);
|
|
@@ -381,7 +402,6 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
381
402
|
]}
|
|
382
403
|
/>}
|
|
383
404
|
<div className="component-wrapper">
|
|
384
|
-
{isFullMode && <CapHeader title={<FormattedMessage {...messages.creatives}/>} description={<FormattedMessage {...messages.creativesDesc}/>}/>}
|
|
385
405
|
<StyledCapTab
|
|
386
406
|
panes={this.state.panes}
|
|
387
407
|
onChange={this.channelChange}
|
|
@@ -744,7 +744,11 @@ export const Whatsapp = (props) => {
|
|
|
744
744
|
carouselIndex,
|
|
745
745
|
} = tagSelectData;
|
|
746
746
|
if (mapData && updatedData) {
|
|
747
|
-
const
|
|
747
|
+
const underscoreIdx = areaId ? areaId.indexOf("_") : -1;
|
|
748
|
+
if (underscoreIdx < 0) {
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
const numId = Number(areaId.slice(underscoreIdx + 1));
|
|
748
752
|
if (!isNaN(numId)) {
|
|
749
753
|
const arr = [...updatedData];
|
|
750
754
|
//when trying to insert tag in empty textarea,{#var#} is replaced with "" and then tag is added
|