refactor: rework async ToolLog

This commit is contained in:
axolotle 2024-08-13 00:30:09 +02:00
parent 732578156a
commit 27f87eeb17
2 changed files with 104 additions and 87 deletions

View file

@ -242,6 +242,33 @@ export type Firewall = {
} }
} }
// LOGS
export type LogInfo = {
description: string
name: string
metadata_path: string
metadata: {
ended_at: string | null
env: Obj
error: string | null
interface: 'cli' | 'api'
operation: string
parent: string | null
related_to: string[][]
started_at: string
success: boolean | '?'
yunohost_version: string
suboperations: {
name: string
description: string
success: boolean | '?'
}[]
}
log_path: string
logs: string[]
}
// DOMAINS // DOMAINS
export type DNSRecord = { export type DNSRecord = {

View file

@ -1,47 +1,34 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { useRouter } from 'vue-router'
import api, { objectToParams } from '@/api' import api, { objectToParams } from '@/api'
import type { APIQuery } from '@/api/api'
import { useInitialQueries } from '@/composables/useInitialQueries'
import { escapeHtml } from '@/helpers/commons' import { escapeHtml } from '@/helpers/commons'
import { readableDate } from '@/helpers/filters/date' import { readableDate } from '@/helpers/filters/date'
import type { LogInfo } from '@/types/core/api'
const props = defineProps<{ const props = withDefaults(
defineProps<{
name: string name: string
}>() n?: number
}>(),
{
n: 25,
},
)
const numberOfLines = ref(25) const router = useRouter()
const queries = computed<APIQuery[]>(() => {
const queryString = objectToParams({ const { description, logs, moreLogsAvailable, info } = await api
.fetch<LogInfo>({
uri: `logs/${props.name}?${objectToParams({
filter_irrelevant: '', filter_irrelevant: '',
with_suboperations: '', with_suboperations: '',
number: numberOfLines.value, number: props.n || 25,
})}`,
}) })
return [{ uri: `logs/${props.name}?${queryString}` }] .then((log) => {
})
const { loading, refetch } = useInitialQueries(queries, {
onQueriesResponse,
})
// Log data
const description = ref()
const info = ref({})
const logs = ref()
// Logs line display
const moreLogsAvailable = ref(false)
function onQueriesResponse(log: any) {
if (log.logs.length === numberOfLines.value) {
moreLogsAvailable.value = true
numberOfLines.value *= 10
} else {
moreLogsAvailable.value = false
}
description.value = log.description
const levels = ['ERROR', 'WARNING', 'SUCCESS', 'INFO'] const levels = ['ERROR', 'WARNING', 'SUCCESS', 'INFO']
logs.value = log.logs const logs = log.logs
.map((line) => { .map((line) => {
const escaped = escapeHtml(line) const escaped = escapeHtml(line)
for (const level of levels) { for (const level of levels) {
@ -54,15 +41,21 @@ function onQueriesResponse(log: any) {
return escaped return escaped
}) })
.join('\n') .join('\n')
// eslint-disable-next-line const { started_at, ended_at, error, suboperations } = log.metadata
const { started_at, ended_at, error, success, suboperations } = log.metadata return {
const info_ = { path: log.log_path, started_at, ended_at } description: log.description,
if (!success) info_.error = error logs,
if (suboperations && suboperations.length) info_.suboperations = suboperations moreLogsAvailable: log.logs.length === props.n || 25,
// eslint-disable-next-line info: {
if (!ended_at) delete info_.ended_at path: log.log_path,
info.value = info started_at: readableDate(started_at),
ended_at: ended_at ? readableDate(ended_at) : null,
error: error ? !!error : null,
suboperations:
suboperations && suboperations.length ? suboperations : null,
},
} }
})
function shareLogs() { function shareLogs() {
api api
@ -78,24 +71,21 @@ function shareLogs() {
</script> </script>
<template> <template>
<ViewBase :loading="loading" skeleton="CardInfoSkeleton"> <div>
<!-- INFO CARD --> <!-- INFO CARD -->
<YCard :title="description" icon="info-circle"> <YCard :title="description" icon="info-circle">
<BRow <template v-for="(value, prop) in info" :key="prop">
v-for="(value, prop) in info" <BRow v-if="value !== null" no-gutters class="row-line">
:key="prop"
no-gutters
class="row-line"
>
<BCol md="3" xl="2"> <BCol md="3" xl="2">
<strong>{{ $t('logs_' + prop) }}</strong> <strong>{{ $t('logs_' + prop) }}</strong>
</BCol> </BCol>
<BCol> <BCol>
<span v-if="prop.endsWith('_at')">{{ readableDate(value) }}</span> <div v-if="prop === 'suboperations'">
<div
<div v-else-if="prop === 'suboperations'"> v-for="operation in value as LogInfo['metadata']['suboperations']"
<div v-for="operation in value" :key="operation.name"> :key="operation.name"
>
<YIcon <YIcon
v-if="operation.success !== true" v-if="operation.success !== true"
iname="times" iname="times"
@ -112,6 +102,7 @@ function shareLogs() {
<span v-else>{{ value }}</span> <span v-else>{{ value }}</span>
</BCol> </BCol>
</BRow> </BRow>
</template>
</YCard> </YCard>
<div v-if="info.error" class="alert alert-danger my-5"> <div v-if="info.error" class="alert alert-danger my-5">
@ -129,9 +120,8 @@ function shareLogs() {
<BButton <BButton
v-if="moreLogsAvailable" v-if="moreLogsAvailable"
variant="white"
class="w-100 rounded-0" class="w-100 rounded-0"
@click="refetch(false)" @click="router.replace({ params: { n: props.n * 10 } })"
> >
<YIcon iname="plus" /> {{ $t('logs_more') }} <YIcon iname="plus" /> {{ $t('logs_more') }}
</BButton> </BButton>
@ -143,5 +133,5 @@ function shareLogs() {
</YCard> </YCard>
<p class="w-100 px-5 py-2 mb-0" v-html="$t('text_selection_is_disabled')" /> <p class="w-100 px-5 py-2 mb-0" v-html="$t('text_selection_is_disabled')" />
</ViewBase> </div>
</template> </template>