@griddo/ax 1.62.6 → 1.63.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.
Files changed (84) hide show
  1. package/package.json +6 -5
  2. package/src/GlobalStore.tsx +1 -1
  3. package/src/Style/index.tsx +2 -0
  4. package/src/api/pages.tsx +20 -0
  5. package/src/api/utils.tsx +5 -2
  6. package/src/components/Browser/index.tsx +144 -39
  7. package/src/components/Browser/style.tsx +47 -11
  8. package/src/components/ConfigPanel/index.tsx +3 -3
  9. package/src/components/Fields/RichText/index.tsx +2 -2
  10. package/src/components/Fields/UrlField/utils.tsx +10 -1
  11. package/src/components/Icon/components/Desktop.js +9 -4
  12. package/src/components/Icon/components/Phone.js +4 -4
  13. package/src/components/Icon/components/Share.js +12 -0
  14. package/src/components/Icon/components/Tablet.js +4 -4
  15. package/src/components/Icon/svgs/Share.svg +3 -0
  16. package/src/components/MainWrapper/AppBar/index.tsx +19 -7
  17. package/src/components/MainWrapper/AppBar/style.tsx +20 -4
  18. package/src/components/MainWrapper/index.tsx +1 -1
  19. package/src/components/SideModal/index.tsx +1 -1
  20. package/src/components/TableFilters/DateFilter/index.tsx +48 -0
  21. package/src/components/TableFilters/DateFilter/style.tsx +29 -0
  22. package/src/components/TableFilters/index.tsx +2 -0
  23. package/src/components/Tabs/index.tsx +17 -7
  24. package/src/components/Tabs/style.tsx +29 -16
  25. package/src/components/Tooltip/index.tsx +1 -1
  26. package/src/components/Tooltip/style.tsx +2 -0
  27. package/src/components/index.tsx +2 -0
  28. package/src/containers/App/reducer.tsx +3 -1
  29. package/src/containers/Navigation/Defaults/actions.tsx +2 -1
  30. package/src/containers/PageEditor/actions.tsx +65 -10
  31. package/src/containers/Settings/DataPacks/actions.tsx +4 -1
  32. package/src/containers/Sites/actions.tsx +3 -1
  33. package/src/helpers/dates.tsx +3 -4
  34. package/src/helpers/index.tsx +2 -0
  35. package/src/helpers/strings.tsx +38 -7
  36. package/src/hooks/forms.tsx +1 -2
  37. package/src/index.tsx +2 -2
  38. package/src/modules/Content/OptionTable/index.tsx +29 -2
  39. package/src/modules/Content/PageItem/index.tsx +11 -2
  40. package/src/modules/Content/index.tsx +9 -0
  41. package/src/modules/GlobalEditor/Editor/index.tsx +7 -9
  42. package/src/modules/GlobalEditor/{Editor/PageBrowser → PageBrowser}/index.tsx +14 -6
  43. package/src/modules/GlobalEditor/Preview/index.tsx +19 -0
  44. package/src/modules/GlobalEditor/Preview/style.tsx +9 -0
  45. package/src/modules/GlobalEditor/index.tsx +41 -9
  46. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +5 -1
  47. package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +9 -7
  48. package/src/modules/PageEditor/Editor/index.tsx +5 -5
  49. package/src/modules/PageEditor/{Editor/PageBrowser → PageBrowser}/index.tsx +11 -4
  50. package/src/modules/PageEditor/Preview/index.tsx +14 -0
  51. package/src/modules/PageEditor/Preview/style.tsx +9 -0
  52. package/src/modules/PageEditor/index.tsx +40 -16
  53. package/src/modules/PublicPreview/index.tsx +92 -0
  54. package/src/modules/PublicPreview/style.tsx +18 -0
  55. package/src/modules/Redirects/BulkHeader/TableHeader/index.tsx +16 -3
  56. package/src/modules/Redirects/BulkHeader/TableHeader/style.tsx +9 -3
  57. package/src/modules/Redirects/BulkHeader/index.tsx +7 -1
  58. package/src/modules/Redirects/RedirectItem/index.tsx +4 -0
  59. package/src/modules/Redirects/RedirectItem/style.tsx +19 -3
  60. package/src/modules/Redirects/atoms.tsx +0 -1
  61. package/src/modules/Redirects/hooks.tsx +67 -0
  62. package/src/modules/Redirects/index.tsx +23 -9
  63. package/src/modules/Redirects/utils.tsx +10 -0
  64. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/Field/index.tsx +107 -0
  65. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/Field/style.tsx +54 -0
  66. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/index.tsx +66 -0
  67. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/style.tsx +42 -0
  68. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/TemplateBrowser/index.tsx +58 -0
  69. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/index.tsx +41 -0
  70. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/index.tsx +93 -0
  71. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/style.tsx +25 -0
  72. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/index.tsx +48 -0
  73. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/style.tsx +53 -0
  74. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/index.tsx +40 -36
  75. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/style.tsx +4 -5
  76. package/src/modules/Settings/ContentTypes/DataPacks/Config/index.tsx +4 -4
  77. package/src/modules/Settings/ContentTypes/DataPacks/index.tsx +5 -1
  78. package/src/modules/Settings/{Analytics → SeoAnalyticsSettings/Analytics}/atoms.tsx +0 -0
  79. package/src/modules/Settings/{Analytics → SeoAnalyticsSettings/Analytics}/index.tsx +20 -11
  80. package/src/modules/Settings/{Analytics → SeoAnalyticsSettings/Analytics}/style.tsx +6 -0
  81. package/src/modules/Settings/{SeoSettings → SeoAnalyticsSettings}/index.tsx +11 -4
  82. package/src/routes/publicRoutes.tsx +3 -1
  83. package/src/routes/site.tsx +14 -10
  84. package/src/types/index.tsx +9 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@griddo/ax",
3
3
  "description": "Griddo Author Experience",
4
- "version": "1.62.6",
4
+ "version": "1.63.0",
5
5
  "authors": [
6
6
  "Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
7
7
  "Carlos Torres <carlos.torres@secuoyas.com>",
@@ -50,7 +50,7 @@
50
50
  "@types/node": "12.11.1",
51
51
  "@types/react": "^17.0.37",
52
52
  "@types/react-datepicker": "^3.1.1",
53
- "@types/react-dom": "^17.0.11",
53
+ "@types/react-dom": "^17.0.14",
54
54
  "@types/react-draft-wysiwyg": "^1.13.1",
55
55
  "@types/react-redux": "7.1.4",
56
56
  "@types/react-router-dom": "5.1.2",
@@ -108,12 +108,13 @@
108
108
  "postcss-normalize": "7.0.1",
109
109
  "postcss-preset-env": "6.7.0",
110
110
  "postcss-safe-parser": "^6.0.0",
111
- "react": "^18.0.0-rc.0-next-3b3daf557-20211210",
111
+ "react": "^18.0.0",
112
112
  "react-app-polyfill": "^1.0.4",
113
113
  "react-datepicker": "^3.2.2",
114
114
  "react-dev-utils": "^11.0.4",
115
- "react-dom": "^18.0.0-rc.0-next-3b3daf557-20211210",
115
+ "react-dom": "^18.0.0",
116
116
  "react-draft-wysiwyg": "^1.14.5",
117
+ "react-frame-component": "^5.2.1",
117
118
  "react-froala-wysiwyg": "3.1.0",
118
119
  "react-redux": "7.1.1",
119
120
  "react-refresh": "^0.10.0",
@@ -244,5 +245,5 @@
244
245
  "publishConfig": {
245
246
  "access": "public"
246
247
  },
247
- "gitHead": "b0c7944b7f9e7b51dd7bb08bc1a033f87a23bf87"
248
+ "gitHead": "69750b52129be69bba914bafa77c6b96f19514eb"
248
249
  }
@@ -37,7 +37,7 @@ export class GlobalStore {
37
37
 
38
38
  const globalReducer: Reducer<any> = combineReducers({
39
39
  router: connectRouter(history),
40
- app: persistReducer(this.authPersistConfig, appReducer),
40
+ app: persistReducer(this.authPersistConfig, appReducer as Reducer<any, Action<any>>),
41
41
  sites: sitesReducer as Reducer<any, Action<any>>,
42
42
  pageEditor: pageEditorReducer as Reducer<any, Action<any>>,
43
43
  menu: menuReducer as Reducer<any, Action<any>>,
@@ -21,6 +21,8 @@ const GlobalStyle = createGlobalStyle`
21
21
  width: 100%;
22
22
  -webkit-font-smoothing: antialiased;
23
23
  overscroll-behavior: none;
24
+ }
25
+ body {
24
26
  min-width: 1280px;
25
27
  }
26
28
  * { box-sizing: border-box; }
package/src/api/pages.tsx CHANGED
@@ -1,6 +1,8 @@
1
1
  import { template } from "./config";
2
2
  import { IServiceConfig, sendRequest } from "./utils";
3
3
 
4
+ const PUBLIC_BASE_PATH = process.env.REACT_APP_PUBLIC_API_ENDPOINT;
5
+
4
6
  const SERVICES: { [key: string]: IServiceConfig } = {
5
7
  GET_PAGE_INFO: {
6
8
  ...template,
@@ -67,6 +69,12 @@ const SERVICES: { [key: string]: IServiceConfig } = {
67
69
  endpoint: ["/page/", "/ping"],
68
70
  method: "POST",
69
71
  },
72
+ GET_PUPLIC_PAGE: {
73
+ ...template,
74
+ host: PUBLIC_BASE_PATH,
75
+ endpoint: ["/page/", "/preview/"],
76
+ method: "GET",
77
+ },
70
78
  };
71
79
 
72
80
  const getPageInfo = async (pageID: number) => {
@@ -180,6 +188,17 @@ const sendPagePing = async (pageID: number) => {
180
188
  return sendRequest(SERVICES.PAGE_PING);
181
189
  };
182
190
 
191
+ const getPublicPage = async (pageID: number, entity: string) => {
192
+ const {
193
+ host,
194
+ endpoint: [prefix, suffix],
195
+ } = SERVICES.GET_PUPLIC_PAGE;
196
+
197
+ SERVICES.GET_PUPLIC_PAGE.dynamicUrl = `${host}${prefix}${pageID}${suffix}${entity}`;
198
+
199
+ return sendRequest(SERVICES.GET_PUPLIC_PAGE);
200
+ };
201
+
183
202
  export default {
184
203
  getPageInfo,
185
204
  updatePage,
@@ -194,4 +213,5 @@ export default {
194
213
  restorePage,
195
214
  bulkRestore,
196
215
  sendPagePing,
216
+ getPublicPage,
197
217
  };
package/src/api/utils.tsx CHANGED
@@ -10,10 +10,13 @@ export interface IServiceConfig {
10
10
  dynamicUrl?: string;
11
11
  }
12
12
 
13
- const getToken = (): Record<string, unknown> => {
13
+ const getToken = (): Record<string, unknown> | null => {
14
14
  // non-null assertion - we will always have token when here
15
15
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
16
- let { token } = JSON.parse(localStorage.getItem("persist:app")!);
16
+ const app = localStorage.getItem("persist:app");
17
+ if (!app) return null;
18
+
19
+ let { token } = JSON.parse(app);
17
20
  token = JSON.parse(token);
18
21
  const authorization = { Authorization: `bearer ${token}` };
19
22
 
@@ -1,79 +1,182 @@
1
- import React, { useEffect } from "react";
1
+ import React, { useEffect, useState } from "react";
2
+ import { FrameContextConsumer } from "react-frame-component";
3
+ import { StyleSheetManager } from "styled-components";
2
4
 
3
5
  import * as components from "components";
4
- import { providers, translations, cloudinaryDefaults } from "components";
6
+ import { providers, translations, cloudinaryDefaults, griddoDamDefaults } from "components";
5
7
  import { Preview } from "@griddo/core";
6
-
7
8
  import { findByEditorID } from "@ax/forms";
9
+ import { copyTextToClipboard } from "@ax/helpers";
10
+ import { useToast } from "@ax/hooks";
11
+ import Icon from "../Icon";
12
+ import Tooltip from "../Tooltip";
13
+ import Toast from "../Toast";
8
14
 
9
15
  import * as S from "./style";
10
16
 
11
17
  const Browser = (props: IBrowserProps): JSX.Element => {
12
- const { url, content, header, footer, isPage, theme, socials, cloudinaryName, siteLangs, disabled, siteID } = props;
18
+ const {
19
+ url,
20
+ content,
21
+ header,
22
+ footer,
23
+ isPage,
24
+ theme,
25
+ socials,
26
+ cloudinaryName,
27
+ siteLangs,
28
+ disabled,
29
+ siteID,
30
+ isPreview,
31
+ damDomain,
32
+ setSelectedContent,
33
+ } = props;
13
34
 
14
35
  const API_URL = process.env.REACT_APP_API_ENDPOINT;
15
36
  const PUBLIC_API_URL = process.env.REACT_APP_PUBLIC_API_ENDPOINT;
16
37
  const { SiteProvider, AnimationProvider } = providers;
17
38
 
39
+ const [resolution, setResolution] = useState("desktop");
40
+ const { isVisible, toggleToast, setIsVisible } = useToast();
41
+
18
42
  useEffect(() => {
19
43
  localStorage.setItem("selectedID", "0");
20
44
  (window as any).browserRef = null;
21
45
  }, []);
22
46
 
23
47
  const selectEditorID = (
24
- selectedComponent: { editorID: number; component: any; type: string, parentEditorID: number },
48
+ selectedComponent: { editorID: number; component: any; type: string; parentEditorID: number },
25
49
  parentComponent: string | undefined | null,
26
50
  e: React.SyntheticEvent
27
51
  ) => {
28
52
  const { element } = findByEditorID(content, selectedComponent.parentEditorID);
29
53
  element && e.stopPropagation();
30
54
 
31
- const { setSelectedContent } = props;
32
-
33
55
  const parent = selectedComponent.component === "Page" ? null : "Page";
34
56
 
35
57
  const { editorID } = selectedComponent;
36
58
 
37
59
  const isNavigationModule = ["header", "footer"].includes(selectedComponent.type);
38
60
 
39
- if (!disabled || isNavigationModule) {
40
- setSelectedContent(editorID, parent);
61
+ if (!isPreview && (!disabled || isNavigationModule)) {
62
+ setSelectedContent && setSelectedContent(editorID, parent);
63
+ }
64
+ };
65
+
66
+ const getWidth = (res: string) => {
67
+ switch (res) {
68
+ case "tablet":
69
+ return "768px";
70
+ case "phone":
71
+ return "425px";
72
+ default:
73
+ return "100%";
41
74
  }
42
75
  };
43
76
 
77
+ const copyUrl = () => {
78
+ const { id, entity } = content;
79
+ const domain = window.location.origin;
80
+ const url = `${domain}/page-preview/${id}/${entity}`;
81
+ copyTextToClipboard(url).then(
82
+ function () {
83
+ toggleToast();
84
+ },
85
+ function (err) {
86
+ console.error("Could not copy text: ", err);
87
+ }
88
+ );
89
+ };
90
+
91
+ const toastProps = {
92
+ setIsVisible,
93
+ message: "URL Copied",
94
+ };
95
+
96
+ const Providers = (
97
+ <SiteProvider
98
+ cloudinaryCloudName={cloudinaryName}
99
+ damDomain={damDomain}
100
+ theme={theme}
101
+ socials={socials}
102
+ siteLangs={siteLangs}
103
+ translations={translations}
104
+ selectEditorID={selectEditorID}
105
+ cloudinaryDefaults={cloudinaryDefaults}
106
+ griddoDamDefaults={griddoDamDefaults}
107
+ renderer="editor"
108
+ apiUrl={API_URL}
109
+ publicApiUrl={PUBLIC_API_URL}
110
+ siteId={siteID}
111
+ >
112
+ <AnimationProvider showOnScroll={{ active: false }}>
113
+ <S.Wrapper ref={(ref: any) => ((window as any).browserRef = ref)}>
114
+ <Preview
115
+ isPage={isPage}
116
+ apiUrl={API_URL}
117
+ library={components}
118
+ content={content}
119
+ header={header}
120
+ footer={footer}
121
+ languageId={content.language}
122
+ pageLanguages={content.pageLanguages}
123
+ />
124
+ </S.Wrapper>
125
+ </AnimationProvider>
126
+ </SiteProvider>
127
+ );
128
+
129
+ const getStylesFromHeader = () => {
130
+ const header = document.head.innerHTML;
131
+
132
+ return header.replace(/<style data-styled="active" \b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, "");
133
+ };
134
+
135
+ const initialContent = `<!DOCTYPE html><html><head>${getStylesFromHeader()}</head><body><div></div></body></html>`;
136
+
44
137
  return (
45
138
  <S.BrowserWrapper>
46
139
  <S.NavBar>
47
140
  <S.NavUrl>{url}</S.NavUrl>
141
+ {isPreview && (
142
+ <S.NavActions>
143
+ <S.IconWrapper onClick={copyUrl}>
144
+ <Tooltip content="Copy url to share draft" bottom>
145
+ <Icon name="share" size="24" />
146
+ </Tooltip>
147
+ </S.IconWrapper>
148
+ <S.IconWrapper active={resolution === "desktop"} onClick={() => setResolution("desktop")}>
149
+ <Tooltip content="Desktop" bottom>
150
+ <Icon name="desktop" size="24" />
151
+ </Tooltip>
152
+ </S.IconWrapper>
153
+ <S.IconWrapper active={resolution === "tablet"} onClick={() => setResolution("tablet")}>
154
+ <Tooltip content="Tablet" bottom>
155
+ <Icon name="tablet" size="24" />
156
+ </Tooltip>
157
+ </S.IconWrapper>
158
+ <S.IconWrapper active={resolution === "phone"} onClick={() => setResolution("phone")}>
159
+ <Tooltip content="Mobile" bottom>
160
+ <Icon name="phone" size="24" />
161
+ </Tooltip>
162
+ </S.IconWrapper>
163
+ </S.NavActions>
164
+ )}
48
165
  </S.NavBar>
49
- <SiteProvider
50
- cloudinaryCloudName={cloudinaryName}
51
- theme={theme}
52
- socials={socials}
53
- siteLangs={siteLangs}
54
- translations={translations}
55
- selectEditorID={selectEditorID}
56
- cloudinaryDefaults={cloudinaryDefaults}
57
- renderer="editor"
58
- apiUrl={API_URL}
59
- publicApiUrl={PUBLIC_API_URL}
60
- siteId={siteID}
61
- >
62
- <AnimationProvider showOnScroll={{ active: false }}>
63
- <S.Wrapper ref={(ref: any) => ((window as any).browserRef = ref)}>
64
- <Preview
65
- isPage={isPage}
66
- apiUrl={API_URL}
67
- library={components}
68
- content={content}
69
- header={header}
70
- footer={footer}
71
- languageId={content.language}
72
- pageLanguages={content.pageLanguages}
73
- />
74
- </S.Wrapper>
75
- </AnimationProvider>
76
- </SiteProvider>
166
+ {isPreview ? (
167
+ <S.FrameWrapper>
168
+ <S.StyledFrame width={getWidth(resolution)} height="100%" initialContent={initialContent}>
169
+ <FrameContextConsumer>
170
+ {(frameContext: any) => (
171
+ <StyleSheetManager target={frameContext.document.head}>{Providers}</StyleSheetManager>
172
+ )}
173
+ </FrameContextConsumer>
174
+ </S.StyledFrame>
175
+ </S.FrameWrapper>
176
+ ) : (
177
+ <>{Providers}</>
178
+ )}
179
+ {isVisible && <Toast {...toastProps} />}
77
180
  </S.BrowserWrapper>
78
181
  );
79
182
  };
@@ -84,14 +187,16 @@ interface IBrowserProps {
84
187
  footer?: any;
85
188
  selectedEditorID: number;
86
189
  url: string;
87
- setSelectedContent: any;
190
+ setSelectedContent?: any;
88
191
  isPage: boolean;
89
192
  theme: string;
90
193
  socials: any;
91
- cloudinaryName: string;
194
+ cloudinaryName: string | null;
195
+ damDomain: string | null;
92
196
  siteLangs: any[];
93
197
  disabled?: boolean;
94
198
  siteID?: number;
199
+ isPreview?: boolean;
95
200
  }
96
201
 
97
202
  export default Browser;
@@ -1,15 +1,16 @@
1
1
  import styled from "styled-components";
2
+ import Frame from "react-frame-component";
2
3
 
3
- export const BrowserWrapper = styled.div`
4
- background: #fff;
4
+ const BrowserWrapper = styled.div`
5
+ background-color: ${(p) => p.theme.color.uiBackground01};
5
6
  height: 100%;
6
7
  width: 100%;
7
8
  `;
8
9
 
9
- export const Wrapper = styled.div`
10
- border-left: 1px solid #DBDDE9;
11
- border-right: 1px solid #DBDDE9;
12
- border-bottom: 1px solid #DBDDE9;
10
+ const Wrapper = styled.div`
11
+ border-left: 1px solid ${(p) => p.theme.color.uiLine};
12
+ border-right: 1px solid ${(p) => p.theme.color.uiLine};
13
+ border-bottom: 1px solid ${(p) => p.theme.color.uiLine};
13
14
  overflow: auto;
14
15
  scroll-behavior: smooth;
15
16
  height: 100%;
@@ -20,19 +21,54 @@ export const Wrapper = styled.div`
20
21
  }
21
22
  `;
22
23
 
23
- // TODO: cambiar color del fondo por el del tema
24
- export const NavBar = styled.div`
25
- background-color: #e6e7f9;
24
+ const NavBar = styled.div`
25
+ display: flex;
26
+ background-color: ${(p) => p.theme.color.uiBackground03};
26
27
  border-radius: 4px 4px 0 0;
27
28
  height: calc(${(p) => p.theme.spacing.m} + (${(p) => p.theme.spacing.xs} * 2));
28
29
  padding: ${(p) => p.theme.spacing.xs} ${(p) => p.theme.spacing.m};
29
30
  `;
30
31
 
31
- export const NavUrl = styled.div`
32
+ const NavUrl = styled.div`
32
33
  ${(p) => p.theme.textStyle.uiXS};
33
- background-color: #ffffff;
34
+ background-color: ${(p) => p.theme.color.uiBackground02};
34
35
  border-radius: 10px;
35
36
  color: ${(p) => p.theme.color.textMediumEmphasis};
36
37
  height: ${(p) => p.theme.spacing.m};
37
38
  padding: ${(p) => p.theme.spacing.xxs} ${(p) => p.theme.spacing.s};
39
+ width: 100%;
40
+ `;
41
+
42
+ const NavActions = styled.div`
43
+ display: flex;
44
+ padding-left: ${(p) => p.theme.spacing.xs};
45
+ `;
46
+
47
+ const IconWrapper = styled.div<{ active?: boolean }>`
48
+ margin-left: ${(p) => p.theme.spacing.m};
49
+ cursor: pointer;
50
+ :hover {
51
+ svg {
52
+ path {
53
+ fill: ${(p) => p.theme.color.interactive01};
54
+ }
55
+ }
56
+ }
57
+ svg {
58
+ path {
59
+ fill: ${(p) => (p.active ? p.theme.color.interactive01 : p.theme.color.iconNonActive)};
60
+ }
61
+ }
38
62
  `;
63
+
64
+ const FrameWrapper = styled.div`
65
+ display: flex;
66
+ justify-content: center;
67
+ height: 100%;
68
+ `;
69
+
70
+ const StyledFrame = styled(Frame)`
71
+ box-shadow: ${(p) => p.theme.shadow.shadowL};
72
+ `;
73
+
74
+ export { BrowserWrapper, Wrapper, NavBar, NavUrl, NavActions, IconWrapper, FrameWrapper, StyledFrame };
@@ -28,7 +28,7 @@ const ConfigPanel = (props: IStateProps): JSX.Element => {
28
28
  isEditable,
29
29
  pageTitle,
30
30
  setHistoryPush,
31
- isPreviewMode,
31
+ isReadOnly,
32
32
  userEditing,
33
33
  theme,
34
34
  } = props;
@@ -41,7 +41,7 @@ const ConfigPanel = (props: IStateProps): JSX.Element => {
41
41
  const isGlobalPageNotEditable = isGlobal && isPage && !isEditable;
42
42
 
43
43
  const getForm = () => {
44
- if (isPreviewMode) {
44
+ if (isReadOnly) {
45
45
  return <PreviewForm setSelectedTab={setSelectedTab} selectedTab={selectedTab} userEditing={userEditing} />;
46
46
  } else if (showNavigationForm) {
47
47
  return <NavigationForm schema={schema} theme={theme} />;
@@ -102,7 +102,7 @@ interface IStateProps {
102
102
  isGlobal?: boolean;
103
103
  pageTitle?: string;
104
104
  setHistoryPush?: (path: string, isEditor: boolean) => void;
105
- isPreviewMode?: boolean;
105
+ isReadOnly?: boolean;
106
106
  userEditing?: IUserEditing | null;
107
107
  theme: string;
108
108
  }
@@ -12,7 +12,7 @@ import * as S from "./style";
12
12
  const RichText = (props: IRichTextProps): JSX.Element => {
13
13
  const { value, error, placeholder, onChange, disabled, editorID, handleValidation, html = false } = props;
14
14
 
15
- const rawData = html ? htmlToDraft(value) : markdownToDraft(value);
15
+ const rawData = html ? htmlToDraft(value || "") : markdownToDraft(value);
16
16
  const { contentBlocks, entityMap } = rawData;
17
17
  const contentState = html ? ContentState.createFromBlockArray(contentBlocks, entityMap) : convertFromRaw(rawData);
18
18
 
@@ -20,7 +20,7 @@ const RichText = (props: IRichTextProps): JSX.Element => {
20
20
  const timeOutRef = useRef<ReturnType<typeof setTimeout>>();
21
21
 
22
22
  useEffect(() => {
23
- const rawData = html ? htmlToDraft(value) : markdownToDraft(value);
23
+ const rawData = html ? htmlToDraft(value || "") : markdownToDraft(value);
24
24
  const { contentBlocks, entityMap } = rawData;
25
25
  const contentState = html ? ContentState.createFromBlockArray(contentBlocks, entityMap) : convertFromRaw(rawData);
26
26
  setEditorState(EditorState.createWithContent(contentState));
@@ -13,9 +13,18 @@ const findAnchorsFromPage = (page: IPage): ISelectOption[] => {
13
13
  const option = { value: module.anchorID, label: module.anchorID };
14
14
  options.push(option);
15
15
  }
16
+ if (module.elements) {
17
+ module.elements.forEach((element: any) => {
18
+ element.componentModules && element.componentModules.forEach((component: any) => {
19
+ if (component.anchorID && component.anchorID.trim() !== "") {
20
+ const option = { value: component.anchorID, label: component.anchorID };
21
+ options.push(option);
22
+ }
23
+ });
24
+ });
25
+ }
16
26
  });
17
27
  });
18
-
19
28
  return options;
20
29
  };
21
30
 
@@ -1,8 +1,13 @@
1
- import React from "react";
1
+ import * as React from "react";
2
2
 
3
- const SvgDesktop = props => (
4
- <svg width={24} height={24} fill="none" {...props}>
5
- <path fillRule="evenodd" clipRule="evenodd" d="M3 2h18c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2h-7v2h2v2H8v-2h2v-2H3c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2zm0 14h18V4H3v12z" fill="#5057FF" />
3
+ const SvgDesktop = (props) => (
4
+ <svg width={24} height={24} fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
5
+ <path
6
+ fillRule="evenodd"
7
+ clipRule="evenodd"
8
+ d="M3 2h18c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2h-7v2h2v2H8v-2h2v-2H3c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2Zm0 14h18V4H3v12Z"
9
+ fill="#5057FF"
10
+ />
6
11
  </svg>
7
12
  );
8
13
 
@@ -1,11 +1,11 @@
1
- import React from "react";
1
+ import * as React from "react";
2
2
 
3
- const SvgPhone = props => (
4
- <svg width={24} height={24} fill="none" {...props}>
3
+ const SvgPhone = (props) => (
4
+ <svg width={24} height={24} fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
5
5
  <path
6
6
  fillRule="evenodd"
7
7
  clipRule="evenodd"
8
- d="M15.5 1h-8A2.5 2.5 0 005 3.5v17A2.5 2.5 0 007.5 23h8a2.5 2.5 0 002.5-2.5v-17A2.5 2.5 0 0015.5 1zm-4 21c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM7 18h9V4H7v14z"
8
+ d="M15.5 1h-8A2.5 2.5 0 0 0 5 3.5v17A2.5 2.5 0 0 0 7.5 23h8a2.5 2.5 0 0 0 2.5-2.5v-17A2.5 2.5 0 0 0 15.5 1Zm-4 21c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5ZM7 18h9V4H7v14Z"
9
9
  fill="#5057FF"
10
10
  />
11
11
  </svg>
@@ -0,0 +1,12 @@
1
+ import * as React from "react";
2
+
3
+ const SvgShare = (props) => (
4
+ <svg width={24} height={24} fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
5
+ <path
6
+ d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92 0-1.61-1.31-2.92-2.92-2.92Z"
7
+ fill="#5057FF"
8
+ />
9
+ </svg>
10
+ );
11
+
12
+ export default SvgShare;
@@ -1,11 +1,11 @@
1
- import React from "react";
1
+ import * as React from "react";
2
2
 
3
- const SvgTablet = props => (
4
- <svg width={24} height={24} fill="none" {...props}>
3
+ const SvgTablet = (props) => (
4
+ <svg width={24} height={24} fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
5
5
  <path
6
6
  fillRule="evenodd"
7
7
  clipRule="evenodd"
8
- d="M18.5 0h-14A2.5 2.5 0 002 2.5v19A2.5 2.5 0 004.5 24h14a2.5 2.5 0 002.5-2.5v-19A2.5 2.5 0 0018.5 0zm-7 23c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM4 19h15V3H4v16z"
8
+ d="M18.5 0h-14A2.5 2.5 0 0 0 2 2.5v19A2.5 2.5 0 0 0 4.5 24h14a2.5 2.5 0 0 0 2.5-2.5v-19A2.5 2.5 0 0 0 18.5 0Zm-7 23c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5ZM4 19h15V3H4v16Z"
9
9
  fill="#5057FF"
10
10
  />
11
11
  </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M18 16.08C17.24 16.08 16.56 16.38 16.04 16.85L8.91 12.7C8.96 12.47 9 12.24 9 12C9 11.76 8.96 11.53 8.91 11.3L15.96 7.19C16.5 7.69 17.21 8 18 8C19.66 8 21 6.66 21 5C21 3.34 19.66 2 18 2C16.34 2 15 3.34 15 5C15 5.24 15.04 5.47 15.09 5.7L8.04 9.81C7.5 9.31 6.79 9 6 9C4.34 9 3 10.34 3 12C3 13.66 4.34 15 6 15C6.79 15 7.5 14.69 8.04 14.19L15.16 18.35C15.11 18.56 15.08 18.78 15.08 19C15.08 20.61 16.39 21.92 18 21.92C19.61 21.92 20.92 20.61 20.92 19C20.92 17.39 19.61 16.08 18 16.08Z" fill="#5057FF"/>
3
+ </svg>
@@ -2,6 +2,7 @@ import React from "react";
2
2
  import { withRouter, RouteComponentProps } from "react-router-dom";
3
3
 
4
4
  import { IErrorItem } from "@ax/types";
5
+ import { trimText } from "@ax/helpers";
5
6
  import {
6
7
  Button,
7
8
  Icon,
@@ -144,19 +145,30 @@ const AppBar = (props: IProps): JSX.Element => {
144
145
 
145
146
  return (
146
147
  <S.Header className={`${fixedClass} ${additionalClass}`} inversed={inversed}>
147
- <S.Wrapper>
148
+ <S.WrapperTitle>
148
149
  {backLink && (
149
150
  <Tooltip content="Back to content screen" bottom>
150
151
  <IconAction icon="FullArrowLeft" onClick={goToPages} inversed={inversed} />
151
152
  </Tooltip>
152
153
  )}
153
154
  <S.Title>
154
- {title}
155
+ {trimText(title, 50)}
155
156
  <S.Subtitle>{subtitle}</S.Subtitle>
156
157
  </S.Title>
157
- {tabs && <Tabs tabs={tabs.tabSet} active={tabs.selectedTab} setSelectedTab={tabs.action} isInAppBar={true} />}
158
- </S.Wrapper>
159
- <S.Wrapper>
158
+ </S.WrapperTitle>
159
+ {tabs && (
160
+ <S.WrapperTabs>
161
+ <Tabs
162
+ tabs={tabs.tabSet}
163
+ icons={tabs.icons}
164
+ active={tabs.selectedTab}
165
+ setSelectedTab={tabs.action}
166
+ isInAppBar={true}
167
+ inversed={inversed}
168
+ />
169
+ </S.WrapperTabs>
170
+ )}
171
+ <S.WrapperEnd>
160
172
  {searchAction && (
161
173
  <>
162
174
  <S.SearchWrapper>
@@ -220,7 +232,7 @@ const AppBar = (props: IProps): JSX.Element => {
220
232
  </FloatingMenu>
221
233
  </Tooltip>
222
234
  )}
223
- </S.Wrapper>
235
+ </S.WrapperEnd>
224
236
  </S.Header>
225
237
  );
226
238
  };
@@ -229,7 +241,7 @@ interface IAppBarProps {
229
241
  backLink?: boolean | string;
230
242
  rightButton?: { label: string; disabled?: boolean; action: (e: any) => void };
231
243
  rightLineButton?: { label: string; disabled?: boolean; action: (e: any) => void };
232
- tabs?: { tabSet: any; selectedTab: string; action: (e: any) => void };
244
+ tabs?: { tabSet?: any; icons?: { name: string; text: string }[]; selectedTab: string; action: (e: any) => void };
233
245
  downArrowMenu?: { displayed: boolean; options: any; button: any };
234
246
  title: string;
235
247
  subtitle?: string;