added info-box for building and queued packages
This commit is contained in:
253
frontend/src/components/CurrentlyBuilding.vue
Normal file
253
frontend/src/components/CurrentlyBuilding.vue
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
<template>
|
||||||
|
<v-card
|
||||||
|
border
|
||||||
|
class="my-6"
|
||||||
|
rounded
|
||||||
|
style="border-radius: 10px; border: 2px solid grey"
|
||||||
|
variant="elevated">
|
||||||
|
<v-card-title class="d-flex align-center justify-space-between w-100">
|
||||||
|
<span v-if="packageCount.building > 0">Building</span>
|
||||||
|
<span v-else>Idle</span>
|
||||||
|
<v-sheet class="d-flex align-center w-100">
|
||||||
|
<v-progress-linear
|
||||||
|
:max="packageCount.built + packageCount.building + packageCount.queued"
|
||||||
|
:model-value="packageCount.built"
|
||||||
|
color="light-blue"
|
||||||
|
height="10"
|
||||||
|
rounded
|
||||||
|
striped
|
||||||
|
style="transform: translateX(-650px)"></v-progress-linear>
|
||||||
|
<span class="text-grey" style="font-size: 13px; min-width: 250px; padding-left: 50px">
|
||||||
|
Last updated
|
||||||
|
{{
|
||||||
|
lastUpdatedSeconds > 59
|
||||||
|
? rtf.format(-Math.floor(lastUpdatedSeconds / 60), 'minutes')
|
||||||
|
: rtf.format(-lastUpdatedSeconds, 'seconds')
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</v-sheet>
|
||||||
|
</v-card-title>
|
||||||
|
|
||||||
|
<v-card-text class="d-flex">
|
||||||
|
<v-list width="50%">
|
||||||
|
<v-list-subheader>Building</v-list-subheader>
|
||||||
|
<v-list-item v-for="(pkg, index) in packages.building" :key="index">
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<div class="pulsating-circle me-4" />
|
||||||
|
</template>
|
||||||
|
<v-list-item-title>
|
||||||
|
{{ pkg.pkgbase }} <span class="text-grey">({{ pkg.repo }})</span>
|
||||||
|
</v-list-item-title>
|
||||||
|
<v-list-item-subtitle>{{ pkg.repo_version }}</v-list-item-subtitle>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
|
||||||
|
<v-list width="50%">
|
||||||
|
<v-list-subheader>Queued</v-list-subheader>
|
||||||
|
<v-list-item
|
||||||
|
v-for="(pkg, index) in packages.queued.slice(0, packageCount.building)"
|
||||||
|
:key="index"
|
||||||
|
prepend-icon="mdi-chevron-right">
|
||||||
|
<v-list-item-title>
|
||||||
|
{{ pkg.pkgbase }} <span class="text-grey">({{ pkg.repo }})</span>
|
||||||
|
</v-list-item-title>
|
||||||
|
<v-list-item-subtitle>{{ pkg.repo_version }}</v-list-item-subtitle>
|
||||||
|
</v-list-item>
|
||||||
|
<v-list-item
|
||||||
|
v-if="packageCount.queued > packageCount.building"
|
||||||
|
prepend-icon="mdi-dots-horizontal">
|
||||||
|
<v-list-item-title>
|
||||||
|
+ {{ packageCount.queued - packageCount.building }} more
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
// built + building + queued = total
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import type { Packages } from '@/types/Packages'
|
||||||
|
import { Package } from '@/types/Package'
|
||||||
|
|
||||||
|
const lastUpdatedTime = ref(0)
|
||||||
|
const lastUpdatedSeconds = ref(0)
|
||||||
|
const rtf = new Intl.RelativeTimeFormat('en', {
|
||||||
|
localeMatcher: 'best fit',
|
||||||
|
numeric: 'always',
|
||||||
|
style: 'long'
|
||||||
|
})
|
||||||
|
|
||||||
|
const packageCount = ref({
|
||||||
|
total: 0,
|
||||||
|
building: 0,
|
||||||
|
built: 0,
|
||||||
|
queued: 0
|
||||||
|
})
|
||||||
|
const packages = ref<{
|
||||||
|
built: Array<Package>
|
||||||
|
building: Array<Package>
|
||||||
|
queued: Array<Package>
|
||||||
|
}>({
|
||||||
|
built: [],
|
||||||
|
building: [],
|
||||||
|
queued: []
|
||||||
|
})
|
||||||
|
|
||||||
|
const getTotalPackages = () => {
|
||||||
|
fetch('https://api.alhp.dev/packages?limit=1&offset=0', {
|
||||||
|
method: 'GET'
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) return response.json()
|
||||||
|
})
|
||||||
|
.then((json: Packages) => {
|
||||||
|
if (!json) return
|
||||||
|
packageCount.value.total = json.total
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getBuiltPackages = () => {
|
||||||
|
fetch('https://api.alhp.dev/packages?limit=0&offset=0&status=build', {
|
||||||
|
method: 'GET'
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) return response.json()
|
||||||
|
})
|
||||||
|
.then((json: Packages) => {
|
||||||
|
if (!json) return
|
||||||
|
packageCount.value.built = json.total
|
||||||
|
packages.value.built = json.packages
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getBuildingPackages = () => {
|
||||||
|
fetch('https://api.alhp.dev/packages?limit=0&offset=0&status=building', {
|
||||||
|
method: 'GET'
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) return response.json()
|
||||||
|
})
|
||||||
|
.then((json: Packages) => {
|
||||||
|
if (!json) return
|
||||||
|
packageCount.value.building = json.total
|
||||||
|
packages.value.building = json.packages
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getQueuedPackages = () => {
|
||||||
|
fetch('https://api.alhp.dev/packages?limit=0&offset=0&status=queued', {
|
||||||
|
method: 'GET'
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) return response.json()
|
||||||
|
})
|
||||||
|
.then((json: Packages) => {
|
||||||
|
if (!json) return
|
||||||
|
packageCount.value.queued = json.total
|
||||||
|
packages.value.queued = json.packages
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTotalPackages()
|
||||||
|
getBuiltPackages()
|
||||||
|
getBuildingPackages()
|
||||||
|
getQueuedPackages()
|
||||||
|
lastUpdatedTime.value = Date.now()
|
||||||
|
lastUpdatedSeconds.value = Math.floor((Date.now() - lastUpdatedTime.value) / 1000)
|
||||||
|
|
||||||
|
const lastUpdatedInterval = setInterval(() => {
|
||||||
|
lastUpdatedSeconds.value = Math.floor((Date.now() - lastUpdatedTime.value) / 1000)
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
getTotalPackages()
|
||||||
|
getBuiltPackages()
|
||||||
|
getBuildingPackages()
|
||||||
|
getQueuedPackages()
|
||||||
|
lastUpdatedTime.value = Date.now()
|
||||||
|
lastUpdatedSeconds.value = Math.floor((Date.now() - lastUpdatedTime.value) / 1000)
|
||||||
|
}, 120_000)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.pulsating-circle {
|
||||||
|
background-color: #f39c12f0;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulsating-circle:before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 200%;
|
||||||
|
height: 200%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-left: -50%;
|
||||||
|
margin-top: -50%;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #f39c12;
|
||||||
|
-webkit-animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
|
||||||
|
animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes pulse-ring {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.33);
|
||||||
|
}
|
||||||
|
80%,
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-ring {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.33);
|
||||||
|
}
|
||||||
|
80%,
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes pulse-dot {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-dot {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user