diff --git a/ui/src/app.tsx b/ui/src/app.tsx index faefb398d..8f079dbf4 100644 --- a/ui/src/app.tsx +++ b/ui/src/app.tsx @@ -22,8 +22,7 @@ import { Deployments } from 'pages/deployments/deployments' import { Jobs } from 'pages/jobs/jobs' import { Occurrences } from 'pages/occurrences/occurrences' import { Algorithms } from 'pages/project/algorithms/algorithms' -import { CollectionDetails } from 'pages/project/collections/collection-details' -import { Collections } from 'pages/project/collections/collections' +import { CaptureSets } from 'pages/project/capture-sets/capture-sets' import { DefaultFilters } from 'pages/project/default-filters/default-filters' import { Devices } from 'pages/project/entities/devices' import { Sites } from 'pages/project/entities/sites' @@ -110,8 +109,8 @@ export const App = () => ( element={} /> } /> + } /> } /> - } /> } /> ( ) + +/* We have changed the wording from "Collections" to "Capture sets". This will redirect users to the new route. */ +const Collections = () => { + const { projectId } = useParams() + + return ( + + ) +} diff --git a/ui/src/components/filtering/filter-control.tsx b/ui/src/components/filtering/filter-control.tsx index 7972a8da7..99933c7e7 100644 --- a/ui/src/components/filtering/filter-control.tsx +++ b/ui/src/components/filtering/filter-control.tsx @@ -1,9 +1,11 @@ -import { XIcon } from 'lucide-react' -import { Button } from 'nova-ui-kit' +import classNames from 'classnames' +import { ChevronRightIcon, InfoIcon, XIcon } from 'lucide-react' +import { Button, buttonVariants, Tooltip } from 'nova-ui-kit' +import { Link } from 'react-router-dom' import { useFilters } from 'utils/useFilters' import { AlgorithmFilter, NotAlgorithmFilter } from './filters/algorithm-filter' import { BooleanFilter } from './filters/boolean-filter' -import { CollectionFilter } from './filters/collection-filter' +import { CaptureSetFilter } from './filters/capture-set-filter' import { DateFilter } from './filters/date-filter' import { ImageFilter } from './filters/image-filter' import { PipelineFilter } from './filters/pipeline-filter' @@ -22,8 +24,8 @@ const ComponentMap: { [key: string]: (props: FilterProps) => JSX.Element } = { algorithm: AlgorithmFilter, - collection: CollectionFilter, - collections: CollectionFilter, + collection: CaptureSetFilter, + collections: CaptureSetFilter, date_end: DateFilter, date_start: DateFilter, deployment: StationFilter, @@ -35,7 +37,7 @@ const ComponentMap: { not_tag_id: TagFilter, not_taxa_list_id: TaxaListFilter, pipeline: PipelineFilter, - source_image_collection: CollectionFilter, + source_image_collection: CaptureSetFilter, source_image_single: ImageFilter, status: StatusFilter, tag_id: TagFilter, @@ -72,9 +74,14 @@ export const FilterControl = ({ return (
- +
+ + {filter.label} + + {filter.info ? ( + + ) : null} +
) } + +export const FilterInfo = ({ text, to }: { text: string; to?: string }) => ( + + + + + + +

{text}

+ {to ? ( + + Configure + + + ) : null} +
+
+
+) diff --git a/ui/src/components/filtering/filters/collection-filter.tsx b/ui/src/components/filtering/filters/capture-set-filter.tsx similarity index 62% rename from ui/src/components/filtering/filters/collection-filter.tsx rename to ui/src/components/filtering/filters/capture-set-filter.tsx index 7e7e962d2..e7eadf71d 100644 --- a/ui/src/components/filtering/filters/collection-filter.tsx +++ b/ui/src/components/filtering/filters/capture-set-filter.tsx @@ -1,25 +1,25 @@ -import { useCollections } from 'data-services/hooks/collections/useCollections' +import { useCaptureSets } from 'data-services/hooks/capture-sets/useCaptureSets' import { Select } from 'nova-ui-kit' import { useParams } from 'react-router-dom' import { FilterProps } from './types' -export const CollectionFilter = ({ value, onAdd }: FilterProps) => { +export const CaptureSetFilter = ({ value, onAdd }: FilterProps) => { const { projectId } = useParams() - const { collections = [], isLoading } = useCollections({ + const { captureSets = [], isLoading } = useCaptureSets({ projectId: projectId as string, }) return ( - + - {collections.map((c) => ( + {captureSets.map((c) => ( {c.name} diff --git a/ui/src/data-services/constants.ts b/ui/src/data-services/constants.ts index c7e65b222..135896386 100644 --- a/ui/src/data-services/constants.ts +++ b/ui/src/data-services/constants.ts @@ -2,9 +2,9 @@ export const API_URL = '/api/v2' export const API_ROUTES = { ALGORITHM: 'ml/algorithms', + CAPTURE_SETS: 'captures/collections', CAPTURES: 'captures', CLASSIFICATIONS: 'classifications', - COLLECTIONS: 'captures/collections', DEPLOYMENTS: 'deployments', DEVICES: 'deployments/devices', EXPORTS: 'exports', diff --git a/ui/src/data-services/hooks/collections/useCollections.ts b/ui/src/data-services/hooks/capture-sets/useCaptureSets.ts similarity index 67% rename from ui/src/data-services/hooks/collections/useCollections.ts rename to ui/src/data-services/hooks/capture-sets/useCaptureSets.ts index 2251ac7f4..8de135843 100644 --- a/ui/src/data-services/hooks/collections/useCollections.ts +++ b/ui/src/data-services/hooks/capture-sets/useCaptureSets.ts @@ -1,43 +1,43 @@ import { API_ROUTES, REFETCH_INTERVAL } from 'data-services/constants' -import { Collection, ServerCollection } from 'data-services/models/collection' +import { CaptureSet, ServerCaptureSet } from 'data-services/models/capture-set' import { FetchParams } from 'data-services/types' import { getFetchUrl } from 'data-services/utils' import { useMemo } from 'react' import { UserPermission } from 'utils/user/types' import { useAuthorizedQuery } from '../auth/useAuthorizedQuery' -const convertServerRecord = (record: ServerCollection) => new Collection(record) +const convertServerRecord = (record: ServerCaptureSet) => new CaptureSet(record) -export const useCollections = ( +export const useCaptureSets = ( params: FetchParams | undefined, poll?: boolean ): { - collections?: Collection[] + captureSets?: CaptureSet[] total: number userPermissions?: UserPermission[] isLoading: boolean isFetching: boolean error?: unknown } => { - const fetchUrl = getFetchUrl({ collection: API_ROUTES.COLLECTIONS, params }) + const fetchUrl = getFetchUrl({ collection: API_ROUTES.CAPTURE_SETS, params }) const { data, isLoading, isFetching, error } = useAuthorizedQuery<{ - results: ServerCollection[] + results: ServerCaptureSet[] user_permissions?: UserPermission[] count: number }>({ - queryKey: [API_ROUTES.COLLECTIONS, params], + queryKey: [API_ROUTES.CAPTURE_SETS, params], url: fetchUrl, refetchInterval: poll ? REFETCH_INTERVAL : undefined, }) - const collections = useMemo( + const captureSets = useMemo( () => data?.results.map(convertServerRecord), [data] ) return { - collections, + captureSets, total: data?.count ?? 0, userPermissions: data?.user_permissions, isLoading, diff --git a/ui/src/data-services/hooks/collections/usePopulateCollection.ts b/ui/src/data-services/hooks/capture-sets/usePopulateCaptureSet.ts similarity index 71% rename from ui/src/data-services/hooks/collections/usePopulateCollection.ts rename to ui/src/data-services/hooks/capture-sets/usePopulateCaptureSet.ts index 39e181140..8b80e3bf0 100644 --- a/ui/src/data-services/hooks/collections/usePopulateCollection.ts +++ b/ui/src/data-services/hooks/capture-sets/usePopulateCaptureSet.ts @@ -4,23 +4,23 @@ import { API_ROUTES, API_URL } from 'data-services/constants' import { getAuthHeader } from 'data-services/utils' import { useUser } from 'utils/user/userContext' -export const usePopulateCollection = () => { +export const usePopulateCaptureSet = () => { const { user } = useUser() const queryClient = useQueryClient() const { mutateAsync, isLoading, isSuccess, error } = useMutation({ mutationFn: (id: string) => axios.post<{ id: number }>( - `${API_URL}/${API_ROUTES.COLLECTIONS}/${id}/populate/`, + `${API_URL}/${API_ROUTES.CAPTURE_SETS}/${id}/populate/`, undefined, { headers: getAuthHeader(user), } ), onSuccess: () => { - queryClient.invalidateQueries([API_ROUTES.COLLECTIONS]) + queryClient.invalidateQueries([API_ROUTES.CAPTURE_SETS]) }, }) - return { populateCollection: mutateAsync, isLoading, isSuccess, error } + return { populateCaptureSet: mutateAsync, isLoading, isSuccess, error } } diff --git a/ui/src/data-services/hooks/collections/useCollectionDetails.ts b/ui/src/data-services/hooks/collections/useCollectionDetails.ts deleted file mode 100644 index 8db764cd3..000000000 --- a/ui/src/data-services/hooks/collections/useCollectionDetails.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { API_ROUTES, API_URL, REFETCH_INTERVAL } from 'data-services/constants' -import { Collection, ServerCollection } from 'data-services/models/collection' -import { useMemo } from 'react' -import { useAuthorizedQuery } from '../auth/useAuthorizedQuery' - -const convertServerRecord = (record: ServerCollection) => new Collection(record) - -export const useCollectionDetails = ( - id: string -): { - collection?: Collection - isLoading: boolean - isFetching: boolean - error?: unknown -} => { - const { data, isLoading, isFetching, error } = useAuthorizedQuery( - { - queryKey: [API_ROUTES.COLLECTIONS, id], - url: `${API_URL}/${API_ROUTES.COLLECTIONS}/${id}/`, - refetchInterval: REFETCH_INTERVAL, - } - ) - - const collection = useMemo( - () => (data ? convertServerRecord(data) : undefined), - [data] - ) - - return { - collection, - isLoading, - isFetching, - error, - } -} diff --git a/ui/src/data-services/hooks/entities/useEntities.ts b/ui/src/data-services/hooks/entities/useEntities.ts index e0d507921..a1d066ca0 100644 --- a/ui/src/data-services/hooks/entities/useEntities.ts +++ b/ui/src/data-services/hooks/entities/useEntities.ts @@ -1,4 +1,4 @@ -import { Collection } from 'data-services/models/collection' +import { CaptureSet } from 'data-services/models/capture-set' import { Entity, ServerEntity } from 'data-services/models/entity' import { StorageSource } from 'data-services/models/storage' import { FetchParams } from 'data-services/types' @@ -12,8 +12,8 @@ const convertServerRecord = (collection: string, record: ServerEntity) => { // look at the customFormMap in constants.ts if (collection === 'storage') { return new StorageSource(record) - } else if (collection === 'collection') { - return new Collection(record) + } else if (collection === 'capture-set') { + return new CaptureSet(record) } return new Entity(record) diff --git a/ui/src/data-services/hooks/storage-sources/useStorageDetails.ts b/ui/src/data-services/hooks/storage-sources/useStorageDetails.ts deleted file mode 100644 index 4ae30af6c..000000000 --- a/ui/src/data-services/hooks/storage-sources/useStorageDetails.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { API_ROUTES, API_URL } from 'data-services/constants' -import { Collection, ServerCollection } from 'data-services/models/collection' -import { useMemo } from 'react' -import { useAuthorizedQuery } from '../auth/useAuthorizedQuery' - -const convertServerRecord = (record: ServerCollection) => new Collection(record) - -export const useCollectionDetails = ( - id: string -): { - collection?: Collection - isLoading: boolean - isFetching: boolean - error?: unknown -} => { - const { data, isLoading, isFetching, error } = useAuthorizedQuery( - { - queryKey: [API_ROUTES.COLLECTIONS, id], - url: `${API_URL}/${API_ROUTES.COLLECTIONS}/${id}/`, - } - ) - - const collection = useMemo( - () => (data ? convertServerRecord(data) : undefined), - [data] - ) - - return { - collection, - isLoading, - isFetching, - error, - } -} diff --git a/ui/src/data-services/models/collection.ts b/ui/src/data-services/models/capture-set.ts similarity index 94% rename from ui/src/data-services/models/collection.ts rename to ui/src/data-services/models/capture-set.ts index e825614e3..f56c8af2e 100644 --- a/ui/src/data-services/models/collection.ts +++ b/ui/src/data-services/models/capture-set.ts @@ -3,12 +3,12 @@ import { UserPermission } from 'utils/user/types' import { Entity } from './entity' import { Job } from './job' -export type ServerCollection = any // TODO: Update this type +export type ServerCaptureSet = any // TODO: Update this type -export class Collection extends Entity { +export class CaptureSet extends Entity { private readonly _jobs: Job[] = [] - public constructor(entity: ServerCollection) { + public constructor(entity: ServerCaptureSet) { super(entity) if (this._data.jobs) { diff --git a/ui/src/design-system/components/collections-picker.tsx b/ui/src/design-system/components/capture-set-picker.tsx similarity index 70% rename from ui/src/design-system/components/collections-picker.tsx rename to ui/src/design-system/components/capture-set-picker.tsx index bc9496778..b20c92a70 100644 --- a/ui/src/design-system/components/collections-picker.tsx +++ b/ui/src/design-system/components/capture-set-picker.tsx @@ -1,8 +1,8 @@ -import { useCollections } from 'data-services/hooks/collections/useCollections' +import { useCaptureSets } from 'data-services/hooks/capture-sets/useCaptureSets' import { Select } from 'design-system/components/select/select' import { useParams } from 'react-router-dom' -export const CollectionsPicker = ({ +export const CaptureSetPicker = ({ onValueChange, showClear, value, @@ -12,7 +12,7 @@ export const CollectionsPicker = ({ value?: string }) => { const { projectId } = useParams() - const { collections = [], isLoading } = useCollections({ + const { captureSets = [], isLoading } = useCaptureSets({ projectId: projectId as string, }) @@ -20,7 +20,7 @@ export const CollectionsPicker = ({