diff --git a/ui/package.json b/ui/package.json
index c7db5adae..b0ef85d78 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -29,7 +29,7 @@
"leaflet": "^1.9.3",
"lodash": "^4.17.21",
"lucide-react": "^1.0.1",
- "nova-ui-kit": "^1.1.33",
+ "nova-ui-kit": "^1.1.34",
"plotly.js": "^2.25.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
diff --git a/ui/src/components/blueprint-collection/blueprint-collection.module.scss b/ui/src/components/blueprint-collection/blueprint-collection.module.scss
index a532fdeb2..4a0812dc6 100644
--- a/ui/src/components/blueprint-collection/blueprint-collection.module.scss
+++ b/ui/src/components/blueprint-collection/blueprint-collection.module.scss
@@ -36,15 +36,10 @@
align-items: center;
max-width: 100%;
- .blueprintImage {
- position: relative;
- margin-bottom: 8px;
-
- img {
- max-width: 100%;
- height: inherit;
- vertical-align: middle;
- }
+ img {
+ max-width: 100%;
+ height: inherit;
+ vertical-align: middle;
}
.blueprintInfo {
diff --git a/ui/src/components/blueprint-collection/blueprint-collection.tsx b/ui/src/components/blueprint-collection/blueprint-collection.tsx
index fee6b85a3..c12c3d7f5 100644
--- a/ui/src/components/blueprint-collection/blueprint-collection.tsx
+++ b/ui/src/components/blueprint-collection/blueprint-collection.tsx
@@ -1,10 +1,10 @@
import classNames from 'classnames'
import { LicenseInfo } from 'components/license-info/license-info'
-import { BasicTooltip } from 'design-system/components/tooltip/basic-tooltip'
-import { EyeIcon } from 'lucide-react'
+import { ChevronRightIcon } from 'lucide-react'
import { buttonVariants } from 'nova-ui-kit'
import { ReactNode, useState } from 'react'
import { Link } from 'react-router-dom'
+import { STRING, translate } from 'utils/language'
import styles from './blueprint-collection.module.scss'
export interface BlueprintItem {
@@ -57,7 +57,7 @@ export const BlueprintItem = ({
{item.timeLabel}
-
+

{item.to ? (
-
-
-
-
-
+
+
{translate(STRING.VIEW_IN_SESSION)}
+
+
) : null}
-
- {item.label}
-
)
}
diff --git a/ui/src/components/determination-score.tsx b/ui/src/components/determination-score.tsx
index 1267612aa..3ab0735be 100644
--- a/ui/src/components/determination-score.tsx
+++ b/ui/src/components/determination-score.tsx
@@ -3,15 +3,15 @@ import { IdentificationScore } from 'nova-ui-kit'
import { STRING, translate } from 'utils/language'
export const DeterminationScore = ({
- confirmed,
score,
scoreLabel,
tooltip,
+ verified,
}: {
- confirmed?: boolean
score?: number
scoreLabel?: string
tooltip?: string
+ verified?: boolean
}) => {
if (score === undefined || scoreLabel === undefined) {
return {translate(STRING.VALUE_NOT_AVAILABLE)}
@@ -20,8 +20,8 @@ export const DeterminationScore = ({
return (
-
- {scoreLabel}
+
+ {verified ? translate(STRING.VERIFIED) : scoreLabel}
)
diff --git a/ui/src/components/filtering/default-filter-control.tsx b/ui/src/components/filtering/default-filter-control.tsx
index d35c09804..b9204bcf2 100644
--- a/ui/src/components/filtering/default-filter-control.tsx
+++ b/ui/src/components/filtering/default-filter-control.tsx
@@ -1,8 +1,5 @@
-import {
- FormActions,
- FormRow,
- FormSection,
-} from 'components/form/layout/layout'
+import classNames from 'classnames'
+import { FormRow } from 'components/form/layout/layout'
import { useProjectDetails } from 'data-services/hooks/projects/useProjectDetails'
import { ProjectDetails } from 'data-services/models/project-details'
import { InputValue } from 'design-system/components/input/input'
@@ -30,7 +27,7 @@ export const DefaultFiltersControl = ({ field }: { field: string }) => {
{filter.label}
- {project ? : null}
+ {project ? : null}
{
)
}
-export const DefaultFiltersPopover = ({
+export const DefaultFiltersTooltip = ({
className,
project,
}: {
@@ -64,43 +61,46 @@ export const DefaultFiltersPopover = ({
-
-
-
-
-
-
- taxon.name)
- .join(', ')}
- />
- taxon.name)
- .join(', ')}
- />
-
-
- {project.canUpdate ? (
-
+
+
+
+
+ {translate(STRING.MESSAGE_DEFAULT_FILTERS)}
+
+
+
+
+
+ taxon.name)
+ .join(', ')}
+ />
+ taxon.name)
+ .join(', ')}
+ />
+
+
+ {project.canUpdate ? (
-
Configure
+
{translate(STRING.CONFIGURE)}
-
- ) : null}
+ ) : null}
+
)
diff --git a/ui/src/components/filtering/filter-control.tsx b/ui/src/components/filtering/filter-control.tsx
index bdbb04b66..d5000abf0 100644
--- a/ui/src/components/filtering/filter-control.tsx
+++ b/ui/src/components/filtering/filter-control.tsx
@@ -1,7 +1,6 @@
-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 { InfoTooltip } from 'design-system/components/info-tooltip'
+import { XIcon } from 'lucide-react'
+import { Button } from 'nova-ui-kit'
import { STRING, translate } from 'utils/language'
import { useFilters } from 'utils/useFilters'
import { AlgorithmFilter, NotAlgorithmFilter } from './filters/algorithm-filter'
@@ -79,9 +78,7 @@ export const FilterControl = ({
{filter.label}
- {filter.info ? (
-
- ) : null}
+ {filter.tooltip ? : null}
)
}
-
-export const FilterInfo = ({ text, to }: { text: string; to?: string }) => (
-
-
-
-
-
-
- {text}
- {to ? (
-
- Configure
-
-
- ) : null}
-
-
-
-)
diff --git a/ui/src/components/filtering/filters/image-filter.tsx b/ui/src/components/filtering/filters/image-filter.tsx
index ad0a88ebe..787bc7dfc 100644
--- a/ui/src/components/filtering/filters/image-filter.tsx
+++ b/ui/src/components/filtering/filters/image-filter.tsx
@@ -10,7 +10,7 @@ export const ImageFilter = ({ value }: FilterProps) => {
})()
return (
-
+
{label}
)
diff --git a/ui/src/components/filtering/filters/session-filter.tsx b/ui/src/components/filtering/filters/session-filter.tsx
index a4c3a4a4f..03001f201 100644
--- a/ui/src/components/filtering/filters/session-filter.tsx
+++ b/ui/src/components/filtering/filters/session-filter.tsx
@@ -15,7 +15,7 @@ export const SessionFilter = ({ value }: FilterProps) => {
})()
return (
-
+
{label}
)
diff --git a/ui/src/components/filtering/filters/verification-status-filter.tsx b/ui/src/components/filtering/filters/verification-status-filter.tsx
index ee5d5a3b7..bea7bd7e3 100644
--- a/ui/src/components/filtering/filters/verification-status-filter.tsx
+++ b/ui/src/components/filtering/filters/verification-status-filter.tsx
@@ -3,16 +3,15 @@ import { STRING, translate } from 'utils/language'
import { booleanToString, stringToBoolean } from '../utils'
import { FilterProps } from './types'
-const OPTIONS = [
- { value: true, label: 'Verified' },
- { value: false, label: 'Not verified' },
-]
-
export const VerificationStatusFilter = ({
value: string,
onAdd,
}: FilterProps) => {
const value = stringToBoolean(string)
+ const options = [
+ { value: true, label: translate(STRING.VERIFIED) },
+ { value: false, label: translate(STRING.NOT_VERIFIED) },
+ ]
return (
@@ -20,7 +19,7 @@ export const VerificationStatusFilter = ({
- {OPTIONS.map((option) => (
+ {options.map((option) => (
- {errorMessage ? (
-
- ) : null}
-
-
- {translate(STRING.ENTITY_DELETE, { type })}
-
-
- {translate(STRING.MESSAGE_DELETE_CONFIRM, { type })}
-
-
+ {errorMessage &&
}
+
+
@@ -53,7 +48,7 @@ export const DeleteForm = ({
) : null}
-
+
>
)
}
diff --git a/ui/src/data-services/hooks/processing-services/useProcessingServiceDetails.ts b/ui/src/data-services/hooks/processing-services/useProcessingServiceDetails.ts
index 492585620..fffe614cd 100644
--- a/ui/src/data-services/hooks/processing-services/useProcessingServiceDetails.ts
+++ b/ui/src/data-services/hooks/processing-services/useProcessingServiceDetails.ts
@@ -10,23 +10,18 @@ const convertServerRecord = (record: ServerProcessingService) =>
new ProcessingService(record)
export const useProcessingServiceDetails = (
- processingServiceId: string,
- projectId?: string
+ id: string,
+ projectId: string
): {
processingService?: ProcessingService
isLoading: boolean
isFetching: boolean
error?: unknown
} => {
- const params = projectId ? `?project_id=${projectId}` : ''
const { data, isLoading, isFetching, error } =
useAuthorizedQuery
({
- queryKey: [
- API_ROUTES.PROCESSING_SERVICES,
- processingServiceId,
- projectId,
- ],
- url: `${API_URL}/${API_ROUTES.PROCESSING_SERVICES}/${processingServiceId}/${params}`,
+ queryKey: [API_ROUTES.PROCESSING_SERVICES, id, projectId],
+ url: `${API_URL}/${API_ROUTES.PROCESSING_SERVICES}/${id}/?project_id=${projectId}`,
})
const processingService = useMemo(
diff --git a/ui/src/data-services/models/capture.ts b/ui/src/data-services/models/capture.ts
index 4e8534775..c2f80bdec 100644
--- a/ui/src/data-services/models/capture.ts
+++ b/ui/src/data-services/models/capture.ts
@@ -1,5 +1,6 @@
import { getFormatedDateTimeString } from 'utils/date/getFormatedDateTimeString/getFormatedDateTimeString'
import { getFormatedTimeString } from 'utils/date/getFormatedTimeString/getFormatedTimeString'
+import { STRING, translate } from 'utils/language'
import { UserPermission } from 'utils/user/types'
export type ServerCapture = any // TODO: Update this type
@@ -15,20 +16,15 @@ export type CaptureDetection = {
bbox: number[]
id: string
label: string
- score: number
- occurrenceId?: string
occurrence?: DetectionOccurrence
+ occurrenceId?: string
occurrenceMeetsCriteria: boolean
+ score: number
+ scoreLabel: string
}
const getDetectionLabel = (detection: CaptureDetection) => {
if (detection.occurrence?.determination) {
- const score = getDetectionScore(detection)
-
- if (score) {
- return `${detection.occurrence.determination.name} (${score.toFixed(2)})`
- }
-
return detection.occurrence.determination.name
}
@@ -39,12 +35,24 @@ const getDetectionScore = (detection: CaptureDetection) => {
// This score label is the confidence of the best & most recent classification of the detection's occurrence
// There will also be a score for the localization of the detection as well.
const occurrence: DetectionOccurrence | undefined = detection.occurrence
+
if (occurrence && occurrence.determination_score) {
return occurrence.determination_score
}
+
return 0
}
+const getDetectionScoreLabel = (detection: CaptureDetection) => {
+ const score = getDetectionScore(detection)
+
+ if (score === 1) {
+ return translate(STRING.VERIFIED)
+ }
+
+ return score.toFixed(2)
+}
+
export class Capture {
protected readonly _capture: ServerCapture
private readonly _detections: CaptureDetection[] = []
@@ -59,11 +67,12 @@ export class Capture {
bbox: detection.bbox,
id: `${detection.id}`,
label: getDetectionLabel(detection),
- score: getDetectionScore(detection),
occurrenceId: detection.occurrence
? `${detection.occurrence.id}`
: undefined,
occurrenceMeetsCriteria: detection.occurrence_meets_criteria,
+ score: getDetectionScore(detection),
+ scoreLabel: getDetectionScoreLabel(detection),
}
}
)
diff --git a/ui/src/data-services/models/species.ts b/ui/src/data-services/models/species.ts
index 082144af4..e507eca4f 100644
--- a/ui/src/data-services/models/species.ts
+++ b/ui/src/data-services/models/species.ts
@@ -64,14 +64,12 @@ export class Species extends Taxon {
: undefined
}
- get lastSeenLabel() {
+ get lastSeen() {
if (!this._species.last_detected) {
return undefined
}
- const date = new Date(this._species.last_detected)
-
- return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
+ return new Date(this._species.last_detected)
}
get numDetections(): number {
diff --git a/ui/src/design-system/components/info-tooltip.tsx b/ui/src/design-system/components/info-tooltip.tsx
new file mode 100644
index 000000000..3bb81df39
--- /dev/null
+++ b/ui/src/design-system/components/info-tooltip.tsx
@@ -0,0 +1,53 @@
+import classNames from 'classnames'
+import { ChevronRightIcon, InfoIcon } from 'lucide-react'
+import { Button, buttonVariants, Tooltip } from 'nova-ui-kit'
+import { Link } from 'react-router-dom'
+import { STRING, translate } from 'utils/language'
+
+export const InfoTooltip = (props: {
+ text: string
+ link?: {
+ text: string
+ to: string
+ }
+}) => (
+
+
+
+
+
+
+
+
+
+
+)
+
+export const Info = ({
+ link,
+ text,
+}: {
+ text: string
+ link?: {
+ text: string
+ to: string
+ }
+}) => (
+
+
{text}
+ {link ? (
+
+
{link.text}
+
+
+ ) : null}
+
+)
diff --git a/ui/src/design-system/components/input/input.module.scss b/ui/src/design-system/components/input/input.module.scss
index 64c4c91ad..d9097e29c 100644
--- a/ui/src/design-system/components/input/input.module.scss
+++ b/ui/src/design-system/components/input/input.module.scss
@@ -12,14 +12,6 @@
margin-bottom: 4px;
}
-.label {
- display: block;
- @include paragraph-small();
- font-weight: 600;
- color: $color-neutral-700;
- white-space: nowrap;
-}
-
.error {
display: block;
@include paragraph-xx-small();
@@ -32,18 +24,6 @@
}
}
-.value {
- display: block;
- @include paragraph-small();
- color: $color-neutral-300;
- white-space: pre-wrap;
-
- &.link {
- color: $color-primary-1-600;
- font-weight: 600;
- }
-}
-
.description {
display: block;
@include paragraph-small();
diff --git a/ui/src/design-system/components/input/input.tsx b/ui/src/design-system/components/input/input.tsx
index 9b8a283d2..c853bf760 100644
--- a/ui/src/design-system/components/input/input.tsx
+++ b/ui/src/design-system/components/input/input.tsx
@@ -14,6 +14,7 @@ import {
import { Link } from 'react-router-dom'
import { getFormatedDateTimeString } from 'utils/date/getFormatedDateTimeString/getFormatedDateTimeString'
import { STRING, translate } from 'utils/language'
+import { InfoTooltip } from '../info-tooltip'
import { BasicTooltip } from '../tooltip/basic-tooltip'
import styles from './input.module.scss'
@@ -57,7 +58,7 @@ export const Input = forwardRef(
return (
-