From fe225f32250c29a0a079f5acd01aa08408d90890 Mon Sep 17 00:00:00 2001 From: mx57 <38256814+mx57@users.noreply.github.com> Date: Sun, 6 Sep 2026 20:30:59 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20log=20file=20download=20featu?= =?UTF-8?q?re=20to=20Web=20Dashboard=20Live=20Log=20Monitor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HomeControllerTests.cs | 69 +++++++++++++++++++ .../IntelliTrader.Trading.Tests.csproj | 1 + .../Controllers/HomeController.cs | 23 +++++++ .../Static/Scripts/Views/dashboard.js | 1 + IntelliTrader.Web/Views/Home/Dashboard.cshtml | 11 ++- magda_agent_system/agent_tasks.json | 18 ++++- 6 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 IntelliTrader.Trading.Tests/HomeControllerTests.cs diff --git a/IntelliTrader.Trading.Tests/HomeControllerTests.cs b/IntelliTrader.Trading.Tests/HomeControllerTests.cs new file mode 100644 index 0000000..b7ab752 --- /dev/null +++ b/IntelliTrader.Trading.Tests/HomeControllerTests.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; +using IntelliTrader.Core; +using IntelliTrader.Web.Controllers; +using Microsoft.AspNetCore.Mvc; +using Moq; +using Xunit; + +namespace IntelliTrader.Trading.Tests +{ + public class HomeControllerTests + { + [Fact] + public void DownloadLog_ReturnsNotFound_WhenLogFileDoesNotExist() + { + // Arrange + var controller = new HomeController(); + string tempDir = Path.Combine(Directory.GetCurrentDirectory(), "log"); + + // Ensure directory exists or create temporary directory context if needed + if (!Directory.Exists(tempDir)) + { + Directory.CreateDirectory(tempDir); + } + + // Act + var result = controller.DownloadLog("nonexistent_log_type"); + + // Assert + var notFoundResult = Assert.IsType(result); + Assert.Equal("Log file not found.", notFoundResult.Value); + } + + [Fact] + public void DownloadLog_ReturnsFileStreamResult_WhenLogFileExists() + { + // Arrange + var controller = new HomeController(); + string logsPath = Path.Combine(Directory.GetCurrentDirectory(), "log"); + if (!Directory.Exists(logsPath)) + { + Directory.CreateDirectory(logsPath); + } + + string testLogFile = Path.Combine(logsPath, $"{DateTime.Now:yyyy-MM-dd}-general.txt"); + File.WriteAllText(testLogFile, "Log line 1\nLog line 2\n"); + + try + { + // Act + var result = controller.DownloadLog("general"); + + // Assert + var fileResult = Assert.IsType(result); + Assert.Equal("text/plain", fileResult.ContentType); + Assert.Equal(Path.GetFileName(testLogFile), fileResult.FileDownloadName); + + fileResult.FileStream.Dispose(); + } + finally + { + if (File.Exists(testLogFile)) + { + File.Delete(testLogFile); + } + } + } + } +} diff --git a/IntelliTrader.Trading.Tests/IntelliTrader.Trading.Tests.csproj b/IntelliTrader.Trading.Tests/IntelliTrader.Trading.Tests.csproj index 3d88629..6d1e7bb 100644 --- a/IntelliTrader.Trading.Tests/IntelliTrader.Trading.Tests.csproj +++ b/IntelliTrader.Trading.Tests/IntelliTrader.Trading.Tests.csproj @@ -22,6 +22,7 @@ + diff --git a/IntelliTrader.Web/Controllers/HomeController.cs b/IntelliTrader.Web/Controllers/HomeController.cs index 27edbbc..6be62e2 100644 --- a/IntelliTrader.Web/Controllers/HomeController.cs +++ b/IntelliTrader.Web/Controllers/HomeController.cs @@ -561,6 +561,29 @@ public IActionResult PollLogs(string type = "general", int maxLines = 100) } } + [HttpGet] + public IActionResult DownloadLog(string type = "general") + { + try + { + string pattern = "general".Equals(type, StringComparison.OrdinalIgnoreCase) ? "*-general.txt" : "*-trades.txt"; + string filePath = GetLatestLogFilePath(pattern); + + if (string.IsNullOrEmpty(filePath) || !System.IO.File.Exists(filePath)) + { + return NotFound("Log file not found."); + } + + string fileName = Path.GetFileName(filePath); + var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + return File(stream, "text/plain", fileName); + } + catch (Exception ex) + { + return BadRequest($"Error downloading log file: {ex.Message}"); + } + } + private string GetLatestLogFilePath(string pattern) { var logsPath = Path.Combine(Directory.GetCurrentDirectory(), "log"); diff --git a/IntelliTrader.Web/Static/Scripts/Views/dashboard.js b/IntelliTrader.Web/Static/Scripts/Views/dashboard.js index 1a2d24f..f323f88 100644 --- a/IntelliTrader.Web/Static/Scripts/Views/dashboard.js +++ b/IntelliTrader.Web/Static/Scripts/Views/dashboard.js @@ -205,6 +205,7 @@ function setLogType(type) { $("#logTypeGeneralBtn").removeClass("active"); } + $("#downloadLogFileBtn").attr("href", "/Home/DownloadLog?type=" + type); $("#logTerminal").html('
Loading logs...
'); pollLiveLogs(); } diff --git a/IntelliTrader.Web/Views/Home/Dashboard.cshtml b/IntelliTrader.Web/Views/Home/Dashboard.cshtml index 29406e5..e4c5340 100644 --- a/IntelliTrader.Web/Views/Home/Dashboard.cshtml +++ b/IntelliTrader.Web/Views/Home/Dashboard.cshtml @@ -457,9 +457,14 @@
Live Log Monitor
-
- - +
+ + Скачать лог + +
+ + +
diff --git a/magda_agent_system/agent_tasks.json b/magda_agent_system/agent_tasks.json index 42a30c7..e565c0c 100644 --- a/magda_agent_system/agent_tasks.json +++ b/magda_agent_system/agent_tasks.json @@ -476,7 +476,7 @@ }, { "id": "web-dashboard-log-download", - "status": "todo", + "status": "done", "area": "web", "risk": "low", "title": "Add log file download button on Web Dashboard", @@ -505,6 +505,22 @@ "acceptance": [ "Users can click export on the Stats page to download summary statistics." ] + }, + { + "id": "web-dashboard-log-search-filter", + "status": "todo", + "area": "web", + "risk": "low", + "title": "Add text search filter to Live Log Monitor on Web Dashboard", + "description": "Add an inline search input field to the Live Log Monitor card allowing users to filter log lines dynamically in real-time.", + "allowed_paths": [ + "IntelliTrader.Web/Views/**", + "IntelliTrader.Web/Controllers/**", + "magda_agent_system/agent_tasks.json" + ], + "acceptance": [ + "Users can type keywords into a filter box to instantly highlight or filter log terminal output." + ] } ] }