chem-generic-ui 0.1.45 → 0.1.46

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 (73) hide show
  1. package/.babelrc +11 -0
  2. package/.eslintrc +23 -0
  3. package/.tool-versions +3 -0
  4. package/chem-generic-ui-v0.1.41.tgz +0 -0
  5. package/dist/bundle.js +1 -1
  6. package/dist/bundle.js.LICENSE.txt +70 -0
  7. package/dist/ds_details.json +57 -0
  8. package/dist/ds_klass.json +102 -0
  9. package/dist/ds_props.json +54 -0
  10. package/dist/index.html +14 -0
  11. package/dist/sg_details.json +2036 -0
  12. package/dist/sg_klass.json +850 -0
  13. package/dist/units_system.json +430 -0
  14. package/package.json +3 -6
  15. package/public/ds_details.json +57 -0
  16. package/public/ds_klass.json +102 -0
  17. package/public/ds_props.json +54 -0
  18. package/public/favicon.ico +0 -0
  19. package/public/images/not_available.svg +1 -0
  20. package/public/index.html +47 -0
  21. package/public/logo192.png +0 -0
  22. package/public/logo512.png +0 -0
  23. package/public/manifest.json +25 -0
  24. package/public/robots.txt +3 -0
  25. package/public/sg_details.json +2036 -0
  26. package/public/sg_klass.json +850 -0
  27. package/public/test/ds_props.json +54 -0
  28. package/public/units_system.json +430 -0
  29. package/src/asserts/bootstrap-theme.min.css +6 -0
  30. package/src/asserts/bootstrap.min.css +6 -0
  31. package/src/asserts/main.css +458 -0
  32. package/src/asserts/main.scss +490 -0
  33. package/src/components/admin/ElementManager.js +28 -0
  34. package/src/components/details/GenDSDetails.js +164 -0
  35. package/src/components/details/GenSgDetails.js +396 -0
  36. package/src/components/dnd/DragDropItemTypes.js +13 -0
  37. package/src/components/dnd/GenericElDropTarget.js +160 -0
  38. package/src/components/dnd/GridDnD.js +42 -0
  39. package/src/components/dnd/PanelDnD.js +85 -0
  40. package/src/components/fields/ButtonConfirm.js +45 -0
  41. package/src/components/fields/ButtonTooltip.js +46 -0
  42. package/src/components/fields/FieldLabel.js +18 -0
  43. package/src/components/fields/GenDSMisType.js +20 -0
  44. package/src/components/fields/GenFormGroupCb.js +17 -0
  45. package/src/components/fields/GenProperties.js +56 -0
  46. package/src/components/fields/GenPropertiesFields.js +440 -0
  47. package/src/components/layers/GenPropertiesLayer.js +178 -0
  48. package/src/components/layers/LayerModal.js +52 -0
  49. package/src/components/layers/LayersLayout.js +68 -0
  50. package/src/components/models/Attachment.js +37 -0
  51. package/src/components/models/GenericSubField.js +10 -0
  52. package/src/components/table/DropLinkRenderer.js +35 -0
  53. package/src/components/table/DropRenderer.js +31 -0
  54. package/src/components/table/DropTextRenderer.js +25 -0
  55. package/src/components/table/GenericElTableDropTarget.js +131 -0
  56. package/src/components/table/GridBtn.js +41 -0
  57. package/src/components/table/GridEntry.js +75 -0
  58. package/src/components/table/SamOption.js +53 -0
  59. package/src/components/table/SelectRenderer.js +34 -0
  60. package/src/components/table/TableRecord.js +254 -0
  61. package/src/components/table/UConverterRenderer.js +24 -0
  62. package/src/components/tools/collate.js +65 -0
  63. package/src/components/tools/orten.js +171 -0
  64. package/src/components/tools/utils.js +414 -0
  65. package/src/data/SystemUnits.js +434 -0
  66. package/src/data/systemUnits.json +430 -0
  67. package/src/index.css +13 -0
  68. package/src/index.html +1 -0
  69. package/src/index.js +45 -0
  70. package/src/logo.svg +1 -0
  71. package/src/simulations/SimuDS.js +52 -0
  72. package/src/simulations/SimuSG.js +54 -0
  73. package/webpack.config.js +46 -0
@@ -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 };
@@ -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, Radio, 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
+ <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
+ </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
+ <Radio
27
+ name={`dropS_${rUUID}`}
28
+ checked={fValue.cr_opt === 1}
29
+ onChange={() => onChange({ node, subField: sField, crOpt: 1 })}
30
+ >
31
+ Split
32
+ </Radio>
33
+ </OverlayTrigger>
34
+ <OverlayTrigger delayShow={1000} placement="right" overlay={<Tooltip id={uuid()}>duplicate the sample first and then associate with it</Tooltip>}>
35
+ <Radio
36
+ name={`dropS_${rUUID}`}
37
+ checked={fValue.cr_opt === 2}
38
+ onChange={() => onChange({ node, subField: sField, crOpt: 2 })}
39
+ >
40
+ Copy
41
+ </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;