Skip to content

Commit

Permalink
feat: Download button (#844)
Browse files Browse the repository at this point in the history
* update

* up

* add test

* fix

* add type

* add link

* better handle redirects
  • Loading branch information
theosanderson authored Jan 26, 2024
1 parent aa99f70 commit 9abac5e
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { SequencesContainer } from './SequencesContainer';
import { type TableDataEntry } from './getTableData';
import { getReferenceGenomes, getRuntimeConfig } from '../../config';
import { routes } from '../../routes.ts';
interface Props {
tableData: TableDataEntry[];
Expand Down Expand Up @@ -33,6 +34,14 @@ const nucleotideSegmentNames = referenceGenomes.nucleotideSequences.map((s) => s
</tbody>
</table>
</div>
<div>
<a
class='mt-4 inline-block text-blue-600 hover:text-blue-800'
href={routes.sequencesFastaPage(organism, accessionVersion) + '?download'}
>
Download FASTA
</a>
</div>
<div class='mt-10'>
<SequencesContainer
client:load
Expand Down
21 changes: 15 additions & 6 deletions website/src/pages/[organism]/seq/[accessionVersion].fa/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import type { ProblemDetail } from '../../../../types/backend.ts';
import { parseAccessionVersionFromString } from '../../../../utils/extractAccessionVersion.ts';
import { fastaEntryToString, parseFasta } from '../../../../utils/parseFasta.ts';

export const GET: APIRoute = async ({ params, redirect }) => {
export const GET: APIRoute = async ({ params, redirect, request }) => {
const accessionVersion = params.accessionVersion!;
const organism = params.organism!;

const result = await getSequenceDetailsUnalignedFasta(accessionVersion, organism);
const isDownload = new URL(request.url).searchParams.has('download');

const result = await getSequenceDetailsUnalignedFasta(accessionVersion, organism, isDownload);
if (!result.isOk()) {
return new Response(undefined, {
status: 404,
Expand All @@ -23,10 +25,16 @@ export const GET: APIRoute = async ({ params, redirect }) => {
return redirect(result.value.redirectUrl);
}

const headers: Record<string, string> = {
'Content-Type': 'text/x-fasta',
};
if (isDownload) {
const filename = `${accessionVersion}.fa`;
headers['Content-Disposition'] = `attachment; filename="${filename}"`;
}

return new Response(result.value.fasta, {
headers: {
'Content-Type': 'text/x-fasta',
},
headers,
});
};

Expand All @@ -48,6 +56,7 @@ type Redirect = {
const getSequenceDetailsUnalignedFasta = async (
accessionVersion: string,
organism: string,
isDownload: boolean,
): Promise<Result<Data | Redirect, ProblemDetail>> => {
const { accession, version } = parseAccessionVersionFromString(accessionVersion);

Expand All @@ -57,7 +66,7 @@ const getSequenceDetailsUnalignedFasta = async (
const latestVersionResult = await lapisClient.getLatestAccessionVersion(accession);
return latestVersionResult.map((latestVersion) => ({
type: ResultType.REDIRECT,
redirectUrl: routes.sequencesFastaPage(organism, latestVersion),
redirectUrl: routes.sequencesFastaPage(organism, latestVersion, isDownload),
}));
}

Expand Down
9 changes: 7 additions & 2 deletions website/src/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ export const routes = {
`/${organism}/seq/${getAccessionVersionString(accessionVersion)}`,
sequencesVersionsPage: (organism: string, accessionVersion: AccessionVersion | string) =>
`/${organism}/seq/${getAccessionVersionString(accessionVersion)}/versions`,
sequencesFastaPage: (organism: string, accessionVersion: AccessionVersion | string) =>
`${routes.sequencesDetailsPage(organism, accessionVersion)}.fa`,
sequencesFastaPage: (organism: string, accessionVersion: AccessionVersion | string, download = false) => {
let url = `${routes.sequencesDetailsPage(organism, accessionVersion)}.fa`;
if (download) {
url += '?download';
}
return url;
},
submitPage: (organism: string) => withOrganism(organism, '/submit'),
revisePage: (organism: string) => withOrganism(organism, '/revise'),
editPage: (organism: string, accessionVersion: AccessionVersion) =>
Expand Down
13 changes: 12 additions & 1 deletion website/tests/pages/sequences/accession.fa.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,18 @@ import { baseUrl, dummyOrganism, expect, test, testSequenceEntry } from '../../e
test.describe('The sequence.fa page', () => {
test('can load and show fasta file', async () => {
const url = `${baseUrl}${routes.sequencesFastaPage(dummyOrganism.key, testSequenceEntry)}`;
const content = await (await fetch(url)).text();
const response = await fetch(url);
const content = await response.text();
expect(content).toBe(`>${testSequenceEntry.name}\n${testSequenceEntry.unaligned}\n`);
});

test('can download fasta file', async () => {
const downloadUrl = `${baseUrl}${routes.sequencesFastaPage(dummyOrganism.key, testSequenceEntry, true)}`;
const response = await fetch(downloadUrl);
const contentDisposition = response.headers.get('Content-Disposition');

expect(contentDisposition).not.toBeNull();
expect(contentDisposition).toContain('attachment');
expect(contentDisposition).toContain(testSequenceEntry.name);
});
});

0 comments on commit 9abac5e

Please sign in to comment.