Log UI: progress indicator (#28914)

This commit is contained in:
Michael Geers 2026-04-07 16:51:28 +02:00 • committed by GitHub
parent c375354f08
commit e75b5e91a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 60 additions and 17 deletions

View file

@ -0,0 +1,52 @@
<template>
<svg
class="progressRing"
:style="{ '--duration': `${duration}ms`, ...svgStyle }"
viewBox="0 0 20 20"
>
<circle class="track" cx="10" cy="10" r="6" fill="none" stroke="currentColor" />
<circle class="bar" cx="10" cy="10" r="6" fill="none" stroke="currentColor" />
</svg>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import icon from "@/mixins/icon";
export default defineComponent({
name: "ProgressRing",
mixins: [icon],
props: {
duration: { type: Number, required: true },
},
});
</script>
<style scoped>
.progressRing {
background: transparent;
transform: rotate(-90deg);
}
.progressRing .track {
fill: none;
stroke: currentColor;
stroke-width: 2.5;
opacity: 0.25;
}
.progressRing .bar {
fill: none;
stroke: currentColor;
stroke-width: 2.5;
stroke-dasharray: 40;
stroke-dashoffset: 40;
animation: progressRing var(--duration, 10s) cubic-bezier(0.4, 0.1, 0.6, 0.9) forwards;
}
@keyframes progressRing {
from {
stroke-dashoffset: 40;
}
to {
stroke-dashoffset: 0;
}
}
</style>

View file

@ -15,11 +15,11 @@
<span class="text-nowrap text-truncate">
{{ $t("log.update") }}
</span>
<Record
<ProgressRing
v-if="autoFollow"
ref="spin"
class="spin flex-shrink-0"
:style="{ animationDuration: `${updateInterval}ms` }"
:key="tick"
class="flex-shrink-0"
:duration="updateInterval"
/>
<Play v-else class="flex-shrink-0 play" />
</button>
@ -110,7 +110,7 @@
import "@h2d2/shopicons/es/regular/download";
import Header from "../components/Top/Header.vue";
import Play from "../components/MaterialIcon/Play.vue";
import Record from "../components/MaterialIcon/Record.vue";
import ProgressRing from "../components/MaterialIcon/ProgressRing.vue";
import MultiSelect from "../components/Helper/MultiSelect.vue";
import api from "../api";
import store from "../store";
@ -126,7 +126,7 @@ export default defineComponent({
components: {
TopHeader: Header,
Play,
Record,
ProgressRing,
MultiSelect,
},
props: {
@ -141,6 +141,7 @@ export default defineComponent({
timeout: null as Timeout,
levels: LOG_LEVELS,
busy: false,
tick: 0,
};
},
head() {
@ -221,6 +222,7 @@ export default defineComponent({
// prevent concurrent requests
if (this.busy) return;
this.tick++;
try {
this.busy = true;
const response = await api.get("/system/log", {
@ -327,17 +329,6 @@ export default defineComponent({
.play {
transform: scale(1.2);
}
.spin {
animation: rotation 3s infinite ease-in-out;
}
@keyframes rotation {
from {
transform: rotate(0deg) scale(1, -1);
}
to {
transform: rotate(1440deg) scale(1, -1);
}
}
@keyframes fadeIn {
from {
opacity: 0.3;