@griddo/ax 11.11.7 → 11.11.8-rc.1
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/config/jest/componentsMock.js +7 -5
- package/package.json +2 -2
- package/src/__tests__/components/Browser/Browser.test.tsx +438 -87
- package/src/__tests__/components/Browser/Browser.utils.test.ts +55 -0
- package/src/__tests__/components/ConfigPanel/ConfigPanel.test.tsx +1 -3
- package/src/__tests__/components/Fields/Button/Button.test.tsx +29 -27
- package/src/__tests__/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem/ErrorItem.test.tsx +158 -0
- package/src/__tests__/components/HeadingsPreviewModal/ErrorsBanner/ErrorsBanner.test.tsx +90 -0
- package/src/__tests__/components/HeadingsPreviewModal/HeadingsPreviewModal.test.tsx +178 -0
- package/src/__tests__/components/HeadingsPreviewModal/HeadingsPreviewModal.utils.test.tsx +150 -0
- package/src/__tests__/components/KeywordsPreviewModal/KeywordItem/KeywordItem.test.tsx +91 -0
- package/src/__tests__/components/KeywordsPreviewModal/KeywordsPreviewModal.test.tsx +122 -0
- package/src/__tests__/components/KeywordsPreviewModal/KeywordsPreviewModal.utils.test.ts +15 -0
- package/src/__tests__/components/KeywordsPreviewModal/atoms.test.tsx +101 -0
- package/src/__tests__/components/ResizePanel/ResizePanel.test.tsx +1 -1
- package/src/__tests__/modules/FramePreview/FramePreview.test.tsx +318 -0
- package/src/__tests__/modules/FramePreview/FramePreview.utils.test.ts +242 -0
- package/src/__tests__/modules/FramePreview/HeadingsOverlay/HeadingsOverlay.test.tsx +185 -0
- package/src/components/Browser/index.tsx +294 -144
- package/src/components/Browser/style.tsx +75 -6
- package/src/components/Browser/utils.tsx +13 -0
- package/src/components/BrowserContent/index.tsx +2 -2
- package/src/components/Button/index.tsx +2 -1
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +2 -4
- package/src/components/Fields/AsyncSelect/style.tsx +13 -0
- package/src/components/Fields/FieldGroup/index.tsx +5 -2
- package/src/components/Fields/FieldGroup/style.tsx +32 -7
- package/src/components/Fields/HeadingField/index.tsx +2 -2
- package/src/components/Fields/HiddenField/style.tsx +1 -1
- package/src/components/Fields/NumberField/index.tsx +15 -16
- package/src/components/Fields/NumberField/style.tsx +2 -0
- package/src/components/Fields/ReferenceField/index.tsx +1 -1
- package/src/components/Fields/SEOPreview/index.tsx +36 -0
- package/src/components/Fields/SEOPreview/style.tsx +24 -0
- package/src/components/Fields/Select/index.tsx +5 -1
- package/src/components/Fields/Select/style.tsx +56 -0
- package/src/components/Fields/SummaryButton/index.tsx +18 -9
- package/src/components/Fields/SummaryButton/style.tsx +1 -2
- package/src/components/Fields/TagsField/index.tsx +8 -9
- package/src/components/Fields/UrlField/index.tsx +26 -27
- package/src/components/Fields/index.tsx +2 -0
- package/src/components/FloatingNote/index.tsx +35 -0
- package/src/components/FloatingNote/style.tsx +26 -0
- package/src/components/FloatingPanel/index.tsx +5 -2
- package/src/components/FloatingPanel/style.tsx +2 -1
- package/src/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem/index.tsx +85 -0
- package/src/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem/style.tsx +80 -0
- package/src/components/HeadingsPreviewModal/ErrorsBanner/index.tsx +57 -0
- package/src/components/HeadingsPreviewModal/ErrorsBanner/style.tsx +82 -0
- package/src/components/HeadingsPreviewModal/HeadingItem/index.tsx +71 -0
- package/src/components/HeadingsPreviewModal/HeadingItem/style.tsx +77 -0
- package/src/components/HeadingsPreviewModal/index.tsx +146 -0
- package/src/components/HeadingsPreviewModal/style.tsx +82 -0
- package/src/components/HeadingsPreviewModal/utils.tsx +257 -0
- package/src/components/IconAction/index.tsx +1 -1
- package/src/components/KeywordsPreviewModal/KeywordItem/index.tsx +46 -0
- package/src/components/KeywordsPreviewModal/KeywordItem/style.tsx +64 -0
- package/src/components/KeywordsPreviewModal/atoms.tsx +96 -0
- package/src/components/KeywordsPreviewModal/index.tsx +99 -0
- package/src/components/KeywordsPreviewModal/style.tsx +87 -0
- package/src/components/KeywordsPreviewModal/utils.tsx +22 -0
- package/src/components/MainWrapper/AppBar/index.tsx +8 -1
- package/src/components/MainWrapper/index.tsx +7 -1
- package/src/components/Notification/index.tsx +2 -2
- package/src/components/OcassionalToast/index.tsx +8 -1
- package/src/components/OcassionalToast/style.tsx +15 -1
- package/src/components/PageFinder/index.tsx +1 -1
- package/src/components/ResizePanel/index.tsx +4 -3
- package/src/components/ResizePanel/style.tsx +1 -1
- package/src/components/SearchField/style.tsx +2 -2
- package/src/components/SideModal/index.tsx +2 -1
- package/src/components/Tabs/index.tsx +13 -4
- package/src/components/Tabs/style.tsx +7 -8
- package/src/components/Toast/index.tsx +4 -2
- package/src/components/Tooltip/index.tsx +4 -3
- package/src/components/index.tsx +8 -2
- package/src/forms/fields.tsx +70 -68
- package/src/hooks/forms.tsx +22 -1
- package/src/hooks/index.tsx +13 -3
- package/src/hooks/modals.tsx +103 -15
- package/src/hooks/users.tsx +25 -8
- package/src/modules/Forms/atoms.tsx +2 -2
- package/src/modules/FramePreview/HeadingsOverlay/index.tsx +113 -0
- package/src/modules/FramePreview/HeadingsOverlay/style.tsx +24 -0
- package/src/modules/FramePreview/index.tsx +55 -16
- package/src/modules/FramePreview/style.tsx +34 -2
- package/src/modules/FramePreview/utils.tsx +140 -0
- package/src/modules/GlobalEditor/Editor/index.tsx +37 -3
- package/src/modules/GlobalEditor/PageBrowser/index.tsx +19 -2
- package/src/modules/GlobalEditor/Preview/index.tsx +0 -2
- package/src/modules/GlobalEditor/Preview/style.tsx +1 -1
- package/src/modules/GlobalEditor/index.tsx +119 -57
- package/src/modules/PageEditor/Editor/index.tsx +33 -2
- package/src/modules/PageEditor/PageBrowser/index.tsx +20 -2
- package/src/modules/PageEditor/Preview/index.tsx +0 -2
- package/src/modules/PageEditor/Preview/style.tsx +1 -1
- package/src/modules/PageEditor/atoms.tsx +1 -1
- package/src/modules/PageEditor/index.tsx +130 -66
- package/src/modules/PublicPreview/index.tsx +8 -5
- package/src/schemas/pages/GlobalPage.ts +87 -70
- package/src/schemas/pages/Page.ts +87 -70
- package/src/types/index.tsx +12 -0
- package/src/components/PageInfoBanner/index.tsx +0 -38
- package/src/components/PageInfoBanner/styles.tsx +0 -40
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
1
2
|
import { connect } from "react-redux";
|
|
2
3
|
|
|
3
4
|
import { BrowserContent, Loading, Toast } from "@ax/components";
|
|
@@ -8,6 +9,9 @@ import { getDefaultTheme } from "@ax/helpers";
|
|
|
8
9
|
import { useOnMessageReceivedFromOutside, useToast, useURLSearchParam } from "@ax/hooks";
|
|
9
10
|
import type { FormContent, ILanguage, IRootState, ISite, ISocialState } from "@ax/types";
|
|
10
11
|
|
|
12
|
+
import HeadingsOverlay from "./HeadingsOverlay";
|
|
13
|
+
import { observeAndAddIdsToHeadings, observeAndHighlightKeywords } from "./utils";
|
|
14
|
+
|
|
11
15
|
import * as S from "./style";
|
|
12
16
|
|
|
13
17
|
const FramePreview = (props: IProps) => {
|
|
@@ -29,11 +33,19 @@ const FramePreview = (props: IProps) => {
|
|
|
29
33
|
copyModule,
|
|
30
34
|
} = props;
|
|
31
35
|
|
|
32
|
-
const
|
|
33
|
-
const
|
|
36
|
+
const previewParam = useURLSearchParam("preview");
|
|
37
|
+
const disabledParam = useURLSearchParam("disabled");
|
|
34
38
|
const type = useURLSearchParam("type");
|
|
35
|
-
|
|
39
|
+
const headingFilter = useURLSearchParam("headingFilter");
|
|
40
|
+
const keywordFilter = useURLSearchParam("keywordFilter");
|
|
41
|
+
|
|
42
|
+
const isPreviewMode = previewParam === "true";
|
|
43
|
+
const isDisabled = disabledParam === "true";
|
|
36
44
|
const isForm = type === "form";
|
|
45
|
+
const isHeadingsEditor = type === "headings";
|
|
46
|
+
const isKeywordsEditor = type === "keywords";
|
|
47
|
+
const keywords: string[] = pageContent?.metaKeywords || [];
|
|
48
|
+
const filteredKeywords = keywordFilter ? [keywordFilter] : keywords;
|
|
37
49
|
const setSelectedContent = isForm ? setSelectedFormContent : setSelectedPageContent;
|
|
38
50
|
const setContent = isForm ? setFormContent : setEditorContent;
|
|
39
51
|
const content = isForm ? formContent : pageContent;
|
|
@@ -42,15 +54,40 @@ const FramePreview = (props: IProps) => {
|
|
|
42
54
|
const { isVisible, toggleToast, setIsVisible, state: toastState } = useToast();
|
|
43
55
|
useOnMessageReceivedFromOutside(setContent, setSelectedContent);
|
|
44
56
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
document.body.classList.add("preview");
|
|
59
|
+
|
|
60
|
+
const handleMouseMove = (e: MouseEvent) => {
|
|
61
|
+
window.parent.postMessage(
|
|
62
|
+
{
|
|
63
|
+
type: "iframe-mousemove",
|
|
64
|
+
clientX: e.clientX,
|
|
65
|
+
},
|
|
66
|
+
"*",
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
71
|
+
return () => window.removeEventListener("mousemove", handleMouseMove);
|
|
72
|
+
}, []);
|
|
73
|
+
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (isDisabled) {
|
|
76
|
+
localStorage.setItem("selectedID", "0");
|
|
77
|
+
}
|
|
78
|
+
}, [isDisabled]);
|
|
79
|
+
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (isHeadingsEditor) {
|
|
82
|
+
return observeAndAddIdsToHeadings(document.body, headingFilter);
|
|
83
|
+
}
|
|
84
|
+
}, [isHeadingsEditor, headingFilter]);
|
|
85
|
+
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (isKeywordsEditor) {
|
|
88
|
+
return observeAndHighlightKeywords(document.body, filteredKeywords);
|
|
89
|
+
}
|
|
90
|
+
}, [isKeywordsEditor, filteredKeywords]);
|
|
54
91
|
|
|
55
92
|
const selectEditorID = (
|
|
56
93
|
selectedComponent: { editorID: number; component: any; type: string; parentEditorID: number },
|
|
@@ -67,7 +104,7 @@ const FramePreview = (props: IProps) => {
|
|
|
67
104
|
|
|
68
105
|
const isNavigationModule = ["header", "footer"].includes(selectedComponent.type);
|
|
69
106
|
|
|
70
|
-
if (
|
|
107
|
+
if (!isPreviewMode && (!isDisabled || isNavigationModule)) {
|
|
71
108
|
window.parent.postMessage({ type: "module-click", message: editorID }, "*");
|
|
72
109
|
setSelectedContent?.(editorID);
|
|
73
110
|
}
|
|
@@ -84,7 +121,7 @@ const FramePreview = (props: IProps) => {
|
|
|
84
121
|
const theme = currentSiteInfo ? currentSiteInfo.theme : globalTheme;
|
|
85
122
|
const langs = currentSiteInfo ? siteLangs : globalLangs;
|
|
86
123
|
const siteID = currentSiteInfo ? currentSiteInfo.id : canonicalSite;
|
|
87
|
-
const renderer = isForm ? "forms" :
|
|
124
|
+
const renderer = isForm ? "forms" : isPreviewMode ? "preview" : "editor";
|
|
88
125
|
|
|
89
126
|
const deleteModuleSelected = (editorID: number) => {
|
|
90
127
|
window.parent.postMessage({ type: "module-delete", message: editorID }, "*");
|
|
@@ -112,8 +149,8 @@ const FramePreview = (props: IProps) => {
|
|
|
112
149
|
if (isLoading) return <Loading />;
|
|
113
150
|
|
|
114
151
|
return (
|
|
115
|
-
|
|
116
|
-
|
|
152
|
+
<S.Wrapper>
|
|
153
|
+
<S.GlobalScrollStyle />
|
|
117
154
|
<BrowserContent
|
|
118
155
|
cloudinaryName={cloudinaryName}
|
|
119
156
|
theme={theme}
|
|
@@ -131,6 +168,8 @@ const FramePreview = (props: IProps) => {
|
|
|
131
168
|
renderer={renderer}
|
|
132
169
|
selectHoverEditorID={selectHoverEditorID}
|
|
133
170
|
/>
|
|
171
|
+
{isHeadingsEditor && <S.Velo />}
|
|
172
|
+
{isHeadingsEditor && <HeadingsOverlay headingFilter={headingFilter} />}
|
|
134
173
|
{isVisible && <Toast message={toastState} setIsVisible={setIsVisible} />}
|
|
135
174
|
</S.Wrapper>
|
|
136
175
|
);
|
|
@@ -1,4 +1,20 @@
|
|
|
1
|
-
import styled from "styled-components";
|
|
1
|
+
import styled, { createGlobalStyle } from "styled-components";
|
|
2
|
+
|
|
3
|
+
const GlobalScrollStyle = createGlobalStyle`
|
|
4
|
+
body.preview {
|
|
5
|
+
overflow-x: hidden;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
body.preview::-webkit-scrollbar {
|
|
9
|
+
-webkit-appearance: none;
|
|
10
|
+
width: 4px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
body.preview::-webkit-scrollbar-thumb {
|
|
14
|
+
border-radius: 4px;
|
|
15
|
+
background-color: ${(p: any) => p.theme.colors.iconNonActive};
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
2
18
|
|
|
3
19
|
const Wrapper = styled.div`
|
|
4
20
|
scroll-behavior: smooth;
|
|
@@ -12,6 +28,22 @@ const Wrapper = styled.div`
|
|
|
12
28
|
body.preview:not(&) {
|
|
13
29
|
min-width: 0 !important;
|
|
14
30
|
}
|
|
31
|
+
|
|
32
|
+
.gdd-keyword {
|
|
33
|
+
background-color: #FFEF9A !important;
|
|
34
|
+
color: #1C1547 !important;
|
|
35
|
+
padding: ${(p) => `0 ${p.theme.spacing.xxs}`};
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
const Velo = styled.div`
|
|
40
|
+
position: fixed;
|
|
41
|
+
top: 0;
|
|
42
|
+
left: 0;
|
|
43
|
+
height: 100%;
|
|
44
|
+
right: 0;
|
|
45
|
+
background: rgba(255, 255, 255, 0.4);
|
|
46
|
+
z-index: 1000;
|
|
15
47
|
`;
|
|
16
48
|
|
|
17
|
-
export { Wrapper };
|
|
49
|
+
export { Wrapper, Velo, GlobalScrollStyle };
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
const addIdsToHeadings = (container: HTMLElement, headingFilter: string | null): void => {
|
|
2
|
+
const selected = headingFilter ? headingFilter : "h1, h2, h3, h4, h5, h6";
|
|
3
|
+
const headings = container.querySelectorAll<HTMLElement>(selected);
|
|
4
|
+
|
|
5
|
+
headings.forEach((heading, index) => {
|
|
6
|
+
const text = heading.textContent?.trim();
|
|
7
|
+
if (!text) return;
|
|
8
|
+
|
|
9
|
+
heading.dataset.griddoid = `heading-${index + 1}`;
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const observeAndAddIdsToHeadings = (container: HTMLElement, headingFilter: string | null): (() => void) => {
|
|
14
|
+
addIdsToHeadings(container, headingFilter);
|
|
15
|
+
|
|
16
|
+
const observer = new MutationObserver(() => {
|
|
17
|
+
addIdsToHeadings(container, headingFilter);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
observer.observe(container, {
|
|
21
|
+
childList: true,
|
|
22
|
+
subtree: true,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return () => observer.disconnect();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const KEYWORD_HIGHLIGHT_CLASS = "gdd-keyword";
|
|
29
|
+
|
|
30
|
+
const removeKeywordHighlights = (container: HTMLElement): void => {
|
|
31
|
+
const marks = container.querySelectorAll<HTMLElement>(`mark.${KEYWORD_HIGHLIGHT_CLASS}`);
|
|
32
|
+
|
|
33
|
+
marks.forEach((mark) => {
|
|
34
|
+
const parent = mark.parentNode;
|
|
35
|
+
if (!parent) return;
|
|
36
|
+
parent.replaceChild(document.createTextNode(mark.textContent || ""), mark);
|
|
37
|
+
parent.normalize();
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const buildKeywordsRegex = (keywords: string[]): RegExp | null => {
|
|
42
|
+
const escapedKeywords = keywords
|
|
43
|
+
.filter((k) => k.trim())
|
|
44
|
+
.sort((a, b) => b.length - a.length)
|
|
45
|
+
.map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
46
|
+
|
|
47
|
+
if (!escapedKeywords.length) return null;
|
|
48
|
+
|
|
49
|
+
return new RegExp(`(${escapedKeywords.join("|")})`, "gi");
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const collectTextNodes = (container: HTMLElement): Text[] => {
|
|
53
|
+
const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, {
|
|
54
|
+
acceptNode: (node) => {
|
|
55
|
+
const parent = node.parentElement;
|
|
56
|
+
if (!parent) return NodeFilter.FILTER_REJECT;
|
|
57
|
+
if (["SCRIPT", "STYLE"].includes(parent.tagName)) return NodeFilter.FILTER_REJECT;
|
|
58
|
+
if (parent.classList.contains(KEYWORD_HIGHLIGHT_CLASS)) return NodeFilter.FILTER_REJECT;
|
|
59
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const textNodes: Text[] = [];
|
|
64
|
+
let current = walker.nextNode();
|
|
65
|
+
while (current) {
|
|
66
|
+
textNodes.push(current as Text);
|
|
67
|
+
current = walker.nextNode();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return textNodes;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const wrapMatches = (text: string, regex: RegExp): DocumentFragment => {
|
|
74
|
+
const fragment = document.createDocumentFragment();
|
|
75
|
+
let lastIndex = 0;
|
|
76
|
+
let match = regex.exec(text);
|
|
77
|
+
|
|
78
|
+
while (match !== null) {
|
|
79
|
+
if (match.index > lastIndex) {
|
|
80
|
+
fragment.appendChild(document.createTextNode(text.slice(lastIndex, match.index)));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const mark = document.createElement("mark");
|
|
84
|
+
mark.className = KEYWORD_HIGHLIGHT_CLASS;
|
|
85
|
+
mark.textContent = match[0];
|
|
86
|
+
fragment.appendChild(mark);
|
|
87
|
+
|
|
88
|
+
lastIndex = regex.lastIndex;
|
|
89
|
+
match = regex.exec(text);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (lastIndex < text.length) {
|
|
93
|
+
fragment.appendChild(document.createTextNode(text.slice(lastIndex)));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return fragment;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const highlightKeywords = (container: HTMLElement, keywords: string[]): void => {
|
|
100
|
+
removeKeywordHighlights(container);
|
|
101
|
+
|
|
102
|
+
const regex = buildKeywordsRegex(keywords);
|
|
103
|
+
if (!regex) return;
|
|
104
|
+
|
|
105
|
+
const textNodes = collectTextNodes(container);
|
|
106
|
+
|
|
107
|
+
for (const textNode of textNodes) {
|
|
108
|
+
const text = textNode.textContent || "";
|
|
109
|
+
if (!regex.test(text)) continue;
|
|
110
|
+
regex.lastIndex = 0;
|
|
111
|
+
|
|
112
|
+
const fragment = wrapMatches(text, regex);
|
|
113
|
+
textNode.parentNode?.replaceChild(fragment, textNode);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const observeAndHighlightKeywords = (container: HTMLElement, keywords: string[]): (() => void) => {
|
|
118
|
+
const observer = new MutationObserver(() => {
|
|
119
|
+
observer.disconnect();
|
|
120
|
+
highlightKeywords(container, keywords);
|
|
121
|
+
observer.observe(container, { childList: true, subtree: true });
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
highlightKeywords(container, keywords);
|
|
125
|
+
observer.observe(container, { childList: true, subtree: true });
|
|
126
|
+
|
|
127
|
+
return () => {
|
|
128
|
+
observer.disconnect();
|
|
129
|
+
removeKeywordHighlights(container);
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export {
|
|
134
|
+
addIdsToHeadings,
|
|
135
|
+
observeAndAddIdsToHeadings,
|
|
136
|
+
highlightKeywords,
|
|
137
|
+
removeKeywordHighlights,
|
|
138
|
+
observeAndHighlightKeywords,
|
|
139
|
+
KEYWORD_HIGHLIGHT_CLASS,
|
|
140
|
+
};
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import { connect } from "react-redux";
|
|
3
2
|
import { pageEditorActions } from "@ax/containers/PageEditor";
|
|
4
3
|
import { ConfigPanel, ResizePanel } from "@ax/components";
|
|
5
|
-
import {
|
|
4
|
+
import type {
|
|
5
|
+
HeadingFilter,
|
|
6
|
+
IBreadcrumbItem,
|
|
7
|
+
IModule,
|
|
8
|
+
INotification,
|
|
9
|
+
IRootState,
|
|
10
|
+
ISchema,
|
|
11
|
+
IUserEditing,
|
|
12
|
+
} from "@ax/types";
|
|
6
13
|
import PageBrowser from "../PageBrowser";
|
|
7
14
|
|
|
8
15
|
const Editor = (props: IProps) => {
|
|
@@ -33,6 +40,12 @@ const Editor = (props: IProps) => {
|
|
|
33
40
|
setNotification,
|
|
34
41
|
isEditLive,
|
|
35
42
|
isDisabled,
|
|
43
|
+
toggleHeadingsPreview,
|
|
44
|
+
toggleKeywordsPreview,
|
|
45
|
+
isHeadingsPreviewOpen,
|
|
46
|
+
isKeywordsPreviewOpen,
|
|
47
|
+
headingsFilter,
|
|
48
|
+
keywordsFilter,
|
|
36
49
|
} = props;
|
|
37
50
|
|
|
38
51
|
const actions = {
|
|
@@ -46,11 +59,26 @@ const Editor = (props: IProps) => {
|
|
|
46
59
|
copyModuleAction: copyModule,
|
|
47
60
|
pasteModuleAction: pasteModule,
|
|
48
61
|
setNotificationAction: setNotification,
|
|
62
|
+
toggleHeadingsPreviewAction: toggleHeadingsPreview,
|
|
63
|
+
toggleKeywordsPreviewAction: toggleKeywordsPreview,
|
|
49
64
|
};
|
|
50
65
|
|
|
51
66
|
return (
|
|
52
67
|
<ResizePanel
|
|
53
|
-
|
|
68
|
+
disabled={isHeadingsPreviewOpen || isKeywordsPreviewOpen}
|
|
69
|
+
leftPanel={
|
|
70
|
+
<PageBrowser
|
|
71
|
+
isReadOnly={isReadOnly || isEditLive}
|
|
72
|
+
theme={theme}
|
|
73
|
+
browserRef={browserRef}
|
|
74
|
+
isHeadingsPreviewOpen={isHeadingsPreviewOpen}
|
|
75
|
+
toggleHeadingsPreview={toggleHeadingsPreview}
|
|
76
|
+
headingsFilter={headingsFilter}
|
|
77
|
+
toggleKeywordsPreview={toggleKeywordsPreview}
|
|
78
|
+
isKeywordsPreviewOpen={isKeywordsPreviewOpen}
|
|
79
|
+
keywordsFilter={keywordsFilter}
|
|
80
|
+
/>
|
|
81
|
+
}
|
|
54
82
|
rightPanel={
|
|
55
83
|
<ConfigPanel
|
|
56
84
|
schema={schema}
|
|
@@ -100,6 +128,8 @@ interface IPageBrowserDispatchProps {
|
|
|
100
128
|
copyModule(editorID: number[]): boolean | number;
|
|
101
129
|
pasteModule(editorID: number, key: string, modulesToPaste: IModule[]): Promise<{ error?: INotification }>;
|
|
102
130
|
setNotification: (notification: INotification) => void;
|
|
131
|
+
toggleHeadingsPreview: () => void;
|
|
132
|
+
toggleKeywordsPreview: () => void;
|
|
103
133
|
isGlobal: boolean;
|
|
104
134
|
isEditable: boolean;
|
|
105
135
|
isReadOnly: boolean;
|
|
@@ -107,6 +137,10 @@ interface IPageBrowserDispatchProps {
|
|
|
107
137
|
browserRef: any;
|
|
108
138
|
isEditLive: boolean;
|
|
109
139
|
isDisabled: boolean;
|
|
140
|
+
isHeadingsPreviewOpen: boolean;
|
|
141
|
+
isKeywordsPreviewOpen: boolean;
|
|
142
|
+
headingsFilter: HeadingFilter;
|
|
143
|
+
keywordsFilter: string[];
|
|
110
144
|
}
|
|
111
145
|
|
|
112
146
|
type IProps = IEditorStateProps & IPageBrowserDispatchProps;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { connect } from "react-redux";
|
|
2
2
|
import { pageEditorActions } from "@ax/containers/PageEditor";
|
|
3
|
-
|
|
4
3
|
import { Browser } from "@ax/components";
|
|
5
|
-
import type { ILanguage, IRootState, ISchema, ISocialState } from "@ax/types";
|
|
4
|
+
import type { HeadingFilter, ILanguage, IRootState, ISchema, ISocialState } from "@ax/types";
|
|
6
5
|
|
|
7
6
|
const PageBrowser = (props: IProps) => {
|
|
8
7
|
const {
|
|
@@ -15,15 +14,22 @@ const PageBrowser = (props: IProps) => {
|
|
|
15
14
|
isReadOnly,
|
|
16
15
|
isPreview,
|
|
17
16
|
browserRef,
|
|
17
|
+
isHeadingsPreviewOpen = false,
|
|
18
|
+
isKeywordsPreviewOpen = false,
|
|
19
|
+
headingsFilter,
|
|
20
|
+
keywordsFilter,
|
|
18
21
|
deleteModule,
|
|
19
22
|
duplicateModule,
|
|
20
23
|
copyModule,
|
|
21
24
|
setScrollEditorID,
|
|
25
|
+
toggleHeadingsPreview,
|
|
26
|
+
toggleKeywordsPreview,
|
|
22
27
|
} = props;
|
|
23
28
|
|
|
24
29
|
const slugWithSlash = slug ? (slug.startsWith("/") ? slug : `/${slug}`) : "";
|
|
25
30
|
const pathWithoutSlash = path ? (path.endsWith("/") ? path.slice(0, -1) : path) : "";
|
|
26
31
|
const url = `${pathWithoutSlash}${slugWithSlash}`;
|
|
32
|
+
const editorType = isHeadingsPreviewOpen ? "headings" : isKeywordsPreviewOpen ? "keywords" : "page";
|
|
27
33
|
|
|
28
34
|
const actions = {
|
|
29
35
|
deleteModuleAction: deleteModule,
|
|
@@ -48,6 +54,11 @@ const PageBrowser = (props: IProps) => {
|
|
|
48
54
|
showIframe={true}
|
|
49
55
|
browserRef={browserRef}
|
|
50
56
|
actions={actions}
|
|
57
|
+
editorType={editorType}
|
|
58
|
+
toggleHeadingsPreview={toggleHeadingsPreview}
|
|
59
|
+
headingFilter={headingsFilter}
|
|
60
|
+
toggleKeywordsPreview={toggleKeywordsPreview}
|
|
61
|
+
keywordsFilter={keywordsFilter}
|
|
51
62
|
/>
|
|
52
63
|
);
|
|
53
64
|
};
|
|
@@ -68,10 +79,16 @@ interface IPageBrowserDispatchProps {
|
|
|
68
79
|
isReadOnly: boolean;
|
|
69
80
|
isPreview?: boolean;
|
|
70
81
|
browserRef?: any;
|
|
82
|
+
isHeadingsPreviewOpen?: boolean;
|
|
83
|
+
isKeywordsPreviewOpen?: boolean;
|
|
84
|
+
headingsFilter?: HeadingFilter;
|
|
85
|
+
keywordsFilter?: string[];
|
|
71
86
|
deleteModule(editorID: number[]): void;
|
|
72
87
|
duplicateModule(editorID: number[]): number;
|
|
73
88
|
copyModule(editorID: number[]): number | boolean;
|
|
74
89
|
setScrollEditorID(editorID: number | null): void;
|
|
90
|
+
toggleHeadingsPreview?(): void;
|
|
91
|
+
toggleKeywordsPreview?(): void;
|
|
75
92
|
}
|
|
76
93
|
|
|
77
94
|
type IProps = IPageBrowserStateProps & IPageBrowserDispatchProps;
|