@griddo/ax 1.59.8 → 1.60.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/config/webpackSchemas.config.js +7 -0
  2. package/package.json +3 -2
  3. package/src/GlobalStore.tsx +3 -0
  4. package/src/api/index.tsx +2 -0
  5. package/src/api/redirects.tsx +71 -0
  6. package/src/api/sites.tsx +11 -25
  7. package/src/components/Fields/ReferenceField/Context/index.tsx +1 -1
  8. package/src/components/Fields/ReferenceField/ManualPanel/Item/index.tsx +4 -3
  9. package/src/components/Fields/ReferenceField/ManualPanel/index.tsx +4 -2
  10. package/src/components/Fields/ReferenceField/index.tsx +2 -2
  11. package/src/components/Fields/TextArea/index.tsx +3 -1
  12. package/src/components/Fields/TextArea/style.tsx +11 -11
  13. package/src/components/FloatingPanel/style.tsx +7 -2
  14. package/src/components/TableFilters/SiteFilter/index.tsx +7 -6
  15. package/src/components/TableFilters/SiteFilter/style.tsx +2 -2
  16. package/src/containers/Redirects/actions.tsx +129 -0
  17. package/src/containers/Redirects/constants.tsx +18 -0
  18. package/src/containers/Redirects/index.tsx +4 -0
  19. package/src/containers/Redirects/interfaces.tsx +13 -0
  20. package/src/containers/Redirects/reducer.tsx +24 -0
  21. package/src/containers/Settings/DataPacks/constants.tsx +11 -11
  22. package/src/containers/Sites/actions.tsx +1 -25
  23. package/src/helpers/environment.tsx +5 -0
  24. package/src/helpers/index.tsx +3 -0
  25. package/src/helpers/thumbnails.tsx +3 -3
  26. package/src/modules/Content/PageItem/index.tsx +5 -8
  27. package/src/modules/Content/index.tsx +25 -35
  28. package/src/modules/GlobalSettings/Robots/Item/index.tsx +1 -1
  29. package/src/modules/GlobalSettings/Robots/index.tsx +5 -2
  30. package/src/modules/GlobalSettings/index.tsx +6 -0
  31. package/src/modules/Redirects/BulkHeader/TableHeader/index.tsx +44 -0
  32. package/src/modules/Redirects/BulkHeader/TableHeader/style.tsx +31 -0
  33. package/src/modules/Redirects/BulkHeader/index.tsx +59 -0
  34. package/src/modules/Redirects/RedirectItem/index.tsx +139 -0
  35. package/src/modules/Redirects/RedirectItem/style.tsx +50 -0
  36. package/src/modules/Redirects/RedirectPanel/index.tsx +117 -0
  37. package/src/modules/Redirects/RedirectPanel/style.tsx +13 -0
  38. package/src/modules/Redirects/index.tsx +310 -0
  39. package/src/modules/Redirects/style.tsx +52 -0
  40. package/src/modules/Settings/SeoSettings/index.tsx +25 -0
  41. package/src/modules/Sites/SitesList/SiteItem/index.tsx +6 -2
  42. package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +1 -1
  43. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +3 -3
  44. package/src/modules/StructuredData/StructuredDataList/index.tsx +1 -0
  45. package/src/modules/StructuredData/StructuredDataList/utils.tsx +1 -1
  46. package/src/routes/multisite.tsx +6 -0
  47. package/src/routes/site.tsx +6 -0
  48. package/src/types/index.tsx +13 -0
@@ -27,6 +27,13 @@ const createConfig = ({ input, output }) => ({
27
27
  },
28
28
  },
29
29
  },
30
+
31
+ // This is for ignoring images defined in the schemas in order to prevent
32
+ // API crashing (it hasn't webpack)
33
+ {
34
+ test: /\.(png|jpe?g|gif)$/i,
35
+ use: [{ loader: "ignore-loader" }],
36
+ },
30
37
  ],
31
38
  },
32
39
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@griddo/ax",
3
3
  "description": "Griddo Author Experience",
4
- "version": "1.59.8",
4
+ "version": "1.60.0",
5
5
  "authors": [
6
6
  "Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
7
7
  "Carlos Torres <carlos.torres@secuoyas.com>",
@@ -154,6 +154,7 @@
154
154
  "eslint-plugin-prettier": "^3.4.0",
155
155
  "eslint-plugin-react": "7.14.3",
156
156
  "eslint-plugin-react-hooks": "^4.2.0",
157
+ "ignore-loader": "^0.1.2",
157
158
  "prettier": "^2.3.0",
158
159
  "react-test-render": "1.1.2"
159
160
  },
@@ -241,5 +242,5 @@
241
242
  "publishConfig": {
242
243
  "access": "public"
243
244
  },
244
- "gitHead": "b177c93d93d54a54a559f81aba2a5572504f9575"
245
+ "gitHead": "6fef1378f392f0463b32f3ad06de2c6e7708f484"
245
246
  }
@@ -17,6 +17,7 @@ import { socialReducer, socialInitialState } from "./containers/Settings/Social/
17
17
  import { usersReducer, usersInitialState } from "./containers/Users/reducer";
18
18
  import { galleryReducer, galleryInitialState } from "./containers/Gallery/reducer";
19
19
  import { domainsReducer, domainsInitialState } from "./containers/Domains/reducer";
20
+ import { redirectsReducer, redirectsInitialState } from "./containers/Redirects/reducer";
20
21
 
21
22
  import { IRootState } from "@ax/types";
22
23
 
@@ -47,6 +48,7 @@ export class GlobalStore {
47
48
  users: usersReducer as Reducer<any, Action<any>>,
48
49
  gallery: galleryReducer as Reducer<any, Action<any>>,
49
50
  domains: domainsReducer as Reducer<any, Action<any>>,
51
+ redirects: redirectsReducer as Reducer<any, Action<any>>,
50
52
  });
51
53
 
52
54
  const rootReducer = (state: IRootState | undefined, action: any) => {
@@ -65,6 +67,7 @@ export class GlobalStore {
65
67
  users: usersInitialState,
66
68
  gallery: galleryInitialState,
67
69
  domains: domainsInitialState,
70
+ redirects: redirectsInitialState,
68
71
  };
69
72
  }
70
73
 
package/src/api/index.tsx CHANGED
@@ -14,6 +14,7 @@ import social from "./social";
14
14
  import files from "./files";
15
15
  import users from "./users";
16
16
  import domains from "./domains";
17
+ import redirects from "./redirects";
17
18
 
18
19
  export {
19
20
  sites,
@@ -32,4 +33,5 @@ export {
32
33
  files,
33
34
  users,
34
35
  domains,
36
+ redirects,
35
37
  };
@@ -0,0 +1,71 @@
1
+ import { template } from "./config";
2
+ import { IServiceConfig, sendRequest } from "./utils";
3
+
4
+ const SERVICES: { [key: string]: IServiceConfig } = {
5
+ GET_REDIRECTS: {
6
+ ...template,
7
+ endpoint: "/redirects",
8
+ method: "GET",
9
+ },
10
+ CREATE_REDIRECT: {
11
+ ...template,
12
+ endpoint: "/redirect",
13
+ method: "POST",
14
+ },
15
+ UPDATE_REDIRECT: {
16
+ ...template,
17
+ endpoint: "/redirect/",
18
+ method: "PUT",
19
+ },
20
+ DELETE_REDIRECT: {
21
+ ...template,
22
+ endpoint: "/redirect/",
23
+ method: "DELETE",
24
+ },
25
+ DELETE_REDIRECT_BULK: {
26
+ ...template,
27
+ endpoint: "/redirects/bulk",
28
+ method: "DELETE",
29
+ },
30
+ };
31
+
32
+ const getRedirects = async (params: any, filters?: string) => {
33
+ const { page, itemsPerPage, pagination } = params;
34
+
35
+ const { host, endpoint } = SERVICES.GET_REDIRECTS;
36
+
37
+ SERVICES.GET_REDIRECTS.dynamicUrl = `${host}${endpoint}?page=${page}&itemsPerPage=${itemsPerPage}&pagination=${pagination}${filters}`;
38
+
39
+ return sendRequest(SERVICES.GET_REDIRECTS);
40
+ };
41
+
42
+ const createRedirect = async (redirect: any, force?: boolean) => {
43
+ const { host, endpoint } = SERVICES.CREATE_REDIRECT;
44
+
45
+ const forceString = force ? "?force=1" : "";
46
+ SERVICES.CREATE_REDIRECT.dynamicUrl = `${host}${endpoint}${forceString}`;
47
+
48
+ return sendRequest(SERVICES.CREATE_REDIRECT, { ...redirect });
49
+ };
50
+
51
+ const updateRedirect = async (redirect: any, redirectID: number) => {
52
+ const { host, endpoint } = SERVICES.UPDATE_REDIRECT;
53
+
54
+ SERVICES.UPDATE_REDIRECT.dynamicUrl = `${host}${endpoint}${redirectID}`;
55
+
56
+ return sendRequest(SERVICES.UPDATE_REDIRECT, { ...redirect });
57
+ };
58
+
59
+ const deleteRedirect = async (redirectID: number) => {
60
+ const { host, endpoint } = SERVICES.DELETE_REDIRECT;
61
+
62
+ SERVICES.DELETE_REDIRECT.dynamicUrl = `${host}${endpoint}${redirectID}`;
63
+
64
+ return sendRequest(SERVICES.DELETE_REDIRECT);
65
+ };
66
+
67
+ const deleteRedirectsBulk = async (ids: number[]) => {
68
+ return sendRequest(SERVICES.DELETE_REDIRECT_BULK, { ids });
69
+ };
70
+
71
+ export default { getRedirects, createRedirect, updateRedirect, deleteRedirect, deleteRedirectsBulk };
package/src/api/sites.tsx CHANGED
@@ -39,11 +39,6 @@ const SERVICES: { [key: string]: IServiceConfig } = {
39
39
  endpoint: ["/site/", "/pages/structured-data/"],
40
40
  method: "GET",
41
41
  },
42
- GET_ORDERED_SITE_PAGES: {
43
- ...template,
44
- endpoint: ["/site/", "/pages"],
45
- method: "GET",
46
- },
47
42
  GET_SITE_IMAGES: {
48
43
  ...template,
49
44
  endpoint: ["/site/", "/images"],
@@ -112,47 +107,38 @@ const getSiteInfo = async (siteID: number) => {
112
107
  return sendRequest(SERVICES.GET_SITE_INFO);
113
108
  };
114
109
 
115
- const getOrderedSitePages = async (siteID: number | string, query: string) => {
116
- const {
117
- host,
118
- endpoint: [prefix, suffix],
119
- } = SERVICES.GET_ORDERED_SITE_PAGES;
120
-
121
- SERVICES.GET_ORDERED_SITE_PAGES.dynamicUrl = `${host}${prefix}${siteID}${suffix}${query}`;
122
-
123
- return sendRequest(SERVICES.GET_ORDERED_SITE_PAGES);
124
- };
125
-
126
110
  const getStructuredSitePages = async (params: IGetSitePagesParams, structuredData: string, filterQuery?: string) => {
127
111
  const {
128
112
  host,
129
113
  endpoint: [prefix, suffix],
130
114
  } = SERVICES.GET_SITE_STRUCTURED_PAGES;
131
115
 
132
- const { siteID, deleted, page, itemsPerPage, query } = params;
116
+ const { siteID, deleted, page, itemsPerPage, query, format } = params;
133
117
 
134
118
  const filters = filterQuery ? `${filterQuery}&` : "?";
135
119
 
136
120
  SERVICES.GET_SITE_STRUCTURED_PAGES.dynamicUrl = `${host}${prefix}${siteID}${suffix}${structuredData}${filters}deleted=${deleted}&page=${page}&itemsPerPage=${itemsPerPage}`;
137
121
 
138
- if (query && query.trim() !== "") {
139
- SERVICES.GET_SITE_STRUCTURED_PAGES.dynamicUrl = SERVICES.GET_SITE_STRUCTURED_PAGES.dynamicUrl + `&query=${query}`;
140
- }
122
+ if (query && query.trim() !== "") SERVICES.GET_SITE_STRUCTURED_PAGES.dynamicUrl = SERVICES.GET_SITE_STRUCTURED_PAGES.dynamicUrl + `&query=${query}`;
123
+ if (format) SERVICES.GET_SITE_STRUCTURED_PAGES.dynamicUrl = SERVICES.GET_SITE_STRUCTURED_PAGES.dynamicUrl + `&format=${format}`;
141
124
 
142
125
  return sendRequest(SERVICES.GET_SITE_STRUCTURED_PAGES);
143
126
  };
144
127
 
145
- const getSitePages = async (params: IGetSitePagesParams) => {
128
+ const getSitePages = async (params: IGetSitePagesParams, filterQuery?: string): Promise<AxiosResponse> => {
146
129
  const {
147
130
  host,
148
131
  endpoint: [prefix, suffix],
149
132
  } = SERVICES.GET_SITE_PAGES;
150
133
 
151
- const { siteID, deleted, page, itemsPerPage, query, filterStructuredData, lang } = params;
134
+ const { siteID, deleted, page, itemsPerPage, query, filterStructuredData, lang, format } = params;
135
+
136
+ const filters = filterQuery ? `${filterQuery}&` : "?";
152
137
 
153
- SERVICES.GET_SITE_PAGES.dynamicUrl = `${host}${prefix}${siteID}${suffix}?deleted=${deleted}&page=${page}&itemsPerPage=${itemsPerPage}`;
138
+ SERVICES.GET_SITE_PAGES.dynamicUrl = `${host}${prefix}${siteID}${suffix}${filters}deleted=${deleted}&page=${page}&itemsPerPage=${itemsPerPage}`;
154
139
  if (query && query.trim() !== "") SERVICES.GET_SITE_PAGES.dynamicUrl = SERVICES.GET_SITE_PAGES.dynamicUrl + `&query=${query}`;
155
140
  if (filterStructuredData) SERVICES.GET_SITE_PAGES.dynamicUrl = SERVICES.GET_SITE_PAGES.dynamicUrl + `&filterStructuredData=${filterStructuredData}`;
141
+ if (format) SERVICES.GET_SITE_PAGES.dynamicUrl = SERVICES.GET_SITE_PAGES.dynamicUrl + `&format=${format}`;
156
142
 
157
143
  const dataHeader = {
158
144
  ...(lang && { lang })
@@ -164,12 +150,13 @@ const getSitePages = async (params: IGetSitePagesParams) => {
164
150
  const getGlobalPages = async (params: IGetGlobalPagesParams, filterQuery?: string): Promise<AxiosResponse> => {
165
151
  const { host, endpoint } = SERVICES.GET_GLOBAL_PAGES;
166
152
 
167
- const { deleted, page, itemsPerPage, query, filterStructuredData } = params;
153
+ const { deleted, page, itemsPerPage, query, filterStructuredData, format } = params;
168
154
 
169
155
  SERVICES.GET_GLOBAL_PAGES.dynamicUrl = `${host}${endpoint}?deleted=${deleted}&page=${page}&itemsPerPage=${itemsPerPage}`;
170
156
  if (query && query.trim() !== "") SERVICES.GET_GLOBAL_PAGES.dynamicUrl += `&query=${query}`;
171
157
  if (filterStructuredData) SERVICES.GET_GLOBAL_PAGES.dynamicUrl += `&filterStructuredData=${filterStructuredData}`;
172
158
  if (filterQuery) SERVICES.GET_GLOBAL_PAGES.dynamicUrl += filterQuery;
159
+ if (format) SERVICES.GET_GLOBAL_PAGES.dynamicUrl = SERVICES.GET_GLOBAL_PAGES.dynamicUrl + `&format=${format}`;
173
160
 
174
161
  return sendRequest(SERVICES.GET_GLOBAL_PAGES);
175
162
  };
@@ -317,7 +304,6 @@ export default {
317
304
  getSiteInfo,
318
305
  getSitePages,
319
306
  getSitePagesLight,
320
- getOrderedSitePages,
321
307
  getStructuredSitePages,
322
308
  getSiteImages,
323
309
  deleteSite,
@@ -10,7 +10,7 @@ const initState = {
10
10
  quantity: 0,
11
11
  items: [],
12
12
  selectedItems: [],
13
- fixed: null,
13
+ fixed: [],
14
14
  search: "",
15
15
  showSelected: false,
16
16
  source: [],
@@ -7,16 +7,16 @@ import { CheckField } from "@ax/components";
7
7
  import * as S from "./style";
8
8
 
9
9
  const Item = (props: IProps) => {
10
- const { handleOnClick, item, isChecked, source } = props;
10
+ const { handleOnClick, item, isChecked, source, disabled } = props;
11
11
 
12
12
  const handleItemClick = (e: any) => {
13
13
  e.preventDefault();
14
- return handleOnClick(item);
14
+ if (!disabled) handleOnClick(item);
15
15
  };
16
16
 
17
17
  return (
18
18
  <S.Item onClick={handleItemClick}>
19
- <CheckField name="check" value={item.id} checked={isChecked} />
19
+ <CheckField name="check" value={item.id} checked={isChecked} disabled={disabled} />
20
20
  <S.TextWrapper>
21
21
  <S.Header>
22
22
  <S.Type>{source.title.toUpperCase()}</S.Type>
@@ -33,6 +33,7 @@ interface IProps {
33
33
  item: any;
34
34
  isChecked: boolean;
35
35
  source: IDataSource;
36
+ disabled: boolean;
36
37
  }
37
38
 
38
39
  export default Item;
@@ -13,7 +13,7 @@ import Item from "./Item";
13
13
  import * as S from "./style";
14
14
 
15
15
  const ManualPanel = (props: IProps) => {
16
- const { onChange, currentSite } = props;
16
+ const { onChange, currentSite, hasMaxItems } = props;
17
17
 
18
18
  const { state, setState } = useReference();
19
19
 
@@ -132,8 +132,9 @@ const ManualPanel = (props: IProps) => {
132
132
  showedItems.map((item: IStructuredDataContent) => {
133
133
  const isChecked = state.fixed.includes(item.id);
134
134
  const source = state.sourceTitles.find((el: IDataSource) => el.id === item.structuredData);
135
+ const disabled = hasMaxItems && !isChecked;
135
136
  return (
136
- <Item key={item.id} isChecked={isChecked} handleOnClick={handleOnClick} item={item} source={source} />
137
+ <Item key={item.id} isChecked={isChecked} handleOnClick={handleOnClick} item={item} source={source} disabled={disabled} />
137
138
  );
138
139
  })}
139
140
  </S.ItemList>
@@ -153,6 +154,7 @@ const ManualPanel = (props: IProps) => {
153
154
  interface IProps {
154
155
  currentSite: number;
155
156
  onChange: (value: any) => void;
157
+ hasMaxItems: boolean;
156
158
  }
157
159
 
158
160
  const mapStateToProps = (state: IRootState) => ({
@@ -28,7 +28,7 @@ const ReferenceField = (props: IProps) => {
28
28
  const { mode } = state;
29
29
  const singleMode = selectionType && selectionType.length === 1;
30
30
  const isAuto = mode === "auto";
31
- const hasMaxItems = value && value.fixed && maxItems && !isAuto && value.fixed.length >= maxItems;
31
+ const hasMaxItems = !!(value && value.fixed && maxItems && !isAuto && value.fixed.length >= maxItems);
32
32
 
33
33
  const handleMode = (mode: string) => {
34
34
  const { fixed, order, quantity, filter } = state;
@@ -157,7 +157,7 @@ const ReferenceField = (props: IProps) => {
157
157
  validators={validators}
158
158
  />
159
159
  ) : (
160
- <ManualPanel onChange={handleOnChange} />
160
+ <ManualPanel onChange={handleOnChange} hasMaxItems={hasMaxItems} />
161
161
  );
162
162
 
163
163
  const manualItems = !isAuto && value && Array.isArray(value.fixed) ? value.fixed.length : 0;
@@ -33,6 +33,8 @@ const TextArea = (props: ITextAreaProps): JSX.Element => {
33
33
  handleValidation && handleValidation(e.target.value);
34
34
  };
35
35
 
36
+ const errorString = error ? "true" : "false";
37
+
36
38
  return (
37
39
  <S.TextArea
38
40
  name={name}
@@ -42,7 +44,7 @@ const TextArea = (props: ITextAreaProps): JSX.Element => {
42
44
  onChange={handleOnChange}
43
45
  onBlur={handleOnBlur}
44
46
  placeholder={placeholder}
45
- error={error}
47
+ error={errorString}
46
48
  disabled={disabled}
47
49
  />
48
50
  );
@@ -1,15 +1,15 @@
1
1
  import styled from "styled-components";
2
2
  import TextareaAutosize from "react-textarea-autosize";
3
3
 
4
- export const TextArea = styled(TextareaAutosize)<{ error: boolean | undefined }>`
5
- ${p => p.theme.textStyle.fieldContent};
6
- border: 1px solid ${p => (p.error === true ? p.theme.color.error : p.theme.color.uiLine)};
4
+ export const TextArea = styled(TextareaAutosize)<{ error: string }>`
5
+ ${(p) => p.theme.textStyle.fieldContent};
6
+ border: 1px solid ${(p) => (p.error === "true" ? p.theme.color.error : p.theme.color.uiLine)};
7
7
  border-radius: 4px;
8
- background-color: ${p => p.theme.color.uiBackground02};
9
- color: ${p => p.theme.color.textHighEmphasis};
10
- padding: ${p => p.theme.spacing.s};
8
+ background-color: ${(p) => p.theme.color.uiBackground02};
9
+ color: ${(p) => p.theme.color.textHighEmphasis};
10
+ padding: ${(p) => p.theme.spacing.s};
11
11
  height: auto;
12
- margin-bottom: ${p => p.theme.spacing.xxs};
12
+ margin-bottom: ${(p) => p.theme.spacing.xxs};
13
13
  width: 100%;
14
14
  resize: none;
15
15
  overflow: auto;
@@ -17,15 +17,15 @@ export const TextArea = styled(TextareaAutosize)<{ error: boolean | undefined }>
17
17
  &:active,
18
18
  &:focus {
19
19
  outline: none;
20
- border-color: ${(p) => (p.error === true ? p.theme.color.error : p.theme.color.interactive01)};
20
+ border-color: ${(p) => (p.error === "true" ? p.theme.color.error : p.theme.color.interactive01)};
21
21
  }
22
22
 
23
23
  &::placeholder {
24
- color: ${p => p.theme.color.textLowEmphasis};
24
+ color: ${(p) => p.theme.color.textLowEmphasis};
25
25
  }
26
26
 
27
27
  &:disabled {
28
- color: ${p => p.theme.color.interactiveDisabled};
29
- border-color: ${p => p.theme.color.interactiveDisabled};
28
+ color: ${(p) => p.theme.color.interactiveDisabled};
29
+ border-color: ${(p) => p.theme.color.interactiveDisabled};
30
30
  }
31
31
  `;
@@ -13,11 +13,16 @@ export const Header = styled.div`
13
13
  padding: 0 ${(p) => p.theme.spacing.m};
14
14
  `;
15
15
 
16
- export const Wrapper = styled.section<{ right?: boolean; isOpen: boolean; isOpenedSecond: boolean | undefined; secondary?: boolean }>`
16
+ export const Wrapper = styled.section<{
17
+ right?: boolean;
18
+ isOpen: boolean;
19
+ isOpenedSecond: boolean | undefined;
20
+ secondary?: boolean;
21
+ }>`
17
22
  position: fixed;
18
23
  right: 0;
19
24
  top: 0;
20
- z-index: 1000;
25
+ z-index: 1200;
21
26
  width: calc(${(p) => p.theme.spacing.xl} * 6);
22
27
  height: 100vh;
23
28
  background: ${(p) => p.theme.colors.uiBackground01};
@@ -8,7 +8,7 @@ import { IFilterValue } from "@ax/types";
8
8
  import * as S from "./style";
9
9
 
10
10
  const SiteFilter = (props: ISiteFilterProps): JSX.Element => {
11
- const { filterItems, value } = props;
11
+ const { filterItems, value, pointer, center = true } = props;
12
12
 
13
13
  const filters: IFilterValue[] = [
14
14
  {
@@ -18,8 +18,8 @@ const SiteFilter = (props: ISiteFilterProps): JSX.Element => {
18
18
  },
19
19
  ];
20
20
 
21
- const storedValue = value.split(",");
22
- const parsedValue = storedValue.map((value) => (isNumber(value) ? parseInt(value) : value));
21
+ const storedValue = value && value[pointer] ? value[pointer].split(",") : [];
22
+ const parsedValue = storedValue.map((value: any) => (isNumber(value) ? parseInt(value) : value));
23
23
  const [initialState] = useState(parsedValue);
24
24
  const selectAllOption = "all";
25
25
  const [selectedValue, setSelectedValue] = useState([...initialState]);
@@ -58,14 +58,13 @@ const SiteFilter = (props: ISiteFilterProps): JSX.Element => {
58
58
  }
59
59
  setSelectedValue(selection);
60
60
  const queryFilters = selection.join(",");
61
- const pointer = "filterSites";
62
61
  filterItems(pointer, queryFilters);
63
62
  };
64
63
 
65
64
  const isActive = !areEquals(selectedValue, initialState);
66
65
 
67
66
  const Header = () => (
68
- <S.Site isActive={isActive}>
67
+ <S.Site isActive={isActive} center={center}>
69
68
  Site
70
69
  <S.IconsWrapper>
71
70
  <Icon name="Filter" size="16" />
@@ -85,7 +84,9 @@ const SiteFilter = (props: ISiteFilterProps): JSX.Element => {
85
84
 
86
85
  interface ISiteFilterProps {
87
86
  filterItems(pointer: string, filter: string): void;
88
- value: string;
87
+ value: any;
88
+ pointer: string;
89
+ center?: boolean;
89
90
  }
90
91
 
91
92
  export default SiteFilter;
@@ -1,9 +1,9 @@
1
1
  import styled from "styled-components";
2
2
  import { Header } from "@ax/components/TableList/style";
3
3
 
4
- const Site = styled(Header)<{ isActive: boolean }>`
4
+ const Site = styled(Header)<{ isActive: boolean; center: boolean }>`
5
5
  width: 170px;
6
- justify-content: center;
6
+ justify-content: ${(p) => (p.center ? "center" : "flex-start")};
7
7
  &:hover {
8
8
  color: ${(p) => p.theme.color.interactive01};
9
9
  }
@@ -0,0 +1,129 @@
1
+ import { redirects } from "@ax/api";
2
+ import { appActions } from "@ax/containers/App";
3
+ import { handleRequest } from "@ax/helpers";
4
+ import { DEFAULT_PARAMS, ERROR_CODE, SET_REDIRECTS, SET_TOTAL_ITEMS } from "./constants";
5
+ import { ISetRedirects, ISetTotalItems } from "./interfaces";
6
+
7
+ function setRedirects(redirects: any[]): ISetRedirects {
8
+ return { type: SET_REDIRECTS, payload: { redirects } };
9
+ }
10
+
11
+ function setTotalItems(totalItems: number): ISetTotalItems {
12
+ return { type: SET_TOTAL_ITEMS, payload: { totalItems } };
13
+ }
14
+
15
+ function getRedirects(params: any, filters?: string): (dispatch: any) => Promise<void> {
16
+ return async (dispatch) => {
17
+ try {
18
+ const callback = async () => redirects.getRedirects(params, filters);
19
+
20
+ const responseActions = {
21
+ handleSuccess: (response: any) => {
22
+ const { items, totalItems } = response;
23
+ dispatch(setRedirects(items));
24
+ dispatch(setTotalItems(totalItems));
25
+ },
26
+ handleError: (response: any) => appActions.handleError(response)(dispatch),
27
+ };
28
+
29
+ await handleRequest(callback, responseActions, [appActions.setIsLoading])(dispatch);
30
+ } catch (e) {
31
+ console.log(e);
32
+ }
33
+ };
34
+ }
35
+
36
+ function addRedirect(
37
+ redirect: { from: string; to: string | number },
38
+ errorAction: () => void,
39
+ force?: boolean,
40
+ filter?: string
41
+ ): (dispatch: any, getState: any) => Promise<void> {
42
+ return async (dispatch, getState) => {
43
+ try {
44
+ const {
45
+ sites: { currentSiteInfo },
46
+ } = getState();
47
+
48
+ const callback = async () => redirects.createRedirect(redirect, force);
49
+
50
+ const responseActions = {
51
+ handleSuccess: () => {
52
+ const params = { ...DEFAULT_PARAMS };
53
+ const siteFilterQuery = currentSiteInfo && currentSiteInfo.id ? `&sites=${currentSiteInfo.id}` : filter;
54
+ dispatch(getRedirects(params, siteFilterQuery));
55
+ },
56
+ handleError: (response: any) => {
57
+ const { status } = response;
58
+
59
+ status === ERROR_CODE.isBeingUsed ? errorAction() : appActions.handleError(response)(dispatch);
60
+ },
61
+ };
62
+
63
+ await handleRequest(callback, responseActions, [])(dispatch);
64
+ } catch (e) {
65
+ console.log(e);
66
+ }
67
+ };
68
+ }
69
+
70
+ function updateRedirect(
71
+ redirect: { from: string; to: string | number },
72
+ redirectID: number,
73
+ filter?: string
74
+ ): (dispatch: any, getState: any) => Promise<void> {
75
+ return async (dispatch, getState) => {
76
+ try {
77
+ const {
78
+ sites: { currentSiteInfo },
79
+ } = getState();
80
+
81
+ const callback = async () => redirects.updateRedirect(redirect, redirectID);
82
+
83
+ const responseActions = {
84
+ handleSuccess: () => {
85
+ const params = { ...DEFAULT_PARAMS };
86
+ const siteFilterQuery = currentSiteInfo && currentSiteInfo.id ? `&sites=${currentSiteInfo.id}` : filter;
87
+ dispatch(getRedirects(params, siteFilterQuery));
88
+ },
89
+ handleError: (response: any) => appActions.handleError(response)(dispatch),
90
+ };
91
+
92
+ await handleRequest(callback, responseActions, [])(dispatch);
93
+ } catch (e) {
94
+ console.log(e);
95
+ }
96
+ };
97
+ }
98
+
99
+ function deleteRedirect(
100
+ redirectID: number | number[],
101
+ filter?: string
102
+ ): (dispatch: any, getState: any) => Promise<boolean> {
103
+ return async (dispatch, getState) => {
104
+ try {
105
+ const {
106
+ sites: { currentSiteInfo },
107
+ } = getState();
108
+
109
+ const callback = async () =>
110
+ Array.isArray(redirectID) ? redirects.deleteRedirectsBulk(redirectID) : redirects.deleteRedirect(redirectID);
111
+
112
+ const responseActions = {
113
+ handleSuccess: () => {
114
+ const params = { ...DEFAULT_PARAMS };
115
+ const siteFilterQuery = currentSiteInfo && currentSiteInfo.id ? `&sites=${currentSiteInfo.id}` : filter;
116
+ dispatch(getRedirects(params, siteFilterQuery));
117
+ },
118
+ handleError: (response: any) => appActions.handleError(response)(dispatch),
119
+ };
120
+
121
+ return await handleRequest(callback, responseActions, [])(dispatch);
122
+ } catch (e) {
123
+ console.log(e);
124
+ return false;
125
+ }
126
+ };
127
+ }
128
+
129
+ export { getRedirects, addRedirect, updateRedirect, deleteRedirect };
@@ -0,0 +1,18 @@
1
+ const NAME = "redirects";
2
+
3
+ const SET_REDIRECTS = `${NAME}/SET_REDIRECTS`;
4
+ const SET_TOTAL_ITEMS = `${NAME}/SET_TOTAL_ITEMS`;
5
+
6
+ const ITEMS_PER_PAGE = 50;
7
+
8
+ const DEFAULT_PARAMS = {
9
+ page: 1,
10
+ itemsPerPage: ITEMS_PER_PAGE,
11
+ pagination: true,
12
+ };
13
+
14
+ const ERROR_CODE = {
15
+ isBeingUsed: 409,
16
+ };
17
+
18
+ export { NAME, SET_REDIRECTS, SET_TOTAL_ITEMS, ERROR_CODE, DEFAULT_PARAMS, ITEMS_PER_PAGE };
@@ -0,0 +1,4 @@
1
+ import * as redirectsActions from "./actions";
2
+ import { redirectsReducer } from "./reducer";
3
+
4
+ export { redirectsActions, redirectsReducer };
@@ -0,0 +1,13 @@
1
+ import { SET_REDIRECTS, SET_TOTAL_ITEMS } from "./constants";
2
+
3
+ export interface ISetRedirects {
4
+ type: typeof SET_REDIRECTS;
5
+ payload: { redirects: any[] };
6
+ }
7
+
8
+ export interface ISetTotalItems {
9
+ type: typeof SET_TOTAL_ITEMS;
10
+ payload: { totalItems: number };
11
+ }
12
+
13
+ export type RedirectsActionsCreators = ISetRedirects;
@@ -0,0 +1,24 @@
1
+ import { SET_REDIRECTS, SET_TOTAL_ITEMS } from "./constants";
2
+ import { RedirectsActionsCreators } from "./interfaces";
3
+
4
+ export interface IRedirectsState {
5
+ redirects: any[];
6
+ totalItems: number;
7
+ }
8
+
9
+ export const initialState = {
10
+ redirects: [],
11
+ totalItems: 0,
12
+ };
13
+
14
+ export function reducer(state = initialState, action: RedirectsActionsCreators): IRedirectsState {
15
+ switch (action.type) {
16
+ case SET_REDIRECTS:
17
+ case SET_TOTAL_ITEMS:
18
+ return { ...state, ...action.payload };
19
+ default:
20
+ return state;
21
+ }
22
+ }
23
+
24
+ export { initialState as redirectsInitialState, reducer as redirectsReducer };