debug de l'application vue

This commit is contained in:
2025-10-26 18:30:50 +01:00
parent 79271514b4
commit bbecd8efb5
4 changed files with 88 additions and 15 deletions

View File

@@ -93,8 +93,8 @@
</div> </div>
<div class="pk">{{ track.pk }}</div> <div class="pk">{{ track.pk }}</div>
<div class="meta"> <div class="meta">
<span v-if="track.metadata?.duration_ms"> <span v-if="durationMs(track) !== undefined">
{{ formatDuration(track.metadata.duration_ms) }} {{ formatDuration(durationMs(track)!) }}
</span> </span>
<span v-if="track.metadata?.sample_rate"> <span v-if="track.metadata?.sample_rate">
{{ formatSampleRate(track.metadata.sample_rate) }} {{ formatSampleRate(track.metadata.sample_rate) }}
@@ -147,7 +147,9 @@
<p v-if="selectedTrack.metadata.year"><strong>Year:</strong> {{ selectedTrack.metadata.year }}</p> <p v-if="selectedTrack.metadata.year"><strong>Year:</strong> {{ selectedTrack.metadata.year }}</p>
<p v-if="selectedTrack.metadata.genre"><strong>Genre:</strong> {{ selectedTrack.metadata.genre }}</p> <p v-if="selectedTrack.metadata.genre"><strong>Genre:</strong> {{ selectedTrack.metadata.genre }}</p>
<p v-if="selectedTrack.metadata.track_number"><strong>Track:</strong> {{ selectedTrack.metadata.track_number }}</p> <p v-if="selectedTrack.metadata.track_number"><strong>Track:</strong> {{ selectedTrack.metadata.track_number }}</p>
<p v-if="selectedTrack.metadata.duration_ms"><strong>Duration:</strong> {{ formatDuration(selectedTrack.metadata.duration_ms) }}</p> <p v-if="durationMs(selectedTrack) !== undefined">
<strong>Duration:</strong> {{ formatDuration(durationMs(selectedTrack)!) }}
</p>
<p v-if="selectedTrack.metadata.sample_rate"><strong>Sample Rate:</strong> {{ formatSampleRate(selectedTrack.metadata.sample_rate) }}</p> <p v-if="selectedTrack.metadata.sample_rate"><strong>Sample Rate:</strong> {{ formatSampleRate(selectedTrack.metadata.sample_rate) }}</p>
<p v-if="selectedTrack.metadata.bitrate"><strong>Bitrate:</strong> {{ formatBitrate(selectedTrack.metadata.bitrate) }}</p> <p v-if="selectedTrack.metadata.bitrate"><strong>Bitrate:</strong> {{ formatBitrate(selectedTrack.metadata.bitrate) }}</p>
<p v-if="selectedTrack.metadata.channels"><strong>Channels:</strong> {{ selectedTrack.metadata.channels }}</p> <p v-if="selectedTrack.metadata.channels"><strong>Channels:</strong> {{ selectedTrack.metadata.channels }}</p>
@@ -155,7 +157,11 @@
<div class="cache-section"> <div class="cache-section">
<h4>Cache Info</h4> <h4>Cache Info</h4>
<p><strong>PK:</strong> {{ selectedTrack.pk }}</p> <p><strong>PK:</strong> {{ selectedTrack.pk }}</p>
<p><strong>Source URL:</strong> <a :href="selectedTrack.source_url" target="_blank">{{ selectedTrack.source_url }}</a></p> <p v-if="resolveTrackOrigin(selectedTrack)">
<strong>Source URL:</strong>
<a :href="resolveTrackOrigin(selectedTrack)" target="_blank">{{ resolveTrackOrigin(selectedTrack) }}</a>
</p>
<p v-else><strong>Source URL:</strong> Unknown</p>
<p><strong>Hits:</strong> {{ selectedTrack.hits }}</p> <p><strong>Hits:</strong> {{ selectedTrack.hits }}</p>
<p v-if="selectedTrack.collection"><strong>Collection:</strong> {{ selectedTrack.collection }}</p> <p v-if="selectedTrack.collection"><strong>Collection:</strong> {{ selectedTrack.collection }}</p>
<p v-if="selectedTrack.last_used"><strong>Last Used:</strong> {{ formatDate(selectedTrack.last_used) }}</p> <p v-if="selectedTrack.last_used"><strong>Last Used:</strong> {{ formatDate(selectedTrack.last_used) }}</p>
@@ -206,6 +212,8 @@ import {
consolidateCache, consolidateCache,
getTrackUrl, getTrackUrl,
getOriginalTrackUrl, getOriginalTrackUrl,
getOriginUrl,
getDurationMs,
formatDuration, formatDuration,
formatBitrate, formatBitrate,
formatSampleRate, formatSampleRate,
@@ -388,6 +396,14 @@ function copyTrackUrl(pk: string) {
alert("✅ URL copied!"); alert("✅ URL copied!");
} }
function resolveTrackOrigin(track: AudioCacheEntry | null): string | undefined {
return track ? getOriginUrl(track) : undefined;
}
function durationMs(track: AudioCacheEntry | null): number | undefined {
return track ? getDurationMs(track.metadata) : undefined;
}
function formatDate(dateString: string) { function formatDate(dateString: string) {
const d = new Date(dateString); const d = new Date(dateString);
const diff = Date.now() - d.getTime(); const diff = Date.now() - d.getTime();

View File

@@ -71,7 +71,7 @@
<div class="image-wrapper"> <div class="image-wrapper">
<img <img
:src="getImageUrl(image.pk, 256)" :src="getImageUrl(image.pk, 256)"
:alt="image.source_url" :alt="resolveOrigin(image) || image.pk"
loading="lazy" loading="lazy"
@error="handleImageError" @error="handleImageError"
/> />
@@ -81,8 +81,8 @@
</div> </div>
<div class="image-info"> <div class="image-info">
<div class="pk">{{ image.pk }}</div> <div class="pk">{{ image.pk }}</div>
<div class="url" :title="image.source_url"> <div class="url" :title="resolveOrigin(image) || 'Unknown source'">
{{ truncateUrl(image.source_url) }} {{ truncateUrl(resolveOrigin(image)) }}
</div> </div>
<div class="meta"> <div class="meta">
<span v-if="image.last_used" class="last-used"> <span v-if="image.last_used" class="last-used">
@@ -108,13 +108,17 @@
<button class="modal-close" @click="selectedImage = null">✕</button> <button class="modal-close" @click="selectedImage = null">✕</button>
<img <img
:src="getImageUrl(selectedImage.pk)" :src="getImageUrl(selectedImage.pk)"
:alt="selectedImage.source_url" :alt="resolveOrigin(selectedImage) || selectedImage.pk"
class="modal-image" class="modal-image"
/> />
<div class="modal-info"> <div class="modal-info">
<h3>Image Details</h3> <h3>Image Details</h3>
<p><strong>PK:</strong> {{ selectedImage.pk }}</p> <p><strong>PK:</strong> {{ selectedImage.pk }}</p>
<p><strong>Source URL:</strong> <a :href="selectedImage.source_url" target="_blank">{{ selectedImage.source_url }}</a></p> <p v-if="resolveOrigin(selectedImage)">
<strong>Source URL:</strong>
<a :href="resolveOrigin(selectedImage)" target="_blank">{{ resolveOrigin(selectedImage) }}</a>
</p>
<p v-else><strong>Source URL:</strong> Unknown</p>
<p><strong>Hits:</strong> {{ selectedImage.hits }}</p> <p><strong>Hits:</strong> {{ selectedImage.hits }}</p>
<p v-if="selectedImage.last_used"><strong>Last Used:</strong> {{ formatDate(selectedImage.last_used) }}</p> <p v-if="selectedImage.last_used"><strong>Last Used:</strong> {{ formatDate(selectedImage.last_used) }}</p>
<div class="modal-actions"> <div class="modal-actions">
@@ -141,6 +145,7 @@ import {
purgeCache, purgeCache,
consolidateCache, consolidateCache,
getImageUrl, getImageUrl,
getOriginUrl,
waitForDownload, waitForDownload,
} from "../services/coverCache"; } from "../services/coverCache";
@@ -229,7 +234,14 @@ function copyImageUrl(pk:string){
alert("✅ URL copied!"); alert("✅ URL copied!");
} }
function truncateUrl(url:string,maxLength=40){ return url.length<=maxLength?url:url.slice(0,maxLength-3)+"..."; } function resolveOrigin(entry: CacheEntry | null): string | undefined {
return entry ? getOriginUrl(entry) : undefined;
}
function truncateUrl(url?:string,maxLength=40){
if(!url) return "Unknown source";
return url.length<=maxLength?url:url.slice(0,maxLength-3)+"...";
}
function formatDate(dateString:string){ function formatDate(dateString:string){
const d=new Date(dateString), diff=Date.now()-d.getTime(), days=Math.floor(diff/(1000*60*60*24)); const d=new Date(dateString), diff=Date.now()-d.getTime(), days=Math.floor(diff/(1000*60*60*24));
if(days===0)return"Today"; if(days===1)return"Yesterday"; if(days<7)return`${days} days ago`; return d.toLocaleDateString(); if(days===0)return"Today"; if(days===1)return"Yesterday"; if(days<7)return`${days} days ago`; return d.toLocaleDateString();

View File

@@ -2,27 +2,32 @@
* Service API pour interagir avec le cache de pistes audio * Service API pour interagir avec le cache de pistes audio
*/ */
export interface AudioMetadata { export interface AudioCacheMetadata {
origin_url?: string;
title?: string; title?: string;
artist?: string; artist?: string;
album?: string; album?: string;
year?: number; year?: number;
genre?: string; genre?: string;
track_number?: number; track_number?: number;
track_total?: number;
disc_number?: number; disc_number?: number;
disc_total?: number;
duration_ms?: number; duration_ms?: number;
duration_secs?: number;
sample_rate?: number; sample_rate?: number;
bitrate?: number; bitrate?: number;
channels?: number; channels?: number;
[key: string]: unknown;
} }
export interface AudioCacheEntry { export interface AudioCacheEntry {
pk: string; pk: string;
source_url: string; id: string | null;
hits: number; hits: number;
last_used: string | null; last_used: string | null;
collection?: string; collection?: string | null;
metadata?: AudioMetadata; metadata?: AudioCacheMetadata | null;
} }
export interface AddTrackRequest { export interface AddTrackRequest {
@@ -48,6 +53,28 @@ export interface ApiError {
message: string; message: string;
} }
export function getOriginUrl(entry: AudioCacheEntry): string | undefined {
const metadata = entry.metadata;
if (metadata && typeof metadata === "object") {
const origin = (metadata as { origin_url?: unknown }).origin_url;
if (typeof origin === "string" && origin.trim().length > 0) {
return origin;
}
}
return undefined;
}
export function getDurationMs(metadata?: AudioCacheMetadata | null): number | undefined {
if (!metadata) return undefined;
if (typeof metadata.duration_ms === "number" && !Number.isNaN(metadata.duration_ms)) {
return metadata.duration_ms;
}
if (typeof metadata.duration_secs === "number" && !Number.isNaN(metadata.duration_secs)) {
return metadata.duration_secs * 1000;
}
return undefined;
}
/** /**
* Liste toutes les pistes en cache * Liste toutes les pistes en cache
*/ */

View File

@@ -2,11 +2,18 @@
* Service API pour interagir avec le cache d'images de couvertures * Service API pour interagir avec le cache d'images de couvertures
*/ */
export interface CacheMetadata {
origin_url?: string;
[key: string]: unknown;
}
export interface CacheEntry { export interface CacheEntry {
pk: string; pk: string;
source_url: string; id: string | null;
collection?: string | null;
hits: number; hits: number;
last_used: string | null; last_used: string | null;
metadata?: CacheMetadata | null;
} }
export interface AddImageRequest { export interface AddImageRequest {
@@ -168,6 +175,17 @@ export async function waitForDownload(
/** /**
* Génère l'URL pour afficher une image * Génère l'URL pour afficher une image
*/ */
export function getOriginUrl(entry: CacheEntry): string | undefined {
const metadata = entry.metadata;
if (metadata && typeof metadata === "object") {
const origin = (metadata as { origin_url?: unknown }).origin_url;
if (typeof origin === "string" && origin.trim().length > 0) {
return origin;
}
}
return undefined;
}
export function getImageUrl(pk: string, size?: number): string { export function getImageUrl(pk: string, size?: number): string {
if (size) { if (size) {
return `/covers/image/${pk}/${size}`; return `/covers/image/${pk}/${size}`;