feat: affiche les versions API, Indexer et Backoffice dans About
- Endpoint GET /version sur l'indexer (sans auth) - Le backoffice fetch la version indexer directement (INDEXER_BASE_URL) - Grille 3 colonnes avec les 3 versions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,7 @@ interface SettingsPageProps {
|
|||||||
initialStatusMappings: Record<string, unknown>[];
|
initialStatusMappings: Record<string, unknown>[];
|
||||||
initialSeriesStatuses: string[];
|
initialSeriesStatuses: string[];
|
||||||
initialProviderStatuses: string[];
|
initialProviderStatuses: string[];
|
||||||
versions?: { api: string; backoffice: string };
|
versions?: { api: string; indexer: string; backoffice: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SettingsPage({ initialSettings, initialCacheStats, initialThumbnailStats, users, initialTab, initialProwlarr, initialQbittorrent, initialTorrentImport, initialTelegram, initialAnilist, initialKomga, initialMetadataProviders, initialStatusMappings, initialSeriesStatuses, initialProviderStatuses, versions }: SettingsPageProps) {
|
export default function SettingsPage({ initialSettings, initialCacheStats, initialThumbnailStats, users, initialTab, initialProwlarr, initialQbittorrent, initialTorrentImport, initialTelegram, initialAnilist, initialKomga, initialMetadataProviders, initialStatusMappings, initialSeriesStatuses, initialProviderStatuses, versions }: SettingsPageProps) {
|
||||||
@@ -543,7 +543,7 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
|||||||
<p className="text-sm text-muted-foreground mt-1">{t("settings.aboutDesc")}</p>
|
<p className="text-sm text-muted-foreground mt-1">{t("settings.aboutDesc")}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
|
||||||
<div className="flex items-center gap-3 p-3 rounded-lg bg-muted/30 border border-border/40">
|
<div className="flex items-center gap-3 p-3 rounded-lg bg-muted/30 border border-border/40">
|
||||||
<div className="w-8 h-8 rounded-md bg-primary/10 flex items-center justify-center shrink-0">
|
<div className="w-8 h-8 rounded-md bg-primary/10 flex items-center justify-center shrink-0">
|
||||||
<Icon name="settings" size="sm" className="text-primary" />
|
<Icon name="settings" size="sm" className="text-primary" />
|
||||||
@@ -553,6 +553,15 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
|||||||
<p className="text-sm font-mono font-medium text-foreground">{versions?.api ?? "?"}</p>
|
<p className="text-sm font-mono font-medium text-foreground">{versions?.api ?? "?"}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex items-center gap-3 p-3 rounded-lg bg-muted/30 border border-border/40">
|
||||||
|
<div className="w-8 h-8 rounded-md bg-primary/10 flex items-center justify-center shrink-0">
|
||||||
|
<Icon name="jobs" size="sm" className="text-primary" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-muted-foreground">Indexer</p>
|
||||||
|
<p className="text-sm font-mono font-medium text-foreground">{versions?.indexer ?? "?"}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="flex items-center gap-3 p-3 rounded-lg bg-muted/30 border border-border/40">
|
<div className="flex items-center gap-3 p-3 rounded-lg bg-muted/30 border border-border/40">
|
||||||
<div className="w-8 h-8 rounded-md bg-primary/10 flex items-center justify-center shrink-0">
|
<div className="w-8 h-8 rounded-md bg-primary/10 flex items-center justify-center shrink-0">
|
||||||
<Icon name="books" size="sm" className="text-primary" />
|
<Icon name="books" size="sm" className="text-primary" />
|
||||||
|
|||||||
@@ -4,9 +4,21 @@ import packageJson from "../../../package.json";
|
|||||||
|
|
||||||
export const dynamic = "force-dynamic";
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
async function fetchIndexerVersion(): Promise<string> {
|
||||||
|
try {
|
||||||
|
const indexerUrl = (process.env.INDEXER_BASE_URL || "http://indexer:7081").replace(/\/$/, "");
|
||||||
|
const res = await fetch(`${indexerUrl}/version`, { signal: AbortSignal.timeout(3000) });
|
||||||
|
if (res.ok) {
|
||||||
|
const data = await res.json();
|
||||||
|
return data?.indexer ?? "?";
|
||||||
|
}
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
export default async function SettingsPageWrapper({ searchParams }: { searchParams: Promise<{ tab?: string }> }) {
|
export default async function SettingsPageWrapper({ searchParams }: { searchParams: Promise<{ tab?: string }> }) {
|
||||||
const { tab } = await searchParams;
|
const { tab } = await searchParams;
|
||||||
const [settings, cacheStats, thumbnailStats, users, prowlarr, qbittorrent, torrentImport, telegram, anilist, komga, metadataProviders, statusMappings, seriesStatuses, providerStatuses, apiVersion] = await Promise.all([
|
const [settings, cacheStats, thumbnailStats, users, prowlarr, qbittorrent, torrentImport, telegram, anilist, komga, metadataProviders, statusMappings, seriesStatuses, providerStatuses, apiVersion, indexerVersion] = await Promise.all([
|
||||||
getSettings().catch(() => ({
|
getSettings().catch(() => ({
|
||||||
image_processing: { format: "webp", quality: 85, filter: "lanczos3", max_width: 2160 },
|
image_processing: { format: "webp", quality: 85, filter: "lanczos3", max_width: 2160 },
|
||||||
cache: { enabled: true, directory: "/tmp/stripstream-image-cache", max_size_mb: 10000 },
|
cache: { enabled: true, directory: "/tmp/stripstream-image-cache", max_size_mb: 10000 },
|
||||||
@@ -27,10 +39,12 @@ export default async function SettingsPageWrapper({ searchParams }: { searchPara
|
|||||||
apiFetch<unknown[]>("/series/statuses").catch(() => []),
|
apiFetch<unknown[]>("/series/statuses").catch(() => []),
|
||||||
apiFetch<unknown[]>("/series/provider-statuses").catch(() => []),
|
apiFetch<unknown[]>("/series/provider-statuses").catch(() => []),
|
||||||
apiFetch<{ api?: string }>("/version").catch(() => ({ api: "?" })),
|
apiFetch<{ api?: string }>("/version").catch(() => ({ api: "?" })),
|
||||||
|
fetchIndexerVersion(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const versions = {
|
const versions = {
|
||||||
api: apiVersion?.api ?? "?",
|
api: apiVersion?.api ?? "?",
|
||||||
|
indexer: indexerVersion,
|
||||||
backoffice: packageJson.version,
|
backoffice: packageJson.version,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ pub async fn health() -> &'static str {
|
|||||||
"ok"
|
"ok"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn version() -> Json<serde_json::Value> {
|
||||||
|
Json(serde_json::json!({
|
||||||
|
"indexer": env!("CARGO_PKG_VERSION"),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn ready(State(state): State<AppState>) -> Result<Json<serde_json::Value>, StatusCode> {
|
pub async fn ready(State(state): State<AppState>) -> Result<Json<serde_json::Value>, StatusCode> {
|
||||||
sqlx::query("SELECT 1")
|
sqlx::query("SELECT 1")
|
||||||
.execute(&state.pool)
|
.execute(&state.pool)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ async fn async_main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/health", get(api::health))
|
.route("/health", get(api::health))
|
||||||
|
.route("/version", get(api::version))
|
||||||
.route("/ready", get(api::ready))
|
.route("/ready", get(api::ready))
|
||||||
.with_state(state.clone());
|
.with_state(state.clone());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user