mirror of
https://github.com/tuna/mirror-web.git
synced 2025-12-25 20:32:46 +00:00
218 lines
6.1 KiB
Vue
218 lines
6.1 KiB
Vue
<script setup>
|
|
import { useMirrorList } from "../lib/mirrorList";
|
|
import { ref, onMounted } from "vue";
|
|
|
|
const rawMirrorList = useMirrorList();
|
|
|
|
const rollMax = 6;
|
|
const rollCur = ref(0);
|
|
|
|
const SCROLL_INTERVAL = 2000;
|
|
const doScroll = function () {
|
|
rollCur.value += 1;
|
|
if (rollCur.value >= rollMax) rollCur.value = 0;
|
|
};
|
|
|
|
const freezedRows = ref({});
|
|
|
|
onMounted(() => {
|
|
setInterval(doScroll, SCROLL_INTERVAL);
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<table class="table text-break table-hover table-borderless">
|
|
<thead>
|
|
<tr class="d-none d-lg-table-row">
|
|
<th class="col-2">Name</th>
|
|
<th class="col-4" colspan="2">Last Update</th>
|
|
<th class="col-4">Upstream</th>
|
|
<th class="col-1">Status</th>
|
|
<th class="col-1">Size</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody
|
|
id="mirror-list"
|
|
:data-tuna-roll-cur="rollCur % rollMax"
|
|
:data-tuna-roll-max="rollMax"
|
|
class="table-group-divider"
|
|
>
|
|
<tr
|
|
v-for="mir in rawMirrorList"
|
|
:class="[
|
|
'row',
|
|
'd-lg-table-row',
|
|
'status-' + mir.status,
|
|
mir.last_ended_ts == mir.last_update_ts ? 'last-succ' : 'last-fail',
|
|
]"
|
|
:key="mir.name"
|
|
:data-tuna-roll-freeze="freezedRows[mir.name]"
|
|
@mouseenter="freezedRows[mir.name] = rollCur"
|
|
@mouseleave="freezedRows[mir.name] = undefined"
|
|
>
|
|
<th class="col-4 d-lg-none text-end">Name</th>
|
|
<td class="col-8 col-lg-2">
|
|
{{ mir.name }}{{ mir.is_master ? "" : " [slave]" }}
|
|
</td>
|
|
<th class="col-4 d-lg-none text-end">Last Success</th>
|
|
<td class="col-8 d-lg-none">
|
|
{{ mir.last_update }}, {{ mir.last_update_ago }}
|
|
</td>
|
|
<template v-if="mir.last_ended_ts != mir.last_update_ts">
|
|
<th class="col-4 d-lg-none text-end">Last Attempt</th>
|
|
<td class="col-8 d-lg-none">
|
|
{{ mir.last_ended }}, {{ mir.last_ended_ago }}
|
|
</td>
|
|
</template>
|
|
<th class="col-4 d-lg-none text-end">Next Sync</th>
|
|
<td class="col-8 d-lg-none" v-if="mir.status != 'syncing'">
|
|
{{ mir.next_schedule }}, {{ mir.next_schedule_ago }}
|
|
</td>
|
|
<td class="col-8 d-lg-none" v-else>Syncing Now</td>
|
|
<td class="col-2 rolling-3 d-none d-lg-table-cell">
|
|
<div class="tuna-roll">
|
|
|
|
<template v-if="mir.last_ended_ts == mir.last_update_ts">
|
|
<div data-tuna-roll-seq="0 1 2 3">Last Successful Sync</div>
|
|
</template>
|
|
<template v-else>
|
|
<div data-tuna-roll-seq="0 1">Last Successful Sync</div>
|
|
<div data-tuna-roll-seq="2 3">Last Attempted Sync</div>
|
|
</template>
|
|
<div v-if="mir.status == 'syncing'" data-tuna-roll-seq="4 5">
|
|
Sync Started
|
|
</div>
|
|
<div v-else data-tuna-roll-seq="4 5">Next Scheduled Sync</div>
|
|
</div>
|
|
</td>
|
|
<td class="col-2 rolling-6 d-none d-lg-table-cell">
|
|
<div class="tuna-roll">
|
|
|
|
<template v-if="mir.last_ended_ts == mir.last_update_ts">
|
|
<div data-tuna-roll-seq="0 1 2 3">
|
|
{{ mir.last_update_ago }}
|
|
<div class="tooltiptext">{{ mir.last_update }}</div>
|
|
</div>
|
|
</template>
|
|
<template v-else>
|
|
<div data-tuna-roll-seq="0 1">
|
|
{{ mir.last_update_ago }}
|
|
<div class="tooltiptext">{{ mir.last_update }}</div>
|
|
</div>
|
|
<div
|
|
data-tuna-roll-seq="2 3"
|
|
v-if="mir.last_ended_ts != mir.last_update_ts"
|
|
>
|
|
{{ mir.last_ended_ago }}
|
|
<div class="tooltiptext">{{ mir.last_ended }}</div>
|
|
</div>
|
|
</template>
|
|
<div v-if="mir.status == 'syncing'" data-tuna-roll-seq="4 5">
|
|
{{ mir.last_started_ago }}
|
|
<div class="tooltiptext">{{ mir.last_started }}</div>
|
|
</div>
|
|
<div v-else data-tuna-roll-seq="4 5">
|
|
{{ mir.next_schedule_ago }}
|
|
<div class="tooltiptext">{{ mir.next_schedule }}</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<th class="col-4 d-lg-none text-end">Upstream</th>
|
|
<td class="col-8 col-lg-4">{{ mir.upstream }}</td>
|
|
<th class="col-4 d-lg-none text-end">Status</th>
|
|
<td class="col-8 col-lg-1">{{ mir.status }}</td>
|
|
<th class="col-4 d-lg-none text-end">Size</th>
|
|
<td class="col-8 col-lg-1">{{ mir.size }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
@use "../styles/sync-status.scss";
|
|
table {
|
|
& > tbody > tr {
|
|
border-bottom-width: var(--bs-border-width);
|
|
}
|
|
|
|
& > thead > tr {
|
|
border-bottom-width: calc(var(--bs-border-width) * 2);
|
|
border-bottom-style: solid;
|
|
border-bottom-color: currentColor;
|
|
}
|
|
}
|
|
|
|
.tuna-roll {
|
|
position: relative;
|
|
overflow: hidden;
|
|
|
|
> div {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
top: 0;
|
|
|
|
animation-timing-function: ease;
|
|
animation-duration: 1s;
|
|
animation-iteration-count: 1;
|
|
|
|
/* Tooltip text */
|
|
> .tooltiptext {
|
|
visibility: hidden;
|
|
width: auto;
|
|
background-color: #555;
|
|
color: #fff;
|
|
text-align: center;
|
|
border-radius: 5px;
|
|
|
|
/* Position the tooltip text - see examples below! */
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
z-index: 1;
|
|
}
|
|
|
|
&:hover > .tooltiptext {
|
|
visibility: visible;
|
|
}
|
|
}
|
|
|
|
@keyframes tuna-roll-enter {
|
|
0% {
|
|
transform: translateY(100%);
|
|
}
|
|
|
|
100% {
|
|
transform: none;
|
|
}
|
|
}
|
|
|
|
@keyframes tuna-roll-leave {
|
|
0% {
|
|
transform: none;
|
|
}
|
|
|
|
100% {
|
|
transform: translateY(-100%);
|
|
}
|
|
}
|
|
}
|
|
|
|
@each $attrib in ("[data-tuna-roll-cur", ".row[data-tuna-roll-freeze") {
|
|
@for $i from 0 to 7 {
|
|
#{$attrib}="#{$i}"] {
|
|
.tuna-roll > div {
|
|
animation-name: tuna-roll-leave;
|
|
transform: translateY(100%);
|
|
}
|
|
|
|
.tuna-roll > div[data-tuna-roll-seq~="#{$i}"] {
|
|
animation-name: tuna-roll-enter;
|
|
transform: none;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|