AzuraCast/frontend/vue/components/Common/StreamingLogView.vue

104 lines
2.2 KiB
Vue

<template>
<b-overlay
variant="card"
:show="loading"
>
<b-form-group label-for="modal_scroll_to_bottom">
<b-form-checkbox
id="modal_scroll_to_bottom"
v-model="scrollToBottom"
>
{{ $gettext('Automatically Scroll to Bottom') }}
</b-form-checkbox>
</b-form-group>
<textarea
id="log-view-contents"
ref="$textarea"
class="form-control log-viewer"
spellcheck="false"
readonly
:value="logs"
/>
</b-overlay>
</template>
<script setup>
import {nextTick, ref, toRef, watch} from "vue";
import {useAxios} from "~/vendor/axios";
import {tryOnScopeDispose} from "@vueuse/core";
const props = defineProps({
logUrl: {
type: String,
required: true,
}
});
const loading = ref(false);
const logs = ref('');
const currentLogPosition = ref(null);
const scrollToBottom = ref(true);
const {axios} = useAxios();
const $textarea = ref(); // Template Ref
let updateInterval = null;
const stop = () => {
if (updateInterval) {
clearInterval(updateInterval);
}
};
tryOnScopeDispose(stop);
const updateLogs = () => {
axios({
method: 'GET',
url: props.logUrl,
params: {
position: currentLogPosition.value
}
}).then((resp) => {
if (resp.data.contents !== '') {
logs.value = logs.value + resp.data.contents + "\n";
if (scrollToBottom.value) {
nextTick(() => {
$textarea.value.scrollTop = $textarea.value.scrollHeight;
});
}
}
currentLogPosition.value = resp.data.position;
if (resp.data.eof) {
stop();
}
}).finally(() => {
loading.value = false;
});
};
watch(toRef(props, 'logUrl'), (newLogUrl) => {
loading.value = true;
logs.value = '';
currentLogPosition.value = 0;
stop();
if (null !== newLogUrl) {
updateInterval = setInterval(updateLogs, 2500);
updateLogs();
}
}, {immediate: true});
const getContents = () => {
return logs.value;
};
defineExpose({
getContents
});
</script>