@aics/vole-app 3.4.4 → 3.5.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 +5 -5
- package/es/aics-image-viewer/components/ColorPicker/index.js +9 -1
- package/es/aics-image-viewer/components/ControlPanel/CopySettingsButton.js +415 -0
- package/es/aics-image-viewer/components/ControlPanel/index.js +12 -4
- package/es/aics-image-viewer/components/ControlPanel/styles.css +29 -2
- package/es/aics-image-viewer/components/StyleProvider/index.js +17 -2
- package/es/aics-image-viewer/components/Toolbar/ViewModeRadioButtons.js +1 -1
- package/es/aics-image-viewer/components/Toolbar/index.js +1 -1
- package/es/aics-image-viewer/components/{CellViewerCanvasWrapper → ViewerCanvasWrapper}/index.js +1 -1
- package/es/aics-image-viewer/components/dimension_sliders/RotationSliders.js +1 -1
- package/es/aics-image-viewer/components/shared/ContextualAlert.js +101 -0
- package/es/aics-image-viewer/components/useVolume.js +1 -1
- package/es/aics-image-viewer/shared/constants.js +1 -1
- package/es/aics-image-viewer/shared/types.js +1 -1
- package/es/aics-image-viewer/shared/utils/controlPointsToLut.js +4 -0
- package/es/aics-image-viewer/shared/utils/parseSnapshot.js +179 -0
- package/es/aics-image-viewer/shared/utils/{urlParsing.js → parseUrl.js} +14 -52
- package/es/aics-image-viewer/shared/utils/permissions.js +46 -0
- package/es/aics-image-viewer/shared/utils/test/camera.test.js +0 -1
- package/es/aics-image-viewer/shared/utils/test/{urlParsing.test.js → parseUrl.test.js} +8 -5
- package/es/aics-image-viewer/state/deserialize.js +443 -331
- package/es/aics-image-viewer/state/reset.js +1 -1
- package/es/aics-image-viewer/state/serialize.js +168 -78
- package/es/aics-image-viewer/state/subscribers.js +1 -1
- package/es/aics-image-viewer/state/test/deserialize.test.js +62 -76
- package/es/aics-image-viewer/state/test/reset.test.js +1 -1
- package/es/aics-image-viewer/state/test/serialize.test.js +41 -43
- package/es/aics-image-viewer/state/test/test_data.js +119 -1
- package/es/aics-image-viewer/state/types.js +157 -245
- package/es/aics-image-viewer/state/util.js +39 -1
- package/es/index.js +4 -2
- package/package.json +1 -1
- package/type-declarations/aics-image-viewer/components/App/types.d.ts +3 -3
- package/type-declarations/aics-image-viewer/components/ControlPanel/CopySettingsButton.d.ts +9 -0
- package/type-declarations/aics-image-viewer/components/Toolbar/ViewModeRadioButtons.d.ts +1 -1
- package/type-declarations/aics-image-viewer/components/{CellViewerCanvasWrapper → ViewerCanvasWrapper}/index.d.ts +3 -3
- package/type-declarations/aics-image-viewer/components/dimension_sliders/AxisClipSliders.d.ts +6 -6
- package/type-declarations/aics-image-viewer/components/shared/ContextualAlert.d.ts +29 -0
- package/type-declarations/aics-image-viewer/shared/constants.d.ts +1 -2
- package/type-declarations/aics-image-viewer/shared/types.d.ts +2 -2
- package/type-declarations/aics-image-viewer/shared/utils/controlPointsToLut.d.ts +1 -1
- package/type-declarations/aics-image-viewer/shared/utils/parseSnapshot.d.ts +47 -0
- package/type-declarations/aics-image-viewer/shared/utils/{urlParsing.d.ts → parseUrl.d.ts} +2 -16
- package/type-declarations/aics-image-viewer/shared/utils/permissions.d.ts +7 -0
- package/type-declarations/aics-image-viewer/shared/utils/viewerChannelSettings.d.ts +1 -1
- package/type-declarations/aics-image-viewer/state/deserialize.d.ts +70 -35
- package/type-declarations/aics-image-viewer/state/reset.d.ts +1 -1
- package/type-declarations/aics-image-viewer/state/serialize.d.ts +44 -10
- package/type-declarations/aics-image-viewer/state/types.d.ts +265 -159
- package/type-declarations/aics-image-viewer/state/util.d.ts +3 -1
- package/type-declarations/index.d.ts +5 -3
- package/es/aics-image-viewer/shared/enums.js +0 -18
- package/type-declarations/aics-image-viewer/shared/enums.d.ts +0 -15
- package/type-declarations/aics-image-viewer/shared/utils/math.d.ts +0 -1
- /package/es/aics-image-viewer/components/{CellViewerCanvasWrapper → ViewerCanvasWrapper}/styles.css +0 -0
|
@@ -20,18 +20,18 @@ import { Layout } from "antd";
|
|
|
20
20
|
import { debounce, isEqual } from "lodash";
|
|
21
21
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
22
22
|
import { AXIS_MARGIN_DEFAULT, CLIPPING_PANEL_HEIGHT_DEFAULT, CLIPPING_PANEL_HEIGHT_TALL, CONTROL_PANEL_CLOSE_WIDTH, getDefaultViewerChannelSettings, SCALE_BAR_MARGIN_DEFAULT } from "../../shared/constants";
|
|
23
|
-
import { ImageType, ViewMode } from "../../shared/enums";
|
|
24
23
|
import { controlPointsToRamp, initializeLut } from "../../shared/utils/controlPointsToLut";
|
|
25
24
|
import { useConstructor } from "../../shared/utils/hooks";
|
|
26
25
|
import { findFirstChannelMatch } from "../../shared/utils/viewerChannelSettings";
|
|
27
26
|
import { select, useViewerState } from "../../state/store";
|
|
28
27
|
import { subscribeImageToState, subscribeViewToState } from "../../state/subscribers";
|
|
28
|
+
import { ImageType, ViewMode } from "../../state/types";
|
|
29
29
|
import useVolume, { ImageLoadStatus } from "../useVolume";
|
|
30
|
-
import CellViewerCanvasWrapper from "../CellViewerCanvasWrapper";
|
|
31
30
|
import ControlPanel from "../ControlPanel";
|
|
32
31
|
import { useErrorAlert } from "../ErrorAlert";
|
|
33
32
|
import StyleProvider from "../StyleProvider";
|
|
34
33
|
import Toolbar from "../Toolbar";
|
|
34
|
+
import CellViewerCanvasWrapper from "../ViewerCanvasWrapper";
|
|
35
35
|
import ChannelUpdater from "./ChannelUpdater";
|
|
36
36
|
import "../../assets/styles/globals.css";
|
|
37
37
|
import "./styles.css";
|
|
@@ -105,7 +105,7 @@ var setIndicatorPositions = function setIndicatorPositions(view3d, panelOpen, ha
|
|
|
105
105
|
view3d.setScaleBarPosition(scaleBarX, scaleBarY);
|
|
106
106
|
};
|
|
107
107
|
var App = function App(props) {
|
|
108
|
-
var _props$showError, _props$viewerChannelS, _scenes$length, _scenes2, _image$imageInfo$volu, _image$imageInfo$subr, _image$imageInfo$time, _props$transform2, _props$transform4;
|
|
108
|
+
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;
|
|
109
109
|
props = _objectSpread(_objectSpread({}, defaultProps), props);
|
|
110
110
|
|
|
111
111
|
// State management /////////////////////////////////////////////////////////
|
|
@@ -582,8 +582,8 @@ var App = function App(props) {
|
|
|
582
582
|
margin: props.canvasMargin
|
|
583
583
|
}
|
|
584
584
|
}, /*#__PURE__*/React.createElement(Content, null, /*#__PURE__*/React.createElement(Toolbar, {
|
|
585
|
-
|
|
586
|
-
|
|
585
|
+
cellDownloadHref: (_props$imageDownloadH = props.imageDownloadHref) !== null && _props$imageDownloadH !== void 0 ? _props$imageDownloadH : defaultProps.imageDownloadHref,
|
|
586
|
+
fovDownloadHref: (_props$parentImageDow = props.parentImageDownloadHref) !== null && _props$parentImageDow !== void 0 ? _props$parentImageDow : defaultProps.parentImageDownloadHref,
|
|
587
587
|
hasParentImage: !!props.parentImageUrl,
|
|
588
588
|
hasCellId: !!props.cellId,
|
|
589
589
|
canPathTrace: view3d ? view3d.hasWebGL2() : false,
|
|
@@ -17,6 +17,13 @@ var DEFAULT_COLOR = {
|
|
|
17
17
|
b: "19",
|
|
18
18
|
a: "1"
|
|
19
19
|
};
|
|
20
|
+
var PRESET_COLOR_HEX = ["#ffffff", "#ff0000", "#ffff00", "#00ff00", "#00ffff", "#0000ff", "#ff00ff", "#c0c0c0"];
|
|
21
|
+
var PRESET_COLORS = PRESET_COLOR_HEX.map(function (color) {
|
|
22
|
+
return {
|
|
23
|
+
color: color,
|
|
24
|
+
title: color.toUpperCase()
|
|
25
|
+
};
|
|
26
|
+
});
|
|
20
27
|
var ColorPicker = function ColorPicker(props) {
|
|
21
28
|
var _React$useState = React.useState(false),
|
|
22
29
|
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
@@ -87,7 +94,8 @@ var ColorPicker = function ColorPicker(props) {
|
|
|
87
94
|
color: currentColor,
|
|
88
95
|
onChange: handleChange,
|
|
89
96
|
onChangeComplete: handleChangeComplete,
|
|
90
|
-
disableAlpha: props.disableAlpha
|
|
97
|
+
disableAlpha: props.disableAlpha,
|
|
98
|
+
presetColors: PRESET_COLORS
|
|
91
99
|
})) : null));
|
|
92
100
|
};
|
|
93
101
|
export default ColorPicker;
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _regeneratorRuntime() { "use strict"; var r = _regenerator(), e = r.m(_regeneratorRuntime), t = (Object.getPrototypeOf ? Object.getPrototypeOf(e) : e.__proto__).constructor; function n(r) { var e = "function" == typeof r && r.constructor; return !!e && (e === t || "GeneratorFunction" === (e.displayName || e.name)); } var o = { "throw": 1, "return": 2, "break": 3, "continue": 3 }; function a(r) { var e, t; return function (n) { e || (e = { stop: function stop() { return t(n.a, 2); }, "catch": function _catch() { return n.v; }, abrupt: function abrupt(r, e) { return t(n.a, o[r], e); }, delegateYield: function delegateYield(r, o, a) { return e.resultName = o, t(n.d, _regeneratorValues(r), a); }, finish: function finish(r) { return t(n.f, r); } }, t = function t(r, _t, o) { n.p = e.prev, n.n = e.next; try { return r(_t, o); } finally { e.next = n.n; } }), e.resultName && (e[e.resultName] = n.v, e.resultName = void 0), e.sent = n.v, e.next = n.n; try { return r.call(this, e); } finally { n.p = e.prev, n.n = e.next; } }; } return (_regeneratorRuntime = function _regeneratorRuntime() { return { wrap: function wrap(e, t, n, o) { return r.w(a(e), t, n, o && o.reverse()); }, isGeneratorFunction: n, mark: r.m, awrap: function awrap(r, e) { return new _OverloadYield(r, e); }, AsyncIterator: _regeneratorAsyncIterator, async: function async(r, e, t, o, u) { return (n(e) ? _regeneratorAsyncGen : _regeneratorAsync)(a(r), e, t, o, u); }, keys: _regeneratorKeys, values: _regeneratorValues }; })(); }
|
|
3
|
+
function _regeneratorValues(e) { if (null != e) { var t = e["function" == typeof Symbol && Symbol.iterator || "@@iterator"], r = 0; if (t) return t.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) return { next: function next() { return e && r >= e.length && (e = void 0), { value: e && e[r++], done: !e }; } }; } throw new TypeError(_typeof(e) + " is not iterable"); }
|
|
4
|
+
function _regeneratorKeys(e) { var n = Object(e), r = []; for (var t in n) r.unshift(t); return function e() { for (; r.length;) if ((t = r.pop()) in n) return e.value = t, e.done = !1, e; return e.done = !0, e; }; }
|
|
5
|
+
function _regeneratorAsync(n, e, r, t, o) { var a = _regeneratorAsyncGen(n, e, r, t, o); return a.next().then(function (n) { return n.done ? n.value : a.next(); }); }
|
|
6
|
+
function _regeneratorAsyncGen(r, e, t, o, n) { return new _regeneratorAsyncIterator(_regenerator().w(r, e, t, o), n || Promise); }
|
|
7
|
+
function _regeneratorAsyncIterator(t, e) { function n(r, o, i, f) { try { var c = t[r](o), u = c.value; return u instanceof _OverloadYield ? e.resolve(u.v).then(function (t) { n("next", t, i, f); }, function (t) { n("throw", t, i, f); }) : e.resolve(u).then(function (t) { c.value = t, i(c); }, function (t) { return n("throw", t, i, f); }); } catch (t) { f(t); } } var r; this.next || (_regeneratorDefine2(_regeneratorAsyncIterator.prototype), _regeneratorDefine2(_regeneratorAsyncIterator.prototype, "function" == typeof Symbol && Symbol.asyncIterator || "@asyncIterator", function () { return this; })), _regeneratorDefine2(this, "_invoke", function (t, o, i) { function f() { return new e(function (e, r) { n(t, i, e, r); }); } return r = r ? r.then(f, f) : f(); }, !0); }
|
|
8
|
+
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
9
|
+
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
10
|
+
function _OverloadYield(e, d) { this.v = e, this.k = d; }
|
|
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
|
+
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 _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
14
|
+
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
|
+
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
|
+
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
|
+
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
|
+
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
|
+
import { DragOutlined, EllipsisOutlined, ExclamationCircleOutlined, WarningOutlined } from "@ant-design/icons";
|
|
25
|
+
import { Alert, Button, Checkbox, Dropdown, Modal, Tooltip, Upload } from "antd";
|
|
26
|
+
import React from "react";
|
|
27
|
+
import { channelStatesToSnapshot, isStoreSnapshot, snapshotToChannelStates } from "../../shared/utils/parseSnapshot";
|
|
28
|
+
import { queryPasteDenied } from "../../shared/utils/permissions";
|
|
29
|
+
import { useViewerState } from "../../state/store";
|
|
30
|
+
import { cloneChannelState } from "../../state/util";
|
|
31
|
+
import { useContextualAlert } from "../shared/ContextualAlert";
|
|
32
|
+
var ImportModalState = /*#__PURE__*/function (ImportModalState) {
|
|
33
|
+
ImportModalState[ImportModalState["Closed"] = 0] = "Closed";
|
|
34
|
+
ImportModalState[ImportModalState["Import"] = 1] = "Import";
|
|
35
|
+
ImportModalState[ImportModalState["Warning"] = 2] = "Warning";
|
|
36
|
+
return ImportModalState;
|
|
37
|
+
}(ImportModalState || {});
|
|
38
|
+
var importSettings = function importSettings(settingsString) {
|
|
39
|
+
var _useViewerState$getSt = useViewerState.getState(),
|
|
40
|
+
channelSettings = _useViewerState$getSt.channelSettings,
|
|
41
|
+
replaceAllChannelSettings = _useViewerState$getSt.replaceAllChannelSettings;
|
|
42
|
+
var parsed;
|
|
43
|
+
try {
|
|
44
|
+
parsed = JSON.parse(settingsString);
|
|
45
|
+
} catch (_unused) {
|
|
46
|
+
parsed = undefined;
|
|
47
|
+
}
|
|
48
|
+
if (!isStoreSnapshot(parsed)) {
|
|
49
|
+
return {
|
|
50
|
+
success: false
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
var channelStates = snapshotToChannelStates(parsed);
|
|
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
|
+
};
|
|
73
|
+
};
|
|
74
|
+
var PartialMatchMessage = function PartialMatchMessage(props) {
|
|
75
|
+
var matchedCount = props.matchedCount,
|
|
76
|
+
unmatched = props.unmatched;
|
|
77
|
+
var unmatchedCount = unmatched.length;
|
|
78
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", null, "Settings applied to ", matchedCount, " channel", matchedCount > 1 ? "s" : "", ". Could not find a match for", " ", unmatchedCount, " channel name", unmatchedCount > 1 ? "s" : "", ":"), /*#__PURE__*/React.createElement("ul", null, unmatched.map(function (channelName, index) {
|
|
79
|
+
return /*#__PURE__*/React.createElement("li", {
|
|
80
|
+
key: index
|
|
81
|
+
}, channelName);
|
|
82
|
+
})));
|
|
83
|
+
};
|
|
84
|
+
var SuccessMessage = function SuccessMessage(_ref) {
|
|
85
|
+
var channelCount = _ref.channelCount,
|
|
86
|
+
undo = _ref.undo;
|
|
87
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, "Settings applied to ", channelCount, " channel", channelCount > 1 ? "s" : "", " -", " ", /*#__PURE__*/React.createElement(Button, {
|
|
88
|
+
type: "link",
|
|
89
|
+
style: {
|
|
90
|
+
padding: 0,
|
|
91
|
+
height: "unset"
|
|
92
|
+
},
|
|
93
|
+
onClick: undo
|
|
94
|
+
}, "Undo"));
|
|
95
|
+
};
|
|
96
|
+
var CopySettingsButton = function CopySettingsButton(props) {
|
|
97
|
+
var imageName = props.imageName,
|
|
98
|
+
scrollContainer = props.scrollContainer,
|
|
99
|
+
hide = props.hide,
|
|
100
|
+
getDropdownContainer = props.getDropdownContainer;
|
|
101
|
+
var buttonRef = React.useRef(null);
|
|
102
|
+
var _React$useState = React.useState(true),
|
|
103
|
+
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
104
|
+
includeColor = _React$useState2[0],
|
|
105
|
+
setIncludeColor = _React$useState2[1];
|
|
106
|
+
var _React$useState3 = React.useState(false),
|
|
107
|
+
_React$useState4 = _slicedToArray(_React$useState3, 2),
|
|
108
|
+
pasteDenied = _React$useState4[0],
|
|
109
|
+
setPasteDenied = _React$useState4[1];
|
|
110
|
+
var _React$useState5 = React.useState(false),
|
|
111
|
+
_React$useState6 = _slicedToArray(_React$useState5, 2),
|
|
112
|
+
dropdownOpen = _React$useState6[0],
|
|
113
|
+
setDropdownOpen = _React$useState6[1];
|
|
114
|
+
var _React$useState7 = React.useState(ImportModalState.Closed),
|
|
115
|
+
_React$useState8 = _slicedToArray(_React$useState7, 2),
|
|
116
|
+
importModalState = _React$useState8[0],
|
|
117
|
+
setImportModalState = _React$useState8[1];
|
|
118
|
+
var _useContextualAlert = useContextualAlert(buttonRef.current, {
|
|
119
|
+
scrollContainer: scrollContainer,
|
|
120
|
+
hide: hide,
|
|
121
|
+
timeout: 8000
|
|
122
|
+
}),
|
|
123
|
+
_useContextualAlert2 = _slicedToArray(_useContextualAlert, 2),
|
|
124
|
+
alert = _useContextualAlert2[0],
|
|
125
|
+
showContextualAlert = _useContextualAlert2[1];
|
|
126
|
+
var _React$useState9 = React.useState(undefined),
|
|
127
|
+
_React$useState10 = _slicedToArray(_React$useState9, 2),
|
|
128
|
+
modalAlert = _React$useState10[0],
|
|
129
|
+
setModalAlert = _React$useState10[1];
|
|
130
|
+
var _React$useState11 = React.useState(undefined),
|
|
131
|
+
_React$useState12 = _slicedToArray(_React$useState11, 2),
|
|
132
|
+
modalAlertType = _React$useState12[0],
|
|
133
|
+
setModalAlertType = _React$useState12[1];
|
|
134
|
+
var showModalAlert = React.useCallback(function (content, alertType) {
|
|
135
|
+
setModalAlert(content);
|
|
136
|
+
setModalAlertType(alertType);
|
|
137
|
+
}, []);
|
|
138
|
+
var undoRef = React.useRef();
|
|
139
|
+
var undo = React.useCallback(function () {
|
|
140
|
+
var _undoRef$current;
|
|
141
|
+
(_undoRef$current = undoRef.current) === null || _undoRef$current === void 0 || _undoRef$current.call(undoRef);
|
|
142
|
+
showModalAlert(undefined);
|
|
143
|
+
showContextualAlert(undefined);
|
|
144
|
+
}, [showContextualAlert, showModalAlert]);
|
|
145
|
+
|
|
146
|
+
// On first render, check if the user has disabled clipboard access
|
|
147
|
+
var firstRenderRef = React.useRef(false);
|
|
148
|
+
if (firstRenderRef.current) {
|
|
149
|
+
queryPasteDenied().then(setPasteDenied);
|
|
150
|
+
firstRenderRef.current = true;
|
|
151
|
+
}
|
|
152
|
+
var pastePrompt = pasteDenied && /*#__PURE__*/React.createElement(Tooltip, {
|
|
153
|
+
title: "You must grant access to the clipboard",
|
|
154
|
+
placement: "right"
|
|
155
|
+
}, /*#__PURE__*/React.createElement(ExclamationCircleOutlined, null));
|
|
156
|
+
var onClickExport = React.useCallback(function () {
|
|
157
|
+
setDropdownOpen(false);
|
|
158
|
+
var _useViewerState$getSt2 = useViewerState.getState(),
|
|
159
|
+
channelSettings = _useViewerState$getSt2.channelSettings;
|
|
160
|
+
var serialized = channelStatesToSnapshot(channelSettings, includeColor ? undefined : ["color"]);
|
|
161
|
+
var stateText = JSON.stringify(serialized);
|
|
162
|
+
var link = document.createElement("a");
|
|
163
|
+
link.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(stateText));
|
|
164
|
+
var isoDate = new Date().toISOString().split("T")[0];
|
|
165
|
+
var imgName = imageName !== null && imageName !== void 0 ? imageName : "settings";
|
|
166
|
+
link.setAttribute("download", "".concat(isoDate, "_").concat(imgName, ".json"));
|
|
167
|
+
link.style.display = "none";
|
|
168
|
+
document.body.appendChild(link);
|
|
169
|
+
link.click();
|
|
170
|
+
document.body.removeChild(link);
|
|
171
|
+
}, [imageName, includeColor]);
|
|
172
|
+
var onClickPaste = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
|
173
|
+
var clipboard, importResult, unmatched, matchedCount, unmatchedCount;
|
|
174
|
+
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
175
|
+
while (1) switch (_context.prev = _context.next) {
|
|
176
|
+
case 0:
|
|
177
|
+
setDropdownOpen(false);
|
|
178
|
+
|
|
179
|
+
// Try to read the clipboard
|
|
180
|
+
clipboard = undefined;
|
|
181
|
+
_context.prev = 2;
|
|
182
|
+
_context.next = 5;
|
|
183
|
+
return navigator.clipboard.readText();
|
|
184
|
+
case 5:
|
|
185
|
+
clipboard = _context.sent;
|
|
186
|
+
_context.next = 13;
|
|
187
|
+
break;
|
|
188
|
+
case 8:
|
|
189
|
+
_context.prev = 8;
|
|
190
|
+
_context.t0 = _context["catch"](2);
|
|
191
|
+
showContextualAlert("Could not read clipboard", "error");
|
|
192
|
+
// If paste failed, check if it was because the user was asked to grant clipboard access and said no
|
|
193
|
+
queryPasteDenied().then(setPasteDenied);
|
|
194
|
+
return _context.abrupt("return");
|
|
195
|
+
case 13:
|
|
196
|
+
importResult = importSettings(clipboard);
|
|
197
|
+
if (importResult.success) {
|
|
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
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
if (matchedCount > 0) {
|
|
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
|
+
}
|
|
231
|
+
}
|
|
232
|
+
case 21:
|
|
233
|
+
case "end":
|
|
234
|
+
return _context.stop();
|
|
235
|
+
}
|
|
236
|
+
}, _callee, null, [[2, 8]]);
|
|
237
|
+
})), [showContextualAlert, showModalAlert, undo]);
|
|
238
|
+
var onImportFile = React.useCallback(/*#__PURE__*/function () {
|
|
239
|
+
var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(_ref3) {
|
|
240
|
+
var file, onSuccess, onError, text, importResult, matchedCount, unmatched, unmatchedCount;
|
|
241
|
+
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
242
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
243
|
+
case 0:
|
|
244
|
+
file = _ref3.file, onSuccess = _ref3.onSuccess, onError = _ref3.onError;
|
|
245
|
+
_context2.next = 3;
|
|
246
|
+
return file.text();
|
|
247
|
+
case 3:
|
|
248
|
+
text = _context2.sent;
|
|
249
|
+
importResult = importSettings(text);
|
|
250
|
+
if (importResult.success) {
|
|
251
|
+
_context2.next = 9;
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
showModalAlert("File does not contain channel settings", "error");
|
|
255
|
+
onError === null || onError === void 0 || onError(new Error());
|
|
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
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
if (matchedCount > 0) {
|
|
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
|
+
}
|
|
286
|
+
}
|
|
287
|
+
onSuccess === null || onSuccess === void 0 || onSuccess(undefined);
|
|
288
|
+
case 14:
|
|
289
|
+
case "end":
|
|
290
|
+
return _context2.stop();
|
|
291
|
+
}
|
|
292
|
+
}, _callee2);
|
|
293
|
+
}));
|
|
294
|
+
return function (_x) {
|
|
295
|
+
return _ref4.apply(this, arguments);
|
|
296
|
+
};
|
|
297
|
+
}(), [showContextualAlert, showModalAlert, undo]);
|
|
298
|
+
var items = [{
|
|
299
|
+
key: 0,
|
|
300
|
+
label: "Copy",
|
|
301
|
+
onClick: function onClick() {
|
|
302
|
+
setDropdownOpen(false);
|
|
303
|
+
try {
|
|
304
|
+
var _useViewerState$getSt3 = useViewerState.getState(),
|
|
305
|
+
channelSettings = _useViewerState$getSt3.channelSettings;
|
|
306
|
+
var serialized = channelStatesToSnapshot(channelSettings, includeColor ? undefined : ["color"]);
|
|
307
|
+
navigator.clipboard.writeText(JSON.stringify(serialized));
|
|
308
|
+
showContextualAlert("Settings copied");
|
|
309
|
+
} catch (_unused3) {
|
|
310
|
+
showContextualAlert("Could not copy settings", "error");
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}, {
|
|
314
|
+
key: 1,
|
|
315
|
+
label: "Export",
|
|
316
|
+
onClick: onClickExport
|
|
317
|
+
}, {
|
|
318
|
+
key: 2,
|
|
319
|
+
label: /*#__PURE__*/React.createElement("div", {
|
|
320
|
+
style: {
|
|
321
|
+
display: "flex",
|
|
322
|
+
justifyContent: "space-between"
|
|
323
|
+
}
|
|
324
|
+
}, /*#__PURE__*/React.createElement("span", null, "Paste"), pastePrompt),
|
|
325
|
+
disabled: pasteDenied,
|
|
326
|
+
onClick: onClickPaste
|
|
327
|
+
}, {
|
|
328
|
+
key: 3,
|
|
329
|
+
label: "Import",
|
|
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,
|
|
340
|
+
className: "import-dropdown-menu-item-include-color",
|
|
341
|
+
label: /*#__PURE__*/React.createElement(Checkbox, {
|
|
342
|
+
checked: includeColor
|
|
343
|
+
}, "Include color setting"),
|
|
344
|
+
onClick: function onClick(_ref5) {
|
|
345
|
+
var domEvent = _ref5.domEvent;
|
|
346
|
+
domEvent.stopPropagation();
|
|
347
|
+
domEvent.preventDefault();
|
|
348
|
+
setIncludeColor(function (includeColor) {
|
|
349
|
+
return !includeColor;
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}];
|
|
353
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Dropdown, {
|
|
354
|
+
menu: {
|
|
355
|
+
items: items
|
|
356
|
+
},
|
|
357
|
+
trigger: ["click"],
|
|
358
|
+
overlayStyle: {
|
|
359
|
+
minWidth: 100
|
|
360
|
+
},
|
|
361
|
+
getPopupContainer: getDropdownContainer,
|
|
362
|
+
open: dropdownOpen,
|
|
363
|
+
onOpenChange: function onOpenChange(open, _ref6) {
|
|
364
|
+
var source = _ref6.source;
|
|
365
|
+
if (open || source === "trigger") {
|
|
366
|
+
setDropdownOpen(open);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}, /*#__PURE__*/React.createElement(Button, {
|
|
370
|
+
type: "text",
|
|
371
|
+
size: "large",
|
|
372
|
+
ref: buttonRef
|
|
373
|
+
}, /*#__PURE__*/React.createElement(EllipsisOutlined, null))), /*#__PURE__*/React.createElement(Modal, {
|
|
374
|
+
closable: true,
|
|
375
|
+
title: importModalState === ImportModalState.Warning ? "Settings applied with exceptions" : "Import channel settings",
|
|
376
|
+
className: "modal-settings-import",
|
|
377
|
+
open: importModalState !== ImportModalState.Closed,
|
|
378
|
+
onCancel: function onCancel() {
|
|
379
|
+
return setImportModalState(ImportModalState.Closed);
|
|
380
|
+
},
|
|
381
|
+
footer: importModalState === ImportModalState.Warning && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
|
382
|
+
onClick: function onClick() {
|
|
383
|
+
undo();
|
|
384
|
+
setImportModalState(ImportModalState.Closed);
|
|
385
|
+
}
|
|
386
|
+
}, "Undo all"), /*#__PURE__*/React.createElement(Button, {
|
|
387
|
+
type: "primary",
|
|
388
|
+
onClick: function onClick() {
|
|
389
|
+
return setImportModalState(ImportModalState.Closed);
|
|
390
|
+
}
|
|
391
|
+
}, "Ok")),
|
|
392
|
+
getContainer: getDropdownContainer
|
|
393
|
+
}, importModalState === ImportModalState.Import && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", null, "Upload a saved .json settings file"), /*#__PURE__*/React.createElement(Upload.Dragger, {
|
|
394
|
+
showUploadList: false,
|
|
395
|
+
customRequest: onImportFile,
|
|
396
|
+
accept: ".json"
|
|
397
|
+
}, /*#__PURE__*/React.createElement(DragOutlined, null), " Drag and drop here or click to browse")), modalAlert !== undefined && /*#__PURE__*/React.createElement(Alert, {
|
|
398
|
+
showIcon: true,
|
|
399
|
+
style: {
|
|
400
|
+
marginTop: 15
|
|
401
|
+
},
|
|
402
|
+
message: modalAlert,
|
|
403
|
+
icon: modalAlertType === "error" ? /*#__PURE__*/React.createElement(WarningOutlined, {
|
|
404
|
+
style: {
|
|
405
|
+
fontSize: 21
|
|
406
|
+
}
|
|
407
|
+
}) : /*#__PURE__*/React.createElement(ExclamationCircleOutlined, {
|
|
408
|
+
style: {
|
|
409
|
+
fontSize: 21
|
|
410
|
+
}
|
|
411
|
+
}),
|
|
412
|
+
type: modalAlertType
|
|
413
|
+
})), alert);
|
|
414
|
+
};
|
|
415
|
+
export default CopySettingsButton;
|
|
@@ -17,6 +17,7 @@ import CustomizeWidget from "../CustomizeWidget";
|
|
|
17
17
|
import GlobalVolumeControls from "../GlobalVolumeControls";
|
|
18
18
|
import MetadataViewer from "../MetadataViewer";
|
|
19
19
|
import ViewerIcon from "../shared/ViewerIcon";
|
|
20
|
+
import CopySettingsButton from "./CopySettingsButton";
|
|
20
21
|
import "./styles.css";
|
|
21
22
|
var ControlTab = /*#__PURE__*/function (ControlTab) {
|
|
22
23
|
ControlTab[ControlTab["Channels"] = 0] = "Channels";
|
|
@@ -38,6 +39,7 @@ function ControlPanel(props) {
|
|
|
38
39
|
var singleChannelMode = useViewerState(select("singleChannelMode"));
|
|
39
40
|
var changeViewerSetting = useViewerState(select("changeViewerSetting"));
|
|
40
41
|
var containerRef = React.useRef(null);
|
|
42
|
+
var columnRef = React.useRef(null);
|
|
41
43
|
var getDropdownContainer = function getDropdownContainer() {
|
|
42
44
|
var _containerRef$current;
|
|
43
45
|
return (_containerRef$current = containerRef.current) !== null && _containerRef$current !== void 0 ? _containerRef$current : document.body;
|
|
@@ -184,10 +186,16 @@ function ControlPanel(props) {
|
|
|
184
186
|
className: "control-panel-col",
|
|
185
187
|
style: {
|
|
186
188
|
flex: "0 0 450px"
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
},
|
|
190
|
+
ref: columnRef
|
|
191
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
192
|
+
className: "control-panel-title-container"
|
|
193
|
+
}, /*#__PURE__*/React.createElement("h2", null, ControlTabNames[tab]), tab === ControlTab.Channels && /*#__PURE__*/React.createElement(CopySettingsButton, {
|
|
194
|
+
imageName: props.imageName,
|
|
195
|
+
scrollContainer: columnRef.current,
|
|
196
|
+
hide: props.collapsed,
|
|
197
|
+
getDropdownContainer: getDropdownContainer
|
|
198
|
+
})), visibleControls.colorPresetsDropdown && tab === ControlTab.Channels && renderChannelSettingsHeader(), hasImage && /*#__PURE__*/React.createElement("div", {
|
|
191
199
|
className: "control-panel-content"
|
|
192
200
|
}, tab === ControlTab.Channels && /*#__PURE__*/React.createElement(ChannelsWidget, {
|
|
193
201
|
channelDataChannels: props.channelDataChannels,
|
|
@@ -57,12 +57,18 @@
|
|
|
57
57
|
display:none;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
.control-panel-col-container .control-panel-col .control-panel-title{
|
|
60
|
+
.control-panel-col-container .control-panel-col .control-panel-title-container{
|
|
61
61
|
margin:16px;
|
|
62
62
|
max-height:24px;
|
|
63
|
-
|
|
63
|
+
display:flex;
|
|
64
|
+
align-items:center;
|
|
65
|
+
justify-content:space-between;
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
.control-panel-col-container .control-panel-col .control-panel-title-container > *{
|
|
69
|
+
font-size:1.4em;
|
|
70
|
+
}
|
|
71
|
+
|
|
66
72
|
.control-panel-col-container .control-panel-col .channel-settings-header{
|
|
67
73
|
margin:0 16px 16px;
|
|
68
74
|
display:flex;
|
|
@@ -177,3 +183,24 @@
|
|
|
177
183
|
font-size:10px;
|
|
178
184
|
top:calc(100% + 3px);
|
|
179
185
|
}
|
|
186
|
+
|
|
187
|
+
.control-panel-col-container .ant-modal.modal-settings-import .ant-upload.ant-upload-drag{
|
|
188
|
+
transition-property:background-color, border-color;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.control-panel-col-container .ant-modal.modal-settings-import .ant-upload.ant-upload-drag:hover{
|
|
192
|
+
background-color:#ffffff20;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.control-panel-col-container .ant-dropdown .import-dropdown-menu-item-include-color{
|
|
196
|
+
white-space:nowrap;
|
|
197
|
+
padding-bottom:9px;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.control-panel-col-container .ant-dropdown .import-dropdown-menu-item-include-color.ant-dropdown-menu-item-active{
|
|
201
|
+
background-color:transparent;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.control-panel-col-container .ant-dropdown .ant-dropdown-menu-item-divider{
|
|
205
|
+
background-color:var(--color-controlpanel-border);
|
|
206
|
+
}
|