From 9bd5774e0847879094e4366f07e316729954a951 Mon Sep 17 00:00:00 2001 From: misya Date: Thu, 29 May 2025 09:23:13 +0800 Subject: [PATCH] fix data display --- Areas/MMS/Controllers/MarineController.cs | 292 ++++++++++++---------- Areas/MMS/Views/Marine/TarBallForm.cshtml | 22 +- 2 files changed, 172 insertions(+), 142 deletions(-) diff --git a/Areas/MMS/Controllers/MarineController.cs b/Areas/MMS/Controllers/MarineController.cs index e629af5..f1ac22e 100644 --- a/Areas/MMS/Controllers/MarineController.cs +++ b/Areas/MMS/Controllers/MarineController.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using MySqlConnector; +using Org.BouncyCastle.Asn1.Cms; namespace PSTW_CentralSystem.Areas.MMS.Controllers { @@ -18,25 +19,40 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers { // From tbl_marine_tarball public int Id { get; set; } - public string StationID { get; set; } - public string Longitude { get; set; } - public string Latitude { get; set; } + public required string StationID { get; set; } + public required string Longitude { get; set; } + public required string Latitude { get; set; } public DateTime DateSample { get; set; } public TimeSpan TimeSample { get; set; } - public string ClassifyID { get; set; } - public string OptionalName1 { get; set; } - public string OptionalName2 { get; set; } - public string OptionalName3 { get; set; } - public string OptionalName4 { get; set; } - public string FirstSampler { get; set; } + public required string ClassifyID { get; set; } + public string? OptionalName1 { get; set; } + public string? OptionalName2 { get; set; } + public string? OptionalName3 { get; set; } + public string? OptionalName4 { get; set; } + public required string FirstSampler { get; set; } // From joined tables - public string LocationName { get; set; } // From tbl_marine_station - public string StateName { get; set; } // From tbl_state - public string FullName { get; set; } // From tbl_user - public string LevelName { get; set; } // From tbl_level + public required string LocationName { get; set; } // From tbl_marine_station + public required string StateName { get; set; } // From tbl_state + public required string FullName { get; set; } // From tbl_user + public required string LevelName { get; set; } // From tbl_level } + public class TarBallGroupViewModel + { + public List Id { get; set; } = new List(); + public required string StationID { get; set; } + public required string Date { get; set; } + public required int TimeSampleCount { get; set; } + public required string LatestTime {get; set; } + public List TimeSamples { get; set; } = new List(); + } + + public class TarBallTimeSample + { + public required int Id { get; set; } + public string Time { get; set; } + } [Area("MMS")] public class MarineController : Controller { @@ -55,28 +71,37 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers return View(); } - public IActionResult TarBallForm()//Queries the database and returns a view with tarball data + public class StationDateGroup + { + public required string StationID { get; set; } + public DateTime DateSample { get; set; } + public List TimeSamples { get; set; } = new List(); + } + public IActionResult TarBallForm() { try { - var marineTarballs = _context.MarineTarballs //ERRORRRRRRR====================================== + var marineTarballs = _context.MarineTarballs .Select(t => new { t.Id, - Date = t.DateSample.ToString("yyyy/MM/dd"), - Station = t.StationID + station = t.StationID, + date = t.DateSample.ToString("yyyy/MM/dd"), + time = t.TimeSample.ToString(@"hh\:mm\:ss"), + fullDate = t.DateSample, // Keep DateTime for sorting + t.TimeSample }) + .AsEnumerable() + .OrderByDescending(t => t.fullDate) + .ThenByDescending(t => t.TimeSample) .ToList(); - Console.WriteLine($"Marine Tarballs Count: {marineTarballs.Count}"); return View(marineTarballs); } catch (Exception ex) { - // Show the real error in the browser (for debugging only) return Content($"Error: {ex.Message}
{ex.StackTrace}", "text/html"); } - } [HttpGet] // Explicitly mark as a GET endpoint @@ -222,7 +247,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers } } - public async Task GenerateReport(int id)//calls GeneratePdfResponse to generate a PDF for inline viewing + public async Task GenerateReport(int id) { return await GeneratePdfResponse(id, true); } @@ -239,7 +264,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers { // Add timeout for safety var task = Task.Run(() => GeneratePdfResponse(id, false)); - if (task.Wait(TimeSpan.FromSeconds(30))) // 30 second timeout + if (task.Wait(TimeSpan.FromSeconds(30))) // 30-second timeout { return task.Result; } @@ -254,159 +279,156 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers private async Task GeneratePdfResponse(int id, bool forceDownload) { - Console.WriteLine($"Requested ID in {(forceDownload ? "GenerateReport" : "ViewPDF")}: {id}"); - - // Temporary network connection test try { - Console.WriteLine("Testing network connection..."); - _networkAccessService.ConnectToNetworkPath(); - Console.WriteLine("Network connected successfully!"); - _networkAccessService.DisconnectFromNetworkShare(); - } - catch (Exception ex) - { - Console.WriteLine($"NETWORK ERROR: {ex.Message}"); - return StatusCode(500, $"Cannot access network: {ex.Message}"); - } - - try - { - // Connect to the network path _networkAccessService.ConnectToNetworkPath(); - // ===== 1. NEW SQL QUERY APPROACH ===== + var record = await _context.MarineTarballs.FirstOrDefaultAsync(t => t.Id == id); + if (record == null) + return NotFound($"No record found for Id: {id}"); + + // Retrieve all entries for the same StationID and DateSample var query = @" SELECT marine.*, station.LocationName, state.StateName, - user.FullName,level.LevelName + user.FullName, + level.LevelName FROM tbl_marine_tarball marine JOIN tbl_marine_station station ON marine.StationID = station.StationID JOIN tbl_state state ON station.StateID = state.StateID - JOIN tbl_user user ON marine.FirstSampler = user.FullName -- Corrected column name + JOIN tbl_user user ON marine.FirstSampler = user.FullName JOIN tbl_level level ON user.LevelID = level.LevelID - WHERE marine.Id = @id"; + WHERE marine.Id=@id"; - var tarball = await _context.Database + var tarballEntries = await _context.Database .SqlQueryRaw(query, new MySqlParameter("@id", id)) - .FirstOrDefaultAsync(); + .ToListAsync(); - if (tarball == null) - return NotFound("Record not found"); + if (!tarballEntries.Any()) + return NotFound($"No records found for Id: {id}"); - //Prepare boolean values for PDF - bool tarBallYes = tarball.ClassifyID != "NO"; - bool tarBallNo = tarball.ClassifyID == "NO"; - bool isSand = tarball.ClassifyID == "SD"; - bool isNonSandy = tarball.ClassifyID == "NS"; - bool isCoquina = tarball.ClassifyID == "CO"; + var pdfList = new List(); - // ===== 2. Get Images from path ===== - var sampleDateString = tarball.DateSample.ToString("yyyyMMdd"); - //var sampleTimeString = tarball.TimeSample.ToString("hhmmss"); - var sampleTimePrefix = ((int)tarball.TimeSample.TotalHours).ToString("D2") + - tarball.TimeSample.Minutes.ToString("D2"); - var stationFolder = Path.Combine(PhotoBasePath, tarball.StationID); - - //Image collection - var stationImages = new Dictionary(); - - if (Directory.Exists(stationFolder)) + // Iterate over each unique TimeSample within the same DateSample + foreach (var timeGroup in tarballEntries.GroupBy(t => t.TimeSample)) { - var imageTypes = new Dictionary - { - { "LEFTSIDECOASTALVIEW", null }, - { "RIGHTSIDECOASTALVIEW", null }, - { "DRAWINGVERTICALLINES", null }, - { "DRAWINGHORIZONTALLINES", null }, - { "OPTIONAL01", null }, // Will remain null if not found - { "OPTIONAL02", null }, - { "OPTIONAL03", null }, - { "OPTIONAL04", null } - }; + var tarball = timeGroup.First(); // Use first entry per time sample - foreach (var imagePath in Directory.GetFiles(stationFolder)) + // Classification logic remains unchanged + bool tarBallYes = tarball.ClassifyID != "NO"; + bool tarBallNo = tarball.ClassifyID == "NO"; + bool isSand = tarball.ClassifyID == "SD"; + bool isNonSandy = tarball.ClassifyID == "NS"; + bool isCoquina = tarball.ClassifyID == "CO"; + + // Construct image paths ensuring correct naming format + var stationFolder = Path.Combine(PhotoBasePath, tarball.StationID); + var sampleDateString = tarball.DateSample.ToString("yyyyMMdd"); + var sampleTimeString = tarball.TimeSample.ToString(@"hhmmss"); + + var stationImages = new Dictionary(); + + if (Directory.Exists(stationFolder)) { - var fileName = Path.GetFileNameWithoutExtension(imagePath); - foreach (var type in imageTypes.Keys.ToList()) + var imageTypes = new Dictionary { - if (fileName.EndsWith(type, StringComparison.OrdinalIgnoreCase)) + { "LEFTSIDECOASTALVIEW", null }, + { "RIGHTSIDECOASTALVIEW", null }, + { "DRAWINGVERTICALLINES", null }, + { "DRAWINGHORIZONTALLINES", null }, + { "OPTIONAL01", null }, + { "OPTIONAL02", null }, + { "OPTIONAL03", null }, + { "OPTIONAL04", null } + }; + + foreach (var imagePath in Directory.GetFiles(stationFolder)) + { + var fileName = Path.GetFileNameWithoutExtension(imagePath); + foreach (var type in imageTypes.Keys.ToList()) { - imageTypes[type] = imagePath; - break; + if (fileName.StartsWith($"{tarball.StationID}_{sampleDateString}_{sampleTimeString}") && + fileName.Contains(type, StringComparison.OrdinalIgnoreCase)) + { + imageTypes[type] = imagePath; + break; + } } } + stationImages = imageTypes; } - stationImages = imageTypes; - } - //Mandatory images - var mandatoryImages = new List - { - "LEFTSIDECOASTALVIEW", - "RIGHTSIDECOASTALVIEW", - "DRAWINGVERTICALLINES", - "DRAWINGHORIZONTALLINES" - }; - foreach(var mandatoryType in mandatoryImages) - { - if(!stationImages.ContainsKey(mandatoryType)) + // Validate mandatory images exist + var mandatoryImages = new List { - return StatusCode(400, $"Missing mandatory image: {mandatoryType}"); + "LEFTSIDECOASTALVIEW", + "RIGHTSIDECOASTALVIEW", + "DRAWINGVERTICALLINES", + "DRAWINGHORIZONTALLINES" + }; + + foreach (var mandatoryType in mandatoryImages) + { + if (!stationImages.ContainsKey(mandatoryType) || stationImages[mandatoryType] == null) + { + return StatusCode(400, $"Missing mandatory image: {mandatoryType} for {tarball.StationID} on {tarball.DateSample}"); + } } + + // Generate PDF using existing classification and sorting logic + var pdfDocument = new TarBallPDF( + tarball.StateName, + tarball.StationID, + tarball.LocationName, + tarball.Longitude, + tarball.Latitude, + tarball.DateSample, + tarball.TimeSample, + tarball.ClassifyID, + tarBallYes, + tarBallNo, + isSand, + isNonSandy, + isCoquina, + stationImages["LEFTSIDECOASTALVIEW"], + stationImages["RIGHTSIDECOASTALVIEW"], + stationImages["DRAWINGVERTICALLINES"], + stationImages["DRAWINGHORIZONTALLINES"], + stationImages.GetValueOrDefault("OPTIONAL01"), + stationImages.GetValueOrDefault("OPTIONAL02"), + stationImages.GetValueOrDefault("OPTIONAL03"), + stationImages.GetValueOrDefault("OPTIONAL04"), + tarball.OptionalName1, + tarball.OptionalName2, + tarball.OptionalName3, + tarball.OptionalName4, + tarball.FirstSampler, + tarball.FullName, + tarball.LevelName + ).GeneratePdf(); + + string pdfFileName = $"{tarball.StationID}_{tarball.DateSample:yyyyMMdd}_{tarball.TimeSample:hhmmss}.pdf"; + + pdfList.Add( + forceDownload + ? File(pdfDocument, "application/pdf", pdfFileName) + : File(pdfDocument, "application/pdf") + ); } - // ===== 3. GENERATE PDF (ADAPTED FOR NEW DTO) ===== - var pdf = new TarBallPDF( - tarball.StateName, - tarball.StationID, - tarball.LocationName, - tarball.Longitude, - tarball.Latitude, - tarball.DateSample, - tarball.TimeSample, - tarball.ClassifyID, - tarBallYes, - tarBallNo, - isSand, - isNonSandy, - isCoquina, - stationImages["LEFTSIDECOASTALVIEW"], - stationImages["RIGHTSIDECOASTALVIEW"], - stationImages["DRAWINGVERTICALLINES"], - stationImages["DRAWINGHORIZONTALLINES"], - stationImages.GetValueOrDefault("OPTIONAL01"), - stationImages.GetValueOrDefault("OPTIONAL02"), - stationImages.GetValueOrDefault("OPTIONAL03"), - stationImages.GetValueOrDefault("OPTIONAL04"), - tarball.OptionalName1, - tarball.OptionalName2, - tarball.OptionalName3, - tarball.OptionalName4, - tarball.FirstSampler, - tarball.FullName, - tarball.LevelName - ).GeneratePdf(); - - return forceDownload - ? File(pdf, "application/pdf", $"{tarball.StationID}_{tarball.DateSample:yyyyMMdd}_{tarball.TimeSample:hhmmss}.pdf") - : File(pdf, "application/pdf"); + return pdfList.Count == 1 ? pdfList.First() : Ok(pdfList); } catch (Exception ex) { - var errorMessage = ex.InnerException != null - ? $"{ex.Message} (Inner: {ex.InnerException.Message})" - : ex.Message; - return Content($"PDF generation failed: {errorMessage}
{ex.StackTrace}", "text/html"); + return StatusCode(500, $"Error: {ex.Message}"); } finally { _networkAccessService.DisconnectFromNetworkShare(); } } - private bool IsImageValid(string imagePath) { try diff --git a/Areas/MMS/Views/Marine/TarBallForm.cshtml b/Areas/MMS/Views/Marine/TarBallForm.cshtml index 40f179f..151a445 100644 --- a/Areas/MMS/Views/Marine/TarBallForm.cshtml +++ b/Areas/MMS/Views/Marine/TarBallForm.cshtml @@ -102,15 +102,21 @@ return []; // Return an empty array if no data is available } - // Extract all years from the data - const allYears = this.dataFromServer.map(data => new Date(data.date).getFullYear()); + // Extract all years from the data (handling both FormattedDate and date) + const allYears = this.dataFromServer.map(data => { + const dateStr = data.Date || data.date; // Handle both cases + return new Date(dateStr).getFullYear(); + }); // Find the minimum and maximum years const minYear = Math.min(...allYears); const maxYear = Math.max(...allYears); // Generate a range of years from minYear to maxYear - return Array.from({ length: maxYear - minYear + 1 }, (_, i) => (minYear + i).toString()); + return Array.from( + { length: maxYear - minYear + 1 }, + (_, i) => (minYear + i).toString() + ); }, sortedFilteredData() { // If no filters are applied, return all data sorted by descending date @@ -154,11 +160,11 @@ "data": null, "render": (data, type, row, meta) => meta.row + 1 // Dynamically generate "No." }, - { "data": "date", "render": (data) => new Date(data).toLocaleDateString('en-GB') }, + { "data": "date"}, { "data": "station" }, { "data": null, - "render": () => ` + "render": (data) => ` ` @@ -166,8 +172,10 @@ { "data": null, "render": (data) => ` - View PDF - Download PDF + View PDF + Download PDF ` } ],