chem-generic-ui 0.1.36 → 0.1.39
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.
- package/.babelrc +11 -0
- package/.eslintrc +23 -0
- package/.tool-versions +3 -0
- package/package.json +46 -39
- package/public/ds_details.json +57 -0
- package/public/ds_klass.json +102 -0
- package/public/ds_props.json +54 -0
- package/public/favicon.ico +0 -0
- package/public/images/not_available.svg +1 -0
- package/public/index.html +47 -0
- package/public/logo192.png +0 -0
- package/public/logo512.png +0 -0
- package/public/manifest.json +25 -0
- package/public/robots.txt +3 -0
- package/public/sg_details.json +2036 -0
- package/public/sg_klass.json +850 -0
- package/public/test/ds_props.json +54 -0
- package/public/units_system.json +430 -0
- package/src/app.js +50 -0
- package/src/asserts/main.css +458 -0
- package/src/asserts/main.scss +490 -0
- package/src/components/admin/ElementManager.js +28 -0
- package/src/components/details/GenDSDetails.js +164 -0
- package/src/components/details/GenSgDetails.js +396 -0
- package/src/components/dnd/DragDropItemTypes.js +13 -0
- package/src/components/dnd/GenericElDropTarget.js +160 -0
- package/src/components/dnd/GridDnD.js +42 -0
- package/src/components/dnd/PanelDnD.js +85 -0
- package/src/components/fields/ButtonConfirm.js +45 -0
- package/src/components/fields/ButtonTooltip.js +46 -0
- package/src/components/fields/FieldLabel.js +18 -0
- package/src/components/fields/GenDSMisType.js +20 -0
- package/src/components/fields/GenFormGroupCb.js +17 -0
- package/src/components/fields/GenProperties.js +56 -0
- package/src/components/fields/GenPropertiesFields.js +318 -0
- package/src/components/layers/GenPropertiesLayer.js +176 -0
- package/src/components/layers/LayerModal.js +52 -0
- package/src/components/layers/LayersLayout.js +68 -0
- package/src/components/models/Attachment.js +37 -0
- package/src/components/models/GenericSubField.js +10 -0
- package/src/components/table/DropLinkRenderer.js +35 -0
- package/src/components/table/DropRenderer.js +31 -0
- package/src/components/table/DropTextRenderer.js +25 -0
- package/src/components/table/GenericElTableDropTarget.js +131 -0
- package/src/components/table/GridBtn.js +41 -0
- package/src/components/table/GridEntry.js +75 -0
- package/src/components/table/SamOption.js +53 -0
- package/src/components/table/SelectRenderer.js +34 -0
- package/src/components/table/TableRecord.js +254 -0
- package/src/components/table/UConverterRenderer.js +24 -0
- package/src/components/tools/collate.js +65 -0
- package/src/components/tools/orten.js +171 -0
- package/src/components/tools/utils.js +414 -0
- package/src/data/SystemUnits.js +434 -0
- package/src/data/systemUnits.json +430 -0
- package/src/index.css +13 -0
- package/src/index.html +1 -0
- package/src/index.js +45 -0
- package/src/logo.svg +1 -0
- package/src/simulations/SimuDS.js +52 -0
- package/src/simulations/SimuSG.js +54 -0
- package/webpack.config.js +51 -0
- package/dist/bundle.min.js +0 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* eslint-disable react/forbid-prop-types */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { FormControl, InputGroup } from 'react-bootstrap';
|
|
4
|
+
|
|
5
|
+
const setCell = (columnDef, rowValue) => {
|
|
6
|
+
const {
|
|
7
|
+
type, field, onCellChange, cellRenderer, cellParams
|
|
8
|
+
} = columnDef;
|
|
9
|
+
switch (type) {
|
|
10
|
+
case 'text':
|
|
11
|
+
return (
|
|
12
|
+
<FormControl type="text" value={rowValue[field] || ''} onChange={e => onCellChange({ e, columnDef, rowValue })} />
|
|
13
|
+
);
|
|
14
|
+
case 'system-defined':
|
|
15
|
+
return (
|
|
16
|
+
<InputGroup>
|
|
17
|
+
<FormControl type="number" value={rowValue[field].value || ''} onChange={e => onCellChange({ e, columnDef, rowValue })} />
|
|
18
|
+
<InputGroup.Button>
|
|
19
|
+
{cellRenderer({ ...cellParams, node: { data: rowValue } })}
|
|
20
|
+
</InputGroup.Button>
|
|
21
|
+
</InputGroup>
|
|
22
|
+
);
|
|
23
|
+
case 'select':
|
|
24
|
+
case 'drag_molecule':
|
|
25
|
+
case 'drag_sample':
|
|
26
|
+
case 'dnd':
|
|
27
|
+
return (cellRenderer({ ...cellParams, node: { data: rowValue } }));
|
|
28
|
+
default:
|
|
29
|
+
return <span />;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const ColumnHeader = (columnDefs) => {
|
|
34
|
+
const ch = [];
|
|
35
|
+
const h = (col, idx) => {
|
|
36
|
+
const {
|
|
37
|
+
width, headerName, headerComponent, headerParams
|
|
38
|
+
} = col;
|
|
39
|
+
const colCss = {};
|
|
40
|
+
if (width) { Object.assign(colCss, { width, minWidth: width }); }
|
|
41
|
+
return (
|
|
42
|
+
<div key={`column_header_${col.colId || col.field}_${idx}`} className="generic_grid_header" style={colCss}>
|
|
43
|
+
{headerComponent ? headerComponent(headerParams) : null}
|
|
44
|
+
<div style={colCss}>{headerName}</div>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
columnDefs.forEach((col, idx) => ch.push(h(col, idx)));
|
|
49
|
+
return (<div className="generic_grid" style={{ borderBottom: '1px solid #ccc' }}><div>{ch}</div></div>);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const ColumnRow = (columnDefs, rowValue) => {
|
|
53
|
+
const ch = [];
|
|
54
|
+
const h = (col, val, idx) => {
|
|
55
|
+
const {
|
|
56
|
+
field, width, cellParams, cellRenderer
|
|
57
|
+
} = col;
|
|
58
|
+
const colCss = {};
|
|
59
|
+
if (width) { Object.assign(colCss, { width, minWidth: width }); }
|
|
60
|
+
return (
|
|
61
|
+
<div key={`column_row_${val.id}_${col.colId || col.field}_${idx}`} className="generic_grid_row" style={colCss}>
|
|
62
|
+
{field ? (setCell(col, val) || '') : (cellRenderer({ ...cellParams, node: { data: val } }) || '')}
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
columnDefs.forEach((col, idx) => ch.push(h(col, rowValue, idx)));
|
|
67
|
+
return (<div key={`column_row_${rowValue.id}`} className="generic_grid"><div>{ch}</div></div>);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const NoRow = (values) => {
|
|
71
|
+
if (values && values.length > 0) return null;
|
|
72
|
+
return (<div className="generic_grid"><div><div className="generic_grid_row" style={{ width: '100%' }}>(No data)</div></div></div>);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export { ColumnHeader, ColumnRow, NoRow };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* eslint-disable react/forbid-prop-types */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import { v4 as uuid } from 'uuid';
|
|
5
|
+
import { OverlayTrigger, InputGroup, Tooltip } from 'react-bootstrap';
|
|
6
|
+
|
|
7
|
+
const SamOption = (props) => {
|
|
8
|
+
const { sField, node, onChange } = props;
|
|
9
|
+
const { data } = node;
|
|
10
|
+
const fValue = (data[sField.id] && data[sField.id].value) || {};
|
|
11
|
+
if (!fValue.is_new) return <div />;
|
|
12
|
+
const rUUID = uuid();
|
|
13
|
+
return (
|
|
14
|
+
<div className="generic_sam_options">
|
|
15
|
+
<OverlayTrigger delayShow={1000} placement="right" overlay={<Tooltip id={uuid()}>associate with this sample</Tooltip>}>
|
|
16
|
+
<InputGroup.Radio
|
|
17
|
+
name={`dropS_${rUUID}`}
|
|
18
|
+
disabled={fValue.isAssoc}
|
|
19
|
+
checked={fValue.cr_opt === 0}
|
|
20
|
+
onChange={() => onChange({ node, subField: sField, crOpt: 0 })}
|
|
21
|
+
>
|
|
22
|
+
Current
|
|
23
|
+
</InputGroup.Radio>
|
|
24
|
+
</OverlayTrigger>
|
|
25
|
+
<OverlayTrigger delayShow={1000} placement="right" overlay={<Tooltip id={uuid()}>split from the sample first and then associate with it</Tooltip>}>
|
|
26
|
+
<InputGroup.Radio
|
|
27
|
+
name={`dropS_${rUUID}`}
|
|
28
|
+
checked={fValue.cr_opt === 1}
|
|
29
|
+
onChange={() => onChange({ node, subField: sField, crOpt: 1 })}
|
|
30
|
+
>
|
|
31
|
+
Split
|
|
32
|
+
</InputGroup.Radio>
|
|
33
|
+
</OverlayTrigger>
|
|
34
|
+
<OverlayTrigger delayShow={1000} placement="right" overlay={<Tooltip id={uuid()}>duplicate the sample first and then associate with it</Tooltip>}>
|
|
35
|
+
<InputGroup.Radio
|
|
36
|
+
name={`dropS_${rUUID}`}
|
|
37
|
+
checked={fValue.cr_opt === 2}
|
|
38
|
+
onChange={() => onChange({ node, subField: sField, crOpt: 2 })}
|
|
39
|
+
>
|
|
40
|
+
Copy
|
|
41
|
+
</InputGroup.Radio>
|
|
42
|
+
</OverlayTrigger>
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
SamOption.propTypes = {
|
|
48
|
+
sField: PropTypes.object.isRequired,
|
|
49
|
+
node: PropTypes.object.isRequired,
|
|
50
|
+
onChange: PropTypes.func.isRequired
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default SamOption;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* eslint-disable react/forbid-prop-types */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import Select from 'react-select';
|
|
5
|
+
|
|
6
|
+
const SelectRenderer = (props) => {
|
|
7
|
+
const {
|
|
8
|
+
sField, onChange, sOptions, node
|
|
9
|
+
} = props;
|
|
10
|
+
if (sField.type !== 'select' || sOptions.length < 1) return null;
|
|
11
|
+
const { data } = node;
|
|
12
|
+
const val = sOptions.find(o => o.value === data[sField.id].value) || null;
|
|
13
|
+
return (
|
|
14
|
+
<Select
|
|
15
|
+
isClearable
|
|
16
|
+
menuContainerStyle={{ position: 'absolute' }}
|
|
17
|
+
multi={false}
|
|
18
|
+
options={sOptions}
|
|
19
|
+
value={val}
|
|
20
|
+
onChange={e => onChange(e, sField, node)}
|
|
21
|
+
className="status-select"
|
|
22
|
+
style={{ textAlign: 'left' }}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
SelectRenderer.propTypes = {
|
|
28
|
+
sField: PropTypes.object.isRequired,
|
|
29
|
+
onChange: PropTypes.func.isRequired,
|
|
30
|
+
node: PropTypes.object.isRequired,
|
|
31
|
+
sOptions: PropTypes.arrayOf(PropTypes.object).isRequired
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default SelectRenderer;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-globals */
|
|
2
|
+
/* eslint-disable no-empty */
|
|
3
|
+
/* eslint-disable react/forbid-prop-types */
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import Numeral from 'numeral';
|
|
7
|
+
import GenericSubField from '../models/GenericSubField';
|
|
8
|
+
import { AddRowBtn, DelRowBtn, DnDRowBtn, NullRowBtn } from './GridBtn';
|
|
9
|
+
import { ColumnHeader, ColumnRow, NoRow } from './GridEntry';
|
|
10
|
+
import UConverterRenderer from './UConverterRenderer';
|
|
11
|
+
import { genUnits, unitConversion, molOptions, samOptions } from '../tools/utils';
|
|
12
|
+
import DropRenderer from './DropRenderer';
|
|
13
|
+
import DropTextRenderer from './DropTextRenderer';
|
|
14
|
+
import DropLinkRenderer from './DropLinkRenderer';
|
|
15
|
+
import SampOption from './SamOption';
|
|
16
|
+
import DragDropItemTypes from '../dnd/DragDropItemTypes';
|
|
17
|
+
import SelectRenderer from './SelectRenderer';
|
|
18
|
+
|
|
19
|
+
export default class TableRecord extends React.Component {
|
|
20
|
+
constructor(props) {
|
|
21
|
+
super(props);
|
|
22
|
+
this.delRow = this.delRow.bind(this);
|
|
23
|
+
this.addRow = this.addRow.bind(this);
|
|
24
|
+
this.moveRow = this.moveRow.bind(this);
|
|
25
|
+
this.onCellChange = this.onCellChange.bind(this);
|
|
26
|
+
this.onSelectClick = this.onSelectClick.bind(this);
|
|
27
|
+
this.onUnitClick = this.onUnitClick.bind(this);
|
|
28
|
+
this.onDrop = this.onDrop.bind(this);
|
|
29
|
+
this.onChk = this.onChk.bind(this);
|
|
30
|
+
this.getColumns = this.getColumns.bind(this);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
onCellChange(params) {
|
|
34
|
+
const { e, columnDef, rowValue } = params;
|
|
35
|
+
const newValue = e.target.value;
|
|
36
|
+
const oldValue = rowValue[columnDef.field].value;
|
|
37
|
+
if (oldValue === newValue) return;
|
|
38
|
+
if (columnDef.type === 'text') {
|
|
39
|
+
rowValue[columnDef.field] = newValue;
|
|
40
|
+
}
|
|
41
|
+
if (columnDef.type === 'system-defined') {
|
|
42
|
+
if (isNaN(newValue)) return;
|
|
43
|
+
rowValue[columnDef.field].value = Numeral(newValue).value();
|
|
44
|
+
}
|
|
45
|
+
const { opt } = this.props;
|
|
46
|
+
const subVals = opt.f_obj.sub_values || [];
|
|
47
|
+
const idx = subVals.findIndex(s => s.id === rowValue.id);
|
|
48
|
+
subVals.splice(idx, 1, rowValue);
|
|
49
|
+
opt.f_obj.sub_values = subVals;
|
|
50
|
+
opt.onSubChange(0, 0, opt.f_obj, true);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
onSelectClick(e, subField, node) {
|
|
54
|
+
const { data } = node;
|
|
55
|
+
const { opt } = this.props;
|
|
56
|
+
const subVals = opt.f_obj.sub_values || [];
|
|
57
|
+
const subVal = subVals.find(s => s.id === data.id);
|
|
58
|
+
subVal[subField.id] = { value: e ? e.value : '' };
|
|
59
|
+
const idx = subVals.findIndex(s => s.id === data.id);
|
|
60
|
+
subVals.splice(idx, 1, subVal);
|
|
61
|
+
opt.f_obj.sub_values = subVals;
|
|
62
|
+
opt.onSubChange(subField, subField.id, opt.f_obj, true);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
onUnitClick(subField, node) {
|
|
66
|
+
const { data } = node;
|
|
67
|
+
const { opt } = this.props;
|
|
68
|
+
const subVals = opt.f_obj.sub_values || [];
|
|
69
|
+
const subVal = subVals.find(s => s.id === data.id);
|
|
70
|
+
const units = genUnits(subField.option_layers);
|
|
71
|
+
let uIdx = units.findIndex(u => u.key === subVal[subField.id].value_system);
|
|
72
|
+
if (uIdx < units.length - 1) uIdx += 1; else uIdx = 0;
|
|
73
|
+
const vs = units.length > 0 ? units[uIdx].key : '';
|
|
74
|
+
const v = unitConversion(subField.option_layers, vs, subVal[subField.id].value);
|
|
75
|
+
subVal[subField.id] = { value: v, value_system: vs };
|
|
76
|
+
const idx = subVals.findIndex(s => s.id === data.id);
|
|
77
|
+
subVals.splice(idx, 1, subVal);
|
|
78
|
+
opt.f_obj.sub_values = subVals;
|
|
79
|
+
opt.onSubChange(subField, subField.id, opt.f_obj, true);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
onDrop(targetProps, targetOpt) {
|
|
83
|
+
const { opt } = this.props;
|
|
84
|
+
const subField = targetOpt.sField;
|
|
85
|
+
const subVals = opt.f_obj.sub_values || [];
|
|
86
|
+
const subVal = subVals.find(s => s.id === targetOpt.data.id);
|
|
87
|
+
subVal[subField.id] = { value: targetProps };
|
|
88
|
+
const idx = subVals.findIndex(s => s.id === targetOpt.data.id);
|
|
89
|
+
subVals.splice(idx, 1, subVal);
|
|
90
|
+
opt.f_obj.sub_values = subVals;
|
|
91
|
+
opt.onSubChange(subField, subField.id, opt.f_obj, true);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
onChk(params) {
|
|
95
|
+
const { node, subField, crOpt } = params;
|
|
96
|
+
const { opt } = this.props;
|
|
97
|
+
const subVals = opt.f_obj.sub_values || [];
|
|
98
|
+
const subVal = subVals.find(s => s.id === node.data.id);
|
|
99
|
+
node.data[subField.id].value.cr_opt = crOpt;
|
|
100
|
+
subVal[subField.id] = { value: node.data[subField.id].value };
|
|
101
|
+
const idx = subVals.findIndex(s => s.id === node.data.id);
|
|
102
|
+
subVals.splice(idx, 1, subVal);
|
|
103
|
+
opt.f_obj.sub_values = subVals;
|
|
104
|
+
opt.onSubChange(subField, subField.id, opt.f_obj, true);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
getColumns() {
|
|
108
|
+
const { opt } = this.props;
|
|
109
|
+
const { selectOptions } = opt;
|
|
110
|
+
const sValues = (opt.f_obj.sub_values || []);
|
|
111
|
+
let columnDefs = [];
|
|
112
|
+
(opt.f_obj.sub_fields || []).forEach((sF) => {
|
|
113
|
+
let colDef = {
|
|
114
|
+
type: sF.type, headerName: sF.col_name, field: sF.id
|
|
115
|
+
};
|
|
116
|
+
const colDefExt = [];
|
|
117
|
+
if (sF.type === 'text') {
|
|
118
|
+
colDef = Object.assign({}, colDef, {
|
|
119
|
+
editable: true, onCellChange: this.onCellChange
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
if (sF.type === 'select') {
|
|
123
|
+
let sOptions =
|
|
124
|
+
(selectOptions[sF.option_layers] && selectOptions[sF.option_layers].options) || [];
|
|
125
|
+
sOptions = sOptions.map(op => ({ value: op.key, name: op.key, label: op.label }));
|
|
126
|
+
const cellParams = { sField: sF, onChange: this.onSelectClick, sOptions };
|
|
127
|
+
colDef = Object.assign({}, colDef, {
|
|
128
|
+
cellRenderer: SelectRenderer, cellParams, onCellChange: this.onCellChange
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
if (sF.type === 'system-defined') {
|
|
132
|
+
const cellParams = { sField: sF, onChange: this.onUnitClick };
|
|
133
|
+
colDef = Object.assign({}, colDef, {
|
|
134
|
+
cellRenderer: UConverterRenderer, cellParams, onCellChange: this.onCellChange
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (sF.type === 'drag_molecule') {
|
|
138
|
+
const cellParams = { sField: sF, opt, onChange: this.onDrop };
|
|
139
|
+
colDef = Object.assign({}, colDef, {
|
|
140
|
+
cellRenderer: DropRenderer, cellParams, onCellChange: this.onCellChange, width: '5vw'
|
|
141
|
+
});
|
|
142
|
+
const conf = ((sF.value || '').split(';') || []);
|
|
143
|
+
conf.forEach((c) => {
|
|
144
|
+
const attr = molOptions.find(m => m.value === c);
|
|
145
|
+
if (attr) {
|
|
146
|
+
const ext = {
|
|
147
|
+
colId: c, editable: false, type: 'text', headerName: attr.label, cellRenderer: DropTextRenderer, cellParams: { attr, sField: sF }
|
|
148
|
+
};
|
|
149
|
+
colDefExt.push(ext);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (sF.type === 'drag_sample') {
|
|
154
|
+
const sOpt = sValues.filter(o => o[sF.id] && o[sF.id].value && o[sF.id].value.is_new);
|
|
155
|
+
const cellParams = { sField: sF, opt, onChange: this.onDrop };
|
|
156
|
+
colDef = Object.assign({}, colDef, {
|
|
157
|
+
cellRenderer: DropRenderer, cellParams, onCellChange: this.onCellChange, width: '5vw'
|
|
158
|
+
});
|
|
159
|
+
const addOption = {
|
|
160
|
+
colId: 'sam_option', editable: false, type: 'text', headerName: '', cellRenderer: SampOption, cellParams: { sField: sF, onChange: this.onChk }, width: '3vw'
|
|
161
|
+
};
|
|
162
|
+
if (sOpt.length > 0) colDefExt.push(addOption);
|
|
163
|
+
const addLink = {
|
|
164
|
+
colId: 'sam_link', editable: false, type: 'text', headerName: 'Short label', cellRenderer: DropLinkRenderer, cellParams: { sField: sF }, width: '5vw'
|
|
165
|
+
};
|
|
166
|
+
colDefExt.push(addLink);
|
|
167
|
+
const conf = ((sF.value || '').split(';') || []);
|
|
168
|
+
conf.forEach((c) => {
|
|
169
|
+
const attr = samOptions.find(m => m.value === c);
|
|
170
|
+
if (attr) {
|
|
171
|
+
const ext = {
|
|
172
|
+
colId: c, editable: false, type: 'text', headerName: attr.label, cellRenderer: DropTextRenderer, cellParams: { attr, sField: sF }
|
|
173
|
+
};
|
|
174
|
+
colDefExt.push(ext);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
columnDefs.push(colDef);
|
|
179
|
+
if (colDefExt.length > 0) columnDefs = columnDefs.concat(colDefExt);
|
|
180
|
+
});
|
|
181
|
+
const act = {
|
|
182
|
+
type: 'button',
|
|
183
|
+
headerName: '',
|
|
184
|
+
colId: opt.f_obj.field,
|
|
185
|
+
headerComponent: AddRowBtn,
|
|
186
|
+
headerParams: { addRow: this.addRow },
|
|
187
|
+
cellRenderer: DelRowBtn,
|
|
188
|
+
cellParams: { delRow: this.delRow },
|
|
189
|
+
width: 'unset',
|
|
190
|
+
};
|
|
191
|
+
columnDefs.splice(0, 0, act);
|
|
192
|
+
const dtype = `${DragDropItemTypes.GENERIC_GRID}_${opt.layer.key}_${opt.f_obj.field}`;
|
|
193
|
+
const move = {
|
|
194
|
+
type: 'dnd',
|
|
195
|
+
field: opt.f_obj.field,
|
|
196
|
+
headerName: '',
|
|
197
|
+
colId: `${opt.f_obj.field}_dnd`,
|
|
198
|
+
headerComponent: NullRowBtn,
|
|
199
|
+
cellRenderer: DnDRowBtn,
|
|
200
|
+
cellParams: { moveRow: this.moveRow, field: opt.f_obj.field, type: dtype },
|
|
201
|
+
width: 'unset',
|
|
202
|
+
};
|
|
203
|
+
columnDefs.splice(0, 0, move);
|
|
204
|
+
return columnDefs;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
moveRow(source, target) {
|
|
208
|
+
const { opt } = this.props;
|
|
209
|
+
const alles = opt.f_obj.sub_values;
|
|
210
|
+
const sid = alles.findIndex(e => e.id === source);
|
|
211
|
+
const tid = alles.findIndex(e => e.id === target);
|
|
212
|
+
const temp = alles[sid];
|
|
213
|
+
alles[sid] = alles[tid];
|
|
214
|
+
alles[tid] = temp;
|
|
215
|
+
opt.onSubChange(0, 0, opt.f_obj, true);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
delRow(rowData) {
|
|
219
|
+
const { opt } = this.props;
|
|
220
|
+
opt.f_obj.sub_values = opt.f_obj.sub_values.filter(s => s.id !== rowData.id);
|
|
221
|
+
opt.onSubChange(0, 0, opt.f_obj, true);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
addRow() {
|
|
225
|
+
const { opt } = this.props;
|
|
226
|
+
const subFields = opt.f_obj.sub_fields || [];
|
|
227
|
+
const newSub = new GenericSubField();
|
|
228
|
+
subFields.map((e) => {
|
|
229
|
+
if (e.type === 'text') return Object.assign(newSub, { [e.id]: '' });
|
|
230
|
+
return Object.assign(newSub, { [e.id]: { value: '', value_system: e.value_system } });
|
|
231
|
+
});
|
|
232
|
+
opt.f_obj.sub_values = opt.f_obj.sub_values || [];
|
|
233
|
+
opt.f_obj.sub_values.push(newSub);
|
|
234
|
+
opt.onSubChange(0, 0, opt.f_obj, true);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
render() {
|
|
238
|
+
const { opt } = this.props;
|
|
239
|
+
if (opt.isSearchCriteria) return (<div>(This is a table)</div>);
|
|
240
|
+
if ((opt.f_obj.sub_fields || []).length < 1) return null;
|
|
241
|
+
const columnDefs = this.getColumns();
|
|
242
|
+
return (
|
|
243
|
+
<div>
|
|
244
|
+
{ColumnHeader(columnDefs)}
|
|
245
|
+
<div>{NoRow(opt.f_obj.sub_values)}</div>
|
|
246
|
+
<div>{(opt.f_obj.sub_values || []).map(s => ColumnRow(columnDefs, s))}</div>
|
|
247
|
+
</div>
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
TableRecord.propTypes = {
|
|
253
|
+
opt: PropTypes.object.isRequired,
|
|
254
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* eslint-disable react/forbid-prop-types */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import { Button } from 'react-bootstrap';
|
|
5
|
+
import { genUnit, genUnitSup } from '../tools/utils';
|
|
6
|
+
|
|
7
|
+
const UConverterRenderer = (props) => {
|
|
8
|
+
const { sField, onChange, node } = props;
|
|
9
|
+
if (sField.type !== 'system-defined') return null;
|
|
10
|
+
const { data } = node;
|
|
11
|
+
return (
|
|
12
|
+
<Button key={`ucr_${data.id}`} active onClick={() => onChange(sField, node)} variant="success">
|
|
13
|
+
{genUnitSup(genUnit(sField.option_layers, data[sField.id].value_system).label) || ''}
|
|
14
|
+
</Button>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
UConverterRenderer.propTypes = {
|
|
19
|
+
sField: PropTypes.object.isRequired,
|
|
20
|
+
onChange: PropTypes.func.isRequired,
|
|
21
|
+
node: PropTypes.object.isRequired
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default UConverterRenderer;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { cloneDeep } from 'lodash';
|
|
2
|
+
import { unitConversion } from './utils';
|
|
3
|
+
import GenericSubField from '../models/GenericSubField';
|
|
4
|
+
|
|
5
|
+
const collateValues = (currentFields, previousFields, previousValues) => {
|
|
6
|
+
const result = [];
|
|
7
|
+
let newSub = new GenericSubField();
|
|
8
|
+
currentFields.map(e => Object.assign(newSub, { [e.id]: '' }));
|
|
9
|
+
const currentValuKeys = Object.keys(newSub);
|
|
10
|
+
const previousValueKeys = Object.keys(previousValues[0]);
|
|
11
|
+
const notInCurrent = previousValueKeys.filter(e => !currentValuKeys.includes(e));
|
|
12
|
+
const currObj = {};
|
|
13
|
+
currentFields.map((c) => {
|
|
14
|
+
if (c.type === 'text') return Object.assign(currObj, { [c.id]: '' });
|
|
15
|
+
return Object.assign(currObj, { [c.id]: { value: '', value_system: c.value_system } });
|
|
16
|
+
});
|
|
17
|
+
previousValues.forEach((e) => {
|
|
18
|
+
newSub = new GenericSubField();
|
|
19
|
+
Object.assign(newSub, currObj, e);
|
|
20
|
+
notInCurrent.forEach(c => delete newSub[c]);
|
|
21
|
+
previousValueKeys.forEach((preKey) => {
|
|
22
|
+
if (newSub[preKey] === undefined || preKey === 'id') return;
|
|
23
|
+
const curr = currentFields.find(f => f.id === preKey);
|
|
24
|
+
const prev = previousFields.find(f => f.id === preKey);
|
|
25
|
+
if (curr.type === 'drag_molecule') {
|
|
26
|
+
if (['text', 'system-defined', 'drag_sample'].includes(prev.type)) {
|
|
27
|
+
newSub[preKey] = { value: undefined };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (curr.type === 'text') {
|
|
31
|
+
if (prev.type === 'system-defined') {
|
|
32
|
+
newSub[preKey] = newSub[preKey].value;
|
|
33
|
+
}
|
|
34
|
+
if (['drag_molecule', 'drag_sample'].includes(prev.type)) {
|
|
35
|
+
newSub[preKey] = '';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (curr.type === 'system-defined') {
|
|
39
|
+
if (prev.type === 'system-defined' && (curr.option_layers !== prev.option_layers)) {
|
|
40
|
+
newSub[preKey].value_system = curr.value_system;
|
|
41
|
+
}
|
|
42
|
+
if (['text', 'drag_molecule', 'drag_sample'].includes(prev.type)) {
|
|
43
|
+
newSub[preKey] = { value: '', value_system: curr.value_system };
|
|
44
|
+
}
|
|
45
|
+
newSub[preKey].value =
|
|
46
|
+
unitConversion(curr.option_layer, newSub[preKey].value_system, newSub[preKey].value);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
result.push(newSub);
|
|
50
|
+
});
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const organizeSubValues = (cur, pre) => {
|
|
55
|
+
const currentFields = cloneDeep(cur.sub_fields || []);
|
|
56
|
+
const previousFields = cloneDeep(pre.sub_fields || []);
|
|
57
|
+
const previousValues = cloneDeep(pre.sub_values || []);
|
|
58
|
+
if (currentFields.length < 1 ||
|
|
59
|
+
previousFields.length < 1 || previousValues.length < 1) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
return collateValues(currentFields, previousFields, previousValues);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default organizeSubValues;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
2
|
+
/* eslint-disable import/prefer-default-export */
|
|
3
|
+
import { cloneDeep, sortBy } from 'lodash';
|
|
4
|
+
import { v4 as uuid } from 'uuid';
|
|
5
|
+
|
|
6
|
+
const getWFNode = (_flow, nodeId) => _flow.elements.filter(e => e.id === nodeId)[0];
|
|
7
|
+
|
|
8
|
+
// full-flow, node id
|
|
9
|
+
const getFlowLayer = (templateFlow, nodeId, sourceLayer, sIdx) => {
|
|
10
|
+
const flow = cloneDeep(templateFlow);
|
|
11
|
+
const nd = flow.elements.filter(e => e.id === nodeId); // fetch node
|
|
12
|
+
if (nd.length < 1) return null;
|
|
13
|
+
const { layer } = nd[0].data;
|
|
14
|
+
const ls = flow.elements.filter(e => e.animated); // lines
|
|
15
|
+
const ns = flow.elements.filter(e => e.type === 'default' && e.data); // nodes - Start - End
|
|
16
|
+
const ndNs = ls.filter(e => e.source === nodeId).map(e => e.target); // next nodes' id
|
|
17
|
+
const wfOpts = ns.filter(n => ndNs.includes(n.id)).map(e => ({ key: e.id, label: `${e.data.layer.label}(${e.data.layer.key})` })); // next nodes
|
|
18
|
+
if (wfOpts.length > 0) {
|
|
19
|
+
const position = (layer.fields || []).length + 1;
|
|
20
|
+
layer.fields.push({
|
|
21
|
+
type: 'wf-next', default: '', field: '_wf_next', label: 'Next', required: false, sub_fields: [], text_sub_fields: [], position, wf_options: wfOpts
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
layer.wf_info = { node_id: nodeId, source_layer: sourceLayer };
|
|
25
|
+
layer.wf_position = sIdx + 1;
|
|
26
|
+
return layer;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const orgLayerObject = (_layers = []) => {
|
|
30
|
+
const layers = _layers;
|
|
31
|
+
return layers.reduce((alles, name) => {
|
|
32
|
+
const all = alles;
|
|
33
|
+
const ok = Object.keys(all);
|
|
34
|
+
if (ok.includes(name.key)) {
|
|
35
|
+
const cnt = ok.filter(e => e === name.key || e.startsWith(`${name.key}.`)).length;
|
|
36
|
+
const nName = `${name.key}.${cnt}`;
|
|
37
|
+
name.key = nName;
|
|
38
|
+
all[nName] = name;
|
|
39
|
+
} else {
|
|
40
|
+
all[name.key] = name;
|
|
41
|
+
}
|
|
42
|
+
return all;
|
|
43
|
+
}, {});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const reformCondFields = (_layer, _oKey) => {
|
|
47
|
+
const layer = _layer;
|
|
48
|
+
layer.fields.map((_f) => {
|
|
49
|
+
const f = _f;
|
|
50
|
+
let conds = f.cond_fields;
|
|
51
|
+
// no cond_fields
|
|
52
|
+
if (!conds || conds.length < 1 || conds.filter(o => !o.field || o.field === '').length === conds.length) return f;
|
|
53
|
+
conds = conds.filter(o => o.layer === _oKey);
|
|
54
|
+
// no same layer, remove cond_fields
|
|
55
|
+
if (conds.length < 1) {
|
|
56
|
+
delete f.cond_fields;
|
|
57
|
+
return f;
|
|
58
|
+
}
|
|
59
|
+
// rename layer
|
|
60
|
+
conds = conds.map((o) => {
|
|
61
|
+
const n = o;
|
|
62
|
+
n.layer = layer.key;
|
|
63
|
+
return n;
|
|
64
|
+
});
|
|
65
|
+
f.cond_fields = conds;
|
|
66
|
+
return f;
|
|
67
|
+
});
|
|
68
|
+
return layer.fields;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const addToObject = (obj, key, addAfter) => {
|
|
72
|
+
const temp = {};
|
|
73
|
+
const ok = Object.keys(obj);
|
|
74
|
+
Object.keys(obj).forEach((e) => {
|
|
75
|
+
if (Object.prototype.hasOwnProperty.call(obj, e)) {
|
|
76
|
+
temp[e] = obj[e];
|
|
77
|
+
if (e === key) {
|
|
78
|
+
const srcPosition = temp[e].position;
|
|
79
|
+
const cnt = ok.filter(o => o === addAfter.key || o.startsWith(`${addAfter.key}.`)).length;
|
|
80
|
+
if (cnt === 0) {
|
|
81
|
+
temp[addAfter.key] = addAfter;
|
|
82
|
+
temp[addAfter.key].position = srcPosition;
|
|
83
|
+
} else {
|
|
84
|
+
const oKey = addAfter.key;
|
|
85
|
+
temp[`${addAfter.key}.${cnt}`] = addAfter;
|
|
86
|
+
temp[`${addAfter.key}.${cnt}`].position = srcPosition;
|
|
87
|
+
temp[`${addAfter.key}.${cnt}`].key = `${addAfter.key}.${cnt}`;
|
|
88
|
+
temp[addAfter.key].fields = reformCondFields(addAfter, oKey);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
if (Object.keys(obj).length === 0) temp[addAfter.key] = addAfter;
|
|
94
|
+
return temp;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const traverseToRemove = (layers, rmKey) => {
|
|
98
|
+
let rms = [];
|
|
99
|
+
Object.keys(layers).forEach((e) => {
|
|
100
|
+
if (Object.prototype.hasOwnProperty.call(layers, e)) {
|
|
101
|
+
if (layers[e].key === rmKey) rms = rms.concat(rmKey);
|
|
102
|
+
else if (layers[e].wf_info && (layers[e].wf_info.source_layer === rmKey)) {
|
|
103
|
+
rms = rms.concat(traverseToRemove(layers, layers[e].key));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
return rms;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const removeFromObject = (_propertiesLayers = {}, srcLayer = '', rmNode = {}) => {
|
|
111
|
+
const layers = _propertiesLayers;
|
|
112
|
+
const rmLayer = rmNode.data && rmNode.data.layer ? rmNode.data.layer.key : null;
|
|
113
|
+
if (!rmLayer) return [];
|
|
114
|
+
let rms = [];
|
|
115
|
+
Object.keys(layers).forEach((e) => {
|
|
116
|
+
if (Object.prototype.hasOwnProperty.call(layers, e)) {
|
|
117
|
+
const wf = layers[e].wf_info;
|
|
118
|
+
if (wf && (wf.source_layer === srcLayer) && (wf.node_id === rmNode.id)) {
|
|
119
|
+
rms = rms.concat(traverseToRemove(layers, layers[e].key));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
rms.forEach(e => delete layers[e]);
|
|
124
|
+
return layers;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const buildInitWF = (template) => {
|
|
128
|
+
const orig = cloneDeep(template);
|
|
129
|
+
const { layers, flow } = orig;
|
|
130
|
+
const sortedLayers = sortBy(layers, l => l.position);
|
|
131
|
+
if (flow && flow.elements.filter(e => !['input', 'output'].includes(e.type).length > 0)) {
|
|
132
|
+
// id = 1 Start, id = 2 End
|
|
133
|
+
const nls = flow.elements; // nodes + lines
|
|
134
|
+
const ls = nls.filter(e => e.animated); // lines
|
|
135
|
+
const ns = nls.filter(e => e.type === 'default' && e.data); // nodes - Start - End
|
|
136
|
+
const nNs = ls.filter(e => e.source === '1').map(e => e.target); // get target ids from Start
|
|
137
|
+
const nextNodes = ns.filter(n => nNs.includes(n.id)); // target nodes
|
|
138
|
+
const result = [];
|
|
139
|
+
sortedLayers.forEach((sortedLayer) => {
|
|
140
|
+
const fLayer = sortedLayer;
|
|
141
|
+
if (fLayer.wf) {
|
|
142
|
+
const position = (fLayer.fields || []).length + 1;
|
|
143
|
+
const passen = nextNodes.filter(n => n.data.layer.key === fLayer.key);
|
|
144
|
+
passen.forEach((pas) => {
|
|
145
|
+
const nextOptions =
|
|
146
|
+
ls.filter(e => e.source === pas.id && e.source !== e.target).map(e => e.target);
|
|
147
|
+
const wfOpts = ns.filter(n => nextOptions.includes(n.id)).map(e => ({ key: e.id, label: `${e.data.layer.label}(${e.data.layer.key})` })); // next nodes
|
|
148
|
+
fLayer.fields.push({
|
|
149
|
+
type: 'wf-next', default: '', field: '_wf_next', label: 'Next', required: false, sub_fields: [], text_sub_fields: [], position, wf_options: wfOpts
|
|
150
|
+
});
|
|
151
|
+
fLayer.wf_info = { node_id: pas.id };
|
|
152
|
+
fLayer.wf_position = 1;
|
|
153
|
+
fLayer.wf_uuid = uuid();
|
|
154
|
+
result.push(fLayer);
|
|
155
|
+
});
|
|
156
|
+
} else {
|
|
157
|
+
result.push(fLayer);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
const ll = orgLayerObject(result);
|
|
161
|
+
orig.layers = ll;
|
|
162
|
+
} else {
|
|
163
|
+
orig.layers = layers;
|
|
164
|
+
}
|
|
165
|
+
return orig;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export {
|
|
169
|
+
getWFNode, getFlowLayer, orgLayerObject,
|
|
170
|
+
addToObject, removeFromObject, reformCondFields, buildInitWF
|
|
171
|
+
};
|