@griddo/ax 11.6.7 → 11.6.8-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.
- package/package.json +2 -2
- package/src/components/Fields/FormContainer/FormModal/index.tsx +31 -38
- package/src/components/Fields/FormContainer/index.tsx +42 -4
- package/src/components/Fields/FormContainer/style.tsx +19 -1
- package/src/components/TableFilters/CategoryFilter/index.tsx +16 -0
- package/src/containers/Navigation/Menu/actions.tsx +54 -67
- package/src/containers/Navigation/Menu/constants.tsx +1 -2
- package/src/containers/Navigation/Menu/interfaces.tsx +11 -15
- package/src/containers/Navigation/Menu/reducer.tsx +10 -12
- package/src/modules/Navigation/Menus/List/Table/index.tsx +1 -1
- package/src/modules/Navigation/Menus/List/index.tsx +12 -10
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "11.6.
|
|
4
|
+
"version": "11.6.8-rc.0",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Diego M. Béjar <diego.bejar@secuoyas.com>",
|
|
@@ -223,5 +223,5 @@
|
|
|
223
223
|
"publishConfig": {
|
|
224
224
|
"access": "public"
|
|
225
225
|
},
|
|
226
|
-
"gitHead": "
|
|
226
|
+
"gitHead": "5ea0f19fe563be2563c7c8ce9c4bc99bbc449fef"
|
|
227
227
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React, { Dispatch, SetStateAction, useCallback, useEffect, useState } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
|
-
import { FormContent, GetFormsParams, IModal, IQueryValue, IRootState
|
|
4
|
+
import { FormContent, GetFormsParams, IModal, IQueryValue, IRootState } from "@ax/types";
|
|
5
5
|
import {
|
|
6
6
|
Button,
|
|
7
|
-
CategoryFilter,
|
|
8
7
|
EmptyState,
|
|
9
8
|
ErrorToast,
|
|
10
9
|
FilterTagsBar,
|
|
@@ -20,8 +19,21 @@ import { formsActions } from "@ax/containers/Forms";
|
|
|
20
19
|
import * as S from "./style";
|
|
21
20
|
|
|
22
21
|
const FormModal = (props: IFormModal): JSX.Element => {
|
|
23
|
-
const {
|
|
24
|
-
|
|
22
|
+
const {
|
|
23
|
+
isOpen,
|
|
24
|
+
toggleModal,
|
|
25
|
+
site,
|
|
26
|
+
forms,
|
|
27
|
+
categories,
|
|
28
|
+
getForms,
|
|
29
|
+
selectedForm,
|
|
30
|
+
setSelectedForm,
|
|
31
|
+
selectForm,
|
|
32
|
+
filters,
|
|
33
|
+
filterValues,
|
|
34
|
+
resetFilterQuery,
|
|
35
|
+
filterItems,
|
|
36
|
+
} = props;
|
|
25
37
|
|
|
26
38
|
const tabs: string[] = [];
|
|
27
39
|
if (site) {
|
|
@@ -29,26 +41,27 @@ const FormModal = (props: IFormModal): JSX.Element => {
|
|
|
29
41
|
}
|
|
30
42
|
|
|
31
43
|
const formCategories = getSchemaFormCategories();
|
|
32
|
-
const isGlobal = !
|
|
44
|
+
const isGlobal = !site;
|
|
33
45
|
|
|
34
46
|
const filterLabels = formCategories.reduce((a, v) => ({ ...a, [v.value]: v.label }), {});
|
|
35
|
-
const initialState = formCategories.reduce((a, v) => ({ ...a, [v.value]: [{ value: "all", label: "All" }] }), {});
|
|
36
47
|
|
|
37
48
|
const [selectedTab, setSelectedTab] = useState(site ? "Site" : "Global");
|
|
38
49
|
const [searchQuery, setSearchQuery] = useState<string>("");
|
|
39
50
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
40
|
-
const [filterValues, setFilterValues] = useState<Record<string, IQueryValue[]>>(initialState);
|
|
41
51
|
|
|
42
|
-
const siteID =
|
|
52
|
+
const siteID = site && selectedTab !== "Global" ? site : null;
|
|
43
53
|
const isFiltering = searchQuery.length > 0 || Object.values(filterValues).length;
|
|
44
54
|
|
|
45
55
|
const getParams = useCallback(() => {
|
|
46
|
-
const
|
|
56
|
+
const userCategories = Object.values(filterValues).reduce((acc: (number | string)[], current: IQueryValue[]) => {
|
|
47
57
|
const values = current.filter((val) => val.value !== "all").map((val) => val.value);
|
|
48
58
|
return [...acc, ...values];
|
|
49
59
|
}, []);
|
|
50
60
|
|
|
51
|
-
const
|
|
61
|
+
const hasSchemaCategories = !!categories && categories.length > 0;
|
|
62
|
+
const filterCategories = hasSchemaCategories ? [...categories, ...userCategories] : userCategories;
|
|
63
|
+
|
|
64
|
+
const typeFilter = filterCategories.length ? `&type=${filterCategories.join(",")}` : "";
|
|
52
65
|
|
|
53
66
|
const params: GetFormsParams = {
|
|
54
67
|
page: 1,
|
|
@@ -58,7 +71,7 @@ const FormModal = (props: IFormModal): JSX.Element => {
|
|
|
58
71
|
};
|
|
59
72
|
|
|
60
73
|
return params;
|
|
61
|
-
}, [searchQuery, filterValues]);
|
|
74
|
+
}, [searchQuery, filterValues, categories]);
|
|
62
75
|
|
|
63
76
|
useEffect(() => {
|
|
64
77
|
const handleGetForms = async () => {
|
|
@@ -85,29 +98,6 @@ const FormModal = (props: IFormModal): JSX.Element => {
|
|
|
85
98
|
}
|
|
86
99
|
};
|
|
87
100
|
|
|
88
|
-
const filterItems = (filterPointer: string, filtersSelected: IQueryValue[]) =>
|
|
89
|
-
setFilterValues((state) => ({ ...state, [filterPointer]: filtersSelected }));
|
|
90
|
-
|
|
91
|
-
const resetFilterQuery = () => setFilterValues(initialState);
|
|
92
|
-
|
|
93
|
-
const Filters = () => (
|
|
94
|
-
<S.Filters>
|
|
95
|
-
{formCategories.map((formCategory, i: number) => (
|
|
96
|
-
<S.FilterWrapper key={formCategory.value}>
|
|
97
|
-
<CategoryFilter
|
|
98
|
-
filterItems={filterItems}
|
|
99
|
-
value={filterValues[formCategory.value]}
|
|
100
|
-
formCategory={formCategory}
|
|
101
|
-
siteID={siteID}
|
|
102
|
-
pointer={formCategory.value}
|
|
103
|
-
autoWidth={true}
|
|
104
|
-
menuPosition={i === formCategories.length - 1 && !isGlobal ? "right" : "left"}
|
|
105
|
-
/>
|
|
106
|
-
</S.FilterWrapper>
|
|
107
|
-
))}
|
|
108
|
-
</S.Filters>
|
|
109
|
-
);
|
|
110
|
-
|
|
111
101
|
const emptySearchStateProps = {
|
|
112
102
|
icon: "search",
|
|
113
103
|
title: "Oh! No Results Found",
|
|
@@ -125,11 +115,11 @@ const FormModal = (props: IFormModal): JSX.Element => {
|
|
|
125
115
|
<Tabs tabs={tabs} active={selectedTab} setSelectedTab={handleSelectedTab} noMargins />
|
|
126
116
|
</S.TabsWrapper>
|
|
127
117
|
)}
|
|
128
|
-
|
|
118
|
+
{filters}
|
|
129
119
|
</S.ModalTabs>
|
|
130
120
|
)}
|
|
131
121
|
<S.SearchWrapper>
|
|
132
|
-
{isGlobal &&
|
|
122
|
+
{isGlobal && filters}
|
|
133
123
|
<S.Search full={!isGlobal}>
|
|
134
124
|
<SearchField
|
|
135
125
|
onChange={setSearchQuery}
|
|
@@ -190,15 +180,18 @@ interface IFormModal extends IModal {
|
|
|
190
180
|
site: number | null;
|
|
191
181
|
forms: FormContent[];
|
|
192
182
|
selectedForm: FormContent | null;
|
|
193
|
-
currentSiteInfo: ISite | null;
|
|
194
183
|
getForms(siteID: number | null, params?: GetFormsParams, loading?: boolean): Promise<void>;
|
|
195
184
|
setSelectedForm: Dispatch<SetStateAction<FormContent | null>>;
|
|
196
185
|
selectForm(): void;
|
|
186
|
+
categories?: string[];
|
|
187
|
+
filters: JSX.Element;
|
|
188
|
+
filterValues: Record<string, IQueryValue[]>;
|
|
189
|
+
resetFilterQuery(): void;
|
|
190
|
+
filterItems(filterPointer: string, filtersSelected: IQueryValue[]): void;
|
|
197
191
|
}
|
|
198
192
|
|
|
199
193
|
const mapStateToProps = (state: IRootState) => ({
|
|
200
194
|
forms: state.forms.forms,
|
|
201
|
-
currentSiteInfo: state.sites.currentSiteInfo,
|
|
202
195
|
});
|
|
203
196
|
|
|
204
197
|
const mapDispatchToProps = {
|
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
2
|
import { useModal, usePermission } from "@ax/hooks";
|
|
3
|
-
import { trimText } from "@ax/helpers";
|
|
4
|
-
import { ActionMenu, HiddenField, Icon } from "@ax/components";
|
|
5
|
-
import { FormContent, ISite } from "@ax/types";
|
|
3
|
+
import { getSchemaFormCategories, trimText } from "@ax/helpers";
|
|
4
|
+
import { ActionMenu, CategoryFilter, HiddenField, Icon } from "@ax/components";
|
|
5
|
+
import { FormContent, IQueryValue, ISite } from "@ax/types";
|
|
6
6
|
|
|
7
7
|
import FormModal from "./FormModal";
|
|
8
8
|
|
|
9
9
|
import * as S from "./style";
|
|
10
10
|
|
|
11
11
|
const FormContainer = (props: IFormContainerProps): JSX.Element => {
|
|
12
|
-
const { value, onChange, goTo, title, disabled, editorID, className, site } = props;
|
|
12
|
+
const { value, onChange, goTo, title, disabled, editorID, className, site, formCategories } = props;
|
|
13
13
|
|
|
14
14
|
const { title: formTitle } = value || { title: "" };
|
|
15
15
|
|
|
16
16
|
const isEmpty = !value;
|
|
17
|
+
const isGlobal = !site;
|
|
18
|
+
const schemaFormCategories = getSchemaFormCategories();
|
|
17
19
|
|
|
18
20
|
const { isOpen, toggleModal } = useModal();
|
|
19
21
|
const [selectedForm, setSelectedForm] = useState<FormContent | null>(value || null);
|
|
22
|
+
const initialState = schemaFormCategories.reduce(
|
|
23
|
+
(a, v) => ({ ...a, [v.value]: [{ value: "all", label: "All" }] }),
|
|
24
|
+
{}
|
|
25
|
+
);
|
|
26
|
+
const [filterValues, setFilterValues] = useState<Record<string, IQueryValue[]>>(initialState);
|
|
20
27
|
|
|
21
28
|
const addFormPermission = site ? "forms.addFormsToPage" : "global.forms.addFormsToPage";
|
|
22
29
|
const overwriteFormPermission = site ? "forms.overwriteDataForms" : "global.forms.overwriteDataForms";
|
|
@@ -46,6 +53,31 @@ const FormContainer = (props: IFormContainerProps): JSX.Element => {
|
|
|
46
53
|
]
|
|
47
54
|
: [];
|
|
48
55
|
|
|
56
|
+
const filterItems = (filterPointer: string, filtersSelected: IQueryValue[]) =>
|
|
57
|
+
setFilterValues((state) => ({ ...state, [filterPointer]: filtersSelected }));
|
|
58
|
+
|
|
59
|
+
const resetFilterQuery = () => setFilterValues(initialState);
|
|
60
|
+
|
|
61
|
+
const filters = (
|
|
62
|
+
<S.Filters>
|
|
63
|
+
{schemaFormCategories.map((formCategory, i: number) => (
|
|
64
|
+
<S.FilterWrapper key={formCategory.value}>
|
|
65
|
+
<CategoryFilter
|
|
66
|
+
filterItems={filterItems}
|
|
67
|
+
value={filterValues[formCategory.value]}
|
|
68
|
+
formCategory={formCategory}
|
|
69
|
+
siteID={site?.id || null}
|
|
70
|
+
pointer={formCategory.value}
|
|
71
|
+
autoWidth={true}
|
|
72
|
+
menuPosition={i === schemaFormCategories.length - 1 && !isGlobal ? "right" : "left"}
|
|
73
|
+
hideValues={formCategories}
|
|
74
|
+
hideOnLoading={true}
|
|
75
|
+
/>
|
|
76
|
+
</S.FilterWrapper>
|
|
77
|
+
))}
|
|
78
|
+
</S.Filters>
|
|
79
|
+
);
|
|
80
|
+
|
|
49
81
|
return (
|
|
50
82
|
<>
|
|
51
83
|
{isEmpty ? (
|
|
@@ -76,6 +108,11 @@ const FormContainer = (props: IFormContainerProps): JSX.Element => {
|
|
|
76
108
|
selectedForm={selectedForm}
|
|
77
109
|
setSelectedForm={setSelectedForm}
|
|
78
110
|
selectForm={handleSelectForm}
|
|
111
|
+
categories={formCategories}
|
|
112
|
+
filters={filters}
|
|
113
|
+
filterValues={filterValues}
|
|
114
|
+
resetFilterQuery={resetFilterQuery}
|
|
115
|
+
filterItems={filterItems}
|
|
79
116
|
/>
|
|
80
117
|
)}
|
|
81
118
|
</>
|
|
@@ -91,6 +128,7 @@ export interface IFormContainerProps {
|
|
|
91
128
|
className?: string;
|
|
92
129
|
title: string;
|
|
93
130
|
site: ISite | null;
|
|
131
|
+
formCategories?: string[];
|
|
94
132
|
}
|
|
95
133
|
|
|
96
134
|
export default FormContainer;
|
|
@@ -71,4 +71,22 @@ const Title = styled.div<{ disabled?: boolean }>`
|
|
|
71
71
|
margin: ${(p) => p.theme.spacing.xxs} 0;
|
|
72
72
|
`;
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
const Filters = styled.div`
|
|
75
|
+
display: flex;
|
|
76
|
+
height: ${(p) => p.theme.spacing.l};
|
|
77
|
+
align-items: center;
|
|
78
|
+
& > * {
|
|
79
|
+
&:not(:last-child) {
|
|
80
|
+
margin-right: ${(p) => p.theme.spacing.m};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
.headerWrapper {
|
|
84
|
+
padding: 0;
|
|
85
|
+
}
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
const FilterWrapper = styled.div`
|
|
89
|
+
position: relative;
|
|
90
|
+
`;
|
|
91
|
+
|
|
92
|
+
export { Component, IconWrapper, Title, HiddenButtonsWrapper, Filters, FilterWrapper };
|
|
@@ -17,6 +17,8 @@ const CategoryFilter = (props: ICategoryFilterProps): JSX.Element => {
|
|
|
17
17
|
pointer = "categories",
|
|
18
18
|
autoWidth = false,
|
|
19
19
|
menuPosition = "left",
|
|
20
|
+
hideValues = [],
|
|
21
|
+
hideOnLoading,
|
|
20
22
|
} = props;
|
|
21
23
|
|
|
22
24
|
const filters: IFilterValue[] = [
|
|
@@ -31,20 +33,25 @@ const CategoryFilter = (props: ICategoryFilterProps): JSX.Element => {
|
|
|
31
33
|
const parsedValue = Array.isArray(value) && value.length ? value.map((val) => val.value) : [selectAllOption];
|
|
32
34
|
const [selectedValue, setSelectedValue] = useState(parsedValue);
|
|
33
35
|
const [options, setOptions] = useState(filters);
|
|
36
|
+
const [hideFilter, setHideFilter] = useState(false);
|
|
37
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
34
38
|
const title = formCategory ? formCategory.label : structuredData.title;
|
|
35
39
|
|
|
36
40
|
const getSelectCategories = async () => {
|
|
41
|
+
setIsLoading(true);
|
|
37
42
|
try {
|
|
38
43
|
const site = siteID ? siteID : "global";
|
|
39
44
|
const items = formCategory
|
|
40
45
|
? await checkgroups.getFormCategories(site, formCategory.value)
|
|
41
46
|
: await checkgroups.getCheckGroupItems(site, structuredData.source);
|
|
42
47
|
if (items && isReqOk(items.status)) {
|
|
48
|
+
setIsLoading(false);
|
|
43
49
|
return items.data;
|
|
44
50
|
}
|
|
45
51
|
} catch (e) {
|
|
46
52
|
console.log(e);
|
|
47
53
|
}
|
|
54
|
+
setIsLoading(false);
|
|
48
55
|
return false;
|
|
49
56
|
};
|
|
50
57
|
|
|
@@ -52,6 +59,9 @@ const CategoryFilter = (props: ICategoryFilterProps): JSX.Element => {
|
|
|
52
59
|
getSelectCategories().then((items) => {
|
|
53
60
|
items &&
|
|
54
61
|
items.forEach((item: { value: string; title: string }) => {
|
|
62
|
+
if (hideValues.includes(item.value)) {
|
|
63
|
+
setHideFilter(true);
|
|
64
|
+
}
|
|
55
65
|
const newFilter = {
|
|
56
66
|
name: item.value,
|
|
57
67
|
value: item.value,
|
|
@@ -93,6 +103,10 @@ const CategoryFilter = (props: ICategoryFilterProps): JSX.Element => {
|
|
|
93
103
|
</S.HeaderWrapper>
|
|
94
104
|
);
|
|
95
105
|
|
|
106
|
+
if (hideFilter || (hideOnLoading && isLoading)) {
|
|
107
|
+
return <></>;
|
|
108
|
+
}
|
|
109
|
+
|
|
96
110
|
return (
|
|
97
111
|
<FloatingMenu Button={Header} position={menuPosition} closeOnSelect={false} isCheckGroup={true}>
|
|
98
112
|
<ListTitle data-testid="category-filter-title">Filter by Category</ListTitle>
|
|
@@ -112,6 +126,8 @@ export interface ICategoryFilterProps {
|
|
|
112
126
|
pointer?: string;
|
|
113
127
|
autoWidth?: boolean;
|
|
114
128
|
menuPosition?: string;
|
|
129
|
+
hideValues?: (string | number)[];
|
|
130
|
+
hideOnLoading?: boolean;
|
|
115
131
|
}
|
|
116
132
|
|
|
117
133
|
export default CategoryFilter;
|
|
@@ -1,68 +1,49 @@
|
|
|
1
1
|
import { Dispatch } from "redux";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { handleRequest } from "@ax/helpers";
|
|
4
4
|
import { generateEditorIDs } from "@ax/forms";
|
|
5
5
|
import { menus } from "@ax/api";
|
|
6
6
|
import { appActions } from "@ax/containers/App";
|
|
7
|
-
import { IMenuItem, IMenu } from "@ax/types";
|
|
7
|
+
import { IMenuItem, IMenu, IRootState, IMenuForm } from "@ax/types";
|
|
8
8
|
import {
|
|
9
9
|
SET_ORIGINAL_MENUS,
|
|
10
10
|
SET_EDITOR_MENU,
|
|
11
|
-
SET_ID,
|
|
12
11
|
SET_ITEM,
|
|
13
12
|
SET_MENU_FORM_DATA,
|
|
14
13
|
SET_ORIGINAL_MENU,
|
|
15
14
|
SET_TOTAL_ITEMS,
|
|
15
|
+
SET_CURRENT_TYPE,
|
|
16
16
|
} from "./constants";
|
|
17
17
|
import {
|
|
18
18
|
ISetSavedMenus,
|
|
19
19
|
ISetEditorMenu,
|
|
20
|
-
ISetId,
|
|
21
20
|
ISetItem,
|
|
22
21
|
ISetMenuForm,
|
|
23
22
|
ISetSavedMenu,
|
|
24
23
|
ISetTotalItems,
|
|
24
|
+
ISetCurrentType,
|
|
25
25
|
} from "./interfaces";
|
|
26
26
|
import { menuInitialState } from "./reducer";
|
|
27
27
|
|
|
28
28
|
const { setIsLoading } = appActions;
|
|
29
29
|
|
|
30
|
-
function setSavedMenus(savedMenus:
|
|
31
|
-
return {
|
|
32
|
-
type: SET_ORIGINAL_MENUS,
|
|
33
|
-
payload: { savedMenus },
|
|
34
|
-
};
|
|
30
|
+
function setSavedMenus(savedMenus: IMenu[]): ISetSavedMenus {
|
|
31
|
+
return { type: SET_ORIGINAL_MENUS, payload: { savedMenus } };
|
|
35
32
|
}
|
|
36
33
|
|
|
37
|
-
function setSavedMenu(savedMenu:
|
|
38
|
-
return {
|
|
39
|
-
type: SET_ORIGINAL_MENU,
|
|
40
|
-
payload: { savedMenu },
|
|
41
|
-
};
|
|
34
|
+
function setSavedMenu(savedMenu: IMenu): ISetSavedMenu {
|
|
35
|
+
return { type: SET_ORIGINAL_MENU, payload: { savedMenu } };
|
|
42
36
|
}
|
|
43
37
|
|
|
44
|
-
function setEditorMenu(editorMenu:
|
|
45
|
-
return {
|
|
46
|
-
type: SET_EDITOR_MENU,
|
|
47
|
-
payload: { editorMenu },
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function setId(id: number): ISetId {
|
|
52
|
-
return {
|
|
53
|
-
type: SET_ID,
|
|
54
|
-
payload: { id },
|
|
55
|
-
};
|
|
38
|
+
function setEditorMenu(editorMenu: IMenu | null): ISetEditorMenu {
|
|
39
|
+
return { type: SET_EDITOR_MENU, payload: { editorMenu } };
|
|
56
40
|
}
|
|
57
41
|
|
|
58
42
|
function setItem(item: IMenuItem): ISetItem {
|
|
59
|
-
return {
|
|
60
|
-
type: SET_ITEM,
|
|
61
|
-
payload: { item },
|
|
62
|
-
};
|
|
43
|
+
return { type: SET_ITEM, payload: { item } };
|
|
63
44
|
}
|
|
64
45
|
|
|
65
|
-
function setMenuFormData(form:
|
|
46
|
+
function setMenuFormData(form: IMenuForm): ISetMenuForm {
|
|
66
47
|
return { type: SET_MENU_FORM_DATA, payload: { form } };
|
|
67
48
|
}
|
|
68
49
|
|
|
@@ -70,8 +51,12 @@ function setTotalItems(totalItems: number): ISetTotalItems {
|
|
|
70
51
|
return { type: SET_TOTAL_ITEMS, payload: { totalItems } };
|
|
71
52
|
}
|
|
72
53
|
|
|
73
|
-
|
|
74
|
-
|
|
54
|
+
function setCurrentType(currentType: string): ISetCurrentType {
|
|
55
|
+
return { type: SET_CURRENT_TYPE, payload: { currentType } };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const getStateValues = (getState: () => IRootState) => {
|
|
59
|
+
const { savedMenus, savedMenu, editorMenu, currentType } = getState().menu;
|
|
75
60
|
const { currentSiteInfo } = getState().sites;
|
|
76
61
|
const { isSaving, isLoading, lang } = getState().app;
|
|
77
62
|
|
|
@@ -79,8 +64,7 @@ const getStateValues = (getState: any) => {
|
|
|
79
64
|
savedMenus,
|
|
80
65
|
savedMenu,
|
|
81
66
|
editorMenu,
|
|
82
|
-
|
|
83
|
-
type,
|
|
67
|
+
type: currentType,
|
|
84
68
|
currentSiteInfo,
|
|
85
69
|
isLoading,
|
|
86
70
|
isSaving,
|
|
@@ -89,17 +73,14 @@ const getStateValues = (getState: any) => {
|
|
|
89
73
|
};
|
|
90
74
|
|
|
91
75
|
function setEditorMenuContent(menus: IMenu[], menuType: string, dispatch: Dispatch) {
|
|
92
|
-
const menu
|
|
93
|
-
const currentMenu = generateEditorIDs(menu).pageContent;
|
|
94
|
-
const id = menu.id;
|
|
76
|
+
const menu = menus.find((menu) => menu.name === menuType) || menus[0];
|
|
95
77
|
|
|
96
|
-
dispatch(setId(id));
|
|
97
78
|
dispatch(setSavedMenu(menu));
|
|
98
|
-
dispatch(setEditorMenu(
|
|
79
|
+
dispatch(setEditorMenu(menu));
|
|
99
80
|
dispatch(setIsLoading(false));
|
|
100
81
|
}
|
|
101
82
|
|
|
102
|
-
function getMenus(): (dispatch: Dispatch, getState:
|
|
83
|
+
function getMenus(hasLoading = true): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
|
|
103
84
|
return async (dispatch, getState) => {
|
|
104
85
|
try {
|
|
105
86
|
const { currentSiteInfo, type } = getStateValues(getState);
|
|
@@ -108,27 +89,31 @@ function getMenus(): (dispatch: Dispatch, getState: any) => Promise<void> {
|
|
|
108
89
|
const responseActions = {
|
|
109
90
|
handleSuccess: (menus: IMenu[]) => {
|
|
110
91
|
dispatch(setSavedMenus(menus));
|
|
111
|
-
|
|
92
|
+
const current = type !== "" ? type : menus.length ? menus[0].name : "";
|
|
93
|
+
dispatch(setCurrentType(current));
|
|
94
|
+
setEditorMenuContent(menus, current, dispatch);
|
|
112
95
|
updateTotalItems(dispatch, getState);
|
|
113
96
|
},
|
|
114
|
-
handleError: () =>
|
|
97
|
+
handleError: (response: any) => appActions.handleError(response)(dispatch),
|
|
115
98
|
};
|
|
116
99
|
|
|
117
|
-
const callback = async () => await menus.getMenus(id);
|
|
100
|
+
const callback = async () => id && (await menus.getMenus(id));
|
|
101
|
+
|
|
102
|
+
const loading = hasLoading ? [appActions.setIsLoading] : [];
|
|
118
103
|
|
|
119
|
-
await handleRequest(callback, responseActions,
|
|
104
|
+
await handleRequest(callback, responseActions, loading)(dispatch);
|
|
120
105
|
} catch (e) {
|
|
121
106
|
console.log("Error", e);
|
|
122
107
|
}
|
|
123
108
|
};
|
|
124
109
|
}
|
|
125
110
|
|
|
126
|
-
function getCurrentMenu(menuType: string): (dispatch: Dispatch, getState:
|
|
111
|
+
function getCurrentMenu(menuType: string): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
|
|
127
112
|
return async (dispatch, getState) => {
|
|
128
113
|
try {
|
|
129
114
|
dispatch(setIsLoading(true));
|
|
130
115
|
const { savedMenus } = getStateValues(getState);
|
|
131
|
-
setEditorMenuContent(savedMenus, menuType, dispatch);
|
|
116
|
+
setEditorMenuContent(savedMenus || [], menuType, dispatch);
|
|
132
117
|
updateTotalItems(dispatch, getState);
|
|
133
118
|
} catch (e) {
|
|
134
119
|
console.log("Error", e);
|
|
@@ -137,9 +122,10 @@ function getCurrentMenu(menuType: string): (dispatch: Dispatch, getState: any) =
|
|
|
137
122
|
};
|
|
138
123
|
}
|
|
139
124
|
|
|
140
|
-
function addMenuItem(item: IMenuItem): (dispatch: Dispatch, getState:
|
|
125
|
+
function addMenuItem(item: IMenuItem): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
|
|
141
126
|
return async (dispatch, getState) => {
|
|
142
127
|
const { editorMenu } = getStateValues(getState);
|
|
128
|
+
if (!editorMenu) return;
|
|
143
129
|
const elements = editorMenu.elements || [];
|
|
144
130
|
const itemWithTemporaryId = { ...item, id: new Date().getTime() };
|
|
145
131
|
const menuElements = [...elements, itemWithTemporaryId];
|
|
@@ -151,9 +137,10 @@ function addMenuItem(item: IMenuItem): (dispatch: Dispatch, getState: any) => Pr
|
|
|
151
137
|
};
|
|
152
138
|
}
|
|
153
139
|
|
|
154
|
-
function updateMenuItem(updatedItem: IMenuItem): (dispatch: Dispatch, getState:
|
|
140
|
+
function updateMenuItem(updatedItem: IMenuItem): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
|
|
155
141
|
return async (dispatch, getState) => {
|
|
156
142
|
const { editorMenu } = getStateValues(getState);
|
|
143
|
+
if (!editorMenu) return;
|
|
157
144
|
|
|
158
145
|
const updateElements = (elements: IMenuItem[]): any => {
|
|
159
146
|
const hasUpdatedChild = elements.some((element) => element.editorID === updatedItem.editorID);
|
|
@@ -185,11 +172,12 @@ function updateMenuItem(updatedItem: IMenuItem): (dispatch: Dispatch, getState:
|
|
|
185
172
|
function deleteMenuItem(
|
|
186
173
|
deletedItemId: number,
|
|
187
174
|
deleteChildren = true
|
|
188
|
-
): (dispatch: Dispatch, getState:
|
|
175
|
+
): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
|
|
189
176
|
return async (dispatch, getState) => {
|
|
190
177
|
const { editorMenu } = getStateValues(getState);
|
|
178
|
+
if (!editorMenu) return;
|
|
191
179
|
|
|
192
|
-
const updateElements = (elements: IMenuItem[]): IMenuItem[]
|
|
180
|
+
const updateElements = (elements: IMenuItem[]): IMenuItem[] => {
|
|
193
181
|
const deletedItem = elements.find((element) => element.id === deletedItemId);
|
|
194
182
|
if (deletedItem) {
|
|
195
183
|
if (deleteChildren) {
|
|
@@ -211,6 +199,7 @@ function deleteMenuItem(
|
|
|
211
199
|
}
|
|
212
200
|
}
|
|
213
201
|
}
|
|
202
|
+
return [];
|
|
214
203
|
};
|
|
215
204
|
|
|
216
205
|
const updatedElements = updateElements([...editorMenu.elements]);
|
|
@@ -225,25 +214,21 @@ function deleteMenuItem(
|
|
|
225
214
|
};
|
|
226
215
|
}
|
|
227
216
|
|
|
228
|
-
function updateMenu(): (dispatch: Dispatch, getState:
|
|
217
|
+
function updateMenu(): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
|
|
229
218
|
return async (dispatch, getState) => {
|
|
230
219
|
try {
|
|
231
|
-
const { savedMenu, editorMenu
|
|
232
|
-
|
|
233
|
-
savedMenu.elements =
|
|
220
|
+
const { savedMenu, editorMenu } = getStateValues(getState);
|
|
221
|
+
if (!savedMenu || !editorMenu) return;
|
|
222
|
+
savedMenu.elements = editorMenu.elements;
|
|
234
223
|
|
|
235
224
|
const responseActions = {
|
|
236
225
|
handleSuccess: async () => {
|
|
237
|
-
|
|
238
|
-
const updatedMenusResponse = await menus.getMenus(currentSiteId);
|
|
239
|
-
const updatedMenus = updatedMenusResponse.data;
|
|
240
|
-
dispatch(setSavedMenus(updatedMenus));
|
|
241
|
-
setEditorMenuContent(updatedMenus, type, dispatch);
|
|
226
|
+
getMenus(false)(dispatch, getState);
|
|
242
227
|
},
|
|
243
|
-
handleError: () =>
|
|
228
|
+
handleError: (response: any) => appActions.handleError(response)(dispatch),
|
|
244
229
|
};
|
|
245
230
|
|
|
246
|
-
const callback = async () => menus.updateMenu(savedMenu, id);
|
|
231
|
+
const callback = async () => menus.updateMenu(savedMenu, savedMenu.id);
|
|
247
232
|
|
|
248
233
|
await handleRequest(callback, responseActions, [appActions.setIsSaving])(dispatch);
|
|
249
234
|
} catch (e) {
|
|
@@ -252,9 +237,10 @@ function updateMenu(): (dispatch: Dispatch, getState: any) => Promise<void> {
|
|
|
252
237
|
};
|
|
253
238
|
}
|
|
254
239
|
|
|
255
|
-
function reorderMenu(elements: IMenuItem[]): (dispatch: Dispatch, getState:
|
|
240
|
+
function reorderMenu(elements: IMenuItem[]): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
|
|
256
241
|
return async (dispatch, getState) => {
|
|
257
242
|
const { editorMenu } = getStateValues(getState);
|
|
243
|
+
if (!editorMenu) return;
|
|
258
244
|
|
|
259
245
|
const updatedMenu = {
|
|
260
246
|
...editorMenu,
|
|
@@ -271,7 +257,7 @@ function setItemValue(page: IMenuItem): (dispatch: Dispatch) => Promise<void> {
|
|
|
271
257
|
};
|
|
272
258
|
}
|
|
273
259
|
|
|
274
|
-
function updateFormValue(valueObj: any): (dispatch: Dispatch, getState:
|
|
260
|
+
function updateFormValue(valueObj: any): (dispatch: Dispatch, getState: () => IRootState) => void {
|
|
275
261
|
return (dispatch, getState) => {
|
|
276
262
|
const {
|
|
277
263
|
menu: { form },
|
|
@@ -290,12 +276,13 @@ function resetItemValues(): (dispatch: Dispatch) => Promise<void> {
|
|
|
290
276
|
|
|
291
277
|
const resetMenuValues = (dispatch: Dispatch) => {
|
|
292
278
|
dispatch(setSavedMenus([]));
|
|
293
|
-
dispatch(setEditorMenu(
|
|
279
|
+
dispatch(setEditorMenu(null));
|
|
294
280
|
dispatch(setMenuFormData(menuInitialState.form));
|
|
295
281
|
};
|
|
296
282
|
|
|
297
|
-
const updateTotalItems = (dispatch: Dispatch, getState:
|
|
283
|
+
const updateTotalItems = (dispatch: Dispatch, getState: () => IRootState) => {
|
|
298
284
|
const { editorMenu } = getState().menu;
|
|
285
|
+
if (!editorMenu) return;
|
|
299
286
|
|
|
300
287
|
let counter = 0;
|
|
301
288
|
const calculateItems = (elements: IMenuItem[]): void => {
|
|
@@ -314,7 +301,6 @@ const updateTotalItems = (dispatch: Dispatch, getState: any) => {
|
|
|
314
301
|
export {
|
|
315
302
|
setSavedMenus,
|
|
316
303
|
setEditorMenu,
|
|
317
|
-
setId,
|
|
318
304
|
setItem,
|
|
319
305
|
setEditorMenuContent,
|
|
320
306
|
getMenus,
|
|
@@ -328,4 +314,5 @@ export {
|
|
|
328
314
|
resetMenuValues,
|
|
329
315
|
reorderMenu,
|
|
330
316
|
updateFormValue,
|
|
317
|
+
setCurrentType,
|
|
331
318
|
};
|
|
@@ -3,8 +3,7 @@ export const NAME = "menu";
|
|
|
3
3
|
export const SET_ORIGINAL_MENUS = `${NAME}/SET_ORIGINAL_MENUS`;
|
|
4
4
|
export const SET_ORIGINAL_MENU = `${NAME}/SET_CURRENT_ORIGINAL_MENU`;
|
|
5
5
|
export const SET_EDITOR_MENU = `${NAME}/SET_EDITOR_MENU`;
|
|
6
|
-
export const SET_ID = `${NAME}/SET_ID`;
|
|
7
6
|
export const SET_ITEM = `${NAME}/SET_ITEM`;
|
|
8
7
|
export const SET_MENU_FORM_DATA = `${NAME}/SET_MENU_FORM_DATA`;
|
|
9
8
|
export const SET_TOTAL_ITEMS = `${NAME}/SET_TOTAL_ITEMS`;
|
|
10
|
-
export const
|
|
9
|
+
export const SET_CURRENT_TYPE = `${NAME}/SET_CURRENT_TYPE`;
|
|
@@ -1,42 +1,38 @@
|
|
|
1
|
+
import { IMenu, IMenuForm, IMenuItem } from "@ax/types";
|
|
2
|
+
|
|
1
3
|
import { SET_TOTAL_ITEMS } from "@ax/containers/Sites/constants";
|
|
2
4
|
import {
|
|
3
5
|
SET_ORIGINAL_MENUS,
|
|
4
6
|
SET_ORIGINAL_MENU,
|
|
5
7
|
SET_EDITOR_MENU,
|
|
6
|
-
SET_ID,
|
|
7
8
|
SET_ITEM,
|
|
8
9
|
SET_MENU_FORM_DATA,
|
|
9
|
-
|
|
10
|
+
SET_CURRENT_TYPE,
|
|
10
11
|
} from "./constants";
|
|
11
12
|
|
|
12
13
|
export interface ISetSavedMenus {
|
|
13
14
|
type: typeof SET_ORIGINAL_MENUS;
|
|
14
|
-
payload: { savedMenus:
|
|
15
|
+
payload: { savedMenus: IMenu[] };
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export interface ISetSavedMenu {
|
|
18
19
|
type: typeof SET_ORIGINAL_MENU;
|
|
19
|
-
payload: { savedMenu:
|
|
20
|
+
payload: { savedMenu: IMenu };
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export interface ISetEditorMenu {
|
|
23
24
|
type: typeof SET_EDITOR_MENU;
|
|
24
|
-
payload: { editorMenu:
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface ISetId {
|
|
28
|
-
type: typeof SET_ID;
|
|
29
|
-
payload: { id: number };
|
|
25
|
+
payload: { editorMenu: IMenu | null };
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
export interface ISetItem {
|
|
33
29
|
type: typeof SET_ITEM;
|
|
34
|
-
payload: { item:
|
|
30
|
+
payload: { item: IMenuItem | null };
|
|
35
31
|
}
|
|
36
32
|
|
|
37
33
|
export interface ISetMenuForm {
|
|
38
34
|
type: typeof SET_MENU_FORM_DATA;
|
|
39
|
-
payload: { form:
|
|
35
|
+
payload: { form: IMenuForm };
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
export interface ISetTotalItems {
|
|
@@ -44,9 +40,9 @@ export interface ISetTotalItems {
|
|
|
44
40
|
payload: { totalItems: number };
|
|
45
41
|
}
|
|
46
42
|
|
|
47
|
-
export interface
|
|
48
|
-
type: typeof
|
|
49
|
-
payload: {
|
|
43
|
+
export interface ISetCurrentType {
|
|
44
|
+
type: typeof SET_CURRENT_TYPE;
|
|
45
|
+
payload: { currentType: string };
|
|
50
46
|
}
|
|
51
47
|
|
|
52
48
|
export type MenuActionsCreators = ISetSavedMenus | ISetEditorMenu | ISetItem | ISetTotalItems;
|
|
@@ -2,32 +2,29 @@ import {
|
|
|
2
2
|
SET_ORIGINAL_MENUS,
|
|
3
3
|
SET_ORIGINAL_MENU,
|
|
4
4
|
SET_EDITOR_MENU,
|
|
5
|
-
SET_ID,
|
|
6
5
|
SET_ITEM,
|
|
7
6
|
SET_MENU_FORM_DATA,
|
|
8
7
|
SET_TOTAL_ITEMS,
|
|
8
|
+
SET_CURRENT_TYPE,
|
|
9
9
|
} from "./constants";
|
|
10
10
|
|
|
11
11
|
import { MenuActionsCreators } from "./interfaces";
|
|
12
|
-
import { IMenuItem, IMenuForm } from "@ax/types";
|
|
12
|
+
import { IMenuItem, IMenuForm, IMenu } from "@ax/types";
|
|
13
13
|
|
|
14
14
|
export interface IMenuState {
|
|
15
|
-
savedMenus:
|
|
16
|
-
savedMenu:
|
|
17
|
-
editorMenu:
|
|
18
|
-
id: number | null;
|
|
15
|
+
savedMenus: IMenu[] | null;
|
|
16
|
+
savedMenu: IMenu | null;
|
|
17
|
+
editorMenu: IMenu | null;
|
|
19
18
|
item: IMenuItem | null;
|
|
20
19
|
form: IMenuForm;
|
|
21
20
|
totalItems: number;
|
|
21
|
+
currentType: string;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const initialState = {
|
|
25
25
|
savedMenus: [],
|
|
26
|
-
savedMenu:
|
|
27
|
-
editorMenu:
|
|
28
|
-
elements: [],
|
|
29
|
-
},
|
|
30
|
-
id: null,
|
|
26
|
+
savedMenu: null,
|
|
27
|
+
editorMenu: null,
|
|
31
28
|
item: null,
|
|
32
29
|
form: {
|
|
33
30
|
url: null,
|
|
@@ -37,6 +34,7 @@ const initialState = {
|
|
|
37
34
|
footerStyle: "",
|
|
38
35
|
},
|
|
39
36
|
totalItems: 0,
|
|
37
|
+
currentType: "",
|
|
40
38
|
};
|
|
41
39
|
|
|
42
40
|
function reducer(state = initialState, action: MenuActionsCreators): IMenuState {
|
|
@@ -44,10 +42,10 @@ function reducer(state = initialState, action: MenuActionsCreators): IMenuState
|
|
|
44
42
|
case SET_ORIGINAL_MENUS:
|
|
45
43
|
case SET_ORIGINAL_MENU:
|
|
46
44
|
case SET_EDITOR_MENU:
|
|
47
|
-
case SET_ID:
|
|
48
45
|
case SET_ITEM:
|
|
49
46
|
case SET_MENU_FORM_DATA:
|
|
50
47
|
case SET_TOTAL_ITEMS:
|
|
48
|
+
case SET_CURRENT_TYPE:
|
|
51
49
|
return { ...state, ...action.payload };
|
|
52
50
|
default:
|
|
53
51
|
return state;
|
|
@@ -188,7 +188,7 @@ const mapDispatchToProps = {
|
|
|
188
188
|
|
|
189
189
|
const mapStateToProps = (state: IRootState) => ({
|
|
190
190
|
isLoading: state.app.isLoading,
|
|
191
|
-
editorMenu: state.menu.editorMenu
|
|
191
|
+
editorMenu: state.menu.editorMenu?.elements || [],
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
interface ITableStateProps {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useCallback
|
|
1
|
+
import React, { useEffect, useCallback } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
4
|
import { IGetSitePagesParams, IRootState, IMenuItem } from "@ax/types";
|
|
@@ -13,15 +13,12 @@ import Table from "./Table";
|
|
|
13
13
|
import * as S from "./style";
|
|
14
14
|
|
|
15
15
|
const List = (props: IMenuList): JSX.Element => {
|
|
16
|
-
const { getMenus, lang, getSitePages, currentSiteID, editorMenu, savedMenu,
|
|
16
|
+
const { getMenus, lang, getSitePages, currentSiteID, editorMenu, savedMenu, currentType, setCurrentType } = props;
|
|
17
17
|
|
|
18
18
|
if (!currentSiteID) {
|
|
19
19
|
throw new Error(`ERROR: User reached Menu List with null site info`);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const initialState = savedMenus && savedMenus.length ? savedMenus[0].name : "";
|
|
23
|
-
const [currentType, setCurrentType] = useState(initialState);
|
|
24
|
-
|
|
25
22
|
const { isDirty } = useShouldBeSaved(editorMenu, savedMenu, currentType);
|
|
26
23
|
const memoizedGetMenus = useCallback(() => getMenus(), [getMenus]);
|
|
27
24
|
const memoizedGetSitePages = useCallback(
|
|
@@ -41,7 +38,10 @@ const List = (props: IMenuList): JSX.Element => {
|
|
|
41
38
|
memoizedGetSitePages(params);
|
|
42
39
|
memoizedGetMenus();
|
|
43
40
|
setIsSavedData(true);
|
|
44
|
-
|
|
41
|
+
return () => {
|
|
42
|
+
setCurrentType("");
|
|
43
|
+
};
|
|
44
|
+
}, [memoizedGetMenus, memoizedGetSitePages, setCurrentType, lang.id, currentSiteID]);
|
|
45
45
|
|
|
46
46
|
return (
|
|
47
47
|
<S.ListWrapper>
|
|
@@ -56,14 +56,15 @@ const List = (props: IMenuList): JSX.Element => {
|
|
|
56
56
|
const mapStateToProps = (state: IRootState) => ({
|
|
57
57
|
currentSiteID: state.sites.currentSiteInfo && state.sites.currentSiteInfo.id,
|
|
58
58
|
lang: state.app.lang,
|
|
59
|
-
editorMenu: state.menu.editorMenu
|
|
60
|
-
savedMenu: state.menu.savedMenu
|
|
61
|
-
|
|
59
|
+
editorMenu: state.menu.editorMenu?.elements || [],
|
|
60
|
+
savedMenu: state.menu.savedMenu?.elements || [],
|
|
61
|
+
currentType: state.menu.currentType,
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
const mapDispatchToProps = {
|
|
65
65
|
getMenus: menuActions.getMenus,
|
|
66
66
|
getSitePages: sitesActions.getSitePages,
|
|
67
|
+
setCurrentType: menuActions.setCurrentType,
|
|
67
68
|
};
|
|
68
69
|
|
|
69
70
|
interface IStateProps {
|
|
@@ -71,12 +72,13 @@ interface IStateProps {
|
|
|
71
72
|
lang: { locale: string; id: number | null };
|
|
72
73
|
editorMenu: IMenuItem[] | undefined;
|
|
73
74
|
savedMenu: IMenuItem[] | undefined;
|
|
74
|
-
|
|
75
|
+
currentType: string;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
interface IDispatchProps {
|
|
78
79
|
getMenus(): void;
|
|
79
80
|
getSitePages(params: IGetSitePagesParams): Promise<void>;
|
|
81
|
+
setCurrentType(type: string): void;
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
type IMenuList = IStateProps & IDispatchProps;
|