@griddo/ax 11.0.29-rc.0 → 11.0.30-rc.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/config/griddo-config/cx-polyfills/componentsBundle.js +1 -1
- package/package.json +2 -2
- package/scripts/griddo-sync-schemas.js +49 -42
- package/src/GlobalStore.tsx +3 -0
- package/src/__tests__/components/TableFilters/LiveFilter/LiveFilter.test.tsx +6 -0
- package/src/api/forms.tsx +191 -0
- package/src/api/index.tsx +2 -0
- package/src/components/Browser/index.tsx +42 -37
- package/src/components/Browser/style.tsx +3 -3
- package/src/components/BrowserContent/index.tsx +1 -1
- package/src/components/ConfigPanel/Form/index.tsx +6 -5
- package/src/components/ConfigPanel/GlobalPageForm/index.tsx +3 -1
- package/src/components/ConfigPanel/Header/index.tsx +1 -0
- package/src/components/Fields/ComponentArray/MixableComponentArray/AddItemButton/index.tsx +4 -5
- package/src/components/Fields/ComponentArray/MixableComponentArray/index.tsx +4 -4
- package/src/components/Fields/ComponentArray/helpers.tsx +1 -1
- package/src/components/Fields/FormFieldArray/index.tsx +13 -0
- package/src/components/Fields/ReferenceField/AutoPanel/index.tsx +1 -2
- package/src/components/Fields/ReferenceField/Context/index.tsx +0 -2
- package/src/components/Fields/ReferenceField/ItemList/index.tsx +1 -2
- package/src/components/Fields/ReferenceField/ManualPanel/index.tsx +2 -2
- package/src/components/Fields/ReferenceField/index.tsx +1 -5
- package/src/components/Fields/TranslateButton/index.tsx +48 -10
- package/src/components/Fields/Wysiwyg/helpers.tsx +2 -2
- package/src/components/Fields/Wysiwyg/index.tsx +4 -11
- package/src/components/Fields/index.tsx +2 -0
- package/src/components/FieldsBehavior/index.tsx +8 -2
- package/src/components/Icon/components/Form.js +12 -0
- package/src/components/Icon/svgs/Form.svg +3 -0
- package/src/components/LanguageMenu/index.tsx +30 -27
- package/src/components/MainWrapper/AppBar/index.tsx +23 -68
- package/src/components/MainWrapper/index.tsx +4 -9
- package/src/components/MenuItem/index.tsx +2 -2
- package/src/components/ResizePanel/index.tsx +3 -2
- package/src/components/ResizePanel/style.tsx +11 -9
- package/src/components/SearchField/style.tsx +2 -2
- package/src/components/SideModal/SideModalOption/index.tsx +3 -2
- package/src/components/SideModal/SideModalOption/style.tsx +2 -2
- package/src/components/SideModal/index.tsx +11 -4
- package/src/components/SideModal/style.tsx +9 -7
- package/src/components/TableFilters/LiveFilter/index.tsx +4 -3
- package/src/components/index.tsx +4 -0
- package/src/containers/App/reducer.tsx +4 -1
- package/src/containers/Forms/actions.tsx +853 -0
- package/src/containers/Forms/constants.tsx +46 -0
- package/src/containers/Forms/index.tsx +4 -0
- package/src/containers/Forms/interfaces.tsx +95 -0
- package/src/containers/Forms/reducer.tsx +81 -0
- package/src/containers/Forms/utils.tsx +42 -0
- package/src/containers/Navigation/Menu/actions.tsx +6 -13
- package/src/containers/Navigation/Menu/reducer.tsx +0 -4
- package/src/containers/PageEditor/actions.tsx +3 -2
- package/src/containers/PageEditor/reducer.tsx +2 -2
- package/src/forms/editor.tsx +3 -1
- package/src/helpers/index.tsx +12 -1
- package/src/helpers/schemas.tsx +35 -9
- package/src/helpers/structuredData.tsx +3 -1
- package/src/helpers/themes.tsx +3 -1
- package/src/helpers/thumbnails.tsx +20 -2
- package/src/modules/Analytics/GroupPanel/utils.tsx +3 -1
- package/src/modules/App/Routing/NavMenu/index.tsx +16 -6
- package/src/modules/App/Routing/index.tsx +26 -9
- package/src/modules/Categories/CategoriesList/CategoryItem/index.tsx +4 -4
- package/src/modules/Categories/CategoriesList/index.tsx +16 -16
- package/src/modules/Content/BulkHeader/TableHeader/index.tsx +1 -5
- package/src/modules/Content/PageItem/index.tsx +34 -33
- package/src/modules/Content/index.tsx +23 -36
- package/src/modules/Content/utils.tsx +3 -1
- package/src/modules/Forms/FormCategoriesList/BulkHeader/TableHeader/index.tsx +42 -0
- package/src/modules/Forms/FormCategoriesList/BulkHeader/TableHeader/style.tsx +36 -0
- package/src/modules/Forms/FormCategoriesList/BulkHeader/index.tsx +37 -0
- package/src/modules/Forms/FormCategoriesList/BulkHeader/style.tsx +9 -0
- package/src/modules/Forms/FormCategoriesList/CategoryItem/index.tsx +125 -0
- package/src/modules/Forms/FormCategoriesList/CategoryItem/style.tsx +91 -0
- package/src/modules/Forms/FormCategoriesList/CategoryPanel/Form/index.tsx +50 -0
- package/src/modules/Forms/FormCategoriesList/CategoryPanel/index.tsx +112 -0
- package/src/modules/Forms/FormCategoriesList/CategoryPanel/style.tsx +31 -0
- package/src/modules/Forms/FormCategoriesList/atoms.tsx +33 -0
- package/src/modules/Forms/FormCategoriesList/hooks.tsx +61 -0
- package/src/modules/Forms/FormCategoriesList/index.tsx +245 -0
- package/src/modules/Forms/FormCategoriesList/style.tsx +82 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Form/ConnectedField/Field/index.tsx +95 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Form/ConnectedField/TemplateManager/index.tsx +102 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Form/ConnectedField/TemplateManager/style.tsx +9 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Form/ConnectedField/index.tsx +109 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Form/index.tsx +76 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Form/style.tsx +28 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Header/index.tsx +132 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Header/style.tsx +30 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/index.tsx +86 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/style.tsx +7 -0
- package/src/modules/Forms/FormEditor/Editor/index.tsx +106 -0
- package/src/modules/Forms/FormEditor/PageBrowser/index.tsx +96 -0
- package/src/modules/Forms/FormEditor/index.tsx +295 -0
- package/src/modules/Forms/FormEditor/style.tsx +32 -0
- package/src/modules/Forms/FormList/BulkHeader/TableHeader/index.tsx +61 -0
- package/src/modules/Forms/FormList/BulkHeader/TableHeader/style.tsx +47 -0
- package/src/modules/Forms/FormList/BulkHeader/index.tsx +60 -0
- package/src/modules/Forms/FormList/FormItem/index.tsx +218 -0
- package/src/modules/Forms/FormList/FormItem/style.tsx +87 -0
- package/src/modules/Forms/FormList/Summary/index.tsx +51 -0
- package/src/modules/Forms/FormList/Summary/style.tsx +46 -0
- package/src/modules/Forms/FormList/TemplateModal/index.tsx +67 -0
- package/src/modules/Forms/FormList/TemplateModal/style.tsx +54 -0
- package/src/modules/Forms/FormList/index.tsx +266 -0
- package/src/modules/Forms/FormList/style.tsx +31 -0
- package/src/modules/Forms/FormsMenu/MenuGroup/index.tsx +57 -0
- package/src/modules/Forms/FormsMenu/MenuGroup/style.tsx +55 -0
- package/src/modules/Forms/FormsMenu/index.tsx +78 -0
- package/src/modules/Forms/FormsMenu/style.tsx +9 -0
- package/src/modules/Forms/atoms.tsx +111 -0
- package/src/modules/Forms/style.tsx +11 -0
- package/src/modules/FramePreview/index.tsx +26 -12
- package/src/modules/GlobalEditor/index.tsx +52 -21
- package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +32 -15
- package/src/modules/Navigation/Defaults/Item/atoms.tsx +6 -5
- package/src/modules/Navigation/Defaults/Item/index.tsx +10 -10
- package/src/modules/Navigation/Defaults/index.tsx +7 -6
- package/src/modules/Navigation/Menus/List/Nav/index.tsx +2 -10
- package/src/modules/Navigation/Menus/List/Table/SidePanel/Form/index.tsx +14 -11
- package/src/modules/Navigation/Menus/List/index.tsx +15 -16
- package/src/modules/Navigation/Menus/index.tsx +9 -17
- package/src/modules/PageEditor/index.tsx +54 -31
- package/src/modules/Settings/Globals/index.tsx +3 -1
- package/src/modules/Settings/Languages/Table/Item/index.tsx +11 -9
- package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/index.tsx +1 -1
- package/src/modules/StructuredData/Form/index.tsx +41 -28
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +1 -5
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +6 -8
- package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/index.tsx +5 -7
- package/src/modules/StructuredData/StructuredDataList/index.tsx +13 -10
- package/src/modules/StructuredData/StructuredDataList/utils.tsx +2 -1
- package/src/routes/multisite.tsx +53 -16
- package/src/routes/site.tsx +1 -0
- package/src/schemas/pages/FormPage.tsx +49 -0
- package/src/schemas/pages/GlobalPage.tsx +1 -0
- package/src/schemas/pages/Page.tsx +4 -1
- package/src/schemas/pages/index.tsx +2 -1
- package/src/types/forms.tsx +87 -0
- package/src/types/index.tsx +43 -7
- /package/src/modules/Navigation/Menus/{helpers.tsx → List/helpers.tsx} +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { ISchema, ISchemaTab, ISchemaField } from "@ax/types";
|
|
4
|
+
import { Tabs } from "@ax/components";
|
|
5
|
+
|
|
6
|
+
import ConnectedField from "./ConnectedField";
|
|
7
|
+
|
|
8
|
+
import * as S from "./style";
|
|
9
|
+
|
|
10
|
+
export const Form = (props: IFormProps): JSX.Element => {
|
|
11
|
+
const { schema, selectedTab, actions, isGlobal, theme, headerHeight, setSelectedTab, setHistoryPush } = props;
|
|
12
|
+
|
|
13
|
+
const tabContent = schema.configTabs.find((tab: ISchemaTab) => tab.title.toLowerCase() === selectedTab);
|
|
14
|
+
const setTab = (tab: string) => setSelectedTab(tab);
|
|
15
|
+
|
|
16
|
+
const generateFields = (field: ISchemaField) => {
|
|
17
|
+
const { setSelectedContent } = props;
|
|
18
|
+
const { key, whiteList } = field;
|
|
19
|
+
|
|
20
|
+
const goTo = (editorID: number) => setSelectedContent(editorID);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ConnectedField
|
|
24
|
+
selectedTab={selectedTab}
|
|
25
|
+
whiteList={whiteList}
|
|
26
|
+
key={key}
|
|
27
|
+
objKey={key}
|
|
28
|
+
field={field}
|
|
29
|
+
goTo={goTo}
|
|
30
|
+
actions={actions}
|
|
31
|
+
componentType={schema.schemaType}
|
|
32
|
+
isGlobal={isGlobal}
|
|
33
|
+
theme={theme}
|
|
34
|
+
setHistoryPush={setHistoryPush}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const getTabs = () => {
|
|
40
|
+
const isPageSchema = schema.schemaType === "page";
|
|
41
|
+
const mappedTabs = schema.configTabs.reduce((acc: string[], curr: ISchemaTab) => {
|
|
42
|
+
const currTitle = curr.title.toLowerCase();
|
|
43
|
+
if (!isPageSchema || (isPageSchema && (currTitle === "content" || currTitle === "config"))) {
|
|
44
|
+
return [...acc, currTitle];
|
|
45
|
+
}
|
|
46
|
+
return acc;
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
49
|
+
return mappedTabs;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const tabs = getTabs();
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<S.Wrapper data-testid="form-section">
|
|
56
|
+
<S.TabsWrapper headerHeight={headerHeight}>
|
|
57
|
+
<Tabs tabs={tabs} active={selectedTab} setSelectedTab={setTab} />
|
|
58
|
+
</S.TabsWrapper>
|
|
59
|
+
{tabContent && tabContent.fields.map((field: ISchemaField) => generateFields(field))}
|
|
60
|
+
</S.Wrapper>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export interface IFormProps {
|
|
65
|
+
selectedTab: string;
|
|
66
|
+
schema: ISchema | Record<string, never>;
|
|
67
|
+
actions: any;
|
|
68
|
+
setSelectedTab(tab: string): void;
|
|
69
|
+
setSelectedContent(editorID: number): void;
|
|
70
|
+
isGlobal?: boolean;
|
|
71
|
+
theme: string;
|
|
72
|
+
setHistoryPush?: (path: string, isEditor: boolean) => void;
|
|
73
|
+
headerHeight: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default Form;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
const Wrapper = styled.section``;
|
|
4
|
+
|
|
5
|
+
const FieldWrapper = styled.div`
|
|
6
|
+
${(p) => p.theme.textStyle.uiXS};
|
|
7
|
+
margin-top: ${(p) => p.theme.spacing.s};
|
|
8
|
+
margin-bottom: ${(p) => p.theme.spacing.s};
|
|
9
|
+
background-color: ${(p) => p.theme.color.uiBackground03};
|
|
10
|
+
padding: ${(p) => p.theme.spacing.s};
|
|
11
|
+
border-radius: ${(p) => p.theme.radii.s};
|
|
12
|
+
color: ${(p) => p.theme.color.textMediumEmphasis};
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
const Link = styled.span`
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
font-weight: bold;
|
|
18
|
+
color: ${(p) => p.theme.color?.interactive01};
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
const TabsWrapper = styled.div<{ headerHeight: number }>`
|
|
22
|
+
background-color: ${(p) => p.theme.color.uiBackground01};
|
|
23
|
+
position: sticky;
|
|
24
|
+
top: ${(p) => (p.headerHeight ? `calc(63px + ${p.headerHeight}px)` : "63px")};
|
|
25
|
+
z-index: 3;
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
export { Wrapper, FieldWrapper, Link, TabsWrapper };
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import React, { memo, useCallback, useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { IBreadcrumbItem, ISchema } from "@ax/types";
|
|
4
|
+
import { Breadcrumb, Toast } from "@ax/components";
|
|
5
|
+
import { useToast } from "@ax/hooks";
|
|
6
|
+
|
|
7
|
+
import * as S from "./style";
|
|
8
|
+
|
|
9
|
+
const Header = (props: IHeaderProps) => {
|
|
10
|
+
const {
|
|
11
|
+
breadcrumb,
|
|
12
|
+
schema,
|
|
13
|
+
selectedParent,
|
|
14
|
+
actions,
|
|
15
|
+
headerRef,
|
|
16
|
+
setSelectedContent,
|
|
17
|
+
setHeaderHeight,
|
|
18
|
+
hasStickyHeader,
|
|
19
|
+
} = props;
|
|
20
|
+
|
|
21
|
+
const { duplicateModuleAction, deleteModuleAction, copyModuleAction } = actions;
|
|
22
|
+
const title = breadcrumb[breadcrumb.length - 1].displayName;
|
|
23
|
+
const editorID = breadcrumb[breadcrumb.length - 1].editorID;
|
|
24
|
+
const parentID = breadcrumb.length > 1 ? breadcrumb[breadcrumb.length - 2].editorID : breadcrumb[0].editorID;
|
|
25
|
+
const isFormComponent = schema.schemaType === "formComponent";
|
|
26
|
+
const isInArray = Array.isArray(selectedParent);
|
|
27
|
+
|
|
28
|
+
const { isVisible, toggleToast, setIsVisible } = useToast();
|
|
29
|
+
const [y, setY] = useState(window.scrollY);
|
|
30
|
+
const [scrollDown, setScrollDown] = useState(false);
|
|
31
|
+
const [breadcrumbOld, setBreadcrumbOld] = useState(breadcrumb);
|
|
32
|
+
|
|
33
|
+
const handleNavigation = useCallback(
|
|
34
|
+
(e: Event) => {
|
|
35
|
+
const window = e.currentTarget as Window;
|
|
36
|
+
const height = headerRef.current ? headerRef.current.offsetHeight + headerRef.current.offsetTop : 0;
|
|
37
|
+
if (isInArray && y > window.scrollY) {
|
|
38
|
+
setHeaderHeight(height);
|
|
39
|
+
setScrollDown(false);
|
|
40
|
+
} else if (y > height && y < window.scrollY) {
|
|
41
|
+
setHeaderHeight(0);
|
|
42
|
+
setScrollDown(true);
|
|
43
|
+
}
|
|
44
|
+
setY(window.scrollY);
|
|
45
|
+
},
|
|
46
|
+
[y, headerRef, setHeaderHeight, isInArray]
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
setY(window.scrollY);
|
|
51
|
+
window.addEventListener("scroll", handleNavigation);
|
|
52
|
+
return () => {
|
|
53
|
+
window.removeEventListener("scroll", handleNavigation);
|
|
54
|
+
};
|
|
55
|
+
}, [handleNavigation]);
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (headerRef.current) {
|
|
59
|
+
const height = headerRef.current.offsetHeight + headerRef.current.offsetTop;
|
|
60
|
+
setHeaderHeight(height);
|
|
61
|
+
setBreadcrumbOld(breadcrumb);
|
|
62
|
+
if (JSON.stringify(breadcrumbOld) !== JSON.stringify(breadcrumb)) {
|
|
63
|
+
window.scrollTo(0, 0);
|
|
64
|
+
setBreadcrumbOld(breadcrumb);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}, [headerRef, breadcrumb, setHeaderHeight]);
|
|
68
|
+
|
|
69
|
+
const removeItem = () => {
|
|
70
|
+
setSelectedContent(parentID);
|
|
71
|
+
deleteModuleAction([editorID]);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const duplicateItem = () => {
|
|
75
|
+
duplicateModuleAction([editorID]);
|
|
76
|
+
setSelectedContent(parentID);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const copyItem = () => {
|
|
80
|
+
const isCopied = copyModuleAction([editorID]);
|
|
81
|
+
isCopied && toggleToast();
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const duplicateOpt = {
|
|
85
|
+
label: "duplicate",
|
|
86
|
+
icon: "duplicate",
|
|
87
|
+
action: duplicateItem,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const deleteOpt = {
|
|
91
|
+
label: "delete",
|
|
92
|
+
icon: "delete",
|
|
93
|
+
action: removeItem,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const copyOpt = {
|
|
97
|
+
label: "copy",
|
|
98
|
+
icon: "copy",
|
|
99
|
+
action: copyItem,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
let menuOptions = [duplicateOpt, deleteOpt];
|
|
103
|
+
menuOptions = isFormComponent ? [...menuOptions, copyOpt] : menuOptions;
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<S.Wrapper scrollDown={scrollDown || !hasStickyHeader}>
|
|
107
|
+
<S.HeaderWrapper data-testid="header-config-wrapper" ref={headerRef}>
|
|
108
|
+
<S.Title>{title}</S.Title>
|
|
109
|
+
<Breadcrumb breadcrumb={breadcrumb} setSelectedContent={setSelectedContent} />
|
|
110
|
+
{isInArray && <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />}
|
|
111
|
+
</S.HeaderWrapper>
|
|
112
|
+
{isVisible && <Toast message="1 module copied to clipboard" setIsVisible={setIsVisible} />}
|
|
113
|
+
</S.Wrapper>
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export interface IHeaderProps {
|
|
118
|
+
schema: ISchema | Record<string, never>;
|
|
119
|
+
actions: {
|
|
120
|
+
deleteModuleAction: (editorID: number[], key?: string) => void;
|
|
121
|
+
duplicateModuleAction: (editorID: number[], key?: string) => number;
|
|
122
|
+
copyModuleAction: (editorID: number[]) => boolean;
|
|
123
|
+
};
|
|
124
|
+
breadcrumb: IBreadcrumbItem[];
|
|
125
|
+
selectedParent: Record<string, unknown> | null;
|
|
126
|
+
setSelectedContent(editorID: number): void;
|
|
127
|
+
headerRef: React.RefObject<HTMLDivElement>;
|
|
128
|
+
setHeaderHeight(height: number): void;
|
|
129
|
+
hasStickyHeader: boolean;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export default memo(Header);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
import { ActionMenu } from "@ax/components";
|
|
3
|
+
|
|
4
|
+
const Wrapper = styled.div<{ scrollDown: boolean }>`
|
|
5
|
+
padding-top: ${(p) => p.theme.spacing.m};
|
|
6
|
+
background-color: ${(p) => p.theme.color.uiBackground01};
|
|
7
|
+
position: ${(p) => (p.scrollDown ? "relative" : "sticky")};
|
|
8
|
+
top: ${(p) => (p.scrollDown ? "0" : "63px")};
|
|
9
|
+
z-index: 3;
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
const HeaderWrapper = styled.div`
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
position: relative;
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
const Title = styled.p`
|
|
19
|
+
${(p) => p.theme.textStyle.headingS};
|
|
20
|
+
margin-bottom: ${(p) => p.theme.spacing.xs};
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
const StyledActionMenu = styled(ActionMenu)`
|
|
24
|
+
width: 32px;
|
|
25
|
+
position: absolute;
|
|
26
|
+
right: 0;
|
|
27
|
+
top: 0;
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
export { Wrapper, HeaderWrapper, Title, StyledActionMenu };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { isEmptyObj } from "@ax/helpers";
|
|
4
|
+
import { Loading } from "@ax/components";
|
|
5
|
+
import { IBreadcrumbItem, ISchema } from "@ax/types";
|
|
6
|
+
|
|
7
|
+
import Form from "./Form";
|
|
8
|
+
import Header from "./Header";
|
|
9
|
+
|
|
10
|
+
import * as S from "./style";
|
|
11
|
+
|
|
12
|
+
const FormConfigPanel = (props: IStateProps): JSX.Element => {
|
|
13
|
+
const {
|
|
14
|
+
isLoading,
|
|
15
|
+
schema,
|
|
16
|
+
actions,
|
|
17
|
+
setSelectedContent,
|
|
18
|
+
setSelectedTab,
|
|
19
|
+
selectedTab,
|
|
20
|
+
isGlobal,
|
|
21
|
+
setHistoryPush,
|
|
22
|
+
theme,
|
|
23
|
+
lastElementAddedId,
|
|
24
|
+
breadcrumb,
|
|
25
|
+
selectedParent,
|
|
26
|
+
} = props;
|
|
27
|
+
|
|
28
|
+
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
29
|
+
const headerRef = useRef<HTMLDivElement>(null);
|
|
30
|
+
const [headerHeight, setHeaderHeight] = useState<number>(0);
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (lastElementAddedId && wrapperRef.current) {
|
|
34
|
+
const element = document.querySelector(`.editorId-${lastElementAddedId}`);
|
|
35
|
+
element && element.scrollIntoView();
|
|
36
|
+
}
|
|
37
|
+
}, [lastElementAddedId]);
|
|
38
|
+
|
|
39
|
+
if (isLoading || isEmptyObj(schema)) {
|
|
40
|
+
return <Loading />;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<S.Wrapper data-testid="config-panel-wrapper" ref={wrapperRef}>
|
|
45
|
+
<Header
|
|
46
|
+
schema={schema}
|
|
47
|
+
actions={actions}
|
|
48
|
+
breadcrumb={breadcrumb}
|
|
49
|
+
selectedParent={selectedParent}
|
|
50
|
+
setSelectedContent={setSelectedContent}
|
|
51
|
+
headerRef={headerRef}
|
|
52
|
+
setHeaderHeight={setHeaderHeight}
|
|
53
|
+
hasStickyHeader={true}
|
|
54
|
+
/>
|
|
55
|
+
<Form
|
|
56
|
+
actions={actions}
|
|
57
|
+
schema={schema}
|
|
58
|
+
setSelectedContent={setSelectedContent}
|
|
59
|
+
setSelectedTab={setSelectedTab}
|
|
60
|
+
selectedTab={selectedTab}
|
|
61
|
+
isGlobal={isGlobal}
|
|
62
|
+
theme={theme}
|
|
63
|
+
setHistoryPush={setHistoryPush}
|
|
64
|
+
headerHeight={headerHeight}
|
|
65
|
+
/>
|
|
66
|
+
</S.Wrapper>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export interface IStateProps {
|
|
71
|
+
isLoading: boolean;
|
|
72
|
+
schema: ISchema | Record<string, never>;
|
|
73
|
+
actions: any;
|
|
74
|
+
setSelectedContent(editorID: number): void;
|
|
75
|
+
selectedTab: string;
|
|
76
|
+
setSelectedTab(tab: string): void;
|
|
77
|
+
isGlobal?: boolean;
|
|
78
|
+
pageTitle?: string;
|
|
79
|
+
setHistoryPush?: (path: string, isEditor: boolean) => void;
|
|
80
|
+
theme: string;
|
|
81
|
+
lastElementAddedId?: null | number;
|
|
82
|
+
breadcrumb: IBreadcrumbItem[];
|
|
83
|
+
selectedParent: Record<string, unknown> | null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default FormConfigPanel;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
3
|
+
import { ResizePanel } from "@ax/components";
|
|
4
|
+
import { IBreadcrumbItem, IModule, INotification, IRootState, ISchema } from "@ax/types";
|
|
5
|
+
import { formsActions } from "@ax/containers/Forms";
|
|
6
|
+
import PageBrowser from "../PageBrowser";
|
|
7
|
+
import FormConfigPanel from "./FormConfigPanel";
|
|
8
|
+
|
|
9
|
+
const Editor = (props: IProps) => {
|
|
10
|
+
const {
|
|
11
|
+
isLoading,
|
|
12
|
+
isGlobal,
|
|
13
|
+
theme,
|
|
14
|
+
browserRef,
|
|
15
|
+
schema,
|
|
16
|
+
selectedTab,
|
|
17
|
+
breadcrumb,
|
|
18
|
+
selectedParent,
|
|
19
|
+
setNotification,
|
|
20
|
+
setSelectedTab,
|
|
21
|
+
setSelectedContent,
|
|
22
|
+
addModule,
|
|
23
|
+
deleteModule,
|
|
24
|
+
duplicateModule,
|
|
25
|
+
moveModule,
|
|
26
|
+
copyModule,
|
|
27
|
+
pasteModule,
|
|
28
|
+
} = props;
|
|
29
|
+
|
|
30
|
+
const actions = {
|
|
31
|
+
setNotificationAction: setNotification,
|
|
32
|
+
addModuleAction: addModule,
|
|
33
|
+
deleteModuleAction: deleteModule,
|
|
34
|
+
duplicateModuleAction: duplicateModule,
|
|
35
|
+
moveModuleAction: moveModule,
|
|
36
|
+
copyModuleAction: copyModule,
|
|
37
|
+
pasteModuleAction: pasteModule,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<ResizePanel
|
|
42
|
+
leftPanel={<PageBrowser isReadOnly={false} theme={theme} browserRef={browserRef} />}
|
|
43
|
+
rightPanel={
|
|
44
|
+
<FormConfigPanel
|
|
45
|
+
schema={schema}
|
|
46
|
+
actions={actions}
|
|
47
|
+
isLoading={isLoading}
|
|
48
|
+
isGlobal={isGlobal}
|
|
49
|
+
theme={theme}
|
|
50
|
+
setSelectedTab={setSelectedTab}
|
|
51
|
+
selectedTab={selectedTab}
|
|
52
|
+
setSelectedContent={setSelectedContent}
|
|
53
|
+
breadcrumb={breadcrumb}
|
|
54
|
+
selectedParent={selectedParent}
|
|
55
|
+
/>
|
|
56
|
+
}
|
|
57
|
+
full={true}
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
interface IEditorStateProps {
|
|
63
|
+
isLoading: boolean;
|
|
64
|
+
selectedTab: string;
|
|
65
|
+
schema: ISchema | Record<string, never>;
|
|
66
|
+
breadcrumb: IBreadcrumbItem[];
|
|
67
|
+
selectedParent: Record<string, unknown> | null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
interface IPageBrowserDispatchProps {
|
|
71
|
+
setNotification: (notification: INotification) => void;
|
|
72
|
+
setSelectedTab(tab: string): void;
|
|
73
|
+
setSelectedContent(editorID: number): void;
|
|
74
|
+
addModule: (moduleType: string, key: string) => void;
|
|
75
|
+
deleteModule: (editorID: number[], key?: string) => void;
|
|
76
|
+
duplicateModule: (editorID: number[], key?: string) => number;
|
|
77
|
+
moveModule: (elementID: number[], content: any, newIndex: number, key: string) => void;
|
|
78
|
+
copyModule: (editorID: number[]) => boolean | number;
|
|
79
|
+
pasteModule: (editorID: number, key: string, modulesToPaste: IModule[]) => Promise<{ error?: INotification }>;
|
|
80
|
+
isGlobal: boolean;
|
|
81
|
+
theme: string;
|
|
82
|
+
browserRef: any;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
type IProps = IEditorStateProps & IPageBrowserDispatchProps;
|
|
86
|
+
|
|
87
|
+
const mapStateToProps = (state: IRootState): IEditorStateProps => ({
|
|
88
|
+
isLoading: state.app.isLoading,
|
|
89
|
+
selectedTab: state.forms.tab,
|
|
90
|
+
schema: state.forms.schema,
|
|
91
|
+
breadcrumb: state.forms.breadcrumb,
|
|
92
|
+
selectedParent: state.forms.selectedParent,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const mapDispatchToProps = {
|
|
96
|
+
setSelectedTab: formsActions.setSelectedTab,
|
|
97
|
+
setSelectedContent: formsActions.setSelectedContent,
|
|
98
|
+
addModule: formsActions.addModule,
|
|
99
|
+
deleteModule: formsActions.deleteModule,
|
|
100
|
+
duplicateModule: formsActions.duplicateModule,
|
|
101
|
+
moveModule: formsActions.moveModule,
|
|
102
|
+
copyModule: formsActions.copyModule,
|
|
103
|
+
pasteModule: formsActions.pasteModule,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export default connect(mapStateToProps, mapDispatchToProps)(Editor);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
3
|
+
import { pageEditorActions } from "@ax/containers/PageEditor";
|
|
4
|
+
import { formsActions } from "@ax/containers/Forms";
|
|
5
|
+
|
|
6
|
+
import { Browser } from "@ax/components";
|
|
7
|
+
import { ILanguage, IRootState, ISchema, ISite, ISocialState } from "@ax/types";
|
|
8
|
+
|
|
9
|
+
const PageBrowser = (props: IProps) => {
|
|
10
|
+
const {
|
|
11
|
+
socials,
|
|
12
|
+
cloudinaryName,
|
|
13
|
+
content,
|
|
14
|
+
setSelectedContent,
|
|
15
|
+
globalLangs,
|
|
16
|
+
theme,
|
|
17
|
+
isReadOnly,
|
|
18
|
+
isPreview,
|
|
19
|
+
browserRef,
|
|
20
|
+
currentSiteInfo,
|
|
21
|
+
deleteModule,
|
|
22
|
+
duplicateModule,
|
|
23
|
+
setScrollEditorID,
|
|
24
|
+
} = props;
|
|
25
|
+
|
|
26
|
+
const { id: siteID } = currentSiteInfo || {};
|
|
27
|
+
|
|
28
|
+
const actions = {
|
|
29
|
+
deleteModuleAction: deleteModule,
|
|
30
|
+
duplicateModuleAction: duplicateModule,
|
|
31
|
+
setSelectedContentAction: setSelectedContent,
|
|
32
|
+
setScrollEditorIDAction: setScrollEditorID,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Browser
|
|
37
|
+
isPage={true}
|
|
38
|
+
content={content}
|
|
39
|
+
socials={socials}
|
|
40
|
+
url={""}
|
|
41
|
+
theme={theme}
|
|
42
|
+
cloudinaryName={cloudinaryName}
|
|
43
|
+
siteLangs={globalLangs}
|
|
44
|
+
disabled={isReadOnly}
|
|
45
|
+
siteID={siteID}
|
|
46
|
+
isPreview={isPreview}
|
|
47
|
+
showIframe={true}
|
|
48
|
+
browserRef={browserRef}
|
|
49
|
+
actions={actions}
|
|
50
|
+
editorType="form"
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
interface IPageBrowserStateProps {
|
|
56
|
+
// TODO: Define content Type
|
|
57
|
+
content: any;
|
|
58
|
+
socials: ISocialState;
|
|
59
|
+
cloudinaryName: string | null;
|
|
60
|
+
globalLangs: ILanguage[];
|
|
61
|
+
schema: ISchema | Record<string, unknown>;
|
|
62
|
+
selectedParent: any;
|
|
63
|
+
currentSiteInfo: ISite | null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface IPageBrowserDispatchProps {
|
|
67
|
+
setSelectedContent(editorID: number): void;
|
|
68
|
+
theme: string;
|
|
69
|
+
isReadOnly: boolean;
|
|
70
|
+
isPreview?: boolean;
|
|
71
|
+
browserRef?: any;
|
|
72
|
+
deleteModule(editorID: number[]): void;
|
|
73
|
+
duplicateModule(editorID: number[]): number;
|
|
74
|
+
setScrollEditorID(editorID: number | null): void;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
type IProps = IPageBrowserStateProps & IPageBrowserDispatchProps;
|
|
78
|
+
|
|
79
|
+
const mapStateToProps = (state: IRootState): IPageBrowserStateProps => ({
|
|
80
|
+
content: { ...state.forms.formContent },
|
|
81
|
+
socials: state.social,
|
|
82
|
+
cloudinaryName: state.app.globalSettings.cloudinaryName,
|
|
83
|
+
globalLangs: state.app.globalLangs,
|
|
84
|
+
schema: state.forms.schema,
|
|
85
|
+
selectedParent: state.forms.selectedParent,
|
|
86
|
+
currentSiteInfo: state.sites.currentSiteInfo,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const mapDispatchToProps = {
|
|
90
|
+
setSelectedContent: formsActions.setSelectedContent,
|
|
91
|
+
deleteModule: pageEditorActions.deleteModule,
|
|
92
|
+
duplicateModule: pageEditorActions.duplicateModule,
|
|
93
|
+
setScrollEditorID: pageEditorActions.setScrollEditorID,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export default connect(mapStateToProps, mapDispatchToProps)(PageBrowser);
|