@griddo/ax 11.14.4 → 11.14.5-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 (48) hide show
  1. package/package.json +2 -2
  2. package/src/api/sites.tsx +2 -2
  3. package/src/components/Fields/ImageField/index.tsx +52 -28
  4. package/src/components/Fields/ImageField/style.tsx +22 -13
  5. package/src/components/Fields/NoteField/index.tsx +1 -3
  6. package/src/components/Fields/NoteField/style.tsx +1 -0
  7. package/src/components/Fields/TextArea/style.tsx +5 -2
  8. package/src/components/Fields/ToggleField/index.tsx +3 -2
  9. package/src/components/FieldsBehavior/index.tsx +27 -3
  10. package/src/components/FieldsBehavior/style.tsx +9 -7
  11. package/src/components/FloatingNote/index.tsx +1 -1
  12. package/src/components/FloatingPanel/style.tsx +4 -1
  13. package/src/components/HeadingsPreviewModal/style.tsx +1 -1
  14. package/src/components/Icon/components/Party.js +16 -0
  15. package/src/components/Icon/svgs/Party.svg +3 -0
  16. package/src/components/Image/index.tsx +2 -1
  17. package/src/components/Image/utils.ts +3 -3
  18. package/src/components/MainWrapper/AppBar/atoms.tsx +118 -34
  19. package/src/components/MainWrapper/AppBar/index.tsx +64 -86
  20. package/src/components/MainWrapper/AppBar/style.tsx +5 -0
  21. package/src/components/MainWrapper/index.tsx +2 -41
  22. package/src/containers/Navigation/Defaults/reducer.tsx +2 -2
  23. package/src/containers/Sites/actions.tsx +2 -3
  24. package/src/modules/Content/index.tsx +26 -8
  25. package/src/modules/Content/style.tsx +5 -0
  26. package/src/modules/GlobalSettings/Robots/Item/RobotsPanel/index.tsx +34 -17
  27. package/src/modules/GlobalSettings/Robots/Item/RobotsPanel/style.tsx +37 -5
  28. package/src/modules/GlobalSettings/Robots/index.tsx +4 -3
  29. package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +8 -17
  30. package/src/modules/Navigation/Defaults/Item/index.tsx +17 -19
  31. package/src/modules/Navigation/Defaults/index.tsx +5 -8
  32. package/src/modules/Settings/Globals/NavigationModules/index.tsx +1 -1
  33. package/src/modules/Settings/Globals/NavigationModules/style.tsx +1 -2
  34. package/src/modules/Settings/Globals/index.tsx +194 -73
  35. package/src/modules/Settings/Globals/style.tsx +67 -1
  36. package/src/modules/Settings/Integrations/IntegrationItem/index.tsx +2 -3
  37. package/src/modules/Sites/SitesList/GridView/GridSiteItem/index.tsx +13 -5
  38. package/src/modules/Sites/SitesList/GridView/GridSiteItem/style.tsx +16 -8
  39. package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/index.tsx +1 -0
  40. package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/style.tsx +7 -1
  41. package/src/modules/Sites/SitesList/ListView/ListSiteItem/index.tsx +8 -1
  42. package/src/modules/Sites/SitesList/ListView/ListSiteItem/style.tsx +7 -1
  43. package/src/modules/Sites/SitesList/SiteModal/index.tsx +77 -23
  44. package/src/modules/Sites/SitesList/atoms.tsx +4 -4
  45. package/src/modules/Sites/SitesList/index.tsx +9 -47
  46. package/src/modules/Sites/SitesList/style.tsx +8 -4
  47. package/src/modules/Users/UserForm/index.tsx +1 -1
  48. package/src/types/index.tsx +11 -22
@@ -1,13 +1,24 @@
1
1
  import { useState } from "react";
2
2
  import { connect } from "react-redux";
3
3
 
4
- import { ErrorToast, FieldGroup, FieldsBehavior, MainWrapper, Modal, Nav, Notification } from "@ax/components";
4
+ import {
5
+ Button,
6
+ ErrorToast,
7
+ FieldsBehavior,
8
+ Icon,
9
+ MainWrapper,
10
+ Modal,
11
+ Nav,
12
+ Notification,
13
+ Toast,
14
+ ToggleField,
15
+ } from "@ax/components";
5
16
  import { appActions } from "@ax/containers/App";
6
17
  import { sitesActions } from "@ax/containers/Sites";
7
18
  import { RouteLeavingGuard } from "@ax/guards";
8
19
  import { getNavigationModules } from "@ax/helpers";
9
- import { useModal, useShouldBeSaved } from "@ax/hooks";
10
- import type { IGriddoTheme, IImage, INavItem, IRootState, ISettingsForm } from "@ax/types";
20
+ import { useModal, useShouldBeSaved, useToast } from "@ax/hooks";
21
+ import type { IGriddoTheme, IImage, INavItem, IRootState, ISite } from "@ax/types";
11
22
 
12
23
  import { config } from "components";
13
24
 
@@ -23,30 +34,27 @@ const Globals = (props: IProps): JSX.Element => {
23
34
 
24
35
  const [isNavigationNotificationOpen, setIsNavigationNotificationOpen] = useState(false);
25
36
  const [tempTheme, setTempTheme] = useState<string | undefined>();
26
- const { isOpen, toggleModal } = useModal();
27
-
28
- const title = "General settings";
29
-
30
37
  const [isNavigationModulesChanged, setIsNavigationModulesChanged] = useState(!!currentSiteInfo.navigationModules);
31
- const [form, setForm] = useState(currentSiteInfo);
32
-
33
- const { name, timezone, theme, favicon, smallAvatar, bigAvatar, thumbnail } = form;
34
-
38
+ const [form, setForm] = useState<ISite>(currentSiteInfo);
39
+ const { isOpen, toggleModal } = useModal();
40
+ const { isOpen: isHiddenOpen, toggleModal: toggleHiddenModal } = useModal();
41
+ const { isVisible, toggleToast, setIsVisible, state: toastState } = useToast();
35
42
  const { isDirty, setIsDirty } = useShouldBeSaved(form);
36
43
 
44
+ const { name, timezone, theme, favicon, smallAvatar, bigAvatar, thumbnail, home, hidden, showSitemapInRobots } = form;
45
+
37
46
  const navigationModules: Record<string, any[]> = getNavigationModules();
38
47
  const hasMultipleNavigationModules = Object.keys(navigationModules).some(
39
48
  (key: string) => navigationModules[key].length > 1,
40
49
  );
41
50
 
42
- const setValue = (newValue: Record<string, string | null>) =>
43
- setForm((state: ISettingsForm) => ({ ...state, ...newValue }));
51
+ const setValue = (newValue: Partial<ISite>) => setForm((state: ISite) => ({ ...state, ...newValue }));
44
52
 
45
53
  const setNameValue = (value: string) => setValue({ name: value });
46
54
  const setTimezoneValue = (value: string) => setValue({ timezone: value });
47
55
  const setThemeValue = (value: string) => {
48
- const theme = (themes as IGriddoTheme[]).find((th) => th.value === value);
49
- if (theme?.elements) {
56
+ const selectedTheme = (themes as IGriddoTheme[]).find((t) => t.value === value);
57
+ if (selectedTheme?.elements) {
50
58
  setTempTheme(value);
51
59
  toggleModal();
52
60
  } else {
@@ -57,6 +65,17 @@ const Globals = (props: IProps): JSX.Element => {
57
65
  const setSmallAvatarValue = (value: IImage) => setValue({ smallAvatar: value.url ? value.url : null });
58
66
  const setBigAvatarValue = (value: IImage) => setValue({ bigAvatar: value.url ? value.url : null });
59
67
  const setThumbnailValue = (value: IImage) => setValue({ thumbnail: value.url ? value.url : null });
68
+ const setRobotsValue = (value: boolean) => {
69
+ setValue({ showSitemapInRobots: value });
70
+ if (value) {
71
+ toggleToast("Sitemap included in robots.txt");
72
+ }
73
+ };
74
+ const setHiddenValue = () => {
75
+ setValue({ hidden: false });
76
+ saveForm({ ...form, hidden: false });
77
+ toggleHiddenModal();
78
+ };
60
79
  const setNavigationModulesValue = (value: any) => setValue({ navigationModules: value });
61
80
 
62
81
  const handleChangeTheme = () => {
@@ -64,43 +83,51 @@ const Globals = (props: IProps): JSX.Element => {
64
83
  toggleModal();
65
84
  };
66
85
 
67
- const saveForm = async () => {
68
- const isSaved = await saveSettings(form);
86
+ const saveForm = async (newForm: ISite) => {
87
+ const isSaved = await saveSettings(newForm);
69
88
  const isNavigationModulesChanging =
70
- JSON.stringify(form?.navigationModules) !== JSON.stringify(currentSiteInfo?.navigationModules);
89
+ JSON.stringify(form.navigationModules) !== JSON.stringify(currentSiteInfo.navigationModules);
71
90
  setIsNavigationNotificationOpen(isNavigationModulesChanging);
72
91
  if (isSaved) setIsDirty(false);
73
92
  };
74
93
 
94
+ const handleOpenUrl = () => {
95
+ const win = window.open(home, "_blank");
96
+ if (win) {
97
+ win.focus();
98
+ }
99
+ };
100
+
75
101
  const rightButtonProps = {
76
102
  label: isSaving ? "Saving" : isDirty ? "Save" : "Saved",
77
103
  disabled: isSaving || !isDirty,
78
- action: saveForm,
104
+ action: () => saveForm(form),
79
105
  };
80
106
 
81
107
  const setRoute = (path: string) => setHistoryPush(path);
108
+
82
109
  const modalText = (
83
110
  <>
84
- Some settings <strong>are not saved</strong>.{" "}
111
+ Some settings <strong>are not saved</strong>.
85
112
  </>
86
113
  );
87
114
 
88
- const handleMenuClick = (path: string) => {
89
- setHistoryPush(path);
90
- };
91
-
92
115
  const closeNavigationNotification = () => setIsNavigationNotificationOpen(false);
93
116
  const goToNavigationModules = () => setHistoryPush("/sites/navigations/modules");
117
+ const goToLanguages = () => setHistoryPush("/sites/settings/languages");
118
+
119
+ const mainThemeAction = { title: "Understood", onClick: handleChangeTheme };
120
+ const secondaryThemeAction = { title: "Cancel", onClick: toggleModal };
94
121
 
95
- const mainDeleteAction = { title: "Understood", onClick: handleChangeTheme };
96
- const secondaryDeleteAction = { title: "Cancel", onClick: toggleModal };
122
+ const mainHiddenAction = { title: "Enable Indexing", onClick: setHiddenValue };
123
+ const secondaryHiddenAction = { title: "Cancel", onClick: toggleHiddenModal };
97
124
 
98
125
  return (
99
126
  <>
100
127
  <RouteLeavingGuard when={isDirty} action={setRoute} text={modalText} />
101
- <MainWrapper backLink={false} title={title} rightButton={rightButtonProps}>
128
+ <MainWrapper backLink={false} title="General settings" rightButton={rightButtonProps} showTagHidden={hidden}>
102
129
  <S.Wrapper>
103
- <Nav current={currentNavItem} items={navItems} onClick={handleMenuClick} />
130
+ <Nav current={currentNavItem} items={navItems} onClick={setRoute} />
104
131
  <S.ContentWrapper>
105
132
  <ErrorToast />
106
133
  {isNavigationNotificationOpen && (
@@ -113,6 +140,28 @@ const Globals = (props: IProps): JSX.Element => {
113
140
  />
114
141
  )}
115
142
  <S.FormWrapper>
143
+ {hidden ? (
144
+ <S.HiddenFieldWrapper>
145
+ <S.IconWrapper>
146
+ <Icon name="working" size="16" />
147
+ </S.IconWrapper>
148
+ <div>
149
+ Site <strong>hidden from search engines and AI models</strong>. Enable indexing to make it public.
150
+ Permanent action.
151
+ </div>
152
+ <S.StyledToggleField name="hidden" value={!hidden} onChange={toggleHiddenModal} size="s" />
153
+ </S.HiddenFieldWrapper>
154
+ ) : (
155
+ <S.HiddenFieldWrapper>
156
+ <S.IconWrapper>
157
+ <Icon name="party" size="16" />
158
+ </S.IconWrapper>
159
+ <div>
160
+ This site is currently <strong>visible to search engines and AI models</strong>. This is permanent
161
+ and cannot be changed.
162
+ </div>
163
+ </S.HiddenFieldWrapper>
164
+ )}
116
165
  <FieldsBehavior
117
166
  title="Site Name"
118
167
  name="name"
@@ -120,6 +169,21 @@ const Globals = (props: IProps): JSX.Element => {
120
169
  value={name || ""}
121
170
  onChange={setNameValue}
122
171
  />
172
+ <FieldsBehavior
173
+ title="Domain default language"
174
+ name="domain"
175
+ fieldType="TextField"
176
+ readonly={true}
177
+ value={home || ""}
178
+ helptext="To make the changes, go to Language's settings."
179
+ icon="openOutside"
180
+ onClickIcon={handleOpenUrl}
181
+ />
182
+ <S.ButtonWrapper>
183
+ <Button type="button" buttonStyle="line" onClick={goToLanguages}>
184
+ Go to languages
185
+ </Button>
186
+ </S.ButtonWrapper>
123
187
  <FieldsBehavior
124
188
  title="Timezone"
125
189
  name="timezone"
@@ -138,15 +202,6 @@ const Globals = (props: IProps): JSX.Element => {
138
202
  onChange={setThemeValue}
139
203
  mandatory={true}
140
204
  />
141
- <FieldsBehavior
142
- title="Site favicon"
143
- name="favicon"
144
- value={favicon || null}
145
- fieldType="ImageField"
146
- onChange={setFaviconValue}
147
- helptext="Upload a 32x32px image"
148
- noGallery={true}
149
- />
150
205
  {hasMultipleNavigationModules && (
151
206
  <NavigationModules
152
207
  navigationModules={navigationModules}
@@ -154,56 +209,122 @@ const Globals = (props: IProps): JSX.Element => {
154
209
  setNavigationModulesValue={setNavigationModulesValue}
155
210
  isNavigationModulesChanged={isNavigationModulesChanged}
156
211
  setIsNavigationModulesChanged={setIsNavigationModulesChanged}
157
- theme={theme}
212
+ theme={theme ?? ""}
158
213
  />
159
214
  )}
160
- <FieldGroup title="Content for CMS">
161
- <FieldsBehavior
162
- title="Small avatar"
163
- name="smallAvatar"
164
- value={smallAvatar || null}
165
- fieldType="ImageField"
166
- onChange={setSmallAvatarValue}
167
- helptext="Upload a 72x64px image to show in menu"
168
- noGallery={true}
169
- />
170
- <FieldsBehavior
171
- title="Big avatar"
172
- name="bigAvatar"
173
- value={bigAvatar || null}
174
- fieldType="ImageField"
175
- onChange={setBigAvatarValue}
176
- helptext="Upload a 256x64px image to show in open menu"
177
- noGallery={true}
178
- />
179
- <FieldsBehavior
180
- title="Site screen thumbnail"
181
- name="thumbnail"
182
- value={thumbnail || null}
183
- fieldType="ImageField"
184
- onChange={setThumbnailValue}
185
- helptext="Image for site screen"
186
- noGallery={true}
187
- />
188
- </FieldGroup>
215
+ <S.SectionWrapper>
216
+ <S.Heading>Include sitemap in Robots.txt</S.Heading>
217
+ <S.RobotsWrapper>
218
+ <S.Description>
219
+ By selecting this option, the <strong>sitemap of this site will be published in robots.txt</strong>,
220
+ making it easier for search engines to find your pages and therefore improving your SEO ranking.
221
+ </S.Description>
222
+ <ToggleField name="robots" value={showSitemapInRobots} onChange={setRobotsValue} size="s" />
223
+ </S.RobotsWrapper>
224
+ </S.SectionWrapper>
225
+ <S.SectionWrapper>
226
+ <S.Heading>Site Identity</S.Heading>
227
+ <S.Description>Manage how this site appears on the dashboard and browser tabs.</S.Description>
228
+ <S.ColumnsWrapper>
229
+ <FieldsBehavior
230
+ title="Favicon"
231
+ name="favicon"
232
+ value={favicon || null}
233
+ fieldType="ImageField"
234
+ onChange={setFaviconValue}
235
+ helptext="Small icon shown in browser tabs. Upload a png, svg, jpg image"
236
+ selectPosition={false}
237
+ fullWidth={true}
238
+ previewHeight={212}
239
+ previewWidth={348}
240
+ objectFit="contain"
241
+ noGallery
242
+ />
243
+ <FieldsBehavior
244
+ title="Dashboard Thumbnail"
245
+ name="thumbnail"
246
+ value={thumbnail || null}
247
+ fieldType="ImageField"
248
+ onChange={setThumbnailValue}
249
+ helptext="Used on the sites dashboard. Upload a png, svg, jpg image"
250
+ selectPosition={false}
251
+ fullWidth={true}
252
+ previewHeight={212}
253
+ previewWidth={348}
254
+ noGallery
255
+ />
256
+ </S.ColumnsWrapper>
257
+ </S.SectionWrapper>
258
+ <S.SectionWrapper>
259
+ <S.Heading>Navigation Branding</S.Heading>
260
+ <S.Description>Upload the logos displayed in the main navigation menu.</S.Description>
261
+ <S.ColumnsWrapper>
262
+ <FieldsBehavior
263
+ title="Collapsed Griddo menu logo"
264
+ name="smallAvatar"
265
+ value={smallAvatar || null}
266
+ fieldType="ImageField"
267
+ onChange={setSmallAvatarValue}
268
+ helptext="When collapsed, it appears in the Griddo menu. Recommended min size: 32x32px."
269
+ selectPosition={false}
270
+ fullWidth={true}
271
+ previewHeight={212}
272
+ previewWidth={348}
273
+ objectFit="contain"
274
+ noGallery
275
+ />
276
+ <FieldsBehavior
277
+ title="Expanded Griddo menu logo"
278
+ name="bigAvatar"
279
+ value={bigAvatar || null}
280
+ fieldType="ImageField"
281
+ onChange={setBigAvatarValue}
282
+ helptext="When expanded, it appears in the Griddo menu. Recommended min size: 208x32px."
283
+ selectPosition={false}
284
+ fullWidth={true}
285
+ previewHeight={212}
286
+ previewWidth={348}
287
+ objectFit="contain"
288
+ noGallery
289
+ />
290
+ </S.ColumnsWrapper>
291
+ </S.SectionWrapper>
189
292
  </S.FormWrapper>
190
293
  </S.ContentWrapper>
191
294
  </S.Wrapper>
295
+ {isVisible && <Toast message={toastState} setIsVisible={setIsVisible} />}
192
296
  <Modal
193
297
  isOpen={isOpen}
194
298
  hide={toggleModal}
195
299
  title="Theme Change Warning"
196
- secondaryAction={secondaryDeleteAction}
197
- mainAction={mainDeleteAction}
300
+ secondaryAction={secondaryThemeAction}
301
+ mainAction={mainThemeAction}
198
302
  size="S"
199
303
  >
200
304
  <S.ModalContent>
201
305
  <p>
202
- The selected theme has some restrictions. By switching to this theme,{" "}
306
+ The selected theme has some restrictions. By switching to this theme,
203
307
  <strong>you may lose access to some modules or templates.</strong>
204
308
  </p>
205
309
  </S.ModalContent>
206
310
  </Modal>
311
+ <Modal
312
+ isOpen={isHiddenOpen}
313
+ hide={toggleHiddenModal}
314
+ title="Enable public indexing?"
315
+ secondaryAction={secondaryHiddenAction}
316
+ mainAction={mainHiddenAction}
317
+ size="S"
318
+ height={240}
319
+ >
320
+ <S.ModalContent>
321
+ <p>
322
+ You are about to <strong>make this site visible to search engines</strong>. This will also{" "}
323
+ <strong>update the llms.txt</strong> file to allow AI models to access and read your content. This action
324
+ is permanent and cannot be undone.
325
+ </p>
326
+ </S.ModalContent>
327
+ </Modal>
207
328
  </MainWrapper>
208
329
  </>
209
330
  );
@@ -211,10 +332,10 @@ const Globals = (props: IProps): JSX.Element => {
211
332
 
212
333
  interface IProps {
213
334
  isSaving: boolean;
214
- currentSiteInfo: any;
335
+ currentSiteInfo: ISite;
215
336
  navItems: INavItem[];
216
337
  currentNavItem: INavItem;
217
- saveSettings(form: ISettingsForm): Promise<boolean>;
338
+ saveSettings(form: ISite): Promise<boolean>;
218
339
  setHistoryPush(path: string, isEditor?: boolean): void;
219
340
  }
220
341
 
@@ -225,7 +346,7 @@ const mapDispatchToProps = {
225
346
 
226
347
  const mapStateToProps = (state: IRootState) => ({
227
348
  isSaving: state.app.isSaving,
228
- currentSiteInfo: state.sites.currentSiteInfo,
349
+ currentSiteInfo: state.sites.currentSiteInfo!,
229
350
  });
230
351
 
231
352
  export default connect(mapStateToProps, mapDispatchToProps)(Globals);
@@ -1,4 +1,5 @@
1
1
  import styled from "styled-components";
2
+ import { ToggleField } from "@ax/components";
2
3
 
3
4
  const Wrapper = styled.div`
4
5
  display: flex;
@@ -21,4 +22,69 @@ const ModalContent = styled.div`
21
22
  padding: ${(p) => p.theme.spacing.m};
22
23
  `;
23
24
 
24
- export { Wrapper, ContentWrapper, FormWrapper, ModalContent };
25
+ const ButtonWrapper = styled.div`
26
+ margin-bottom: ${(p) => p.theme.spacing.m};
27
+ margin-top: ${(p) => `-${p.theme.spacing.xs}`};
28
+ `;
29
+
30
+ const SectionWrapper = styled.div`
31
+ border-top: 1px solid ${(p) => p.theme.color.uiLine};
32
+ padding-top: ${(p) => p.theme.spacing.m};
33
+ `;
34
+
35
+ const Heading = styled.div`
36
+ ${(p) => p.theme.textStyle.headingXS};
37
+ color: ${(p) => p.theme.color.textHighEmphasis};
38
+ margin-bottom: ${(p) => p.theme.spacing.xs};
39
+ `;
40
+
41
+ const Description = styled.div`
42
+ ${(p) => p.theme.textStyle.uiM};
43
+ color: ${(p) => p.theme.color.textMediumEmphasis};
44
+ margin-bottom: ${(p) => p.theme.spacing.m};
45
+ `;
46
+
47
+ const RobotsWrapper = styled.div`
48
+ display: flex;
49
+ `;
50
+
51
+ const ColumnsWrapper = styled.div`
52
+ display: flex;
53
+ gap: ${(p) => p.theme.spacing.m};
54
+ `;
55
+
56
+ const IconWrapper = styled.div`
57
+ width: ${(p) => p.theme.spacing.s};
58
+ height: ${(p) => p.theme.spacing.s};
59
+ margin-right: ${(p) => p.theme.spacing.xs};
60
+ `;
61
+
62
+ const HiddenFieldWrapper = styled.div`
63
+ display: flex;
64
+ ${(p) => p.theme.textStyle.uiS};
65
+ color: ${(p) => p.theme.color.textMediumEmphasis};
66
+ background-color: ${(p) => p.theme.color.uiBackground03};
67
+ padding: ${(p) => p.theme.spacing.s};
68
+ margin-bottom: ${(p) => p.theme.spacing.m};
69
+ border-radius: ${({ theme }) => theme.radii.s};
70
+ `;
71
+
72
+ const StyledToggleField = styled(ToggleField)`
73
+ margin-left: auto;
74
+ `;
75
+
76
+ export {
77
+ Wrapper,
78
+ ContentWrapper,
79
+ FormWrapper,
80
+ ModalContent,
81
+ ButtonWrapper,
82
+ Heading,
83
+ SectionWrapper,
84
+ Description,
85
+ RobotsWrapper,
86
+ ColumnsWrapper,
87
+ IconWrapper,
88
+ HiddenFieldWrapper,
89
+ StyledToggleField,
90
+ };
@@ -1,11 +1,10 @@
1
- import React from "react";
2
1
  import { connect } from "react-redux";
3
2
  import { Link } from "react-router-dom";
4
- import { UniqueIdentifier } from "@dnd-kit/core";
3
+ import type { UniqueIdentifier } from "@dnd-kit/core";
5
4
  import { useSortable } from "@dnd-kit/sortable";
6
5
 
7
6
  import { useModal, usePermission, useToast } from "@ax/hooks";
8
- import { ICheck, IIntegration } from "@ax/types";
7
+ import type { ICheck, IIntegration } from "@ax/types";
9
8
  import { CheckField, Icon, Modal, Toast, ToggleField, Tooltip } from "@ax/components";
10
9
  import { integrations } from "@ax/api";
11
10
  import { integrationsActions } from "@ax/containers/Integrations";
@@ -1,6 +1,6 @@
1
1
  import { connect } from "react-redux";
2
2
 
3
- import { FieldsBehavior, Icon, Modal, Tooltip } from "@ax/components";
3
+ import { FieldsBehavior, Icon, Modal, Tag, Tooltip } from "@ax/components";
4
4
  import { appActions } from "@ax/containers/App";
5
5
  import { sitesActions } from "@ax/containers/Sites";
6
6
  import { isDevelopment } from "@ax/helpers";
@@ -13,6 +13,7 @@ import * as S from "./style";
13
13
 
14
14
  const GridSiteItem = (props: IGridSiteItemProps): JSX.Element => {
15
15
  const { site, setSiteInfo, setHistoryPush, deleteSite, publishSite, unpublishSite, getParams } = props;
16
+ const { hidden } = site;
16
17
 
17
18
  const {
18
19
  publishedState,
@@ -37,20 +38,27 @@ const GridSiteItem = (props: IGridSiteItemProps): JSX.Element => {
37
38
  return (
38
39
  <>
39
40
  <S.SiteWrapper key={site.id} onClick={setSite} data-testid="grid-site-item">
40
- <Tooltip content={siteTooltip}>
41
- <ItemThumbnail src={site.thumbnail} width={290} height={199} />
42
- </Tooltip>
41
+ <S.ImageContainer>
42
+ <Tooltip content={siteTooltip}>
43
+ <ItemThumbnail src={site.thumbnail} height={199} />
44
+ </Tooltip>
45
+ </S.ImageContainer>
43
46
  <S.Wrapper>
44
47
  <S.Title>
45
48
  <ItemName name={site.name} length={40} />
46
49
  </S.Title>
47
50
  <S.IconsWrapper>
48
51
  <Tooltip content={publishedTooltip[publishedState]}>
49
- {publishedState && <Icon name={publishedState} size="24" />}
52
+ <Icon name={publishedState} size="24" />
50
53
  </Tooltip>
51
54
  <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
52
55
  </S.IconsWrapper>
53
56
  </S.Wrapper>
57
+ {hidden && (
58
+ <S.TagWrapper>
59
+ <Tag text="Hidden" type="square" icon="hide" />
60
+ </S.TagWrapper>
61
+ )}
54
62
  </S.SiteWrapper>
55
63
  <Modal
56
64
  isOpen={isOpenDelete}
@@ -2,18 +2,23 @@ import styled from "styled-components";
2
2
  import { ActionMenu } from "@ax/components";
3
3
 
4
4
  const SiteWrapper = styled.div`
5
+ position: relative;
5
6
  background: ${(p) => p.theme.color.uiBackground02};
6
7
  border-radius: 4px;
7
8
  display: flex;
8
9
  flex-direction: column;
9
10
  align-items: flex-start;
10
- padding: ${(p) => p.theme.spacing.s};
11
+ padding: ${(p) => `${p.theme.spacing.s} ${p.theme.spacing.s} ${p.theme.spacing.xs} ${p.theme.spacing.s}`};
11
12
  cursor: pointer;
12
13
  div {
13
14
  max-width: 100%;
14
15
  }
15
16
  `;
16
17
 
18
+ const ImageContainer = styled.div`
19
+ width: 100%;
20
+ `;
21
+
17
22
  const Wrapper = styled.div`
18
23
  position: relative;
19
24
  margin-top: ${(p) => p.theme.spacing.xs};
@@ -22,24 +27,21 @@ const Wrapper = styled.div`
22
27
  max-height: 36px;
23
28
  width: 100%;
24
29
  height: 100%;
25
- padding-right: 36px;
26
30
  justify-content: space-between;
27
31
  `;
28
32
 
29
- const Title = styled.span`
33
+ const Title = styled.div`
30
34
  ${(p) => p.theme.textStyle.headingXS};
31
35
  `;
32
36
 
33
37
  const IconsWrapper = styled.div`
34
38
  display: flex;
35
39
  align-items: center;
36
- justify-content: center;
40
+ margin-left: auto;
37
41
  `;
38
42
 
39
43
  const StyledActionMenu = styled(ActionMenu)`
40
- position: absolute;
41
- right: 0;
42
- top: 0;
44
+ margin-left: ${(p) => p.theme.spacing.xxs};
43
45
  `;
44
46
 
45
47
  const ModalContent = styled.div`
@@ -54,4 +56,10 @@ const ModalContent = styled.div`
54
56
  }
55
57
  `;
56
58
 
57
- export { SiteWrapper, Wrapper, Title, IconsWrapper, StyledActionMenu, ModalContent };
59
+ const TagWrapper = styled.div`
60
+ position: absolute;
61
+ top: 8px;
62
+ right: 8px;
63
+ `;
64
+
65
+ export { SiteWrapper, Wrapper, Title, IconsWrapper, StyledActionMenu, ModalContent, TagWrapper, ImageContainer };
@@ -51,6 +51,7 @@ const TableHeader = (props: IProps): JSX.Element => {
51
51
  <S.LiveHeader>
52
52
  <LiveFilter filterItems={filterItems} value={liveFilterValue} filterOptions={["offline", "active"]} />
53
53
  </S.LiveHeader>
54
+ <S.TagHeader />
54
55
  <S.LastAccessCell>
55
56
  <LastAccessFilter sortItems={sortItems} sortedState={sortedListStatus} />
56
57
  </S.LastAccessCell>
@@ -40,6 +40,12 @@ const DomainHeader = styled(Header)`
40
40
  const LiveHeader = styled(Header)`
41
41
  position: relative;
42
42
  justify-content: center;
43
+ width: 100px;
44
+ `;
45
+
46
+ const TagHeader = styled(Header)`
47
+ position: relative;
48
+ width: 125px;
43
49
  `;
44
50
 
45
51
  const LastAccessCell = styled(Header)`
@@ -48,4 +54,4 @@ const LastAccessCell = styled(Header)`
48
54
  width: 200px;
49
55
  `;
50
56
 
51
- export { TableHeader, CheckHeader, DomainHeader, LiveHeader, NameWrapper, HeaderWrapper, LastAccessCell };
57
+ export { TableHeader, CheckHeader, DomainHeader, LiveHeader, NameWrapper, HeaderWrapper, LastAccessCell, TagHeader };
@@ -1,6 +1,6 @@
1
1
  import { connect } from "react-redux";
2
2
 
3
- import { CheckField, FieldsBehavior, Icon, Modal, Tooltip } from "@ax/components";
3
+ import { CheckField, FieldsBehavior, Icon, Modal, Tag, Tooltip } from "@ax/components";
4
4
  import { appActions } from "@ax/containers/App";
5
5
  import { sitesActions } from "@ax/containers/Sites";
6
6
  import { getFormattedDateWithTimezone } from "@ax/helpers";
@@ -25,6 +25,8 @@ const ListSiteItem = (props: IListSiteItemProps): JSX.Element => {
25
25
  hoverCheck,
26
26
  } = props;
27
27
 
28
+ const { hidden } = site;
29
+
28
30
  const {
29
31
  publishedState,
30
32
  publishedTooltip,
@@ -45,6 +47,8 @@ const ListSiteItem = (props: IListSiteItemProps): JSX.Element => {
45
47
 
46
48
  const handleOnChange = (value: ICheck) => onCheck(value);
47
49
 
50
+ console.log(site, "site");
51
+
48
52
  return (
49
53
  <>
50
54
  <S.SiteItemRow key={site.id} role="rowgroup" selected={isSelected} data-testid="list-site-item">
@@ -67,6 +71,9 @@ const ListSiteItem = (props: IListSiteItemProps): JSX.Element => {
67
71
  {publishedState && <Icon name={publishedState} size="24" />}
68
72
  </Tooltip>
69
73
  </S.LiveCell>
74
+ <S.TagCell role="cell" onClick={setSite}>
75
+ {hidden && <Tag text="Hidden" type="square" icon="hide" />}
76
+ </S.TagCell>
70
77
  <S.DateCell role="cell">
71
78
  {site?.lastAccess ? getFormattedDateWithTimezone(new Date(site?.lastAccess), "MMM d, Y") : ""}
72
79
  </S.DateCell>