diff --git a/_src/components/StatusMirrorList.vue b/_src/components/StatusMirrorList.vue
new file mode 100644
index 0000000..63244d2
--- /dev/null
+++ b/_src/components/StatusMirrorList.vue
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+
+
diff --git a/_src/entrypoints/status.js b/_src/entrypoints/status.js
index d5c33a2..6f6a113 100644
--- a/_src/entrypoints/status.js
+++ b/_src/entrypoints/status.js
@@ -1,7 +1,8 @@
import "./default";
-import "../styles/status.scss";
import DiskBar from "../components/DiskBar.vue";
+import StatusMirrorList from "../components/StatusMirrorList.vue";
import { createApp } from "vue";
createApp(DiskBar).mount("#disk-usage");
+createApp(StatusMirrorList).mount("#mirror-list");
diff --git a/_src/styles/status.scss b/_src/styles/status.scss
deleted file mode 100644
index df07798..0000000
--- a/_src/styles/status.scss
+++ /dev/null
@@ -1,100 +0,0 @@
-table.flat {
- &>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;
- }
-}
-
-
-// Scrolling columns in status page
-.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;
- }
- }
- }
-
- #{$attrib}="-1"] {
- .tuna-roll>div {
- transform: translateY(100%);
- animation-name: tuna-roll-leave;
- animation-duration: 0s;
- }
-
- .tuna-roll>div[data-tuna-roll-seq~="0"] {
- transform: none;
- animation-name: tuna-roll-enter;
- animation-duration: 0s;
- }
- }
-}
diff --git a/static/js/status.es6 b/static/js/status.es6
deleted file mode 100644
index 4799ffd..0000000
--- a/static/js/status.es6
+++ /dev/null
@@ -1,26 +0,0 @@
----
----
-document.addEventListener("DOMContentLoaded", () => {
-
- const SCROLL_INTERVAL = 2000;
-
- var step = 0;
- const doScroll = function() {
- const target = document.getElementById('mirror-list');
- const max = parseInt(target.attributes['data-tuna-roll-max'].value, 10);
- Array.from(target.querySelectorAll(".row:hover:not([data-tuna-roll-freeze])")).forEach((el) => {
- const attr = document.createAttribute('data-tuna-roll-freeze');
- attr.value = String((step) % max);
- el.attributes.setNamedItem(attr);
- })
- Array.from(target.querySelectorAll(".row:not(:hover)[data-tuna-roll-freeze]")).forEach((el) => {
- el.removeAttribute('data-tuna-roll-freeze');
- });
- step += 1;
- if(step < 0) step = 0;
- const attr = document.createAttribute('data-tuna-roll-cur');
- attr.value = String(step % max);
- target.attributes.setNamedItem(attr);
- }
- setInterval(doScroll, SCROLL_INTERVAL);
-});
diff --git a/status.html b/status.html
index 71edf17..41e8300 100644
--- a/status.html
+++ b/status.html
@@ -32,113 +32,11 @@ jsEntry: status
{% endunless %}
+
+
+
+ Name
+ Last Update
+ Upstream
+ Status
+ Size
+
+
+
+ Name
+
+ {{ mir.name }}{{ mir.is_master ? "" : " [slave]" }}
+
+ Last Success
+
+ {{ mir.last_update }}, {{ mir.last_update_ago }}
+
+
+ Last Attempt
+
+ {{ mir.last_ended }}, {{ mir.last_ended_ago }}
+
+
+ Next Sync
+
+ {{ mir.next_schedule }}, {{ mir.next_schedule_ago }}
+
+ Syncing Now
+
+
+
+
+ Upstream
+ {{ mir.upstream }}
+ Status
+ {{ mir.status }}
+ Size
+ {{ mir.size }}
+
| Name | -Last Update | -Upstream | -Status | -Size | -||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Name | -{{mir.name}}{{mir.is_master ? '' : ' [slave]'}} | -Last Success | -{{mir.last_update}}, {{mir.last_update_ago}} | - -Last Attempt | -{{mir.last_ended}}, {{mir.last_ended_ago}} | - -Next Sync | -{{mir.next_schedule}}, {{mir.next_schedule_ago}} | -Syncing Now | -
-
-
-
- Last Successful Sync
-
-
- Last Successful Sync
- Last Attempted Sync
-
- Sync Started
- Next Scheduled Sync
-
-
-
- Last Successful Sync
-
-
- Last Successful Sync
- Last Attempted Sync
- Last Successful Sync
- Last Attempted Sync
-
- Next Scheduled Sync
- |
-
-
-
-
- {{mir.last_update_ago}}
-
-
-
- {{mir.last_update}}
- {{mir.last_update_ago}}
-
- {{mir.last_update}}
- {{mir.last_ended_ago}}
-
-
- {{mir.last_ended}}
- {{mir.last_started_ago}}
-
- {{mir.last_started}}
- {{mir.next_schedule_ago}}
-
- {{mir.next_schedule}}
-
-
-
- {{mir.last_update}}
- {{mir.last_update_ago}}
-
-
- {{mir.last_update}}
- {{mir.last_ended}}
- {{mir.last_update_ago}}
- {{mir.last_ended_ago}}
-
-
- Syncing Now
-
-
- {{mir.next_schedule}}
- {{mir.next_schedule_ago}}
-
- |
- Upstream | -{{mir.upstream}} | -Status | -{{mir.status}} | -Size | -{{mir.size}} | -