@antscorp/antsomi-ui 2.0.57 → 2.0.59
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/icons/LazyIcon/LazyIcon.d.ts +3 -0
- package/es/components/icons/LazyIcon/LazyIcon.js +3 -0
- package/es/components/icons/TaskAltIcon.js +1 -1
- package/es/components/icons/UnsubscribeIcon.d.ts +3 -0
- package/es/components/icons/UnsubscribeIcon.js +7 -0
- package/es/components/icons/UnsubscribersIcon.d.ts +3 -0
- package/es/components/icons/UnsubscribersIcon.js +7 -0
- package/es/components/icons/index.d.ts +3 -0
- package/es/components/icons/index.js +3 -0
- package/es/components/molecules/EditingListV2/EditingList.d.ts +2 -0
- package/es/components/molecules/EditingListV2/EditingList.js +18 -0
- package/es/components/molecules/EditingListV2/components/List/List.d.ts +9 -0
- package/es/components/molecules/EditingListV2/components/List/List.js +48 -0
- package/es/components/molecules/EditingListV2/components/List/index.d.ts +1 -0
- package/es/components/molecules/EditingListV2/components/List/index.js +1 -0
- package/es/components/molecules/EditingListV2/components/Loadable.d.ts +8 -0
- package/es/components/molecules/EditingListV2/components/Loadable.js +2 -0
- package/es/components/molecules/EditingListV2/components/Popover/Popover.d.ts +11 -0
- package/es/components/molecules/EditingListV2/components/Popover/Popover.js +11 -0
- package/es/components/molecules/EditingListV2/components/Popover/index.d.ts +1 -0
- package/es/components/molecules/EditingListV2/components/Popover/index.js +1 -0
- package/es/components/molecules/EditingListV2/components/index.d.ts +3 -0
- package/es/components/molecules/EditingListV2/components/index.js +3 -0
- package/es/components/molecules/EditingListV2/index.d.ts +2 -0
- package/es/components/molecules/EditingListV2/index.js +1 -0
- package/es/components/molecules/EditingListV2/types.d.ts +20 -0
- package/es/components/molecules/EditingListV2/types.js +1 -0
- package/es/components/molecules/EditingListV2/utils.d.ts +27 -0
- package/es/components/molecules/EditingListV2/utils.js +28 -0
- package/es/components/molecules/SearchPopover/components/PopoverAddField/PopoverAddField.js +2 -2
- package/es/components/molecules/SearchPopover/components/PopoverSelect/PopoverSelect.js +4 -4
- package/es/components/molecules/SearchPopover/components/PopoverSelect/styled.js +1 -0
- package/es/components/molecules/SearchPopover/types.d.ts +1 -0
- 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/components/molecules/VirtualizedMenu/types.d.ts +1 -0
- package/es/components/molecules/index.d.ts +1 -0
- package/es/components/molecules/index.js +1 -0
- package/es/constants/queries.d.ts +1 -0
- package/es/constants/queries.js +1 -0
- package/es/constants/theme.js +3 -0
- package/es/locales/en/translation.json +2 -1
- package/es/locales/i18n.d.ts +2 -0
- package/es/locales/vi/translation.json +2 -1
- 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
|
@@ -343,6 +343,7 @@ export declare const LazyIcon: {
|
|
|
343
343
|
TabGroupIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
344
344
|
TableIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
345
345
|
TableVer2Icon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
346
|
+
TaskAltIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
346
347
|
TextIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
347
348
|
ThirdPartyPluginV130Icon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
348
349
|
ThirdPartyPluginV230Icon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
@@ -357,6 +358,8 @@ export declare const LazyIcon: {
|
|
|
357
358
|
UnblockIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
358
359
|
UndoIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
359
360
|
Unknown30Icon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
361
|
+
UnsubscribersIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
362
|
+
UnsubscribeIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
360
363
|
UploadIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
361
364
|
UploadMenuIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
362
365
|
UserActivityIcon: import("react").LazyExoticComponent<import("react").ForwardRefExoticComponent<import("../types").IconProps & import("react").RefAttributes<SVGSVGElement>>>;
|
|
@@ -349,6 +349,7 @@ export const LazyIcon = {
|
|
|
349
349
|
TabGroupIcon: lazy(() => import('../TabGroupIcon').then(m => ({ default: m.TabGroupIcon }))),
|
|
350
350
|
TableIcon: lazy(() => import('../TableIcon').then(m => ({ default: m.TableIcon }))),
|
|
351
351
|
TableVer2Icon: lazy(() => import('../TableVer2Icon').then(m => ({ default: m.TableVer2Icon }))),
|
|
352
|
+
TaskAltIcon: lazy(() => import('../TaskAltIcon').then(m => ({ default: m.TaskAltIcon }))),
|
|
352
353
|
TextIcon: lazy(() => import('../TextIcon').then(m => ({ default: m.TextIcon }))),
|
|
353
354
|
ThirdPartyPluginV130Icon: lazy(() => import('../ThirdPartyPluginV130Icon').then(m => ({ default: m.ThirdPartyPluginV130Icon }))),
|
|
354
355
|
ThirdPartyPluginV230Icon: lazy(() => import('../ThirdPartyPluginV230Icon').then(m => ({ default: m.ThirdPartyPluginV230Icon }))),
|
|
@@ -363,6 +364,8 @@ export const LazyIcon = {
|
|
|
363
364
|
UnblockIcon: lazy(() => import('../UnblockIcon').then(m => ({ default: m.UnblockIcon }))),
|
|
364
365
|
UndoIcon: lazy(() => import('../UndoIcon').then(m => ({ default: m.UndoIcon }))),
|
|
365
366
|
Unknown30Icon: lazy(() => import('../Unknown30Icon').then(m => ({ default: m.Unknown30Icon }))),
|
|
367
|
+
UnsubscribersIcon: lazy(() => import('../UnsubscribersIcon').then(m => ({ default: m.UnsubscribersIcon }))),
|
|
368
|
+
UnsubscribeIcon: lazy(() => import('../UnsubscribeIcon').then(m => ({ default: m.UnsubscribeIcon }))),
|
|
366
369
|
UploadIcon: lazy(() => import('../UploadIcon').then(m => ({ default: m.UploadIcon }))),
|
|
367
370
|
UploadMenuIcon: lazy(() => import('../UploadMenuIcon').then(m => ({ default: m.UploadMenuIcon }))),
|
|
368
371
|
UserActivityIcon: lazy(() => import('../UserActivityIcon').then(m => ({ default: m.UserActivityIcon }))),
|
|
@@ -3,5 +3,5 @@ import { forwardRef } from 'react';
|
|
|
3
3
|
import { useIcon } from './hooks/useIcon';
|
|
4
4
|
export const TaskAltIcon = forwardRef((props, ref) => {
|
|
5
5
|
const { width, height } = useIcon(props);
|
|
6
|
-
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 -960 960 960", fill: "
|
|
6
|
+
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 -960 960 960", fill: "currentColor", ...props, ref: ref, width: width, height: height, children: _jsx("path", { d: "M480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q65 0 123 19t107 53l-58 59q-38-24-81-37.5T480-800q-133 0-226.5 93.5T160-480q0 133 93.5 226.5T480-160q133 0 226.5-93.5T800-480q0-18-2-36t-6-35l65-65q11 32 17 66t6 70q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm-56-216L254-466l56-56 114 114 400-401 56 56-456 457Z" }) }));
|
|
7
7
|
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { useIcon } from './hooks/useIcon';
|
|
4
|
+
export const UnsubscribeIcon = forwardRef((props, ref) => {
|
|
5
|
+
const { width, height } = useIcon(props);
|
|
6
|
+
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 -960 960 960", fill: "currentColor", ...props, ref: ref, width: width, height: height, children: _jsx("path", { d: "M480-440 160-640v400h320q0 21 3 40.5t9 39.5H160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v228q-18-9-38.5-15t-41.5-9v-124L480-440Zm0-80 320-200H160l320 200ZM760-40q-83 0-141.5-58.5T560-240q0-83 58.5-141.5T760-440q83 0 141.5 58.5T960-240q0 83-58.5 141.5T760-40ZM640-220h240v-40H640v40Zm-480-20v-480 480Z" }) }));
|
|
7
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { useIcon } from './hooks/useIcon';
|
|
4
|
+
export const UnsubscribersIcon = forwardRef((props, ref) => {
|
|
5
|
+
const { width, height } = useIcon(props);
|
|
6
|
+
return (_jsx("svg", { viewBox: "0 0 30 30", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, ref: ref, width: width, height: height, children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M16.2695 20.3125C16.2695 21.3145 16.4839 22.2665 16.8693 23.125H2.5V21.8945L5.01953 19.375V13.1641C5.01953 11.2109 5.50781 9.51172 6.48438 8.06641C7.5 6.62109 8.88672 5.68359 10.6445 5.25391V4.375C10.6445 3.86719 10.8203 3.4375 11.1719 3.08594C11.5234 2.69531 11.9727 2.5 12.5195 2.5C13.0664 2.5 13.5156 2.69531 13.8672 3.08594C14.2188 3.4375 14.3945 3.86719 14.3945 4.375V5.25391C16.1523 5.68359 17.5195 6.62109 18.4961 8.06641C19.5117 9.51172 20.0195 11.2109 20.0195 13.1641V14.1871C17.7935 15.3251 16.2695 17.6408 16.2695 20.3125ZM12.5195 26.875C11.8164 26.875 11.2109 26.6406 10.7031 26.1719C10.2344 25.7031 10 25.1172 10 24.4141H15.0391C15.0391 25.0781 14.7852 25.6641 14.2773 26.1719C13.7695 26.6406 13.1836 26.875 12.5195 26.875ZM28.7695 20.3125C28.7695 23.4191 26.2511 25.9375 23.1445 25.9375C20.0379 25.9375 17.5195 23.4191 17.5195 20.3125C17.5195 17.2059 20.0379 14.6875 23.1445 14.6875C26.2511 14.6875 28.7695 17.2059 28.7695 20.3125ZM26.2695 19.6875V20.9375H20.0195V19.6875H26.2695Z", fill: "currentColor" }) }));
|
|
7
|
+
});
|
|
@@ -339,6 +339,7 @@ export { SystemRunningIcon } from './SystemRunningIcon';
|
|
|
339
339
|
export { TabGroupIcon } from './TabGroupIcon';
|
|
340
340
|
export { TableIcon } from './TableIcon';
|
|
341
341
|
export { TableVer2Icon } from './TableVer2Icon';
|
|
342
|
+
export { TaskAltIcon } from './TaskAltIcon';
|
|
342
343
|
export { TextIcon } from './TextIcon';
|
|
343
344
|
export { ThirdPartyPluginV130Icon } from './ThirdPartyPluginV130Icon';
|
|
344
345
|
export { ThirdPartyPluginV230Icon } from './ThirdPartyPluginV230Icon';
|
|
@@ -353,6 +354,8 @@ export { TipsIdeaLight30Icon } from './TipsIdeaLight30Icon';
|
|
|
353
354
|
export { UnblockIcon } from './UnblockIcon';
|
|
354
355
|
export { UndoIcon } from './UndoIcon';
|
|
355
356
|
export { Unknown30Icon } from './Unknown30Icon';
|
|
357
|
+
export { UnsubscribersIcon } from './UnsubscribersIcon';
|
|
358
|
+
export { UnsubscribeIcon } from './UnsubscribeIcon';
|
|
356
359
|
export { UploadIcon } from './UploadIcon';
|
|
357
360
|
export { UploadMenuIcon } from './UploadMenuIcon';
|
|
358
361
|
export { UserActivityIcon } from './UserActivityIcon';
|
|
@@ -339,6 +339,7 @@ export { SystemRunningIcon } from './SystemRunningIcon';
|
|
|
339
339
|
export { TabGroupIcon } from './TabGroupIcon';
|
|
340
340
|
export { TableIcon } from './TableIcon';
|
|
341
341
|
export { TableVer2Icon } from './TableVer2Icon';
|
|
342
|
+
export { TaskAltIcon } from './TaskAltIcon';
|
|
342
343
|
export { TextIcon } from './TextIcon';
|
|
343
344
|
export { ThirdPartyPluginV130Icon } from './ThirdPartyPluginV130Icon';
|
|
344
345
|
export { ThirdPartyPluginV230Icon } from './ThirdPartyPluginV230Icon';
|
|
@@ -353,6 +354,8 @@ export { TipsIdeaLight30Icon } from './TipsIdeaLight30Icon';
|
|
|
353
354
|
export { UnblockIcon } from './UnblockIcon';
|
|
354
355
|
export { UndoIcon } from './UndoIcon';
|
|
355
356
|
export { Unknown30Icon } from './Unknown30Icon';
|
|
357
|
+
export { UnsubscribersIcon } from './UnsubscribersIcon';
|
|
358
|
+
export { UnsubscribeIcon } from './UnsubscribeIcon';
|
|
356
359
|
export { UploadIcon } from './UploadIcon';
|
|
357
360
|
export { UploadMenuIcon } from './UploadMenuIcon';
|
|
358
361
|
export { UserActivityIcon } from './UserActivityIcon';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Libraries
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
// Components
|
|
5
|
+
import { Suspense } from '../../atoms';
|
|
6
|
+
import { ListItem, LazyComponent } from './components';
|
|
7
|
+
const { Popover } = LazyComponent;
|
|
8
|
+
export const EditingListV2 = (props) => {
|
|
9
|
+
const { isLoading = false, addButtonLabel = 'Add', options = [], selected = [], removable = true, popupPlacement = 'leftBottom', className, onChange, } = props;
|
|
10
|
+
const popoverOptions = useMemo(() => options.filter(opt => !opt.errorMessage), [options]);
|
|
11
|
+
const selectedOptions = useMemo(() => options.filter(opt => selected.includes(opt.key)), [selected, options]);
|
|
12
|
+
// const isSelectAll = selectedOptions.length === options.length;
|
|
13
|
+
const handleRemove = (removedKey) => {
|
|
14
|
+
const selectedKeys = selectedOptions.filter(opt => opt.key !== removedKey).map(opt => opt.key);
|
|
15
|
+
onChange?.(selectedKeys);
|
|
16
|
+
};
|
|
17
|
+
return (_jsxs("div", { className: className, children: [_jsx(ListItem, { isLoading: isLoading, selectOptions: selectedOptions, removable: removable, onClickRemove: handleRemove }), !isLoading && (_jsx(Suspense, { children: _jsx(Popover, { placement: popupPlacement, options: popoverOptions, selected: selected, addButtonLabel: addButtonLabel, onChange: onChange }) }))] }));
|
|
18
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Option } from '../../types';
|
|
2
|
+
type ListProps = {
|
|
3
|
+
isLoading: boolean;
|
|
4
|
+
selectOptions: Option[];
|
|
5
|
+
removable?: boolean;
|
|
6
|
+
onClickRemove?: (key: string) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare const ListItem: (props: ListProps) => import("react/jsx-runtime").JSX.Element | undefined;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Libraries
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { isEmpty } from 'lodash';
|
|
5
|
+
// Components
|
|
6
|
+
import { Spin, Typography, Tooltip } from '../../../../atoms';
|
|
7
|
+
import { List } from 'antd';
|
|
8
|
+
import { CloseIcon, WarningIcon } from '@antscorp/antsomi-ui/es/components/icons';
|
|
9
|
+
// Utils
|
|
10
|
+
import { CLS } from '../../utils';
|
|
11
|
+
// Constants
|
|
12
|
+
import { globalToken } from '@antscorp/antsomi-ui/es/constants';
|
|
13
|
+
export const ListItem = (props) => {
|
|
14
|
+
const { isLoading, selectOptions, onClickRemove, removable } = props;
|
|
15
|
+
const [hover, setHover] = useState('');
|
|
16
|
+
const renderLabel = (label) => {
|
|
17
|
+
if (typeof label === 'string') {
|
|
18
|
+
return _jsx(Typography.Text, { ellipsis: { tooltip: true }, children: label });
|
|
19
|
+
}
|
|
20
|
+
return label;
|
|
21
|
+
};
|
|
22
|
+
const items = selectOptions.map(opt => ({
|
|
23
|
+
className: CLS.ListItem.default,
|
|
24
|
+
key: opt.key,
|
|
25
|
+
errorMessage: opt.errorMessage,
|
|
26
|
+
label: renderLabel(opt.label),
|
|
27
|
+
}));
|
|
28
|
+
if (isLoading) {
|
|
29
|
+
return _jsx(Spin, { indicatorSize: 24 });
|
|
30
|
+
}
|
|
31
|
+
if (isEmpty(selectOptions)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
return (_jsx(List, { dataSource: items, renderItem: item => (_jsxs(List.Item, { style: {
|
|
35
|
+
display: 'flex',
|
|
36
|
+
alignItems: 'center',
|
|
37
|
+
border: `1px solid ${item.errorMessage ? '#EF3340' : '#B8CFE6'}`,
|
|
38
|
+
borderRadius: '4px',
|
|
39
|
+
padding: '10px',
|
|
40
|
+
marginBottom: '10px',
|
|
41
|
+
minHeight: '40px',
|
|
42
|
+
}, onMouseEnter: () => setHover(item.key), onMouseLeave: () => setHover(''), children: [item.label, _jsxs("div", { style: {
|
|
43
|
+
flexShrink: 0,
|
|
44
|
+
display: 'flex',
|
|
45
|
+
alignItems: 'center',
|
|
46
|
+
gap: '5px',
|
|
47
|
+
}, children: [item.errorMessage && (_jsx(Tooltip, { title: item.errorMessage, children: _jsx(WarningIcon, { size: 18 }) })), hover === item.key && removable && (_jsx(CloseIcon, { size: 18, color: globalToken?.bw8, style: { cursor: 'pointer' }, onClick: onClickRemove ? () => onClickRemove(item.key) : undefined }))] })] })) }));
|
|
48
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ListItem } from './List';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ListItem } from './List';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export declare const Popover: import("react").LazyExoticComponent<(props: {
|
|
3
|
+
placement?: "leftTop" | "leftBottom" | "rightTop" | "rightBottom" | "left" | "right" | "bottom" | "top" | "bottomLeft" | "bottomRight" | "topLeft" | "topRight" | undefined;
|
|
4
|
+
options: import("../types").Option[];
|
|
5
|
+
selected: string[];
|
|
6
|
+
addButtonLabel: import("react").ReactNode;
|
|
7
|
+
onChange?: ((selected: string[]) => void) | undefined;
|
|
8
|
+
}) => import("react/jsx-runtime").JSX.Element>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { Option } from '../../types';
|
|
3
|
+
type PopoverProps = {
|
|
4
|
+
placement?: 'left' | 'right' | 'top' | 'bottom' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom';
|
|
5
|
+
options: Option[];
|
|
6
|
+
selected: string[];
|
|
7
|
+
addButtonLabel: React.ReactNode;
|
|
8
|
+
onChange?: (selected: string[]) => void;
|
|
9
|
+
};
|
|
10
|
+
export declare const Popover: (props: PopoverProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/* eslint-disable react/jsx-boolean-value */
|
|
3
|
+
// Components
|
|
4
|
+
import { Button } from '@antscorp/antsomi-ui/es/components/atoms';
|
|
5
|
+
import { PopoverAddField } from '../../../SearchPopover';
|
|
6
|
+
// Icons
|
|
7
|
+
import { AddIcon } from '../../../../icons';
|
|
8
|
+
export const Popover = (props) => {
|
|
9
|
+
const { options, selected, addButtonLabel, onChange, placement } = props;
|
|
10
|
+
return (_jsx(PopoverAddField, { style: { margin: 0, position: 'absolute', width: '300px' }, fields: options, placement: placement, selected: selected, onApply: onChange, isAllowEmpty: true, children: _jsxs(Button, { type: "text", style: { gap: 2 }, children: [_jsx(AddIcon, { size: 14 }), addButtonLabel] }) }));
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Popover } from './Popover';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Popover } from './Popover';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { EditingListV2 } from './EditingList';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export type Option = {
|
|
3
|
+
key: string;
|
|
4
|
+
label: React.ReactNode;
|
|
5
|
+
errorMessage?: string;
|
|
6
|
+
search?: string;
|
|
7
|
+
};
|
|
8
|
+
export type EditingListProps = {
|
|
9
|
+
popupPlacement?: 'left' | 'right' | 'top' | 'bottom' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom';
|
|
10
|
+
addButtonLabel?: string;
|
|
11
|
+
options?: Option[];
|
|
12
|
+
selected?: string[];
|
|
13
|
+
showNum?: boolean;
|
|
14
|
+
className?: string;
|
|
15
|
+
isLoading?: boolean;
|
|
16
|
+
emptyDescription?: string;
|
|
17
|
+
removable?: boolean;
|
|
18
|
+
isAllowEmpty?: boolean;
|
|
19
|
+
onChange?: (selected: string[]) => void;
|
|
20
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const componentCls: (className: string) => string;
|
|
2
|
+
export declare const CLS: {
|
|
3
|
+
readonly Root: {
|
|
4
|
+
readonly default: string;
|
|
5
|
+
};
|
|
6
|
+
readonly Title: {
|
|
7
|
+
readonly default: string;
|
|
8
|
+
};
|
|
9
|
+
readonly Search: {
|
|
10
|
+
readonly default: string;
|
|
11
|
+
};
|
|
12
|
+
readonly RemoveButton: {
|
|
13
|
+
readonly default: string;
|
|
14
|
+
};
|
|
15
|
+
readonly AddButton: {
|
|
16
|
+
readonly default: string;
|
|
17
|
+
};
|
|
18
|
+
readonly ListWapper: {
|
|
19
|
+
readonly default: string;
|
|
20
|
+
};
|
|
21
|
+
readonly List: {
|
|
22
|
+
readonly default: string;
|
|
23
|
+
};
|
|
24
|
+
readonly ListItem: {
|
|
25
|
+
readonly default: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { antsomiClsx } from '@antscorp/antsomi-ui/es/utils';
|
|
2
|
+
export const componentCls = antsomiClsx('editing-list');
|
|
3
|
+
export const CLS = {
|
|
4
|
+
Root: {
|
|
5
|
+
default: componentCls('root'),
|
|
6
|
+
},
|
|
7
|
+
Title: {
|
|
8
|
+
default: componentCls('title'),
|
|
9
|
+
},
|
|
10
|
+
Search: {
|
|
11
|
+
default: componentCls('search'),
|
|
12
|
+
},
|
|
13
|
+
RemoveButton: {
|
|
14
|
+
default: componentCls('remove-btn'),
|
|
15
|
+
},
|
|
16
|
+
AddButton: {
|
|
17
|
+
default: componentCls('add-btn'),
|
|
18
|
+
},
|
|
19
|
+
ListWapper: {
|
|
20
|
+
default: componentCls('selected-list-wrapper'),
|
|
21
|
+
},
|
|
22
|
+
List: {
|
|
23
|
+
default: componentCls('selected-list'),
|
|
24
|
+
},
|
|
25
|
+
ListItem: {
|
|
26
|
+
default: componentCls('selected-list-item'),
|
|
27
|
+
},
|
|
28
|
+
};
|
|
@@ -6,7 +6,7 @@ import { PopoverSelect } from '../PopoverSelect';
|
|
|
6
6
|
import { Flex, Typography } from 'antd';
|
|
7
7
|
import { IconField } from '@antscorp/antsomi-ui/es/components/atoms/IconField';
|
|
8
8
|
export const PopoverAddField = (props) => {
|
|
9
|
-
const { fields, onSearchPredicate, className, children, ...rest } = props;
|
|
9
|
+
const { fields, onSearchPredicate, className, children, isAllowEmpty, ...rest } = props;
|
|
10
10
|
const originalFieldByKey = useMemo(() => new Map(fields.map(field => [field.key, field])), [fields]);
|
|
11
11
|
const handleOnSearchPredicate = useCallback((option) => {
|
|
12
12
|
const originalField = originalFieldByKey.get(option.key);
|
|
@@ -26,5 +26,5 @@ export const PopoverAddField = (props) => {
|
|
|
26
26
|
selected: params.selected.includes(field.key),
|
|
27
27
|
})] })),
|
|
28
28
|
})), [fields]);
|
|
29
|
-
return (_jsx(PopoverSelect, { ...rest, options: options, onSearchPredicate: handleOnSearchPredicate, className: clsx(className, 'ants-popover-add-fields'), children: children || (_jsxs(Button, { type: "text", children: [_jsx(Icon, { type: "icon-ants-plus-slim", size: 14 }), "Add fields"] })) }));
|
|
29
|
+
return (_jsx(PopoverSelect, { ...rest, options: options, onSearchPredicate: handleOnSearchPredicate, className: clsx(className, 'ants-popover-add-fields'), isAllowEmpty: isAllowEmpty || false, children: children || (_jsxs(Button, { type: "text", children: [_jsx(Icon, { type: "icon-ants-plus-slim", size: 14 }), "Add fields"] })) }));
|
|
30
30
|
};
|
|
@@ -12,7 +12,7 @@ import { VirtualizedMenu } from '../../../VirtualizedMenu';
|
|
|
12
12
|
import { ITEM_SIZE, ITEM_SPACING } from '../../../VirtualizedMenu/config';
|
|
13
13
|
const { t } = i18nInstance;
|
|
14
14
|
export const PopoverSelect = (props) => {
|
|
15
|
-
const { open: openProp, selected, options: optionsProp = [], inputSearchProps = {}, children, showAllLabel = 'Show all', showSelectedLabel = 'Show selected', selectAllLabel = 'Select all', deselectAllLabel = 'Unselect all', menuProps = {}, onCancel, onApply, onSearchPredicate, ...rest } = props;
|
|
15
|
+
const { open: openProp, selected, options: optionsProp = [], inputSearchProps = {}, children, showAllLabel = 'Show all', showSelectedLabel = 'Show selected', selectAllLabel = 'Select all', deselectAllLabel = 'Unselect all', menuProps = {}, isAllowEmpty = false, onCancel, onApply, onSearchPredicate, ...rest } = props;
|
|
16
16
|
const itemSize = menuProps.itemSize || ITEM_SIZE;
|
|
17
17
|
const itemSpacing = menuProps.itemSpacing || ITEM_SPACING;
|
|
18
18
|
const { value: searchValue, ...restInputSearchProps } = inputSearchProps;
|
|
@@ -24,7 +24,7 @@ export const PopoverSelect = (props) => {
|
|
|
24
24
|
const [selectedKeys, setSelectedKeys] = useState(new Set());
|
|
25
25
|
const [search, setSearch] = useState('');
|
|
26
26
|
const [showSelected, setShowSelected] = useState(false);
|
|
27
|
-
const applyDisabled = selectedKeys.size === 0;
|
|
27
|
+
const applyDisabled = selectedKeys.size === 0 && !isAllowEmpty;
|
|
28
28
|
const options = useMemo(() => typeof optionsProp === 'function'
|
|
29
29
|
? optionsProp({ selected: [...selectedKeys] })
|
|
30
30
|
: optionsProp, [optionsProp, selectedKeys]);
|
|
@@ -109,11 +109,11 @@ export const PopoverSelect = (props) => {
|
|
|
109
109
|
key: opt.key,
|
|
110
110
|
label: (_jsx(Checkbox, { onChange: e => handleToggleField(opt, e.target.checked), checked: selectedKeys.has(opt.key), children: renderCheckBoxLabel(opt) })),
|
|
111
111
|
}));
|
|
112
|
-
return (_jsx(SearchPopover, { destroyTooltipOnHide: true, ...rest, content: _jsxs(_Fragment, { children: [optionsProp.length > 0 && (_jsxs(StyledAction, { children: [_jsx(Button, { type: "link", size: "small", onClick: () => setShowSelected(current => !current), children: showSelected ? showAllLabel : showSelectedLabel }), selectedKeys.size === options.length ? (_jsx(Button, { type: "link", onClick: handleDeselectAll, children: deselectAllLabel })) : (_jsx(Button, { type: "link", onClick: handleSelectAll, children: selectAllLabel }))] })), filteredOptions.length ? (_jsx(StyledListFieldsWrapper, { "$minHeight": calDefaultListHeightInPopover({
|
|
112
|
+
return (_jsx(SearchPopover, { destroyTooltipOnHide: true, placement: "bottomLeft", ...rest, content: _jsxs(_Fragment, { children: [optionsProp.length > 0 && (_jsxs(StyledAction, { children: [_jsx(Button, { type: "link", size: "small", onClick: () => setShowSelected(current => !current), children: showSelected ? showAllLabel : showSelectedLabel }), selectedKeys.size === options.length ? (_jsx(Button, { type: "link", onClick: handleDeselectAll, children: deselectAllLabel })) : (_jsx(Button, { type: "link", onClick: handleSelectAll, children: selectAllLabel }))] })), filteredOptions.length ? (_jsx(StyledListFieldsWrapper, { "$minHeight": calDefaultListHeightInPopover({
|
|
113
113
|
listLength: filteredOptions.length,
|
|
114
114
|
itemSize,
|
|
115
115
|
itemSpacing,
|
|
116
|
-
}), children: _jsx(VirtualizedMenu, { ...menuProps, itemSize: itemSize, items: items }) })) : (_jsx(EmptyData, { showIcon: false, description: t(translations.noData).toString() })), _jsxs(StyledFooter, { children: [_jsx(Button, { onClick: handleCancel, children: "Cancel" }), _jsx(Button, { onClick: handleApply, disabled: applyDisabled, type: "primary", children: "Apply" })] })] }), trigger: ['click'],
|
|
116
|
+
}), children: _jsx(VirtualizedMenu, { ...menuProps, itemSize: itemSize, items: items }) })) : (_jsx(EmptyData, { showIcon: false, description: t(translations.noData).toString() })), _jsxs(StyledFooter, { children: [_jsx(Button, { onClick: handleCancel, children: "Cancel" }), _jsx(Button, { onClick: handleApply, disabled: applyDisabled, type: "primary", children: "Apply" })] })] }), trigger: ['click'], open: open, inputSearchProps: {
|
|
117
117
|
...restInputSearchProps,
|
|
118
118
|
value: search,
|
|
119
119
|
onAfterChange: handleOnSearch,
|
|
@@ -4,6 +4,7 @@ import React, { PropsWithChildren } from 'react';
|
|
|
4
4
|
import { MenuInlineProps } from '../VirtualizedMenu/types';
|
|
5
5
|
export type SearchPopoverProps = PropsWithChildren<{
|
|
6
6
|
inputSearchProps?: InputProps;
|
|
7
|
+
isAllowEmpty?: boolean;
|
|
7
8
|
} & PopoverProps>;
|
|
8
9
|
export type Option = {
|
|
9
10
|
key: string;
|
|
@@ -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>;
|
|
@@ -6,6 +6,7 @@ export { Select } from './Select';
|
|
|
6
6
|
export { SelectV2 } from './SelectV2';
|
|
7
7
|
export { DatePicker } from './DatePicker';
|
|
8
8
|
export { ChatBox, ChatBoxInsight } from './ChatBox';
|
|
9
|
+
export { EditingListV2 } from './EditingListV2';
|
|
9
10
|
export { PopupDraggable } from './PopupDraggable';
|
|
10
11
|
export { CaptureScreen } from './CaptureScreen';
|
|
11
12
|
export { SettingWrapper } from './SettingWrapper';
|
|
@@ -6,6 +6,7 @@ export { Select } from './Select';
|
|
|
6
6
|
export { SelectV2 } from './SelectV2';
|
|
7
7
|
export { DatePicker } from './DatePicker';
|
|
8
8
|
export { ChatBox, ChatBoxInsight } from './ChatBox';
|
|
9
|
+
export { EditingListV2 } from './EditingListV2';
|
|
9
10
|
export { PopupDraggable } from './PopupDraggable';
|
|
10
11
|
export { CaptureScreen } from './CaptureScreen';
|
|
11
12
|
export { SettingWrapper } from './SettingWrapper';
|
|
@@ -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',
|
package/es/constants/theme.js
CHANGED
|
@@ -103,6 +103,9 @@ THEME.components = {
|
|
|
103
103
|
colorTextDisabled: THEME.token?.bw0,
|
|
104
104
|
textHoverBg: '#F2F9FF',
|
|
105
105
|
marginXS: 0,
|
|
106
|
+
primaryShadow: 'none',
|
|
107
|
+
dangerShadow: 'none',
|
|
108
|
+
defaultShadow: 'none',
|
|
106
109
|
/* Text type */
|
|
107
110
|
colorBgTextHover: THEME.token?.blue,
|
|
108
111
|
colorBgTextActive: THEME.token?.blue1_1,
|
package/es/locales/i18n.d.ts
CHANGED
|
@@ -3408,6 +3408,7 @@ export declare const translationsJson: {
|
|
|
3408
3408
|
_builtIn: string;
|
|
3409
3409
|
_standard: string;
|
|
3410
3410
|
_ipRestriction: string;
|
|
3411
|
+
_unsubscribers: string;
|
|
3411
3412
|
};
|
|
3412
3413
|
};
|
|
3413
3414
|
layout: {
|
|
@@ -6390,6 +6391,7 @@ export declare const translationsJson: {
|
|
|
6390
6391
|
_builtIn: string;
|
|
6391
6392
|
_standard: string;
|
|
6392
6393
|
_ipRestriction: string;
|
|
6394
|
+
_unsubscribers: string;
|
|
6393
6395
|
};
|
|
6394
6396
|
};
|
|
6395
6397
|
layout: {
|
|
@@ -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));
|