From 8e65f8ab86c3bc9d762acaae6066148c251522e7 Mon Sep 17 00:00:00 2001 From: Anna Viklund Date: Mon, 27 Oct 2025 16:51:32 +0100 Subject: [PATCH 1/5] feat: setup simple form to add taxa --- ui/src/data-services/constants.ts | 5 +- .../data-services/hooks/species/useSpecies.ts | 4 + ui/src/data-services/models/taxa.ts | 19 +- .../entities/details-form/constants.ts | 6 +- .../details-form/taxon-details-form.tsx | 163 ++++++++++++++++++ ui/src/pages/species/species.tsx | 24 ++- ui/src/utils/constants.ts | 12 ++ ui/src/utils/language.ts | 88 +++++----- 8 files changed, 255 insertions(+), 66 deletions(-) create mode 100644 ui/src/pages/project/entities/details-form/taxon-details-form.tsx diff --git a/ui/src/data-services/constants.ts b/ui/src/data-services/constants.ts index e67a6f21d..438d586a5 100644 --- a/ui/src/data-services/constants.ts +++ b/ui/src/data-services/constants.ts @@ -23,10 +23,11 @@ export const API_ROUTES = { SESSIONS: 'events', SITES: 'deployments/sites', SPECIES: 'taxa', - TAGS: 'tags', - TAXA_LISTS: 'taxa/lists', STORAGE: 'storage', SUMMARY: 'status/summary', + TAGS: 'tags', + TAXA_LISTS: 'taxa/lists', + TAXA: 'taxa', USERS: 'users', } diff --git a/ui/src/data-services/hooks/species/useSpecies.ts b/ui/src/data-services/hooks/species/useSpecies.ts index 27f5fbd5f..2884a4a6e 100644 --- a/ui/src/data-services/hooks/species/useSpecies.ts +++ b/ui/src/data-services/hooks/species/useSpecies.ts @@ -2,6 +2,7 @@ import { API_ROUTES } from 'data-services/constants' import { FetchParams } from 'data-services/types' import { getFetchUrl } from 'data-services/utils' import { useMemo } from 'react' +import { UserPermission } from 'utils/user/types' import { ServerSpecies, Species } from '../../models/species' import { useAuthorizedQuery } from '../auth/useAuthorizedQuery' @@ -12,6 +13,7 @@ export const useSpecies = ( ): { species?: Species[] total: number + userPermissions?: UserPermission[] isLoading: boolean isFetching: boolean error?: unknown @@ -20,6 +22,7 @@ export const useSpecies = ( const { data, isLoading, isFetching, error } = useAuthorizedQuery<{ results: ServerSpecies[] + user_permissions?: UserPermission[] count: number }>({ queryKey: [API_ROUTES.SPECIES, params], @@ -31,6 +34,7 @@ export const useSpecies = ( return { species, total: data?.count ?? 0, + userPermissions: data?.user_permissions, isLoading, isFetching, error, diff --git a/ui/src/data-services/models/taxa.ts b/ui/src/data-services/models/taxa.ts index 18d36810e..7f63464b0 100644 --- a/ui/src/data-services/models/taxa.ts +++ b/ui/src/data-services/models/taxa.ts @@ -1,3 +1,5 @@ +import { RANKS } from 'utils/constants' + export type ServerTaxon = { id: string name: string @@ -7,19 +9,6 @@ export type ServerTaxon = { parents?: ServerTaxon[] } -const SORTED_RANKS = [ - 'Unknown', - 'ORDER', - 'SUBORDER', - 'SUPERFAMILY', - 'FAMILY', - 'SUBFAMILY', - 'TRIBE', - 'SUBTRIBE', - 'GENUS', - 'SPECIES', - 'SUBSPECIES', -] export class Taxon { readonly id: string readonly name: string @@ -46,8 +35,8 @@ export class Taxon { // TODO: Perhaps sorting should happen backend side? If so, let's remove this later. this.ranks.sort((r1, r2) => { - const value1 = SORTED_RANKS.indexOf(r1.rank) - const value2 = SORTED_RANKS.indexOf(r2.rank) + const value1 = RANKS.indexOf(r1.rank) + const value2 = RANKS.indexOf(r2.rank) return value1 - value2 }) diff --git a/ui/src/pages/project/entities/details-form/constants.ts b/ui/src/pages/project/entities/details-form/constants.ts index 09729e5bc..5efe96225 100644 --- a/ui/src/pages/project/entities/details-form/constants.ts +++ b/ui/src/pages/project/entities/details-form/constants.ts @@ -2,13 +2,15 @@ import { CollectionDetailsForm } from './collection-details-form' import { ExportDetailsForm } from './export-details-form' import { ProcessingServiceDetailsForm } from './processing-service-details-form' import { StorageDetailsForm } from './storage-details-form' +import { TaxonDetailsForm } from './taxon-details-form' import { DetailsFormProps } from './types' export const customFormMap: { [key: string]: (props: DetailsFormProps) => JSX.Element } = { - export: ExportDetailsForm, - storage: StorageDetailsForm, collection: CollectionDetailsForm, + export: ExportDetailsForm, service: ProcessingServiceDetailsForm, + storage: StorageDetailsForm, + taxon: TaxonDetailsForm, } diff --git a/ui/src/pages/project/entities/details-form/taxon-details-form.tsx b/ui/src/pages/project/entities/details-form/taxon-details-form.tsx new file mode 100644 index 000000000..af483ab7f --- /dev/null +++ b/ui/src/pages/project/entities/details-form/taxon-details-form.tsx @@ -0,0 +1,163 @@ +import { FormController } from 'components/form/form-controller' +import { FormField } from 'components/form/form-field' +import { + FormActions, + FormError, + FormSection, +} from 'components/form/layout/layout' +import { FormConfig } from 'components/form/types' +import { TaxonSelect } from 'components/taxon-search/taxon-select' +import { SaveButton } from 'design-system/components/button/save-button' +import { InputContent } from 'design-system/components/input/input' +import { Select } from 'nova-ui-kit' +import { useForm } from 'react-hook-form' +import { RANKS } from 'utils/constants' +import { STRING, translate } from 'utils/language' +import { useFormError } from 'utils/useFormError' +import { DetailsFormProps, FormValues } from './types' + +type TaxonFormValues = FormValues & { + rank: string + parent: { id: string; name: string } + gbif_taxon_key: string +} + +const config: FormConfig = { + name: { + label: translate(STRING.FIELD_LABEL_NAME), + rules: { + required: true, + }, + }, + rank: { + label: translate(STRING.FIELD_LABEL_RANK), + }, + parent: { + label: translate(STRING.FIELD_LABEL_PARENT), + rules: { + required: true, + }, + }, + gbif_taxon_key: { + label: translate(STRING.FIELD_LABEL_GBIF_TAXON_KEY), + }, +} + +export const TaxonDetailsForm = ({ + error, + isLoading, + isSuccess, + onSubmit, +}: DetailsFormProps) => { + const { + control, + handleSubmit, + setError: setFieldError, + } = useForm({ + mode: 'onChange', + defaultValues: { + name: '', + rank: 'SPECIES', + gbif_taxon_key: '', + }, + }) + + const errorMessage = useFormError({ error, setFieldError }) + + return ( +
+ onSubmit({ + name: values.name, + customFields: { + gbif_taxon_key: values.gbif_taxon_key.length + ? values.gbif_taxon_key + : undefined, + rank: values.rank, + parent_id: values.parent.id, + }, + }) + )} + > + {errorMessage && ( + + )} + + + + ( + + + + )} + /> + ( + + { + if (taxon) { + field.onChange({ id: taxon.id, name: taxon.name }) + } + }} + /> + + )} + /> + + + + + + + + + ) +} + +const RankPicker = ({ + value, + onValueChange, +}: { + value: string + onValueChange: (value: string) => void +}) => ( + + + + + + {RANKS.map((rank) => ( + + {rank} + + ))} + + +) diff --git a/ui/src/pages/species/species.tsx b/ui/src/pages/species/species.tsx index 29190afdf..3ebb9c7ae 100644 --- a/ui/src/pages/species/species.tsx +++ b/ui/src/pages/species/species.tsx @@ -1,6 +1,7 @@ import { DefaultFiltersControl } from 'components/filtering/default-filter-control' import { FilterControl } from 'components/filtering/filter-control' import { FilterSection } from 'components/filtering/filter-section' +import { API_ROUTES } from 'data-services/constants' import { useProjectDetails } from 'data-services/hooks/projects/useProjectDetails' import { useSpecies } from 'data-services/hooks/species/useSpecies' import { useSpeciesDetails } from 'data-services/hooks/species/useSpeciesDetails' @@ -14,6 +15,7 @@ import { PaginationBar } from 'design-system/components/pagination-bar/paginatio import { ColumnSettings } from 'design-system/components/table/column-settings/column-settings' import { Table } from 'design-system/components/table/table/table' import { ToggleGroup } from 'design-system/components/toggle-group/toggle-group' +import { NewEntityDialog } from 'pages/project/entities/new-entity-dialog' import { SpeciesDetails, TABS } from 'pages/species-details/species-details' import { useContext, useEffect, useMemo } from 'react' import { useNavigate, useParams } from 'react-router-dom' @@ -24,6 +26,7 @@ import { STRING, translate } from 'utils/language' import { useColumnSettings } from 'utils/useColumnSettings' import { useFilters } from 'utils/useFilters' import { usePagination } from 'utils/usePagination' +import { UserPermission } from 'utils/user/types' import { useSelectedView } from 'utils/useSelectedView' import { useSort } from 'utils/useSort' import { columns } from './species-columns' @@ -45,12 +48,13 @@ export const Species = () => { const { sort, setSort } = useSort({ field: 'name', order: 'asc' }) const { pagination, setPage } = usePagination() const { filters } = useFilters() - const { species, total, isLoading, isFetching, error } = useSpecies({ - projectId, - sort, - pagination, - filters, - }) + const { species, userPermissions, total, isLoading, isFetching, error } = + useSpecies({ + projectId, + sort, + pagination, + filters, + }) const { selectedView, setSelectedView } = useSelectedView('table') const { taxaLists = [] } = useTaxaLists({ projectId: projectId as string }) const { tags = [] } = useTags({ projectId: projectId as string }) @@ -66,6 +70,7 @@ export const Species = () => { ? activeTaxaList.name : translate(STRING.NAV_ITEM_TAXA) }, [filters, taxaLists]) + const canCreate = userPermissions?.includes(UserPermission.Create) return ( <> @@ -111,6 +116,13 @@ export const Species = () => { value={selectedView} onValueChange={setSelectedView} /> + {canCreate && ( + + )} Date: Wed, 29 Oct 2025 10:25:39 +0100 Subject: [PATCH 2/5] copy: update "Create new taxon" -> "Add taxon" --- ui/src/pages/project/entities/new-entity-dialog.tsx | 10 +++++++--- ui/src/pages/species/species.tsx | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ui/src/pages/project/entities/new-entity-dialog.tsx b/ui/src/pages/project/entities/new-entity-dialog.tsx index ffaf78ed4..dd3729158 100644 --- a/ui/src/pages/project/entities/new-entity-dialog.tsx +++ b/ui/src/pages/project/entities/new-entity-dialog.tsx @@ -16,12 +16,14 @@ export const NewEntityDialog = ({ buttonSize = 'small', buttonVariant = 'outline', collection, + customLabel, type, isCompact, }: { buttonSize?: string buttonVariant?: string collection: string + customLabel?: string type: string isCompact?: boolean }) => { @@ -35,9 +37,11 @@ export const NewEntityDialog = ({ }, CLOSE_TIMEOUT) ) - const label = translate(STRING.ENTITY_CREATE, { - type, - }) + const label = + customLabel ?? + translate(STRING.ENTITY_CREATE, { + type, + }) const DetailsForm = customFormMap[type] ?? EntityDetailsForm diff --git a/ui/src/pages/species/species.tsx b/ui/src/pages/species/species.tsx index 3ebb9c7ae..3df3c837a 100644 --- a/ui/src/pages/species/species.tsx +++ b/ui/src/pages/species/species.tsx @@ -119,6 +119,7 @@ export const Species = () => { {canCreate && ( From 80b6479c18ced461874ab89dae8e0163ffdbfe6e Mon Sep 17 00:00:00 2001 From: Anna Viklund Date: Wed, 29 Oct 2025 11:12:47 +0100 Subject: [PATCH 3/5] feat: setup GBIF select component --- ui/src/components/gbif/gbif-search.tsx | 56 ++++++++++++++++++++++ ui/src/components/gbif/gbif-select.tsx | 58 +++++++++++++++++++++++ ui/src/components/gbif/types.ts | 5 ++ ui/src/components/gbif/useGBIFSearch.ts | 63 +++++++++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 ui/src/components/gbif/gbif-search.tsx create mode 100644 ui/src/components/gbif/gbif-select.tsx create mode 100644 ui/src/components/gbif/types.ts create mode 100644 ui/src/components/gbif/useGBIFSearch.ts diff --git a/ui/src/components/gbif/gbif-search.tsx b/ui/src/components/gbif/gbif-search.tsx new file mode 100644 index 000000000..993655131 --- /dev/null +++ b/ui/src/components/gbif/gbif-search.tsx @@ -0,0 +1,56 @@ +import { Command } from 'nova-ui-kit' +import { useState } from 'react' +import { useDebounce } from 'utils/useDebounce' +import { GBIFTaxon } from './types' +import { useGBIFSearch } from './useGBIFSearch' + +export const GBIFSearch = ({ + onTaxonChange, + rank, + taxon, +}: { + onTaxonChange: (taxon?: GBIFTaxon) => void + rank?: string + taxon?: GBIFTaxon +}) => { + const [searchString, setSearchString] = useState('') + const debouncedSearchString = useDebounce(searchString, 200) + const { data, isLoading } = useGBIFSearch({ + searchString: debouncedSearchString, + rank, + }) + + return ( + + + + No results found. + + {data?.map((t) => ( + onTaxonChange(t)} + > + + + ))} + + + + ) +} diff --git a/ui/src/components/gbif/gbif-select.tsx b/ui/src/components/gbif/gbif-select.tsx new file mode 100644 index 000000000..9c1b124eb --- /dev/null +++ b/ui/src/components/gbif/gbif-select.tsx @@ -0,0 +1,58 @@ +import { ChevronDownIcon, Loader2Icon } from 'lucide-react' +import { Button, Popover } from 'nova-ui-kit' +import { useState } from 'react' +import { GBIFSearch } from './gbif-search' +import { GBIFTaxon } from './types' + +export const GBIFSelect = ({ + isLoading, + onTaxonChange, + rank, + taxon, + triggerLabel, +}: { + isLoading?: boolean + onTaxonChange: (taxon?: GBIFTaxon) => void + rank?: string + taxon?: GBIFTaxon + triggerLabel: string +}) => { + const [open, setOpen] = useState(false) + + return ( + + + + + + { + onTaxonChange(taxon) + setOpen(false) + }} + rank={rank} + taxon={taxon} + /> + + + ) +} diff --git a/ui/src/components/gbif/types.ts b/ui/src/components/gbif/types.ts new file mode 100644 index 000000000..b60ac58bc --- /dev/null +++ b/ui/src/components/gbif/types.ts @@ -0,0 +1,5 @@ +export type GBIFTaxon = { + canonicalName: string + key: number + rank: string +} diff --git a/ui/src/components/gbif/useGBIFSearch.ts b/ui/src/components/gbif/useGBIFSearch.ts new file mode 100644 index 000000000..0a4ae69bd --- /dev/null +++ b/ui/src/components/gbif/useGBIFSearch.ts @@ -0,0 +1,63 @@ +import axios from 'axios' +import { useEffect, useState } from 'react' +import { GBIFTaxon } from './types' + +const BASE_URL = 'https://api.gbif.org/v1/species' // See docs at https://techdocs.gbif.org/en/openapi/v1/species +const DATASET_KEY = 'd7dddbf4-2cf0-4f39-9b2a-bb099caae36c' // GBIF Backbone Taxonomy +const HIGHER_TAXON_KEY = 216 // Insecta +const STATUS = 'ACCEPTED' +const LIMIT = 10 + +const getFetchUrl = ({ + rank, + searchString, +}: { + rank?: string + searchString: string +}) => { + if (!searchString.length) { + return undefined + } + + let url = `${BASE_URL}/search?datasetKey=${DATASET_KEY}&higherTaxonKey=${HIGHER_TAXON_KEY}&status=${STATUS}&limit=${LIMIT}&q=${searchString}` + + if (rank) { + url = `${url}&rank=${rank}` + } + + return url +} + +export const useGBIFSearch = (params: { + rank?: string + searchString: string +}) => { + const [data, setData] = useState() + const [isLoading, setIsLoading] = useState() + const [error, setError] = useState() + const fetchUrl = getFetchUrl(params) + + useEffect(() => { + setError(undefined) + + if (!fetchUrl) { + setData(undefined) + setIsLoading(false) + return + } + + setIsLoading(true) + axios + .get<{ results: GBIFTaxon[] }>(fetchUrl) + .then((res) => { + setData(res.data.results) + setIsLoading(false) + }) + .catch((error: Error) => { + setError(error) + setIsLoading(false) + }) + }, [fetchUrl]) + + return { data, isLoading, error } +} From aa7c7bb8f2cb58c91c5af0f5e92bd0ecce41289f Mon Sep 17 00:00:00 2001 From: Anna Viklund Date: Wed, 29 Oct 2025 11:28:01 +0100 Subject: [PATCH 4/5] feat: update form with more information and GBIF select component --- .../details-form/taxon-details-form.tsx | 169 +++++++++++------- .../project/entities/details-form/types.ts | 2 +- ui/src/pages/species/species.tsx | 1 - 3 files changed, 107 insertions(+), 65 deletions(-) diff --git a/ui/src/pages/project/entities/details-form/taxon-details-form.tsx b/ui/src/pages/project/entities/details-form/taxon-details-form.tsx index af483ab7f..12c5dc1d5 100644 --- a/ui/src/pages/project/entities/details-form/taxon-details-form.tsx +++ b/ui/src/pages/project/entities/details-form/taxon-details-form.tsx @@ -1,46 +1,51 @@ import { FormController } from 'components/form/form-controller' -import { FormField } from 'components/form/form-field' import { FormActions, FormError, + FormRow, FormSection, } from 'components/form/layout/layout' import { FormConfig } from 'components/form/types' +import { GBIFSelect } from 'components/gbif/gbif-select' +import { GBIFTaxon } from 'components/gbif/types' import { TaxonSelect } from 'components/taxon-search/taxon-select' import { SaveButton } from 'design-system/components/button/save-button' import { InputContent } from 'design-system/components/input/input' +import { InfoIcon } from 'lucide-react' import { Select } from 'nova-ui-kit' import { useForm } from 'react-hook-form' import { RANKS } from 'utils/constants' import { STRING, translate } from 'utils/language' import { useFormError } from 'utils/useFormError' -import { DetailsFormProps, FormValues } from './types' +import { DetailsFormProps } from './types' -type TaxonFormValues = FormValues & { +type TaxonFormValues = { rank: string - parent: { id: string; name: string } - gbif_taxon_key: string + name?: GBIFTaxon + parent?: { id: string; name: string } } const config: FormConfig = { + rank: { + label: translate(STRING.FIELD_LABEL_RANK), + description: + 'Specify the taxon rank. The rank will affect the GBIF search results.', + }, name: { label: translate(STRING.FIELD_LABEL_NAME), + description: 'Specify the taxon name, based on GBIF search results.', rules: { required: true, }, }, - rank: { - label: translate(STRING.FIELD_LABEL_RANK), - }, parent: { label: translate(STRING.FIELD_LABEL_PARENT), + description: + 'Specify the taxon parent, based on Antenna search results. If the parent does not exist on Antenna, please add it first.', rules: { required: true, }, }, - gbif_taxon_key: { - label: translate(STRING.FIELD_LABEL_GBIF_TAXON_KEY), - }, } export const TaxonDetailsForm = ({ @@ -53,28 +58,27 @@ export const TaxonDetailsForm = ({ control, handleSubmit, setError: setFieldError, + setValue, + watch, } = useForm({ mode: 'onChange', defaultValues: { - name: '', rank: 'SPECIES', - gbif_taxon_key: '', }, }) + const rank = watch('rank') const errorMessage = useFormError({ error, setFieldError }) return (
onSubmit({ - name: values.name, + name: values.name?.canonicalName, customFields: { - gbif_taxon_key: values.gbif_taxon_key.length - ? values.gbif_taxon_key - : undefined, + gbif_taxon_key: values.name?.key, + parent_id: values.parent?.id, rank: values.rank, - parent_id: values.parent.id, }, }) )} @@ -86,53 +90,92 @@ export const TaxonDetailsForm = ({ message={errorMessage} /> )} - - - ( - - - - )} - /> - ( - + +

+ From this form you can add missing taxa to Antenna. Since taxa are + shared across projects, names are currently restricted to the{' '} + - { - if (taxon) { - field.onChange({ id: taxon.id, name: taxon.name }) - } - }} - /> - - )} - /> - - - + GBIF Backbone Taxonomy + + . One other restriction is that taxa have to be added one by one. We + are working on a more flexible workflow for taxa. Please reach out + to the team if you have custom requests in the meantime. +

+ + + ( + + { + field.onChange(value) + setValue('name', undefined) // Reset GBIF taxon if rank is updated + }} + /> + + )} + /> + ( + + { + if (taxon) { + field.onChange(taxon) + } + }} + triggerLabel={field.value?.canonicalName ?? 'Select a value'} + /> + + )} + /> + + + ( + + { + if (taxon) { + field.onChange({ id: taxon.id, name: taxon.name }) + } + }} + triggerLabel={field.value?.name ?? 'Select a value'} + /> + + )} + /> +
diff --git a/ui/src/pages/project/entities/details-form/types.ts b/ui/src/pages/project/entities/details-form/types.ts index d048d6ca1..ccc709149 100644 --- a/ui/src/pages/project/entities/details-form/types.ts +++ b/ui/src/pages/project/entities/details-form/types.ts @@ -13,6 +13,6 @@ export type DetailsFormProps = { } export type FormValues = { - name: string + name?: string description?: string } diff --git a/ui/src/pages/species/species.tsx b/ui/src/pages/species/species.tsx index 3df3c837a..bdb950798 100644 --- a/ui/src/pages/species/species.tsx +++ b/ui/src/pages/species/species.tsx @@ -120,7 +120,6 @@ export const Species = () => { )} From d1439e9644452f9201a69b1704cf2f8f0dfc166f Mon Sep 17 00:00:00 2001 From: Anna Viklund Date: Wed, 29 Oct 2025 12:02:17 +0100 Subject: [PATCH 5/5] fix: reset server errors on dialog open state change + fix type --- ui/src/data-services/hooks/entities/types.ts | 2 +- ui/src/data-services/hooks/entities/useCreateEntity.ts | 2 +- ui/src/pages/project/entities/new-entity-dialog.tsx | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ui/src/data-services/hooks/entities/types.ts b/ui/src/data-services/hooks/entities/types.ts index 43d7d4612..65829495c 100644 --- a/ui/src/data-services/hooks/entities/types.ts +++ b/ui/src/data-services/hooks/entities/types.ts @@ -1,6 +1,6 @@ export interface EntityFieldValues { description?: string - name: string + name?: string projectId: string customFields?: { [key: string]: string | number | object | undefined } } diff --git a/ui/src/data-services/hooks/entities/useCreateEntity.ts b/ui/src/data-services/hooks/entities/useCreateEntity.ts index 869855746..9e0175604 100644 --- a/ui/src/data-services/hooks/entities/useCreateEntity.ts +++ b/ui/src/data-services/hooks/entities/useCreateEntity.ts @@ -26,5 +26,5 @@ export const useCreateEntity = (collection: string, onSuccess?: () => void) => { }, }) - return { createEntity: mutateAsync, isLoading, isSuccess, error } + return { createEntity: mutateAsync, isLoading, isSuccess, error, reset } } diff --git a/ui/src/pages/project/entities/new-entity-dialog.tsx b/ui/src/pages/project/entities/new-entity-dialog.tsx index dd3729158..5541b3c5f 100644 --- a/ui/src/pages/project/entities/new-entity-dialog.tsx +++ b/ui/src/pages/project/entities/new-entity-dialog.tsx @@ -3,7 +3,7 @@ import { useCreateEntity } from 'data-services/hooks/entities/useCreateEntity' import * as Dialog from 'design-system/components/dialog/dialog' import { PlusIcon } from 'lucide-react' import { Button } from 'nova-ui-kit' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { useParams } from 'react-router-dom' import { STRING, translate } from 'utils/language' import { customFormMap } from './details-form/constants' @@ -29,7 +29,7 @@ export const NewEntityDialog = ({ }) => { const { projectId } = useParams() const [isOpen, setIsOpen] = useState(false) - const { createEntity, isLoading, isSuccess, error } = useCreateEntity( + const { createEntity, isLoading, isSuccess, error, reset } = useCreateEntity( collection, () => setTimeout(() => { @@ -37,6 +37,8 @@ export const NewEntityDialog = ({ }, CLOSE_TIMEOUT) ) + useEffect(reset, [isOpen]) + const label = customLabel ?? translate(STRING.ENTITY_CREATE, {