@antscorp/antsomi-ui 2.0.57 → 2.0.58
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/UploadImage/index.d.ts +102 -2
- package/es/components/molecules/UploadImage/index.js +48 -73
- package/es/components/molecules/UploadImage/styled.d.ts +2 -1
- package/es/constants/queries.d.ts +1 -0
- package/es/constants/queries.js +1 -0
- package/es/queries/ThirdParty/index.d.ts +1 -0
- package/es/queries/ThirdParty/index.js +1 -0
- package/es/queries/ThirdParty/useStoreSavedMedia.d.ts +1 -0
- package/es/queries/ThirdParty/useStoreSavedMedia.js +12 -0
- package/es/services/MediaTemplateDesign/UploadFile/index.d.ts +1 -1
- package/es/services/MediaTemplateDesign/UploadFile/index.js +2 -2
- package/package.json +1 -1
|
@@ -1,33 +1,133 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { UploadProps as AntdUploadProps } from 'antd/lib/upload';
|
|
3
3
|
export type MediaMode = 'image' | 'video';
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Props for the UploadImage component.
|
|
6
|
+
*/
|
|
7
|
+
export interface UploadImageProps extends AntdUploadProps {
|
|
8
|
+
/**
|
|
9
|
+
* Heading text for the image upload modal.
|
|
10
|
+
* @default "Image Selection"
|
|
11
|
+
*/
|
|
5
12
|
labelHeadingModal?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Label for the button used to select an image.
|
|
15
|
+
* @default "Select Image from computer"
|
|
16
|
+
*/
|
|
6
17
|
labelButtonSelect?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Label for the modal confirming image deletion.
|
|
20
|
+
* @default "Delete Image"
|
|
21
|
+
*/
|
|
7
22
|
labelModalDelete?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Placeholder text for the search input inside the modal.
|
|
25
|
+
* @default "Search image..."
|
|
26
|
+
*/
|
|
8
27
|
searchPlaceholder?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Callback triggered when an image is removed.
|
|
30
|
+
*/
|
|
9
31
|
onRemoveImage?: Function;
|
|
32
|
+
/**
|
|
33
|
+
* Callback triggered when an image is selected or changed.
|
|
34
|
+
*/
|
|
10
35
|
onChangeImage?: Function;
|
|
36
|
+
/**
|
|
37
|
+
* The currently selected image object.
|
|
38
|
+
*/
|
|
11
39
|
selectedImage?: UploadMediaObject;
|
|
40
|
+
/**
|
|
41
|
+
* Controls the visibility of the image upload modal.
|
|
42
|
+
* @default false
|
|
43
|
+
*/
|
|
12
44
|
isOpen?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Determines if the component should operate in input mode.
|
|
47
|
+
* @default true
|
|
48
|
+
*/
|
|
13
49
|
isInputMode?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Name of the icon to be displayed.
|
|
52
|
+
* @default "image-3"
|
|
53
|
+
*/
|
|
14
54
|
iconName?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Mode in which the media should be handled.
|
|
57
|
+
* @default "image"
|
|
58
|
+
*/
|
|
15
59
|
mode?: MediaMode;
|
|
16
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Width of the upload component.
|
|
62
|
+
* @default "100%"
|
|
63
|
+
*/
|
|
64
|
+
width?: string | number;
|
|
65
|
+
/**
|
|
66
|
+
* List of validation errors related to the upload.
|
|
67
|
+
* @default []
|
|
68
|
+
*/
|
|
17
69
|
errors?: Array<any>;
|
|
70
|
+
/**
|
|
71
|
+
* Allowed file extensions for the upload.
|
|
72
|
+
* @default [".jpg", ".png", ".jfif", ".jpeg", ".gif", ".webp"]
|
|
73
|
+
*/
|
|
18
74
|
extensions?: string[];
|
|
75
|
+
/**
|
|
76
|
+
* Maximum file size allowed for upload (in MB).
|
|
77
|
+
* @default 10
|
|
78
|
+
*/
|
|
19
79
|
maxSize?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Title text for the upload section.
|
|
82
|
+
*/
|
|
20
83
|
title?: string;
|
|
84
|
+
/**
|
|
85
|
+
* Whether to display the image URL after upload.
|
|
86
|
+
* @default true
|
|
87
|
+
*/
|
|
21
88
|
showImageURL?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Placeholder text for the upload input field.
|
|
91
|
+
* @default "Enter image URL"
|
|
92
|
+
*/
|
|
22
93
|
placeholder?: string;
|
|
94
|
+
/**
|
|
95
|
+
* Domain-specific media folder or endpoint.
|
|
96
|
+
* @default "https://sandbox-media-template.antsomi.com/cdp"
|
|
97
|
+
*/
|
|
23
98
|
domainMedia: string;
|
|
99
|
+
/**
|
|
100
|
+
* Unique slug identifier for media categorization.
|
|
101
|
+
* @default "api/v1"
|
|
102
|
+
*/
|
|
24
103
|
slug: string;
|
|
104
|
+
/**
|
|
105
|
+
* Configuration parameters for API requests.
|
|
106
|
+
*/
|
|
25
107
|
paramConfigs?: {
|
|
108
|
+
/**
|
|
109
|
+
* Authentication token for media uploads.
|
|
110
|
+
* @default ""
|
|
111
|
+
*/
|
|
26
112
|
token?: string;
|
|
113
|
+
/**
|
|
114
|
+
* User identifier for media ownership.
|
|
115
|
+
* @default ""
|
|
116
|
+
*/
|
|
27
117
|
userId?: string;
|
|
118
|
+
/**
|
|
119
|
+
* Account identifier for media association.
|
|
120
|
+
* @default ""
|
|
121
|
+
*/
|
|
28
122
|
accountId: string;
|
|
29
123
|
};
|
|
124
|
+
/**
|
|
125
|
+
* Whether the image upload is required.
|
|
126
|
+
*/
|
|
30
127
|
required?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Indicates if the input is currently focused.
|
|
130
|
+
*/
|
|
31
131
|
focused?: boolean;
|
|
32
132
|
}
|
|
33
133
|
interface UploadMediaObject {
|
|
@@ -3,15 +3,19 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
4
4
|
/* eslint-disable react-hooks/exhaustive-deps */
|
|
5
5
|
// Libraries
|
|
6
|
-
import { useEffect, useState, useRef } from 'react';
|
|
6
|
+
import { useEffect, useState, useRef, useMemo } from 'react';
|
|
7
7
|
import Upload from 'antd/lib/upload';
|
|
8
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
9
|
+
import { cloneDeep, flattenDeep } from 'lodash';
|
|
10
|
+
import { useInView } from 'react-intersection-observer';
|
|
8
11
|
// Hooks
|
|
9
|
-
import {
|
|
12
|
+
import { useDebounce } from '@antscorp/antsomi-ui/es/hooks/useDebounce';
|
|
13
|
+
import { useStoreSavedMedia } from '@antscorp/antsomi-ui/es/queries';
|
|
10
14
|
// Assets
|
|
11
15
|
import PlaceholderImage from '@antscorp/antsomi-ui/es/assets/images/placeholder-image.png';
|
|
12
16
|
import MediaIcon from './MediaIcon';
|
|
13
17
|
// Service
|
|
14
|
-
import { uploadFile, createSavedMedia, deleteSavedMedia,
|
|
18
|
+
import { uploadFile, createSavedMedia, deleteSavedMedia, } from '@antscorp/antsomi-ui/es/services/MediaTemplateDesign/UploadFile';
|
|
15
19
|
// Atoms
|
|
16
20
|
import { Button, Icon, Text, message, Spin, Input, Space, } from '@antscorp/antsomi-ui/es/components/atoms';
|
|
17
21
|
// Molecules
|
|
@@ -19,10 +23,10 @@ import { Modal, InputSearch, Select } from '@antscorp/antsomi-ui/es/components/m
|
|
|
19
23
|
// Styled
|
|
20
24
|
import { Boxed, ErrorMessage, Image, Overlay, Paragraph, TextStyled, UploadImageWrapper, WrapperBtn, WrapperIcon, WrapperInputMode, WrapperListImages, } from './styled';
|
|
21
25
|
// Utils
|
|
22
|
-
import {
|
|
26
|
+
import { safeParse } from '@antscorp/antsomi-ui/es/utils';
|
|
23
27
|
import { getMediaTypeByMode, getReplacementExtension } from './utils';
|
|
24
28
|
// Constants
|
|
25
|
-
import { THEME } from '@antscorp/antsomi-ui/es/constants';
|
|
29
|
+
import { QUERY_KEYS, THEME } from '@antscorp/antsomi-ui/es/constants';
|
|
26
30
|
const flexStyleCenter = {
|
|
27
31
|
display: 'flex',
|
|
28
32
|
gap: '15px',
|
|
@@ -39,75 +43,45 @@ const SORT_OPTIONS = {
|
|
|
39
43
|
label: 'Sort by Size',
|
|
40
44
|
},
|
|
41
45
|
};
|
|
42
|
-
const PATH = '@antscorp/antsomi-ui/es/components/molecules/UploadImage/index.tsx';
|
|
43
46
|
export const UploadImage = props => {
|
|
44
47
|
const { labelHeadingModal, labelButtonSelect, labelModalDelete, searchPlaceholder, onRemoveImage, onChangeImage: onChangeMedia, isOpen, isInputMode, width, placeholder, extensions, maxSize, title, showImageURL: showMediaURL, selectedImage: selectedMediaProp, required, focused, domainMedia, slug, paramConfigs, errors, iconName, mode, } = props;
|
|
45
48
|
const { Dragger } = Upload;
|
|
46
|
-
const [storeSavedMedia, setStoreSavedMedia] = useState([]);
|
|
47
49
|
const [selectedMedia, setSelectedMedia] = useState(selectedMediaProp || { url: '' });
|
|
48
50
|
const [isModalOpen, setIsModalOpen] = useState(isOpen);
|
|
49
|
-
const [
|
|
51
|
+
const [textSearchDebounce, textSearch, setTextSearch] = useDebounce('', 350);
|
|
50
52
|
const [sortOption, setSortOption] = useState(SORT_OPTIONS.BY_UPLOAD_DATE.value);
|
|
51
53
|
const [loading, setLoading] = useState(false);
|
|
52
54
|
const [isOpenConfirmDelete, setOpenConfirmDelete] = useState(false);
|
|
53
|
-
const [triggerRefresh, setTriggerRefresh] = useState(1);
|
|
54
55
|
const uploadFilesRef = useRef([]);
|
|
55
56
|
const uploadFilesTimeoutRef = useRef();
|
|
56
57
|
const deleteMediaRef = useRef();
|
|
57
58
|
const isError = safeParse(errors, []).length > 0;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
const queryClient = useQueryClient();
|
|
60
|
+
const paramsMemo = useMemo(() => ({
|
|
61
|
+
...paramConfigs,
|
|
62
|
+
type: getMediaTypeByMode(mode),
|
|
63
|
+
}), [paramConfigs, mode]);
|
|
64
|
+
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading: isLoadingStore, refetch, } = useStoreSavedMedia(domainMedia, slug, paramsMemo);
|
|
65
|
+
const flattenedMedia = useMemo(() => {
|
|
66
|
+
const flattened = cloneDeep(flattenDeep(data?.pages));
|
|
67
|
+
// Filter media based on search text
|
|
68
|
+
const filteredMedia = textSearchDebounce
|
|
69
|
+
? flattened.filter(media => media.name?.toLowerCase().includes(textSearchDebounce.toLowerCase()))
|
|
70
|
+
: flattened;
|
|
71
|
+
// Sort media based on the selected sort option
|
|
72
|
+
if (sortOption === SORT_OPTIONS.BY_SIZE.value) {
|
|
73
|
+
return filteredMedia.sort((media1, media2) => media1.size - media2.size);
|
|
74
|
+
}
|
|
75
|
+
return filteredMedia.sort((media1, media2) => media1.createdAt && media2.createdAt
|
|
76
|
+
? media1.createdAt.isAfter(media2.createdAt)
|
|
77
|
+
? -1
|
|
78
|
+
: 1
|
|
79
|
+
: 0);
|
|
80
|
+
}, [data?.pages, sortOption, textSearchDebounce]);
|
|
62
81
|
// When selectedMediaProp onChange
|
|
63
82
|
useEffect(() => {
|
|
64
83
|
setSelectedMedia(selectedMediaProp || { url: '' });
|
|
65
84
|
}, [selectedMediaProp]);
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
if (sortOption === SORT_OPTIONS.BY_SIZE.value) {
|
|
68
|
-
setListMedia(listMedia ? [...listMedia].sort((media1, media2) => media1.size - media2.size) : []);
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
setListMedia(listMedia
|
|
72
|
-
? [...listMedia].sort((media1, media2) => media1.createdAt && media2.createdAt
|
|
73
|
-
? media1.createdAt.isAfter(media2.createdAt)
|
|
74
|
-
? -1
|
|
75
|
-
: 1
|
|
76
|
-
: 0)
|
|
77
|
-
: []);
|
|
78
|
-
}
|
|
79
|
-
}, [sortOption]);
|
|
80
|
-
const handleGetStoreSavedMedia = async (domain, slug, paramConfigs) => {
|
|
81
|
-
try {
|
|
82
|
-
setLoading(true);
|
|
83
|
-
const type = getMediaTypeByMode(mode);
|
|
84
|
-
const params = {
|
|
85
|
-
...paramConfigs,
|
|
86
|
-
type,
|
|
87
|
-
};
|
|
88
|
-
const result = await getListingSavedMedia(domain, slug, params);
|
|
89
|
-
if (result) {
|
|
90
|
-
setStoreSavedMedia(result || []);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
handleError(error, {
|
|
95
|
-
path: PATH,
|
|
96
|
-
name: 'handleGetStoreSavedMedia',
|
|
97
|
-
args: {
|
|
98
|
-
error,
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
// eslint-disable-next-line no-console
|
|
102
|
-
console.log('error :>', error);
|
|
103
|
-
}
|
|
104
|
-
finally {
|
|
105
|
-
setLoading(false);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
useEffect(() => {
|
|
109
|
-
handleGetStoreSavedMedia(domainMedia, slug, paramConfigs);
|
|
110
|
-
}, [triggerRefresh]);
|
|
111
85
|
const showModal = (e) => {
|
|
112
86
|
e.stopPropagation();
|
|
113
87
|
setIsModalOpen(true);
|
|
@@ -125,6 +99,14 @@ export const UploadImage = props => {
|
|
|
125
99
|
const onChangeSort = (option) => {
|
|
126
100
|
setSortOption(option);
|
|
127
101
|
};
|
|
102
|
+
const { ref } = useInView({
|
|
103
|
+
triggerOnce: false,
|
|
104
|
+
onChange: inView => {
|
|
105
|
+
if (inView && hasNextPage && !isFetchingNextPage) {
|
|
106
|
+
fetchNextPage();
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
});
|
|
128
110
|
const renderListMedia = (listMediaRender) => listMediaRender.map((media, idx) => (_jsxs(WrapperListImages, { className: "ants-group", children: [_jsxs(Boxed, { children: [_jsx(Image, { src: mode === 'video' ? media.thumbnail : media.url, alt: "img", loading: "lazy" }), _jsxs(WrapperBtn, { className: "group-hover", children: [_jsx(Button, { onClick: () => handleSelectMedia(media), style: { backgroundColor: 'rgb(255,255,255)' }, children: "USE" }), _jsx(Button, { onClick: () => handleRemoveUploadedMedia(media), style: { backgroundColor: 'rgb(255,255,255)' }, children: _jsx(Icon, { type: "icon-ants-remove-trash", size: 15, style: { color: THEME.token?.colorPrimary } }) })] }), _jsx(Overlay, { className: "group-hover" })] }), _jsx(Paragraph, { style: {
|
|
129
111
|
overflow: 'hidden',
|
|
130
112
|
textOverflow: 'ellipsis',
|
|
@@ -134,16 +116,7 @@ export const UploadImage = props => {
|
|
|
134
116
|
}, title: media.name, children: media.name }), _jsxs(Paragraph, { children: ["Uploaded: ", media.createdAt.format('DD/MM/YYYY'), " at ", media.createdAt.format('hh:mm:ss A')] }), _jsxs(Paragraph, { children: ["Size: ", media.sizeString] })] }, idx)));
|
|
135
117
|
const onChangeSearchImage = (e) => {
|
|
136
118
|
const { value } = e.target;
|
|
137
|
-
|
|
138
|
-
setListMedia(storeSavedMedia
|
|
139
|
-
? storeSavedMedia
|
|
140
|
-
.filter(item => item.name.toLocaleLowerCase().includes(value.trim().toLocaleLowerCase()))
|
|
141
|
-
.slice(0, 15)
|
|
142
|
-
: []);
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
setListMedia(storeSavedMedia);
|
|
146
|
-
}
|
|
119
|
+
setTextSearch(value.trim());
|
|
147
120
|
};
|
|
148
121
|
const handleRemoveMedia = () => {
|
|
149
122
|
if (onRemoveImage) {
|
|
@@ -161,7 +134,9 @@ export const UploadImage = props => {
|
|
|
161
134
|
if (res && res.data && res.data.code === 200 && res.data.data) {
|
|
162
135
|
const { success_media = [] } = res.data.data;
|
|
163
136
|
if (Array.isArray(success_media) && success_media.length) {
|
|
164
|
-
|
|
137
|
+
queryClient.invalidateQueries([QUERY_KEYS.GET_LIST_SAVED_MEDIA, domainMedia, slug, paramsMemo], {
|
|
138
|
+
exact: false,
|
|
139
|
+
});
|
|
165
140
|
}
|
|
166
141
|
}
|
|
167
142
|
setOpenConfirmDelete(false);
|
|
@@ -235,7 +210,7 @@ export const UploadImage = props => {
|
|
|
235
210
|
})));
|
|
236
211
|
await Promise.all(arrPromise);
|
|
237
212
|
setLoading(false);
|
|
238
|
-
|
|
213
|
+
refetch({ refetchPage: (_page, index) => index === 0 });
|
|
239
214
|
}
|
|
240
215
|
else {
|
|
241
216
|
setLoading(false);
|
|
@@ -279,7 +254,7 @@ export const UploadImage = props => {
|
|
|
279
254
|
justifyContent: 'space-between',
|
|
280
255
|
alignItems: 'center',
|
|
281
256
|
marginBottom: 20,
|
|
282
|
-
}, children: [_jsx(InputSearch, { style: { width: 232 }, onChange: onChangeSearchImage, placeholder: searchPlaceholder }), _jsx(Select, { defaultValue: SORT_OPTIONS.BY_UPLOAD_DATE.value, value: sortOption, options: Object.values(SORT_OPTIONS), style: { width: 232 }, onChange: onChangeSort })] }), _jsx(Spin, { spinning: loading, children: _jsx(Dragger, { ...props, accept: extensions?.join(','),
|
|
257
|
+
}, children: [_jsx(InputSearch, { value: textSearch, style: { width: 232 }, onChange: onChangeSearchImage, placeholder: searchPlaceholder }), _jsx(Select, { defaultValue: SORT_OPTIONS.BY_UPLOAD_DATE.value, value: sortOption, options: Object.values(SORT_OPTIONS), style: { width: 232 }, onChange: onChangeSort })] }), _jsx(Spin, { spinning: loading || isFetchingNextPage || isLoadingStore, children: _jsx(Dragger, { ...props, accept: extensions?.join(','),
|
|
283
258
|
// action={`${APP_CONFIG.API_URL}/file-upload/file?&_token=${userInfo?.token}&_user_id=${userInfo?.user_id}&_account_id=${userInfo?.account_id}`}
|
|
284
259
|
// beforeUpload={handleBeforeUploadFile}
|
|
285
260
|
// onChange={onChangeFileUpload}
|
|
@@ -289,13 +264,13 @@ export const UploadImage = props => {
|
|
|
289
264
|
}, children: [_jsx(Icon, { type: `icon-ants-${iconName}`, size: 36, style: { color: THEME.token?.colorIcon } }), _jsxs("div", { style: { ...flexStyleCenter, justifyContent: 'flex-start' }, children: [_jsx(TextStyled, { className: "ant-upload-text", children: "Drag & Drop file here" }), _jsx("span", { children: "or" }), _jsx(Button, { style: { backgroundColor: '#ffffff' }, children: labelButtonSelect }), _jsx(Button, { onClick: handleRemoveMedia, style: {
|
|
290
265
|
display: 'none !important',
|
|
291
266
|
backgroundColor: '#ffffff',
|
|
292
|
-
}, children: _jsx(Icon, { type: "icon-ants-remove-trash", size: 15, style: { color: THEME.token?.colorPrimary } }) })] })] }) }) }),
|
|
267
|
+
}, children: _jsx(Icon, { type: "icon-ants-remove-trash", size: 15, style: { color: THEME.token?.colorPrimary } }) })] })] }) }) }), _jsxs("div", { style: {
|
|
293
268
|
display: 'flex',
|
|
294
269
|
flexWrap: 'wrap',
|
|
295
270
|
gap: '35px',
|
|
296
271
|
paddingTop: 20,
|
|
297
272
|
width: '100%',
|
|
298
|
-
}, children: renderListMedia(
|
|
273
|
+
}, children: [renderListMedia(flattenedMedia), _jsx("div", { ref: ref })] })] })] }));
|
|
299
274
|
};
|
|
300
275
|
UploadImage.defaultProps = {
|
|
301
276
|
isOpen: false,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
1
2
|
export declare const WrapperListImages: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
2
3
|
export declare const TextStyled: import("styled-components").StyledComponent<"span", any, {}, never>;
|
|
3
4
|
export declare const Boxed: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
@@ -6,7 +7,7 @@ export declare const WrapperBtn: import("styled-components").StyledComponent<"di
|
|
|
6
7
|
export declare const Paragraph: import("styled-components").StyledComponent<"p", any, {}, never>;
|
|
7
8
|
export declare const Overlay: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
8
9
|
export declare const WrapperInputMode: import("styled-components").StyledComponent<"div", any, {
|
|
9
|
-
width?:
|
|
10
|
+
width?: CSSProperties['width'];
|
|
10
11
|
}, never>;
|
|
11
12
|
export declare const WrapperIcon: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
12
13
|
export declare const ErrorMessage: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
@@ -18,6 +18,7 @@ export declare const QUERY_KEYS: {
|
|
|
18
18
|
GET_OBJECT_TEMPLATE_DETAIL: string;
|
|
19
19
|
GET_SAVE_AS_GALLERY_PERMISSION_EMAILS: string;
|
|
20
20
|
GET_LIST_FALLBACK_BO: string;
|
|
21
|
+
GET_LIST_SAVED_MEDIA: string;
|
|
21
22
|
GET_DASHBOARD: string;
|
|
22
23
|
GET_LIST_MENU: string;
|
|
23
24
|
GET_LIST_MENU_PERMISSION: string;
|
package/es/constants/queries.js
CHANGED
|
@@ -27,6 +27,7 @@ export const QUERY_KEYS = {
|
|
|
27
27
|
GET_SAVE_AS_GALLERY_PERMISSION_EMAILS: 'GET_SAVE_AS_GALLERY_PERMISSION_EMAILS',
|
|
28
28
|
// THIRD PARTY
|
|
29
29
|
GET_LIST_FALLBACK_BO: 'GET_LIST_FALLBACK_BO',
|
|
30
|
+
GET_LIST_SAVED_MEDIA: 'GET_LIST_SAVED_MEDIA',
|
|
30
31
|
// Left menu
|
|
31
32
|
GET_DASHBOARD: 'GET_DASHBOARD',
|
|
32
33
|
GET_LIST_MENU: 'GET_LIST_MENU',
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useStoreSavedMedia: (domain: string, slug: string, infos: any) => import("@tanstack/react-query").UseInfiniteQueryResult<import("../../models/SavedMedia").SavedMedia[], unknown>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Libraries
|
|
2
|
+
import { useInfiniteQuery } from '@tanstack/react-query';
|
|
3
|
+
// Services
|
|
4
|
+
import { getListingSavedMedia } from '../../services/MediaTemplateDesign/UploadFile';
|
|
5
|
+
// Constants
|
|
6
|
+
import { QUERY_KEYS } from '../../constants';
|
|
7
|
+
// Hook to fetch data with infinite scrolling
|
|
8
|
+
export const useStoreSavedMedia = (domain, slug, infos) => useInfiniteQuery({
|
|
9
|
+
queryKey: [QUERY_KEYS.GET_LIST_SAVED_MEDIA, domain, slug, infos],
|
|
10
|
+
queryFn: ({ pageParam }) => getListingSavedMedia(domain, slug, infos, pageParam),
|
|
11
|
+
getNextPageParam: (lastPage, pages) => (lastPage.length >= 10 ? pages.length + 1 : undefined),
|
|
12
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SavedMedia } from '@antscorp/antsomi-ui/es/models/SavedMedia';
|
|
2
2
|
import { Upload } from '@antscorp/antsomi-ui/es/models/Upload';
|
|
3
|
-
export declare const getListingSavedMedia: (domainUrl: string, slug: string, infos: any) => Promise<SavedMedia[]>;
|
|
3
|
+
export declare const getListingSavedMedia: (domainUrl: string, slug: string, infos: any, page?: number) => Promise<SavedMedia[]>;
|
|
4
4
|
export declare const createSavedMedia: (domainUrl: string, slug: string, infos: any, data: any) => Promise<any>;
|
|
5
5
|
export declare const deleteSavedMedia: (domainUrl: string, slug: string, infos: any, id: string | number) => Promise<any>;
|
|
6
6
|
export declare const uploadFile: (domainUrl: string, slug: string, infos: any, files: any) => Promise<Upload[]>;
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
import { SavedMedia } from '@antscorp/antsomi-ui/es/models/SavedMedia';
|
|
4
4
|
import { Upload } from '@antscorp/antsomi-ui/es/models/Upload';
|
|
5
5
|
import { services } from '@antscorp/antsomi-ui/es/services';
|
|
6
|
-
export const getListingSavedMedia = async (domainUrl, slug, infos) => {
|
|
6
|
+
export const getListingSavedMedia = async (domainUrl, slug, infos, page = 1) => {
|
|
7
7
|
try {
|
|
8
8
|
const { type = '', ...restInfos } = infos || {};
|
|
9
9
|
const { data } = await services.mediaTemplateDesign.getList({
|
|
10
|
-
API_HOST: `${domainUrl}/${slug}/saved-media/index?type=${type}`,
|
|
10
|
+
API_HOST: `${domainUrl}/${slug}/saved-media/index?type=${type}&page=${page}&limit=10`,
|
|
11
11
|
}, restInfos);
|
|
12
12
|
let savedImages = data?.data || [];
|
|
13
13
|
savedImages = savedImages.map((savedImage) => new SavedMedia(savedImage));
|