ui_migration fix(deps): Replace component instance event by external event bus from mitt package.

This commit is contained in:
Antonio Anaya 2026-01-24 16:13:49 -06:00
parent 6e14bf1dd0
commit 2a9ee759c4
12 changed files with 1964 additions and 10660 deletions

12510
webapp/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -12,10 +12,11 @@
"lint:fix": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore" "lint:fix": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
}, },
"dependencies": { "dependencies": {
"@vue/compat": "^3.2.0",
"@vitejs/plugin-vue": "^5.0.0", "@vitejs/plugin-vue": "^5.0.0",
"@vue/compat": "^3.2.0",
"axios": "^1.7.7", "axios": "^1.7.7",
"material-design-icons": "^3.0", "material-design-icons": "^3.0",
"mitt": "^3.0.1",
"mousetrap": "^1.6.5", "mousetrap": "^1.6.5",
"openseadragon": "^5.0.0", "openseadragon": "^5.0.0",
"uikit": "^3.24.2", "uikit": "^3.24.2",

View file

@ -28,6 +28,7 @@ import loadingContent from "./components/loadingContent.vue";
import MouseTrap from "mousetrap"; import MouseTrap from "mousetrap";
// vue3 migration // vue3 migration
import { markRaw } from "vue"; import { markRaw } from "vue";
import { eventBus } from "./eventBus.js";
MouseTrap.prototype.stopCallback = function (e, element) { MouseTrap.prototype.stopCallback = function (e, element) {
// if the element has the class "mousetrap" then no need to stop // if the element has the class "mousetrap" then no need to stop
@ -153,10 +154,10 @@ export default {
// Focus keys // Focus keys
Mousetrap.bind("pageup", () => { Mousetrap.bind("pageup", () => {
this.$root.$emit("globalMoveStepEvent", 0, 0, 1); eventBus.emit("globalMoveStepEvent", 0, 0, 1);
}); });
Mousetrap.bind("pagedown", () => { Mousetrap.bind("pagedown", () => {
this.$root.$emit("globalMoveStepEvent", 0, 0, -1); eventBus.emit("globalMoveStepEvent", 0, 0, -1);
}); });
this.keyboardManual.push({ this.keyboardManual.push({
shortcut: "pgup / pgdn", shortcut: "pgup / pgdn",
@ -165,7 +166,7 @@ export default {
// Capture // Capture
Mousetrap.bind("c", () => { Mousetrap.bind("c", () => {
this.$root.$emit("globalCaptureEvent"); eventBus.emit("globalCaptureEvent");
}); });
this.keyboardManual.push({ this.keyboardManual.push({
shortcut: "c", shortcut: "c",
@ -174,7 +175,7 @@ export default {
// Autofocus // Autofocus
Mousetrap.bind("a", () => { Mousetrap.bind("a", () => {
this.$root.$emit("globalFastAutofocusEvent"); eventBus.emit("globalFastAutofocusEvent");
}); });
this.keyboardManual.push({ this.keyboardManual.push({
shortcut: "a", shortcut: "a",
@ -183,10 +184,10 @@ export default {
// Increment/decrement tab // Increment/decrement tab
Mousetrap.bind("shift+down", () => { Mousetrap.bind("shift+down", () => {
this.$root.$emit("globalIncrementTab"); eventBus.emit("globalIncrementTab");
}); });
Mousetrap.bind("shift+up", () => { Mousetrap.bind("shift+up", () => {
this.$root.$emit("globalDecrementTab"); eventBus.emit("globalDecrementTab");
}); });
this.keyboardManual.push({ this.keyboardManual.push({
shortcut: "shift+↑ / shift+↓", shortcut: "shift+↑ / shift+↓",
@ -237,7 +238,7 @@ export default {
} }
}, },
handleExit: function () { handleExit: function () {
this.$root.$emit("globalTogglePreview", false); eventBus.emit("globalTogglePreview", false);
}, },
// Handle global mouse wheel events to be associated with navigation // Handle global mouse wheel events to be associated with navigation
@ -249,7 +250,7 @@ export default {
) { ) {
var z_rel = event.deltaY / 100; var z_rel = event.deltaY / 100;
// Emit a signal to move, acted on by panelControl.vue // Emit a signal to move, acted on by panelControl.vue
this.$root.$emit("globalMoveStepEvent", 0, 0, z_rel, false); eventBus.emit("globalMoveStepEvent", 0, 0, z_rel, false);
} }
}, },
@ -276,7 +277,7 @@ export default {
} }
// Make a position request // Make a position request
// Emit a signal to move, acted on by panelControl.vue // Emit a signal to move, acted on by panelControl.vue
this.$root.$emit("globalMoveStepEvent", x_rel, y_rel, z_rel); eventBus.emit("globalMoveStepEvent", x_rel, y_rel, z_rel);
}, },
}, },
}; };

View file

@ -92,6 +92,7 @@ import slideScanContent from "./tabContentComponents/slideScanContent.vue";
import viewContent from "./tabContentComponents/viewContent.vue"; import viewContent from "./tabContentComponents/viewContent.vue";
// vue3 migration // vue3 migration
import { shallowRef, markRaw, ref } from 'vue' import { shallowRef, markRaw, ref } from 'vue'
import { eventBus } from "../eventBus.js";
// Import modal components for device initialisation // Import modal components for device initialisation
import calibrationWizard from "./modalComponents/calibrationWizard.vue"; import calibrationWizard from "./modalComponents/calibrationWizard.vue";
@ -207,15 +208,15 @@ export default {
mounted() { mounted() {
// A global signal listener to switch tab // A global signal listener to switch tab
this.$root.$on("globalSwitchTab", (tabID) => { eventBus.on("globalSwitchTab", (tabID) => {
this.currentTab = tabID; this.currentTab = tabID;
}); });
// A global signal listener to increment tab // A global signal listener to increment tab
this.$root.$on("globalIncrementTab", () => { eventBus.on("globalIncrementTab", () => {
this.incrementTabBy(1); this.incrementTabBy(1);
}); });
// A global signal listener to decrement tab // A global signal listener to decrement tab
this.$root.$on("globalDecrementTab", () => { eventBus.on("globalDecrementTab", () => {
this.incrementTabBy(-1); this.incrementTabBy(-1);
}); });
if (this.$store.getters.ready) { if (this.$store.getters.ready) {

View file

@ -29,6 +29,7 @@
import ActionProgressBar from "./actionProgressBar.vue"; import ActionProgressBar from "./actionProgressBar.vue";
import ActionStatusModal from "./actionStatusModal.vue"; import ActionStatusModal from "./actionStatusModal.vue";
import { markRaw } from "vue"; import { markRaw } from "vue";
import { eventBus } from "../../eventBus.js";
export default { export default {
name: "ActionButton", name: "ActionButton",
@ -134,19 +135,19 @@ export default {
watch: { watch: {
progress(newval) { progress(newval) {
this.$emit("update:progress", newval); eventBus.emit("update:progress", newval);
}, },
taskStarted(newval) { taskStarted(newval) {
this.$emit("update:taskStarted", newval); eventBus.emit("update:taskStarted", newval);
}, },
taskRunning(newval) { taskRunning(newval) {
this.$emit("update:taskRunning", newval); eventBus.emit("update:taskRunning", newval);
}, },
log(newval) { log(newval) {
this.$emit("update:log", newval); eventBus.emit("update:log", newval);
}, },
taskStatus(newval) { taskStatus(newval) {
this.$emit("update:taskStatus", newval); eventBus.emit("update:taskStatus", newval);
}, },
}, },
@ -157,7 +158,7 @@ export default {
} }
// A global signal listener to perform the action // A global signal listener to perform the action
if (this.submitOnEvent) { if (this.submitOnEvent) {
this.$root.$on(this.submitOnEvent, () => { eventBus.on(this.submitOnEvent, () => {
if (this.isDisabled) return; if (this.isDisabled) return;
// Bootstrap task if button is not disabled. // Bootstrap task if button is not disabled.
this.bootstrapTask(); this.bootstrapTask();
@ -167,7 +168,11 @@ export default {
beforeUnmount() { beforeUnmount() {
if (this.submitOnEvent) { if (this.submitOnEvent) {
this.$root.$off(this.submitOnEvent); eventBus.off(this.submitOnEvent, () => {
if (this.isDisabled) return;
// Bootstrap task if button is not disabled.
this.bootstrapTask();
});
} }
}, },
@ -203,7 +208,7 @@ export default {
if (ongoingTask) { if (ongoingTask) {
// There is a started task // There is a started task
this.taskStarted = true; this.taskStarted = true;
this.$emit("taskStarted"); eventBus.emit("taskStarted");
// Find its URL // Find its URL
const taskUrl = ongoingTask.links.find((t) => t.rel == "self").href; const taskUrl = ongoingTask.links.find((t) => t.rel == "self").href;
this.startPollingTask(ongoingTask.id, taskUrl); this.startPollingTask(ongoingTask.id, taskUrl);
@ -226,10 +231,10 @@ export default {
async startTask() { async startTask() {
// Starts a new Action task // Starts a new Action task
this.$emit("submit", this.submitData); eventBus.emit("submit", this.submitData);
// Send a request to start a task // Send a request to start a task
this.taskStarted = true; this.taskStarted = true;
this.$emit("taskStarted"); eventBus.emit("taskStarted");
let response; let response;
try { try {
response = await this.invokeAction( response = await this.invokeAction(
@ -239,7 +244,7 @@ export default {
false, // Stop invokeAction handling the error. false, // Stop invokeAction handling the error.
); );
} catch (error) { } catch (error) {
this.$emit("error", error); eventBus.emit("error", error);
this.onTaskEnd(); this.onTaskEnd();
return; return;
} }
@ -257,7 +262,7 @@ export default {
this.taskUrl = taskUrl; this.taskUrl = taskUrl;
// Start the store polling TaskId for success // Start the store polling TaskId for success
this.taskRunning = true; this.taskRunning = true;
this.$emit("taskRunning", taskId); eventBus.emit("taskRunning", taskId);
this.pollUntilComplete( this.pollUntilComplete(
taskUrl, taskUrl,
this.onPollingResponse, this.onPollingResponse,
@ -271,17 +276,17 @@ export default {
this.taskStatus = response.data.status; this.taskStatus = response.data.status;
this.log = response.data.log; this.log = response.data.log;
if (response.data.status == "completed") { if (response.data.status == "completed") {
this.$emit("response", response.data); eventBus.emit("response", response.data);
this.$emit("completed", response.data.output); eventBus.emit("completed", response.data.output);
} else if (response.data.status == "cancelled") { } else if (response.data.status == "cancelled") {
this.$emit("cancelled", response.data); eventBus.emit("cancelled", response.data);
this.modalNotify(`The action '${this.submitLabel}' was cancelled.`); this.modalNotify(`The action '${this.submitLabel}' was cancelled.`);
} }
} }
this.taskUrl = null; this.taskUrl = null;
this.taskRunning = false; this.taskRunning = false;
this.taskStarted = false; this.taskStarted = false;
this.$emit("finished"); eventBus.emit("finished");
}, },
onPollingResponse(response) { onPollingResponse(response) {

View file

@ -75,7 +75,7 @@ export default {
}, },
hide() { hide() {
UIkit.modal(this.$refs.modal).hide(); UIkit.modal(this.$refs.modal).hide();
this.$root.$emit("modalClosed"); eventBus.emit("modalClosed");
}, },
}, },
}; };

View file

@ -40,7 +40,7 @@ export default {
}, },
afterAutofocus() { afterAutofocus() {
this.isAutofocusing = false; this.isAutofocusing = false;
this.$root.$emit("globalUpdatePositionEvent"); eventBus.emit("globalUpdatePositionEvent");
}, },
}, },
}; };

View file

@ -63,6 +63,7 @@ import syncPropertyButton from "../../labThingsComponents/syncPropertyButton.vue
import stageControlButtons from "./stageControlButtons.vue"; import stageControlButtons from "./stageControlButtons.vue";
// vue3 migration // vue3 migration
import { markRaw } from "vue"; import { markRaw } from "vue";
import { eventBus } from "../../../eventBus.js";
export default { export default {
name: "PaneControl", name: "PaneControl",
@ -89,20 +90,20 @@ export default {
async mounted() { async mounted() {
let self = this; let self = this;
// A global signal listener to perform a move action // A global signal listener to perform a move action
this.$root.$on("globalMoveEvent", self.move); eventBus.on("globalMoveEvent", self.move);
this.$root.$on("globalUpdatePositionEvent", self.updatePosition); eventBus.on("globalUpdatePositionEvent", self.updatePosition);
// A global signal listener to perform a move action in pixels // A global signal listener to perform a move action in pixels
this.$root.$on("globalMoveInImageCoordinatesEvent", (x, y, absolute) => { eventBus.on("globalMoveInImageCoordinatesEvent", (x, y, absolute) => {
this.moveInImageCoordinatesRequest(x, y, absolute); this.moveInImageCoordinatesRequest(x, y, absolute);
}); });
// A global signal listener to perform a move in multiples of a step size // A global signal listener to perform a move in multiples of a step size
this.$root.$on("globalMoveStepEvent", (x_steps, y_steps, z_steps) => { eventBus.on("globalMoveStepEvent", (x_steps, y_steps, z_steps) => {
const navigationStepSize = this.$store.state.navigationStepSize; const navigationStepSize = this.$store.state.navigationStepSize;
const navigationInvert = this.$store.state.navigationInvert; const navigationInvert = this.$store.state.navigationInvert;
const x = x_steps * navigationStepSize.x * (navigationInvert.x ? -1 : 1); const x = x_steps * navigationStepSize.x * (navigationInvert.x ? -1 : 1);
const y = y_steps * navigationStepSize.y * (navigationInvert.y ? -1 : 1); const y = y_steps * navigationStepSize.y * (navigationInvert.y ? -1 : 1);
const z = z_steps * navigationStepSize.z * (navigationInvert.z ? -1 : 1); const z = z_steps * navigationStepSize.z * (navigationInvert.z ? -1 : 1);
this.$root.$emit("globalMoveEvent", x, y, z, false); eventBus.emit("globalMoveEvent", x, y, z, false);
}); });
// Update the current position in text boxes // Update the current position in text boxes
await this.updatePosition(); await this.updatePosition();
@ -110,10 +111,10 @@ export default {
beforeUnmount() { beforeUnmount() {
// Remove global signal listener to perform a move action // Remove global signal listener to perform a move action
this.$root.$off("globalMoveEvent"); eventBus.off("globalMoveEvent");
this.$root.$off("globalMoveInImageCoordinatesEvent"); eventBus.off("globalMoveInImageCoordinatesEvent");
this.$root.$off("globalMoveStepEvent"); eventBus.off("globalMoveStepEvent");
this.$root.$off("globalUpdatePositionEvent"); eventBus.off("globalUpdatePositionEvent");
}, },
methods: { methods: {

View file

@ -41,7 +41,7 @@ export default {
name: "StageControlButtons", name: "StageControlButtons",
methods: { methods: {
move(x, y, z) { move(x, y, z) {
this.$root.$emit("globalMoveStepEvent", x, y, z); eventBus.emit("globalMoveStepEvent", x, y, z);
}, },
}, },
}; };

View file

@ -102,6 +102,7 @@ import scanCard from "./scanListComponents/scanCard.vue";
import ScanViewerModal from "./scanListComponents/scanViewer.vue"; import ScanViewerModal from "./scanListComponents/scanViewer.vue";
// vue3 migration // vue3 migration
import { markRaw } from "vue"; import { markRaw } from "vue";
import { eventBus } from "../../eventBus.js";
// Export main app // Export main app
export default { export default {
@ -150,10 +151,10 @@ export default {
// Update on mount (does nothing if not connected) // Update on mount (does nothing if not connected)
await this.updateScans(); await this.updateScans();
// A global signal listener to perform a gallery refresh // A global signal listener to perform a gallery refresh
this.$root.$on("globalUpdateScans", () => { eventBus.on("globalUpdateScans", () => {
this.updateScans(); this.updateScans();
}); });
this.$root.$on("modalClosed", () => { eventBus.on("modalClosed", () => {
// Handle the modal closed event here // Handle the modal closed event here
this.updateScans(); this.updateScans();
}); });
@ -179,13 +180,13 @@ export default {
beforeUnmount() { beforeUnmount() {
// Remove global signal listener to perform a gallery refresh // Remove global signal listener to perform a gallery refresh
this.$root.$off("globalUpdateScans"); eventBus.off("globalUpdateScans");
// Then we call that function here to unwatch // Then we call that function here to unwatch
if (this.unwatchStoreFunction) { if (this.unwatchStoreFunction) {
this.unwatchStoreFunction(); this.unwatchStoreFunction();
this.unwatchStoreFunction = null; this.unwatchStoreFunction = null;
} }
this.$root.$off("modalClosed"); // Clean up event listener eventBus.off("modalClosed"); // Clean up event listener
}, },
methods: { methods: {

View file

@ -35,6 +35,9 @@
</template> </template>
<script> <script>
// vue3 migration
import { eventBus } from "../../eventBus.js";
// Export main app // Export main app
export default { export default {
name: "StreamDisplay", name: "StreamDisplay",
@ -63,7 +66,7 @@ export default {
mounted() { mounted() {
// A global signal listener to flash the stream element // A global signal listener to flash the stream element
this.$root.$on("globalFlashStream", () => { eventBus.on("globalFlashStream", () => {
this.flashStream(); this.flashStream();
}); });
@ -83,9 +86,9 @@ export default {
beforeUnmount: function () { beforeUnmount: function () {
// Remove global signal listener to change the GPU preview state // Remove global signal listener to change the GPU preview state
this.$root.$off("globalTogglePreview"); eventBus.off("globalTogglePreview");
// Remove global signal listener to flash the stream element // Remove global signal listener to flash the stream element
this.$root.$off("globalFlashStream"); eventBus.off("globalFlashStream");
// Disconnect the size observer // Disconnect the size observer
this.sizeObserver.disconnect(); this.sizeObserver.disconnect();
// Remove from the array of active streams // Remove from the array of active streams
@ -126,7 +129,7 @@ export default {
let yRelative = (0.5 * event.target.offsetHeight - yCoordinate) * scale; let yRelative = (0.5 * event.target.offsetHeight - yCoordinate) * scale;
// Emit a signal to move, acted on by paneControl.vue // Emit a signal to move, acted on by paneControl.vue
this.$root.$emit("globalMoveInImageCoordinatesEvent", -xRelative, -yRelative); eventBus.emit("globalMoveInImageCoordinatesEvent", -xRelative, -yRelative);
}, },
handleResize: function () { handleResize: function () {

3
webapp/src/eventBus.js Normal file
View file

@ -0,0 +1,3 @@
import mitt from "mitt";
export const eventBus = mitt();