TargetFramework update,
reference updates and added tests for Viewer
This commit is contained in:
29
Viewer/ApiControllers/AppSettingsController.cs
Normal file
29
Viewer/ApiControllers/AppSettingsController.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using OI.Metrology.Shared.Models.Stateless;
|
||||
|
||||
namespace OI.Metrology.Viewer.ApiControllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AppSettingsController : ControllerBase, IAppSettingsController<ActionResult>
|
||||
{
|
||||
|
||||
private readonly IAppSettingsRepository _AppSettingsRepository;
|
||||
|
||||
public AppSettingsController(IAppSettingsRepository AppSettingsRepository) => _AppSettingsRepository = AppSettingsRepository;
|
||||
|
||||
[HttpGet(nameof(IAppSettingsController<ActionResult>.Action.App))]
|
||||
public ActionResult GetAppSettings()
|
||||
{
|
||||
List<string> results = _AppSettingsRepository.GetAppSettings();
|
||||
return Ok(results);
|
||||
}
|
||||
|
||||
[HttpGet(nameof(IAppSettingsController<ActionResult>.Action.DevOps))]
|
||||
public ActionResult GetBuildNumberAndGitCommitSeven()
|
||||
{
|
||||
string result = _AppSettingsRepository.GetBuildNumberAndGitCommitSeven();
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
}
|
@ -1,50 +1,39 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using OI.Metrology.Shared.DataModels;
|
||||
using OI.Metrology.Shared.Repositories;
|
||||
using OI.Metrology.Shared.Models.Stateless;
|
||||
using OI.Metrology.Shared.Services;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace OI.Metrology.Viewer.ApiControllers;
|
||||
|
||||
public class AttachmentsController : Controller
|
||||
{
|
||||
private readonly IMetrologyRepo _Repo;
|
||||
private readonly IAttachmentsService _AttachmentsService;
|
||||
|
||||
public AttachmentsController(IMetrologyRepo repo, IAttachmentsService attachmentsService)
|
||||
private readonly IAttachmentsService _AttachmentsService;
|
||||
private readonly IMetrologyRepository _MetrologyRepository;
|
||||
|
||||
public AttachmentsController(IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService)
|
||||
{
|
||||
_Repo = repo;
|
||||
_AttachmentsService = attachmentsService;
|
||||
_MetrologyRepository = metrologyRepository;
|
||||
}
|
||||
|
||||
// this endpoint was created in hope that it would make retrieving attachments to display in OpenInsight easier
|
||||
// url would be like /api/attachments/mercuryprobe/header/HgProbe_66-232268-4329_20180620052640032/data.pdf
|
||||
|
||||
[HttpGet("/api/attachments/{toolTypeName}/{tabletype}/{title}/{filename}")]
|
||||
public IActionResult GetAttachment(
|
||||
string toolTypeName,
|
||||
string tabletype,
|
||||
string title,
|
||||
string filename)
|
||||
public IActionResult GetAttachment(string toolTypeName, string tabletype, string title, string filename)
|
||||
{
|
||||
ToolType tt = _Repo.GetToolTypeByName(toolTypeName);
|
||||
|
||||
ToolType tt = _MetrologyRepository.GetToolTypeByName(toolTypeName);
|
||||
bool header = !string.Equals(tabletype.Trim(), "data", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
try
|
||||
{
|
||||
string contenttype = "application/pdf";
|
||||
if (filename.ToLower().TrimEnd().EndsWith(".txt"))
|
||||
contenttype = "text/plain";
|
||||
|
||||
Stream fs = _AttachmentsService.GetAttachmentStreamByTitle(tt, header, title, filename);
|
||||
return File(fs, contenttype);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Content(ex.Message);
|
||||
}
|
||||
|
||||
catch (Exception ex) { return Content(ex.Message); }
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +1,31 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace OI.Metrology.Viewer.ApiContollers;
|
||||
namespace OI.Metrology.Viewer.ApiControllers;
|
||||
|
||||
using OI.Metrology.Shared.Repositories;
|
||||
using OI.Metrology.Shared.Models.Stateless;
|
||||
using System.Text.Json;
|
||||
|
||||
// this controller is for the Awaiting Dispo functionality
|
||||
|
||||
[Route("api/[controller]")]
|
||||
public class AwaitingDispoController : Controller
|
||||
{
|
||||
private readonly IMetrologyRepo _Repo;
|
||||
|
||||
public AwaitingDispoController(IMetrologyRepo repo) => _Repo = repo;
|
||||
private readonly IMetrologyRepository _MetrologyRepository;
|
||||
public AwaitingDispoController(IMetrologyRepository metrologyRepository) =>
|
||||
_MetrologyRepository = metrologyRepository;
|
||||
|
||||
// returns the data to show in the Awaiting Dispo grid
|
||||
// marked no-cache, just-in-case since igniteUI automatically adds a query string parameter to prevent caching
|
||||
[HttpGet("/api/awaitingdispo")]
|
||||
[HttpGet]
|
||||
[ResponseCache(NoStore = true)]
|
||||
public IActionResult Index()
|
||||
{
|
||||
|
||||
var r = new
|
||||
{
|
||||
Results = _Repo.GetAwaitingDispo()
|
||||
};
|
||||
return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
|
||||
}
|
||||
public IActionResult Index() =>
|
||||
Json(_MetrologyRepository.GetAwaitingDispo(), new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
|
||||
|
||||
// this endpoint is used to set the ReviewDate column, causing the header to no longer show in Awaiting Dispo
|
||||
[HttpPost("/api/awaitingdispo/markasreviewed")]
|
||||
public IActionResult MarkAsReviewed([FromQuery] long headerid, [FromQuery] int tooltypeid)
|
||||
{
|
||||
_ = _Repo.UpdateReviewDate(tooltypeid, headerid, false);
|
||||
_ = _MetrologyRepository.UpdateReviewDate(tooltypeid, headerid, false);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@ -39,7 +33,7 @@ public class AwaitingDispoController : Controller
|
||||
[HttpPost("/api/awaitingdispo/markasawaiting")]
|
||||
public IActionResult MarkAsAwaiting([FromQuery] long headerid, [FromQuery] int tooltypeid)
|
||||
{
|
||||
if (_Repo.UpdateReviewDate(tooltypeid, headerid, true) <= 1)
|
||||
if (_MetrologyRepository.UpdateReviewDate(tooltypeid, headerid, true) <= 1)
|
||||
return Ok();
|
||||
else
|
||||
return StatusCode(444);
|
||||
|
29
Viewer/ApiControllers/ClientSettingsController.cs
Normal file
29
Viewer/ApiControllers/ClientSettingsController.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using OI.Metrology.Shared.Models.Stateless;
|
||||
|
||||
namespace OI.Metrology.Viewer.ApiControllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class ClientSettingsController : ControllerBase, IClientSettingsController<ActionResult>
|
||||
{
|
||||
|
||||
private readonly IClientSettingsRepository _ClientSettingsRepository;
|
||||
|
||||
public ClientSettingsController(IClientSettingsRepository clientSettingsRepository) => _ClientSettingsRepository = clientSettingsRepository;
|
||||
|
||||
[HttpGet(nameof(IClientSettingsController<ActionResult>.Action.Client))]
|
||||
public ActionResult GetClientSettings()
|
||||
{
|
||||
List<string> results = _ClientSettingsRepository.GetClientSettings(Request.HttpContext.Connection?.RemoteIpAddress);
|
||||
return Ok(results);
|
||||
}
|
||||
|
||||
[HttpGet(nameof(IClientSettingsController<ActionResult>.Action.IP))]
|
||||
public ActionResult GetIpAddress()
|
||||
{
|
||||
string result = _ClientSettingsRepository.GetIpAddress(Request.HttpContext.Connection?.RemoteIpAddress);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
}
|
@ -1,168 +1,78 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OI.Metrology.Shared.DataModels;
|
||||
using OI.Metrology.Shared.Repositories;
|
||||
using OI.Metrology.Shared.Models;
|
||||
using OI.Metrology.Shared.Models.Stateless;
|
||||
using OI.Metrology.Shared.Services;
|
||||
using OI.Metrology.Viewer.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
||||
namespace OI.Metrology.Viewer.ApiContollers;
|
||||
namespace OI.Metrology.Viewer.ApiControllers;
|
||||
|
||||
[ApiController]
|
||||
public class InboundController : ControllerBase
|
||||
[Route("api/[controller]")]
|
||||
public partial class InboundController : ControllerBase, IInboundController<IActionResult>
|
||||
{
|
||||
|
||||
private readonly ILogger _Logger;
|
||||
private readonly IMetrologyRepo _Repo;
|
||||
private readonly AppSettings _AppSettings;
|
||||
private readonly IAttachmentsService _AttachmentService;
|
||||
private readonly IInboundRepository _InboundRepository;
|
||||
private readonly IAttachmentsService _AttachmentsService;
|
||||
private readonly IInboundDataService _InboundDataService;
|
||||
private readonly IMetrologyRepository _MetrologyRepository;
|
||||
|
||||
public InboundController(AppSettings appSettings, ILogger<InboundController> logger, IMetrologyRepo repo, IInboundDataService inboundDataService, IAttachmentsService attachmentService)
|
||||
public InboundController(AppSettings appSettings, ILogger<InboundController> logger, IMetrologyRepository metrologyRepository, IInboundRepository inboundRepository, IInboundDataService inboundDataService, IAttachmentsService attachmentsService)
|
||||
{
|
||||
_Repo = repo;
|
||||
_Logger = logger;
|
||||
_AppSettings = appSettings;
|
||||
_AttachmentService = attachmentService;
|
||||
_InboundRepository = inboundRepository;
|
||||
_AttachmentsService = attachmentsService;
|
||||
_InboundDataService = inboundDataService;
|
||||
_MetrologyRepository = metrologyRepository;
|
||||
}
|
||||
|
||||
// this class represents the API response back to the client
|
||||
public class DataResponse
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public long HeaderID { get; set; }
|
||||
public List<string> Errors { get; set; }
|
||||
public List<string> Warnings { get; set; }
|
||||
}
|
||||
|
||||
// this is the main endpoint, it accepts a JSON message that contains both the header and data records together
|
||||
// tooltype is the ToolTypeName column from the ToolType table
|
||||
// JToken is how you can accept a JSON message without deserialization.
|
||||
// Using "string" doesn't work because ASP.NET Core will expect a json encoded string, not give you the actual string.
|
||||
[HttpPost("/api/inbound/{tooltype}")]
|
||||
[HttpPost]
|
||||
[Route("{tooltype}")]
|
||||
public IActionResult Data(string tooltype, [FromBody] JToken jsonbody)
|
||||
{
|
||||
DataResponse r = new()
|
||||
IPAddress? remoteIP = HttpContext.Connection.RemoteIpAddress;
|
||||
if (!_InboundRepository.IsIPAddressAllowed(_AppSettings.InboundApiAllowedIPList, remoteIP))
|
||||
{
|
||||
Success = false,
|
||||
HeaderID = -1,
|
||||
Errors = new List<string>(),
|
||||
Warnings = new List<string>()
|
||||
};
|
||||
|
||||
if (!IsIPAddressAllowed())
|
||||
{
|
||||
_Logger.LogInformation($"Rejected remote IP: {HttpContext.Connection.RemoteIpAddress}");
|
||||
r.Errors.Add("Remote IP is not on allowed list");
|
||||
return Unauthorized(r);
|
||||
}
|
||||
|
||||
ToolType toolType = _Repo.GetToolTypeByName(tooltype);
|
||||
|
||||
if (toolType == null)
|
||||
{
|
||||
r.Errors.Add("Invalid tool type: " + tooltype);
|
||||
return BadRequest(r);
|
||||
}
|
||||
|
||||
// get metadata
|
||||
|
||||
List<ToolTypeMetadata> metaData = _Repo.GetToolTypeMetadataByToolTypeID(toolType.ID).ToList();
|
||||
|
||||
if (metaData == null)
|
||||
{
|
||||
r.Errors.Add("Invalid metadata for tool type: " + tooltype);
|
||||
return BadRequest(r);
|
||||
}
|
||||
|
||||
// validate fields
|
||||
|
||||
if (jsonbody != null)
|
||||
_InboundDataService.ValidateJSONFields(jsonbody, 0, metaData, r.Errors, r.Warnings);
|
||||
else
|
||||
r.Errors.Add("Invalid json");
|
||||
|
||||
if (r.Errors.Count == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
r.HeaderID = _InboundDataService.DoSQLInsert(jsonbody, toolType, metaData);
|
||||
r.Success = r.HeaderID > 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
r.Errors.Add(ex.Message);
|
||||
}
|
||||
return Ok(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
return BadRequest(r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// this is the endpoint for attaching a field. It is not JSON, it is form-data/multipart like an HTML form because that's the normal way.
|
||||
// header ID is the ID value from the Header table
|
||||
// datauniqueid is the Title value from the Data/Detail table
|
||||
[HttpPost("/api/inbound/{tooltype}/attachment")]
|
||||
public IActionResult AttachFile(string tooltype, [FromQuery] long headerid, [FromQuery] string datauniqueid = "")
|
||||
{
|
||||
if (!IsIPAddressAllowed())
|
||||
{
|
||||
_Logger.LogInformation($"Rejected remote IP: {HttpContext.Connection.RemoteIpAddress}");
|
||||
_Logger.LogInformation($"Rejected remote IP: {remoteIP}");
|
||||
return Unauthorized("Remote IP is not on allowed list");
|
||||
}
|
||||
|
||||
ToolType toolType = _Repo.GetToolTypeByName(tooltype);
|
||||
|
||||
if (toolType == null)
|
||||
return BadRequest($"Invalid tool type: {tooltype}");
|
||||
|
||||
if (Request.Form == null)
|
||||
return BadRequest($"Invalid form");
|
||||
|
||||
if (Request.Form.Files.Count != 1)
|
||||
return BadRequest($"Invalid file count");
|
||||
|
||||
string filename = System.IO.Path.GetFileName(Request.Form.Files[0].FileName);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(filename))
|
||||
return BadRequest("Empty filename");
|
||||
|
||||
if (filename.IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) >= 0)
|
||||
return BadRequest("Invalid filename");
|
||||
|
||||
_AttachmentService.SaveAttachment(toolType, headerid, datauniqueid, filename, Request.Form.Files[0]);
|
||||
|
||||
return Ok();
|
||||
else
|
||||
{
|
||||
DataResponse dataResponse = _InboundRepository.Data(_MetrologyRepository, _InboundDataService, tooltype, jsonbody);
|
||||
if (!dataResponse.Errors.Any())
|
||||
return Ok(dataResponse);
|
||||
else
|
||||
return BadRequest(dataResponse);
|
||||
}
|
||||
}
|
||||
|
||||
protected bool IsIPAddressAllowed()
|
||||
[HttpPost]
|
||||
[Route("{tooltype}/attachment")]
|
||||
public IActionResult AttachFile(string tooltype, [FromQuery] long headerid, [FromQuery] string datauniqueid = "")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_AppSettings.InboundApiAllowedIPList))
|
||||
return true;
|
||||
|
||||
System.Net.IPAddress remoteIP = HttpContext.Connection.RemoteIpAddress;
|
||||
byte[] remoteIPBytes = remoteIP.GetAddressBytes();
|
||||
|
||||
string[] allowedIPs = _AppSettings.InboundApiAllowedIPList.Split(';');
|
||||
foreach (string ip in allowedIPs)
|
||||
IPAddress? remoteIP = HttpContext.Connection.RemoteIpAddress;
|
||||
if (!_InboundRepository.IsIPAddressAllowed(_AppSettings.InboundApiAllowedIPList, remoteIP))
|
||||
{
|
||||
System.Net.IPAddress parsedIP;
|
||||
if (System.Net.IPAddress.TryParse(ip, out parsedIP))
|
||||
{
|
||||
if (parsedIP.GetAddressBytes().SequenceEqual(remoteIPBytes))
|
||||
return true;
|
||||
}
|
||||
_Logger.LogInformation($"Rejected remote IP: {remoteIP}");
|
||||
return Unauthorized("Remote IP is not on allowed list");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Request.Form is null)
|
||||
return BadRequest($"Invalid form");
|
||||
if (Request.Form.Files.Count != 1)
|
||||
return BadRequest($"Invalid file count");
|
||||
IFormFile formFile = Request.Form.Files[0];
|
||||
string? message = _InboundRepository.AttachFile(_MetrologyRepository, _AttachmentsService, tooltype, headerid, datauniqueid, formFile.FileName, formFile);
|
||||
if (message is null)
|
||||
return Ok();
|
||||
else
|
||||
return BadRequest(message);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
46
Viewer/ApiControllers/ServiceShopOrderController.cs
Normal file
46
Viewer/ApiControllers/ServiceShopOrderController.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using OI.Metrology.Shared.Models.Stateless;
|
||||
|
||||
namespace OI.Metrology.Viewer.ApiControllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class ServiceShopOrderController : ControllerBase, IServiceShopOrderController<ActionResult>
|
||||
{
|
||||
|
||||
private readonly IServiceShopOrderRepository _ServiceShopOrderRepository;
|
||||
|
||||
public ServiceShopOrderController(IServiceShopOrderRepository ServiceShopOrderRepository) => _ServiceShopOrderRepository = ServiceShopOrderRepository;
|
||||
|
||||
[HttpGet(nameof(IServiceShopOrderController<ActionResult>.Action.All))]
|
||||
public async Task<ActionResult> GetAllServiceShopOrders()
|
||||
{
|
||||
try
|
||||
{
|
||||
Shared.ViewModels.ServiceShopOrder[] results = await _ServiceShopOrderRepository.GetAllServiceShopOrders();
|
||||
return Ok(results);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return StatusCode(StatusCodes.Status500InternalServerError,
|
||||
"Error retrieving data from the database");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("{id}")]
|
||||
public async Task<ActionResult> GetServiceShopOrders(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
Shared.ViewModels.ServiceShopOrder[] results = await _ServiceShopOrderRepository.GetServiceShopOrders(id);
|
||||
return Ok(results);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return StatusCode(StatusCodes.Status500InternalServerError,
|
||||
"Error retrieving data from the database");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,249 +1,84 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OI.Metrology.Viewer.ApiContollers;
|
||||
namespace OI.Metrology.Viewer.ApiControllers;
|
||||
|
||||
using OI.Metrology.Shared.DataModels;
|
||||
using OI.Metrology.Shared.Repositories;
|
||||
using OI.Metrology.Shared.Models.Stateless;
|
||||
using OI.Metrology.Shared.Services;
|
||||
using OI.Metrology.Viewer.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
|
||||
// using System.Data.Common;
|
||||
|
||||
public class ToolTypesController : Controller
|
||||
[Route("api/[controller]")]
|
||||
public class ToolTypesController : Controller, IToolTypesController<IActionResult>
|
||||
{
|
||||
// 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 readonly IMetrologyRepo _Repo;
|
||||
private readonly AppSettings _AppSettings;
|
||||
private readonly IMetrologyRepository _MetrologyRepo;
|
||||
private readonly IAttachmentsService _AttachmentsService;
|
||||
private readonly IToolTypesRepository _ToolTypesRepository;
|
||||
|
||||
public ToolTypesController(AppSettings appSettings, IMetrologyRepo repo, IAttachmentsService attachmentsService)
|
||||
public ToolTypesController(AppSettings appSettings, IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService, IToolTypesRepository toolTypesRepository)
|
||||
{
|
||||
_Repo = repo;
|
||||
_AppSettings = appSettings;
|
||||
_MetrologyRepo = metrologyRepository;
|
||||
_AttachmentsService = attachmentsService;
|
||||
_ToolTypesRepository = toolTypesRepository;
|
||||
}
|
||||
|
||||
// Get a list of tooltypes, returns just Name and ID
|
||||
[HttpGet("/api/tooltypes")]
|
||||
public IActionResult Index()
|
||||
[HttpGet]
|
||||
public IActionResult Index() =>
|
||||
Json(_ToolTypesRepository.Index(_MetrologyRepo), new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
|
||||
|
||||
[HttpGet]
|
||||
[Route("{id}")]
|
||||
public IActionResult GetToolTypeMetadata(int id, string sortby = "") =>
|
||||
Json(_ToolTypesRepository.GetToolTypeMetadata(_MetrologyRepo, id, sortby), new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
|
||||
|
||||
[HttpGet]
|
||||
[Route("{id}/headers")]
|
||||
public IActionResult GetHeaders(int id, [FromQuery] DateTime? datebegin, [FromQuery] DateTime? dateend, [FromQuery] int? page, [FromQuery] int? pagesize, [FromQuery] long? headerid) =>
|
||||
Content(_ToolTypesRepository.GetHeaders(_MetrologyRepo, id, datebegin, dateend, page, pagesize, headerid));
|
||||
|
||||
[HttpGet]
|
||||
[Route("{id}/headertitles")]
|
||||
public IActionResult GetHeaderTitles(int id, [FromQuery] int? page, [FromQuery] int? pagesize) =>
|
||||
Content(_ToolTypesRepository.GetHeaderTitles(_MetrologyRepo, id, page, pagesize));
|
||||
|
||||
[HttpGet]
|
||||
[Route("{id}/headers/{headerid}/fields")]
|
||||
public IActionResult GetHeaderFields(int id, long headerid) =>
|
||||
Content(_ToolTypesRepository.GetHeaderFields(_MetrologyRepo, id, headerid));
|
||||
|
||||
[HttpGet]
|
||||
[Route("{id}/headers/{headerid}/data")]
|
||||
public IActionResult GetData(int id, long headerid) =>
|
||||
Content(_ToolTypesRepository.GetData(_MetrologyRepo, id, headerid));
|
||||
|
||||
[HttpGet]
|
||||
[Route("{toolTypeId}/{tabletype}/files/{attachmentId}/{filename}")]
|
||||
public IActionResult GetAttachment(int toolTypeId, string tabletype, string attachmentId, string filename)
|
||||
{
|
||||
var r = new
|
||||
{
|
||||
Results = _Repo.GetToolTypes().Select(tt => new { tt.ToolTypeName, tt.ID })
|
||||
};
|
||||
return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
|
||||
(string? message, string? contenttype, Stream? stream) = _ToolTypesRepository.GetAttachment(_MetrologyRepo, _AttachmentsService, toolTypeId, tabletype, attachmentId, filename);
|
||||
if (message is not null)
|
||||
return Content(message);
|
||||
else if (contenttype is not null && stream is not null)
|
||||
return File(stream, contenttype);
|
||||
else
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
// 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<ToolTypeMetadata> 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 });
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
long totalRecs;
|
||||
|
||||
System.Data.DataTable dt = _Repo.GetHeaders(id, datebegin, dateend, page, pagesize, headerid, out totalRecs);
|
||||
|
||||
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)
|
||||
{
|
||||
long totalRecs;
|
||||
|
||||
IEnumerable<HeaderCommon> dt = _Repo.GetHeaderTitles(id, page, pagesize, out totalRecs);
|
||||
|
||||
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)
|
||||
{
|
||||
var r = new
|
||||
{
|
||||
Results = _Repo.GetHeaderFields(id, headerid).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/{headerid}/data")]
|
||||
public IActionResult GetData(
|
||||
int id,
|
||||
long headerid)
|
||||
{
|
||||
var r = new
|
||||
{
|
||||
Results = _Repo.GetData(id, headerid)
|
||||
};
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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")]
|
||||
[HttpPost]
|
||||
[Route("{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
|
||||
|
||||
// Write the file
|
||||
System.IO.File.WriteAllText(
|
||||
Path.Join(_AppSettings.OIExportPath, filename),
|
||||
sb.ToString());
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string json = JsonConvert.SerializeObject(new
|
||||
{
|
||||
ex.Message,
|
||||
});
|
||||
return BadRequest(json);
|
||||
}
|
||||
|
||||
var r = new
|
||||
{
|
||||
Message = "OK",
|
||||
};
|
||||
return Ok(r);
|
||||
Exception? exception = _ToolTypesRepository.OIExport(_MetrologyRepo, _AppSettings.OIExportPath, toolTypeId, headerid);
|
||||
if (exception is null)
|
||||
return Ok(new { Message = "OK" });
|
||||
else
|
||||
return BadRequest(JsonConvert.SerializeObject(new { exception.Message }));
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user