Skip to content

Commit 96b2f73

Browse files
committed
refactor(spectra): submit payload for multi-save with spectra_list (#2993)
1 parent e1d0806 commit 96b2f73

4 files changed

Lines changed: 194 additions & 75 deletions

File tree

app/javascript/src/apps/mydb/elements/details/ViewSpectra.js

Lines changed: 166 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ class ViewSpectra extends React.Component {
229229

230230
const content = this.getContent();
231231
let built = content?.jcamp ? FN.buildData(content.jcamp) : null;
232-
232+
233233
if (!built) {
234234
const listMuliSpcs = content?.listMuliSpcs;
235235
if (Array.isArray(listMuliSpcs) && listMuliSpcs.length) {
@@ -239,23 +239,23 @@ class ViewSpectra extends React.Component {
239239
}
240240
const entity = built?.entity;
241241
if (!entity) return [];
242-
242+
243243
const features = entity?.features;
244244
const f0 = Array.isArray(features)
245245
? features[0]
246246
: (features?.editPeak || features?.autoPeak || features) || {};
247247
const temperature = entity?.temperature;
248-
248+
249249
let observeFrequency = Array.isArray(f0?.observeFrequency)
250250
? f0.observeFrequency[0]
251251
: f0?.observeFrequency;
252252
const freq = Array.isArray(observeFrequency) ? observeFrequency[0] : observeFrequency;
253253
const freqStr = freq ? `${parseInt(freq, 10)} MHz, ` : '';
254-
254+
255255
const boundary = (f0 && (typeof f0.maxY !== 'undefined') && (typeof f0.minY !== 'undefined'))
256256
? { maxY: f0.maxY, minY: f0.minY }
257257
: undefined;
258-
258+
259259
const mBody = body || FN.peaksBody({
260260
peaks,
261261
layout,
@@ -372,11 +372,11 @@ class ViewSpectra extends React.Component {
372372
];
373373
}
374374

375-
writeCommon({
376-
peaks, shift, scan, thres, analysis, layout, isAscend, decimal, body,
377-
keepPred, isIntensity, multiplicity, integration, cyclicvoltaSt, curveSt,
378-
waveLength, axesUnitsSt, detectorSt, dscMetaData,
379-
}, isMpy = false) {
375+
writeCommon(params, isMpy = false) {
376+
const {
377+
peaks, shift, layout, isAscend, decimal, body,
378+
isIntensity, multiplicity, integration, cyclicvoltaSt, curveSt, waveLength
379+
} = params;
380380
const { sample, handleSampleChanged } = this.props;
381381
const si = this.getSpcInfo();
382382
if (!si) return;
@@ -419,11 +419,7 @@ class ViewSpectra extends React.Component {
419419
});
420420
});
421421

422-
const cb = () => (
423-
this.saveOp({
424-
peaks, shift, scan, thres, analysis, keepPred, integration, multiplicity, cyclicvoltaSt, curveSt, layout, waveLength, axesUnitsSt, detectorSt, dscMetaData,
425-
})
426-
);
422+
const cb = () => this.saveOp(params);
427423
handleSampleChanged(sample, cb);
428424
}
429425

@@ -458,60 +454,166 @@ class ViewSpectra extends React.Component {
458454
this.writeCommon(params, isMpy);
459455
}
460456

461-
saveOp({
462-
peaks, shift, scan, thres, analysis, keepPred, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, simulatenmr = false, layout, axesUnitsSt, detectorSt, dscMetaData,
463-
}) {
464-
const { handleSubmit } = this.props;
465-
const { curveIdx } = curveSt;
466-
const si = this.getSpcInfo(curveIdx);
467-
if (!si) return;
468-
const fPeaks = FN.rmRef(peaks, shift);
469-
const peaksStr = FN.toPeakStr(fPeaks);
470-
const predict = JSON.stringify(rmRefreshed(analysis));
471-
const waveLengthStr = JSON.stringify(waveLength);
472-
const cyclicvolta = JSON.stringify(cyclicvoltaSt);
473-
const axesUnitsStr = JSON.stringify(axesUnitsSt);
474-
const detector = JSON.stringify(detectorSt);
457+
getSavePayloads(params, overrideValues = {}) {
458+
const spectraList = Array.isArray(params?.spectra_list) ? params.spectra_list : [];
459+
return spectraList.map((payload) => ({
460+
...payload,
461+
...overrideValues,
462+
simulatenmr: overrideValues.simulatenmr ?? payload?.simulatenmr ?? false,
463+
}));
464+
}
475465

476-
const { shifts } = shift;
477-
const selectedShift = shifts[curveIdx];
478-
const { integrations } = integration;
479-
const selectedIntegration = integrations[curveIdx];
480-
const { multiplicities } = multiplicity;
481-
const selectedMutiplicity = multiplicities[curveIdx];
466+
buildSerializedPayload(payload, curveIdx) {
467+
const hasShiftArray = Array.isArray(payload?.shift?.shifts);
468+
const fPeaks = payload?.peaks && hasShiftArray ? FN.rmRef(payload.peaks, payload.shift, curveIdx) : payload?.peaks;
469+
const selectedShift = payload.shift?.shifts ? payload.shift.shifts[curveIdx] : payload.shift;
470+
const selectedIntegration = payload.integration?.integrations ? payload.integration.integrations[curveIdx] : payload.integration;
471+
const selectedMultiplicity = payload.multiplicity?.multiplicities ? payload.multiplicity.multiplicities[curveIdx] : payload.multiplicity;
472+
473+
return {
474+
peaksStr: FN.toPeakStr(fPeaks),
475+
predict: JSON.stringify(rmRefreshed(payload.analysis)),
476+
waveLengthStr: JSON.stringify(payload.waveLength),
477+
cyclicvolta: JSON.stringify(payload.cyclicvoltaSt),
478+
axesUnitsStr: JSON.stringify(payload.axesUnitsSt),
479+
detector: JSON.stringify(payload.detectorSt),
480+
dscMetaDataStr: JSON.stringify(payload.dscMetaData),
481+
selectedShift,
482+
integrationStr: JSON.stringify(selectedIntegration),
483+
multiplicityStr: JSON.stringify(selectedMultiplicity),
484+
};
485+
}
486+
487+
async saveTarget(target, shouldCombineAfterBatch) {
488+
const { spcInfos, arrSpcIdx } = this.state;
489+
const previousSpcInfos = spcInfos.filter((spc) => (spc.idDt === target.si.idDt && arrSpcIdx.includes(spc.idx)));
490+
const serialized = this.buildSerializedPayload(target.payload, target.curveIdx);
491+
const isSaveCombined = FN.isCyclicVoltaLayout(target.payload.layout) && !shouldCombineAfterBatch;
492+
493+
return new Promise((resolve) => {
494+
SpectraActions.SaveToFile.defer(
495+
target.si,
496+
serialized.peaksStr,
497+
serialized.selectedShift,
498+
target.payload.scan,
499+
target.payload.thres,
500+
serialized.integrationStr,
501+
serialized.multiplicityStr,
502+
serialized.predict,
503+
null,
504+
target.payload.keepPred,
505+
serialized.waveLengthStr,
506+
serialized.cyclicvolta,
507+
target.curveIdx,
508+
target.payload.simulatenmr,
509+
previousSpcInfos,
510+
isSaveCombined,
511+
serialized.axesUnitsStr,
512+
serialized.detector,
513+
serialized.dscMetaDataStr,
514+
(fetchedFiles, _spcInfo, errorMessage) => {
515+
const newIds = (fetchedFiles?.files || []).map((file) => file.id).filter(Boolean);
516+
resolve({ oldId: target.si.idx, newIds, errorMessage });
517+
},
518+
);
519+
});
520+
}
521+
522+
async combineBatchIfNeeded(saveResults, targets, combineCurveIdx) {
523+
if (targets.length <= 1) return;
524+
const layout = targets[0]?.payload?.layout;
525+
if (!layoutsWillShowMulti.includes(layout)) return;
482526

483-
const isSaveCombined = FN.isCyclicVoltaLayout(layout);
484527
const { spcInfos, arrSpcIdx } = this.state;
485-
const previousSpcInfos = spcInfos.filter((spc) => (spc.idDt === si.idDt && arrSpcIdx.includes(spc.idx)));
528+
const combineTarget = targets.find((target) => target.curveIdx === combineCurveIdx) || targets[0];
529+
const combineIdDt = combineTarget?.si?.idDt;
530+
const isSameDataset = !!combineIdDt && targets.every((target) => target.si?.idDt === combineIdDt);
531+
if (!isSameDataset) return;
532+
533+
const replacedIds = saveResults
534+
.filter((result) => result.newIds.length > 0)
535+
.map((result) => result.oldId);
536+
const keptIds = spcInfos
537+
.filter((spc) => (spc.idDt === combineIdDt && arrSpcIdx.includes(spc.idx)))
538+
.map((spc) => spc.idx)
539+
.filter((id) => !replacedIds.includes(id));
540+
const newIds = saveResults.flatMap((result) => result.newIds);
541+
if (newIds.length === 0) return;
542+
543+
const combineIds = [...new Set([...keptIds, ...newIds])];
544+
if (combineIds.length === 0) return;
545+
546+
const combineSerialized = this.buildSerializedPayload(combineTarget.payload, combineCurveIdx);
547+
const combineExtras = {
548+
attachmentId: combineTarget?.si?.idx,
549+
peaksStr: combineSerialized.peaksStr,
550+
shiftSelectX: combineSerialized.selectedShift?.peak?.x,
551+
shiftRefName: combineSerialized.selectedShift?.ref?.name,
552+
shiftRefValue: combineSerialized.selectedShift?.ref?.value,
553+
scan: combineTarget.payload.scan,
554+
thres: combineTarget.payload.thres,
555+
integration: combineSerialized.integrationStr,
556+
multiplicity: combineSerialized.multiplicityStr,
557+
predict: combineSerialized.predict,
558+
keepPred: combineTarget.payload.keepPred,
559+
waveLength: combineSerialized.waveLengthStr,
560+
cyclicvolta: combineSerialized.cyclicvolta,
561+
curveIdx: combineCurveIdx,
562+
simulatenmr: combineTarget.payload.simulatenmr,
563+
axesUnits: combineSerialized.axesUnitsStr,
564+
detector: combineSerialized.detector,
565+
dscMetaData: combineSerialized.dscMetaDataStr,
566+
};
567+
568+
await new Promise((resolve) => {
569+
SpectraActions.CombineSpectra.defer(
570+
combineIds,
571+
combineCurveIdx,
572+
combineExtras,
573+
() => resolve(),
574+
);
575+
});
576+
}
577+
578+
saveOp(params) {
579+
const { handleSubmit } = this.props;
580+
if (!Array.isArray(params?.spectra_list) || params.spectra_list.length === 0) {
581+
console.warn('saveOp expects a non-empty spectra_list payload.'); // eslint-disable-line no-console
582+
return;
583+
}
584+
const payloads = this.getSavePayloads(params);
585+
const targets = payloads.map((payload, idx) => {
586+
const curveIdx = payload.curveSt?.curveIdx ?? payload.curveIdx ?? idx;
587+
const si = this.getSpcInfo(curveIdx);
588+
if (!si) return null;
589+
return { payload, curveIdx, si };
590+
}).filter(Boolean);
591+
if (targets.length === 0) return;
592+
593+
const combineCurveIdx = params.curveSt?.curveIdx ?? targets[0].curveIdx;
594+
const shouldCombineAfterBatch = targets.length > 1
595+
&& layoutsWillShowMulti.includes(targets[0].payload.layout);
596+
486597
LoadingActions.start.defer();
487-
SpectraActions.SaveToFile.defer(
488-
si,
489-
peaksStr,
490-
selectedShift,
491-
scan,
492-
thres,
493-
JSON.stringify(selectedIntegration),
494-
JSON.stringify(selectedMutiplicity),
495-
predict,
496-
handleSubmit,
497-
keepPred,
498-
waveLengthStr,
499-
cyclicvolta,
500-
curveIdx,
501-
simulatenmr,
502-
previousSpcInfos,
503-
isSaveCombined,
504-
axesUnitsStr,
505-
detector,
506-
JSON.stringify(dscMetaData),
507-
);
598+
(async () => {
599+
const saveResults = [];
600+
for (const target of targets) {
601+
const result = await this.saveTarget(target, shouldCombineAfterBatch);
602+
saveResults.push(result);
603+
}
604+
await this.combineBatchIfNeeded(saveResults, targets, combineCurveIdx);
605+
handleSubmit();
606+
})().catch((errorMessage) => {
607+
console.log(errorMessage); // eslint-disable-line
608+
handleSubmit();
609+
});
508610
}
509611

510-
refreshOp({
511-
peaks, shift, scan, thres, analysis, keepPred, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, layout, axesUnitsSt, detectorSt
512-
}) {
612+
refreshOp(params) {
613+
const refreshPayloads = this.getSavePayloads(params, { simulatenmr: true });
513614
this.saveOp({
514-
peaks, shift, scan, thres, analysis, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, simulatenmr: true, layout, axesUnitsSt, detectorSt
615+
...params,
616+
spectra_list: refreshPayloads,
515617
});
516618
}
517619

@@ -536,12 +638,8 @@ class ViewSpectra extends React.Component {
536638
this.closeOp();
537639
}
538640

539-
saveCloseOp({
540-
peaks, shift, scan, thres, analysis, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, layout, axesUnitsSt, detectorSt, dscMetaData,
541-
}) {
542-
this.saveOp({
543-
peaks, shift, scan, thres, analysis, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, layout, axesUnitsSt, detectorSt, dscMetaData,
544-
});
641+
saveCloseOp(params) {
642+
this.saveOp(params);
545643
this.closeOp();
546644
}
547645

app/javascript/src/stores/alt/actions/SpectraActions.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,35 @@ class SpectraActions {
3535
};
3636
}
3737

38-
SaveToFile(spcInfo, peaksStr, shift, scan, thres, integration, multiplicity, predict, cb, keepPred = false, waveLengthStr, cyclicvolta, curveIdx = 0, simulatenmr = false, previousSpcInfos, isSaveCombined = false, axesUnitsStr, detector, dscMetaData) {
38+
SaveToFile(spcInfo, peaksStr, shift, scan, thres, integration, multiplicity, predict, cb, keepPred = false, waveLengthStr, cyclicvolta, curveIdx = 0, simulatenmr = false, previousSpcInfos, isSaveCombined = false, axesUnitsStr, detector, dscMetaData, onSaved) {
3939
return (dispatch) => {
4040
AttachmentFetcher.saveSpectrum(spcInfo.idx, peaksStr, shift, scan, thres, integration, multiplicity, predict, keepPred, waveLengthStr, cyclicvolta, curveIdx, simulatenmr, previousSpcInfos, isSaveCombined, axesUnitsStr, detector, dscMetaData)
4141
.then((fetchedFiles) => {
4242
dispatch({ fetchedFiles, spcInfo });
43-
cb();
43+
if (onSaved) {
44+
onSaved(fetchedFiles, spcInfo);
45+
}
46+
if (cb) {
47+
cb();
48+
}
4449
}).catch((errorMessage) => {
4550
console.log(errorMessage); // eslint-disable-line
51+
if (onSaved) {
52+
onSaved(null, spcInfo, errorMessage);
53+
}
54+
});
55+
};
56+
}
57+
58+
CombineSpectra(jcampIds, curveIdx, extraParams, cb) {
59+
return () => {
60+
AttachmentFetcher.combineSpectra(jcampIds, curveIdx, extraParams)
61+
.then((combined) => {
62+
if (cb) cb(combined);
63+
})
64+
.catch((errorMessage) => {
65+
console.log(errorMessage); // eslint-disable-line
66+
if (cb) cb(null, errorMessage);
4667
});
4768
};
4869
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"@citation-js/plugin-isbn": "0.3.0",
1515
"@complat/chem-spectra-client": "1.3.5",
1616
"@complat/chemotion-converter-client": "~0.15.0",
17-
"@complat/react-spectra-editor": "1.6.0",
17+
"@complat/react-spectra-editor": "1.7.0",
1818
"@novnc/novnc": "~1.5.0",
1919
"@sentry/react": "^7.73.0",
2020
"@sentry/tracing": "^7.16.0",

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,10 +1560,10 @@
15601560
reselect "^4.0.0"
15611561
typescript "^5.0.4"
15621562

1563-
"@complat/react-spectra-editor@1.6.0":
1564-
version "1.6.0"
1565-
resolved "https://registry.yarnpkg.com/@complat/react-spectra-editor/-/react-spectra-editor-1.6.0.tgz#aa4801ca6b0cb032b650817e39455873e29a9e20"
1566-
integrity sha512-tmn1AfQEL/sloCjD/TW+uNq0WvnIdEfgKIhVmdG7XMx6kuLQbWgQD7idt8iQ7+EU9x9dBdFPqKf+JfjEWZrcaw==
1563+
"@complat/react-spectra-editor@1.7.0":
1564+
version "1.7.0"
1565+
resolved "https://registry.yarnpkg.com/@complat/react-spectra-editor/-/react-spectra-editor-1.7.0.tgz#9e1dde68ed61794f31f72d5b7fe57227a5612521"
1566+
integrity sha512-Tk9apRDvPuAAj1/IPJKmnpyidqPrQZmLl3/YSdSZF0/LcSmtL6VQm7NIPaRqDj9/sL9XjRAZW8IyJb6A4v7pxQ==
15671567
dependencies:
15681568
"@complat/react-svg-file-zoom-pan" "1.1.4"
15691569
"@emotion/react" "^11.11.1"

0 commit comments

Comments
 (0)