Merge branch 'improve-local-development' into 'master'

Local development improvements

See merge request openflexure/openflexure-microscope-server!125
This commit is contained in:
Richard Bowman 2021-05-18 10:56:10 +00:00
commit de28b0e2f6
8 changed files with 145 additions and 83 deletions

View file

@ -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": {

View file

@ -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",

View file

@ -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) {

View file

@ -1,12 +1,36 @@
<template>
<div>
<form class="uk-form-stacked" @submit.prevent="overrideAPIHost">
<form
class="uk-form-stacked"
action=""
method="GET"
@submit="overrideAPIHost"
>
<label class="uk-form-label">Override API origin</label>
<input v-model="newOrigin" class="uk-input" type="text" />
<input
v-model="newOrigin"
name="overrideOrigin"
class="uk-input"
type="text"
/>
<label class="uk-form-label">
<input
v-model="reloadWhenOverridingOrigin"
class="uk-input uk-checkbox"
type="checkbox"
/>
Reload web app with new origin
</label>
<button class="uk-button uk-button-default uk-margin-small">
Apply
</button>
</form>
<form class="uk-form-stacked" @submit.prevent="resetTour">
<label class="uk-form-label">Re-run tour on next load</label>
<button class="uk-button uk-button-default uk-margin-small">
Reset
</button>
</form>
</div>
</template>
@ -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);
}
}
};

View file

@ -33,7 +33,6 @@ export default {
},
set(value) {
this.$store.commit("changeIHIEnabled", value);
this.$root.$emit("globalSafeTogglePreview", value);
}
}
},

View file

@ -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];
}
}
}
};
</script>

View file

@ -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() {

View file

@ -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: "",