add and remove from collection works 📖

This commit is contained in:
Nate Kelley 2025-04-09 14:46:45 -06:00
parent 77d9203383
commit 4e5ac6f752
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
4 changed files with 80 additions and 20 deletions

View File

@ -106,7 +106,7 @@ export const updateCollectionShare = async ({
export const addAssetToCollection = async ({
id,
...params
assets
}: {
id: string;
assets: {
@ -114,13 +114,14 @@ export const addAssetToCollection = async ({
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 (
params: Parameters<typeof addAssetToCollection>[0]
) => {
export const removeAssetFromCollection = async ({
id,
assets
}: Parameters<typeof addAssetToCollection>[0]) => {
return mainApi
.delete<null>(`/collections/${params.id}/assets`, { data: params })
.delete<null>(`/collections/${id}/assets`, { data: { assets } })
.then((res) => res.data);
};

View File

@ -1,19 +1,15 @@
import { useGetMetricsList } from '@/api/buster_rest/metrics';
import { useDebounce, useMemoizedFn } from '@/hooks';
import React, { useLayoutEffect, useMemo, useState } from 'react';
import { InputSelectModal, InputSelectModalProps } from '@/components/ui/modal/InputSelectModal';
import { formatDate } from '@/lib';
import { Button } from '@/components/ui/buttons';
import { useGetDashboardsList } from '@/api/buster_rest/dashboards';
import {
useAddAndRemoveAssetsFromCollection,
useGetCollection
} from '@/api/buster_rest/collections';
import { Text } from '@/components/ui/typography';
import { ASSET_ICONS } from '../config/assetIcons';
import pluralize from 'pluralize';
import { useSearch } from '@/api/buster_rest/search';
import { ShareAssetType } from '@/api/asset_interfaces/share';
export const AddToCollectionModal: React.FC<{
open: boolean;
@ -103,6 +99,61 @@ export const AddToCollectionModal: React.FC<{
return originalIds.length !== newIds.length || originalIds.some((id) => !newIds.includes(id));
}, [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(() => {
if (rows.length === 0) {
return 'No assets found';
@ -123,18 +174,19 @@ export const AddToCollectionModal: React.FC<{
onClick: onClose
},
primaryButton: {
text:
selectedAssets.length === 0
? 'Update collection'
: `Add ${selectedAssets.length} ${pluralize('asset', selectedAssets.length)} to collection`,
text: primaryButtonText,
onClick: handleAddAndRemoveMetrics,
disabled: !isSelectedChanged,
tooltip: isSelectedChanged
? `Adding ${selectedAssets.length} assets`
: 'No changes to update'
tooltip: primaryButtonTooltipText
}
};
}, [selectedAssets.length, isSelectedChanged, handleAddAndRemoveMetrics]);
}, [
selectedAssets.length,
isSelectedChanged,
handleAddAndRemoveMetrics,
primaryButtonText,
primaryButtonTooltipText
]);
useLayoutEffect(() => {
if (isFetchedCollection) {

View File

@ -189,7 +189,6 @@ export const AddToDashboardModal: React.FC<{
emptyState={emptyState}
searchText={searchTerm}
handleSearchChange={setSearchTerm}
className="data-[state=closed]:slide-out-to-top-[5%]! data-[state=open]:slide-in-from-top-[5%]! top-28 translate-y-0"
/>
);
});

View File

@ -6,6 +6,7 @@ import { useDebounceSearch } from '@/hooks';
import { VisuallyHidden } from '@radix-ui/react-visually-hidden';
import { DialogDescription, DialogTitle } from '@radix-ui/react-dialog';
import { Text } from '../typography';
import { cn } from '@/lib/classMerge';
export interface InputSelectModalProps extends Omit<BorderedModalProps, 'children'> {
inputPlaceholder?: string;
@ -25,6 +26,7 @@ export const InputSelectModal = React.memo(
columns,
rows,
emptyState,
className,
onSelectChange,
selectedRowKeys,
searchText,
@ -51,7 +53,13 @@ export const InputSelectModal = React.memo(
}, [searchText, handleSearchChange, inputPlaceholder, rows.length]);
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
className="max-h-[65vh]"
style={{