@griddo/ax 11.11.5 → 11.11.7-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.
Files changed (36) hide show
  1. package/README.md +0 -5
  2. package/package.json +2 -2
  3. package/src/__tests__/components/Browser/Browser.test.tsx +1 -87
  4. package/src/__tests__/helpers/shareToken.test.ts +91 -0
  5. package/src/api/index.tsx +4 -0
  6. package/src/api/pages.tsx +21 -18
  7. package/src/api/shareToken.tsx +62 -0
  8. package/src/api/utils.tsx +13 -0
  9. package/src/components/Browser/index.tsx +77 -31
  10. package/src/components/Browser/style.tsx +15 -8
  11. package/src/components/BrowserContent/index.tsx +20 -5
  12. package/src/components/ErrorPage/index.tsx +28 -14
  13. package/src/components/Fields/TextField/index.tsx +18 -4
  14. package/src/components/Icon/components/GriddoLogo.js +16 -0
  15. package/src/components/Icon/index.tsx +1 -0
  16. package/src/components/Icon/svgs/GriddoLogo.svg +9 -0
  17. package/src/components/Modal/index.tsx +3 -1
  18. package/src/components/Modal/style.tsx +19 -10
  19. package/src/components/PageInfoBanner/index.tsx +38 -0
  20. package/src/components/PageInfoBanner/styles.tsx +40 -0
  21. package/src/components/SearchField/index.tsx +10 -6
  22. package/src/components/SearchField/style.tsx +48 -27
  23. package/src/components/SharePageModal/index.tsx +187 -0
  24. package/src/components/SharePageModal/style.tsx +41 -0
  25. package/src/components/StatusTile/index.tsx +28 -0
  26. package/src/components/StatusTile/styles.ts +63 -0
  27. package/src/components/index.tsx +103 -102
  28. package/src/global.d.ts +8 -0
  29. package/src/helpers/dates.tsx +14 -8
  30. package/src/helpers/index.tsx +5 -0
  31. package/src/helpers/shareToken.ts +25 -0
  32. package/src/locales/en-US.ts +1 -0
  33. package/src/locales/es-ES.ts +1 -0
  34. package/src/modules/PublicPreview/index.tsx +35 -13
  35. package/src/routes/publicRoutes.tsx +2 -2
  36. package/src/themes/theme.json +4 -0
@@ -0,0 +1,25 @@
1
+ import type { IShareData } from "@ax/api";
2
+
3
+ import { differenceInCalendarDays, isBefore } from "date-fns";
4
+
5
+ import { formatDate } from "./dates";
6
+
7
+ const TOKEN_CAN_BE_RENEWED_DAYS = 14;
8
+
9
+ // DEV ONLY — set a future/past date to simulate token states, then revert to undefined
10
+ export const DEV_NOW: Date | undefined = undefined; // new Date("2036-04-13");
11
+
12
+ export const getShareTokenInfo = (shareData: IShareData, now = new Date()) => {
13
+ const expirationDate = new Date(shareData.endDate);
14
+ const tokenHasExpired = isBefore(expirationDate, now);
15
+ const validTokenDaysUntilExpires = Math.max(0, differenceInCalendarDays(expirationDate, now));
16
+
17
+ return {
18
+ tokenExpirationDate: formatDate(expirationDate),
19
+ tokenHasExpired,
20
+ tokenCanBeRenewed: !tokenHasExpired && validTokenDaysUntilExpires < TOKEN_CAN_BE_RENEWED_DAYS,
21
+ validTokenDaysUntilExpires,
22
+ };
23
+ };
24
+
25
+ export type ShareTokenInfo = ReturnType<typeof getShareTokenInfo>;
@@ -26,6 +26,7 @@ export const enUS = {
26
26
  moving: "moving",
27
27
  deactivating: "deactivating",
28
28
  activating: "activating",
29
+ typeSomething: "Type something",
29
30
  },
30
31
  fields: {
31
32
  tags: {
@@ -26,6 +26,7 @@ export const esES = {
26
26
  moving: "moviendo",
27
27
  deactivating: "desactivando",
28
28
  activating: "activando",
29
+ typeSomething: "Escribe algo",
29
30
  },
30
31
  fields: {
31
32
  tags: {
@@ -1,8 +1,8 @@
1
1
  import { useEffect, useState } from "react";
2
2
  import { useParams } from "react-router-dom";
3
3
 
4
- import { pages } from "@ax/api";
5
- import { BrowserContent, Loading } from "@ax/components";
4
+ import { pages, shareToken as shareTokenApi } from "@ax/api";
5
+ import { BrowserContent, ErrorPage, Loading } from "@ax/components";
6
6
  import { getDefaultTheme, isReqOk } from "@ax/helpers";
7
7
 
8
8
  import * as S from "./style";
@@ -11,21 +11,35 @@ const PublicPreview = () => {
11
11
  const { id: pageID, entity } = useParams<{ id: string; entity: string }>();
12
12
  const [state, setState] = useState<any>(null);
13
13
  const [isLoading, setIsLoading] = useState(false);
14
+ const [tokenError, setTokenError] = useState(false);
15
+ const [shareEndDate, setShareEndDate] = useState<string | null>(null);
14
16
 
15
17
  // biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
16
18
  useEffect(() => {
17
19
  let isMounted = true;
18
20
  document.body.classList.add("preview");
19
21
 
22
+ // Store preview credentials in sessionStorage for API calls
23
+ if (pageID && entity) {
24
+ sessionStorage.setItem("previewPageId", pageID);
25
+ sessionStorage.setItem("previewEntity", entity);
26
+ }
27
+
20
28
  const getPage = async () => {
21
29
  if (!isMounted) return;
22
30
 
23
31
  setIsLoading(true);
32
+
24
33
  const response = await pages.getPublicPage(parseInt(pageID), entity);
25
34
  if (isReqOk(response.status)) {
26
35
  setState(response.data);
36
+
37
+ const shareResponse = await shareTokenApi.getShare(parseInt(pageID));
38
+ if (isReqOk(shareResponse.status)) {
39
+ setShareEndDate(shareResponse.data.endDate);
40
+ }
27
41
  } else {
28
- console.log("Error en getPublicPage");
42
+ setTokenError(true);
29
43
  }
30
44
  setIsLoading(false);
31
45
  };
@@ -35,14 +49,21 @@ const PublicPreview = () => {
35
49
  return function cleanup() {
36
50
  isMounted = false;
37
51
  document.body.classList.remove("preview");
52
+ // Clean up preview credentials when leaving preview
53
+ sessionStorage.removeItem("previewPageId");
54
+ sessionStorage.removeItem("previewEntity");
38
55
  };
39
56
  }, []);
40
57
 
41
58
  const globalTheme = getDefaultTheme();
42
- const theme = state && state.site ? state.siteInfo.theme : globalTheme;
43
- const socials = state && state.site ? state.siteInfo.socials : [];
44
- const langs = state && state.site ? state.siteInfo.siteLanguages : [];
45
- const siteID = state && state.siteInfo ? state.siteInfo.siteId : undefined;
59
+ const theme = state?.site ? state.siteInfo.theme : globalTheme;
60
+ const socials = state?.site ? state.siteInfo.socials : [];
61
+ const langs = state?.site ? state.siteInfo.siteLanguages : [];
62
+ const siteID = state?.siteInfo ? state.siteInfo.siteId : undefined;
63
+
64
+ if (tokenError) {
65
+ return <ErrorPage type="linkExpired" />;
66
+ }
46
67
 
47
68
  if (isLoading || !state) return <Loading />;
48
69
 
@@ -50,18 +71,19 @@ const PublicPreview = () => {
50
71
  // biome-ignore lint/suspicious/noAssignInExpressions: TODO: fix this
51
72
  <S.Wrapper ref={(ref: any) => ((window as any).browserRef = ref)}>
52
73
  <BrowserContent
53
- cloudinaryName={state && state.cloudinaryName}
74
+ cloudinaryName={state?.cloudinaryName}
54
75
  theme={theme}
55
76
  socials={socials}
56
77
  siteLangs={langs}
57
78
  siteID={siteID}
58
79
  isPage={true}
59
80
  content={state}
60
- header={state && state.headerContent}
61
- footer={state && state.footerContent}
62
- languageID={state && state.language}
63
- pageLanguages={state && state.pageLanguages}
64
- renderer="preview"
81
+ header={state?.headerContent}
82
+ footer={state?.footerContent}
83
+ languageID={state?.language}
84
+ pageLanguages={state?.pageLanguages}
85
+ renderer="sharedPage"
86
+ shareEndDate={shareEndDate}
65
87
  />
66
88
  </S.Wrapper>
67
89
  );
@@ -1,14 +1,14 @@
1
- import ResetPass from "./../modules/ResetPass";
2
1
  import CreatePass from "./../modules/CreatePass";
3
2
  import Login from "./../modules/Login";
4
3
  import PublicPreview from "./../modules/PublicPreview";
4
+ import ResetPass from "./../modules/ResetPass";
5
5
 
6
6
  const publicRoutes = [
7
7
  { path: "/login/:petitionId", component: Login, name: "Login", hideNav: true },
8
8
  { path: "/login", component: Login, name: "Login", hideNav: true },
9
9
  { path: "/new-password/:id/:token", component: ResetPass, name: "Reset Password", hideNav: true },
10
10
  { path: "/set-password/:id/:token", component: CreatePass, name: "Create Password", hideNav: true },
11
- { path: "/page-preview/:id/:entity", component: PublicPreview, name: "Preview", hideNav: true },
11
+ { path: "/page-preview/:id/:entity/:token?", component: PublicPreview, name: "Preview", hideNav: true },
12
12
  ];
13
13
 
14
14
  export default publicRoutes;
@@ -227,6 +227,10 @@
227
227
  "description": "warning modified",
228
228
  "value": "#ffbb37"
229
229
  },
230
+ "success": {
231
+ "description": "success",
232
+ "value": "#afc628"
233
+ },
230
234
  "borderInverse": {
231
235
  "description": "Border for ocassional toasts",
232
236
  "type": "RGB",