gramene-search 2.1.10 → 2.2.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.
Files changed (41) hide show
  1. package/.claude/launch.json +11 -0
  2. package/.claude/settings.local.json +21 -1
  3. package/.env.example +6 -0
  4. package/.parcel-cache/13f2d5707e7af45c-RequestGraph +0 -0
  5. package/.parcel-cache/5ae0570a78c0dba3-AssetGraph +0 -0
  6. package/.parcel-cache/9ac092379278e465-BundleGraph +0 -0
  7. package/.parcel-cache/data.mdb +0 -0
  8. package/.parcel-cache/lock.mdb +0 -0
  9. package/.parcel-cache/snapshot-13f2d5707e7af45c.txt +2 -2
  10. package/dist/index.css +1 -4
  11. package/dist/index.css.map +1 -1
  12. package/dist/index.js +2308 -433
  13. package/dist/index.js.map +1 -1
  14. package/package.json +5 -2
  15. package/src/bundles/api.js +24 -42
  16. package/src/bundles/docs.js +2 -1
  17. package/src/bundles/exprViz.js +97 -1
  18. package/src/bundles/index.js +4 -1
  19. package/src/bundles/ontologyEnrichment.js +14 -1
  20. package/src/bundles/savedViews.js +335 -0
  21. package/src/bundles/uiViewState.js +174 -0
  22. package/src/bundles/viewSnapshot.js +313 -0
  23. package/src/bundles/views.js +24 -2
  24. package/src/components/Auth.js +23 -3
  25. package/src/components/SaveView.js +157 -0
  26. package/src/components/exprViz/ExprVizView.js +16 -11
  27. package/src/components/exprViz/ParallelCoordsPlot.js +15 -0
  28. package/src/components/results/GeneList.js +45 -49
  29. package/src/components/results/OntologyEnrichment.js +13 -6
  30. package/src/components/results/TaxDist.js +11 -0
  31. package/src/components/results/details/BAR.js +148 -0
  32. package/src/components/results/details/Expression.js +50 -14
  33. package/src/components/results/details/Homology.js +171 -39
  34. package/src/components/results/details/Pathways.js +4 -2
  35. package/src/components/results/details/Sequences.js +24 -8
  36. package/src/components/results/details/VEP.js +65 -19
  37. package/src/components/styles.css +1 -4
  38. package/src/demo.js +30 -13
  39. package/src/index.js +2 -1
  40. package/src/suppressDevWarnings.js +13 -0
  41. package/src/utils/bootView.js +38 -0
@@ -14,8 +14,7 @@
14
14
  flex: 0 0 250px;
15
15
  position: sticky;
16
16
  top: 0;
17
- max-height: 100vh;
18
- overflow-y: auto;
17
+ align-self: flex-start;
19
18
  padding-left: 8px;
20
19
  padding-right: 8px;
21
20
  padding-bottom: 8px;
@@ -38,8 +37,6 @@
38
37
  flex: 0 0 auto;
39
38
  position: static;
40
39
  width: 100%;
41
- max-height: none;
42
- overflow-y: visible;
43
40
  }
44
41
  .search-views-content {
45
42
  width: 100%;
package/src/demo.js CHANGED
@@ -21,16 +21,21 @@ import {
21
21
  } from "react-router-dom";
22
22
  import Feedback from './components/Feedback';
23
23
  import MDView from 'gramene-mdview';
24
+ import bootViewFromUrl from './utils/bootView';
24
25
 
25
- const cache = getConfiguredCache({
26
- maxAge: 24 * 60 * 60 * 1000,
27
- version: 1
28
- });
29
26
  // const subsite = 'main';
30
27
  const subsite = process.env.SUBSITE;
31
28
  // const subsite = 'grapevine';
32
29
  // const subsite = 'sorghum';
33
30
  // const subsite = 'rice';
31
+ // Scope the IndexedDB store to the subsite so caches from `npm run start-main`
32
+ // don't leak into `npm run start-sorghum` (and vice versa). money-clip uses
33
+ // the default keyval store when `name` is unset, which is shared across sites.
34
+ const cache = getConfiguredCache({
35
+ maxAge: 24 * 60 * 60 * 1000,
36
+ version: 1,
37
+ name: `gramene_cache_${subsite || 'default'}`
38
+ });
34
39
 
35
40
  const subsitelut = {
36
41
  main: 0,
@@ -141,20 +146,12 @@ const panSites = [
141
146
  ensemblURL: 'https://ensembl.sorghumbase.org',
142
147
  ensemblSite: 'https://ensembl.sorghumbase.org',
143
148
  ensemblRest: 'https://data.gramene.org/pansite-ensembl-108',
144
- grameneData: 'https://data.sorghumbase.org/auth_testing',
149
+ grameneData: 'https://data.sorghumbase.org/sorghum_v10',
145
150
  ga: 'G-L5KXDCCZ16',
146
151
  targetTaxonId: 4558001,
147
152
  alertText: 'Click the search icon in the menu bar or type /',
148
153
  showViews: true,
149
154
  partialCompara: true,
150
- firebaseConfig: {
151
- apiKey: "AIzaSyCyTJmxfWgfuhI6-8uqocSiE9KOWUlkgkk",
152
- authDomain: "gramene-auth.firebaseapp.com",
153
- projectId: "gramene-auth",
154
- storageBucket: "gramene-auth.appspot.com",
155
- messagingSenderId: "590873346270",
156
- appId: "1:590873346270:web:f76a31a93619e69439824f"
157
- },
158
155
  details: {
159
156
  sequences: true,
160
157
  VEP: true,
@@ -273,6 +270,23 @@ const panSites = [
273
270
  }
274
271
  }
275
272
  ];
273
+
274
+ // Firebase web config is loaded from FIREBASE_CONFIG_JSON in the build-time
275
+ // env (.env, never committed). If unset, the Auth panel mounts but stays
276
+ // inert. Attached to the sites that use gramene-auth.
277
+ const firebaseConfig = (() => {
278
+ const raw = process.env.FIREBASE_CONFIG_JSON;
279
+ if (!raw) return null;
280
+ try { return JSON.parse(raw); }
281
+ catch (e) { console.warn('FIREBASE_CONFIG_JSON is not valid JSON; Auth disabled.', e); return null; }
282
+ })();
283
+ if (firebaseConfig) {
284
+ ['main', 'sorghum'].forEach(id => {
285
+ const site = panSites[subsitelut[id]];
286
+ if (site) site.firebaseConfig = firebaseConfig;
287
+ });
288
+ }
289
+
276
290
  const initialState = Object.assign({helpIsOn:false}, panSites[subsitelut[subsite]]);
277
291
 
278
292
  const config = {
@@ -534,6 +548,9 @@ cache.getAll().then(initialData => {
534
548
  window.store = store;
535
549
  const config = store.selectConfiguration();
536
550
  ReactGA.initialize(config.ga);
551
+ // If the URL has ?view=<hash>, hydrate the snapshot before the user
552
+ // interacts. Errors are non-fatal (see utils/bootView.js).
553
+ bootViewFromUrl(store);
537
554
  if (initialData.hasOwnProperty('grameneMaps')) {
538
555
  // check for hidden genomes
539
556
  let notHidden = {};
package/src/index.js CHANGED
@@ -3,5 +3,6 @@ import resultList from './components/resultList';
3
3
  import resultSummary from './components/resultSummary';
4
4
  import suggestions from './components/suggestions';
5
5
  import {Status, Filters, Results, Views, Auth} from './components/geneSearchUI';
6
+ import bootViewFromUrl from './utils/bootView';
6
7
 
7
- export { bundles, resultList, resultSummary, suggestions, Status, Filters, Results, Views, Auth };
8
+ export { bundles, resultList, resultSummary, suggestions, Status, Filters, Results, Views, Auth, bootViewFromUrl };
@@ -12,6 +12,19 @@ if (typeof console !== 'undefined' && typeof console.error === 'function') {
12
12
  'uses the legacy childContextTypes API',
13
13
  'uses the legacy contextTypes API',
14
14
  'findDOMNode is deprecated',
15
+ // Third-party libs (gramene-search-vis, gramene-mdview, Pathways, etc.)
16
+ // still use the pre-16.3 lifecycle methods. We can't fix them from here.
17
+ 'componentWillReceiveProps has been renamed',
18
+ 'componentWillMount has been renamed',
19
+ 'componentWillUpdate has been renamed',
20
+ // Kept as a guard — react warns on any kebab-case inline-style property
21
+ // and Parcel's overlay turns that into a fatal runtime error. The known
22
+ // offender (BAR's max-width) was fixed when the component was absorbed
23
+ // from gramene-efp-browser, but the suppressor protects against any
24
+ // future regression in third-party libs.
25
+ 'Unsupported style property',
26
+ // Stale-state setState after unmount in legacy class components.
27
+ "Can't perform a React state update on an unmounted component",
15
28
  ];
16
29
  console.error = function (...args) {
17
30
  const msg = typeof args[0] === 'string' ? args[0] : '';
@@ -0,0 +1,38 @@
1
+ // Boot-time hydration of a shared view link.
2
+ //
3
+ // Entry points call `bootViewFromUrl(store)` once the store is created.
4
+ // Public views resolve anonymously. For private views, the initial call
5
+ // will 401; the Auth panel then re-invokes with `{user}` once Firebase has
6
+ // emitted its first signed-in state, and the fetch retries with a Bearer
7
+ // token. On success we apply the snapshot and strip `?view=` from the URL
8
+ // so subsequent user actions don't sit under a stale shared-state URL.
9
+ //
10
+ // All errors are non-fatal — they surface in state.savedViews.fetchError
11
+ // for any UI that wants to show them.
12
+
13
+ const PARAM = 'view';
14
+
15
+ export default function bootViewFromUrl(store, opts = {}) {
16
+ if (typeof window === 'undefined') return Promise.resolve(null);
17
+ const url = new URL(window.location.href);
18
+ const hash = url.searchParams.get(PARAM);
19
+ if (!hash) return Promise.resolve(null);
20
+
21
+ const { user = null } = opts;
22
+
23
+ return store.doFetchView({ hash, user })
24
+ .then(({ snapshot }) => {
25
+ store.doApplyViewSnapshot(snapshot);
26
+ url.searchParams.delete(PARAM);
27
+ window.history.replaceState({}, '', url.toString());
28
+ return { hash, applied: true };
29
+ })
30
+ .catch((err) => {
31
+ // 401 here on the anonymous pass is expected for private views — the
32
+ // Auth panel will retry once it has a user. Other errors (404, 5xx,
33
+ // network) are reported and leave the param so a manual refresh can
34
+ // retry too.
35
+ console.warn('bootViewFromUrl:', err.message || err);
36
+ return { hash, applied: false, error: err.message || String(err) };
37
+ });
38
+ }