hise-flow-graphs 1.0.21 → 1.1.0
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/.env.dev +1 -0
- package/.env.prod +1 -0
- package/.env.stage +1 -0
- package/dist/main.js +1 -1
- package/package.json +7 -2
- package/src/@types/CertificateTypes.ts +25 -15
- package/src/components/Certificates/CertificateGraph/LayerBackButton.tsx +1 -1
- package/src/components/Certificates/CertificateGraph/NodeAttributes.tsx +10 -10
- package/src/components/Certificates/CertificateGraph/helpers.tsx +24 -17
- package/src/components/Certificates/CertificateGraph/index.tsx +23 -28
- package/src/components/Certificates/EditCertificate/EditNode.tsx +8 -12
- package/src/components/Certificates/EditCertificate/{EditNodeModal.jsx → EditNodeModal.tsx} +57 -50
- package/src/components/Certificates/EditCertificate/MaskMetadataModal/EMRMaskingTables.tsx +69 -0
- package/src/components/Certificates/EditCertificate/MaskMetadataModal/MaskMetadataTable.tsx +105 -0
- package/src/components/Certificates/EditCertificate/MaskMetadataModal/helpers.ts +41 -0
- package/src/components/Certificates/EditCertificate/MaskMetadataModal/index.tsx +167 -0
- package/src/components/Certificates/EditCertificate/helpers.ts +2 -44
- package/src/components/Certificates/EditCertificate/{index.jsx → index.tsx} +9 -4
- package/src/components/Certificates/FileLayerNode/index.tsx +12 -23
- package/src/components/Certificates/ReadCertificate/MetadataModal/MetadataTable.tsx +100 -0
- package/src/components/Certificates/ReadCertificate/MetadataModal/helpers.tsx +46 -0
- package/src/components/Certificates/ReadCertificate/MetadataModal/index.tsx +142 -0
- package/src/components/Certificates/ReadCertificate/ReadNode.tsx +7 -2
- package/src/components/Certificates/ReadCertificate/index.tsx +2 -3
- package/src/components/Certificates/ReviewCertificate/RestrictNode/index.tsx +161 -0
- package/src/components/Certificates/ReviewCertificate/ReviewNode.tsx +8 -5
- package/src/components/Certificates/ReviewCertificate/ReviewNodes/index.tsx +5 -4
- package/src/components/Certificates/ReviewCertificate/helpers.ts +18 -60
- package/src/components/Certificates/ReviewCertificate/{index.jsx → index.tsx} +14 -10
- package/src/components/Certificates/WorkspaceCertificate/ReplicaIDENode/index.tsx +5 -2
- package/src/components/Certificates/WorkspaceCertificate/ReplicaPipelineNode/index.tsx +4 -2
- package/src/components/Certificates/WorkspaceCertificate/RestrictedNode/index.tsx +106 -0
- package/src/components/Certificates/WorkspaceCertificate/WorkspaceFileNode/index.tsx +6 -2
- package/src/components/Certificates/WorkspaceCertificate/WorkspaceIDENode/index.tsx +10 -5
- package/src/components/Certificates/WorkspaceCertificate/WorkspaceNode/index.tsx +9 -3
- package/src/components/Certificates/WorkspaceCertificate/WorkspacePipelineNode/index.tsx +5 -5
- package/src/components/Certificates/WorkspaceCertificate/helpers.ts +7 -41
- package/src/components/Certificates/WorkspaceCertificate/index.tsx +10 -11
- package/src/components/Certificates/WorkspaceCertificate/style.css +0 -10
- package/src/index.ts +2 -2
- package/src/state/GraphContext.tsx +23 -22
- package/src/utils/getCertificateBody.ts +89 -0
- package/webpack.config.js +71 -54
- package/src/components/Certificates/EditCertificate/MaskMetadataModal.jsx +0 -299
- package/src/components/Certificates/FileLayerNode/helpers.ts +0 -31
- package/src/components/Certificates/ReadCertificate/MetadataModal/helpers.jsx +0 -22
- package/src/components/Certificates/ReadCertificate/MetadataModal/index.jsx +0 -169
- package/src/components/Certificates/ReadCertificate/helpers.ts +0 -38
- package/src/components/Certificates/ReviewCertificate/ReviewNodes/AllNodesModal.jsx +0 -63
- package/src/components/Certificates/ReviewCertificate/ReviewNodes/SingleNodeModal.jsx +0 -83
package/webpack.config.js
CHANGED
|
@@ -1,60 +1,77 @@
|
|
|
1
|
+
const webpack = require('webpack');
|
|
1
2
|
const path = require('path');
|
|
3
|
+
const dotenv = require('dotenv');
|
|
4
|
+
dotenv.config();
|
|
2
5
|
|
|
3
|
-
module.exports = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
},
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
6
|
+
module.exports = (env) => {
|
|
7
|
+
const envFile = `.env.${env.ENVIRONMENT}`;
|
|
8
|
+
|
|
9
|
+
const envConfig = dotenv.config({ path: envFile }).parsed;
|
|
10
|
+
|
|
11
|
+
const envKeys = Object.keys(envConfig).reduce((prev, next) => {
|
|
12
|
+
prev[`process.env.${next}`] = JSON.stringify(envConfig[next]);
|
|
13
|
+
return prev;
|
|
14
|
+
}, {});
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
mode: 'production',
|
|
18
|
+
entry: path.join(__dirname, 'src', 'index.ts'),
|
|
19
|
+
output: {
|
|
20
|
+
library: 'hise-flow-graphs',
|
|
21
|
+
libraryTarget: 'umd',
|
|
22
|
+
path: path.resolve(__dirname, 'dist'),
|
|
23
|
+
filename: 'main.js',
|
|
24
|
+
},
|
|
25
|
+
plugins: [
|
|
26
|
+
new webpack.DefinePlugin(envKeys),
|
|
27
|
+
],
|
|
28
|
+
module: {
|
|
29
|
+
rules: [
|
|
30
|
+
{
|
|
31
|
+
test: /\.(js|jsx)$/,
|
|
32
|
+
exclude: /node_modules/,
|
|
33
|
+
use: {
|
|
34
|
+
loader: 'babel-loader',
|
|
35
|
+
options: {
|
|
36
|
+
presets: [
|
|
37
|
+
'@babel/preset-env',
|
|
38
|
+
'@babel/preset-react',
|
|
39
|
+
],
|
|
40
|
+
}
|
|
24
41
|
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
test: /\.(ts|tsx)$/,
|
|
45
|
+
exclude: /node_modules/,
|
|
46
|
+
use: {
|
|
47
|
+
loader: 'ts-loader',
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
test: /\.css$/,
|
|
52
|
+
use: ['style-loader', 'css-loader'],
|
|
53
|
+
},
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
resolve: {
|
|
57
|
+
extensions: ['.js', '.jsx', '.tsx', '.ts'],
|
|
58
|
+
},
|
|
59
|
+
externals: {
|
|
60
|
+
react: {
|
|
61
|
+
umd: 'react',
|
|
62
|
+
commonjs: 'react',
|
|
63
|
+
commonjs2: 'react',
|
|
33
64
|
},
|
|
34
|
-
{
|
|
35
|
-
|
|
36
|
-
|
|
65
|
+
'react-dom': {
|
|
66
|
+
umd: 'react-dom',
|
|
67
|
+
commonjs: 'react-dom',
|
|
68
|
+
commonjs2: 'react-dom',
|
|
37
69
|
},
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
externals: {
|
|
44
|
-
react: {
|
|
45
|
-
umd: 'react',
|
|
46
|
-
commonjs: 'react',
|
|
47
|
-
commonjs2: 'react',
|
|
48
|
-
},
|
|
49
|
-
'react-dom': {
|
|
50
|
-
umd: 'react-dom',
|
|
51
|
-
commonjs: 'react-dom',
|
|
52
|
-
commonjs2: 'react-dom',
|
|
70
|
+
'react/jsx-runtime': {
|
|
71
|
+
umd: 'react/jsx-runtime',
|
|
72
|
+
commonjs: 'react/jsx-runtime',
|
|
73
|
+
commonjs2: 'react/jsx-runtime',
|
|
74
|
+
}
|
|
53
75
|
},
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
commonjs: 'react/jsx-runtime',
|
|
57
|
-
commonjs2: 'react/jsx-runtime',
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
};
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import * as R from 'ramda';
|
|
3
|
-
import { Button, ConfirmationModal, HISETabs, MessageStripe } from 'hise-components';
|
|
4
|
-
import { useGraph } from '../../../state/GraphContext';
|
|
5
|
-
import { getKey, getValue } from '../CertificateGraph/helpers';
|
|
6
|
-
|
|
7
|
-
const labels = {
|
|
8
|
-
labData: 'Lab Results',
|
|
9
|
-
surveyData: 'Survey Data',
|
|
10
|
-
emrData: 'EMR Data',
|
|
11
|
-
demographicsData: 'Demographics Data',
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const MaskAllSectionButton = (props) => {
|
|
15
|
-
return (
|
|
16
|
-
<Button
|
|
17
|
-
className="mt-3 mb-2 float-right"
|
|
18
|
-
onClick={() => props.update({
|
|
19
|
-
...props.currMetadata,
|
|
20
|
-
[props.dataType]: {},
|
|
21
|
-
})}
|
|
22
|
-
>
|
|
23
|
-
{labels[props.dataType]}
|
|
24
|
-
: Mask All
|
|
25
|
-
</Button>
|
|
26
|
-
);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const maskRow = (variable, currMetadata, dataType, update) => {
|
|
30
|
-
const omitted = R.omit(
|
|
31
|
-
[variable],
|
|
32
|
-
currMetadata[dataType],
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
update({
|
|
36
|
-
...currMetadata,
|
|
37
|
-
[dataType]: omitted,
|
|
38
|
-
});
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const maskEMRRow = (variable, currMetadata, update, emrEntry, emrIndex) => update({
|
|
42
|
-
...currMetadata,
|
|
43
|
-
emrData: [
|
|
44
|
-
...currMetadata.emrData.slice(0, emrIndex),
|
|
45
|
-
{
|
|
46
|
-
...emrEntry,
|
|
47
|
-
patientData: R.omit([variable], emrEntry.patientData),
|
|
48
|
-
},
|
|
49
|
-
...currMetadata.emrData.slice((Number(emrIndex) + 1)),
|
|
50
|
-
],
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const MaskMetadataTable = ({
|
|
54
|
-
metadata, scheme, tab, setMetadata, emrEntry, emrIndex,
|
|
55
|
-
}) => {
|
|
56
|
-
if (R.isNil(metadata) || R.isEmpty(metadata)) return null;
|
|
57
|
-
|
|
58
|
-
const items = Object.entries((tab !== 'emrData') ? metadata[tab] : emrEntry.patientData);
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<>
|
|
62
|
-
<MaskAllSectionButton dataType={tab} currMetadata={metadata} update={setMetadata} />
|
|
63
|
-
|
|
64
|
-
<table className="table">
|
|
65
|
-
<thead>
|
|
66
|
-
<tr>
|
|
67
|
-
<th scope="col" />
|
|
68
|
-
<th scope="col">Variable</th>
|
|
69
|
-
<th scope="col">Value</th>
|
|
70
|
-
</tr>
|
|
71
|
-
</thead>
|
|
72
|
-
<tbody>
|
|
73
|
-
{items.map((item) => (
|
|
74
|
-
<tr key={item.variable}>
|
|
75
|
-
<td>
|
|
76
|
-
<Button
|
|
77
|
-
key={`${item}-mask-btn`}
|
|
78
|
-
icon="fas fa-times"
|
|
79
|
-
color="link"
|
|
80
|
-
className="btn-sm text-danger"
|
|
81
|
-
noText
|
|
82
|
-
onClick={() => {
|
|
83
|
-
if (tab === 'emrData') {
|
|
84
|
-
maskEMRRow(item[0], metadata, setMetadata, emrEntry, emrIndex);
|
|
85
|
-
} else {
|
|
86
|
-
maskRow(item[0], metadata, tab, setMetadata);
|
|
87
|
-
}
|
|
88
|
-
}}
|
|
89
|
-
/>
|
|
90
|
-
</td>
|
|
91
|
-
<td>
|
|
92
|
-
{getKey(item[0], scheme, tab)}
|
|
93
|
-
</td>
|
|
94
|
-
<td>
|
|
95
|
-
{getValue(item[0], item[1], scheme, tab)}
|
|
96
|
-
</td>
|
|
97
|
-
</tr>
|
|
98
|
-
))}
|
|
99
|
-
</tbody>
|
|
100
|
-
</table>
|
|
101
|
-
</>
|
|
102
|
-
);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
MaskMetadataTable.defaultProps = {
|
|
106
|
-
emrEntry: null,
|
|
107
|
-
emrIndex: null,
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const EMRDropdown = ({ data, entry, setEntry }) => (
|
|
111
|
-
<div className="text-center mt-3">
|
|
112
|
-
<div className="dropdown">
|
|
113
|
-
<button className="btn btn-secondary dropdown-toggle" type="button" id="emrDropdownBtn" data-bs-toggle="dropdown" aria-expanded="false">
|
|
114
|
-
Visit Day
|
|
115
|
-
{' '}
|
|
116
|
-
{entry.daysSinceFirstResearchVisit}
|
|
117
|
-
</button>
|
|
118
|
-
<ul className="dropdown-menu" aria-labelledby="emrDropdownBtn">
|
|
119
|
-
{Object.entries(data).map(([i, emr]) => (
|
|
120
|
-
<li key={i}>
|
|
121
|
-
<button
|
|
122
|
-
type="button"
|
|
123
|
-
className="dropdown-item"
|
|
124
|
-
onClick={() => setEntry(i)}
|
|
125
|
-
>
|
|
126
|
-
Visit Day
|
|
127
|
-
{' '}
|
|
128
|
-
{emr.daysSinceFirstResearchVisit}
|
|
129
|
-
</button>
|
|
130
|
-
</li>
|
|
131
|
-
))}
|
|
132
|
-
</ul>
|
|
133
|
-
</div>
|
|
134
|
-
</div>
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
const EMRMasking = ({ metadata, tab, setMetadata }) => {
|
|
138
|
-
const emrData = metadata[tab];
|
|
139
|
-
|
|
140
|
-
const [activeEntry, setActiveEntry] = React.useState(0);
|
|
141
|
-
|
|
142
|
-
return (
|
|
143
|
-
<>
|
|
144
|
-
<EMRDropdown
|
|
145
|
-
data={emrData}
|
|
146
|
-
entry={emrData[activeEntry]}
|
|
147
|
-
setEntry={setActiveEntry}
|
|
148
|
-
/>
|
|
149
|
-
|
|
150
|
-
<MaskMetadataTable
|
|
151
|
-
tab={tab}
|
|
152
|
-
metadata={metadata}
|
|
153
|
-
setMetadata={setMetadata}
|
|
154
|
-
emrEntry={emrData[activeEntry]}
|
|
155
|
-
emrIndex={activeEntry}
|
|
156
|
-
/>
|
|
157
|
-
</>
|
|
158
|
-
);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
export const MaskMetadataButton = ({ show, node }) => {
|
|
162
|
-
const { setNode } = useGraph();
|
|
163
|
-
|
|
164
|
-
if (R.isNil(show) || R.isEmpty(show)) return null;
|
|
165
|
-
|
|
166
|
-
return (
|
|
167
|
-
<Button
|
|
168
|
-
id="mask-btn"
|
|
169
|
-
key="mask-btn"
|
|
170
|
-
color="link"
|
|
171
|
-
className="text-warning px-1 pt-0"
|
|
172
|
-
icon="fas fa-eye-slash"
|
|
173
|
-
noText
|
|
174
|
-
onClick={() => {
|
|
175
|
-
node.toggleMaskModal();
|
|
176
|
-
setNode(node);
|
|
177
|
-
}}
|
|
178
|
-
/>
|
|
179
|
-
);
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
const MaskMetadataModal = ({
|
|
183
|
-
isOpen,
|
|
184
|
-
loading,
|
|
185
|
-
toggle,
|
|
186
|
-
handleUpdate,
|
|
187
|
-
refresh,
|
|
188
|
-
}) => {
|
|
189
|
-
const { node } = useGraph();
|
|
190
|
-
|
|
191
|
-
const { vertex, schemes, metadata } = node;
|
|
192
|
-
|
|
193
|
-
const nodeMetadata = (metadata || {})[vertex];
|
|
194
|
-
|
|
195
|
-
if (R.isNil(nodeMetadata) || R.isEmpty(nodeMetadata)) return null;
|
|
196
|
-
|
|
197
|
-
const [error, setError] = useState('');
|
|
198
|
-
|
|
199
|
-
const [md, setMd] = useState({});
|
|
200
|
-
|
|
201
|
-
useEffect(() => {
|
|
202
|
-
if (metadata) setMd(metadata[vertex]);
|
|
203
|
-
}, [metadata, node, isOpen]);
|
|
204
|
-
|
|
205
|
-
const tabs = Object.keys(nodeMetadata);
|
|
206
|
-
|
|
207
|
-
return (
|
|
208
|
-
<ConfirmationModal
|
|
209
|
-
id="mask-metadata-modal"
|
|
210
|
-
scrollable
|
|
211
|
-
isOpen={isOpen}
|
|
212
|
-
onClose={toggle}
|
|
213
|
-
headerContent="Mask Node Metadata"
|
|
214
|
-
noSubmit
|
|
215
|
-
noCancel
|
|
216
|
-
content={(
|
|
217
|
-
<>
|
|
218
|
-
{(error && !loading) && (
|
|
219
|
-
<MessageStripe message={error} color="danger" dismissible={false} />
|
|
220
|
-
)}
|
|
221
|
-
|
|
222
|
-
<HISETabs
|
|
223
|
-
activeTab={tabs[0]}
|
|
224
|
-
tabs={tabs.map((tab) => {
|
|
225
|
-
return ({
|
|
226
|
-
key: tab,
|
|
227
|
-
label: labels[tab] || tab,
|
|
228
|
-
content: (tab === 'emrData')
|
|
229
|
-
? (
|
|
230
|
-
<EMRMasking
|
|
231
|
-
tab={tab}
|
|
232
|
-
metadata={md}
|
|
233
|
-
setMetadata={setMd}
|
|
234
|
-
scheme={schemes[tab]}
|
|
235
|
-
/>
|
|
236
|
-
) : (
|
|
237
|
-
<MaskMetadataTable
|
|
238
|
-
tab={tab}
|
|
239
|
-
metadata={md}
|
|
240
|
-
setMetadata={setMd}
|
|
241
|
-
scheme={schemes[tab]}
|
|
242
|
-
/>
|
|
243
|
-
),
|
|
244
|
-
});
|
|
245
|
-
})}
|
|
246
|
-
/>
|
|
247
|
-
</>
|
|
248
|
-
)}
|
|
249
|
-
customFooter={(
|
|
250
|
-
<div className="float-right">
|
|
251
|
-
{loading && (
|
|
252
|
-
<div className="spinner-grow spinner-grow-sm text-warning" role="status" />
|
|
253
|
-
)}
|
|
254
|
-
|
|
255
|
-
<Button
|
|
256
|
-
id="cancel-btn"
|
|
257
|
-
icon="fas fa-times"
|
|
258
|
-
noText
|
|
259
|
-
className="mx-2"
|
|
260
|
-
onClick={() => {
|
|
261
|
-
toggle();
|
|
262
|
-
setMd({});
|
|
263
|
-
setError('');
|
|
264
|
-
}}
|
|
265
|
-
/>
|
|
266
|
-
|
|
267
|
-
<Button
|
|
268
|
-
id="ok-btn"
|
|
269
|
-
icon="fas fa-check"
|
|
270
|
-
color="primary"
|
|
271
|
-
onClick={() => {
|
|
272
|
-
const body = {
|
|
273
|
-
metadata: {
|
|
274
|
-
...metadata,
|
|
275
|
-
[vertex]: md,
|
|
276
|
-
},
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
handleUpdate(body)
|
|
280
|
-
.then((response) => {
|
|
281
|
-
if (response.status === 200) {
|
|
282
|
-
toggle();
|
|
283
|
-
refresh();
|
|
284
|
-
setError('');
|
|
285
|
-
} else {
|
|
286
|
-
setError(response.data.Message);
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
}}
|
|
290
|
-
>
|
|
291
|
-
Update Metadata
|
|
292
|
-
</Button>
|
|
293
|
-
</div>
|
|
294
|
-
)}
|
|
295
|
-
/>
|
|
296
|
-
);
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
export default MaskMetadataModal;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Node } from 'reactflow';
|
|
2
|
-
import { getReadNodeData } from '../ReadCertificate/helpers';
|
|
3
|
-
import { getEditNodeData } from '../EditCertificate/helpers';
|
|
4
|
-
import { getReviewNodeData } from '../ReviewCertificate/helpers';
|
|
5
|
-
import { Certificate, Replica } from '../../../@types/CertificateTypes';
|
|
6
|
-
import { getWorkspaceData } from '../WorkspaceCertificate/helpers';
|
|
7
|
-
|
|
8
|
-
export const getData = (
|
|
9
|
-
type: string,
|
|
10
|
-
vertices: Array<string>,
|
|
11
|
-
certificate: Certificate,
|
|
12
|
-
replica: Replica,
|
|
13
|
-
nodeData: Node['data']
|
|
14
|
-
) => {
|
|
15
|
-
switch (type) {
|
|
16
|
-
case 'readNode':
|
|
17
|
-
return getReadNodeData(vertices, certificate, nodeData.toggle);
|
|
18
|
-
|
|
19
|
-
case 'editNode':
|
|
20
|
-
return getEditNodeData(vertices, certificate, nodeData.toggleEditModal, nodeData.toggleMaskModal);
|
|
21
|
-
|
|
22
|
-
case 'reviewNode':
|
|
23
|
-
return getReviewNodeData(vertices, certificate, nodeData.toggleReviewModal, nodeData.toggleMetadataModal);
|
|
24
|
-
|
|
25
|
-
case 'fileLayerNode':
|
|
26
|
-
return getWorkspaceData(vertices, certificate, replica, nodeData.refresh);
|
|
27
|
-
|
|
28
|
-
default:
|
|
29
|
-
return {};
|
|
30
|
-
}
|
|
31
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export const getHeader = (label, desc) => {
|
|
2
|
-
if (label === 'Sample') return `${label} (${desc['Visit Name']} - ${desc['Visit Details']})`;
|
|
3
|
-
return label;
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
export const getTabs = (metadata) => {
|
|
7
|
-
const tabs = [];
|
|
8
|
-
|
|
9
|
-
if (!metadata) return tabs;
|
|
10
|
-
|
|
11
|
-
const keys = Object.keys(metadata);
|
|
12
|
-
|
|
13
|
-
if (!keys.length) return tabs;
|
|
14
|
-
|
|
15
|
-
keys.forEach((key) => {
|
|
16
|
-
const data = metadata[key];
|
|
17
|
-
|
|
18
|
-
if (data.length || Object.keys(data).length) tabs.push(key);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
return tabs;
|
|
22
|
-
};
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Button, ConfirmationModal } from 'hise-components';
|
|
3
|
-
import { useGraph } from '../../../../state/GraphContext';
|
|
4
|
-
import { getHeader, getTabs } from './helpers';
|
|
5
|
-
import { getKey, getValue } from '../../CertificateGraph/helpers';
|
|
6
|
-
|
|
7
|
-
const EMRDropdown = ({ activeEntry, setActiveEntry, emrData }) => (
|
|
8
|
-
<div className="text-center">
|
|
9
|
-
<div className="btn-group mb-3">
|
|
10
|
-
<button className="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
|
11
|
-
Visit Day
|
|
12
|
-
{' '}
|
|
13
|
-
{activeEntry}
|
|
14
|
-
</button>
|
|
15
|
-
|
|
16
|
-
<ul className="dropdown-menu">
|
|
17
|
-
{emrData.map((emr) => (
|
|
18
|
-
<li key={emr.daysSinceFirstResearchVisit}>
|
|
19
|
-
<button
|
|
20
|
-
type="button"
|
|
21
|
-
className="dropdown-item"
|
|
22
|
-
onClick={() => setActiveEntry(emr.daysSinceFirstResearchVisit)}
|
|
23
|
-
>
|
|
24
|
-
Visit Day
|
|
25
|
-
{' '}
|
|
26
|
-
{emr.daysSinceFirstResearchVisit}
|
|
27
|
-
</button>
|
|
28
|
-
</li>
|
|
29
|
-
))}
|
|
30
|
-
</ul>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
const EMRTable = ({ emrData, scheme }) => {
|
|
36
|
-
const [activeEntry, setActiveEntry] = React.useState(emrData[0].daysSinceFirstResearchVisit);
|
|
37
|
-
|
|
38
|
-
const emrDataValues = Object.values(emrData);
|
|
39
|
-
const emrMap = emrDataValues.reduce((accum, emr) => ({
|
|
40
|
-
...accum, [emr.daysSinceFirstResearchVisit]: emr,
|
|
41
|
-
}), {});
|
|
42
|
-
|
|
43
|
-
const entries = Object.entries(emrMap[activeEntry].patientData);
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<React.Fragment>
|
|
47
|
-
<EMRDropdown
|
|
48
|
-
activeEntry={activeEntry}
|
|
49
|
-
setActiveEntry={setActiveEntry}
|
|
50
|
-
emrData={emrDataValues}
|
|
51
|
-
/>
|
|
52
|
-
|
|
53
|
-
<Table entries={entries} scheme={scheme} tab="emrData" />
|
|
54
|
-
</React.Fragment>
|
|
55
|
-
);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const MetadataTable = ({ metadata, scheme, activeTab }) => {
|
|
59
|
-
if (!metadata) return null;
|
|
60
|
-
|
|
61
|
-
const tabMetadata = metadata[activeTab];
|
|
62
|
-
const tabScheme = scheme[activeTab];
|
|
63
|
-
|
|
64
|
-
const entries = Object.entries(tabMetadata || {});
|
|
65
|
-
|
|
66
|
-
if (activeTab === 'emrData') return <EMRTable emrData={tabMetadata} scheme={tabScheme} />;
|
|
67
|
-
|
|
68
|
-
return <Table entries={entries} scheme={tabScheme} tab={activeTab} />;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const Table = ({ entries, scheme, tab }) => {
|
|
72
|
-
return (
|
|
73
|
-
<table className="table">
|
|
74
|
-
<tbody>
|
|
75
|
-
{entries.map(([key, value]) => (
|
|
76
|
-
<tr key={key}>
|
|
77
|
-
<th scope="row">
|
|
78
|
-
{getKey(key, scheme, tab)}
|
|
79
|
-
</th>
|
|
80
|
-
<td>{getValue(key, value, scheme, tab)}</td>
|
|
81
|
-
</tr>
|
|
82
|
-
))}
|
|
83
|
-
</tbody>
|
|
84
|
-
</table>
|
|
85
|
-
);
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const Tabs = ({ tabs, activeTab, setActiveTab }) => (
|
|
89
|
-
<ul className="nav justify-content-center">
|
|
90
|
-
{tabs.map((tab) => (
|
|
91
|
-
<li className="nav-item" key={tab}>
|
|
92
|
-
<button
|
|
93
|
-
type="button"
|
|
94
|
-
className={`nav-link btn btn-link ${(activeTab === tab) && 'font-weight-bold'}`}
|
|
95
|
-
onClick={() => setActiveTab(tab)}
|
|
96
|
-
>
|
|
97
|
-
{tab.split(/(?=[A-Z])/).join(' ').toUpperCase()}
|
|
98
|
-
</button>
|
|
99
|
-
</li>
|
|
100
|
-
))}
|
|
101
|
-
</ul>
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
export const MetadataButton = ({ node }) => {
|
|
105
|
-
const { setNode } = useGraph();
|
|
106
|
-
|
|
107
|
-
const { metadata, toggleMetadataModal } = node;
|
|
108
|
-
|
|
109
|
-
const hasMetadata = getTabs(metadata).length;
|
|
110
|
-
|
|
111
|
-
if (!hasMetadata || !toggleMetadataModal) return null;
|
|
112
|
-
|
|
113
|
-
return (
|
|
114
|
-
<Button
|
|
115
|
-
id="metadata-btn"
|
|
116
|
-
key="metadata-btn"
|
|
117
|
-
color="link"
|
|
118
|
-
className="p-0"
|
|
119
|
-
icon="fas fa-bars"
|
|
120
|
-
noText
|
|
121
|
-
onClick={() => {
|
|
122
|
-
toggleMetadataModal();
|
|
123
|
-
setNode(node);
|
|
124
|
-
}}
|
|
125
|
-
/>
|
|
126
|
-
);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
const MetadataModal = ({ isOpen, toggle }) => {
|
|
130
|
-
const { node } = useGraph();
|
|
131
|
-
const { metadata, schemes, label, description } = node;
|
|
132
|
-
|
|
133
|
-
const header = getHeader(label, description)
|
|
134
|
-
const tabs = getTabs(metadata);
|
|
135
|
-
|
|
136
|
-
const [activeTab, setActiveTab] = React.useState('');
|
|
137
|
-
|
|
138
|
-
React.useEffect(() => {
|
|
139
|
-
if (!activeTab) setActiveTab(tabs[0]);
|
|
140
|
-
}, [tabs]);
|
|
141
|
-
|
|
142
|
-
React.useEffect(() => setActiveTab(tabs[0]), [header]);
|
|
143
|
-
|
|
144
|
-
return (
|
|
145
|
-
<ConfirmationModal
|
|
146
|
-
scrollable
|
|
147
|
-
isOpen={isOpen}
|
|
148
|
-
onClose={toggle}
|
|
149
|
-
headerContent={header}
|
|
150
|
-
noSubmit
|
|
151
|
-
cancelButtonText="Close"
|
|
152
|
-
content={(
|
|
153
|
-
<>
|
|
154
|
-
<Tabs tabs={tabs} activeTab={activeTab} setActiveTab={setActiveTab} />
|
|
155
|
-
|
|
156
|
-
<div className="mt-2">
|
|
157
|
-
<MetadataTable
|
|
158
|
-
metadata={metadata}
|
|
159
|
-
scheme={schemes}
|
|
160
|
-
activeTab={activeTab}
|
|
161
|
-
/>
|
|
162
|
-
</div>
|
|
163
|
-
</>
|
|
164
|
-
)}
|
|
165
|
-
/>
|
|
166
|
-
);
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
export default MetadataModal;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { Node } from 'reactflow';
|
|
2
|
-
import * as R from 'ramda';
|
|
3
|
-
import { getSchemes } from '../CertificateGraph/helpers';
|
|
4
|
-
import { Certificate } from '../../../@types/CertificateTypes';
|
|
5
|
-
|
|
6
|
-
export const getReadNodeData = (
|
|
7
|
-
vertices: Certificate['vertices'],
|
|
8
|
-
certificate: Certificate,
|
|
9
|
-
toggleMetadataModal: Function,
|
|
10
|
-
) => {
|
|
11
|
-
const data: { [key: string]: Node['data'] } = {};
|
|
12
|
-
|
|
13
|
-
const {
|
|
14
|
-
generatedLabels,
|
|
15
|
-
customLabels,
|
|
16
|
-
serviceLabels,
|
|
17
|
-
schemes,
|
|
18
|
-
metadata,
|
|
19
|
-
} = certificate;
|
|
20
|
-
|
|
21
|
-
if (R.isEmpty(vertices) || R.isNil(vertices)) return data;
|
|
22
|
-
|
|
23
|
-
vertices.forEach((vertex: string) => {
|
|
24
|
-
const label = vertex.split('/')[0];
|
|
25
|
-
const description = customLabels[vertex] || generatedLabels[vertex];
|
|
26
|
-
|
|
27
|
-
data[vertex] = {
|
|
28
|
-
label,
|
|
29
|
-
description,
|
|
30
|
-
customLabels,
|
|
31
|
-
metadata: metadata ? metadata[vertex] : null,
|
|
32
|
-
schemes: getSchemes(vertex, serviceLabels, schemes),
|
|
33
|
-
toggleMetadataModal,
|
|
34
|
-
};
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
return data;
|
|
38
|
-
};
|