gramene-search 2.14.0 → 2.15.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
@@ -219,6 +219,7 @@ $parcel$export(module.exports, "resultSummary", () => $27617dbc24e7faf0$export$2
219
219
  $parcel$export(module.exports, "suggestions", () => $541b8b0d8c5501d2$export$2e2bcd8739ae039);
220
220
  $parcel$export(module.exports, "Status", () => $693dd8c7a5607c3a$export$96e9906d6d93a972);
221
221
  $parcel$export(module.exports, "Filters", () => $693dd8c7a5607c3a$export$92a576f896a9bf72);
222
+ $parcel$export(module.exports, "Facets", () => $7d7b7dad5e71dfd3$export$2e2bcd8739ae039);
222
223
  $parcel$export(module.exports, "Results", () => $693dd8c7a5607c3a$export$4a34de49b46a2bfa);
223
224
  $parcel$export(module.exports, "Views", () => $693dd8c7a5607c3a$export$5cb791131c501f6a);
224
225
  $parcel$export(module.exports, "Auth", () => $c5d403787de8b05f$export$2e2bcd8739ae039);
@@ -4744,12 +4745,12 @@ const $4b8473139e48e77e$export$a61929d6d484c6d4 = $4b8473139e48e77e$export$4bb93
4744
4745
  }, {});
4745
4746
  const $4b8473139e48e77e$export$c6dbe9be8c8b382e = {
4746
4747
  up: {
4747
- bg: '#fdecea',
4748
- fg: '#c0392b'
4749
- },
4750
- down: {
4751
4748
  bg: '#eaf2fb',
4752
4749
  fg: '#2e6fae'
4750
+ },
4751
+ down: {
4752
+ bg: '#fdecea',
4753
+ fg: '#c0392b'
4753
4754
  }
4754
4755
  };
4755
4756
  const $4b8473139e48e77e$export$39a35029fe99c21 = '#d35400'; // specific-to dot / enhanced-in outline
@@ -5061,6 +5062,188 @@ var $12feb7ca48271e17$export$2e2bcd8739ae039 = $12feb7ca48271e17$var$attrTable;
5061
5062
 
5062
5063
 
5063
5064
 
5065
+ const $6c52be7952d5ec43$export$f3878c70e70de19e = [
5066
+ {
5067
+ field: 'capabilities',
5068
+ heading: 'Available data',
5069
+ hide: [
5070
+ 'expression_attributes',
5071
+ 'location',
5072
+ 'taxonomy',
5073
+ 'xrefs',
5074
+ 'familyRoot',
5075
+ 'MAKER',
5076
+ 'Grassius'
5077
+ ],
5078
+ // Per-value display overrides (raw value -> label). Anything not listed falls
5079
+ // back to underscores->spaces. The raw value is still what gets filtered on.
5080
+ labels: {
5081
+ expression: 'Expression',
5082
+ homology: 'Homology',
5083
+ domains: 'Domains',
5084
+ grassius_homolog: 'Grassius',
5085
+ GO: 'Gene Ontology',
5086
+ PO: 'Plant Ontology',
5087
+ TO: 'Trait Ontology',
5088
+ QTL_TO: 'QTL',
5089
+ VEP: 'Loss-of-function variants',
5090
+ pubs: 'Curated in literature'
5091
+ }
5092
+ },
5093
+ {
5094
+ field: 'expr_class__attr_ss',
5095
+ heading: 'Expression class'
5096
+ },
5097
+ {
5098
+ field: 'grassius_homolog__attr_ss',
5099
+ heading: 'TF family (GRASSIUS)'
5100
+ }
5101
+ ];
5102
+ const $6c52be7952d5ec43$var$FACET_FIELDS = $6c52be7952d5ec43$export$f3878c70e70de19e.map((g)=>g.field);
5103
+ // field -> Set of raw values to omit from the rendered group.
5104
+ const $6c52be7952d5ec43$var$HIDE_BY_FIELD = {};
5105
+ $6c52be7952d5ec43$export$f3878c70e70de19e.forEach((g)=>{
5106
+ if (g.hide && g.hide.length) $6c52be7952d5ec43$var$HIDE_BY_FIELD[g.field] = new Set(g.hide);
5107
+ });
5108
+ // The output key of a Solr facet defaults to the field name, so no {!key=...}
5109
+ // local params are needed — just one facet.field per field.
5110
+ const $6c52be7952d5ec43$var$FACET_PARAMS = $6c52be7952d5ec43$var$FACET_FIELDS.map((f)=>`facet.field=${f}`).join('&');
5111
+ let $6c52be7952d5ec43$var$fetchPendingId = 0;
5112
+ // Same rule the main search uses: only constrain by taxon_id when the user has
5113
+ // actually subset the visible genomes (see bundles/api.js). Keeps counts in step
5114
+ // with the visible result set without bloating the URL.
5115
+ function $6c52be7952d5ec43$var$genomeSubset(g, m) {
5116
+ const maps = m || {};
5117
+ const visibleTaxa = Object.keys(maps).filter((tid)=>!maps[tid].hidden);
5118
+ const activeVisible = Object.keys(g && g.active || {}).filter((tid)=>maps[tid] && !maps[tid].hidden);
5119
+ const subset = activeVisible.length > 0 && activeVisible.length < visibleTaxa.length;
5120
+ const sorted = activeVisible.slice().sort();
5121
+ return {
5122
+ fq: subset ? `&fq=taxon_id:(${sorted.join(' OR ')})` : '',
5123
+ key: subset ? sorted.join(',') : ''
5124
+ };
5125
+ }
5126
+ function $6c52be7952d5ec43$var$computeSignature(q, g, m) {
5127
+ return `${q}|${$6c52be7952d5ec43$var$genomeSubset(g, m).key}`;
5128
+ }
5129
+ const $6c52be7952d5ec43$var$facetCounts = {
5130
+ name: 'facetCounts',
5131
+ getReducer: ()=>{
5132
+ const initialState = {
5133
+ status: 'idle',
5134
+ signature: null,
5135
+ groups: {},
5136
+ error: null,
5137
+ requestId: 0,
5138
+ open: false
5139
+ };
5140
+ return (state = initialState, { type: type, payload: payload })=>{
5141
+ switch(type){
5142
+ case 'FACETCOUNTS_TOGGLE_OPEN':
5143
+ return {
5144
+ ...state,
5145
+ open: typeof payload === 'boolean' ? payload : !state.open
5146
+ };
5147
+ case 'FACETCOUNTS_FETCH_STARTED':
5148
+ // Keep the previous groups visible during a refetch (smooth update);
5149
+ // they're replaced when the new counts land.
5150
+ return {
5151
+ ...state,
5152
+ status: 'loading',
5153
+ error: null,
5154
+ signature: payload.signature,
5155
+ requestId: payload.requestId
5156
+ };
5157
+ case 'FACETCOUNTS_FETCH_DONE':
5158
+ if (payload.requestId !== state.requestId) return state; // superseded
5159
+ return {
5160
+ ...state,
5161
+ status: 'ready',
5162
+ groups: payload.groups
5163
+ };
5164
+ case 'FACETCOUNTS_FETCH_FAILED':
5165
+ if (payload.requestId !== state.requestId) return state;
5166
+ return {
5167
+ ...state,
5168
+ status: 'error',
5169
+ error: payload.error
5170
+ };
5171
+ default:
5172
+ return state;
5173
+ }
5174
+ };
5175
+ },
5176
+ doToggleFacetCounts: (open)=>({ dispatch: dispatch })=>dispatch({
5177
+ type: 'FACETCOUNTS_TOGGLE_OPEN',
5178
+ payload: open
5179
+ }),
5180
+ doFetchFacetCounts: ()=>({ dispatch: dispatch, store: store })=>{
5181
+ const q = store.selectGrameneFiltersQueryString();
5182
+ const { fq: fq } = $6c52be7952d5ec43$var$genomeSubset(store.selectGrameneGenomes(), store.selectGrameneMaps());
5183
+ const signature = $6c52be7952d5ec43$var$computeSignature(q, store.selectGrameneGenomes(), store.selectGrameneMaps());
5184
+ const requestId = ++$6c52be7952d5ec43$var$fetchPendingId;
5185
+ dispatch({
5186
+ type: 'FACETCOUNTS_FETCH_STARTED',
5187
+ payload: {
5188
+ requestId: requestId,
5189
+ signature: signature
5190
+ }
5191
+ });
5192
+ const api = store.selectGrameneAPI();
5193
+ const url = `${api}/search?q=${q}${fq}&rows=0&facet=true&facet.mincount=1&facet.limit=-1&${$6c52be7952d5ec43$var$FACET_PARAMS}`;
5194
+ fetch(url).then((r)=>r.json()).then((json)=>{
5195
+ if (requestId !== $6c52be7952d5ec43$var$fetchPendingId) return;
5196
+ const ff = json.facet_counts && json.facet_counts.facet_fields || {};
5197
+ const groups = {};
5198
+ $6c52be7952d5ec43$var$FACET_FIELDS.forEach((f)=>{
5199
+ const arr = ff[f] || [];
5200
+ const hidden = $6c52be7952d5ec43$var$HIDE_BY_FIELD[f];
5201
+ const vals = [];
5202
+ for(let i = 0; i < arr.length; i += 2){
5203
+ if (hidden && hidden.has(arr[i])) continue;
5204
+ vals.push({
5205
+ value: arr[i],
5206
+ count: arr[i + 1]
5207
+ });
5208
+ }
5209
+ groups[f] = vals;
5210
+ });
5211
+ dispatch({
5212
+ type: 'FACETCOUNTS_FETCH_DONE',
5213
+ payload: {
5214
+ requestId: requestId,
5215
+ groups: groups
5216
+ }
5217
+ });
5218
+ }).catch((err)=>{
5219
+ dispatch({
5220
+ type: 'FACETCOUNTS_FETCH_FAILED',
5221
+ payload: {
5222
+ requestId: requestId,
5223
+ error: String(err)
5224
+ }
5225
+ });
5226
+ });
5227
+ },
5228
+ selectFacetCounts: (state)=>state.facetCounts,
5229
+ selectFacetCountsOpen: (state)=>state.facetCounts.open,
5230
+ selectFacetCountsGroups: (state)=>state.facetCounts.groups,
5231
+ // Fetch only while the section is open, once per unique (query, genomes).
5232
+ reactFacetCountsFetch: (0, $gXNCa$reduxbundler.createSelector)('selectFacetCounts', 'selectGrameneFiltersStatus', 'selectGrameneFiltersQueryString', 'selectGrameneGenomes', 'selectGrameneMaps', (fc, filtersStatus, q, g, m)=>{
5233
+ if (!fc || !fc.open) return;
5234
+ if (filtersStatus === 'init') return;
5235
+ if (fc.status === 'loading') return;
5236
+ const sig = $6c52be7952d5ec43$var$computeSignature(q, g, m);
5237
+ if (fc.signature === sig && (fc.status === 'ready' || fc.status === 'error')) return;
5238
+ return {
5239
+ actionCreator: 'doFetchFacetCounts'
5240
+ };
5241
+ })
5242
+ };
5243
+ var $6c52be7952d5ec43$export$2e2bcd8739ae039 = $6c52be7952d5ec43$var$facetCounts;
5244
+
5245
+
5246
+
5064
5247
  // Ontology over-representation analysis (clusterProfiler::enrichGO-style).
5065
5248
  //
5066
5249
  // For each species tab we run:
@@ -6818,6 +7001,7 @@ var $5df6c55c1bef3469$export$2e2bcd8739ae039 = [
6818
7001
  (0, $c921a0d2b34aadb6$export$2e2bcd8739ae039),
6819
7002
  (0, $4f15cd8a7d970b18$export$2e2bcd8739ae039),
6820
7003
  (0, $12feb7ca48271e17$export$2e2bcd8739ae039),
7004
+ (0, $6c52be7952d5ec43$export$2e2bcd8739ae039),
6821
7005
  (0, $d365d8c287ab0c94$export$2e2bcd8739ae039),
6822
7006
  (0, $7f865ea0feda21af$export$2e2bcd8739ae039),
6823
7007
  (0, $6048209b532f201d$export$2e2bcd8739ae039),
@@ -19693,6 +19877,149 @@ var $15504f5eba8e73bd$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.conn
19693
19877
 
19694
19878
 
19695
19879
 
19880
+ // How many values to show per group before a "show N more" toggle. GRASSIUS has
19881
+ // ~90 TF families, so an uncapped list would swamp the sidebar.
19882
+ const $7d7b7dad5e71dfd3$var$INITIAL_VISIBLE = 12;
19883
+ // Display label for a raw facet value: a per-group override (group.labels) if
19884
+ // present, else underscores -> spaces. The raw value is still what gets filtered.
19885
+ const $7d7b7dad5e71dfd3$var$labelFor = (group, value)=>group.labels && group.labels[value] || String(value).replace(/_/g, ' ');
19886
+ // One collapsible group = one facet field. Values arrive pre-sorted by count
19887
+ // (Solr default facet.sort). Clicking a count adds the filter.
19888
+ const $7d7b7dad5e71dfd3$var$FacetGroup = ({ group: group, values: values, onAdd: onAdd })=>{
19889
+ const [open, setOpen] = (0, $gXNCa$react.useState)(true);
19890
+ const [showAll, setShowAll] = (0, $gXNCa$react.useState)(false);
19891
+ const shown = showAll ? values : values.slice(0, $7d7b7dad5e71dfd3$var$INITIAL_VISIBLE);
19892
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
19893
+ className: "facet-group",
19894
+ children: [
19895
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
19896
+ className: "facet-group-header",
19897
+ onClick: ()=>setOpen(!open),
19898
+ children: [
19899
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
19900
+ className: "facet-group-caret",
19901
+ children: open ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsChevronDown), {}) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsChevronRight), {})
19902
+ }),
19903
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
19904
+ className: "facet-group-title",
19905
+ children: group.heading
19906
+ }),
19907
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
19908
+ className: "facet-group-nvals",
19909
+ children: values.length
19910
+ })
19911
+ ]
19912
+ }),
19913
+ open && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
19914
+ className: "facet-group-body",
19915
+ children: [
19916
+ values.length === 0 && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
19917
+ className: "facet-empty",
19918
+ children: "none in this result set"
19919
+ }),
19920
+ shown.map(({ value: value, count: count })=>{
19921
+ const label = $7d7b7dad5e71dfd3$var$labelFor(group, value);
19922
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
19923
+ className: "facet-row",
19924
+ children: [
19925
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
19926
+ className: "facet-val",
19927
+ title: label,
19928
+ children: label
19929
+ }),
19930
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("button", {
19931
+ type: "button",
19932
+ className: "facet-count",
19933
+ title: `Add filter: ${group.heading} = ${label}`,
19934
+ onClick: ()=>onAdd(group.field, group.heading, value, label),
19935
+ children: count.toLocaleString()
19936
+ })
19937
+ ]
19938
+ }, value);
19939
+ }),
19940
+ values.length > $7d7b7dad5e71dfd3$var$INITIAL_VISIBLE && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("button", {
19941
+ type: "button",
19942
+ className: "facet-more",
19943
+ onClick: ()=>setShowAll(!showAll),
19944
+ children: showAll ? 'show less' : `show ${values.length - $7d7b7dad5e71dfd3$var$INITIAL_VISIBLE} more`
19945
+ })
19946
+ ]
19947
+ })
19948
+ ]
19949
+ });
19950
+ };
19951
+ const $7d7b7dad5e71dfd3$var$FacetsCmp = (props)=>{
19952
+ const { facetCounts: facetCounts, configuration: configuration, doToggleFacetCounts: doToggleFacetCounts, doAcceptGrameneSuggestion: doAcceptGrameneSuggestion } = props;
19953
+ const open = facetCounts.open;
19954
+ const status = facetCounts.status;
19955
+ const groups = facetCounts.groups || {};
19956
+ const containerClass = configuration && configuration.id === 'sorghum' ? 'sorghumbase-facet-container' : 'gramene-facet-container';
19957
+ const hasData = (0, $6c52be7952d5ec43$export$f3878c70e70de19e).some((g)=>(groups[g.field] || []).length > 0);
19958
+ const onAdd = (field, heading, value, label)=>{
19959
+ doAcceptGrameneSuggestion({
19960
+ fq_field: field,
19961
+ fq_value: value,
19962
+ category: heading,
19963
+ name: label
19964
+ });
19965
+ };
19966
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
19967
+ className: containerClass,
19968
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
19969
+ className: "sidebar-section",
19970
+ children: [
19971
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
19972
+ className: "sidebar-section-header",
19973
+ onClick: ()=>doToggleFacetCounts(!open),
19974
+ children: [
19975
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("b", {
19976
+ children: "Refine"
19977
+ }),
19978
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
19979
+ className: "sidebar-section-actions",
19980
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
19981
+ className: "sidebar-section-toggle",
19982
+ children: open ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsChevronDown), {}) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsChevronRight), {})
19983
+ })
19984
+ })
19985
+ ]
19986
+ }),
19987
+ open && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
19988
+ className: "sidebar-section-body",
19989
+ children: [
19990
+ !hasData && status === 'error' && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
19991
+ className: "facet-status",
19992
+ children: "counts unavailable"
19993
+ }),
19994
+ !hasData && status !== 'error' && status !== 'ready' && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
19995
+ className: "facet-status",
19996
+ children: "counting\u2026"
19997
+ }),
19998
+ !hasData && status === 'ready' && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
19999
+ className: "facet-status",
20000
+ children: "no categories for this result set"
20001
+ }),
20002
+ hasData && (0, $6c52be7952d5ec43$export$f3878c70e70de19e).map((g)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($7d7b7dad5e71dfd3$var$FacetGroup, {
20003
+ group: g,
20004
+ values: groups[g.field] || [],
20005
+ onAdd: onAdd
20006
+ }, g.field))
20007
+ ]
20008
+ })
20009
+ ]
20010
+ })
20011
+ });
20012
+ };
20013
+ const $7d7b7dad5e71dfd3$var$Facets = (0, $gXNCa$reduxbundlerreact.connect)('selectFacetCounts', 'selectConfiguration', 'doToggleFacetCounts', 'doAcceptGrameneSuggestion', $7d7b7dad5e71dfd3$var$FacetsCmp);
20014
+ var $7d7b7dad5e71dfd3$export$2e2bcd8739ae039 = $7d7b7dad5e71dfd3$var$Facets;
20015
+
20016
+
20017
+
20018
+
20019
+
20020
+
20021
+
20022
+
19696
20023
 
19697
20024
  // "Save this view" UI — sits inside the Auth sidebar panel.
19698
20025
  //