Move Vue app to a js directory
This commit is contained in:
parent
515bee1422
commit
13f7252dd7
72 changed files with 0 additions and 0 deletions
|
|
@ -1,476 +0,0 @@
|
|||
<template>
|
||||
<div
|
||||
id="app"
|
||||
class="uk-height-1-1 uk-margin-remove uk-padding-remove"
|
||||
:class="handleTheme"
|
||||
>
|
||||
<loadingContent v-if="!$store.getters.ready" />
|
||||
<div v-if="$store.getters.ready" id="tour-header"></div>
|
||||
<appContent v-if="$store.getters.ready" />
|
||||
<!-- Runtime modals -->
|
||||
<div
|
||||
id="modal-center"
|
||||
ref="keyboardManualModal"
|
||||
class="uk-flex-top"
|
||||
uk-modal
|
||||
>
|
||||
<div class="uk-modal-dialog uk-modal-body uk-margin-auto-vertical">
|
||||
<button class="uk-modal-close-default" type="button" uk-close></button>
|
||||
<div
|
||||
v-for="shortcut in keyboardManual"
|
||||
:key="shortcut.shortcut"
|
||||
class="uk-margin-small"
|
||||
uk-grid
|
||||
>
|
||||
<div class="uk-width-small">{{ shortcut.shortcut }}</div>
|
||||
<div class="uk-width-expand">{{ shortcut.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<v-tour
|
||||
v-show="$store.getters.ready"
|
||||
name="guidedTour"
|
||||
:steps="tourSteps"
|
||||
:callbacks="tourCallbacks"
|
||||
:options="{ highlight: true }"
|
||||
></v-tour>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Import components
|
||||
import appContent from "./components/appContent.vue";
|
||||
import loadingContent from "./components/loadingContent.vue";
|
||||
|
||||
import axios from "axios";
|
||||
var Mousetrap = require("mousetrap");
|
||||
|
||||
Mousetrap.prototype.stopCallback = function(e, element) {
|
||||
// if the element has the class "mousetrap" then no need to stop
|
||||
if ((" " + element.className + " ").indexOf(" mousetrap ") > -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we're in a lightbox, stop mousetrap
|
||||
if (element.classList.contains("lightbox-link")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// stop for input, select, and textarea
|
||||
return (
|
||||
element.tagName == "INPUT" ||
|
||||
element.tagName == "SELECT" ||
|
||||
element.tagName == "TEXTAREA" ||
|
||||
(element.contentEditable && element.contentEditable == "true")
|
||||
);
|
||||
};
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: "App",
|
||||
|
||||
components: {
|
||||
appContent,
|
||||
loadingContent
|
||||
},
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
appAvailable: false,
|
||||
arrowKeysDown: {},
|
||||
keyboardManual: [],
|
||||
systemDark: undefined,
|
||||
themeObserver: undefined,
|
||||
tourCallbacks: {
|
||||
onStop: () => {
|
||||
this.setLocalStorageObj("completedTour", true);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
isSystemDark: function() {
|
||||
if (
|
||||
window.matchMedia &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
handleTheme: function() {
|
||||
var isDark = false;
|
||||
if (this.$store.state.appTheme == "dark") {
|
||||
isDark = true;
|
||||
} else if (this.$store.state.appTheme == "system") {
|
||||
if (this.systemDark) {
|
||||
isDark = true;
|
||||
}
|
||||
}
|
||||
return {
|
||||
"uk-light": isDark,
|
||||
"uk-background-secondary": isDark
|
||||
};
|
||||
},
|
||||
tourSteps: function() {
|
||||
let tabPopperParams = {
|
||||
modifiers: {
|
||||
preventOverflow: {
|
||||
boundariesElement: "window"
|
||||
}
|
||||
},
|
||||
placement: "right"
|
||||
};
|
||||
return [
|
||||
{
|
||||
target: "#tour-header", // We're using document.querySelector() under the hood
|
||||
header: {
|
||||
title: "Welcome to the OpenFlexure Microscope"
|
||||
},
|
||||
content: `Click Next to learn how to use your microscope`,
|
||||
params: {
|
||||
placement: "bottom"
|
||||
}
|
||||
},
|
||||
{
|
||||
target: "#gallery-tab-icon",
|
||||
header: {
|
||||
title: "Capture gallery"
|
||||
},
|
||||
content: `View and download your microscope images from the gallery tab`,
|
||||
params: tabPopperParams
|
||||
},
|
||||
{
|
||||
target: "#navigate-tab-icon",
|
||||
header: {
|
||||
title: "Navigate around your sample"
|
||||
},
|
||||
content: `Move your microscope stage and perform autofocus from the navigate tab`,
|
||||
params: tabPopperParams
|
||||
},
|
||||
{
|
||||
target: "#capture-tab-icon",
|
||||
header: {
|
||||
title: "Capture microscope images"
|
||||
},
|
||||
content: `Take images and simple tile scans from the capture tab`,
|
||||
params: tabPopperParams
|
||||
},
|
||||
{
|
||||
target: "#settings-tab-icon",
|
||||
header: {
|
||||
title: "Change settings"
|
||||
},
|
||||
content: `Change app and microscope settings, including microscope calibration, from the settings tab`,
|
||||
params: tabPopperParams
|
||||
},
|
||||
{
|
||||
target: "#extension-tab-divider",
|
||||
header: {
|
||||
title: "Microscope extensions"
|
||||
},
|
||||
content: `Extensions installed on your microscope will appear below this line`,
|
||||
params: tabPopperParams
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// Query CSS dark theme preference
|
||||
var mql = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
// Check for system dark theme when mounted
|
||||
if (mql.matches) {
|
||||
this.systemDark = true;
|
||||
}
|
||||
// Create a theme observer to watch for changes
|
||||
this.themeObserver = mql.addListener(e => {
|
||||
if (e.matches) {
|
||||
this.systemDark = true;
|
||||
} else {
|
||||
this.systemDark = false;
|
||||
}
|
||||
});
|
||||
// Check connection to API
|
||||
this.checkConnection();
|
||||
// Handle guided tour
|
||||
// If the user has already completed or skipped the guided tour
|
||||
var completedTour = this.getLocalStorageObj("completedTour") || false;
|
||||
if (!completedTour) {
|
||||
this.$tours["guidedTour"].start();
|
||||
}
|
||||
},
|
||||
|
||||
created: function() {
|
||||
window.addEventListener("beforeunload", this.handleExit);
|
||||
// Scrollwheel listener
|
||||
window.addEventListener("wheel", this.wheelMonitor);
|
||||
// Watch for origin changes
|
||||
this.unwatchOriginFunction = this.$store.watch(
|
||||
(state, getters) => {
|
||||
return getters.uriV2;
|
||||
},
|
||||
() => {
|
||||
this.checkConnection();
|
||||
}
|
||||
);
|
||||
|
||||
// Keyboard shortcuts
|
||||
Mousetrap.bind("?", () => {
|
||||
this.toggleModalElement(this.$refs["keyboardManualModal"]); // Calls the mixin
|
||||
});
|
||||
|
||||
// Arrow keys
|
||||
Mousetrap.bind(
|
||||
["up", "down", "left", "right"],
|
||||
event => {
|
||||
this.arrowKeysDown[event.keyCode] = true; //Add key to array
|
||||
this.navigateKeyHandler();
|
||||
},
|
||||
"keydown"
|
||||
);
|
||||
Mousetrap.bind(
|
||||
["up", "down", "left", "right"],
|
||||
event => {
|
||||
delete this.arrowKeysDown[event.keyCode]; //Remove key from array
|
||||
},
|
||||
"keyup"
|
||||
);
|
||||
this.keyboardManual.push({
|
||||
shortcut: "←↑→↓",
|
||||
description: "Move the microscope stage"
|
||||
});
|
||||
|
||||
// Focus keys
|
||||
Mousetrap.bind("pageup", () => {
|
||||
this.$root.$emit("globalMoveStepEvent", 0, 0, 1);
|
||||
});
|
||||
Mousetrap.bind("pagedown", () => {
|
||||
this.$root.$emit("globalMoveStepEvent", 0, 0, -1);
|
||||
});
|
||||
this.keyboardManual.push({
|
||||
shortcut: "pgup / pgdn",
|
||||
description: "Move the microscope focus"
|
||||
});
|
||||
|
||||
// Capture
|
||||
Mousetrap.bind("c", () => {
|
||||
this.$root.$emit("globalCaptureEvent");
|
||||
});
|
||||
this.keyboardManual.push({
|
||||
shortcut: "c",
|
||||
description: "Take a capture"
|
||||
});
|
||||
|
||||
// Autofocus
|
||||
Mousetrap.bind("a", () => {
|
||||
this.$root.$emit("globalFastAutofocusEvent");
|
||||
});
|
||||
this.keyboardManual.push({
|
||||
shortcut: "a",
|
||||
description: "Fast autofocus"
|
||||
});
|
||||
|
||||
// Increment/decrement tab
|
||||
Mousetrap.bind("shift+down", () => {
|
||||
this.$root.$emit("globalIncrementTab");
|
||||
});
|
||||
Mousetrap.bind("shift+up", () => {
|
||||
this.$root.$emit("globalDecrementTab");
|
||||
});
|
||||
this.keyboardManual.push({
|
||||
shortcut: "shift+↑ / shift+↓",
|
||||
description: "Switch tab"
|
||||
});
|
||||
|
||||
// Re-run tour
|
||||
Mousetrap.bind("alt+t", () => {
|
||||
this.$tours["guidedTour"].start();
|
||||
});
|
||||
},
|
||||
|
||||
beforeDestroy: function() {
|
||||
// Disconnect the theme observer
|
||||
if (this.themeObserver) {
|
||||
this.themeObserver.disconnect();
|
||||
}
|
||||
// Remove scrollwheel listener
|
||||
window.removeEventListener("wheel", this.wheelMonitor);
|
||||
// Remove origin watcher
|
||||
this.unwatchOriginFunction();
|
||||
// Remove key listeners
|
||||
Mousetrap.reset();
|
||||
},
|
||||
|
||||
methods: {
|
||||
checkConnection: function() {
|
||||
var uriV2 = this.$store.getters.uriV2;
|
||||
this.$store.commit("changeWaiting", true);
|
||||
axios
|
||||
.get(uriV2)
|
||||
.then(() => {
|
||||
this.$store.commit("setConnected");
|
||||
this.$store.commit("setErrorMessage", null);
|
||||
})
|
||||
.catch(error => {
|
||||
this.$store.commit("setErrorMessage", error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.$store.commit("changeWaiting", false);
|
||||
});
|
||||
},
|
||||
|
||||
handleExit: function() {
|
||||
this.$root.$emit("globalTogglePreview", false);
|
||||
},
|
||||
|
||||
// Handle global mouse wheel events to be associated with navigation
|
||||
wheelMonitor: function(event) {
|
||||
// Only capture scroll if the event target's parent contains the "scrollTarget" class
|
||||
if (
|
||||
event.target.parentNode.classList.contains("scrollTarget") ||
|
||||
event.target.classList.contains("scrollTarget")
|
||||
) {
|
||||
var z_rel = event.deltaY / 100;
|
||||
// Emit a signal to move, acted on by panelNavigate.vue
|
||||
this.$root.$emit("globalMoveStepEvent", 0, 0, z_rel, false);
|
||||
}
|
||||
},
|
||||
|
||||
navigateKeyHandler: function() {
|
||||
// Calculate movement array
|
||||
var x_rel = 0;
|
||||
var y_rel = 0;
|
||||
var z_rel = 0;
|
||||
if (37 in this.arrowKeysDown) {
|
||||
x_rel = x_rel + 1;
|
||||
}
|
||||
if (39 in this.arrowKeysDown) {
|
||||
x_rel = x_rel - 1;
|
||||
}
|
||||
if (38 in this.arrowKeysDown) {
|
||||
y_rel = y_rel + 1;
|
||||
}
|
||||
if (40 in this.arrowKeysDown) {
|
||||
y_rel = y_rel - 1;
|
||||
}
|
||||
// Make a position request
|
||||
// Emit a signal to move, acted on by panelNavigate.vue
|
||||
this.$root.$emit("globalMoveStepEvent", x_rel, y_rel, z_rel);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
// Basic UIkit CSS
|
||||
@import "../node_modules/uikit/src/less/uikit.less";
|
||||
// Custom UIkit CSS modifications
|
||||
@import "./assets/less/theme.less";
|
||||
|
||||
// We override the custom-electron-titlebar z-index
|
||||
// UIKit lightbox must be able to draw over the titlebar
|
||||
// as it currently always spawns at the root of the DOM
|
||||
.titlebar,
|
||||
.titlebar > * {
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
#app {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: left;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uk-disabled {
|
||||
pointer-events: none;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.control-component {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
background-color: rgba(180, 180, 180, 0.03);
|
||||
border-width: 0 1px 0 0;
|
||||
border-style: solid;
|
||||
border-color: rgba(180, 180, 180, 0.25);
|
||||
}
|
||||
|
||||
.view-component {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.section-content {
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// Style tour
|
||||
.v-tour__target--highlighted {
|
||||
box-shadow: 0px 40px 200px 30px rgba(0, 0, 0, 0.5),
|
||||
0px 0px 0px 4px rgba(128, 128, 128, 0.5) !important;
|
||||
border-radius: 5px;
|
||||
opacity: 100% !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
.v-step {
|
||||
background: @global-primary-background !important;
|
||||
}
|
||||
|
||||
.v-step__header {
|
||||
background-color: darken(@global-primary-background, 7%) !important;
|
||||
}
|
||||
|
||||
.v-step__button {
|
||||
font-size: 0.9rem !important;
|
||||
}
|
||||
|
||||
// Change step arrow colour
|
||||
// This is awful and hacky and makes me sad, but needs must
|
||||
.v-step .v-step__arrow {
|
||||
border-color: darken(@global-primary-background, 7%) !important;
|
||||
&--dark {
|
||||
border-color: darken(@global-primary-background, 7%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.v-step[x-placement^="top"] .v-step__arrow {
|
||||
border-left-color: transparent !important;
|
||||
border-right-color: transparent !important;
|
||||
border-bottom-color: transparent !important;
|
||||
}
|
||||
|
||||
.v-step[x-placement^="bottom"] .v-step__arrow {
|
||||
border-left-color: transparent !important;
|
||||
border-right-color: transparent !important;
|
||||
border-top-color: transparent !important;
|
||||
}
|
||||
|
||||
.v-step[x-placement^="right"] .v-step__arrow {
|
||||
border-left-color: transparent !important;
|
||||
border-top-color: transparent !important;
|
||||
border-bottom-color: transparent !important;
|
||||
}
|
||||
|
||||
.v-step[x-placement^="left"] .v-step__arrow {
|
||||
border-top-color: transparent !important;
|
||||
border-right-color: transparent !important;
|
||||
border-bottom-color: transparent !important;
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue