@griddo/ax 11.10.41 → 11.10.42
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/griddo-config/index.js +1 -0
- package/package.json +2 -2
- package/src/components/BulkSelectionOptions/index.tsx +78 -28
- package/src/components/BulkSelectionOptions/style.tsx +7 -1
- package/src/components/BulkSelectionOptions/utils.tsx +25 -0
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/index.tsx +2 -2
- package/src/components/ConfigPanel/GlobalPageForm/index.tsx +14 -4
- package/src/components/ConfigPanel/index.tsx +6 -0
- package/src/components/Fields/ComponentArray/SameComponentArray/index.tsx +9 -9
- package/src/components/Fields/ReferenceField/ItemList/Item/index.tsx +5 -6
- package/src/components/Fields/ReferenceField/ItemList/Item/style.tsx +16 -10
- package/src/components/Fields/ReferenceField/ManualPanel/Item/index.tsx +3 -4
- package/src/components/Fields/ReferenceField/ManualPanel/Item/style.tsx +7 -1
- package/src/components/Fields/VisualUniqueSelection/ScrollableSelection/index.tsx +3 -3
- package/src/components/Fields/VisualUniqueSelection/index.tsx +2 -4
- package/src/components/FloatingMenu/index.tsx +5 -5
- package/src/components/Loader/components/SmallCircle.js +29 -0
- package/src/components/Loader/index.tsx +3 -2
- package/src/components/MainWrapper/AppBar/atoms.tsx +4 -6
- package/src/components/MainWrapper/AppBar/index.tsx +14 -12
- package/src/components/MainWrapper/AppBar/style.tsx +23 -18
- package/src/components/MainWrapper/index.tsx +3 -3
- package/src/components/OcassionalToast/index.tsx +1 -1
- package/src/components/OcassionalToast/style.tsx +6 -0
- package/src/components/PageFinder/SelectionListItem/index.tsx +5 -4
- package/src/components/PageFinder/SelectionListItem/style.tsx +7 -1
- package/src/components/PageFinder/index.tsx +1 -0
- package/src/constants/index.ts +27 -0
- package/src/forms/elements.tsx +8 -24
- package/src/forms/index.tsx +0 -2
- package/src/helpers/containerEvaluations.tsx +5 -0
- package/src/helpers/content.ts +35 -0
- package/src/helpers/index.tsx +91 -89
- package/src/helpers/strings.tsx +19 -0
- package/src/helpers/types.ts +1 -0
- package/src/hooks/forms.tsx +2 -1
- package/src/locales/en-US.ts +29 -0
- package/src/locales/es-ES.ts +29 -0
- package/src/locales/index.ts +11 -0
- package/src/modules/Categories/CategoriesList/BulkHeader/index.tsx +5 -0
- package/src/modules/Categories/CategoriesList/index.tsx +10 -4
- package/src/modules/Content/BulkHeader/index.tsx +11 -0
- package/src/modules/Content/PageItem/index.tsx +1 -0
- package/src/modules/Content/atoms.tsx +1 -1
- package/src/modules/Content/index.tsx +27 -2
- package/src/modules/FileDrive/BulkGridHeader/index.tsx +6 -1
- package/src/modules/FileDrive/BulkListHeader/index.tsx +5 -0
- package/src/modules/FileDrive/index.tsx +10 -0
- package/src/modules/Forms/FormCategoriesList/BulkHeader/index.tsx +15 -2
- package/src/modules/Forms/FormCategoriesList/index.tsx +8 -0
- package/src/modules/Forms/FormEditor/index.tsx +10 -1
- package/src/modules/Forms/FormList/BulkHeader/index.tsx +5 -0
- package/src/modules/Forms/FormList/index.tsx +12 -3
- package/src/modules/Forms/FormUseModal/FormUseItem/index.tsx +1 -2
- package/src/modules/Forms/FormUseModal/index.tsx +3 -3
- package/src/modules/GlobalEditor/index.tsx +1 -0
- package/src/modules/MediaGallery/BulkGridHeader/index.tsx +6 -1
- package/src/modules/MediaGallery/BulkListHeader/index.tsx +15 -2
- package/src/modules/MediaGallery/index.tsx +47 -36
- package/src/modules/Navigation/Defaults/BulkHeader/index.tsx +5 -0
- package/src/modules/Navigation/Defaults/index.tsx +26 -23
- package/src/modules/PageEditor/Editor/index.tsx +6 -0
- package/src/modules/PageEditor/index.tsx +52 -0
- package/src/modules/Redirects/BulkHeader/index.tsx +6 -1
- package/src/modules/Redirects/index.tsx +7 -2
- package/src/modules/Settings/Integrations/BulkHeader/index.tsx +5 -0
- package/src/modules/Settings/Integrations/index.tsx +7 -1
- package/src/modules/Sites/SitesList/ListView/BulkHeader/index.tsx +5 -0
- package/src/modules/Sites/SitesList/index.tsx +7 -2
- package/src/modules/StructuredData/Form/index.tsx +1 -0
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/index.tsx +5 -0
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/atoms.tsx +3 -2
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +17 -11
- package/src/modules/StructuredData/StructuredDataList/index.tsx +6 -0
- package/src/modules/Users/Roles/BulkHeader/index.tsx +5 -0
- package/src/modules/Users/Roles/index.tsx +6 -1
- package/src/modules/Users/UserList/BulkHeader/index.tsx +5 -0
- package/src/modules/Users/UserList/index.tsx +12 -7
- package/tsconfig.paths.json +4 -1
package/src/locales/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ItemLabel } from "@ax/constants";
|
|
2
|
+
|
|
1
3
|
import { enUS } from "./en-US";
|
|
2
4
|
import { esES } from "./es-ES";
|
|
3
5
|
|
|
@@ -8,4 +10,13 @@ const allLocales = {
|
|
|
8
10
|
"es-ES": esES,
|
|
9
11
|
} as const;
|
|
10
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Obtiene la traducción correcta basada en la cantidad.
|
|
15
|
+
* @param entry La entrada del objeto de locales
|
|
16
|
+
* @param count El número de elementos (por defecto 1)
|
|
17
|
+
*/
|
|
18
|
+
export const pluralize = (entry: ItemLabel, count: number = 1): string => {
|
|
19
|
+
return count === 1 ? entry.one : entry.other;
|
|
20
|
+
};
|
|
21
|
+
|
|
11
22
|
export const LOCALE = allLocales[currentLocale as keyof typeof allLocales];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BulkSelectionOptions } from "@ax/components";
|
|
2
|
+
import { itemLabel } from "@ax/constants";
|
|
2
3
|
import type { IBulkSelectedItems } from "@ax/hooks";
|
|
3
4
|
import type { IQueryValue } from "@ax/types";
|
|
4
5
|
|
|
@@ -17,6 +18,7 @@ const BulkHeader = (props: IProps): JSX.Element => {
|
|
|
17
18
|
filterValues,
|
|
18
19
|
setHoverCheck,
|
|
19
20
|
selectedItems,
|
|
21
|
+
isLoading,
|
|
20
22
|
} = props;
|
|
21
23
|
|
|
22
24
|
return showBulk ? (
|
|
@@ -26,6 +28,8 @@ const BulkHeader = (props: IProps): JSX.Element => {
|
|
|
26
28
|
selectItems={selectItems}
|
|
27
29
|
totalItems={totalItems}
|
|
28
30
|
selectedItems={selectedItems}
|
|
31
|
+
isLoading={isLoading}
|
|
32
|
+
itemLabel={itemLabel.CATEGORY}
|
|
29
33
|
/>
|
|
30
34
|
) : (
|
|
31
35
|
<TableHeader
|
|
@@ -52,6 +56,7 @@ interface IProps {
|
|
|
52
56
|
filterItems: (filterPointer: string, filtersSelected: IQueryValue[]) => void;
|
|
53
57
|
setHoverCheck: (state: boolean) => void;
|
|
54
58
|
selectedItems: IBulkSelectedItems;
|
|
59
|
+
isLoading: boolean;
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
export default BulkHeader;
|
|
@@ -46,9 +46,10 @@ import CategoryNav from "./CategoryNav";
|
|
|
46
46
|
import CategoryPanel from "./CategoryPanel";
|
|
47
47
|
import { buildTree, type FlattenedItem, flattenTree, getProjection, removeChildrenOf, setProperty } from "./helpers";
|
|
48
48
|
import { useFilterQuery } from "./hooks";
|
|
49
|
-
import * as S from "./style";
|
|
50
49
|
import { filterCategoriesAndGroups, getAllLangCategoriesIds } from "./utils";
|
|
51
50
|
|
|
51
|
+
import * as S from "./style";
|
|
52
|
+
|
|
52
53
|
const CategoriesList = (props: IProps): JSX.Element => {
|
|
53
54
|
const {
|
|
54
55
|
currentSiteID,
|
|
@@ -71,6 +72,7 @@ const CategoriesList = (props: IProps): JSX.Element => {
|
|
|
71
72
|
} = props;
|
|
72
73
|
|
|
73
74
|
const [isScrolling, setIsScrolling] = useState(false);
|
|
75
|
+
const [isBulkLoading, setIsBulkLoading] = useState(false);
|
|
74
76
|
const [deleteGroupCategories, setDeleteGroupCategories] = useState(false);
|
|
75
77
|
const [searchQuery, setSearchQuery] = useState<string>("");
|
|
76
78
|
const [items, setItems] = useState<TreeItem[]>(currentDataContent);
|
|
@@ -94,7 +96,7 @@ const CategoriesList = (props: IProps): JSX.Element => {
|
|
|
94
96
|
const currentCategories = categories[scope].sort(sortBy("title", false));
|
|
95
97
|
const isEmpty = currentDataContent && currentDataContent.length === 0;
|
|
96
98
|
const hasCategories = currentCategories.length > 0;
|
|
97
|
-
const categoryName =
|
|
99
|
+
const categoryName = currentStructuredData?.title || "";
|
|
98
100
|
const availableLanguages = currentSiteID ? siteLanguages : globalLangs;
|
|
99
101
|
const isTranslatable = currentStructuredData ? currentStructuredData.translate : true;
|
|
100
102
|
const indentationWidth = 35;
|
|
@@ -102,6 +104,7 @@ const CategoriesList = (props: IProps): JSX.Element => {
|
|
|
102
104
|
const flattenedItems = useMemo(() => {
|
|
103
105
|
const flattenedTree = flattenTree(items);
|
|
104
106
|
const collapsedItems = flattenedTree.reduce<number[]>(
|
|
107
|
+
// biome-ignore lint/performance/noAccumulatingSpread: TODO: fix this
|
|
105
108
|
(acc, { children, collapsed, id }) => (collapsed && children.length ? [...acc, id] : acc),
|
|
106
109
|
[],
|
|
107
110
|
);
|
|
@@ -197,6 +200,7 @@ const CategoriesList = (props: IProps): JSX.Element => {
|
|
|
197
200
|
: undefined;
|
|
198
201
|
|
|
199
202
|
const bulkDelete = async () => {
|
|
203
|
+
setIsBulkLoading(true);
|
|
200
204
|
const { groups, categories } = filterCategoriesAndGroups(currentDataContent);
|
|
201
205
|
const idsCatsToBeDeleted = getAllLangCategoriesIds(categories, selectedItems);
|
|
202
206
|
const idsGroupsToBeDeleted = getAllLangCategoriesIds(groups, selectedItems);
|
|
@@ -210,6 +214,7 @@ const CategoriesList = (props: IProps): JSX.Element => {
|
|
|
210
214
|
isDeleteOpen && toggleDeleteModal();
|
|
211
215
|
isGroupOpen && toggleGroupModal();
|
|
212
216
|
}
|
|
217
|
+
setIsBulkLoading(false);
|
|
213
218
|
};
|
|
214
219
|
|
|
215
220
|
const handleToggleDeleteModal = () => {
|
|
@@ -257,6 +262,7 @@ const CategoriesList = (props: IProps): JSX.Element => {
|
|
|
257
262
|
filterItems={filterItems}
|
|
258
263
|
setHoverCheck={setHoverCheck}
|
|
259
264
|
selectedItems={selectedItems}
|
|
265
|
+
isLoading={isBulkLoading}
|
|
260
266
|
/>
|
|
261
267
|
);
|
|
262
268
|
|
|
@@ -424,7 +430,7 @@ const CategoriesList = (props: IProps): JSX.Element => {
|
|
|
424
430
|
depth={id === activeId && projected ? projected.depth : depth}
|
|
425
431
|
indentationWidth={indentationWidth}
|
|
426
432
|
collapsed={Boolean(collapsed && children.length)}
|
|
427
|
-
onCollapse={children
|
|
433
|
+
onCollapse={children?.length ? () => handleCollapse(id) : undefined}
|
|
428
434
|
/>
|
|
429
435
|
);
|
|
430
436
|
})}
|
|
@@ -461,7 +467,7 @@ const CategoriesList = (props: IProps): JSX.Element => {
|
|
|
461
467
|
|
|
462
468
|
const mapStateToProps = (state: IRootState) => ({
|
|
463
469
|
categories: state.structuredData.categories,
|
|
464
|
-
currentSiteID: state.sites.currentSiteInfo
|
|
470
|
+
currentSiteID: state.sites.currentSiteInfo?.id ?? null,
|
|
465
471
|
siteLanguages: state.sites.currentSiteLanguages,
|
|
466
472
|
globalLangs: state.app.globalLangs,
|
|
467
473
|
currentDataContent: state.structuredData.currentDataCategory,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BulkSelectionOptions } from "@ax/components";
|
|
2
|
+
import { getContentItemLabel } from "@ax/helpers/content";
|
|
2
3
|
import type { IBulkSelectedItems } from "@ax/hooks";
|
|
3
4
|
import { usePermission } from "@ax/hooks";
|
|
4
5
|
import type { IColumn, IQueryValue } from "@ax/types";
|
|
@@ -31,6 +32,8 @@ const BulkHeader = (props: IProps): JSX.Element => {
|
|
|
31
32
|
exportAction,
|
|
32
33
|
setHoverCheck,
|
|
33
34
|
selectedItems,
|
|
35
|
+
isLoading,
|
|
36
|
+
checkFromPage,
|
|
34
37
|
} = props;
|
|
35
38
|
|
|
36
39
|
const isAllowedToDeletePage = usePermission("content.deletePages");
|
|
@@ -68,6 +71,12 @@ const BulkHeader = (props: IProps): JSX.Element => {
|
|
|
68
71
|
totalItems={totalItems}
|
|
69
72
|
exportAction={exportAction}
|
|
70
73
|
selectedItems={selectedItems}
|
|
74
|
+
isLoading={isLoading}
|
|
75
|
+
itemLabel={getContentItemLabel({
|
|
76
|
+
isPageContentType: checkFromPage,
|
|
77
|
+
isSimpleContentType: isStructuredData,
|
|
78
|
+
isStandardPage: !checkFromPage && !isStructuredData,
|
|
79
|
+
})}
|
|
71
80
|
/>
|
|
72
81
|
) : (
|
|
73
82
|
<TableHeader
|
|
@@ -116,6 +125,8 @@ interface IProps {
|
|
|
116
125
|
exportAction?(formats: (number | string)[]): void;
|
|
117
126
|
setHoverCheck: (state: boolean) => void;
|
|
118
127
|
selectedItems: IBulkSelectedItems;
|
|
128
|
+
isLoading: boolean;
|
|
129
|
+
checkFromPage: boolean;
|
|
119
130
|
}
|
|
120
131
|
|
|
121
132
|
export default BulkHeader;
|
|
@@ -300,6 +300,7 @@ const PageItem = (props: IPageItemProps): JSX.Element => {
|
|
|
300
300
|
onClick: handleDuplicatePage,
|
|
301
301
|
disabled: !modalState.title.trim() || !modalState.slug.trim() || isSaving,
|
|
302
302
|
};
|
|
303
|
+
|
|
303
304
|
const secondaryModalAction = { title: "Cancel", onClick: handleCloseDuplicate };
|
|
304
305
|
|
|
305
306
|
const currentLanguages = getCurrentPageLanguages();
|
|
@@ -210,6 +210,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
210
210
|
const [columnsState, setColumnsState] = useState(initialColumns);
|
|
211
211
|
|
|
212
212
|
const [isDeleting, setIsDeleting] = useState<boolean>(false);
|
|
213
|
+
const [isBulkLoading, setIsBulkLoading] = useState<boolean>(false);
|
|
213
214
|
|
|
214
215
|
const createPermission = isDataPrivate ? "content.createPrivateContentTypes" : "content.createPages";
|
|
215
216
|
const exportPermission = isDataPrivate ? "content.exportPrivateContentTypes" : "content.exportContentTypes";
|
|
@@ -491,6 +492,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
491
492
|
|
|
492
493
|
const bulkDelete = async () => {
|
|
493
494
|
let allPageVersions: number[] = [];
|
|
495
|
+
setIsBulkLoading(true); // se podría usar setIsDeleting pero por seguridad prefiero usar uno propio
|
|
494
496
|
setIsDeleting(true);
|
|
495
497
|
if (deleteAllVersions) {
|
|
496
498
|
const selectedPages = currentSitePages.filter((page) => selectedItems.all.includes(page.id));
|
|
@@ -516,6 +518,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
516
518
|
const previousPage = page - 1;
|
|
517
519
|
page > 1 && (isLastItem || allPageItemsSelected) ? setPage(previousPage) : getSiteContent();
|
|
518
520
|
unselectAllItems();
|
|
521
|
+
setIsBulkLoading(false);
|
|
519
522
|
setIsDeleting(false);
|
|
520
523
|
};
|
|
521
524
|
|
|
@@ -527,6 +530,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
527
530
|
};
|
|
528
531
|
|
|
529
532
|
const bulkPublishAction = async (isPublish: boolean) => {
|
|
533
|
+
setIsBulkLoading(true);
|
|
530
534
|
const { notPublished, published, drafts } = selectedItems;
|
|
531
535
|
|
|
532
536
|
if (drafts && drafts.length > 0) {
|
|
@@ -555,11 +559,30 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
555
559
|
|
|
556
560
|
getSiteContent();
|
|
557
561
|
unselectAllItems();
|
|
562
|
+
setIsBulkLoading(false);
|
|
558
563
|
};
|
|
559
564
|
|
|
560
|
-
const bulkPublish = () =>
|
|
565
|
+
const bulkPublish = () => {
|
|
566
|
+
if (isStructuredData) {
|
|
567
|
+
setIsBulkLoading(true);
|
|
568
|
+
setDataStatus(selectedItems.all, "undraft");
|
|
569
|
+
unselectAllItems();
|
|
570
|
+
setIsBulkLoading(false);
|
|
571
|
+
} else {
|
|
572
|
+
bulkPublishAction(true);
|
|
573
|
+
}
|
|
574
|
+
};
|
|
561
575
|
|
|
562
|
-
const bulkUnpublish = () =>
|
|
576
|
+
const bulkUnpublish = () => {
|
|
577
|
+
if (isStructuredData) {
|
|
578
|
+
setIsBulkLoading(true);
|
|
579
|
+
setDataStatus(selectedItems.all, "draft");
|
|
580
|
+
unselectAllItems();
|
|
581
|
+
setIsBulkLoading(false);
|
|
582
|
+
} else {
|
|
583
|
+
bulkPublishAction(false);
|
|
584
|
+
}
|
|
585
|
+
};
|
|
563
586
|
|
|
564
587
|
const sortItems = (orderPointer: IQueryValue[], isAscending: boolean) => {
|
|
565
588
|
setPage(firstPage);
|
|
@@ -600,6 +623,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
600
623
|
sortedListStatus={sortedListStatus}
|
|
601
624
|
filterItems={filterItems}
|
|
602
625
|
isEditable={isDataEditable}
|
|
626
|
+
isLoading={isBulkLoading}
|
|
603
627
|
filterValues={filterValues}
|
|
604
628
|
categoryColumns={categoryColumns}
|
|
605
629
|
columns={columnsState}
|
|
@@ -610,6 +634,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
610
634
|
exportAction={exportContent}
|
|
611
635
|
setHoverCheck={setHoverCheck}
|
|
612
636
|
selectedItems={selectedItems}
|
|
637
|
+
checkFromPage={checkFromPage}
|
|
613
638
|
/>
|
|
614
639
|
);
|
|
615
640
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { itemLabel } from "@ax/constants";
|
|
1
2
|
import type { IBulkSelectedItems } from "@ax/hooks";
|
|
2
3
|
import type { IBulkAction } from "@ax/types";
|
|
3
4
|
|
|
@@ -6,7 +7,8 @@ import GridHeader from "./GridHeader";
|
|
|
6
7
|
import * as S from "./style";
|
|
7
8
|
|
|
8
9
|
const BulkGridHeader = (props: IBulkHeaderProps): JSX.Element => {
|
|
9
|
-
const { showBulk, checkState, selectItems, selectAllItems, totalItems, bulkActions, selectedItems } =
|
|
10
|
+
const { showBulk, checkState, selectItems, selectAllItems, totalItems, bulkActions, selectedItems, isLoading } =
|
|
11
|
+
props;
|
|
10
12
|
|
|
11
13
|
return showBulk ? (
|
|
12
14
|
<S.BulkWrapper>
|
|
@@ -17,6 +19,8 @@ const BulkGridHeader = (props: IBulkHeaderProps): JSX.Element => {
|
|
|
17
19
|
selectItems={selectItems}
|
|
18
20
|
totalItems={totalItems}
|
|
19
21
|
selectedItems={selectedItems}
|
|
22
|
+
isLoading={isLoading}
|
|
23
|
+
itemLabel={itemLabel.FILE}
|
|
20
24
|
/>
|
|
21
25
|
</S.BulkWrapper>
|
|
22
26
|
) : (
|
|
@@ -32,6 +36,7 @@ export interface IBulkHeaderProps {
|
|
|
32
36
|
totalItems: number;
|
|
33
37
|
bulkActions: IBulkAction[];
|
|
34
38
|
selectedItems: IBulkSelectedItems;
|
|
39
|
+
isLoading: boolean;
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
export default BulkGridHeader;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { itemLabel } from "@ax/constants";
|
|
1
2
|
import type { IBulkSelectedItems } from "@ax/hooks";
|
|
2
3
|
import type { IBulkAction } from "@ax/types";
|
|
3
4
|
|
|
@@ -16,6 +17,7 @@ const BulkListHeader = (props: IBulkHeaderProps): JSX.Element => {
|
|
|
16
17
|
isSearching,
|
|
17
18
|
setHoverCheck,
|
|
18
19
|
selectedItems,
|
|
20
|
+
isLoading,
|
|
19
21
|
} = props;
|
|
20
22
|
|
|
21
23
|
return showBulk ? (
|
|
@@ -27,6 +29,8 @@ const BulkListHeader = (props: IBulkHeaderProps): JSX.Element => {
|
|
|
27
29
|
selectItems={selectItems}
|
|
28
30
|
totalItems={totalItems}
|
|
29
31
|
selectedItems={selectedItems}
|
|
32
|
+
isLoading={isLoading}
|
|
33
|
+
itemLabel={itemLabel.FILE}
|
|
30
34
|
/>
|
|
31
35
|
</S.BulkWrapper>
|
|
32
36
|
) : (
|
|
@@ -51,6 +55,7 @@ export interface IBulkHeaderProps {
|
|
|
51
55
|
isSearching: boolean;
|
|
52
56
|
setHoverCheck: (state: boolean) => void;
|
|
53
57
|
selectedItems: IBulkSelectedItems;
|
|
58
|
+
isLoading: boolean;
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
export default BulkListHeader;
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
} from "@ax/components";
|
|
22
22
|
import { fileDriveActions } from "@ax/containers/FileDrive";
|
|
23
23
|
import { useBulkSelection, useIsDirty, useModal, usePermission, useResizable, useToast } from "@ax/hooks";
|
|
24
|
+
import { LOCALE, pluralize } from "@ax/locales";
|
|
24
25
|
import type {
|
|
25
26
|
IBulkAction,
|
|
26
27
|
IFile,
|
|
@@ -78,6 +79,7 @@ const FileDrive = (props: IProps) => {
|
|
|
78
79
|
folders,
|
|
79
80
|
} = currentFolderContent || { files: { totalItems: 0, items: [] }, folders: [] };
|
|
80
81
|
|
|
82
|
+
const [isBulkLoading, setIsBulkLoading] = useState(false);
|
|
81
83
|
const [isPanelOpen, setPanelOpen] = useState(false);
|
|
82
84
|
const [fileSelected, setFileSelected] = useState<IFile | null>(null);
|
|
83
85
|
const [selectedFolder, setSelectedFolder] = useState<number>(currentFolderID || 0);
|
|
@@ -341,6 +343,7 @@ const FileDrive = (props: IProps) => {
|
|
|
341
343
|
};
|
|
342
344
|
|
|
343
345
|
const handleBulkDeleteFile = async () => {
|
|
346
|
+
setIsBulkLoading(true);
|
|
344
347
|
const isDeleted = await deleteFile(selectedItems.all, siteID);
|
|
345
348
|
if (isDeleted) {
|
|
346
349
|
setNumDocs(selectedItems.all.length);
|
|
@@ -348,6 +351,7 @@ const FileDrive = (props: IProps) => {
|
|
|
348
351
|
toggleDeleteToast();
|
|
349
352
|
resetBulkSelection();
|
|
350
353
|
}
|
|
354
|
+
setIsBulkLoading(false);
|
|
351
355
|
};
|
|
352
356
|
|
|
353
357
|
const handleMoveFile = async (fileID: number, folderID: number) => {
|
|
@@ -359,6 +363,7 @@ const FileDrive = (props: IProps) => {
|
|
|
359
363
|
};
|
|
360
364
|
|
|
361
365
|
const handleBulkMoveFile = async () => {
|
|
366
|
+
setIsBulkLoading(true);
|
|
362
367
|
const isMoved = await moveFile(selectedItems.all, selectedFolder, siteID);
|
|
363
368
|
if (isMoved) {
|
|
364
369
|
setNumDocs(selectedItems.all.length);
|
|
@@ -367,6 +372,7 @@ const FileDrive = (props: IProps) => {
|
|
|
367
372
|
setSelectedFolder(0);
|
|
368
373
|
resetBulkSelection();
|
|
369
374
|
}
|
|
375
|
+
setIsBulkLoading(false);
|
|
370
376
|
};
|
|
371
377
|
|
|
372
378
|
const handleBulkEditFile = () => {
|
|
@@ -392,8 +398,10 @@ const FileDrive = (props: IProps) => {
|
|
|
392
398
|
};
|
|
393
399
|
|
|
394
400
|
const handleDownloadBulk = async () => {
|
|
401
|
+
setIsBulkLoading(true);
|
|
395
402
|
await downloadFiles(selectedItems.all, true);
|
|
396
403
|
resetBulkSelection();
|
|
404
|
+
setIsBulkLoading(false);
|
|
397
405
|
};
|
|
398
406
|
|
|
399
407
|
const handleUpdateCurrentFolder = (folderID: number | null) => {
|
|
@@ -460,6 +468,7 @@ const FileDrive = (props: IProps) => {
|
|
|
460
468
|
isSearching={isSearching}
|
|
461
469
|
setHoverCheck={setHoverCheck}
|
|
462
470
|
selectedItems={selectedItems}
|
|
471
|
+
isLoading={isBulkLoading}
|
|
463
472
|
/>
|
|
464
473
|
);
|
|
465
474
|
|
|
@@ -713,6 +722,7 @@ const FileDrive = (props: IProps) => {
|
|
|
713
722
|
selectItems={selectItems}
|
|
714
723
|
bulkActions={bulkActions}
|
|
715
724
|
selectedItems={selectedItems}
|
|
725
|
+
isLoading={isBulkLoading}
|
|
716
726
|
/>
|
|
717
727
|
)}
|
|
718
728
|
{!hasFolders && isRoot && !isSearching && <NewFolderButton />}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { itemLabel } from "@ax/constants";
|
|
1
2
|
import type { IBulkSelectedItems } from "@ax/hooks";
|
|
2
3
|
|
|
3
4
|
import TableHeader from "./TableHeader";
|
|
@@ -5,8 +6,17 @@ import TableHeader from "./TableHeader";
|
|
|
5
6
|
import * as S from "./style";
|
|
6
7
|
|
|
7
8
|
const BulkHeader = (props: IProps): JSX.Element => {
|
|
8
|
-
const {
|
|
9
|
-
|
|
9
|
+
const {
|
|
10
|
+
showBulk,
|
|
11
|
+
checkState,
|
|
12
|
+
selectItems,
|
|
13
|
+
totalItems,
|
|
14
|
+
isScrolling,
|
|
15
|
+
bulkActions,
|
|
16
|
+
setHoverCheck,
|
|
17
|
+
selectedItems,
|
|
18
|
+
isLoading,
|
|
19
|
+
} = props;
|
|
10
20
|
|
|
11
21
|
return showBulk ? (
|
|
12
22
|
<S.StyledBulkSelectionOptions
|
|
@@ -15,6 +25,8 @@ const BulkHeader = (props: IProps): JSX.Element => {
|
|
|
15
25
|
selectItems={selectItems}
|
|
16
26
|
totalItems={totalItems}
|
|
17
27
|
selectedItems={selectedItems}
|
|
28
|
+
isLoading={isLoading}
|
|
29
|
+
itemLabel={itemLabel.CATEGORY}
|
|
18
30
|
/>
|
|
19
31
|
) : (
|
|
20
32
|
<TableHeader
|
|
@@ -36,6 +48,7 @@ interface IProps {
|
|
|
36
48
|
bulkActions: { icon: string; text: string; action: () => void }[];
|
|
37
49
|
setHoverCheck: (state: boolean) => void;
|
|
38
50
|
selectedItems: IBulkSelectedItems;
|
|
51
|
+
isLoading: boolean;
|
|
39
52
|
}
|
|
40
53
|
|
|
41
54
|
export default BulkHeader;
|
|
@@ -25,6 +25,7 @@ import { DeleteModal } from "./atoms";
|
|
|
25
25
|
import BulkHeader from "./BulkHeader";
|
|
26
26
|
import CategoryItem from "./CategoryItem";
|
|
27
27
|
import CategoryPanel from "./CategoryPanel";
|
|
28
|
+
|
|
28
29
|
import * as S from "./style";
|
|
29
30
|
|
|
30
31
|
const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
@@ -41,6 +42,7 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
41
42
|
const isSiteView = !!currentSiteID;
|
|
42
43
|
|
|
43
44
|
const [isScrolling, setIsScrolling] = useState(false);
|
|
45
|
+
const [isBulkLoading, setIsBulkLoading] = useState(false);
|
|
44
46
|
const [draggingId, setDraggingId] = useState<number | null>(null);
|
|
45
47
|
const [searchQuery, setSearchQuery] = useState<string>("");
|
|
46
48
|
const { isVisible, toggleToast, setIsVisible, state: toastState } = useToast();
|
|
@@ -100,10 +102,14 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
100
102
|
: undefined;
|
|
101
103
|
|
|
102
104
|
const bulkDelete = async () => {
|
|
105
|
+
setIsBulkLoading(true);
|
|
103
106
|
const deleted = await deleteFormCategory(selectedItems.all, category);
|
|
104
107
|
if (deleted) {
|
|
108
|
+
resetBulkSelection();
|
|
109
|
+
toggleToast(`${selectedItems.all.length} categor${selectedItems.all.length > 1 ? "ies" : "y"} deleted`);
|
|
105
110
|
toggleDeleteModal();
|
|
106
111
|
}
|
|
112
|
+
setIsBulkLoading(false);
|
|
107
113
|
};
|
|
108
114
|
|
|
109
115
|
const selectItems = () => (checkState.isAllSelected ? resetBulkSelection() : selectAllItems());
|
|
@@ -135,6 +141,7 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
135
141
|
isScrolling={isScrolling}
|
|
136
142
|
bulkActions={bulkActions}
|
|
137
143
|
setHoverCheck={setHoverCheck}
|
|
144
|
+
isLoading={isBulkLoading}
|
|
138
145
|
/>
|
|
139
146
|
);
|
|
140
147
|
|
|
@@ -260,6 +267,7 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
260
267
|
|
|
261
268
|
const mapStateToProps = (state: IRootState) => ({
|
|
262
269
|
categories: state.forms.currentFormCategories,
|
|
270
|
+
// biome-ignore lint/complexity/useOptionalChain: TODO: fix this
|
|
263
271
|
currentSiteID: state.sites.currentSiteInfo && state.sites.currentSiteInfo.id,
|
|
264
272
|
});
|
|
265
273
|
|
|
@@ -90,7 +90,15 @@ const FormEditor = (props: IProps) => {
|
|
|
90
90
|
const isAllowedToDeleteForm = usePermission(deleteFormPermission);
|
|
91
91
|
const isAllowedToPublishForm = usePermission(publishFormPermission);
|
|
92
92
|
|
|
93
|
-
const toastMsg =
|
|
93
|
+
const toastMsg = (
|
|
94
|
+
<>
|
|
95
|
+
This form is used in some pages. Changes will apply to all pages where it’s{" "}
|
|
96
|
+
<button type="button" onClick={toggleUseModal}>
|
|
97
|
+
in use.
|
|
98
|
+
</button>
|
|
99
|
+
</>
|
|
100
|
+
);
|
|
101
|
+
|
|
94
102
|
const backLinkRoute = isSiteView ? "/sites/forms" : "/forms";
|
|
95
103
|
const { defaultTheme: theme } = useDefaultTheme();
|
|
96
104
|
|
|
@@ -293,6 +301,7 @@ const FormEditor = (props: IProps) => {
|
|
|
293
301
|
isDirty={isDirty}
|
|
294
302
|
errors={errors}
|
|
295
303
|
errorActions={{ goToError }}
|
|
304
|
+
isSaving={isSaving}
|
|
296
305
|
>
|
|
297
306
|
{notification && (
|
|
298
307
|
<S.NotificationWrapper>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BulkSelectionOptions } from "@ax/components";
|
|
2
|
+
import { itemLabel } from "@ax/constants";
|
|
2
3
|
import type { IBulkSelectedItems } from "@ax/hooks";
|
|
3
4
|
import type { IQueryValue } from "@ax/types";
|
|
4
5
|
|
|
@@ -21,6 +22,7 @@ const BulkHeader = (props: IProps): JSX.Element => {
|
|
|
21
22
|
featuredCategory,
|
|
22
23
|
bulkActions,
|
|
23
24
|
siteID,
|
|
25
|
+
isLoading,
|
|
24
26
|
} = props;
|
|
25
27
|
|
|
26
28
|
return showBulk ? (
|
|
@@ -30,6 +32,8 @@ const BulkHeader = (props: IProps): JSX.Element => {
|
|
|
30
32
|
selectItems={selectItems}
|
|
31
33
|
totalItems={totalItems}
|
|
32
34
|
selectedItems={selectedItems}
|
|
35
|
+
isLoading={isLoading}
|
|
36
|
+
itemLabel={itemLabel.FORM}
|
|
33
37
|
/>
|
|
34
38
|
) : (
|
|
35
39
|
<TableHeader
|
|
@@ -64,6 +68,7 @@ interface IProps {
|
|
|
64
68
|
filterItems: (filterPointer: string, filtersSelected: IQueryValue[]) => void;
|
|
65
69
|
setHoverCheck: (state: boolean) => void;
|
|
66
70
|
selectedItems: IBulkSelectedItems;
|
|
71
|
+
isLoading: boolean;
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
export default BulkHeader;
|
|
@@ -16,6 +16,7 @@ import { formsActions } from "@ax/containers/Forms";
|
|
|
16
16
|
import { ITEMS_PER_PAGE } from "@ax/containers/Forms/constants";
|
|
17
17
|
import { getFormTemplates, getSchemaFormCategories } from "@ax/helpers";
|
|
18
18
|
import { useBulkSelection, useCategoryColors, useModal, usePermission, useToast } from "@ax/hooks";
|
|
19
|
+
import { LOCALE, pluralize } from "@ax/locales";
|
|
19
20
|
import type {
|
|
20
21
|
FormContent,
|
|
21
22
|
FormState,
|
|
@@ -35,9 +36,10 @@ import BulkHeader from "./BulkHeader";
|
|
|
35
36
|
import FormItem from "./FormItem";
|
|
36
37
|
import { useFilterQuery, useSortedListStatus } from "./hooks";
|
|
37
38
|
import Summary from "./Summary";
|
|
38
|
-
import * as S from "./style";
|
|
39
39
|
import { TemplateModal } from "./TemplateModal";
|
|
40
40
|
|
|
41
|
+
import * as S from "./style";
|
|
42
|
+
|
|
41
43
|
const FormList = (props: IUserListProps): JSX.Element => {
|
|
42
44
|
const {
|
|
43
45
|
currentSiteInfo,
|
|
@@ -70,6 +72,7 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
70
72
|
|
|
71
73
|
const [page, setPage] = useState(firstPage);
|
|
72
74
|
const [isScrolling, setIsScrolling] = useState(false);
|
|
75
|
+
const [isBulkLoading, setIsBulkLoading] = useState(false);
|
|
73
76
|
const [selectedTemplate, setSelectedTemplate] = useState<ISchema | null>(null);
|
|
74
77
|
const [deleteAllVersions, setDeleteAllVersions] = useState(false);
|
|
75
78
|
const [arePagesTranslated, setArePagesTranslated] = useState(false);
|
|
@@ -175,14 +178,17 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
175
178
|
};
|
|
176
179
|
|
|
177
180
|
const publishForm = async () => {
|
|
181
|
+
setIsBulkLoading(true);
|
|
178
182
|
const isUpdated = await updateFormState(selectedItems.all, "active");
|
|
179
183
|
if (isUpdated) {
|
|
180
184
|
resetBulkSelection();
|
|
181
185
|
toggleToast(`${selectedItems.all.length} form${selectedItems.all.length > 1 ? "s" : ""} published`);
|
|
182
186
|
}
|
|
187
|
+
setIsBulkLoading(false);
|
|
183
188
|
};
|
|
184
189
|
|
|
185
190
|
const unpublishForm = async () => {
|
|
191
|
+
setIsBulkLoading(true);
|
|
186
192
|
const isUsed = forms.some((form) => selectedItems.all.includes(form.id) && !!form.formInUse);
|
|
187
193
|
if (isUsed) {
|
|
188
194
|
setNotification({
|
|
@@ -197,9 +203,11 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
197
203
|
}
|
|
198
204
|
}
|
|
199
205
|
isUnpublishOpen && toggleUnpublishModal();
|
|
206
|
+
setIsBulkLoading(false);
|
|
200
207
|
};
|
|
201
208
|
|
|
202
209
|
const handleDeleteForm = async () => {
|
|
210
|
+
setIsBulkLoading(true);
|
|
203
211
|
const idsToBeDeleted = getAllLangFormsIds(forms, selectedItems.all, deleteAllVersions);
|
|
204
212
|
const isUsed = forms.some((form) => idsToBeDeleted.includes(form.id) && !!form.formInUse);
|
|
205
213
|
if (isUsed) {
|
|
@@ -214,6 +222,7 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
214
222
|
}
|
|
215
223
|
}
|
|
216
224
|
isDeleteOpen && toggleDeleteModal();
|
|
225
|
+
setIsBulkLoading(false);
|
|
217
226
|
};
|
|
218
227
|
|
|
219
228
|
const handleToggleBulkDelete = () => {
|
|
@@ -269,6 +278,7 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
269
278
|
featuredCategory={featuredCategory}
|
|
270
279
|
bulkActions={bulkActions}
|
|
271
280
|
siteID={currentSiteInfo?.id || null}
|
|
281
|
+
isLoading={isBulkLoading}
|
|
272
282
|
/>
|
|
273
283
|
);
|
|
274
284
|
|
|
@@ -378,8 +388,7 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
378
388
|
)}
|
|
379
389
|
</S.EmptyWrapper>
|
|
380
390
|
) : (
|
|
381
|
-
forms
|
|
382
|
-
forms.map((form) => {
|
|
391
|
+
forms?.map((form) => {
|
|
383
392
|
const isItemSelected = isSelected(form.id);
|
|
384
393
|
return (
|
|
385
394
|
<FormItem
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import { ElementsTooltip, IconAction } from "@ax/components";
|
|
3
2
|
|
|
4
3
|
import * as S from "./style";
|
|
@@ -7,7 +6,7 @@ const FormUseItem = (props: IFormUseItem): JSX.Element => {
|
|
|
7
6
|
const { isSiteView, title, subtitle, structuredDataTitle, categoryColors, availableSiteNames, goToItem } = props;
|
|
8
7
|
|
|
9
8
|
return (
|
|
10
|
-
<S.Item>
|
|
9
|
+
<S.Item data-testid="form-use-item">
|
|
11
10
|
<S.PageInfo>
|
|
12
11
|
<S.Title>{title}</S.Title>
|
|
13
12
|
<S.SubTitle>{subtitle}</S.SubTitle>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import type {
|
|
5
5
|
IAvailableSites,
|
|
6
6
|
IFilterValue,
|
|
7
7
|
IGetPagesParams,
|
|
@@ -80,7 +80,7 @@ const FormUseModal = (props: IFormUseModalModal): JSX.Element => {
|
|
|
80
80
|
let pagesData: IPage[] = [];
|
|
81
81
|
let navsData: INavigation[] = [];
|
|
82
82
|
|
|
83
|
-
if (page
|
|
83
|
+
if (page?.length) {
|
|
84
84
|
const params = getParams();
|
|
85
85
|
const data = await getPages(params);
|
|
86
86
|
|
|
@@ -153,7 +153,7 @@ const FormUseModal = (props: IFormUseModalModal): JSX.Element => {
|
|
|
153
153
|
setHistoryPush("/sites/pages/editor", true);
|
|
154
154
|
} else {
|
|
155
155
|
setCurrentPageID(pageID);
|
|
156
|
-
setHistoryPush(isSiteView ? "pages/editor" : "/data/pages/editor", true);
|
|
156
|
+
setHistoryPush(isSiteView ? "/sites/pages/editor" : "/data/pages/editor", true);
|
|
157
157
|
}
|
|
158
158
|
};
|
|
159
159
|
|