verification status

This commit is contained in:
Nate Kelley 2025-03-14 17:22:31 -06:00
parent 9fe1c69075
commit 873ba448e0
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
3 changed files with 84 additions and 42 deletions

View File

@ -3,7 +3,7 @@ import React, { useMemo } from 'react';
import { getTooltipText } from './helpers'; import { getTooltipText } from './helpers';
import { useMemoizedFn } from '@/hooks'; import { useMemoizedFn } from '@/hooks';
import { StatusBadgeIndicator } from './StatusBadgeIndicator'; import { StatusBadgeIndicator } from './StatusBadgeIndicator';
import { Dropdown, DropdownItem } from '@/components/ui/dropdown'; import { Dropdown, DropdownItem, DropdownProps } from '@/components/ui/dropdown';
const statuses = [ const statuses = [
VerificationStatus.NOT_REQUESTED, VerificationStatus.NOT_REQUESTED,
@ -26,6 +26,32 @@ export const StatusDropdownContent: React.FC<{
onChangeStatus: (status: VerificationStatus) => void; onChangeStatus: (status: VerificationStatus) => void;
onOpenChange: (open: boolean) => void; onOpenChange: (open: boolean) => void;
}> = React.memo(({ isAdmin, status, onChangeStatus, children, onOpenChange }) => { }> = React.memo(({ isAdmin, status, onChangeStatus, children, onOpenChange }) => {
const dropdownProps = useStatusDropdownContent({
isAdmin,
selectedStatus: status,
onChangeStatus
});
return (
<Dropdown {...dropdownProps} onOpenChange={onOpenChange}>
{children}
</Dropdown>
);
});
StatusDropdownContent.displayName = 'StatusDropdownContent';
export const useStatusDropdownContent = ({
isAdmin,
selectedStatus,
onChangeStatus
}: {
isAdmin: boolean;
selectedStatus: VerificationStatus;
onChangeStatus: (status: VerificationStatus) => void;
}): Pick<
DropdownProps<VerificationStatus>,
'showIndex' | 'items' | 'emptyStateText' | 'menuHeader' | 'selectType'
> => {
const items = useMemo(() => { const items = useMemo(() => {
return statuses.map<DropdownItem<VerificationStatus>>((status) => { return statuses.map<DropdownItem<VerificationStatus>>((status) => {
const requiresAdmin = requiresAdminItems.includes(status); const requiresAdmin = requiresAdminItems.includes(status);
@ -34,6 +60,7 @@ export const StatusDropdownContent: React.FC<{
value: status, value: status,
icon: <StatusBadgeIndicator status={status} showTooltip={false} />, icon: <StatusBadgeIndicator status={status} showTooltip={false} />,
disabled: requiresAdmin && !isAdmin, disabled: requiresAdmin && !isAdmin,
selected: status === selectedStatus,
onClick: () => { onClick: () => {
if (!requiresAdmin || isAdmin) { if (!requiresAdmin || isAdmin) {
onChangeStatus(status); onChangeStatus(status);
@ -43,21 +70,14 @@ export const StatusDropdownContent: React.FC<{
}); });
}, [isAdmin, status, onChangeStatus]); }, [isAdmin, status, onChangeStatus]);
const onSelect = useMemoizedFn((item: VerificationStatus) => { return useMemo(
onChangeStatus(item); () => ({
}); emptyStateText: 'Nothing to see here...',
menuHeader: 'Verification status...',
return ( items,
<Dropdown selectType: 'single',
emptyStateText="Nothing to see here..." showIndex: true
items={items} }),
showIndex [items]
onOpenChange={onOpenChange}
onSelect={onSelect}
selectType="single"
menuHeader="Verification status...">
{children}
</Dropdown>
); );
}); };
StatusDropdownContent.displayName = 'StatusDropdownContent';

View File

@ -91,7 +91,7 @@ const DropdownMenuItem = React.forwardRef<
ref={ref} ref={ref}
className={cn( className={cn(
'relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-base outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0', 'relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-base outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
'focus:bg-item-hover focus:text-foreground', 'focus:bg-item-select focus:text-foreground',
'dropdown-item mx-1 [&.dropdown-item:first-child]:mt-1! [&.dropdown-item:has(+.dropdown-separator)]:mb-1 [&.dropdown-item:has(~.dropdown-separator)]:mt-1 [&.dropdown-item:last-child]:mb-1!', 'dropdown-item mx-1 [&.dropdown-item:first-child]:mt-1! [&.dropdown-item:has(+.dropdown-separator)]:mb-1 [&.dropdown-item:has(~.dropdown-separator)]:mt-1 [&.dropdown-item:last-child]:mb-1!',
inset && 'pl-8', inset && 'pl-8',
truncate && 'overflow-hidden', truncate && 'overflow-hidden',
@ -132,7 +132,7 @@ const DropdownMenuCheckboxItemSingle = React.forwardRef<
) => ( ) => (
<DropdownMenuPrimitive.CheckboxItem <DropdownMenuPrimitive.CheckboxItem
ref={ref} ref={ref}
className={cn(itemClass, 'data-[state=checked]:bg-item-hover', 'pr-6 pl-2', className)} className={cn(itemClass, 'data-[state=checked]:bg-item-select', 'pr-6 pl-2', className)}
checked={checked} checked={checked}
onClick={(e) => { onClick={(e) => {
if (closeOnSelect) { if (closeOnSelect) {
@ -143,9 +143,9 @@ const DropdownMenuCheckboxItemSingle = React.forwardRef<
}} }}
{...props}> {...props}>
{children} {children}
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center"> <span className="absolute right-2 flex h-3.5 w-fit items-center justify-center space-x-1">
<DropdownMenuPrimitive.ItemIndicator> <DropdownMenuPrimitive.ItemIndicator>
<div className="text-icon-color flex h-4 w-4 items-center justify-center text-sm"> <div className="text-icon-color flex items-center justify-center text-sm">
<Check /> <Check />
</div> </div>
</DropdownMenuPrimitive.ItemIndicator> </DropdownMenuPrimitive.ItemIndicator>

View File

@ -4,7 +4,8 @@ import {
useRemoveMetricFromCollection, useRemoveMetricFromCollection,
useRemoveMetricFromDashboard, useRemoveMetricFromDashboard,
useSaveMetricToCollection, useSaveMetricToCollection,
useSaveMetricToDashboard useSaveMetricToDashboard,
useUpdateMetric
} from '@/api/buster_rest/metrics'; } from '@/api/buster_rest/metrics';
import { DropdownContent, DropdownItem, DropdownItems } from '@/components/ui/dropdown'; import { DropdownContent, DropdownItem, DropdownItems } from '@/components/ui/dropdown';
import { import {
@ -33,6 +34,9 @@ import { StatusNotRequestedIcon } from '@/assets';
import { useSaveToDashboardDropdownContent } from '@/components/features/dropdowns/SaveToDashboardDropdown'; import { useSaveToDashboardDropdownContent } from '@/components/features/dropdowns/SaveToDashboardDropdown';
import { useMemoizedFn } from '@/hooks'; import { useMemoizedFn } from '@/hooks';
import { useSaveToCollectionsDropdownContent } from '@/components/features/dropdowns/SaveToCollectionsDropdown'; import { useSaveToCollectionsDropdownContent } from '@/components/features/dropdowns/SaveToCollectionsDropdown';
import { VerificationStatus } from '@/api/asset_interfaces/share';
import { useStatusDropdownContent } from '@/components/features/metrics/StatusBadgeIndicator/StatusDropdownContent';
import { StatusBadgeIndicator } from '@/components/features/metrics/StatusBadgeIndicator';
export const ThreeDotMenuButton = React.memo(({ metricId }: { metricId: string }) => { export const ThreeDotMenuButton = React.memo(({ metricId }: { metricId: string }) => {
const { mutateAsync: deleteMetric, isPending: isDeletingMetric } = useDeleteMetric(); const { mutateAsync: deleteMetric, isPending: isDeletingMetric } = useDeleteMetric();
@ -40,8 +44,9 @@ export const ThreeDotMenuButton = React.memo(({ metricId }: { metricId: string }
const onSetSelectedFile = useChatLayoutContextSelector((x) => x.onSetSelectedFile); const onSetSelectedFile = useChatLayoutContextSelector((x) => x.onSetSelectedFile);
const dashboardSelectMenu = useDashboardSelectMenu({ metricId }); const dashboardSelectMenu = useDashboardSelectMenu({ metricId });
const versionHistoryItems = useVersionHistoryItems({ metricId }); const versionHistoryItems = useVersionHistorySelectMenu({ metricId });
const collectionSelectMenu = useCollectionSelectMenu({ metricId }); const collectionSelectMenu = useCollectionSelectMenu({ metricId });
const statusSelectMenu = useStatusSelectMenu({ metricId });
const items: DropdownItems = useMemo( const items: DropdownItems = useMemo(
() => [ () => [
@ -54,15 +59,7 @@ export const ThreeDotMenuButton = React.memo(({ metricId }: { metricId: string }
console.log('share metric'); console.log('share metric');
} }
}, },
{ statusSelectMenu,
label: 'Request verification',
value: 'request-verification',
icon: <StatusNotRequestedIcon />,
items: [],
onClick: () => {
console.log('share metric');
}
},
{ type: 'divider' }, { type: 'divider' },
dashboardSelectMenu, dashboardSelectMenu,
collectionSelectMenu, collectionSelectMenu,
@ -193,10 +190,7 @@ const useDashboardSelectMenu = ({ metricId }: { metricId: string }) => {
label: 'Add to dashboard', label: 'Add to dashboard',
value: 'add-to-dashboard', value: 'add-to-dashboard',
icon: <ASSET_ICONS.dashboardAdd />, icon: <ASSET_ICONS.dashboardAdd />,
items: [<React.Fragment key="dashboard-sub-menu">{dashboardSubMenu}</React.Fragment>], items: [<React.Fragment key="dashboard-sub-menu">{dashboardSubMenu}</React.Fragment>]
onClick: () => {
console.log('add to dashboard');
}
}), }),
[dashboardSubMenu] [dashboardSubMenu]
); );
@ -204,7 +198,7 @@ const useDashboardSelectMenu = ({ metricId }: { metricId: string }) => {
return dashboardDropdownItem; return dashboardDropdownItem;
}; };
const useVersionHistoryItems = ({ metricId }: { metricId: string }) => { const useVersionHistorySelectMenu = ({ metricId }: { metricId: string }) => {
const { data } = useGetMetric(metricId, (x) => ({ const { data } = useGetMetric(metricId, (x) => ({
versions: x.versions, versions: x.versions,
version_number: x.version_number version_number: x.version_number
@ -276,13 +270,41 @@ const useCollectionSelectMenu = ({ metricId }: { metricId: string }) => {
<React.Fragment key="collection-sub-menu"> <React.Fragment key="collection-sub-menu">
{collectionSubMenu} {modal} {collectionSubMenu} {modal}
</React.Fragment> </React.Fragment>
], ]
onClick: () => {
console.log('add to collection');
}
}), }),
[collectionSubMenu] [collectionSubMenu]
); );
return collectionDropdownItem; return collectionDropdownItem;
}; };
const useStatusSelectMenu = ({ metricId }: { metricId: string }) => {
const { data: metric } = useGetMetric(metricId, (x) => x);
const { mutateAsync: updateMetric } = useUpdateMetric();
const onChangeStatus = useMemoizedFn(async (status: VerificationStatus) => {
await updateMetric({ id: metricId, status });
});
const dropdownProps = useStatusDropdownContent({
isAdmin: true,
selectedStatus: metric?.status || VerificationStatus.NOT_REQUESTED,
onChangeStatus
});
const statusSubMenu = useMemo(() => {
return <DropdownContent {...dropdownProps} />;
}, [dropdownProps]);
const statusDropdownItem: DropdownItem = useMemo(
() => ({
label: 'Status',
value: 'status',
icon: <StatusBadgeIndicator status={metric?.status || VerificationStatus.NOT_REQUESTED} />,
items: [<React.Fragment key="status-sub-menu">{statusSubMenu}</React.Fragment>]
}),
[statusSubMenu]
);
return statusDropdownItem;
};