UNPKG

molstar

Version:

A comprehensive macromolecular library.

347 lines 24.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RemoteStateSnapshots = exports.LocalStateSnapshotList = exports.LocalStateSnapshots = exports.LocalStateSnapshotParams = exports.StateExportImportControls = exports.StateSnapshots = void 0; var tslib_1 = require("tslib"); var jsx_runtime_1 = require("react/jsx-runtime"); /** * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> */ var immutable_1 = require("immutable"); var commands_1 = require("../../mol-plugin/commands"); var config_1 = require("../../mol-plugin/config"); var state_1 = require("../../mol-plugin/state"); var mol_util_1 = require("../../mol-util"); var now_1 = require("../../mol-util/now"); var param_definition_1 = require("../../mol-util/param-definition"); var url_1 = require("../../mol-util/url"); var base_1 = require("../base"); var common_1 = require("../controls/common"); var icons_1 = require("../controls/icons"); var parameters_1 = require("../controls/parameters"); var StateSnapshots = /** @class */ (function (_super) { (0, tslib_1.__extends)(StateSnapshots, _super); function StateSnapshots() { return _super !== null && _super.apply(this, arguments) || this; } StateSnapshots.prototype.render = function () { var _a; return (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(common_1.SectionHeader, { icon: icons_1.SaveOutlinedSvg, title: 'Plugin State' }, void 0), (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ style: { marginBottom: '10px' } }, { children: (0, jsx_runtime_1.jsx)(common_1.ExpandGroup, (0, tslib_1.__assign)({ header: 'Save Options', initiallyExpanded: false }, { children: (0, jsx_runtime_1.jsx)(LocalStateSnapshotParams, {}, void 0) }), void 0) }), void 0), (0, jsx_runtime_1.jsx)(LocalStateSnapshots, {}, void 0), (0, jsx_runtime_1.jsx)(LocalStateSnapshotList, {}, void 0), (0, jsx_runtime_1.jsx)(common_1.SectionHeader, { title: 'Save as File', accent: 'blue' }, void 0), (0, jsx_runtime_1.jsx)(StateExportImportControls, {}, void 0), ((_a = this.plugin.spec.components) === null || _a === void 0 ? void 0 : _a.remoteState) !== 'none' && (0, jsx_runtime_1.jsx)(RemoteStateSnapshots, {}, void 0)] }, void 0); }; return StateSnapshots; }(base_1.PluginUIComponent)); exports.StateSnapshots = StateSnapshots; var StateExportImportControls = /** @class */ (function (_super) { (0, tslib_1.__extends)(StateExportImportControls, _super); function StateExportImportControls() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.downloadToFileJson = function () { var _a, _b; (_b = (_a = _this.props).onAction) === null || _b === void 0 ? void 0 : _b.call(_a); commands_1.PluginCommands.State.Snapshots.DownloadToFile(_this.plugin, { type: 'json' }); }; _this.downloadToFileZip = function () { var _a, _b; (_b = (_a = _this.props).onAction) === null || _b === void 0 ? void 0 : _b.call(_a); commands_1.PluginCommands.State.Snapshots.DownloadToFile(_this.plugin, { type: 'zip' }); }; _this.open = function (e) { var _a, _b; if (!e.target.files || !e.target.files[0]) { _this.plugin.log.error('No state file selected'); return; } (_b = (_a = _this.props).onAction) === null || _b === void 0 ? void 0 : _b.call(_a); commands_1.PluginCommands.State.Snapshots.OpenFile(_this.plugin, { file: e.target.files[0] }); }; return _this; } StateExportImportControls.prototype.render = function () { return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-flex-row' }, { children: [(0, jsx_runtime_1.jsx)(common_1.Button, (0, tslib_1.__assign)({ icon: icons_1.GetAppSvg, onClick: this.downloadToFileJson, title: 'Save the state description. Input data are loaded using the provided sources. Does not work if local files are used as input.' }, { children: "State" }), void 0), (0, jsx_runtime_1.jsx)(common_1.Button, (0, tslib_1.__assign)({ icon: icons_1.GetAppSvg, onClick: this.downloadToFileZip, title: 'Save the state including the input data.' }, { children: "Session" }), void 0), (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-btn msp-btn-block msp-btn-action msp-loader-msp-btn-file' }, { children: [(0, jsx_runtime_1.jsx)(icons_1.Icon, { svg: icons_1.OpenInBrowserSvg, inline: true }, void 0), " Open ", (0, jsx_runtime_1.jsx)("input", { onChange: this.open, type: 'file', multiple: false, accept: '.molx,.molj' }, void 0)] }), void 0)] }), void 0), (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-help-text', style: { padding: '10px' } }, { children: [(0, jsx_runtime_1.jsx)(icons_1.Icon, { svg: icons_1.WarningSvg }, void 0), " This is an experimental feature and stored states/sessions might not be openable in a future version."] }), void 0)] }, void 0); }; return StateExportImportControls; }(base_1.PluginUIComponent)); exports.StateExportImportControls = StateExportImportControls; var LocalStateSnapshotParams = /** @class */ (function (_super) { (0, tslib_1.__extends)(LocalStateSnapshotParams, _super); function LocalStateSnapshotParams() { return _super !== null && _super.apply(this, arguments) || this; } LocalStateSnapshotParams.prototype.componentDidMount = function () { var _this = this; this.subscribe(this.plugin.state.snapshotParams, function () { return _this.forceUpdate(); }); }; LocalStateSnapshotParams.prototype.render = function () { return (0, jsx_runtime_1.jsx)(parameters_1.ParameterControls, { params: state_1.PluginState.SnapshotParams, values: this.plugin.state.snapshotParams.value, onChangeValues: this.plugin.state.setSnapshotParams }, void 0); }; return LocalStateSnapshotParams; }(base_1.PluginUIComponent)); exports.LocalStateSnapshotParams = LocalStateSnapshotParams; var LocalStateSnapshots = /** @class */ (function (_super) { (0, tslib_1.__extends)(LocalStateSnapshots, _super); function LocalStateSnapshots() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.state = { params: param_definition_1.ParamDefinition.getDefaultValues(LocalStateSnapshots.Params) }; _this.add = function () { commands_1.PluginCommands.State.Snapshots.Add(_this.plugin, { name: _this.state.params.name, description: _this.state.params.description }); }; _this.updateParams = function (params) { return _this.setState({ params: params }); }; _this.clear = function () { commands_1.PluginCommands.State.Snapshots.Clear(_this.plugin, {}); }; return _this; } LocalStateSnapshots.prototype.shouldComponentUpdate = function (nextProps, nextState) { return !(0, mol_util_1.shallowEqualObjects)(this.props, nextProps) || !(0, mol_util_1.shallowEqualObjects)(this.state, nextState); }; LocalStateSnapshots.prototype.render = function () { return (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(parameters_1.ParameterControls, { params: LocalStateSnapshots.Params, values: this.state.params, onEnter: this.add, onChangeValues: this.updateParams }, void 0), (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-flex-row' }, { children: [(0, jsx_runtime_1.jsx)(common_1.IconButton, { onClick: this.clear, svg: icons_1.DeleteOutlinedSvg, title: 'Remove All' }, void 0), (0, jsx_runtime_1.jsx)(common_1.Button, (0, tslib_1.__assign)({ onClick: this.add, icon: icons_1.AddSvg, style: { textAlign: 'right' }, commit: true }, { children: "Add" }), void 0)] }), void 0)] }, void 0); }; LocalStateSnapshots.Params = { name: param_definition_1.ParamDefinition.Text(), description: param_definition_1.ParamDefinition.Text() }; return LocalStateSnapshots; }(base_1.PluginUIComponent)); exports.LocalStateSnapshots = LocalStateSnapshots; var LocalStateSnapshotList = /** @class */ (function (_super) { (0, tslib_1.__extends)(LocalStateSnapshotList, _super); function LocalStateSnapshotList() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.apply = function (e) { var id = e.currentTarget.getAttribute('data-id'); if (!id) return; commands_1.PluginCommands.State.Snapshots.Apply(_this.plugin, { id: id }); }; _this.remove = function (e) { var id = e.currentTarget.getAttribute('data-id'); if (!id) return; commands_1.PluginCommands.State.Snapshots.Remove(_this.plugin, { id: id }); }; _this.moveUp = function (e) { var id = e.currentTarget.getAttribute('data-id'); if (!id) return; commands_1.PluginCommands.State.Snapshots.Move(_this.plugin, { id: id, dir: -1 }); }; _this.moveDown = function (e) { var id = e.currentTarget.getAttribute('data-id'); if (!id) return; commands_1.PluginCommands.State.Snapshots.Move(_this.plugin, { id: id, dir: 1 }); }; _this.replace = function (e) { var id = e.currentTarget.getAttribute('data-id'); if (!id) return; commands_1.PluginCommands.State.Snapshots.Replace(_this.plugin, { id: id }); }; return _this; } LocalStateSnapshotList.prototype.componentDidMount = function () { var _this = this; this.subscribe(this.plugin.managers.snapshot.events.changed, function () { return _this.forceUpdate(); }); }; LocalStateSnapshotList.prototype.render = function () { var _this = this; var current = this.plugin.managers.snapshot.state.current; return (0, jsx_runtime_1.jsx)("ul", (0, tslib_1.__assign)({ style: { listStyle: 'none', marginTop: '10px' }, className: 'msp-state-list' }, { children: this.plugin.managers.snapshot.state.entries.map(function (e) { return (0, jsx_runtime_1.jsxs)("li", (0, tslib_1.__assign)({ className: 'msp-flex-row' }, { children: [(0, jsx_runtime_1.jsxs)(common_1.Button, (0, tslib_1.__assign)({ "data-id": e.snapshot.id, onClick: _this.apply, className: 'msp-no-overflow' }, { children: [(0, jsx_runtime_1.jsx)("span", (0, tslib_1.__assign)({ style: { fontWeight: e.snapshot.id === current ? 'bold' : void 0 } }, { children: e.name || new Date(e.timestamp).toLocaleString() }), void 0), " ", (0, jsx_runtime_1.jsx)("small", { children: "" + (e.snapshot.durationInMs ? (0, now_1.formatTimespan)(e.snapshot.durationInMs, false) + ("" + (e.description ? ', ' : '')) : '') + (e.description ? e.description : '') }, void 0)] }), void 0), (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: icons_1.ArrowUpwardSvg, "data-id": e.snapshot.id, title: 'Move Up', onClick: _this.moveUp, flex: '20px' }, void 0), (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: icons_1.ArrowDownwardSvg, "data-id": e.snapshot.id, title: 'Move Down', onClick: _this.moveDown, flex: '20px' }, void 0), (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: icons_1.SwapHorizSvg, "data-id": e.snapshot.id, title: 'Replace', onClick: _this.replace, flex: '20px' }, void 0), (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: icons_1.DeleteOutlinedSvg, "data-id": e.snapshot.id, title: 'Remove', onClick: _this.remove, flex: '20px' }, void 0)] }), e.snapshot.id); }) }), void 0); }; return LocalStateSnapshotList; }(base_1.PluginUIComponent)); exports.LocalStateSnapshotList = LocalStateSnapshotList; var RemoteStateSnapshots = /** @class */ (function (_super) { (0, tslib_1.__extends)(RemoteStateSnapshots, _super); function RemoteStateSnapshots() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.Params = { name: param_definition_1.ParamDefinition.Text(), options: param_definition_1.ParamDefinition.Group({ description: param_definition_1.ParamDefinition.Text(), playOnLoad: param_definition_1.ParamDefinition.Boolean(false), serverUrl: param_definition_1.ParamDefinition.Text(_this.plugin.config.get(config_1.PluginConfig.State.CurrentServer)) }) }; _this.state = { params: param_definition_1.ParamDefinition.getDefaultValues(_this.Params), entries: (0, immutable_1.OrderedMap)(), isBusy: false }; _this.ListOnlyParams = { options: param_definition_1.ParamDefinition.Group({ serverUrl: param_definition_1.ParamDefinition.Text(_this.plugin.config.get(config_1.PluginConfig.State.CurrentServer)) }, { isFlat: true }) }; _this._mounted = false; _this.refresh = function () { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () { var json, entries, _i, json_1, e, e_1; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); this.setState({ isBusy: true }); this.plugin.config.set(config_1.PluginConfig.State.CurrentServer, this.state.params.options.serverUrl); return [4 /*yield*/, this.plugin.runTask(this.plugin.fetch({ url: this.serverUrl('list'), type: 'json' }))]; case 1: json = (_a.sent()) || []; json.sort(function (a, b) { if (a.isSticky === b.isSticky) return a.timestamp - b.timestamp; return a.isSticky ? -1 : 1; }); entries = (0, immutable_1.OrderedMap)().asMutable(); for (_i = 0, json_1 = json; _i < json_1.length; _i++) { e = json_1[_i]; entries.set(e.id, (0, tslib_1.__assign)((0, tslib_1.__assign)({}, e), { url: this.serverUrl("get/" + e.id), removeUrl: this.serverUrl("remove/" + e.id) })); } if (this._mounted) this.setState({ entries: entries.asImmutable(), isBusy: false }); return [3 /*break*/, 3]; case 2: e_1 = _a.sent(); this.plugin.log.error('Fetching Remote Snapshots: ' + e_1); if (this._mounted) this.setState({ entries: (0, immutable_1.OrderedMap)(), isBusy: false }); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }; _this.upload = function () { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () { return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: this.setState({ isBusy: true }); this.plugin.config.set(config_1.PluginConfig.State.CurrentServer, this.state.params.options.serverUrl); return [4 /*yield*/, commands_1.PluginCommands.State.Snapshots.Upload(this.plugin, { name: this.state.params.name, description: this.state.params.options.description, playOnLoad: this.state.params.options.playOnLoad, serverUrl: this.state.params.options.serverUrl })]; case 1: _a.sent(); this.plugin.log.message('Snapshot uploaded.'); if (this._mounted) { this.setState({ isBusy: false }); this.refresh(); } return [2 /*return*/]; } }); }); }; _this.fetch = function (e) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () { var id, entry; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: id = e.currentTarget.getAttribute('data-id'); if (!id) return [2 /*return*/]; entry = this.state.entries.get(id); if (!entry) return [2 /*return*/]; this.setState({ isBusy: true }); _a.label = 1; case 1: _a.trys.push([1, , 3, 4]); return [4 /*yield*/, commands_1.PluginCommands.State.Snapshots.Fetch(this.plugin, { url: entry.url })]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: if (this._mounted) this.setState({ isBusy: false }); return [7 /*endfinally*/]; case 4: return [2 /*return*/]; } }); }); }; _this.remove = function (e) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () { var id, entry, _a; return (0, tslib_1.__generator)(this, function (_b) { switch (_b.label) { case 0: id = e.currentTarget.getAttribute('data-id'); if (!id) return [2 /*return*/]; entry = this.state.entries.get(id); if (!entry) return [2 /*return*/]; this.setState({ entries: this.state.entries.remove(id) }); _b.label = 1; case 1: _b.trys.push([1, 3, , 4]); return [4 /*yield*/, fetch(entry.removeUrl)]; case 2: _b.sent(); return [3 /*break*/, 4]; case 3: _a = _b.sent(); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; return _this; } RemoteStateSnapshots.prototype.componentDidMount = function () { this.refresh(); // TODO: solve this by using "PluginComponent" with behaviors intead this._mounted = true; // this.subscribe(UploadedEvent, this.refresh); }; RemoteStateSnapshots.prototype.componentWillUnmount = function () { this._mounted = false; }; RemoteStateSnapshots.prototype.serverUrl = function (q) { if (!q) return this.state.params.options.serverUrl; return (0, url_1.urlCombine)(this.state.params.options.serverUrl, q); }; RemoteStateSnapshots.prototype.render = function () { var _this = this; return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(common_1.SectionHeader, { title: 'Remote States', accent: 'blue' }, void 0), !this.props.listOnly && (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(parameters_1.ParameterControls, { params: this.Params, values: this.state.params, onEnter: this.upload, onChange: function (p) { var _a; _this.setState({ params: (0, tslib_1.__assign)((0, tslib_1.__assign)({}, _this.state.params), (_a = {}, _a[p.name] = p.value, _a)) }); }, isDisabled: this.state.isBusy }, void 0), (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-flex-row' }, { children: [(0, jsx_runtime_1.jsx)(common_1.IconButton, { onClick: this.refresh, disabled: this.state.isBusy, svg: icons_1.RefreshSvg }, void 0), (0, jsx_runtime_1.jsx)(common_1.Button, (0, tslib_1.__assign)({ icon: icons_1.CloudUploadSvg, onClick: this.upload, disabled: this.state.isBusy, commit: true }, { children: "Upload" }), void 0)] }), void 0)] }, void 0), (0, jsx_runtime_1.jsx)(RemoteStateSnapshotList, { entries: this.state.entries, isBusy: this.state.isBusy, serverUrl: this.state.params.options.serverUrl, fetch: this.fetch, remove: this.props.listOnly ? void 0 : this.remove }, void 0), this.props.listOnly && (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ style: { marginTop: '10px' } }, { children: [(0, jsx_runtime_1.jsx)(parameters_1.ParameterControls, { params: this.ListOnlyParams, values: this.state.params, onEnter: this.upload, onChange: function (p) { var _a; _this.setState({ params: (0, tslib_1.__assign)((0, tslib_1.__assign)({}, _this.state.params), (_a = {}, _a[p.name] = p.value, _a)) }); }, isDisabled: this.state.isBusy }, void 0), (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-flex-row' }, { children: (0, jsx_runtime_1.jsx)(common_1.Button, (0, tslib_1.__assign)({ onClick: this.refresh, disabled: this.state.isBusy, icon: icons_1.RefreshSvg }, { children: "Refresh" }), void 0) }), void 0)] }), void 0)] }, void 0); }; return RemoteStateSnapshots; }(base_1.PluginUIComponent)); exports.RemoteStateSnapshots = RemoteStateSnapshots; var RemoteStateSnapshotList = /** @class */ (function (_super) { (0, tslib_1.__extends)(RemoteStateSnapshotList, _super); function RemoteStateSnapshotList() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.open = function (e) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () { var id, entry, url, qi; return (0, tslib_1.__generator)(this, function (_a) { id = e.currentTarget.getAttribute('data-id'); if (!id) return [2 /*return*/]; entry = this.props.entries.get(id); if (!entry) return [2 /*return*/]; e.preventDefault(); url = "" + window.location; qi = url.indexOf('?'); if (qi > 0) url = url.substr(0, qi); window.open(url + "?snapshot-url=" + encodeURIComponent(entry.url), '_blank'); return [2 /*return*/]; }); }); }; return _this; } RemoteStateSnapshotList.prototype.render = function () { var _this = this; return (0, jsx_runtime_1.jsx)("ul", (0, tslib_1.__assign)({ style: { listStyle: 'none', marginTop: '10px' }, className: 'msp-state-list' }, { children: this.props.entries.valueSeq().map(function (e) { return (0, jsx_runtime_1.jsxs)("li", (0, tslib_1.__assign)({ className: 'msp-flex-row' }, { children: [(0, jsx_runtime_1.jsxs)(common_1.Button, (0, tslib_1.__assign)({ "data-id": e.id, onClick: _this.props.fetch, disabled: _this.props.isBusy, onContextMenu: _this.open, title: 'Click to download, right-click to open in a new tab.' }, { children: [e.name || new Date(e.timestamp).toLocaleString(), " ", (0, jsx_runtime_1.jsx)("small", { children: e.description }, void 0)] }), void 0), !e.isSticky && _this.props.remove && (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: icons_1.DeleteOutlinedSvg, "data-id": e.id, title: 'Remove', onClick: _this.props.remove, disabled: _this.props.isBusy, small: true }, void 0)] }), e.id); }) }), void 0); }; return RemoteStateSnapshotList; }(base_1.PurePluginUIComponent)); //# sourceMappingURL=snapshots.js.map