Skip to content

Commit 55cbb6b

Browse files
authored
feat: auto select Reference from solvent metadata when unset (#263)
* feat: auto select Reference from solvent metadata when unset Auto select the Reference in the top bar when a matching solvent is found Use a robust matcher on solvent label and name Keep manual choice if a Reference is already set Build a normalized solvent key from feature metadata Score each candidate and choose the best one Select value is now ref.name
1 parent 6f39754 commit 55cbb6b

File tree

2 files changed

+142
-34
lines changed

2 files changed

+142
-34
lines changed

src/components/cmd_bar/r01_layout.js

Lines changed: 98 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable prefer-object-spread, function-paren-newline,
22
react/function-component-definition */
3-
import React from 'react';
3+
import React, { useEffect } from 'react';
44
import PropTypes from 'prop-types';
55
import classNames from 'classnames';
66
import { connect } from 'react-redux';
@@ -37,44 +37,46 @@ const styles = () => (
3737
const shiftSelect = (
3838
classes, layoutSt, setShiftRefAct, shiftSt, curveSt,
3939
) => {
40-
if (Cfg.hideSolvent(layoutSt)) return null;
41-
// const onChange = (e) => setShiftRefAct(e.target.value);
40+
if (Cfg.hideSolvent(layoutSt)) {
41+
return null;
42+
}
43+
4244
const { curveIdx } = curveSt;
4345
const { shifts } = shiftSt;
44-
const selectedShift = shifts[curveIdx];
45-
const shiftRef = selectedShift.ref;
46+
const selectedShift = shifts[curveIdx] || {};
47+
const listShift = getListShift(layoutSt) || [];
48+
49+
const shiftRefName = selectedShift?.ref?.name || '';
50+
const isInList = listShift.some((r) => r.name === shiftRefName);
51+
const selectValue = isInList ? shiftRefName : '';
4652

4753
const onChange = (e) => {
48-
const payload = { dataToSet: e.target.value, curveIdx };
49-
setShiftRefAct(payload);
54+
const name = e.target.value;
55+
const refObj = listShift.find((r) => r.name === name);
56+
if (refObj) {
57+
setShiftRefAct({ dataToSet: refObj, curveIdx });
58+
}
5059
};
5160

52-
const listShift = getListShift(layoutSt);
53-
54-
const content = listShift.map((ref) => (
55-
<MenuItem value={ref} key={ref.name}>
56-
<span className={classNames(classes.txtOpt, 'option-sv-bar-shift')}>
57-
{ `${ref.name}: ${Format.strNumberFixedDecimal(ref.value, 2)} ppm` }
58-
</span>
59-
</MenuItem>
60-
));
61-
6261
return (
63-
<FormControl
64-
className={classNames(classes.fieldShift)}
65-
variant="outlined"
66-
>
62+
<FormControl className={classNames(classes.fieldShift)} variant="outlined">
6763
<InputLabel id="select-solvent-label" className={classNames(classes.selectLabel, 'select-sv-bar-label')}>
6864
Reference
6965
</InputLabel>
7066
<Select
71-
value={shiftRef}
67+
value={selectValue}
7268
labelId="select-solvent-label"
7369
label="Solvent"
7470
onChange={onChange}
7571
className={classNames(classes.selectInput, 'input-sv-bar-shift')}
7672
>
77-
{ content }
73+
{listShift.map((ref) => (
74+
<MenuItem value={ref.name} key={ref.name}>
75+
<span className={classNames(classes.txtOpt, 'option-sv-bar-shift')}>
76+
{`${ref.name}: ${Format.strNumberFixedDecimal(ref.value, 2)} ppm`}
77+
</span>
78+
</MenuItem>
79+
))}
7880
</Select>
7981
</FormControl>
8082
);
@@ -189,16 +191,82 @@ const layoutSelect = (classes, layoutSt, updateLayoutAct) => {
189191
);
190192
};
191193

194+
const PLACEHOLDER = '- - -';
195+
196+
const norm = (s) => (s || '').toString().toLowerCase().normalize('NFKD').replace(/[^a-z0-9]+/g, '');
197+
198+
function solventKeyOf(feature) {
199+
const r = feature?.metadata?.solventName ?? feature?.metadata?.solvent
200+
?? feature?.meta?.solventName ?? feature?.meta?.solvent
201+
?? feature?.solventName ?? feature?.solvent ?? null;
202+
const a = feature?.metadata?.solvent_label ?? feature?.metadata?.solventLabel ?? null;
203+
const raw = r && r !== PLACEHOLDER ? r : null;
204+
const alt = a && a !== PLACEHOLDER ? a : null;
205+
return norm(raw || alt || '');
206+
}
207+
208+
function pickBestRef(list, key) {
209+
if (!key || !list?.length) return null;
210+
const scored = [];
211+
list.forEach((r) => {
212+
const nLabel = norm(r.label);
213+
const nName = norm(r.name);
214+
const nNsdb = norm(r.nsdb);
215+
let s = 0;
216+
if (nLabel && nLabel === key) s += 3;
217+
if (nNsdb && nNsdb.includes(key)) s += 2;
218+
if (nName && nName.includes(key)) s += 1;
219+
if (s > 0) scored.push({ r, s });
220+
});
221+
if (!scored.length) return null;
222+
let max = 0;
223+
scored.forEach((x) => {
224+
if (x.s > max) max = x.s;
225+
});
226+
let cand = scored.filter((x) => x.s === max).map((x) => x.r);
227+
if (cand.length > 1) {
228+
const vals = cand.map((c) => (typeof c.value === 'number' ? c.value : null))
229+
.filter((v) => v != null).sort((a, b) => a - b);
230+
if (vals.length) {
231+
const m = vals[Math.floor(vals.length / 2)];
232+
cand = cand.slice().sort((a, b) => Math.abs((a.value ?? m) - m)
233+
- Math.abs((b.value ?? m) - m));
234+
}
235+
if (cand.length > 1) {
236+
cand.sort((a, b) => (a.name?.length || 0) - (b.name?.length || 0));
237+
}
238+
}
239+
return cand[0] || null;
240+
}
241+
242+
function isRefUnset(shiftSt, curveIdx, list) {
243+
const name = shiftSt?.shifts?.[curveIdx]?.ref?.name || '';
244+
if (!name || name === PLACEHOLDER) return true;
245+
return !(list || []).some((r) => r.name === name);
246+
}
247+
192248
const Layout = ({
193249
classes, feature, hasEdit, layoutSt,
194250
setShiftRefAct, updateLayoutAct, curveSt, shiftSt,
195-
}) => (
196-
<span className={classes.groupRight}>
197-
{ layoutSelect(classes, layoutSt, updateLayoutAct) }
198-
{ shiftSelect(classes, layoutSt, setShiftRefAct, shiftSt, curveSt) }
199-
<Scan feature={feature} hasEdit={hasEdit} />
200-
</span>
201-
);
251+
}) => {
252+
const { curveIdx } = curveSt;
253+
const list = getListShift(layoutSt) || [];
254+
const unset = isRefUnset(shiftSt, curveIdx, list);
255+
const key = solventKeyOf(feature);
256+
const best = pickBestRef(list, key);
257+
258+
useEffect(() => {
259+
if (unset && best) setShiftRefAct({ dataToSet: best, curveIdx });
260+
}, [unset, best, curveIdx, setShiftRefAct]);
261+
262+
return (
263+
<span className={classes.groupRight}>
264+
{ layoutSelect(classes, layoutSt, updateLayoutAct) }
265+
{ shiftSelect(classes, layoutSt, setShiftRefAct, shiftSt, curveSt) }
266+
<Scan feature={feature} hasEdit={hasEdit} />
267+
</span>
268+
);
269+
};
202270

203271
const mapStateToProps = (state, props) => ( // eslint-disable-line
204272
{

src/constants/list_shift.js

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -484,11 +484,51 @@ const LIST_SHIFT_1H = [
484484
hTolueneD8Broad4, hTFADS, hTrifluoroethanolD31, hTrifluoroethanolD32,
485485
];
486486

487-
const LIST_SHIFT_19F = [];
487+
const LIST_SHIFT_19F = [
488+
noReference,
489+
hActicAcidD4Quin, hActicAcidD4S, hAcetoneD6Quin, hAcetonitrileD3Qquin,
490+
hBenzeneS, hChloroformDS, hCyclohexaneD12S, hDeuteriumOxideS,
491+
hDichloroethaneD4S, hDichloromethaneD2T, hDMFD7Quin1, hDMFD7Quin2,
492+
hDMFD7Broad3, hDioxaneD8Broad, hDMSOD6Quin, hEthanolD6Broad1,
493+
hEthanolD6S2, hEthanolD6S3, hMethanolD4Quin, hMethanolD4S,
494+
hNitromethaneD3S, hPyridineD5Broad1, hPyridineD5Broad2, hPyridineD5Broad3,
495+
hTHFD8S1, hTHFD8S2, hTMSS, hTolueneD8Quin, hTolueneD8Boad2, hTolueneD8S3,
496+
hTolueneD8Broad4, hTFADS, hTrifluoroethanolD31, hTrifluoroethanolD32,
497+
];
488498

489-
const LIST_SHIFT_31P = [];
490-
const LIST_SHIFT_15N = [];
491-
const LIST_SHIFT_29Si = [];
499+
const LIST_SHIFT_31P = [
500+
noReference,
501+
hActicAcidD4Quin, hActicAcidD4S, hAcetoneD6Quin, hAcetonitrileD3Qquin,
502+
hBenzeneS, hChloroformDS, hCyclohexaneD12S, hDeuteriumOxideS,
503+
hDichloroethaneD4S, hDichloromethaneD2T, hDMFD7Quin1, hDMFD7Quin2,
504+
hDMFD7Broad3, hDioxaneD8Broad, hDMSOD6Quin, hEthanolD6Broad1,
505+
hEthanolD6S2, hEthanolD6S3, hMethanolD4Quin, hMethanolD4S,
506+
hNitromethaneD3S, hPyridineD5Broad1, hPyridineD5Broad2, hPyridineD5Broad3,
507+
hTHFD8S1, hTHFD8S2, hTMSS, hTolueneD8Quin, hTolueneD8Boad2, hTolueneD8S3,
508+
hTolueneD8Broad4, hTFADS, hTrifluoroethanolD31, hTrifluoroethanolD32,
509+
];
510+
const LIST_SHIFT_15N = [
511+
noReference,
512+
hActicAcidD4Quin, hActicAcidD4S, hAcetoneD6Quin, hAcetonitrileD3Qquin,
513+
hBenzeneS, hChloroformDS, hCyclohexaneD12S, hDeuteriumOxideS,
514+
hDichloroethaneD4S, hDichloromethaneD2T, hDMFD7Quin1, hDMFD7Quin2,
515+
hDMFD7Broad3, hDioxaneD8Broad, hDMSOD6Quin, hEthanolD6Broad1,
516+
hEthanolD6S2, hEthanolD6S3, hMethanolD4Quin, hMethanolD4S,
517+
hNitromethaneD3S, hPyridineD5Broad1, hPyridineD5Broad2, hPyridineD5Broad3,
518+
hTHFD8S1, hTHFD8S2, hTMSS, hTolueneD8Quin, hTolueneD8Boad2, hTolueneD8S3,
519+
hTolueneD8Broad4, hTFADS, hTrifluoroethanolD31, hTrifluoroethanolD32,
520+
];
521+
const LIST_SHIFT_29Si = [
522+
noReference,
523+
hActicAcidD4Quin, hActicAcidD4S, hAcetoneD6Quin, hAcetonitrileD3Qquin,
524+
hBenzeneS, hChloroformDS, hCyclohexaneD12S, hDeuteriumOxideS,
525+
hDichloroethaneD4S, hDichloromethaneD2T, hDMFD7Quin1, hDMFD7Quin2,
526+
hDMFD7Broad3, hDioxaneD8Broad, hDMSOD6Quin, hEthanolD6Broad1,
527+
hEthanolD6S2, hEthanolD6S3, hMethanolD4Quin, hMethanolD4S,
528+
hNitromethaneD3S, hPyridineD5Broad1, hPyridineD5Broad2, hPyridineD5Broad3,
529+
hTHFD8S1, hTHFD8S2, hTMSS, hTolueneD8Quin, hTolueneD8Boad2, hTolueneD8S3,
530+
hTolueneD8Broad4, hTFADS, hTrifluoroethanolD31, hTrifluoroethanolD32,
531+
];
492532

493533
const getListShift = (layoutSt) => {
494534
switch (layoutSt) {

0 commit comments

Comments
 (0)