@jbrowse/plugin-linear-genome-view
Version:
JBrowse 2 linear genome view
110 lines (109 loc) • 6.57 kB
JavaScript
;
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;