From b5dafc108410a5032b777361a2bfc9156602dcb9 Mon Sep 17 00:00:00 2001 From: adambasha0 Date: Wed, 6 Nov 2024 09:31:23 +0000 Subject: [PATCH 1/4] feat: conversion field in reaction scheme for product materials --- app/api/entities/reaction_material_entity.rb | 1 + app/api/helpers/report_helpers.rb | 2 + app/models/reaction.rb | 2 + app/models/reactions_product_sample.rb | 25 +++--- .../reactions_purification_solvent_sample.rb | 25 +++--- app/models/reactions_reactant_sample.rb | 25 +++--- app/models/reactions_sample.rb | 25 +++--- app/models/reactions_solvent_sample.rb | 25 +++--- .../reactions_starting_material_sample.rb | 25 +++--- .../details/NumeralInputWithUnitsCompo.js | 2 +- .../details/reactions/ReactionDetails.js | 18 ++++ .../details/reactions/schemeTab/Material.js | 83 +++++++++++++++---- .../reactions/schemeTab/MaterialGroup.js | 48 +++++++++-- .../schemeTab/MaterialGroupContainer.js | 9 +- .../schemeTab/ReactionDetailsScheme.js | 46 +++++++++- .../src/components/common/ToggleButton.js | 6 +- app/packs/src/models/Sample.js | 1 + app/usecases/reactions/update_materials.rb | 4 +- ...dd_conversion_rate_to_reactions_samples.rb | 5 ++ db/schema.rb | 3 +- lib/import/import_collections.rb | 1 + lib/import/import_json.rb | 7 +- lib/reporter/docx/detail_reaction.rb | 3 +- spec/factories/reactions_samples.rb | 1 + .../components/common/ToggleButton.spec.js | 2 + 25 files changed, 293 insertions(+), 101 deletions(-) create mode 100644 db/migrate/20240917085816_add_conversion_rate_to_reactions_samples.rb diff --git a/app/api/entities/reaction_material_entity.rb b/app/api/entities/reaction_material_entity.rb index 7f9aa42c0d..f9c9d4d326 100644 --- a/app/api/entities/reaction_material_entity.rb +++ b/app/api/entities/reaction_material_entity.rb @@ -17,5 +17,6 @@ class ReactionMaterialEntity < ApplicationEntity expose! :waste expose! :gas_type expose! :gas_phase_data + expose! :conversion_rate end end diff --git a/app/api/helpers/report_helpers.rb b/app/api/helpers/report_helpers.rb index 1e24dc2a2a..63fd3c38dd 100644 --- a/app/api/helpers/report_helpers.rb +++ b/app/api/helpers/report_helpers.rb @@ -614,6 +614,7 @@ def build_sql_reaction_sample(columns, c_id, ids, checkedAll = false) # reactions_sample: equivalent: ['r_s.equivalent', '"r eq"', 10], reference: ['r_s.reference', '"r ref"', 10], + conversion_rate: ['r_s.conversion_rate', '"r conversion rate"', 10], }, analysis: { name: ['anac."name"', '"name"', 10], @@ -723,6 +724,7 @@ def force_molfile_selection equivalent reference type + conversion_rate ], sample: %i[ sample_svg_file diff --git a/app/models/reaction.rb b/app/models/reaction.rb index a300bcee65..a3cb52c747 100644 --- a/app/models/reaction.rb +++ b/app/models/reaction.rb @@ -36,6 +36,8 @@ # variations :jsonb # plain_text_description :text # plain_text_observation :text +# gaseous :boolean default(FALSE) +# vessel_size :jsonb # # Indexes # diff --git a/app/models/reactions_product_sample.rb b/app/models/reactions_product_sample.rb index 50d1beebf5..eb98e45fef 100644 --- a/app/models/reactions_product_sample.rb +++ b/app/models/reactions_product_sample.rb @@ -2,17 +2,20 @@ # # Table name: reactions_samples # -# id :integer not null, primary key -# reaction_id :integer -# sample_id :integer -# reference :boolean -# equivalent :float -# position :integer -# type :string -# deleted_at :datetime -# waste :boolean default(FALSE) -# coefficient :float default(1.0) -# show_label :boolean default(FALSE), not null +# id :integer not null, primary key +# reaction_id :integer +# sample_id :integer +# reference :boolean +# equivalent :float +# position :integer +# type :string +# deleted_at :datetime +# waste :boolean default(FALSE) +# coefficient :float default(1.0) +# show_label :boolean default(FALSE), not null +# gas_type :integer default("off") +# gas_phase_data :jsonb +# conversion_rate :float # # Indexes # diff --git a/app/models/reactions_purification_solvent_sample.rb b/app/models/reactions_purification_solvent_sample.rb index aa2c1c9faf..f1a81ee41b 100644 --- a/app/models/reactions_purification_solvent_sample.rb +++ b/app/models/reactions_purification_solvent_sample.rb @@ -2,17 +2,20 @@ # # Table name: reactions_samples # -# id :integer not null, primary key -# reaction_id :integer -# sample_id :integer -# reference :boolean -# equivalent :float -# position :integer -# type :string -# deleted_at :datetime -# waste :boolean default(FALSE) -# coefficient :float default(1.0) -# show_label :boolean default(FALSE), not null +# id :integer not null, primary key +# reaction_id :integer +# sample_id :integer +# reference :boolean +# equivalent :float +# position :integer +# type :string +# deleted_at :datetime +# waste :boolean default(FALSE) +# coefficient :float default(1.0) +# show_label :boolean default(FALSE), not null +# gas_type :integer default("off") +# gas_phase_data :jsonb +# conversion_rate :float # # Indexes # diff --git a/app/models/reactions_reactant_sample.rb b/app/models/reactions_reactant_sample.rb index 958da1b44c..1cc9d8e1fb 100644 --- a/app/models/reactions_reactant_sample.rb +++ b/app/models/reactions_reactant_sample.rb @@ -2,17 +2,20 @@ # # Table name: reactions_samples # -# id :integer not null, primary key -# reaction_id :integer -# sample_id :integer -# reference :boolean -# equivalent :float -# position :integer -# type :string -# deleted_at :datetime -# waste :boolean default(FALSE) -# coefficient :float default(1.0) -# show_label :boolean default(FALSE), not null +# id :integer not null, primary key +# reaction_id :integer +# sample_id :integer +# reference :boolean +# equivalent :float +# position :integer +# type :string +# deleted_at :datetime +# waste :boolean default(FALSE) +# coefficient :float default(1.0) +# show_label :boolean default(FALSE), not null +# gas_type :integer default("off") +# gas_phase_data :jsonb +# conversion_rate :float # # Indexes # diff --git a/app/models/reactions_sample.rb b/app/models/reactions_sample.rb index e16ec9cc10..ffc902dacc 100644 --- a/app/models/reactions_sample.rb +++ b/app/models/reactions_sample.rb @@ -2,17 +2,20 @@ # # Table name: reactions_samples # -# id :integer not null, primary key -# reaction_id :integer -# sample_id :integer -# reference :boolean -# equivalent :float -# position :integer -# type :string -# deleted_at :datetime -# waste :boolean default(FALSE) -# coefficient :float default(1.0) -# show_label :boolean default(FALSE), not null +# id :integer not null, primary key +# reaction_id :integer +# sample_id :integer +# reference :boolean +# equivalent :float +# position :integer +# type :string +# deleted_at :datetime +# waste :boolean default(FALSE) +# coefficient :float default(1.0) +# show_label :boolean default(FALSE), not null +# gas_type :integer default("off") +# gas_phase_data :jsonb +# conversion_rate :float # # Indexes # diff --git a/app/models/reactions_solvent_sample.rb b/app/models/reactions_solvent_sample.rb index 947359f815..97c621b4e9 100644 --- a/app/models/reactions_solvent_sample.rb +++ b/app/models/reactions_solvent_sample.rb @@ -2,17 +2,20 @@ # # Table name: reactions_samples # -# id :integer not null, primary key -# reaction_id :integer -# sample_id :integer -# reference :boolean -# equivalent :float -# position :integer -# type :string -# deleted_at :datetime -# waste :boolean default(FALSE) -# coefficient :float default(1.0) -# show_label :boolean default(FALSE), not null +# id :integer not null, primary key +# reaction_id :integer +# sample_id :integer +# reference :boolean +# equivalent :float +# position :integer +# type :string +# deleted_at :datetime +# waste :boolean default(FALSE) +# coefficient :float default(1.0) +# show_label :boolean default(FALSE), not null +# gas_type :integer default("off") +# gas_phase_data :jsonb +# conversion_rate :float # # Indexes # diff --git a/app/models/reactions_starting_material_sample.rb b/app/models/reactions_starting_material_sample.rb index cc73df3429..99eda97344 100644 --- a/app/models/reactions_starting_material_sample.rb +++ b/app/models/reactions_starting_material_sample.rb @@ -2,17 +2,20 @@ # # Table name: reactions_samples # -# id :integer not null, primary key -# reaction_id :integer -# sample_id :integer -# reference :boolean -# equivalent :float -# position :integer -# type :string -# deleted_at :datetime -# waste :boolean default(FALSE) -# coefficient :float default(1.0) -# show_label :boolean default(FALSE), not null +# id :integer not null, primary key +# reaction_id :integer +# sample_id :integer +# reference :boolean +# equivalent :float +# position :integer +# type :string +# deleted_at :datetime +# waste :boolean default(FALSE) +# coefficient :float default(1.0) +# show_label :boolean default(FALSE), not null +# gas_type :integer default("off") +# gas_phase_data :jsonb +# conversion_rate :float # # Indexes # diff --git a/app/packs/src/apps/mydb/elements/details/NumeralInputWithUnitsCompo.js b/app/packs/src/apps/mydb/elements/details/NumeralInputWithUnitsCompo.js index e1bc89da43..96afd1faa7 100644 --- a/app/packs/src/apps/mydb/elements/details/NumeralInputWithUnitsCompo.js +++ b/app/packs/src/apps/mydb/elements/details/NumeralInputWithUnitsCompo.js @@ -124,7 +124,7 @@ export default class NumeralInputWithUnitsCompo extends Component { togglePrefix(currentUnit) { const units = ['TON/h', 'TON/m', 'TON/s', '°C', '°F', 'K', 'h', 'm', 's']; - const excludedUnits = ['ppm', 'TON']; + const excludedUnits = ['ppm', 'TON', '%']; const { onMetricsChange, unit } = this.props; if (units.includes(currentUnit)) { // eslint-disable-next-line no-unused-expressions diff --git a/app/packs/src/apps/mydb/elements/details/reactions/ReactionDetails.js b/app/packs/src/apps/mydb/elements/details/reactions/ReactionDetails.js index 165ea1f7cc..d81ea86e11 100644 --- a/app/packs/src/apps/mydb/elements/details/reactions/ReactionDetails.js +++ b/app/packs/src/apps/mydb/elements/details/reactions/ReactionDetails.js @@ -513,6 +513,24 @@ export default class ReactionDetails extends Component { render() { const { reaction, visible, activeTab } = this.state; this.updateReactionVesselSize(reaction); + const schemeTitle = reaction && activeTab === 'scheme' ? ( +
+
+ +
+
+ ) : 'Scheme'; const tabContentsMap = { scheme: ( diff --git a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js index ad18b38d98..34e6223b8f 100644 --- a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js +++ b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js @@ -120,6 +120,7 @@ class Material extends Component { this.gasFieldsUnitsChanged = this.gasFieldsUnitsChanged.bind(this); this.handleCoefficientChange = this.handleCoefficientChange.bind(this); this.debounceHandleAmountUnitChange = debounce(this.handleAmountUnitChange, 500); + this.yieldOrConversionRate = this.yieldOrConversionRate.bind(this); } handleMaterialClick(sample) { @@ -242,34 +243,65 @@ class Material extends Component { return result > 1 ? '100%' : `${(result * 100).toFixed(0)}%`; } - equivalentOrYield(material) { - const { reaction, materialGroup } = this.props; - if (materialGroup === 'products') { - const refMaterial = reaction.getReferenceMaterial(); - let calculateYield = material.equivalent; - if (material.gas_type === 'gas') { - calculateYield = this.recalculateYieldForGasProduct(material, reaction); - } else if (reaction.hasPolymers()) { - calculateYield = `${((material.equivalent || 0) * 100).toFixed(0)}%`; - } else if (refMaterial && (refMaterial.decoupled || material.decoupled)) { - calculateYield = 'n.a.'; - } else if (material.purity < 1 && material.equivalent > 1) { - calculateYield = `${((material.purity / 100 * (material.amount_g * 1000)) * 100).toFixed(1)}%`; - } else { - calculateYield = `${((material.equivalent <= 1 ? material.equivalent || 0 : 1) * 100).toFixed(0)}%`; - } + calculateYield(material, reaction) { + const refMaterial = reaction.getReferenceMaterial(); + let calculateYield = material.equivalent; + if (material.gas_type === 'gas') { + calculateYield = this.recalculateYieldForGasProduct(material, reaction); + } else if (reaction.hasPolymers()) { + calculateYield = `${((material.equivalent || 0) * 100).toFixed(0)}%`; + } else if (refMaterial && (refMaterial.decoupled || material.decoupled)) { + calculateYield = 'n.a.'; + } else if (material.purity < 1 && material.equivalent > 1) { + calculateYield = `${((material.purity / 100 * (material.amount_g * 1000)) * 100).toFixed(1)}%`; + } else { + calculateYield = `${((material.equivalent <= 1 ? material.equivalent || 0 : 1) * 100).toFixed(0)}%`; + } + return calculateYield; + } + + conversionRateField(material) { + const { reaction } = this.props; + const condition = material.conversion_rate / 100 > 1; + const allowedConversionRateValue = material.conversion_rate && condition + ? 100 : material.conversion_rate; + return ( +
+ this.handleConversionRateChange(e)} + /> +
+ ); + } + + yieldOrConversionRate(material) { + const { reaction, displayYieldField } = this.props; + if (displayYieldField) { return (
); } + return this.conversionRateField(material); + } + + equivalentOrYield(material) { + const { materialGroup } = this.props; + if (materialGroup === 'products') { + return this.yieldOrConversionRate(material); + } return ( )); @@ -76,6 +79,8 @@ function MaterialGroup({ addDefaultSolvent={addDefaultSolvent} switchEquiv={switchEquiv} lockEquivColumn={lockEquivColumn} + displayYieldField={displayYieldField} + switchYield={switchYield} /> ); } @@ -106,7 +111,7 @@ function SwitchEquivButton(lockEquivColumn, switchEquiv) { function GeneralMaterialGroup({ contents, materialGroup, showLoadingColumn, reaction, addDefaultSolvent, - switchEquiv, lockEquivColumn + switchEquiv, lockEquivColumn, displayYieldField, switchYield }) { const isReactants = materialGroup === 'reactants'; let headers = { @@ -154,9 +159,32 @@ function GeneralMaterialGroup({ ); } + const yieldConversionRateFields = () => { + const conversionText = 'Click to switch to conversion field.' + + ' The conversion will not be displayed as part of the reaction scheme'; + const yieldText = 'Click to switch to yield field.' + + ' The yield will be displayed as part of the reaction scheme'; + return ( +
+ +
+ ); + }; + if (materialGroup === 'products') { headers.group = 'Products'; - headers.eq = 'Yield'; + headers.eq = yieldConversionRateFields(); } const refTHead = (materialGroup !== 'products') ? headers.ref : null; @@ -306,7 +334,9 @@ MaterialGroup.propTypes = { dropMaterial: PropTypes.func.isRequired, dropSample: PropTypes.func.isRequired, switchEquiv: PropTypes.func.isRequired, - lockEquivColumn: PropTypes.bool + lockEquivColumn: PropTypes.bool, + displayYieldField: PropTypes.bool, + switchYield: PropTypes.func.isRequired }; GeneralMaterialGroup.propTypes = { @@ -316,7 +346,9 @@ GeneralMaterialGroup.propTypes = { addDefaultSolvent: PropTypes.func.isRequired, contents: PropTypes.arrayOf(PropTypes.shape).isRequired, switchEquiv: PropTypes.func.isRequired, - lockEquivColumn: PropTypes.bool + lockEquivColumn: PropTypes.bool, + displayYieldField: PropTypes.bool, + switchYield: PropTypes.func.isRequired }; SolventsMaterialGroup.propTypes = { @@ -328,12 +360,14 @@ SolventsMaterialGroup.propTypes = { MaterialGroup.defaultProps = { showLoadingColumn: false, - lockEquivColumn: false + lockEquivColumn: false, + displayYieldField: true }; GeneralMaterialGroup.defaultProps = { showLoadingColumn: false, - lockEquivColumn: false + lockEquivColumn: false, + displayYieldField: true }; export { MaterialGroup, GeneralMaterialGroup, SolventsMaterialGroup }; diff --git a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/MaterialGroupContainer.js b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/MaterialGroupContainer.js index d90e7c7bfc..942d7574f1 100644 --- a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/MaterialGroupContainer.js +++ b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/MaterialGroupContainer.js @@ -55,7 +55,8 @@ class MaterialGroupContainer extends Component { const { materials, materialGroup, showLoadingColumn, headIndex, isOver, canDrop, connectDropTarget, - deleteMaterial, onChange, reaction, dropSample, dropMaterial, switchEquiv, lockEquivColumn + deleteMaterial, onChange, reaction, dropSample, dropMaterial, switchEquiv, lockEquivColumn, + displayYieldField, switchYield, } = this.props; let className=''; if (canDrop) { @@ -80,6 +81,8 @@ class MaterialGroupContainer extends Component { headIndex={headIndex} switchEquiv={switchEquiv} lockEquivColumn={lockEquivColumn} + displayYieldField={displayYieldField} + switchYield={switchYield} /> ); @@ -106,7 +109,9 @@ MaterialGroupContainer.propTypes = { canDrop: PropTypes.bool.isRequired, connectDropTarget: PropTypes.func.isRequired, switchEquiv: PropTypes.func, - lockEquivColumn: PropTypes.bool + lockEquivColumn: PropTypes.bool, + displayYieldField: PropTypes.bool.isRequired, + switchYield: PropTypes.func.isRequired, }; MaterialGroupContainer.defaultProps = { diff --git a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/ReactionDetailsScheme.js b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/ReactionDetailsScheme.js index 61a3c780a4..779d5a8487 100644 --- a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/ReactionDetailsScheme.js +++ b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/ReactionDetailsScheme.js @@ -43,6 +43,7 @@ export default class ReactionDetailsScheme extends Component { const textTemplate = TextTemplateStore.getState().reactionDescription; this.state = { lockEquivColumn: false, + displayYieldField: true, reactionDescTemplate: textTemplate.toJS(), }; @@ -58,6 +59,7 @@ export default class ReactionDetailsScheme extends Component { this.dropMaterial = this.dropMaterial.bind(this); this.dropSample = this.dropSample.bind(this); this.switchEquiv = this.switchEquiv.bind(this); + this.switchYield = this.switchYield.bind(this); this.handleOnConditionSelect = this.handleOnConditionSelect.bind(this); this.updateTextTemplates = this.updateTextTemplates.bind(this); this.reactionVesselSize = this.reactionVesselSize.bind(this); @@ -126,6 +128,11 @@ export default class ReactionDetailsScheme extends Component { this.setState({ lockEquivColumn: !lockEquivColumn }); } + switchYield() { + const { displayYieldField } = this.state; + this.setState({ displayYieldField: !displayYieldField }); + } + handleOnConditionSelect(eventKey) { const { reaction } = this.props; const val = eventKey.value; @@ -348,6 +355,11 @@ export default class ReactionDetailsScheme extends Component { this.updatedReactionForGasFieldsUnitsChange(changeEvent) ); break; + case 'conversionRateChanged': + this.onReactionChange( + this.updatedReactionForConversionRateChange(changeEvent) + ); + break; default: break; } @@ -620,6 +632,22 @@ export default class ReactionDetailsScheme extends Component { ); } + updatedReactionForConversionRateChange(changeEvent) { + const { reaction } = this.props; + const { sampleID, conversionRate } = changeEvent; + const updatedSample = reaction.sampleById(sampleID); + + updatedSample.conversion_rate = conversionRate; + if (conversionRate / 100 > 1) { + NotificationActions.add({ + message: 'conversion rate cannot be more than 100%', + level: 'warning' + }); + } + + return this.updatedReactionWithSample(this.updatedSamplesForConversionRateChange.bind(this), updatedSample); + } + calculateEquivalent(refM, updatedSample) { if (!refM.contains_residues) { NotificationActions.add({ @@ -1004,6 +1032,15 @@ export default class ReactionDetailsScheme extends Component { }); } + updatedSamplesForConversionRateChange(samples, updatedSample) { + return samples.map((sample) => { + if (sample.id === updatedSample.id) { + sample.conversion_rate = updatedSample.conversion_rate; + } + return sample; + }); + } + updatedReactionWithSample(updateFunction, updatedSample, type) { const { reaction } = this.props; reaction.starting_materials = updateFunction(reaction.starting_materials, updatedSample, 'starting_materials', type); @@ -1063,9 +1100,12 @@ export default class ReactionDetailsScheme extends Component { } render() { - const { lockEquivColumn, reactionDescTemplate } = this.state; + const { + lockEquivColumn, + reactionDescTemplate, + displayYieldField, + } = this.state; const { reaction } = this.props; - if (reaction.editedSample !== undefined) { if (reaction.editedSample.amountType === 'target') { this.updatedSamplesForEquivalentChange(reaction.samples, reaction.editedSample); @@ -1154,6 +1194,8 @@ export default class ReactionDetailsScheme extends Component { onChange={(changeEvent) => this.handleMaterialsChange(changeEvent)} switchEquiv={this.switchEquiv} lockEquivColumn={this.state.lockEquivColumn} + switchYield={this.switchYield} + displayYieldField={displayYieldField} headIndex={0} /> diff --git a/app/packs/src/components/common/ToggleButton.js b/app/packs/src/components/common/ToggleButton.js index 029c097d7d..42641b2698 100644 --- a/app/packs/src/components/common/ToggleButton.js +++ b/app/packs/src/components/common/ToggleButton.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; export default function ToggleButton({ isToggledInitial, onToggle, onChange, onLabel, offLabel, - onColor, offColor, tooltipOn, tooltipOff + onColor, offColor, tooltipOn, tooltipOff, fontSize, fontWeight }) { const [isToggled, setIsToggled] = useState(isToggledInitial); @@ -44,6 +44,8 @@ ToggleButton.propTypes = { offColor: PropTypes.string, tooltipOn: PropTypes.string, tooltipOff: PropTypes.string, + fontWeight: PropTypes.string, + fontSize: PropTypes.string, }; ToggleButton.defaultProps = { @@ -55,4 +57,6 @@ ToggleButton.defaultProps = { offColor: '#d3d3d3', tooltipOn: 'Click to switch off', tooltipOff: 'Click to switch on', + fontWeight: 'normal', + fontSize: '1em', }; diff --git a/app/packs/src/models/Sample.js b/app/packs/src/models/Sample.js index 5e3947ec76..cc1ec53abb 100644 --- a/app/packs/src/models/Sample.js +++ b/app/packs/src/models/Sample.js @@ -1047,6 +1047,7 @@ export default class Sample extends Element { coefficient: this.coefficient, gas_type: this.gas_type || false, gas_phase_data: this.gas_phase_data, + conversion_rate: this.conversion_rate, }; _.merge(params, extra_params); return params; diff --git a/app/usecases/reactions/update_materials.rb b/app/usecases/reactions/update_materials.rb index 7badd390c2..b734b71e82 100644 --- a/app/usecases/reactions/update_materials.rb +++ b/app/usecases/reactions/update_materials.rb @@ -113,7 +113,7 @@ def create_new_sample(sample, fixed_label) :type, :molecule, :collection_id, :short_label, :waste, :show_label, :coefficient, :user_labels, :boiling_point_lowerbound, :boiling_point_upperbound, :melting_point_lowerbound, :melting_point_upperbound, :segments, :gas_type, - :gas_phase_data + :gas_phase_data, :conversion_rate ).merge(created_by: @current_user.id, boiling_point: rangebound(sample.boiling_point_lowerbound, sample.boiling_point_upperbound), melting_point: rangebound(sample.melting_point_lowerbound, sample.melting_point_upperbound)) @@ -215,6 +215,7 @@ def associate_sample_with_reaction(sample, modified_sample, material_group) type: reactions_sample_klass, gas_type: sample.gas_type, gas_phase_data: sample.gas_phase_data, + conversion_rate: sample.conversion_rate, ) # sample was moved to other materialgroup else @@ -230,6 +231,7 @@ def associate_sample_with_reaction(sample, modified_sample, material_group) type: reactions_sample_klass, gas_type: sample.gas_type, gas_phase_data: sample.gas_phase_data, + conversion_rate: sample.conversion_rate, ) end end diff --git a/db/migrate/20240917085816_add_conversion_rate_to_reactions_samples.rb b/db/migrate/20240917085816_add_conversion_rate_to_reactions_samples.rb new file mode 100644 index 0000000000..2118a61692 --- /dev/null +++ b/db/migrate/20240917085816_add_conversion_rate_to_reactions_samples.rb @@ -0,0 +1,5 @@ +class AddConversionRateToReactionsSamples < ActiveRecord::Migration[6.1] + def change + add_column :reactions_samples, :conversion_rate, :float, null: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 12ab0a0f71..a127a7df25 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2024_07_11_120833) do +ActiveRecord::Schema.define(version: 2024_09_17_085816) do # These are extensions that must be enabled in order to support this database enable_extension "hstore" @@ -983,6 +983,7 @@ t.boolean "show_label", default: false, null: false t.integer "gas_type", default: 0 t.jsonb "gas_phase_data", default: {"time"=>{"unit"=>"h", "value"=>nil}, "temperature"=>{"unit"=>"°C", "value"=>nil}, "turnover_number"=>nil, "part_per_million"=>nil, "turnover_frequency"=>{"unit"=>"TON/h", "value"=>nil}} + t.float "conversion_rate" t.index ["reaction_id"], name: "index_reactions_samples_on_reaction_id" t.index ["sample_id"], name: "index_reactions_samples_on_sample_id" end diff --git a/lib/import/import_collections.rb b/lib/import/import_collections.rb index de3d257dbb..a326a858a0 100644 --- a/lib/import/import_collections.rb +++ b/lib/import/import_collections.rb @@ -388,6 +388,7 @@ def import_reactions_samples 'coefficient', 'gas_type', 'gas_phase_data', + 'conversion_rate', ).merge( reaction: @instances.fetch('Reaction').fetch(fields.fetch('reaction_id')), sample: @instances.fetch('Sample').fetch(fields.fetch('sample_id')), diff --git a/lib/import/import_json.rb b/lib/import/import_json.rb index a59314421a..a6907add5c 100644 --- a/lib/import/import_json.rb +++ b/lib/import/import_json.rb @@ -82,6 +82,9 @@ class Import::ImportJson # 'r_uuid' => nil, # 'r_reference' => nil, # 'r_equivalent' => nil, + # 'r_gas_type' => nil, + # 'r_gas_phase_data' => nil, + # 'r_conversion_rate' => nil, # ] # } # end @@ -374,7 +377,9 @@ def add_to_reaction(klass, el, new_el) if new_data && new_data[r_uuid] && new_data[r_uuid]['id'] @log['samples'][el_uuid][klass.name] = klass.create( sample_id: new_el.id, reaction_id: new_data[r_uuid]['id'], - reference: ref, equivalent: eq, position: el['r_position'] + reference: ref, equivalent: eq, position: el['r_position'], + gas_type: el['r_gas_type'], gas_phase_data: el['r_gas_phase_data'], + conversion_rate: el['r_conversion_rate'] ) && '201' || '500' else @log['samples'][el_uuid][klass.name] = '404' diff --git a/lib/reporter/docx/detail_reaction.rb b/lib/reporter/docx/detail_reaction.rb index d060908651..a59dd65dfa 100644 --- a/lib/reporter/docx/detail_reaction.rb +++ b/lib/reporter/docx/detail_reaction.rb @@ -361,7 +361,7 @@ def material_hash(material, is_product=false) mol: valid_digit(mmol, digit), mmol_unit: mmol_unit, equiv: valid_digit(s.equivalent, digit), - molecule_name_hash: s[:molecule_name_hash] + molecule_name_hash: s[:molecule_name_hash], } if is_product @@ -372,6 +372,7 @@ def material_hash(material, is_product=false) mol: valid_digit(mmol, digit), equiv: equiv, molecule_name_hash: s[:molecule_name_hash], + conversion_rate: s.conversion_rate, }) end diff --git a/spec/factories/reactions_samples.rb b/spec/factories/reactions_samples.rb index d9438a94dd..539dc781b6 100644 --- a/spec/factories/reactions_samples.rb +++ b/spec/factories/reactions_samples.rb @@ -6,6 +6,7 @@ association :sample reference { false } equivalent { 1.0 } + conversion_rate { 1.0 } position { 0 } type { 'ReactionsSample' } waste { false } diff --git a/spec/javascripts/packs/src/components/common/ToggleButton.spec.js b/spec/javascripts/packs/src/components/common/ToggleButton.spec.js index 5e2ffefc27..429ff5c112 100644 --- a/spec/javascripts/packs/src/components/common/ToggleButton.spec.js +++ b/spec/javascripts/packs/src/components/common/ToggleButton.spec.js @@ -27,6 +27,8 @@ describe('', () => { offColor="#d3d3d3" tooltipOn="Click to enable Default mode" tooltipOff="Click to enable Gas mode" + fontSize="1em" + fontWeight="normal" /> ); }); From e8622cc1c676f41e84ca3d381b5b421a9181fcbd Mon Sep 17 00:00:00 2001 From: adambasha0 Date: Wed, 6 Nov 2024 09:32:22 +0000 Subject: [PATCH 2/4] merge: resolve merge conflict --- .../details/reactions/schemeTab/Material.js | 2 +- .../reactions/schemeTab/MaterialGroup.js | 10 +++++++--- .../schemeTab/ReactionDetailsScheme.js | 17 +++++++++++++---- app/packs/src/components/common/ToggleButton.js | 6 +++++- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js index 34e6223b8f..26476cf016 100644 --- a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js +++ b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js @@ -280,7 +280,7 @@ class Material extends Component { yieldOrConversionRate(material) { const { reaction, displayYieldField } = this.props; - if (displayYieldField) { + if (displayYieldField === true || displayYieldField === null) { return (
{ const { displayYieldField } = this.state; - this.setState({ displayYieldField: !displayYieldField }); - } + this.setState({ displayYieldField: shouldDisplayYield ?? !displayYieldField }); + }; handleOnConditionSelect(eventKey) { const { reaction } = this.props; @@ -1141,6 +1141,15 @@ export default class ReactionDetailsScheme extends Component { reaction.markSampleAsReference(refM.id); } + if (displayYieldField === null) { + const allHaveNoConversion = reaction.products.every( + (material) => material.conversion_rate && material.conversion_rate !== 0 + ); + if (allHaveNoConversion) { + this.switchYield(!allHaveNoConversion); + } + } + const headReactants = reaction.starting_materials.length ?? 0; return ( <> diff --git a/app/packs/src/components/common/ToggleButton.js b/app/packs/src/components/common/ToggleButton.js index 42641b2698..3686d3c115 100644 --- a/app/packs/src/components/common/ToggleButton.js +++ b/app/packs/src/components/common/ToggleButton.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { Button, OverlayTrigger, Tooltip } from 'react-bootstrap'; import PropTypes from 'prop-types'; @@ -15,6 +15,10 @@ export default function ToggleButton({ if (onChange) onChange(newToggledState); }; + useEffect(() => { + setIsToggled(isToggledInitial); + }, [isToggledInitial]); + const buttonColor = isToggled ? onColor : offColor; const toolTipMessage = isToggled ? tooltipOn : tooltipOff; From a11b53bf224ee5e43d35d70f76ca619f2dfa7c23 Mon Sep 17 00:00:00 2001 From: adambasha0 Date: Wed, 6 Nov 2024 13:44:24 +0000 Subject: [PATCH 3/4] refactor: adjust styling of conversion field in reaction scheme --- .../details/reactions/ReactionDetails.js | 18 ------------------ .../details/reactions/schemeTab/Material.js | 3 ++- .../reactions/schemeTab/MaterialGroup.js | 4 ++-- .../src/components/common/ToggleButton.js | 14 +++++++------- 4 files changed, 11 insertions(+), 28 deletions(-) diff --git a/app/packs/src/apps/mydb/elements/details/reactions/ReactionDetails.js b/app/packs/src/apps/mydb/elements/details/reactions/ReactionDetails.js index d81ea86e11..165ea1f7cc 100644 --- a/app/packs/src/apps/mydb/elements/details/reactions/ReactionDetails.js +++ b/app/packs/src/apps/mydb/elements/details/reactions/ReactionDetails.js @@ -513,24 +513,6 @@ export default class ReactionDetails extends Component { render() { const { reaction, visible, activeTab } = this.state; this.updateReactionVesselSize(reaction); - const schemeTitle = reaction && activeTab === 'scheme' ? ( -
-
- -
-
- ) : 'Scheme'; const tabContentsMap = { scheme: ( diff --git a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js index 26476cf016..8dcc24ac0c 100644 --- a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js +++ b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/Material.js @@ -273,6 +273,7 @@ class Material extends Component { unit="%" disabled={!permitOn(reaction)} onChange={(e) => this.handleConversionRateChange(e)} + size="sm" />
); @@ -287,7 +288,7 @@ class Material extends Component { name="yield" type="text" bsClass="bs-form--compact form-control" - bsSize="small" + size="sm" value={this.calculateYield(material, reaction) || 'n.d.'} disabled /> diff --git a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/MaterialGroup.js b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/MaterialGroup.js index 5ee876c033..495e8a6efc 100644 --- a/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/MaterialGroup.js +++ b/app/packs/src/apps/mydb/elements/details/reactions/schemeTab/MaterialGroup.js @@ -179,8 +179,8 @@ function GeneralMaterialGroup({ offColor="transparent" tooltipOn={conversionText} tooltipOff={yieldText} - fontSize="14px" - fontWeight="bold" + fontType="fw-bold" + fontColor="text-dark" /> ); diff --git a/app/packs/src/components/common/ToggleButton.js b/app/packs/src/components/common/ToggleButton.js index 3686d3c115..6489d61d70 100644 --- a/app/packs/src/components/common/ToggleButton.js +++ b/app/packs/src/components/common/ToggleButton.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; export default function ToggleButton({ isToggledInitial, onToggle, onChange, onLabel, offLabel, - onColor, offColor, tooltipOn, tooltipOff, fontSize, fontWeight + onColor, offColor, tooltipOn, tooltipOff, fontType, fontColor }) { const [isToggled, setIsToggled] = useState(isToggledInitial); @@ -28,9 +28,9 @@ export default function ToggleButton({ className={`toggle-button ${isToggled ? 'on' : 'off'}`} size="xs" onClick={handleChange} - style={{ backgroundColor: buttonColor, minWidth: '50px', border: 'none' }} + style={{ backgroundColor: buttonColor, border: 'none', padding: '0px 0px 0px 0px' }} > - + {isToggled ? onLabel : offLabel} @@ -48,8 +48,8 @@ ToggleButton.propTypes = { offColor: PropTypes.string, tooltipOn: PropTypes.string, tooltipOff: PropTypes.string, - fontWeight: PropTypes.string, - fontSize: PropTypes.string, + fontType: PropTypes.string, + fontColor: PropTypes.string, }; ToggleButton.defaultProps = { @@ -61,6 +61,6 @@ ToggleButton.defaultProps = { offColor: '#d3d3d3', tooltipOn: 'Click to switch off', tooltipOff: 'Click to switch on', - fontWeight: 'normal', - fontSize: '1em', + fontType: 'normal', + fontColor: '1em', }; From 68fac94a1d74333d4f2092e4028cf330df48515a Mon Sep 17 00:00:00 2001 From: adambasha0 Date: Fri, 15 Nov 2024 09:17:19 +0000 Subject: [PATCH 4/4] refactor: use bootstrap utility classes for ToggleButton component --- app/packs/src/components/common/ToggleButton.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/packs/src/components/common/ToggleButton.js b/app/packs/src/components/common/ToggleButton.js index 6489d61d70..10824df880 100644 --- a/app/packs/src/components/common/ToggleButton.js +++ b/app/packs/src/components/common/ToggleButton.js @@ -25,10 +25,9 @@ export default function ToggleButton({ return ( {toolTipMessage}}>