@griddo/ax 1.62.8 → 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 (81) 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/PageEditor/actions.tsx +65 -10
  30. package/src/containers/Settings/DataPacks/actions.tsx +4 -1
  31. package/src/containers/Sites/actions.tsx +3 -1
  32. package/src/helpers/dates.tsx +3 -4
  33. package/src/helpers/index.tsx +2 -0
  34. package/src/helpers/strings.tsx +38 -7
  35. package/src/index.tsx +2 -2
  36. package/src/modules/Content/OptionTable/index.tsx +29 -2
  37. package/src/modules/Content/PageItem/index.tsx +11 -2
  38. package/src/modules/Content/index.tsx +9 -0
  39. package/src/modules/GlobalEditor/Editor/index.tsx +7 -9
  40. package/src/modules/GlobalEditor/{Editor/PageBrowser → PageBrowser}/index.tsx +14 -6
  41. package/src/modules/GlobalEditor/Preview/index.tsx +19 -0
  42. package/src/modules/GlobalEditor/Preview/style.tsx +9 -0
  43. package/src/modules/GlobalEditor/index.tsx +36 -9
  44. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +5 -1
  45. package/src/modules/PageEditor/Editor/index.tsx +5 -5
  46. package/src/modules/PageEditor/{Editor/PageBrowser → PageBrowser}/index.tsx +11 -4
  47. package/src/modules/PageEditor/Preview/index.tsx +14 -0
  48. package/src/modules/PageEditor/Preview/style.tsx +9 -0
  49. package/src/modules/PageEditor/index.tsx +39 -16
  50. package/src/modules/PublicPreview/index.tsx +92 -0
  51. package/src/modules/PublicPreview/style.tsx +18 -0
  52. package/src/modules/Redirects/BulkHeader/TableHeader/index.tsx +16 -3
  53. package/src/modules/Redirects/BulkHeader/TableHeader/style.tsx +9 -3
  54. package/src/modules/Redirects/BulkHeader/index.tsx +7 -1
  55. package/src/modules/Redirects/RedirectItem/index.tsx +4 -0
  56. package/src/modules/Redirects/RedirectItem/style.tsx +19 -3
  57. package/src/modules/Redirects/atoms.tsx +0 -1
  58. package/src/modules/Redirects/hooks.tsx +67 -0
  59. package/src/modules/Redirects/index.tsx +23 -9
  60. package/src/modules/Redirects/utils.tsx +10 -0
  61. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/Field/index.tsx +107 -0
  62. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/Field/style.tsx +54 -0
  63. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/index.tsx +66 -0
  64. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/style.tsx +42 -0
  65. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/TemplateBrowser/index.tsx +58 -0
  66. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/index.tsx +41 -0
  67. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/index.tsx +93 -0
  68. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/style.tsx +25 -0
  69. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/index.tsx +48 -0
  70. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/style.tsx +53 -0
  71. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/index.tsx +40 -36
  72. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/style.tsx +4 -5
  73. package/src/modules/Settings/ContentTypes/DataPacks/Config/index.tsx +4 -4
  74. package/src/modules/Settings/ContentTypes/DataPacks/index.tsx +5 -1
  75. package/src/modules/Settings/{Analytics → SeoAnalyticsSettings/Analytics}/atoms.tsx +0 -0
  76. package/src/modules/Settings/{Analytics → SeoAnalyticsSettings/Analytics}/index.tsx +20 -11
  77. package/src/modules/Settings/{Analytics → SeoAnalyticsSettings/Analytics}/style.tsx +6 -0
  78. package/src/modules/Settings/{SeoSettings → SeoAnalyticsSettings}/index.tsx +11 -4
  79. package/src/routes/publicRoutes.tsx +3 -1
  80. package/src/routes/site.tsx +14 -10
  81. package/src/types/index.tsx +9 -0
@@ -9,10 +9,11 @@ import { appActions } from "@ax/containers/App";
9
9
  import { navigationActions } from "@ax/containers/Navigation";
10
10
  import { pageStatus } from "@ax/containers/PageEditor/interfaces";
11
11
  import { RouteLeavingGuard } from "@ax/guards";
12
- import { useIsDirty, useModal } from "@ax/hooks";
12
+ import { useIsDirty, useModal, useToast } from "@ax/hooks";
13
13
  import { isModuleDisabled } from "@ax/helpers";
14
14
  import { dataPacksActions } from "@ax/containers/Settings/DataPacks";
15
15
  import Editor from "./Editor";
16
+ import Preview from "./Preview";
16
17
 
17
18
  import * as S from "./style";
18
19
 
@@ -44,7 +45,8 @@ const PageEditor = (props: IProps) => {
44
45
  isNewTranslation,
45
46
  } = props;
46
47
 
47
- const [isPreviewMode, setIsPreviewMode] = useState(false);
48
+ const [isReadOnly, setIsReadOnly] = useState(false);
49
+ const [selectedTab, setSelectedTab] = useState("edit");
48
50
  const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent.editorContent, isNewTranslation);
49
51
  const { isOpen, toggleModal } = useModal();
50
52
  const { isOpen: isUnpublishOpen, toggleModal: toggleUnpublishModal } = useModal();
@@ -55,6 +57,7 @@ const PageEditor = (props: IProps) => {
55
57
  const isDraft = props.pageStatus === pageStatus.MODIFIED;
56
58
  const hasDraft = editorContent.editorContent && editorContent.editorContent.haveDraftPage;
57
59
  const isLivePageChanged = editorContent.editorContent && editorContent.editorContent.liveChanged;
60
+ const structuredData = editorContent.editorContent ? editorContent.editorContent.structuredData : "";
58
61
 
59
62
  useEffect(() => {
60
63
  const { pageID, getPage, setTab, sendPagePing } = props;
@@ -77,10 +80,10 @@ const PageEditor = (props: IProps) => {
77
80
  useEffect(() => {
78
81
  const { pageID, sendPagePing, currentUserID } = props;
79
82
  if (userEditing && userEditing.id !== currentUserID) {
80
- setIsPreviewMode(true);
83
+ setIsReadOnly(true);
81
84
  !isOpen && toggleModal();
82
85
  } else {
83
- setIsPreviewMode(false);
86
+ setIsReadOnly(false);
84
87
  pageID && sendPagePing(pageID);
85
88
  isOpen && toggleModal();
86
89
  }
@@ -205,9 +208,14 @@ const PageEditor = (props: IProps) => {
205
208
  }
206
209
  };
207
210
 
211
+ const handleNewTranlation = (isNewTranslation: boolean) => {
212
+ setSelectedTab("edit");
213
+ createNewTranslation && createNewTranslation(isNewTranslation);
214
+ };
215
+
208
216
  const languageActions = {
209
217
  setLanguage,
210
- createNewTranslation,
218
+ createNewTranslation: handleNewTranlation,
211
219
  getContent: getPage,
212
220
  };
213
221
 
@@ -247,7 +255,7 @@ const PageEditor = (props: IProps) => {
247
255
  : [];
248
256
 
249
257
  const downArrowMenu = {
250
- displayed: !isPreviewMode,
258
+ displayed: !isReadOnly,
251
259
  button: getPublishButton(props.pageStatus),
252
260
  options: menuOptions,
253
261
  };
@@ -317,7 +325,7 @@ const PageEditor = (props: IProps) => {
317
325
  disabled:
318
326
  (!isDirty && pageID !== null && !isNewTranslation) ||
319
327
  isSaving ||
320
- isPreviewMode ||
328
+ isReadOnly ||
321
329
  (!isTemplateActivated && !isGlobal),
322
330
  action: handleSavePage,
323
331
  };
@@ -393,6 +401,15 @@ const PageEditor = (props: IProps) => {
393
401
 
394
402
  const mainUnpublishAction = { title: "Ok", onClick: toggleUnpublishModal };
395
403
 
404
+ const tabsPreview = {
405
+ icons: [
406
+ { name: "edit", text: "Edit mode" },
407
+ { name: "view", text: "Preview mode" },
408
+ ],
409
+ selectedTab,
410
+ action: (tab: string) => setSelectedTab(tab),
411
+ };
412
+
396
413
  return isLoading ? (
397
414
  <Loading />
398
415
  ) : (
@@ -400,6 +417,7 @@ const PageEditor = (props: IProps) => {
400
417
  <RouteLeavingGuard when={isDirty} action={goToPages} text={modalText} />
401
418
  <MainWrapper
402
419
  title={pageName}
420
+ subtitle={structuredData}
403
421
  backLink={backLinkRoute}
404
422
  rightButton={rightButtonProps}
405
423
  downArrowMenu={downArrowMenu}
@@ -415,6 +433,7 @@ const PageEditor = (props: IProps) => {
415
433
  errors={errors}
416
434
  errorActions={{ goToError }}
417
435
  isFromEditor={true}
436
+ tabs={tabsPreview}
418
437
  >
419
438
  {(!isTemplateActivated || hasDeactivatedModules) && !isGlobal && (
420
439
  <S.NotificationWrapper>
@@ -442,15 +461,19 @@ const PageEditor = (props: IProps) => {
442
461
  </S.NotificationWrapper>
443
462
  )}
444
463
  <ErrorToast size="l" />
445
- <S.Content>
446
- <Editor
447
- isTemplateActivated={isTemplateActivated}
448
- isGlobal={isGlobal}
449
- isEditable={isEditable}
450
- pageTitle={pageName}
451
- isPreviewMode={isPreviewMode}
452
- />
453
- </S.Content>
464
+ {selectedTab === "edit" ? (
465
+ <S.Content>
466
+ <Editor
467
+ isTemplateActivated={isTemplateActivated}
468
+ isGlobal={isGlobal}
469
+ isEditable={isEditable}
470
+ pageTitle={pageName}
471
+ isReadOnly={isReadOnly}
472
+ />
473
+ </S.Content>
474
+ ) : (
475
+ <Preview />
476
+ )}
454
477
  <Modal
455
478
  isOpen={isOpen}
456
479
  hide={toggleModal}
@@ -0,0 +1,92 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { useParams } from "react-router-dom";
3
+
4
+ import * as components from "components";
5
+ import { providers, translations, cloudinaryDefaults, themes, griddoDamDefaults } from "components";
6
+ import { Preview } from "@griddo/core";
7
+ import { pages } from "@ax/api";
8
+ import { isReqOk } from "@ax/helpers";
9
+ import { Loading } from "@ax/components";
10
+
11
+ import * as S from "./style";
12
+
13
+ const PublicPreview = () => {
14
+ const { id: pageID, entity } = useParams<{ id: string; entity: string }>();
15
+ const [state, setState] = useState<any>(null);
16
+ const [isLoading, setIsLoading] = useState(false);
17
+
18
+ useEffect(() => {
19
+ let isMounted = true;
20
+ document.body.classList.add("preview");
21
+
22
+ const getPage = async () => {
23
+ if (!isMounted) return;
24
+
25
+ setIsLoading(true);
26
+ const response = await pages.getPublicPage(parseInt(pageID), entity);
27
+ if (isReqOk(response.status)) {
28
+ setState(response.data);
29
+ } else {
30
+ console.log("Error en getPublicPage");
31
+ }
32
+ setIsLoading(false);
33
+ };
34
+
35
+ getPage();
36
+
37
+ return function cleanup() {
38
+ isMounted = false;
39
+ document.body.classList.remove("preview");
40
+ };
41
+ // eslint-disable-next-line react-hooks/exhaustive-deps
42
+ }, []);
43
+
44
+ const API_URL = process.env.REACT_APP_API_ENDPOINT;
45
+ const PUBLIC_API_URL = process.env.REACT_APP_PUBLIC_API_ENDPOINT;
46
+ const { SiteProvider, AnimationProvider } = providers;
47
+
48
+ const defaultTheme = themes.find((theme: any) => theme.default);
49
+ const globalTheme = defaultTheme ? defaultTheme.value : themes[0].value;
50
+ const theme = state && state.site ? state.siteInfo.theme : globalTheme;
51
+ const socials = state && state.site ? state.siteInfo.socials : [];
52
+ const langs = state && state.site ? state.siteInfo.siteLanguages : [];
53
+
54
+ if (isLoading) return <Loading />;
55
+
56
+ return (
57
+ <SiteProvider
58
+ cloudinaryCloudName={state && state.cloudinaryName}
59
+ damDomain={state && state.damDomain}
60
+ theme={theme}
61
+ socials={socials}
62
+ siteLangs={langs}
63
+ translations={translations}
64
+ selectEditorID={0}
65
+ cloudinaryDefaults={cloudinaryDefaults}
66
+ griddoDamDefaults={griddoDamDefaults}
67
+ renderer="editor"
68
+ apiUrl={API_URL}
69
+ publicApiUrl={PUBLIC_API_URL}
70
+ siteId={state && state.site}
71
+ >
72
+ <AnimationProvider showOnScroll={{ active: false }}>
73
+ <S.Wrapper ref={(ref: any) => ((window as any).browserRef = ref)}>
74
+ {state && (
75
+ <Preview
76
+ isPage={true}
77
+ apiUrl={API_URL}
78
+ library={components}
79
+ content={state}
80
+ header={state && state.headerContent}
81
+ footer={state && state.footerContent}
82
+ languageId={state && state.language}
83
+ pageLanguages={state && state.pageLanguages}
84
+ />
85
+ )}
86
+ </S.Wrapper>
87
+ </AnimationProvider>
88
+ </SiteProvider>
89
+ );
90
+ };
91
+
92
+ export default PublicPreview;
@@ -0,0 +1,18 @@
1
+ import styled from "styled-components";
2
+
3
+ const Wrapper = styled.div`
4
+ overflow: auto;
5
+ scroll-behavior: smooth;
6
+ height: 100%;
7
+ position: relative;
8
+
9
+ .headroom {
10
+ position: relative !important;
11
+ }
12
+
13
+ body.preview:not(&) {
14
+ min-width: 0 !important;
15
+ }
16
+ `;
17
+
18
+ export { Wrapper };
@@ -1,10 +1,20 @@
1
1
  import React from "react";
2
2
 
3
- import { CheckField, SiteFilter, TableCounter } from "@ax/components";
3
+ import { CheckField, SiteFilter, TableCounter, DateFilter } from "@ax/components";
4
4
  import * as S from "./style";
5
5
 
6
- const TableHeader = (props: IProps) => {
7
- const { totalItems, selectAllItems, isScrolling, filterItems, filterValues, isSiteItem } = props;
6
+ const TableHeader = (props: IProps): JSX.Element => {
7
+ const {
8
+ totalItems,
9
+ selectAllItems,
10
+ isScrolling,
11
+ filterItems,
12
+ filterValues,
13
+ isSiteItem,
14
+ sortItems,
15
+ sortedListStatus,
16
+ } = props;
17
+
8
18
  return (
9
19
  <S.TableHeader isScrolling={isScrolling}>
10
20
  <S.CheckHeader>
@@ -25,6 +35,7 @@ const TableHeader = (props: IProps) => {
25
35
  )}
26
36
  <S.UrlHeader>Old URL</S.UrlHeader>
27
37
  <S.UrlHeader>New URL</S.UrlHeader>
38
+ <DateFilter sortItems={sortItems} sortedState={sortedListStatus} />
28
39
  <S.ActionsHeader>
29
40
  <TableCounter totalItems={totalItems} />
30
41
  </S.ActionsHeader>
@@ -39,6 +50,8 @@ interface IProps {
39
50
  filterItems: (filterPointer: string, filtersSelected: string) => void;
40
51
  filterValues: any;
41
52
  isSiteItem: boolean;
53
+ sortItems: (orderPointer: string, isAscending: boolean) => void;
54
+ sortedListStatus: { isAscending: boolean; sortedByDate: boolean };
42
55
  }
43
56
 
44
57
  export default TableHeader;
@@ -15,11 +15,11 @@ const CheckHeader = styled(Header)`
15
15
  `;
16
16
 
17
17
  const SiteHeader = styled(Header)`
18
- width: 270px;
18
+ width: 200px;
19
19
  `;
20
20
 
21
21
  const UrlHeader = styled(Header)`
22
- width: 50%;
22
+ flex: 1;
23
23
  `;
24
24
 
25
25
  const ActionsHeader = styled(Header)`
@@ -28,4 +28,10 @@ const ActionsHeader = styled(Header)`
28
28
  justify-content: flex-end;
29
29
  `;
30
30
 
31
- export { TableHeader, CheckHeader, SiteHeader, UrlHeader, ActionsHeader };
31
+ export {
32
+ TableHeader,
33
+ CheckHeader,
34
+ SiteHeader,
35
+ UrlHeader,
36
+ ActionsHeader,
37
+ };
@@ -14,6 +14,8 @@ const BulkHeader = (props: IProps): JSX.Element => {
14
14
  filterItems,
15
15
  filterValues,
16
16
  isSiteItem,
17
+ sortItems,
18
+ sortedListStatus,
17
19
  } = props;
18
20
 
19
21
  const bulkActions = [
@@ -39,7 +41,9 @@ const BulkHeader = (props: IProps): JSX.Element => {
39
41
  filterItems={filterItems}
40
42
  filterValues={filterValues}
41
43
  isSiteItem={isSiteItem}
42
- />
44
+ sortItems={sortItems}
45
+ sortedListStatus={sortedListStatus}
46
+ />
43
47
  );
44
48
  };
45
49
 
@@ -54,6 +58,8 @@ interface IProps {
54
58
  filterItems: (filterPointer: string, filtersSelected: string) => void;
55
59
  filterValues: any;
56
60
  isSiteItem: boolean;
61
+ sortItems: (orderPointer: string, isAscending: boolean) => void;
62
+ sortedListStatus: { isAscending: boolean; sortedByDate: boolean };
57
63
  }
58
64
 
59
65
  export default BulkHeader;
@@ -1,5 +1,6 @@
1
1
  import React, { useState } from "react";
2
2
  import { connect } from "react-redux";
3
+ import { format } from "date-fns";
3
4
 
4
5
  import { useModal } from "@ax/hooks";
5
6
  import { ICheck, IRedirect } from "@ax/types";
@@ -84,6 +85,9 @@ const RedirectItem = (props: IRedirectItemProps): JSX.Element => {
84
85
  <S.UrlCell role="cell" onClick={handleClick}>
85
86
  {redirect.to?.url.replace(regex, "")}
86
87
  </S.UrlCell>
88
+ <S.DateCell role="cell" onClick={handleClick}>
89
+ {redirect.date && format(new Date(redirect.date), "dd MMM yyyy")}
90
+ </S.DateCell>
87
91
  <S.ActionsCell role="cell">
88
92
  <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
89
93
  </S.ActionsCell>
@@ -12,12 +12,19 @@ const CheckCell = styled(Cell)`
12
12
  `;
13
13
 
14
14
  const SiteCell = styled(Cell)`
15
- width: 270px;
15
+ width: 200px;
16
16
  `;
17
17
 
18
18
  const UrlCell = styled(Cell)`
19
19
  ${(p) => p.theme.textStyle.uiXS};
20
- width: 50%;
20
+ color: ${(p) => p.theme.color.textHighEmphasis};
21
+ flex: 1;
22
+ `;
23
+
24
+ const DateCell = styled(Cell)`
25
+ ${(p) => p.theme.textStyle.uiXS};
26
+ color: ${(p) => p.theme.color.textMediumEmphasis};
27
+ width: 100px;
21
28
  `;
22
29
 
23
30
  const ActionsCell = styled(Cell)`
@@ -47,4 +54,13 @@ const ModalContent = styled.div`
47
54
  }
48
55
  `;
49
56
 
50
- export { CheckCell, SiteCell, ActionsCell, UrlCell, StyledActionMenu, ItemRow, ModalContent };
57
+ export {
58
+ CheckCell,
59
+ SiteCell,
60
+ ActionsCell,
61
+ UrlCell,
62
+ StyledActionMenu,
63
+ ItemRow,
64
+ ModalContent,
65
+ DateCell,
66
+ };
@@ -2,7 +2,6 @@ import React, { useRef } from "react";
2
2
 
3
3
  import { IModal, IRedirect } from "@ax/types";
4
4
  import { Button, Icon, Modal } from "@ax/components";
5
- import { trimText } from "@ax/helpers";
6
5
 
7
6
  import * as S from "./style";
8
7
 
@@ -0,0 +1,67 @@
1
+ import { useState } from "react";
2
+
3
+ const useSortedListStatus = () => {
4
+ const sortedInitialState: { isAscending: boolean; sortedByDate: boolean; } = {
5
+ isAscending: false,
6
+ sortedByDate: false,
7
+ };
8
+
9
+ const [sortedListStatus, setSortedListStatus] = useState(sortedInitialState);
10
+
11
+ return {
12
+ sortedListStatus,
13
+ setSortedListStatus,
14
+ };
15
+ };
16
+
17
+ const useFilterQuery = (currentSiteID: number | null) => {
18
+ const initialQueryValues = {
19
+ sites: currentSiteID || "all",
20
+ order: "",
21
+ };
22
+
23
+ const [query, setQuery] = useState(initialQueryValues);
24
+
25
+ const setFilterQuery = (filterValues: any) => {
26
+ const { sites, order } = filterValues;
27
+ let filterQuery = "";
28
+
29
+ const currentQuery = (pointer: string, values: string) => {
30
+ return filterQuery.concat(`&${pointer}=${values}`);
31
+ };
32
+
33
+ if (sites) {
34
+ filterQuery = currentQuery("sites", sites);
35
+ }
36
+
37
+ if (order) {
38
+ filterQuery = currentQuery("order", order);
39
+ }
40
+
41
+ return filterQuery;
42
+ };
43
+
44
+ const setFiltersSelection = (pointer: string, filter: string, isAscendent?: boolean) => {
45
+ const { sites, order } = query;
46
+ const orderMethod = isAscendent ? "asc" : "desc";
47
+ const filterValues = {
48
+ sites: pointer === "sites" ? filter : sites,
49
+ order: pointer === "order" ? `${filter}-${orderMethod}` : order,
50
+ };
51
+
52
+ setQuery(filterValues);
53
+
54
+ return filterValues;
55
+ };
56
+
57
+ const resetFilterQuery = () => setQuery(initialQueryValues);
58
+
59
+ return {
60
+ setFiltersSelection,
61
+ setFilterQuery,
62
+ resetFilterQuery,
63
+ filterValues: query,
64
+ };
65
+ };
66
+
67
+ export { useSortedListStatus, useFilterQuery };
@@ -6,10 +6,13 @@ import { appActions } from "@ax/containers/App";
6
6
  import { redirectsActions } from "@ax/containers/Redirects";
7
7
  import { MainWrapper, ErrorToast, Nav, TableList, EmptyState, Toast } from "@ax/components";
8
8
  import { useBulkSelection, useModal, useToast } from "@ax/hooks";
9
+
9
10
  import BulkHeader from "./BulkHeader";
10
11
  import RedirectItem from "./RedirectItem";
11
12
  import RedirectPanel from "./RedirectPanel";
12
13
  import { DeleteModal, ImportCheckModal, ImportModal, OverwriteModal } from "./atoms";
14
+ import { getSortedListStatus } from "./utils";
15
+ import { useSortedListStatus, useFilterQuery } from "./hooks";
13
16
 
14
17
  import * as S from "./style";
15
18
 
@@ -30,14 +33,16 @@ const Redirects = (props: IProps): JSX.Element => {
30
33
  } = props;
31
34
 
32
35
  const itemsPerPage = 50;
36
+ const firstPage = 1;
33
37
  const [page, setPage] = useState(1);
34
38
  const [isScrolling, setIsScrolling] = useState(false);
35
39
  const [isOpenedSecond, setIsOpenedSecond] = useState(false);
36
40
  const { isOpen, toggleModal } = useModal();
37
41
  const { isOpen: isOpenDelete, toggleModal: toggleModalDelete } = useModal();
38
42
  const tableRef = useRef<HTMLDivElement>(null);
39
- const [currentFilterQuery, setCurrentFilterQuery] = useState("");
40
- const [filterValues, setFilterValues] = useState({ sites: "all" });
43
+ const { sortedListStatus, setSortedListStatus } = useSortedListStatus();
44
+ const { setFiltersSelection, setFilterQuery, filterValues } = useFilterQuery(currentSiteID);
45
+ const [currentFilterQuery, setCurrentFilterQuery] = useState(`&sites=${currentSiteID}`);
41
46
  const { isVisible, toggleToast, setIsVisible } = useToast();
42
47
  const { isVisible: isImportVisible, toggleToast: toggleImportToast, setIsVisible: setIsImportVisible } = useToast();
43
48
  const { isOpen: isOpenOverwrite, toggleModal: toggleOverwriteModal } = useModal();
@@ -71,8 +76,7 @@ const Redirects = (props: IProps): JSX.Element => {
71
76
 
72
77
  useEffect(() => {
73
78
  const params = getParams();
74
- const siteFilterQuery = currentSiteID ? `&sites=${currentSiteID}` : currentFilterQuery;
75
- getRedirects(params, siteFilterQuery);
79
+ getRedirects(params, currentFilterQuery);
76
80
  if (tableRef.current) {
77
81
  tableRef.current.scrollTo(0, 0);
78
82
  }
@@ -103,12 +107,20 @@ const Redirects = (props: IProps): JSX.Element => {
103
107
 
104
108
  const handleSelectAll = () => selectAllItems();
105
109
 
110
+ const sortItems = async (orderPointer: string, isAscending: boolean) => {
111
+ setPage(firstPage);
112
+ const sortedState = getSortedListStatus(orderPointer, isAscending);
113
+ setSortedListStatus(sortedState);
114
+
115
+ const filtersSelection = setFiltersSelection("order", orderPointer, isAscending);
116
+ const filterQuery = setFilterQuery(filtersSelection);
117
+ setCurrentFilterQuery(filterQuery);
118
+ };
119
+
106
120
  const filterItems = async (filterPointer: string, filtersSelected: string) => {
107
- let filterQuery = "";
108
- if (filtersSelected !== "all") {
109
- filterQuery = `&${filterPointer}=${filtersSelected}`;
110
- }
111
- setFilterValues({ sites: filtersSelected });
121
+ setPage(firstPage);
122
+ const filtersSelection = setFiltersSelection(filterPointer, filtersSelected);
123
+ const filterQuery = setFilterQuery(filtersSelection);
112
124
  setCurrentFilterQuery(filterQuery);
113
125
  };
114
126
 
@@ -124,6 +136,8 @@ const Redirects = (props: IProps): JSX.Element => {
124
136
  filterItems={filterItems}
125
137
  filterValues={filterValues}
126
138
  isSiteItem={!!currentSiteID}
139
+ sortItems={sortItems}
140
+ sortedListStatus={sortedListStatus}
127
141
  />
128
142
  );
129
143
 
@@ -0,0 +1,10 @@
1
+ const getSortedListStatus = (orderPointer: string, isAscending: boolean): { isAscending: boolean, sortedByDate: boolean } => {
2
+ const sortedListStatus = {
3
+ isAscending,
4
+ sortedByDate: orderPointer === "date",
5
+ };
6
+
7
+ return sortedListStatus;
8
+ };
9
+
10
+ export { getSortedListStatus }
@@ -0,0 +1,107 @@
1
+ import React from "react";
2
+
3
+ import { useModal } from "@ax/hooks";
4
+ import { SideModal, ActionMenu } from "@ax/components";
5
+
6
+ import * as S from "./style";
7
+
8
+ const pageEditorID = 0;
9
+
10
+ const Field = (props: IField): JSX.Element => {
11
+ const {
12
+ type,
13
+ template,
14
+ defaults,
15
+ updateEditorContent,
16
+ content,
17
+ updateDataPackFormValue,
18
+ dataPackConfigFormData,
19
+ theme,
20
+ } = props;
21
+ const { isOpen, toggleModal } = useModal();
22
+ const options = defaults.filter((component: any) =>
23
+ component.type === type && content[component.type]?.id !== component.id && !component.setAsDefault
24
+ );
25
+ const optionsType = `${type}s`;
26
+
27
+ const actionMenuOptions = [
28
+ {
29
+ label: "replace",
30
+ icon: "change",
31
+ action: toggleModal,
32
+ },
33
+ ];
34
+
35
+ const actionMenuIcon = "more";
36
+
37
+ const handleReplace = (option: any) => {
38
+ const configFormData = {
39
+ ...dataPackConfigFormData,
40
+ templates: {
41
+ ...dataPackConfigFormData.templates,
42
+ [template]: {
43
+ ...(!!dataPackConfigFormData.templates && dataPackConfigFormData.templates[template]),
44
+ ...(type === "header" && { defaultHeader: option.id }),
45
+ ...(type === "footer" && { defaultFooter: option.id }),
46
+ }
47
+ },
48
+ }
49
+ updateDataPackFormValue(configFormData);
50
+ updateEditorContent(pageEditorID, type, option.id);
51
+ toggleModal();
52
+ };
53
+
54
+ const isDefaultNavigation = () => {
55
+ const defaultType = type === "header" ? "defaultHeader" : "defaultFooter";
56
+ const templateNavigation = dataPackConfigFormData.templates && dataPackConfigFormData.templates[template]
57
+ const templateDefaultNavigation = templateNavigation && templateNavigation[defaultType];
58
+ if (!templateDefaultNavigation) return true;
59
+ const siteDefaultNavigation = defaults.find((navigation: any) => navigation.id === templateDefaultNavigation);
60
+ return !!siteDefaultNavigation?.isDefault;
61
+ }
62
+
63
+ const setDefault = {
64
+ title: `Put the default ${type}`,
65
+ action: () => handleReplace({ id: null }),
66
+ checked: isDefaultNavigation(),
67
+ }
68
+
69
+ const hasOptions: boolean | undefined = options?.length > 0 || !isDefaultNavigation();
70
+
71
+ if (!content[type]) return <></>;
72
+
73
+ return (
74
+ <>
75
+ <S.Component isArray disabled>
76
+ <S.Label>{content[type].title}</S.Label>
77
+ <S.HiddenButtonsWrapper>
78
+ {hasOptions && <ActionMenu options={actionMenuOptions} icon={actionMenuIcon} />}
79
+ </S.HiddenButtonsWrapper>
80
+ </S.Component>
81
+ {hasOptions && (
82
+ <SideModal
83
+ optionsType={optionsType}
84
+ whiteList={options}
85
+ handleClick={handleReplace}
86
+ toggleModal={toggleModal}
87
+ isOpen={isOpen}
88
+ setDefault={setDefault}
89
+ theme={theme}
90
+ />
91
+ )}
92
+ </>
93
+ )
94
+ }
95
+
96
+ interface IField {
97
+ type: string;
98
+ template: string;
99
+ defaults: any;
100
+ content: any,
101
+ dataPackConfigFormData: any;
102
+ theme: string;
103
+ updateEditorContent: (selectedEditorID: number, key: string, value: any) => void;
104
+ updateDataPackFormValue: (value: any) => void;
105
+ }
106
+
107
+ export { Field }