Skip to content

Commit

Permalink
feat(website): allow organisms without sequences
Browse files Browse the repository at this point in the history
  • Loading branch information
fengelniederhammer committed Jan 17, 2025
1 parent 1c9d3f1 commit 1fd2905
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 66 deletions.
16 changes: 14 additions & 2 deletions website/src/components/Edit/EditPage.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { beforeEach, describe, expect, test } from 'vitest';

import { EditPage } from './EditPage.tsx';
import { defaultReviewData, editableEntry, metadataKey, testAccessToken, testOrganism } from '../../../vitest.setup.ts';
import type { SequenceEntryToEdit, UnprocessedMetadataRecord } from '../../types/backend.ts';
import type { UnprocessedMetadataRecord } from '../../types/backend.ts';
import type { ClientConfig } from '../../types/runtimeConfig.ts';

const queryClient = new QueryClient();
Expand All @@ -19,7 +19,11 @@ const inputFields = [
},
];

function renderEditPage(editedData: SequenceEntryToEdit = defaultReviewData, clientConfig: ClientConfig = dummyConfig) {
function renderEditPage({
editedData = defaultReviewData,
clientConfig = dummyConfig,
allowSubmissionOfConsensusSequences = true,
} = {}) {
render(
<QueryClientProvider client={queryClient}>
<EditPage
Expand All @@ -28,6 +32,7 @@ function renderEditPage(editedData: SequenceEntryToEdit = defaultReviewData, cli
clientConfig={clientConfig}
accessToken={testAccessToken}
inputFields={inputFields}
allowSubmissionOfConsensusSequences={allowSubmissionOfConsensusSequences}
/>
</QueryClientProvider>,
);
Expand All @@ -51,6 +56,13 @@ describe('EditPage', () => {
await userEvent.click(submitButton);
});

test('should render without allowed submission of consensus sequences', () => {
renderEditPage({ allowSubmissionOfConsensusSequences: false });

expect(screen.getByText(/Original Data/i)).toBeInTheDocument();
expectTextInSequenceData.originalMetadata(defaultReviewData.originalData.metadata);
});

test('should show original data and processed data', () => {
renderEditPage();

Expand Down
60 changes: 35 additions & 25 deletions website/src/components/Edit/EditPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type EditPageProps = {
dataToEdit: SequenceEntryToEdit;
accessToken: string;
inputFields: InputField[];
allowSubmissionOfConsensusSequences: boolean;
};

const logger = getClientLogger('EditPage');
Expand Down Expand Up @@ -75,7 +76,8 @@ const InnerEditPage: FC<EditPageProps> = ({
clientConfig,
accessToken,
inputFields,
}: EditPageProps) => {
allowSubmissionOfConsensusSequences,
}) => {
const [editedMetadata, setEditedMetadata] = useState(mapMetadataToRow(dataToEdit));
const [editedSequences, setEditedSequences] = useState(mapSequencesToRow(dataToEdit));
const [processedSequenceTab, setProcessedSequenceTab] = useState(0);
Expand Down Expand Up @@ -141,25 +143,31 @@ const InnerEditPage: FC<EditPageProps> = ({
setEditedMetadata={setEditedMetadata}
inputFields={inputFields}
/>
<EditableOriginalSequences
editedSequences={editedSequences}
setEditedSequences={setEditedSequences}
/>
{allowSubmissionOfConsensusSequences && (
<EditableOriginalSequences
editedSequences={editedSequences}
setEditedSequences={setEditedSequences}
/>
)}

<Subtitle title='Processed Data' bold />
<ProcessedInsertions
processedInsertions={processedInsertions}
insertionType='nucleotideInsertions'
/>
<ProcessedInsertions
processedInsertions={processedInsertions}
insertionType='aminoAcidInsertions'
/>
<Subtitle title='Sequences' />
{allowSubmissionOfConsensusSequences && (
<>
<ProcessedInsertions
processedInsertions={processedInsertions}
insertionType='nucleotideInsertions'
/>
<ProcessedInsertions
processedInsertions={processedInsertions}
insertionType='aminoAcidInsertions'
/>
<Subtitle title='Sequences' />
</>
)}
</tbody>
</table>

{processedSequences.length > 0 && (
{allowSubmissionOfConsensusSequences && processedSequences.length > 0 && (
<div>
<BoxWithTabsTabBar>
{processedSequences.map(({ label }, i) => (
Expand Down Expand Up @@ -199,16 +207,18 @@ const InnerEditPage: FC<EditPageProps> = ({
Submit
</button>

<button
className='btn normal-case'
onClick={() => generateAndDownloadFastaFile(editedSequences, dataToEdit)}
title={`Download the original, unaligned sequence${
editedSequences.length > 1 ? 's' : ''
} as provided by the submitter`}
disabled={isLoading}
>
Download Sequence{editedSequences.length > 1 ? 's' : ''}
</button>
{allowSubmissionOfConsensusSequences && (
<button
className='btn normal-case'
onClick={() => generateAndDownloadFastaFile(editedSequences, dataToEdit)}
title={`Download the original, unaligned sequence${
editedSequences.length > 1 ? 's' : ''
} as provided by the submitter`}
disabled={isLoading}
>
Download Sequence{editedSequences.length > 1 ? 's' : ''}
</button>
)}
</div>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export const SequenceDataUI: FC<Props> = ({
/>
)}

{/* TODO ! */}
<a
href={routes.editPage(organism, {
accession: accessionVersion.split('.')[0],
Expand Down
72 changes: 40 additions & 32 deletions website/src/components/Submission/DataUploadForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type DataUploadFormProps = {
referenceGenomeSequenceNames: ReferenceGenomesSequenceNames;
onSuccess: () => void;
onError: (message: string) => void;
allowSubmissionOfConsensusSequences: boolean;
};

const logger = getClientLogger('DataUploadForm');
Expand Down Expand Up @@ -84,15 +85,13 @@ const DataUseTerms = ({
const DevExampleData = ({
setExampleEntries,
exampleEntries,
metadataFile,
sequenceFile,
handleLoadExampleData,
dataIsLoaded,
}: {
setExampleEntries: (entries: number) => void;
exampleEntries: number | undefined;
metadataFile: File | null;
sequenceFile: File | null;
handleLoadExampleData: () => void;
dataIsLoaded: boolean;
}) => {
return (
<p className='text-gray-800 text-xs mt-5 opacity-50'>
Expand All @@ -108,7 +107,7 @@ const DevExampleData = ({
Load Example Data
</button>{' '}
<br />
{metadataFile && sequenceFile && <span className='text-xs text-gray-500'>Example data loaded</span>}
{dataIsLoaded && <span className='text-xs text-gray-500'>Example data loaded</span>}
</p>
);
};
Expand All @@ -122,9 +121,10 @@ const InnerDataUploadForm = ({
onError,
group,
referenceGenomeSequenceNames,
allowSubmissionOfConsensusSequences,
}: DataUploadFormProps) => {
const [metadataFile, setMetadataFile] = useState<File | null>(null);
const [sequenceFile, setSequenceFile] = useState<File | null>(null);
const [metadataFile, setMetadataFile] = useState<File | undefined>(undefined);
const [sequenceFile, setSequenceFile] = useState<File | undefined>(undefined);
const [exampleEntries, setExampleEntries] = useState<number | undefined>(10);

const { submit, revise, isLoading } = useSubmitFiles(accessToken, organism, clientConfig, onSuccess, onError);
Expand All @@ -143,10 +143,12 @@ const InnerDataUploadForm = ({
const exampleMetadataContent = action === `submit` ? metadataFileContent : revisedMetadataFileContent;

const metadataFile = createTempFile(exampleMetadataContent, 'text/tab-separated-values', 'metadata.tsv');
const sequenceFile = createTempFile(sequenceFileContent, 'application/octet-stream', 'sequences.fasta');

setMetadataFile(metadataFile);
setSequenceFile(sequenceFile);

if (allowSubmissionOfConsensusSequences) {
const sequenceFile = createTempFile(sequenceFileContent, 'application/octet-stream', 'sequences.fasta');
setSequenceFile(sequenceFile);
}
};

const handleSubmit = (event: FormEvent) => {
Expand All @@ -168,7 +170,7 @@ const InnerDataUploadForm = ({
onError('Please select metadata file');
return;
}
if (!sequenceFile) {
if (!sequenceFile && allowSubmissionOfConsensusSequences) {
onError('Please select a sequences file');
return;
}
Expand Down Expand Up @@ -201,8 +203,12 @@ const InnerDataUploadForm = ({
<div className='flex-col flex gap-8 divide-y'>
<div className='grid sm:grid-cols-3 gap-x-16'>
<div className=''>
<h2 className='font-medium text-lg'>Sequences and metadata</h2>
<p className='text-gray-500 text-sm'>Select your sequence data and metadata files</p>
<h2 className='font-medium text-lg'>
{allowSubmissionOfConsensusSequences ? 'Sequences and metadata' : 'Metadata'}
</h2>
<p className='text-gray-500 text-sm'>
Select your {allowSubmissionOfConsensusSequences && 'sequence data and'}metadata files
</p>
<p className='text-gray-400 text-xs mt-5'>
{action === 'revise' && (
<span>
Expand Down Expand Up @@ -250,28 +256,30 @@ const InnerDataUploadForm = ({
.
</p>

{(organism.startsWith('not-aligned-organism') || organism.startsWith('dummy-organism')) &&
action === 'submit' && (
<DevExampleData
setExampleEntries={setExampleEntries}
exampleEntries={exampleEntries}
metadataFile={metadataFile}
sequenceFile={sequenceFile}
handleLoadExampleData={handleLoadExampleData}
/>
)}
{organism.startsWith('dummy-organism') && action === 'submit' && (
<DevExampleData
setExampleEntries={setExampleEntries}
exampleEntries={exampleEntries}
handleLoadExampleData={handleLoadExampleData}
dataIsLoaded={
!!metadataFile && (!allowSubmissionOfConsensusSequences || !!sequenceFile)
}
/>
)}
</div>
<form className='sm:col-span-2'>
<div className='flex flex-col lg:flex-row gap-6'>
<div className='w-60 space-y-2'>
<label className='text-gray-900 font-medium text-sm block'>Sequence File</label>
<UploadComponent
setFile={setSequenceFile}
name='sequence_file'
ariaLabel='Sequence File'
fileKind={FASTA_FILE_KIND}
/>
</div>
{allowSubmissionOfConsensusSequences && (
<div className='w-60 space-y-2'>
<label className='text-gray-900 font-medium text-sm block'>Sequence File</label>
<UploadComponent
setFile={setSequenceFile}
name='sequence_file'
ariaLabel='Sequence File'
fileKind={FASTA_FILE_KIND}
/>
</div>
)}
<div className='w-60 space-y-2'>
<label className='text-gray-900 font-medium text-sm block'>Metadata File</label>
<UploadComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const UploadComponent = ({
ariaLabel,
fileKind,
}: {
setFile: (file: File | null) => void;
setFile: (file: File | undefined) => void;
name: string;
ariaLabel: string;
fileKind: FileKind;
Expand All @@ -37,7 +37,7 @@ export const UploadComponent = ({
},
);
}
setFile(processedFile !== null ? processedFile.inner() : null);
setFile(processedFile !== null ? processedFile.inner() : undefined);
rawSetMyFile(processedFile);
},
[setFile, rawSetMyFile],
Expand Down
32 changes: 29 additions & 3 deletions website/src/components/Submission/SubmissionForm.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { toast } from 'react-toastify';
import { describe, expect, test, vi } from 'vitest';
import { afterEach, describe, expect, test, vi } from 'vitest';

import { SubmissionForm } from './SubmissionForm';
import { mockRequest, testAccessToken, testConfig, testGroups, testOrganism } from '../../../vitest.setup.ts';
import type { Group, ProblemDetail, SubmissionIdMapping } from '../../types/backend.ts';
import type { ReferenceGenomesSequenceNames, ReferenceAccession } from '../../types/referencesGenomes.ts';
import type { ReferenceAccession, ReferenceGenomesSequenceNames } from '../../types/referencesGenomes.ts';

vi.mock('../../api', () => ({
getClientLogger: () => ({
Expand Down Expand Up @@ -48,14 +48,15 @@ const defaultReferenceGenomesSequenceNames: ReferenceGenomesSequenceNames = {
insdcAccessionFull: [defaultAccession],
};

function renderSubmissionForm() {
function renderSubmissionForm({ allowSubmissionOfConsensusSequences = true } = {}) {
return render(
<SubmissionForm
accessToken={testAccessToken}
referenceGenomeSequenceNames={defaultReferenceGenomesSequenceNames}
organism={testOrganism}
clientConfig={testConfig.public}
group={group}
allowSubmissionOfConsensusSequences={allowSubmissionOfConsensusSequences}
/>,
);
}
Expand All @@ -69,6 +70,10 @@ const testResponse: SubmissionIdMapping[] = [
];

describe('SubmitForm', () => {
afterEach(() => {
vi.clearAllMocks();
});

test('should handle file upload and server response', async () => {
mockRequest.backend.submit(200, testResponse);
mockRequest.backend.getGroupsOfUser();
Expand Down Expand Up @@ -180,4 +185,25 @@ describe('SubmitForm', () => {
});
});
}

test('should accept submission without sequence file for organism that does not allow consensus sequences', async () => {
mockRequest.backend.submit(200, testResponse);
mockRequest.backend.getGroupsOfUser();

const { getByLabelText } = renderSubmissionForm({
allowSubmissionOfConsensusSequences: false,
});

await userEvent.upload(getByLabelText(/Metadata File/i), metadataFile);
await userEvent.click(
getByLabelText(/I confirm I have not and will not submit this data independently to INSDC/i),
);
await userEvent.click(
getByLabelText(/I confirm that the data submitted is not sensitive or human-identifiable/i),
);

await waitFor(() => {
expect(toast.error).not.toHaveBeenCalled();
});
});
});
3 changes: 3 additions & 0 deletions website/src/components/Submission/SubmissionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type SubmissionFormProps = {
clientConfig: ClientConfig;
group: Group;
referenceGenomeSequenceNames: ReferenceGenomesSequenceNames;
allowSubmissionOfConsensusSequences: boolean;
};

export const SubmissionForm: FC<SubmissionFormProps> = ({
Expand All @@ -21,6 +22,7 @@ export const SubmissionForm: FC<SubmissionFormProps> = ({
clientConfig,
group,
referenceGenomeSequenceNames,
allowSubmissionOfConsensusSequences,
}) => {
return (
<div className='flex flex-col items-center'>
Expand All @@ -35,6 +37,7 @@ export const SubmissionForm: FC<SubmissionFormProps> = ({
onSuccess={() => {
window.location.href = routes.userSequenceReviewPage(organism, group.groupId);
}}
allowSubmissionOfConsensusSequences={allowSubmissionOfConsensusSequences}
/>
</div>
);
Expand Down
Loading

0 comments on commit 1fd2905

Please sign in to comment.