mirror of
https://github.com/Zproger/Aurum.git
synced 2026-10-13 02:56:39 +07:00
feat: показывать версию приложения в настройках, версия 1.1.0
Версии бэкенда и фронтенда были не синхронизированы и нигде не отображались в интерфейсе — непонятно было, обновилось ли приложение после пересборки. Теперь единая версия 1.1.0 приходит с бэкенда через /api/health и мелким текстом выводится внизу страницы настроек.
This commit is contained in:
@@ -4,9 +4,10 @@ from functools import lru_cache
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
# Single source of truth for the running app's version — surfaced in the API
|
||||
# title and embedded in exported backups so an old file can be told apart
|
||||
# from a current one.
|
||||
APP_VERSION = "0.20.0"
|
||||
# title, /api/health (which the frontend reads to show it in Settings), and
|
||||
# embedded in exported backups so an old file can be told apart from a
|
||||
# current one.
|
||||
APP_VERSION = "1.1.0"
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
|
||||
@@ -88,4 +88,7 @@ app.include_router(crypto.router, prefix="/api")
|
||||
|
||||
@app.get("/api/health")
|
||||
async def health() -> dict[str, str]:
|
||||
return {"status": "ok"}
|
||||
# version rides along so the frontend's Settings page can show which
|
||||
# release is actually running without a separate authenticated endpoint —
|
||||
# this route is already auth_basic-exempt for Docker's HEALTHCHECK.
|
||||
return {"status": "ok", "version": APP_VERSION}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "aurum-frontend",
|
||||
"private": true,
|
||||
"version": "0.26.0",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
6
frontend/src/api/health.ts
Normal file
6
frontend/src/api/health.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { api } from "@/api/client";
|
||||
import type { HealthStatus } from "@/types";
|
||||
|
||||
export function fetchHealth() {
|
||||
return api.get<HealthStatus>("/health");
|
||||
}
|
||||
8
frontend/src/hooks/useHealth.ts
Normal file
8
frontend/src/hooks/useHealth.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchHealth } from "@/api/health";
|
||||
|
||||
// The running version only changes on a deploy (a full page reload), so
|
||||
// there's no need to ever refetch within a session.
|
||||
export function useHealth() {
|
||||
return useQuery({ queryKey: ["health"], queryFn: fetchHealth, staleTime: Infinity });
|
||||
}
|
||||
@@ -341,6 +341,7 @@ const ru = {
|
||||
"Восстановить данные из «{{filename}}»?\n\nЭто ПОЛНОСТЬЮ заменит все текущие счета, категории, транзакции и активы данными из файла. Отменить это действие нельзя — если хотите сохранить текущие данные, сначала сделайте экспорт.",
|
||||
"backup.footerWarning":
|
||||
"Восстановление полностью заменяет текущие данные содержимым файла — это нельзя отменить.",
|
||||
"settings.version": "Aurum v{{version}}",
|
||||
|
||||
"insights.negativeCashFlow": "Расходы превышают доходы {{months}} мес. подряд (по последним завершённым месяцам)",
|
||||
"insights.netWorthDecline": "Капитал снижается {{months}} мес. подряд",
|
||||
@@ -823,6 +824,7 @@ const en: Record<keyof typeof ru, string> = {
|
||||
"Restore data from “{{filename}}”?\n\nThis will COMPLETELY replace all current accounts, categories, transactions, and assets with the data from the file. This action cannot be undone — if you want to keep your current data, export it first.",
|
||||
"backup.footerWarning":
|
||||
"Restoring completely replaces your current data with the file's contents — this cannot be undone.",
|
||||
"settings.version": "Aurum v{{version}}",
|
||||
|
||||
"insights.negativeCashFlow": "Expenses have exceeded income for {{months}} months in a row (based on the last completed months)",
|
||||
"insights.netWorthDecline": "Net worth has been declining for {{months}} months in a row",
|
||||
|
||||
@@ -2,14 +2,26 @@ import { AlertThresholdsCard } from "@/components/settings/AlertThresholdsCard";
|
||||
import { BackupCard } from "@/components/settings/BackupCard";
|
||||
import { CurrencyCard } from "@/components/settings/CurrencyCard";
|
||||
import { PreferencesCard } from "@/components/settings/PreferencesCard";
|
||||
import { useHealth } from "@/hooks/useHealth";
|
||||
import { t } from "@/lib/i18n";
|
||||
|
||||
export function SettingsPage() {
|
||||
// Purely informational — if /api/health hasn't answered yet (or is
|
||||
// unreachable), just show nothing rather than a loading/error state for
|
||||
// one line of fine print.
|
||||
const { data: health } = useHealth();
|
||||
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
<PreferencesCard />
|
||||
<CurrencyCard />
|
||||
<AlertThresholdsCard />
|
||||
<BackupCard />
|
||||
{health?.version && (
|
||||
<p className="text-center text-xs text-text-muted">
|
||||
{t("settings.version", { version: health.version })}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -517,3 +517,8 @@ export interface AppSettings {
|
||||
idle_cash_threshold_days: number;
|
||||
}
|
||||
|
||||
export interface HealthStatus {
|
||||
status: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user