From 846065dcfbf1f4dea4ebbb38d6be51f0ca437e17 Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer Date: Tue, 13 Feb 2024 11:13:19 +0100 Subject: [PATCH] fix(website): improve metadata types unprocessed metadata is always Map, processed metadata fields can be null --- website/src/components/Edit/EditPage.spec.tsx | 15 +++++++------ website/src/components/Edit/EditPage.tsx | 10 ++++++--- .../src/components/ReviewPage/ReviewCard.tsx | 22 +++++++++---------- website/src/types/backend.ts | 9 +++++--- website/src/utils/displayMetadataField.ts | 3 +++ 5 files changed, 34 insertions(+), 25 deletions(-) create mode 100644 website/src/utils/displayMetadataField.ts diff --git a/website/src/components/Edit/EditPage.spec.tsx b/website/src/components/Edit/EditPage.spec.tsx index 6bfb352fb2..9197729da8 100644 --- a/website/src/components/Edit/EditPage.spec.tsx +++ b/website/src/components/Edit/EditPage.spec.tsx @@ -6,7 +6,7 @@ import { beforeEach, describe, expect, test } from 'vitest'; import { EditPage } from './EditPage.tsx'; import { testAccessToken, testOrganism } from '../../../vitest.setup.ts'; -import type { MetadataField, SequenceEntryToEdit } from '../../types/backend.ts'; +import type { MetadataField, SequenceEntryToEdit, UnprocessedMetadataRecord } from '../../types/backend.ts'; import type { ClientConfig } from '../../types/runtimeConfig.ts'; const queryClient = new QueryClient(); @@ -49,6 +49,7 @@ const defaultReviewData: SequenceEntryToEdit = { processedData: { metadata: { processedMetaDataField: 'processedMetaDataValue', + nullField: null, }, unalignedNucleotideSequences: { unalignedProcessedSequenceName: 'processedUnalignedNucleotideSequencesValue', @@ -158,17 +159,17 @@ describe('EditPage', () => { }); const expectTextInSequenceData = { - original: (metadata: Record): void => + original: (metadata: Record): void => Object.entries(metadata).forEach(([key, value]) => { expect(screen.getByText(key + ':')).toBeInTheDocument(); - expect(screen.getByDisplayValue(value.toString())).toBeInTheDocument(); + expect(screen.getByDisplayValue(value)).toBeInTheDocument(); }), - originalMetadata: (metadata: Record): void => + originalMetadata: (metadata: UnprocessedMetadataRecord): void => Object.entries(metadata).forEach(([key, value]) => { expect(screen.getByText(sentenceCase(key) + ':')).toBeInTheDocument(); - expect(screen.getByDisplayValue(value.toString())).toBeInTheDocument(); + expect(screen.getByDisplayValue(value)).toBeInTheDocument(); }), - processed: (metadata: Record): void => + processed: (metadata: Record): void => Object.entries(metadata).forEach(([key, value]) => { expect(screen.getByText(key + ':')).toBeInTheDocument(); expect(screen.getByText(value.toString())).toBeInTheDocument(); @@ -176,6 +177,6 @@ const expectTextInSequenceData = { processedMetadata: (metadata: Record): void => Object.entries(metadata).forEach(([key, value]) => { expect(screen.getByText(sentenceCase(key) + ':')).toBeInTheDocument(); - expect(screen.getByText(value.toString())).toBeInTheDocument(); + expect(screen.getByText((value ?? 'null').toString())).toBeInTheDocument(); }), }; diff --git a/website/src/components/Edit/EditPage.tsx b/website/src/components/Edit/EditPage.tsx index 44bc473aed..e3ee1ea4ec 100644 --- a/website/src/components/Edit/EditPage.tsx +++ b/website/src/components/Edit/EditPage.tsx @@ -10,6 +10,7 @@ import { ACCESSION_FIELD } from '../../settings.ts'; import type { MetadataRecord, ProcessingAnnotationSourceType, SequenceEntryToEdit } from '../../types/backend.ts'; import type { ClientConfig } from '../../types/runtimeConfig.ts'; import { createAuthorizationHeader } from '../../utils/createAuthorizationHeader.ts'; +import { displayMetadataField } from '../../utils/displayMetadataField.ts'; import { getAccessionVersionString } from '../../utils/extractAccessionVersion.ts'; import { ConfirmationDialog } from '../DeprecatedConfirmationDialog.tsx'; import { ManagedErrorFeedback, useErrorFeedbackState } from '../common/ManagedErrorFeedback.tsx'; @@ -248,7 +249,10 @@ const ProcessedMetadata: FC = ({ processedMetadata }) => <> {Object.entries(processedMetadata).map(([key, value]) => ( - + ))} ); @@ -282,8 +286,8 @@ const ProcessedInsertions: FC = ({ processedInsertions const mapMetadataToRow = (editedData: SequenceEntryToEdit): Row[] => Object.entries(editedData.originalData.metadata).map(([key, value]) => ({ key, - initialValue: value.toString(), - value: value.toString(), + value, + initialValue: value, ...mapErrorsAndWarnings(editedData, key, 'Metadata'), })); diff --git a/website/src/components/ReviewPage/ReviewCard.tsx b/website/src/components/ReviewPage/ReviewCard.tsx index df20ee6562..979f77e6d6 100644 --- a/website/src/components/ReviewPage/ReviewCard.tsx +++ b/website/src/components/ReviewPage/ReviewCard.tsx @@ -16,6 +16,7 @@ import { } from '../../types/backend.ts'; import type { ClientConfig } from '../../types/runtimeConfig.ts'; import { createAuthorizationHeader } from '../../utils/createAuthorizationHeader.ts'; +import { displayMetadataField } from '../../utils/displayMetadataField.ts'; import Edit from '~icons/bxs/edit'; import Trash from '~icons/bxs/trash'; import Send from '~icons/fa/send'; @@ -126,18 +127,15 @@ const isAnnotationPresent = (metadataField: string) => (item: ProcessingAnnotati const MetadataList: FC = ({ data, isLoading }) => (
{!isLoading && - Object.entries(data.processedData.metadata).map((entry, index) => { - const valueString = entry[1].toString(); - return ( - - ); - })} + Object.entries(data.processedData.metadata).map(([metadataName, value], index) => ( + + ))}
); diff --git a/website/src/types/backend.ts b/website/src/types/backend.ts index 3f5a5dcbcf..bc859590c3 100644 --- a/website/src/types/backend.ts +++ b/website/src/types/backend.ts @@ -32,7 +32,10 @@ const processingAnnotation = z.object({ }); export type ProcessingAnnotation = z.infer; -export const metadataField = z.union([z.string(), z.number(), z.date()]); +const unprocessedMetadataRecord = z.record(z.string()); +export type UnprocessedMetadataRecord = z.infer; + +export const metadataField = z.union([z.string(), z.number(), z.date(), z.null()]); export type MetadataField = z.infer; const metadataRecord = z.record(metadataField); @@ -104,7 +107,7 @@ export type SubmissionIdMapping = z.infer; export const unprocessedData = accessionVersion.merge( z.object({ data: z.object({ - metadata: metadataRecord, + metadata: unprocessedMetadataRecord, unalignedNucleotideSequences: z.record(z.string()), }), }), @@ -117,7 +120,7 @@ export const sequenceEntryToEdit = accessionVersion.merge( errors: z.array(processingAnnotation).nullable(), warnings: z.array(processingAnnotation).nullable(), originalData: z.object({ - metadata: metadataRecord, + metadata: unprocessedMetadataRecord, unalignedNucleotideSequences: z.record(z.string()), }), processedData: z.object({ diff --git a/website/src/utils/displayMetadataField.ts b/website/src/utils/displayMetadataField.ts new file mode 100644 index 0000000000..74b84460d8 --- /dev/null +++ b/website/src/utils/displayMetadataField.ts @@ -0,0 +1,3 @@ +import type { MetadataField } from '../types/backend.ts'; + +export const displayMetadataField = (value: MetadataField) => (value === null ? 'null' : value.toString());