From 920aaaa424d2d7ceafd54f7e49918ae9131b7931 Mon Sep 17 00:00:00 2001 From: lorsan Date: Mon, 26 Jan 2026 18:34:12 +0300 Subject: [PATCH] Add mobile interface and add handle metrics --- backend/app/main.py | 8 ++++++- backend/poetry.lock | 35 +++++++++++++++++++++++++++- backend/pyproject.toml | 3 ++- frontend/src/pages/AuthPage.tsx | 12 +++++----- frontend/src/pages/ChatPage.tsx | 30 +++++++++++++----------- frontend/src/pages/ProfilePage.tsx | 22 ++++++++--------- frontend/src/services/userService.ts | 6 ++++- 7 files changed, 82 insertions(+), 34 deletions(-) diff --git a/backend/app/main.py b/backend/app/main.py index 0d0bec7..9ffbece 100755 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -7,6 +7,7 @@ import asyncio from fastapi import FastAPI, APIRouter, Request, Response from fastapi.middleware.cors import CORSMiddleware +from prometheus_fastapi_instrumentator import Instrumentator from app.core.redis import close_redis, init_redis from app.users.router import router as user_router @@ -51,7 +52,6 @@ async def get_file(filename: str): if filename.endswith(".png"): content_type = "image/png" - # Возвращаем файл напрямую из памяти return Response( content=file_data, media_type=content_type @@ -61,6 +61,12 @@ app = FastAPI( description="## Backend messenger aether", lifespan=lifespan ) + +Instrumentator().instrument(app).expose( + app, + endpoint="/api/v1/p2qNT2Cz/SGQmQ==", + include_in_schema=False +) app.include_router(api_router) diff --git a/backend/poetry.lock b/backend/poetry.lock index 86a9e34..1043818 100755 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -1681,6 +1681,39 @@ files = [ dev = ["pre-commit", "tox"] testing = ["coverage", "pytest", "pytest-benchmark"] +[[package]] +name = "prometheus-client" +version = "0.24.1" +description = "Python client for the Prometheus monitoring system." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055"}, + {file = "prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9"}, +] + +[package.extras] +aiohttp = ["aiohttp"] +django = ["django"] +twisted = ["twisted"] + +[[package]] +name = "prometheus-fastapi-instrumentator" +version = "7.1.0" +description = "Instrument your FastAPI app with Prometheus metrics" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "prometheus_fastapi_instrumentator-7.1.0-py3-none-any.whl", hash = "sha256:978130f3c0bb7b8ebcc90d35516a6fe13e02d2eb358c8f83887cdef7020c31e9"}, + {file = "prometheus_fastapi_instrumentator-7.1.0.tar.gz", hash = "sha256:be7cd61eeea4e5912aeccb4261c6631b3f227d8924542d79eaf5af3f439cbe5e"}, +] + +[package.dependencies] +prometheus-client = ">=0.8.0,<1.0.0" +starlette = ">=0.30.0,<1.0.0" + [[package]] name = "prompt-toolkit" version = "3.0.52" @@ -3841,4 +3874,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.1" python-versions = ">=3.13" -content-hash = "0bc3ba3c9bfed0b76ac6aa34c14882ea972d982a889c657d5c39d5c317df1775" +content-hash = "7e4b0bc421fae38a72c65c92dad367b672b4cb7b6179059eac78773689af43db" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index e724d34..6596b80 100755 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -22,7 +22,8 @@ dependencies = [ "pytest (>=9.0.2,<10.0.0)", "aiobotocore (>=3.1.0,<4.0.0)", "types-aiobotocore[essential] (>=3.1.0,<4.0.0)", - "websockets (>=16.0,<17.0)" + "websockets (>=16.0,<17.0)", + "prometheus-fastapi-instrumentator (>=7.1.0,<8.0.0)" ] diff --git a/frontend/src/pages/AuthPage.tsx b/frontend/src/pages/AuthPage.tsx index 2b9a956..46ad6e5 100644 --- a/frontend/src/pages/AuthPage.tsx +++ b/frontend/src/pages/AuthPage.tsx @@ -8,7 +8,7 @@ export default function AuthPage() { const [isLogin, setIsLogin] = useState(true); return ( -
+
{/* Subtle texture background */}
-
+
{/* Logo */} -
-
+
+
Aether Logo
-
+
AETHER
{/* Sidebar */} -
+
{/* Header */} -
-

+
+

AETHER

@@ -470,11 +472,11 @@ export default function ChatPage() { )} {/* User Profile Section */} -
-
+
+
{/* Avatar */}
{/* Main Chat Area */} -
+
{selectedChat ? ( <> {/* Chat Header */} -
@@ -974,7 +978,7 @@ export default function ChatPage() { animate={{ opacity: 1, scale: 1, y: 0 }} exit={{ opacity: 0, scale: 0.8, y: 20 }} onClick={() => scrollToBottom(true)} - className="absolute bottom-24 right-8 p-3 rounded-full shadow-xl hover:scale-110 transition-transform" + className="absolute bottom-20 md:bottom-24 right-4 md:right-8 p-2.5 md:p-3 rounded-full shadow-xl hover:scale-110 transition-transform" style={{ backgroundColor: 'var(--accent-primary)', color: 'white', @@ -1002,11 +1006,11 @@ export default function ChatPage() { {/* Message Input */} -
-
+
{sendingMessage ? ( diff --git a/frontend/src/pages/ProfilePage.tsx b/frontend/src/pages/ProfilePage.tsx index 5a8e3c7..de79844 100644 --- a/frontend/src/pages/ProfilePage.tsx +++ b/frontend/src/pages/ProfilePage.tsx @@ -152,16 +152,16 @@ export default function ProfilePage() { return (
-
+
{/* Header */} -
+
)}
-

+

{user.username}

diff --git a/frontend/src/services/userService.ts b/frontend/src/services/userService.ts index 58d70fe..875d28b 100644 --- a/frontend/src/services/userService.ts +++ b/frontend/src/services/userService.ts @@ -32,7 +32,11 @@ export const userService = { }, updateProfile: async (data: UserUpdate): Promise => { - const response = await apiClient.put('/users/me', data); + // Filter out empty strings to avoid validation errors + const filteredData = Object.fromEntries( + Object.entries(data).filter(([_, value]) => value !== '') + ); + const response = await apiClient.put('/users/me', filteredData); return response.data; },