247 lines
8.8 KiB
Vue
247 lines
8.8 KiB
Vue
<script setup lang="ts">
|
|
import { useLeafletStore } from 'stores/leaflet';
|
|
import type { Control, coords, CtrlAttr, CtrlAttrs } from 'components/models';
|
|
import { storeToRefs } from 'pinia';
|
|
import { socket } from 'boot/socketio';
|
|
import ConfirmCommandDialog from 'components/ConfirmCommandDiaglog.vue';
|
|
import { useQuasar } from 'quasar';
|
|
import { useRoute } from 'vue-router';
|
|
import { useSocketioStore } from 'stores/socketio';
|
|
import { ref } from 'vue';
|
|
import { favorites } from 'constants/favorites';
|
|
import { controls } from 'constants/controls';
|
|
|
|
const route = useRoute();
|
|
const $q = useQuasar();
|
|
|
|
const leafletStore = useLeafletStore();
|
|
const socketStore = useSocketioStore();
|
|
const { center, markerLatLng } = storeToRefs(leafletStore);
|
|
|
|
|
|
const { simulationRunning, simulationState, simulationQueueLength } = storeToRefs(socketStore);
|
|
|
|
const menuOpen = ref();
|
|
|
|
|
|
function handleFavClick(coords: coords) {
|
|
center.value = [coords.lat, coords.lng];
|
|
markerLatLng.value = [coords.lat, coords.lng];
|
|
}
|
|
|
|
function handleControlClick(cmdAttr: CtrlAttr) {
|
|
if (cmdAttr.cnfrm) {
|
|
$q.dialog({
|
|
component: ConfirmCommandDialog,
|
|
componentProps: {
|
|
name: cmdAttr.name,
|
|
},
|
|
})
|
|
.onOk(() => {
|
|
if (cmdAttr.cmdClass === 'simulation_control') {
|
|
try {
|
|
const ack = socketStore.simulationControl(cmdAttr.cmd, cmdAttr.delay);
|
|
$q.notify({ type: 'positive', message: ack });
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error('Simulation Command ERROR: ', error.message);
|
|
const ack = `Simulation Command Error: ${error.message}`;
|
|
$q.notify({ type: 'negative', message: ack });
|
|
} else {
|
|
console.error('Simmulation Command Error: ', error);
|
|
const ack = 'Simulation Command Error: Unknow error';
|
|
$q.notify({ type: 'negative', message: ack });
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ctrl.cmdClass === 'device_control') {
|
|
socket.emit('device_control', { command: ctrl.cmd, delay: 0 }, (response) => {
|
|
console.log(response.status, response.command);
|
|
});
|
|
}
|
|
})
|
|
.onCancel(() => {
|
|
console.log('Dialog cancelled');
|
|
})
|
|
.onDismiss(() => {
|
|
console.log('Dialog dismissed');
|
|
});
|
|
} else {
|
|
if (ctrl.cmdClass === 'simulation_control') {
|
|
try {
|
|
const response = socketStore.simulationControl(ctrl.cmd);
|
|
$q.notify({ type: 'positive', message: response });
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error('Error: ' + error.message);
|
|
$q.notify({ type: 'negative', message: error.toString() });
|
|
} else {
|
|
console.error('Error setting location:', error);
|
|
$q.notify({ type: 'negative', message: error.toString() });
|
|
}
|
|
}
|
|
}
|
|
if (ctrl.cmdClass === 'device_control') {
|
|
socket.emit('device_control', { command: ctrl.cmd, delay: 0 }, (response) => {
|
|
console.log(response.status, response.command);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<q-toolbar class="bg-primary text-white">
|
|
<q-btn @click="$emit('drawer')" flat round dense icon="menu" class="q-mr-sm" />
|
|
<q-separator dark inset />
|
|
<q-space />
|
|
<q-btn :icon-right="menuOpen ? 'arrow_drop_up' : 'arrow_drop_down'" stretch flat label="Favorites" v-if="route.name === 'Leaflet'">
|
|
<q-menu @show="menuOpen = true" @hide="menuOpen = false" anchor="bottom end" self="top end">
|
|
<q-list>
|
|
<template v-for="fav, index) in favorites" :key="index">
|
|
<q-item
|
|
v-if="fav.coords"
|
|
clickable
|
|
v-ripple
|
|
v-close-popup
|
|
@click="handleFavClick(fav.coords)"
|
|
>
|
|
<q-item-section avatar>
|
|
<q-avatar :icon="fav.icon" color="primary" text-color="white" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label>{{ fav.name }}</q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
<q-item v-else clickable v-ripple>
|
|
<q-item-section avatar>
|
|
<q-avatar :icon="fav.icon" color="primary" text-color="white" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label>{{ fav.name }}</q-item-label>
|
|
</q-item-section>
|
|
<q-item-section side>
|
|
<q-icon name="keyboard_arrow_right" />
|
|
</q-item-section>
|
|
<q-menu anchor="top end" self="top start">
|
|
<q-list>
|
|
<q-item
|
|
v-for="(f, indx) in fav.subitems"
|
|
:key="indx"
|
|
clickable
|
|
v-ripple
|
|
v-close-popup
|
|
@click="handleFavClick(f.coords)"
|
|
>
|
|
<q-item-section avatar>
|
|
<q-avatar :icon="f.icon" color="primary" text-color="white" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label>{{ f.name }}</q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
</q-list>
|
|
</q-menu>
|
|
</q-item>
|
|
</template>
|
|
</q-list>
|
|
</q-menu>
|
|
</q-btn>
|
|
<q-btn-dropdown stretch flat label="Controls">
|
|
<q-list>
|
|
<q-item-label header>Simulation Controls</q-item-label>
|
|
<q-item
|
|
v-if="!simulationRunning"
|
|
clickable
|
|
v-ripple
|
|
v-close-popup
|
|
@click="handleControlClick(controls.sim_start)">
|
|
<q-item-section avatar>
|
|
<q-avatar :icon="controls.sim_start.icon" color="primary" text-color="white" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label> {{ controls.sim_start.name }} </q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
<q-item
|
|
v-if="simulationState === 'RUNNING' && simulationRunning"
|
|
clickable
|
|
v-ripple
|
|
v-close-popup
|
|
@click="handleControlClick(controls.sim_pause)"
|
|
>
|
|
<q-item-section avatar>
|
|
<q-avatar :icon="controls.sim_pause.icon" color="primary" text-color="white" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label> {{ controls.sim_pause.name }} </q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
<q-item
|
|
v-if="simulationState === 'PAUSED'"
|
|
clickable
|
|
v-ripple
|
|
v-close-popup
|
|
@click="handleControlClick(controls.sim_resume)"
|
|
>
|
|
<q-item-section avatar>
|
|
<q-avatar :icon="controls.sim_resume.icon" color="primary" text-color="white" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label> {{ controls.sim_resume.name }} </q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
<q-item
|
|
v-if="simulationQueueLength > 0"
|
|
clickable
|
|
v-ripple
|
|
v-close-popup
|
|
@click="handleControlClick(controls.sim_clear)"
|
|
>
|
|
<q-item-section avatar>
|
|
<q-avatar :icon="controls.sim_clear.icon" color="primary" text-color="white" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label> {{ controls.sim_clear.name }} </q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
<q-item
|
|
v-if="simulationRunning"
|
|
clickable
|
|
v-ripple
|
|
v-close-popup
|
|
@click="handleControlClick(controls.sim_end)"
|
|
>
|
|
<q-item-section avatar>
|
|
<q-avatar :icon="controls.sim_end.icon" color="primary" text-color="white" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label> {{ controls.sim_end.name }} </q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
<q-separator spaced />
|
|
<q-item-label header>Device Controls</q-item-label>
|
|
<q-item clickable v-ripple v-close-popup @click="handleControlClick(controls.dev_reboot)">
|
|
<q-item-section avatar>
|
|
<q-avatar :icon="controls.dev_reboot.icon" color="primary" text-color="white" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label> {{ controls.dev_reboot.name }} </q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
<q-item clickable v-ripple v-close-popup @click="handleControlClick(controls.dev_shutdown)">
|
|
<q-item-section avatar>
|
|
<q-avatar :icon="controls.dev_shutdown.icon" color="primary" text-color="white" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label> {{ controls.dev_shutdown.name }} </q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
</q-list>
|
|
</q-btn-dropdown>
|
|
</q-toolbar>
|
|
</template>
|
|
|
|
<style scoped></style>
|