Refactor Packages component for better readability and maintainability
Simplified logic by extracting helper functions and constants, and improved state management with more descriptive variable names. Enhanced URL parameter handling and adjusted watchers to dynamically update based on changes, ensuring cleaner and more modular code.
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
<template>
|
||||
<v-sheet class="mt-6" color="transparent" width="100%">
|
||||
<v-sheet :color="TRANSPARENT_COLOR" class="mt-6" width="100%">
|
||||
<h5 class="text-h5 mb-4">Packages</h5>
|
||||
|
||||
<v-row :style="mobile ? '' : 'height: 60px'" width="100%">
|
||||
<v-row :style="mobile ? '' : `height: ${ROW_HEIGHT}px`" width="100%">
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-2">
|
||||
<v-text-field
|
||||
v-model="inputPkgBase"
|
||||
@@ -11,10 +10,9 @@
|
||||
placeholder="Search Pkgbase"
|
||||
variant="outlined"></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-2 mt-n6 mt-sm-0">
|
||||
<v-select
|
||||
v-model="selectRepo"
|
||||
v-model="selectedRepo"
|
||||
:items="selectRepoItems"
|
||||
clearable
|
||||
color="primary"
|
||||
@@ -25,10 +23,9 @@
|
||||
single-line
|
||||
variant="outlined"></v-select>
|
||||
</v-col>
|
||||
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-3 mt-n6 mt-sm-0">
|
||||
<v-select
|
||||
v-model="selectStatus"
|
||||
v-model="selectedStatuses"
|
||||
:items="selectStatusItems"
|
||||
chips
|
||||
closable-chips
|
||||
@@ -41,11 +38,9 @@
|
||||
return-object
|
||||
variant="outlined"></v-select>
|
||||
</v-col>
|
||||
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-2 mt-n6 mt-sm-0">
|
||||
<v-switch v-model="enableExact" color="primary" label="Exact search"></v-switch>
|
||||
</v-col>
|
||||
|
||||
<v-col :class="mobile ? 'mt-n6' : ''" :cols="mobile ? 12 : 'auto'" class="ms-auto">
|
||||
<v-pagination
|
||||
v-model="page"
|
||||
@@ -57,7 +52,6 @@
|
||||
variant="text"></v-pagination>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-table class="mt-2 mt-sm-6" style="width: 100%; background: transparent; font-size: 1rem">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -84,7 +78,6 @@
|
||||
<th class="text-end" scope="col" style="width: 30px">Info</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody id="main-tbody">
|
||||
<tr v-if="noPackagesFound">
|
||||
No Packages found
|
||||
@@ -93,16 +86,16 @@
|
||||
<tr
|
||||
v-for="(pkg, index) in packages"
|
||||
:key="index"
|
||||
:style="`background-color: ${getStatus(pkg.status)};`">
|
||||
:style="`background-color: ${getStatusColor(pkg.status)};`">
|
||||
<td class="font-weight-bold text-no-wrap">
|
||||
{{ pkg.repo.split('-')[0] }}
|
||||
{{ repoName(pkg.repo) }}
|
||||
<v-chip
|
||||
:color="getVersionColor(pkg.repo.split('-')[pkg.repo.split('-').length - 1])"
|
||||
:color="getVersionColor(repoVersion(pkg.repo))"
|
||||
class="ms-2"
|
||||
density="comfortable"
|
||||
label
|
||||
variant="flat">
|
||||
{{ pkg.repo.split('-')[pkg.repo.split('-').length - 1] }}
|
||||
{{ repoVersion(pkg.repo) }}
|
||||
</v-chip>
|
||||
</td>
|
||||
<td class="text-no-wrap">{{ pkg.pkgbase }}</td>
|
||||
@@ -165,23 +158,31 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, UnwrapRef, watch } from 'vue'
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
import { type Package } from '@/types/Package'
|
||||
import { type Packages } from '@/types/Packages'
|
||||
import { useDisplay } from 'vuetify'
|
||||
|
||||
// Constants
|
||||
const OFFSET = 50
|
||||
const ROW_HEIGHT = 60
|
||||
const TRANSPARENT_COLOR = 'transparent'
|
||||
|
||||
// Refs
|
||||
const page = ref(0)
|
||||
const pagesMax = ref(1)
|
||||
const packages = ref<Array<Package>>([])
|
||||
const noPackagesFound = ref(false)
|
||||
const init = ref(false)
|
||||
const inputPkgBase = ref('')
|
||||
const selectedRepo = ref<{ title: string; value: string } | undefined>(undefined)
|
||||
const selectedStatuses = ref<Array<{ title: string; value: string }>>([])
|
||||
const enableExact = ref(false)
|
||||
|
||||
// Display
|
||||
const { mobile } = useDisplay()
|
||||
|
||||
const inputPkgBase = ref('')
|
||||
const selectRepo = ref()
|
||||
// Select Items
|
||||
const selectRepoItems = [
|
||||
{ title: 'core-x86-64-v2', value: 'core-x86-64-v2' },
|
||||
{ title: 'extra-x86-64-v2', value: 'extra-x86-64-v2' },
|
||||
@@ -193,7 +194,7 @@ const selectRepoItems = [
|
||||
{ title: 'extra-x86-64-v4', value: 'extra-x86-64-v4' },
|
||||
{ title: 'multilib-x86-64-v4', value: 'multilib-x86-64-v4' }
|
||||
]
|
||||
const selectStatus = ref<Array<{ title: string; value: string }>>([])
|
||||
|
||||
const selectStatusItems = [
|
||||
{ title: 'Latest', value: 'latest' },
|
||||
{ title: 'Built', value: 'built' },
|
||||
@@ -205,63 +206,142 @@ const selectStatusItems = [
|
||||
{ title: 'Signing', value: 'signing' },
|
||||
{ title: 'Unknown', value: 'unknown' }
|
||||
]
|
||||
const enableExact = ref(false)
|
||||
|
||||
const searchPackages = () => {
|
||||
const offset = OFFSET * (page.value > 0 ? page.value - 1 : page.value)
|
||||
noPackagesFound.value = false
|
||||
// Computed properties
|
||||
const repoName = (repo: string) => repo.split('-')[0]
|
||||
const repoVersion = (repo: string) => repo.split('-')[repo.split('-').length - 1]
|
||||
|
||||
// init params
|
||||
// Helper function for getting the color associated with a version
|
||||
const getVersionColor = (version: string) => {
|
||||
switch (version) {
|
||||
case 'v2':
|
||||
return '#3498db'
|
||||
case 'v3':
|
||||
return '#f39c12'
|
||||
case 'v4':
|
||||
return '#2ecc71'
|
||||
default:
|
||||
return 'grey'
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for getting the status color
|
||||
const getStatusColor = (status: Package['status']) => {
|
||||
switch (status) {
|
||||
case 'skipped':
|
||||
return '#373737'
|
||||
case 'queued':
|
||||
return '#5d2f03'
|
||||
case 'latest':
|
||||
return ''
|
||||
case 'failed':
|
||||
return '#4f140f'
|
||||
case 'signing':
|
||||
return '#093372'
|
||||
case 'building':
|
||||
return '#084f46'
|
||||
case 'unknown':
|
||||
return '#191919'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const getLto = (lto: Package['lto']) => {
|
||||
switch (lto) {
|
||||
case 'enabled':
|
||||
return {
|
||||
title: 'built with LTO',
|
||||
class: 'fa fa-check fa-lg text-success'
|
||||
}
|
||||
case 'unknown':
|
||||
return {
|
||||
title: 'not built with LTO yet',
|
||||
class: 'fa fa-hourglass-o fa-lg text-grey'
|
||||
}
|
||||
case 'disabled':
|
||||
return {
|
||||
title: 'LTO explicitly disabled',
|
||||
class: 'fa fa-times fa-lg text-red'
|
||||
}
|
||||
case 'auto_disabled':
|
||||
return {
|
||||
title: 'LTO automatically disabled',
|
||||
class: 'fa fa-times-circle-o fa-lg text-amber'
|
||||
}
|
||||
default:
|
||||
return { title: '', class: '' }
|
||||
}
|
||||
}
|
||||
|
||||
const getDs = (ds: Package['debug_symbols']) => {
|
||||
switch (ds) {
|
||||
case 'available':
|
||||
return {
|
||||
title: 'Debug symbols available',
|
||||
class: 'fa fa-check fa-lg text-success'
|
||||
}
|
||||
case 'unknown':
|
||||
return {
|
||||
title: 'Not built yet',
|
||||
class: 'fa fa-hourglass-o fa-lg text-grey'
|
||||
}
|
||||
case 'not_available':
|
||||
return {
|
||||
title: 'Not built with debug symbols',
|
||||
class: 'fa fa-times fa-lg text-red'
|
||||
}
|
||||
default:
|
||||
return { title: '', class: '' }
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for updating URL params dynamically
|
||||
const updateUrlParams = () => {
|
||||
const params = new URLSearchParams()
|
||||
|
||||
// set params
|
||||
if (offset > 0) {
|
||||
url.searchParams.set('offset', offset.toString())
|
||||
} else {
|
||||
url.searchParams.delete('offset')
|
||||
if (page.value > 0) {
|
||||
params.set('offset', (page.value * OFFSET).toString())
|
||||
}
|
||||
if (inputPkgBase.value) {
|
||||
params.set('pkgbase', inputPkgBase.value.toLowerCase())
|
||||
url.searchParams.set('pkgbase', inputPkgBase.value.toLowerCase())
|
||||
} else {
|
||||
params.delete('pkgbase')
|
||||
url.searchParams.delete('pkgbase')
|
||||
}
|
||||
if (selectRepo.value) {
|
||||
params.set('repo', selectRepo.value.value)
|
||||
url.searchParams.set('repo', selectRepo.value.value)
|
||||
} else {
|
||||
params.delete('repo')
|
||||
url.searchParams.delete('repo')
|
||||
if (selectedRepo.value) {
|
||||
params.set('repo', selectedRepo.value.value)
|
||||
}
|
||||
if (selectStatus.value.length > 0) {
|
||||
selectStatus.value.forEach((status) => {
|
||||
if (!params.has('status', status.value)) {
|
||||
params.append('status', status.value)
|
||||
}
|
||||
if (!url.searchParams.has('status', status.value)) {
|
||||
url.searchParams.append('status', status.value)
|
||||
}
|
||||
if (selectedStatuses.value.length > 0) {
|
||||
selectedStatuses.value.forEach((status) => {
|
||||
params.append('status', status.value)
|
||||
})
|
||||
} else {
|
||||
params.delete('status')
|
||||
url.searchParams.delete('status')
|
||||
}
|
||||
if (enableExact.value) {
|
||||
params.set('exact', '')
|
||||
url.searchParams.set('exact', '')
|
||||
} else {
|
||||
params.delete('exact')
|
||||
url.searchParams.delete('exact')
|
||||
}
|
||||
window.history.pushState(null, '', `${window.location.pathname}?${params}`)
|
||||
}
|
||||
|
||||
// push params to url
|
||||
window.history.pushState(null, '', url.toString())
|
||||
|
||||
// add limit to query params
|
||||
const searchPackages = () => {
|
||||
const offset = OFFSET * page.value
|
||||
noPackagesFound.value = false
|
||||
const params = new URLSearchParams()
|
||||
if (page.value > 0) {
|
||||
params.set('offset', offset.toString())
|
||||
}
|
||||
if (inputPkgBase.value) {
|
||||
params.set('pkgbase', inputPkgBase.value.toLowerCase())
|
||||
}
|
||||
if (selectedRepo.value) {
|
||||
params.set('repo', selectedRepo.value.value)
|
||||
}
|
||||
if (selectedStatuses.value.length > 0) {
|
||||
selectedStatuses.value.forEach((status) => {
|
||||
params.append('status', status.value)
|
||||
})
|
||||
}
|
||||
if (enableExact.value) {
|
||||
params.set('exact', '')
|
||||
}
|
||||
params.set('limit', OFFSET.toString())
|
||||
params.set('offset', offset.toString())
|
||||
|
||||
fetch('https://api.alhp.dev/packages?' + params, {
|
||||
method: 'GET'
|
||||
})
|
||||
@@ -276,174 +356,43 @@ const searchPackages = () => {
|
||||
})
|
||||
.then((json: Packages) => {
|
||||
if (!json) return
|
||||
|
||||
if (pagesMax.value !== json.total) {
|
||||
pagesMax.value = json.total / OFFSET + 1
|
||||
}
|
||||
|
||||
pagesMax.value = json.total / OFFSET + 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', () => {
|
||||
init.value = true
|
||||
|
||||
url.searchParams.has('offset')
|
||||
? (page.value = parseInt(url.searchParams.get('offset') || '0'))
|
||||
: (page.value = 0)
|
||||
inputPkgBase.value = url.searchParams.has('pkgbase')
|
||||
? (url.searchParams.get('pkgbase') || '').toLowerCase()
|
||||
: ''
|
||||
url.searchParams.has('repo')
|
||||
? (selectRepo.value = {
|
||||
value: url.searchParams.get('repo'),
|
||||
title: url.searchParams.get('repo')
|
||||
})
|
||||
: undefined
|
||||
url.searchParams.has('status')
|
||||
? url.searchParams.getAll('status').forEach((status) => {
|
||||
selectStatus.value.push({ value: status, title: status.toLocaleUpperCase() })
|
||||
})
|
||||
: undefined
|
||||
enableExact.value = url.searchParams.has('exact')
|
||||
|
||||
searchPackages()
|
||||
init.value = false
|
||||
})
|
||||
|
||||
watch(
|
||||
[
|
||||
() => enableExact.value,
|
||||
() => inputPkgBase.value,
|
||||
() => selectRepo.value,
|
||||
() => selectStatus.value
|
||||
],
|
||||
() => {
|
||||
page.value = 0
|
||||
|
||||
searchPackages()
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => page.value,
|
||||
() => {
|
||||
searchPackages()
|
||||
}
|
||||
)
|
||||
|
||||
// Properly set the initial values from URL params
|
||||
onMounted(() => {
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
page.value = urlParams.has('offset')
|
||||
? Math.floor(parseInt(urlParams.get('offset') || '0') / OFFSET)
|
||||
: 0
|
||||
inputPkgBase.value = urlParams.get('pkgbase') || ''
|
||||
const repoValue = urlParams.get('repo')
|
||||
if (repoValue) {
|
||||
selectedRepo.value = { title: repoValue, value: repoValue }
|
||||
} else {
|
||||
selectedRepo.value = undefined
|
||||
}
|
||||
const statuses = urlParams.getAll('status')
|
||||
selectedStatuses.value = statuses.map((status) => ({
|
||||
title: status.toUpperCase(),
|
||||
value: status
|
||||
}))
|
||||
enableExact.value = urlParams.has('exact')
|
||||
searchPackages()
|
||||
})
|
||||
|
||||
// Watchers
|
||||
watch(
|
||||
[page, inputPkgBase, selectedRepo, selectedStatuses, enableExact],
|
||||
() => {
|
||||
if (init.value) return
|
||||
updateUrlParams()
|
||||
searchPackages()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
</script>
|
||||
|
Reference in New Issue
Block a user