@griddo/ax 1.75.258 → 10.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/package.json +2 -2
  2. package/src/GlobalStore.tsx +3 -0
  3. package/src/__tests__/components/ConfigPanel/GlobalPageForm/GlobalPageForm.test.tsx +10 -1
  4. package/src/__tests__/components/Fields/IntegrationsField/IntegrationsField.test.tsx +391 -0
  5. package/src/__tests__/modules/Settings/Integrations/Integrations.test.tsx +167 -0
  6. package/src/api/index.tsx +3 -1
  7. package/src/api/integrations.tsx +153 -0
  8. package/src/api/sites.tsx +4 -2
  9. package/src/components/ActionMenu/index.tsx +3 -1
  10. package/src/components/ActionMenu/style.tsx +1 -0
  11. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +4 -1
  12. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/index.tsx +3 -0
  13. package/src/components/ConfigPanel/GlobalPageForm/index.tsx +11 -2
  14. package/src/components/FieldContainer/index.tsx +2 -1
  15. package/src/components/Fields/IntegrationsField/IntegrationItem/CustomPanel/index.tsx +101 -0
  16. package/src/components/Fields/IntegrationsField/IntegrationItem/CustomPanel/style.tsx +23 -0
  17. package/src/components/Fields/IntegrationsField/IntegrationItem/VariablesPanel/helpers.ts +31 -0
  18. package/src/components/Fields/IntegrationsField/IntegrationItem/VariablesPanel/index.tsx +120 -0
  19. package/src/components/Fields/IntegrationsField/IntegrationItem/VariablesPanel/style.tsx +23 -0
  20. package/src/components/Fields/IntegrationsField/IntegrationItem/atoms.tsx +27 -0
  21. package/src/components/Fields/IntegrationsField/IntegrationItem/index.tsx +132 -0
  22. package/src/components/Fields/IntegrationsField/IntegrationItem/style.tsx +63 -0
  23. package/src/components/Fields/IntegrationsField/PasteIntegrationButton/index.tsx +30 -0
  24. package/src/components/Fields/IntegrationsField/SideModal/SideModalOption/index.tsx +52 -0
  25. package/src/components/Fields/IntegrationsField/SideModal/SideModalOption/style.tsx +54 -0
  26. package/src/components/Fields/IntegrationsField/SideModal/index.tsx +57 -0
  27. package/src/components/Fields/IntegrationsField/SideModal/style.tsx +50 -0
  28. package/src/components/Fields/IntegrationsField/index.tsx +145 -0
  29. package/src/components/Fields/IntegrationsField/style.tsx +29 -0
  30. package/src/components/Fields/TextArea/index.tsx +1 -1
  31. package/src/components/Fields/ToggleField/index.tsx +5 -3
  32. package/src/components/Fields/UrlField/index.tsx +8 -8
  33. package/src/components/Fields/index.tsx +2 -0
  34. package/src/components/Icon/components/Deactivate.js +14 -0
  35. package/src/components/Icon/components/Lock.js +15 -0
  36. package/src/components/Icon/svgs/Deactivate.svg +8 -0
  37. package/src/components/Icon/svgs/Lock.svg +6 -0
  38. package/src/components/PageFinder/SelectionListItem/index.tsx +46 -0
  39. package/src/components/PageFinder/SelectionListItem/style.tsx +46 -0
  40. package/src/components/{Fields/UrlField/PageFinder → PageFinder}/index.tsx +99 -21
  41. package/src/components/{Fields/UrlField/PageFinder → PageFinder}/style.tsx +14 -1
  42. package/src/components/TableFilters/CheckGroupFilter/index.tsx +83 -0
  43. package/src/components/TableFilters/CheckGroupFilter/style.tsx +40 -0
  44. package/src/components/TableFilters/StateFilter/index.tsx +66 -0
  45. package/src/components/TableFilters/StateFilter/style.tsx +30 -0
  46. package/src/components/TableFilters/index.tsx +4 -0
  47. package/src/components/index.tsx +9 -1
  48. package/src/containers/Integrations/actions.tsx +190 -0
  49. package/src/containers/Integrations/constants.tsx +14 -0
  50. package/src/containers/Integrations/index.tsx +4 -0
  51. package/src/containers/Integrations/interfaces.tsx +24 -0
  52. package/src/containers/Integrations/reducer.tsx +31 -0
  53. package/src/containers/PageEditor/actions.tsx +11 -1
  54. package/src/containers/PageEditor/utils.tsx +30 -2
  55. package/src/hooks/content.tsx +46 -2
  56. package/src/hooks/index.tsx +2 -1
  57. package/src/hooks/modals.tsx +4 -2
  58. package/src/modules/App/Routing/NavMenu/NavItem/style.tsx +13 -12
  59. package/src/modules/Content/index.tsx +5 -0
  60. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/IntegrationsField/index.tsx +47 -0
  61. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/IntegrationsField/style.tsx +7 -0
  62. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/{Field → NavigationField}/index.tsx +2 -2
  63. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/index.tsx +7 -7
  64. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/index.tsx +1 -1
  65. package/src/modules/Settings/Integrations/BulkHeader/TableHeader/index.tsx +81 -0
  66. package/src/modules/Settings/Integrations/BulkHeader/TableHeader/style.tsx +35 -0
  67. package/src/modules/Settings/Integrations/BulkHeader/index.tsx +69 -0
  68. package/src/modules/Settings/Integrations/IntegrationForm/VariableItem/index.tsx +95 -0
  69. package/src/modules/Settings/Integrations/IntegrationForm/VariableItem/style.tsx +62 -0
  70. package/src/modules/Settings/Integrations/IntegrationForm/VariablePanel/index.tsx +138 -0
  71. package/src/modules/Settings/Integrations/IntegrationForm/VariablePanel/style.tsx +28 -0
  72. package/src/modules/Settings/Integrations/IntegrationForm/index.tsx +319 -0
  73. package/src/modules/Settings/Integrations/IntegrationForm/style.tsx +77 -0
  74. package/src/modules/Settings/Integrations/IntegrationItem/CopyModal/index.tsx +44 -0
  75. package/src/modules/Settings/Integrations/IntegrationItem/CopyModal/style.tsx +13 -0
  76. package/src/modules/Settings/Integrations/IntegrationItem/index.tsx +197 -0
  77. package/src/modules/Settings/Integrations/IntegrationItem/style.tsx +81 -0
  78. package/src/modules/Settings/Integrations/atoms.tsx +49 -0
  79. package/src/modules/Settings/Integrations/hooks.tsx +72 -0
  80. package/src/modules/Settings/Integrations/index.tsx +299 -0
  81. package/src/modules/Settings/Integrations/style.tsx +48 -0
  82. package/src/modules/Settings/Integrations/utils.tsx +39 -0
  83. package/src/routes/site.tsx +19 -0
  84. package/src/schemas/pages/Page.tsx +5 -0
  85. package/src/types/index.tsx +35 -0
  86. package/tsconfig.paths.json +2 -0
  87. package/src/components/Fields/UrlField/PageFinder/SelectionListItem/index.tsx +0 -34
  88. package/src/components/Fields/UrlField/PageFinder/SelectionListItem/style.tsx +0 -35
  89. /package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/{Field → NavigationField}/style.tsx +0 -0
@@ -0,0 +1,153 @@
1
+ import { AxiosResponse } from "axios";
2
+ import { IIntegration } from "@ax/types";
3
+ import { template } from "./config";
4
+ import { IServiceConfig, sendRequest } from "./utils";
5
+
6
+ const SERVICES: { [key: string]: IServiceConfig } = {
7
+ GET_INTEGRATIONS: {
8
+ ...template,
9
+ endpoint: ["/site/", "/integrations"],
10
+ method: "GET",
11
+ },
12
+ GET_INTEGRATION: {
13
+ ...template,
14
+ endpoint: ["/site/", "/integration/"],
15
+ method: "GET",
16
+ },
17
+ CREATE_INTEGRATION: {
18
+ ...template,
19
+ endpoint: "/integration/site/",
20
+ method: "POST",
21
+ },
22
+ UPDATE_INTEGRATION: {
23
+ ...template,
24
+ endpoint: ["/integration/", "/site/"],
25
+ method: "PUT",
26
+ },
27
+ DELETE_INTEGRATION: {
28
+ ...template,
29
+ endpoint: "/integration/",
30
+ method: "DELETE",
31
+ },
32
+ DELETE_INTEGRATION_BULK: {
33
+ ...template,
34
+ endpoint: "/integration/bulk",
35
+ method: "DELETE",
36
+ },
37
+ CHANGE_INTEGRATION_STATE: {
38
+ ...template,
39
+ endpoint: ["/integration/", "/state/"],
40
+ method: "PUT",
41
+ },
42
+ CHANGE_INTEGRATION_STATE_BULK: {
43
+ ...template,
44
+ endpoint: ["/integration/state/", "/bulk"],
45
+ method: "PUT",
46
+ },
47
+ DUPLICATE_INTEGRATION: {
48
+ ...template,
49
+ endpoint: ["/integration/", "/duplicate/"],
50
+ method: "POST",
51
+ },
52
+ };
53
+
54
+ const getIntegrations = async (site: number, params: any = {}): Promise<AxiosResponse> => {
55
+ const { page, itemsPerPage, pagination = false, filter = "", filterState } = params;
56
+ const {
57
+ host,
58
+ endpoint: [prefix, suffix],
59
+ } = SERVICES.GET_INTEGRATIONS;
60
+
61
+ const stateQuery = filterState ? `&filterState=${filterState}` : "";
62
+ SERVICES.GET_INTEGRATIONS.dynamicUrl = `${host}${prefix}${site}${suffix}?pagination=${pagination}${filter}${stateQuery}`;
63
+ if (pagination) SERVICES.GET_INTEGRATIONS.dynamicUrl += `&page=${page}&itemsPerPage=${itemsPerPage}`;
64
+
65
+ return sendRequest(SERVICES.GET_INTEGRATIONS);
66
+ };
67
+
68
+ const getIntegration = async (id: number, siteID: number): Promise<AxiosResponse> => {
69
+ const {
70
+ host,
71
+ endpoint: [prefix, suffix],
72
+ } = SERVICES.GET_INTEGRATION;
73
+
74
+ SERVICES.GET_INTEGRATION.dynamicUrl = `${host}${prefix}${siteID}${suffix}${id}`;
75
+
76
+ return sendRequest(SERVICES.GET_INTEGRATION);
77
+ };
78
+
79
+ const createIntegration = async (data: IIntegration, siteID: number): Promise<AxiosResponse> => {
80
+ const { host, endpoint } = SERVICES.CREATE_INTEGRATION;
81
+
82
+ SERVICES.CREATE_INTEGRATION.dynamicUrl = `${host}${endpoint}${siteID}`;
83
+
84
+ return sendRequest(SERVICES.CREATE_INTEGRATION, { ...data });
85
+ };
86
+
87
+ const updateIntegration = async (data: IIntegration, siteID: number): Promise<AxiosResponse> => {
88
+ const {
89
+ host,
90
+ endpoint: [prefix, suffix],
91
+ } = SERVICES.UPDATE_INTEGRATION;
92
+
93
+ SERVICES.UPDATE_INTEGRATION.dynamicUrl = `${host}${prefix}${data.id}${suffix}${siteID}`;
94
+
95
+ return sendRequest(SERVICES.UPDATE_INTEGRATION, { ...data });
96
+ };
97
+
98
+ const deleteIntegration = async (id: number): Promise<AxiosResponse> => {
99
+ const { host, endpoint } = SERVICES.DELETE_INTEGRATION;
100
+
101
+ SERVICES.DELETE_INTEGRATION.dynamicUrl = `${host}${endpoint}${id}`;
102
+
103
+ return sendRequest(SERVICES.DELETE_INTEGRATION);
104
+ };
105
+
106
+ const deleteIntegrationsBulk = async (ids: number[]): Promise<AxiosResponse> => {
107
+ return sendRequest(SERVICES.DELETE_INTEGRATION_BULK, { ids });
108
+ };
109
+
110
+ const changeState = async (id: number, state: "enable" | "disable"): Promise<AxiosResponse> => {
111
+ const {
112
+ host,
113
+ endpoint: [prefix, suffix],
114
+ } = SERVICES.CHANGE_INTEGRATION_STATE;
115
+
116
+ SERVICES.CHANGE_INTEGRATION_STATE.dynamicUrl = `${host}${prefix}${id}${suffix}${state}`;
117
+
118
+ return sendRequest(SERVICES.CHANGE_INTEGRATION_STATE);
119
+ };
120
+
121
+ const changeStateBulk = async (ids: number[], state: "enable" | "disable"): Promise<AxiosResponse> => {
122
+ const {
123
+ host,
124
+ endpoint: [prefix, suffix],
125
+ } = SERVICES.CHANGE_INTEGRATION_STATE_BULK;
126
+
127
+ SERVICES.CHANGE_INTEGRATION_STATE_BULK.dynamicUrl = `${host}${prefix}${state}${suffix}`;
128
+
129
+ return sendRequest(SERVICES.CHANGE_INTEGRATION_STATE_BULK, { ids });
130
+ };
131
+
132
+ const duplicateIntegration = async (id: number, site: number): Promise<AxiosResponse> => {
133
+ const {
134
+ host,
135
+ endpoint: [prefix, suffix],
136
+ } = SERVICES.DUPLICATE_INTEGRATION;
137
+
138
+ SERVICES.DUPLICATE_INTEGRATION.dynamicUrl = `${host}${prefix}${id}${suffix}${site}`;
139
+
140
+ return sendRequest(SERVICES.DUPLICATE_INTEGRATION);
141
+ };
142
+
143
+ export default {
144
+ getIntegrations,
145
+ createIntegration,
146
+ updateIntegration,
147
+ getIntegration,
148
+ deleteIntegration,
149
+ deleteIntegrationsBulk,
150
+ changeState,
151
+ changeStateBulk,
152
+ duplicateIntegration,
153
+ };
package/src/api/sites.tsx CHANGED
@@ -1,7 +1,7 @@
1
1
  import { AxiosResponse } from "axios";
2
2
  import { IGetGlobalPagesParams, IGetSitePagesParams, IGetSitesParams } from "@ax/types";
3
3
  import { template } from "./config";
4
- import { sendRequest, sendInitialRequest, IServiceConfig } from "./utils";
4
+ import { sendRequest, IServiceConfig, sendInitialRequest } from "./utils";
5
5
 
6
6
  const SERVICES: { [key: string]: IServiceConfig } = {
7
7
  GET_ALL_SITES: {
@@ -173,7 +173,8 @@ const getSitePages = async (params: IGetSitePagesParams, filterQuery?: string):
173
173
  endpoint: [prefix, suffix],
174
174
  } = SERVICES.GET_SITE_PAGES;
175
175
 
176
- const { siteID, deleted, page, itemsPerPage, query, filterStructuredData, lang, format, filterPages } = params;
176
+ const { siteID, deleted, page, itemsPerPage, query, filterStructuredData, lang, format, filterPages, ignoreLang } =
177
+ params;
177
178
 
178
179
  const filters = filterQuery ? `${filterQuery}&` : "?";
179
180
 
@@ -190,6 +191,7 @@ const getSitePages = async (params: IGetSitePagesParams, filterQuery?: string):
190
191
  if (format) SERVICES.GET_SITE_PAGES.dynamicUrl = SERVICES.GET_SITE_PAGES.dynamicUrl + `&format=${format}`;
191
192
  if (filterPages)
192
193
  SERVICES.GET_SITE_PAGES.dynamicUrl = SERVICES.GET_SITE_PAGES.dynamicUrl + `&filterPages=${filterPages.join(",")}`;
194
+ if (ignoreLang) SERVICES.GET_SITE_PAGES.dynamicUrl = SERVICES.GET_SITE_PAGES.dynamicUrl + `&ignoreLang=${ignoreLang}`;
193
195
 
194
196
  const dataHeader = {
195
197
  ...(lang && { lang }),
@@ -31,7 +31,7 @@ const ActionMenu = (props: IActionMenuProps): JSX.Element => {
31
31
  </S.ActionItem>
32
32
  );
33
33
 
34
- return (
34
+ return options.length > 0 ? (
35
35
  <S.Wrapper className={className} data-testid="action-menu-wrapper">
36
36
  <Tooltip content={tooltip} hideOnClick>
37
37
  <FloatingMenu Button={MoreInfoButton}>
@@ -39,6 +39,8 @@ const ActionMenu = (props: IActionMenuProps): JSX.Element => {
39
39
  </FloatingMenu>
40
40
  </Tooltip>
41
41
  </S.Wrapper>
42
+ ) : (
43
+ <></>
42
44
  );
43
45
  };
44
46
 
@@ -12,6 +12,7 @@ export const IconActionWrapper = styled.div`
12
12
 
13
13
  export const ActionMenu = styled.ul`
14
14
  padding: 0;
15
+ cursor: pointer;
15
16
  `;
16
17
 
17
18
  export const ActionText = styled.div`
@@ -2,7 +2,7 @@ import React from "react";
2
2
 
3
3
  import { getInnerFields } from "@ax/forms";
4
4
  import { FieldContainer, FieldGroup } from "@ax/components";
5
- import { IErrorItem, IPage, ISite } from "@ax/types";
5
+ import { IErrorItem, IPage, ISite, ILanguage } from "@ax/types";
6
6
 
7
7
  const Field = (props: IFieldProps): JSX.Element => {
8
8
  const {
@@ -29,6 +29,7 @@ const Field = (props: IFieldProps): JSX.Element => {
29
29
  availableDataPacks,
30
30
  template,
31
31
  setHistoryPush,
32
+ languages,
32
33
  } = props;
33
34
  const isGroup = field.type === "FieldGroup";
34
35
  const isCollapsed = isGroup && field.collapsed;
@@ -81,6 +82,7 @@ const Field = (props: IFieldProps): JSX.Element => {
81
82
  availableDataPacks={availableDataPacks}
82
83
  template={template}
83
84
  setHistoryPush={setHistoryPush}
85
+ languages={languages}
84
86
  />
85
87
  );
86
88
  };
@@ -110,6 +112,7 @@ export interface IFieldProps {
110
112
  availableDataPacks: Record<string, any>[];
111
113
  template: any;
112
114
  setHistoryPush?: (path: string, isEditor: boolean) => void;
115
+ languages?: ILanguage[];
113
116
  }
114
117
 
115
118
  export default Field;
@@ -37,6 +37,7 @@ const PageConnectedField = (props: any) => {
37
37
  availableDataPacks,
38
38
  template,
39
39
  setHistoryPush,
40
+ languages,
40
41
  isReadOnly,
41
42
  } = props;
42
43
 
@@ -192,6 +193,7 @@ const PageConnectedField = (props: any) => {
192
193
  availableDataPacks={availableDataPacks}
193
194
  template={template}
194
195
  setHistoryPush={setHistoryPush}
196
+ languages={languages}
195
197
  />
196
198
  );
197
199
  };
@@ -209,6 +211,7 @@ const mapStateToProps = (state: IRootState) => ({
209
211
  moduleCopy: state.pageEditor.moduleCopy,
210
212
  availableDataPacks: state.dataPacks.available,
211
213
  template: state.pageEditor.template,
214
+ languages: state.sites.currentSiteLanguages,
212
215
  });
213
216
 
214
217
  const mapDispatchToProps = {
@@ -25,7 +25,7 @@ const GlobalPageForm = (props: IGlobalPageFormProps): JSX.Element => {
25
25
  setHistoryPush && setHistoryPush(path, true);
26
26
  };
27
27
 
28
- const field = {
28
+ const parentField = {
29
29
  title: "Parent",
30
30
  type: "AsyncSelect",
31
31
  entity: "pages",
@@ -131,7 +131,7 @@ const GlobalPageForm = (props: IGlobalPageFormProps): JSX.Element => {
131
131
  selectedTab={selectedTab}
132
132
  key="parent"
133
133
  objKey="parent"
134
- field={field}
134
+ field={parentField}
135
135
  componentType={schema.schemaType}
136
136
  isPage={true}
137
137
  isGlobal={true}
@@ -145,6 +145,15 @@ const GlobalPageForm = (props: IGlobalPageFormProps): JSX.Element => {
145
145
  isPage={true}
146
146
  isGlobal={true}
147
147
  />
148
+ <ConnectedField
149
+ selectedTab={selectedTab}
150
+ key="integrations"
151
+ objKey="integrations"
152
+ field={{ type: "IntegrationsField", key: "integrations" }}
153
+ componentType={schema.schemaType}
154
+ isPage={true}
155
+ isGlobal={true}
156
+ />
148
157
  </>
149
158
  )}
150
159
  </section>
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
 
3
- import { IPage, ISite } from "@ax/types";
3
+ import { IPage, ISite, ILanguage } from "@ax/types";
4
4
  import { getNullValue, getDefaultSchema, getDefaultTemplate } from "@ax/helpers";
5
5
 
6
6
  import { FieldsBehavior, HiddenField } from "@ax/components";
@@ -81,4 +81,5 @@ export interface IFieldContainerProps {
81
81
  availableDataPacks?: Record<string, unknown>[];
82
82
  template?: any;
83
83
  setHistoryPush?: (path: string, isEditor: boolean) => void;
84
+ languages?: ILanguage[];
84
85
  }
@@ -0,0 +1,101 @@
1
+ import React, { useState } from "react";
2
+
3
+ import { IIntegration } from "@ax/types";
4
+ import { FloatingPanel, Button, FieldsBehavior, NoteField } from "@ax/components";
5
+
6
+ import * as S from "./style";
7
+
8
+ const CustomPanel = (props: IProps): JSX.Element => {
9
+ const { isOpen, toggleModal, integration, setIntegration } = props;
10
+
11
+ const [form, setForm] = useState(integration);
12
+
13
+ const handleChange = (value: Record<string, string>) => setForm((state) => ({ ...state, ...value }));
14
+
15
+ const editItemAction = () => {
16
+ form && setIntegration(form);
17
+ toggleModal();
18
+ };
19
+
20
+ const editButton = {
21
+ label: "Add custom code",
22
+ action: editItemAction,
23
+ };
24
+
25
+ const noteText =
26
+ "Add custom code to the head or body for this page. The third-party must give you instructions about where to place the code and how to use it.";
27
+
28
+ const bodyCodeOptions = [
29
+ {
30
+ title: "Start of the body",
31
+ name: "start",
32
+ value: "start",
33
+ },
34
+ {
35
+ title: "End of the body",
36
+ name: "end",
37
+ value: "end",
38
+ },
39
+ ];
40
+
41
+ return (
42
+ <FloatingPanel title="Add custom code" toggleModal={toggleModal} isOpen={isOpen}>
43
+ <S.ContentWrapper>
44
+ <S.NoteWrapper>
45
+ <NoteField value={{ text: noteText }} />
46
+ </S.NoteWrapper>
47
+ <FieldsBehavior
48
+ title="Name"
49
+ name="name"
50
+ fieldType="TextField"
51
+ value={form.name}
52
+ placeholder="Type a name"
53
+ onChange={(value: string) => handleChange({ name: value })}
54
+ mandatory
55
+ validators={{ mandatory: true }}
56
+ />
57
+ <FieldsBehavior
58
+ title="Head Code"
59
+ name="contentHead"
60
+ fieldType="TextArea"
61
+ value={form.contentHead}
62
+ placeholder="Enter the code that will be injected into the head’s page."
63
+ onChange={(value: string) => handleChange({ contentHead: value })}
64
+ rows={4}
65
+ />
66
+ <FieldsBehavior
67
+ title="Body Code"
68
+ name="contentBody"
69
+ fieldType="TextArea"
70
+ value={form.contentBody}
71
+ placeholder="Enter the code that will be injected into the body’s page."
72
+ onChange={(value: string) => handleChange({ contentBody: value })}
73
+ rows={4}
74
+ />
75
+ <FieldsBehavior
76
+ title="Page body code in:"
77
+ name="contentBodyPosition"
78
+ fieldType="RadioGroup"
79
+ value={form.contentBodyPosition}
80
+ options={bodyCodeOptions}
81
+ onChange={(value: string) => handleChange({ contentBodyPosition: value })}
82
+ disabled={!form.contentBody?.length}
83
+ />
84
+ </S.ContentWrapper>
85
+ <S.Footer>
86
+ <Button className="button" type="button" onClick={editButton.action} disabled={!form.name?.length}>
87
+ {editButton.label}
88
+ </Button>
89
+ </S.Footer>
90
+ </FloatingPanel>
91
+ );
92
+ };
93
+
94
+ interface IProps {
95
+ integration: Partial<IIntegration>;
96
+ isOpen: boolean;
97
+ toggleModal: () => void;
98
+ setIntegration(modifiedIntegration: Partial<IIntegration>): void;
99
+ }
100
+
101
+ export default CustomPanel;
@@ -0,0 +1,23 @@
1
+ import styled from "styled-components";
2
+
3
+ const Footer = styled.div`
4
+ position: absolute;
5
+ bottom: ${(p) => p.theme.spacing.m};
6
+ right: ${(p) => p.theme.spacing.m};
7
+ `;
8
+
9
+ const NoteWrapper = styled.div`
10
+ margin-bottom: ${(p) => p.theme.spacing.m};
11
+
12
+ `
13
+
14
+ const ContentWrapper = styled.div`
15
+ height: calc(100% - ${(p) => p.theme.spacing.s} * 10);
16
+ overflow-y: scroll;
17
+ border-bottom: 1px solid ${(p) => p.theme.color.uiLine};
18
+ position: absolute;
19
+ left: 0;
20
+ padding: 0 ${(p) => p.theme.spacing.m} ${(p) => p.theme.spacing.s} ${(p) => p.theme.spacing.m};
21
+ `;
22
+
23
+ export { Footer, NoteWrapper, ContentWrapper };
@@ -0,0 +1,31 @@
1
+ import { IIntegrationVariable } from "@ax/types";
2
+
3
+ const modifyVariableValue = (
4
+ variables: IIntegrationVariable[] | undefined,
5
+ newVariableValues: {
6
+ id: number | undefined;
7
+ value: string;
8
+ multiLangVariable?: { id?: number; languageId: number; value: string };
9
+ }
10
+ ): IIntegrationVariable[] | undefined => {
11
+ const { id, value, multiLangVariable } = newVariableValues;
12
+ let newVariables;
13
+ if (multiLangVariable) {
14
+ newVariables = variables?.map((variable) =>
15
+ variable.id === id
16
+ ? {
17
+ ...variable,
18
+ multilanguage:
19
+ variable.multilanguage?.map((langVariable) =>
20
+ langVariable.id === multiLangVariable.id ? { ...langVariable, value } : langVariable
21
+ ) || null,
22
+ }
23
+ : variable
24
+ );
25
+ } else {
26
+ newVariables = variables?.map((variable) => (variable.id === id ? { ...variable, value } : variable));
27
+ }
28
+ return newVariables;
29
+ };
30
+
31
+ export { modifyVariableValue };
@@ -0,0 +1,120 @@
1
+ import React, { useCallback, useRef, useState } from "react";
2
+
3
+ import { IIntegration, IIntegrationVariable, ILanguage } from "@ax/types";
4
+ import { FloatingPanel, Button, FieldsBehavior, NoteField } from "@ax/components";
5
+
6
+ import * as S from "./style";
7
+ import { modifyVariableValue } from "./helpers";
8
+
9
+ const VariablesPanel = (props: IProps): JSX.Element => {
10
+ const { isOpen, toggleModal, integration, setIntegrationVariables, languages } = props;
11
+ const { variables } = integration;
12
+
13
+ const [variablesForm, setVariablesForm] = useState(variables);
14
+
15
+ const setVariableValue = (
16
+ id: number | undefined,
17
+ value: string,
18
+ multiLangVariable?: { id?: number; languageId: number; value: string }
19
+ ) => {
20
+ const newVariableValues = { id, value, multiLangVariable };
21
+ const newVariables = modifyVariableValue(variablesForm, newVariableValues);
22
+ setVariablesForm(newVariables);
23
+ };
24
+ const setVariableValueRef = useRef(setVariableValue);
25
+ setVariableValueRef.current = setVariableValue;
26
+
27
+ const editItemAction = () => {
28
+ variablesForm && setIntegrationVariables(variablesForm);
29
+ toggleModal();
30
+ };
31
+
32
+ const editButton = {
33
+ label: "Update values",
34
+ action: editItemAction,
35
+ };
36
+
37
+ const noteText =
38
+ "This integration has some variables assigned. You can define its values to customize some properties.";
39
+
40
+ const Variable = ({ variable }: { variable: IIntegrationVariable }) => {
41
+ const handleChange = (value: string) => setVariableValueRef.current(variable.id, value);
42
+ return (
43
+ <FieldsBehavior
44
+ title={variable.variableName}
45
+ name={variable.variableName}
46
+ fieldType="TextArea"
47
+ value={variable.value}
48
+ placeholder={variable.defaultValue}
49
+ onChange={handleChange}
50
+ mandatory
51
+ validators={{ mandatory: true }}
52
+ rows={4}
53
+ />
54
+ );
55
+ };
56
+
57
+ const MultilanguageVariable = (props: {
58
+ variable: IIntegrationVariable;
59
+ multiLangVariable: { id?: number; languageId: number; value: string };
60
+ }) => {
61
+ const { variable, multiLangVariable } = props;
62
+ const langName = languages.find((lang) => lang.id === multiLangVariable.languageId)?.language;
63
+ const variableName = `${langName} ${variable.variableName}`;
64
+ const handleChange = (value: string) => setVariableValueRef.current(variable.id, value, multiLangVariable);
65
+ return (
66
+ <FieldsBehavior
67
+ title={variableName}
68
+ name={variable.variableName}
69
+ fieldType="TextArea"
70
+ value={multiLangVariable.value}
71
+ placeholder={variable.defaultValue}
72
+ onChange={handleChange}
73
+ mandatory
74
+ validators={{ mandatory: true }}
75
+ rows={4}
76
+ />
77
+ );
78
+ };
79
+
80
+ const renderVariables = useCallback(
81
+ () =>
82
+ variablesForm?.map((variable, index) =>
83
+ variable.isMultilanguage ? (
84
+ variable.multilanguage?.map((multiLangVariable, i) => (
85
+ <MultilanguageVariable key={i} variable={variable} multiLangVariable={multiLangVariable} />
86
+ ))
87
+ ) : (
88
+ <Variable key={index} variable={variable} />
89
+ )
90
+ ),
91
+ // eslint-disable-next-line react-hooks/exhaustive-deps
92
+ [variables]
93
+ );
94
+
95
+ return (
96
+ <FloatingPanel title="Define values" toggleModal={toggleModal} isOpen={isOpen}>
97
+ <S.ContentWrapper>
98
+ <S.NoteWrapper>
99
+ <NoteField value={{ text: noteText }} />
100
+ </S.NoteWrapper>
101
+ {renderVariables()}
102
+ </S.ContentWrapper>
103
+ <S.Footer>
104
+ <Button className="button" type="button" onClick={editButton.action}>
105
+ {editButton.label}
106
+ </Button>
107
+ </S.Footer>
108
+ </FloatingPanel>
109
+ );
110
+ };
111
+
112
+ interface IProps {
113
+ integration: Partial<IIntegration>;
114
+ isOpen: boolean;
115
+ toggleModal: () => void;
116
+ setIntegrationVariables(variables: IIntegrationVariable[]): void;
117
+ languages: ILanguage[];
118
+ }
119
+
120
+ export default VariablesPanel;
@@ -0,0 +1,23 @@
1
+ import styled from "styled-components";
2
+
3
+ const Footer = styled.div`
4
+ position: absolute;
5
+ bottom: ${(p) => p.theme.spacing.m};
6
+ right: ${(p) => p.theme.spacing.m};
7
+ `;
8
+
9
+ const NoteWrapper = styled.div`
10
+ margin-bottom: ${(p) => p.theme.spacing.m};
11
+
12
+ `
13
+
14
+ const ContentWrapper = styled.div`
15
+ height: calc(100% - ${(p) => p.theme.spacing.s} * 10);
16
+ overflow-y: scroll;
17
+ border-bottom: 1px solid ${(p) => p.theme.color.uiLine};
18
+ position: absolute;
19
+ left: 0;
20
+ padding: 0 ${(p) => p.theme.spacing.m} ${(p) => p.theme.spacing.s} ${(p) => p.theme.spacing.m};
21
+ `;
22
+
23
+ export { Footer, NoteWrapper, ContentWrapper };
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+
3
+ import { IModal } from "@ax/types";
4
+ import { Modal } from "@ax/components";
5
+
6
+ import * as S from "./style";
7
+
8
+ const DeleteModal = (props: IModal & { integrationName: string | undefined }): JSX.Element => {
9
+ const { isOpen, toggleModal, mainModalAction, secondaryModalAction, integrationName } = props;
10
+
11
+ return (
12
+ <Modal
13
+ isOpen={isOpen}
14
+ hide={toggleModal}
15
+ title={`Remove ${integrationName} integration`}
16
+ secondaryAction={secondaryModalAction}
17
+ mainAction={mainModalAction}
18
+ size="S"
19
+ >
20
+ <S.ModalContent>
21
+ Are you sure you want to remove <strong>{integrationName}</strong> from this page?
22
+ </S.ModalContent>
23
+ </Modal>
24
+ );
25
+ };
26
+
27
+ export { DeleteModal };