Run lint:fix and accept a huge formatting change

This commit is contained in:
Julian Stirling 2025-10-27 18:00:00 +00:00
parent 3900c3e1ad
commit c085d2c0ac
68 changed files with 756 additions and 1047 deletions

View file

@ -1,24 +1,10 @@
<template>
<div>
<form
class="uk-form-stacked"
action=""
method="GET"
@submit="overrideAPIHost"
>
<form class="uk-form-stacked" action="" method="GET" @submit="overrideAPIHost">
<label class="uk-form-label">Override API origin</label>
<input
v-model="newOrigin"
name="overrideOrigin"
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"
/>
<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">
@ -38,7 +24,7 @@ export default {
data: function() {
return {
newOrigin: this.$store.state.origin,
reloadWhenOverridingOrigin: true
reloadWhenOverridingOrigin: true,
};
},
@ -62,8 +48,8 @@ export default {
this.$store.commit("changeOrigin", this.newOrigin);
event.preventDefault();
}
}
}
},
},
};
</script>

View file

@ -53,9 +53,7 @@
<div v-else-if="$store.state.waiting">
Loading...
</div>
<div v-else-if="$store.state.error">
<b>Error:</b> {{ $store.state.error }}
</div>
<div v-else-if="$store.state.error"><b>Error:</b> {{ $store.state.error }}</div>
<div v-else>No active connection</div>
</div>
</template>
@ -70,37 +68,33 @@ export default {
data: function() {
return {
version: undefined,
version_source: undefined
}
},
async mounted() {
let version_data = await this.readThingProperty(
"system",
"version_data"
);
this.version = version_data.version;
this.version_source = this.truncate(version_data.version_source);
version_source: undefined,
};
},
computed: {
things: function() {
return this.$store.getters["wot/thingDescriptions"];
}
},
},
async mounted() {
let version_data = await this.readThingProperty("system", "version_data");
this.version = version_data.version;
this.version_source = this.truncate(version_data.version_source);
},
methods: {
truncate(string, max_length=15) {
if (!(typeof string === 'string' || string instanceof String)) {
truncate(string, max_length = 15) {
if (!(typeof string === "string" || string instanceof String)) {
return string;
}
if (string.length <= max_length) {
return string;
}
return string.slice(0, max_length - 3) + "...";
}
}
},
},
};
</script>

View file

@ -30,7 +30,7 @@ export default {
components: {
devTools,
statusPane
}
statusPane,
},
};
</script>

View file

@ -1,5 +1,5 @@
<template>
<div class="uk-padding-small" v-observe-visibility="visibilityChanged">
<div v-observe-visibility="visibilityChanged" class="uk-padding-small">
<div>
<ul uk-accordion="multiple: true">
<li>
@ -35,7 +35,7 @@
thing="camera"
action="image_is_sample"
submit-label="Check Current Image"
:isDisabled="!ready"
:is-disabled="!ready"
:can-terminate="false"
:poll-interval="0.1"
@response="alertImageLabel"
@ -53,13 +53,13 @@ import InputFromSchema from "../../labThingsComponents/inputFromSchema.vue";
export default {
components: {
ActionButton,
InputFromSchema
InputFromSchema,
},
data() {
return {
backgroundDetectorStatus: undefined,
animate: false
animate: false,
};
},
@ -67,7 +67,13 @@ export default {
ready() {
const status = this.backgroundDetectorStatus;
return status && status.ready === true;
}
},
},
async created() {
this.backgroundDetectorStatus = await this.readThingProperty(
"camera",
"background_detector_status",
);
},
methods: {
@ -86,27 +92,17 @@ export default {
readSettings: async function() {
this.backgroundDetectorStatus = await this.readThingProperty(
"camera",
"background_detector_status"
"background_detector_status",
);
},
writeSettings: async function(requestedValue) {
await this.invokeAction(
"camera",
"update_detector_settings",
{"data": requestedValue}
);
await this.invokeAction("camera", "update_detector_settings", { data: requestedValue });
this.animate = true;
this.readSettings();
},
resetAnimate: function() {
this.animate = false;
}
this.animate = false;
},
},
async created() {
this.backgroundDetectorStatus = await this.readThingProperty(
"camera",
"background_detector_status"
);
}
};
</script>

View file

@ -19,7 +19,7 @@ export default {
components: {
paneBackgroundDetect,
streamDisplay
}
streamDisplay,
},
};
</script>

View file

@ -18,12 +18,7 @@
/>
</div>
<label class="uk-margin-small-right"
><input
v-model="invert.x"
class="uk-checkbox"
type="checkbox"
/>
Invert x</label
><input v-model="invert.x" class="uk-checkbox" type="checkbox" /> Invert x</label
>
</div>
@ -38,12 +33,7 @@
/>
</div>
<label class="uk-margin-small-right"
><input
v-model="invert.y"
class="uk-checkbox"
type="checkbox"
/>
Invert y</label
><input v-model="invert.y" class="uk-checkbox" type="checkbox" /> Invert y</label
>
</div>
@ -59,7 +49,7 @@
</div>
</div>
</div>
<br>
<br />
<action-button
thing="stage"
action="set_zero_position"
@ -165,8 +155,7 @@
<div v-else class="uk-text-warning">
<p>Stage positioning is disabled since no stage is connected.</p>
<p>
Please check all data and power connections to your motor controller
board.
Please check all data and power connections to your motor controller board.
</p>
</div>
</div>
@ -183,7 +172,7 @@ export default {
components: {
ActionButton,
syncPropertyButton
syncPropertyButton,
},
data: function() {
@ -193,16 +182,16 @@ export default {
stepSize: {
x: 200,
y: 200,
z: 50
z: 50,
},
invert: {
x: false,
y: false,
z: false
z: false,
},
setPosition: null,
isAutofocusing: 0,
moveLock: false
moveLock: false,
};
},
@ -214,11 +203,8 @@ export default {
return `${this.baseUri}/stage/position`;
},
moveInImageCoordinatesUri: function() {
return this.thingActionUrl(
"camera_stage_mapping",
"move_in_image_coordinates"
);
}
return this.thingActionUrl("camera_stage_mapping", "move_in_image_coordinates");
},
},
watch: {
@ -226,20 +212,19 @@ export default {
deep: true,
handler() {
this.setLocalStorageObj("navigation_stepSize", this.stepSize);
}
},
},
invert: {
deep: true,
handler() {
this.setLocalStorageObj("navigation_invert", this.invert);
}
}
},
},
},
async mounted() {
// Reload saved settings
this.stepSize =
this.getLocalStorageObj("navigation_stepSize") || this.stepSize;
this.stepSize = this.getLocalStorageObj("navigation_stepSize") || this.stepSize;
this.invert = this.getLocalStorageObj("navigation_invert") || this.invert;
let self = this;
// A global signal listener to perform a move action
@ -255,7 +240,7 @@ export default {
x_steps * this.stepSize.x * (this.invert.x ? -1 : 1),
y_steps * this.stepSize.y * (this.invert.y ? -1 : 1),
z_steps * this.stepSize.z * (this.invert.z ? -1 : 1),
false
false,
);
});
// Update the current position in text boxes
@ -287,7 +272,7 @@ export default {
this.setPosition = {
x: this.setPosition.x + x,
y: this.setPosition.y + y,
z: this.setPosition.z + z
z: this.setPosition.z + z,
};
}
await this.timeout(1); // Wait for Vue to update the position
@ -304,7 +289,7 @@ export default {
if (!this.moveInImageCoordinatesUri) {
this.modalError(
"Moving in image coordinates is not supported - you will need to upgrade your microscope's software."
"Moving in image coordinates is not supported - you will need to upgrade your microscope's software.",
);
}
@ -312,7 +297,7 @@ export default {
axios
.post(this.moveInImageCoordinatesUri, {
x: x, // NB the coordinates are numpy/PIL style, meaning X and Y are swapped.
y: y
y: y,
})
.then(() => {
this.updatePosition(); // Update the position in text boxes
@ -346,8 +331,8 @@ export default {
link.setAttribute("download", `OFM_${new Date().toISOString()}.jpeg`);
document.body.appendChild(link);
link.click();
}
}
},
},
};
</script>

View file

@ -19,7 +19,7 @@ export default {
components: {
paneControl,
streamDisplay
}
streamDisplay,
},
};
</script>

View file

@ -1,17 +1,9 @@
<template>
<div
v-observe-visibility="visibilityChanged"
class="uk-padding uk-padding-remove-top"
>
<div v-observe-visibility="visibilityChanged" class="uk-padding uk-padding-remove-top">
<!-- Logging nav bar -->
<nav
class="logging-navbar uk-navbar-container uk-navbar-transparent"
uk-navbar="mode: click"
>
<nav class="logging-navbar uk-navbar-container uk-navbar-transparent" uk-navbar="mode: click">
<!-- Left side controls -->
<div
class="uk-navbar-left uk-padding-remove-top uk-padding-remove-bottom"
>
<div class="uk-navbar-left uk-padding-remove-top uk-padding-remove-bottom">
<select v-model="filterLevel" class="uk-select">
<option v-for="level in allLevels" :key="level">{{ level }}</option>
</select>
@ -30,11 +22,11 @@
</button>
</div>
<div>
<EndpointButton
class="uk-button uk-width-1-1"
:URL="logFileURI"
buttonLabel="Download Log File"
:buttonPrimary="false"
<EndpointButton
class="uk-button uk-width-1-1"
:u-r-l="logFileURI"
button-label="Download Log File"
:button-primary="false"
/>
</div>
</div>
@ -50,7 +42,7 @@
class="logging-entry"
:class="{
'uk-alert-warning uk-alert': item.level == 'WARNING',
'uk-alert-danger uk-alert': item.level == 'ERROR'
'uk-alert-danger uk-alert': item.level == 'ERROR',
}"
>
<b>{{ formatDateTime(item.timestamp) }}: {{ item.level }}</b>
@ -64,11 +56,7 @@
More info...
</a>
<!-- eslint-disable vue/no-v-html -->
<div
v-if="item.expanded"
class="logging-message"
v-html="item.message"
></div>
<div v-if="item.expanded" class="logging-message" v-html="item.message"></div>
<!-- eslint-enable -->
</div>
</div>
@ -101,7 +89,7 @@ export default {
components: {
Paginate,
EndpointButton
EndpointButton,
},
data: function() {
@ -110,7 +98,7 @@ export default {
page: 1,
logs: [],
allLevels: ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
filterLevel: "WARNING"
filterLevel: "WARNING",
};
},
@ -142,7 +130,7 @@ export default {
},
numberOfPages: function() {
return Math.floor(this.filteredItems.length / this.maxitems);
}
},
},
methods: {
@ -172,7 +160,7 @@ export default {
summary: m[3],
message: this.escapeText(m[3]),
sequence: logs.length,
expanded: false
expanded: false,
});
} else if (logs) {
// If a line does not look like a log entry, append it to the last
@ -198,9 +186,7 @@ export default {
} else {
// if there's no existing log message to append to, discard lines
// until we find one.
console.log(
"Ignored non-matching lines at the start of the log file."
);
console.log("Ignored non-matching lines at the start of the log file.");
continue;
}
}
@ -216,8 +202,8 @@ export default {
let div = document.createElement("div");
div.innerText = unsafeText;
return div.innerHTML;
}
}
},
},
};
</script>

View file

@ -1,11 +1,12 @@
<template>
<!-- Grid managing tab content -->
<div class="container">
<h1 id="power-title"> Power</h1>
<p id="power-msg"> It's essential to turn off your OpenFlexure Microscope here before unplugging it.
<br>
<br>
Unplugging the microscope unexpectedly can damage the SD card or onboard computer.
<h1 id="power-title">Power</h1>
<p id="power-msg">
It's essential to turn off your OpenFlexure Microscope here before unplugging it.
<br />
<br />
Unplugging the microscope unexpectedly can damage the SD card or onboard computer.
</p>
<div class="buttons-container">
<button
@ -37,44 +38,38 @@ export default {
data: function() {
return {
isRaspberrypi: undefined,
}
};
},
computed: {
things: function() {
return this.$store.getters["wot/thingDescriptions"];
}
},
},
async mounted() {
this.isRaspberrypi = await this.readThingProperty(
"system",
"is_raspberrypi"
);
this.isRaspberrypi = await this.readThingProperty("system", "is_raspberrypi");
},
methods: {
systemRequest: function(action) {
let message = "";
if (action == "reboot") {
message = "Restart microscope?"
}
else {
message = "Shutdown microscope?"
message = "Restart microscope?";
} else {
message = "Shutdown microscope?";
}
this.modalConfirm(message).then(
() => {
this.$store.commit("resetState");
this.$store.commit("wot/deleteAllThingDescriptions");
// Post and silence errors
axios
.post(this.thingActionUrl("system", action))
.catch(() => {});
axios.post(this.thingActionUrl("system", action)).catch(() => {});
},
() => {}
() => {},
);
}
}
},
},
};
</script>
@ -82,7 +77,6 @@ export default {
// Custom UIkit CSS modifications
@import "../../assets/less/theme.less";
.container {
display: flex;
flex-direction: column;
@ -109,7 +103,7 @@ export default {
.shutdown-button {
display: inline;
text-align:center;
text-align: center;
margin: 30px 30px 30px 30px;
}
</style>
</style>

View file

@ -1,7 +1,7 @@
<template>
<div v-observe-visibility="visibilityChanged">
<div id="openseadragon"></div>
</div>
<div v-observe-visibility="visibilityChanged">
<div id="openseadragon"></div>
</div>
</template>
<script>
@ -13,26 +13,25 @@ export default {
props: {
src: {
type: String,
required: true
required: true,
},
brightness: {
type: Number,
required: true
required: true,
},
contrast: {
type: Number,
required: true
required: true,
},
saturation: {
type: Number,
required: true
}
required: true,
},
},
data: function() {
return {
osdViewer: null
osdViewer: null,
};
},
@ -41,7 +40,7 @@ export default {
immediate: true,
handler(newVal) {
this.loadOpenSeaDragon(newVal);
}
},
},
brightness() {
this.updateFilter();
@ -51,7 +50,7 @@ export default {
},
saturation() {
this.updateFilter();
}
},
},
async mounted() {
@ -69,7 +68,7 @@ export default {
visibilityChanged(isVisible) {
if (isVisible) {
this.loadOpenSeaDragon();
}else{
} else {
this.osdViewer.destroy();
}
},
@ -79,13 +78,13 @@ export default {
}
this.osdViewer = OpenSeaDragon({
id: "openseadragon",
crossOriginPolicy: 'Anonymous',
crossOriginPolicy: "Anonymous",
tileSources: this.src,
showNavigationControl: false,
maxZoomPixelRatio: 2,
gestureSettingsMouse: {
clickToZoom: false
}
clickToZoom: false,
},
});
this.updateFilter();
@ -106,7 +105,7 @@ export default {
this.osdViewer.setFullScreen(true);
}
},
}
},
};
</script>
@ -117,4 +116,4 @@ export default {
background-color: black;
z-index: 1;
}
</style>
</style>

View file

@ -2,9 +2,7 @@
<div class="uk-card">
<div class="uk-card-body">
<div class="uk-card-media-top">
<div
class="view-image uk-padding-remove uk-height-1-1"
>
<div class="view-image uk-padding-remove uk-height-1-1">
<img
id="thumbnail-stitched-image"
class="thumbnail-fit"
@ -15,39 +13,36 @@
</div>
</div>
<h3 class="uk-card-title scan-card-title">{{ scanData.name }}</h3>
<h4 class="ongoing-msg" v-if="ongoing">Scan in progress</h4>
<div class="button-container" v-if="!ongoing">
<h4 v-if="ongoing" class="ongoing-msg">Scan in progress</h4>
<div v-if="!ongoing" class="button-container">
<div class="uk-button-group scan-card-buttons">
<action-button
class="uk-width-1-2"
thing="smart_scan"
action="download_zip"
submit-label="Download All"
:can-terminate="false"
:submit-data="{ scan_name: scanData.name }"
:button-primary="true"
@response="downloadZipFile"
@error="modalError"
class="uk-width-1-2"
thing="smart_scan"
action="download_zip"
submit-label="Download All"
:can-terminate="false"
:submit-data="{ scan_name: scanData.name }"
:button-primary="true"
@response="downloadZipFile"
@error="modalError"
/>
<EndpointButton
class="uk-width-1-2"
:buttonPrimary=true
:isDisabled=!scanData.stitch_available
:URL="downloadStitchFile"
buttonLabel="Download JPEG"
/>
:button-primary="true"
:is-disabled="!scanData.stitch_available"
:u-r-l="downloadStitchFile"
button-label="Download JPEG"
/>
</div>
<button
class="uk-button uk-button-default uk-width-1-1"
@click="deleteScan"
>
<button class="uk-button uk-button-default uk-width-1-1" @click="deleteScan">
Delete
</button>
<action-button
v-if="scanData.can_stitch | (scanData.stitch_available & !scanData.dzi)"
submit-label="Stitch Images"
thing="smart_scan"
action="stitch_scan"
v-if="scanData.can_stitch | (scanData.stitch_available & !scanData.dzi)"
:can-terminate="true"
:submit-data="{ scan_name: scanData.name }"
:button-primary="false"
@ -55,10 +50,11 @@
@error="modalError"
/>
<button
v-if="scanData.dzi" class="uk-button uk-button-default uk-width-1-1"
v-if="scanData.dzi"
class="uk-button uk-button-default uk-width-1-1"
@click="requestViewer"
>
Show Stitched Scan
Show Stitched Scan
</button>
</div>
<div class="scan-info">
@ -68,9 +64,15 @@
<li>duration: {{ formatDuration(scanData.duration) }}</li>
</ul>
<ul v-if="!ongoing">
<li v-if="scanData.number_of_images<3" class="warning-msg">Not enough images to stitch</li>
<li v-else-if="!scanData.dzi && scanData.stitch_available" class="alert-msg">Interactive preview not available</li>
<li v-else-if="!scanData.stitch_available" class="alert-msg">High quality stitch not available</li>
<li v-if="scanData.number_of_images < 3" class="warning-msg">
Not enough images to stitch
</li>
<li v-else-if="!scanData.dzi && scanData.stitch_available" class="alert-msg">
Interactive preview not available
</li>
<li v-else-if="!scanData.stitch_available" class="alert-msg">
High quality stitch not available
</li>
</ul>
</div>
</div>
@ -90,16 +92,16 @@ export default {
props: {
scanData: {
type: Object,
required: true
required: true,
},
scansUri: {
type: String,
required: true
required: true,
},
ongoing: {
type: Boolean,
required: true
}
required: true,
},
},
computed: {
@ -114,7 +116,7 @@ export default {
methods: {
formatDate(timestamp) {
// Multiply by 1000 as JS uses ms not s
let d = new Date(timestamp*1000);
let d = new Date(timestamp * 1000);
// Convert to a string in a very javascript way!
let yyyy = d.getFullYear();
let mm = d.getMonth() + 1;
@ -146,14 +148,14 @@ export default {
requestViewer() {
// Notify parent that thumbnail was clicked
if (!this.ongoing) {
this.$emit('viewer-requested', this.scanData);
this.$emit("viewer-requested", this.scanData);
}
},
async deleteScan() {
try {
await this.modalConfirm(`Are you sure you want to delete ${this.scanData.name}?`);
await axios.delete(`${this.scansUri}/${this.scanData.name}`);
this.$emit('update-requested');
this.$emit("update-requested");
this.modalNotify(`Deleted ${this.scanData.name}`);
} catch (e) {
// if the confirmation was cancelled, it's rejected with null error
@ -170,15 +172,15 @@ export default {
console.log(link);
document.body.appendChild(link);
link.click();
}
}
}
},
},
};
</script>
<style lang="less" scoped>
ul {
display: block;
text-align: center;
list-style-type:none;
list-style-type: none;
margin: 5px 0px 10px 0px;
padding: 0;
}
@ -207,5 +209,4 @@ ul {
text-align: center;
padding: 2rem 0;
}
</style>
</style>

View file

@ -1,10 +1,6 @@
<template>
<div id="scan-modal" ref="scanModal" uk-modal>
<div
id="scan-modal-body"
class="uk-modal-dialog uk-modal-body"
v-if="selectedScan"
>
<div v-if="selectedScan" id="scan-modal-body" class="uk-modal-dialog uk-modal-body">
<h2 id="scan-modal-title" class="uk-modal-title">
{{ selectedScan.name }}
<button class="uk-modal-close uk-float-right" type="button">
@ -16,11 +12,7 @@
</h2>
<!-- Viewer -->
<div
v-if="selectedScanDZI"
id="viewer_container"
class="viewer_container"
>
<div v-if="selectedScanDZI" id="viewer_container" class="viewer_container">
<OpenSeadragonViewer
id="openseadragon"
ref="openseadragon"
@ -32,40 +24,19 @@
</div>
<!-- Controls -->
<div
v-if="selectedScanDZI"
class="viewer-controls"
>
<div v-if="selectedScanDZI" class="viewer-controls">
<div class="controlsContainer">
<label>
Brightness
<input
type="range"
min="0.2"
max="1.8"
step="0.01"
v-model.number="brightness"
/>
<input v-model.number="brightness" type="range" min="0.2" max="1.8" step="0.01" />
</label>
<label>
Contrast
<input
type="range"
min="0.2"
max="1.8"
step="0.01"
v-model.number="contrast"
/>
<input v-model.number="contrast" type="range" min="0.2" max="1.8" step="0.01" />
</label>
<label>
Saturation
<input
type="range"
min="0"
max="2"
step="0.01"
v-model.number="saturation"
/>
<input v-model.number="saturation" type="range" min="0" max="2" step="0.01" />
</label>
</div>
@ -155,26 +126,26 @@ input[type="range"] {
}
.controlsContainer {
display: flex;
justify-content: center;
gap: 1.5rem;
display: flex;
justify-content: center;
gap: 1.5rem;
}
.viewer-controls {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
margin-top: 0.5rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
margin-top: 0.5rem;
}
.viewer_container {
flex: 1 1 auto;
position: relative;
overflow: hidden;
flex: 1 1 auto;
position: relative;
overflow: hidden;
}
.reset-button{
.reset-button {
margin-top: 0.5rem;
}
</style>

View file

@ -1,12 +1,10 @@
<template>
<div
v-observe-visibility="visibilityChanged"
class="galleryDisplay uk-padding uk-padding-remove-top">
class="galleryDisplay uk-padding uk-padding-remove-top"
>
<!-- Gallery nav bar -->
<nav
class="gallery-navbar uk-navbar-container uk-navbar-transparent"
uk-navbar="mode: click"
>
<nav class="gallery-navbar uk-navbar-container uk-navbar-transparent" uk-navbar="mode: click">
<!-- Right side buttons -->
<div class="uk-navbar-right">
<div class="uk-grid">
@ -50,18 +48,17 @@
<ScanViewerModal
ref="scanViewer"
:selectedScan="selectedScan"
:baseUri="$store.getters.baseUri"
:selected-scan="selectedScan"
:base-uri="$store.getters.baseUri"
/>
<!-- Gallery -->
<div
v-if="$store.getters.ready"
class="uk-padding-remove-top"
uk-lightbox="toggle: .lightbox-link"
>
<!-- Gallery capture cards -->
<!-- Gallery capture cards -->
<div class="gallery-grid uk-grid-match" uk-grid>
<div v-if="scansEmpty">
<h2>No scans available</h2>
@ -99,7 +96,7 @@ export default {
scans: [],
ongoing: null,
selectedScan: null,
osdViewer: null
osdViewer: null,
};
},
@ -109,19 +106,19 @@ export default {
"smart_scan",
"scans",
"readproperty",
true
true,
);
},
scansEmpty() {
return this.scans.length == 0;
},
selectedScanDZI() {
if (this.selectedScan && this.selectedScan.dzi!="") {
if (this.selectedScan && this.selectedScan.dzi != "") {
return `${this.$store.getters.baseUri}/scans/${this.selectedScan.name}/images/${this.selectedScan.dzi}`;
} else {
return null;
}
}
},
},
async mounted() {
@ -132,7 +129,7 @@ export default {
this.updateScans();
});
this.$root.$on("modalClosed", () => {
// Handle the modal closed event here
// Handle the modal closed event here
this.updateScans();
});
},
@ -151,7 +148,7 @@ export default {
// If the connection is now disconnected, empty capture list
this.captures = {};
}
}
},
);
},
@ -175,8 +172,8 @@ export default {
async updateScans() {
try {
let scans_information = await this.readThingProperty("smart_scan", "scans");
let scans = scans_information.scans
this.ongoing = scans_information.ongoing
let scans = scans_information.scans;
this.ongoing = scans_information.ongoing;
if (!scans | (scans.length == 0)) {
this.scans = scans;
}
@ -194,13 +191,13 @@ export default {
}
},
isOngoing(name) {
return name === this.ongoing
return name === this.ongoing;
},
async deleteAllScans() {
try {
await this.modalConfirm(
"Are you sure you want to delete all scans from the microscope? " +
"This is <b>irreversible</b>!"
"This is <b>irreversible</b>!",
);
await axios.delete(`${this.scansUri}`);
await this.updateScans();
@ -217,9 +214,9 @@ export default {
} else {
this.modalError("Scan not stitched for viewing in webapp, please download or stitch");
}
}
}
}
},
},
};
</script>
<style lang="less" scoped>
@ -238,4 +235,4 @@ export default {
margin-top: 5px;
margin-bottom: 2px;
}
</style>
</style>

View file

@ -1,15 +1,10 @@
<template>
<div
id="CSMSettings"
class="uk-grid uk-grid-divider uk-child-width-expand"
uk-grid
>
<div id="CSMSettings" class="uk-grid uk-grid-divider uk-child-width-expand" uk-grid>
<div class="uk-width-xlarge">
<h3>Camera to Stage Mapping</h3>
<p>
Camera-stage mapping allows the stage to move relative to the camera
view. This enables functions like click-to-move, and more precise tile
scans.
Camera-stage mapping allows the stage to move relative to the camera view. This enables
functions like click-to-move, and more precise tile scans.
</p>
<CSMCalibrationSettings />
</div>
@ -29,8 +24,8 @@ export default {
components: {
CSMCalibrationSettings,
miniStreamDisplay
}
miniStreamDisplay,
},
};
</script>

View file

@ -1,5 +1,5 @@
<template>
<div v-observe-visibility="visibilityChanged" id="CSMCalibrationSettings">
<div id="CSMCalibrationSettings" v-observe-visibility="visibilityChanged">
<!--Show auto calibrate if default plugin is enabled-->
<div v-if="'calibrate_xy' in actions" class="uk-margin-small">
<action-button
@ -26,15 +26,18 @@
>
Download Calibration Data
</button>
<div v-if="this.csmMatrix!='undefined'" style="margin:10px;">
<details><summary>Calibration Details</summary>
<strong>CSM calculated for images with a resolution of {{ csmResolution }}</strong>
<ul>
<li>Current CSM Matrix: <tt>{{ csmMatrix }}</tt></li>
<li>Pixels per motor step: {{ csmRatio }}</li>
<li>Full field of view: {{ csmFOV }} motor steps</li>
</ul>
</details>
<div v-if="this.csmMatrix != 'undefined'" style="margin:10px;">
<details
><summary>Calibration Details</summary>
<strong>CSM calculated for images with a resolution of {{ csmResolution }}</strong>
<ul>
<li>
Current CSM Matrix: <tt>{{ csmMatrix }}</tt>
</li>
<li>Pixels per motor step: {{ csmRatio }}</li>
<li>Full field of view: {{ csmFOV }} motor steps</li>
</ul>
</details>
</div>
</div>
</template>
@ -47,36 +50,32 @@ export default {
name: "CSMCalibrationSettings",
components: {
ActionButton
ActionButton,
},
props: {
showExtraSettings: {
type: Boolean,
required: false,
default: true
}
default: true,
},
},
data() {
return {
csmMatrix: "undefined",
csmResolution: "undefined",
csmRatio: "undefined"
csmRatio: "undefined",
};
},
computed: {
actions() {
return this.$store.getters["wot/thingDescription"]("camera_stage_mapping")
.actions;
return this.$store.getters["wot/thingDescription"]("camera_stage_mapping").actions;
},
properties() {
return this.$store.getters["wot/thingDescription"]("camera_stage_mapping")
.properties;
}
return this.$store.getters["wot/thingDescription"]("camera_stage_mapping").properties;
},
},
methods: {
@ -87,10 +86,7 @@ export default {
},
getCalibrationData: async function() {
try {
let data = await this.readThingProperty(
"camera_stage_mapping",
"last_calibration"
);
let data = await this.readThingProperty("camera_stage_mapping", "last_calibration");
if (data == {}) {
throw "No calibration data available.";
}
@ -107,33 +103,29 @@ export default {
},
updateDisplayedCSM: async function() {
let csmMatrix = await this.readThingProperty(
"camera_stage_mapping",
"image_to_stage_displacement_matrix"
);
this.csmResolution = await this.readThingProperty(
"camera_stage_mapping",
"image_resolution"
);
let streamResolution = await this.readThingProperty(
"camera",
"stream_resolution"
"image_to_stage_displacement_matrix",
);
this.csmResolution = await this.readThingProperty("camera_stage_mapping", "image_resolution");
let streamResolution = await this.readThingProperty("camera", "stream_resolution");
csmMatrix[0][0] = Number(csmMatrix[0][0].toFixed(3));
csmMatrix[0][1] = Number(csmMatrix[0][1].toFixed(3));
csmMatrix[1][0] = Number(csmMatrix[1][0].toFixed(3));
csmMatrix[1][1] = Number(csmMatrix[1][1].toFixed(3));
this.csmMatrix = csmMatrix;
this.csmRatio = Number((Math.abs(csmMatrix[1][0]) + Math.abs(csmMatrix[0][1])) / 2).toFixed(3);
this.csmRatio = Number((Math.abs(csmMatrix[1][0]) + Math.abs(csmMatrix[0][1])) / 2).toFixed(
3,
);
this.csmFOV = [
Number((streamResolution[0]**2 * this.csmRatio / this.csmResolution[1]).toFixed(0)),
Number((streamResolution[1]**2 * this.csmRatio / this.csmResolution[0]).toFixed(0)),
]
Number(((streamResolution[0] ** 2 * this.csmRatio) / this.csmResolution[1]).toFixed(0)),
Number(((streamResolution[1] ** 2 * this.csmRatio) / this.csmResolution[0]).toFixed(0)),
];
},
onRecalibrateResponse: function() {
this.modalNotify("Finished stage-to-camera calibration.");
this.updateDisplayedCSM();
}
}
},
},
};
</script>

View file

@ -34,8 +34,19 @@ export default {
},
set(value) {
this.$store.commit("changeAppTheme", value);
}
}
},
},
},
watch: {
appTheme: function() {
this.setLocalStorageObj("appTheme", this.appTheme);
},
},
mounted() {
// Try loading settings from localStorage. If null, don't change.
this.appTheme = this.getLocalStorageObj("appTheme") || this.appTheme;
},
methods: {
@ -45,19 +56,8 @@ export default {
} else {
await document.exitFullscreen();
}
}
},
},
watch: {
appTheme: function() {
this.setLocalStorageObj("appTheme", this.appTheme);
}
},
mounted() {
// Try loading settings from localStorage. If null, don't change.
this.appTheme = this.getLocalStorageObj("appTheme") || this.appTheme;
}
};
</script>

View file

@ -33,7 +33,7 @@ export default {
components: {
cameraCalibrationSettings,
miniStreamDisplay,
ServerSpecifiedPropertyControl
ServerSpecifiedPropertyControl,
},
data() {
@ -45,15 +45,12 @@ export default {
computed: {
cameraUri: function() {
return `${this.$store.getters.baseUri}/camera/`;
}
},
},
async created() {
this.manualCameraSettings = await this.readThingProperty(
"camera",
"manual_camera_settings"
);
}
this.manualCameraSettings = await this.readThingProperty("camera", "manual_camera_settings");
},
};
</script>

View file

@ -28,44 +28,44 @@ export default {
name: "CameraCalibrationSettings",
components: {
ServerSpecifiedActionButton
ServerSpecifiedActionButton,
},
props: {
showExtraSettings: {
type: Boolean,
required: false,
default: true
default: true,
},
cameraUri: {
type: String,
required: true
}
required: true,
},
},
data() {
return {
primaryCalibrationActions: [],
secondaryCalibrationActions: []
secondaryCalibrationActions: [],
};
},
computed: {
actions() {
return this.$store.getters["wot/thingDescription"]("camera").actions;
}
},
},
async created() {
this.primaryCalibrationActions = await this.readThingProperty(
"camera",
"primary_calibration_actions"
"primary_calibration_actions",
);
this.secondaryCalibrationActions = await this.readThingProperty(
"camera",
"secondary_calibration_actions"
"secondary_calibration_actions",
);
}
},
};
</script>

View file

@ -1,5 +1,5 @@
<template>
<div id="stageSettings" class="uk-width-large" v-observe-visibility="visibilityChanged">
<div id="stageSettings" v-observe-visibility="visibilityChanged" class="uk-width-large">
The microscope stage is a <b>{{ stageType }}</b>
<div>
<div class="uk-margin">
@ -48,6 +48,12 @@ export default {
};
},
computed: {
stageType: function() {
return this.thingDescription("stage").title;
}
},
methods:{
visibilityChanged(isVisible) {
if (isVisible) {
@ -61,12 +67,6 @@ export default {
);
this.z_inverted = axes_inverted['z'] ? "" : "not ";
}
},
computed: {
stageType: function() {
return this.thingDescription("stage").title;
}
}
};
</script>

View file

@ -3,8 +3,8 @@
<div>
<h3>Stream Settings</h3>
<label
><input v-model="disableStream" class="uk-checkbox" type="checkbox" />
Disable Web Stream</label
><input v-model="disableStream" class="uk-checkbox" type="checkbox" /> Disable Web
Stream</label
>
<p class="uk-margin-small">
This will disable the embedded web stream of the camera.
@ -29,8 +29,8 @@ export default {
},
set(value) {
this.$store.commit("changeDisableStream", value);
}
}
},
},
},
watch: {
@ -38,8 +38,8 @@ export default {
// (the next 3 functions all relate to this)
disableStream: function(newValue) {
this.setLocalStorageObj("disableStream", newValue);
}
}
},
},
};
</script>

View file

@ -1,9 +1,7 @@
<template>
<!-- Grid managing tab content -->
<div uk-grid class="uk-height-1-1 uk-margin-remove uk-padding-remove">
<calibrationWizard
ref="calibrationWizard"
></calibrationWizard>
<calibrationWizard ref="calibrationWizard"></calibrationWizard>
<div class="settings-nav">
<ul class="uk-nav uk-nav-default">
<li class="uk-nav-header">Application Settings</li>
@ -22,11 +20,13 @@
</li>
<li class="uk-nav-header">Microscope Settings</li>
<button
submit-label="Launch Calibration Wizard"
type="button"
class="uk-button uk-button-default uk-width-1-1"
@click="startModals"
>Launch Calibration Wizard</button>
submit-label="Launch Calibration Wizard"
type="button"
class="uk-button uk-button-default uk-width-1-1"
@click="startModals"
>
Launch Calibration Wizard
</button>
<li>
<tabIcon
id="settings-camera-icon"
@ -69,42 +69,26 @@
</ul>
</div>
<div class="view-component uk-width-expand uk-padding-small">
<tabContent
tab-i-d="display"
:require-connection="false"
:current-tab="currentTab"
>
<tabContent tab-i-d="display" :require-connection="false" :current-tab="currentTab">
<div class="settings-pane uk-padding-small">
<appSettings />
<streamSettings />
</div>
</tabContent>
<tabContent
tab-i-d="camera"
:require-connection="true"
:current-tab="currentTab"
>
<tabContent tab-i-d="camera" :require-connection="true" :current-tab="currentTab">
<div class="settings-pane uk-padding-small">
<cameraSettings />
</div>
</tabContent>
<tabContent
tab-i-d="stage"
:require-connection="true"
:current-tab="currentTab"
>
<tabContent tab-i-d="stage" :require-connection="true" :current-tab="currentTab">
<div class="settings-pane uk-padding-small">
<stageSettings />
</div>
</tabContent>
<tabContent
tab-i-d="mapping"
:require-connection="true"
:current-tab="currentTab"
>
<tabContent tab-i-d="mapping" :require-connection="true" :current-tab="currentTab">
<div class="settings-pane uk-padding-small">
<CSMSettings />
</div>
@ -136,13 +120,13 @@ export default {
appSettings,
tabIcon,
tabContent,
calibrationWizard
calibrationWizard,
},
data: function() {
return {
selected: "display",
currentTab: "display"
currentTab: "display",
};
},
@ -154,8 +138,8 @@ export default {
},
startModals: function() {
this.$refs.calibrationWizard.force_show();
}
}
},
},
};
</script>

View file

@ -29,7 +29,7 @@
thing-name="autofocus"
property-name="stack_dz"
label="Stack dz (steps)"
/>
/>
</div>
<div class="uk-margin">
<propertyControl
@ -83,12 +83,7 @@
</ul>
<label class="uk-form-label" for="form-stacked-text">Sample ID</label>
<div class="uk-form-controls">
<input
v-model="scan_name"
class="uk-input uk-form-small"
type="text"
name="Scan Name"
/>
<input v-model="scan_name" class="uk-input uk-form-small" type="text" name="Scan Name" />
</div>
<div class="uk-margin">
<action-button
@ -110,11 +105,7 @@
Live stitching preview
</h2>
<mini-stream-display v-if="displayImageOnRight" />
<action-log-display
id="log-display"
:log="log"
:task-status="taskStatus"
/>
<action-log-display id="log-display" :log="log" :task-status="taskStatus" />
<action-progress-bar :progress="progress" :task-status="taskStatus" />
<button
v-if="cancellable"
@ -124,11 +115,7 @@
>
Cancel
</button>
<div
v-if="!cancellable"
class="uk-margin uk-grid-small uk-child-width-expand"
uk-grid
>
<div v-if="!cancellable" class="uk-margin uk-grid-small uk-child-width-expand" uk-grid>
<button
type="button"
class="uk-button"
@ -182,7 +169,7 @@ export default {
actionLogDisplay,
actionProgressBar,
MiniStreamDisplay,
ActionButton
ActionButton,
},
data() {
@ -195,7 +182,7 @@ export default {
progress: null,
log: [],
lastStitchedImage: null,
scan_name: ""
scan_name: "",
};
},
@ -208,7 +195,7 @@ export default {
},
displayImageOnRight() {
return this.scanning & (this.lastStitchedImage !== null);
}
},
},
methods: {
@ -225,17 +212,11 @@ export default {
async pollScan() {
if (this.cancellable) {
// while the scan is running
let mtime = await this.readThingProperty(
"smart_scan",
"latest_preview_stitch_time"
);
let mtime = await this.readThingProperty("smart_scan", "latest_preview_stitch_time");
if (mtime !== null) {
this.lastStitchedImage = `${this.$store.getters.baseUri}/smart_scan/latest_preview_stitch.jpg?t=${mtime}`;
}
this.lastScanName = await this.readThingProperty(
"smart_scan",
"latest_scan_name"
);
this.lastScanName = await this.readThingProperty("smart_scan", "latest_scan_name");
setTimeout(this.pollScan, 1000); // keep rescheduling until it's stopped
}
},
@ -249,8 +230,8 @@ export default {
console.log(link);
document.body.appendChild(link);
link.click();
}
}
},
},
};
</script>

View file

@ -44,7 +44,7 @@ export default {
isVisible: false,
displaySize: [0, 0],
displayPosition: [0, 0],
resizeTimeoutId: setTimeout(this.doneResizing, 500)
resizeTimeoutId: setTimeout(this.doneResizing, 500),
};
},
@ -58,7 +58,7 @@ export default {
},
streamImgUri: function() {
return `${this.$store.getters.baseUri}/camera/mjpeg_stream`;
}
},
},
mounted() {
@ -119,18 +119,14 @@ export default {
// factor.
let scale = Math.max(
event.target.naturalWidth / event.target.offsetWidth,
event.target.naturalHeight / event.target.offsetHeight
event.target.naturalHeight / event.target.offsetHeight,
);
let xRelative = (0.5 * event.target.offsetWidth - xCoordinate) * scale;
let yRelative = (0.5 * event.target.offsetHeight - yCoordinate) * scale;
// Emit a signal to move, acted on by paneControl.vue
this.$root.$emit(
"globalMoveInImageCoordinatesEvent",
-xRelative,
-yRelative
);
this.$root.$emit("globalMoveInImageCoordinatesEvent", -xRelative, -yRelative);
},
handleResize: function() {
@ -167,18 +163,13 @@ export default {
let windowChromeHeight = window.outerHeight - window.innerHeight;
let elementPositionOnDisplay = [
Math.max(0, windowPositionOnDisplay[0] + elementPositionOnWindow[0]),
Math.max(
0,
windowPositionOnDisplay[1] +
elementPositionOnWindow[1] +
windowChromeHeight
)
Math.max(0, windowPositionOnDisplay[1] + elementPositionOnWindow[1] + windowChromeHeight),
];
this.displaySize = elementSize;
this.displayPosition = elementPositionOnDisplay;
}
}
},
},
};
</script>

View file

@ -14,7 +14,7 @@ export default {
name: "ViewContent",
components: {
streamDisplay
}
streamDisplay,
},
};
</script>