Added Run via console in tasks, added console WebUI and basic system report.

This commit is contained in:
abdulmohsen
2024-05-07 16:09:07 +03:00
parent 55145cc8fb
commit 8503178590
9 changed files with 452 additions and 19 deletions

127
frontend/pages/console.vue Normal file
View File

@@ -0,0 +1,127 @@
<template>
<div class="columns is-multiline">
<div class="column is-12 is-clearfix">
<span class="title is-4">
Console
</span>
<div class="subtitle is-6">
You can execute <strong>non-interactive</strong> commands here. The interface jailed to the <code>console</code>
command. You do not have to write <code>console</code> or <code>docker exec -ti watchstate console</code> here.
The majority of the commands will not show any output unless error has occurred or important information needs
to be communicated. To see all output, add <code>-vvv</code> to command.
</div>
</div>
<div class="column is-12">
<form @submit.prevent="RunCommand">
<div class="field is-grouped">
<p class="control is-expanded has-icons-left">
<input type="text" class="input" v-model="command" placeholder="system:view" autocomplete="off" autofocus
:disabled="isLoading">
<span class="icon is-small is-left">
<i class="fas fa-terminal"></i>
</span>
</p>
<p class="control">
<button class="button is-primary" type="submit" :disabled="isLoading" :class="{'is-loading':isLoading}">
<span class="icon-text">
<span class="icon">
<i class="fa fa-server"></i>
</span>
<span>Run</span>
</span>
</button>
</p>
<p class="control">
<button class="button is-info" type="button" v-tooltip="'Clear output'" @click="response = []">
<span class="icon">
<i class="fa fa-broom"></i>
</span>
</button>
</p>
<p class="control" v-if="isLoading">
<button class="button is-danger" type="button" @click="finished" v-tooltip="'Close connection.'">
<span class="icon">
<i class="fa fa-power-off"></i>
</span>
</button>
</p>
</div>
</form>
</div>
<div class="column is-12">
<pre ref="outputConsole" style="min-height: 60vh;max-height:80vh; overflow-y: scroll"
><code><span v-for="(item, index) in response" :key="'log_line-'+index" class="is-block">{{
item
}}</span></code></pre>
</div>
</div>
</template>
<script setup>
import {useStorage} from "@vueuse/core";
const fromTask = useRoute().query.task || '';
useHead({title: `Console`})
let sse;
const response = ref([]);
const command = ref('');
const isLoading = ref(false);
const outputConsole = ref();
const RunCommand = async () => {
response.value = []
const api_path = useStorage('api_path', '/v1/api')
const api_url = useStorage('api_url', '')
const api_token = useStorage('api_token', '')
const searchParams = new URLSearchParams();
searchParams.append('apikey', api_token.value);
searchParams.append('json', btoa(JSON.stringify({command: command.value})));
sse = new EventSource(`${api_url.value}${api_path.value}/system/command/?${searchParams.toString()}`);
isLoading.value = true;
sse.addEventListener('data', async e => {
let lines = e.data.split(/\n/g);
for (let x = 0; x < lines.length; x++) {
response.value.push(lines[x]);
}
});
sse.addEventListener('close', () => finished());
sse.onclose = () => finished();
sse.onerror = () => finished();
}
const finished = () => {
if (sse) {
sse.close();
}
isLoading.value = false;
}
onUpdated(() => outputConsole.value.scrollTop = outputConsole.value.scrollHeight);
onMounted(async () => {
if (!fromTask) {
await RunCommand();
return
}
const response = await request(`/tasks/${fromTask}`);
const json = await response.json();
command.value = `${json.command} ${json.args || ''}`;
await RunCommand();
});
</script>