From 25c22b2ff548add1cf0249fbf3f5ff9735049b53 Mon Sep 17 00:00:00 2001 From: Toutsu Date: Sat, 2 May 2026 15:40:24 +0300 Subject: [PATCH] fix: stabilize session table layout --- .gitea/workflows/deploy.yml | 2 +- Directory.Build.props | 2 +- README.md | 2 +- compose.yaml | 4 +- .../Components/Layout/NavMenu.razor | 2 +- .../Components/Pages/GroupDetails.razor | 11 +- src/GmRelay.Web/wwwroot/app.css | 152 ++++++++++++------ tests/GmRelay.Bot.Tests/Web/WebStylesTests.cs | 50 ++++++ 8 files changed, 162 insertions(+), 63 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 1af3c02..4b6f329 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -6,7 +6,7 @@ on: - main env: - VERSION: 1.9.4 + VERSION: 1.9.5 jobs: # ЧАСТЬ 1: Собираем образы и кладем в Gitea (чтобы делиться с ребятами) diff --git a/Directory.Build.props b/Directory.Build.props index af95313..064759d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 1.9.4 + 1.9.5 net10.0 preview enable diff --git a/README.md b/README.md index 5085d44..d150dec 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Проект разработан с упором на производительность, архитектуру Vertical Slice, Native AOT (для бота) и удобство развертывания с использованием .NET Aspire. -**Текущая версия:** `v1.9.4`. +**Текущая версия:** `v1.9.5`. --- diff --git a/compose.yaml b/compose.yaml index 6b0bf48..ccf543b 100644 --- a/compose.yaml +++ b/compose.yaml @@ -17,7 +17,7 @@ services: retries: 10 bot: - image: git.codeanddice.ru/toutsu/gmrelay-bot:1.9.4 + image: git.codeanddice.ru/toutsu/gmrelay-bot:1.9.5 restart: always depends_on: db: @@ -30,7 +30,7 @@ services: - gmrelay web: - image: git.codeanddice.ru/toutsu/gmrelay-web:1.9.4 + image: git.codeanddice.ru/toutsu/gmrelay-web:1.9.5 restart: always depends_on: db: diff --git a/src/GmRelay.Web/Components/Layout/NavMenu.razor b/src/GmRelay.Web/Components/Layout/NavMenu.razor index 05d502e..0841b6e 100644 --- a/src/GmRelay.Web/Components/Layout/NavMenu.razor +++ b/src/GmRelay.Web/Components/Layout/NavMenu.razor @@ -56,7 +56,7 @@ - + diff --git a/src/GmRelay.Web/Components/Pages/GroupDetails.razor b/src/GmRelay.Web/Components/Pages/GroupDetails.razor index 46d6ff6..b14b5e1 100644 --- a/src/GmRelay.Web/Components/Pages/GroupDetails.razor +++ b/src/GmRelay.Web/Components/Pages/GroupDetails.razor @@ -214,7 +214,7 @@ @* Desktop table *@ -
+
@@ -237,19 +237,18 @@ @TranslateStatus(session.Status)
- + Подключиться ↗ -
- +
+ ✏️ Изменить @if (CanPromote(session)) { - } diff --git a/src/GmRelay.Web/wwwroot/app.css b/src/GmRelay.Web/wwwroot/app.css index 4a0b96e..4eed4be 100644 --- a/src/GmRelay.Web/wwwroot/app.css +++ b/src/GmRelay.Web/wwwroot/app.css @@ -1,5 +1,5 @@ /* ============================================ - GM-Relay Design System v1.9.4 + GM-Relay Design System v1.9.5 Dark RPG Dashboard Theme ============================================ */ @@ -422,6 +422,46 @@ select option { border-bottom: none; } +.session-table-desktop { + overflow-x: auto; + overflow-y: hidden; +} + +.session-table-desktop-card { + padding: 0; +} + +.session-table-desktop .gm-table { + min-width: 760px; +} + +.session-table-desktop .gm-table th:last-child, +.session-table-desktop .gm-table td:last-child { + width: 8.5rem; + min-width: 8.5rem; +} + +.session-join-link { + display: inline-block; + max-width: 150px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.session-table-actions { + display: flex; + align-items: center; + gap: 0.5rem; + flex-wrap: wrap; +} + +.session-table-actions .btn-gm { + font-size: 0.8125rem; + padding: 0.375rem 0.75rem; + white-space: nowrap; +} + /* === Alerts === */ .gm-alert { padding: 0.875rem 1.125rem; @@ -918,7 +958,64 @@ body.telegram-mini-app .content { display: none; } -@media (max-width: 768px) { +body.telegram-mini-app .session-table-desktop { + display: none; +} + +body.telegram-mini-app .session-card-mobile { + display: block; +} + +.session-card { + background: var(--glass-bg); + backdrop-filter: blur(var(--glass-blur)); + border: 1px solid var(--glass-border); + border-radius: var(--radius-md); + padding: 1rem; + margin-bottom: 0.75rem; + transition: all var(--transition-smooth); +} + +.session-card:hover { + border-color: var(--border-glow); +} + +.session-card-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 0.75rem; +} + +.session-card-title { + font-weight: 600; + font-size: 0.9375rem; + color: var(--text-primary); +} + +.session-card-body { + display: flex; + flex-direction: column; + gap: 0.5rem; + font-size: 0.8125rem; + color: var(--text-secondary); +} + +.session-card-row { + display: flex; + justify-content: space-between; + align-items: center; +} + +.session-card-actions { + margin-top: 0.75rem; + padding-top: 0.75rem; + border-top: 1px solid var(--border-color); + display: flex; + gap: 0.5rem; +} + +@media (max-width: 1024px) { .session-table-desktop { display: none; } @@ -926,56 +1023,9 @@ body.telegram-mini-app .content { .session-card-mobile { display: block; } +} - .session-card { - background: var(--glass-bg); - backdrop-filter: blur(var(--glass-blur)); - border: 1px solid var(--glass-border); - border-radius: var(--radius-md); - padding: 1rem; - margin-bottom: 0.75rem; - transition: all var(--transition-smooth); - } - - .session-card:hover { - border-color: var(--border-glow); - } - - .session-card-header { - display: flex; - justify-content: space-between; - align-items: flex-start; - margin-bottom: 0.75rem; - } - - .session-card-title { - font-weight: 600; - font-size: 0.9375rem; - color: var(--text-primary); - } - - .session-card-body { - display: flex; - flex-direction: column; - gap: 0.5rem; - font-size: 0.8125rem; - color: var(--text-secondary); - } - - .session-card-row { - display: flex; - justify-content: space-between; - align-items: center; - } - - .session-card-actions { - margin-top: 0.75rem; - padding-top: 0.75rem; - border-top: 1px solid var(--border-color); - display: flex; - gap: 0.5rem; - } - +@media (max-width: 768px) { .card-grid { grid-template-columns: 1fr; } diff --git a/tests/GmRelay.Bot.Tests/Web/WebStylesTests.cs b/tests/GmRelay.Bot.Tests/Web/WebStylesTests.cs index ac29adf..635d945 100644 --- a/tests/GmRelay.Bot.Tests/Web/WebStylesTests.cs +++ b/tests/GmRelay.Bot.Tests/Web/WebStylesTests.cs @@ -25,6 +25,56 @@ public sealed class WebStylesTests Assert.Contains(".telegram-mini-app .nav-toggle", appCss, StringComparison.Ordinal); } + [Fact] + public async Task AppCss_ShouldKeepDesktopSessionActionsReadableWhenTableOverflows() + { + var appCss = await File.ReadAllTextAsync(FindRepositoryFile("src/GmRelay.Web/wwwroot/app.css")); + + Assert.Matches( + @"\.session-table-desktop\s*\{[\s\S]*overflow-x:\s*auto;", + appCss); + Assert.Matches( + @"\.session-table-desktop\s+\.gm-table\s*\{[\s\S]*min-width:\s*760px;", + appCss); + Assert.Matches( + @"\.session-table-actions\s+\.btn-gm\s*\{[\s\S]*white-space:\s*nowrap;", + appCss); + } + + [Fact] + public async Task AppCss_ShouldUseCardSessionLayoutInsideTelegramMiniApp() + { + var appCss = await File.ReadAllTextAsync(FindRepositoryFile("src/GmRelay.Web/wwwroot/app.css")); + + Assert.Matches( + @"body\.telegram-mini-app\s+\.session-table-desktop\s*\{[\s\S]*display:\s*none;", + appCss); + Assert.Matches( + @"body\.telegram-mini-app\s+\.session-card-mobile\s*\{[\s\S]*display:\s*block;", + appCss); + } + + [Fact] + public async Task AppCss_ShouldUseCardSessionLayoutWhenDesktopSidebarLeavesNarrowContent() + { + var appCss = await File.ReadAllTextAsync(FindRepositoryFile("src/GmRelay.Web/wwwroot/app.css")); + + Assert.Matches( + @"@media\s*\(max-width:\s*1024px\)\s*\{[\s\S]*\.session-table-desktop\s*\{[\s\S]*display:\s*none;[\s\S]*\.session-card-mobile\s*\{[\s\S]*display:\s*block;", + appCss); + } + + [Fact] + public async Task GroupDetailsPage_ShouldUseSessionTableLayoutClasses() + { + var groupDetailsPage = await File.ReadAllTextAsync(FindRepositoryFile("src/GmRelay.Web/Components/Pages/GroupDetails.razor")); + + Assert.Contains("session-table-desktop-card", groupDetailsPage, StringComparison.Ordinal); + Assert.Contains("session-table-actions", groupDetailsPage, StringComparison.Ordinal); + Assert.Contains("session-join-link", groupDetailsPage, StringComparison.Ordinal); + Assert.DoesNotContain("overflow: hidden", groupDetailsPage, StringComparison.Ordinal); + } + private static string FindRepositoryFile(string relativePath) { var directory = new DirectoryInfo(AppContext.BaseDirectory);