gramene-search 2.23.1 → 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/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
@@ -11444,6 +11485,80 @@ var $527ebc19dc92444d$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.conn
11444
11485
 
11445
11486
 
11446
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
+
11447
11562
 
11448
11563
  let $6c5c4f90059875bf$var$external = /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("small", {
11449
11564
  title: "This link opens a page from an external site",
@@ -11456,6 +11571,7 @@ let $6c5c4f90059875bf$var$external = /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.js
11456
11571
  });
11457
11572
  let $6c5c4f90059875bf$var$inventory = {
11458
11573
  sequences: (0, $527ebc19dc92444d$export$2e2bcd8739ae039),
11574
+ primers: (0, $88d24ae9beb83d5d$export$2e2bcd8739ae039),
11459
11575
  location: (0, $264d7db426cab787$export$2e2bcd8739ae039),
11460
11576
  expression: (0, $9e29a4f60318db7a$export$2e2bcd8739ae039),
11461
11577
  homology: (0, $64fad37f770d2bfe$export$2e2bcd8739ae039),
@@ -11587,6 +11703,12 @@ const $6c5c4f90059875bf$var$allDetails = [
11587
11703
  popup: 'Gene/cDNA/protein fasta',
11588
11704
  available: true
11589
11705
  },
11706
+ {
11707
+ id: 'primers',
11708
+ label: 'Primers',
11709
+ popup: 'Design PCR/qPCR primers; check specificity and pan-genome coverage',
11710
+ available: true
11711
+ },
11590
11712
  {
11591
11713
  id: 'location',
11592
11714
  label: 'Location',
@@ -11774,13 +11896,7 @@ class $6c5c4f90059875bf$var$Gene extends (0, ($parcel$interopDefault($gXNCa$reac
11774
11896
  children: [
11775
11897
  d.label,
11776
11898
  isExpanded && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsArrowsFullscreen), {
11777
- style: {
11778
- position: 'absolute',
11779
- right: 8,
11780
- top: '50%',
11781
- transform: 'translateY(-50%)',
11782
- cursor: 'pointer'
11783
- },
11899
+ className: "gene-detail-tab-fullscreen",
11784
11900
  title: "View full screen",
11785
11901
  onClick: (e)=>{
11786
11902
  e.stopPropagation();