Commit 6de89376 authored by jasonych99's avatar jasonych99
Browse files

Add Report Label - FE

parent 9347e9e4
import React from 'react'
import ReactDOM from 'react-dom'
import Quill from 'quill'
import _ from 'lodash';
export default class QuillViewer extends React.Component {
constructor (props) {
......@@ -13,6 +14,14 @@ export default class QuillViewer extends React.Component {
this.initQuill();
}
componentWillReceiveProps(nextProps) {
const oldVal = this.props.value;
const newVal = nextProps.value;
if (oldVal && newVal && !_.isEqual(newVal, oldVal)) {
this.viewer.setContents(newVal);
}
}
initQuill() {
if (!this.viewer) {
const quillViewer = ReactDOM.findDOMNode(this.refs.quillViewer);
......
......@@ -136,6 +136,10 @@ class ReportActions {
reset() {
return null;
}
updMSVal(moleculeId, value) {
return { moleculeId, value };
}
}
export default alt.createActions(ReportActions);
import React, { Component } from 'react';
export default class CommonInput extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value,
};
this.onBlur = this.onBlur.bind(this);
this.onChange = this.onChange.bind(this);
}
onBlur(e) {
this.props.onCompleteEdit(e.target.value);
}
onChange(e) {
this.setState({ value: e.target.value });
}
render() {
const { placeholder } = this.props;
const { value } = this.state;
return (
<input
value={value || ''}
placeholder={placeholder || ''}
onBlur={this.onBlur}
onChange={this.onChange}
/>
);
}
}
......@@ -101,7 +101,6 @@ const clickToDelete = (e, archive) => {
const deleteBtn = (archive) => {
const onClickToDelete = e => clickToDelete(e, archive);
const downloadable = archive.downloadable;
const deleteTP = (
<Tooltip id="delete-tp">
Delete this archive.
......@@ -116,7 +115,7 @@ const deleteBtn = (archive) => {
</OverlayTrigger>
);
return downloadable ? btn : null;
return btn;
};
const clickToClone = (e, archive) => {
......@@ -128,7 +127,6 @@ const clickToClone = (e, archive) => {
const cloneBtn = (archive) => {
const onClickToClone = e => clickToClone(e, archive);
const downloadable = archive.downloadable;
const cloneTP = (
<Tooltip id="clone-tp">
Load date from this report.
......@@ -143,7 +141,7 @@ const cloneBtn = (archive) => {
</OverlayTrigger>
);
return downloadable ? btn : null;
return btn;
};
export default Archives;
const paramize = (state) => {
const { selectedObjs, splSettings, rxnSettings, configs,
fileName, fileDescription, imgFormat, template } = state;
const { selectedObjs, splSettings, rxnSettings, configs, selMolSerials,
fileName, fileDescription, imgFormat, template } = state;
const params = {
objTags: JSON.stringify(objTags(selectedObjs)),
splSettings: JSON.stringify(abstractSplSettings(splSettings)),
rxnSettings: JSON.stringify(rxnSettings),
configs: JSON.stringify(abstractConfigs(configs)),
imgFormat: imgFormat,
fileName: fileName,
fileDescription: fileDescription,
template: template,
}
imgFormat,
fileName,
fileDescription,
template,
molSerials: JSON.stringify(selMolSerials),
};
return params;
};
......
......@@ -29,34 +29,39 @@ const StdPreviews = ({selectedObjs, splSettings, rxnSettings, configs}) => {
)
}
const SiPreviews = ({selectedObjs, configs}) => {
const configs_pairs = objToKeyValPairs(configs);
const SiPreviews = ({ selectedObjs, configs, molSerials }) => {
const configsPairs = objToKeyValPairs(configs);
return (
<div>
<p>Experimental Part:</p>
<br/>
<br />
<p>[1 Versions] Version InCHI (), Version SMILES()</p>
<br/>
<br />
<p>[2 General remarks]</p>
<br/>
<br />
<p>[3 General procedures]</p>
<SectionSiProcedures selectedObjs={selectedObjs} />
<br/>
<br />
<p>[4 Synthesis]</p>
<SectionSiSynthesis selectedObjs={selectedObjs} configs={configs_pairs} />
<br/>
<SectionSiSynthesis
selectedObjs={selectedObjs}
configs={configsPairs}
molSerials={molSerials}
/>
<br />
<p>[5 Spectra and Copies]</p>
<br/>
<br />
</div>
);
}
};
const Previews = ({selectedObjs, splSettings, rxnSettings, configs, template}) => {
const Previews = ({selectedObjs, splSettings, rxnSettings, configs, template, molSerials}) => {
const content = template === 'supporting_information'
? <SiPreviews
selectedObjs={selectedObjs}
configs={configs}
molSerials={molSerials}
/>
: <StdPreviews
selectedObjs={selectedObjs}
......
......@@ -6,6 +6,7 @@ import UIStore from '../stores/UIStore';
import Setting from './Setting';
import Previews from './Previews';
import Orders from './Orders';
import Serials from './Serials';
import Archives from './Archives';
import Config from './Config';
import PanelHeader from '../common/PanelHeader';
......@@ -98,7 +99,9 @@ export default class ReportContainer extends Component {
render() {
const { splSettings, checkedAllSplSettings, archives, activeKey,
rxnSettings, checkedAllRxnSettings, imgFormat, fileName, template,
configs, checkedAllConfigs, selectedObjs } = this.state;
configs, checkedAllConfigs, selectedObjs, selMolSerials } = this.state;
const archivesTitle = this.archivesTitle();
return (
<Panel
header={this.panelHeader()}
......@@ -134,7 +137,12 @@ export default class ReportContainer extends Component {
<Orders selectedObjs={selectedObjs} template={template} />
</div>
</Tab>
<Tab eventKey={3} title={'Preview'}>
<Tab eventKey={3} title={'Label'}>
<div className="panel-fit-screen">
<Serials selMolSerials={selMolSerials} template={template} />
</div>
</Tab>
<Tab eventKey={4} title={'Preview'}>
<div className="panel-fit-screen">
<Previews
selectedObjs={selectedObjs}
......@@ -142,10 +150,11 @@ export default class ReportContainer extends Component {
rxnSettings={rxnSettings}
configs={configs}
template={template}
molSerials={selMolSerials}
/>
</div>
</Tab>
<Tab eventKey={4} title={this.archivesTitle()}>
<Tab eventKey={5} title={archivesTitle}>
<div className="panel-fit-screen">
<Archives archives={archives} />
</div>
......
......@@ -25,25 +25,36 @@ const sampleMoleculeName = (s) => {
return null;
};
const Title = ({ el, counter }) => {
let iupacs = el.products.map((p, i) => {
const key1 = `${i}-text`;
const key2 = `${i}-slash`;
const userSerial = (molecule, molSerials = []) => {
let output = 'xx';
molSerials.forEach((ms) => {
if (ms.mol.id === molecule.id && ms.value) output = ms.value;
});
return output;
};
const deltaUserSerial = (molecule, molSerials) => {
const insert = userSerial(molecule, molSerials);
return { insert };
};
const Title = ({ el, counter, molSerials }) => {
let title = [];
el.products.forEach((p, i) => {
const us = userSerial(p.molecule, molSerials);
const key = `${i}-text`;
const comma = <span key={`${i}-comma`}>, </span>;
const smn = sampleMoleculeName(p);
if (smn) {
return [<span key={key1}>{smn}</span>,
<span key={key2}> / </span>];
}
return [<span key={key1}>"<b>NAME</b>"</span>,
<span key={key2}> / </span>];
title = smn
? [...title, <span key={key}>{smn} ({us})</span>, comma]
: [...title, <span key={key}>"<b>NAME</b>"</span>, comma];
});
iupacs = _.flatten(iupacs).slice(0, -1);
title = _.flatten(title).slice(0, -1);
return (
<p>
<span>[4.{counter}] </span>
{iupacs}
<span> (<b>xx</b>)</span>
<span>{title}</span>
</p>
);
};
......@@ -56,10 +67,6 @@ const deltaSampleMoleculeName = (s) => {
return { attributes: { bold: 'true' }, insert: '"NAME"' };
};
const boldXX = () => {
return { attributes: { bold: "true" }, insert: "xx" };
}
const ProductsInfo = ({ products = [] }) => {
let content = [];
products.forEach((p) => {
......@@ -94,14 +101,14 @@ const ProductsInfo = ({ products = [] }) => {
return <QuillViewer value={{ ops: content }} />;
};
const stAndReContent = (el, prevCounter, prevContent) => {
const stAndReContent = (el, prevCounter, prevContent, molSerials) => {
let counter = prevCounter;
let content = prevContent;
[...el.starting_materials, ...el.reactants].forEach((elm) => {
counter += 1;
content = [...content,
{ insert: `{${Alphabet(counter)}|` },
boldXX(),
deltaUserSerial(elm.molecule, molSerials),
{ insert: '} ' },
deltaSampleMoleculeName(elm),
{ insert: ` (${elm.amount_g} g, ${digit(elm.amount_mol * 1000, 4)} mmol, ${digit(elm.equivalent, 2)} equiv.); ` }];
......@@ -123,15 +130,16 @@ const solventsContent = (el, prevCounter, prevContent) => {
return { counter, content };
};
const porductsContent = (el, prevCounter, prevContent) => {
const porductsContent = (el, prevCounter, prevContent, molSerials) => {
let counter = prevCounter;
let content = prevContent;
content = [...content, { insert: 'Yield: ' }];
el.products.forEach((p) => {
const m = p.molecule;
counter += 1;
content = [...content,
{ insert: `{${Alphabet(counter)}|` },
boldXX(),
deltaUserSerial(m, molSerials),
{ insert: '} ' },
{ insert: ` = ${digit(p.equivalent * 100, 0)}%` },
{ insert: ` (${p.amount_g} g, ${digit(p.amount_mol * 1000, 4)} mmol)` },
......@@ -142,12 +150,13 @@ const porductsContent = (el, prevCounter, prevContent) => {
return { counter, content };
};
const materailsContent = (el) => {
const materailsContent = (el, molSerials) => {
const counter = 0;
const content = [];
const stAndRe = stAndReContent(el, counter, content);
const stAndRe = stAndReContent(el, counter, content, molSerials);
const solvCon = solventsContent(el, stAndRe.counter, stAndRe.content);
const prodCon = porductsContent(el, solvCon.counter, solvCon.content);
const prodCon = porductsContent(el, solvCon.counter,
solvCon.content, molSerials);
return prodCon.content;
};
......@@ -259,19 +268,19 @@ const descContent = (el) => {
const synNameContent = el => [{ insert: `${el.name}: ` }];
const ContentBlock = ({ el }) => {
const ContentBlock = ({ el, molSerials }) => {
const synName = synNameContent(el);
const desc = descContent(el);
const materials = materailsContent(el);
const materials = materailsContent(el, molSerials);
const obsvTlc = obsvTlcContent(el);
const analyses = analysesContent(el.products);
const block = [...synName, ...desc, ...materials, ...obsvTlc, ...analyses];
return <QuillViewer value={{ ops: block }} />;
};
const SynthesisRow = ({ el, counter, configs }) => (
const SynthesisRow = ({ el, counter, configs, molSerials }) => (
<div>
<Title el={el} counter={counter} />
<Title el={el} counter={counter} molSerials={molSerials} />
<SVGContent
show
svgPath={el.svgPath}
......@@ -279,12 +288,12 @@ const SynthesisRow = ({ el, counter, configs }) => (
isProductOnly={!configs.Showallchemi}
/>
<ProductsInfo products={el.products} />
<ContentBlock el={el} />
<ContentBlock el={el} molSerials={molSerials} />
<DangerBlock el={el} />
</div>
);
const SectionSiSynthesis = ({ selectedObjs, configs }) => {
const SectionSiSynthesis = ({ selectedObjs, configs, molSerials }) => {
let counter = 0;
const contents = selectedObjs.map((obj) => {
if (obj.type === 'reaction' && obj.role !== 'gp') {
......@@ -296,6 +305,7 @@ const SectionSiSynthesis = ({ selectedObjs, configs }) => {
el={obj}
counter={counter}
configs={configs}
molSerials={molSerials}
/>
);
}
......
import React from 'react';
import SVG from 'react-inlinesvg';
import { Panel } from 'react-bootstrap';
import Formula from '../common/Formula';
import CommonInput from '../common/CommonInput';
import ReportActions from '../actions/ReportActions';
const Serial = ({serial, counter}) => {
if (!serial) return null;
const mol = serial.mol;
const oddClass = counter % 2 === 1 ? 'order-even' : null;
const onCompleteEdit = val => ReportActions.updMSVal(mol.id, val);
return (
<Panel eventKey={counter} key={counter} >
<div className="report-serial">
<div className={`order ${oddClass}`}>{counter + 1}</div>
<div className="svg">
<SVG src={mol.svgPath} key={mol.svgPath} />
</div>
<div className="info">
<p><Formula formula={mol.sumFormula} /></p>
<p>{mol.iupacName}</p>
</div>
<div className="input">
<CommonInput
value={serial.value}
key={mol.id}
placeholder="xx"
onCompleteEdit={onCompleteEdit}
/>
</div>
</div>
</Panel>
);
};
const Serials = ({selMolSerials, template}) => {
if (template !== 'supporting_information') {
return <h5>This is only available for Supporting Information.</h5>;
}
const contents = selMolSerials.map((molSer, i) => (
<Serial id={i} key={`ms-${molSer.mol.id}`} serial={molSer} counter={i} />
));
return <div className="report-serials">{contents}</div>;
};
export default Serials;
......@@ -29,6 +29,7 @@ class ReportStore {
this.defaultObjTags = { sampleIds: [], reactionIds: [] }
this.selectedObjTags = { sampleIds: [], reactionIds: [] }
this.selectedObjs = []
this.selMolSerials = []
this.imgFormat = 'png'
this.archives = []
this.fileName = this.initFileName()
......@@ -59,6 +60,7 @@ class ReportStore {
handleDelete: ReportActions.delete,
hadnleRemove: ReportActions.remove,
hadnleReset: ReportActions.reset,
handleUpdMSVal: ReportActions.updMSVal,
})
}
......@@ -67,9 +69,13 @@ class ReportStore {
}
handleUpdateTemplate(value) {
const newSelectedObjs = this.orderObjsForTemplate(value);
const molSerials = this.updMolSerials(newSelectedObjs, value);
this.setState({ template: value,
fileName: this.initFileName(value),
selectedObjs: this.orderObjsForTemplate(value) });
selectedObjs: newSelectedObjs,
selMolSerials: molSerials,
});
}
orderObjsForTemplate(template, oldObjs = null) {
......@@ -154,7 +160,7 @@ class ReportStore {
handleGenerateReport(result) {
const newArchives = [result.report, ...this.archives];
this.setState({ processingReport: !this.processingReport,
activeKey: 4,
activeKey: 5,
archives: newArchives,
processings: this.getProcessings(newArchives),
fileName: this.initFileName(this.template) });
......@@ -182,7 +188,11 @@ class ReportStore {
this.defaultObjTags,
this.selectedObjs);
const finalObjs = this.orderObjsForTemplate(this.template, newSelectedObjs);
this.setState({selectedObjs: finalObjs});
const molSerials = this.updMolSerials(finalObjs);
this.setState({
selectedObjs: finalObjs,
selMolSerials: molSerials,
});
}
isEqTypeId(a, b) {
......@@ -193,7 +203,11 @@ class ReportStore {
const oldObjs = this.selectedObjs || [];
const newObjs = reOrderArr(sourceTag, targetTag, this.isEqTypeId, oldObjs);
const finalObjs = this.orderObjsForTemplate(this.template, newObjs);
this.setState({selectedObjs: finalObjs});
const molSerials = this.updMolSerials(finalObjs);
this.setState({
selectedObjs: finalObjs,
selMolSerials: molSerials,
});
}
initFileName(template = 'supporting_information') {
......@@ -286,6 +300,8 @@ class ReportStore {
const newObjs = UpdateSelectedObjs(defaultObjTags, objs, defaultObjTags);
const orderedArObjs = this.orderObjsForArchive(newObjs, archive.objects);
const orderedArTpObjs = this.orderObjsForTemplate(template, orderedArObjs);
const molSerials = archive.mol_serials ||
this.updMolSerials(orderedArTpObjs);
this.setState({
activeKey: 0,
......@@ -322,6 +338,7 @@ class ReportStore {
defaultObjTags,
selectedObjTags: { sampleIds: [], reactionIds: [] },
selectedObjs: orderedArTpObjs,
selMolSerials: molSerials,
});
}
......@@ -345,11 +362,13 @@ class ReportStore {
sTags = { sampleIds: [], reactionIds: [] };
const newObjs = UpdateSelectedObjs(sTags, currentObjs, dTags, currentObjs);
const finalObjs = this.orderObjsForTemplate(this.template, newObjs);
const molSerials = this.updMolSerials(finalObjs);
this.setState({
defaultObjTags: dTags,
selectedObjTags: sTags,
selectedObjs: finalObjs,
selMolSerials: molSerials,
});
}
......@@ -389,6 +408,7 @@ class ReportStore {
defaultObjTags: { sampleIds: [], reactionIds: [] },
selectedObjTags: { sampleIds: [], reactionIds: [] },
selectedObjs: [],
selMolSerials: [],
});
}
......@@ -399,6 +419,68 @@ class ReportStore {
this.setState({ archives: newArchives });
}
updMolSerials(objs, template) {
const currentTemplate = template || this.template;
if (currentTemplate !== 'supporting_information') return [];
if (objs.length === 0) return [];
return this.extractMolSerials(objs);
}
extractMolSerials(objs) {
const oldSelMolSerials = this.selMolSerials;
const newSelMols = this.msMolFromSelected(objs);
const newSelMolSerials = newSelMols.map((newMol) => {
const unchangedMolSerial = oldSelMolSerials.find(osm => (
osm && osm.mol.id === newMol.id
));
return unchangedMolSerial || { mol: newMol, value: null };
});
return newSelMolSerials;
}
nonGpRxns(objs) {
return objs.map((obj) => {
if (obj.type === 'reaction' && obj.role !== 'gp') {
return obj;
}
return null;
}).filter(r => r !== null);
}
msMolFromSelected(objs) {
const rxns = this.nonGpRxns(objs);
let msMols = [];
rxns.forEach((o) => {