favorites on list endpoint

This commit is contained in:
Nate Kelley 2025-03-22 16:05:12 -06:00
parent 2ef2ad1499
commit 7fd5d346ff
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
6 changed files with 68 additions and 43 deletions

View File

@ -110,7 +110,7 @@ export const DropdownBase = <T,>({
<span className="dropdown-trigger">{children}</span> <span className="dropdown-trigger">{children}</span>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent <DropdownMenuContent
className={cn('max-w-72 min-w-44', className)} className={cn('max-w-72 min-w-48', className)}
align={align} align={align}
side={side} side={side}
sideOffset={sideOffset}> sideOffset={sideOffset}>

View File

@ -14,18 +14,20 @@ const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>, React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => ( >(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Content <TooltipPrimitive.Portal>
ref={ref} <TooltipPrimitive.Content
sideOffset={sideOffset} ref={ref}
className={cn( sideOffset={sideOffset}
'bg-popover text-popover-foreground', className={cn(
'rounded border py-1.5 pr-0.5 pl-1.5', 'bg-popover text-popover-foreground',
'text-sm shadow', 'rounded border py-1.5 pr-0.5 pl-1.5',
'animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden', 'text-sm shadow',
className 'animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden',
)} className
{...props} )}
/> {...props}
/>
</TooltipPrimitive.Portal>
)); ));
TooltipContent.displayName = TooltipPrimitive.Content.displayName; TooltipContent.displayName = TooltipPrimitive.Content.displayName;

View File

@ -13,8 +13,10 @@ import {
} from '@/components/ui/list'; } from '@/components/ui/list';
import { useMemoizedFn } from '@/hooks'; import { useMemoizedFn } from '@/hooks';
import { NewCollectionModal } from '@/components/features/modal/NewCollectionModal'; import { NewCollectionModal } from '@/components/features/modal/NewCollectionModal';
import { BusterCollectionListItem } from '@/api/asset_interfaces'; import { BusterCollectionListItem, ShareAssetType } from '@/api/asset_interfaces';
import { CollectionListSelectedPopup } from './CollectionListSelectedPopup'; import { CollectionListSelectedPopup } from './CollectionListSelectedPopup';
import { Text } from '@/components/ui/typography';
import { FavoriteStar } from '@/components/features/list';
export const CollectionsListContent: React.FC<{ export const CollectionsListContent: React.FC<{
openNewCollectionModal: boolean; openNewCollectionModal: boolean;
@ -54,17 +56,28 @@ export const CollectionsListContent: React.FC<{
CollectionsListContent.displayName = 'CollectionsListContent'; CollectionsListContent.displayName = 'CollectionsListContent';
const columns: BusterListColumn[] = [ const columns: BusterListColumn[] = [
{ dataIndex: 'title', title: 'Title' },
{ {
dataIndex: 'createdAt', dataIndex: 'name',
title: 'Created at', title: 'Title',
width: 145, render: (v, { id, ...rest }: BusterCollectionListItem) => {
render: (v) => formatDate({ date: v, format: 'lll' }) return (
<div className="mr-2 flex items-center space-x-1.5">
<Text truncate>{v}</Text>
<FavoriteStar
id={id}
type={ShareAssetType.COLLECTION}
iconStyle="tertiary"
title={v}
className="opacity-0 group-hover:opacity-100"
/>
</div>
);
}
}, },
{ {
dataIndex: 'lastEdited', dataIndex: 'last_edited',
title: 'Last edited', title: 'Last edited',
width: 145, width: 150,
render: (v) => formatDate({ date: v, format: 'lll' }) render: (v) => formatDate({ date: v, format: 'lll' })
}, },
{ {
@ -98,13 +111,7 @@ const CollectionList: React.FC<{
route: BusterRoutes.APP_COLLECTIONS_ID, route: BusterRoutes.APP_COLLECTIONS_ID,
collectionId: collection.id collectionId: collection.id
}), }),
data: { data: collection
title: collection.name,
lastEdited: collection.last_edited,
createdAt: collection.created_at,
owner: collection.owner,
sharing: collection.sharing
}
}; };
}); });
}, [collectionsList]); }, [collectionsList]);

View File

@ -16,14 +16,28 @@ import type { BusterDashboardListItem } from '@/api/asset_interfaces';
import { getShareStatus } from '@/components/features/metrics/StatusBadgeIndicator/helpers'; import { getShareStatus } from '@/components/features/metrics/StatusBadgeIndicator/helpers';
import { useCreateDashboard } from '@/api/buster_rest/dashboards'; import { useCreateDashboard } from '@/api/buster_rest/dashboards';
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout'; import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
import { FavoriteStar } from '@/components/features/list';
import { ShareAssetType } from '@/api/asset_interfaces';
import { Text } from '@/components/ui/typography';
const columns: BusterListColumn[] = [ const columns: BusterListColumn[] = [
{ {
dataIndex: 'name', dataIndex: 'name',
title: 'Title', title: 'Title',
render: (data) => { render: (data, { id }) => {
if (data) return data; const name = data || 'New Dashboard';
return 'New Dashboard'; return (
<div className="mr-2 flex items-center space-x-1.5">
<Text truncate>{name}</Text>
<FavoriteStar
id={id}
type={ShareAssetType.DASHBOARD}
iconStyle="tertiary"
title={name}
className="opacity-0 group-hover:opacity-100"
/>
</div>
);
} }
}, },
{ {

View File

@ -158,20 +158,18 @@ const TitleCell = React.memo<{ title: string; status: VerificationStatus; metric
}); });
return ( return (
<div className="flex w-full items-center space-x-2"> <div className="mr-2 flex w-full items-center space-x-2">
<div className="flex items-center justify-center"> <div className="flex items-center justify-center">
<StatusBadgeIndicator status={status} /> <StatusBadgeIndicator status={status} />
</div> </div>
<Text truncate>{title}</Text> <Text truncate>{title}</Text>
<div className="mr-2 flex items-center" onClick={onFavoriteDivClick}> <FavoriteStar
<FavoriteStar id={metricId}
id={metricId} type={ShareAssetType.METRIC}
type={ShareAssetType.METRIC} iconStyle="tertiary"
iconStyle="tertiary" title={title}
title={title} className="opacity-0 group-hover:opacity-100"
className="opacity-0 group-hover:opacity-100" />
/>
</div>
</div> </div>
); );
} }

View File

@ -33,6 +33,7 @@ import { ShareMenuContent } from '@/components/features/ShareMenu/ShareMenuConte
import { DASHBOARD_TITLE_INPUT_ID } from '@/controllers/DashboardController/DashboardViewDashboardController/DashboardEditTitle'; import { DASHBOARD_TITLE_INPUT_ID } from '@/controllers/DashboardController/DashboardViewDashboardController/DashboardEditTitle';
import { canEdit, canFilter, getIsEffectiveOwner } from '@/lib/share'; import { canEdit, canFilter, getIsEffectiveOwner } from '@/lib/share';
import { getShareAssetConfig } from '@/components/features/ShareMenu/helpers'; import { getShareAssetConfig } from '@/components/features/ShareMenu/helpers';
import { useDashboardContentStore } from '@/context/Dashboards';
export const DashboardThreeDotMenu = React.memo(({ dashboardId }: { dashboardId: string }) => { export const DashboardThreeDotMenu = React.memo(({ dashboardId }: { dashboardId: string }) => {
const versionHistoryItems = useVersionHistorySelectMenu({ dashboardId }); const versionHistoryItems = useVersionHistorySelectMenu({ dashboardId });
@ -245,13 +246,16 @@ export const useShareMenuSelectMenu = ({ dashboardId }: { dashboardId: string })
}; };
const useAddContentToDashboardSelectMenu = () => { const useAddContentToDashboardSelectMenu = () => {
const onOpenAddContentModal = useDashboardContentStore((x) => x.onOpenAddContentModal);
return useMemo( return useMemo(
() => ({ () => ({
label: 'Add content', label: 'Add content',
value: 'add-content', value: 'add-content',
icon: <Plus /> icon: <Plus />,
onClick: onOpenAddContentModal
}), }),
[] [onOpenAddContentModal]
); );
}; };