Refactor package types and improve filter handling

Switch to API schema-defined types for package properties, replacing custom typings for consistency. Streamline filter initialization, validation, and URL parameter handling, while adding safeguards for null values. Simplify components by removing unused exports and types.
This commit is contained in:
2025-05-04 23:32:51 +02:00
parent 3886c7bcbd
commit 7445919003
7 changed files with 45 additions and 37 deletions

View File

@@ -8,7 +8,6 @@ export {}
/* prettier-ignore */ /* prettier-ignore */
declare module 'vue' { declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
ApiExample: typeof import('./src/components/ApiExample.vue')['default']
BuildServerStats: typeof import('./src/components/BuildServerStats.vue')['default'] BuildServerStats: typeof import('./src/components/BuildServerStats.vue')['default']
BuildStats: typeof import('./src/components/MainNav/BuildStats.vue')['default'] BuildStats: typeof import('./src/components/MainNav/BuildStats.vue')['default']
CurrentlyBuilding: typeof import('./src/components/CurrentlyBuilding.vue')['default'] CurrentlyBuilding: typeof import('./src/components/CurrentlyBuilding.vue')['default']
@@ -19,6 +18,5 @@ declare module 'vue' {
QueuedPackagesList: typeof import('./src/components/CurrentlyBuilding/QueuedPackagesList.vue')['default'] QueuedPackagesList: typeof import('./src/components/CurrentlyBuilding/QueuedPackagesList.vue')['default']
StatItem: typeof import('./src/components/MainNav/BuildStats/StatItem.vue')['default'] StatItem: typeof import('./src/components/MainNav/BuildStats/StatItem.vue')['default']
StatsListSection: typeof import('./src/components/MainNav/BuildStats/StatsListSection.vue')['default'] StatsListSection: typeof import('./src/components/MainNav/BuildStats/StatsListSection.vue')['default']
StoreExample: typeof import('./src/components/StoreExample.vue')['default']
} }
} }

View File

@@ -39,11 +39,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import { defineProps } from 'vue' import { defineProps } from 'vue'
import type { Package } from '@/types/Package' import { components } from '@/api'
defineProps({ defineProps({
packages: { packages: {
type: Array<Package>, type: Array<components['schemas']['Package']>,
required: true, required: true,
default: () => [] default: () => []
} }

View File

@@ -53,6 +53,7 @@ import { useDisplay } from 'vuetify'
import { REPO_ITEMS, ROW_HEIGHT, STATUS_ITEMS } from '@/config/constants' import { REPO_ITEMS, ROW_HEIGHT, STATUS_ITEMS } from '@/config/constants'
import { usePackagesStore } from '@/stores' import { usePackagesStore } from '@/stores'
import { computed, onMounted, ref, watch } from 'vue' import { computed, onMounted, ref, watch } from 'vue'
import { components } from '@/api'
const { mobile } = useDisplay() const { mobile } = useDisplay()
const packagesStore = usePackagesStore() const packagesStore = usePackagesStore()
@@ -77,7 +78,9 @@ const updateFilter = (pageVal?: number) => {
packagesStore.setFilters( packagesStore.setFilters(
{ {
exact: exact.value, exact: exact.value,
status: status.value?.map((state) => state.value), status: status.value.map(
(state) => state.value as components['schemas']['Package']['status']
),
pkgbase: pkgbase.value !== null ? pkgbase.value : undefined, pkgbase: pkgbase.value !== null ? pkgbase.value : undefined,
repo: repo.value repo: repo.value
}, },
@@ -92,7 +95,9 @@ const initFilters = () => {
exact.value = packagesStore.state.filters.exact exact.value = packagesStore.state.filters.exact
if (packagesStore.state.filters.status) { if (packagesStore.state.filters.status) {
for (const state of packagesStore.state.filters.status) { for (const state of packagesStore.state.filters.status) {
status.value.push({ title: state.toUpperCase(), value: state.toLowerCase() }) if (state) {
status.value.push({ title: state.toUpperCase(), value: state.toLowerCase() })
}
} }
} }
} }

View File

@@ -26,7 +26,7 @@
</tr> </tr>
</thead> </thead>
<tbody id="main-tbody"> <tbody id="main-tbody">
<tr v-if="noResults"> <tr v-if="packagesStore.state.packages.length === 0">
No Packages found No Packages found
</tr> </tr>
<template v-else> <template v-else>
@@ -36,17 +36,17 @@
:style="`background-color: ${getStatusColor(pkg.status)};`"> :style="`background-color: ${getStatusColor(pkg.status)};`">
<td class="font-weight-bold text-no-wrap"> <td class="font-weight-bold text-no-wrap">
<v-chip <v-chip
:color="getVersionColor(repoVersion(pkg.repo))" :color="getVersionColor(repoVersion(pkg.repo || ''))"
class="me-2" class="me-2"
density="comfortable" density="comfortable"
label label
variant="flat"> variant="flat">
{{ repoVersion(pkg.repo) }} {{ repoVersion(pkg.repo || '') }}
</v-chip> </v-chip>
{{ repoName(pkg.repo) }} {{ repoName(pkg.repo || '') }}
</td> </td>
<td class="text-no-wrap">{{ pkg.pkgbase }}</td> <td class="text-no-wrap">{{ pkg.pkgbase }}</td>
<td>{{ pkg.status.toLocaleUpperCase() }}</td> <td>{{ (pkg.status || '').toLocaleUpperCase() }}</td>
<td>{{ pkg.skip_reason || '' }}</td> <td>{{ pkg.skip_reason || '' }}</td>
<td><i :class="getLto(pkg.lto).class" :title="getLto(pkg.lto).title"></i></td> <td><i :class="getLto(pkg.lto).class" :title="getLto(pkg.lto).title"></i></td>
<td> <td>
@@ -57,7 +57,7 @@
<td class="d-flex align-center" style="gap: 3px"> <td class="d-flex align-center" style="gap: 3px">
<a <a
v-if="pkg.status === 'failed'" v-if="pkg.status === 'failed'"
:href="`https://alhp.dev/logs/${pkg.repo.slice(pkg.repo.indexOf('-') + 1)}/${pkg.pkgbase}.log`" :href="`https://alhp.dev/logs/${(pkg.repo || '').slice((pkg.repo || '').indexOf('-') + 1)}/${pkg.pkgbase}.log`"
class="text-decoration-none" class="text-decoration-none"
style=" style="
color: darkgrey; color: darkgrey;

View File

@@ -1,4 +1,4 @@
import { type Package } from '@/types/Package' import { components } from '@/api'
export function usePackageDisplay() { export function usePackageDisplay() {
const repoName = (repo: string) => repo.split('-')[0] const repoName = (repo: string) => repo.split('-')[0]
@@ -17,7 +17,7 @@ export function usePackageDisplay() {
} }
} }
const getStatusColor = (status: Package['status']) => { const getStatusColor = (status: components['schemas']['Package']['status']) => {
switch (status) { switch (status) {
case 'skipped': case 'skipped':
return '#373737' return '#373737'
@@ -38,7 +38,7 @@ export function usePackageDisplay() {
} }
} }
const getLto = (lto: Package['lto']) => { const getLto = (lto: components['schemas']['Package']['lto']) => {
switch (lto) { switch (lto) {
case 'enabled': case 'enabled':
return { return {
@@ -65,7 +65,7 @@ export function usePackageDisplay() {
} }
} }
const getDs = (ds: Package['debug_symbols']) => { const getDs = (ds: components['schemas']['Package']['debug_symbols']) => {
switch (ds) { switch (ds) {
case 'available': case 'available':
return { return {

View File

@@ -1,6 +1,3 @@
// Export all stores // Export all stores
export { useStatsStore } from './statsStore' export { useStatsStore } from './statsStore'
export { usePackagesStore } from './packagesStore' export { usePackagesStore } from './packagesStore'
// Export types
export type { PackageFilters, PaginationOptions } from './packagesStore'

View File

@@ -2,10 +2,10 @@ import { defineStore } from 'pinia'
import { reactive } from 'vue' import { reactive } from 'vue'
import { components, getPackages } from '@/api' import { components, getPackages } from '@/api'
export interface PackageFilters { interface PackageFilters {
status?: components['schemas']['Package']['status'][] status?: components['schemas']['Package']['status'][]
pkgbase?: components['schemas']['Package']['pkgbase'] pkgbase?: components['schemas']['Package']['pkgbase']
exact?: boolean | undefined exact?: boolean
repo?: components['schemas']['Package']['repo'] repo?: components['schemas']['Package']['repo']
} }
@@ -20,10 +20,10 @@ export const usePackagesStore = defineStore('packages', () => {
error: null as string | null, error: null as string | null,
lastUpdated: Date.now(), lastUpdated: Date.now(),
filters: { filters: {
status: undefined as components['schemas']['Package']['status'][] | undefined, status: undefined,
pkgbase: undefined as components['schemas']['Package']['pkgbase'] | undefined, pkgbase: undefined,
exact: undefined as boolean | undefined, exact: undefined,
repo: undefined as components['schemas']['Package']['repo'] | undefined repo: undefined
} as PackageFilters } as PackageFilters
}) })
@@ -36,20 +36,21 @@ export const usePackagesStore = defineStore('packages', () => {
initFromUrl() initFromUrl()
} }
const filter = {} const filter: PackageFilters = {}
if (state.filters.status && state.filters.status.length > 0) { if (state.filters.status && state.filters.status.length > 0) {
filter['status'] = state.filters.status filter.status = state.filters.status
} }
if (state.filters.pkgbase) { if (state.filters.pkgbase) {
filter['pkgbase'] = state.filters.pkgbase filter.pkgbase = state.filters.pkgbase
} }
if (state.filters.exact === true) { if (state.filters.exact === true) {
filter['exact'] = '' filter.exact = state.filters.exact
} }
if (state.filters.repo) { if (state.filters.repo) {
filter['repo'] = state.filters.repo filter.repo = state.filters.repo
} }
// @ts-ignore
getPackages({ getPackages({
limit: state.limit, limit: state.limit,
offset: state.offset, offset: state.offset,
@@ -139,14 +140,16 @@ export const usePackagesStore = defineStore('packages', () => {
const params = new URLSearchParams() const params = new URLSearchParams()
let page = state.offset / state.limit + 1 let page = state.offset / state.limit + 1
// Only add page parameter if it's not the first page // Only add a page parameter if it's not the first page
if (page > 1) { if (page > 1) {
params.set('page', page.toString()) params.set('page', page.toString())
} }
if (state.filters.status && state.filters.status.length > 0) { if (state.filters.status && state.filters.status.length > 0) {
state.filters.status.forEach((status) => { state.filters.status.forEach((status: components['schemas']['Package']['status']) => {
params.append('status', status) if (status) {
params.append('status', status)
}
}) })
} }
@@ -179,19 +182,24 @@ export const usePackagesStore = defineStore('packages', () => {
const pageParam = urlParams.get('page') || '1' const pageParam = urlParams.get('page') || '1'
const parsedPage = parseInt(pageParam, 10) const parsedPage = parseInt(pageParam, 10)
const page = !isNaN(parsedPage) && parsedPage > 0 ? parsedPage : 1 const page = !isNaN(parsedPage) && parsedPage > 0 ? parsedPage : 1
state.offset = (page - 1) * state.limitq state.offset = (page - 1) * state.limit
} }
if (urlParams.has('status')) { if (urlParams.has('status')) {
state.filters.status = urlParams.getAll('status') const status = urlParams.getAll('status')
state.filters.status = status as components['schemas']['Package']['status'][]
} }
if (urlParams.has('pkgbase')) { if (urlParams.has('pkgbase')) {
state.filters.pkgbase = urlParams.get('pkgbase') const pkgbase = urlParams.get('pkgbase')
if (pkgbase === null) return
state.filters.pkgbase = pkgbase as components['schemas']['Package']['pkgbase']
} }
if (urlParams.has('repo')) { if (urlParams.has('repo')) {
state.filters.repo = urlParams.get('repo') const repo = urlParams.get('repo')
if (repo === null) return
state.filters.repo = repo as components['schemas']['Package']['repo']
} }
if (urlParams.has('exact')) { if (urlParams.has('exact')) {