UNPKG

@jbrowse/plugin-linear-genome-view

Version:

JBrowse 2 linear genome view

110 lines (109 loc) 6.57 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const ui_1 = require("@jbrowse/core/ui"); const util_1 = require("@jbrowse/core/util"); const formatFastaStrings_1 = require("@jbrowse/core/util/formatFastaStrings"); const ContentCopy_1 = __importDefault(require("@mui/icons-material/ContentCopy")); const GetApp_1 = __importDefault(require("@mui/icons-material/GetApp")); const material_1 = require("@mui/material"); const copy_to_clipboard_1 = __importDefault(require("copy-to-clipboard")); const file_saver_1 = require("file-saver"); const mobx_react_1 = require("mobx-react"); const mui_1 = require("tss-react/mui"); const fetchSequence_1 = require("./fetchSequence"); const useStyles = (0, mui_1.makeStyles)()({ dialogContent: { width: '80em', }, textAreaFont: { fontFamily: 'Courier New', }, ml: { marginLeft: 10, }, }); const GetSequenceDialog = (0, mobx_react_1.observer)(function ({ model, handleClose, }) { const { classes } = useStyles(); const [error, setError] = (0, react_1.useState)(); const [sequenceChunks, setSequenceChunks] = (0, react_1.useState)(); const [rev, setReverse] = (0, react_1.useState)(false); const [copied, setCopied] = (0, react_1.useState)(false); const [comp, setComplement] = (0, react_1.useState)(false); const { leftOffset, rightOffset } = model; const loading = sequenceChunks === undefined; (0, react_1.useEffect)(() => { const controller = new AbortController(); (async () => { try { const selection = model.getSelectedRegions(leftOffset, rightOffset); if (selection.length === 0) { throw new Error('Selected region is out of bounds'); } setSequenceChunks(await (0, fetchSequence_1.fetchSequence)(model, selection)); } catch (e) { console.error(e); setError(e); } })(); return () => { controller.abort(); }; }, [model, leftOffset, rightOffset]); const sequence = sequenceChunks ? (0, formatFastaStrings_1.formatSeqFasta)(sequenceChunks.map(chunk => { let chunkSeq = chunk.get('seq'); const chunkRefName = chunk.get('refName'); const chunkStart = chunk.get('start') + 1; const chunkEnd = chunk.get('end'); const loc = `${chunkRefName}:${chunkStart}-${chunkEnd}`; if ((chunkSeq === null || chunkSeq === void 0 ? void 0 : chunkSeq.length) !== chunkEnd - chunkStart + 1) { throw new Error(`${loc} returned ${chunkSeq.length.toLocaleString()} bases, but should have returned ${(chunkEnd - chunkStart).toLocaleString()}`); } if (rev) { chunkSeq = (0, util_1.reverse)(chunkSeq); } if (comp) { chunkSeq = (0, util_1.complement)(chunkSeq); } return { header: loc + (rev ? '-rev' : '') + (comp ? '-comp' : ''), seq: chunkSeq, }; })) : ''; const sequenceTooLarge = sequence ? sequence.length > 1000000 : false; return ((0, jsx_runtime_1.jsxs)(ui_1.Dialog, { maxWidth: "xl", open: true, onClose: () => { handleClose(); model.setOffsets(); }, title: "Reference sequence", children: [(0, jsx_runtime_1.jsxs)(material_1.DialogContent, { children: [error ? ((0, jsx_runtime_1.jsx)(ui_1.ErrorMessage, { error: error })) : loading ? ((0, jsx_runtime_1.jsx)(ui_1.LoadingEllipses, { message: "Retrieving sequences" })) : null, (0, jsx_runtime_1.jsx)(material_1.TextField, { "data-testid": "rubberband-sequence", variant: "outlined", multiline: true, minRows: 5, maxRows: 10, disabled: sequenceTooLarge, className: classes.dialogContent, fullWidth: true, value: sequenceTooLarge ? 'Reference sequence too large to display, use the download FASTA button' : sequence, slotProps: { input: { readOnly: true, classes: { input: classes.textAreaFont, }, }, } }), (0, jsx_runtime_1.jsxs)(material_1.FormGroup, { children: [(0, jsx_runtime_1.jsx)(material_1.FormControlLabel, { control: (0, jsx_runtime_1.jsx)(material_1.Checkbox, { value: rev, onChange: event => { setReverse(event.target.checked); } }), label: "Reverse sequence" }), (0, jsx_runtime_1.jsx)(material_1.FormControlLabel, { control: (0, jsx_runtime_1.jsx)(material_1.Checkbox, { value: comp, onChange: event => { setComplement(event.target.checked); } }), label: "Complement sequence" })] }), (0, jsx_runtime_1.jsx)(material_1.Typography, { style: { margin: 10 }, children: "Note: Check both boxes for the \"reverse complement\"" })] }), (0, jsx_runtime_1.jsxs)(material_1.DialogActions, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { onClick: () => { (0, copy_to_clipboard_1.default)(sequence); setCopied(true); setTimeout(() => { setCopied(false); }, 500); }, disabled: loading || !!error || sequenceTooLarge, color: "primary", startIcon: (0, jsx_runtime_1.jsx)(ContentCopy_1.default, {}), children: copied ? 'Copied' : 'Copy to clipboard' }), (0, jsx_runtime_1.jsx)(material_1.Button, { onClick: () => { (0, file_saver_1.saveAs)(new Blob([sequence || ''], { type: 'text/x-fasta;charset=utf-8', }), 'jbrowse_ref_seq.fa'); }, disabled: loading || !!error, color: "primary", startIcon: (0, jsx_runtime_1.jsx)(GetApp_1.default, {}), children: "Download FASTA" }), (0, jsx_runtime_1.jsx)(material_1.Button, { onClick: handleClose, variant: "contained", children: "Close" })] })] })); }); exports.default = GetSequenceDialog;