diff --git a/integration-tests/tests/pages/CliPage.ts b/integration-tests/tests/pages/CliPage.ts index d728b14eb0..85cc6f2a94 100644 --- a/integration-tests/tests/pages/CliPage.ts +++ b/integration-tests/tests/pages/CliPage.ts @@ -210,48 +210,6 @@ export class CliPage { ); } - /** - * Set default organism - */ - async setDefaultOrganism(organism: string): Promise { - return this.execute(['organism', 'select', organism]); - } - - /** - * Set default group - */ - async setDefaultGroup(groupId: number): Promise { - return this.execute(['group', 'select', groupId.toString()]); - } - - /** - * Clear default organism - */ - async clearDefaultOrganism(): Promise { - return this.execute(['organism', 'select', '--none']); - } - - /** - * Clear default group - */ - async clearDefaultGroup(): Promise { - return this.execute(['group', 'select', '--none']); - } - - /** - * Get available organisms - */ - async getAvailableOrganisms(): Promise { - return this.execute(['organism', 'list']); - } - - /** - * Get available groups - */ - async getAvailableGroups(): Promise { - return this.execute(['group', 'list']); - } - /** * Login with username and password */ @@ -259,13 +217,6 @@ export class CliPage { return this.execute(['auth', 'login', '--username', username, '--password', password]); } - /** - * Check authentication status - */ - async authStatus(): Promise { - return this.execute(['auth', 'status']); - } - /** * Logout */ diff --git a/integration-tests/tests/pages/edit.page.ts b/integration-tests/tests/pages/edit.page.ts index 9175374a95..a89d9d1d1c 100644 --- a/integration-tests/tests/pages/edit.page.ts +++ b/integration-tests/tests/pages/edit.page.ts @@ -1,9 +1,14 @@ import { expect, Page } from '@playwright/test'; import { ReviewPage } from './review.page'; +import { prepareTmpDirForSingleUpload, uploadFilesFromTmpDir } from '../utils/file-upload-helpers'; export class EditPage { constructor(private page: Page) {} + async goto(organism: string, accession: string, version: number) { + await this.page.goto(`/${organism}/submission/edit/${accession}/${version}`); + } + async discardSequenceFile() { await this.page.getByRole('button', { name: 'Discard file' }).click(); } @@ -31,4 +36,14 @@ export class EditPage { await this.page.waitForURL('**/review', { timeout: 15_000 }); return new ReviewPage(this.page); } + + async uploadExternalFiles( + fileId: string, + fileContents: Record, + tmpDir: string, + ) { + await prepareTmpDirForSingleUpload(fileContents, tmpDir); + const fileCount = Object.keys(fileContents).length; + await uploadFilesFromTmpDir(this.page, fileId, tmpDir, fileCount); + } } diff --git a/integration-tests/tests/pages/group.page.ts b/integration-tests/tests/pages/group.page.ts index e5c5e54085..b309343534 100644 --- a/integration-tests/tests/pages/group.page.ts +++ b/integration-tests/tests/pages/group.page.ts @@ -166,10 +166,6 @@ export class GroupPage { await this.page.getByLabel('Address Line 1').fill(line1); } - async editAddressLine2(line2: string) { - await this.page.getByLabel('Address Line 2').fill(line2); - } - async editCity(city: string) { await this.page.getByLabel('City').fill(city); } diff --git a/integration-tests/tests/pages/review.page.ts b/integration-tests/tests/pages/review.page.ts index 735a010389..43c0d1f4fa 100644 --- a/integration-tests/tests/pages/review.page.ts +++ b/integration-tests/tests/pages/review.page.ts @@ -137,14 +137,6 @@ export class ReviewPage { .toBe(true); } - async navigateToReviewPage() { - await this.page.goto('/'); - await this.navigation.openOrganismNavigation(); - await this.navigation.selectOrganism('Ebola Sudan'); - await this.navigation.clickSubmitSequences(); - await this.page.getByRole('link', { name: "Review Review your group's" }).click(); - } - async releaseValidSequences() { await this.page.getByRole('button', { name: /Release \d+ valid sequence/ }).click(); await this.page.getByRole('button', { name: 'Release', exact: true }).click(); diff --git a/integration-tests/tests/pages/revision.page.ts b/integration-tests/tests/pages/revision.page.ts index 14ef24f645..6b3376b103 100644 --- a/integration-tests/tests/pages/revision.page.ts +++ b/integration-tests/tests/pages/revision.page.ts @@ -1,4 +1,5 @@ import { expect, type Page } from '@playwright/test'; +import { prepareTmpDirForBulkUpload, uploadFilesFromTmpDir } from '../utils/file-upload-helpers'; /** * Page object for the sequence revision page. @@ -14,23 +15,6 @@ export class RevisionPage { await this.page.goto(`/${organism}/submission/${groupId}/revise`); } - /** - * Navigate to revision page from a sequence details page - * Clicks the "Revise this sequence" link - */ - async clickReviseSequenceLink() { - // Sometimes clicking revise button doesn't register, so let's wait for sequence viewer to be visible first - // See #5447 - await expect(this.page.getByTestId('fixed-length-text-viewer')).toBeVisible(); - - await this.page - .getByRole('link', { name: 'Revise this sequence' }) - .click({ timeout: 15000 }); - await expect( - this.page.getByRole('heading', { name: 'Create new revision from' }), - ).toBeVisible(); - } - /** * Upload a sequence file */ @@ -55,39 +39,6 @@ export class RevisionPage { await expect(this.page.getByTestId('discard_metadata_file')).toBeEnabled(); } - /** - * Upload a segment file for multi-segment organisms - */ - async uploadSegmentFile(segmentName: string, fileName: string, content: string | Buffer) { - await this.page.getByTestId(`${segmentName}_segment_file`).setInputFiles({ - name: fileName, - mimeType: 'text/plain', - buffer: typeof content === 'string' ? Buffer.from(content) : content, - }); - await expect(this.page.getByTestId(`discard_${segmentName}_segment_file`)).toBeEnabled(); - } - - /** - * Discard a segment file for multi-segment organisms - */ - async discardSegmentFile(segmentName: string) { - await this.page.getByTestId(`discard_${segmentName}_segment_file`).click(); - } - - /** - * Discard the sequence file - */ - async discardSequenceFile() { - await this.page.getByTestId('discard_sequence_file').click(); - } - - /** - * Discard the metadata file - */ - async discardMetadataFile() { - await this.page.getByTestId('discard_metadata_file').click(); - } - /** * Accept the data submission terms */ @@ -107,13 +58,6 @@ export class RevisionPage { await this.page.getByRole('button', { name: 'Submit' }).click(); } - /** - * Click the Confirm button in the confirmation dialog - */ - async clickConfirm() { - await this.page.getByRole('button', { name: 'Confirm' }).click(); - } - /** * Complete the full revision submission flow * Accepts terms, submits, and confirms @@ -121,70 +65,18 @@ export class RevisionPage { async submitRevision() { await this.acceptTerms(); await this.clickSubmit(); - await this.clickConfirm(); } - /** - * Download metadata template in TSV format - */ - async downloadTsvTemplate() { - const downloadPromise = this.page.waitForEvent('download'); - await this.page.getByText('TSV', { exact: true }).click(); - return downloadPromise; - } - - /** - * Download metadata template in XLSX format - */ - async downloadXlsxTemplate() { - const downloadPromise = this.page.waitForEvent('download'); - await this.page.getByText('XLSX', { exact: true }).click(); - return downloadPromise; - } - - /** - * High-level helper: Revise a single-segment sequence - */ - async reviseSequence(options: { - sequenceFile?: { name: string; content: string | Buffer }; - metadataFile?: { name: string; content: string | Buffer }; - }) { - if (options.sequenceFile) { - await this.uploadSequenceFile(options.sequenceFile.name, options.sequenceFile.content); - } - if (options.metadataFile) { - await this.uploadMetadataFile(options.metadataFile.name, options.metadataFile.content); - } - await this.submitRevision(); - } - - /** - * High-level helper: Revise a multi-segment sequence - */ - async reviseMultiSegmentSequence(options: { - segments?: Record; - metadataFile?: { name: string; content: string | Buffer }; - discardSegments?: string[]; - }) { - // Discard segments first if specified - if (options.discardSegments) { - for (const segment of options.discardSegments) { - await this.discardSegmentFile(segment); - } - } - - // Upload new segment files - if (options.segments) { - for (const [segmentName, file] of Object.entries(options.segments)) { - await this.uploadSegmentFile(segmentName, file.name, file.content); - } - } - - // Upload metadata if provided - if (options.metadataFile) { - await this.uploadMetadataFile(options.metadataFile.name, options.metadataFile.content); - } - - await this.submitRevision(); + async uploadExternalFiles( + fileId: string, + fileContents: Record>, + tmpDir: string, + ) { + await prepareTmpDirForBulkUpload(fileContents, tmpDir); + const fileCount = Object.values(fileContents).reduce( + (total, files) => total + Object.keys(files).length, + 0, + ); + await uploadFilesFromTmpDir(this.page, fileId, tmpDir, fileCount); } } diff --git a/integration-tests/tests/pages/search.page.ts b/integration-tests/tests/pages/search.page.ts index d14d8aad9e..265efd6285 100644 --- a/integration-tests/tests/pages/search.page.ts +++ b/integration-tests/tests/pages/search.page.ts @@ -149,14 +149,6 @@ export class SearchPage { return accessionVersion; } - getSequencePreviewModal() { - return this.page.locator('[data-testid="sequence-preview-modal"]'); - } - - getHalfScreenPreview() { - return this.page.locator('[data-testid="half-screen-preview"]'); - } - toggleHalfScreenButton() { return this.page.locator('[data-testid="toggle-half-screen-button"]'); } diff --git a/integration-tests/tests/pages/sequence-detail.page.ts b/integration-tests/tests/pages/sequence-detail.page.ts index 044c39c7c1..5244bf7b71 100644 --- a/integration-tests/tests/pages/sequence-detail.page.ts +++ b/integration-tests/tests/pages/sequence-detail.page.ts @@ -26,12 +26,6 @@ export class SequenceDetailPage { } } - async selectAlignedTab() { - if (await this.alignedTab.isVisible()) { - await this.alignedTab.click(); - } - } - async expectSequenceContentVisible(timeout = 10000) { await expect(this.page.getByText(/[ACGTN]{20,}/)).toBeVisible({ timeout }); } @@ -83,8 +77,4 @@ export class SequenceDetailPage { await expect(link).toBeVisible(); await link.click(); } - - getPage() { - return this.page; - } } diff --git a/integration-tests/tests/pages/submission.page.ts b/integration-tests/tests/pages/submission.page.ts index 02f71bc10b..c1b7a9d6e0 100644 --- a/integration-tests/tests/pages/submission.page.ts +++ b/integration-tests/tests/pages/submission.page.ts @@ -1,10 +1,12 @@ import { Page } from '@playwright/test'; import { ReviewPage } from './review.page'; -import fs from 'fs'; -import path from 'path'; import Papa from 'papaparse'; import { NavigationPage } from './navigation.page'; -import { clearTmpDir } from '../utils/tmpdir'; +import { + prepareTmpDirForBulkUpload, + prepareTmpDirForSingleUpload, + uploadFilesFromTmpDir, +} from '../utils/file-upload-helpers'; class SubmissionPage { protected page: Page; @@ -68,17 +70,6 @@ class SubmissionPage { await reviewPage.waitForZeroProcessing(); return reviewPage; } - - protected async _uploadFilesFromTmpDir(testId: string, tmpDir: string, fileCount: number) { - await this.page.getByRole('heading', { name: 'Extra files' }).scrollIntoViewIfNeeded(); - // Trigger file upload (don't await) and wait for checkmarks to appear (indicates success) - void this.page.getByTestId(testId).setInputFiles(tmpDir); - return Promise.all( - Array.from({ length: fileCount }, (_, i) => - this.page.getByText('✓').nth(i).waitFor({ state: 'visible' }), - ), - ); - } } export class SingleSequenceSubmissionPage extends SubmissionPage { @@ -105,11 +96,6 @@ export class SingleSequenceSubmissionPage extends SubmissionPage { await this.page.getByLabel('Author affiliations').fill(authorAffiliations); } - async fillField(fieldName: string, value: string) { - await this.page.getByLabel(fieldName).fill(value); - await this.page.getByLabel(fieldName).blur(); - } - async fillSubmissionFormDummyOrganism({ submissionId, country, @@ -140,19 +126,9 @@ export class SingleSequenceSubmissionPage extends SubmissionPage { fileContents: Record, tmpDir: string, ) { - await this._prepareTmpDirWithFiles(fileContents, tmpDir); + await prepareTmpDirForSingleUpload(fileContents, tmpDir); const fileCount = Object.keys(fileContents).length; - await this._uploadFilesFromTmpDir(fileId, tmpDir, fileCount); - } - - private async _prepareTmpDirWithFiles(fileContents: Record, tmpDir: string) { - await clearTmpDir(tmpDir); - - await Promise.all( - Object.entries(fileContents).map(([fileName, fileContent]) => - fs.promises.writeFile(path.join(tmpDir, fileName), fileContent), - ), - ); + await uploadFilesFromTmpDir(this.page, fileId, tmpDir, fileCount); } async completeSubmission( @@ -229,43 +205,16 @@ export class BulkSubmissionPage extends SubmissionPage { }); } - /** - * The given file contents will be stored in a temp dir and then submitted - * for the given file ID. - * @param fileId For which file ID to upload the files. - * @param fileContents A struct: submissionID -> filename -> filecontent. - * @param tmpDir The temporary directory to use for storing files. - */ async uploadExternalFiles( fileId: string, fileContents: Record>, tmpDir: string, ) { - await this._prepareTmpDirWithFiles(fileContents, tmpDir); + await prepareTmpDirForBulkUpload(fileContents, tmpDir); const fileCount = Object.values(fileContents).reduce( (total, files) => total + Object.keys(files).length, 0, ); - await this._uploadFilesFromTmpDir(fileId, tmpDir, fileCount); - } - - private async _prepareTmpDirWithFiles( - fileContents: Record>, - tmpDir: string, - ) { - await clearTmpDir(tmpDir); - - // Create submission directories and write files - const submissionIds = Object.keys(fileContents); - await Promise.all( - submissionIds.map((submissionId) => fs.promises.mkdir(path.join(tmpDir, submissionId))), - ); - await Promise.all( - Object.entries(fileContents).flatMap(([submissionId, files]) => { - return Object.entries(files).map(([fileName, fileContent]) => - fs.promises.writeFile(path.join(tmpDir, submissionId, fileName), fileContent), - ); - }), - ); + await uploadFilesFromTmpDir(this.page, fileId, tmpDir, fileCount); } } diff --git a/integration-tests/tests/specs/features/file-sharing.spec.ts b/integration-tests/tests/specs/features/file-sharing.spec.ts index b8e6b1b4e9..51364e6dea 100644 --- a/integration-tests/tests/specs/features/file-sharing.spec.ts +++ b/integration-tests/tests/specs/features/file-sharing.spec.ts @@ -1,7 +1,13 @@ +import { expect } from '@playwright/test'; import { test } from '../../fixtures/tmpdir.fixture'; +import { EditPage } from '../../pages/edit.page'; +import { ReviewPage } from '../../pages/review.page'; +import { RevisionPage } from '../../pages/revision.page'; +import { SearchPage } from '../../pages/search.page'; import { BulkSubmissionPage, SingleSequenceSubmissionPage } from '../../pages/submission.page'; const ORGANISM_NAME = 'Test organism (with files)'; +const ORGANISM_URL_NAME = 'dummy-organism-with-files'; const RAW_READS = 'raw_reads'; const METADATA_HEADERS = ['submissionId', 'country', 'date']; const COUNTRY_1 = 'Norway'; @@ -88,3 +94,116 @@ test('bulk submit 1 seq with a 35 MB file', async ({ page, groupId, tmpDir }) => const searchPage = await reviewPage.releaseAndGoToReleasedSequences(); await searchPage.checkFileContentInModal('cell', COUNTRY_1, LARGE_FILE); }); + +const REVISION_METADATA_HEADERS = ['accession', 'submissionId', 'country', 'date']; +const REVISION_FILES = { 'revised_file.txt': 'This is a revised file.' }; +const REVISION_FILES_2 = { 'another_file.txt': 'Another revised file content.' }; + +test('bulk revise 2 seqs with files', async ({ page, groupId, tmpDir }) => { + test.setTimeout(300_000); + + const timestamp = Date.now(); + const id1 = `bulk-rev-1-${timestamp}`; + const id2 = `bulk-rev-2-${timestamp}`; + const revId1 = `bulk-rev-updated-1-${timestamp}`; + const revId2 = `bulk-rev-updated-2-${timestamp}`; + + // Step 1: Submit and release 2 sequences + const submissionPage = new BulkSubmissionPage(page); + await submissionPage.navigateToSubmissionPage(ORGANISM_NAME); + await submissionPage.uploadMetadataFile(METADATA_HEADERS, [ + [id1, COUNTRY_1, '2022-01-01'], + [id2, COUNTRY_2, '2022-01-02'], + ]); + const reviewPage = await submissionPage.submitAndWaitForProcessingDone(); + const searchPage = await reviewPage.releaseAndGoToReleasedSequences(); + + // Get the accessions of the released sequences + const accessionVersions = await searchPage.waitForSequencesInSearch(2); + const accession1 = accessionVersions.find((av) => av.version === 1)?.accession; + const accession2 = accessionVersions.find( + (av) => av.version === 1 && av.accession !== accession1, + )?.accession; + expect(accession1).toBeDefined(); + expect(accession2).toBeDefined(); + + // Step 2: Bulk revise with files + const revisionPage = new RevisionPage(page); + await revisionPage.goto(ORGANISM_URL_NAME, groupId); + + // Upload revision metadata (with accession column) + const revisionMetadata = [ + [accession1, revId1, COUNTRY_1, '2022-02-01'], + [accession2, revId2, COUNTRY_2, '2022-02-02'], + ]; + await page.getByTestId('metadata_file').setInputFiles({ + name: 'revision_metadata.tsv', + mimeType: 'text/plain', + buffer: Buffer.from( + [ + REVISION_METADATA_HEADERS.join('\t'), + ...revisionMetadata.map((r) => r.join('\t')), + ].join('\n'), + ), + }); + + // Upload files for each revision + await revisionPage.uploadExternalFiles( + RAW_READS, + { [revId1]: REVISION_FILES, [revId2]: REVISION_FILES_2 }, + tmpDir, + ); + await revisionPage.submitRevision(); + + // Step 3: Verify in review page and release + const reviewPage2 = new ReviewPage(page); + await reviewPage2.waitForZeroProcessing(); + await reviewPage2.releaseValidSequences(); + + const searchPage2 = new SearchPage(page); + await searchPage2.goToReleasedSequences(ORGANISM_URL_NAME, groupId); + await page.goto(page.url() + '?column_submissionId=true'); + + // Check that revised sequences have the files + await searchPage2.checkFileContentInModal('cell', revId1, REVISION_FILES); + await searchPage2.checkFileContentInModal('cell', revId2, REVISION_FILES_2); +}); + +test('single revise seq with files via edit page', async ({ page, groupId, tmpDir }) => { + test.setTimeout(300_000); + + // Step 1: Submit and release a sequence + const submissionPage = new SingleSequenceSubmissionPage(page); + await submissionPage.navigateToSubmissionPage(ORGANISM_NAME); + await submissionPage.fillSubmissionFormDummyOrganism({ + submissionId: 'single-rev', + country: COUNTRY_1, + date: '2023-01-01', + }); + const reviewPage = await submissionPage.submitAndWaitForProcessingDone(); + const searchPage = await reviewPage.releaseAndGoToReleasedSequences(); + + // Step 2: Wait until sequence is available and directly go to revise/edit page + const accessionVersions = await searchPage.waitForSequencesInSearch(1); + const editPage = new EditPage(page); + await editPage.goto( + ORGANISM_URL_NAME, + accessionVersions[0].accession, + accessionVersions[0].version, + ); + + // Step 3: Upload files in the edit page + await editPage.uploadExternalFiles(RAW_READS, REVISION_FILES, tmpDir); + const reviewPage2 = await editPage.submitChanges(); + await reviewPage2.waitForZeroProcessing(); + await reviewPage2.releaseValidSequences(); + + // Step 4: Release and verify files + const searchPage2 = new SearchPage(page); + await searchPage2.goToReleasedSequences(ORGANISM_URL_NAME, groupId); + await searchPage2.checkFileContentInModal( + 'link', + `${accessionVersions[0].accession}.${accessionVersions[0].version + 1}`, + REVISION_FILES, + ); +}); diff --git a/integration-tests/tests/utils/file-upload-helpers.ts b/integration-tests/tests/utils/file-upload-helpers.ts new file mode 100644 index 0000000000..07cf5d9231 --- /dev/null +++ b/integration-tests/tests/utils/file-upload-helpers.ts @@ -0,0 +1,61 @@ +import { Page } from '@playwright/test'; +import fs from 'fs'; +import path from 'path'; +import { clearTmpDir } from './tmpdir'; + +/** + * @param fileContents A struct: submissionID -> filename -> filecontent + * @param tmpDir The temporary directory to use for storing files + */ +export async function prepareTmpDirForBulkUpload( + fileContents: Record>, + tmpDir: string, +) { + await clearTmpDir(tmpDir); + + // Create submission directories and write files + const submissionIds = Object.keys(fileContents); + await Promise.all( + submissionIds.map((submissionId) => fs.promises.mkdir(path.join(tmpDir, submissionId))), + ); + await Promise.all( + Object.entries(fileContents).flatMap(([submissionId, files]) => { + return Object.entries(files).map(([fileName, fileContent]) => + fs.promises.writeFile(path.join(tmpDir, submissionId, fileName), fileContent), + ); + }), + ); +} + +/** + * @param fileContents A struct: filename -> filecontent + * @param tmpDir The temporary directory to use for storing files + */ +export async function prepareTmpDirForSingleUpload( + fileContents: Record, + tmpDir: string, +) { + await clearTmpDir(tmpDir); + + await Promise.all( + Object.entries(fileContents).map(([fileName, fileContent]) => + fs.promises.writeFile(path.join(tmpDir, fileName), fileContent), + ), + ); +} + +export async function uploadFilesFromTmpDir( + page: Page, + testId: string, + tmpDir: string, + fileCount: number, +) { + await page.getByRole('heading', { name: 'Extra files' }).scrollIntoViewIfNeeded(); + // Trigger file upload (don't await) and wait for checkmarks to appear (indicates success) + void page.getByTestId(testId).setInputFiles(tmpDir); + return Promise.all( + Array.from({ length: fileCount }, (_, i) => + page.getByText('✓').nth(i).waitFor({ state: 'visible' }), + ), + ); +} diff --git a/website/src/components/Edit/EditPage.tsx b/website/src/components/Edit/EditPage.tsx index 41572a34ff..175af25d50 100644 --- a/website/src/components/Edit/EditPage.tsx +++ b/website/src/components/Edit/EditPage.tsx @@ -9,12 +9,13 @@ import { getClientLogger } from '../../clientLogger.ts'; import { routes } from '../../routes/routes.ts'; import { backendApi } from '../../services/backendApi.ts'; import { backendClientHooks } from '../../services/serviceHooks.ts'; -import { type SequenceEntryToEdit, approvedForReleaseStatus } from '../../types/backend.ts'; +import { type FilesBySubmissionId, type SequenceEntryToEdit, approvedForReleaseStatus } from '../../types/backend.ts'; import { type InputField, type SubmissionDataTypes } from '../../types/config.ts'; import type { ClientConfig } from '../../types/runtimeConfig.ts'; import { createAuthorizationHeader } from '../../utils/createAuthorizationHeader.ts'; import { getAccessionVersionString } from '../../utils/extractAccessionVersion.ts'; import { displayConfirmationDialog } from '../ConfirmationDialog.tsx'; +import { ExtraFilesUpload } from '../Submission/DataUploadForm.tsx'; import { Button } from '../common/Button'; import { withQueryProvider } from '../common/withQueryProvider.tsx'; @@ -54,8 +55,10 @@ const InnerEditPage: FC = ({ const [editableSequences, setEditableSequences] = useState( EditableSequences.fromInitialData(dataToEdit, submissionDataTypes.maxSequencesPerEntry), ); + const [fileMapping, setFileMapping] = useState(undefined); const isCreatingRevision = dataToEdit.status === approvedForReleaseStatus; + const extraFilesEnabled = submissionDataTypes.files?.enabled ?? false; const { mutate: submitRevision, isPending: isRevisionPending } = useSubmitRevision( organism, @@ -85,9 +88,17 @@ const InnerEditPage: FC = ({ toast.error('Please enter metadata.', { position: 'top-center', autoClose: false }); return; } + + let fileMappingWithSubmissionId: FilesBySubmissionId | undefined; + if (extraFilesEnabled && fileMapping !== undefined && Object.keys(fileMapping).length > 0) { + const files = Object.values(fileMapping)[0]; + fileMappingWithSubmissionId = { [dataToEdit.submissionId]: files }; + } + if (!submissionDataTypes.consensusSequences) { submitRevision({ metadataFile, + fileMapping: fileMappingWithSubmissionId, }); return; } @@ -102,6 +113,7 @@ const InnerEditPage: FC = ({ submitRevision({ metadataFile, sequenceFile, + fileMapping: fileMappingWithSubmissionId, }); } else { submitEdit({ @@ -146,6 +158,19 @@ const InnerEditPage: FC = ({ /> )} + {isCreatingRevision && extraFilesEnabled && ( +
+ toast.error(msg, { position: 'top-center', autoClose: false })} + /> +
+ )}