@antscorp/antsomi-ui 1.3.5-beta.21 → 1.3.5-beta.23
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/es/components/molecules/TemplateSaveAs/TemplateSaveAs.d.ts +15 -5
- package/es/components/molecules/TemplateSaveAs/TemplateSaveAs.js +29 -15
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/ImageSlider.js +4 -10
- package/es/components/molecules/TemplateSaveAs/hooks/useTemplateSave.d.ts +48 -0
- package/es/components/molecules/TemplateSaveAs/hooks/useTemplateSave.js +132 -0
- package/es/components/molecules/TemplateSaveAs/styled.js +4 -1
- package/package.json +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { SelectProps } from 'antd';
|
|
2
3
|
import { ShareAccessProps } from '../ShareAccess/types';
|
|
3
|
-
type categoriesProps = Array<{
|
|
4
|
-
label: string;
|
|
4
|
+
export type categoriesProps = Array<{
|
|
5
|
+
label: string | React.ReactNode;
|
|
5
6
|
key: string | number;
|
|
6
7
|
children: Array<{
|
|
7
|
-
label: string;
|
|
8
|
+
label: string | React.ReactNode;
|
|
8
9
|
key: string | number;
|
|
9
10
|
}>;
|
|
10
11
|
}>;
|
|
@@ -14,7 +15,7 @@ export interface TemplateValueOptions {
|
|
|
14
15
|
id?: string | number;
|
|
15
16
|
label?: string;
|
|
16
17
|
};
|
|
17
|
-
|
|
18
|
+
description?: string;
|
|
18
19
|
defaultThumbnail?: number;
|
|
19
20
|
categories?: categoriesProps;
|
|
20
21
|
accessInfo?: ShareAccessProps['accessInfo'];
|
|
@@ -41,12 +42,21 @@ export interface TemplateSaveAsProps {
|
|
|
41
42
|
* Default thumbnail - order of default thumbnail in thumbnails array
|
|
42
43
|
*/
|
|
43
44
|
categories?: categoriesProps;
|
|
45
|
+
/**
|
|
46
|
+
* Hide categories with following key
|
|
47
|
+
*/
|
|
48
|
+
omitCategories?: string[];
|
|
44
49
|
templateNames: Array<{
|
|
45
50
|
label: string;
|
|
46
51
|
id: string | number;
|
|
47
52
|
}>;
|
|
53
|
+
templateNamesOptions?: {
|
|
54
|
+
isLoading?: boolean;
|
|
55
|
+
searchValue?: string;
|
|
56
|
+
onSearch?: SelectProps['onSearch'];
|
|
57
|
+
onNamePopupScroll?: SelectProps['onPopupScroll'];
|
|
58
|
+
};
|
|
48
59
|
value?: TemplateValueOptions;
|
|
49
60
|
onChange?: (value: Partial<TemplateValueOptions>) => void;
|
|
50
61
|
}
|
|
51
62
|
export declare const TemplateSaveAs: React.FC<TemplateSaveAsProps>;
|
|
52
|
-
export {};
|
|
@@ -14,24 +14,27 @@ import React, { useState } from 'react';
|
|
|
14
14
|
import { Dropdown } from 'antd';
|
|
15
15
|
import dayjs from 'dayjs';
|
|
16
16
|
// Components
|
|
17
|
-
import { Button, Flex, Input, Typography, Select, ShareAccess, RadioGroup, Radio, } from '@antscorp/antsomi-ui/es/components';
|
|
17
|
+
import { Tooltip, Button, Flex, Input, Typography, Select, ShareAccess, RadioGroup, Radio, Space, Spin, } from '@antscorp/antsomi-ui/es/components';
|
|
18
18
|
// Styles
|
|
19
19
|
import { TemplateSaveAsStyled } from './styled';
|
|
20
20
|
import { ImageSlider } from './components';
|
|
21
21
|
const { Text } = Typography;
|
|
22
22
|
export const TemplateSaveAs = props => {
|
|
23
|
-
const { className, shareAccess, saveOptions, imageReview, categories, templateNames, value, onChange,
|
|
23
|
+
const { className, shareAccess, saveOptions, imageReview, categories, omitCategories, templateNames, templateNamesOptions, value, onChange,
|
|
24
|
+
// onNamePopupScroll,
|
|
25
|
+
} = props;
|
|
24
26
|
const { show: isShowShareAccess } = shareAccess, shareAccessProps = __rest(shareAccess, ["show"]);
|
|
25
27
|
const { thumbnails, skeleton, previewNavigation, slidesPerView } = imageReview;
|
|
28
|
+
const { isLoading, searchValue, onSearch, onNamePopupScroll } = templateNamesOptions || {};
|
|
26
29
|
const { saveNewText = 'Save as a new media Template', saveExistText = 'Save as an existing media Template', saveNewValue = 'save-new', saveExistValue = 'save-exist', } = saveOptions || {};
|
|
27
|
-
const { saveOption = saveNewValue, templateName: defaultTemplateName,
|
|
30
|
+
const { saveOption = saveNewValue, templateName: defaultTemplateName, description: defaultTemplateDesc, defaultThumbnail = 0, categories: categoriesValue = [], accessInfo, } = value || {};
|
|
28
31
|
const [templateName, setTemplateName] = useState(`Untitled Media Template#${dayjs().format('YYYY-MM-DD HH:mm:ss')}`);
|
|
29
32
|
const [templateNameExist, setTemplateNameExist] = useState((defaultTemplateName === null || defaultTemplateName === void 0 ? void 0 : defaultTemplateName.id) ? defaultTemplateName : templateNames === null || templateNames === void 0 ? void 0 : templateNames[0]);
|
|
30
33
|
const handleChangeValue = (newValue) => {
|
|
31
34
|
if (onChange) {
|
|
32
35
|
onChange(Object.assign(Object.assign(Object.assign({}, value), newValue), {
|
|
33
36
|
// TODO: return saveOption and templateName generate default value if not pass as value props
|
|
34
|
-
saveOption: !(value === null || value === void 0 ? void 0 : value.saveOption) && !newValue.saveOption
|
|
37
|
+
defaultThumbnail: newValue.defaultThumbnail || defaultThumbnail, saveOption: !(value === null || value === void 0 ? void 0 : value.saveOption) && !newValue.saveOption
|
|
35
38
|
? saveOption
|
|
36
39
|
: newValue.saveOption || (value === null || value === void 0 ? void 0 : value.saveOption), templateName: !defaultTemplateName && !newValue.templateName
|
|
37
40
|
? saveOption === saveNewValue
|
|
@@ -51,7 +54,7 @@ export const TemplateSaveAs = props => {
|
|
|
51
54
|
const newCategory = [...categoriesValue, { label: parent, key: parentKey, children: [item] }];
|
|
52
55
|
handleChangeValue({ categories: newCategory });
|
|
53
56
|
};
|
|
54
|
-
const handleRemoveCategory = ({ parent, item }) => {
|
|
57
|
+
const handleRemoveCategory = ({ parent, item, }) => {
|
|
55
58
|
const currCategory = categoriesValue.find(category => category.label === parent);
|
|
56
59
|
if (!currCategory)
|
|
57
60
|
return;
|
|
@@ -80,7 +83,15 @@ export const TemplateSaveAs = props => {
|
|
|
80
83
|
saveOption === saveNewValue ? (React.createElement(Input, { debounce: 1000, className: "field-input", value: templateName, onAfterChange: value => {
|
|
81
84
|
handleChangeValue({ templateName: { id: undefined, label: value } });
|
|
82
85
|
setTemplateName(value);
|
|
83
|
-
}, required: true })) : (React.createElement(Select, { className: "field-input",
|
|
86
|
+
}, required: true })) : (React.createElement(Select, { className: "field-input", showSearch: true, searchValue: searchValue, onSearch: onSearch, onPopupScroll: onNamePopupScroll, filterOption: false, dropdownRender: menu => (React.createElement(React.Fragment, null,
|
|
87
|
+
isLoading && templateNames.length === 0 ? null : menu,
|
|
88
|
+
isLoading ? (React.createElement(Space, { style: {
|
|
89
|
+
padding: '4px 0',
|
|
90
|
+
width: '100%',
|
|
91
|
+
justifyContent: 'center',
|
|
92
|
+
alignItems: 'center',
|
|
93
|
+
} },
|
|
94
|
+
React.createElement(Spin, { size: "small" }))) : null)), value: templateNameExist === null || templateNameExist === void 0 ? void 0 : templateNameExist.id, options: (templateNames === null || templateNames === void 0 ? void 0 : templateNames.length) > 0
|
|
84
95
|
? templateNames.map(item => ({ value: item.id, label: item.label }))
|
|
85
96
|
: [], onChange: value => {
|
|
86
97
|
var _a, _b;
|
|
@@ -97,14 +108,14 @@ export const TemplateSaveAs = props => {
|
|
|
97
108
|
} }))),
|
|
98
109
|
React.createElement(Flex, { className: "field-container" },
|
|
99
110
|
React.createElement(Text, { className: "field-title field-title--middle" }, "Description"),
|
|
100
|
-
React.createElement(Input, { placeholder: "Describe your media template", className: "field-input", value: defaultTemplateDesc, debounce: 1000, onAfterChange: value => handleChangeValue({
|
|
111
|
+
React.createElement(Input, { placeholder: "Describe your media template", className: "field-input", value: defaultTemplateDesc, debounce: 1000, onAfterChange: value => handleChangeValue({ description: value }) })),
|
|
101
112
|
React.createElement(Flex, { className: "field-container" },
|
|
102
113
|
React.createElement(Text, { className: "field-title" },
|
|
103
114
|
"Thumbnail template ",
|
|
104
115
|
React.createElement("span", null, "*")),
|
|
105
116
|
React.createElement(ImageSlider, { thumbnails: thumbnails, skeleton: skeleton, previewNavigation: previewNavigation, slidesPerView: slidesPerView, defaultThumbnail: defaultThumbnail, onSelectDefault: value => handleChangeValue({ defaultThumbnail: value }) })), categories === null || categories === void 0 ? void 0 :
|
|
106
117
|
categories.map(parentCategory => {
|
|
107
|
-
var _a, _b;
|
|
118
|
+
var _a, _b, _c;
|
|
108
119
|
const selectedChildren = (_a = categoriesValue
|
|
109
120
|
.find(item => item.label === parentCategory.label)) === null || _a === void 0 ? void 0 : _a.children.map(item => item.label);
|
|
110
121
|
const remainChildren = parentCategory.children.filter(item => !(selectedChildren === null || selectedChildren === void 0 ? void 0 : selectedChildren.includes(item.label)));
|
|
@@ -112,14 +123,18 @@ export const TemplateSaveAs = props => {
|
|
|
112
123
|
label: item.label,
|
|
113
124
|
key: idx,
|
|
114
125
|
}));
|
|
115
|
-
|
|
126
|
+
// NOTE: filter to remove device and template categories
|
|
127
|
+
if ((omitCategories === null || omitCategories === void 0 ? void 0 : omitCategories.length) && omitCategories.includes(parentCategory.key.toString()))
|
|
128
|
+
return null;
|
|
129
|
+
return (React.createElement(Flex, { key: parentCategory.key, className: "field-container" },
|
|
116
130
|
React.createElement(Text, { className: "field-title" }, parentCategory.label),
|
|
117
131
|
React.createElement(Flex, { wrap: "wrap", gap: 10, className: "category-container" },
|
|
118
132
|
/* selectedCategory */
|
|
119
133
|
(_b = categoriesValue
|
|
120
134
|
.find(item => item.label === parentCategory.label)) === null || _b === void 0 ? void 0 :
|
|
121
|
-
_b.children.map(selectedItem => (React.createElement(Flex, { key: selectedItem.
|
|
122
|
-
React.createElement(
|
|
135
|
+
_b.children.map(selectedItem => (React.createElement(Flex, { key: selectedItem.key, className: "selected-category", justify: "space-between", align: "center" },
|
|
136
|
+
React.createElement(Tooltip, { title: selectedItem.label },
|
|
137
|
+
React.createElement(Text, { ellipsis: true, style: { textOverflow: 'ellipsis' } }, selectedItem.label)),
|
|
123
138
|
' ',
|
|
124
139
|
React.createElement("span", { className: "remove-btn", onClick: () => handleRemoveCategory({
|
|
125
140
|
parent: parentCategory.label,
|
|
@@ -134,10 +149,9 @@ export const TemplateSaveAs = props => {
|
|
|
134
149
|
item: remainChildren[key],
|
|
135
150
|
});
|
|
136
151
|
},
|
|
137
|
-
}, getPopupContainer: triggerNode => triggerNode.parentElement, trigger: ['click'] },
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
parentCategory.label.toLowerCase())))));
|
|
152
|
+
}, getPopupContainer: triggerNode => triggerNode.parentElement, trigger: ['click'] }, typeof parentCategory.label === 'string' ? (React.createElement(Button, null,
|
|
153
|
+
"+ Add ", (_c = parentCategory.label) === null || _c === void 0 ? void 0 :
|
|
154
|
+
_c.toLowerCase())) : (parentCategory.label)))));
|
|
141
155
|
})),
|
|
142
156
|
isShowShareAccess ? (React.createElement("div", { className: "share-access-container" },
|
|
143
157
|
React.createElement(ShareAccess, Object.assign({ accessInfo: accessInfo, onChange: value => handleChangeValue({ accessInfo: value }) }, shareAccessProps)))) : null)));
|
|
@@ -10,13 +10,10 @@ import clsx from 'clsx';
|
|
|
10
10
|
export const ImageSlider = props => {
|
|
11
11
|
var _a, _b;
|
|
12
12
|
const { thumbnails, className, skeleton, previewNavigation, slidesPerView = 3, defaultThumbnail, onSelectDefault, } = props;
|
|
13
|
-
console.log('🚀 ~ ImageSlider ~ thumbnails:', thumbnails);
|
|
14
13
|
const sliderContainerRef = useRef(null);
|
|
15
14
|
const thumbnailSelectedRef = useRef(null);
|
|
16
15
|
const [selectedThumbnail, setSelectedThumbnail] = useState(0);
|
|
17
|
-
console.log('🚀 ~ selectedThumbnail:', selectedThumbnail);
|
|
18
16
|
const [defaultThumbnailInternal, setDefaultThumbnailInternal] = useState(defaultThumbnail || 0);
|
|
19
|
-
console.log('🚀 ~ defaultThumbnailInternal:', defaultThumbnailInternal);
|
|
20
17
|
(_a = thumbnailSelectedRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({
|
|
21
18
|
left: selectedThumbnail * 330,
|
|
22
19
|
behavior: 'smooth',
|
|
@@ -49,13 +46,10 @@ export const ImageSlider = props => {
|
|
|
49
46
|
} },
|
|
50
47
|
defaultThumbnailInternal === index ? (React.createElement(Icon, { type: "icon-ants-check", style: { fontSize: '12px' } })) : null,
|
|
51
48
|
defaultThumbnailInternal === index ? 'Default thumbnail' : 'Set as default'))))),
|
|
52
|
-
React.createElement(Flex, { gap: 10, className: "thumbnail-slider-container", ref: sliderContainerRef }, thumbnails.map((url, index) => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}), onClick: () => setSelectedThumbnail(index) },
|
|
57
|
-
React.createElement(Image, { key: url, preview: false, width: "80%", height: "96%", src: url })));
|
|
58
|
-
})),
|
|
49
|
+
React.createElement(Flex, { gap: 10, className: "thumbnail-slider-container", ref: sliderContainerRef }, thumbnails.map((url, index) => (React.createElement("div", { key: `${url}_${index * 2}`, className: clsx('image-container--small', {
|
|
50
|
+
'image-container--selected': index === selectedThumbnail,
|
|
51
|
+
}), onClick: () => setSelectedThumbnail(index) },
|
|
52
|
+
React.createElement(Image, { key: url, preview: false, width: "80%", height: "96%", src: url }))))),
|
|
59
53
|
previewNavigation ? (React.createElement(React.Fragment, null,
|
|
60
54
|
React.createElement("div", { className: "change-preview-button change-preview-button--left", onClick: handlePrevThumbnail },
|
|
61
55
|
React.createElement(Icon, { type: "icon-ants-angle-left" })),
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { PayloadInfo } from '@antscorp/antsomi-ui/es/types';
|
|
2
|
+
import { TCategoryItem, TCheckedCategories, TTemplateItem } from '../../../template';
|
|
3
|
+
import { TTemplateListingConfig } from '@antscorp/antsomi-ui/es/types/templateListing';
|
|
4
|
+
import { TemplateCategory } from '@antscorp/antsomi-ui/es/models/TemplateCategory';
|
|
5
|
+
interface TemplateListingOptions {
|
|
6
|
+
service: PayloadInfo;
|
|
7
|
+
config: TTemplateListingConfig & {
|
|
8
|
+
filter?: any;
|
|
9
|
+
};
|
|
10
|
+
checkedCategoriesDefault?: TCheckedCategories;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Custom React Hook for managing state and data fetching logic related to a template listing.
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} options - The options object for configuring the hook.
|
|
16
|
+
* @param {PayloadInfo} options.service - Payload information for making API requests.
|
|
17
|
+
* @param {TTemplateListingConfig} options.config - Configuration options for the template listing.
|
|
18
|
+
*
|
|
19
|
+
* @returns {Object} - An object containing various properties and functions for template listing management.
|
|
20
|
+
*
|
|
21
|
+
* @property {TCategoryItem[]} categoryItems - An array of category items for rendering the template listing's category structure.
|
|
22
|
+
* @property {TTemplateItem[]} templateItems - An array of template items representing the templates available for the specified configuration.
|
|
23
|
+
* @property {string[]} openCategoryKeys - An array of keys representing the currently open category items in the template listing.
|
|
24
|
+
* @property {TCheckedCategories} checkedCategories - An object containing information about the checked categories in the template listing.
|
|
25
|
+
* @property {boolean} isLoading - A boolean indicating whether data is currently being loaded.
|
|
26
|
+
*
|
|
27
|
+
* @property {Function} onChangeCheckedCategories - A function to update the checked categories in the template listing.
|
|
28
|
+
* @param {TCheckedCategories} checkedCategories - An object containing information about the checked categories.
|
|
29
|
+
*
|
|
30
|
+
* @property {Function} onChangeOpenCategoryKeys - A function to update the open category keys in the template listing.
|
|
31
|
+
* @param {string[]} openKeys - An array of keys representing the currently open category items.
|
|
32
|
+
*
|
|
33
|
+
* @property {Function} onLoadMore - A function to load more template data when scrolling in the template listing.
|
|
34
|
+
*/
|
|
35
|
+
export declare const useTemplateSave: (options: TemplateListingOptions) => {
|
|
36
|
+
categoryItems: TCategoryItem[];
|
|
37
|
+
templateItems: TTemplateItem[];
|
|
38
|
+
openCategoryKeys: string[];
|
|
39
|
+
checkedCategories: TCheckedCategories;
|
|
40
|
+
isLoadingCategoryList: boolean;
|
|
41
|
+
isLoadingTemplateList: boolean;
|
|
42
|
+
refetchCategoryList: <TPageData>(options?: (import("@tanstack/query-core").RefetchOptions & import("@tanstack/query-core").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/query-core").QueryObserverResult<TemplateCategory[], any>>;
|
|
43
|
+
refetchTemplateList: <TPageData_1>(options?: (import("@tanstack/query-core").RefetchOptions & import("@tanstack/query-core").RefetchQueryFilters<TPageData_1>) | undefined) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("@antscorp/antsomi-ui/es/types").ResponseListing<import("../../../../models/ObjectTemplate").ObjectTemplate>>, any>>;
|
|
44
|
+
onChangeCheckedCategories: (checkedCategories: TCheckedCategories) => void;
|
|
45
|
+
onChangeOpenCategoryKeys: (openKeys: string[]) => void;
|
|
46
|
+
onLoadMore: () => void;
|
|
47
|
+
};
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Libraries
|
|
2
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
3
|
+
import { useGetTemplateCategoryList, useGetObjectTemplateList, } from '@antscorp/antsomi-ui/es/queries/TemplateListing';
|
|
4
|
+
// Hooks
|
|
5
|
+
import { useDeepCompareEffect, useDeepCompareMemo } from '@antscorp/antsomi-ui/es/hooks';
|
|
6
|
+
// Constants
|
|
7
|
+
import { CATEGORY_SPLIT_KEY } from '@antscorp/antsomi-ui/es/constants/templateListing';
|
|
8
|
+
/**
|
|
9
|
+
* Custom React Hook for managing state and data fetching logic related to a template listing.
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} options - The options object for configuring the hook.
|
|
12
|
+
* @param {PayloadInfo} options.service - Payload information for making API requests.
|
|
13
|
+
* @param {TTemplateListingConfig} options.config - Configuration options for the template listing.
|
|
14
|
+
*
|
|
15
|
+
* @returns {Object} - An object containing various properties and functions for template listing management.
|
|
16
|
+
*
|
|
17
|
+
* @property {TCategoryItem[]} categoryItems - An array of category items for rendering the template listing's category structure.
|
|
18
|
+
* @property {TTemplateItem[]} templateItems - An array of template items representing the templates available for the specified configuration.
|
|
19
|
+
* @property {string[]} openCategoryKeys - An array of keys representing the currently open category items in the template listing.
|
|
20
|
+
* @property {TCheckedCategories} checkedCategories - An object containing information about the checked categories in the template listing.
|
|
21
|
+
* @property {boolean} isLoading - A boolean indicating whether data is currently being loaded.
|
|
22
|
+
*
|
|
23
|
+
* @property {Function} onChangeCheckedCategories - A function to update the checked categories in the template listing.
|
|
24
|
+
* @param {TCheckedCategories} checkedCategories - An object containing information about the checked categories.
|
|
25
|
+
*
|
|
26
|
+
* @property {Function} onChangeOpenCategoryKeys - A function to update the open category keys in the template listing.
|
|
27
|
+
* @param {string[]} openKeys - An array of keys representing the currently open category items.
|
|
28
|
+
*
|
|
29
|
+
* @property {Function} onLoadMore - A function to load more template data when scrolling in the template listing.
|
|
30
|
+
*/
|
|
31
|
+
export const useTemplateSave = (options) => {
|
|
32
|
+
const { service, config } = options;
|
|
33
|
+
const { objectType, categoryCodes, publicLevel, limitListPerPage = 10, filter } = config;
|
|
34
|
+
// const { message } = App.useApp();
|
|
35
|
+
// State
|
|
36
|
+
const [state, setState] = useState({
|
|
37
|
+
checkedCategories: {},
|
|
38
|
+
openCategoryKeys: [],
|
|
39
|
+
});
|
|
40
|
+
const { checkedCategories, openCategoryKeys } = state;
|
|
41
|
+
const { data: categoryList, isLoading: isLoadingCategoryList, refetch: refetchCategoryList, } = useGetTemplateCategoryList({
|
|
42
|
+
args: {
|
|
43
|
+
auth: service,
|
|
44
|
+
params: {
|
|
45
|
+
objectTypes: [objectType],
|
|
46
|
+
categoryCodes,
|
|
47
|
+
publicLevel,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
// Queries
|
|
52
|
+
const { data: infiniteObjectTemplate, isFetchingNextPage, isFetching, hasNextPage, fetchNextPage, refetch: refetchTemplateList, } = useGetObjectTemplateList({
|
|
53
|
+
args: {
|
|
54
|
+
auth: service,
|
|
55
|
+
params: Object.assign({ object_type: objectType, public_level: publicLevel, limit: limitListPerPage }, (filter ? { filter } : {})),
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
// Variables
|
|
59
|
+
const isLoadingTemplateList = isFetching || isFetchingNextPage;
|
|
60
|
+
// Memo
|
|
61
|
+
const categoryItems = useDeepCompareMemo(() => {
|
|
62
|
+
const recursiveCategory = (categories = [], parentCategoryCode = '') => categories.map(category => {
|
|
63
|
+
const { categoryCode, categoryId, categoryName, children, total } = category;
|
|
64
|
+
const key = Array.isArray(children) && children.length
|
|
65
|
+
? categoryCode
|
|
66
|
+
: [parentCategoryCode, categoryId].join(CATEGORY_SPLIT_KEY);
|
|
67
|
+
return {
|
|
68
|
+
key,
|
|
69
|
+
label: categoryName,
|
|
70
|
+
total,
|
|
71
|
+
children: recursiveCategory(children || [], categoryCode),
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
return recursiveCategory(categoryList || []);
|
|
75
|
+
}, [categoryList]);
|
|
76
|
+
const templateItems = useMemo(() => {
|
|
77
|
+
if (infiniteObjectTemplate) {
|
|
78
|
+
const { pages } = infiniteObjectTemplate;
|
|
79
|
+
return pages.flatMap(({ entities }) => entities.flatMap(({ id, name, thumbnail }) => ({
|
|
80
|
+
id,
|
|
81
|
+
name,
|
|
82
|
+
thumbnail,
|
|
83
|
+
})));
|
|
84
|
+
}
|
|
85
|
+
return [];
|
|
86
|
+
}, [infiniteObjectTemplate]);
|
|
87
|
+
// Effects
|
|
88
|
+
useDeepCompareEffect(() => {
|
|
89
|
+
setState(prev => (Object.assign(Object.assign({}, prev), { openCategoryKeys: (categoryList === null || categoryList === void 0 ? void 0 : categoryList.map(({ categoryCode }) => categoryCode)) || [] })));
|
|
90
|
+
}, [categoryList]);
|
|
91
|
+
// useDeepCompareEffect(() => {
|
|
92
|
+
// if (!isEmpty(checkedCategoriesDefault)) {
|
|
93
|
+
// setState(prev => ({
|
|
94
|
+
// ...prev,
|
|
95
|
+
// checkedCategories:
|
|
96
|
+
// Object.entries(checkedCategoriesDefault).reduce((acc, curr) => {
|
|
97
|
+
// const [key, value] = curr;
|
|
98
|
+
// acc[key] = value.map(item => [key, item].join(CATEGORY_SPLIT_KEY));
|
|
99
|
+
// return acc;
|
|
100
|
+
// }, {}) || {},
|
|
101
|
+
// }));
|
|
102
|
+
// }
|
|
103
|
+
// }, [checkedCategoriesDefault]);
|
|
104
|
+
// Handles
|
|
105
|
+
const onChangeCheckedCategories = (checkedCategories) => {
|
|
106
|
+
setState(prev => (Object.assign(Object.assign({}, prev), { checkedCategories })));
|
|
107
|
+
};
|
|
108
|
+
const onChangeOpenCategoryKeys = useCallback((openKeys) => {
|
|
109
|
+
setState(prev => (Object.assign(Object.assign({}, prev), { openCategoryKeys: openKeys })));
|
|
110
|
+
}, []);
|
|
111
|
+
const onLoadMore = useCallback(() => {
|
|
112
|
+
if (!isFetchingNextPage && hasNextPage) {
|
|
113
|
+
fetchNextPage();
|
|
114
|
+
}
|
|
115
|
+
}, [fetchNextPage, hasNextPage, isFetchingNextPage]);
|
|
116
|
+
return {
|
|
117
|
+
// MapKeys
|
|
118
|
+
categoryItems,
|
|
119
|
+
templateItems,
|
|
120
|
+
openCategoryKeys,
|
|
121
|
+
// Values
|
|
122
|
+
checkedCategories,
|
|
123
|
+
isLoadingCategoryList,
|
|
124
|
+
isLoadingTemplateList,
|
|
125
|
+
// Functions
|
|
126
|
+
refetchCategoryList,
|
|
127
|
+
refetchTemplateList,
|
|
128
|
+
onChangeCheckedCategories,
|
|
129
|
+
onChangeOpenCategoryKeys,
|
|
130
|
+
onLoadMore,
|
|
131
|
+
};
|
|
132
|
+
};
|
|
@@ -51,10 +51,13 @@ export const TemplateSaveAsStyled = styled(Flex) `
|
|
|
51
51
|
|
|
52
52
|
.category-container {
|
|
53
53
|
flex: 1;
|
|
54
|
+
display: grid;
|
|
55
|
+
grid-template-columns: repeat(2, 1fr);
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
.selected-category {
|
|
57
|
-
width: 240px;
|
|
59
|
+
/* width: 240px; */
|
|
60
|
+
overflow: hidden;
|
|
58
61
|
height: 30px;
|
|
59
62
|
border: 1px solid #b8cfe6;
|
|
60
63
|
padding: 0 5px;
|