cloudmr-ux 4.3.4 → 4.3.6

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.
@@ -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
+ }
@@ -1,11 +1,8 @@
1
- import { CSSProperties } from "react";
2
- export declare const ROITable: (props: {
3
- pipelineID: string;
4
- rois: any[];
5
- resampleImage: () => void;
6
- zipAndSendROI: (url: string, filename: string, blob: Blob) => Promise<void>;
7
- unpackROI: (url: string) => Promise<void>;
8
- setLabelAlias: (label: number | string, alias: string) => void;
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
- 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 { 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
- import { AuthenticatedHttpClient } from "../../common/utilities/AuthenticatedRequests";
62
- /** Default merged ROI label in NiivuePatcher `groupLabelsInto` keep in sync with patcher */
63
- var GROUP_TARGET_LABEL = 7;
64
- /** Toolbar action icons: `action.active` → rgba(0, 0, 0, 0.54) in default MUI light theme */
65
- var ROI_TOOLBAR_ICON_SIZE_PX = 24;
66
- var ROI_TOOLBAR_ICON_BUTTON_SX = {
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
- var roiColumns = [
87
- {
88
- headerName: "ROI Label",
89
- field: "alias",
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
+ }
package/dist/index.d.ts CHANGED
@@ -31,6 +31,8 @@ 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";
36
38
  export declare const CmrTable: FC<CmrTableProps>;
package/dist/index.js CHANGED
@@ -28,6 +28,7 @@ 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
+ export { NiivueRoiTable, DEFAULT_ROI_GROUP_TARGET_LABEL, } from "./CmrComponents/niivue-roi-table/NiivueRoiTable";
31
32
  import CmrTableComponent from "./CmrTable/CmrTable";
32
33
  export var CmrTable = CmrTableComponent;
33
34
  export * from "./core";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudmr-ux",
3
- "version": "4.3.4",
3
+ "version": "4.3.6",
4
4
  "author": "erosmontin@gmail.com",
5
5
  "license": "MIT",
6
6
  "repository": "erosmontin/cloudmr-ux",