@griddo/ax 11.1.7 → 11.1.9
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/config/jest/componentsMock.js +1456 -1449
- package/package.json +2 -2
- package/src/__tests__/components/Fields/TranslateButton/TranslateButton.test.tsx +27 -0
- package/src/__tests__/components/MainWrapper/AppBar/AppBar.test.tsx +16 -0
- package/src/api/checkgroups.tsx +22 -6
- package/src/api/forms.tsx +18 -2
- package/src/components/Fields/AsyncCheckGroup/index.tsx +17 -2
- package/src/components/Fields/FormCategorySelect/index.tsx +44 -0
- package/src/components/Fields/MultiCheckSelect/index.tsx +26 -21
- package/src/components/Fields/MultiCheckSelectGroup/index.tsx +13 -4
- package/src/components/Fields/index.tsx +2 -0
- package/src/components/FloatingMenu/index.tsx +2 -2
- package/src/components/Loading/style.tsx +7 -10
- package/src/components/MainWrapper/style.tsx +5 -1
- package/src/components/TableFilters/CategoryFilter/index.tsx +10 -5
- package/src/components/TableFilters/CheckGroupFilter/index.tsx +6 -10
- package/src/components/TableFilters/NameFilter/index.tsx +7 -6
- package/src/components/TableList/style.tsx +14 -9
- package/src/containers/Forms/actions.tsx +9 -3
- package/src/containers/Sites/actions.tsx +16 -7
- package/src/containers/Sites/constants.tsx +1 -0
- package/src/containers/Sites/interfaces.tsx +6 -0
- package/src/containers/Sites/reducer.tsx +6 -2
- package/src/containers/StructuredData/actions.tsx +5 -2
- package/src/containers/Users/actions.tsx +9 -3
- package/src/helpers/index.tsx +2 -0
- package/src/helpers/objects.tsx +15 -0
- package/src/helpers/schemas.tsx +2 -1
- package/src/hooks/content.tsx +3 -1
- package/src/modules/Forms/FormList/BulkHeader/TableHeader/index.tsx +99 -11
- package/src/modules/Forms/FormList/BulkHeader/TableHeader/style.tsx +5 -2
- package/src/modules/Forms/FormList/BulkHeader/index.tsx +15 -10
- package/src/modules/Forms/FormList/FormItem/index.tsx +22 -7
- package/src/modules/Forms/FormList/FormItem/style.tsx +2 -2
- package/src/modules/Forms/FormList/Summary/index.tsx +10 -4
- package/src/modules/Forms/FormList/Summary/style.tsx +3 -0
- package/src/modules/Forms/FormList/hooks.tsx +101 -0
- package/src/modules/Forms/FormList/index.tsx +140 -11
- package/src/modules/Forms/FormList/style.tsx +10 -1
- package/src/modules/Forms/FormsMenu/index.tsx +13 -4
- package/src/modules/Forms/utils.tsx +26 -0
- package/src/modules/PublicPreview/index.tsx +2 -1
- package/src/modules/Redirects/style.tsx +1 -1
- package/src/modules/Settings/ContentTypes/DataPacks/AddModal/Filter/index.tsx +2 -2
- package/src/modules/Sites/SitesList/hooks.tsx +4 -4
- package/src/modules/Sites/SitesList/index.tsx +26 -7
- package/src/modules/Sites/SitesList/style.tsx +4 -0
- package/src/modules/Sites/index.tsx +15 -17
- package/src/types/forms.tsx +1 -4
- package/src/types/index.tsx +1 -1
|
@@ -6,11 +6,11 @@ import { IQueryValue } from "@ax/types";
|
|
|
6
6
|
import * as S from "./style";
|
|
7
7
|
|
|
8
8
|
const NameFilter = (props: INameFilterProps): JSX.Element => {
|
|
9
|
-
const { sortItems, sortedState, urlSorting, pointer = "title" } = props;
|
|
9
|
+
const { sortItems, sortedState, urlSorting, title, pointer = "title" } = props;
|
|
10
10
|
const { isAscending, sortedByTitle, sortedByURL } = sortedState;
|
|
11
11
|
|
|
12
|
-
const sortByName = (isAscending: boolean) => sortItems([{ value: pointer, label: pointer}], isAscending);
|
|
13
|
-
const sortAscendingURL = () => sortItems([{ value: "slug", label: "slug"}], true);
|
|
12
|
+
const sortByName = (isAscending: boolean) => sortItems([{ value: pointer, label: pointer }], isAscending);
|
|
13
|
+
const sortAscendingURL = () => sortItems([{ value: "slug", label: "slug" }], true);
|
|
14
14
|
const sortAscendingName = () => sortByName(true);
|
|
15
15
|
const sortDescendingName = () => sortByName(false);
|
|
16
16
|
|
|
@@ -18,11 +18,11 @@ const NameFilter = (props: INameFilterProps): JSX.Element => {
|
|
|
18
18
|
isAscending ? <Icon name="FullArrowUp" size="16" /> : <Icon name="FullArrowDown" size="16" />;
|
|
19
19
|
const isActive = sortedByTitle || sortedByURL;
|
|
20
20
|
|
|
21
|
-
const
|
|
21
|
+
const headerTitle = title ? title : urlSorting ? "Name & URL" : "Name";
|
|
22
22
|
|
|
23
23
|
const Header = () => (
|
|
24
24
|
<S.NameHeader isActive={isActive} data-testid="name-filter-header">
|
|
25
|
-
{
|
|
25
|
+
{headerTitle}
|
|
26
26
|
<S.IconsWrapper>
|
|
27
27
|
{isActive ? (
|
|
28
28
|
<SortedStateArrow />
|
|
@@ -44,7 +44,7 @@ const NameFilter = (props: INameFilterProps): JSX.Element => {
|
|
|
44
44
|
<ListItem isSelected={sortedByTitle && !isAscending} onClick={sortDescendingName}>
|
|
45
45
|
Descendent
|
|
46
46
|
</ListItem>
|
|
47
|
-
{urlSorting && (
|
|
47
|
+
{!!urlSorting && (
|
|
48
48
|
<>
|
|
49
49
|
<ListTitle>URL Sorting</ListTitle>
|
|
50
50
|
<ListItem isSelected={sortedByURL} onClick={sortAscendingURL}>
|
|
@@ -61,6 +61,7 @@ export interface INameFilterProps {
|
|
|
61
61
|
sortItems(orderPointer: IQueryValue[], isAscendent: boolean): void;
|
|
62
62
|
urlSorting?: boolean;
|
|
63
63
|
pointer?: string;
|
|
64
|
+
title?: string;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
export default NameFilter;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import styled from "styled-components";
|
|
2
2
|
|
|
3
|
-
const TableList = styled.div<{overflow?: string}>`
|
|
3
|
+
const TableList = styled.div<{ overflow?: string }>`
|
|
4
4
|
width: 100%;
|
|
5
5
|
height: 100%;
|
|
6
6
|
overflow: ${(p) => p.overflow};
|
|
@@ -8,33 +8,38 @@ const TableList = styled.div<{overflow?: string}>`
|
|
|
8
8
|
|
|
9
9
|
const Table = styled.div`
|
|
10
10
|
width: 100%;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-flow: column;
|
|
13
|
+
height: 100%;
|
|
13
14
|
`;
|
|
14
15
|
|
|
15
|
-
const TableHeader = styled.div<{hasFixedHeader?: boolean}>`
|
|
16
|
+
const TableHeader = styled.div<{ hasFixedHeader?: boolean }>`
|
|
16
17
|
display: flex;
|
|
17
18
|
flex-direction: row;
|
|
18
19
|
width: 100%;
|
|
19
20
|
position: relative; /* fallback */
|
|
20
|
-
position: ${(p) => p.hasFixedHeader ? `sticky` : `relative`};
|
|
21
|
+
position: ${(p) => (p.hasFixedHeader ? `sticky` : `relative`)};
|
|
21
22
|
z-index: 6;
|
|
22
23
|
top: 0;
|
|
23
24
|
background: ${(p) => p.theme.color.uiBackground01};
|
|
24
25
|
`;
|
|
25
26
|
|
|
26
|
-
const Header = styled.div<{isActive?: boolean}>`
|
|
27
|
+
const Header = styled.div<{ isActive?: boolean }>`
|
|
27
28
|
${(p) => p.theme.textStyle.uiS};
|
|
29
|
+
position: relative;
|
|
28
30
|
box-sizing: border-box;
|
|
29
31
|
padding: ${(p) => ` 0 ${p.theme.spacing.s}`};
|
|
30
32
|
display: flex;
|
|
31
33
|
flex-flow: column wrap;
|
|
32
34
|
flex-direction: row;
|
|
33
|
-
color: ${(p) => p.isActive ? p.theme.color.textHighEmphasis : p.theme.color.textMediumEmphasis};
|
|
35
|
+
color: ${(p) => (p.isActive ? p.theme.color.textHighEmphasis : p.theme.color.textMediumEmphasis)};
|
|
34
36
|
`;
|
|
35
37
|
|
|
36
38
|
const TableBody = styled.div`
|
|
37
|
-
padding:
|
|
39
|
+
padding: ${(p) => `0 ${p.theme.spacing.m}`};
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-flow: column;
|
|
42
|
+
flex-grow: 1;
|
|
38
43
|
|
|
39
44
|
&.no-padding {
|
|
40
45
|
padding: 0;
|
|
@@ -95,5 +100,5 @@ export {
|
|
|
95
100
|
TransHeader,
|
|
96
101
|
SeoHeader,
|
|
97
102
|
ActionsHeader,
|
|
98
|
-
PaginationWrapper
|
|
103
|
+
PaginationWrapper,
|
|
99
104
|
};
|
|
@@ -379,7 +379,7 @@ function deleteForm(id: number | number[]): (dispatch: Dispatch, getState: any)
|
|
|
379
379
|
},
|
|
380
380
|
};
|
|
381
381
|
|
|
382
|
-
const callback = async () => (Array.isArray(id) ? forms.deleteFormBulk(id) : forms.deleteForm(id));
|
|
382
|
+
const callback = async () => (Array.isArray(id) ? await forms.deleteFormBulk(id) : await forms.deleteForm(id));
|
|
383
383
|
|
|
384
384
|
return await handleRequest(callback, responseActions, [])(dispatch);
|
|
385
385
|
} catch (e) {
|
|
@@ -389,10 +389,16 @@ function deleteForm(id: number | number[]): (dispatch: Dispatch, getState: any)
|
|
|
389
389
|
};
|
|
390
390
|
}
|
|
391
391
|
|
|
392
|
-
function updateFormState(
|
|
392
|
+
function updateFormState(
|
|
393
|
+
formID: number | number[],
|
|
394
|
+
state: FormState
|
|
395
|
+
): (dispatch: Dispatch, getState: any) => Promise<boolean> {
|
|
393
396
|
return async (dispatch, getState) => {
|
|
394
397
|
try {
|
|
395
|
-
const callback = async () =>
|
|
398
|
+
const callback = async () =>
|
|
399
|
+
Array.isArray(formID)
|
|
400
|
+
? await forms.updateFormStateBulk(formID, state)
|
|
401
|
+
: await forms.updateFormState(formID, state);
|
|
396
402
|
|
|
397
403
|
const responseActions = {
|
|
398
404
|
handleSuccess: () => {
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
SET_CONFIG,
|
|
18
18
|
SET_CURRENT_SEARCH,
|
|
19
19
|
SET_THEME_ELEMENTS,
|
|
20
|
+
SET_IS_SITES_LOADING,
|
|
20
21
|
} from "./constants";
|
|
21
22
|
|
|
22
23
|
import {
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
ISetConfig,
|
|
37
38
|
ISetCurrentSearch,
|
|
38
39
|
ISetThemeElements,
|
|
40
|
+
ISetIsSitesLoading,
|
|
39
41
|
} from "./interfaces";
|
|
40
42
|
|
|
41
43
|
import {
|
|
@@ -61,7 +63,7 @@ import { integrationsActions } from "@ax/containers/Integrations";
|
|
|
61
63
|
import { getDefaultTheme, getThemeElements, handleRequest, isReqOk, sortBy } from "@ax/helpers";
|
|
62
64
|
import { usersActions } from "@ax/containers/Users";
|
|
63
65
|
|
|
64
|
-
const {
|
|
66
|
+
const { setIsSaving, setLanguage } = appActions;
|
|
65
67
|
const { resetDefaultsValues, getDefaults } = navigationActions;
|
|
66
68
|
const { resetMenuValues } = menuActions;
|
|
67
69
|
const { getAnalytics } = analyticsActions;
|
|
@@ -132,6 +134,10 @@ function setThemeElements(themeElements: IThemeElements | null): ISetThemeElemen
|
|
|
132
134
|
return { type: SET_THEME_ELEMENTS, payload: { themeElements } };
|
|
133
135
|
}
|
|
134
136
|
|
|
137
|
+
function setIsSitesLoading(isSitesLoading: boolean): ISetIsSitesLoading {
|
|
138
|
+
return { type: SET_IS_SITES_LOADING, payload: { isSitesLoading } };
|
|
139
|
+
}
|
|
140
|
+
|
|
135
141
|
// TODO: hay que controlar que cuando da error la API borrar los sites ya guardados y sacar el error (ver los siguientes FIXME)
|
|
136
142
|
function getSites(params: IGetSitesParams = { recentSitesNumber: 7 }): (dispatch: Dispatch) => Promise<void> {
|
|
137
143
|
return async (dispatch) => {
|
|
@@ -146,7 +152,9 @@ function getSites(params: IGetSitesParams = { recentSitesNumber: 7 }): (dispatch
|
|
|
146
152
|
};
|
|
147
153
|
const callback = async () => sites.getAllSites(params);
|
|
148
154
|
|
|
149
|
-
|
|
155
|
+
const setIsLoading = setIsSitesLoading;
|
|
156
|
+
|
|
157
|
+
await handleRequest(callback, responseActions, [setIsLoading])(dispatch);
|
|
150
158
|
} catch (e) {
|
|
151
159
|
console.log(e);
|
|
152
160
|
}
|
|
@@ -255,7 +263,7 @@ function setSiteInfo(currentSiteInfo: ISite): (dispatch: any, getState: any) =>
|
|
|
255
263
|
structuredData: { categories: currentCategories },
|
|
256
264
|
} = getState();
|
|
257
265
|
|
|
258
|
-
dispatch(setIsLoading(true));
|
|
266
|
+
dispatch(appActions.setIsLoading(true));
|
|
259
267
|
|
|
260
268
|
resetSiteValues(currentSiteInfo.id)(dispatch);
|
|
261
269
|
dispatch(structuredDataActions.resetStructuredData());
|
|
@@ -374,7 +382,7 @@ function getSitePages(
|
|
|
374
382
|
): (dispatch: any) => Promise<void> {
|
|
375
383
|
return async (dispatch) => {
|
|
376
384
|
try {
|
|
377
|
-
dispatch(setIsLoading(true));
|
|
385
|
+
dispatch(appActions.setIsLoading(true));
|
|
378
386
|
const response: any = structuredData
|
|
379
387
|
? await sites.getStructuredSitePages(params, structuredData, filterQuery)
|
|
380
388
|
: await sites.getSitePages(params, filterQuery);
|
|
@@ -386,7 +394,7 @@ function getSitePages(
|
|
|
386
394
|
} else {
|
|
387
395
|
console.log("Error en getSitePages"); // FIXME: capturar errores mejor
|
|
388
396
|
}
|
|
389
|
-
dispatch(setIsLoading(false));
|
|
397
|
+
dispatch(appActions.setIsLoading(false));
|
|
390
398
|
} catch (e) {
|
|
391
399
|
console.log(e); // FIXME: capturar errores mejor
|
|
392
400
|
}
|
|
@@ -416,9 +424,9 @@ function getAllSitePages(params: IGetSitePagesParams): (dispatch: any) => Promis
|
|
|
416
424
|
function getSiteLanguages(siteID: number): (dispatch: any) => Promise<void> {
|
|
417
425
|
return async (dispatch) => {
|
|
418
426
|
try {
|
|
419
|
-
dispatch(setIsLoading(true));
|
|
427
|
+
dispatch(appActions.setIsLoading(true));
|
|
420
428
|
const response: any = await languages.getSiteLanguages(siteID);
|
|
421
|
-
dispatch(setIsLoading(false));
|
|
429
|
+
dispatch(appActions.setIsLoading(false));
|
|
422
430
|
if (isReqOk(response.status)) {
|
|
423
431
|
const siteLanguages = response.data.items;
|
|
424
432
|
|
|
@@ -785,4 +793,5 @@ export {
|
|
|
785
793
|
setListConfig,
|
|
786
794
|
getSite,
|
|
787
795
|
updateCurrentSearch,
|
|
796
|
+
setIsSitesLoading,
|
|
788
797
|
};
|
|
@@ -17,6 +17,7 @@ export const SET_CONTENT_FILTERS = `${NAME}/SET_CONTENT_FILTERS`;
|
|
|
17
17
|
export const SET_CONFIG = `${NAME}/SET_CONFIG`;
|
|
18
18
|
export const SET_CURRENT_SEARCH = `${NAME}/SET_CURRENT_SEARCH`;
|
|
19
19
|
export const SET_THEME_ELEMENTS = `${NAME}/SET_THEME_ELEMENTS`;
|
|
20
|
+
export const SET_IS_SITES_LOADING = `${NAME}/SET_IS_SITES_LOADING`;
|
|
20
21
|
|
|
21
22
|
export const ITEMS_PER_PAGE = 50;
|
|
22
23
|
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
SET_CONFIG,
|
|
17
17
|
SET_CURRENT_SEARCH,
|
|
18
18
|
SET_THEME_ELEMENTS,
|
|
19
|
+
SET_IS_SITES_LOADING,
|
|
19
20
|
} from "./constants";
|
|
20
21
|
import { IQueryValue, ISite, ISiteListConfig, IThemeElements } from "@ax/types";
|
|
21
22
|
|
|
@@ -104,4 +105,9 @@ export interface ISetThemeElements {
|
|
|
104
105
|
payload: { themeElements: IThemeElements | null };
|
|
105
106
|
}
|
|
106
107
|
|
|
108
|
+
export interface ISetIsSitesLoading {
|
|
109
|
+
type: typeof SET_IS_SITES_LOADING;
|
|
110
|
+
payload: { isSitesLoading: boolean };
|
|
111
|
+
}
|
|
112
|
+
|
|
107
113
|
export type SitesActionsCreators = ISetSitesAction & ISetCurrentSiteInfoAction;
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
SET_CONFIG,
|
|
17
17
|
SET_CURRENT_SEARCH,
|
|
18
18
|
SET_THEME_ELEMENTS,
|
|
19
|
+
SET_IS_SITES_LOADING,
|
|
19
20
|
} from "./constants";
|
|
20
21
|
|
|
21
22
|
import { ISite, IPage, ILanguage, ISiteListConfig, IQueryValue, IThemeElements } from "@ax/types";
|
|
@@ -40,13 +41,14 @@ export interface ISitesState {
|
|
|
40
41
|
config: ISiteListConfig;
|
|
41
42
|
currentSearch: string;
|
|
42
43
|
themeElements: IThemeElements | null;
|
|
44
|
+
isSitesLoading: boolean;
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
const config = {
|
|
47
|
+
const config: ISiteListConfig = {
|
|
46
48
|
displayRecentSites: false,
|
|
47
49
|
mode: "grid",
|
|
48
50
|
filter: "&order=lastAccess-desc",
|
|
49
|
-
filterValues: { order: "desc", liveStatus: "all" },
|
|
51
|
+
filterValues: { order: "desc", liveStatus: [{ value: "all", label: "All" }] },
|
|
50
52
|
sortedListStatus: {
|
|
51
53
|
isAscending: false,
|
|
52
54
|
sortedByDateCreated: false,
|
|
@@ -73,6 +75,7 @@ export const initialState = {
|
|
|
73
75
|
config,
|
|
74
76
|
currentSearch: "",
|
|
75
77
|
themeElements: null,
|
|
78
|
+
isSitesLoading: false,
|
|
76
79
|
};
|
|
77
80
|
|
|
78
81
|
export function reducer(state = initialState, action: any): ISitesState {
|
|
@@ -94,6 +97,7 @@ export function reducer(state = initialState, action: any): ISitesState {
|
|
|
94
97
|
case SET_CONFIG:
|
|
95
98
|
case SET_CURRENT_SEARCH:
|
|
96
99
|
case SET_THEME_ELEMENTS:
|
|
100
|
+
case SET_IS_SITES_LOADING:
|
|
97
101
|
return { ...state, ...action.payload };
|
|
98
102
|
default:
|
|
99
103
|
return state;
|
|
@@ -177,7 +177,8 @@ const filterStructuredData = (data: IStructuredData[], isTaxonomy: boolean, site
|
|
|
177
177
|
|
|
178
178
|
function getStructuredData(
|
|
179
179
|
token: string | null,
|
|
180
|
-
siteID?: number | null
|
|
180
|
+
siteID?: number | null,
|
|
181
|
+
hasLoading = true
|
|
181
182
|
): (dispatch: Dispatch, getState: any) => Promise<void> {
|
|
182
183
|
return async (dispatch, getState) => {
|
|
183
184
|
try {
|
|
@@ -205,7 +206,9 @@ function getStructuredData(
|
|
|
205
206
|
|
|
206
207
|
const callback = async () => structuredData.getData(token, siteID);
|
|
207
208
|
|
|
208
|
-
|
|
209
|
+
const loading = hasLoading === false ? [] : [appActions.setIsLoading];
|
|
210
|
+
|
|
211
|
+
await handleRequest(callback, responseActions, loading)(dispatch);
|
|
209
212
|
} catch (e) {
|
|
210
213
|
console.log(e);
|
|
211
214
|
}
|
|
@@ -64,7 +64,11 @@ function getUsers(params: any, siteID?: number | null): (dispatch: Dispatch) =>
|
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
function getUser(
|
|
67
|
+
function getUser(
|
|
68
|
+
id: string | number,
|
|
69
|
+
token?: string,
|
|
70
|
+
hasLoading = true
|
|
71
|
+
): (dispatch: Dispatch, getState: any) => Promise<void> {
|
|
68
72
|
return async (dispatch, getState) => {
|
|
69
73
|
try {
|
|
70
74
|
const callback = async () => users.getUser(id, token);
|
|
@@ -84,7 +88,9 @@ function getUser(id: string | number, token?: string): (dispatch: Dispatch, getS
|
|
|
84
88
|
handleError: (response: any) => appActions.handleError(response)(dispatch),
|
|
85
89
|
};
|
|
86
90
|
|
|
87
|
-
|
|
91
|
+
const loading = hasLoading === false ? [] : [appActions.setIsLoading];
|
|
92
|
+
|
|
93
|
+
await handleRequest(callback, responseActions, loading)(dispatch);
|
|
88
94
|
} catch (e) {
|
|
89
95
|
console.log(e); // TODO: capturar error bien
|
|
90
96
|
}
|
|
@@ -336,7 +342,7 @@ function getUserCurrentPermissions(): (dispatch: Dispatch, getState: any) => voi
|
|
|
336
342
|
});
|
|
337
343
|
}
|
|
338
344
|
dispatch(setCurrentPermissions(permissions));
|
|
339
|
-
if(!currentSiteInfo) {
|
|
345
|
+
if (!currentSiteInfo) {
|
|
340
346
|
dispatch(setGlobalPermissions(permissions));
|
|
341
347
|
}
|
|
342
348
|
};
|
package/src/helpers/index.tsx
CHANGED
package/src/helpers/objects.tsx
CHANGED
|
@@ -115,6 +115,20 @@ const encodeData = (data: Record<string, string | number | boolean>): string =>
|
|
|
115
115
|
.map((pair) => pair.map(encodeURIComponent).join("="))
|
|
116
116
|
.join("&");
|
|
117
117
|
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
119
|
+
const findObjectValue = (obj: Record<string, any>, key: string): any | undefined => {
|
|
120
|
+
if (!obj || typeof obj !== "object") return undefined;
|
|
121
|
+
if (key in obj) return obj[key];
|
|
122
|
+
|
|
123
|
+
for (const prop of Object.values(obj)) {
|
|
124
|
+
if (typeof prop === "object" && prop !== null) {
|
|
125
|
+
const foundValue = findObjectValue(prop, key);
|
|
126
|
+
if (foundValue) return foundValue;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return undefined;
|
|
130
|
+
};
|
|
131
|
+
|
|
118
132
|
export {
|
|
119
133
|
isEmptyObj,
|
|
120
134
|
deepClone,
|
|
@@ -129,4 +143,5 @@ export {
|
|
|
129
143
|
trimObject,
|
|
130
144
|
hasProps,
|
|
131
145
|
encodeData,
|
|
146
|
+
findObjectValue,
|
|
132
147
|
};
|
package/src/helpers/schemas.tsx
CHANGED
|
@@ -60,7 +60,8 @@ const getFormTemplate = (name: string) => formSchemas?.templates[name];
|
|
|
60
60
|
|
|
61
61
|
const getDefaultFormTemplate = (name: string) => formSchemas?.templates[name].default;
|
|
62
62
|
|
|
63
|
-
const getSchemaFormCategories = (): { label: string; value: string }[] =>
|
|
63
|
+
const getSchemaFormCategories = (): { label: string; value: string; featured?: boolean }[] =>
|
|
64
|
+
formSchemas?.categories || [];
|
|
64
65
|
|
|
65
66
|
const getTemplateThumbnails = (name: string, theme?: string) => {
|
|
66
67
|
if (!schemas.templates[name]?.thumbnails) return null;
|
package/src/hooks/content.tsx
CHANGED
|
@@ -2,7 +2,9 @@ import { useEffect, useState, useLayoutEffect } from "react";
|
|
|
2
2
|
import { IEmptyStateProps } from "@ax/types";
|
|
3
3
|
import { useWindowSize } from "./window";
|
|
4
4
|
|
|
5
|
-
const useCategoryColors = (
|
|
5
|
+
const useCategoryColors = (
|
|
6
|
+
categories?: string[]
|
|
7
|
+
): { categoryColors: Record<string, string>; addCategoryColors: (cats: string[]) => void } => {
|
|
6
8
|
const fixedColors = [
|
|
7
9
|
"#FFE695",
|
|
8
10
|
"#C1F0FF",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
CategoryFilter,
|
|
5
|
+
CheckField,
|
|
6
|
+
CheckGroupFilter,
|
|
7
|
+
NameFilter,
|
|
8
|
+
StatusFilter,
|
|
9
|
+
TableCounter,
|
|
10
|
+
Tooltip,
|
|
11
|
+
} from "@ax/components";
|
|
12
|
+
import { IFilterValue, IQueryValue } from "@ax/types";
|
|
5
13
|
|
|
6
14
|
import * as S from "./style";
|
|
7
15
|
|
|
@@ -12,12 +20,52 @@ const TableHeader = (props: IProps): JSX.Element => {
|
|
|
12
20
|
isScrolling,
|
|
13
21
|
sortItems,
|
|
14
22
|
filterItems,
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
sortedListStatus,
|
|
24
|
+
filterValues,
|
|
17
25
|
checkState,
|
|
18
26
|
setHoverCheck,
|
|
27
|
+
featuredCategory,
|
|
28
|
+
siteID,
|
|
19
29
|
} = props;
|
|
20
30
|
|
|
31
|
+
const statusFilters: IFilterValue[] = [
|
|
32
|
+
{
|
|
33
|
+
name: "all",
|
|
34
|
+
value: "all",
|
|
35
|
+
title: "All states",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "inactive",
|
|
39
|
+
value: "inactive",
|
|
40
|
+
title: "Inactive",
|
|
41
|
+
icon: "offline",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "active",
|
|
45
|
+
value: "active",
|
|
46
|
+
title: "Active",
|
|
47
|
+
icon: "active",
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const langfilters: IFilterValue[] = [
|
|
52
|
+
{
|
|
53
|
+
name: "all",
|
|
54
|
+
value: "all",
|
|
55
|
+
title: "All forms",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "only",
|
|
59
|
+
value: "only",
|
|
60
|
+
title: "Translated content",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "no",
|
|
64
|
+
value: "no",
|
|
65
|
+
title: "Not translated content",
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
|
|
21
69
|
return (
|
|
22
70
|
<S.TableHeader isScrolling={isScrolling}>
|
|
23
71
|
<S.CheckHeader>
|
|
@@ -34,11 +82,49 @@ const TableHeader = (props: IProps): JSX.Element => {
|
|
|
34
82
|
/>
|
|
35
83
|
</Tooltip>
|
|
36
84
|
</S.CheckHeader>
|
|
37
|
-
<S.NameWrapper>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
85
|
+
<S.NameWrapper>
|
|
86
|
+
<NameFilter sortItems={sortItems} sortedState={sortedListStatus} title="Form name" />
|
|
87
|
+
</S.NameWrapper>
|
|
88
|
+
{featuredCategory && (
|
|
89
|
+
<S.TypeHeader>
|
|
90
|
+
<CategoryFilter
|
|
91
|
+
filterItems={filterItems}
|
|
92
|
+
value={filterValues.type}
|
|
93
|
+
formCategory={featuredCategory}
|
|
94
|
+
siteID={siteID}
|
|
95
|
+
pointer="type"
|
|
96
|
+
/>
|
|
97
|
+
</S.TypeHeader>
|
|
98
|
+
)}
|
|
99
|
+
<S.UpdateHeader>
|
|
100
|
+
<StatusFilter sortItems={sortItems} sortedState={sortedListStatus} />
|
|
101
|
+
</S.UpdateHeader>
|
|
102
|
+
<S.StateHeader>
|
|
103
|
+
<CheckGroupFilter
|
|
104
|
+
filterItems={filterItems}
|
|
105
|
+
value={filterValues.state}
|
|
106
|
+
pointer="state"
|
|
107
|
+
label="State"
|
|
108
|
+
description="Live Filter"
|
|
109
|
+
initialState={["all"]}
|
|
110
|
+
selectAllOption="all"
|
|
111
|
+
filters={statusFilters}
|
|
112
|
+
menuPosition="left"
|
|
113
|
+
/>
|
|
114
|
+
</S.StateHeader>
|
|
115
|
+
<S.LangHeader>
|
|
116
|
+
<CheckGroupFilter
|
|
117
|
+
filterItems={filterItems}
|
|
118
|
+
value={filterValues.translated}
|
|
119
|
+
pointer="translated"
|
|
120
|
+
label="Lang"
|
|
121
|
+
description="Filter by Translations"
|
|
122
|
+
initialState={["all"]}
|
|
123
|
+
selectAllOption="all"
|
|
124
|
+
filters={langfilters}
|
|
125
|
+
menuPosition="right"
|
|
126
|
+
/>
|
|
127
|
+
</S.LangHeader>
|
|
42
128
|
<S.ActionsHeader>
|
|
43
129
|
<TableCounter totalItems={totalItems} />
|
|
44
130
|
</S.ActionsHeader>
|
|
@@ -49,12 +135,14 @@ const TableHeader = (props: IProps): JSX.Element => {
|
|
|
49
135
|
interface IProps {
|
|
50
136
|
totalItems: number;
|
|
51
137
|
isScrolling: boolean;
|
|
138
|
+
featuredCategory?: { value: string; label: string };
|
|
52
139
|
selectAllItems: () => void;
|
|
53
140
|
filterItems: (filterPointer: string, filtersSelected: IQueryValue[]) => void;
|
|
54
141
|
sortItems: (orderPointer: IQueryValue[], isAscending: boolean) => void;
|
|
55
|
-
|
|
56
|
-
|
|
142
|
+
sortedListStatus: { isAscending: boolean; sortedByTitle: boolean; sortedByDate: boolean };
|
|
143
|
+
filterValues: Record<string, IQueryValue[]>;
|
|
57
144
|
checkState: Record<string, boolean>;
|
|
145
|
+
siteID: number | null;
|
|
58
146
|
setHoverCheck: (state: boolean) => void;
|
|
59
147
|
}
|
|
60
148
|
|
|
@@ -17,6 +17,7 @@ const CheckHeader = styled(Header)`
|
|
|
17
17
|
const NameWrapper = styled(Header)`
|
|
18
18
|
flex-grow: 1;
|
|
19
19
|
position: relative;
|
|
20
|
+
padding-left: 0;
|
|
20
21
|
`;
|
|
21
22
|
|
|
22
23
|
const ActionsHeader = styled(Header)`
|
|
@@ -25,17 +26,19 @@ const ActionsHeader = styled(Header)`
|
|
|
25
26
|
`;
|
|
26
27
|
|
|
27
28
|
const TypeHeader = styled(Header)`
|
|
28
|
-
flex: 0 0
|
|
29
|
+
flex: 0 0 215px;
|
|
29
30
|
justify-content: center;
|
|
31
|
+
padding: 0;
|
|
30
32
|
`;
|
|
31
33
|
|
|
32
34
|
const UpdateHeader = styled(Header)`
|
|
33
35
|
flex: 0 0 170px;
|
|
34
36
|
justify-content: center;
|
|
37
|
+
padding: 0;
|
|
35
38
|
`;
|
|
36
39
|
|
|
37
40
|
const StateHeader = styled(Header)`
|
|
38
|
-
flex: 0 0
|
|
41
|
+
flex: 0 0 85px;
|
|
39
42
|
justify-content: center;
|
|
40
43
|
`;
|
|
41
44
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { BulkSelectionOptions } from "@ax/components";
|
|
3
|
-
import { IQueryValue
|
|
4
|
-
import { usePermission } from "@ax/hooks";
|
|
3
|
+
import { IQueryValue } from "@ax/types";
|
|
5
4
|
import TableHeader from "./TableHeader";
|
|
6
5
|
|
|
7
6
|
const BulkHeader = (props: IProps): JSX.Element => {
|
|
@@ -14,13 +13,14 @@ const BulkHeader = (props: IProps): JSX.Element => {
|
|
|
14
13
|
isScrolling,
|
|
15
14
|
sortItems,
|
|
16
15
|
filterItems,
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
sortedListStatus,
|
|
17
|
+
filterValues,
|
|
19
18
|
setHoverCheck,
|
|
19
|
+
featuredCategory,
|
|
20
|
+
bulkActions,
|
|
21
|
+
siteID,
|
|
20
22
|
} = props;
|
|
21
23
|
|
|
22
|
-
const bulkActions: any[] = [];
|
|
23
|
-
|
|
24
24
|
return showBulk ? (
|
|
25
25
|
<BulkSelectionOptions
|
|
26
26
|
checkState={checkState}
|
|
@@ -30,15 +30,17 @@ const BulkHeader = (props: IProps): JSX.Element => {
|
|
|
30
30
|
/>
|
|
31
31
|
) : (
|
|
32
32
|
<TableHeader
|
|
33
|
-
|
|
33
|
+
filterValues={filterValues}
|
|
34
34
|
totalItems={totalItems}
|
|
35
35
|
selectAllItems={selectAllItems}
|
|
36
36
|
filterItems={filterItems}
|
|
37
37
|
isScrolling={isScrolling}
|
|
38
38
|
sortItems={sortItems}
|
|
39
|
-
|
|
39
|
+
sortedListStatus={sortedListStatus}
|
|
40
40
|
setHoverCheck={setHoverCheck}
|
|
41
41
|
checkState={checkState}
|
|
42
|
+
featuredCategory={featuredCategory}
|
|
43
|
+
siteID={siteID}
|
|
42
44
|
/>
|
|
43
45
|
);
|
|
44
46
|
};
|
|
@@ -50,9 +52,12 @@ interface IProps {
|
|
|
50
52
|
selectAllItems: () => void;
|
|
51
53
|
totalItems: number;
|
|
52
54
|
isScrolling: boolean;
|
|
55
|
+
featuredCategory?: { value: string; label: string };
|
|
56
|
+
bulkActions: { icon: string; text: string; action: () => void }[];
|
|
53
57
|
sortItems: (orderPointer: IQueryValue[], isAscending: boolean) => void;
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
sortedListStatus: { isAscending: boolean; sortedByTitle: boolean; sortedByDate: boolean };
|
|
59
|
+
filterValues: Record<string, IQueryValue[]>;
|
|
60
|
+
siteID: number | null;
|
|
56
61
|
filterItems: (filterPointer: string, filtersSelected: IQueryValue[]) => void;
|
|
57
62
|
setHoverCheck: (state: boolean) => void;
|
|
58
63
|
}
|