get system status with sse
This commit is contained in:
parent
52411f61ef
commit
5f203a809b
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -28,4 +28,7 @@
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"cSpell.words": [
|
||||
"nuxt"
|
||||
],
|
||||
}
|
||||
|
12
components/EventStatus.vue
Normal file
12
components/EventStatus.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div class="flex items-center ps-4 pe-1">
|
||||
<div
|
||||
class="w-2 h-2 rounded-full"
|
||||
:class="indexStore.sseConnected ? 'bg-success shadow shadow-success' : 'bg-error shadow shadow-error'"
|
||||
:title="indexStore.sseConnected ? $t('socketConnected') : $t('socketDisconnected')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const indexStore = useIndex()
|
||||
</script>
|
@ -3,6 +3,7 @@
|
||||
<NuxtLink class="navbar-brand min-w-[46px] p-2" href="/">
|
||||
<img src="~/assets/images/ffplayout-small.png" class="img-fluid" alt="Logo" width="30" height="30" />
|
||||
</NuxtLink>
|
||||
<EventStatus class="z-10"/>
|
||||
<div class="navbar-end w-1/5 grow">
|
||||
<label class="swap swap-rotate me-2 md:hidden">
|
||||
<input type="checkbox" :checked="indexStore.darkMode" @change="toggleDarkTheme" />
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="grid grid-cols-1 xs:grid-cols-2 border-4 rounded-md border-primary text-left shadow max-w-[960px]">
|
||||
<!-- <div v-if="data">{{ systemStatus(data) }}</div> -->
|
||||
<div class="grid grid-cols-1 xs:grid-cols-2 border-4 rounded-md border-primary text-left shadow min-w-[728px] max-w-[960px]">
|
||||
<div class="p-4 bg-base-100">
|
||||
<span class="text-3xl">{{ sysStat.system.name }} {{ sysStat.system.version }}</span>
|
||||
<span v-if="sysStat.system.kernel">
|
||||
@ -92,51 +93,67 @@ const { fileSize } = stringFormatter()
|
||||
|
||||
const authStore = useAuth()
|
||||
const configStore = useConfig()
|
||||
const timer = ref()
|
||||
const sysStat = ref({
|
||||
cpu: { cores: 0.0, usage: 0.0 },
|
||||
const indexStore = useIndex()
|
||||
|
||||
const streamUrl = ref(
|
||||
`/data/event/${configStore.configGui[configStore.configID].id}?endpoint=system&uuid=${authStore.uuid}`
|
||||
)
|
||||
|
||||
// 'http://127.0.0.1:8787/data/event/1?endpoint=system&uuid=f2f8c29b-712a-48c5-8919-b535d3a05a3a'
|
||||
const { status, data, error, close } = useEventSource(streamUrl, [], {
|
||||
autoReconnect: {
|
||||
retries: -1,
|
||||
delay: 1000,
|
||||
onFailed() {
|
||||
indexStore.sseConnected = false
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const errorCounter = ref(0)
|
||||
const defaultStat = {
|
||||
cpu: { cores: 1, usage: 0.0 },
|
||||
load: { one: 0.0, five: 0.0, fifteen: 0.0 },
|
||||
memory: { total: 0.0, used: 0.0, free: 0.0 },
|
||||
network: { name: '', current_in: 0.0, current_out: 0.0, total_in: 0.0, total_out: 0.0 },
|
||||
network: { name: '...', current_in: 0.0, current_out: 0.0, total_in: 0.0, total_out: 0.0 },
|
||||
storage: { path: '', total: 0.0, used: 0.0 },
|
||||
swap: { total: 0.0, used: 0.0, free: 0.0 },
|
||||
system: { name: '', kernel: '', version: '', ffp_version: '' },
|
||||
} as SystemStatistics)
|
||||
system: { name: '...', kernel: '...', version: '...', ffp_version: '...' },
|
||||
} as SystemStatistics
|
||||
|
||||
onMounted(() => {
|
||||
status()
|
||||
})
|
||||
const sysStat = ref(defaultStat)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (timer.value) {
|
||||
clearTimeout(timer.value)
|
||||
close()
|
||||
indexStore.sseConnected = false
|
||||
})
|
||||
|
||||
watch([status, error], async () => {
|
||||
if (status.value === 'OPEN') {
|
||||
indexStore.sseConnected = true
|
||||
errorCounter.value = 0
|
||||
} else {
|
||||
indexStore.sseConnected = false
|
||||
errorCounter.value += 1
|
||||
sysStat.value = defaultStat
|
||||
|
||||
if (errorCounter.value > 15) {
|
||||
await authStore.obtainUuid()
|
||||
streamUrl.value = `/data/event/${configStore.configGui[configStore.configID].id}?endpoint=system&uuid=${
|
||||
authStore.uuid
|
||||
}`
|
||||
errorCounter.value = 0
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
async function status() {
|
||||
systemStatus()
|
||||
|
||||
async function setStatus(resolve: any) {
|
||||
/*
|
||||
recursive function as a endless loop
|
||||
*/
|
||||
systemStatus()
|
||||
|
||||
timer.value = setTimeout(() => setStatus(resolve), 1000)
|
||||
watch([data], () => {
|
||||
if (data.value) {
|
||||
try {
|
||||
sysStat.value = JSON.parse(data.value)
|
||||
} catch (_) {
|
||||
indexStore.sseConnected = true
|
||||
}
|
||||
}
|
||||
return new Promise((resolve) => setStatus(resolve))
|
||||
}
|
||||
|
||||
async function systemStatus() {
|
||||
const channel = configStore.configGui[configStore.configID].id
|
||||
|
||||
if (!document?.hidden) {
|
||||
await $fetch<SystemStatistics>(`/api/system/${channel}`, {
|
||||
method: 'GET',
|
||||
headers: { ...configStore.contentType, ...authStore.authHeader },
|
||||
}).then((stat) => {
|
||||
sysStat.value = stat
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
22
error.vue
22
error.vue
@ -28,16 +28,16 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
const statusCode = props.error?.statusCode || 400
|
||||
// onMounted(() => {
|
||||
// const statusCode = props.error?.statusCode || 400
|
||||
|
||||
if (statusCode >= 400) {
|
||||
setTimeout(() => {
|
||||
reloadNuxtApp({
|
||||
path: localePath({ name: 'index' }),
|
||||
ttl: 1000,
|
||||
})
|
||||
}, 3000)
|
||||
}
|
||||
})
|
||||
// if (statusCode >= 400) {
|
||||
// setTimeout(() => {
|
||||
// reloadNuxtApp({
|
||||
// path: localePath({ name: 'index' }),
|
||||
// ttl: 1000,
|
||||
// })
|
||||
// }, 3000)
|
||||
// }
|
||||
// })
|
||||
</script>
|
||||
|
@ -1,6 +1,8 @@
|
||||
export default {
|
||||
ok: 'Ok',
|
||||
cancel: 'Abbrechen',
|
||||
socketConnected: 'Event Stream verbunden',
|
||||
socketDisconnected: 'Event Stream nicht verbunden',
|
||||
alert: {
|
||||
wrongLogin: 'Falsche Anmeldedaten!',
|
||||
},
|
||||
|
@ -1,6 +1,8 @@
|
||||
export default {
|
||||
ok: 'Ok',
|
||||
cancel: 'Cancel',
|
||||
socketConnected: 'Event stream connected',
|
||||
socketDisconnected: 'Event stream disconnected',
|
||||
alert: {
|
||||
wrongLogin: 'Incorrect login data!',
|
||||
},
|
||||
|
@ -1,6 +1,8 @@
|
||||
export default {
|
||||
ok: 'Ok',
|
||||
cancel: 'Cancelar',
|
||||
socketConnected: 'Event stream conectado',
|
||||
socketDisconnected: 'Event stream desconectado',
|
||||
alert: {
|
||||
wrongLogin: 'Dados incorretos!',
|
||||
},
|
||||
|
@ -9,6 +9,7 @@ export default defineNuxtConfig({
|
||||
devProxy: {
|
||||
'/api': { target: 'http://127.0.0.1:8787/api' },
|
||||
'/auth': { target: 'http://127.0.0.1:8787/auth' },
|
||||
'/data': { target: 'http://127.0.0.1:8787/data' },
|
||||
'/live': { target: 'http://127.0.0.1:8787/live' },
|
||||
'/file': { target: 'http://127.0.0.1:8787/file' },
|
||||
},
|
||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ffplayout-frontend",
|
||||
"version": "0.8.1",
|
||||
"version": "0.9.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ffplayout-frontend",
|
||||
"version": "0.8.1",
|
||||
"version": "0.9.0",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@nuxtjs/color-mode": "^3.4.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ffplayout-frontend",
|
||||
"version": "0.8.1",
|
||||
"version": "0.9.0",
|
||||
"description": "Web GUI for ffplayout",
|
||||
"author": "Jonathan Baecker",
|
||||
"private": true,
|
||||
|
@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<div class="w-full min-h-screen xs:h-full flex justify-center items-center">
|
||||
<div v-if="authStore.isLogin" class="flex flex-wrap justify-center text-center w-full max-w-[1024px] p-5">
|
||||
<div class="absolute top-4 left-1">
|
||||
<EventStatus />
|
||||
</div>
|
||||
<SystemStats v-if="configStore.configGui.length > 0" />
|
||||
<div class="flex flex-wrap justify-center gap-1 md:gap-0 md:join mt-5">
|
||||
<NuxtLink :to="localePath({ name: 'player' })" class="btn join-item btn-primary px-2">
|
||||
|
@ -7,6 +7,7 @@ export const useAuth = defineStore('auth', {
|
||||
jwtToken: '',
|
||||
authHeader: {},
|
||||
role: '',
|
||||
uuid: null as null | string,
|
||||
}),
|
||||
|
||||
getters: {},
|
||||
@ -56,6 +57,19 @@ export const useAuth = defineStore('auth', {
|
||||
return code
|
||||
},
|
||||
|
||||
async obtainUuid() {
|
||||
await $fetch<DataAuth>('/api/generate-uuid', {
|
||||
method: 'POST',
|
||||
headers: this.authHeader,
|
||||
})
|
||||
.then((response) => {
|
||||
this.uuid = response.uuid
|
||||
})
|
||||
.catch(() => {
|
||||
this.uuid = null
|
||||
})
|
||||
},
|
||||
|
||||
inspectToken() {
|
||||
const token = useCookie('token').value
|
||||
|
||||
|
@ -23,6 +23,7 @@ export const useConfig = defineStore('config', {
|
||||
authStore.inspectToken()
|
||||
|
||||
if (authStore.isLogin) {
|
||||
await authStore.obtainUuid()
|
||||
await this.getGuiConfig()
|
||||
await this.getPlayoutConfig()
|
||||
await this.getUserConfig()
|
||||
|
@ -6,6 +6,7 @@ export const useIndex = defineStore('index', {
|
||||
showAlert: false,
|
||||
alertVariant: 'success',
|
||||
alertMsg: '',
|
||||
sseConnected: false,
|
||||
}),
|
||||
|
||||
getters: {},
|
||||
|
4
types/index.d.ts
vendored
4
types/index.d.ts
vendored
@ -17,6 +17,10 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
interface DataAuth {
|
||||
uuid: string
|
||||
}
|
||||
|
||||
interface GuiConfig {
|
||||
id: number
|
||||
config_path: string
|
||||
|
Loading…
Reference in New Issue
Block a user