Compare commits
22 Commits
8fe8f1e122
...
main
Author | SHA1 | Date | |
---|---|---|---|
e384635da5 | |||
145de73133 | |||
35806589f0 | |||
7445919003 | |||
3886c7bcbd | |||
075c246710 | |||
555feddabf | |||
83debac064 | |||
24c3463c86 | |||
6f861798ba | |||
7ab90d4af6 | |||
d5f24feb9e | |||
ad5ce609fc | |||
c458b564ce | |||
bcb9569b26 | |||
90be95afda | |||
c864664536 | |||
9762505a24 | |||
9adeaa4483 | |||
43ce135fc6 | |||
4e722e5e60 | |||
265bfac74a |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,6 +11,8 @@
|
|||||||
.idea/**/usage.statistics.xml
|
.idea/**/usage.statistics.xml
|
||||||
.idea/**/dictionaries
|
.idea/**/dictionaries
|
||||||
.idea/**/shelf
|
.idea/**/shelf
|
||||||
|
.idea/codeStyles
|
||||||
|
.idea/codeStyles/*
|
||||||
|
|
||||||
# AWS User-specific
|
# AWS User-specific
|
||||||
.idea/**/aws.xml
|
.idea/**/aws.xml
|
||||||
|
19
api.go
19
api.go
@@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/go-chi/render"
|
"github.com/go-chi/render"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"somegit.dev/ALHP/ALHP.GO/ent"
|
"somegit.dev/ALHP/ALHP.GO/ent"
|
||||||
"somegit.dev/ALHP/ALHP.GO/ent/dbpackage"
|
"somegit.dev/ALHP/ALHP.GO/ent/dbpackage"
|
||||||
"somegit.dev/ALHP/ALHP.GO/ent/predicate"
|
"somegit.dev/ALHP/ALHP.GO/ent/predicate"
|
||||||
@@ -18,6 +19,8 @@ type StatsResponse struct {
|
|||||||
Skipped int `json:"skipped"`
|
Skipped int `json:"skipped"`
|
||||||
Latest int `json:"latest"`
|
Latest int `json:"latest"`
|
||||||
Queued int `json:"queued"`
|
Queued int `json:"queued"`
|
||||||
|
Building int `json:"building"`
|
||||||
|
LastMirrorTimestamp *int64 `json:"last_mirror_timestamp,omitempty"`
|
||||||
LTO *struct {
|
LTO *struct {
|
||||||
Enabled int `json:"enabled"`
|
Enabled int `json:"enabled"`
|
||||||
Disabled int `json:"disabled"`
|
Disabled int `json:"disabled"`
|
||||||
@@ -71,6 +74,8 @@ func GetStats(w http.ResponseWriter, r *http.Request) {
|
|||||||
resp.Latest = c.Count
|
resp.Latest = c.Count
|
||||||
case dbpackage.StatusQueued:
|
case dbpackage.StatusQueued:
|
||||||
resp.Queued = c.Count
|
resp.Queued = c.Count
|
||||||
|
case dbpackage.StatusBuilding:
|
||||||
|
resp.Building = c.Count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +98,20 @@ func GetStats(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if os.Getenv("ALHP_TIMESTAMP_PATH") != "" {
|
||||||
|
tsFile, err := os.ReadFile(os.Getenv("ALHP_TIMESTAMP_PATH"))
|
||||||
|
if err != nil {
|
||||||
|
log.Warningf("error reading timestamp file: %v", err)
|
||||||
|
} else {
|
||||||
|
ts, err := strconv.ParseInt(string(tsFile), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Warningf("error parsing timestamp file: %v", err)
|
||||||
|
} else {
|
||||||
|
resp.LastMirrorTimestamp = &ts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render.Status(r, http.StatusOK)
|
render.Status(r, http.StatusOK)
|
||||||
render.JSON(w, r, resp)
|
render.JSON(w, r, resp)
|
||||||
}
|
}
|
||||||
|
1
frontend/.gitignore
vendored
1
frontend/.gitignore
vendored
@@ -3,6 +3,7 @@ node_modules
|
|||||||
/dist
|
/dist
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
|
.env
|
||||||
.env.local
|
.env.local
|
||||||
.env.*.local
|
.env.*.local
|
||||||
|
|
||||||
|
8
frontend/components.d.ts
vendored
8
frontend/components.d.ts
vendored
@@ -9,10 +9,14 @@ export {}
|
|||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
BuildServerStats: typeof import('./src/components/BuildServerStats.vue')['default']
|
BuildServerStats: typeof import('./src/components/BuildServerStats.vue')['default']
|
||||||
BuildStats: typeof import('./src/components/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']
|
||||||
MainNav: typeof import('./src/components/MainNav.vue')['default']
|
MainNav: typeof import('./src/components/MainNav.vue')['default']
|
||||||
|
PackageFilters: typeof import('./src/components/Packages/PackageFilters.vue')['default']
|
||||||
Packages: typeof import('./src/components/Packages.vue')['default']
|
Packages: typeof import('./src/components/Packages.vue')['default']
|
||||||
QueuedPackagesList: typeof import('./src/components/QueuedPackagesList.vue')['default']
|
PackageTable: typeof import('./src/components/Packages/PackageTable.vue')['default']
|
||||||
|
QueuedPackagesList: typeof import('./src/components/CurrentlyBuilding/QueuedPackagesList.vue')['default']
|
||||||
|
StatItem: typeof import('./src/components/MainNav/BuildStats/StatItem.vue')['default']
|
||||||
|
StatsListSection: typeof import('./src/components/MainNav/BuildStats/StatsListSection.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
frontend/env.d.ts
vendored
Normal file
13
frontend/env.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
readonly VITE_BASE_URL: string
|
||||||
|
readonly VITE_UPDATE_INTERVAL: number
|
||||||
|
readonly VITE_LIMIT: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
readonly env: ImportMetaEnv
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@/*'
|
3
frontend/example.env
Normal file
3
frontend/example.env
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
VITE_BASE_URL="https://API.URL"
|
||||||
|
VITE_UPDATE_INTERVAL=5
|
||||||
|
VITE_LIMIT=50
|
@@ -2,6 +2,8 @@
|
|||||||
"name": "alhp-web",
|
"name": "alhp-web",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"generate-api-types": "yarn openapi-typescript ../openapi_alhp.yaml --output src/generated/alhp.ts",
|
||||||
|
"prebuild": "npm run generate-api-types",
|
||||||
"dev": "node --no-warnings ./node_modules/.bin/vite",
|
"dev": "node --no-warnings ./node_modules/.bin/vite",
|
||||||
"build": "vue-tsc --noEmit && vite build",
|
"build": "vue-tsc --noEmit && vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
@@ -10,21 +12,24 @@
|
|||||||
"@fontsource/roboto": "^5.2.5",
|
"@fontsource/roboto": "^5.2.5",
|
||||||
"@mdi/font": "7.4.47",
|
"@mdi/font": "7.4.47",
|
||||||
"fork-awesome": "^1.2.0",
|
"fork-awesome": "^1.2.0",
|
||||||
|
"openapi-fetch": "^0.13.5",
|
||||||
|
"pinia": "^3.0.2",
|
||||||
"roboto-fontface": "^0.10.0",
|
"roboto-fontface": "^0.10.0",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vuetify": "^3.7.18"
|
"vuetify": "^3.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/types": "^7.26.10",
|
"@babel/types": "^7.27.0",
|
||||||
"@types/node": "^22.13.11",
|
"@types/node": "^22.14.1",
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
|
"openapi-typescript": "^7.6.1",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"sass": "^1.86.0",
|
"sass": "^1.86.3",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.3",
|
||||||
"unplugin-fonts": "^1.3.1",
|
"unplugin-fonts": "^1.3.1",
|
||||||
"unplugin-vue-components": "^28.4.1",
|
"unplugin-vue-components": "^28.5.0",
|
||||||
"vite": "^6.2.2",
|
"vite": "^6.2.6",
|
||||||
"vite-plugin-vuetify": "^2.1.0",
|
"vite-plugin-vuetify": "^2.1.1",
|
||||||
"vue-tsc": "^2.2.8"
|
"vue-tsc": "^2.2.8"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@4.7.0"
|
"packageManager": "yarn@4.7.0"
|
||||||
|
@@ -15,6 +15,43 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import MainNav from '@/components/MainNav.vue'
|
import MainNav from '@/components/MainNav.vue'
|
||||||
import BuildServerStats from '@/components/BuildServerStats.vue'
|
import BuildServerStats from '@/components/BuildServerStats.vue'
|
||||||
import Packages from '@/components/Packages.vue'
|
|
||||||
import CurrentlyBuilding from '@/components/CurrentlyBuilding.vue'
|
import CurrentlyBuilding from '@/components/CurrentlyBuilding.vue'
|
||||||
|
import Packages from '@/components/Packages.vue'
|
||||||
|
import { useStatsStore } from '@/stores/statsStore'
|
||||||
|
import { onBeforeMount, onUnmounted } from 'vue'
|
||||||
|
import { usePackagesStore } from '@/stores'
|
||||||
|
|
||||||
|
const statsStore = useStatsStore()
|
||||||
|
const packagesStore = usePackagesStore()
|
||||||
|
|
||||||
|
let refreshInterval: number | null = null
|
||||||
|
const startAutoRefresh = (intervalMinutes = Number(import.meta.env.VITE_UPDATE_INTERVAL) || 5) => {
|
||||||
|
stopAutoRefresh()
|
||||||
|
refreshInterval = window.setInterval(
|
||||||
|
() => {
|
||||||
|
statsStore.fetchStats()
|
||||||
|
packagesStore.fetchPackages()
|
||||||
|
packagesStore.fetchCurrentlyBuilding()
|
||||||
|
},
|
||||||
|
intervalMinutes * 60 * 1000
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const stopAutoRefresh = () => {
|
||||||
|
if (refreshInterval !== null) {
|
||||||
|
clearInterval(refreshInterval)
|
||||||
|
refreshInterval = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
statsStore.fetchStats()
|
||||||
|
packagesStore.fetchPackages(true)
|
||||||
|
packagesStore.fetchCurrentlyBuilding()
|
||||||
|
startAutoRefresh()
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
stopAutoRefresh()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
106
frontend/src/api/README.md
Normal file
106
frontend/src/api/README.md
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# ALHP API Client
|
||||||
|
|
||||||
|
This directory contains a type-safe API client for the ALHP API, generated from the OpenAPI specification.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Importing
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Import the API client and its functions
|
||||||
|
import { apiClient, getPackages, getStats } from '@/api';
|
||||||
|
|
||||||
|
// Import types
|
||||||
|
import type { components } from '@/api';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fetching Packages
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { getPackages } from '@/api';
|
||||||
|
import type { components } from '@/api';
|
||||||
|
|
||||||
|
// Example: Get packages with filtering
|
||||||
|
async function fetchPackages() {
|
||||||
|
try {
|
||||||
|
const result = await getPackages({
|
||||||
|
status: ['latest', 'building'],
|
||||||
|
pkgbase: 'linux',
|
||||||
|
exact: false,
|
||||||
|
repo: 'core-x86-64-v3',
|
||||||
|
offset: 0,
|
||||||
|
limit: 50
|
||||||
|
});
|
||||||
|
|
||||||
|
// Access the packages
|
||||||
|
const packages: components['schemas']['Package'][] = result.packages || [];
|
||||||
|
const total: number = result.total || 0;
|
||||||
|
|
||||||
|
return { packages, total };
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch packages:', error);
|
||||||
|
return { packages: [], total: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fetching Stats
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { getStats } from '@/api';
|
||||||
|
import type { components } from '@/api';
|
||||||
|
|
||||||
|
// Example: Get build statistics
|
||||||
|
async function fetchStats() {
|
||||||
|
try {
|
||||||
|
const stats = await getStats();
|
||||||
|
|
||||||
|
// Access the stats
|
||||||
|
const failedCount: number = stats.failed || 0;
|
||||||
|
const ltoEnabled: number = stats.lto?.enabled || 0;
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch stats:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using the Raw API Client
|
||||||
|
|
||||||
|
If you need more control or want to use endpoints not covered by the utility functions, you can use the raw API client:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { apiClient } from '@/api';
|
||||||
|
|
||||||
|
// Example: Custom API call
|
||||||
|
async function customApiCall() {
|
||||||
|
const { data, error } = await apiClient.GET('/packages', {
|
||||||
|
params: {
|
||||||
|
query: {
|
||||||
|
// Your custom parameters
|
||||||
|
status: ['latest'],
|
||||||
|
limit: 10,
|
||||||
|
offset: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error('API error:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
The API client uses types generated from the OpenAPI specification. The main types are:
|
||||||
|
|
||||||
|
- `components['schemas']['Package']`: Type for package data
|
||||||
|
- `components['schemas']['Stats']`: Type for statistics data
|
||||||
|
|
||||||
|
These types provide full TypeScript intellisense and type checking.
|
59
frontend/src/api/client.ts
Normal file
59
frontend/src/api/client.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import createFetch from 'openapi-fetch'
|
||||||
|
import type { paths } from '@/generated/alhp'
|
||||||
|
|
||||||
|
// Create a type-safe API client using the OpenAPI types
|
||||||
|
const apiClient = createFetch<paths>({
|
||||||
|
baseUrl: import.meta.env.VITE_BASE_URL
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get packages with optional filtering
|
||||||
|
* @param params Query parameters for filtering packages
|
||||||
|
* @returns Promise with the packages response
|
||||||
|
*/
|
||||||
|
export const getPackages = async (params: {
|
||||||
|
status?: Array<
|
||||||
|
| 'latest'
|
||||||
|
| 'failed'
|
||||||
|
| 'built'
|
||||||
|
| 'skipped'
|
||||||
|
| 'delayed'
|
||||||
|
| 'building'
|
||||||
|
| 'signing'
|
||||||
|
| 'unknown'
|
||||||
|
| 'queued'
|
||||||
|
>
|
||||||
|
pkgbase?: string
|
||||||
|
exact?: boolean
|
||||||
|
repo?: string
|
||||||
|
offset: number
|
||||||
|
limit: number
|
||||||
|
}) => {
|
||||||
|
const { data, error } = await apiClient.GET('/packages', {
|
||||||
|
params: {
|
||||||
|
query: params
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw new Error(`Failed to fetch packages: ${(error as any).statusCode}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get build statistics
|
||||||
|
* @returns Promise with the stats response
|
||||||
|
*/
|
||||||
|
export const getStats = async () => {
|
||||||
|
const { data, error } = await apiClient.GET('/stats')
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw new Error(`Failed to fetch stats: ${(error as any).statusCode || 'unknown error'}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
export default apiClient
|
6
frontend/src/api/index.ts
Normal file
6
frontend/src/api/index.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Export the API client and its functions
|
||||||
|
export { default as apiClient } from './client';
|
||||||
|
export { getPackages, getStats } from './client';
|
||||||
|
|
||||||
|
// Export types from the generated OpenAPI file
|
||||||
|
export type { components } from '../generated/alhp';
|
@@ -2,7 +2,7 @@
|
|||||||
<v-sheet class="mt-2" color="transparent">
|
<v-sheet class="mt-2" color="transparent">
|
||||||
<h5 class="text-h5">Buildserver Stats</h5>
|
<h5 class="text-h5">Buildserver Stats</h5>
|
||||||
<iframe
|
<iframe
|
||||||
:height="width <= 800 ? `${IFRAME_HEIGHT}px` : '420px'"
|
:height="iframeHeight"
|
||||||
allowtransparency="true"
|
allowtransparency="true"
|
||||||
class="w-100 border-0"
|
class="w-100 border-0"
|
||||||
src="https://stats.itsh.dev/public-dashboards/0fb04abb0c5e4b7390cf26a98e6dead1"></iframe>
|
src="https://stats.itsh.dev/public-dashboards/0fb04abb0c5e4b7390cf26a98e6dead1"></iframe>
|
||||||
@@ -11,40 +11,14 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const { width } = useDisplay()
|
const { width } = useDisplay()
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the height of a graph in pixels.
|
|
||||||
* This constant is used to define the vertical dimension of the graph
|
|
||||||
* when rendering it in a user interface or graphical representation.
|
|
||||||
*
|
|
||||||
* @constant {number} GRAPH_HEIGHT
|
|
||||||
*/
|
|
||||||
const GRAPH_HEIGHT = 335
|
const GRAPH_HEIGHT = 335
|
||||||
/**
|
|
||||||
* Represents the total number of graphs to be processed or displayed.
|
|
||||||
*
|
|
||||||
* This variable is used to define the fixed amount of graphs that the system
|
|
||||||
* is intended to handle at a given time. It can be leveraged to set limits
|
|
||||||
* on iterations, arrays, or display logic related to graph management.
|
|
||||||
*
|
|
||||||
* Default value: 4
|
|
||||||
*
|
|
||||||
* Type: number
|
|
||||||
*/
|
|
||||||
const NUMBER_OF_GRAPHS = 4
|
const NUMBER_OF_GRAPHS = 4
|
||||||
/**
|
|
||||||
* Represents the height of an iframe calculated dynamically based on the number of graphs
|
const iframeHeight = computed(() =>
|
||||||
* and the height of each graph.
|
width.value <= 800 ? `${NUMBER_OF_GRAPHS * GRAPH_HEIGHT}px` : '420px'
|
||||||
*
|
)
|
||||||
* IFRAME_HEIGHT is determined by multiplying the number of graphs (`NUMBER_OF_GRAPHS`)
|
|
||||||
* displayed in the iframe by the height of a single graph (`GRAPH_HEIGHT`).
|
|
||||||
*
|
|
||||||
* This variable is commonly used to ensure the iframe adjusts correctly to accommodate
|
|
||||||
* all graphs without introducing unnecessary scrollbars.
|
|
||||||
*
|
|
||||||
* @constant {number} IFRAME_HEIGHT
|
|
||||||
*/
|
|
||||||
const IFRAME_HEIGHT = NUMBER_OF_GRAPHS * GRAPH_HEIGHT
|
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,102 +0,0 @@
|
|||||||
<template>
|
|
||||||
<v-sheet :style="sheetStyles" class="d-flex" color="transparent">
|
|
||||||
<!-- Dynamically render the "Stats" section -->
|
|
||||||
<v-list :style="listStyles" bg-color="transparent" class="d-flex">
|
|
||||||
<v-list-subheader>Stats:</v-list-subheader>
|
|
||||||
<v-list-item
|
|
||||||
v-for="item in statsList"
|
|
||||||
:key="item.label"
|
|
||||||
:style="{ color: item.color }"
|
|
||||||
:title="item.label">
|
|
||||||
{{ item.value }}
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
<!-- Dynamically render the "LTO" section -->
|
|
||||||
<v-list :style="listStyles" bg-color="transparent" class="d-flex">
|
|
||||||
<v-list-subheader>LTO:</v-list-subheader>
|
|
||||||
<v-list-item
|
|
||||||
v-for="item in ltoList"
|
|
||||||
:key="item.label"
|
|
||||||
:style="{ color: item.color }"
|
|
||||||
:title="item.label">
|
|
||||||
{{ item.value }}
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-sheet>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { onMounted, ref } from 'vue'
|
|
||||||
import { type Stats } from '@/types/Stats'
|
|
||||||
|
|
||||||
// Define reusable styles and colors
|
|
||||||
const sheetStyles = { gap: '50px' }
|
|
||||||
const listStyles = { borderRadius: '5px' }
|
|
||||||
const colors = {
|
|
||||||
latest: '#069b35',
|
|
||||||
queued: '#b97808',
|
|
||||||
skipped: '#878787',
|
|
||||||
failed: '#b30303',
|
|
||||||
enabled: '#069b35',
|
|
||||||
disabled: '#b30303',
|
|
||||||
unknown: '#878787'
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reactive stats object
|
|
||||||
const stats = ref<Stats>({
|
|
||||||
latest: 0,
|
|
||||||
queued: 0,
|
|
||||||
skipped: 0,
|
|
||||||
failed: 0,
|
|
||||||
lto: {
|
|
||||||
enabled: 0,
|
|
||||||
disabled: 0,
|
|
||||||
unknown: 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Map stats and LTO data for simpler rendering in the template
|
|
||||||
const statsList = ref([
|
|
||||||
{ label: 'latest', value: stats.value.latest, color: colors.latest },
|
|
||||||
{ label: 'queued', value: stats.value.queued, color: colors.queued },
|
|
||||||
{ label: 'skipped', value: stats.value.skipped, color: colors.skipped },
|
|
||||||
{ label: 'failed', value: stats.value.failed, color: colors.failed }
|
|
||||||
])
|
|
||||||
|
|
||||||
const ltoList = ref([
|
|
||||||
{ label: 'enabled', value: stats.value.lto.enabled, color: colors.enabled },
|
|
||||||
{ label: 'disabled', value: stats.value.lto.disabled, color: colors.disabled },
|
|
||||||
{ label: 'unknown', value: stats.value.lto.unknown, color: colors.unknown }
|
|
||||||
])
|
|
||||||
|
|
||||||
// Function to fetch stats data (refactored with async/await)
|
|
||||||
const getStats = async (): Promise<void> => {
|
|
||||||
try {
|
|
||||||
const response = await fetch('https://api.alhp.dev/stats')
|
|
||||||
if (!response.ok) throw new Error(response.statusText)
|
|
||||||
|
|
||||||
const statistics = await response.json()
|
|
||||||
stats.value = statistics
|
|
||||||
|
|
||||||
// Update lists with fresh data
|
|
||||||
statsList.value = [
|
|
||||||
{ label: 'latest', value: stats.value.latest, color: colors.latest },
|
|
||||||
{ label: 'queued', value: stats.value.queued, color: colors.queued },
|
|
||||||
{ label: 'skipped', value: stats.value.skipped, color: colors.skipped },
|
|
||||||
{ label: 'failed', value: stats.value.failed, color: colors.failed }
|
|
||||||
]
|
|
||||||
ltoList.value = [
|
|
||||||
{ label: 'enabled', value: stats.value.lto.enabled, color: colors.enabled },
|
|
||||||
{ label: 'disabled', value: stats.value.lto.disabled, color: colors.disabled },
|
|
||||||
{ label: 'unknown', value: stats.value.lto.unknown, color: colors.unknown }
|
|
||||||
]
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to fetch stats:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch stats on mount
|
|
||||||
onMounted(() => {
|
|
||||||
getStats()
|
|
||||||
})
|
|
||||||
</script>
|
|
@@ -11,18 +11,32 @@
|
|||||||
<v-row :class="mobile ? 'mt-1' : ''" class="flex-nowrap ms-1 d-flex align-items-center">
|
<v-row :class="mobile ? 'mt-1' : ''" class="flex-nowrap ms-1 d-flex align-items-center">
|
||||||
<div
|
<div
|
||||||
:class="
|
:class="
|
||||||
packageCount.building > 0 ? 'pulsating-circle-amber' : 'pulsating-circle-green'
|
updateFailed
|
||||||
|
? 'pulsating-circle-error'
|
||||||
|
: packageArrays.building.length > 0
|
||||||
|
? 'pulsating-circle-amber'
|
||||||
|
: 'pulsating-circle-green'
|
||||||
"
|
"
|
||||||
class="circle-offset flex-circle" />
|
class="circle-offset flex-circle" />
|
||||||
<span class="ms-2">
|
<span class="ms-2">
|
||||||
{{ packageCount.building > 0 ? 'Building' : 'Idle' }}
|
{{
|
||||||
|
updateFailed
|
||||||
|
? 'Could not fetch data.'
|
||||||
|
: packageArrays.building.length > 0
|
||||||
|
? 'Building'
|
||||||
|
: 'Idle'
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col v-if="packageCount.building > 0" class="v-col-12 v-col-lg-8 mb-3">
|
<v-col v-if="packageArrays.building.length > 0" class="v-col-12 v-col-lg-8 mb-3">
|
||||||
<v-progress-linear
|
<v-progress-linear
|
||||||
:max="packageCount.built + packageCount.building + packageCount.queued"
|
:max="
|
||||||
:model-value="packageCount.built"
|
packageArrays.built.length +
|
||||||
|
packageArrays.building.length +
|
||||||
|
packageArrays.queued.length
|
||||||
|
"
|
||||||
|
:model-value="packageArrays.built.length"
|
||||||
color="light-blue"
|
color="light-blue"
|
||||||
height="10"
|
height="10"
|
||||||
rounded
|
rounded
|
||||||
@@ -33,21 +47,41 @@
|
|||||||
class="text-grey v-col-12 v-col-lg-2 mb-3"
|
class="text-grey v-col-12 v-col-lg-2 mb-3"
|
||||||
cols="auto"
|
cols="auto"
|
||||||
style="font-size: 13px">
|
style="font-size: 13px">
|
||||||
|
<div v-if="!updateFailed" class="d-flex flex-column">
|
||||||
|
<span>
|
||||||
Last updated
|
Last updated
|
||||||
|
{{ formatTimeAgo(lastUpdatedSeconds) }}
|
||||||
|
<v-tooltip activator="parent" location="start">
|
||||||
{{
|
{{
|
||||||
lastUpdatedSeconds > 59
|
unixTimestampToLocalizedDate(
|
||||||
? rtf.format(-Math.floor(lastUpdatedSeconds / 60), 'minutes')
|
Math.floor((packagesStore.state.lastUpdated || Date.now()) / 1000)
|
||||||
: rtf.format(-lastUpdatedSeconds, 'seconds')
|
)
|
||||||
}}
|
}}
|
||||||
|
</v-tooltip>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
Last Mirror sync
|
||||||
|
{{ formatTimeAgo(lastMirrorSync) }}
|
||||||
|
<v-tooltip activator="parent" location="start">
|
||||||
|
{{
|
||||||
|
unixTimestampToLocalizedDate(
|
||||||
|
statsStore.state.stats?.last_mirror_timestamp || Math.floor(Date.now() / 1000)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</v-tooltip>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-else>Please try again later.</template>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-card-text
|
<v-card-text
|
||||||
v-if="packageCount.building > 0 || packageCount.queued > 0"
|
v-if="packageArrays.building.length > 0 || packageArrays.queued.length > 0"
|
||||||
class="d-flex flex-column">
|
class="d-flex flex-column">
|
||||||
<v-list width="100%">
|
<v-list v-if="packageArrays.building.length > 0" class="mb-4" width="100%">
|
||||||
<v-list-subheader>Building</v-list-subheader>
|
<v-list-subheader>Building</v-list-subheader>
|
||||||
<v-list-item v-for="(pkg, index) in packages.building" :key="index">
|
<v-list-item v-for="(pkg, index) in packageArrays.building" :key="index">
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<div class="pulsating-circle-amber me-4" />
|
<div class="pulsating-circle-amber me-4" />
|
||||||
</template>
|
</template>
|
||||||
@@ -58,124 +92,87 @@
|
|||||||
<v-list-item-subtitle>{{ pkg.arch_version }}</v-list-item-subtitle>
|
<v-list-item-subtitle>{{ pkg.arch_version }}</v-list-item-subtitle>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
<v-sheet class="ps-4 mt-4" color="transparent" rounded width="100%">
|
<v-sheet class="ps-4" color="transparent" rounded width="100%">
|
||||||
<h4 class="mb-2 font-weight-light text-grey">Queued</h4>
|
<h4 class="mb-2 font-weight-light text-grey">Queued</h4>
|
||||||
<QueuedPackagesList :packages="packages.queued" />
|
<queued-packages-list :packages="packageArrays.queued" />
|
||||||
</v-sheet>
|
</v-sheet>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from 'vue'
|
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||||
import type { Packages } from '@/types/Packages'
|
|
||||||
import { Package } from '@/types/Package'
|
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
import QueuedPackagesList from './QueuedPackagesList.vue'
|
import QueuedPackagesList from '@/components/CurrentlyBuilding/QueuedPackagesList.vue'
|
||||||
|
import { usePackagesStore, useStatsStore } from '@/stores'
|
||||||
|
|
||||||
const BASE_URL = 'https://api.alhp.dev/packages'
|
const statsStore = useStatsStore()
|
||||||
const UPDATE_INTERVAL_MINUTES = 5
|
const packagesStore = usePackagesStore()
|
||||||
|
|
||||||
const { mobile } = useDisplay()
|
const { mobile } = useDisplay()
|
||||||
const lastUpdatedTime = ref(0)
|
|
||||||
const lastUpdatedSeconds = ref(0)
|
|
||||||
const rtf = new Intl.RelativeTimeFormat('en', {
|
const rtf = new Intl.RelativeTimeFormat('en', {
|
||||||
localeMatcher: 'best fit',
|
localeMatcher: 'best fit',
|
||||||
numeric: 'always',
|
numeric: 'always',
|
||||||
style: 'long'
|
style: 'long'
|
||||||
})
|
})
|
||||||
|
|
||||||
const packageCount = ref({
|
const now = ref(Math.floor(Date.now() / 1000))
|
||||||
total: 0,
|
|
||||||
building: 0,
|
const updateFailed = computed(
|
||||||
built: 0,
|
() => !!packagesStore.state.errorCurrentlyBuilding || !!statsStore.state.error
|
||||||
queued: 0
|
)
|
||||||
|
const lastUpdatedSeconds = computed(
|
||||||
|
() => now.value - Math.floor((packagesStore.state.lastUpdated || Date.now()) / 1000)
|
||||||
|
)
|
||||||
|
const lastMirrorSync = computed(
|
||||||
|
() => now.value - (statsStore.state.stats?.last_mirror_timestamp || Math.floor(Date.now() / 1000))
|
||||||
|
)
|
||||||
|
|
||||||
|
const packageArrays = reactive({
|
||||||
|
building: computed(
|
||||||
|
() =>
|
||||||
|
packagesStore.state.currentlyBuildingPackages.filter((pkg) => pkg.status === 'building') || []
|
||||||
|
),
|
||||||
|
queued: computed(
|
||||||
|
() =>
|
||||||
|
packagesStore.state.currentlyBuildingPackages.filter((pkg) => pkg.status === 'queued') || []
|
||||||
|
),
|
||||||
|
built: computed(
|
||||||
|
() =>
|
||||||
|
packagesStore.state.currentlyBuildingPackages.filter((pkg) => pkg.status === 'built') || []
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const packages = ref<{
|
let updateTimer: number | undefined
|
||||||
built: Array<Package>
|
const startLastUpdatedTimer = () => {
|
||||||
building: Array<Package>
|
updateTimer = window.setInterval(() => {
|
||||||
queued: Array<Package>
|
now.value = Math.floor(Date.now() / 1000)
|
||||||
}>({
|
}, 1000)
|
||||||
built: [],
|
|
||||||
building: [],
|
|
||||||
queued: []
|
|
||||||
})
|
|
||||||
|
|
||||||
const fetchPackages = async (endpoint: string, status?: string) => {
|
|
||||||
let url = `${BASE_URL}?limit=0&offset=0`
|
|
||||||
if (status) {
|
|
||||||
url += `&status=${status}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const formatTimeAgo = (seconds: number): string => {
|
||||||
const response = await fetch(url, { method: 'GET' })
|
if (seconds >= 3600) {
|
||||||
if (!response.ok) {
|
return rtf.format(-Math.floor(seconds / 3600), 'hours')
|
||||||
throw new Error(`HTTP error! status: ${response.status}`)
|
} else if (seconds >= 60) {
|
||||||
}
|
return rtf.format(-Math.floor(seconds / 60), 'minutes')
|
||||||
const json: Packages = await response.json()
|
} else {
|
||||||
return json
|
return rtf.format(-seconds, 'seconds')
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching packages:', error)
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTotalPackages = async () => {
|
function unixTimestampToLocalizedDate(timestamp: number): string {
|
||||||
const json = await fetchPackages(`${BASE_URL}?limit=1&offset=0`)
|
const date = new Date(timestamp * 1000) // convert to milliseconds
|
||||||
if (json) {
|
return date.toLocaleString(navigator.language)
|
||||||
packageCount.value.total = json.total
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getBuiltPackages = async () => {
|
|
||||||
const json = await fetchPackages(`${BASE_URL}?limit=0&offset=0`, 'built')
|
|
||||||
if (json) {
|
|
||||||
packageCount.value.built = json.total
|
|
||||||
packages.value.built = json.packages
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getBuildingPackages = async () => {
|
|
||||||
const json = await fetchPackages(`${BASE_URL}?limit=0&offset=0`, 'building')
|
|
||||||
if (json) {
|
|
||||||
packageCount.value.building = json.total
|
|
||||||
packages.value.building = json.packages
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getQueuedPackages = async () => {
|
|
||||||
const json = await fetchPackages(`${BASE_URL}?limit=0&offset=0`, 'queued')
|
|
||||||
if (json) {
|
|
||||||
packageCount.value.queued = json.total
|
|
||||||
packages.value.queued = json.packages
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getTotalPackages()
|
startLastUpdatedTimer()
|
||||||
getBuiltPackages()
|
})
|
||||||
getBuildingPackages()
|
|
||||||
getQueuedPackages()
|
|
||||||
|
|
||||||
lastUpdatedTime.value = Date.now()
|
onUnmounted(() => {
|
||||||
lastUpdatedSeconds.value = Math.floor((Date.now() - lastUpdatedTime.value) / 1000)
|
if (updateTimer) {
|
||||||
|
clearInterval(updateTimer)
|
||||||
setInterval(() => {
|
}
|
||||||
lastUpdatedSeconds.value = Math.floor((Date.now() - lastUpdatedTime.value) / 1000)
|
|
||||||
}, 1000)
|
|
||||||
|
|
||||||
setInterval(
|
|
||||||
() => {
|
|
||||||
getTotalPackages()
|
|
||||||
getBuiltPackages()
|
|
||||||
getBuildingPackages()
|
|
||||||
getQueuedPackages()
|
|
||||||
lastUpdatedTime.value = Date.now()
|
|
||||||
lastUpdatedSeconds.value = Math.floor((Date.now() - lastUpdatedTime.value) / 1000)
|
|
||||||
},
|
|
||||||
UPDATE_INTERVAL_MINUTES * 60 * 1000
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -222,16 +219,37 @@ onMounted(() => {
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pulsating-circle-error {
|
||||||
|
background-color: rgba(225, 64, 6, 0.94);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulsating-circle-error:before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 200%;
|
||||||
|
height: 200%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-left: -50%;
|
||||||
|
margin-top: -50%;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: rgba(225, 64, 6, 0.94);
|
||||||
|
-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;
|
||||||
|
}
|
||||||
|
|
||||||
.circle-offset {
|
.circle-offset {
|
||||||
transform: translateY(10px); /* Preserves vertical shift as needed */
|
transform: translateY(10px); /* Preserves vertical shift as needed */
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex-circle {
|
.flex-circle {
|
||||||
flex-shrink: 0; /* Prevents shrinking */
|
flex-shrink: 0;
|
||||||
flex-grow: 0; /* Prevents growing */
|
flex-grow: 0;
|
||||||
width: 12px; /* Ensures consistent dimensions */
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
border-radius: 50%; /* Maintains circular appearance */
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@-webkit-keyframes pulse-ring {
|
@-webkit-keyframes pulse-ring {
|
||||||
|
@@ -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: () => []
|
||||||
}
|
}
|
@@ -1,38 +1,102 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app-bar color="#191c2a" style="background: #0d1538">
|
<v-app-bar :color="appBarColors.background" aria-label="Main Navigation" role="navigation">
|
||||||
<v-container :class="width < 1440 ? 'ms-3' : 'mx-auto'" fluid style="max-width: 1440px">
|
<v-container :class="containerClasses" :style="{ maxWidth: maxContainerWidth }" fluid>
|
||||||
<v-row>
|
<v-row align="center">
|
||||||
<v-app-bar-title style="align-self: center">
|
<v-app-bar-title class="app-title">
|
||||||
<span style="font-size: 20px">
|
<span aria-label="Home" class="home-link" role="button" tabindex="0">
|
||||||
ALHP Status
|
{{ appTitle }}
|
||||||
<a class="ms-2 gitea-link" href="https://somegit.dev/ALHP/ALHP.GO" target="_blank">
|
|
||||||
<i class="fa fa-gitea"></i>
|
|
||||||
</a>
|
|
||||||
</span>
|
</span>
|
||||||
|
<a
|
||||||
|
:href="repoUrl"
|
||||||
|
aria-label="ALHP GitHub Repository"
|
||||||
|
class="ms-2 gitea-link"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
target="_blank">
|
||||||
|
<i aria-hidden="true" class="fa fa-gitea"></i>
|
||||||
|
</a>
|
||||||
</v-app-bar-title>
|
</v-app-bar-title>
|
||||||
|
|
||||||
<build-stats v-if="!mobile" />
|
<v-spacer v-if="isDesktop"></v-spacer>
|
||||||
|
|
||||||
|
<build-stats v-if="isDesktop || isTablet" :show-lto="isDesktop" />
|
||||||
|
|
||||||
|
<!-- Mobile menu button could be added here -->
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import BuildStats from '@/components/BuildStats.vue'
|
import BuildStats from '@/components/MainNav/BuildStats.vue'
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const { mobile, width } = useDisplay()
|
const { mobile, width } = useDisplay()
|
||||||
|
const isTablet = computed(() => mobile && width.value >= 650 && width.value < 960)
|
||||||
|
const isDesktop = computed(() => !mobile.value && !isTablet.value)
|
||||||
|
|
||||||
|
interface AppBarColors {
|
||||||
|
background: string
|
||||||
|
accent: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const appTitle = 'ALHP Status'
|
||||||
|
const repoUrl = 'https://somegit.dev/ALHP/ALHP.GO'
|
||||||
|
const maxContainerWidth = '1440px'
|
||||||
|
const appBarColors: AppBarColors = {
|
||||||
|
background: '#0d1538',
|
||||||
|
accent: '#609926'
|
||||||
|
}
|
||||||
|
|
||||||
|
const containerClasses = computed(() => ({
|
||||||
|
'ms-3': width.value < 1440,
|
||||||
|
'mx-auto': width.value >= 1440
|
||||||
|
}))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.app-title {
|
||||||
|
align-self: center;
|
||||||
|
font-size: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-link {
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-link:hover,
|
||||||
|
.home-link:focus {
|
||||||
|
opacity: 0.9;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
.gitea-link {
|
.gitea-link {
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
text-decoration: none; /* Optional: To prevent underlining */
|
text-decoration: none;
|
||||||
transition: color 0.2s; /* Smooth color transition */
|
transition: color 0.2s;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gitea-link:hover {
|
.gitea-link:hover,
|
||||||
color: #609926;
|
.gitea-link:focus {
|
||||||
|
color: v-bind('appBarColors.accent');
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.app-title {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gitea-link {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
104
frontend/src/components/MainNav/BuildStats.vue
Normal file
104
frontend/src/components/MainNav/BuildStats.vue
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<template>
|
||||||
|
<v-sheet
|
||||||
|
v-if="!statsStore.state.loading && !statsStore.state.error"
|
||||||
|
:style="sheetStyles"
|
||||||
|
class="d-flex"
|
||||||
|
color="transparent">
|
||||||
|
<StatsListSection title="Stats">
|
||||||
|
<StatItem
|
||||||
|
v-for="(stat, key) in generalStats"
|
||||||
|
:key="key"
|
||||||
|
:color="stat.color"
|
||||||
|
:count="stat.count"
|
||||||
|
:title="key" />
|
||||||
|
</StatsListSection>
|
||||||
|
|
||||||
|
<StatsListSection v-if="showLto" title="LTO">
|
||||||
|
<StatItem
|
||||||
|
v-for="(stat, key) in ltoStats"
|
||||||
|
:key="key"
|
||||||
|
:color="stat.color"
|
||||||
|
:count="stat.count"
|
||||||
|
:title="key" />
|
||||||
|
</StatsListSection>
|
||||||
|
</v-sheet>
|
||||||
|
<v-sheet
|
||||||
|
v-else-if="statsStore.state.loading"
|
||||||
|
:style="sheetStyles"
|
||||||
|
class="d-flex align-center"
|
||||||
|
color="transparent">
|
||||||
|
<v-progress-circular class="mr-2" color="white" indeterminate size="20"></v-progress-circular>
|
||||||
|
<span class="text-caption">Loading stats...</span>
|
||||||
|
</v-sheet>
|
||||||
|
<v-sheet
|
||||||
|
v-else-if="statsStore.state.error"
|
||||||
|
:style="sheetStyles"
|
||||||
|
class="d-flex align-center"
|
||||||
|
color="transparent">
|
||||||
|
<span class="text-caption text-error">Error loading stats</span>
|
||||||
|
</v-sheet>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useStatsStore } from '@/stores/statsStore'
|
||||||
|
import StatsListSection from '@/components/MainNav/BuildStats/StatsListSection.vue'
|
||||||
|
import StatItem from '@/components/MainNav/BuildStats/StatItem.vue'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
showLto?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
withDefaults(defineProps<Props>(), {
|
||||||
|
showLto: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const COLORS = {
|
||||||
|
SUCCESS: '#069b35',
|
||||||
|
WARNING: '#b97808',
|
||||||
|
ERROR: '#b30303',
|
||||||
|
NEUTRAL: '#878787'
|
||||||
|
}
|
||||||
|
|
||||||
|
const sheetStyles = { gap: '50px' }
|
||||||
|
|
||||||
|
const statsStore = useStatsStore()
|
||||||
|
|
||||||
|
const generalStats = computed(() => ({
|
||||||
|
latest: {
|
||||||
|
count: statsStore.state.stats?.latest || 0,
|
||||||
|
color: COLORS.SUCCESS
|
||||||
|
},
|
||||||
|
queued: {
|
||||||
|
count: statsStore.state.stats?.queued || 0,
|
||||||
|
color: COLORS.WARNING
|
||||||
|
},
|
||||||
|
building: {
|
||||||
|
count: statsStore.state.stats?.building || 0,
|
||||||
|
color: COLORS.WARNING
|
||||||
|
},
|
||||||
|
skipped: {
|
||||||
|
count: statsStore.state.stats?.skipped || 0,
|
||||||
|
color: COLORS.NEUTRAL
|
||||||
|
},
|
||||||
|
failed: {
|
||||||
|
count: statsStore.state.stats?.failed || 0,
|
||||||
|
color: COLORS.ERROR
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
const ltoStats = computed(() => ({
|
||||||
|
enabled: {
|
||||||
|
count: statsStore.state.stats?.lto?.enabled || 0,
|
||||||
|
color: COLORS.SUCCESS
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
count: statsStore.state.stats?.lto?.disabled || 0,
|
||||||
|
color: COLORS.ERROR
|
||||||
|
},
|
||||||
|
unknown: {
|
||||||
|
count: statsStore.state.stats?.lto?.unknown || 0,
|
||||||
|
color: COLORS.NEUTRAL
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
</script>
|
13
frontend/src/components/MainNav/BuildStats/StatItem.vue
Normal file
13
frontend/src/components/MainNav/BuildStats/StatItem.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<v-list-item :style="{ color }" :title="title">
|
||||||
|
{{ count }}
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
defineProps<{
|
||||||
|
title: string
|
||||||
|
count: number
|
||||||
|
color: string
|
||||||
|
}>()
|
||||||
|
</script>
|
@@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<v-list bg-color="transparent" class="stats-list d-flex">
|
||||||
|
<v-list-subheader>{{ title }}:</v-list-subheader>
|
||||||
|
<slot></slot>
|
||||||
|
</v-list>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
defineProps<{
|
||||||
|
title: string
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.stats-list {
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -1,398 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-sheet :color="TRANSPARENT_COLOR" class="mt-6" width="100%">
|
<v-sheet :color="TRANSPARENT_COLOR" class="mt-6" width="100%">
|
||||||
<h5 class="text-h5 mb-4">Packages</h5>
|
<h5 class="text-h5 mb-4">Packages</h5>
|
||||||
<v-row :style="mobile ? '' : `height: ${ROW_HEIGHT}px`" width="100%">
|
|
||||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-2">
|
<PackageFilters />
|
||||||
<v-text-field
|
|
||||||
v-model="inputPkgBase"
|
<PackageTable />
|
||||||
clearable
|
|
||||||
color="primary"
|
|
||||||
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="selectedRepo"
|
|
||||||
:items="selectRepoItems"
|
|
||||||
clearable
|
|
||||||
color="primary"
|
|
||||||
item-title="title"
|
|
||||||
item-value="value"
|
|
||||||
placeholder="Any Repo"
|
|
||||||
return-object
|
|
||||||
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="selectedStatuses"
|
|
||||||
:items="selectStatusItems"
|
|
||||||
chips
|
|
||||||
closable-chips
|
|
||||||
color="primary"
|
|
||||||
density="default"
|
|
||||||
item-title="title"
|
|
||||||
item-value="value"
|
|
||||||
multiple
|
|
||||||
placeholder="Any Status"
|
|
||||||
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"
|
|
||||||
:length="pagesMax"
|
|
||||||
:total-visible="mobile ? undefined : 3"
|
|
||||||
active-color="primary"
|
|
||||||
density="comfortable"
|
|
||||||
start="1"
|
|
||||||
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>
|
|
||||||
<th scope="col">Repository</th>
|
|
||||||
<th scope="col">Pkgbase</th>
|
|
||||||
<th scope="col">Status</th>
|
|
||||||
<th scope="col">Reason</th>
|
|
||||||
<th scope="col">
|
|
||||||
LTO
|
|
||||||
<v-tooltip activator="parent" location="bottom">
|
|
||||||
Link time optimization;
|
|
||||||
<br />
|
|
||||||
Does not guarantee that package is actually built with LTO
|
|
||||||
</v-tooltip>
|
|
||||||
</th>
|
|
||||||
<th scope="col">
|
|
||||||
DS
|
|
||||||
<v-tooltip activator="parent" location="bottom">
|
|
||||||
Debug-symbols available via debuginfod
|
|
||||||
</v-tooltip>
|
|
||||||
</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: ${getStatusColor(pkg.status)};`">
|
|
||||||
<td class="font-weight-bold text-no-wrap">
|
|
||||||
{{ repoName(pkg.repo) }}
|
|
||||||
<v-chip
|
|
||||||
:color="getVersionColor(repoVersion(pkg.repo))"
|
|
||||||
class="ms-2"
|
|
||||||
density="comfortable"
|
|
||||||
label
|
|
||||||
variant="flat">
|
|
||||||
{{ repoVersion(pkg.repo) }}
|
|
||||||
</v-chip>
|
|
||||||
</td>
|
|
||||||
<td class="text-no-wrap">{{ 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(-22px);
|
|
||||||
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>
|
</v-sheet>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref, watch } from 'vue'
|
import { TRANSPARENT_COLOR } from '@/config/constants'
|
||||||
import { type Package } from '@/types/Package'
|
import PackageFilters from '@/components/Packages/PackageFilters.vue'
|
||||||
import { type Packages } from '@/types/Packages'
|
import PackageTable from '@/components/Packages/PackageTable.vue'
|
||||||
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()
|
|
||||||
|
|
||||||
// Select Items
|
|
||||||
const selectRepoItems = [
|
|
||||||
{ 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 selectStatusItems = [
|
|
||||||
{ 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' }
|
|
||||||
]
|
|
||||||
|
|
||||||
// Computed properties
|
|
||||||
const repoName = (repo: string) => repo.split('-')[0]
|
|
||||||
const repoVersion = (repo: string) => repo.split('-')[repo.split('-').length - 1]
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
if (page.value > 0) {
|
|
||||||
params.set('offset', (page.value * 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', '')
|
|
||||||
}
|
|
||||||
window.history.pushState(null, '', `${window.location.pathname}?${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'
|
|
||||||
})
|
|
||||||
.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
|
|
||||||
pagesMax.value = json.total / OFFSET + 1
|
|
||||||
packages.value = json.packages
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 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>
|
</script>
|
||||||
|
140
frontend/src/components/Packages/PackageFilters.vue
Normal file
140
frontend/src/components/Packages/PackageFilters.vue
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
<template>
|
||||||
|
<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="pkgbase"
|
||||||
|
clearable
|
||||||
|
color="primary"
|
||||||
|
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="repo"
|
||||||
|
:items="REPO_ITEMS"
|
||||||
|
clearable
|
||||||
|
color="primary"
|
||||||
|
placeholder="Any Repo"
|
||||||
|
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="status"
|
||||||
|
:items="STATUS_ITEMS"
|
||||||
|
chips
|
||||||
|
closable-chips
|
||||||
|
color="primary"
|
||||||
|
density="default"
|
||||||
|
item-title="title"
|
||||||
|
item-value="value"
|
||||||
|
multiple
|
||||||
|
placeholder="Any Status"
|
||||||
|
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="exact" 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"
|
||||||
|
:length="totalPages"
|
||||||
|
:total-visible="mobile ? undefined : 3"
|
||||||
|
active-color="primary"
|
||||||
|
density="comfortable"
|
||||||
|
start="1"
|
||||||
|
variant="text"></v-pagination>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useDisplay } from 'vuetify'
|
||||||
|
import { REPO_ITEMS, ROW_HEIGHT, STATUS_ITEMS } from '@/config/constants'
|
||||||
|
import { usePackagesStore } from '@/stores'
|
||||||
|
import { computed, onMounted, ref, watch } from 'vue'
|
||||||
|
import { components } from '@/api'
|
||||||
|
|
||||||
|
const { mobile } = useDisplay()
|
||||||
|
const packagesStore = usePackagesStore()
|
||||||
|
|
||||||
|
const page = ref<number>(1)
|
||||||
|
const pkgbase = ref<string>()
|
||||||
|
const repo = ref<string>()
|
||||||
|
const status = ref<{ title: string; value: string }[]>([])
|
||||||
|
const exact = ref<boolean>()
|
||||||
|
|
||||||
|
const totalPages = computed(() => Math.ceil(packagesStore.state.total / packagesStore.state.limit))
|
||||||
|
|
||||||
|
const updateFilter = (pageVal?: number) => {
|
||||||
|
if (packagesStore.state.loading) return
|
||||||
|
|
||||||
|
if (pageVal) {
|
||||||
|
page.value = pageVal
|
||||||
|
} else {
|
||||||
|
page.value = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
packagesStore.setFilters(
|
||||||
|
{
|
||||||
|
exact: exact.value,
|
||||||
|
status: status.value.map(
|
||||||
|
(state) => state.value as components['schemas']['Package']['status']
|
||||||
|
),
|
||||||
|
pkgbase: pkgbase.value !== null ? pkgbase.value : undefined,
|
||||||
|
repo: repo.value
|
||||||
|
},
|
||||||
|
page.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const initFilters = () => {
|
||||||
|
page.value = packagesStore.state.offset / packagesStore.state.limit + 1
|
||||||
|
pkgbase.value = packagesStore.state.filters.pkgbase
|
||||||
|
repo.value = packagesStore.state.filters.repo
|
||||||
|
exact.value = packagesStore.state.filters.exact
|
||||||
|
if (packagesStore.state.filters.status) {
|
||||||
|
for (const state of packagesStore.state.filters.status) {
|
||||||
|
if (state) {
|
||||||
|
status.value.push({ title: state.toUpperCase(), value: state.toLowerCase() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => page.value,
|
||||||
|
(pageVal) => {
|
||||||
|
packagesStore.goToPage(pageVal)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Watcher for pkgbase with debounce
|
||||||
|
let pkgbaseTimeout: ReturnType<typeof setTimeout> | null = null
|
||||||
|
watch(
|
||||||
|
() => pkgbase.value,
|
||||||
|
() => {
|
||||||
|
if (pkgbaseTimeout) clearTimeout(pkgbaseTimeout)
|
||||||
|
pkgbaseTimeout = setTimeout(() => {
|
||||||
|
updateFilter()
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Watcher for other filters (repo, status, exact) without debounce
|
||||||
|
watch(
|
||||||
|
[() => repo.value, () => status.value?.map((state) => state.value), () => exact.value],
|
||||||
|
() => {
|
||||||
|
// Cancel pending pkgbase debounce if any
|
||||||
|
if (pkgbaseTimeout) {
|
||||||
|
clearTimeout(pkgbaseTimeout)
|
||||||
|
pkgbaseTimeout = null
|
||||||
|
}
|
||||||
|
updateFilter()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initFilters()
|
||||||
|
})
|
||||||
|
</script>
|
112
frontend/src/components/Packages/PackageTable.vue
Normal file
112
frontend/src/components/Packages/PackageTable.vue
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<template>
|
||||||
|
<v-table class="mt-2 mt-sm-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">
|
||||||
|
LTO
|
||||||
|
<v-tooltip activator="parent" location="bottom">
|
||||||
|
Link time optimization;
|
||||||
|
<br />
|
||||||
|
Does not guarantee that package is actually built with LTO
|
||||||
|
</v-tooltip>
|
||||||
|
</th>
|
||||||
|
<th scope="col">
|
||||||
|
DS
|
||||||
|
<v-tooltip activator="parent" location="bottom">
|
||||||
|
Debug-symbols available via debuginfod
|
||||||
|
</v-tooltip>
|
||||||
|
</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="packagesStore.state.packages.length === 0">
|
||||||
|
No Packages found
|
||||||
|
</tr>
|
||||||
|
<template v-else>
|
||||||
|
<tr
|
||||||
|
v-for="(pkg, index) in packagesStore.state.packages"
|
||||||
|
:key="index"
|
||||||
|
:style="`background-color: ${getStatusColor(pkg.status)};`">
|
||||||
|
<td class="font-weight-bold text-no-wrap">
|
||||||
|
<v-chip
|
||||||
|
:color="getVersionColor(repoVersion(pkg.repo || ''))"
|
||||||
|
class="me-2"
|
||||||
|
density="comfortable"
|
||||||
|
label
|
||||||
|
variant="flat">
|
||||||
|
{{ repoVersion(pkg.repo || '') }}
|
||||||
|
</v-chip>
|
||||||
|
{{ repoName(pkg.repo || '') }}
|
||||||
|
</td>
|
||||||
|
<td class="text-no-wrap">{{ 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(-22px);
|
||||||
|
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>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { usePackageDisplay } from '@/composables/Packages/usePackageDisplay'
|
||||||
|
import { usePackagesStore } from '@/stores'
|
||||||
|
|
||||||
|
const { repoName, repoVersion, getVersionColor, getStatusColor, getLto, getDs } =
|
||||||
|
usePackageDisplay()
|
||||||
|
|
||||||
|
const packagesStore = usePackagesStore()
|
||||||
|
</script>
|
98
frontend/src/composables/Packages/usePackageDisplay.ts
Normal file
98
frontend/src/composables/Packages/usePackageDisplay.ts
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import { components } from '@/api'
|
||||||
|
|
||||||
|
export function usePackageDisplay() {
|
||||||
|
const repoName = (repo: string) => repo.split('-')[0]
|
||||||
|
const repoVersion = (repo: string) => repo.split('-')[repo.split('-').length - 1]
|
||||||
|
|
||||||
|
const getVersionColor = (version: string) => {
|
||||||
|
switch (version) {
|
||||||
|
case 'v2':
|
||||||
|
return '#3498db'
|
||||||
|
case 'v3':
|
||||||
|
return '#f39c12'
|
||||||
|
case 'v4':
|
||||||
|
return '#2ecc71'
|
||||||
|
default:
|
||||||
|
return 'grey'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusColor = (status: components['schemas']['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: components['schemas']['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: components['schemas']['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: '' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
repoName,
|
||||||
|
repoVersion,
|
||||||
|
getVersionColor,
|
||||||
|
getStatusColor,
|
||||||
|
getLto,
|
||||||
|
getDs
|
||||||
|
}
|
||||||
|
}
|
28
frontend/src/config/constants.ts
Normal file
28
frontend/src/config/constants.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// UI Constants
|
||||||
|
export const TRANSPARENT_COLOR = 'transparent'
|
||||||
|
export const ROW_HEIGHT = 60
|
||||||
|
|
||||||
|
// Select Items Constants
|
||||||
|
export const REPO_ITEMS = [
|
||||||
|
'core-x86-64-v2',
|
||||||
|
'core-x86-64-v3',
|
||||||
|
'core-x86-64-v4',
|
||||||
|
'extra-x86-64-v2',
|
||||||
|
'extra-x86-64-v3',
|
||||||
|
'extra-x86-64-v4',
|
||||||
|
'multilib-x86-64-v2',
|
||||||
|
'multilib-x86-64-v3',
|
||||||
|
'multilib-x86-64-v4'
|
||||||
|
]
|
||||||
|
|
||||||
|
export const STATUS_ITEMS = [
|
||||||
|
{ 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' }
|
||||||
|
]
|
273
frontend/src/generated/alhp.ts
Normal file
273
frontend/src/generated/alhp.ts
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
/**
|
||||||
|
* This file was auto-generated by openapi-typescript.
|
||||||
|
* Do not make direct changes to the file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface paths {
|
||||||
|
"/packages": {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Retrieve package information
|
||||||
|
* @description Fetch packages from the ALHP system. You can filter results using query parameters.
|
||||||
|
*/
|
||||||
|
get: operations["getPackages"];
|
||||||
|
put?: never;
|
||||||
|
post?: never;
|
||||||
|
delete?: never;
|
||||||
|
options?: never;
|
||||||
|
head?: never;
|
||||||
|
patch?: never;
|
||||||
|
trace?: never;
|
||||||
|
};
|
||||||
|
"/stats": {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
/** Retrieve general build statistics */
|
||||||
|
get: operations["getStats"];
|
||||||
|
put?: never;
|
||||||
|
post?: never;
|
||||||
|
delete?: never;
|
||||||
|
options?: never;
|
||||||
|
head?: never;
|
||||||
|
patch?: never;
|
||||||
|
trace?: never;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export type webhooks = Record<string, never>;
|
||||||
|
export interface components {
|
||||||
|
schemas: {
|
||||||
|
Package: {
|
||||||
|
/**
|
||||||
|
* @description The base name of the package
|
||||||
|
* @example linux-zen
|
||||||
|
*/
|
||||||
|
pkgbase?: string;
|
||||||
|
/**
|
||||||
|
* @description Repository from which the package originates
|
||||||
|
* @example extra-x86-64-v4
|
||||||
|
*/
|
||||||
|
repo?: string;
|
||||||
|
/**
|
||||||
|
* @description List of package names split from the base package
|
||||||
|
* @example [
|
||||||
|
* "linux-zen",
|
||||||
|
* "linux-zen-headers",
|
||||||
|
* "linux-zen-docs"
|
||||||
|
* ]
|
||||||
|
*/
|
||||||
|
split_packages?: string[];
|
||||||
|
/**
|
||||||
|
* @description Current build or repository status of the package
|
||||||
|
* @example latest
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
status?: "latest" | "failed" | "built" | "skipped" | "delayed" | "building" | "signing" | "unknown" | "queued";
|
||||||
|
/**
|
||||||
|
* @description Reason for skipping the package build (if any)
|
||||||
|
* @example blacklisted
|
||||||
|
*/
|
||||||
|
skip_reason?: string;
|
||||||
|
/**
|
||||||
|
* @description Link Time Optimization (LTO) status for the package
|
||||||
|
* @example enabled
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
lto?: "enabled" | "unknown" | "disabled" | "auto_disabled";
|
||||||
|
/**
|
||||||
|
* @description Availability of debug symbols in the package
|
||||||
|
* @example available
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
debug_symbols?: "available" | "unknown" | "not_available";
|
||||||
|
/**
|
||||||
|
* @description Version available in the official Arch Linux repositories
|
||||||
|
* @example 1.3.4-2
|
||||||
|
*/
|
||||||
|
arch_version?: string;
|
||||||
|
/**
|
||||||
|
* @description Version available in ALHP repositories (may be empty if not built)
|
||||||
|
* @example 1.3.4-2.1
|
||||||
|
*/
|
||||||
|
repo_version?: string;
|
||||||
|
/**
|
||||||
|
* @description Date and time when the package was built (RFC1123 format)
|
||||||
|
* @example Fri, 15 Dec 2023 03:43:11 UTC
|
||||||
|
*/
|
||||||
|
build_date?: string;
|
||||||
|
/**
|
||||||
|
* @description Peak memory usage during the build process (human-readable format)
|
||||||
|
* @example 5 GB
|
||||||
|
*/
|
||||||
|
peak_mem?: string;
|
||||||
|
};
|
||||||
|
/** @description Aggregated statistics across all packages */
|
||||||
|
Stats: {
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @description Number of packages that failed to build
|
||||||
|
* @example 17
|
||||||
|
*/
|
||||||
|
failed?: number;
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @description Number of packages that were skipped
|
||||||
|
* @example 29
|
||||||
|
*/
|
||||||
|
skipped?: number;
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @description Number of packages that are up-to-date
|
||||||
|
* @example 743
|
||||||
|
*/
|
||||||
|
latest?: number;
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @description Number of packages currently in the build queue
|
||||||
|
* @example 5
|
||||||
|
*/
|
||||||
|
queued?: number;
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @description Number of packages currently building
|
||||||
|
* @example 11
|
||||||
|
*/
|
||||||
|
building?: number;
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @description Latest mirror timestamp to detect outdated mirrors (Unix timestamp)
|
||||||
|
* @example 1702612991
|
||||||
|
*/
|
||||||
|
last_mirror_timestamp?: number;
|
||||||
|
/** @description LTO status summary across all packages */
|
||||||
|
lto?: {
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @description Number of packages with LTO enabled
|
||||||
|
* @example 532
|
||||||
|
*/
|
||||||
|
enabled?: number;
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @description Number of packages with LTO explicitly disabled
|
||||||
|
* @example 203
|
||||||
|
*/
|
||||||
|
disabled?: number;
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @description Number of packages with unknown LTO status
|
||||||
|
* @example 11
|
||||||
|
*/
|
||||||
|
unknown?: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: never;
|
||||||
|
parameters: never;
|
||||||
|
requestBodies: never;
|
||||||
|
headers: never;
|
||||||
|
pathItems: never;
|
||||||
|
}
|
||||||
|
export type $defs = Record<string, never>;
|
||||||
|
export interface operations {
|
||||||
|
getPackages: {
|
||||||
|
parameters: {
|
||||||
|
query: {
|
||||||
|
/** @description Filter by package status. Accepts multiple values via repeated parameters. */
|
||||||
|
status?: ("latest" | "failed" | "built" | "skipped" | "delayed" | "building" | "signing" | "unknown" | "queued")[];
|
||||||
|
/** @description Filter by the base package name (`pkgbase`). This is often the main identifier of a package group. */
|
||||||
|
pkgbase?: string;
|
||||||
|
/** @description If present, matches the `pkgbase` exactly. If not provided, allows partial matches. */
|
||||||
|
exact?: boolean;
|
||||||
|
/** @description Filter by repository name. */
|
||||||
|
repo?: string;
|
||||||
|
/** @description Number of results to skip (for pagination). */
|
||||||
|
offset: number;
|
||||||
|
/** @description Maximum number of results to return. */
|
||||||
|
limit: number;
|
||||||
|
};
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
requestBody?: never;
|
||||||
|
responses: {
|
||||||
|
/** @description Package data retrieved successfully */
|
||||||
|
200: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
packages?: components["schemas"]["Package"][];
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @description Total number of matching packages
|
||||||
|
* @example 1423
|
||||||
|
*/
|
||||||
|
total?: number;
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @example 0
|
||||||
|
*/
|
||||||
|
offset?: number;
|
||||||
|
/**
|
||||||
|
* Format: int64
|
||||||
|
* @example 25
|
||||||
|
*/
|
||||||
|
limit?: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/** @description No packages found matching the specified filters */
|
||||||
|
404: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content?: never;
|
||||||
|
};
|
||||||
|
/** @description Internal server error occurred */
|
||||||
|
500: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content?: never;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
getStats: {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
requestBody?: never;
|
||||||
|
responses: {
|
||||||
|
/** @description General statistics retrieved successfully */
|
||||||
|
200: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["Stats"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/** @description Internal server error occurred */
|
||||||
|
500: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content?: never;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@@ -1,22 +1,13 @@
|
|||||||
/**
|
|
||||||
* main.ts
|
|
||||||
*
|
|
||||||
* Bootstraps Vuetify and other plugins then mounts the App`
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Plugins
|
|
||||||
import { registerPlugins } from '@/plugins'
|
import { registerPlugins } from '@/plugins'
|
||||||
|
|
||||||
// Components
|
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
|
||||||
// Composables
|
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
|
|
||||||
// Styles
|
|
||||||
import '@/assets/styles/base.scss'
|
import '@/assets/styles/base.scss'
|
||||||
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
|
const pinia = createPinia()
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
app.use(pinia)
|
||||||
|
|
||||||
registerPlugins(app)
|
registerPlugins(app)
|
||||||
|
|
||||||
|
3
frontend/src/stores/index.ts
Normal file
3
frontend/src/stores/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Export all stores
|
||||||
|
export { useStatsStore } from './statsStore'
|
||||||
|
export { usePackagesStore } from './packagesStore'
|
229
frontend/src/stores/packagesStore.ts
Normal file
229
frontend/src/stores/packagesStore.ts
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { reactive } from 'vue'
|
||||||
|
import { components, getPackages } from '@/api'
|
||||||
|
|
||||||
|
interface PackageFilters {
|
||||||
|
status?: components['schemas']['Package']['status'][]
|
||||||
|
pkgbase?: components['schemas']['Package']['pkgbase']
|
||||||
|
exact?: boolean
|
||||||
|
repo?: components['schemas']['Package']['repo']
|
||||||
|
}
|
||||||
|
|
||||||
|
export const usePackagesStore = defineStore('packages', () => {
|
||||||
|
const state = reactive({
|
||||||
|
packages: [] as components['schemas']['Package'][],
|
||||||
|
currentlyBuildingPackages: [] as components['schemas']['Package'][],
|
||||||
|
total: 0,
|
||||||
|
offset: 0,
|
||||||
|
limit: Number(import.meta.env.VITE_LIMIT) || 50,
|
||||||
|
loading: false,
|
||||||
|
loadingCurrentlyBuilding: false,
|
||||||
|
error: null as string | null,
|
||||||
|
errorCurrentlyBuilding: null as string | null,
|
||||||
|
lastUpdated: Date.now(),
|
||||||
|
filters: {
|
||||||
|
status: undefined,
|
||||||
|
pkgbase: undefined,
|
||||||
|
exact: undefined,
|
||||||
|
repo: undefined
|
||||||
|
} as PackageFilters
|
||||||
|
})
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
const fetchPackages = (init = false) => {
|
||||||
|
state.loading = true
|
||||||
|
state.error = null
|
||||||
|
state.packages = []
|
||||||
|
state.total = 0
|
||||||
|
|
||||||
|
if (init) {
|
||||||
|
initFromUrl()
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter: PackageFilters = {}
|
||||||
|
if (state.filters.status && state.filters.status.length > 0) {
|
||||||
|
filter.status = state.filters.status
|
||||||
|
}
|
||||||
|
if (state.filters.pkgbase) {
|
||||||
|
filter.pkgbase = state.filters.pkgbase
|
||||||
|
}
|
||||||
|
if (state.filters.exact === true) {
|
||||||
|
filter.exact = state.filters.exact
|
||||||
|
}
|
||||||
|
if (state.filters.repo) {
|
||||||
|
filter.repo = state.filters.repo
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
getPackages({
|
||||||
|
limit: state.limit,
|
||||||
|
offset: state.offset,
|
||||||
|
...filter
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (!response) throw new Error('No response from API')
|
||||||
|
state.packages = response.packages || []
|
||||||
|
state.total = response.total || 0
|
||||||
|
state.offset = response.offset || 0
|
||||||
|
state.limit = response.limit || state.limit
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (err.statusCode === 404) {
|
||||||
|
state.packages = []
|
||||||
|
state.total = 0
|
||||||
|
state.offset = 0
|
||||||
|
state.limit = Number(import.meta.env.VITE_LIMIT) || 50
|
||||||
|
} else {
|
||||||
|
state.error = err instanceof Error ? err.message : 'Failed to fetch packages'
|
||||||
|
console.error('Error fetching packages:', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
state.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchCurrentlyBuilding = () => {
|
||||||
|
state.loadingCurrentlyBuilding = true
|
||||||
|
state.errorCurrentlyBuilding = null
|
||||||
|
state.currentlyBuildingPackages = []
|
||||||
|
|
||||||
|
getPackages({
|
||||||
|
limit: 0,
|
||||||
|
offset: 0,
|
||||||
|
status: ['queued', 'building', 'built']
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
state.currentlyBuildingPackages = response?.packages || []
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (err.statusCode === 404) {
|
||||||
|
state.currentlyBuildingPackages = []
|
||||||
|
} else {
|
||||||
|
state.errorCurrentlyBuilding =
|
||||||
|
err instanceof Error ? err.message : 'Failed to fetch currently building packages'
|
||||||
|
console.error('Error fetching queued packages:', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
state.loadingCurrentlyBuilding = false
|
||||||
|
state.lastUpdated = Date.now()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const goToPage = (page: number) => {
|
||||||
|
state.offset = (page - 1) * state.limit
|
||||||
|
|
||||||
|
updateUrlParams()
|
||||||
|
fetchPackages()
|
||||||
|
}
|
||||||
|
|
||||||
|
const setFilters = (newFilters: PackageFilters, page?: number) => {
|
||||||
|
state.filters = JSON.parse(JSON.stringify(newFilters))
|
||||||
|
if (state.filters.exact === false) {
|
||||||
|
state.filters.exact = undefined
|
||||||
|
}
|
||||||
|
if (page) {
|
||||||
|
state.offset = (page - 1) * state.limit
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUrlParams()
|
||||||
|
fetchPackages()
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetFilters = () => {
|
||||||
|
state.filters = {
|
||||||
|
status: undefined,
|
||||||
|
pkgbase: undefined,
|
||||||
|
exact: undefined,
|
||||||
|
repo: undefined
|
||||||
|
}
|
||||||
|
state.offset = 0
|
||||||
|
state.limit = Number(import.meta.env.VITE_LIMIT) || 50
|
||||||
|
|
||||||
|
updateUrlParams()
|
||||||
|
fetchPackages()
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateUrlParams = () => {
|
||||||
|
const params = new URLSearchParams()
|
||||||
|
|
||||||
|
let page = state.offset / state.limit + 1
|
||||||
|
// Only add a page parameter if it's not the first page
|
||||||
|
if (page > 1) {
|
||||||
|
params.set('page', page.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.filters.status && state.filters.status.length > 0) {
|
||||||
|
state.filters.status.forEach((status: components['schemas']['Package']['status']) => {
|
||||||
|
if (status) {
|
||||||
|
params.append('status', status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.filters.pkgbase) {
|
||||||
|
params.set('pkgbase', state.filters.pkgbase.toLowerCase())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.filters.repo) {
|
||||||
|
params.set('repo', state.filters.repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.filters.exact === true) {
|
||||||
|
params.set('exact', '')
|
||||||
|
} else {
|
||||||
|
params.delete('exact')
|
||||||
|
}
|
||||||
|
|
||||||
|
const paramsString = params.toString()
|
||||||
|
if (paramsString) {
|
||||||
|
window.history.pushState(null, '', `${window.location.pathname}?${paramsString}`)
|
||||||
|
} else {
|
||||||
|
window.history.pushState(null, '', window.location.pathname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const initFromUrl = () => {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
|
||||||
|
if (urlParams.has('page')) {
|
||||||
|
const pageParam = urlParams.get('page') || '1'
|
||||||
|
const parsedPage = parseInt(pageParam, 10)
|
||||||
|
const page = !isNaN(parsedPage) && parsedPage > 0 ? parsedPage : 1
|
||||||
|
state.offset = (page - 1) * state.limit
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlParams.has('status')) {
|
||||||
|
const status = urlParams.getAll('status')
|
||||||
|
state.filters.status = status as components['schemas']['Package']['status'][]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlParams.has('pkgbase')) {
|
||||||
|
const pkgbase = urlParams.get('pkgbase')
|
||||||
|
if (pkgbase === null) return
|
||||||
|
state.filters.pkgbase = pkgbase as components['schemas']['Package']['pkgbase']
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlParams.has('repo')) {
|
||||||
|
const repo = urlParams.get('repo')
|
||||||
|
if (repo === null) return
|
||||||
|
state.filters.repo = repo as components['schemas']['Package']['repo']
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlParams.has('exact')) {
|
||||||
|
state.filters.exact = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
state,
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
fetchPackages,
|
||||||
|
fetchCurrentlyBuilding,
|
||||||
|
goToPage,
|
||||||
|
setFilters,
|
||||||
|
resetFilters
|
||||||
|
}
|
||||||
|
})
|
37
frontend/src/stores/statsStore.ts
Normal file
37
frontend/src/stores/statsStore.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { reactive } from 'vue'
|
||||||
|
import { components, getStats } from '@/api'
|
||||||
|
|
||||||
|
export const useStatsStore = defineStore('stats', () => {
|
||||||
|
const state = reactive({
|
||||||
|
stats: {} as components['schemas']['Stats'] | undefined | null,
|
||||||
|
loading: false,
|
||||||
|
error: null as string | null,
|
||||||
|
lastUpdated: Date.now()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
const fetchStats = () => {
|
||||||
|
state.loading = true
|
||||||
|
state.error = null
|
||||||
|
|
||||||
|
getStats()
|
||||||
|
.then((response) => {
|
||||||
|
state.stats = response
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
state.error = err instanceof Error ? err.message : 'Failed to fetch packages'
|
||||||
|
console.error('Error fetching packages:', err)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
state.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
state,
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
fetchStats
|
||||||
|
}
|
||||||
|
})
|
@@ -1,22 +0,0 @@
|
|||||||
export interface Package {
|
|
||||||
pkgbase: string
|
|
||||||
repo: string
|
|
||||||
split_packages: Array<string>
|
|
||||||
status:
|
|
||||||
| 'latest'
|
|
||||||
| 'failed'
|
|
||||||
| 'built'
|
|
||||||
| 'skipped'
|
|
||||||
| 'delayed'
|
|
||||||
| 'building'
|
|
||||||
| 'signing'
|
|
||||||
| 'unknown'
|
|
||||||
| 'queued'
|
|
||||||
skip_reason: string
|
|
||||||
lto: 'enabled' | 'unknown' | 'disabled' | 'auto_disabled'
|
|
||||||
debug_symbols: 'available' | 'unknown' | 'not_available'
|
|
||||||
arch_version: string
|
|
||||||
repo_version: string
|
|
||||||
build_date: string
|
|
||||||
peak_mem: any
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
import { type Package } from '@/types/Package'
|
|
||||||
|
|
||||||
export interface Packages {
|
|
||||||
packages: Array<Package>
|
|
||||||
total: number
|
|
||||||
offset: number
|
|
||||||
limit: number
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
import { type Stats_Lto } from '@/types/Stats_Lto'
|
|
||||||
|
|
||||||
export interface Stats {
|
|
||||||
latest: number
|
|
||||||
queued: number
|
|
||||||
skipped: number
|
|
||||||
failed: number
|
|
||||||
lto: Stats_Lto
|
|
||||||
}
|
|
@@ -1,5 +0,0 @@
|
|||||||
export interface Stats_Lto {
|
|
||||||
enabled: number
|
|
||||||
disabled: number
|
|
||||||
unknown: number
|
|
||||||
}
|
|
@@ -5,6 +5,17 @@ __metadata:
|
|||||||
version: 8
|
version: 8
|
||||||
cacheKey: 10c0
|
cacheKey: 10c0
|
||||||
|
|
||||||
|
"@babel/code-frame@npm:^7.26.2":
|
||||||
|
version: 7.26.2
|
||||||
|
resolution: "@babel/code-frame@npm:7.26.2"
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-validator-identifier": "npm:^7.25.9"
|
||||||
|
js-tokens: "npm:^4.0.0"
|
||||||
|
picocolors: "npm:^1.0.0"
|
||||||
|
checksum: 10c0/7d79621a6849183c415486af99b1a20b84737e8c11cd55b6544f688c51ce1fd710e6d869c3dd21232023da272a79b91efb3e83b5bc2dc65c1187c5fcd1b72ea8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@babel/helper-string-parser@npm:^7.25.9":
|
"@babel/helper-string-parser@npm:^7.25.9":
|
||||||
version: 7.25.9
|
version: 7.25.9
|
||||||
resolution: "@babel/helper-string-parser@npm:7.25.9"
|
resolution: "@babel/helper-string-parser@npm:7.25.9"
|
||||||
@@ -40,6 +51,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@babel/types@npm:^7.27.0":
|
||||||
|
version: 7.27.0
|
||||||
|
resolution: "@babel/types@npm:7.27.0"
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-string-parser": "npm:^7.25.9"
|
||||||
|
"@babel/helper-validator-identifier": "npm:^7.25.9"
|
||||||
|
checksum: 10c0/6f1592eabe243c89a608717b07b72969be9d9d2fce1dee21426238757ea1fa60fdfc09b29de9e48d8104311afc6e6fb1702565a9cc1e09bc1e76f2b2ddb0f6e1
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@esbuild/aix-ppc64@npm:0.25.1":
|
"@esbuild/aix-ppc64@npm:0.25.1":
|
||||||
version: 0.25.1
|
version: 0.25.1
|
||||||
resolution: "@esbuild/aix-ppc64@npm:0.25.1"
|
resolution: "@esbuild/aix-ppc64@npm:0.25.1"
|
||||||
@@ -450,6 +471,42 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@redocly/ajv@npm:^8.11.2":
|
||||||
|
version: 8.11.2
|
||||||
|
resolution: "@redocly/ajv@npm:8.11.2"
|
||||||
|
dependencies:
|
||||||
|
fast-deep-equal: "npm:^3.1.1"
|
||||||
|
json-schema-traverse: "npm:^1.0.0"
|
||||||
|
require-from-string: "npm:^2.0.2"
|
||||||
|
uri-js-replace: "npm:^1.0.1"
|
||||||
|
checksum: 10c0/249ca2e237f7b1248ee1018ba1ad3a739cb9f16e5f7fe821875948806980d65246c79ef7d5e7bd8db773c120e2cd5ce15aa47883893608e1965ca4d45c5572f4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@redocly/config@npm:^0.22.0":
|
||||||
|
version: 0.22.2
|
||||||
|
resolution: "@redocly/config@npm:0.22.2"
|
||||||
|
checksum: 10c0/625e947e7939e2d59bd83f516af5a581411167e3fc83adf7322bddf9bc69038fc601ed4ee8abae44d298ed367a16a1a09e7cdbe8b5dde172b4ce53c88d8717f4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@redocly/openapi-core@npm:^1.28.0":
|
||||||
|
version: 1.34.2
|
||||||
|
resolution: "@redocly/openapi-core@npm:1.34.2"
|
||||||
|
dependencies:
|
||||||
|
"@redocly/ajv": "npm:^8.11.2"
|
||||||
|
"@redocly/config": "npm:^0.22.0"
|
||||||
|
colorette: "npm:^1.2.0"
|
||||||
|
https-proxy-agent: "npm:^7.0.5"
|
||||||
|
js-levenshtein: "npm:^1.1.6"
|
||||||
|
js-yaml: "npm:^4.1.0"
|
||||||
|
minimatch: "npm:^5.0.1"
|
||||||
|
pluralize: "npm:^8.0.0"
|
||||||
|
yaml-ast-parser: "npm:0.0.43"
|
||||||
|
checksum: 10c0/252710cdc7fd182f37c2fedaa27cbd8ea5f882e3340515bf572372adc35e5cdc0bfc0aae2ce51defa91d1fd9a2f9d82454104b0c9ab22895f941196f50830b33
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@rollup/rollup-android-arm-eabi@npm:4.36.0":
|
"@rollup/rollup-android-arm-eabi@npm:4.36.0":
|
||||||
version: 4.36.0
|
version: 4.36.0
|
||||||
resolution: "@rollup/rollup-android-arm-eabi@npm:4.36.0"
|
resolution: "@rollup/rollup-android-arm-eabi@npm:4.36.0"
|
||||||
@@ -590,12 +647,12 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/node@npm:^22.13.11":
|
"@types/node@npm:^22.14.1":
|
||||||
version: 22.13.11
|
version: 22.14.1
|
||||||
resolution: "@types/node@npm:22.13.11"
|
resolution: "@types/node@npm:22.14.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: "npm:~6.20.0"
|
undici-types: "npm:~6.21.0"
|
||||||
checksum: 10c0/f6ee33d36372242535c38640fe7550a6640d8a775ec19b55bfc11775b521cba072d892ca92a912332ce01b317293d645c1bf767f3f882ec719f2404a3d2a5b96
|
checksum: 10c0/d49c4d00403b1c2348cf0701b505fd636d80aabe18102105998dc62fdd36dcaf911e73c7a868c48c21c1022b825c67b475b65b1222d84b704d8244d152bb7f86
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -696,6 +753,39 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@vue/devtools-api@npm:^7.7.2":
|
||||||
|
version: 7.7.2
|
||||||
|
resolution: "@vue/devtools-api@npm:7.7.2"
|
||||||
|
dependencies:
|
||||||
|
"@vue/devtools-kit": "npm:^7.7.2"
|
||||||
|
checksum: 10c0/418d3c868143a91518bc846965f7c8a955f072b8526d0f739f4d7dc00b13a0f56b214d876bfff338dc841762b526a1a4c11b5e8b0ab6dd7f3250a694ec8dfbe3
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@vue/devtools-kit@npm:^7.7.2":
|
||||||
|
version: 7.7.2
|
||||||
|
resolution: "@vue/devtools-kit@npm:7.7.2"
|
||||||
|
dependencies:
|
||||||
|
"@vue/devtools-shared": "npm:^7.7.2"
|
||||||
|
birpc: "npm:^0.2.19"
|
||||||
|
hookable: "npm:^5.5.3"
|
||||||
|
mitt: "npm:^3.0.1"
|
||||||
|
perfect-debounce: "npm:^1.0.0"
|
||||||
|
speakingurl: "npm:^14.0.1"
|
||||||
|
superjson: "npm:^2.2.1"
|
||||||
|
checksum: 10c0/e052ba756558040855304b6ee13ba39131a44c89a9f78ab262c79f8a0e6b58fa379e1efa306a9a50675cac3e48baeb3f86b1560f64edf48cbc0695165d0b2be6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@vue/devtools-shared@npm:^7.7.2":
|
||||||
|
version: 7.7.2
|
||||||
|
resolution: "@vue/devtools-shared@npm:7.7.2"
|
||||||
|
dependencies:
|
||||||
|
rfdc: "npm:^1.4.1"
|
||||||
|
checksum: 10c0/6399135da41a91f48c3db7c59cedb01ad331af7784ef0877c15c669ad5a5d1cce68f73d50d81f85a31a90b0d6323ff807ebe5b1fb041d1e86932f2c983a0cdad
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@vue/language-core@npm:2.2.8":
|
"@vue/language-core@npm:2.2.8":
|
||||||
version: 2.2.8
|
version: 2.2.8
|
||||||
resolution: "@vue/language-core@npm:2.2.8"
|
resolution: "@vue/language-core@npm:2.2.8"
|
||||||
@@ -804,6 +894,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"agent-base@npm:^7.1.2":
|
||||||
|
version: 7.1.3
|
||||||
|
resolution: "agent-base@npm:7.1.3"
|
||||||
|
checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"aggregate-error@npm:^3.0.0":
|
"aggregate-error@npm:^3.0.0":
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
resolution: "aggregate-error@npm:3.1.0"
|
resolution: "aggregate-error@npm:3.1.0"
|
||||||
@@ -818,23 +915,26 @@ __metadata:
|
|||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "alhp-web@workspace:."
|
resolution: "alhp-web@workspace:."
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types": "npm:^7.26.10"
|
"@babel/types": "npm:^7.27.0"
|
||||||
"@fontsource/roboto": "npm:^5.2.5"
|
"@fontsource/roboto": "npm:^5.2.5"
|
||||||
"@mdi/font": "npm:7.4.47"
|
"@mdi/font": "npm:7.4.47"
|
||||||
"@types/node": "npm:^22.13.11"
|
"@types/node": "npm:^22.14.1"
|
||||||
"@vitejs/plugin-vue": "npm:^5.2.3"
|
"@vitejs/plugin-vue": "npm:^5.2.3"
|
||||||
fork-awesome: "npm:^1.2.0"
|
fork-awesome: "npm:^1.2.0"
|
||||||
|
openapi-fetch: "npm:^0.13.5"
|
||||||
|
openapi-typescript: "npm:^7.6.1"
|
||||||
|
pinia: "npm:^3.0.2"
|
||||||
prettier: "npm:^3.5.3"
|
prettier: "npm:^3.5.3"
|
||||||
roboto-fontface: "npm:^0.10.0"
|
roboto-fontface: "npm:^0.10.0"
|
||||||
sass: "npm:^1.86.0"
|
sass: "npm:^1.86.3"
|
||||||
typescript: "npm:^5.8.2"
|
typescript: "npm:^5.8.3"
|
||||||
unplugin-fonts: "npm:^1.3.1"
|
unplugin-fonts: "npm:^1.3.1"
|
||||||
unplugin-vue-components: "npm:^28.4.1"
|
unplugin-vue-components: "npm:^28.5.0"
|
||||||
vite: "npm:^6.2.2"
|
vite: "npm:^6.2.6"
|
||||||
vite-plugin-vuetify: "npm:^2.1.0"
|
vite-plugin-vuetify: "npm:^2.1.1"
|
||||||
vue: "npm:^3.5.13"
|
vue: "npm:^3.5.13"
|
||||||
vue-tsc: "npm:^2.2.8"
|
vue-tsc: "npm:^2.2.8"
|
||||||
vuetify: "npm:^3.7.18"
|
vuetify: "npm:^3.8.1"
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
@@ -845,6 +945,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"ansi-colors@npm:^4.1.3":
|
||||||
|
version: 4.1.3
|
||||||
|
resolution: "ansi-colors@npm:4.1.3"
|
||||||
|
checksum: 10c0/ec87a2f59902f74e61eada7f6e6fe20094a628dab765cfdbd03c3477599368768cffccdb5d3bb19a1b6c99126783a143b1fee31aab729b31ffe5836c7e5e28b9
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"ansi-regex@npm:^5.0.1":
|
"ansi-regex@npm:^5.0.1":
|
||||||
version: 5.0.1
|
version: 5.0.1
|
||||||
resolution: "ansi-regex@npm:5.0.1"
|
resolution: "ansi-regex@npm:5.0.1"
|
||||||
@@ -885,6 +992,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"argparse@npm:^2.0.1":
|
||||||
|
version: 2.0.1
|
||||||
|
resolution: "argparse@npm:2.0.1"
|
||||||
|
checksum: 10c0/c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"balanced-match@npm:^1.0.0":
|
"balanced-match@npm:^1.0.0":
|
||||||
version: 1.0.2
|
version: 1.0.2
|
||||||
resolution: "balanced-match@npm:1.0.2"
|
resolution: "balanced-match@npm:1.0.2"
|
||||||
@@ -899,6 +1013,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"birpc@npm:^0.2.19":
|
||||||
|
version: 0.2.19
|
||||||
|
resolution: "birpc@npm:0.2.19"
|
||||||
|
checksum: 10c0/be3c6a4044e3041a5d8eb4c4d50b57b46158dc8149ada718ead20544e50b68b72b34c9d8bf0457d23d5f18e5a66d206b8bef5ff22c1018e1e39d373187eed455
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"brace-expansion@npm:^2.0.1":
|
"brace-expansion@npm:^2.0.1":
|
||||||
version: 2.0.1
|
version: 2.0.1
|
||||||
resolution: "brace-expansion@npm:2.0.1"
|
resolution: "brace-expansion@npm:2.0.1"
|
||||||
@@ -946,6 +1067,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"change-case@npm:^5.4.4":
|
||||||
|
version: 5.4.4
|
||||||
|
resolution: "change-case@npm:5.4.4"
|
||||||
|
checksum: 10c0/2a9c2b9c9ad6ab2491105aaf506db1a9acaf543a18967798dcce20926c6a173aa63266cb6189f3086e3c14bf7ae1f8ea4f96ecc466fcd582310efa00372f3734
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"chokidar@npm:^3.6.0":
|
"chokidar@npm:^3.6.0":
|
||||||
version: 3.6.0
|
version: 3.6.0
|
||||||
resolution: "chokidar@npm:3.6.0"
|
resolution: "chokidar@npm:3.6.0"
|
||||||
@@ -1004,6 +1132,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"colorette@npm:^1.2.0":
|
||||||
|
version: 1.4.0
|
||||||
|
resolution: "colorette@npm:1.4.0"
|
||||||
|
checksum: 10c0/4955c8f7daafca8ae7081d672e4bd89d553bd5782b5846d5a7e05effe93c2f15f7e9c0cb46f341b59f579a39fcf436241ff79594899d75d5f3460c03d607fe9e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"confbox@npm:^0.1.8":
|
"confbox@npm:^0.1.8":
|
||||||
version: 0.1.8
|
version: 0.1.8
|
||||||
resolution: "confbox@npm:0.1.8"
|
resolution: "confbox@npm:0.1.8"
|
||||||
@@ -1018,6 +1153,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"copy-anything@npm:^3.0.2":
|
||||||
|
version: 3.0.5
|
||||||
|
resolution: "copy-anything@npm:3.0.5"
|
||||||
|
dependencies:
|
||||||
|
is-what: "npm:^4.1.8"
|
||||||
|
checksum: 10c0/01eadd500c7e1db71d32d95a3bfaaedcb839ef891c741f6305ab0461398056133de08f2d1bf4c392b364e7bdb7ce498513896e137a7a183ac2516b065c28a4fe
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"cross-spawn@npm:^7.0.0":
|
"cross-spawn@npm:^7.0.0":
|
||||||
version: 7.0.3
|
version: 7.0.3
|
||||||
resolution: "cross-spawn@npm:7.0.3"
|
resolution: "cross-spawn@npm:7.0.3"
|
||||||
@@ -1246,6 +1390,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"fast-deep-equal@npm:^3.1.1":
|
||||||
|
version: 3.1.3
|
||||||
|
resolution: "fast-deep-equal@npm:3.1.3"
|
||||||
|
checksum: 10c0/40dedc862eb8992c54579c66d914635afbec43350afbbe991235fdcb4e3a8d5af1b23ae7e79bef7d4882d0ecee06c3197488026998fb19f72dc95acff1d1b1d0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"fast-glob@npm:^3.3.2":
|
"fast-glob@npm:^3.3.2":
|
||||||
version: 3.3.2
|
version: 3.3.2
|
||||||
resolution: "fast-glob@npm:3.3.2"
|
resolution: "fast-glob@npm:3.3.2"
|
||||||
@@ -1393,6 +1544,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"hookable@npm:^5.5.3":
|
||||||
|
version: 5.5.3
|
||||||
|
resolution: "hookable@npm:5.5.3"
|
||||||
|
checksum: 10c0/275f4cc84d27f8d48c5a5cd5685b6c0fea9291be9deea5bff0cfa72856ed566abde1dcd8cb1da0f9a70b4da3d7ec0d60dc3554c4edbba647058cc38816eced3d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"http-cache-semantics@npm:^4.1.1":
|
"http-cache-semantics@npm:^4.1.1":
|
||||||
version: 4.1.1
|
version: 4.1.1
|
||||||
resolution: "http-cache-semantics@npm:4.1.1"
|
resolution: "http-cache-semantics@npm:4.1.1"
|
||||||
@@ -1420,6 +1578,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"https-proxy-agent@npm:^7.0.5":
|
||||||
|
version: 7.0.6
|
||||||
|
resolution: "https-proxy-agent@npm:7.0.6"
|
||||||
|
dependencies:
|
||||||
|
agent-base: "npm:^7.1.2"
|
||||||
|
debug: "npm:4"
|
||||||
|
checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"iconv-lite@npm:^0.6.2":
|
"iconv-lite@npm:^0.6.2":
|
||||||
version: 0.6.3
|
version: 0.6.3
|
||||||
resolution: "iconv-lite@npm:0.6.3"
|
resolution: "iconv-lite@npm:0.6.3"
|
||||||
@@ -1450,6 +1618,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"index-to-position@npm:^1.1.0":
|
||||||
|
version: 1.1.0
|
||||||
|
resolution: "index-to-position@npm:1.1.0"
|
||||||
|
checksum: 10c0/77ef140f0218df0486a08cff204de4d382e8c43892039aaa441ac5b87f0c8d8a72af633c8a1c49f1b1ec4177bd809e4e045958a9aebe65545f203342b95886b3
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"ip-address@npm:^9.0.5":
|
"ip-address@npm:^9.0.5":
|
||||||
version: 9.0.5
|
version: 9.0.5
|
||||||
resolution: "ip-address@npm:9.0.5"
|
resolution: "ip-address@npm:9.0.5"
|
||||||
@@ -1506,6 +1681,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"is-what@npm:^4.1.8":
|
||||||
|
version: 4.1.16
|
||||||
|
resolution: "is-what@npm:4.1.16"
|
||||||
|
checksum: 10c0/611f1947776826dcf85b57cfb7bd3b3ea6f4b94a9c2f551d4a53f653cf0cb9d1e6518846648256d46ee6c91d114b6d09d2ac8a07306f7430c5900f87466aae5b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"isexe@npm:^2.0.0":
|
"isexe@npm:^2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "isexe@npm:2.0.0"
|
resolution: "isexe@npm:2.0.0"
|
||||||
@@ -1533,6 +1715,31 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"js-levenshtein@npm:^1.1.6":
|
||||||
|
version: 1.1.6
|
||||||
|
resolution: "js-levenshtein@npm:1.1.6"
|
||||||
|
checksum: 10c0/14045735325ea1fd87f434a74b11d8a14380f090f154747e613529c7cff68b5ee607f5230fa40665d5fb6125a3791f4c223f73b9feca754f989b059f5c05864f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"js-tokens@npm:^4.0.0":
|
||||||
|
version: 4.0.0
|
||||||
|
resolution: "js-tokens@npm:4.0.0"
|
||||||
|
checksum: 10c0/e248708d377aa058eacf2037b07ded847790e6de892bbad3dac0abba2e759cb9f121b00099a65195616badcb6eca8d14d975cb3e89eb1cfda644756402c8aeed
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"js-yaml@npm:^4.1.0":
|
||||||
|
version: 4.1.0
|
||||||
|
resolution: "js-yaml@npm:4.1.0"
|
||||||
|
dependencies:
|
||||||
|
argparse: "npm:^2.0.1"
|
||||||
|
bin:
|
||||||
|
js-yaml: bin/js-yaml.js
|
||||||
|
checksum: 10c0/184a24b4eaacfce40ad9074c64fd42ac83cf74d8c8cd137718d456ced75051229e5061b8633c3366b8aada17945a7a356b337828c19da92b51ae62126575018f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"jsbn@npm:1.1.0":
|
"jsbn@npm:1.1.0":
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
resolution: "jsbn@npm:1.1.0"
|
resolution: "jsbn@npm:1.1.0"
|
||||||
@@ -1540,7 +1747,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"local-pkg@npm:^1.0.0":
|
"json-schema-traverse@npm:^1.0.0":
|
||||||
|
version: 1.0.0
|
||||||
|
resolution: "json-schema-traverse@npm:1.0.0"
|
||||||
|
checksum: 10c0/71e30015d7f3d6dc1c316d6298047c8ef98a06d31ad064919976583eb61e1018a60a0067338f0f79cabc00d84af3fcc489bd48ce8a46ea165d9541ba17fb30c6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"local-pkg@npm:^1.1.1":
|
||||||
version: 1.1.1
|
version: 1.1.1
|
||||||
resolution: "local-pkg@npm:1.1.1"
|
resolution: "local-pkg@npm:1.1.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -1614,6 +1828,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"minimatch@npm:^5.0.1":
|
||||||
|
version: 5.1.6
|
||||||
|
resolution: "minimatch@npm:5.1.6"
|
||||||
|
dependencies:
|
||||||
|
brace-expansion: "npm:^2.0.1"
|
||||||
|
checksum: 10c0/3defdfd230914f22a8da203747c42ee3c405c39d4d37ffda284dac5e45b7e1f6c49aa8be606509002898e73091ff2a3bbfc59c2c6c71d4660609f63aa92f98e3
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"minimatch@npm:^9.0.3":
|
"minimatch@npm:^9.0.3":
|
||||||
version: 9.0.3
|
version: 9.0.3
|
||||||
resolution: "minimatch@npm:9.0.3"
|
resolution: "minimatch@npm:9.0.3"
|
||||||
@@ -1716,6 +1939,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"mitt@npm:^3.0.1":
|
||||||
|
version: 3.0.1
|
||||||
|
resolution: "mitt@npm:3.0.1"
|
||||||
|
checksum: 10c0/3ab4fdecf3be8c5255536faa07064d05caa3dd332bd318ff02e04621f7b3069ca1de9106cfe8e7ced675abfc2bec2ce4c4ef321c4a1bb1fb29df8ae090741913
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"mkdirp@npm:^1.0.3":
|
"mkdirp@npm:^1.0.3":
|
||||||
version: 1.0.4
|
version: 1.0.4
|
||||||
resolution: "mkdirp@npm:1.0.4"
|
resolution: "mkdirp@npm:1.0.4"
|
||||||
@@ -1821,6 +2051,40 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"openapi-fetch@npm:^0.13.5":
|
||||||
|
version: 0.13.5
|
||||||
|
resolution: "openapi-fetch@npm:0.13.5"
|
||||||
|
dependencies:
|
||||||
|
openapi-typescript-helpers: "npm:^0.0.15"
|
||||||
|
checksum: 10c0/57736d9d4310d7bc7fa5e4e37e80d28893a7fefee88ee6e0327600de893e0638479445bf0c9f5bd7b1a2429f409425d3945d6e942b23b37b8081630ac52244fb
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"openapi-typescript-helpers@npm:^0.0.15":
|
||||||
|
version: 0.0.15
|
||||||
|
resolution: "openapi-typescript-helpers@npm:0.0.15"
|
||||||
|
checksum: 10c0/5eb68d487b787e3e31266470b1a310726549dd45a1079655ab18066ab291b0b3c343fdf629991013706a2329b86964f8798d56ef0272b94b931fe6c19abd7a88
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"openapi-typescript@npm:^7.6.1":
|
||||||
|
version: 7.6.1
|
||||||
|
resolution: "openapi-typescript@npm:7.6.1"
|
||||||
|
dependencies:
|
||||||
|
"@redocly/openapi-core": "npm:^1.28.0"
|
||||||
|
ansi-colors: "npm:^4.1.3"
|
||||||
|
change-case: "npm:^5.4.4"
|
||||||
|
parse-json: "npm:^8.1.0"
|
||||||
|
supports-color: "npm:^9.4.0"
|
||||||
|
yargs-parser: "npm:^21.1.1"
|
||||||
|
peerDependencies:
|
||||||
|
typescript: ^5.x
|
||||||
|
bin:
|
||||||
|
openapi-typescript: bin/cli.js
|
||||||
|
checksum: 10c0/3591be796ac5eb1fe051b765c29e7cc5fcf9bb59e83eb43e13b4c98f25957d78523a5c8922eb52f1785b3fab6f5e269bc02892d72350ac7274d41192a36673c9
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"p-map@npm:^4.0.0":
|
"p-map@npm:^4.0.0":
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
resolution: "p-map@npm:4.0.0"
|
resolution: "p-map@npm:4.0.0"
|
||||||
@@ -1837,6 +2101,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"parse-json@npm:^8.1.0":
|
||||||
|
version: 8.3.0
|
||||||
|
resolution: "parse-json@npm:8.3.0"
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame": "npm:^7.26.2"
|
||||||
|
index-to-position: "npm:^1.1.0"
|
||||||
|
type-fest: "npm:^4.39.1"
|
||||||
|
checksum: 10c0/0eb5a50f88b8428c8f7a9cf021636c16664f0c62190323652d39e7bdf62953e7c50f9957e55e17dc2d74fc05c89c11f5553f381dbc686735b537ea9b101c7153
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"path-browserify@npm:^1.0.1":
|
"path-browserify@npm:^1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "path-browserify@npm:1.0.1"
|
resolution: "path-browserify@npm:1.0.1"
|
||||||
@@ -1868,7 +2143,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"picocolors@npm:^1.1.1":
|
"perfect-debounce@npm:^1.0.0":
|
||||||
|
version: 1.0.0
|
||||||
|
resolution: "perfect-debounce@npm:1.0.0"
|
||||||
|
checksum: 10c0/e2baac416cae046ef1b270812cf9ccfb0f91c04ea36ac7f5b00bc84cb7f41bdbba087c0ab21b4e02a7ef3a1f1f6db399f137cecec46868bd7d8d88c2a9ee431f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1":
|
||||||
version: 1.1.1
|
version: 1.1.1
|
||||||
resolution: "picocolors@npm:1.1.1"
|
resolution: "picocolors@npm:1.1.1"
|
||||||
checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58
|
checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58
|
||||||
@@ -1889,6 +2171,21 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"pinia@npm:^3.0.2":
|
||||||
|
version: 3.0.2
|
||||||
|
resolution: "pinia@npm:3.0.2"
|
||||||
|
dependencies:
|
||||||
|
"@vue/devtools-api": "npm:^7.7.2"
|
||||||
|
peerDependencies:
|
||||||
|
typescript: ">=4.4.4"
|
||||||
|
vue: ^2.7.0 || ^3.5.11
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
checksum: 10c0/4c21412ddb32c48c1d9fb9fb47a2cd40bc4af9198e65392423ab97f6a9da31d0b880bc59b008967058643a988cb574025f885a1d0e4faf47bec25521933bb27f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"pkg-types@npm:^1.3.0":
|
"pkg-types@npm:^1.3.0":
|
||||||
version: 1.3.1
|
version: 1.3.1
|
||||||
resolution: "pkg-types@npm:1.3.1"
|
resolution: "pkg-types@npm:1.3.1"
|
||||||
@@ -1911,6 +2208,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"pluralize@npm:^8.0.0":
|
||||||
|
version: 8.0.0
|
||||||
|
resolution: "pluralize@npm:8.0.0"
|
||||||
|
checksum: 10c0/2044cfc34b2e8c88b73379ea4a36fc577db04f651c2909041b054c981cd863dd5373ebd030123ab058d194ae615d3a97cfdac653991e499d10caf592e8b3dc33
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"postcss@npm:^8.4.48, postcss@npm:^8.5.3":
|
"postcss@npm:^8.4.48, postcss@npm:^8.5.3":
|
||||||
version: 8.5.3
|
version: 8.5.3
|
||||||
resolution: "postcss@npm:8.5.3"
|
resolution: "postcss@npm:8.5.3"
|
||||||
@@ -1985,6 +2289,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"require-from-string@npm:^2.0.2":
|
||||||
|
version: 2.0.2
|
||||||
|
resolution: "require-from-string@npm:2.0.2"
|
||||||
|
checksum: 10c0/aaa267e0c5b022fc5fd4eef49d8285086b15f2a1c54b28240fdf03599cbd9c26049fee3eab894f2e1f6ca65e513b030a7c264201e3f005601e80c49fb2937ce2
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"retry@npm:^0.12.0":
|
"retry@npm:^0.12.0":
|
||||||
version: 0.12.0
|
version: 0.12.0
|
||||||
resolution: "retry@npm:0.12.0"
|
resolution: "retry@npm:0.12.0"
|
||||||
@@ -1999,6 +2310,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"rfdc@npm:^1.4.1":
|
||||||
|
version: 1.4.1
|
||||||
|
resolution: "rfdc@npm:1.4.1"
|
||||||
|
checksum: 10c0/4614e4292356cafade0b6031527eea9bc90f2372a22c012313be1dcc69a3b90c7338158b414539be863fa95bfcb2ddcd0587be696841af4e6679d85e62c060c7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"roboto-fontface@npm:^0.10.0":
|
"roboto-fontface@npm:^0.10.0":
|
||||||
version: 0.10.0
|
version: 0.10.0
|
||||||
resolution: "roboto-fontface@npm:0.10.0"
|
resolution: "roboto-fontface@npm:0.10.0"
|
||||||
@@ -2094,9 +2412,9 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"sass@npm:^1.86.0":
|
"sass@npm:^1.86.3":
|
||||||
version: 1.86.0
|
version: 1.86.3
|
||||||
resolution: "sass@npm:1.86.0"
|
resolution: "sass@npm:1.86.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@parcel/watcher": "npm:^2.4.1"
|
"@parcel/watcher": "npm:^2.4.1"
|
||||||
chokidar: "npm:^4.0.0"
|
chokidar: "npm:^4.0.0"
|
||||||
@@ -2107,7 +2425,7 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
bin:
|
bin:
|
||||||
sass: sass.js
|
sass: sass.js
|
||||||
checksum: 10c0/921caea1fd8a450d4a986e5570ce13c4ca7b2a57da390811add3d2087ad8f46f53b34652ddcb237d8bdaad49c560b8d6eee130c733c787d058bc5a71a914c139
|
checksum: 10c0/ba819a0828f732adf7a94cd8ca017bce92bc299ffb878836ed1da80a30612bfbbf56a5e42d6dff3ad80d919c2025afb42948fc7b54a7bc61a9a2d58e1e0c558a
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -2192,6 +2510,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"speakingurl@npm:^14.0.1":
|
||||||
|
version: 14.0.1
|
||||||
|
resolution: "speakingurl@npm:14.0.1"
|
||||||
|
checksum: 10c0/1de1d1b938a7c4d9e79593ff7a26d312ec04a7c3234ca40b7f9b8106daf74ea9d2110a077f5db97ecf3762b83069e3ccbf9694431b51d4fcfd863f0b3333c342
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"sprintf-js@npm:^1.1.3":
|
"sprintf-js@npm:^1.1.3":
|
||||||
version: 1.1.3
|
version: 1.1.3
|
||||||
resolution: "sprintf-js@npm:1.1.3"
|
resolution: "sprintf-js@npm:1.1.3"
|
||||||
@@ -2248,6 +2573,22 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"superjson@npm:^2.2.1":
|
||||||
|
version: 2.2.2
|
||||||
|
resolution: "superjson@npm:2.2.2"
|
||||||
|
dependencies:
|
||||||
|
copy-anything: "npm:^3.0.2"
|
||||||
|
checksum: 10c0/aa49ebe6653e963020bc6a1ed416d267dfda84cfcc3cbd3beffd75b72e44eb9df7327215f3e3e77528f6e19ad8895b16a4964fdcd56d1799d14350db8c92afbc
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"supports-color@npm:^9.4.0":
|
||||||
|
version: 9.4.0
|
||||||
|
resolution: "supports-color@npm:9.4.0"
|
||||||
|
checksum: 10c0/6c24e6b2b64c6a60e5248490cfa50de5924da32cf09ae357ad8ebbf305cc5d2717ba705a9d4cb397d80bbf39417e8fdc8d7a0ce18bd0041bf7b5b456229164e4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"tar@npm:^6.1.11, tar@npm:^6.1.2":
|
"tar@npm:^6.1.11, tar@npm:^6.1.2":
|
||||||
version: 6.2.1
|
version: 6.2.1
|
||||||
resolution: "tar@npm:6.2.1"
|
resolution: "tar@npm:6.2.1"
|
||||||
@@ -2281,23 +2622,30 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"typescript@npm:^5.8.2":
|
"type-fest@npm:^4.39.1":
|
||||||
version: 5.8.2
|
version: 4.39.1
|
||||||
resolution: "typescript@npm:5.8.2"
|
resolution: "type-fest@npm:4.39.1"
|
||||||
bin:
|
checksum: 10c0/f5bf302eb2e2f70658be1757aa578f4a09da3f65699b0b12b7ae5502ccea76e5124521a6e6b69540f442c3dc924c394202a2ab58718d0582725c7ac23c072594
|
||||||
tsc: bin/tsc
|
|
||||||
tsserver: bin/tsserver
|
|
||||||
checksum: 10c0/5c4f6fbf1c6389b6928fe7b8fcd5dc73bb2d58cd4e3883f1d774ed5bd83b151cbac6b7ecf11723de56d4676daeba8713894b1e9af56174f2f9780ae7848ec3c6
|
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"typescript@patch:typescript@npm%3A^5.8.2#optional!builtin<compat/typescript>":
|
"typescript@npm:^5.8.3":
|
||||||
version: 5.8.2
|
version: 5.8.3
|
||||||
resolution: "typescript@patch:typescript@npm%3A5.8.2#optional!builtin<compat/typescript>::version=5.8.2&hash=5786d5"
|
resolution: "typescript@npm:5.8.3"
|
||||||
bin:
|
bin:
|
||||||
tsc: bin/tsc
|
tsc: bin/tsc
|
||||||
tsserver: bin/tsserver
|
tsserver: bin/tsserver
|
||||||
checksum: 10c0/5448a08e595cc558ab321e49d4cac64fb43d1fa106584f6ff9a8d8e592111b373a995a1d5c7f3046211c8a37201eb6d0f1566f15cdb7a62a5e3be01d087848e2
|
checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"typescript@patch:typescript@npm%3A^5.8.3#optional!builtin<compat/typescript>":
|
||||||
|
version: 5.8.3
|
||||||
|
resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin<compat/typescript>::version=5.8.3&hash=5786d5"
|
||||||
|
bin:
|
||||||
|
tsc: bin/tsc
|
||||||
|
tsserver: bin/tsserver
|
||||||
|
checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -2308,10 +2656,10 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"undici-types@npm:~6.20.0":
|
"undici-types@npm:~6.21.0":
|
||||||
version: 6.20.0
|
version: 6.21.0
|
||||||
resolution: "undici-types@npm:6.20.0"
|
resolution: "undici-types@npm:6.21.0"
|
||||||
checksum: 10c0/68e659a98898d6a836a9a59e6adf14a5d799707f5ea629433e025ac90d239f75e408e2e5ff086afc3cace26f8b26ee52155293564593fbb4a2f666af57fc59bf
|
checksum: 10c0/c01ed51829b10aa72fc3ce64b747f8e74ae9b60eafa19a7b46ef624403508a54c526ffab06a14a26b3120d055e1104d7abe7c9017e83ced038ea5cf52f8d5e04
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -2359,17 +2707,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"unplugin-vue-components@npm:^28.4.1":
|
"unplugin-vue-components@npm:^28.5.0":
|
||||||
version: 28.4.1
|
version: 28.5.0
|
||||||
resolution: "unplugin-vue-components@npm:28.4.1"
|
resolution: "unplugin-vue-components@npm:28.5.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar: "npm:^3.6.0"
|
chokidar: "npm:^3.6.0"
|
||||||
debug: "npm:^4.4.0"
|
debug: "npm:^4.4.0"
|
||||||
local-pkg: "npm:^1.0.0"
|
local-pkg: "npm:^1.1.1"
|
||||||
magic-string: "npm:^0.30.17"
|
magic-string: "npm:^0.30.17"
|
||||||
mlly: "npm:^1.7.4"
|
mlly: "npm:^1.7.4"
|
||||||
tinyglobby: "npm:^0.2.12"
|
tinyglobby: "npm:^0.2.12"
|
||||||
unplugin: "npm:^2.2.0"
|
unplugin: "npm:^2.3.2"
|
||||||
unplugin-utils: "npm:^0.2.4"
|
unplugin-utils: "npm:^0.2.4"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@babel/parser": ^7.15.8
|
"@babel/parser": ^7.15.8
|
||||||
@@ -2380,7 +2728,7 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
"@nuxt/kit":
|
"@nuxt/kit":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/f05448285e6d049b8aeadf5747cf7cda23105bfe8691326217abf3a5aa924768279f1c26f37ed0cd98c00f97ea7ce1cd5d5ed2916fb09f2b817f25563ece825a
|
checksum: 10c0/4a2419cee6a8d19e0dd121fa56afef29c981434ee4f632e972e46aec52f161608c85b0806737308c597ca6d19b07d62f654f4070bd4302c1691a1c865acb9248
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -2394,13 +2742,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"unplugin@npm:^2.2.0":
|
"unplugin@npm:^2.3.2":
|
||||||
version: 2.2.2
|
version: 2.3.2
|
||||||
resolution: "unplugin@npm:2.2.2"
|
resolution: "unplugin@npm:2.3.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: "npm:^8.14.1"
|
acorn: "npm:^8.14.1"
|
||||||
|
picomatch: "npm:^4.0.2"
|
||||||
webpack-virtual-modules: "npm:^0.6.2"
|
webpack-virtual-modules: "npm:^0.6.2"
|
||||||
checksum: 10c0/76ba320f0c5d18c31c6efab0bcf1f487e900193da7d9a63d50ccb87ea3c50bc9952111caee4ec5017bdcb53445dce275b994c6aeca6b92567db283ec5d9fc01b
|
checksum: 10c0/157a50072601b9bfbf3ab27a76a04685fb0af0c1a579d958787ffcb28a4d64e09acf42f0176e8767ccd940f27ee52d97a7f6aa6ce2e1e0dbe666ec26519750ef
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -2411,9 +2760,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"vite-plugin-vuetify@npm:^2.1.0":
|
"uri-js-replace@npm:^1.0.1":
|
||||||
version: 2.1.0
|
version: 1.0.1
|
||||||
resolution: "vite-plugin-vuetify@npm:2.1.0"
|
resolution: "uri-js-replace@npm:1.0.1"
|
||||||
|
checksum: 10c0/0be6c972c84c316e29667628ce7b4ce4de7fc77cec9a514f70c4a3336eea8d1d783c71c9988ac5da333f0f6a85a04a7ae05a3c4aa43af6cd07b7a4d85c8d9f11
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"vite-plugin-vuetify@npm:^2.1.1":
|
||||||
|
version: 2.1.1
|
||||||
|
resolution: "vite-plugin-vuetify@npm:2.1.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vuetify/loader-shared": "npm:^2.1.0"
|
"@vuetify/loader-shared": "npm:^2.1.0"
|
||||||
debug: "npm:^4.3.3"
|
debug: "npm:^4.3.3"
|
||||||
@@ -2422,13 +2778,13 @@ __metadata:
|
|||||||
vite: ">=5"
|
vite: ">=5"
|
||||||
vue: ^3.0.0
|
vue: ^3.0.0
|
||||||
vuetify: ^3.0.0
|
vuetify: ^3.0.0
|
||||||
checksum: 10c0/c9b6b3ee4b75ffc9b1f124f8f635d372f3258bd6f2abb48db42a80a4efe54127c9e325ad12eb92278ddbd629dfd1111810ec2bd6b1fb076f0724b789f33054e7
|
checksum: 10c0/629893488ae23ffd9e9a32fccf2d6ff4d5a00826329ec90e9765a17d182a9200ffe11430bd418227119e8ef3ed21eaec1bab0635a77fdcb4b64aac10f38adcb0
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"vite@npm:^6.2.2":
|
"vite@npm:^6.2.6":
|
||||||
version: 6.2.2
|
version: 6.2.6
|
||||||
resolution: "vite@npm:6.2.2"
|
resolution: "vite@npm:6.2.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: "npm:^0.25.0"
|
esbuild: "npm:^0.25.0"
|
||||||
fsevents: "npm:~2.3.3"
|
fsevents: "npm:~2.3.3"
|
||||||
@@ -2474,7 +2830,7 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
bin:
|
bin:
|
||||||
vite: bin/vite.js
|
vite: bin/vite.js
|
||||||
checksum: 10c0/52f5b1c10cfe5e3b6382c6de1811ebbf76df9b5a8bab3d65169446c6b54a5f1528f775b1548009a6d8aad11def20fba046bb3e9abb10c0c2c9ccd78118623bb8
|
checksum: 10c0/68a2ed3e61bdd654c59b817b4f3203065241c66d1739faa707499130f3007bc3a666c7a8320a4198e275e62b5e4d34d9b78a6533f69e321d366e76f5093b2071
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -2517,14 +2873,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"vuetify@npm:^3.7.18":
|
"vuetify@npm:^3.8.1":
|
||||||
version: 3.7.18
|
version: 3.8.1
|
||||||
resolution: "vuetify@npm:3.7.18"
|
resolution: "vuetify@npm:3.8.1"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: ">=4.7"
|
typescript: ">=4.7"
|
||||||
vite-plugin-vuetify: ">=1.0.0"
|
vite-plugin-vuetify: ">=2.1.0"
|
||||||
vue: ^3.3.0
|
vue: ^3.5.0
|
||||||
webpack-plugin-vuetify: ">=2.0.0"
|
webpack-plugin-vuetify: ">=3.1.0"
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
@@ -2532,7 +2888,7 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
webpack-plugin-vuetify:
|
webpack-plugin-vuetify:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/98686640dc11bb59e12fdb214e0fc8b2a4ecd2f8286448fddb6abecd858a0fd5db5927d443e9b3be7ff92303ae1c8bc01bf4712278a9b6e4f4d72358a36e0a0e
|
checksum: 10c0/b6fd1a96325b16a1f88acd1ef9d385118c09f25793bc7eddc3da2fe57e84a17d200d77dc14a2e0bc1b67fb6f301ce15b760185d2faafeaf61c584a92df6b0b45
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -2593,3 +2949,17 @@ __metadata:
|
|||||||
checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a
|
checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"yaml-ast-parser@npm:0.0.43":
|
||||||
|
version: 0.0.43
|
||||||
|
resolution: "yaml-ast-parser@npm:0.0.43"
|
||||||
|
checksum: 10c0/4d2f1e761067b2c6abdd882279a406f879258787af470a6d4a659cb79cb2ab056b870b25f1f80f46ed556e8b499d611d247806376f53edf3412f72c0a8ea2e98
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"yargs-parser@npm:^21.1.1":
|
||||||
|
version: 21.1.1
|
||||||
|
resolution: "yargs-parser@npm:21.1.1"
|
||||||
|
checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
10
go.mod
10
go.mod
@@ -39,10 +39,10 @@ require (
|
|||||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||||
github.com/zclconf/go-cty v1.16.2 // indirect
|
github.com/zclconf/go-cty v1.16.2 // indirect
|
||||||
github.com/zclconf/go-cty-yaml v1.1.0 // indirect
|
github.com/zclconf/go-cty-yaml v1.1.0 // indirect
|
||||||
golang.org/x/crypto v0.36.0 // indirect
|
golang.org/x/crypto v0.37.0 // indirect
|
||||||
golang.org/x/mod v0.24.0 // indirect
|
golang.org/x/mod v0.24.0 // indirect
|
||||||
golang.org/x/sync v0.12.0 // indirect
|
golang.org/x/sync v0.13.0 // indirect
|
||||||
golang.org/x/sys v0.31.0 // indirect
|
golang.org/x/sys v0.32.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/text v0.24.0 // indirect
|
||||||
golang.org/x/tools v0.31.0 // indirect
|
golang.org/x/tools v0.32.0 // indirect
|
||||||
)
|
)
|
||||||
|
20
go.sum
20
go.sum
@@ -191,8 +191,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
|
|||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
|
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
@@ -212,8 +212,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
|||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -232,8 +232,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
@@ -249,8 +249,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
@@ -262,8 +262,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
|||||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
@@ -224,6 +224,16 @@ components:
|
|||||||
format: int64
|
format: int64
|
||||||
description: Number of packages currently in the build queue
|
description: Number of packages currently in the build queue
|
||||||
example: 5
|
example: 5
|
||||||
|
building:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: Number of packages currently building
|
||||||
|
example: 11
|
||||||
|
last_mirror_timestamp:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: Latest mirror timestamp to detect outdated mirrors (Unix timestamp)
|
||||||
|
example: 1702612991
|
||||||
lto:
|
lto:
|
||||||
type: object
|
type: object
|
||||||
description: LTO status summary across all packages
|
description: LTO status summary across all packages
|
||||||
|
Reference in New Issue
Block a user