diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/prettier.config.js b/prettier.config.js index f12ed4a..e48a4e4 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -3,4 +3,5 @@ module.exports = { singleQuote: true, trailingComma: 'es5', arrowParens: 'always', + endOfLine: 'lf', }; diff --git a/src/app.js b/src/app.js index 59a0045..c9e7b0e 100644 --- a/src/app.js +++ b/src/app.js @@ -22,6 +22,7 @@ import Config from 'paraview-glance/src/config'; import createStore from 'paraview-glance/src/store'; import Remote from 'paraview-glance/src/remote/remote'; import { ProxyManagerVuePlugin } from 'paraview-glance/src/plugins'; +import Settings from 'paraview-glance/src/settings'; // Expose IO API to Glance global object export const { @@ -92,7 +93,21 @@ export function createViewer(container, proxyConfig = null) { window.history.replaceState({ app: false }, ''); window.addEventListener('popstate', onRoute); + const settings = new Settings(); + settings.syncWithStore(store, { + collapseDatasetPanels: { + set: (val) => store.dispatch('collapseDatasetPanels', val), + get: (state) => state.collapseDatasetPanels, + }, + suppressBrowserWarning: { + set: (val) => store.dispatch('suppressBrowserWarning', val), + get: (state) => state.suppressBrowserWarning, + }, + }); + return { + proxyManager, + processURLArgs() { const { name, url, wsServer } = vtkURLExtract.extractURLParameters(); @@ -110,9 +125,14 @@ export function createViewer(container, proxyConfig = null) { addDatasetPanel(component) { store.commit('addPanel', { component }); }, - proxyManager, showApp() { store.commit('showApp'); }, + getSetting(name) { + return settings.get(name); + }, + setSetting(name, value) { + return settings.set(name, value); + }, }; } diff --git a/src/components/core/BrowserIssues/script.js b/src/components/core/BrowserIssues/script.js index be47686..f215641 100644 --- a/src/components/core/BrowserIssues/script.js +++ b/src/components/core/BrowserIssues/script.js @@ -1,4 +1,4 @@ -const WARNING_KEY = 'BrowserIssues.suppressWarning'; +import { mapState, mapActions } from 'vuex'; // ---------------------------------------------------------------------------- // Component API @@ -24,42 +24,29 @@ function getBrowserIssues() { // } } - if (Object.keys(this.issues).length && !this.suppressWarning) { + if (Object.keys(this.issues).length && !this.suppressBrowserWarning) { this.dialog = true; } } // ---------------------------------------------------------------------------- -function closeDialog() { - if (this.suppressWarning && window.localStorage) { - window.localStorage.setItem(WARNING_KEY, true); - } - this.dialog = false; -} - -// ---------------------------------------------------------------------------- - export default { name: 'BrowserIssues', data() { return { issues: {}, dialog: false, - dontShow: false, - suppressWarning: false, }; }, - created() { - if (window.localStorage) { - this.suppressWarning = !!window.localStorage.getItem(WARNING_KEY); - } - }, + computed: mapState(['suppressBrowserWarning']), mounted() { this.getBrowserIssues(); }, methods: { - closeDialog, getBrowserIssues, + ...mapActions({ + setSuppressBrowserWarning: 'suppressBrowserWarning', + }), }, }; diff --git a/src/components/core/BrowserIssues/template.html b/src/components/core/BrowserIssues/template.html index d7234e7..4f3ef72 100644 --- a/src/components/core/BrowserIssues/template.html +++ b/src/components/core/BrowserIssues/template.html @@ -22,14 +22,15 @@ Okay diff --git a/src/components/core/Datasets/script.js b/src/components/core/Datasets/script.js index 255590f..96a9520 100644 --- a/src/components/core/Datasets/script.js +++ b/src/components/core/Datasets/script.js @@ -20,6 +20,7 @@ export default { }, computed: { ...mapState({ + collapseDatasetPanels: 'collapseDatasetPanels', panels: (state) => { const priorities = Object.keys(state.panels).map((n) => Number(n)); priorities.sort((a, b) => a - b); @@ -96,12 +97,16 @@ export default { const proxy = sources[i]; const proxyId = proxy.getProxyId(); if (!(proxyId in this.internalPanelState)) { - this.internalPanelState[proxyId] = true; + this.internalPanelState[proxyId] = !this.collapseDatasetPanels; } if (!(proxyId in this.subpanels)) { - this.subpanels[proxyId] = Controls.filter((c) => c.visible(proxy)) - .map((c, j) => (c.defaultExpand ? j : -1)) - .filter((v) => v > -1); + if (this.collapseDatasetPanels) { + this.subpanels[proxyId] = []; + } else { + this.subpanels[proxyId] = Controls.filter((c) => c.visible(proxy)) + .map((c, j) => (c.defaultExpand ? j : -1)) + .filter((v) => v > -1); + } } } diff --git a/src/components/core/GlobalSettings/script.js b/src/components/core/GlobalSettings/script.js index 9c349f5..7597cf1 100644 --- a/src/components/core/GlobalSettings/script.js +++ b/src/components/core/GlobalSettings/script.js @@ -53,6 +53,14 @@ export default { }; }, computed: { + collapseDatasetPanelsModel: { + get() { + return this.collapseDatasetPanels; + }, + set(v) { + this.setCollapseDatasetPanels(v); + }, + }, backgroundColorModel: { get() { return this.backgroundColor; @@ -126,6 +134,7 @@ export default { this.setMaxTextureLODSize(size); }, }, + ...mapState(['collapseDatasetPanels']), ...mapState('views', { backgroundColor: (state) => state.globalBackgroundColor, orientationAxis: (state) => state.axisVisible, @@ -192,6 +201,9 @@ export default { } } }, + ...mapActions({ + setCollapseDatasetPanels: 'collapseDatasetPanels', + }), ...mapActions('views', { setBackgroundColor: (dispatch, bg) => dispatch('setGlobalBackground', bg), setOrientationAxis: (dispatch, axis) => dispatch('setAxisVisible', axis), diff --git a/src/components/core/GlobalSettings/template.html b/src/components/core/GlobalSettings/template.html index 5b8e0f8..58c0437 100644 --- a/src/components/core/GlobalSettings/template.html +++ b/src/components/core/GlobalSettings/template.html @@ -1,4 +1,24 @@ + +
+ General Settings +
+ + + + + Default collapse datasets + + + + + + +
Background diff --git a/src/settings.js b/src/settings.js new file mode 100644 index 0000000..63ae3c5 --- /dev/null +++ b/src/settings.js @@ -0,0 +1,61 @@ +function callAndEmpty(l) { + while (l.length) { + l.pop()(); + } +} + +export default class Settings { + constructor(keyPrefix = 'settings') { + this.keyPrefix = keyPrefix; + this.storeSettingsMap = {}; + this.store = null; + this.storeWatchers = []; + } + + key(name) { + if (this.keyPrefix) { + return `${this.keyPrefix}.${name}`; + } + return name; + } + + get(name) { + const result = window.localStorage.getItem(this.key(name)); + if (result === null) { + return undefined; + } + return JSON.parse(result); + } + + set(name, value) { + return window.localStorage.setItem(this.key(name), JSON.stringify(value)); + } + + syncWithStore(store, syncInfo) { + callAndEmpty(this.storeWatchers); + this.store = store; + this.storeSettingsMap = syncInfo; + + const settingNames = Object.keys(syncInfo); + // localStorage -> store + settingNames.forEach((name) => { + const value = this.get(name); + if (value !== undefined) { + const { set } = syncInfo[name]; + set(value); + } + }); + + // store -> localStorage + this.storeWatchers = settingNames.map((name) => { + const { get } = syncInfo[name]; + return store.watch(get, (value) => this.set(name, value)); + }); + } + + delete() { + callAndEmpty(this.storeWatchers); + this.storeSettingsMap = {}; + this.store = null; + } +} diff --git a/src/store/index.js b/src/store/index.js index b118205..6047ab0 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -69,6 +69,8 @@ function createStore(services) { panels: {}, cameraViewPoints: {}, mostRecentViewPoint: null, + collapseDatasetPanels: false, + suppressBrowserWarning: false, }, getters: { proxyManager(state) { @@ -117,10 +119,18 @@ function createStore(services) { mostRecentViewPoint(state, viewPoint) { state.mostRecentViewPoint = viewPoint; }, + collapseDatasetPanels(state, value) { + state.collapseDatasetPanels = value; + }, + suppressBrowserWarning(state, value) { + state.suppressBrowserWarning = value; + }, }, actions: { addPanel: wrapMutationAsAction('addPanel'), closeScreenshotDialog: wrapMutationAsAction('closeScreenshotDialog'), + collapseDatasetPanels: wrapMutationAsAction('collapseDatasetPanels'), + suppressBrowserWarning: wrapMutationAsAction('suppressBrowserWarning'), saveState({ commit, state }, fileNameToUse) { const t = new Date(); const fileName =