See #2. Co-authored-by: vikingowl <christian@nachtigall.dev> Reviewed-on: #2 Reviewed-by: anonfunc <539@idlegandalf.com> Co-authored-by: vikingowl <vikingowl@noreply.somegit.dev> Co-committed-by: vikingowl <vikingowl@noreply.somegit.dev>
422 lines
12 KiB
Vue
422 lines
12 KiB
Vue
<template>
|
|
<v-sheet class="mt-6" color="transparent" width="100%">
|
|
<h5 class="text-h5 mb-4">Packages</h5>
|
|
|
|
<v-sheet class="d-flex justify-space-between" color="transparent" width="100%">
|
|
<v-sheet class="d-flex align-center w-50" color="transparent" style="gap: 15px">
|
|
<v-text-field
|
|
v-model="inputPkgBase"
|
|
clearable
|
|
color="primary"
|
|
placeholder="Search Pkgbase"
|
|
style="width: 30%; height: 60px"
|
|
variant="outlined"></v-text-field>
|
|
|
|
<v-select
|
|
v-model="selectRepo"
|
|
:items="selectRepoItems"
|
|
color="primary"
|
|
item-title="title"
|
|
item-value="value"
|
|
return-object
|
|
single-line
|
|
style="width: 30%; height: 60px"
|
|
variant="outlined"></v-select>
|
|
|
|
<v-select
|
|
v-model="selectStatus"
|
|
:items="selectStatusItems"
|
|
color="primary"
|
|
item-title="title"
|
|
item-value="value"
|
|
return-object
|
|
single-line
|
|
style="width: 30%; height: 60px"
|
|
variant="outlined"></v-select>
|
|
</v-sheet>
|
|
|
|
<v-sheet
|
|
class="d-flex align-center justify-end w-50"
|
|
color="transparent"
|
|
style="height: 60px">
|
|
<v-pagination
|
|
v-model="page"
|
|
:length="pagesMax"
|
|
active-color="primary"
|
|
density="comfortable"
|
|
start="1"
|
|
total-visible="7"
|
|
variant="text"></v-pagination>
|
|
</v-sheet>
|
|
</v-sheet>
|
|
|
|
<v-table class="mt-6" style="width: 100%; background: transparent; font-size: 1rem">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">Repository</th>
|
|
<th scope="col">Pkgbase</th>
|
|
<th scope="col">Status</th>
|
|
<th scope="col">Reason</th>
|
|
<th
|
|
scope="col"
|
|
title="link time optimization does not guarantee that package is actually built with LTO">
|
|
LTO
|
|
</th>
|
|
<th scope="col" title="Debug-symbols available via debuginfod">DS</th>
|
|
<th scope="col">Archlinux Version</th>
|
|
<th scope="col">ALHP Version</th>
|
|
<th class="text-end" scope="col" style="width: 30px">Info</th>
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody id="main-tbody">
|
|
<tr v-if="noPackagesFound">
|
|
No Packages found
|
|
</tr>
|
|
<template v-else>
|
|
<tr
|
|
v-for="(pkg, index) in packages"
|
|
:key="index"
|
|
:style="`background-color: ${getStatus(pkg.status)};`">
|
|
<td class="font-weight-bold">
|
|
{{ pkg.repo.split('-')[0] }}
|
|
<v-chip
|
|
:color="getVersionColor(pkg.repo.split('-')[pkg.repo.split('-').length - 1])"
|
|
class="ms-2"
|
|
density="comfortable"
|
|
label
|
|
variant="flat">
|
|
{{ pkg.repo.split('-')[pkg.repo.split('-').length - 1] }}
|
|
</v-chip>
|
|
</td>
|
|
<td>{{ pkg.pkgbase }}</td>
|
|
<td>{{ pkg.status.toLocaleUpperCase() }}</td>
|
|
<td>{{ pkg.skip_reason || '' }}</td>
|
|
<td><i :class="getLto(pkg.lto).class" :title="getLto(pkg.lto).title"></i></td>
|
|
<td>
|
|
<i
|
|
:class="getDs(pkg.debug_symbols).class"
|
|
:title="getDs(pkg.debug_symbols).title"></i>
|
|
</td>
|
|
<td>{{ pkg.arch_version }}</td>
|
|
<td>{{ pkg.repo_version }}</td>
|
|
<td class="d-flex align-center" style="gap: 3px">
|
|
<a
|
|
v-if="pkg.status === 'failed'"
|
|
:href="`https://alhp.dev/logs/${pkg.repo.slice(pkg.repo.indexOf('-') + 1)}/${pkg.pkgbase}.log`"
|
|
class="text-decoration-none"
|
|
style="
|
|
color: darkgrey;
|
|
transform: translateY(-3px) translateX(-15px);
|
|
max-width: 15px;
|
|
"
|
|
target="_blank">
|
|
<i class="fa fa-file-text fa-lg"></i>
|
|
</a>
|
|
<span v-else style="width: 15px"></span>
|
|
<a
|
|
:href="`https://archlinux.org/packages/?q=${pkg.pkgbase}`"
|
|
class="text-decoration-none font-weight-bold"
|
|
style="
|
|
color: darkgrey;
|
|
font-size: 18px;
|
|
padding: 0;
|
|
margin: 0;
|
|
width: 15px;
|
|
transform: translateX(-15px);
|
|
"
|
|
target="_blank"
|
|
title="ArchWeb">
|
|
AW
|
|
</a>
|
|
<span
|
|
v-if="pkg.build_date && pkg.peak_mem"
|
|
class="fa fa-info-circle fa-lg"
|
|
style="color: darkgrey; transform: translateY(-1px); max-width: 15px !important">
|
|
<v-tooltip activator="parent" location="start">
|
|
{{ `Built on ${pkg.build_date}` }}
|
|
<br />
|
|
{{ `Peak-Memory: ${pkg.peak_mem}` }}
|
|
</v-tooltip>
|
|
</span>
|
|
<span v-else style="max-width: 15px !important"></span>
|
|
</td>
|
|
</tr>
|
|
</template>
|
|
</tbody>
|
|
</v-table>
|
|
</v-sheet>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, ref, UnwrapRef, watch } from 'vue'
|
|
import { type Package } from '@/types/Package'
|
|
import { type Packages } from '@/types/Packages'
|
|
|
|
const inputPkgBase = ref('')
|
|
const selectRepo = ref({ title: 'Repository (any)', value: 'any' })
|
|
const selectRepoItems = [
|
|
{ title: 'Repository (any)', value: 'any' },
|
|
{ title: 'core-x86-64-v2', value: 'core-x86-64-v2' },
|
|
{ title: 'extra-x86-64-v2', value: 'extra-x86-64-v2' },
|
|
{ title: 'multilib-x86-64-v2', value: 'multilib-x86-64-v2' },
|
|
{ title: 'core-x86-64-v3', value: 'core-x86-64-v3' },
|
|
{ title: 'extra-x86-64-v3', value: 'extra-x86-64-v3' },
|
|
{ title: 'multilib-x86-64-v3', value: 'multilib-x86-64-v3' },
|
|
{ title: 'core-x86-64-v4', value: 'core-x86-64-v4' },
|
|
{ title: 'extra-x86-64-v4', value: 'extra-x86-64-v4' },
|
|
{ title: 'multilib-x86-64-v4', value: 'multilib-x86-64-v4' }
|
|
]
|
|
const selectStatus = ref({ title: 'Status (any)', value: 'any' })
|
|
const selectStatusItems = [
|
|
{ title: 'Status (any)', value: 'any' },
|
|
{ title: 'Latest', value: 'latest' },
|
|
{ title: 'Built', value: 'built' },
|
|
{ title: 'Failed', value: 'failed' },
|
|
{ title: 'Skipped', value: 'skipped' },
|
|
{ title: 'Delayed', value: 'delayed' },
|
|
{ title: 'Queued', value: 'queued' },
|
|
{ title: 'Building', value: 'building' },
|
|
{ title: 'Signing', value: 'signing' },
|
|
{ title: 'Unknown', value: 'unknown' }
|
|
]
|
|
|
|
const page = ref(1)
|
|
const pagesMax = ref(1)
|
|
const packages = ref<Array<Package>>([])
|
|
const noPackagesFound = ref(false)
|
|
|
|
const searchPackages = (offset: number) => {
|
|
noPackagesFound.value = false
|
|
|
|
const params = new URLSearchParams({
|
|
limit: '50',
|
|
offset: offset.toString()
|
|
})
|
|
|
|
if (inputPkgBase.value) params.append('pkgbase', inputPkgBase.value.toLowerCase())
|
|
if (selectRepo.value.value !== 'any') params.append('repo', selectRepo.value.value)
|
|
if (selectStatus.value.value !== 'any') params.append('status', selectStatus.value.value)
|
|
|
|
fetch('https://api.alhp.dev/packages?' + params, {
|
|
method: 'GET'
|
|
})
|
|
.then((response) => {
|
|
if (response.ok) return response.json()
|
|
if (response.status === 404) {
|
|
noPackagesFound.value = true
|
|
pagesMax.value = 1
|
|
} else {
|
|
throw new Error(response.statusText)
|
|
}
|
|
})
|
|
.then((json: Packages) => {
|
|
if (!json) return
|
|
|
|
if (pagesMax.value !== json.total) {
|
|
pagesMax.value = json.total / 50 + 1
|
|
}
|
|
|
|
packages.value = json.packages
|
|
})
|
|
.catch((error) => {
|
|
console.error(error)
|
|
})
|
|
}
|
|
|
|
const getVersionColor = (version: string) => {
|
|
let color = 'grey'
|
|
switch (version) {
|
|
case 'v2':
|
|
color = '#3498db'
|
|
break
|
|
case 'v3':
|
|
color = '#f39c12'
|
|
break
|
|
case 'v4':
|
|
color = '#2ecc71'
|
|
break
|
|
}
|
|
return color
|
|
}
|
|
|
|
const getStatus = (status: UnwrapRef<Package['status']>) => {
|
|
let color = ''
|
|
switch (status) {
|
|
case 'skipped':
|
|
color = '#373737'
|
|
break
|
|
case 'queued':
|
|
color = '#5d2f03'
|
|
break
|
|
case 'latest':
|
|
color = ''
|
|
break
|
|
case 'failed':
|
|
color = '#4f140f'
|
|
break
|
|
case 'signing':
|
|
color = '#093372'
|
|
break
|
|
case 'building':
|
|
color = '#084f46'
|
|
break
|
|
case 'unknown':
|
|
color = '#191919'
|
|
break
|
|
}
|
|
return color
|
|
}
|
|
|
|
const getLto = (lto: UnwrapRef<Package['lto']>) => {
|
|
let icon = {
|
|
title: '',
|
|
class: ''
|
|
}
|
|
switch (lto) {
|
|
case 'enabled':
|
|
icon = {
|
|
title: 'built with LTO',
|
|
class: 'fa fa-check fa-lg text-success'
|
|
}
|
|
break
|
|
case 'unknown':
|
|
icon = {
|
|
title: 'not built with LTO yet',
|
|
class: 'fa fa-hourglass-o fa-lg text-grey'
|
|
}
|
|
break
|
|
case 'disabled':
|
|
icon = {
|
|
title: 'LTO explicitly disabled',
|
|
class: 'fa fa-times fa-lg text-red'
|
|
}
|
|
break
|
|
case 'auto_disabled':
|
|
icon = {
|
|
title: 'LTO automatically disabled',
|
|
class: 'fa fa-times-circle-o fa-lg text-amber'
|
|
}
|
|
break
|
|
}
|
|
return icon
|
|
}
|
|
|
|
const getDs = (ds: UnwrapRef<Package['debug_symbols']>) => {
|
|
let icon = {
|
|
title: '',
|
|
class: ''
|
|
}
|
|
switch (ds) {
|
|
case 'available':
|
|
icon = {
|
|
title: 'Debug symbols available',
|
|
class: 'fa fa-check fa-lg text-success'
|
|
}
|
|
break
|
|
case 'unknown':
|
|
icon = {
|
|
title: 'Not built yet',
|
|
class: 'fa fa-hourglass-o fa-lg text-grey'
|
|
}
|
|
break
|
|
case 'not_available':
|
|
icon = {
|
|
title: 'Not built with debug symbols',
|
|
class: 'fa fa-times fa-lg text-red'
|
|
}
|
|
break
|
|
}
|
|
return icon
|
|
}
|
|
|
|
const url = new URL(window.location.href)
|
|
|
|
window.addEventListener('load', () => {
|
|
inputPkgBase.value = url.searchParams.has('pkgbase')
|
|
? (url.searchParams.get('pkgbase') || '').toLowerCase()
|
|
: ''
|
|
selectRepo.value = {
|
|
value: url.searchParams.has('repo')
|
|
? (url.searchParams.get('repo') || '').toLowerCase()
|
|
: 'any',
|
|
title: url.searchParams.has('repo')
|
|
? (url.searchParams.get('repo') || '').toLowerCase()
|
|
: 'Repository (any)'
|
|
}
|
|
selectStatus.value = {
|
|
value: url.searchParams.has('status')
|
|
? (url.searchParams.get('status') || '').toLowerCase()
|
|
: 'any',
|
|
title: url.searchParams.has('status')
|
|
? (url.searchParams.get('status') || '').substring(0, 1).toLocaleUpperCase() +
|
|
(url.searchParams.get('status') || '')
|
|
.substring(1, url.searchParams.get('status')!!.length - 1)
|
|
.toLocaleUpperCase()
|
|
: 'Status (any)'
|
|
}
|
|
|
|
searchPackages(0)
|
|
})
|
|
|
|
watch(
|
|
() => page.value,
|
|
() => {
|
|
searchPackages(page.value)
|
|
}
|
|
)
|
|
|
|
// @ts-ignore
|
|
let delayTimer = null
|
|
watch(
|
|
() => inputPkgBase.value,
|
|
() => {
|
|
// @ts-ignore
|
|
if (delayTimer) clearTimeout(delayTimer)
|
|
delayTimer = setTimeout(function () {
|
|
if (inputPkgBase.value) {
|
|
url.searchParams.set('pkgbase', inputPkgBase.value.toLowerCase())
|
|
} else {
|
|
url.searchParams.delete('pkgbase')
|
|
}
|
|
window.history.pushState(null, '', url.toString())
|
|
searchPackages(0)
|
|
}, 250)
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => selectRepo.value,
|
|
() => {
|
|
if (selectRepo.value) {
|
|
if (selectRepo.value.value === 'any') {
|
|
url.searchParams.delete('repo')
|
|
} else {
|
|
url.searchParams.set('repo', selectRepo.value.value)
|
|
}
|
|
window.history.pushState(null, '', url.toString())
|
|
}
|
|
searchPackages(0)
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => selectStatus.value,
|
|
() => {
|
|
if (selectStatus.value) {
|
|
if (selectStatus.value.value === 'any') {
|
|
url.searchParams.delete('status')
|
|
} else {
|
|
url.searchParams.set('status', selectStatus.value.value)
|
|
}
|
|
window.history.pushState(null, '', url.toString())
|
|
}
|
|
searchPackages(0)
|
|
}
|
|
)
|
|
|
|
onMounted(() => {
|
|
searchPackages(0)
|
|
})
|
|
</script>
|