@griddo/ax 1.65.26 → 1.66.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.
Files changed (57) hide show
  1. package/package.json +2 -2
  2. package/src/GlobalStore.tsx +4 -3
  3. package/src/api/structuredData.tsx +15 -1
  4. package/src/components/Browser/index.tsx +13 -16
  5. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +12 -0
  6. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/TemplateManager/index.tsx +11 -0
  7. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/index.tsx +13 -0
  8. package/src/components/ConfigPanel/Form/index.tsx +3 -1
  9. package/src/components/ConfigPanel/index.tsx +19 -5
  10. package/src/components/ConfigPanel/style.tsx +5 -0
  11. package/src/components/FieldContainer/index.tsx +4 -0
  12. package/src/components/Fields/ComponentArray/MixableComponentArray/PasteModuleButton/index.tsx +49 -0
  13. package/src/components/Fields/ComponentArray/MixableComponentArray/index.tsx +51 -11
  14. package/src/components/Fields/ComponentArray/MixableComponentArray/style.tsx +14 -1
  15. package/src/components/Fields/ComponentContainer/index.tsx +24 -5
  16. package/src/components/Fields/ImageField/index.tsx +18 -5
  17. package/src/components/Image/index.tsx +25 -0
  18. package/src/components/Notification/index.tsx +3 -1
  19. package/src/components/index.tsx +2 -0
  20. package/src/containers/Navigation/Defaults/actions.tsx +27 -9
  21. package/src/containers/PageEditor/actions.tsx +104 -5
  22. package/src/containers/PageEditor/constants.tsx +2 -0
  23. package/src/containers/PageEditor/interfaces.tsx +12 -0
  24. package/src/containers/PageEditor/reducer.tsx +8 -0
  25. package/src/containers/PageEditor/utils.tsx +2 -2
  26. package/src/helpers/index.tsx +6 -0
  27. package/src/helpers/schemas.tsx +36 -7
  28. package/src/modules/App/Routing/index.tsx +1 -1
  29. package/src/modules/Content/OptionTable/index.tsx +44 -43
  30. package/src/modules/Content/OptionTable/store.tsx +1 -1
  31. package/src/modules/Content/OptionTable/style.tsx +27 -12
  32. package/src/modules/Content/PageItem/index.tsx +14 -4
  33. package/src/modules/Content/atoms.tsx +19 -2
  34. package/src/modules/Content/index.tsx +37 -14
  35. package/src/modules/Content/utils.tsx +27 -12
  36. package/src/modules/GlobalEditor/Editor/index.tsx +12 -1
  37. package/src/modules/GlobalEditor/index.tsx +20 -2
  38. package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +13 -0
  39. package/src/modules/Navigation/Defaults/atoms.tsx +28 -0
  40. package/src/modules/Navigation/Defaults/index.tsx +30 -4
  41. package/src/modules/Navigation/Defaults/style.tsx +32 -1
  42. package/src/modules/PageEditor/Editor/index.tsx +16 -1
  43. package/src/modules/PageEditor/index.tsx +14 -1
  44. package/src/modules/PublicPreview/index.tsx +15 -18
  45. package/src/modules/Settings/Globals/NavigationModules/SideModal/SideModalOption/index.tsx +35 -0
  46. package/src/modules/Settings/Globals/NavigationModules/SideModal/SideModalOption/style.tsx +22 -0
  47. package/src/modules/Settings/Globals/NavigationModules/SideModal/index.tsx +111 -0
  48. package/src/modules/Settings/Globals/NavigationModules/SideModal/style.tsx +64 -0
  49. package/src/modules/Settings/Globals/NavigationModules/index.tsx +89 -0
  50. package/src/modules/Settings/Globals/NavigationModules/style.tsx +36 -0
  51. package/src/modules/Settings/Globals/index.tsx +38 -1
  52. package/src/modules/Sites/SitesList/SiteItem/index.tsx +7 -5
  53. package/src/modules/StructuredData/StructuredDataList/OptionTable/index.tsx +14 -3
  54. package/src/modules/StructuredData/StructuredDataList/OptionTable/style.tsx +11 -2
  55. package/src/modules/StructuredData/StructuredDataList/atoms.tsx +19 -2
  56. package/src/modules/StructuredData/StructuredDataList/index.tsx +4 -13
  57. package/src/types/index.tsx +11 -0
@@ -0,0 +1,89 @@
1
+ import React, { Dispatch, SetStateAction } from "react";
2
+
3
+ import { Button, Modal } from "@ax/components";
4
+ import { useModal } from "@ax/hooks";
5
+
6
+ import SideModal from "./SideModal";
7
+ import * as S from "./style";
8
+
9
+ const NavigationModules = (props: IProps): JSX.Element => {
10
+ const {
11
+ navigationModules,
12
+ form,
13
+ theme,
14
+ setNavigationModulesValue,
15
+ isNavigationModulesChanged,
16
+ setIsNavigationModulesChanged,
17
+ } = props;
18
+ const { isOpen: isModalOpen, toggleModal } = useModal();
19
+ const { isOpen: isSideModalOpen, toggleModal: toggleSideModal } = useModal();
20
+
21
+ const buttonText = isNavigationModulesChanged
22
+ ? "Change Navigation modules design"
23
+ : "Select Navigation modules design";
24
+
25
+ const handleButtonClick = isNavigationModulesChanged ? toggleModal : toggleSideModal;
26
+
27
+ const mainAction = {
28
+ title: "Yes, change design",
29
+ onClick: () => {
30
+ toggleModal();
31
+ toggleSideModal();
32
+ },
33
+ };
34
+
35
+ const secondaryAction = {
36
+ title: "Cancel",
37
+ onClick: toggleModal,
38
+ };
39
+
40
+ return (
41
+ <S.Wrapper>
42
+ <S.Heading>Navigation Modules</S.Heading>
43
+ <S.Text>
44
+ There are multiple designs for the navigation modules in the library.{" "}
45
+ <strong>Choose the design you want for your site</strong> and add as many headers and footers as you need.
46
+ </S.Text>
47
+ <S.Separator />
48
+ <Button type="button" onClick={handleButtonClick} buttonStyle="line">
49
+ {buttonText}
50
+ </Button>
51
+ <Modal
52
+ isOpen={isModalOpen}
53
+ hide={toggleModal}
54
+ size="S"
55
+ title="Change Design"
56
+ mainAction={mainAction}
57
+ secondaryAction={secondaryAction}
58
+ >
59
+ {
60
+ <S.ModalContent>
61
+ <strong>There is already a navigation modules design defined</strong>. If you change it, headers and footers
62
+ on all pages of the site will be affected. Are you sure you want to proceed with the change?
63
+ </S.ModalContent>
64
+ }
65
+ </Modal>
66
+ <SideModal
67
+ navigationModules={navigationModules}
68
+ form={form}
69
+ toggleModal={toggleSideModal}
70
+ isOpen={isSideModalOpen}
71
+ theme={theme}
72
+ setNavigationModulesValue={setNavigationModulesValue}
73
+ isNavigationModulesChanged={isNavigationModulesChanged}
74
+ setIsNavigationModulesChanged={setIsNavigationModulesChanged}
75
+ />
76
+ </S.Wrapper>
77
+ );
78
+ };
79
+
80
+ interface IProps {
81
+ navigationModules: Record<string, any[]>;
82
+ theme: string;
83
+ form: any;
84
+ setNavigationModulesValue: (value: any) => void;
85
+ isNavigationModulesChanged: boolean;
86
+ setIsNavigationModulesChanged: Dispatch<SetStateAction<boolean>>;
87
+ }
88
+
89
+ export default NavigationModules;
@@ -0,0 +1,36 @@
1
+ import styled from "styled-components";
2
+
3
+ const Wrapper = styled.div`
4
+ border-top: 1px solid ${(p) => p.theme.color.uiLine};
5
+ border-bottom: 1px solid ${(p) => p.theme.color.uiLine};
6
+ margin: ${(p) => p.theme.spacing.m} 0;
7
+ padding: ${(p) => p.theme.spacing.m} 0;
8
+ `;
9
+
10
+ const Heading = styled.div`
11
+ ${(p) => p.theme.textStyle.headingXS};
12
+ color: ${(p) => p.theme.color.textHighEmphasis};
13
+ padding-bottom: ${(p) => p.theme.spacing.xs};
14
+ `;
15
+
16
+ const Text = styled.div`
17
+ ${(p) => p.theme.textStyle.uiM};
18
+ color: ${(p) => p.theme.color.textMediumEmphasis};
19
+ width: calc(${(p) => p.theme.spacing.l} * 12);
20
+ `;
21
+
22
+ const Separator = styled.div`
23
+ margin-bottom: ${(p) => p.theme.spacing.m};
24
+ `;
25
+
26
+ const ModalContent = styled.div`
27
+ padding: ${(p) => p.theme.spacing.m};
28
+ p {
29
+ margin-bottom: ${(p) => p.theme.spacing.m};
30
+ }
31
+ div {
32
+ margin-bottom: 0;
33
+ }
34
+ `;
35
+
36
+ export { Wrapper, Heading, Text, Separator, ModalContent };
@@ -6,22 +6,33 @@ import { IImage, INavItem, IRootState, ISettingsForm } from "@ax/types";
6
6
  import { RouteLeavingGuard } from "@ax/guards";
7
7
  import { useIsDirty } from "@ax/hooks";
8
8
  import { appActions } from "@ax/containers/App";
9
- import { FieldsBehavior, FieldGroup, MainWrapper, ErrorToast, Nav } from "@ax/components";
9
+ import { FieldsBehavior, FieldGroup, MainWrapper, ErrorToast, Nav, Notification } from "@ax/components";
10
10
  import { sitesActions } from "@ax/containers/Sites";
11
+ import { getNavigationModules } from "@ax/helpers";
11
12
 
13
+ import NavigationModules from "./NavigationModules";
12
14
  import { timezones } from "./constants";
13
15
  import * as S from "./style";
14
16
 
15
17
  const Globals = (props: IProps): JSX.Element => {
16
18
  const { isSaving, currentSiteInfo, saveSettings, setHistoryPush, navItems, currentNavItem } = props;
17
19
 
20
+ const [isNavigationNotificationOpen, setIsNavigationNotificationOpen] = useState(false);
21
+
18
22
  const title = "General settings";
19
23
 
24
+ const [isNavigationModulesChanged, setIsNavigationModulesChanged] = useState(!!currentSiteInfo.navigationModules);
20
25
  const [form, setForm] = useState(currentSiteInfo);
26
+
21
27
  const { name, timezone, theme, favicon, smallAvatar, bigAvatar, thumbnail } = form;
22
28
 
23
29
  const { isDirty, setIsDirty } = useIsDirty(form);
24
30
 
31
+ const navigationModules: Record<string, any[]> = getNavigationModules();
32
+ const hasMultipleNavigationModules = Object.keys(navigationModules).some(
33
+ (key: string) => navigationModules[key].length > 1
34
+ );
35
+
25
36
  const setValue = (newValue: Record<string, string | null>) =>
26
37
  setForm((state: ISettingsForm) => ({ ...state, ...newValue }));
27
38
 
@@ -32,9 +43,13 @@ const Globals = (props: IProps): JSX.Element => {
32
43
  const setSmallAvatarValue = (value: IImage) => setValue({ smallAvatar: value.url ? value.url : null });
33
44
  const setBigAvatarValue = (value: IImage) => setValue({ bigAvatar: value.url ? value.url : null });
34
45
  const setThumbnailValue = (value: IImage) => setValue({ thumbnail: value.url ? value.url : null });
46
+ const setNavigationModulesValue = (value: any) => setValue({ navigationModules: value });
35
47
 
36
48
  const saveForm = async () => {
37
49
  const isSaved = await saveSettings(form);
50
+ const isNavigationModulesChanging =
51
+ JSON.stringify(form?.navigationModules) !== JSON.stringify(currentSiteInfo?.navigationModules);
52
+ setIsNavigationNotificationOpen(isNavigationModulesChanging);
38
53
  if (isSaved) setIsDirty(false);
39
54
  };
40
55
 
@@ -55,6 +70,9 @@ const Globals = (props: IProps): JSX.Element => {
55
70
  setHistoryPush(path);
56
71
  };
57
72
 
73
+ const closeNavigationNotification = () => setIsNavigationNotificationOpen(false);
74
+ const goToNavigationModules = () => setHistoryPush("/sites/navigations/modules");
75
+
58
76
  return (
59
77
  <>
60
78
  <RouteLeavingGuard when={isDirty} action={setRoute} text={modalText} />
@@ -63,6 +81,15 @@ const Globals = (props: IProps): JSX.Element => {
63
81
  <Nav current={currentNavItem} items={navItems} onClick={handleMenuClick} />
64
82
  <S.ContentWrapper>
65
83
  <ErrorToast />
84
+ {isNavigationNotificationOpen && (
85
+ <Notification
86
+ type="warning"
87
+ text="The design of the navigation modules has changed. Please, check the previously created."
88
+ btnText="Go to check"
89
+ onClick={goToNavigationModules}
90
+ onClose={closeNavigationNotification}
91
+ />
92
+ )}
66
93
  <S.FormWrapper>
67
94
  <FieldsBehavior
68
95
  title="Site Name"
@@ -97,6 +124,16 @@ const Globals = (props: IProps): JSX.Element => {
97
124
  onChange={setFaviconValue}
98
125
  helptext="Upload a 32x32px image"
99
126
  />
127
+ {hasMultipleNavigationModules && (
128
+ <NavigationModules
129
+ navigationModules={navigationModules}
130
+ form={form}
131
+ setNavigationModulesValue={setNavigationModulesValue}
132
+ isNavigationModulesChanged={isNavigationModulesChanged}
133
+ setIsNavigationModulesChanged={setIsNavigationModulesChanged}
134
+ theme={theme}
135
+ />
136
+ )}
100
137
  <FieldGroup title="Content for CMS">
101
138
  <FieldsBehavior
102
139
  title="Small avatar"
@@ -6,7 +6,7 @@ import { trimText, isDevelopment } from "@ax/helpers";
6
6
  import { ISite } from "@ax/types";
7
7
  import { appActions } from "@ax/containers/App";
8
8
  import { sitesActions } from "@ax/containers/Sites";
9
- import { FieldsBehavior, Icon, Modal, Tooltip } from "@ax/components";
9
+ import { FieldsBehavior, Icon, Modal, Tooltip, Image } from "@ax/components";
10
10
 
11
11
  import * as S from "./style";
12
12
 
@@ -36,7 +36,11 @@ const SiteItem = (props: ISiteItemProps): JSX.Element => {
36
36
  };
37
37
 
38
38
  const thumbnailPlaceholder = "/img/placeholder/thumbnail@1x.png";
39
- const thumbnail = site.thumbnail ? site.thumbnail : thumbnailPlaceholder;
39
+ const thumbnail = site.thumbnail ? (
40
+ <Image width={238} height={178} url={site.thumbnail} />
41
+ ) : (
42
+ <S.Thumbnail backgroundUrl={thumbnailPlaceholder} />
43
+ );
40
44
 
41
45
  const setSite = async () => {
42
46
  await setSiteInfo(site);
@@ -127,9 +131,7 @@ const SiteItem = (props: ISiteItemProps): JSX.Element => {
127
131
  return (
128
132
  <>
129
133
  <S.SiteWrapper key={site.id} onClick={setSite}>
130
- <Tooltip content={siteTooltip}>
131
- <S.Thumbnail backgroundUrl={thumbnail} />
132
- </Tooltip>
134
+ <Tooltip content={siteTooltip}>{thumbnail}</Tooltip>
133
135
  <S.Wrapper>
134
136
  <S.Title>{siteName}</S.Title>
135
137
  <S.IconsWrapper>
@@ -5,11 +5,11 @@ import { getDefaultTheme, getThumbnailProps } from "@ax/helpers";
5
5
  import { MenuItem, RadioGroup } from "@ax/components";
6
6
 
7
7
  import { reducer, IOptionTableStore, setColumnValues, setShowThumbnail, setSelectedType, setOption } from "./store";
8
-
8
+ import { SecondaryActionButton, MainActionButton } from "./../atoms";
9
9
  import * as S from "./style";
10
10
 
11
11
  const OptionTable = (props: IOptionTableProps): JSX.Element => {
12
- const { selectPage, filters, values, selectedValue } = props;
12
+ const { selectPage, filters, values, selectedValue, mainAction, secondaryAction } = props;
13
13
 
14
14
  const filterOptions = (value: string, objKey: keyof IStructuredDataValue): IStructuredDataValue[] =>
15
15
  values.filter((item: IStructuredDataValue) => item[objKey] === value);
@@ -96,16 +96,27 @@ const OptionTable = (props: IOptionTableProps): JSX.Element => {
96
96
  {thumbnailProps && <S.Thumbnail backgroundUrl={thumbnailProps.src} />}
97
97
  </S.ThumbnailWrapper>
98
98
  )}
99
+ <S.Actions>
100
+ <SecondaryActionButton onClick={secondaryAction.onClick} title={secondaryAction.title}/>
101
+ <MainActionButton onClick={mainAction.onClick} title={mainAction.title}/>
102
+ </S.Actions>
99
103
  </S.Column>
100
104
  </S.Table>
101
105
  );
102
106
  };
103
107
 
108
+ interface IAction {
109
+ title: string;
110
+ onClick: any;
111
+ }
112
+
104
113
  interface IOptionTableProps {
105
114
  selectPage: (value: string) => void;
106
115
  filters: IStructuredDataFilter[];
107
116
  values: IStructuredDataValue[];
108
117
  selectedValue: string;
118
+ mainAction: IAction;
119
+ secondaryAction: IAction;
109
120
  }
110
121
 
111
- export default OptionTable;
122
+ export default OptionTable;
@@ -36,8 +36,8 @@ export const ThumbnailWrapper = styled.div`
36
36
  overflow: hidden;
37
37
  border-radius: 4px;
38
38
  padding: ${(p) => p.theme.spacing.xs};
39
- height: 100%;
40
39
  background-color: #ffffff;
40
+ height: 220px;
41
41
  `;
42
42
 
43
43
  export const Thumbnail = styled.div<{ backgroundUrl: string | boolean }>`
@@ -50,5 +50,14 @@ export const Thumbnail = styled.div<{ backgroundUrl: string | boolean }>`
50
50
  `;
51
51
 
52
52
  export const Link = styled.div<{ active: boolean }>`
53
- color: ${p => p.active ? p.theme.color.textHighEmphasis : p.theme.color.textMediumEmphasis};
53
+ color: ${(p) => (p.active ? p.theme.color.textHighEmphasis : p.theme.color.textMediumEmphasis)};
54
54
  `;
55
+
56
+ export const Actions = styled.div`
57
+ position: fixed;
58
+ bottom: ${(p) => p.theme.spacing.m};
59
+ right: ${(p) => p.theme.spacing.m};
60
+ button {
61
+ margin-left: ${(p) => p.theme.spacing.s};
62
+ }
63
+ `;
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
 
3
3
  import { IModal } from "@ax/types";
4
- import { Modal, FieldsBehavior } from "@ax/components";
4
+ import { Modal, FieldsBehavior, Button } from "@ax/components";
5
5
 
6
6
  import * as S from "./style";
7
7
 
@@ -64,10 +64,27 @@ const DeleteModal = (props: IDeleteModal): JSX.Element => {
64
64
  );
65
65
  };
66
66
 
67
+ const MainActionButton = (props: IActionButton): JSX.Element => (
68
+ <Button type="button" onClick={props.onClick}>
69
+ {props.title}
70
+ </Button>
71
+ );
72
+
73
+ const SecondaryActionButton = (props: IActionButton): JSX.Element => (
74
+ <Button type="button" buttonStyle="text" onClick={props.onClick}>
75
+ {props.title}
76
+ </Button>
77
+ );
78
+
67
79
  interface IDeleteModal extends IModal {
68
80
  arePagesTranslated: boolean;
69
81
  deleteAllVersions: boolean;
70
82
  setDeleteAllVersions: React.Dispatch<React.SetStateAction<boolean>>;
71
83
  }
72
84
 
73
- export { DeleteModal };
85
+ interface IActionButton {
86
+ onClick: () => void;
87
+ title: string;
88
+ }
89
+
90
+ export { DeleteModal, MainActionButton, SecondaryActionButton };
@@ -82,7 +82,6 @@ const StructuredDataList = (props: IProps): JSX.Element => {
82
82
  restorePage,
83
83
  resetPageEditor,
84
84
  getAnalytics,
85
- setCurrentDataID,
86
85
  } = props;
87
86
 
88
87
  const itemsPerPage = 50;
@@ -172,7 +171,6 @@ const StructuredDataList = (props: IProps): JSX.Element => {
172
171
  include_draft: true,
173
172
  query: searchQuery,
174
173
  format: "list",
175
- relatedFields: true,
176
174
  };
177
175
 
178
176
  return params;
@@ -214,7 +212,6 @@ const StructuredDataList = (props: IProps): JSX.Element => {
214
212
  resetFilter();
215
213
  setIsFirstRender(false);
216
214
  resetPageEditor();
217
- setCurrentDataID(null);
218
215
  // eslint-disable-next-line react-hooks/exhaustive-deps
219
216
  }, []);
220
217
 
@@ -582,18 +579,14 @@ const StructuredDataList = (props: IProps): JSX.Element => {
582
579
  </TableList>
583
580
  </S.TableListWrapper>
584
581
  </S.StructuredDataWrapper>
585
- <Modal
586
- isOpen={isNewOpen}
587
- hide={toggleNewModal}
588
- size="M"
589
- title="New content"
590
- mainAction={{ onClick: addNewPage, title: "ADD" }}
591
- >
582
+ <Modal isOpen={isNewOpen} hide={toggleNewModal} size="M" title="New content">
592
583
  <OptionTable
593
584
  selectPage={addTemplate}
594
585
  filters={options.filters}
595
586
  values={options.values}
596
587
  selectedValue={selectedValue}
588
+ mainAction={{ onClick: addNewPage, title: "Add" }}
589
+ secondaryAction={{ title: "Cancel", onClick: toggleNewModal }}
597
590
  />
598
591
  </Modal>
599
592
  <DeleteModal
@@ -650,7 +643,6 @@ const mapDispatchToProps = {
650
643
  restorePage: pageEditorActions.restorePage,
651
644
  resetPageEditor: pageEditorActions.resetPageEditor,
652
645
  getAnalytics: analyticsActions.getAnalytics,
653
- setCurrentDataID: structuredDataActions.setCurrentDataID,
654
646
  };
655
647
 
656
648
  interface IDispatchProps {
@@ -673,7 +665,6 @@ interface IDispatchProps {
673
665
  restorePage(id: number | number[]): Promise<boolean>;
674
666
  resetPageEditor(): Promise<void>;
675
667
  getAnalytics(): void;
676
- setCurrentDataID(id: number | null): void;
677
668
  }
678
669
 
679
670
  interface ICategoriesProps {
@@ -693,4 +684,4 @@ interface ICategoriesProps {
693
684
 
694
685
  type IProps = ICategoriesProps & IDispatchProps;
695
686
 
696
- export default connect(mapStateToProps, mapDispatchToProps)(StructuredDataList);
687
+ export default connect(mapStateToProps, mapDispatchToProps)(StructuredDataList);
@@ -485,6 +485,10 @@ export interface ISettingsForm {
485
485
  smallAvatar?: IImage | string | null;
486
486
  bigAvatar?: IImage | string | null;
487
487
  thumbnail?: IImage | string | null;
488
+ navigationModules?: {
489
+ header: string;
490
+ footer: string;
491
+ };
488
492
  }
489
493
 
490
494
  export interface IDataSource {
@@ -729,6 +733,13 @@ export interface ITemplate {
729
733
  type: { label: string; value: string; mode: string };
730
734
  }
731
735
 
736
+ export interface INotification {
737
+ type: "error" | "info" | "success" | "warning";
738
+ text: string;
739
+ btnText?: string;
740
+ onClick?: () => void;
741
+ }
742
+
732
743
  export type Field =
733
744
  | "AsyncCheckGroup"
734
745
  | "AsyncSelect"