using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using System; using System.IO; using System.Linq; namespace OI.Metrology.Archive.ApiContollers; using OI.Metrology.Shared.DataModels; using OI.Metrology.Shared.Repositories; using OI.Metrology.Shared.Services; using System.Collections.Generic; using System.Text.Json; // using System.Data.Common; public class ToolTypesController : Controller { // this controller powers the bulk of the UI // it is named after the /api/tooltypes prefix // the URL pattern is RESTful and the tool type is the root of every request private IConfiguration Config { get; } protected IMetrologyRepo _Repo; protected IAttachmentsService _AttachmentsService; public ToolTypesController(IConfiguration config, IMetrologyRepo repo, IAttachmentsService attachmentsService) { Config = config; _Repo = repo; _AttachmentsService = attachmentsService; } // Get a list of tooltypes, returns just Name and ID [HttpGet("/api/tooltypes")] public IActionResult Index() { var r = new { Results = _Repo.GetToolTypes().Select(tt => new { tt.ToolTypeName, tt.ID }) }; return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true }); } // Gets the metadata for a tooltype, accepts a parameter which sorts the results // This is used to setup the grid displays on the UI [HttpGet("/api/tooltypes/{id}")] public IActionResult GetToolTypeMetadata(int id, string sortby = "") { ToolType tt = _Repo.GetToolTypeByID(id); IEnumerable md = _Repo.GetToolTypeMetadataByToolTypeID(id); if (string.Equals(sortby, "grid", StringComparison.OrdinalIgnoreCase)) md = md.OrderBy(f => f.GridDisplayOrder).ToList(); if (string.Equals(sortby, "table", StringComparison.OrdinalIgnoreCase)) md = md.OrderBy(f => f.GridDisplayOrder).ToList(); var r = new { Results = new { ToolType = tt, Metadata = md } }; return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true }); } //Just Changed here // Gets headers, request/response format is to allow paging with igniteUI // The headerid parameter is used for navigating directly to a header, when the button is clicked in Awaiting Dispo [HttpGet("/api/tooltypes/{id}/headers")] public IActionResult GetHeaders( int id, [FromQuery] DateTime? datebegin, [FromQuery] DateTime? dateend, [FromQuery] int? page, [FromQuery] int? pagesize, [FromQuery] long? headerid, bool isSharePoint) { long totalRecs; System.Data.DataTable dt = _Repo.GetHeaders(id, datebegin, dateend, page, pagesize, headerid, out totalRecs, isSharePoint); var r = new { Results = dt, TotalRows = totalRecs, }; string json = JsonConvert.SerializeObject(r); return Content(json); } // Gets header titles, used in the Run Headers UI [HttpGet("/api/tooltypes/{id}/headertitles")] public IActionResult GetHeaderTitles( int id, [FromQuery] int? page, [FromQuery] int? pagesize, bool isArchive) { long totalRecs; IEnumerable dt = _Repo.GetHeaderTitles(id, page, pagesize, out totalRecs, isArchive); var r = new { Results = dt, TotalRows = totalRecs, }; string json = JsonConvert.SerializeObject(r); return Content(json); } // Get all of the fields for a header, used with the Run Header UI [HttpGet("/api/tooltypes/{id}/headers/{headerid}/fields")] public IActionResult GetHeaderFields( int id, long headerid, bool isArchive) { var r = new { Results = _Repo.GetHeaderFields(id, headerid, isArchive).Select(x => new { Column = x.Key, x.Value }).ToList() }; string json = JsonConvert.SerializeObject(r); return Content(json); } // Get the data for a header, used with the Run Info UI [HttpGet("/api/tooltypes/{id}/headers/{title}/data/isSharePoint")] public IActionResult GetData( int id, string title) { var r = new { Results = _Repo.GetDataSharePoint(id, title) }; string json = JsonConvert.SerializeObject(r); return Content(json); } // Get the data for a header, used with the Run Info UI [HttpGet("/api/tooltypes/{id}/headers/{headerid}/data")] public IActionResult GetData( int id, long headerid, bool isSharePoint) { var r = new { Results = _Repo.GetData(id, headerid, isSharePoint) }; string json = JsonConvert.SerializeObject(r); return Content(json); } // Display an attachment, used for Run Info - note it is by tool type ID and attachment GUID, so it is best for internal use [HttpGet("/api/tooltypes/{toolTypeId}/{tabletype}/files/{attachmentId}/{filename}")] public IActionResult GetAttachment( int toolTypeId, string tabletype, string attachmentId, string filename, bool isArchive) { ToolType tt = _Repo.GetToolTypeByID(toolTypeId); bool header = !string.Equals(tabletype.Trim(), "data", StringComparison.OrdinalIgnoreCase); Guid attachmentIdParsed; if (!Guid.TryParse(attachmentId, out attachmentIdParsed)) return Content("Invalid attachment id"); //try // { // figure out what content type to use. this is very simple because there are only two types being used string contenttype = "application/pdf"; if (filename.ToLower().TrimEnd().EndsWith(".txt")) contenttype = "text/plain"; // Get attachment stream and feed it to the client Stream fs = _AttachmentsService.GetAttachmentStreamByAttachmentId(tt, header, attachmentIdParsed, filename); /*if (isArchive) { fs = attachmentsService.GetAttachmentStreamByAttachmentIdArchive(tt, header, attachmentIdParsed, filename); //fs = attachmentsService.GetAttachmentStreamByAttachmentId }*/ return File(fs, contenttype); //} /*catch (Exception ex) { return Content(ex.Message); }*/ } // This endpoint triggers writing of the OI Export file [HttpPost("/api/tooltypes/{toolTypeId}/headers/{headerid}/oiexport")] public IActionResult OIExport(int toolTypeId, long headerid) { // Call the export stored procedure System.Data.DataSet ds = _Repo.GetOIExportData(toolTypeId, headerid); try { // The SP must return 3 result tables if (ds.Tables.Count != 3) throw new Exception("Error exporting, invalid results"); // The first table has just one row, which is the export filename if (ds.Tables[0].Rows.Count != 1) throw new Exception("Error exporting, invalid filename"); string filename = Convert.ToString(ds.Tables[0].Rows[0][0]); // The second table has the header data if (ds.Tables[1].Rows.Count != 1) throw new Exception("Error exporting, invalid header data"); System.Text.StringBuilder sb = new(); foreach (object o in ds.Tables[1].Rows[0].ItemArray) { if ((o != null) && (!Convert.IsDBNull(o))) _ = sb.Append(Convert.ToString(o)); _ = sb.Append('\t'); } // The third table has the detail data foreach (System.Data.DataRow dr in ds.Tables[2].Rows) { foreach (object o in dr.ItemArray) { if ((o != null) && (!Convert.IsDBNull(o))) _ = sb.Append(Convert.ToString(o)); _ = sb.Append('\t'); } } _ = sb.AppendLine(); // The output file will only have one line, the header columns are output first // Then each detail rows has it's columns appended // H1, H2, H3, D1.1, D1.2, D1.3, D2.1, D2.2, D2.3, etc // Get the configured export path string exportRootPath = Config[Constants.OIExportPathKey]; // Write the file System.IO.File.WriteAllText( Path.Join(exportRootPath, filename), sb.ToString()); } catch (Exception ex) { string json = JsonConvert.SerializeObject(new { ex.Message, }); return BadRequest(json); } var r = new { Message = "OK", }; return Ok(r); } }