Skip to content

Commit e6ade07

Browse files
authored
Download table data (#848)
1 parent 555a9df commit e6ade07

9 files changed

Lines changed: 251 additions & 37 deletions

File tree

src/content/app/tools/blast/blast-download/submissionDownload.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ const downloadBlastSubmission = async (
100100
csv = createCSVForGenomicBlast(job.data);
101101
} else if (blastedAgainst === 'cdna') {
102102
csv = createCSVForTranscriptBlast(job.data);
103-
} else if (blastedAgainst === 'protein') {
103+
} else if (blastedAgainst === 'pep') {
104104
csv = createCSVForProteinBlast(job.data);
105105
}
106106

src/content/app/tools/blast/views/blast-submission-results/BlastSubmissionResults.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,8 @@ const Main = () => {
124124
key={data.sequence.id}
125125
species={data.species}
126126
sequence={data.sequence}
127-
preset={blastSubmission.submittedData.preset}
127+
submission={blastSubmission}
128128
blastResults={data.blastResults}
129-
parameters={blastSubmission.submittedData.parameters}
130129
/>
131130
)
132131
);

src/content/app/tools/blast/views/blast-submission-results/components/blast-results-per-sequence/BlastResultsPerSequence.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,10 @@ import SingleBlastJobResult from '../single-blast-job-result/SingleBlastJobResul
2626
import { parseBlastInput } from 'src/content/app/tools/blast/utils/blastInputParser';
2727

2828
import type {
29-
BlastSubmissionParameters,
30-
BlastJobWithResults
29+
BlastJobWithResults,
30+
BlastSubmission
3131
} from 'src/content/app/tools/blast/state/blast-results/blastResultsSlice';
3232
import type { Species } from 'src/content/app/tools/blast/state/blast-form/blastFormSlice';
33-
import type { DatabaseType } from 'src/content/app/tools/blast/types/blastSettings';
3433

3534
import styles from './BlastResultsPerSequence.scss';
3635

@@ -40,13 +39,19 @@ type BlastResultsPerSequenceProps = {
4039
value: string;
4140
};
4241
species: Species[];
43-
preset: string;
4442
blastResults: BlastJobWithResults[];
45-
parameters: BlastSubmissionParameters;
43+
submission: BlastSubmission;
4644
};
4745

4846
const BlastResultsPerSequence = (props: BlastResultsPerSequenceProps) => {
49-
const { sequence, species, blastResults, parameters } = props;
47+
const {
48+
sequence,
49+
species,
50+
blastResults,
51+
submission: {
52+
submittedData: { parameters, preset }
53+
}
54+
} = props;
5055
const parsedBlastSequence = parseBlastInput(sequence.value)[0];
5156
const { header: sequenceHeader, value: sequenceValue } = parsedBlastSequence;
5257
const sequenceHeaderLabel =
@@ -73,7 +78,7 @@ const BlastResultsPerSequence = (props: BlastResultsPerSequenceProps) => {
7378
<JobParameters
7479
sequenceValue={sequence.value}
7580
parameters={parameters}
76-
preset={props.preset}
81+
preset={preset}
7782
/>
7883
)}
7984
</div>
@@ -103,7 +108,7 @@ const BlastResultsPerSequence = (props: BlastResultsPerSequenceProps) => {
103108
species={speciesInfo}
104109
jobResult={result}
105110
diagramWidth={plotwidth}
106-
blastDatabase={parameters.database as DatabaseType}
111+
submission={props.submission}
107112
/>
108113
);
109114
})}

src/content/app/tools/blast/views/blast-submission-results/components/single-blast-job-result/SingleBlastJobResult.tsx

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,22 @@ import ShowHide from 'src/shared/components/show-hide/ShowHide';
2424
import BlastHitsDiagram from 'src/content/app/tools/blast/components/blast-hits-diagram/BlastHitsDiagram';
2525
import BlastSequenceAlignment from 'src/content/app/tools/blast/components/blast-sequence-alignment/BlastSequenceAlignment';
2626

27+
import {
28+
createCSVForGenomicBlast,
29+
createCSVForProteinBlast,
30+
createCSVForTranscriptBlast
31+
} from 'src/content/app/tools/blast/blast-download/createBlastCSVTable';
32+
import { downloadTextAsFile } from 'src/shared/helpers/downloadAsFile';
33+
2734
import type {
2835
BlastHit,
2936
BlastJobResult,
3037
HSP
3138
} from 'src/content/app/tools/blast/types/blastJob';
32-
import type { BlastJobWithResults } from 'src/content/app/tools/blast/state/blast-results/blastResultsSlice';
39+
import type {
40+
BlastJobWithResults,
41+
BlastSubmission
42+
} from 'src/content/app/tools/blast/state/blast-results/blastResultsSlice';
3343
import type { Species } from 'src/content/app/tools/blast/state/blast-form/blastFormSlice';
3444
import type { BlastSequenceAlignmentInput } from 'src/content/app/tools/blast/components/blast-sequence-alignment/blastSequenceAlignmentTypes';
3545
import type { DatabaseType } from 'src/content/app/tools/blast/types/blastSettings';
@@ -48,7 +58,7 @@ type SingleBlastJobResultProps = {
4858
jobResult: BlastJobWithResults;
4959
species: Species;
5060
diagramWidth: number;
51-
blastDatabase: DatabaseType;
61+
submission: BlastSubmission;
5262
};
5363

5464
const hitsTableColumns: DataTableColumns = [
@@ -70,7 +80,12 @@ const hitsTableColumns: DataTableColumns = [
7080
title: 'Length',
7181
isSortable: true
7282
},
73-
{ width: '200px', columnId: 'view_alignment', isHideable: false },
83+
{
84+
width: '200px',
85+
columnId: 'view_alignment',
86+
isHideable: false,
87+
isExportable: false
88+
},
7489
{
7590
width: '100px',
7691
columnId: 'percentage_id',
@@ -153,12 +168,7 @@ const hitsTableColumns: DataTableColumns = [
153168
];
154169

155170
const SingleBlastJobResult = (props: SingleBlastJobResultProps) => {
156-
const {
157-
species: speciesInfo,
158-
jobResult,
159-
diagramWidth,
160-
blastDatabase
161-
} = props;
171+
const { species: speciesInfo, jobResult, diagramWidth, submission } = props;
162172
const [isExpanded, setExpanded] = useState(false);
163173

164174
const alignmentsCount = countAlignments(jobResult.data);
@@ -186,18 +196,21 @@ const SingleBlastJobResult = (props: SingleBlastJobResultProps) => {
186196
</div>
187197

188198
{isExpanded && (
189-
<HitsTable jobResult={jobResult} blastDatabase={blastDatabase} />
199+
<HitsTable jobResult={jobResult} submission={submission} />
190200
)}
191201
</div>
192202
);
193203
};
194204

195205
type HitsTableProps = {
196206
jobResult: SingleBlastJobResultProps['jobResult'];
197-
blastDatabase: DatabaseType;
207+
submission: BlastSubmission;
198208
};
199209
const HitsTable = (props: HitsTableProps) => {
200-
const { jobResult, blastDatabase } = props;
210+
const { jobResult, submission } = props;
211+
212+
const blastDatabase = submission.submittedData.parameters
213+
.database as DatabaseType;
201214

202215
const [tableState, setTableState] = useState<Partial<DataTableState>>({
203216
rowsPerPage: 100,
@@ -228,13 +241,12 @@ const HitsTable = (props: HitsTableProps) => {
228241
hitHsp.hsp_align_len,
229242
'', // view_alignment
230243
hitHsp.hsp_identity,
231-
hitHsp.hsp_score,
232-
<DynamicColumnContent
233-
key={counter}
234-
hit={hit}
235-
blastDatabase={blastDatabase}
236-
hitHsp={hitHsp}
237-
/>,
244+
hitHsp.hsp_bit_score,
245+
getDynamicColumnContent({
246+
hit,
247+
blastDatabase,
248+
hitHsp
249+
}),
238250
<span key={counter} className={styles.hitOrientation}>
239251
{hitHsp.hsp_hit_frame === '1' ? 'Forward' : 'Reverse'}
240252
</span>,
@@ -330,6 +342,19 @@ const HitsTable = (props: HitsTableProps) => {
330342
);
331343
};
332344

345+
const downloadHandler = async () => {
346+
let csv = '';
347+
if (blastDatabase === 'dna') {
348+
csv = createCSVForGenomicBlast(jobResult.data);
349+
} else if (blastDatabase === 'cdna') {
350+
csv = createCSVForTranscriptBlast(jobResult.data);
351+
} else if (blastDatabase === 'pep') {
352+
csv = createCSVForProteinBlast(jobResult.data);
353+
}
354+
355+
await downloadTextAsFile(csv, 'table.csv');
356+
};
357+
333358
return (
334359
<div className={styles.tableWrapper}>
335360
<DataTable
@@ -341,9 +366,10 @@ const HitsTable = (props: HitsTableProps) => {
341366
expandedContent={expandedContent}
342367
disabledActions={[
343368
TableAction.FILTERS,
344-
TableAction.DOWNLOAD_ALL_DATA,
369+
TableAction.FIND_IN_TABLE,
345370
TableAction.DOWNLOAD_SHOWN_DATA
346371
]}
372+
downloadHandler={downloadHandler}
347373
/>
348374
</div>
349375
);
@@ -373,7 +399,7 @@ type DynamicColumnContentProps = {
373399
blastDatabase: DatabaseType;
374400
};
375401

376-
const DynamicColumnContent = (props: DynamicColumnContentProps) => {
402+
const getDynamicColumnContent = (props: DynamicColumnContentProps) => {
377403
const { hit, blastDatabase, hitHsp } = props;
378404

379405
if (blastDatabase !== 'dna') {

src/shared/components/data-table/DataTable.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ type TableContextType = DataTableState & {
4040
selectableColumnIndex: number;
4141
expandedContent: { [rowId: string]: ReactNode };
4242
disabledActions?: TableAction[];
43+
downloadFileName?: string;
44+
downloadHandler?: () => Promise<void>;
4345
rows: TableRows;
4446
};
4547

@@ -48,14 +50,16 @@ export const TableContext = React.createContext(
4850
);
4951

5052
export type TableProps = {
51-
onStateChange?: (newState: DataTableState) => void;
53+
state: Partial<DataTableState>;
5254
columns: DataTableColumns;
53-
state?: Partial<DataTableState>;
5455
theme: TableTheme;
5556
selectableColumnIndex: number;
56-
className?: string;
5757
expandedContent: { [rowId: string]: ReactNode };
5858
disabledActions?: TableAction[];
59+
className?: string;
60+
downloadFileName?: string;
61+
downloadHandler?: () => Promise<void>;
62+
onStateChange?: (newState: DataTableState) => void;
5963
};
6064
const DataTable = (props: TableProps) => {
6165
const initialDataTableState = {
@@ -96,7 +100,9 @@ const DataTable = (props: TableProps) => {
96100
theme: props.theme,
97101
selectableColumnIndex: props.selectableColumnIndex,
98102
expandedContent: props.expandedContent,
99-
disabledActions: props.disabledActions
103+
disabledActions: props.disabledActions,
104+
downloadFileName: props.downloadFileName,
105+
downloadHandler: props.downloadHandler
100106
}}
101107
>
102108
<div className={wrapperClasses}>

src/shared/components/data-table/components/table-controls/components/table-actions/TableActions.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { TableContext } from 'src/shared/components/data-table/DataTable';
2121
import RowVisibilityController from 'src/shared/components/data-table/components/main/components/table-row/components/row-visibility-controller/RowVisibilityController';
2222
import FindInTable from './components/find-in-table/FindInTable';
2323
import ShowHideColumns from './components/show-hide-columns/ShowHideColumns';
24+
import DownloadData from './components/download-data/DownloadData';
2425

2526
import {
2627
type DataTableState,
@@ -54,7 +55,7 @@ const actionOptions = [
5455
},
5556
{
5657
value: TableAction.DOWNLOAD_ALL_DATA,
57-
label: 'Download all data'
58+
label: 'Download this table'
5859
},
5960
{
6061
value: TableAction.RESTORE_DEFAULTS,
@@ -144,6 +145,10 @@ const getActionComponent = (selectedAction: TableAction) => {
144145
return <ShowHideColumns />;
145146
case TableAction.SHOW_HIDE_ROWS:
146147
return <RowVisibilityController />;
148+
case TableAction.DOWNLOAD_ALL_DATA:
149+
return <DownloadData />;
150+
case TableAction.DOWNLOAD_SHOWN_DATA:
151+
return <DownloadData />;
147152
default:
148153
return null;
149154
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
@import 'src/styles/common';
2+
3+
.downloadData {
4+
display: flex;
5+
column-gap: 10px;
6+
margin-left: 10px;
7+
align-items: center;
8+
}
9+
10+
.cancel {
11+
color: $blue;
12+
cursor: pointer;
13+
margin-left: 10px;
14+
}

0 commit comments

Comments
 (0)