diff --git a/openflexure_microscope/api/static/package-lock.json b/openflexure_microscope/api/static/package-lock.json index f8a024be..364ee484 100644 --- a/openflexure_microscope/api/static/package-lock.json +++ b/openflexure_microscope/api/static/package-lock.json @@ -3043,9 +3043,9 @@ "optional": true }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, "optional": true, "requires": { @@ -3235,9 +3235,9 @@ } }, "vue-loader-v16": { - "version": "npm:vue-loader@16.1.1", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.1.tgz", - "integrity": "sha512-wz/+HFg/3SBayHWAlZXARcnDTl3VOChrfW9YnxvAweiuyKX/7IGx1ad/4yJHmwhgWlOVYMAbTiI7GV8G33PfGQ==", + "version": "npm:vue-loader@16.2.0", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.2.0.tgz", + "integrity": "sha512-TitGhqSQ61RJljMmhIGvfWzJ2zk9m1Qug049Ugml6QP3t0e95o0XJjk29roNEiPKJQBEi8Ord5hFuSuELzSp8Q==", "dev": true, "optional": true, "requires": { @@ -3247,9 +3247,9 @@ }, "dependencies": { "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "optional": true, "requires": { @@ -3917,38 +3917,12 @@ "dev": true }, "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "dev": true, "requires": { - "follow-redirects": "1.5.10" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "dev": true, - "requires": { - "debug": "=3.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "follow-redirects": "^1.10.0" } }, "babel-eslint": { diff --git a/openflexure_microscope/api/static/package.json b/openflexure_microscope/api/static/package.json index a0d8b116..af3524c4 100644 --- a/openflexure_microscope/api/static/package.json +++ b/openflexure_microscope/api/static/package.json @@ -20,7 +20,7 @@ "@vue/cli-plugin-eslint": "^4.5.9", "@vue/cli-service": "^4.5.9", "@vue/eslint-config-prettier": "^6.0.0", - "axios": "^0.19.2", + "axios": "^0.21.1", "babel-eslint": "^10.1.0", "css-loader": "^3.6.0", "eslint": "^6.8.0", diff --git a/openflexure_microscope/api/static/src/components/appContent.vue b/openflexure_microscope/api/static/src/components/appContent.vue index 60713801..fbc12e8d 100644 --- a/openflexure_microscope/api/static/src/components/appContent.vue +++ b/openflexure_microscope/api/static/src/components/appContent.vue @@ -140,6 +140,8 @@ import loggingContent from "./tabContentComponents/loggingContent.vue"; // Import modal components for device initialisation import calibrationModal from "./modalComponents/calibrationModal.vue"; +import { mapState } from "vuex"; + // Export main app export default { name: "AppContent", @@ -241,21 +243,21 @@ export default { currentTabIndex: function() { return this.tabOrder.indexOf(this.currentTab); + }, + + // Map the setting for IHI's interface so we can watch it + ...mapState(["IHIEnabled"]) + }, + + watch: { + // Update the interface when the IHI interface is enabled/disabled + IHIEnabled: function(newValue) { + this.updateTopTabs(newValue); } }, created: function() { if (this.$store.getters.ready) { - // Detect local connection - if ( - ["localhost", "0.0.0.0", "127.0.0.1", "[::1]"].includes( - window.location.hostname - ) - ) { - this.$store.commit("changeDisableStream", true); - this.$store.commit("changeAutoGpuPreview", true); - this.$store.commit("changeTrackWindow", true); - } // Update top tabs this.updateTopTabs(this.$store.state.IHIEnabled); // Update plugins @@ -264,16 +266,6 @@ export default { this.startModals(); }); } - - // Watch for host 'ready', then update status - this.unwatchStoreFunction = this.$store.watch( - state => { - return state.IHIEnabled; - }, - IHIEnabled => { - this.updateTopTabs(IHIEnabled); - } - ); }, mounted() { @@ -291,14 +283,6 @@ export default { }); }, - beforeDestroy() { - // Then we call that function here to unwatch - if (this.unwatchStoreFunction) { - this.unwatchStoreFunction(); - this.unwatchStoreFunction = null; - } - }, - methods: { updateTopTabs: function(IHIEnabled) { if (IHIEnabled) { diff --git a/openflexure_microscope/api/static/src/components/tabContentComponents/aboutComponents/devTools.vue b/openflexure_microscope/api/static/src/components/tabContentComponents/aboutComponents/devTools.vue index f0372c94..0bcc9cb5 100644 --- a/openflexure_microscope/api/static/src/components/tabContentComponents/aboutComponents/devTools.vue +++ b/openflexure_microscope/api/static/src/components/tabContentComponents/aboutComponents/devTools.vue @@ -1,12 +1,36 @@ @@ -19,22 +43,35 @@ export default { data: function() { return { - newOrigin: this.$store.state.origin + newOrigin: this.$store.state.origin, + reloadWhenOverridingOrigin: true }; }, mounted() { - if (localStorage.overrideOrigin){ + if (localStorage.overrideOrigin) { this.newOrigin = localStorage.overrideOrigin; - }else{ + } else { this.newOrigin = "http://microscope.local:5000"; } }, methods: { - overrideAPIHost: function() { - this.$store.commit("changeOrigin", this.newOrigin); - localStorage.overrideOrigin = this.newOrigin + overrideAPIHost: function(event) { + // Save the origin override, so that if we reload the web app, you can easily + localStorage.overrideOrigin = this.newOrigin; + + // If we have elected not to reload the interface, just update the origin + // in the store. Otherwise, the form's default action will do the job for us. + // TODO: preserve other query parameters when reloading + if (!this.reloadWhenOverridingOrigin) { + this.$store.commit("changeOrigin", this.newOrigin); + event.preventDefault(); + } + }, + resetTour: function() { + // Make the introduction tour run next time the app loads + this.setLocalStorageObj("completedTour", false); } } }; diff --git a/openflexure_microscope/api/static/src/components/tabContentComponents/settingsComponents/featuresSettings.vue b/openflexure_microscope/api/static/src/components/tabContentComponents/settingsComponents/featuresSettings.vue index 8d2fbde2..581d7c0f 100644 --- a/openflexure_microscope/api/static/src/components/tabContentComponents/settingsComponents/featuresSettings.vue +++ b/openflexure_microscope/api/static/src/components/tabContentComponents/settingsComponents/featuresSettings.vue @@ -33,7 +33,6 @@ export default { }, set(value) { this.$store.commit("changeIHIEnabled", value); - this.$root.$emit("globalSafeTogglePreview", value); } } }, diff --git a/openflexure_microscope/api/static/src/components/tabContentComponents/settingsComponents/streamSettings.vue b/openflexure_microscope/api/static/src/components/tabContentComponents/settingsComponents/streamSettings.vue index b21627a6..60b7cdb7 100644 --- a/openflexure_microscope/api/static/src/components/tabContentComponents/settingsComponents/streamSettings.vue +++ b/openflexure_microscope/api/static/src/components/tabContentComponents/settingsComponents/streamSettings.vue @@ -73,8 +73,11 @@ export default { return this.$store.state.autoGpuPreview; }, set(value) { + // NB the stream viewer watches the store, and is + // responsible for making the request that switches + // GPU preview on/off + // see streamContent.vue this.$store.commit("changeAutoGpuPreview", value); - this.$root.$emit("globalSafeTogglePreview", value); } }, @@ -86,6 +89,51 @@ export default { this.$store.commit("changeTrackWindow", value); } } + }, + + watch: { + // Cache the stream settings to local storage for persistence + // (the next 3 functions all relate to this) + disableStream: function(newValue) { + console.log( + `disableStream updated to ${newValue} and saved in local storage` + ); + this.setLocalStorageObj("disableStream", newValue); + }, + autoGpuPreview: function(newValue) { + console.log( + `GPU preview updated to ${newValue} and saved in local storage` + ); + this.setLocalStorageObj("autoGpuPreview", newValue); + }, + trackWindow: function(newValue) { + console.log( + `trackWindow updated to ${newValue} and saved in local storage` + ); + this.setLocalStorageObj("trackWindow", newValue); + } + }, + + created() { + // Apply sensible defaults for stream settings, depending on + // whether we're connecting locally or remotely, respecting + // the settings that were cached previously. + const localMode = ["localhost", "0.0.0.0", "127.0.0.1", "[::1]"].includes( + window.location.hostname + ); + const localDefaults = { + disableStream: true, + autoGpuPreview: true, + trackWindow: true + }; + for (let k in localDefaults) { + if (localStorage.getItem(k) !== null) { + this[k] = this.getLocalStorageObj(k); + } else if (localMode) { + console.log(`${k} set to default value for a local connection`); + this[k] = localDefaults[k]; + } + } } }; diff --git a/openflexure_microscope/api/static/src/components/tabContentComponents/streamContent.vue b/openflexure_microscope/api/static/src/components/tabContentComponents/streamContent.vue index 2554d621..16fde3e1 100644 --- a/openflexure_microscope/api/static/src/components/tabContentComponents/streamContent.vue +++ b/openflexure_microscope/api/static/src/components/tabContentComponents/streamContent.vue @@ -69,6 +69,16 @@ export default { }, settingsUri: function() { return `${this.$store.getters.baseUri}/api/v2/instrument/settings`; + }, + autoGpuPreview: function() { + return this.$store.state.autoGpuPreview; + } + }, + + watch: { + autoGpuPreview: function(newValue) { + // When the GPU preview setting in the store changes, update the server + this.safePreviewRequest(newValue); } }, @@ -77,9 +87,6 @@ export default { this.$root.$on("globalTogglePreview", state => { this.previewRequest(state); }); - this.$root.$on("globalSafeTogglePreview", state => { - this.safePreviewRequest(state); - }); // A global signal listener to flash the stream element this.$root.$on("globalFlashStream", () => { this.flashStream(); @@ -97,7 +104,7 @@ export default { created: function() { // Send a request to start/stop GPU preview based on global setting - this.safePreviewRequest(this.$store.state.autoGpuPreview); + this.safePreviewRequest(this.autoGpuPreview); }, beforeDestroy: function() { diff --git a/openflexure_microscope/api/static/src/store.js b/openflexure_microscope/api/static/src/store.js index 8b92ca38..f8255fdc 100644 --- a/openflexure_microscope/api/static/src/store.js +++ b/openflexure_microscope/api/static/src/store.js @@ -3,9 +3,22 @@ import Vuex from "vuex"; Vue.use(Vuex); +function getOriginFromLocation() { + // This will default to the same origin that's serving + // the web app - but can be overridden by the URL. + // See also devTools.vue which can change the origin. + let url = new URL(window.location.href); + let origin = url.searchParams.get("overrideOrigin"); + if (origin) { + return origin; + } else { + return url.origin; + } +} + export default new Vuex.Store({ state: { - origin: window.location.origin, + origin: getOriginFromLocation(), available: false, waiting: false, error: "",