From f221f79e6e18948fe4743ba8a6e670006409f449 Mon Sep 17 00:00:00 2001 From: Beate Quednau Date: Wed, 8 Nov 2023 15:12:58 +0100 Subject: [PATCH] Add more fields and functions to new sample form --- .../element_form_type_fields_and_modal.scss | 71 ++- .../elements/details/PrivateNoteElement.js | 4 +- .../samples/propertiesTab/SampleFormByType.js | 406 +++++++++++++++--- .../elementFormTypes/ElementStructures.js | 80 ++-- .../src/stores/mobx/ElementFormTypesStore.jsx | 66 ++- 5 files changed, 512 insertions(+), 115 deletions(-) diff --git a/app/assets/stylesheets/element_form_type_fields_and_modal.scss b/app/assets/stylesheets/element_form_type_fields_and_modal.scss index 0b43627087..8d801b8bc8 100644 --- a/app/assets/stylesheets/element_form_type_fields_and_modal.scss +++ b/app/assets/stylesheets/element_form_type_fields_and_modal.scss @@ -1,10 +1,3 @@ -.edit-form-fields { - position: absolute; - top: 6px; - right: 6px; - color: #fff; -} - [dialogas=form-editor].modal { width: fit-content; height: fit-content; @@ -126,6 +119,10 @@ width: 24%; } } +.grouped-fields-row.cols-1 { + margin-bottom: 0; +} + .grouped-fields-row.cols-2 .form-group { width: 49%; margin-right: 1%; @@ -168,6 +165,9 @@ div[class^="grouped-fields-row cols-"] { .form-group.column-size-small { width: 9%; } + .form-group.column-size-amount { + margin-bottom: -10px; + } .tab { margin-right: 1%; margin-bottom: 5px; @@ -275,6 +275,19 @@ div[class^="grouped-fields-row cols-"] { margin-right: 1%; } +.select-with-button div.css-2b097c-container { + width: calc(100% - 42px); +} + +.edit-form-fields.btn { + width: 37px; + height: 37px; + margin-left: 5px; + padding-left: 11px; + color: #fff; + font-size: 17px; +} + .section.toggle { padding: 0 10px 0 13px; } @@ -331,6 +344,8 @@ button.element-form-type-add-button { .grouped-fields-row { width: 100%; padding-left: 0; + margin-bottom: 0; + margin-right: 0; } div[class^="grouped-fields-row cols-"] { @@ -372,10 +387,21 @@ button.element-form-type-add-button { } } - .input-group { + .input-group, .input-group .form-control { z-index: 0; } + .input-group.molecule-name { + z-index: 10000; + } + + div.css-1pahdxg-control { + z-index: 10000; + } + div.css-26l3qy-menu { + z-index: 10002; + } + .input-group-addon { font-size: 13px; padding: 6px 8px; @@ -386,4 +412,33 @@ button.element-form-type-add-button { width: calc((100% / 3) - 3.5%); } } + + .selected-solvents { + display: flex; + flex-wrap: wrap; + width: 100%; + + input.form-control, span { + width: calc((100% - 34px - 2%) / 2); + margin-top: 12px; + margin-right: 1%; + } + + span { + font-weight: bold; + margin-bottom: -7px; + } + + input.form-control:disabled { + background-color: #eee; + color: #555; + } + + .delete-solvent { + width: 34px; + height: 34px; + padding-left: 9px; + margin-top: 12px; + } + } } diff --git a/app/packs/src/apps/mydb/elements/details/PrivateNoteElement.js b/app/packs/src/apps/mydb/elements/details/PrivateNoteElement.js index 78d9d64394..929c44361b 100644 --- a/app/packs/src/apps/mydb/elements/details/PrivateNoteElement.js +++ b/app/packs/src/apps/mydb/elements/details/PrivateNoteElement.js @@ -83,13 +83,13 @@ export default class PrivateNoteElement extends React.Component { } return ( -
+
Only you can see this note - } + } > Private Note diff --git a/app/packs/src/apps/mydb/elements/details/samples/propertiesTab/SampleFormByType.js b/app/packs/src/apps/mydb/elements/details/samples/propertiesTab/SampleFormByType.js index abb546bf0b..bd3371040f 100644 --- a/app/packs/src/apps/mydb/elements/details/samples/propertiesTab/SampleFormByType.js +++ b/app/packs/src/apps/mydb/elements/details/samples/propertiesTab/SampleFormByType.js @@ -5,11 +5,15 @@ import { } from 'react-bootstrap'; import Select from 'react-select3'; import CreatableSelect from 'react-select3/creatable'; +import VirtualizedSelect from 'react-virtualized-select'; import ElementFormTypeEditorModal from 'src/components/elementFormTypes/ElementFormTypeEditorModal'; import PrivateNoteElement from 'src/apps/mydb/elements/details/PrivateNoteElement'; import { metPreConv } from 'src/utilities/metricPrefix'; +import { useDrop } from 'react-dnd'; +import DragDropItemTypes from 'src/components/DragDropItemTypes'; import UserStore from 'src/stores/alt/stores/UserStore'; import * as FieldOptions from 'src/components/staticDropdownOptions/options'; +import { ionic_liquids } from 'src/components/staticDropdownOptions/ionic_liquids'; import { observer } from 'mobx-react'; import { StoreContext } from 'src/stores/mobx/RootStore'; @@ -26,17 +30,33 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, //console.log(unitsSystem); //console.log(FieldOptions); + const [{ isOver, canDrop }, dropRef] = useDrop({ + accept: [ + DragDropItemTypes.SAMPLE, + DragDropItemTypes.MOLECULE + ], + drop: (item, monitor) => { + const tagGroup = monitor.getItemType() === 'molecule' ? true : ''; + elementFormTypesStore.addSolventValues(element, tagGroup); + }, + collect: (monitor) => ({ + isOver: monitor.isOver(), + canDrop: monitor.canDrop(), + }), + }); + useEffect(() => { elementFormTypesStore.initFormByElementType('sample', sample); console.log(elementFormTypesStore.element); }, []); - const valueByType = (type, e) => { switch (type) { case 'text': case 'textarea': case 'textWithAddOn': + case 'textRangeWithAddOn': + case 'flashPoint': case 'system-defined': case 'formula-field': case 'subGroupWithAddOn': @@ -55,50 +75,110 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, } const handleNumericValue = (e, field, metric) => { - const inputField = e.target; - const { value, selectionStart } = inputField; + let { value, selectionStart } = e.target; const fieldValue = field.opt ? element[field.column][field.opt] : element[field.column]; - let newValue = value; const lastChar = value[selectionStart - 1] || ''; if (lastChar !== '' && !lastChar.match(/-|\d|\.|(,)/)) return 0; - const md = lastChar.match(/-|\d/); - const mc = lastChar.match(/\.|(,)/); + const decimal = lastChar.match(/-|\d/); + const comma = lastChar.match(/\.|(,)/); - if (mc && mc[1]) { - newValue = `${value.slice(0, selectionStart - 1)}.${value.slice(selectionStart)}`; + if (comma && comma[1]) { + value = `${value.slice(0, selectionStart - 1)}.${value.slice(selectionStart)}`; } - newValue = newValue.replace('--', ''); - newValue = newValue.replace('..', '.'); - const matchMinus = newValue.match(/\d+(-+)\d*/); - if (matchMinus && matchMinus[1]) newValue = newValue.replace(matchMinus[1], ''); + value = value.replace('--', ''); + value = value.replace('..', '.'); + const matchMinus = value.match(/\d+(-+)\d*/); + if (matchMinus && matchMinus[1]) { value = value.replace(matchMinus[1], '') }; - if (md || mc) { - return newValue; + if (decimal || comma) { + return value; } else { return metPreConv(fieldValue, 'n', metric);; } } + const handleNumRangeValue = (e) => { + let { value, selectionStart } = e.target; + const lastChar = value[selectionStart - 1] || ''; + let lower = ''; + let upper = ''; + + if (lastChar !== '' && !lastChar.match(/-|\d|\.| |(,)/)) { + const reg = new RegExp(lastChar, 'g'); + value = value.replace(reg, ''); + } else { + value = value.replace(/--/g, ''); + value = value.replace(/,/g, '.'); + value = value.replace(/\.+\./g, '.'); + value = value.replace(/ - /g, ' '); + } + + lower = value; + upper = value; + + const result = value.match(/[-.0-9]+|[0-9]/g); + if (result) { + const nums = result.filter(r => !isNaN(r)); + if (nums.length > 0) { + if (nums.length === 1) { + lower = nums.shift(); + upper = lower; + } else { + lower = nums.shift(); + upper = nums.pop(); + } + lower = Number.parseFloat(lower); + upper = Number.parseFloat(upper); + } + } + + return { lower, upper, value }; + } + const handleFieldChanged = (field, type) => (e) => { let value = e === null ? '' : valueByType(type, e); const { unit, metric } = unitAndMeticByField(field); - // if element form type => structure wechseln - if (field.prefixes && field.precision) { + if (field == 'element_form_type_id') { + elementFormTypesStore.changeElementFormType(value); + } else if (field.prefixes && field.precision) { value = metPreConv(value, metric, 'n'); const numericValue = handleNumericValue(e, field, metric); elementFormTypesStore.changeNumericValues(field, value, unit, metric, numericValue); + } else if (type == 'textRangeWithAddOn') { + const { lower, upper, value } = handleNumRangeValue(e); + elementFormTypesStore.changeNumRangeValues(field, lower, upper, unit, metric, value); + } else if (type == 'flashPoint') { + elementFormTypesStore.changeFlashPointValues(field, value, unit, metric); } else { - console.log(field); elementFormTypesStore.changeElementValues(field, value); } } + const changeSolventRatio = (solvent) => (e) => { + solvent.ratio = e.target.value; + elementFormTypesStore.changeSolventValues(solvent); + } + + const deleteSolvent = (solvent) => { + elementFormTypesStore.deleteSolvent(solvent); + } + + const createDefaultSolvents = (e) => { + const solvent = e.value; + const smiles = solvent.smiles; + elementFormTypesStore.fetchMoleculeBySmiles(smiles, solvent); + console.log(elementFormTypesStore.solventErrorMessage); + }; + const fieldHasFocusAndBlurOptions = (field, type) => { - const columns = ['molecular_mass', 'molarity_value', 'density', 'purity']; + const columns = [ + 'molecular_mass', 'molarity_value', 'density', 'purity', + 'melting_point', 'boiling_point' + ]; return type == 'amount' || columns.includes(field.column) ? true : false; } @@ -106,7 +186,12 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, if (!fieldHasFocusAndBlurOptions(field, type)) { return null; } const { unit, metric } = unitAndMeticByField(field); - const numericValue = handleNumericValue(e, field, metric); + let numericValue = handleNumericValue(e, field, metric); + + if (type == 'textRangeWithAddOn') { + numericValue = e.target.value.trim().replace(/ – /g, ' '); + } + elementFormTypesStore.changeActiveUnits(field.key, unit, metric, numericValue); elementFormTypesStore.changeElementFocus(field.key, true); } @@ -117,13 +202,36 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, elementFormTypesStore.changeElementFocus(field.key, false); } - const changeUnit = (options, key, prefixes) => (e) => { + const kelvinToCelsius = (value) => value - 273.15; + const celsiusToFahrenheit = (value) => ((value * 9) / 5) + 32; + const fahrenheitToKelvin = (value) => (((value - 32) * 5) / 9) + 273.15; + + const calculateTemperatures = (activeUnit, value) => { + if (value == '') { return ''; } + + switch (activeUnit) { + case '°C': + return celsiusToFahrenheit(value); + case '°F': + return fahrenheitToKelvin(value); + case 'K': + return kelvinToCelsius(value); + } + } + + const changeUnit = (options, field) => (e) => { let activeUnit = e.target.innerHTML; let activeUnitIndex = options.findIndex((f) => { return f.value == activeUnit }); let nextUnitIndex = activeUnitIndex === options.length - 1 ? 0 : activeUnitIndex + 1; let nextUnit = options[nextUnitIndex].value; - let metric = prefixes[nextUnitIndex]; - elementFormTypesStore.changeActiveUnits(key, nextUnit, metric); + let metric = field.prefixes[nextUnitIndex]; + let value = ''; + if (field.type == 'flashPoint') { + value = calculateTemperatures(activeUnit, element[field.column][field.opt].value); + elementFormTypesStore.changeFlashPointValues(field, value, nextUnit, metric); + } else { + elementFormTypesStore.changeActiveUnits(field.key, nextUnit, metric, value); + } } const unitAndMeticByField = (field) => { @@ -140,20 +248,26 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, const { focused } = isFieldFocused(field, ''); if (field.prefixes && field.precision) { - let { metric, acitveUnitValue } = unitAndMeticByField(field); + const { metric, acitveUnitValue } = unitAndMeticByField(field); if (focused) { - console.log('focused', value, acitveUnitValue); value = acitveUnitValue ? acitveUnitValue : metPreConv(value, 'n', metric) || ''; } else { - console.log('notFocused', value); value = metPreConv(value, 'n', metric).toPrecision(field.precision); } + + value = value === 'NaN' ? 0.0.toPrecision(field.precision) : value; } return value; } + const numRangeValue = (field) => { + const { focused } = isFieldFocused(field, ''); + const { acitveUnitValue } = unitAndMeticByField(field); + return focused && acitveUnitValue ? acitveUnitValue : element[`${field.column}_display`]; + } + const isFieldFocused = (field, amountKey) => { const focusIndex = elementHasFocus.findIndex((e) => { return Object.keys(e).indexOf(field.key) != -1 }); let focusedKeys = []; @@ -175,23 +289,25 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, let value = options.find((o) => { return element.element_form_type_id && o.value == element.element_form_type_id }); return ( - + Element form type - + +
); } @@ -202,9 +318,12 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, if (field.conditions) { Object.entries(field.conditions).map(([key, value]) => { const isMolarityDensity = ['has_molarity', 'has_density'].includes(key); + const isPolymer = (element.molfile || '').indexOf(' R# ') !== -1; if (isMolarityDensity && !element['has_molarity'] && !element['has_density']) { notAllowed.push(key); + } else if (key == 'isPolymer' && isPolymer != value) { + notAllowed.push(key); } else if (element[key] !== undefined && element[key] != value && !isMolarityDensity) { notAllowed.push(key); } @@ -216,6 +335,21 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, return notAllowed; } + const infoButton = (field) => { + if (!field.description) { return null; } + + return ( + {field.description} + } + > + + + ); + } + const numericInput = (field, type) => { let value = valueOrCalculateNumericValue(field); @@ -236,17 +370,21 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, ); } - const addonButton = (field, color) => { + const addonButton = (field, color, elementUnit = '') => { let addon = ({field.addon}); if (field.option_layers) { const options = optionsForSelect(field); const { unit } = unitAndMeticByField(field); + const fieldUnit = elementUnit && !unit ? elementUnit : unit; addon = ( - ); @@ -254,7 +392,57 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, return addon; } + const flashPointInput = (field, type) => { + const column = element[field.column][field.opt]; + const unit = column ? column.unit : ''; + + return ( + + {field.label} +
+ + + {addonButton(field, 'green', unit)} + +
+
+ ); + } + + const textRangeWithAddOnInput = (field, type) => { + const isDisabled = allowToDisplayField(field).length >= 1 ? true : false; + const value = numRangeValue(field); + + return ( + + + {field.label} + {infoButton(field)} + + + + {field.addon} + + + ); + } + const textWithAddOnInput = (field, type, tabOrAmount = false, color = 'green') => { + if (field.conditions && field.conditions.decoupled && !element.decoupled) { return null; } + let label = ({field.label}); const value = valueOrCalculateNumericValue(field); const className = type == 'amount' ? 'column-size-amount' : `column-size-${field.column_size}`; @@ -326,27 +514,128 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, name={field.column} key={`${field.key}-${index}`} checked={element[field.column]} - onChange={handleFieldChanged(field.column, type)} + onChange={handleFieldChanged(field, type)} > {field.label} ); } + const solventRowHeader = () => { + return ( +
+ Label + Ratio +
+ ); + } + + const solventRow = (solvent, i) => { + return ( +
+ + + +
+ ); + } + + const selectedSolvents = (index) => { + const elementSolvents = element.solvent; + let solvents = []; + + if (elementSolvents && elementSolvents.length == 0) { return solvents; } + + solvents.push(solventRowHeader()); + + elementSolvents.map((solvent, i) => { + solvents.push(solventRow(solvent, index + i)); + }); + return solvents; + } + const optionsForSelect = (field) => { let options = []; let systemOptions = unitsSystem.fields.find((u) => { return u.field === field.option_layers }); options = systemOptions ? systemOptions.units : FieldOptions[field.option_layers]; + if (options && options[0] && options[0].value !== '') { + options.unshift({ label: '', value: '' }); + } return options; } + const ionicLiquidOptions = (defaultOptions) => { + return Object.keys(ionic_liquids) + .reduce((solvents, ionicLiquid) => solvents.concat({ + label: ionicLiquid, + value: { + external_label: ionicLiquid, + smiles: ionic_liquids[ionicLiquid], + density: 1.0 + } + }), defaultOptions); + } + + const dragAndDropStyle = () => { + let style = { width: '100%' }; + if (canDrop) { + style.borderStyle = 'dashed'; + style.padding = '0 10px'; + } + if (isOver && canDrop) { + style.borderColor = '#337ab7'; + } + return style; + } + + const solventSelectInput = (field, type, index) => { + const defaultOptions = optionsForSelect(field); + const options = ionicLiquidOptions(defaultOptions); + const solvents = selectedSolvents(index); + + return ( +
+ + {field.label} +
+ +
+ {solvents} +
+
+ ); + } + const selectInput = (field, type, index) => { - let options = optionsForSelect(field); - let columnValue = field.opt ? element[field.column][field.opt] : element[field.column]; - let fieldValue = field.opt ? field : field.column; - let value = options.find((o) => { return o.value == columnValue }); + const options = optionsForSelect(field); + const columnValue = field.opt ? element[field.column][field.opt] : element[field.column]; + const value = options.find((o) => { return o.value == columnValue }); return ( @@ -358,7 +647,7 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, options={options} value={value} disabled={!element.can_update} - onChange={handleFieldChanged(fieldValue, type)} + onChange={handleFieldChanged(field, type)} />
@@ -382,14 +671,14 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, {field.label}
- + showStructureEditor(!element.can_update)} /> @@ -420,6 +709,7 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, const textInput = (field, type) => { let value = valueOrCalculateNumericValue(field); + if (field.conditions && field.conditions.decoupled && !element.decoupled) { return null; } return ( @@ -483,7 +773,9 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, case 'select': fields.push(selectInput(field, 'select', index)); break; - // case 'solventSelect': + case 'solventSelect': + fields.push(solventSelectInput(field, 'select', index)); + break; case 'checkbox': fields.push(checkboxInput(field, 'checkbox', index)); break; @@ -494,6 +786,12 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, case 'numeric': fields.push(numericInput(field, 'numeric')); break; + case 'textRangeWithAddOn': + fields.push(textRangeWithAddOnInput(field, 'textRangeWithAddOn')); + break; + case 'flashPoint': + fields.push(flashPointInput(field, 'flashPoint')); + break; default: fields.push(textInput(field, 'text')); } @@ -531,9 +829,11 @@ const SampleFormByType = ({ sample, parent, customizableField, enableDecoupled, section.rows.map((row, j) => { let rowClassName = `grouped-fields-row cols-${row.cols}`; let rowFields = []; + if (row.visible !== undefined && !row.visible) { return; } row.fields.map((field) => { if (field.opt == 'cas') { return; } + if (field.visible !== undefined && !field.visible) { return; } let subFields = []; if (field.sub_fields && field.type == 'tab') { diff --git a/app/packs/src/components/elementFormTypes/ElementStructures.js b/app/packs/src/components/elementFormTypes/ElementStructures.js index 00a7525a86..71cb13a18e 100644 --- a/app/packs/src/components/elementFormTypes/ElementStructures.js +++ b/app/packs/src/components/elementFormTypes/ElementStructures.js @@ -31,12 +31,12 @@ export default { { cols: 4, // felder pro reihe visible: true, - key: 'iupac_name_stereo_decoupled', + key: 'molecule_name_stereo_decoupled', fields: [ { - column: 'iupac_name', // db feld + column: 'molecule_name', // db feld column_size: 'column', - key: 'iupac_name', + key: 'molecule_name', label: 'Molecule', type: 'moleculeSelect', // spezielles select visible: true, // für modal zur auswahl, was angezeigt werden soll @@ -166,7 +166,7 @@ export default { setterNewValue: 'setMolecularMass', conditions: { decoupled: true, - } + }, }, { column: 'sum_formula', @@ -180,7 +180,7 @@ export default { description: '', conditions: { decoupled: true, - } + }, }, ], }, @@ -214,7 +214,7 @@ export default { setterNewValue: 'setAmount', conditions: { can_update: true, - } + }, }, { column: 'amount_l', @@ -233,7 +233,7 @@ export default { has_density: true, has_molarity: true, contains_residues: false, - } + }, }, { column: 'amount_mol', @@ -249,7 +249,7 @@ export default { setterNewValue: 'setAmount', conditions: { can_update: true, - } + }, }, { column: 'defined_part_amount', @@ -265,7 +265,7 @@ export default { setterNewValue: 'setAmount', conditions: { contains_residues: true, - } + }, }, ], }, @@ -292,7 +292,7 @@ export default { setterNewValue: 'setDensity', conditions: { can_update: true, - } + }, }, { column: 'molarity_value', @@ -310,7 +310,7 @@ export default { setterNewValue: 'setMolarity', conditions: { can_update: true, - } + }, }, ], }, @@ -328,7 +328,7 @@ export default { description: '', conditions: { can_update: true, - } + }, }, ], }, @@ -349,24 +349,34 @@ export default { column_size: 'column', key: 'melting_point', label: 'Melting point', - type: 'textWithAddOn', + type: 'textRangeWithAddOn', addon: '°C', visible: true, default: '', required: false, - description: '', + setterNewValue: 'updateRange', + description: 'Use space-separated value to input a Temperature range', + conditions: { + can_update: true, + isPolymer: false, + }, }, { column: 'boiling_point', column_size: 'column', key: 'boiling_point', label: 'Boiling point', - type: 'textWithAddOn', + type: 'textRangeWithAddOn', addon: '°C', visible: true, default: '', required: false, - description: '', + setterNewValue: 'updateRange', + description: 'Use space-separated value to input a Temperature range', + conditions: { + can_update: true, + isPolymer: false, + }, }, { column: 'xref', @@ -374,9 +384,10 @@ export default { opt: 'flash_point', key: 'xref_flash_point', label: 'Flash Point', - type: 'system-defined', // hat noch berechnungen (numeric input) + type: 'flashPoint', // hat noch berechnungen (numeric input) option_layers: 'temperatureOptions', addon: '°C', + prefixes: ['n'], visible: true, default: '', required: false, @@ -455,6 +466,7 @@ export default { key: 'solvent', label: 'Solvent', type: 'solventSelect', // spezial select mit molecule dropdown und ausgewählten Feldern darunter + option_layers: 'defaultMultiSolventsSmilesOptions', visible: true, default: 'Select solvents or drag-n-drop molecules from the sample list', required: false, @@ -462,40 +474,6 @@ export default { }, ], }, - // { - // cols: 3, - // visible: true, - // key: 'solvent_label_solvent_ration_trash', - // fields: [ - // { - // column: 'solvent', - // opt: 'label', - // key: 'solvent_label', - // label: 'Label', - // type: 'text', // disabled - // visible: true, - // default: '', - // required: false, - // description: '', - // }, - // { - // column: 'solvent', - // opt: 'ratio', - // key: 'solvent_ratio', - // label: 'Ratio', - // type: 'text', // nur zahlen - // visible: true, - // default: '', - // required: false, - // description: '', - // }, - // { - // column: 'solvent', - // label: '', - // type: 'trash', // ausgewähltes Molecule löschen - // }, - // ], - // }, ], }, { diff --git a/app/packs/src/stores/mobx/ElementFormTypesStore.jsx b/app/packs/src/stores/mobx/ElementFormTypesStore.jsx index 9ecc6a8594..45ae87298a 100644 --- a/app/packs/src/stores/mobx/ElementFormTypesStore.jsx +++ b/app/packs/src/stores/mobx/ElementFormTypesStore.jsx @@ -4,6 +4,8 @@ import { cloneDeep } from 'lodash'; import ElementFormTypesFetcher from 'src/fetchers/ElementFormTypesFetcher'; import MoleculesFetcher from 'src/fetchers/MoleculesFetcher'; +import Molecule from 'src/models/Molecule'; +import Sample from 'src/models/Sample'; import ElementStructures from 'src/components/elementFormTypes/ElementStructures'; const ElementFormType = types.model({ @@ -35,10 +37,11 @@ export const ElementFormTypesStore = types element: types.optional(types.frozen({}), {}), element_structure: types.optional(types.frozen({}), {}), element_type_options: types.optional(types.array(types.frozen({})), []), - error_message: types.optional(types.string, ""), + error_message: types.optional(types.string, ''), show_success_message: types.optional(types.boolean, false), active_units: types.optional(types.array(types.frozen({})), []), element_has_focus: types.optional(types.array(types.frozen({})), []), + solvent_error_message: types.optional(types.string, ''), }) .actions(self => ({ load: flow(function* loadElementFormTypes() { @@ -83,6 +86,19 @@ export const ElementFormTypesStore = types } return result }), + fetchMoleculeBySmiles: flow(function* fetchMoleculeBySmiles(smiles, solvent) { + let result = yield MoleculesFetcher.fetchBySmi(smiles); + if (result) { + const molecule = new Molecule(result); + const moleculeDensity = molecule.density; + const solventDensity = solvent.density || 1; + + molecule.density = (moleculeDensity && moleculeDensity > 0) || solventDensity; + self.addSolventValues(molecule, ''); + } else { + self.solvent_error_message = 'Failed to fetch molecule data.' + } + }), updateMoleculeNames: flow(function* updateMoleculeNames(newMoleculeName) { if (!self.element.molecule) { return null; } @@ -169,6 +185,13 @@ export const ElementFormTypesStore = types } self.element = element; }, + changeElementFormType(elementFormTypeId) { + const element = cloneDeep(self.element); + + self.fetchById(elementFormTypeId); + element.element_form_type_id = elementFormTypeId; + self.element = element; + }, changeNumericValues(field, value, unit, metric, numericValue) { const element = cloneDeep(self.element); const values = { unit: field.unit, value: value, metricPrefix: metric }; @@ -186,6 +209,46 @@ export const ElementFormTypesStore = types self.element = element; self.changeActiveUnits(field.key, unit, metric, numericValue); }, + changeNumRangeValues(field, lower, upper, unit, metric, numericValue) { + const element = cloneDeep(self.element); + element.updateRange(field.column, lower, upper); + self.element = element; + + if (unit && metric) { + self.changeActiveUnits(field.key, unit, metric, numericValue); + } + }, + changeFlashPointValues(field, value, unit, metric) { + const element = cloneDeep(self.element); + const values = { value: value, unit: unit }; + element[field.column][field.opt] = values; + self.element = element; + self.changeActiveUnits(field.key, unit, metric, value); + }, + addSolventValues(molecule, tagGroup) { + let splitSample; + let element = cloneDeep(self.element); + + if (molecule instanceof Molecule || false) { + // Create new Sample with counter + splitSample = Sample.buildNew(molecule, element.collection_id, tagGroup); + } else if (molecule instanceof Sample) { + splitSample = element.buildChild(); + } + + element.addSolvent(splitSample) + self.element = element + }, + changeSolventValues(solvent) { + const element = cloneDeep(self.element); + element.updateSolvent(solvent); + self.element = element; + }, + deleteSolvent(solvent) { + const element = cloneDeep(self.element); + element.deleteSolvent(solvent) + self.element = element; + }, toggleModalMinimized() { self.modal_minimized = !self.modal_minimized; }, @@ -258,4 +321,5 @@ export const ElementFormTypesStore = types get showSuccessMessage() { return self.show_success_message }, get activeUnits() { return values(self.active_units) }, get ElementHasFocus() { return values(self.element_has_focus) }, + get solventErrorMessage() { return self.solvent_error_message }, }));