gramene-search 1.7.21 → 1.7.23

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gramene-search",
3
- "version": "1.7.21",
3
+ "version": "1.7.23",
4
4
  "description": "search wrapper for gramene",
5
5
  "source": "src/index.js",
6
6
  "main": "dist/index.js",
@@ -42,7 +42,7 @@ function compressChain(node, tax, maps) {
42
42
  while (true) {
43
43
  const kids = (cur.children || [])
44
44
  .map(cid => tax[cid])
45
- .filter(c => c && c.leafIds.length > 0);
45
+ .filter(c => c && c.leafIds && c.leafIds.length > 0);
46
46
  if (kids.length !== 1) break;
47
47
  if (maps[cur._id]) break;
48
48
  cur = kids[0];
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useMemo, useState } from 'react';
1
+ import React, { useEffect, useMemo, useState, useRef } from 'react';
2
2
  import { connect } from 'redux-bundler-react';
3
3
  import { BsArrowLeftShort, BsArrowRightShort, BsSliders } from 'react-icons/bs';
4
4
  import { buildTableData, toJSON } from './formatters';
@@ -149,9 +149,37 @@ const PreviewCmp = props => {
149
149
  );
150
150
  };
151
151
 
152
+ const MIN_COL_WIDTH = 40;
153
+
152
154
  const TSVTable = ({ docs, fields, catalog, resolverCtx, onMoveField }) => {
153
155
  const { header, headerKeys, rows } = buildTableData(docs, fields, catalog, resolverCtx);
154
156
  const reorderableCount = fields.length;
157
+ const [colWidths, setColWidths] = useState({});
158
+ const thRefs = useRef({});
159
+
160
+ const startResize = (key) => (e) => {
161
+ e.preventDefault();
162
+ e.stopPropagation();
163
+ const th = thRefs.current[key];
164
+ const startWidth = (th && th.getBoundingClientRect().width) || 100;
165
+ const startX = e.clientX;
166
+ const onMove = (ev) => {
167
+ const delta = ev.clientX - startX;
168
+ const next = Math.max(MIN_COL_WIDTH, startWidth + delta);
169
+ setColWidths(prev => ({ ...prev, [key]: next }));
170
+ };
171
+ const onUp = () => {
172
+ window.removeEventListener('pointermove', onMove);
173
+ window.removeEventListener('pointerup', onUp);
174
+ window.removeEventListener('pointercancel', onUp);
175
+ document.body.style.userSelect = '';
176
+ };
177
+ document.body.style.userSelect = 'none';
178
+ window.addEventListener('pointermove', onMove);
179
+ window.addEventListener('pointerup', onUp);
180
+ window.addEventListener('pointercancel', onUp);
181
+ };
182
+
155
183
  return (
156
184
  <div className="exporter-preview-tsv-scroll">
157
185
  <table className="exporter-preview-tsv">
@@ -161,8 +189,10 @@ const TSVTable = ({ docs, fields, catalog, resolverCtx, onMoveField }) => {
161
189
  const key = headerKeys[i];
162
190
  const fieldIdx = fields.indexOf(key);
163
191
  const reorderable = fieldIdx !== -1;
192
+ const w = colWidths[key];
193
+ const thStyle = w ? { width: `${w}px`, maxWidth: `${w}px`, minWidth: `${w}px` } : undefined;
164
194
  return (
165
- <th key={key} title={key}>
195
+ <th key={key} title={key} style={thStyle} ref={el => { thRefs.current[key] = el; }}>
166
196
  <div className="exporter-preview-th-inner">
167
197
  <button
168
198
  type="button"
@@ -180,6 +210,12 @@ const TSVTable = ({ docs, fields, catalog, resolverCtx, onMoveField }) => {
180
210
  title="Move right"
181
211
  ><BsArrowRightShort/></button>
182
212
  </div>
213
+ <span
214
+ className="exporter-preview-col-resizer"
215
+ onPointerDown={startResize(key)}
216
+ onDoubleClick={() => setColWidths(prev => { const n = { ...prev }; delete n[key]; return n; })}
217
+ title="Drag to resize · double-click to reset"
218
+ />
183
219
  </th>
184
220
  );
185
221
  })}
@@ -188,9 +224,14 @@ const TSVTable = ({ docs, fields, catalog, resolverCtx, onMoveField }) => {
188
224
  <tbody>
189
225
  {rows.map((row, r) => (
190
226
  <tr key={r}>
191
- {row.map((c, i) => (
192
- <td key={headerKeys[i]} title={c}>{c}</td>
193
- ))}
227
+ {row.map((c, i) => {
228
+ const key = headerKeys[i];
229
+ const w = colWidths[key];
230
+ const tdStyle = w ? { width: `${w}px`, maxWidth: `${w}px`, minWidth: `${w}px` } : undefined;
231
+ return (
232
+ <td key={key} title={c} style={tdStyle}>{c}</td>
233
+ );
234
+ })}
194
235
  </tr>
195
236
  ))}
196
237
  {rows.length === 0 && (
@@ -461,12 +461,45 @@
461
461
  .exporter-preview-tsv td {
462
462
  padding: 0.2rem 0.5rem;
463
463
  border: 1px solid #e5e7ea;
464
- max-width: 280px;
464
+ max-width: 420px;
465
465
  overflow: hidden;
466
466
  text-overflow: ellipsis;
467
467
  white-space: nowrap;
468
468
  }
469
469
 
470
+ .exporter-preview-tsv th {
471
+ position: relative;
472
+ }
473
+
474
+ .exporter-preview-col-resizer {
475
+ position: absolute;
476
+ top: 0;
477
+ right: -3px;
478
+ width: 6px;
479
+ height: 100%;
480
+ cursor: col-resize;
481
+ user-select: none;
482
+ z-index: 2;
483
+ }
484
+
485
+ .exporter-preview-col-resizer::after {
486
+ content: '';
487
+ position: absolute;
488
+ top: 0;
489
+ bottom: 0;
490
+ left: 50%;
491
+ transform: translateX(-50%);
492
+ width: 1px;
493
+ background: transparent;
494
+ transition: background 0.15s;
495
+ }
496
+
497
+ .exporter-preview-col-resizer:hover::after,
498
+ .exporter-preview-col-resizer:active::after {
499
+ background: #7a8aa0;
500
+ width: 2px;
501
+ }
502
+
470
503
  .exporter-preview-tsv th {
471
504
  background: #f0f3f6;
472
505
  text-align: left;
@@ -142,13 +142,13 @@
142
142
  "expressed_in_gxa_attr_ss": { "group": "expression", "label": "Expressed in GXA", "multiValued": true },
143
143
 
144
144
  "MAKER__AED__attr_f": { "group": "MAKER", "label": "AED", "description": "Annotation Edit Distance" },
145
- "MAKER__QI1__attr_i": { "group": "MAKER", "label": "Length of the 5' UTR" },
146
- "MAKER__QI2__attr_f": { "group": "MAKER", "label": "Fraction of splice sites confirmed by EST" },
147
- "MAKER__QI3__attr_f": { "group": "MAKER", "label": "Fraction of exons overlapping an EST" },
148
- "MAKER__QI4__attr_f": { "group": "MAKER", "label": "Fraction of exons overlapping EST or protein" },
149
- "MAKER__QI7__attr_i": { "group": "MAKER", "label": "Number of exons in the mRNA" },
150
- "MAKER__QI8__attr_i": { "group": "MAKER", "label": "Length of the 3' UTR" },
151
- "MAKER__QI9__attr_i": { "group": "MAKER", "label": "Length of the protein sequence" },
145
+ "MAKER__QI1__attr_i": { "group": "MAKER", "label": "QI1: Length of the 5' UTR" },
146
+ "MAKER__QI2__attr_f": { "group": "MAKER", "label": "QI2: Fraction of splice sites confirmed by EST" },
147
+ "MAKER__QI3__attr_f": { "group": "MAKER", "label": "QI3: Fraction of exons overlapping an EST" },
148
+ "MAKER__QI4__attr_f": { "group": "MAKER", "label": "QI4: Fraction of exons overlapping EST or protein" },
149
+ "MAKER__QI7__attr_i": { "group": "MAKER", "label": "QI7: Number of exons in the mRNA" },
150
+ "MAKER__QI8__attr_i": { "group": "MAKER", "label": "QI8: Length of the 3' UTR" },
151
+ "MAKER__QI9__attr_i": { "group": "MAKER", "label": "QI9: Length of the protein sequence" },
152
152
 
153
153
  "homology__all_orthologs": { "group": "homology", "label": "All orthologs", "multiValued": true, "order": 15 },
154
154
  "homology__ortholog_one2one": { "group": "homology", "label": "1:1 orthologs", "multiValued": true, "order": 16 },
@@ -168,5 +168,5 @@
168
168
  "compara_idx", "compara_idx_multi",
169
169
  "_id", "annotations", "bins", "gene_structure",
170
170
  "homology", "location", "xrefs",
171
- "domain_roots", "familyRoot__ancestors"
171
+ "domain_roots", "familyRoot__ancestors", "taxonomy__ancestors", "capabilities"
172
172
  ]}