From d6241491bc544851a5dfe0d8107074a3ebbac636 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Fri, 8 Feb 2019 14:35:23 +0100 Subject: [PATCH] mol-plugin: Save & open state from a JSON file --- src/mol-plugin/behavior/static/state.ts | 31 +++++++++++++++++++++++++ src/mol-plugin/command.ts | 5 +++- src/mol-plugin/ui/state.tsx | 16 +++++++++++++ src/mol-util/date.ts | 11 +++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/mol-plugin/behavior/static/state.ts b/src/mol-plugin/behavior/static/state.ts index af9541687..420ae299c 100644 --- a/src/mol-plugin/behavior/static/state.ts +++ b/src/mol-plugin/behavior/static/state.ts @@ -11,6 +11,8 @@ import { PluginStateSnapshotManager } from 'mol-plugin/state/snapshots'; import { PluginStateObject as SO, PluginStateObject } from '../../state/objects'; import { EmptyLoci, EveryLoci } from 'mol-model/loci'; import { Structure } from 'mol-model/structure'; +import { getFormattedTime } from 'mol-util/date'; +import { readFromFile } from 'mol-util/data-source'; export function registerDefault(ctx: PluginContext) { SyncBehaviors(ctx); @@ -134,4 +136,33 @@ export function Snapshots(ctx: PluginContext) { const json = await req.json(); return ctx.state.setSnapshot(json.data); }); + + PluginCommands.State.Snapshots.DownloadToFile.subscribe(ctx, ({ name }) => { + const element = document.createElement('a'); + const json = JSON.stringify(ctx.state.getSnapshot(), null, 2); + element.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(json)); + element.setAttribute('download', `mol-star_state_${(name || getFormattedTime())}.json`); + element.style.display = 'none'; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); + }); + + PluginCommands.State.Snapshots.OpenFile.subscribe(ctx, async ({ file }) => { + try { + const data = await readFromFile(file, 'string').run(); + const json = JSON.parse(data as string); + await ctx.state.setSnapshot(json); + } catch (e) { + ctx.log.error(`Reading JSON state: ${e}`); + } + // const element = document.createElement('a'); + // const json = JSON.stringify(ctx.state.getSnapshot(), null, 2); + // element.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(json)); + // element.setAttribute('download', `mol-star_state_${(name || getFormattedTime())}.json`); + // element.style.display = 'none'; + // document.body.appendChild(element); + // element.click(); + // document.body.removeChild(element); + }); } \ No newline at end of file diff --git a/src/mol-plugin/command.ts b/src/mol-plugin/command.ts index 211e70870..6e8cfff33 100644 --- a/src/mol-plugin/command.ts +++ b/src/mol-plugin/command.ts @@ -32,7 +32,10 @@ export const PluginCommands = { Clear: PluginCommand<{}>({ isImmediate: true }), Upload: PluginCommand<{ name?: string, description?: string, serverUrl: string }>({ isImmediate: true }), - Fetch: PluginCommand<{ url: string }>() + Fetch: PluginCommand<{ url: string }>(), + + DownloadToFile: PluginCommand<{ name?: string }>({ isImmediate: true }), + OpenFile: PluginCommand<{ file: File }>({ isImmediate: true }), } }, Camera: { diff --git a/src/mol-plugin/ui/state.tsx b/src/mol-plugin/ui/state.tsx index a30896fb1..b9a16ad12 100644 --- a/src/mol-plugin/ui/state.tsx +++ b/src/mol-plugin/ui/state.tsx @@ -61,6 +61,16 @@ class StateSnapshotControls extends PluginComponent<{ serverUrl: string, serverC UploadedEvent.next(); } + download = () => { + PluginCommands.State.Snapshots.DownloadToFile.dispatch(this.plugin, { name: this.state.name }); + } + + open = (e: React.ChangeEvent<HTMLInputElement>) => { + if (!e.target.files || !e.target.files![0]) return; + + PluginCommands.State.Snapshots.OpenFile.dispatch(this.plugin, { file: e.target.files![0] }); + } + render() { return <div> <ParameterControls params={StateSnapshotControls.Params} values={this.state} onEnter={this.add} onChange={p => { @@ -73,6 +83,12 @@ class StateSnapshotControls extends PluginComponent<{ serverUrl: string, serverC <button className='msp-btn msp-btn-block msp-form-control' onClick={this.upload} disabled={this.state.isUploading}>Upload</button> <button className='msp-btn msp-btn-block msp-form-control' onClick={this.clear}>Clear</button> </div> + <div className='msp-btn-row-group'> + <button className='msp-btn msp-btn-block msp-form-control' onClick={this.download}>Download JSON</button> + <div className='msp-btn msp-btn-block msp-btn-action msp-loader-msp-btn-file'> + {'Open JSON'} <input onChange={this.open} type='file' multiple={false} accept='.json' /> + </div> + </div> </div>; } } diff --git a/src/mol-util/date.ts b/src/mol-util/date.ts index 90d03997b..cfb4cdb37 100644 --- a/src/mol-util/date.ts +++ b/src/mol-util/date.ts @@ -6,4 +6,15 @@ export function dateToUtcString(date: Date) { return date.toISOString().replace(/T/, ' ').replace(/\..+/, ''); +} + +export function getFormattedTime() { + const today = new Date(); + const y = today.getFullYear(); + const m = today.getMonth() + 1; + const d = today.getDate(); + const h = today.getHours(); + const mi = today.getMinutes(); + const s = today.getSeconds(); + return y + '-' + m + '-' + d + '-' + h + '-' + mi + '-' + s; } \ No newline at end of file -- GitLab