gramene-search 2.23.0 → 2.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -1
- package/dist/index.css +28 -3
- package/dist/index.css.map +1 -1
- package/dist/index.js +156 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ var $gXNCa$reactsimpletreemenu = require("react-simple-tree-menu");
|
|
|
31
31
|
require("@fortawesome/fontawesome-free/css/all.min.css");
|
|
32
32
|
var $gXNCa$gramenedbxrefs = require("gramene-dbxrefs");
|
|
33
33
|
var $gXNCa$reacticonsai = require("react-icons/ai");
|
|
34
|
+
var $gXNCa$grameneprimers = require("gramene-primers");
|
|
34
35
|
var $gXNCa$gramenesearchvis = require("gramene-search-vis");
|
|
35
36
|
var $gXNCa$numeral = require("numeral");
|
|
36
37
|
var $gXNCa$firebaseauth = require("firebase/auth");
|
|
@@ -6280,6 +6281,15 @@ var $d365d8c287ab0c94$export$2e2bcd8739ae039 = $d365d8c287ab0c94$var$ontologyEnr
|
|
|
6280
6281
|
// ('gene'|'paralogs'|'eFP'), atlasExperiment (selected GXA experiment id),
|
|
6281
6282
|
// barStudy (selected eFP/BAR study). Driven in controlled mode from this so a
|
|
6282
6283
|
// saved view restores the chosen sub-tab and study.
|
|
6284
|
+
// - primers: the Primers detail's PrimerDesignerState (gramene-primers), a
|
|
6285
|
+
// serializable {v: 1, mode, transcriptId, flankUp, flankDown, region,
|
|
6286
|
+
// target, included, excluded, junctionSpanning, avoidRepeats, preset,
|
|
6287
|
+
// params, designed, selectedRank, checkedRanks, check: {checks, genomes,
|
|
6288
|
+
// params, jobId, submitted}, view}. Replaced wholesale on every change and
|
|
6289
|
+
// driven in controlled mode, so a saved view re-runs the design and
|
|
6290
|
+
// re-attaches to the check job. A pasted `sequence` is kept here so it
|
|
6291
|
+
// survives a detail-tab switch; viewSnapshot drops it from saved views.
|
|
6292
|
+
// Design responses and check results are never stored.
|
|
6283
6293
|
//
|
|
6284
6294
|
// What does NOT live here:
|
|
6285
6295
|
// - derived/computed state like `details` (per-render config from
|
|
@@ -6403,6 +6413,12 @@ const $7f865ea0feda21af$var$uiViewState = {
|
|
|
6403
6413
|
// payload: { geneId, patch } -- merges into the expression slice
|
|
6404
6414
|
// (e.g. { activeTab }, { atlasExperiment }, { barStudy })
|
|
6405
6415
|
return $7f865ea0feda21af$var$setExpression(state, payload.geneId, payload.patch);
|
|
6416
|
+
case 'UI_PRIMERS_SET':
|
|
6417
|
+
// payload: { geneId, state } -- replaces the primers slice with the
|
|
6418
|
+
// full PrimerDesignerState emitted by <PrimerDesigner> (not merged)
|
|
6419
|
+
return $7f865ea0feda21af$var$setGene(state, payload.geneId, {
|
|
6420
|
+
primers: payload.state
|
|
6421
|
+
});
|
|
6406
6422
|
case 'UI_VIEW_STATE_REPLACED':
|
|
6407
6423
|
// payload: { byGene } -- used by the snapshot loader in a later phase
|
|
6408
6424
|
return {
|
|
@@ -6476,6 +6492,15 @@ const $7f865ea0feda21af$var$uiViewState = {
|
|
|
6476
6492
|
}
|
|
6477
6493
|
});
|
|
6478
6494
|
},
|
|
6495
|
+
doSetPrimersState: ({ geneId: geneId, state: state })=>({ dispatch: dispatch })=>{
|
|
6496
|
+
dispatch({
|
|
6497
|
+
type: 'UI_PRIMERS_SET',
|
|
6498
|
+
payload: {
|
|
6499
|
+
geneId: geneId,
|
|
6500
|
+
state: state
|
|
6501
|
+
}
|
|
6502
|
+
});
|
|
6503
|
+
},
|
|
6479
6504
|
doReplaceUiViewState: (byGene)=>({ dispatch: dispatch })=>{
|
|
6480
6505
|
dispatch({
|
|
6481
6506
|
type: 'UI_VIEW_STATE_REPLACED',
|
|
@@ -6567,7 +6592,9 @@ var $6048209b532f201d$export$2e2bcd8739ae039 = $6048209b532f201d$var$taxTreeView
|
|
|
6567
6592
|
// fullscreen: boolean,
|
|
6568
6593
|
// homology: { viewer, height, tbrowse: <ViewState> } | undefined,
|
|
6569
6594
|
// sequences: { tab, tid, upstream, downstream } | undefined,
|
|
6570
|
-
// expression: { activeTab, atlasExperiment, barStudy } | undefined
|
|
6595
|
+
// expression: { activeTab, atlasExperiment, barStudy } | undefined,
|
|
6596
|
+
// primers: <gramene-primers PrimerDesignerState, {v: 1, ...}, without
|
|
6597
|
+
// the pasted `sequence`> | undefined
|
|
6571
6598
|
// }, ...
|
|
6572
6599
|
// ]
|
|
6573
6600
|
// }
|
|
@@ -6622,8 +6649,18 @@ const $472fe3745b238881$var$isMeaningfulGene = (entry)=>{
|
|
|
6622
6649
|
if (entry.homology && (entry.homology.viewer !== undefined || entry.homology.height !== undefined || entry.homology.tbrowse !== undefined)) return true;
|
|
6623
6650
|
if (entry.sequences && Object.keys(entry.sequences).length) return true;
|
|
6624
6651
|
if (entry.expression && Object.keys(entry.expression).length) return true;
|
|
6652
|
+
if (entry.primers && Object.keys(entry.primers).length) return true;
|
|
6625
6653
|
return false;
|
|
6626
6654
|
};
|
|
6655
|
+
// The Primers slice keeps a pasted sequence in memory (so it survives a detail
|
|
6656
|
+
// tab switch), but a saved view must not carry it: it can be long and is the
|
|
6657
|
+
// user's own data. A restored sequence-mode design then waits for a new paste
|
|
6658
|
+
// (gramene-primers does not re-run a design whose inputs are incomplete).
|
|
6659
|
+
const $472fe3745b238881$var$snapshotPrimers = (primers)=>{
|
|
6660
|
+
if (!primers || !Object.keys(primers).length) return undefined;
|
|
6661
|
+
const { sequence: sequence, ...rest } = primers;
|
|
6662
|
+
return rest;
|
|
6663
|
+
};
|
|
6627
6664
|
const $472fe3745b238881$var$viewSnapshot = {
|
|
6628
6665
|
name: 'viewSnapshot',
|
|
6629
6666
|
// No reducer — this bundle is pure derivation + dispatch orchestration.
|
|
@@ -6687,6 +6724,9 @@ const $472fe3745b238881$var$viewSnapshot = {
|
|
|
6687
6724
|
} : {},
|
|
6688
6725
|
expression: e.expression ? {
|
|
6689
6726
|
...e.expression
|
|
6727
|
+
} : {},
|
|
6728
|
+
primers: e.primers ? {
|
|
6729
|
+
...e.primers
|
|
6690
6730
|
} : {}
|
|
6691
6731
|
};
|
|
6692
6732
|
}
|
|
@@ -6759,7 +6799,8 @@ function $472fe3745b238881$var$buildSnapshot(state) {
|
|
|
6759
6799
|
} : undefined,
|
|
6760
6800
|
expression: e.expression && Object.keys(e.expression).length ? {
|
|
6761
6801
|
...e.expression
|
|
6762
|
-
} : undefined
|
|
6802
|
+
} : undefined,
|
|
6803
|
+
primers: $472fe3745b238881$var$snapshotPrimers(e.primers)
|
|
6763
6804
|
}));
|
|
6764
6805
|
else snap.expandedDetails = [];
|
|
6765
6806
|
// Expression-visualization view config. Capture only the selection/config
|
|
@@ -10206,6 +10247,21 @@ var $54c74a4689d5a778$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.conn
|
|
|
10206
10247
|
|
|
10207
10248
|
|
|
10208
10249
|
|
|
10250
|
+
// Grid row height. Overrides the ag-theme-quartz default (42px) via the
|
|
10251
|
+
// `rowHeight` prop, and drives the container height calc below so the two
|
|
10252
|
+
// can't drift apart.
|
|
10253
|
+
const $283508ffcf8a47c4$var$ROW_HEIGHT = 36;
|
|
10254
|
+
// Header allowance in the container height calc (quartz header ≈ 49px).
|
|
10255
|
+
const $283508ffcf8a47c4$var$HEADER_HEIGHT_ALLOWANCE = 50;
|
|
10256
|
+
// Compact "Search" button so it sits comfortably inside a ROW_HEIGHT row —
|
|
10257
|
+
// react-bootstrap's `size="sm"` alone is ~31px, which crowds a 36px row.
|
|
10258
|
+
// Bump padding/fontSize here if the button should be taller.
|
|
10259
|
+
const $283508ffcf8a47c4$var$SEARCH_BUTTON_STYLE = {
|
|
10260
|
+
whiteSpace: 'nowrap',
|
|
10261
|
+
lineHeight: 1.4,
|
|
10262
|
+
padding: '1px 8px',
|
|
10263
|
+
fontSize: 12
|
|
10264
|
+
};
|
|
10209
10265
|
const $283508ffcf8a47c4$var$ggURL = {
|
|
10210
10266
|
xIRRI: 'https://gringlobal.irri.org/gringlobal/accessiondetail?id=',
|
|
10211
10267
|
IRRI: 'https://www.irri.org/genesys-rice#/a/',
|
|
@@ -10500,6 +10556,7 @@ const $283508ffcf8a47c4$var$GridWithGroups = ({ groups: groups, gene_id: gene_id
|
|
|
10500
10556
|
currentURL.searchParams.set('name', accession.germplasm.ens_id);
|
|
10501
10557
|
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
|
|
10502
10558
|
size: "sm",
|
|
10559
|
+
style: $283508ffcf8a47c4$var$SEARCH_BUTTON_STYLE,
|
|
10503
10560
|
href: currentURL.toString(),
|
|
10504
10561
|
children: "Search"
|
|
10505
10562
|
});
|
|
@@ -10519,7 +10576,7 @@ const $283508ffcf8a47c4$var$GridWithGroups = ({ groups: groups, gene_id: gene_id
|
|
|
10519
10576
|
}
|
|
10520
10577
|
};
|
|
10521
10578
|
const nVisible = getVisibleRowData().length;
|
|
10522
|
-
const tableHeight =
|
|
10579
|
+
const tableHeight = $283508ffcf8a47c4$var$HEADER_HEIGHT_ALLOWANCE + Math.min(nVisible, 10) * $283508ffcf8a47c4$var$ROW_HEIGHT;
|
|
10523
10580
|
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
10524
10581
|
style: {
|
|
10525
10582
|
overflowX: "auto",
|
|
@@ -10537,8 +10594,20 @@ const $283508ffcf8a47c4$var$GridWithGroups = ({ groups: groups, gene_id: gene_id
|
|
|
10537
10594
|
rowData: getVisibleRowData(),
|
|
10538
10595
|
columnDefs: columnDefs,
|
|
10539
10596
|
getRowNodeId: (data)=>data.id,
|
|
10540
|
-
|
|
10541
|
-
defaultColDef: defaultColDef
|
|
10597
|
+
rowHeight: $283508ffcf8a47c4$var$ROW_HEIGHT,
|
|
10598
|
+
defaultColDef: defaultColDef,
|
|
10599
|
+
// ag-grid sets `user-select: none` on cells by default, which is why
|
|
10600
|
+
// accession / consequence text couldn't be selected and copied.
|
|
10601
|
+
// `enableCellTextSelection` restores native selection; `ensureDomOrder`
|
|
10602
|
+
// keeps DOM order matching visual order so a multi-row copy comes out
|
|
10603
|
+
// as displayed rather than scrambled by row virtualization/sorting.
|
|
10604
|
+
//
|
|
10605
|
+
// NB: ag-grid's isAnimateRows() returns false whenever ensureDomOrder
|
|
10606
|
+
// is set, so `animateRows` was removed rather than left as dead config.
|
|
10607
|
+
// Correct copy order matters more here than row-slide animation; drop
|
|
10608
|
+
// `ensureDomOrder` and restore `animateRows={true}` to trade back.
|
|
10609
|
+
enableCellTextSelection: true,
|
|
10610
|
+
ensureDomOrder: true
|
|
10542
10611
|
})
|
|
10543
10612
|
})
|
|
10544
10613
|
});
|
|
@@ -11416,6 +11485,80 @@ var $527ebc19dc92444d$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.conn
|
|
|
11416
11485
|
|
|
11417
11486
|
|
|
11418
11487
|
|
|
11488
|
+
// Primers detail: PCR/qPCR primer design, genome specificity and pan-genome
|
|
11489
|
+
// coverage checks (gramene-primers <PrimerDesigner>, backed by the
|
|
11490
|
+
// gramene-swagger /primers endpoints).
|
|
11491
|
+
//
|
|
11492
|
+
// Enabled per site by config.details.primers:
|
|
11493
|
+
// true use the site's grameneData API
|
|
11494
|
+
// { apiBase, pangenome } apiBase: a swagger that serves /primers;
|
|
11495
|
+
// pangenome: false hides the pan-genome check
|
|
11496
|
+
//
|
|
11497
|
+
// The designer's serializable state ({v: 1, ...}) lives in the uiViewState
|
|
11498
|
+
// bundle keyed by geneId (controlled mode), so a saved view restores the
|
|
11499
|
+
// inputs, re-runs the design and re-attaches to a submitted check (an expired
|
|
11500
|
+
// job shows "Re-run check"). The store keeps a pasted sequence, so switching
|
|
11501
|
+
// detail tabs (which unmounts this component) does not lose it; viewSnapshot
|
|
11502
|
+
// leaves it out of saved views. Styles are injected at runtime by the
|
|
11503
|
+
// component; no CSS import is needed.
|
|
11504
|
+
const $88d24ae9beb83d5d$var$MODES = [
|
|
11505
|
+
'gene',
|
|
11506
|
+
'transcript',
|
|
11507
|
+
'region',
|
|
11508
|
+
'sequence'
|
|
11509
|
+
];
|
|
11510
|
+
const $88d24ae9beb83d5d$var$geneHref = (id)=>`?idList=${encodeURIComponent(id)}`;
|
|
11511
|
+
// Plain left clicks on gene links in check results open a new tab, so the
|
|
11512
|
+
// design and a running check's job id survive; modified clicks use geneHref.
|
|
11513
|
+
const $88d24ae9beb83d5d$var$openGene = (id)=>window.open($88d24ae9beb83d5d$var$geneHref(id), '_blank', 'noopener');
|
|
11514
|
+
const $88d24ae9beb83d5d$var$Primers = (props)=>{
|
|
11515
|
+
const geneId = props.searchResult.id;
|
|
11516
|
+
const gene = props.geneDocs[geneId] // Gene.ensureGene() guarantees it is loaded
|
|
11517
|
+
;
|
|
11518
|
+
const conf = props.config.details.primers // true | { apiBase?, pangenome? }
|
|
11519
|
+
;
|
|
11520
|
+
const apiBase = conf && typeof conf === 'object' && conf.apiBase || props.grameneAPI;
|
|
11521
|
+
const byGene = props.uiViewState && props.uiViewState.byGene && props.uiViewState.byGene[geneId];
|
|
11522
|
+
const saved = byGene && byGene.primers;
|
|
11523
|
+
const { doSetPrimersState: doSetPrimersState } = props;
|
|
11524
|
+
const onStateChange = (0, $gXNCa$react.useCallback)((state)=>doSetPrimersState({
|
|
11525
|
+
geneId: geneId,
|
|
11526
|
+
state: state
|
|
11527
|
+
}), [
|
|
11528
|
+
geneId,
|
|
11529
|
+
doSetPrimersState
|
|
11530
|
+
]);
|
|
11531
|
+
if (!conf) // e.g. a saved view opened on a site that does not enable the tab
|
|
11532
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("p", {
|
|
11533
|
+
children: "Primer design is not enabled on this site."
|
|
11534
|
+
});
|
|
11535
|
+
if (!gene) return null;
|
|
11536
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$grameneprimers.PrimerDesigner), {
|
|
11537
|
+
apiBase: apiBase,
|
|
11538
|
+
gene: gene,
|
|
11539
|
+
systemName: gene.system_name,
|
|
11540
|
+
modes: $88d24ae9beb83d5d$var$MODES,
|
|
11541
|
+
defaultMode: "gene",
|
|
11542
|
+
// an empty slice (never visited, or a snapshot without primers) leaves
|
|
11543
|
+
// the designer uncontrolled until its first change is stored
|
|
11544
|
+
state: saved && Object.keys(saved).length ? saved : undefined,
|
|
11545
|
+
onStateChange: onStateChange,
|
|
11546
|
+
features: {
|
|
11547
|
+
pangenome: !(conf && conf.pangenome === false)
|
|
11548
|
+
},
|
|
11549
|
+
geneHref: $88d24ae9beb83d5d$var$geneHref,
|
|
11550
|
+
onGeneClick: $88d24ae9beb83d5d$var$openGene,
|
|
11551
|
+
geneLabel: gene.name || gene._id,
|
|
11552
|
+
theme: "light"
|
|
11553
|
+
}, geneId);
|
|
11554
|
+
};
|
|
11555
|
+
var $88d24ae9beb83d5d$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneAPI', 'selectUiViewState', 'doSetPrimersState', $88d24ae9beb83d5d$var$Primers);
|
|
11556
|
+
|
|
11557
|
+
|
|
11558
|
+
|
|
11559
|
+
|
|
11560
|
+
|
|
11561
|
+
|
|
11419
11562
|
|
|
11420
11563
|
let $6c5c4f90059875bf$var$external = /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("small", {
|
|
11421
11564
|
title: "This link opens a page from an external site",
|
|
@@ -11428,6 +11571,7 @@ let $6c5c4f90059875bf$var$external = /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.js
|
|
|
11428
11571
|
});
|
|
11429
11572
|
let $6c5c4f90059875bf$var$inventory = {
|
|
11430
11573
|
sequences: (0, $527ebc19dc92444d$export$2e2bcd8739ae039),
|
|
11574
|
+
primers: (0, $88d24ae9beb83d5d$export$2e2bcd8739ae039),
|
|
11431
11575
|
location: (0, $264d7db426cab787$export$2e2bcd8739ae039),
|
|
11432
11576
|
expression: (0, $9e29a4f60318db7a$export$2e2bcd8739ae039),
|
|
11433
11577
|
homology: (0, $64fad37f770d2bfe$export$2e2bcd8739ae039),
|
|
@@ -11559,6 +11703,12 @@ const $6c5c4f90059875bf$var$allDetails = [
|
|
|
11559
11703
|
popup: 'Gene/cDNA/protein fasta',
|
|
11560
11704
|
available: true
|
|
11561
11705
|
},
|
|
11706
|
+
{
|
|
11707
|
+
id: 'primers',
|
|
11708
|
+
label: 'Primers',
|
|
11709
|
+
popup: 'Design PCR/qPCR primers; check specificity and pan-genome coverage',
|
|
11710
|
+
available: true
|
|
11711
|
+
},
|
|
11562
11712
|
{
|
|
11563
11713
|
id: 'location',
|
|
11564
11714
|
label: 'Location',
|
|
@@ -11746,13 +11896,7 @@ class $6c5c4f90059875bf$var$Gene extends (0, ($parcel$interopDefault($gXNCa$reac
|
|
|
11746
11896
|
children: [
|
|
11747
11897
|
d.label,
|
|
11748
11898
|
isExpanded && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsArrowsFullscreen), {
|
|
11749
|
-
|
|
11750
|
-
position: 'absolute',
|
|
11751
|
-
right: 8,
|
|
11752
|
-
top: '50%',
|
|
11753
|
-
transform: 'translateY(-50%)',
|
|
11754
|
-
cursor: 'pointer'
|
|
11755
|
-
},
|
|
11899
|
+
className: "gene-detail-tab-fullscreen",
|
|
11756
11900
|
title: "View full screen",
|
|
11757
11901
|
onClick: (e)=>{
|
|
11758
11902
|
e.stopPropagation();
|