mirror of https://github.com/buster-so/buster.git
add and remove from collection works 📖
This commit is contained in:
parent
77d9203383
commit
4e5ac6f752
|
@ -106,7 +106,7 @@ export const updateCollectionShare = async ({
|
||||||
|
|
||||||
export const addAssetToCollection = async ({
|
export const addAssetToCollection = async ({
|
||||||
id,
|
id,
|
||||||
...params
|
assets
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
assets: {
|
assets: {
|
||||||
|
@ -114,13 +114,14 @@ export const addAssetToCollection = async ({
|
||||||
id: string;
|
id: string;
|
||||||
}[];
|
}[];
|
||||||
}) => {
|
}) => {
|
||||||
return mainApi.post<null>(`/collections/${id}/assets`, params).then((res) => res.data);
|
return mainApi.post<null>(`/collections/${id}/assets`, { assets }).then((res) => res.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeAssetFromCollection = async (
|
export const removeAssetFromCollection = async ({
|
||||||
params: Parameters<typeof addAssetToCollection>[0]
|
id,
|
||||||
) => {
|
assets
|
||||||
|
}: Parameters<typeof addAssetToCollection>[0]) => {
|
||||||
return mainApi
|
return mainApi
|
||||||
.delete<null>(`/collections/${params.id}/assets`, { data: params })
|
.delete<null>(`/collections/${id}/assets`, { data: { assets } })
|
||||||
.then((res) => res.data);
|
.then((res) => res.data);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
import { useGetMetricsList } from '@/api/buster_rest/metrics';
|
|
||||||
import { useDebounce, useMemoizedFn } from '@/hooks';
|
import { useDebounce, useMemoizedFn } from '@/hooks';
|
||||||
import React, { useLayoutEffect, useMemo, useState } from 'react';
|
import React, { useLayoutEffect, useMemo, useState } from 'react';
|
||||||
import { InputSelectModal, InputSelectModalProps } from '@/components/ui/modal/InputSelectModal';
|
import { InputSelectModal, InputSelectModalProps } from '@/components/ui/modal/InputSelectModal';
|
||||||
import { formatDate } from '@/lib';
|
import { formatDate } from '@/lib';
|
||||||
import { Button } from '@/components/ui/buttons';
|
import { Button } from '@/components/ui/buttons';
|
||||||
import { useGetDashboardsList } from '@/api/buster_rest/dashboards';
|
|
||||||
import {
|
import {
|
||||||
useAddAndRemoveAssetsFromCollection,
|
useAddAndRemoveAssetsFromCollection,
|
||||||
useGetCollection
|
useGetCollection
|
||||||
} from '@/api/buster_rest/collections';
|
} from '@/api/buster_rest/collections';
|
||||||
import { Text } from '@/components/ui/typography';
|
import { Text } from '@/components/ui/typography';
|
||||||
import { ASSET_ICONS } from '../config/assetIcons';
|
import { ASSET_ICONS } from '../config/assetIcons';
|
||||||
import pluralize from 'pluralize';
|
|
||||||
import { useSearch } from '@/api/buster_rest/search';
|
import { useSearch } from '@/api/buster_rest/search';
|
||||||
import { ShareAssetType } from '@/api/asset_interfaces/share';
|
|
||||||
|
|
||||||
export const AddToCollectionModal: React.FC<{
|
export const AddToCollectionModal: React.FC<{
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
@ -103,6 +99,61 @@ export const AddToCollectionModal: React.FC<{
|
||||||
return originalIds.length !== newIds.length || originalIds.some((id) => !newIds.includes(id));
|
return originalIds.length !== newIds.length || originalIds.some((id) => !newIds.includes(id));
|
||||||
}, [originalIds, selectedAssets]);
|
}, [originalIds, selectedAssets]);
|
||||||
|
|
||||||
|
const removedAssetCount = useMemo(() => {
|
||||||
|
return originalIds.filter((id) => !selectedAssets.includes(id)).length;
|
||||||
|
}, [originalIds, selectedAssets]);
|
||||||
|
|
||||||
|
const addedAssetCount = useMemo(() => {
|
||||||
|
return selectedAssets.filter((id) => !originalIds.includes(id)).length;
|
||||||
|
}, [originalIds, selectedAssets]);
|
||||||
|
|
||||||
|
const primaryButtonText = useMemo(() => {
|
||||||
|
if (!isFetchedCollection) {
|
||||||
|
return 'Loading assets...';
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasRemovedItems = removedAssetCount > 0;
|
||||||
|
const hasAddedItems = addedAssetCount > 0;
|
||||||
|
|
||||||
|
if (hasRemovedItems && hasAddedItems) {
|
||||||
|
return `Update collection`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasRemovedItems) {
|
||||||
|
return `Remove assets`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasAddedItems) {
|
||||||
|
return `Add assets`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `Update collection`;
|
||||||
|
}, [isFetchedCollection, removedAssetCount, addedAssetCount]);
|
||||||
|
|
||||||
|
const primaryButtonTooltipText = useMemo(() => {
|
||||||
|
if (!isFetchedCollection) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasRemovedItems = removedAssetCount > 0;
|
||||||
|
const hasAddedItems = addedAssetCount > 0;
|
||||||
|
const returnText: string[] = [];
|
||||||
|
|
||||||
|
if (!hasRemovedItems && !hasAddedItems) {
|
||||||
|
return 'No changes to update';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasRemovedItems) {
|
||||||
|
returnText.push(`Removing ${removedAssetCount}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasAddedItems) {
|
||||||
|
returnText.push(`Adding ${addedAssetCount}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnText.join(', ');
|
||||||
|
}, [isFetchedCollection, addedAssetCount, removedAssetCount]);
|
||||||
|
|
||||||
const emptyState = useMemo(() => {
|
const emptyState = useMemo(() => {
|
||||||
if (rows.length === 0) {
|
if (rows.length === 0) {
|
||||||
return 'No assets found';
|
return 'No assets found';
|
||||||
|
@ -123,18 +174,19 @@ export const AddToCollectionModal: React.FC<{
|
||||||
onClick: onClose
|
onClick: onClose
|
||||||
},
|
},
|
||||||
primaryButton: {
|
primaryButton: {
|
||||||
text:
|
text: primaryButtonText,
|
||||||
selectedAssets.length === 0
|
|
||||||
? 'Update collection'
|
|
||||||
: `Add ${selectedAssets.length} ${pluralize('asset', selectedAssets.length)} to collection`,
|
|
||||||
onClick: handleAddAndRemoveMetrics,
|
onClick: handleAddAndRemoveMetrics,
|
||||||
disabled: !isSelectedChanged,
|
disabled: !isSelectedChanged,
|
||||||
tooltip: isSelectedChanged
|
tooltip: primaryButtonTooltipText
|
||||||
? `Adding ${selectedAssets.length} assets`
|
|
||||||
: 'No changes to update'
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [selectedAssets.length, isSelectedChanged, handleAddAndRemoveMetrics]);
|
}, [
|
||||||
|
selectedAssets.length,
|
||||||
|
isSelectedChanged,
|
||||||
|
handleAddAndRemoveMetrics,
|
||||||
|
primaryButtonText,
|
||||||
|
primaryButtonTooltipText
|
||||||
|
]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (isFetchedCollection) {
|
if (isFetchedCollection) {
|
||||||
|
|
|
@ -189,7 +189,6 @@ export const AddToDashboardModal: React.FC<{
|
||||||
emptyState={emptyState}
|
emptyState={emptyState}
|
||||||
searchText={searchTerm}
|
searchText={searchTerm}
|
||||||
handleSearchChange={setSearchTerm}
|
handleSearchChange={setSearchTerm}
|
||||||
className="data-[state=closed]:slide-out-to-top-[5%]! data-[state=open]:slide-in-from-top-[5%]! top-28 translate-y-0"
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { useDebounceSearch } from '@/hooks';
|
||||||
import { VisuallyHidden } from '@radix-ui/react-visually-hidden';
|
import { VisuallyHidden } from '@radix-ui/react-visually-hidden';
|
||||||
import { DialogDescription, DialogTitle } from '@radix-ui/react-dialog';
|
import { DialogDescription, DialogTitle } from '@radix-ui/react-dialog';
|
||||||
import { Text } from '../typography';
|
import { Text } from '../typography';
|
||||||
|
import { cn } from '@/lib/classMerge';
|
||||||
|
|
||||||
export interface InputSelectModalProps extends Omit<BorderedModalProps, 'children'> {
|
export interface InputSelectModalProps extends Omit<BorderedModalProps, 'children'> {
|
||||||
inputPlaceholder?: string;
|
inputPlaceholder?: string;
|
||||||
|
@ -25,6 +26,7 @@ export const InputSelectModal = React.memo(
|
||||||
columns,
|
columns,
|
||||||
rows,
|
rows,
|
||||||
emptyState,
|
emptyState,
|
||||||
|
className,
|
||||||
onSelectChange,
|
onSelectChange,
|
||||||
selectedRowKeys,
|
selectedRowKeys,
|
||||||
searchText,
|
searchText,
|
||||||
|
@ -51,7 +53,13 @@ export const InputSelectModal = React.memo(
|
||||||
}, [searchText, handleSearchChange, inputPlaceholder, rows.length]);
|
}, [searchText, handleSearchChange, inputPlaceholder, rows.length]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BorderedModal header={memoizedHeader} {...props}>
|
<BorderedModal
|
||||||
|
header={memoizedHeader}
|
||||||
|
className={cn(
|
||||||
|
'data-[state=closed]:slide-out-to-top-[5%]! data-[state=open]:slide-in-from-top-[5%]! top-28 translate-y-0',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}>
|
||||||
<div
|
<div
|
||||||
className="max-h-[65vh]"
|
className="max-h-[65vh]"
|
||||||
style={{
|
style={{
|
||||||
|
|
Loading…
Reference in New Issue