-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
379 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,181 @@ | ||
<template> | ||
<div class="text-grey-lighten-1 text-body-2"> | ||
<p class="mb-3"> | ||
VatIRIS is an interpretation of its real-world counterpart | ||
<a href="https://www.awos.se/sv-se/products/iris.aspx" target="_blank">IRIS</a> - | ||
Integrated Real-time Information System, but adapted and extended for use by VATSIM | ||
controllers in Sweden. | ||
</p> | ||
<p>It's currently under heavy development, so please expect bugs.</p> | ||
<p> | ||
Welcome to file bug reports or feature requests as | ||
<a href="https://github.com/minsulander/vatiris/issues" target="_blank">issues</a> | ||
</p> | ||
<p class="mt-3" v-if="auth.user"> | ||
Logged in as {{ auth.user.personal.name_full }}, {{ auth.user.cid }}, | ||
{{ auth.user.vatsim.rating.short }} | ||
<span v-if="auth.user.vatsim.subdivision && auth.user.vatsim.subdivision.name"> | ||
from {{ auth.user.vatsim.subdivision.name }}</span | ||
> | ||
<span v-else-if="auth.user.vatsim.division && auth.user.vatsim.division.name"> | ||
from {{ auth.user.vatsim.division.name }}</span | ||
> | ||
</p> | ||
<p class="mt-3"> | ||
<router-link class="text-grey-darken-1" to="privacy">Privacy policy</router-link> | ||
</p> | ||
<p class="text-grey-darken-1 mt-3"> | ||
Copyright © 2024 Martin Insulander and contributors | ||
</p> | ||
<p class="mt-3"> | ||
<a | ||
class="text-grey-darken-1" | ||
href="https://github.com/minsulander/vatiris" | ||
target="_blank" | ||
><v-icon>mdi-github</v-icon> VatIRIS on GitHub</a | ||
> | ||
</p> | ||
<p class="mb-3"> | ||
VatIRIS is an interpretation of its real-world counterpart | ||
<a href="https://www.awos.se/sv-se/products/iris.aspx" target="_blank">IRIS</a> - | ||
Integrated Real-time Information System, but adapted and extended for use by VATSIM | ||
controllers in Sweden. | ||
</p> | ||
<p>It's currently under heavy development, so please expect bugs.</p> | ||
<p> | ||
Welcome to file bug reports or feature requests as | ||
<a href="https://github.com/minsulander/vatiris/issues" target="_blank">issues</a> | ||
</p> | ||
<p class="mt-3" v-if="auth.user"> | ||
Logged in as {{ auth.user.personal.name_full }}, {{ auth.user.cid }}, | ||
{{ auth.user.vatsim.rating.short }} | ||
<span v-if="auth.user.vatsim.subdivision && auth.user.vatsim.subdivision.name"> | ||
from {{ auth.user.vatsim.subdivision.name }}</span | ||
> | ||
<span v-else-if="auth.user.vatsim.division && auth.user.vatsim.division.name"> | ||
from {{ auth.user.vatsim.division.name }}</span | ||
> | ||
</p> | ||
<p class="mt-3"> | ||
<router-link class="text-grey-darken-1" to="privacy">Privacy policy</router-link> | ||
</p> | ||
<p class="text-grey-darken-1 mt-3"> | ||
Copyright © 2024 Martin Insulander and contributors | ||
</p> | ||
<p class="mt-3"> | ||
<a | ||
class="text-grey-darken-1" | ||
href="https://github.com/minsulander/vatiris" | ||
target="_blank" | ||
><v-icon>mdi-github</v-icon> VatIRIS on GitHub</a | ||
> | ||
</p> | ||
|
||
<!-- New buttons for selecting logic --> | ||
<div class="mt-3"> | ||
Set PLS Logic | ||
<v-btn | ||
:color="logic === 'cid' ? 'primary' : 'default'" | ||
@click="setLogic('cid')" | ||
class="mr-2" | ||
> | ||
CID | ||
</v-btn> | ||
<v-btn | ||
:color="logic === 'position' ? 'primary' : 'default'" | ||
@click="setLogic('position')" | ||
> | ||
Position | ||
</v-btn> | ||
</div> | ||
|
||
<!-- CID logic --> | ||
<div v-if="logic === 'cid'" class="mt-3"> | ||
<v-checkbox | ||
v-model="useVatsimCid" | ||
label="Use VATSIM connect CID" | ||
@change="handleCidOption" | ||
></v-checkbox> | ||
<div v-if="!useVatsimCid"> | ||
<v-text-field | ||
label="CID 1" | ||
v-model="manualCid1" | ||
outlined | ||
dense | ||
></v-text-field> | ||
<v-text-field | ||
label="CID 2" | ||
v-model="manualCid2" | ||
outlined | ||
dense | ||
></v-text-field> | ||
</div> | ||
</div> | ||
|
||
<!-- Position logic --> | ||
<div v-if="logic === 'position'" class="mt-3"> | ||
<v-text-field | ||
label="Position 1" | ||
v-model="pos1" | ||
outlined | ||
dense | ||
></v-text-field> | ||
<v-text-field | ||
label="Position 2" | ||
v-model="pos2" | ||
outlined | ||
dense | ||
></v-text-field> | ||
</div> | ||
|
||
<!-- Apply button --> | ||
<v-btn color="success" class="mt-3" @click="applyLogic">Apply</v-btn> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { useAuthStore } from "@/stores/auth" | ||
const auth = useAuthStore() | ||
</script> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { ref, watch } from "vue" | ||
import { useAuthStore } from "@/stores/auth" | ||
import axios from "axios" | ||
import useEventBus from "@/eventbus" | ||
const auth = useAuthStore() | ||
const bus = useEventBus() // Event bus instance | ||
// Reactive state variables | ||
const logic = ref("cid") // Default logic set to 'cid' | ||
const pos1 = ref("") | ||
const pos2 = ref("") | ||
const useVatsimCid = ref(true) // Default checkbox state is checked | ||
const manualCid1 = ref("") | ||
const manualCid2 = ref("") | ||
// Method to handle logic selection | ||
const setLogic = (selectedLogic: string) => { | ||
logic.value = selectedLogic | ||
console.log(`Selected logic: ${selectedLogic}`) | ||
// Reset relevant fields when logic changes | ||
if (selectedLogic === "cid") { | ||
useVatsimCid.value = true | ||
manualCid1.value = "" | ||
manualCid2.value = "" | ||
} else if (selectedLogic === "position") { | ||
pos1.value = "" | ||
pos2.value = "" | ||
} | ||
} | ||
// Method to handle checkbox change | ||
const handleCidOption = () => { | ||
if (useVatsimCid.value) { | ||
manualCid1.value = "" | ||
manualCid2.value = "" | ||
} | ||
} | ||
// Method to apply the logic selection and emit the event | ||
const applyLogic = () => { | ||
let type = logic.value.toUpperCase() | ||
let value = [] | ||
if (logic.value === "cid") { | ||
if (useVatsimCid.value) { | ||
// Use VATSIM CID from auth store | ||
value = [auth.user.cid] | ||
} else { | ||
// Use manually entered CIDs | ||
value = [manualCid1.value, manualCid2.value].filter(v => v) | ||
} | ||
} else if (logic.value === "position") { | ||
// Use positions | ||
value = [pos1.value, pos2.value].filter(v => v) | ||
} | ||
// Emit an event to notify PLSTimer.vue of the updated logic | ||
bus.emit("logicChanged", { type, value }) | ||
console.log(`Logic applied: type=${type}, value=${value}`) | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
.mt-3 { | ||
margin-top: 1rem; | ||
} | ||
.mr-2 { | ||
margin-right: 0.5rem; | ||
} | ||
h2 { | ||
font-size: 1.5rem; | ||
margin-bottom: 0.5rem; | ||
} | ||
</style> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
<template> | ||
<div> | ||
<span v-if="loading">-</span> | ||
<span v-else-if="matchedControllers.length > 0"> | ||
( PLS: {{ sessionLength }} ) | ||
</span> | ||
<span v-else>( PLS: NIL )</span> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { ref, onMounted, onBeforeUnmount } from "vue" | ||
import axios from "axios" | ||
import moment from "moment" | ||
import useEventBus from "@/eventbus" | ||
// Reactive data | ||
const searchType = ref("CID") // Default to "CID" | ||
const searchValue = ref([]) // Array of CIDs or positions to search for | ||
const sessionLength = ref("00:00:00") | ||
const matchedControllers = ref([]) | ||
const matchedGroup = ref("") // Tracks which group the matched controller belongs to | ||
const loading = ref(true) // To track the loading state | ||
let intervalId = null // To keep track of the setInterval ID | ||
let refreshIntervalId = null // To keep track of the 10-second refresh interval | ||
const bus = useEventBus() // Event bus instance | ||
// Function to fetch and filter controllers | ||
async function fetchSessionData() { | ||
loading.value = true // Set loading to true when fetching data | ||
try { | ||
const response = await axios.get("http://localhost:3001/api/controllers") | ||
const controllers = [ | ||
...response.data.activeControllers, | ||
...response.data.availableControllers, | ||
...response.data.awayControllers, | ||
] | ||
// Reset the matched group and controllers | ||
matchedControllers.value = [] | ||
matchedGroup.value = "" | ||
// Filter controllers based on selected CID or Position | ||
if (searchType.value === "CID") { | ||
// Check activeControllers | ||
matchedControllers.value = response.data.activeControllers.filter(controller => | ||
searchValue.value.includes(controller.CID) | ||
) | ||
if (matchedControllers.value.length > 0) { | ||
matchedGroup.value = "active" | ||
} else { | ||
// Check availableControllers if no match in active | ||
matchedControllers.value = response.data.availableControllers.filter(controller => | ||
searchValue.value.includes(controller.CID) | ||
) | ||
if (matchedControllers.value.length > 0) { | ||
matchedGroup.value = "available" | ||
} else { | ||
// Check awayControllers if no match in active or available | ||
matchedControllers.value = response.data.awayControllers.filter(controller => | ||
searchValue.value.includes(controller.CID) | ||
) | ||
if (matchedControllers.value.length > 0) { | ||
matchedGroup.value = "away" | ||
} | ||
} | ||
} | ||
} else { | ||
// Check for position match in all controller groups | ||
matchedControllers.value = response.data.activeControllers.filter(controller => | ||
searchValue.value.includes(controller.position) | ||
) | ||
if (matchedControllers.value.length > 0) { | ||
matchedGroup.value = "active" | ||
} else { | ||
matchedControllers.value = response.data.availableControllers.filter(controller => | ||
searchValue.value.includes(controller.position) | ||
) | ||
if (matchedControllers.value.length > 0) { | ||
matchedGroup.value = "available" | ||
} else { | ||
matchedControllers.value = response.data.awayControllers.filter(controller => | ||
searchValue.value.includes(controller.position) | ||
) | ||
if (matchedControllers.value.length > 0) { | ||
matchedGroup.value = "away" | ||
} | ||
} | ||
} | ||
} | ||
// Calculate the session length if a match is found | ||
if (matchedControllers.value.length > 0) { | ||
const timestamp = matchedControllers.value[0].timestamp | ||
const sessionStart = moment(timestamp) | ||
startUpdatingSessionLength(sessionStart) | ||
} else { | ||
sessionLength.value = "00:00:00" | ||
clearInterval(intervalId) | ||
} | ||
} catch (error) { | ||
console.error("Error fetching session data:", error) | ||
} finally { | ||
loading.value = false // Set loading to false after fetching data | ||
} | ||
} | ||
// Function to start updating session length in real-time | ||
function startUpdatingSessionLength(sessionStart) { | ||
if (intervalId) { | ||
clearInterval(intervalId) // Clear any existing interval before starting a new one | ||
} | ||
intervalId = setInterval(() => { | ||
const now = moment() | ||
const duration = moment.duration(now.diff(sessionStart)) | ||
let formattedTime = `${String(duration.hours()).padStart(2, "0")}:${String( | ||
duration.minutes() | ||
).padStart(2, "0")}:${String(duration.seconds()).padStart(2, "0")}` | ||
// Append "P" or "Ö" depending on the matched group | ||
if (matchedGroup.value === "available") { | ||
formattedTime += " P" | ||
} else if (matchedGroup.value === "away") { | ||
formattedTime += " \u00D6" // Append Unicode character "Ö" | ||
} | ||
sessionLength.value = formattedTime | ||
}, 1000) | ||
} | ||
// Function to set up auto-refresh every 10 seconds | ||
function startAutoRefresh() { | ||
if (refreshIntervalId) { | ||
clearInterval(refreshIntervalId) // Clear any existing refresh interval | ||
} | ||
refreshIntervalId = setInterval(() => { | ||
fetchSessionData() // Refresh data every 10 seconds | ||
}, 10000) | ||
} | ||
// Clear interval when component is unmounted | ||
onBeforeUnmount(() => { | ||
if (intervalId) { | ||
clearInterval(intervalId) | ||
} | ||
if (refreshIntervalId) { | ||
clearInterval(refreshIntervalId) | ||
} | ||
}) | ||
// Fetch data and start auto-refresh when component is mounted | ||
onMounted(() => { | ||
fetchSessionData() // Initial fetch | ||
startAutoRefresh() // Start auto-refresh every 10 seconds | ||
// Listen for the "refresh" event from the event bus | ||
bus.on("refresh", () => { | ||
fetchSessionData() // Fetch data immediately on refresh event | ||
}) | ||
// Listen for logic change event from About.vue | ||
bus.on("logicChanged", ({ type, value }) => { | ||
searchType.value = type | ||
searchValue.value = value | ||
fetchSessionData() // Fetch data based on the new logic | ||
}) | ||
}) | ||
</script> | ||
|
Oops, something went wrong.