@aics/vole-app 3.5.0 → 3.6.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/es/aics-image-viewer/components/App/index.js +10 -0
- package/es/aics-image-viewer/components/ChannelsWidget.js +3 -1
- package/es/aics-image-viewer/components/ChannelsWidgetRow.js +29 -16
- package/es/aics-image-viewer/components/ControlPanel/CopySettingsButton.js +177 -147
- package/es/aics-image-viewer/components/ControlPanel/index.js +4 -1
- package/es/aics-image-viewer/components/Toolbar/styles.css +0 -10
- package/es/aics-image-viewer/components/ViewerCanvasWrapper/index.js +2 -1
- package/es/aics-image-viewer/components/dimension_sliders/AxisClipSliders.js +21 -8
- package/es/aics-image-viewer/components/dimension_sliders/RotationSliders.js +5 -7
- package/es/aics-image-viewer/components/dimension_sliders/SliderRows.js +8 -6
- package/es/aics-image-viewer/components/shared/ControlPanelRow/index.js +4 -2
- package/es/aics-image-viewer/components/shared/ControlPanelRow/styles.css +4 -3
- package/es/aics-image-viewer/components/useVolume.js +58 -24
- package/es/aics-image-viewer/shared/constants.js +24 -0
- package/es/aics-image-viewer/shared/utils/parseSnapshot.js +28 -2
- package/es/aics-image-viewer/shared/utils/parseUrl.js +41 -139
- package/es/aics-image-viewer/shared/utils/test/camera.test.js +1 -1
- package/es/aics-image-viewer/shared/utils/test/parseUrl.test.js +20 -20
- package/es/aics-image-viewer/shared/utils/test/storage.test.js +2 -2
- package/es/aics-image-viewer/shared/utils/test/viewerChannelSettings.test.js +1 -1
- package/es/aics-image-viewer/state/test/deserialize.test.js +1 -1
- package/es/aics-image-viewer/state/test/reset.test.js +1 -1
- package/es/aics-image-viewer/state/test/serialize.test.js +1 -0
- package/package.json +26 -44
- package/type-declarations/aics-image-viewer/components/ChannelsWidget.d.ts +3 -0
- package/type-declarations/aics-image-viewer/components/ChannelsWidgetRow.d.ts +3 -0
- package/type-declarations/aics-image-viewer/components/ControlPanel/CopySettingsButton.d.ts +2 -0
- package/type-declarations/aics-image-viewer/components/ViewerCanvasWrapper/index.d.ts +1 -0
- package/type-declarations/aics-image-viewer/components/dimension_sliders/AxisClipSliders.d.ts +1 -0
- package/type-declarations/aics-image-viewer/components/dimension_sliders/SliderRows.d.ts +1 -2
- package/type-declarations/aics-image-viewer/components/shared/ControlPanelRow/index.d.ts +1 -0
- package/type-declarations/aics-image-viewer/components/useVolume.d.ts +3 -0
- package/type-declarations/aics-image-viewer/shared/constants.d.ts +1 -0
- package/type-declarations/aics-image-viewer/shared/utils/parseSnapshot.d.ts +2 -0
- package/type-declarations/aics-image-viewer/shared/utils/parseUrl.d.ts +1 -8
- package/es/Globals.d.js +0 -0
- package/es/aics-image-viewer/shared/utils/firebase/index.js +0 -109
- package/type-declarations/aics-image-viewer/shared/utils/firebase/index.d.ts +0 -69
|
@@ -103,6 +103,7 @@ var setIndicatorPositions = function setIndicatorPositions(view3d, panelOpen, ha
|
|
|
103
103
|
view3d.setAxisPosition(AXIS_MARGIN_DEFAULT[0], axisY);
|
|
104
104
|
view3d.setTimestepIndicatorPosition(SCALE_BAR_MARGIN_DEFAULT[0], scaleBarY);
|
|
105
105
|
view3d.setScaleBarPosition(scaleBarX, scaleBarY);
|
|
106
|
+
view3d.setLowResIndicatorPosition(scaleBarY);
|
|
106
107
|
};
|
|
107
108
|
var App = function App(props) {
|
|
108
109
|
var _props$showError, _props$viewerChannelS, _scenes$length, _scenes2, _image$imageInfo$volu, _image$imageInfo$subr, _image$imageInfo$time, _props$transform2, _props$transform4, _props$imageDownloadH, _props$parentImageDow;
|
|
@@ -338,12 +339,20 @@ var App = function App(props) {
|
|
|
338
339
|
showError(error, image);
|
|
339
340
|
onImageTitleChange === null || onImageTitleChange === void 0 || onImageTitleChange(undefined);
|
|
340
341
|
}, [showError, onImageTitleChange]);
|
|
342
|
+
var onScrub = useCallback(function (isScrubbing, image) {
|
|
343
|
+
if (isScrubbing) {
|
|
344
|
+
void view3d.enableScrubIndicator(image)["catch"](onError);
|
|
345
|
+
} else {
|
|
346
|
+
view3d.disableScrubIndicator();
|
|
347
|
+
}
|
|
348
|
+
}, [view3d, onError]);
|
|
341
349
|
var volume = useVolume(scenes, {
|
|
342
350
|
viewerChannelSettings: props.viewerChannelSettings,
|
|
343
351
|
onCreateImage: onCreateImage,
|
|
344
352
|
onChannelLoaded: onChannelLoaded,
|
|
345
353
|
onChangeScene: onChangeScene,
|
|
346
354
|
onError: onError,
|
|
355
|
+
onScrub: onScrub,
|
|
347
356
|
maskChannelName: maskChannelName
|
|
348
357
|
});
|
|
349
358
|
var image = volume.image,
|
|
@@ -603,6 +612,7 @@ var App = function App(props) {
|
|
|
603
612
|
numScenes: numScenes,
|
|
604
613
|
playControls: volume.playControls,
|
|
605
614
|
playingAxis: volume.playingAxis,
|
|
615
|
+
setScrubbingAxis: volume.setScrubbingAxis,
|
|
606
616
|
appHeight: props.appHeight,
|
|
607
617
|
visibleControls: visibleControls,
|
|
608
618
|
clippingPanelOpen: clippingPanelOpen,
|
|
@@ -145,7 +145,9 @@ var ChannelsWidget = function ChannelsWidget(props) {
|
|
|
145
145
|
channelDataForChannel: channelDataChannels[channelIndex],
|
|
146
146
|
name: getDisplayName(channelName, channelIndex, viewerChannelSettings),
|
|
147
147
|
onColorChangeComplete: props.onColorChangeComplete,
|
|
148
|
-
saveIsosurface: props.saveIsosurface
|
|
148
|
+
saveIsosurface: props.saveIsosurface,
|
|
149
|
+
getDropdownContainer: props.getDropdownContainer,
|
|
150
|
+
scrollContainer: props.scrollContainer
|
|
149
151
|
});
|
|
150
152
|
};
|
|
151
153
|
var rows = channelDataChannels && Object.entries(channelGroupedByType).filter(function (_ref3) {
|
|
@@ -4,12 +4,13 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
|
|
|
4
4
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
5
5
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
6
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
7
|
-
import {
|
|
7
|
+
import { RightOutlined } from "@ant-design/icons";
|
|
8
|
+
import { Checkbox } from "antd";
|
|
8
9
|
import React, { useCallback, useState } from "react";
|
|
9
10
|
import { colorArrayToObject, colorObjectToArray } from "../shared/utils/colorRepresentations";
|
|
10
11
|
import { select, useViewerState } from "../state/store";
|
|
12
|
+
import CopySettingsButton from "./ControlPanel/CopySettingsButton";
|
|
11
13
|
import ControlPanelRow from "./shared/ControlPanelRow";
|
|
12
|
-
import ViewerIcon from "./shared/ViewerIcon";
|
|
13
14
|
import TfEditor from "./TfEditor";
|
|
14
15
|
var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
|
|
15
16
|
var index = props.index,
|
|
@@ -28,6 +29,11 @@ var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
|
|
|
28
29
|
setControlsOpen = _useState2[1];
|
|
29
30
|
// Don't show controls in single-channel mode
|
|
30
31
|
var controlsOpen = _controlsOpen && !singleChannelMode;
|
|
32
|
+
var toggleControlsOpen = useCallback(function () {
|
|
33
|
+
return setControlsOpen(function (open) {
|
|
34
|
+
return !open;
|
|
35
|
+
});
|
|
36
|
+
}, []);
|
|
31
37
|
var onClickChannel = useCallback(function () {
|
|
32
38
|
if (singleChannelMode) {
|
|
33
39
|
changeViewerSetting("singleChannelIndex", index);
|
|
@@ -70,18 +76,12 @@ var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
|
|
|
70
76
|
}, "Vol"), /*#__PURE__*/React.createElement(Checkbox, {
|
|
71
77
|
checked: channelState.isosurfaceEnabled,
|
|
72
78
|
onChange: isosurfaceCheckHandler
|
|
73
|
-
}, "Surf"), /*#__PURE__*/React.createElement(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}),
|
|
80
|
-
onClick: function onClick() {
|
|
81
|
-
return setControlsOpen(!controlsOpen);
|
|
82
|
-
},
|
|
83
|
-
title: "Open channel settings",
|
|
84
|
-
type: "text"
|
|
79
|
+
}, "Surf"), /*#__PURE__*/React.createElement(CopySettingsButton, {
|
|
80
|
+
hide: props.controlPanelCollapsed,
|
|
81
|
+
getDropdownContainer: props.getDropdownContainer,
|
|
82
|
+
scrollContainer: props.scrollContainer,
|
|
83
|
+
hideImportExport: true,
|
|
84
|
+
channelIndex: props.index
|
|
85
85
|
}));
|
|
86
86
|
var renderControls = function renderControls() {
|
|
87
87
|
var showEditor = singleChannelMode ? singleChannelIndex === index : channelState.volumeEnabled || channelState.isosurfaceEnabled;
|
|
@@ -126,13 +126,26 @@ var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
|
|
|
126
126
|
var rowClass = controlsOpen ? "" : " controls-closed";
|
|
127
127
|
return /*#__PURE__*/React.createElement(ControlPanelRow, {
|
|
128
128
|
key: index,
|
|
129
|
-
title:
|
|
129
|
+
title: /*#__PURE__*/React.createElement("span", {
|
|
130
|
+
onClick: toggleControlsOpen,
|
|
131
|
+
style: {
|
|
132
|
+
cursor: "pointer"
|
|
133
|
+
}
|
|
134
|
+
}, props.name),
|
|
130
135
|
color: colorArrayToObject(channelState.color),
|
|
131
136
|
onColorChange: onColorChange,
|
|
132
137
|
onColorChangeComplete: props.onColorChangeComplete,
|
|
133
138
|
onClick: onClickChannel,
|
|
134
139
|
className: rowClass,
|
|
135
|
-
highlight: thisChannelOnly
|
|
140
|
+
highlight: thisChannelOnly,
|
|
141
|
+
icon: /*#__PURE__*/React.createElement(RightOutlined, {
|
|
142
|
+
style: {
|
|
143
|
+
transition: "transform 0.3s",
|
|
144
|
+
transform: controlsOpen ? "rotate(90deg)" : "rotate(0deg)",
|
|
145
|
+
cursor: "pointer"
|
|
146
|
+
},
|
|
147
|
+
onClick: toggleControlsOpen
|
|
148
|
+
})
|
|
136
149
|
}, visibilityControls, controlsOpen && /*#__PURE__*/React.createElement("div", {
|
|
137
150
|
style: {
|
|
138
151
|
width: "100%"
|
|
@@ -10,21 +10,21 @@ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try {
|
|
|
10
10
|
function _OverloadYield(e, d) { this.v = e, this.k = d; }
|
|
11
11
|
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
12
12
|
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
13
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
14
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
15
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
16
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
17
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
13
18
|
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
14
19
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
15
20
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
16
21
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
17
22
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
18
23
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
19
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
20
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
21
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
22
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
23
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
24
24
|
import { DragOutlined, EllipsisOutlined, ExclamationCircleOutlined, WarningOutlined } from "@ant-design/icons";
|
|
25
25
|
import { Alert, Button, Checkbox, Dropdown, Modal, Tooltip, Upload } from "antd";
|
|
26
26
|
import React from "react";
|
|
27
|
-
import { channelStatesToSnapshot, isStoreSnapshot, snapshotToChannelStates } from "../../shared/utils/parseSnapshot";
|
|
27
|
+
import { channelStatesToSnapshot, isStoreSnapshot, singleChannelStateToSnapshot, snapshotToChannelStates } from "../../shared/utils/parseSnapshot";
|
|
28
28
|
import { queryPasteDenied } from "../../shared/utils/permissions";
|
|
29
29
|
import { useViewerState } from "../../state/store";
|
|
30
30
|
import { cloneChannelState } from "../../state/util";
|
|
@@ -35,41 +35,17 @@ var ImportModalState = /*#__PURE__*/function (ImportModalState) {
|
|
|
35
35
|
ImportModalState[ImportModalState["Warning"] = 2] = "Warning";
|
|
36
36
|
return ImportModalState;
|
|
37
37
|
}(ImportModalState || {});
|
|
38
|
-
var
|
|
39
|
-
var _useViewerState$getSt = useViewerState.getState(),
|
|
40
|
-
channelSettings = _useViewerState$getSt.channelSettings,
|
|
41
|
-
replaceAllChannelSettings = _useViewerState$getSt.replaceAllChannelSettings;
|
|
38
|
+
var parseSnapshot = function parseSnapshot(snapshotString) {
|
|
42
39
|
var parsed;
|
|
43
40
|
try {
|
|
44
|
-
parsed = JSON.parse(
|
|
41
|
+
parsed = JSON.parse(snapshotString);
|
|
45
42
|
} catch (_unused) {
|
|
46
43
|
parsed = undefined;
|
|
47
44
|
}
|
|
48
45
|
if (!isStoreSnapshot(parsed)) {
|
|
49
|
-
return
|
|
50
|
-
success: false
|
|
51
|
-
};
|
|
46
|
+
return undefined;
|
|
52
47
|
}
|
|
53
|
-
|
|
54
|
-
var channelCount = Object.keys(channelStates).length;
|
|
55
|
-
var currentStates = channelSettings.map(cloneChannelState);
|
|
56
|
-
var nextStates = channelSettings.map(function (state) {
|
|
57
|
-
var result = _objectSpread(_objectSpread({}, cloneChannelState(state)), channelStates[state.name]);
|
|
58
|
-
delete channelStates[state.name];
|
|
59
|
-
return result;
|
|
60
|
-
});
|
|
61
|
-
replaceAllChannelSettings(nextStates);
|
|
62
|
-
var undo = function undo() {
|
|
63
|
-
return replaceAllChannelSettings(currentStates);
|
|
64
|
-
};
|
|
65
|
-
var unmatched = Object.keys(channelStates);
|
|
66
|
-
var matchedCount = channelCount - unmatched.length;
|
|
67
|
-
return {
|
|
68
|
-
success: true,
|
|
69
|
-
matchedCount: matchedCount,
|
|
70
|
-
unmatched: unmatched,
|
|
71
|
-
undo: undo
|
|
72
|
-
};
|
|
48
|
+
return snapshotToChannelStates(parsed);
|
|
73
49
|
};
|
|
74
50
|
var PartialMatchMessage = function PartialMatchMessage(props) {
|
|
75
51
|
var matchedCount = props.matchedCount,
|
|
@@ -84,7 +60,7 @@ var PartialMatchMessage = function PartialMatchMessage(props) {
|
|
|
84
60
|
var SuccessMessage = function SuccessMessage(_ref) {
|
|
85
61
|
var channelCount = _ref.channelCount,
|
|
86
62
|
undo = _ref.undo;
|
|
87
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, "Settings applied to "
|
|
63
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, "Settings applied", channelCount !== undefined && " to ".concat(channelCount, " channel").concat(channelCount > 1 ? "s" : ""), " -", " ", /*#__PURE__*/React.createElement(Button, {
|
|
88
64
|
type: "link",
|
|
89
65
|
style: {
|
|
90
66
|
padding: 0,
|
|
@@ -124,13 +100,13 @@ var CopySettingsButton = function CopySettingsButton(props) {
|
|
|
124
100
|
alert = _useContextualAlert2[0],
|
|
125
101
|
showContextualAlert = _useContextualAlert2[1];
|
|
126
102
|
var _React$useState9 = React.useState(undefined),
|
|
127
|
-
_React$
|
|
128
|
-
modalAlert = _React$
|
|
129
|
-
setModalAlert = _React$
|
|
130
|
-
var _React$
|
|
131
|
-
_React$
|
|
132
|
-
modalAlertType = _React$
|
|
133
|
-
setModalAlertType = _React$
|
|
103
|
+
_React$useState0 = _slicedToArray(_React$useState9, 2),
|
|
104
|
+
modalAlert = _React$useState0[0],
|
|
105
|
+
setModalAlert = _React$useState0[1];
|
|
106
|
+
var _React$useState1 = React.useState(undefined),
|
|
107
|
+
_React$useState10 = _slicedToArray(_React$useState1, 2),
|
|
108
|
+
modalAlertType = _React$useState10[0],
|
|
109
|
+
setModalAlertType = _React$useState10[1];
|
|
134
110
|
var showModalAlert = React.useCallback(function (content, alertType) {
|
|
135
111
|
setModalAlert(content);
|
|
136
112
|
setModalAlertType(alertType);
|
|
@@ -153,11 +129,106 @@ var CopySettingsButton = function CopySettingsButton(props) {
|
|
|
153
129
|
title: "You must grant access to the clipboard",
|
|
154
130
|
placement: "right"
|
|
155
131
|
}, /*#__PURE__*/React.createElement(ExclamationCircleOutlined, null));
|
|
132
|
+
var applySnapshotText = React.useCallback(function (jsonTextSnapshot, sourceName, defaultModalAlerts) {
|
|
133
|
+
var showDefaultAlert = defaultModalAlerts ? showModalAlert : showContextualAlert;
|
|
134
|
+
var sourceNameCapitalized = sourceName.charAt(0).toUpperCase() + sourceName.slice(1);
|
|
135
|
+
var parsedStates = parseSnapshot(jsonTextSnapshot);
|
|
136
|
+
var _useViewerState$getSt = useViewerState.getState(),
|
|
137
|
+
channelSettings = _useViewerState$getSt.channelSettings,
|
|
138
|
+
replaceAllChannelSettings = _useViewerState$getSt.replaceAllChannelSettings;
|
|
139
|
+
var currentStates = channelSettings.map(cloneChannelState);
|
|
140
|
+
if (parsedStates === undefined) {
|
|
141
|
+
showDefaultAlert("".concat(sourceNameCapitalized, " does not contain channel settings"), "error");
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
var channelCount = Object.keys(parsedStates).length;
|
|
145
|
+
var states = currentStates.map(function (state) {
|
|
146
|
+
var result = _objectSpread(_objectSpread({}, cloneChannelState(state)), parsedStates[state.name]);
|
|
147
|
+
delete parsedStates[state.name];
|
|
148
|
+
return result;
|
|
149
|
+
});
|
|
150
|
+
var unmatched = Object.keys(parsedStates);
|
|
151
|
+
var matchedCount = channelCount - unmatched.length;
|
|
152
|
+
var unmatchedCount = unmatched.length;
|
|
153
|
+
replaceAllChannelSettings(states);
|
|
154
|
+
undoRef.current = function () {
|
|
155
|
+
return replaceAllChannelSettings(currentStates);
|
|
156
|
+
};
|
|
157
|
+
if (unmatchedCount > 0) {
|
|
158
|
+
if (matchedCount > 0) {
|
|
159
|
+
// Some channels in the text snapshot matched, some did not
|
|
160
|
+
setImportModalState(ImportModalState.Warning);
|
|
161
|
+
showModalAlert(/*#__PURE__*/React.createElement(PartialMatchMessage, {
|
|
162
|
+
matchedCount: matchedCount,
|
|
163
|
+
unmatched: unmatched
|
|
164
|
+
}), "warning");
|
|
165
|
+
} else {
|
|
166
|
+
// No channels in the text snapshot matched channels in the current image
|
|
167
|
+
showDefaultAlert("Channel names in ".concat(sourceName, " did not match names in image"), "error");
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
if (matchedCount > 0) {
|
|
171
|
+
// All channels matched!
|
|
172
|
+
setImportModalState(ImportModalState.Closed);
|
|
173
|
+
showContextualAlert(/*#__PURE__*/React.createElement(SuccessMessage, {
|
|
174
|
+
channelCount: matchedCount,
|
|
175
|
+
undo: undo
|
|
176
|
+
}));
|
|
177
|
+
} else {
|
|
178
|
+
// There were no channels in the text snapshot at all!
|
|
179
|
+
showDefaultAlert("".concat(sourceNameCapitalized, " does not contain channel settings"), "error");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return true;
|
|
183
|
+
}, [showContextualAlert, showModalAlert, undo]);
|
|
184
|
+
var applySingleChannelSnapshotText = React.useCallback(function (textSnapshot, sourceName, defaultModalAlerts, channelIndex) {
|
|
185
|
+
var showDefaultAlert = defaultModalAlerts ? showModalAlert : showContextualAlert;
|
|
186
|
+
var sourceNameCapitalized = sourceName.charAt(0).toUpperCase() + sourceName.slice(1);
|
|
187
|
+
var parsedStates = parseSnapshot(textSnapshot);
|
|
188
|
+
if (parsedStates === undefined) {
|
|
189
|
+
showDefaultAlert("".concat(sourceNameCapitalized, " does not contain a channel setting"), "error");
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
var states = Object.values(parsedStates);
|
|
193
|
+
if (states.length < 1) {
|
|
194
|
+
showDefaultAlert("".concat(sourceNameCapitalized, " does not contain a channel setting"), "error");
|
|
195
|
+
return false;
|
|
196
|
+
} else if (states.length > 1) {
|
|
197
|
+
showDefaultAlert("".concat(sourceNameCapitalized, " contains multiple channel settings and can't be applied to a single channel"), "error");
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
var state = states[0];
|
|
201
|
+
var _useViewerState$getSt2 = useViewerState.getState(),
|
|
202
|
+
channelSettings = _useViewerState$getSt2.channelSettings,
|
|
203
|
+
replaceAllChannelSettings = _useViewerState$getSt2.replaceAllChannelSettings;
|
|
204
|
+
var currentStates = channelSettings.map(cloneChannelState);
|
|
205
|
+
var newStates = channelSettings.map(function (currentState, index) {
|
|
206
|
+
if (index === channelIndex) {
|
|
207
|
+
return _objectSpread(_objectSpread({}, cloneChannelState(currentState)), state);
|
|
208
|
+
} else {
|
|
209
|
+
return cloneChannelState(currentState);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
replaceAllChannelSettings(newStates);
|
|
213
|
+
undoRef.current = function () {
|
|
214
|
+
return replaceAllChannelSettings(currentStates);
|
|
215
|
+
};
|
|
216
|
+
showContextualAlert(/*#__PURE__*/React.createElement(SuccessMessage, {
|
|
217
|
+
undo: undo
|
|
218
|
+
}));
|
|
219
|
+
return true;
|
|
220
|
+
}, [showContextualAlert, showModalAlert, undo]);
|
|
156
221
|
var onClickExport = React.useCallback(function () {
|
|
157
222
|
setDropdownOpen(false);
|
|
158
|
-
var _useViewerState$
|
|
159
|
-
channelSettings = _useViewerState$
|
|
160
|
-
var serialized
|
|
223
|
+
var _useViewerState$getSt3 = useViewerState.getState(),
|
|
224
|
+
channelSettings = _useViewerState$getSt3.channelSettings;
|
|
225
|
+
var serialized;
|
|
226
|
+
if (props.channelIndex !== undefined) {
|
|
227
|
+
var channel = channelSettings[props.channelIndex];
|
|
228
|
+
serialized = singleChannelStateToSnapshot(channel, includeColor ? undefined : ["color"]);
|
|
229
|
+
} else {
|
|
230
|
+
serialized = channelStatesToSnapshot(channelSettings, includeColor ? undefined : ["color"]);
|
|
231
|
+
}
|
|
161
232
|
var stateText = JSON.stringify(serialized);
|
|
162
233
|
var link = document.createElement("a");
|
|
163
234
|
link.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(stateText));
|
|
@@ -168,9 +239,9 @@ var CopySettingsButton = function CopySettingsButton(props) {
|
|
|
168
239
|
document.body.appendChild(link);
|
|
169
240
|
link.click();
|
|
170
241
|
document.body.removeChild(link);
|
|
171
|
-
}, [imageName, includeColor]);
|
|
242
|
+
}, [imageName, includeColor, props.channelIndex]);
|
|
172
243
|
var onClickPaste = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
|
173
|
-
var clipboard
|
|
244
|
+
var clipboard;
|
|
174
245
|
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
175
246
|
while (1) switch (_context.prev = _context.next) {
|
|
176
247
|
case 0:
|
|
@@ -193,51 +264,20 @@ var CopySettingsButton = function CopySettingsButton(props) {
|
|
|
193
264
|
queryPasteDenied().then(setPasteDenied);
|
|
194
265
|
return _context.abrupt("return");
|
|
195
266
|
case 13:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
_context.next = 17;
|
|
199
|
-
break;
|
|
200
|
-
}
|
|
201
|
-
showContextualAlert("Clipboard does not contain channel settings", "error");
|
|
202
|
-
return _context.abrupt("return");
|
|
203
|
-
case 17:
|
|
204
|
-
unmatched = importResult.unmatched, matchedCount = importResult.matchedCount;
|
|
205
|
-
unmatchedCount = unmatched.length;
|
|
206
|
-
undoRef.current = function () {
|
|
207
|
-
importResult.undo();
|
|
208
|
-
showContextualAlert(undefined);
|
|
209
|
-
showModalAlert(undefined);
|
|
210
|
-
};
|
|
211
|
-
if (unmatchedCount > 0) {
|
|
212
|
-
if (matchedCount > 0) {
|
|
213
|
-
showModalAlert(/*#__PURE__*/React.createElement(PartialMatchMessage, importResult), "warning");
|
|
214
|
-
setImportModalState(ImportModalState.Warning);
|
|
215
|
-
} else {
|
|
216
|
-
showContextualAlert("Channel names in clipboard did not match names in image", "error");
|
|
217
|
-
}
|
|
267
|
+
if (props.channelIndex !== undefined) {
|
|
268
|
+
applySingleChannelSnapshotText(clipboard, "clipboard", false, props.channelIndex);
|
|
218
269
|
} else {
|
|
219
|
-
|
|
220
|
-
showContextualAlert(/*#__PURE__*/React.createElement(React.Fragment, null, "Settings applied to ", matchedCount, " channel", matchedCount > 1 ? "s" : "", " -", " ", /*#__PURE__*/React.createElement(Button, {
|
|
221
|
-
type: "link",
|
|
222
|
-
style: {
|
|
223
|
-
padding: 0,
|
|
224
|
-
height: "unset"
|
|
225
|
-
},
|
|
226
|
-
onClick: undo
|
|
227
|
-
}, "Undo")));
|
|
228
|
-
} else {
|
|
229
|
-
showContextualAlert("Clipboard does not contain channel settings", "error");
|
|
230
|
-
}
|
|
270
|
+
applySnapshotText(clipboard, "clipboard", false);
|
|
231
271
|
}
|
|
232
|
-
case
|
|
272
|
+
case 14:
|
|
233
273
|
case "end":
|
|
234
274
|
return _context.stop();
|
|
235
275
|
}
|
|
236
276
|
}, _callee, null, [[2, 8]]);
|
|
237
|
-
})), [
|
|
277
|
+
})), [applySingleChannelSnapshotText, applySnapshotText, props.channelIndex, showContextualAlert]);
|
|
238
278
|
var onImportFile = React.useCallback(/*#__PURE__*/function () {
|
|
239
279
|
var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(_ref3) {
|
|
240
|
-
var file, onSuccess, onError, text,
|
|
280
|
+
var file, onSuccess, onError, text, result;
|
|
241
281
|
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
242
282
|
while (1) switch (_context2.prev = _context2.next) {
|
|
243
283
|
case 0:
|
|
@@ -246,46 +286,17 @@ var CopySettingsButton = function CopySettingsButton(props) {
|
|
|
246
286
|
return file.text();
|
|
247
287
|
case 3:
|
|
248
288
|
text = _context2.sent;
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
289
|
+
if (props.channelIndex !== undefined) {
|
|
290
|
+
result = applySingleChannelSnapshotText(text, "file", true, props.channelIndex);
|
|
291
|
+
} else {
|
|
292
|
+
result = applySnapshotText(text, "file", true);
|
|
253
293
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
return _context2.abrupt("return");
|
|
257
|
-
case 9:
|
|
258
|
-
matchedCount = importResult.matchedCount, unmatched = importResult.unmatched;
|
|
259
|
-
unmatchedCount = unmatched.length;
|
|
260
|
-
undoRef.current = function () {
|
|
261
|
-
importResult.undo();
|
|
262
|
-
showContextualAlert(undefined);
|
|
263
|
-
showModalAlert(undefined);
|
|
264
|
-
};
|
|
265
|
-
if (unmatchedCount > 0) {
|
|
266
|
-
if (matchedCount > 0) {
|
|
267
|
-
// Some channels in the file matched, some did not
|
|
268
|
-
setImportModalState(ImportModalState.Warning);
|
|
269
|
-
showModalAlert(/*#__PURE__*/React.createElement(PartialMatchMessage, importResult), "warning");
|
|
270
|
-
} else {
|
|
271
|
-
// No channels in the file matched channels in the current image
|
|
272
|
-
showModalAlert("Channel names in file did not match names in image", "error");
|
|
273
|
-
}
|
|
294
|
+
if (result) {
|
|
295
|
+
onSuccess === null || onSuccess === void 0 || onSuccess(undefined);
|
|
274
296
|
} else {
|
|
275
|
-
|
|
276
|
-
// All channels matched!
|
|
277
|
-
setImportModalState(ImportModalState.Closed);
|
|
278
|
-
showContextualAlert(/*#__PURE__*/React.createElement(SuccessMessage, {
|
|
279
|
-
channelCount: matchedCount,
|
|
280
|
-
undo: undo
|
|
281
|
-
}));
|
|
282
|
-
} else {
|
|
283
|
-
// There were no channels in the file at all!
|
|
284
|
-
showModalAlert("File does not contain channel settings", "error");
|
|
285
|
-
}
|
|
297
|
+
onError === null || onError === void 0 || onError(new Error());
|
|
286
298
|
}
|
|
287
|
-
|
|
288
|
-
case 14:
|
|
299
|
+
case 6:
|
|
289
300
|
case "end":
|
|
290
301
|
return _context2.stop();
|
|
291
302
|
}
|
|
@@ -294,28 +305,31 @@ var CopySettingsButton = function CopySettingsButton(props) {
|
|
|
294
305
|
return function (_x) {
|
|
295
306
|
return _ref4.apply(this, arguments);
|
|
296
307
|
};
|
|
297
|
-
}(), [
|
|
298
|
-
var
|
|
299
|
-
key:
|
|
308
|
+
}(), [applySingleChannelSnapshotText, applySnapshotText, props.channelIndex]);
|
|
309
|
+
var copyItem = {
|
|
310
|
+
key: "Copy",
|
|
300
311
|
label: "Copy",
|
|
301
312
|
onClick: function onClick() {
|
|
302
313
|
setDropdownOpen(false);
|
|
303
314
|
try {
|
|
304
|
-
var _useViewerState$
|
|
305
|
-
channelSettings = _useViewerState$
|
|
306
|
-
var serialized
|
|
315
|
+
var _useViewerState$getSt4 = useViewerState.getState(),
|
|
316
|
+
channelSettings = _useViewerState$getSt4.channelSettings;
|
|
317
|
+
var serialized;
|
|
318
|
+
if (props.channelIndex !== undefined) {
|
|
319
|
+
var channel = channelSettings[props.channelIndex];
|
|
320
|
+
serialized = singleChannelStateToSnapshot(channel, includeColor ? undefined : ["color"]);
|
|
321
|
+
} else {
|
|
322
|
+
serialized = channelStatesToSnapshot(channelSettings, includeColor ? undefined : ["color"]);
|
|
323
|
+
}
|
|
307
324
|
navigator.clipboard.writeText(JSON.stringify(serialized));
|
|
308
325
|
showContextualAlert("Settings copied");
|
|
309
326
|
} catch (_unused3) {
|
|
310
327
|
showContextualAlert("Could not copy settings", "error");
|
|
311
328
|
}
|
|
312
329
|
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
onClick: onClickExport
|
|
317
|
-
}, {
|
|
318
|
-
key: 2,
|
|
330
|
+
};
|
|
331
|
+
var pasteItem = {
|
|
332
|
+
key: "Paste",
|
|
319
333
|
label: /*#__PURE__*/React.createElement("div", {
|
|
320
334
|
style: {
|
|
321
335
|
display: "flex",
|
|
@@ -324,19 +338,9 @@ var CopySettingsButton = function CopySettingsButton(props) {
|
|
|
324
338
|
}, /*#__PURE__*/React.createElement("span", null, "Paste"), pastePrompt),
|
|
325
339
|
disabled: pasteDenied,
|
|
326
340
|
onClick: onClickPaste
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
onClick: function onClick() {
|
|
331
|
-
setDropdownOpen(false);
|
|
332
|
-
setImportModalState(ImportModalState.Import);
|
|
333
|
-
showModalAlert(undefined);
|
|
334
|
-
}
|
|
335
|
-
}, {
|
|
336
|
-
key: 4,
|
|
337
|
-
type: "divider"
|
|
338
|
-
}, {
|
|
339
|
-
key: 5,
|
|
341
|
+
};
|
|
342
|
+
var includeColorItem = {
|
|
343
|
+
key: "IncludeColor",
|
|
340
344
|
className: "import-dropdown-menu-item-include-color",
|
|
341
345
|
label: /*#__PURE__*/React.createElement(Checkbox, {
|
|
342
346
|
checked: includeColor
|
|
@@ -349,7 +353,33 @@ var CopySettingsButton = function CopySettingsButton(props) {
|
|
|
349
353
|
return !includeColor;
|
|
350
354
|
});
|
|
351
355
|
}
|
|
352
|
-
}
|
|
356
|
+
};
|
|
357
|
+
var items;
|
|
358
|
+
if (props.hideImportExport) {
|
|
359
|
+
items = [copyItem, pasteItem, {
|
|
360
|
+
key: "divider",
|
|
361
|
+
type: "divider"
|
|
362
|
+
}, includeColorItem];
|
|
363
|
+
} else {
|
|
364
|
+
var exportItem = {
|
|
365
|
+
key: 1,
|
|
366
|
+
label: "Export",
|
|
367
|
+
onClick: onClickExport
|
|
368
|
+
};
|
|
369
|
+
var importItem = {
|
|
370
|
+
key: 3,
|
|
371
|
+
label: "Import",
|
|
372
|
+
onClick: function onClick() {
|
|
373
|
+
setDropdownOpen(false);
|
|
374
|
+
setImportModalState(ImportModalState.Import);
|
|
375
|
+
showModalAlert(undefined);
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
items = [copyItem, exportItem, pasteItem, importItem, {
|
|
379
|
+
key: "divider",
|
|
380
|
+
type: "divider"
|
|
381
|
+
}, includeColorItem];
|
|
382
|
+
}
|
|
353
383
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Dropdown, {
|
|
354
384
|
menu: {
|
|
355
385
|
items: items
|
|
@@ -204,7 +204,10 @@ function ControlPanel(props) {
|
|
|
204
204
|
onColorChangeComplete: props.onColorChangeComplete,
|
|
205
205
|
onApplyColorPresets: props.onApplyColorPresets,
|
|
206
206
|
filterFunc: props.filterFunc,
|
|
207
|
-
viewerChannelSettings: viewerChannelSettings
|
|
207
|
+
viewerChannelSettings: viewerChannelSettings,
|
|
208
|
+
getDropdownContainer: getDropdownContainer,
|
|
209
|
+
scrollContainer: columnRef.current,
|
|
210
|
+
controlPanelCollapsed: props.collapsed
|
|
208
211
|
}), tab === ControlTab.Advanced && renderAdvancedSettings(), tab === ControlTab.Metadata && /*#__PURE__*/React.createElement(MetadataViewer, {
|
|
209
212
|
metadata: props.metadata
|
|
210
213
|
}))));
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
width:100%;
|
|
4
4
|
z-index:250;
|
|
5
5
|
}
|
|
6
|
-
|
|
7
6
|
.viewer-toolbar-container .viewer-toolbar-scroll-left,
|
|
8
7
|
.viewer-toolbar-container .viewer-toolbar-scroll-right{
|
|
9
8
|
height:100%;
|
|
@@ -17,28 +16,22 @@
|
|
|
17
16
|
z-index:255;
|
|
18
17
|
transition:color 0.3s;
|
|
19
18
|
}
|
|
20
|
-
|
|
21
19
|
.viewer-toolbar-container .viewer-toolbar-scroll-left:hover, .viewer-toolbar-container .viewer-toolbar-scroll-right:hover{
|
|
22
20
|
color:white;
|
|
23
21
|
}
|
|
24
|
-
|
|
25
22
|
.viewer-toolbar-container .viewer-toolbar-scroll-left{
|
|
26
23
|
left:0;
|
|
27
24
|
}
|
|
28
|
-
|
|
29
25
|
.viewer-toolbar-container .viewer-toolbar-scroll-right{
|
|
30
26
|
right:0;
|
|
31
27
|
}
|
|
32
|
-
|
|
33
28
|
.viewer-toolbar-container.viewer-toolbar-scroll{
|
|
34
29
|
border-bottom:1px solid var(--color-layout-dividers);
|
|
35
30
|
}
|
|
36
|
-
|
|
37
31
|
.viewer-toolbar-container.viewer-toolbar-scroll .viewer-toolbar-scroll-left,
|
|
38
32
|
.viewer-toolbar-container.viewer-toolbar-scroll .viewer-toolbar-scroll-right{
|
|
39
33
|
display:flex;
|
|
40
34
|
}
|
|
41
|
-
|
|
42
35
|
.viewer-toolbar-container.viewer-toolbar-scroll .viewer-toolbar{
|
|
43
36
|
white-space:nowrap;
|
|
44
37
|
justify-content:normal;
|
|
@@ -46,16 +39,13 @@
|
|
|
46
39
|
overflow-x:scroll;
|
|
47
40
|
scrollbar-width:none;
|
|
48
41
|
}
|
|
49
|
-
|
|
50
42
|
.viewer-toolbar-container.viewer-toolbar-scroll .viewer-toolbar::-webkit-scrollbar{
|
|
51
43
|
display:none;
|
|
52
44
|
}
|
|
53
|
-
|
|
54
45
|
.viewer-toolbar-container.viewer-toolbar-scroll .viewer-toolbar .viewer-toolbar-left{
|
|
55
46
|
position:static;
|
|
56
47
|
margin-left:15px;
|
|
57
48
|
}
|
|
58
|
-
|
|
59
49
|
.viewer-toolbar-container.viewer-toolbar-scroll .viewer-toolbar .viewer-toolbar-right{
|
|
60
50
|
position:static;
|
|
61
51
|
margin-right:15px;
|