@complat/react-spectra-editor 1.5.4 → 1.7.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.
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _reduxMockStore = _interopRequireDefault(require("redux-mock-store"));
5
+ var _reactRedux = require("react-redux");
6
+ var _react = require("@testing-library/react");
7
+ require("@testing-library/jest-dom");
8
+ var _r05_submit_btn = _interopRequireDefault(require("../../../../components/cmd_bar/r05_submit_btn"));
9
+ var _jsxRuntime = require("react/jsx-runtime");
10
+ jest.mock('../../../../helpers/extractPeaksEdit', () => ({
11
+ extractPeaksEdit: jest.fn(() => [{
12
+ x: 1,
13
+ y: 2
14
+ }])
15
+ }));
16
+ const mockStore = (0, _reduxMockStore.default)([]);
17
+ const buildBaseState = (overrides = {}) => ({
18
+ editPeak: {
19
+ present: {
20
+ selectedIdx: 0,
21
+ peaks: [{
22
+ pos: [],
23
+ neg: []
24
+ }]
25
+ }
26
+ },
27
+ threshold: {
28
+ list: [{
29
+ isEdit: true,
30
+ value: 10,
31
+ upper: false,
32
+ lower: false
33
+ }]
34
+ },
35
+ layout: '1H',
36
+ shift: {
37
+ shifts: []
38
+ },
39
+ scan: {
40
+ target: 5,
41
+ isAuto: false
42
+ },
43
+ forecast: {
44
+ predictions: {}
45
+ },
46
+ submit: {
47
+ decimal: 2
48
+ },
49
+ integration: {
50
+ present: {
51
+ integrations: [{
52
+ stack: [],
53
+ refArea: 1,
54
+ refFactor: 1
55
+ }]
56
+ }
57
+ },
58
+ multiplicity: {
59
+ present: {
60
+ multiplicities: [{
61
+ stack: [],
62
+ shift: 0
63
+ }]
64
+ }
65
+ },
66
+ wavelength: {},
67
+ cyclicvolta: {
68
+ useCurrentDensity: false,
69
+ areaUnit: 'cm²',
70
+ areaValue: 1.0
71
+ },
72
+ curve: {
73
+ curveIdx: 0,
74
+ listCurves: []
75
+ },
76
+ axesUnits: {
77
+ axes: [{
78
+ xUnit: '',
79
+ yUnit: ''
80
+ }]
81
+ },
82
+ detector: {},
83
+ meta: {
84
+ dscMetaData: {}
85
+ },
86
+ ...overrides
87
+ });
88
+ const renderBtnSubmit = (state, operationValue) => {
89
+ const store = mockStore(state);
90
+ const feature = {
91
+ xUnit: 'ppm',
92
+ yUnit: 'intensity',
93
+ scanAutoTarget: 1,
94
+ thresRef: 3
95
+ };
96
+ const view = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactRedux.Provider, {
97
+ store: store,
98
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_r05_submit_btn.default, {
99
+ operation: {
100
+ name: 'save',
101
+ value: operationValue
102
+ },
103
+ feature: feature,
104
+ isAscend: true,
105
+ isIntensity: true
106
+ })
107
+ }));
108
+ const button = view.container.querySelector('.btn-sv-bar-submit');
109
+ _react.fireEvent.click(button);
110
+ return view;
111
+ };
112
+ describe('<BtnSubmit payload contract />', () => {
113
+ it('sends a spectra_list with length 1 in single-spectrum mode', () => {
114
+ const operationValue = jest.fn();
115
+ const state = buildBaseState({
116
+ curve: {
117
+ curveIdx: 0,
118
+ listCurves: []
119
+ }
120
+ });
121
+ renderBtnSubmit(state, operationValue);
122
+ expect(operationValue).toHaveBeenCalledTimes(1);
123
+ const payload = operationValue.mock.calls[0][0];
124
+ expect(Array.isArray(payload.spectra_list)).toBe(true);
125
+ expect(payload.spectra_list).toHaveLength(1);
126
+ expect(payload).toHaveProperty('curveSt');
127
+ expect(payload.curveSt).toEqual({
128
+ curveIdx: 0
129
+ });
130
+ });
131
+ it('sends a spectra_list with length N in multi-spectrum mode', () => {
132
+ const operationValue = jest.fn();
133
+ const state = buildBaseState({
134
+ curve: {
135
+ curveIdx: 1,
136
+ listCurves: [{
137
+ feature: {
138
+ xUnit: 'ppm',
139
+ yUnit: 'intensity',
140
+ scanAutoTarget: 1,
141
+ thresRef: 3
142
+ }
143
+ }, {
144
+ feature: {
145
+ xUnit: 'ppm',
146
+ yUnit: 'intensity',
147
+ scanAutoTarget: 2,
148
+ thresRef: 4
149
+ }
150
+ }, {
151
+ feature: {
152
+ xUnit: 'ppm',
153
+ yUnit: 'intensity',
154
+ scanAutoTarget: 3,
155
+ thresRef: 5
156
+ }
157
+ }]
158
+ },
159
+ threshold: {
160
+ list: [{
161
+ value: 10
162
+ }, {
163
+ value: 20
164
+ }, {
165
+ value: 30
166
+ }]
167
+ },
168
+ axesUnits: {
169
+ axes: [{
170
+ xUnit: '',
171
+ yUnit: ''
172
+ }, {
173
+ xUnit: '',
174
+ yUnit: ''
175
+ }, {
176
+ xUnit: '',
177
+ yUnit: ''
178
+ }]
179
+ }
180
+ });
181
+ renderBtnSubmit(state, operationValue);
182
+ const payload = operationValue.mock.calls[0][0];
183
+ expect(payload.spectra_list).toHaveLength(3);
184
+ expect(payload.curveSt).toEqual({
185
+ curveIdx: 1
186
+ });
187
+ });
188
+ it('controls presence/absence of keepPred and simulatenmr', () => {
189
+ const withFlagsCb = jest.fn();
190
+ const noFlagsCb = jest.fn();
191
+ const withFlagsState = buildBaseState({
192
+ forecast: {
193
+ predictions: {
194
+ keepPred: true,
195
+ simulatenmr: false
196
+ }
197
+ }
198
+ });
199
+ renderBtnSubmit(withFlagsState, withFlagsCb);
200
+ const withFlagsPayload = withFlagsCb.mock.calls[0][0];
201
+ expect(withFlagsPayload.spectra_list[0]).toMatchObject({
202
+ keepPred: true,
203
+ simulatenmr: false
204
+ });
205
+ const noFlagsState = buildBaseState({
206
+ forecast: {
207
+ predictions: {
208
+ keepPred: 'yes'
209
+ }
210
+ }
211
+ });
212
+ renderBtnSubmit(noFlagsState, noFlagsCb);
213
+ const noFlagsPayload = noFlagsCb.mock.calls[0][0];
214
+ expect(noFlagsPayload.spectra_list[0]).not.toHaveProperty('keepPred');
215
+ expect(noFlagsPayload.spectra_list[0]).not.toHaveProperty('simulatenmr');
216
+ });
217
+ });
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.setWorkWithMaxPeak = exports.setCylicVoltaRefFactor = exports.setCylicVoltaRef = exports.selectRefPeaks = exports.selectPairPeak = exports.removeCylicVoltaPecker = exports.removeCylicVoltaPairPeak = exports.removeCylicVoltaMinPeak = exports.removeCylicVoltaMaxPeak = exports.addNewCylicVoltaPairPeak = exports.addCylicVoltaPecker = exports.addCylicVoltaMinPeak = exports.addCylicVoltaMaxPeak = void 0;
6
+ exports.toggleCyclicVoltaDensity = exports.setWorkWithMaxPeak = exports.setCylicVoltaRefFactor = exports.setCylicVoltaRef = exports.setCyclicVoltaAreaValue = exports.setCyclicVoltaAreaUnit = exports.selectRefPeaks = exports.selectPairPeak = exports.removeCylicVoltaPecker = exports.removeCylicVoltaPairPeak = exports.removeCylicVoltaMinPeak = exports.removeCylicVoltaMaxPeak = exports.addNewCylicVoltaPairPeak = exports.addCylicVoltaPecker = exports.addCylicVoltaMinPeak = exports.addCylicVoltaMaxPeak = void 0;
7
7
  var _action_type = require("../constants/action_type");
8
8
  const addNewCylicVoltaPairPeak = payload => ({
9
9
  type: _action_type.CYCLIC_VOLTA_METRY.ADD_PAIR_PEAKS,
@@ -69,4 +69,23 @@ const setCylicVoltaRef = payload => ({
69
69
  type: _action_type.CYCLIC_VOLTA_METRY.SET_REF,
70
70
  payload
71
71
  });
72
- exports.setCylicVoltaRef = setCylicVoltaRef;
72
+ exports.setCylicVoltaRef = setCylicVoltaRef;
73
+ const setCyclicVoltaAreaValue = value => ({
74
+ type: _action_type.CYCLIC_VOLTA_METRY.SET_AREA_VALUE,
75
+ payload: {
76
+ value
77
+ }
78
+ });
79
+ exports.setCyclicVoltaAreaValue = setCyclicVoltaAreaValue;
80
+ const setCyclicVoltaAreaUnit = unit => ({
81
+ type: _action_type.CYCLIC_VOLTA_METRY.SET_AREA_UNIT,
82
+ payload: {
83
+ unit
84
+ }
85
+ });
86
+ exports.setCyclicVoltaAreaUnit = setCyclicVoltaAreaUnit;
87
+ const toggleCyclicVoltaDensity = payload => ({
88
+ type: _action_type.CYCLIC_VOLTA_METRY.TOGGLE_DENSITY,
89
+ payload
90
+ });
91
+ exports.toggleCyclicVoltaDensity = toggleCyclicVoltaDensity;
@@ -24,6 +24,8 @@ var _r07_wavelength_btn = _interopRequireDefault(require("./r07_wavelength_btn")
24
24
  var _pecker = _interopRequireDefault(require("./07_pecker"));
25
25
  var _r08_change_axes = _interopRequireDefault(require("./r08_change_axes"));
26
26
  var _r09_detector = _interopRequireDefault(require("./r09_detector"));
27
+ var _r10_cv_density = _interopRequireDefault(require("./r10_cv_density"));
28
+ var _format = _interopRequireDefault(require("../../helpers/format"));
27
29
  var _jsxRuntime = require("react/jsx-runtime");
28
30
  /* eslint-disable prefer-object-spread, function-paren-newline,
29
31
  react/function-component-definition, react/require-default-props */
@@ -37,34 +39,40 @@ const CmdBar = ({
37
39
  operations,
38
40
  editorOnly,
39
41
  jcampIdx,
40
- hideThreshold
41
- }) => /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
42
- className: classes.card,
43
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_viewer.default, {
44
- editorOnly: editorOnly
45
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_zoom.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_peak.default, {
46
- jcampIdx: jcampIdx,
47
- feature: feature
48
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_pecker.default, {
49
- jcampIdx: jcampIdx
50
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_integration.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_multiplicity.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_undo_redo.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r04_submit.default, {
51
- operations: operations,
52
- feature: feature,
53
- forecast: forecast,
54
- editorOnly: editorOnly,
55
- hideSwitch: false,
56
- disabled: false
57
- }), hideThreshold ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_r03_threshold.default, {
58
- feature: feature,
59
- hasEdit: hasEdit
60
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r01_layout.default, {
61
- feature: feature,
62
- hasEdit: hasEdit
63
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r07_wavelength_btn.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r08_change_axes.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r09_detector.default, {})]
64
- });
42
+ hideThreshold,
43
+ layoutSt
44
+ }) => {
45
+ const isCvLayout = _format.default.isCyclicVoltaLayout(layoutSt);
46
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
47
+ className: classes.card,
48
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_viewer.default, {
49
+ editorOnly: editorOnly
50
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_zoom.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_peak.default, {
51
+ jcampIdx: jcampIdx,
52
+ feature: feature
53
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_pecker.default, {
54
+ jcampIdx: jcampIdx
55
+ }), isCvLayout ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_integration.default, {}), isCvLayout ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_multiplicity.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_undo_redo.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r04_submit.default, {
56
+ operations: operations,
57
+ feature: feature,
58
+ forecast: forecast,
59
+ editorOnly: editorOnly,
60
+ hideSwitch: false,
61
+ disabled: false
62
+ }), hideThreshold ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_r03_threshold.default, {
63
+ feature: feature,
64
+ hasEdit: hasEdit
65
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r01_layout.default, {
66
+ feature: feature,
67
+ hasEdit: hasEdit
68
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r07_wavelength_btn.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r10_cv_density.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r08_change_axes.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_r09_detector.default, {})]
69
+ });
70
+ };
65
71
  const mapStateToProps = (state, _) => (
66
72
  // eslint-disable-line
67
- {});
73
+ {
74
+ layoutSt: state.layout
75
+ });
68
76
  const mapDispatchToProps = dispatch => (0, _redux.bindActionCreators)({}, dispatch);
69
77
  CmdBar.propTypes = {
70
78
  classes: _propTypes.default.object.isRequired,
@@ -73,6 +81,7 @@ CmdBar.propTypes = {
73
81
  hasEdit: _propTypes.default.bool.isRequired,
74
82
  operations: _propTypes.default.array.isRequired,
75
83
  editorOnly: _propTypes.default.bool.isRequired,
84
+ layoutSt: _propTypes.default.string.isRequired,
76
85
  jcampIdx: _propTypes.default.any,
77
86
  hideThreshold: _propTypes.default.bool
78
87
  };
@@ -33,6 +33,35 @@ const styles = () => Object.assign({
33
33
  width: 100
34
34
  }
35
35
  }, _common.commonStyle);
36
+ const chemSubStyle = {
37
+ fontSize: '0.85em',
38
+ position: 'relative',
39
+ top: '0.24em',
40
+ lineHeight: 1
41
+ };
42
+ const renderReadableSubscript = (txt = '') => {
43
+ if (typeof txt !== 'string') return txt;
44
+ const regex = /([A-Za-z])(\d+)/g;
45
+ if (!regex.test(txt)) return txt;
46
+ regex.lastIndex = 0;
47
+ const parts = [];
48
+ let cursor = 0;
49
+ let match = regex.exec(txt);
50
+ while (match) {
51
+ const [raw, prefix, digits] = match;
52
+ const at = match.index;
53
+ if (at > cursor) parts.push(txt.slice(cursor, at));
54
+ parts.push(prefix);
55
+ parts.push(/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
56
+ style: chemSubStyle,
57
+ children: digits
58
+ }, `${at}-${digits}`));
59
+ cursor = at + raw.length;
60
+ match = regex.exec(txt);
61
+ }
62
+ if (cursor < txt.length) parts.push(txt.slice(cursor));
63
+ return parts;
64
+ };
36
65
  const shiftSelect = (classes, layoutSt, setShiftRefAct, shiftSt, curveSt) => {
37
66
  if (_cfg.default.hideSolvent(layoutSt)) {
38
67
  return null;
@@ -73,9 +102,9 @@ const shiftSelect = (classes, layoutSt, setShiftRefAct, shiftSt, curveSt) => {
73
102
  className: (0, _classnames.default)(classes.selectInput, 'input-sv-bar-shift'),
74
103
  children: listShift.map(ref => /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.MenuItem, {
75
104
  value: ref.name,
76
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
105
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
77
106
  className: (0, _classnames.default)(classes.txtOpt, 'option-sv-bar-shift'),
78
- children: `${ref.name}: ${_format.default.strNumberFixedDecimal(ref.value, 2)} ppm`
107
+ children: [renderReadableSubscript(ref.name), `: ${_format.default.strNumberFixedDecimal(ref.value, 2)} ppm`]
79
108
  })
80
109
  }, ref.name))
81
110
  })]
@@ -16,34 +16,186 @@ var _styles = require("@mui/styles");
16
16
  var _chem = require("../../helpers/chem");
17
17
  var _common = require("./common");
18
18
  var _extractPeaksEdit = require("../../helpers/extractPeaksEdit");
19
+ var _format = _interopRequireDefault(require("../../helpers/format"));
19
20
  var _jsxRuntime = require("react/jsx-runtime");
20
21
  /* eslint-disable prefer-object-spread, function-paren-newline,
21
22
  react/function-component-definition, function-call-argument-newline,
22
23
  react/require-default-props */
23
24
 
24
25
  const styles = () => Object.assign({}, _common.commonStyle);
25
- const onClickCb = (operation, peaksEdit, isAscend, isIntensity, scan, thres, layoutSt, shiftSt, analysis, decimalSt, integrationSt, multiplicitySt, allIntegrationSt, aucValues, waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt, dscMetaData) => () => {
26
- operation({
26
+ const getAxesSelection = (axesUnitsSt, curveIdx) => {
27
+ const axes = axesUnitsSt?.axes;
28
+ if (!Array.isArray(axes) || axes.length === 0) return {
29
+ xUnit: '',
30
+ yUnit: ''
31
+ };
32
+ const idx = Number.isFinite(curveIdx) ? curveIdx : 0;
33
+ return axes[idx] || axes[0] || {
34
+ xUnit: '',
35
+ yUnit: ''
36
+ };
37
+ };
38
+ const resolveAxisLabels = (xLabel, yLabel, axesUnitsSt, curveIdx) => {
39
+ const {
40
+ xUnit,
41
+ yUnit
42
+ } = getAxesSelection(axesUnitsSt, curveIdx);
43
+ return {
44
+ xLabel: xUnit === '' ? xLabel : xUnit,
45
+ yLabel: yUnit === '' ? yLabel : yUnit
46
+ };
47
+ };
48
+ const getBaseCurrentUnit = label => /mA/i.test(String(label)) ? 'mA' : 'A';
49
+ const buildCvAxisYLabel = (yLabel, cyclicvoltaSt) => {
50
+ const baseUnit = getBaseCurrentUnit(yLabel);
51
+ const areaUnit = cyclicvoltaSt?.areaUnit || 'cm²';
52
+ if (cyclicvoltaSt?.useCurrentDensity) {
53
+ return `Current density in ${baseUnit}/${areaUnit}`;
54
+ }
55
+ return `Current in ${baseUnit}`;
56
+ };
57
+ const computeCvYScaleFactor = (feature, cyclicvoltaSt) => {
58
+ if (!cyclicvoltaSt?.useCurrentDensity) return 1.0;
59
+ const rawArea = (cyclicvoltaSt.areaValue === '' ? 1.0 : cyclicvoltaSt.areaValue) || 1.0;
60
+ const areaUnit = cyclicvoltaSt.areaUnit || 'cm²';
61
+ const safeArea = rawArea > 0 ? rawArea : 1.0;
62
+ const areaInCm2 = areaUnit === 'mm²' ? safeArea / 100.0 : safeArea;
63
+ let factor = 1.0 / areaInCm2;
64
+ const baseY = feature && feature.yUnit ? String(feature.yUnit) : 'A';
65
+ if (/mA/i.test(baseY)) {
66
+ factor *= 1000.0;
67
+ }
68
+ if (areaUnit === 'mm²') {
69
+ factor /= 100.0;
70
+ }
71
+ return factor;
72
+ };
73
+ const defaultThreshold = {
74
+ isEdit: true,
75
+ value: false,
76
+ upper: false,
77
+ lower: false
78
+ };
79
+ const pickFromList = (list, index, fallback = null) => Array.isArray(list) && list[index] !== undefined ? list[index] : fallback;
80
+ const hasBoolean = value => typeof value === 'boolean';
81
+ const resolveOptionalBooleanFlags = analysis => {
82
+ const flags = {};
83
+ if (hasBoolean(analysis?.keepPred)) flags.keepPred = analysis.keepPred;
84
+ if (hasBoolean(analysis?.simulatenmr)) flags.simulatenmr = analysis.simulatenmr;
85
+ return flags;
86
+ };
87
+ const buildSpectrumPayload = ({
88
+ feature,
89
+ curveIdx,
90
+ editPeakSt,
91
+ thresList,
92
+ shiftSt,
93
+ layoutSt,
94
+ scanSt,
95
+ integrationSt,
96
+ multiplicitySt,
97
+ waveLengthSt,
98
+ cyclicvoltaSt,
99
+ axesUnitsSt,
100
+ detectorSt,
101
+ dscMetaData,
102
+ isAscend,
103
+ isIntensity,
104
+ analysis,
105
+ decimalSt
106
+ }) => {
107
+ const threshold = thresList?.[curveIdx] || thresList?.[0] || defaultThreshold;
108
+ const editPeakAtIndex = Object.assign({}, editPeakSt, {
109
+ selectedIdx: curveIdx
110
+ });
111
+ const peaksEdit = (0, _extractPeaksEdit.extractPeaksEdit)(feature, editPeakAtIndex, threshold, shiftSt, layoutSt, curveIdx);
112
+ const scan = (0, _chem.Convert2Scan)(feature, scanSt);
113
+ const thres = (0, _chem.Convert2Thres)(feature, threshold);
114
+ const shift = pickFromList(shiftSt?.shifts, curveIdx, shiftSt);
115
+ const integration = pickFromList(integrationSt?.integrations, curveIdx, integrationSt);
116
+ const multiplicity = pickFromList(multiplicitySt?.multiplicities, curveIdx, multiplicitySt);
117
+ const {
118
+ xLabel,
119
+ yLabel
120
+ } = resolveAxisLabels(feature?.xUnit, feature?.yUnit, axesUnitsSt, curveIdx);
121
+ const axisYLabel = _format.default.isCyclicVoltaLayout(layoutSt) ? buildCvAxisYLabel(yLabel, cyclicvoltaSt) : yLabel;
122
+ const axisDisplay = {
123
+ xLabel,
124
+ yLabel: axisYLabel
125
+ };
126
+ const cvDisplay = _format.default.isCyclicVoltaLayout(layoutSt) ? {
127
+ mode: cyclicvoltaSt?.useCurrentDensity ? 'density' : 'current',
128
+ yScaleFactor: computeCvYScaleFactor(feature, cyclicvoltaSt)
129
+ } : null;
130
+ const cyclicvoltaPayload = {
131
+ ...cyclicvoltaSt,
132
+ axisDisplay,
133
+ cvDisplay
134
+ };
135
+ const optionalBooleanFlags = resolveOptionalBooleanFlags(analysis);
136
+ return {
27
137
  peaks: peaksEdit,
28
138
  layout: layoutSt,
29
- shift: shiftSt,
139
+ shift,
30
140
  scan,
31
141
  thres,
32
142
  isAscend,
33
143
  isIntensity,
34
144
  analysis,
35
145
  decimal: decimalSt,
36
- integration: integrationSt,
37
- multiplicity: multiplicitySt,
38
- allIntegration: allIntegrationSt,
39
- aucValues,
146
+ integration,
147
+ multiplicity,
40
148
  waveLength: waveLengthSt,
41
- cyclicvoltaSt,
42
- curveSt,
149
+ cyclicvoltaSt: cyclicvoltaPayload,
150
+ curveSt: {
151
+ curveIdx
152
+ },
43
153
  axesUnitsSt,
44
154
  detectorSt,
45
- dscMetaData
155
+ dscMetaData,
156
+ ...optionalBooleanFlags
157
+ };
158
+ };
159
+ const onClickCb = (operationValue, isAscend, isIntensity, layoutSt, shiftSt, analysis, decimalSt, integrationSt, multiplicitySt, waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt, dscMetaData, curveList, editPeakSt, thresList, scanSt, feature) => () => {
160
+ const defaultCurves = feature ? [{
161
+ feature
162
+ }] : [];
163
+ const curves = Array.isArray(curveList) && curveList.length > 0 ? curveList : defaultCurves;
164
+ const fallbackIdx = Number.isFinite(curveSt?.curveIdx) ? curveSt.curveIdx : 0;
165
+ const indicesToSend = curves.length > 0 ? curves.map((_, index) => index) : [fallbackIdx];
166
+ const spectraList = indicesToSend.map(curveIdx => {
167
+ const curve = curves[curveIdx] || {};
168
+ const curveFeature = curve.feature || feature;
169
+ return buildSpectrumPayload({
170
+ feature: curveFeature,
171
+ curveIdx,
172
+ editPeakSt,
173
+ thresList,
174
+ shiftSt,
175
+ layoutSt,
176
+ scanSt,
177
+ integrationSt,
178
+ multiplicitySt,
179
+ waveLengthSt,
180
+ cyclicvoltaSt,
181
+ axesUnitsSt,
182
+ detectorSt,
183
+ dscMetaData,
184
+ isAscend,
185
+ isIntensity,
186
+ analysis,
187
+ decimalSt
188
+ });
46
189
  });
190
+ const payload = {
191
+ spectra_list: spectraList
192
+ };
193
+ if (Number.isFinite(curveSt?.curveIdx)) {
194
+ payload.curveSt = {
195
+ curveIdx: curveSt.curveIdx
196
+ };
197
+ }
198
+ operationValue(payload);
47
199
  };
48
200
  const BtnSubmit = ({
49
201
  classes,
@@ -52,7 +204,7 @@ const BtnSubmit = ({
52
204
  isAscend,
53
205
  isIntensity,
54
206
  editPeakSt,
55
- thresSt,
207
+ thresList,
56
208
  layoutSt,
57
209
  shiftSt,
58
210
  scanSt,
@@ -60,22 +212,37 @@ const BtnSubmit = ({
60
212
  decimalSt,
61
213
  integrationSt,
62
214
  multiplicitySt,
63
- allIntegrationSt,
64
215
  waveLengthSt,
65
216
  cyclicvoltaSt,
66
217
  curveSt,
218
+ curveList,
67
219
  axesUnitsSt,
68
220
  detectorSt,
69
221
  metaSt
70
222
  }) => {
71
- const peaksEdit = (0, _extractPeaksEdit.extractPeaksEdit)(feature, editPeakSt, thresSt, shiftSt, layoutSt);
72
223
  // const disBtn = peaksEdit.length === 0 || statusSt.btnSubmit || disabled;
73
- const scan = (0, _chem.Convert2Scan)(feature, scanSt);
74
- const thres = (0, _chem.Convert2Thres)(feature, thresSt);
75
- const aucValues = (0, _extractPeaksEdit.extractAreaUnderCurve)(allIntegrationSt, integrationSt, layoutSt);
76
224
  const {
77
225
  dscMetaData
78
226
  } = metaSt;
227
+ const isCvLayout = _format.default.isCyclicVoltaLayout(layoutSt);
228
+ const {
229
+ xLabel,
230
+ yLabel
231
+ } = resolveAxisLabels(feature?.xUnit, feature?.yUnit, axesUnitsSt, curveSt?.curveIdx);
232
+ const axisYLabel = isCvLayout ? buildCvAxisYLabel(yLabel, cyclicvoltaSt) : yLabel;
233
+ const axisDisplay = {
234
+ xLabel,
235
+ yLabel: axisYLabel
236
+ };
237
+ const cvDisplay = isCvLayout ? {
238
+ mode: cyclicvoltaSt?.useCurrentDensity ? 'density' : 'current',
239
+ yScaleFactor: computeCvYScaleFactor(feature, cyclicvoltaSt)
240
+ } : null;
241
+ const cyclicvoltaPayload = {
242
+ ...cyclicvoltaSt,
243
+ axisDisplay,
244
+ cvDisplay
245
+ };
79
246
  if (!operation) return null;
80
247
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
81
248
  title: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
@@ -85,7 +252,7 @@ const BtnSubmit = ({
85
252
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
86
253
  className: (0, _classnames.default)('btn-sv-bar-submit'),
87
254
  color: "primary",
88
- onClick: onClickCb(operation.value, peaksEdit, isAscend, isIntensity, scan, thres, layoutSt, shiftSt, forecastSt.predictions, decimalSt, integrationSt, multiplicitySt, allIntegrationSt, aucValues, waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt, dscMetaData),
255
+ onClick: onClickCb(operation.value, isAscend, isIntensity, layoutSt, shiftSt, forecastSt.predictions, decimalSt, integrationSt, multiplicitySt, waveLengthSt, cyclicvoltaPayload, curveSt, axesUnitsSt, detectorSt, dscMetaData, curveList, editPeakSt, thresList, scanSt, feature),
89
256
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_PlayCircleOutline.default, {
90
257
  className: classes.icon
91
258
  })
@@ -96,7 +263,7 @@ const mapStateToProps = (state, props) => (
96
263
  // eslint-disable-line
97
264
  {
98
265
  editPeakSt: state.editPeak.present,
99
- thresSt: state.threshold.list[state.curve.curveIdx],
266
+ thresList: state.threshold.list,
100
267
  layoutSt: state.layout,
101
268
  shiftSt: state.shift,
102
269
  scanSt: state.scan,
@@ -104,10 +271,10 @@ const mapStateToProps = (state, props) => (
104
271
  decimalSt: state.submit.decimal,
105
272
  integrationSt: state.integration.present,
106
273
  multiplicitySt: state.multiplicity.present,
107
- allIntegrationSt: state.integration.past.concat(state.integration.present),
108
274
  waveLengthSt: state.wavelength,
109
275
  cyclicvoltaSt: state.cyclicvolta,
110
276
  curveSt: state.curve,
277
+ curveList: state.curve.listCurves,
111
278
  axesUnitsSt: state.axesUnits,
112
279
  detectorSt: state.detector,
113
280
  metaSt: state.meta
@@ -120,7 +287,7 @@ BtnSubmit.propTypes = {
120
287
  isIntensity: _propTypes.default.bool.isRequired,
121
288
  operation: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.bool]).isRequired,
122
289
  editPeakSt: _propTypes.default.object.isRequired,
123
- thresSt: _propTypes.default.object.isRequired,
290
+ thresList: _propTypes.default.array.isRequired,
124
291
  layoutSt: _propTypes.default.string.isRequired,
125
292
  shiftSt: _propTypes.default.object.isRequired,
126
293
  scanSt: _propTypes.default.object.isRequired,
@@ -128,10 +295,10 @@ BtnSubmit.propTypes = {
128
295
  decimalSt: _propTypes.default.number.isRequired,
129
296
  integrationSt: _propTypes.default.object.isRequired,
130
297
  multiplicitySt: _propTypes.default.object.isRequired,
131
- allIntegrationSt: _propTypes.default.object.isRequired,
132
298
  waveLengthSt: _propTypes.default.object.isRequired,
133
299
  cyclicvoltaSt: _propTypes.default.object.isRequired,
134
300
  curveSt: _propTypes.default.object,
301
+ curveList: _propTypes.default.array.isRequired,
135
302
  axesUnitsSt: _propTypes.default.object.isRequired,
136
303
  detectorSt: _propTypes.default.object.isRequired,
137
304
  metaSt: _propTypes.default.object.isRequired