/** * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal */ import { PluginCommands } from '../../mol-plugin/command'; import * as React from 'react'; import { PluginUIComponent, PurePluginUIComponent } from './base'; import { shallowEqual } from '../../mol-util'; import { OrderedMap } from 'immutable'; import { ParameterControls } from './controls/parameters'; import { ParamDefinition as PD} from '../../mol-util/param-definition'; import { PluginState } from '../../mol-plugin/state'; import { urlCombine } from '../../mol-util/url'; import { IconButton, Icon } from './controls/common'; import { formatTimespan } from '../../mol-util/now'; export class StateSnapshots extends PluginUIComponent<{ }> { downloadToFile = () => { PluginCommands.State.Snapshots.DownloadToFile.dispatch(this.plugin, { }); } open = (e: React.ChangeEvent) => { if (!e.target.files || !e.target.files![0]) return; PluginCommands.State.Snapshots.OpenFile.dispatch(this.plugin, { file: e.target.files![0] }); } render() { return
State
{'Open JSON'}
; } } class LocalStateSnapshots extends PluginUIComponent< { }, { params: PD.Values }> { state = { params: PD.getDefaultValues(LocalStateSnapshots.Params) }; static Params = { name: PD.Text(), options: PD.Group({ description: PD.Text(), ...PluginState.GetSnapshotParams }) }; add = () => { PluginCommands.State.Snapshots.Add.dispatch(this.plugin, { name: this.state.params.name, description: this.state.params.options.description, params: this.state.params.options }); this.setState({ params: { name: '', options: { ...this.state.params.options, description: '' } } }); } clear = () => { PluginCommands.State.Snapshots.Clear.dispatch(this.plugin, {}); } shouldComponentUpdate(nextProps: any, nextState: any) { return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState); } render() { // TODO: proper styling return
{ const params = { ...this.state.params, [p.name]: p.value }; this.setState({ params } as any); this.plugin.state.snapshots.currentGetSnapshotParams = params.options; }}/>
{/* */}
; } } class LocalStateSnapshotList extends PluginUIComponent<{ }, { }> { componentDidMount() { this.subscribe(this.plugin.events.state.snapshots.changed, () => this.forceUpdate()); } apply = (e: React.MouseEvent) => { const id = e.currentTarget.getAttribute('data-id'); if (!id) return; PluginCommands.State.Snapshots.Apply.dispatch(this.plugin, { id }); } remove = (e: React.MouseEvent) => { const id = e.currentTarget.getAttribute('data-id'); if (!id) return; PluginCommands.State.Snapshots.Remove.dispatch(this.plugin, { id }); } moveUp = (e: React.MouseEvent) => { const id = e.currentTarget.getAttribute('data-id'); if (!id) return; PluginCommands.State.Snapshots.Move.dispatch(this.plugin, { id, dir: -1 }); } moveDown = (e: React.MouseEvent) => { const id = e.currentTarget.getAttribute('data-id'); if (!id) return; PluginCommands.State.Snapshots.Move.dispatch(this.plugin, { id, dir: 1 }); } replace = (e: React.MouseEvent) => { const id = e.currentTarget.getAttribute('data-id'); if (!id) return; PluginCommands.State.Snapshots.Replace.dispatch(this.plugin, { id, params: this.plugin.state.snapshots.currentGetSnapshotParams }); } render() { const current = this.plugin.state.snapshots.state.current; return
    {this.plugin.state.snapshots.state.entries.map(e =>
  • )}
; } } type RemoteEntry = { url: string, removeUrl: string, timestamp: number, id: string, name: string, description: string, isSticky?: boolean } class RemoteStateSnapshots extends PluginUIComponent< { }, { params: PD.Values, entries: OrderedMap, isBusy: boolean }> { state = { params: PD.getDefaultValues(RemoteStateSnapshots.Params), entries: OrderedMap(), isBusy: false }; static Params = { name: PD.Text(), options: PD.Group({ description: PD.Text(), playOnLoad: PD.Boolean(false), serverUrl: PD.Text('https://webchem.ncbr.muni.cz/molstar-state') }) }; componentDidMount() { this.refresh(); // this.subscribe(UploadedEvent, this.refresh); } serverUrl(q?: string) { if (!q) return this.state.params.options.serverUrl; return urlCombine(this.state.params.options.serverUrl, q); } refresh = async () => { try { this.setState({ isBusy: true }); const json = (await this.plugin.runTask(this.plugin.fetch({ url: this.serverUrl('list'), type: 'json' }))) || []; json.sort((a, b) => { if (a.isSticky === b.isSticky) return a.timestamp - b.timestamp; return a.isSticky ? -1 : 1; }); const entries = OrderedMap().asMutable(); for (const e of json) { entries.set(e.id, { ...e, url: this.serverUrl(`get/${e.id}`), removeUrl: this.serverUrl(`remove/${e.id}`) }); } this.setState({ entries: entries.asImmutable(), isBusy: false }) } catch (e) { this.plugin.log.error('Fetching Remote Snapshots: ' + e); this.setState({ entries: OrderedMap(), isBusy: false }) } } upload = async () => { this.setState({ isBusy: true }); if (this.plugin.state.snapshots.state.entries.size === 0) { await PluginCommands.State.Snapshots.Add.dispatch(this.plugin, { name: this.state.params.name, description: this.state.params.options.description, params: this.plugin.state.snapshots.currentGetSnapshotParams }); } await PluginCommands.State.Snapshots.Upload.dispatch(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 }); this.setState({ isBusy: false }); this.plugin.log.message('Snapshot uploaded.'); this.refresh(); } fetch = async (e: React.MouseEvent) => { const id = e.currentTarget.getAttribute('data-id'); if (!id) return; const entry = this.state.entries.get(id); if (!entry) return; this.setState({ isBusy: true }); try { await PluginCommands.State.Snapshots.Fetch.dispatch(this.plugin, { url: entry.url }); } finally { this.setState({ isBusy: false }); } } remove = async (e: React.MouseEvent) => { const id = e.currentTarget.getAttribute('data-id'); if (!id) return; const entry = this.state.entries.get(id); if (!entry) return; this.setState({ entries: this.state.entries.remove(id) }); try { await fetch(entry.removeUrl); } catch { } } render() { return
Remote State
{ this.setState({ params: { ...this.state.params, [p.name]: p.value } } as any); }} isDisabled={this.state.isBusy}/>
; } } class RemoteStateSnapshotList extends PurePluginUIComponent< { entries: OrderedMap, serverUrl: string, isBusy: boolean, fetch: (e: React.MouseEvent) => void, remove: (e: React.MouseEvent) => void }, { }> { open = async (e: React.MouseEvent) => { const id = e.currentTarget.getAttribute('data-id'); if (!id) return; const entry = this.props.entries.get(id); if (!entry) return; e.preventDefault(); let url = `${window.location}`, qi = url.indexOf('?'); if (qi > 0) url = url.substr(0, qi); window.open(`${url}?snapshot-url=${encodeURIComponent(entry.url)}`, '_blank'); } render() { return
    {this.props.entries.valueSeq().map(e =>
  • {!e!.isSticky &&
    }
  • )}
; } }