cloudmr-ux 4.3.5 → 4.3.7
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/dist/CmrComponents/niivue-roi-table/NiivueRoiTable.d.ts +25 -0
- package/dist/CmrComponents/niivue-roi-table/NiivueRoiTable.js +253 -0
- package/dist/CmrTable/CmrTable.css +31 -7
- package/dist/CmrTable/CmrTable.d.ts +19 -0
- package/dist/CmrTable/CmrTable.js +39 -26
- package/dist/core/app/results/Rois.d.ts +8 -11
- package/dist/core/app/results/Rois.js +14 -291
- package/dist/core/features/rois/resultSlice.js +3 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -1
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { CSSProperties } from "react";
|
|
2
|
+
/** Default merged ROI label in Niivue patcher `groupLabelsInto` / `groupLabelsFromSelection`. */
|
|
3
|
+
export declare const DEFAULT_ROI_GROUP_TARGET_LABEL = 7;
|
|
4
|
+
export interface NiivueRoiTableProps {
|
|
5
|
+
pipelineID: string;
|
|
6
|
+
rois: any[];
|
|
7
|
+
resampleImage: () => void;
|
|
8
|
+
zipAndSendROI: (url: string, filename: string, blob: Blob) => Promise<void>;
|
|
9
|
+
unpackROI: (url: string) => Promise<void>;
|
|
10
|
+
setLabelAlias: (label: number | string, alias: string) => void;
|
|
11
|
+
nv: any;
|
|
12
|
+
style?: CSSProperties;
|
|
13
|
+
/**
|
|
14
|
+
* Called after a successful ROI upload handshake, multipart upload, and `unpackROI`.
|
|
15
|
+
* Use this to refresh server-side ROI metadata (e.g. `dispatch(getPipelineROI(...))`).
|
|
16
|
+
*/
|
|
17
|
+
onAfterRoiUpload?: () => void | Promise<void>;
|
|
18
|
+
/** Niivue label index ROIs merge into when grouping. Default: {@link DEFAULT_ROI_GROUP_TARGET_LABEL}. */
|
|
19
|
+
groupTargetLabel?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Data grid + toolbar for Niivue ROI labels: edit aliases, visibility, group / ungroup,
|
|
23
|
+
* download subset, delete, and upload replacement mask. No Redux — pass callbacks and `nv`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function NiivueRoiTable(props: NiivueRoiTableProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
23
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
49
|
+
import { useState } from "react";
|
|
50
|
+
import { Tooltip, IconButton, Snackbar, Alert, } from "@mui/material";
|
|
51
|
+
import Box from "@mui/material/Box";
|
|
52
|
+
import VisibilityIcon from "@mui/icons-material/Visibility";
|
|
53
|
+
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
|
|
54
|
+
import GetAppIcon from "@mui/icons-material/GetApp";
|
|
55
|
+
import DeleteIcon from "@mui/icons-material/Delete";
|
|
56
|
+
import { Icon as WpIcon, group as wpGroup, ungroup as wpUngroup } from "@wordpress/icons";
|
|
57
|
+
import CmrTable from "../../CmrTable/CmrTable";
|
|
58
|
+
import CMRUpload from "../upload/Upload";
|
|
59
|
+
import { getEndpoints } from "../../core/config/AppConfig";
|
|
60
|
+
import { AuthenticatedHttpClient } from "../../core/common/utilities/AuthenticatedRequests";
|
|
61
|
+
/** Default merged ROI label in Niivue patcher `groupLabelsInto` / `groupLabelsFromSelection`. */
|
|
62
|
+
export var DEFAULT_ROI_GROUP_TARGET_LABEL = 7;
|
|
63
|
+
var ROI_TOOLBAR_ICON_SIZE_PX = 24;
|
|
64
|
+
var ROI_TOOLBAR_ICON_BUTTON_SX = {
|
|
65
|
+
color: "action.active",
|
|
66
|
+
"&.Mui-disabled": {
|
|
67
|
+
color: function (theme) { return theme.palette.action.disabled; }
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var ROI_TOOLBAR_MUI_ICON_SX = {
|
|
71
|
+
fontSize: ROI_TOOLBAR_ICON_SIZE_PX,
|
|
72
|
+
color: "inherit"
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Data grid + toolbar for Niivue ROI labels: edit aliases, visibility, group / ungroup,
|
|
76
|
+
* download subset, delete, and upload replacement mask. No Redux — pass callbacks and `nv`.
|
|
77
|
+
*/
|
|
78
|
+
export function NiivueRoiTable(props) {
|
|
79
|
+
var _this = this;
|
|
80
|
+
var _a = props.groupTargetLabel, groupTargetLabel = _a === void 0 ? DEFAULT_ROI_GROUP_TARGET_LABEL : _a, onAfterRoiUpload = props.onAfterRoiUpload;
|
|
81
|
+
var _b = useState(1), uploadKey = _b[0], setUploadKey = _b[1];
|
|
82
|
+
var endpoints = getEndpoints();
|
|
83
|
+
var _c = useState([]), selectedData = _c[0], setSelectedData = _c[1];
|
|
84
|
+
var roiColumns = [
|
|
85
|
+
{
|
|
86
|
+
headerName: "ROI Label",
|
|
87
|
+
field: "alias",
|
|
88
|
+
flex: 1,
|
|
89
|
+
editable: true,
|
|
90
|
+
valueSetter: function (params) {
|
|
91
|
+
if (params.value !== params.row.alias) {
|
|
92
|
+
props.setLabelAlias(params.row.label, params.value);
|
|
93
|
+
}
|
|
94
|
+
return params.row;
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
headerName: "Color",
|
|
99
|
+
field: "color",
|
|
100
|
+
flex: 0.5,
|
|
101
|
+
sortable: false,
|
|
102
|
+
renderCell: function (params) { return (_jsx(Box, __assign({ sx: { width: "100%", display: "flex", justifyContent: "center" } }, { children: _jsx("div", { style: {
|
|
103
|
+
width: "14pt",
|
|
104
|
+
height: "14pt",
|
|
105
|
+
borderRadius: "3pt",
|
|
106
|
+
background: "".concat(params.row.color)
|
|
107
|
+
} }) }))); }
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
headerName: "Mean",
|
|
111
|
+
field: "mu",
|
|
112
|
+
flex: 1,
|
|
113
|
+
renderCell: function (params) { return (_jsx("div", { children: "".concat(params.row.mu.toFixed(3)) })); }
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
headerName: "SD",
|
|
117
|
+
field: "std",
|
|
118
|
+
flex: 1,
|
|
119
|
+
renderCell: function (params) { return (_jsx("div", { children: "".concat(params.row.std.toFixed(3)) })); }
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
headerName: "Visibility",
|
|
123
|
+
field: "visibility",
|
|
124
|
+
flex: 1,
|
|
125
|
+
sortable: false,
|
|
126
|
+
renderCell: function (params) { return (_jsx(Box, __assign({ sx: { width: "100%", display: "flex", justifyContent: "center" } }, { children: _jsx(IconButton, __assign({ onClick: function (event) {
|
|
127
|
+
props.nv.setLabelVisibility(Number(params.row.label), !props.nv.getLabelVisibility(Number(params.row.label)));
|
|
128
|
+
props.resampleImage();
|
|
129
|
+
props.nv.drawScene();
|
|
130
|
+
event.stopPropagation();
|
|
131
|
+
} }, { children: params.row.visibility ? (_jsx(VisibilityIcon, { sx: { color: "#aaa" } })) : (_jsx(VisibilityOffIcon, { sx: { color: "#aaa" } })) })) }))); }
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
headerName: "Voxel Count",
|
|
135
|
+
field: "count",
|
|
136
|
+
flex: 1.5
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
var _d = useState(false), warningVisible = _d[0], setWarningVisible = _d[1];
|
|
140
|
+
var _e = useState(""), warningMessage = _e[0], setWarningMessage = _e[1];
|
|
141
|
+
var warnEmptySelection = function (message) {
|
|
142
|
+
setWarningMessage(message);
|
|
143
|
+
setWarningVisible(true);
|
|
144
|
+
};
|
|
145
|
+
var selectedNums = selectedData.map(function (v) { return Number(v); });
|
|
146
|
+
var uniqueSelected = new Set(selectedNums);
|
|
147
|
+
var canGroupSelection = selectedNums.length >= 2 && uniqueSelected.size >= 2;
|
|
148
|
+
var groupButtonDisabled = selectedData.length > 0 && !canGroupSelection;
|
|
149
|
+
var groupTooltip = selectedData.length === 0
|
|
150
|
+
? "Group selected ROIs"
|
|
151
|
+
: uniqueSelected.size < 2 || selectedNums.length < 2
|
|
152
|
+
? "Select at least two different ROIs to group"
|
|
153
|
+
: "Group selected ROIs";
|
|
154
|
+
return (_jsxs(Box, __assign({ style: props.style }, { children: [_jsx(CmrTable, { hideFooter: true, getRowId: function (row) { return row.label; }, style: { height: "70%" }, dataSource: props.rois, columns: roiColumns, columnHeaderHeight: 40, rowSelectionModel: selectedData, onRowSelectionModelChange: function (rowSelectionModel) {
|
|
155
|
+
setSelectedData(rowSelectionModel);
|
|
156
|
+
} }), _jsxs(Box, __assign({ sx: {
|
|
157
|
+
display: "flex",
|
|
158
|
+
justifyContent: "flex-start",
|
|
159
|
+
alignItems: "center",
|
|
160
|
+
flexWrap: "wrap",
|
|
161
|
+
gap: 2,
|
|
162
|
+
mt: 0,
|
|
163
|
+
px: 2,
|
|
164
|
+
py: 1,
|
|
165
|
+
backgroundColor: "#f8f9fa",
|
|
166
|
+
border: "1px solid rgba(0, 0, 0, 0.12)",
|
|
167
|
+
borderTop: "none",
|
|
168
|
+
borderRadius: "0 0 4px 4px"
|
|
169
|
+
} }, { children: [_jsx(Tooltip, __assign({ title: groupTooltip }, { children: _jsx("span", { children: _jsx(IconButton, __assign({ disabled: groupButtonDisabled, sx: ROI_TOOLBAR_ICON_BUTTON_SX, onClick: function () {
|
|
170
|
+
if (selectedData.length === 0) {
|
|
171
|
+
warnEmptySelection("Please select an ROI to group");
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (!canGroupSelection) {
|
|
175
|
+
warnEmptySelection("Please select at least two different ROIs to group");
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (typeof props.nv.groupLabelsFromSelection === "function") {
|
|
179
|
+
props.nv.groupLabelsFromSelection(selectedNums, groupTargetLabel);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
props.nv.groupLabelsInto(selectedNums, groupTargetLabel);
|
|
183
|
+
}
|
|
184
|
+
props.nv.drawScene();
|
|
185
|
+
props.resampleImage();
|
|
186
|
+
} }, { children: _jsx(WpIcon, { icon: wpGroup, size: 24, fill: "currentColor" }) })) }) })), _jsx(Tooltip, __assign({ title: "Ungroup ROIs" }, { children: _jsx(IconButton, __assign({ sx: ROI_TOOLBAR_ICON_BUTTON_SX, onClick: function () {
|
|
187
|
+
if (selectedData.length === 0) {
|
|
188
|
+
warnEmptySelection("Please select an ROI to ungroup");
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
props.nv.ungroup();
|
|
192
|
+
props.nv.drawScene();
|
|
193
|
+
props.resampleImage();
|
|
194
|
+
} }, { children: _jsx(WpIcon, { icon: wpUngroup, size: ROI_TOOLBAR_ICON_SIZE_PX, fill: "currentColor" }) })) })), _jsx(Tooltip, __assign({ title: "Download" }, { children: _jsx(IconButton, __assign({ sx: ROI_TOOLBAR_ICON_BUTTON_SX, onClick: function () { return __awaiter(_this, void 0, void 0, function () {
|
|
195
|
+
var fileName, selectedLabels, _i, selectedData_1, label;
|
|
196
|
+
return __generator(this, function (_a) {
|
|
197
|
+
switch (_a.label) {
|
|
198
|
+
case 0:
|
|
199
|
+
fileName = "label";
|
|
200
|
+
selectedLabels = [];
|
|
201
|
+
for (_i = 0, selectedData_1 = selectedData; _i < selectedData_1.length; _i++) {
|
|
202
|
+
label = selectedData_1[_i];
|
|
203
|
+
fileName += label;
|
|
204
|
+
selectedLabels.push(Number(label));
|
|
205
|
+
}
|
|
206
|
+
fileName += ".nii";
|
|
207
|
+
if (selectedLabels.length === 0) {
|
|
208
|
+
warnEmptySelection("Please select an ROI to download");
|
|
209
|
+
return [2 /*return*/];
|
|
210
|
+
}
|
|
211
|
+
return [4 /*yield*/, props.nv.saveImageByLabels(fileName, selectedLabels)];
|
|
212
|
+
case 1:
|
|
213
|
+
_a.sent();
|
|
214
|
+
return [2 /*return*/];
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}); } }, { children: _jsx(GetAppIcon, { sx: ROI_TOOLBAR_MUI_ICON_SX }) })) })), _jsx(Tooltip, __assign({ title: "Delete" }, { children: _jsx(IconButton, __assign({ sx: ROI_TOOLBAR_ICON_BUTTON_SX, onClick: function () {
|
|
218
|
+
if (selectedData.length === 0) {
|
|
219
|
+
warnEmptySelection("Please select an ROI to delete");
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
props.nv.deleteDrawingByLabel(selectedData.map(function (value) { return Number(value); }));
|
|
223
|
+
props.resampleImage();
|
|
224
|
+
props.nv.drawScene();
|
|
225
|
+
} }, { children: _jsx(DeleteIcon, { sx: ROI_TOOLBAR_MUI_ICON_SX }) })) })), _jsx(CMRUpload, { changeNameAfterUpload: false, color: "primary", onUploaded: function () { }, uploadHandler: function (file, _fileAlias, _fileDatabase) { return __awaiter(_this, void 0, void 0, function () {
|
|
226
|
+
var filename, response;
|
|
227
|
+
return __generator(this, function (_a) {
|
|
228
|
+
switch (_a.label) {
|
|
229
|
+
case 0:
|
|
230
|
+
filename = file.name;
|
|
231
|
+
return [4 /*yield*/, AuthenticatedHttpClient.post(endpoints.ROI_UPLOAD, {
|
|
232
|
+
filename: filename,
|
|
233
|
+
pipeline_id: props.pipelineID,
|
|
234
|
+
type: "image",
|
|
235
|
+
contentType: "application/octet-stream"
|
|
236
|
+
})];
|
|
237
|
+
case 1:
|
|
238
|
+
response = _a.sent();
|
|
239
|
+
return [4 /*yield*/, props.zipAndSendROI(response.data.upload_url, filename, file)];
|
|
240
|
+
case 2:
|
|
241
|
+
_a.sent();
|
|
242
|
+
return [4 /*yield*/, props.unpackROI(response.data.access_url)];
|
|
243
|
+
case 3:
|
|
244
|
+
_a.sent();
|
|
245
|
+
return [4 /*yield*/, (onAfterRoiUpload === null || onAfterRoiUpload === void 0 ? void 0 : onAfterRoiUpload())];
|
|
246
|
+
case 4:
|
|
247
|
+
_a.sent();
|
|
248
|
+
setUploadKey(function (k) { return k + 1; });
|
|
249
|
+
return [2 /*return*/, 200];
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}); }, maxCount: 1 }, uploadKey)] })), _jsx(Snackbar, __assign({ open: warningVisible, autoHideDuration: 3000, onClose: function () { return setWarningVisible(false); }, anchorOrigin: { vertical: "top", horizontal: "center" } }, { children: _jsx(Alert, __assign({ severity: "warning", sx: { width: "100%" }, onClose: function () { return setWarningVisible(false); } }, { children: warningMessage })) }))] })));
|
|
253
|
+
}
|
|
@@ -6,18 +6,42 @@
|
|
|
6
6
|
margin-bottom: 0;
|
|
7
7
|
} */
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
/**
|
|
10
|
+
* CmrTable root — colors are driven by CSS variables set on `.cmr-table` from props.
|
|
11
|
+
* Defaults preserve the package purple accent (#580f8b). Host apps can override per instance
|
|
12
|
+
* via `headerIconColor` / `checkboxCheckedColor` / `checkboxUncheckedColor`, or by setting
|
|
13
|
+
* variables on a parent: `--cmr-table-header-icon`, etc.
|
|
14
|
+
*/
|
|
15
|
+
.cmr-table {
|
|
16
|
+
/* Fallbacks = package defaults */
|
|
17
|
+
--cmr-table-header-bg: #f3e5f5;
|
|
18
|
+
--cmr-table-header-text: #333;
|
|
19
|
+
--cmr-table-header-icon: #580f8b;
|
|
20
|
+
--cmr-table-checkbox-unchecked: rgba(88, 15, 139, 0.54);
|
|
21
|
+
--cmr-table-checkbox-checked: #580f8b;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.cmr-table .MuiDataGrid-columnHeaders {
|
|
25
|
+
background: var(--cmr-table-header-bg);
|
|
26
|
+
color: var(--cmr-table-header-text);
|
|
12
27
|
font-weight: bold;
|
|
13
28
|
}
|
|
14
29
|
|
|
15
|
-
.MuiDataGrid-columnHeaders .MuiSvgIcon-root {
|
|
16
|
-
color:
|
|
30
|
+
.cmr-table .MuiDataGrid-columnHeaders .MuiSvgIcon-root {
|
|
31
|
+
color: var(--cmr-table-header-icon) !important;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.cmr-table .MuiCheckbox-root {
|
|
35
|
+
color: var(--cmr-table-checkbox-unchecked);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.cmr-table .MuiCheckbox-root.Mui-checked,
|
|
39
|
+
.cmr-table .MuiCheckbox-root.MuiCheckbox-indeterminate {
|
|
40
|
+
color: var(--cmr-table-checkbox-checked) !important;
|
|
17
41
|
}
|
|
18
42
|
|
|
19
|
-
/*
|
|
20
|
-
.MuiDataGrid-columnHeaderCheckbox .MuiDataGrid-columnHeaderTitleContainerContent {
|
|
43
|
+
/* Religning MUI checkbox in the header */
|
|
44
|
+
.cmr-table .MuiDataGrid-columnHeaderCheckbox .MuiDataGrid-columnHeaderTitleContainerContent {
|
|
21
45
|
padding: 0 !important;
|
|
22
46
|
margin: 0 !important;
|
|
23
47
|
display: flex;
|
|
@@ -2,15 +2,34 @@ import React from 'react';
|
|
|
2
2
|
import './CmrTable.css';
|
|
3
3
|
import { DataGridProps } from '@mui/x-data-grid';
|
|
4
4
|
import { CSSProperties } from 'react';
|
|
5
|
+
/** Default header icon / selection accent (purple). Exposed for host apps that want the package default explicitly. */
|
|
6
|
+
export declare const CMR_TABLE_DEFAULT_HEADER_ICON = "#580f8b";
|
|
5
7
|
export interface CmrTableProps extends Omit<DataGridProps, 'rows'> {
|
|
6
8
|
dataSource: any[];
|
|
7
9
|
idAlias?: string;
|
|
8
10
|
name?: string;
|
|
9
11
|
style?: CSSProperties;
|
|
10
12
|
showCheckbox?: boolean;
|
|
13
|
+
/** Column header background. @default `#F3E5F5` */
|
|
11
14
|
headerBgColor?: string;
|
|
15
|
+
/** Column header text color. @default `#333` */
|
|
12
16
|
headerTextColor?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Sort icons, menu icons, and header “select all” checkbox accent.
|
|
19
|
+
* Also the default for {@link checkboxCheckedColor} when that prop is omitted.
|
|
20
|
+
* @default `#580f8b`
|
|
21
|
+
*/
|
|
13
22
|
headerIconColor?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Row / header checkbox color when checked or indeterminate.
|
|
25
|
+
* @default same as `headerIconColor` (`#580f8b` when defaults apply)
|
|
26
|
+
*/
|
|
27
|
+
checkboxCheckedColor?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Row / header checkbox color when unchecked (non-checked outline state).
|
|
30
|
+
* @default `rgba(88, 15, 139, 0.54)` (pairs with default purple accent)
|
|
31
|
+
*/
|
|
32
|
+
checkboxUncheckedColor?: string;
|
|
14
33
|
/**
|
|
15
34
|
* Optional function to customize how rows are filtered/sorted before display.
|
|
16
35
|
* Receives the mapped rows; return a new array in the desired order.
|
|
@@ -32,6 +32,12 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
32
32
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
33
33
|
import './CmrTable.css';
|
|
34
34
|
import { DataGrid } from '@mui/x-data-grid';
|
|
35
|
+
/** Default header icon / selection accent (purple). Exposed for host apps that want the package default explicitly. */
|
|
36
|
+
export var CMR_TABLE_DEFAULT_HEADER_ICON = '#580f8b';
|
|
37
|
+
var DEFAULT_HEADER_BG = '#F3E5F5';
|
|
38
|
+
var DEFAULT_HEADER_TEXT = '#333';
|
|
39
|
+
/** Unchecked row/header checkbox tint that pairs with {@link CMR_TABLE_DEFAULT_HEADER_ICON}. */
|
|
40
|
+
var DEFAULT_CHECKBOX_UNCHECKED = 'rgba(88, 15, 139, 0.54)';
|
|
35
41
|
/** Extracts a comparable timestamp from a row for sorting. Supports createdAt, created_at, or similar date fields. */
|
|
36
42
|
function getSubmittedTimestamp(row) {
|
|
37
43
|
var _a, _b, _c;
|
|
@@ -46,38 +52,45 @@ function defaultSortByRecent(rows) {
|
|
|
46
52
|
return __spreadArray([], rows, true).sort(function (a, b) { return getSubmittedTimestamp(b) - getSubmittedTimestamp(a); });
|
|
47
53
|
}
|
|
48
54
|
var CmrTable = function (props) {
|
|
49
|
-
var
|
|
55
|
+
var _a;
|
|
56
|
+
var dataSource = props.dataSource, columns = props.columns, idAlias = props.idAlias, className = props.className, onRowSelectionModelChange = props.onRowSelectionModelChange, style = props.style, _b = props.showCheckbox, showCheckbox = _b === void 0 ? true : _b, _c = props.headerBgColor, headerBgColor = _c === void 0 ? DEFAULT_HEADER_BG : _c, _d = props.headerTextColor, headerTextColor = _d === void 0 ? DEFAULT_HEADER_TEXT : _d, _e = props.headerIconColor, headerIconColor = _e === void 0 ? CMR_TABLE_DEFAULT_HEADER_ICON : _e, checkboxCheckedColor = props.checkboxCheckedColor, checkboxUncheckedColor = props.checkboxUncheckedColor, processRows = props.processRows, userSx = props.sx, rest = __rest(props, ["dataSource", "columns", "idAlias", "className", "onRowSelectionModelChange", "style", "showCheckbox", "headerBgColor", "headerTextColor", "headerIconColor", "checkboxCheckedColor", "checkboxUncheckedColor", "processRows", "sx"]);
|
|
57
|
+
var resolvedCheckboxChecked = checkboxCheckedColor !== null && checkboxCheckedColor !== void 0 ? checkboxCheckedColor : headerIconColor;
|
|
58
|
+
var resolvedCheckboxUnchecked = checkboxUncheckedColor !== null && checkboxUncheckedColor !== void 0 ? checkboxUncheckedColor : DEFAULT_CHECKBOX_UNCHECKED;
|
|
59
|
+
var wrapperStyle = __assign(__assign({ height: '400px', width: '100%' }, (style !== null && style !== void 0 ? style : {})), (_a = {}, _a['--cmr-table-header-bg'] = headerBgColor, _a['--cmr-table-header-text'] = headerTextColor, _a['--cmr-table-header-icon'] = headerIconColor, _a['--cmr-table-checkbox-checked'] = resolvedCheckboxChecked, _a['--cmr-table-checkbox-unchecked'] = resolvedCheckboxUnchecked, _a));
|
|
60
|
+
var tableClassName = ['cmr-table', className].filter(Boolean).join(' ');
|
|
50
61
|
var mappedRows = dataSource
|
|
51
62
|
? dataSource.map(function (row) { return (__assign({ id: idAlias ? row[idAlias] : row['id'] }, row)); })
|
|
52
63
|
: [];
|
|
53
64
|
var displayRows = processRows ? processRows(mappedRows) : defaultSortByRecent(mappedRows);
|
|
54
|
-
|
|
65
|
+
var baseSx = {
|
|
66
|
+
'& .MuiDataGrid-columnHeaders': {
|
|
67
|
+
backgroundColor: headerBgColor,
|
|
68
|
+
color: headerTextColor
|
|
69
|
+
},
|
|
70
|
+
'&& .MuiDataGrid-columnHeader .MuiSvgIcon-root': {
|
|
71
|
+
color: "".concat(headerIconColor, " !important")
|
|
72
|
+
},
|
|
73
|
+
'&& .MuiDataGrid-columnHeader .MuiDataGrid-sortIcon': {
|
|
74
|
+
color: "".concat(headerIconColor, " !important")
|
|
75
|
+
},
|
|
76
|
+
'&& .MuiDataGrid-columnHeader .MuiDataGrid-menuIconButton .MuiSvgIcon-root': {
|
|
77
|
+
color: "".concat(headerIconColor, " !important")
|
|
78
|
+
},
|
|
79
|
+
'&& .MuiDataGrid-columnHeader .MuiDataGrid-iconButtonContainer .MuiSvgIcon-root': {
|
|
80
|
+
color: "".concat(headerIconColor, " !important")
|
|
81
|
+
},
|
|
82
|
+
'& .MuiDataGrid-columnHeaderTitle': {
|
|
83
|
+
fontWeight: 'bold'
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var mergedSx = userSx == null
|
|
87
|
+
? baseSx
|
|
88
|
+
: Array.isArray(userSx)
|
|
89
|
+
? __spreadArray([baseSx], userSx, true) : [baseSx, userSx];
|
|
90
|
+
return (_jsx("div", __assign({ style: wrapperStyle, className: tableClassName }, { children: _jsx(DataGrid, __assign({ rows: displayRows, columns: columns, checkboxSelection: showCheckbox, onRowSelectionModelChange: onRowSelectionModelChange, initialState: {
|
|
55
91
|
pagination: {
|
|
56
92
|
paginationModel: { pageSize: 50, page: 0 }
|
|
57
93
|
}
|
|
58
|
-
}, sx: {
|
|
59
|
-
'& .MuiDataGrid-columnHeaders': {
|
|
60
|
-
backgroundColor: headerBgColor,
|
|
61
|
-
color: headerTextColor
|
|
62
|
-
},
|
|
63
|
-
// '& .MuiDataGrid-columnHeaders .MuiSvgIcon-root': {
|
|
64
|
-
// color: headerIconColor,
|
|
65
|
-
// },
|
|
66
|
-
'&& .MuiDataGrid-columnHeader .MuiSvgIcon-root': {
|
|
67
|
-
color: "".concat(headerIconColor, " !important")
|
|
68
|
-
},
|
|
69
|
-
'&& .MuiDataGrid-columnHeader .MuiDataGrid-sortIcon': {
|
|
70
|
-
color: "".concat(headerIconColor, " !important")
|
|
71
|
-
},
|
|
72
|
-
'&& .MuiDataGrid-columnHeader .MuiDataGrid-menuIconButton .MuiSvgIcon-root': {
|
|
73
|
-
color: "".concat(headerIconColor, " !important")
|
|
74
|
-
},
|
|
75
|
-
'&& .MuiDataGrid-columnHeader .MuiDataGrid-iconButtonContainer .MuiSvgIcon-root': {
|
|
76
|
-
color: "".concat(headerIconColor, " !important")
|
|
77
|
-
},
|
|
78
|
-
'& .MuiDataGrid-columnHeaderTitle': {
|
|
79
|
-
fontWeight: 'bold'
|
|
80
|
-
}
|
|
81
|
-
}, localeText: { noRowsLabel: 'No Rows' } }, rest)) })));
|
|
94
|
+
}, sx: mergedSx, localeText: { noRowsLabel: 'No Rows' } }, rest)) })));
|
|
82
95
|
};
|
|
83
96
|
export default CmrTable;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
style?: CSSProperties | undefined;
|
|
10
|
-
nv: any;
|
|
11
|
-
}) => import("react/jsx-runtime").JSX.Element;
|
|
1
|
+
import type { NiivueRoiTableProps } from "../../../CmrComponents/niivue-roi-table/NiivueRoiTable";
|
|
2
|
+
export type { NiivueRoiTableProps };
|
|
3
|
+
type ReduxRoiTableProps = Omit<NiivueRoiTableProps, "onAfterRoiUpload">;
|
|
4
|
+
/**
|
|
5
|
+
* ROI table wired to the core Redux store: refreshes pipeline ROI metadata after upload.
|
|
6
|
+
* Prefer {@link NiivueRoiTable} from `cloudmr-ux` when building screens without this store.
|
|
7
|
+
*/
|
|
8
|
+
export declare function ROITable(props: ReduxRoiTableProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -9,298 +9,21 @@ var __assign = (this && this.__assign) || function () {
|
|
|
9
9
|
};
|
|
10
10
|
return __assign.apply(this, arguments);
|
|
11
11
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
-
});
|
|
20
|
-
};
|
|
21
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
23
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
-
function step(op) {
|
|
26
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
-
switch (op[0]) {
|
|
31
|
-
case 0: case 1: t = op; break;
|
|
32
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
-
default:
|
|
36
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
-
if (t[2]) _.ops.pop();
|
|
41
|
-
_.trys.pop(); continue;
|
|
42
|
-
}
|
|
43
|
-
op = body.call(thisArg, _);
|
|
44
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
49
|
-
import { CmrTable, CMRUpload, CmrConfirmation } from "../../../index";
|
|
50
|
-
import { useState } from "react";
|
|
51
|
-
import { Tooltip, IconButton, } from "@mui/material";
|
|
52
|
-
import { getEndpoints } from "../../config/AppConfig";
|
|
12
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
+
import { NiivueRoiTable } from "../../../CmrComponents/niivue-roi-table/NiivueRoiTable";
|
|
53
14
|
import { useAppDispatch, useAppSelector } from "../../store/hooks";
|
|
54
|
-
import Box from "@mui/material/Box";
|
|
55
|
-
import VisibilityIcon from "@mui/icons-material/Visibility";
|
|
56
|
-
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
|
|
57
|
-
import GetAppIcon from "@mui/icons-material/GetApp";
|
|
58
|
-
import DeleteIcon from "@mui/icons-material/Delete";
|
|
59
|
-
import { Icon as WpIcon, group as wpGroup, ungroup as wpUngroup } from "@wordpress/icons";
|
|
60
15
|
import { getPipelineROI } from "../../features/rois/resultActionCreation";
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
var
|
|
67
|
-
color: "action.active",
|
|
68
|
-
"&.Mui-disabled": {
|
|
69
|
-
color: function (theme) { return theme.palette.action.disabled; }
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
var ROI_TOOLBAR_MUI_ICON_SX = {
|
|
73
|
-
fontSize: ROI_TOOLBAR_ICON_SIZE_PX,
|
|
74
|
-
color: "inherit"
|
|
75
|
-
};
|
|
76
|
-
export var ROITable = function (props) {
|
|
77
|
-
// const rois:ROI[] = useAppSelector(state=>{
|
|
78
|
-
// return (state.roi.rois[props.pipelineID]==undefined)?[]:state.roi.rois[props.pipelineID];
|
|
79
|
-
// })
|
|
80
|
-
// console.log(rois);
|
|
81
|
-
var endpoints = getEndpoints();
|
|
82
|
-
var _a = useState(1), uploadKey = _a[0], setUploadKey = _a[1];
|
|
83
|
-
var pipeline = useAppSelector(function (state) { var _a; return (_a = state.result.activeJob) === null || _a === void 0 ? void 0 : _a.pipeline_id; });
|
|
84
|
-
var _b = useState([]), selectedData = _b[0], setSelectedData = _b[1];
|
|
16
|
+
/**
|
|
17
|
+
* ROI table wired to the core Redux store: refreshes pipeline ROI metadata after upload.
|
|
18
|
+
* Prefer {@link NiivueRoiTable} from `cloudmr-ux` when building screens without this store.
|
|
19
|
+
*/
|
|
20
|
+
export function ROITable(props) {
|
|
21
|
+
var pipeline = useAppSelector(function (s) { var _a; return (_a = s.result.activeJob) === null || _a === void 0 ? void 0 : _a.pipeline_id; });
|
|
85
22
|
var dispatch = useAppDispatch();
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
flex: 1,
|
|
91
|
-
editable: true,
|
|
92
|
-
valueSetter: function (params) {
|
|
93
|
-
var value = params.value;
|
|
94
|
-
// console.log(params);
|
|
95
|
-
var newAlias = params.value; // Value entered by the user
|
|
96
|
-
// console.log(newAlias);
|
|
97
|
-
if (newAlias != params.row.alias) {
|
|
98
|
-
props.setLabelAlias(params.row.label, newAlias);
|
|
99
|
-
}
|
|
100
|
-
return params.row;
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
headerName: "Color",
|
|
105
|
-
field: "color",
|
|
106
|
-
flex: 0.5,
|
|
107
|
-
sortable: false,
|
|
108
|
-
// renderHeader: (params: any) => {
|
|
109
|
-
// return (
|
|
110
|
-
// <Box sx={{ display: 'flex', justifyContent: 'center', width: '100%' }}>
|
|
111
|
-
// {params.colDef.headerName}
|
|
112
|
-
// </Box>
|
|
113
|
-
// );
|
|
114
|
-
// },
|
|
115
|
-
renderCell: function (params) {
|
|
116
|
-
return (_jsx(Box, __assign({ sx: {
|
|
117
|
-
width: "100%",
|
|
118
|
-
display: "flex",
|
|
119
|
-
justifyContent: "center"
|
|
120
|
-
} }, { children: _jsx("div", { style: {
|
|
121
|
-
width: "14pt",
|
|
122
|
-
height: "14pt",
|
|
123
|
-
borderRadius: "3pt",
|
|
124
|
-
background: "".concat(params.row.color)
|
|
125
|
-
} }) })));
|
|
23
|
+
return (_jsx(NiivueRoiTable, __assign({}, props, { onAfterRoiUpload: function () {
|
|
24
|
+
var p = pipeline !== null && pipeline !== void 0 ? pipeline : props.pipelineID;
|
|
25
|
+
if (p) {
|
|
26
|
+
void dispatch(getPipelineROI({ pipeline: p }));
|
|
126
27
|
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
headerName: "Mean",
|
|
130
|
-
field: "mu",
|
|
131
|
-
flex: 1,
|
|
132
|
-
renderCell: function (params) {
|
|
133
|
-
return _jsx("div", { children: "".concat(params.row.mu.toFixed(3)) });
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
headerName: "SD",
|
|
138
|
-
field: "std",
|
|
139
|
-
flex: 1,
|
|
140
|
-
renderCell: function (params) {
|
|
141
|
-
return _jsx("div", { children: "".concat(params.row.std.toFixed(3)) });
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
headerName: "Visibility",
|
|
146
|
-
field: "visibility",
|
|
147
|
-
flex: 1,
|
|
148
|
-
sortable: false,
|
|
149
|
-
// renderHeader: (params: any) => {
|
|
150
|
-
// return (
|
|
151
|
-
// <Box sx={{ display: 'flex', justifyContent: 'center', width: '100%' }}>
|
|
152
|
-
// {params.colDef.headerName}
|
|
153
|
-
// </Box>
|
|
154
|
-
// );
|
|
155
|
-
// },
|
|
156
|
-
renderCell: function (params) {
|
|
157
|
-
return (_jsx(Box, __assign({ sx: {
|
|
158
|
-
width: "100%",
|
|
159
|
-
display: "flex",
|
|
160
|
-
justifyContent: "center"
|
|
161
|
-
} }, { children: _jsx(IconButton, __assign({ onClick: function (event) {
|
|
162
|
-
props.nv.setLabelVisibility(Number(params.row.label), !props.nv.getLabelVisibility(Number(params.row.label)));
|
|
163
|
-
props.resampleImage();
|
|
164
|
-
props.nv.drawScene();
|
|
165
|
-
event.stopPropagation();
|
|
166
|
-
} }, { children: params.row.visibility ? (_jsx(VisibilityIcon, { sx: { color: "#aaa" } })) : (_jsx(VisibilityOffIcon, { sx: { color: "#aaa" } })) })) })));
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
headerName: "Voxel Count",
|
|
171
|
-
field: "count",
|
|
172
|
-
flex: 1.5
|
|
173
|
-
},
|
|
174
|
-
];
|
|
175
|
-
var _c = useState(false), warningVisible = _c[0], setWarningVisible = _c[1];
|
|
176
|
-
var _d = useState(""), warningMessage = _d[0], setWarningMessage = _d[1];
|
|
177
|
-
var warnEmptySelection = function (message) {
|
|
178
|
-
setWarningMessage(message);
|
|
179
|
-
setWarningVisible(true);
|
|
180
|
-
};
|
|
181
|
-
var selectedNums = selectedData.map(function (v) { return Number(v); });
|
|
182
|
-
var uniqueSelected = new Set(selectedNums);
|
|
183
|
-
var canGroupSelection = selectedNums.length >= 2 && uniqueSelected.size >= 2;
|
|
184
|
-
var groupButtonDisabled = selectedData.length > 0 && !canGroupSelection;
|
|
185
|
-
var groupTooltip = selectedData.length === 0
|
|
186
|
-
? "Group selected ROIs"
|
|
187
|
-
: uniqueSelected.size < 2 || selectedNums.length < 2
|
|
188
|
-
? "Select at least two different ROIs to group"
|
|
189
|
-
: "Group selected ROIs";
|
|
190
|
-
return (_jsxs(Box, __assign({ style: props.style }, { children: [_jsx(CmrTable
|
|
191
|
-
// sx={{
|
|
192
|
-
// borderBottomLeftRadius: 0,
|
|
193
|
-
// borderBottomRightRadius: 0,
|
|
194
|
-
// marginBottom: 0,
|
|
195
|
-
// paddingBottom: 0,
|
|
196
|
-
// }}
|
|
197
|
-
, {
|
|
198
|
-
// sx={{
|
|
199
|
-
// borderBottomLeftRadius: 0,
|
|
200
|
-
// borderBottomRightRadius: 0,
|
|
201
|
-
// marginBottom: 0,
|
|
202
|
-
// paddingBottom: 0,
|
|
203
|
-
// }}
|
|
204
|
-
hideFooter: true, getRowId: function (row) { return row.label; }, style: { height: "70%" }, dataSource: props.rois, columns: roiColumns, columnHeaderHeight: 40, rowSelectionModel: selectedData, onRowSelectionModelChange: function (rowSelectionModel) {
|
|
205
|
-
setSelectedData(rowSelectionModel);
|
|
206
|
-
} }), _jsxs(Box, __assign({ sx: {
|
|
207
|
-
display: "flex",
|
|
208
|
-
justifyContent: "flex-start",
|
|
209
|
-
alignItems: "center",
|
|
210
|
-
flexWrap: "wrap",
|
|
211
|
-
gap: 2,
|
|
212
|
-
mt: 0,
|
|
213
|
-
px: 2,
|
|
214
|
-
py: 1,
|
|
215
|
-
backgroundColor: "#f8f9fa",
|
|
216
|
-
border: "1px solid rgba(0, 0, 0, 0.12)",
|
|
217
|
-
borderTop: "none",
|
|
218
|
-
borderRadius: "0 0 4px 4px"
|
|
219
|
-
} }, { children: [_jsx(Tooltip, __assign({ title: groupTooltip }, { children: _jsx("span", { children: _jsx(IconButton, __assign({ disabled: groupButtonDisabled, sx: ROI_TOOLBAR_ICON_BUTTON_SX, onClick: function () {
|
|
220
|
-
if (selectedData.length === 0) {
|
|
221
|
-
warnEmptySelection("Please select an ROI to group");
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
if (!canGroupSelection) {
|
|
225
|
-
warnEmptySelection("Please select at least two different ROIs to group");
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
if (typeof props.nv.groupLabelsFromSelection === "function") {
|
|
229
|
-
props.nv.groupLabelsFromSelection(selectedNums, GROUP_TARGET_LABEL);
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
props.nv.groupLabelsInto(selectedNums, GROUP_TARGET_LABEL);
|
|
233
|
-
}
|
|
234
|
-
props.nv.drawScene();
|
|
235
|
-
props.resampleImage();
|
|
236
|
-
} }, { children: _jsx(WpIcon, { icon: wpGroup, size: ROI_TOOLBAR_ICON_SIZE_PX, fill: "currentColor" }) })) }) })), _jsx(Tooltip, __assign({ title: "Ungroup" }, { children: _jsx(IconButton, __assign({ sx: ROI_TOOLBAR_ICON_BUTTON_SX, onClick: function () {
|
|
237
|
-
props.nv.ungroup();
|
|
238
|
-
props.nv.drawScene();
|
|
239
|
-
props.resampleImage();
|
|
240
|
-
} }, { children: _jsx(WpIcon, { icon: wpUngroup, size: 16, fill: "currentColor" }) })) })), _jsx(Tooltip, __assign({ title: "Download" }, { children: _jsx(IconButton, __assign({ sx: ROI_TOOLBAR_ICON_BUTTON_SX, onClick: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
241
|
-
var fileName, selectedLabels, _i, selectedData_1, label;
|
|
242
|
-
return __generator(this, function (_a) {
|
|
243
|
-
switch (_a.label) {
|
|
244
|
-
case 0:
|
|
245
|
-
fileName = "label";
|
|
246
|
-
selectedLabels = [];
|
|
247
|
-
for (_i = 0, selectedData_1 = selectedData; _i < selectedData_1.length; _i++) {
|
|
248
|
-
label = selectedData_1[_i];
|
|
249
|
-
fileName += label;
|
|
250
|
-
selectedLabels.push(Number(label));
|
|
251
|
-
}
|
|
252
|
-
fileName += ".nii";
|
|
253
|
-
if (selectedLabels.length == 0) {
|
|
254
|
-
warnEmptySelection("No ROI selected for download");
|
|
255
|
-
return [2 /*return*/];
|
|
256
|
-
}
|
|
257
|
-
return [4 /*yield*/, props.nv.saveImageByLabels(fileName, selectedLabels)];
|
|
258
|
-
case 1:
|
|
259
|
-
_a.sent();
|
|
260
|
-
return [2 /*return*/];
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
}); } }, { children: _jsx(GetAppIcon, { sx: ROI_TOOLBAR_MUI_ICON_SX }) })) })), _jsx(Tooltip, __assign({ title: "Delete" }, { children: _jsx(IconButton, __assign({ sx: ROI_TOOLBAR_ICON_BUTTON_SX, onClick: function () {
|
|
264
|
-
props.nv.deleteDrawingByLabel(selectedData.map(function (value) { return Number(value); }));
|
|
265
|
-
props.resampleImage();
|
|
266
|
-
props.nv.drawScene();
|
|
267
|
-
} }, { children: _jsx(DeleteIcon, { sx: ROI_TOOLBAR_MUI_ICON_SX }) })) })), _jsx(CMRUpload, { changeNameAfterUpload: false, color: "primary", onUploaded: function (res, file) { }, uploadHandler: function (file) { return __awaiter(void 0, void 0, void 0, function () {
|
|
268
|
-
var filename, response;
|
|
269
|
-
return __generator(this, function (_a) {
|
|
270
|
-
switch (_a.label) {
|
|
271
|
-
case 0:
|
|
272
|
-
console.log(props);
|
|
273
|
-
filename = file.name;
|
|
274
|
-
filename.split(".").pop();
|
|
275
|
-
return [4 /*yield*/, AuthenticatedHttpClient.post(endpoints.ROI_UPLOAD, {
|
|
276
|
-
filename: filename,
|
|
277
|
-
pipeline_id: props.pipelineID,
|
|
278
|
-
type: "image",
|
|
279
|
-
contentType: "application/octet-stream"
|
|
280
|
-
})];
|
|
281
|
-
case 1:
|
|
282
|
-
response = _a.sent();
|
|
283
|
-
console.log(response);
|
|
284
|
-
return [4 /*yield*/, props
|
|
285
|
-
.zipAndSendROI(response.data.upload_url, filename, file)
|
|
286
|
-
.then(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
287
|
-
return __generator(this, function (_a) {
|
|
288
|
-
switch (_a.label) {
|
|
289
|
-
case 0: return [4 /*yield*/, props.unpackROI(response.data.access_url)];
|
|
290
|
-
case 1:
|
|
291
|
-
_a.sent();
|
|
292
|
-
// @ts-ignore
|
|
293
|
-
dispatch(getPipelineROI({ pipeline: pipeline }));
|
|
294
|
-
return [2 /*return*/];
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
}); })];
|
|
298
|
-
case 2:
|
|
299
|
-
_a.sent();
|
|
300
|
-
return [2 /*return*/, 200];
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
}); },
|
|
304
|
-
// createPayload={createPayload}
|
|
305
|
-
maxCount: 1 }, uploadKey)] })), _jsx(CmrConfirmation, { name: "Warning", message: warningMessage, color: "error", width: 400, open: warningVisible, setOpen: function (open) { return setWarningVisible(open); }, confirmText: "OK" })] })));
|
|
306
|
-
};
|
|
28
|
+
} })));
|
|
29
|
+
}
|
|
@@ -43,7 +43,7 @@ export var resultSlice = createSlice({
|
|
|
43
43
|
state.resultLoading = action.meta.jobId;
|
|
44
44
|
}),
|
|
45
45
|
builder.addCase(loadResult.fulfilled, function (state, action) {
|
|
46
|
-
var _a;
|
|
46
|
+
var _a, _b, _c, _d, _e;
|
|
47
47
|
// console.log(action.payload);
|
|
48
48
|
state.activeJob = action.payload.job;
|
|
49
49
|
//@ts-ignore
|
|
@@ -52,9 +52,9 @@ export var resultSlice = createSlice({
|
|
|
52
52
|
state.activeJob.setup.task = action.payload.result.headers.options;
|
|
53
53
|
//@ts-ignore
|
|
54
54
|
state.activeJob.logs =
|
|
55
|
-
action.payload.result.log || action.payload.result.headers.
|
|
55
|
+
(_c = (_a = action.payload.result.log) !== null && _a !== void 0 ? _a : (_b = action.payload.result.headers) === null || _b === void 0 ? void 0 : _b.log) !== null && _c !== void 0 ? _c : (_d = action.payload.result.headers) === null || _d === void 0 ? void 0 : _d.logs;
|
|
56
56
|
//@ts-ignore
|
|
57
|
-
state.activeJob.slices = (
|
|
57
|
+
state.activeJob.slices = (_e = action.payload.result.info) === null || _e === void 0 ? void 0 : _e.slices;
|
|
58
58
|
//@ts-ignore
|
|
59
59
|
state.niis[state.activeJob.pipeline_id] = action.payload.niis;
|
|
60
60
|
state.selectedVolume = 1;
|
package/dist/index.d.ts
CHANGED
|
@@ -31,8 +31,12 @@ export { resampleNiivueRoiHistogram, getDefaultRoiHistogramLayout, } from "./Cmr
|
|
|
31
31
|
export type { NiivueRoiHistogramRow, RoiLabelMapping, } from "./CmrComponents/niivue-roi-histogram/resampleNiivueRoiHistogram";
|
|
32
32
|
export { NiivueRoiHistogram } from "./CmrComponents/niivue-roi-histogram/NiivueRoiHistogram";
|
|
33
33
|
export { useNiivueRoiHistogram } from "./CmrComponents/niivue-roi-histogram/useNiivueRoiHistogram";
|
|
34
|
+
export { NiivueRoiTable, DEFAULT_ROI_GROUP_TARGET_LABEL, } from "./CmrComponents/niivue-roi-table/NiivueRoiTable";
|
|
35
|
+
export type { NiivueRoiTableProps } from "./CmrComponents/niivue-roi-table/NiivueRoiTable";
|
|
34
36
|
import type { FC } from "react";
|
|
35
37
|
import type { CmrTableProps } from "./CmrTable/CmrTable";
|
|
38
|
+
import { CMR_TABLE_DEFAULT_HEADER_ICON } from "./CmrTable/CmrTable";
|
|
36
39
|
export declare const CmrTable: FC<CmrTableProps>;
|
|
37
40
|
export type { CmrTableProps };
|
|
41
|
+
export { CMR_TABLE_DEFAULT_HEADER_ICON };
|
|
38
42
|
export * from "./core";
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,8 @@ export { DrawToolkit } from "./CmrComponents/draw-toolkit/DrawToolkit";
|
|
|
28
28
|
export { resampleNiivueRoiHistogram, getDefaultRoiHistogramLayout, } from "./CmrComponents/niivue-roi-histogram/resampleNiivueRoiHistogram";
|
|
29
29
|
export { NiivueRoiHistogram } from "./CmrComponents/niivue-roi-histogram/NiivueRoiHistogram";
|
|
30
30
|
export { useNiivueRoiHistogram } from "./CmrComponents/niivue-roi-histogram/useNiivueRoiHistogram";
|
|
31
|
-
|
|
31
|
+
export { NiivueRoiTable, DEFAULT_ROI_GROUP_TARGET_LABEL, } from "./CmrComponents/niivue-roi-table/NiivueRoiTable";
|
|
32
|
+
import CmrTableComponent, { CMR_TABLE_DEFAULT_HEADER_ICON } from "./CmrTable/CmrTable";
|
|
32
33
|
export var CmrTable = CmrTableComponent;
|
|
34
|
+
export { CMR_TABLE_DEFAULT_HEADER_ICON };
|
|
33
35
|
export * from "./core";
|