chem-generic-ui 0.1.34 → 0.1.37

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.
Files changed (102) hide show
  1. package/.babelrc +17 -0
  2. package/.eslintrc +23 -0
  3. package/.tool-versions +3 -0
  4. package/package.json +55 -38
  5. package/public/ds_details.json +57 -0
  6. package/public/ds_klass.json +102 -0
  7. package/public/ds_props.json +54 -0
  8. package/public/favicon.ico +0 -0
  9. package/public/images/not_available.svg +1 -0
  10. package/public/index.html +47 -0
  11. package/public/logo192.png +0 -0
  12. package/public/logo512.png +0 -0
  13. package/public/manifest.json +25 -0
  14. package/public/robots.txt +3 -0
  15. package/public/sg_details.json +2036 -0
  16. package/public/sg_klass.json +850 -0
  17. package/public/test/ds_props.json +54 -0
  18. package/{dist/data/systemUnits.json → public/units_system.json} +0 -0
  19. package/src/app.js +50 -0
  20. package/{dist → src}/asserts/main.css +0 -7
  21. package/{dist → src}/asserts/main.scss +1 -7
  22. package/src/components/admin/ElementManager.js +28 -0
  23. package/src/components/details/GenDSDetails.js +164 -0
  24. package/src/components/details/GenSgDetails.js +396 -0
  25. package/{dist → src}/components/dnd/DragDropItemTypes.js +1 -8
  26. package/src/components/dnd/GenericElDropTarget.js +160 -0
  27. package/src/components/dnd/GridDnD.js +42 -0
  28. package/src/components/dnd/PanelDnD.js +85 -0
  29. package/src/components/fields/ButtonConfirm.js +45 -0
  30. package/src/components/fields/ButtonTooltip.js +46 -0
  31. package/src/components/fields/FieldLabel.js +18 -0
  32. package/src/components/fields/GenDSMisType.js +20 -0
  33. package/src/components/fields/GenFormGroupCb.js +17 -0
  34. package/src/components/fields/GenProperties.js +56 -0
  35. package/src/components/fields/GenPropertiesFields.js +318 -0
  36. package/src/components/layers/GenPropertiesLayer.js +176 -0
  37. package/src/components/layers/LayerModal.js +52 -0
  38. package/src/components/layers/LayersLayout.js +68 -0
  39. package/src/components/models/Attachment.js +37 -0
  40. package/src/components/models/GenericSubField.js +10 -0
  41. package/src/components/table/DropLinkRenderer.js +35 -0
  42. package/src/components/table/DropRenderer.js +31 -0
  43. package/src/components/table/DropTextRenderer.js +25 -0
  44. package/src/components/table/GenericElTableDropTarget.js +131 -0
  45. package/src/components/table/GridBtn.js +41 -0
  46. package/src/components/table/GridEntry.js +75 -0
  47. package/src/components/table/SamOption.js +53 -0
  48. package/src/components/table/SelectRenderer.js +34 -0
  49. package/src/components/table/TableRecord.js +254 -0
  50. package/src/components/table/UConverterRenderer.js +24 -0
  51. package/src/components/tools/collate.js +65 -0
  52. package/src/components/tools/orten.js +171 -0
  53. package/src/components/tools/utils.js +414 -0
  54. package/src/data/SystemUnits.js +434 -0
  55. package/src/data/systemUnits.json +430 -0
  56. package/{dist → src}/index.css +0 -0
  57. package/src/index.html +1 -0
  58. package/src/index.js +45 -0
  59. package/{dist → src}/logo.svg +0 -0
  60. package/src/simulations/SimuDS.js +52 -0
  61. package/src/simulations/SimuSG.js +54 -0
  62. package/webpack.config.js +52 -0
  63. package/dist/app.js +0 -105
  64. package/dist/components/admin/ElementManager.js +0 -54
  65. package/dist/components/details/GenDSDetails.js +0 -273
  66. package/dist/components/details/GenSgDetails.js +0 -566
  67. package/dist/components/dnd/GenericElDropTarget.js +0 -274
  68. package/dist/components/dnd/GridDnD.js +0 -77
  69. package/dist/components/dnd/PanelDnD.js +0 -171
  70. package/dist/components/fields/ButtonConfirm.js +0 -76
  71. package/dist/components/fields/ButtonTooltip.js +0 -88
  72. package/dist/components/fields/FieldLabel.js +0 -38
  73. package/dist/components/fields/GenDSMisType.js +0 -44
  74. package/dist/components/fields/GenFormGroupCb.js +0 -31
  75. package/dist/components/fields/GenProperties.js +0 -83
  76. package/dist/components/fields/GenPropertiesFields.js +0 -616
  77. package/dist/components/flow/FlowView.js +0 -88
  78. package/dist/components/flow/FlowViewerModal.js +0 -81
  79. package/dist/components/flow/LayerNode.js +0 -59
  80. package/dist/components/layers/GenPropertiesLayer.js +0 -280
  81. package/dist/components/layers/LayerModal.js +0 -81
  82. package/dist/components/layers/LayersLayout.js +0 -88
  83. package/dist/components/models/Attachment.js +0 -73
  84. package/dist/components/models/GenericSubField.js +0 -37
  85. package/dist/components/table/DropLinkRenderer.js +0 -55
  86. package/dist/components/table/DropRenderer.js +0 -45
  87. package/dist/components/table/DropTextRenderer.js +0 -45
  88. package/dist/components/table/GenericElTableDropTarget.js +0 -252
  89. package/dist/components/table/GridBtn.js +0 -102
  90. package/dist/components/table/GridEntry.js +0 -163
  91. package/dist/components/table/SamOption.js +0 -87
  92. package/dist/components/table/SelectRenderer.js +0 -52
  93. package/dist/components/table/TableRecord.js +0 -454
  94. package/dist/components/table/UConverterRenderer.js +0 -41
  95. package/dist/components/tools/collate.js +0 -103
  96. package/dist/components/tools/orten.js +0 -294
  97. package/dist/components/tools/utils.js +0 -593
  98. package/dist/data/SystemUnits.js +0 -588
  99. package/dist/index.js +0 -39
  100. package/dist/simulations/SimWF.js +0 -123
  101. package/dist/simulations/SimuDS.js +0 -118
  102. package/dist/simulations/SimuSG.js +0 -123
@@ -0,0 +1,176 @@
1
+ /* eslint-disable max-len */
2
+ /* eslint-disable react/require-default-props */
3
+ /* eslint-disable react/forbid-prop-types */
4
+ import React, { Component } from 'react';
5
+ import PropTypes from 'prop-types';
6
+ import { Card, Col, CardGroup, Row } from 'react-bootstrap';
7
+ import GenProperties from '../fields/GenProperties';
8
+ import { genUnits, showProperties, unitConversion } from '../tools/utils';
9
+ import PanelDnD from '../dnd/PanelDnD';
10
+
11
+ export default class GenPropertiesLayer extends Component {
12
+ constructor(props) {
13
+ super(props);
14
+ this.handleChange = this.handleChange.bind(this);
15
+ this.handleSubChange = this.handleSubChange.bind(this);
16
+ this.moveLayer = this.moveLayer.bind(this);
17
+ }
18
+
19
+ handleChange(e, f, k, t) {
20
+ this.props.onChange(e, f, k, t);
21
+ }
22
+
23
+ handleSubChange(e, id, f, valueOnly = false) {
24
+ const sub = f.sub_fields.find(m => m.id === id);
25
+ if (!valueOnly) {
26
+ if (e.type === 'system-defined') {
27
+ const units = genUnits(e.option_layers);
28
+ let uIdx = units.findIndex(u => u.key === e.value_system);
29
+ if (uIdx < units.length - 1) uIdx += 1; else uIdx = 0;
30
+ sub.value_system = units.length > 0 ? units[uIdx].key : '';
31
+ sub.value = unitConversion(e.option_layers, sub.value_system, e.value);
32
+ } else {
33
+ sub.value = e.target.value;
34
+ }
35
+ }
36
+ const { layer } = this.props;
37
+ const obj = { f, sub };
38
+ this.props.onSubChange(layer.key, obj, valueOnly);
39
+ }
40
+
41
+ handleClick(keyLayer, obj, val) {
42
+ const units = genUnits(obj.option_layers);
43
+ let uIdx = units.findIndex(e => e.key === val);
44
+ if (uIdx < units.length - 1) uIdx += 1; else uIdx = 0;
45
+ const update = obj;
46
+ update.value_system = units.length > 0 ? units[uIdx].key : '';
47
+ this.props.onClick(keyLayer, update);
48
+ }
49
+
50
+ views() {
51
+ const {
52
+ layer, selectOptions, id, layers, isPreview
53
+ } = this.props;
54
+ const { cols, fields, key } = layer;
55
+ const perRow = cols || 1;
56
+ const col = Math.floor(12 / perRow);
57
+ const klaz = (12 % perRow) > 0 ? 'g_col_w' : '';
58
+ const vs = [];
59
+ let op = [];
60
+ let newRow = 0;
61
+ let rowId = 1;
62
+ (fields || []).forEach((f, i) => {
63
+ if (showProperties(f, layers)) {
64
+ const unit = genUnits(f.option_layers)[0] || {};
65
+ const tabCol = (f.cols || 1) * 1;
66
+ const rCol = (f.type === 'table') ? (12 / (tabCol || 1)) : col;
67
+ newRow = (f.type === 'table') ? newRow += (perRow / (tabCol || 1)) : newRow += 1;
68
+
69
+ if (newRow > perRow) {
70
+ vs.push(<Row key={rowId}>{op}</Row>);
71
+ rowId += 1;
72
+ op = [];
73
+ newRow = (f.type === 'table') ? newRow = (perRow / (tabCol || 1)) : newRow = 1;
74
+ }
75
+ const eachCol = (
76
+ <Col key={`prop_${key}_${f.priority}_${f.field}`} md={rCol} lg={rCol} className={f.type === 'table' ? '' : klaz}>
77
+ <GenProperties
78
+ key={`${id}_${layer}_${f.field}_GenPropertiesLayer`}
79
+ layers={layers}
80
+ id={id}
81
+ layer={layer}
82
+ f_obj={f}
83
+ label={f.label}
84
+ value={f.value || ''}
85
+ description={f.description || ''}
86
+ type={f.type || 'text'}
87
+ field={f.field || 'field'}
88
+ formula={f.formula || ''}
89
+ options={(selectOptions && selectOptions[f.option_layers] && selectOptions[f.option_layers].options) || []}
90
+ onChange={event => this.handleChange(event, f.field, key, f.type)}
91
+ onSubChange={this.handleSubChange}
92
+ isEditable
93
+ isPreview={isPreview}
94
+ readOnly={false}
95
+ isRequired={f.required || false}
96
+ placeholder={f.placeholder || ''}
97
+ option_layers={f.option_layers}
98
+ value_system={f.value_system || unit.key}
99
+ onClick={() => this.handleClick(key, f, (f.value_system || unit.key))}
100
+ selectOptions={selectOptions || {}}
101
+ />
102
+ </Col>
103
+ );
104
+ op.push(eachCol);
105
+ if (newRow % perRow === 0) newRow = 0;
106
+ if ((newRow === 0) || (fields.length === (i + 1))) {
107
+ vs.push(<Row key={rowId}>{op}</Row>);
108
+ rowId += 1;
109
+ op = [];
110
+ }
111
+ } else if (fields.length === (i + 1)) {
112
+ vs.push(<Row key={rowId}>{op}</Row>);
113
+ rowId += 1;
114
+ op = [];
115
+ }
116
+ });
117
+ return vs;
118
+ }
119
+
120
+ moveLayer(src, tar) {
121
+ this.handleChange(null, src, tar, 'drop-layer');
122
+ }
123
+
124
+ render() {
125
+ const { id, layer, activeWF } = this.props;
126
+ const { color, style, label } = layer;
127
+ let bs = color || 'default';
128
+ const cl = (style || 'panel_generic_heading').replace('panel_generic_heading', 'panel_generic_heading_slim');
129
+ // panel header color is based on input bs value
130
+ const panelDnD = (<PanelDnD
131
+ type="gen_panel"
132
+ layer={layer}
133
+ field="layer"
134
+ rowValue={{ id: layer.key }}
135
+ handleMove={this.moveLayer}
136
+ id={id}
137
+ handleChange={this.handleChange}
138
+ bs={bs}
139
+ />);
140
+ const panelHeader = label === '' ? (<span />) : (
141
+ <Card.Heading className={cl}>
142
+ <Card.Title toggle>{label}</Card.Title>
143
+ </Card.Heading>
144
+ );
145
+ const noneKlass = bs === 'none' ? 'generic_panel_none' : '';
146
+ if (bs === 'none') bs = 'default';
147
+ return (
148
+ <CardGroup id="accordion_generic_layer" defaultActiveKey="1" style={{ marginBottom: '0px' }}>
149
+ <Card bg={bs} className={`panel_generic_properties ${noneKlass}`}>
150
+
151
+ <Card.Body className="panel_generic_properties_body">{this.views()}</Card.Body>
152
+ </Card>
153
+ </CardGroup>
154
+ );
155
+ }
156
+ }
157
+
158
+ GenPropertiesLayer.propTypes = {
159
+ id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // element id or new id
160
+ layer: PropTypes.object,
161
+ selectOptions: PropTypes.object,
162
+ onChange: PropTypes.func.isRequired,
163
+ onSubChange: PropTypes.func.isRequired,
164
+ onClick: PropTypes.func,
165
+ layers: PropTypes.object.isRequired,
166
+ isPreview: PropTypes.bool,
167
+ activeWF: PropTypes.bool
168
+ };
169
+
170
+ GenPropertiesLayer.defaultProps = {
171
+ id: 0,
172
+ selectOptions: {},
173
+ onClick: () => {},
174
+ isPreview: false,
175
+ activeWF: false
176
+ };
@@ -0,0 +1,52 @@
1
+ /* eslint-disable react/forbid-prop-types */
2
+ import React from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import { Button, Tooltip, Modal, OverlayTrigger } from 'react-bootstrap';
5
+ import { sortBy } from 'lodash';
6
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
7
+
8
+ const block = (layer, fnAdd) => (
9
+ <div className="generic_layer_column">
10
+ <div>
11
+ <div><b>{layer.label}</b><br />({layer.key})</div>
12
+ <OverlayTrigger delayShow={1000} placement="top" overlay={<Tooltip id="_tooltip_layers">click to add layer</Tooltip>}>
13
+ <Button bsStyle="primary" onClick={event => fnAdd(event, layer)}><FontAwesomeIcon icon="fas fa-plus" /></Button>
14
+ </OverlayTrigger>
15
+ </div>
16
+ </div>
17
+ );
18
+
19
+ const drawLayout = (layers, fnAdd) => {
20
+ const layout = [];
21
+ layers.forEach((layer) => { layout.push(<div key={layer.key}>{block(layer, fnAdd)}</div>); });
22
+ return layout;
23
+ };
24
+
25
+ const LayerModal = (props) => {
26
+ const {
27
+ show, layers, fnClose, fnAdd
28
+ } = props;
29
+ if (!show) return null;
30
+ const sortedLayers = sortBy(layers, ['position', 'wf_position']) || [];
31
+ if (sortedLayers.length < 1) return null;
32
+ const layout = drawLayout(sortedLayers, fnAdd);
33
+ return (
34
+ <Modal show={show} onHide={fnClose}>
35
+ <Modal.Header closeButton><Modal.Title>Choose Layer</Modal.Title></Modal.Header>
36
+ <Modal.Body>
37
+ <div style={{ maxHeight: '80vh', overflow: 'auto' }}>
38
+ <div className="generic_grid">{layout}</div>
39
+ </div>
40
+ </Modal.Body>
41
+ </Modal>
42
+ );
43
+ };
44
+
45
+ LayerModal.propTypes = {
46
+ show: PropTypes.bool.isRequired,
47
+ layers: PropTypes.object.isRequired,
48
+ fnClose: PropTypes.func.isRequired,
49
+ fnAdd: PropTypes.func.isRequired
50
+ };
51
+
52
+ export default LayerModal;
@@ -0,0 +1,68 @@
1
+ import React from 'react';
2
+ import { sortBy } from 'lodash';
3
+ import GenPropertiesLayer from './GenPropertiesLayer';
4
+
5
+ const LayersLayout = (
6
+ layers, options, funcChange,
7
+ funcSubChange = () => {}, funcClick = () => {}, layout = [], id = 0, isPreview = false,
8
+ activeWF = false
9
+ ) => {
10
+ const sortedLayers = sortBy(layers, ['position', 'wf_position']) || [];
11
+ sortedLayers.forEach((layer, idx) => {
12
+ const uk = `${layer.key}_${idx}`;
13
+ if (typeof layer.cond_fields === 'undefined' || layer.cond_fields == null || layer.cond_fields.length === 0) {
14
+ const ig = (
15
+ <GenPropertiesLayer
16
+ id={id}
17
+ key={uk}
18
+ layer={layer}
19
+ onChange={funcChange}
20
+ onSubChange={funcSubChange}
21
+ selectOptions={options}
22
+ onClick={funcClick}
23
+ layers={layers}
24
+ isPreview={isPreview}
25
+ activeWF={activeWF}
26
+ />
27
+ );
28
+ layout.push(ig);
29
+ } else if (layer.cond_fields && layer.cond_fields.length > 0) {
30
+ let showLayer = false;
31
+
32
+ for (let i = 0; i < layer.cond_fields.length; i += 1) {
33
+ const cond = layer.cond_fields[i] || {};
34
+ const fd = ((layers[cond.layer] || {}).fields || [])
35
+ .find(f => f.field === cond.field) || {};
36
+ if (fd.type === 'checkbox' && ((['false', 'no', 'f', '0'].includes((cond.value || '').trim().toLowerCase()) && (typeof (fd && fd.value) === 'undefined' || fd.value === false)) ||
37
+ (['true', 'yes', 't', '1'].includes((cond.value || '').trim().toLowerCase()) && (typeof fd.value !== 'undefined' && fd.value === true)))) {
38
+ showLayer = true;
39
+ break;
40
+ } else if (['text', 'select'].includes(fd.type) && (typeof (fd && fd.value) !== 'undefined' && (fd.value || '').trim() === (cond.value || '').trim())) {
41
+ showLayer = true;
42
+ break;
43
+ }
44
+ }
45
+
46
+ if (showLayer === true) {
47
+ const igs = (
48
+ <GenPropertiesLayer
49
+ id={id}
50
+ key={uk}
51
+ layer={layer}
52
+ onChange={funcChange}
53
+ onSubChange={funcSubChange}
54
+ selectOptions={options}
55
+ onClick={funcClick}
56
+ layers={layers}
57
+ isPreview={isPreview}
58
+ activeWF={activeWF}
59
+ />
60
+ );
61
+ layout.push(igs);
62
+ }
63
+ }
64
+ });
65
+ return layout;
66
+ };
67
+
68
+ export default LayersLayout;
@@ -0,0 +1,37 @@
1
+ import { v4 as uuid } from 'uuid';
2
+
3
+ export default class Attachment {
4
+ constructor(args) {
5
+ Object.assign(this, args);
6
+ if (!this.id) { this.id = Attachment.buildID(); }
7
+ }
8
+
9
+ static buildID() { return uuid(); }
10
+
11
+ static fromFile(file) {
12
+ return new Attachment({
13
+ file,
14
+ name: file.name,
15
+ filename: file.name,
16
+ identifier: file.id,
17
+ is_deleted: false,
18
+ });
19
+ }
20
+
21
+ get isNew() {
22
+ return this.is_new === true;
23
+ }
24
+
25
+ serialize() {
26
+ return super.serialize({
27
+ filename: this.filename,
28
+ identifier: this.identifier,
29
+ file: this.file,
30
+ thumb: this.thumb,
31
+ content_type: this.content_type,
32
+ is_deleted: this.is_deleted,
33
+ id: this.id,
34
+ is_new: this.isNew || false
35
+ });
36
+ }
37
+ }
@@ -0,0 +1,10 @@
1
+ import { v4 as uuid } from 'uuid';
2
+
3
+ export default class GenericSubField {
4
+ constructor(args) {
5
+ Object.assign(this, args);
6
+ if (!this.id) { this.id = GenericSubField.buildID(); }
7
+ }
8
+
9
+ static buildID() { return uuid(); }
10
+ }
@@ -0,0 +1,35 @@
1
+ /* eslint-disable jsx-a11y/anchor-is-valid */
2
+ /* eslint-disable jsx-a11y/click-events-have-key-events */
3
+ /* eslint-disable jsx-a11y/interactive-supports-focus */
4
+ /* eslint-disable react/forbid-prop-types */
5
+ import React from 'react';
6
+ import PropTypes from 'prop-types';
7
+ // import Aviator from 'aviator';
8
+ // import UIStore from '../stores/UIStore';
9
+
10
+ // const linkSample = (type, id) => {
11
+ // const { currentCollection, isSync } = UIStore.getState();
12
+ // const collectionUrl = (!isNaN(id)) ?
13
+ // `${currentCollection.id}/${type}/${id}` : `${currentCollection.id}/${type}`;
14
+ // Aviator.navigate(isSync ? `/scollection/${collectionUrl}` : `/collection/${collectionUrl}`);
15
+ // };
16
+
17
+ const DropLinkRenderer = (props) => {
18
+ const { sField, node, onLink } = props;
19
+ const dId = ((node.data[sField.id] || {}).value || {}).el_id || '';
20
+ const dVal = ((node.data[sField.id] || {}).value || {}).el_short_label || ' ';
21
+ if (dId === '') return <div />;
22
+ return (
23
+ <a role="link" onClick={() => onLink('sample', dId)} style={{ cursor: 'pointer' }}>
24
+ <span className="reaction-material-link">{dVal}</span>
25
+ </a>
26
+ );
27
+ };
28
+
29
+ DropLinkRenderer.propTypes = {
30
+ sField: PropTypes.object.isRequired,
31
+ node: PropTypes.object.isRequired,
32
+ onLink: PropTypes.func.isRequired
33
+ };
34
+
35
+ export default DropLinkRenderer;
@@ -0,0 +1,31 @@
1
+ /* eslint-disable react/forbid-prop-types */
2
+ import React from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import { cloneDeep } from 'lodash';
5
+ import GenericElTableDropTarget from './GenericElTableDropTarget';
6
+
7
+ const DropRenderer = (props) => {
8
+ const {
9
+ opt, sField, onChange, node
10
+ } = props;
11
+ if (!['drag_molecule', 'drag_sample'].includes(sField.type)) return null;
12
+ const { data } = node;
13
+ opt.dndItems = [sField.type.split('_')[1]];
14
+ opt.sField = sField;
15
+ opt.data = data;
16
+ const oopt = cloneDeep(opt);
17
+ return (
18
+ <div className="drop_generic_properties drop_generic_table_wrap">
19
+ <GenericElTableDropTarget opt={oopt} onDrop={onChange} />
20
+ </div>
21
+ );
22
+ };
23
+
24
+ DropRenderer.propTypes = {
25
+ sField: PropTypes.object.isRequired,
26
+ opt: PropTypes.object.isRequired,
27
+ onChange: PropTypes.func.isRequired,
28
+ node: PropTypes.object.isRequired
29
+ };
30
+
31
+ export default DropRenderer;
@@ -0,0 +1,25 @@
1
+ /* eslint-disable react/forbid-prop-types */
2
+ import React from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import { OverlayTrigger, Tooltip } from 'react-bootstrap';
5
+
6
+ const DropTextRenderer = (props) => {
7
+ const { attr, sField, node } = props;
8
+ let displayValue = ((node.data[sField.id] || {}).value || {})[`el_${attr.value}`] || '';
9
+ displayValue = (attr.value === 'molecular_weight' && displayValue !== '') ? displayValue.toFixed(6) : displayValue;
10
+ return (
11
+ <OverlayTrigger placement="top" overlay={<Tooltip id="copy_clipboard">copy to clipboard</Tooltip>}>
12
+ <div role="button" data-clipboard-text={displayValue} className="clipboardBtn" style={{ wordBreak: 'break-all', cursor: 'copy' }}>
13
+ {displayValue}
14
+ </div>
15
+ </OverlayTrigger>
16
+ );
17
+ };
18
+
19
+ DropTextRenderer.propTypes = {
20
+ attr: PropTypes.object.isRequired,
21
+ sField: PropTypes.object.isRequired,
22
+ node: PropTypes.object.isRequired
23
+ };
24
+
25
+ export default DropTextRenderer;
@@ -0,0 +1,131 @@
1
+ /* eslint-disable no-unused-vars */
2
+ /* eslint-disable react/forbid-prop-types */
3
+ import React, { Component } from 'react';
4
+ import PropTypes from 'prop-types';
5
+ import { v4 as uuid } from 'uuid';
6
+ import { DropTarget } from 'react-dnd';
7
+ import { Tooltip, OverlayTrigger, Popover, Button } from 'react-bootstrap';
8
+
9
+ const base = (opt, iconClass, onDrop = () => {}, params = {}) => {
10
+ const noSvg = '/images/not_available.svg';
11
+ if (opt.value && opt.value.el_id) {
12
+ const label = opt.value.el_label;
13
+ const svg = (opt.value.el_svg && opt.value.el_svg.endsWith('.svg')) ? opt.value.el_svg : noSvg;
14
+ const pop = (
15
+ <Popover id="popover-svg" title={label} style={{ maxWidth: 'none', maxHeight: 'none' }}>
16
+ <img src={svg} style={{ height: '26vh', width: '26vh' }} alt="" />
17
+ </Popover>
18
+ );
19
+ const simg = (path, txt) => ((path && path !== '') ? (
20
+ <div className="s-img">
21
+ <OverlayTrigger delayShow={1000} trigger={['hover']} placement="top" rootClose onHide={null} overlay={pop}>
22
+ <img className="generic_grid_img" src={path} alt="" />
23
+ </OverlayTrigger>
24
+ <div className="del_btn">
25
+ <OverlayTrigger delayShow={1000} placement="top" overlay={<Tooltip id={uuid()}>remove this molecule</Tooltip>}>
26
+ <Button className="btn_del" bsSize="xsmall" onClick={() => onDrop({}, params)} ><i className="fa fa-trash-o" aria-hidden="true" /></Button>
27
+ </OverlayTrigger>
28
+ </div>
29
+ </div>
30
+ ) : (<div className="data" style={{ width: '4vw' }}>{txt}</div>));
31
+ return simg(svg, label);
32
+ }
33
+ return (<span className={`icon-${iconClass} indicator`} style={{ width: '4vw' }} />);
34
+ };
35
+
36
+ const show = (opt, iconClass, onDrop) => {
37
+ if (opt.type === 'table') {
38
+ const sField = opt.sField || {};
39
+ const subVal = opt.data[sField.id];
40
+ const { data } = opt;
41
+ return base(subVal, iconClass, onDrop, { sField, data });
42
+ }
43
+ return base(opt, iconClass);
44
+ };
45
+
46
+ const source = (type, props, id) => {
47
+ let isAssoc = false;
48
+ const taggable = (props && props.tag && props.tag.taggable_data) || {};
49
+ if (taggable.element && taggable.element.id === id) {
50
+ isAssoc = false;
51
+ } else {
52
+ isAssoc = !!(taggable.reaction_id || taggable.wellplate_id || taggable.element);
53
+ }
54
+
55
+ switch (type) {
56
+ case 'molecule':
57
+ return {
58
+ el_id: props.molecule.id,
59
+ el_type: 'molecule',
60
+ el_label: props.molecule.cano_smiles || props.molecule_formula || props.molecule_name_label,
61
+ el_inchikey: props.molecule.inchikey,
62
+ el_smiles: props.molecule.cano_smiles,
63
+ el_iupac: props.molecule.iupac_name,
64
+ el_molecular_weight: props.molecule.molecular_weight,
65
+ el_svg: `/images/molecules/${props.molecule.molecule_svg_file}`,
66
+ };
67
+ case 'sample':
68
+ return {
69
+ el_id: props.id,
70
+ is_new: true,
71
+ cr_opt: 1,
72
+ isAssoc,
73
+ el_type: 'sample',
74
+ el_label: props.short_label,
75
+ el_short_label: props.short_label,
76
+ el_name: props.name,
77
+ el_external_label: props.external_label,
78
+ el_molecular_weight: props.molecule_molecular_weight,
79
+ el_svg: props.sample_svg_file ? `/images/samples/${props.sample_svg_file}` : `/images/molecules/${props.molecule.molecule_svg_file}`,
80
+ };
81
+ default:
82
+ return {
83
+ el_id: props.id,
84
+ is_new: true,
85
+ cr_opt: 0,
86
+ el_type: props.type,
87
+ el_label: props.short_label,
88
+ };
89
+ }
90
+ };
91
+
92
+ const dropTarget = {
93
+ drop(targetProps, monitor) {
94
+ const sourceProps = monitor.getItem().element;
95
+ const type = targetProps.opt.sField.type.split('_')[1];
96
+ const sourceTag = source(type, sourceProps, targetProps.opt.id);
97
+ targetProps.onDrop(sourceTag, targetProps.opt);
98
+ },
99
+ canDrop(targetProps, monitor) {
100
+ return true;
101
+ },
102
+ };
103
+
104
+ const dropCollect = (connect, monitor) => ({
105
+ connectDropTarget: connect.dropTarget(),
106
+ isOver: monitor.isOver(),
107
+ canDrop: monitor.canDrop()
108
+ });
109
+
110
+ class GenericElTableDropTarget extends Component {
111
+ render() {
112
+ const {
113
+ connectDropTarget, isOver, canDrop, opt, onDrop
114
+ } = this.props;
115
+ const className = `target${isOver ? ' is-over' : ''}${canDrop ? ' can-drop' : ''}`;
116
+ return connectDropTarget(<div className={className} style={{ display: 'inline-flex', justifyContent: 'center' }}>{show(opt, 'sample', onDrop)}</div>);
117
+ }
118
+ }
119
+
120
+ export default
121
+ DropTarget(props => props.opt.dndItems, dropTarget, dropCollect)(GenericElTableDropTarget);
122
+
123
+ GenericElTableDropTarget.propTypes = {
124
+ connectDropTarget: PropTypes.func.isRequired,
125
+ isOver: PropTypes.bool.isRequired,
126
+ canDrop: PropTypes.bool.isRequired,
127
+ opt: PropTypes.object.isRequired,
128
+ onDrop: PropTypes.func
129
+ };
130
+
131
+ GenericElTableDropTarget.defaultProps = { onDrop: () => {} };
@@ -0,0 +1,41 @@
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 { Button, OverlayTrigger, Tooltip } from 'react-bootstrap';
6
+ import GridDnD from '../dnd/GridDnD';
7
+
8
+ const AddRowBtn = ({ addRow }) => (
9
+ <OverlayTrigger delayShow={1000} placement="top" overlay={<Tooltip id={uuid()}>add entry</Tooltip>}>
10
+ <Button onClick={() => addRow()} bsSize="xsmall" bsStyle="primary"><i className="fa fa-plus" aria-hidden="true" /></Button>
11
+ </OverlayTrigger>
12
+ );
13
+
14
+ AddRowBtn.propTypes = { addRow: PropTypes.func.isRequired };
15
+
16
+ const DelRowBtn = ({ delRow, node }) => {
17
+ const { data } = node;
18
+ return (
19
+ <OverlayTrigger delayShow={1000} placement="top" overlay={<Tooltip id={uuid()}>remove</Tooltip>}>
20
+ <Button onClick={() => delRow(data)} bsSize="xsmall"><i className="fa fa-times" aria-hidden="true" /></Button>
21
+ </OverlayTrigger>);
22
+ };
23
+
24
+ DelRowBtn.propTypes = { delRow: PropTypes.func.isRequired, node: PropTypes.object.isRequired };
25
+
26
+ const NullRowBtn = () => (<div className="grid-btn-none"><span className="fa fa-arrows" /></div>);
27
+
28
+ const DnDRowBtn = ({
29
+ moveRow, field, type, node
30
+ }) => (
31
+ <GridDnD field={field} type={type} rowValue={node.data} handleMove={moveRow} />
32
+ );
33
+
34
+ DnDRowBtn.propTypes = {
35
+ moveRow: PropTypes.func.isRequired,
36
+ field: PropTypes.string.isRequired,
37
+ type: PropTypes.string.isRequired,
38
+ node: PropTypes.object.isRequired
39
+ };
40
+
41
+ export { AddRowBtn, DelRowBtn, DnDRowBtn, NullRowBtn };