8 Commits

Author SHA1 Message Date
b7447b207f Test Dev Pipeline 2023-02-16 15:12:33 -07:00
1e1d4803b2 Ready to demo 2023-02-16 14:28:03 -07:00
1e7f70c6c4 launchSettings 2023-02-16 10:11:41 -07:00
2e416ce8ab Test on ec server 2023-02-16 10:01:48 -07:00
45ea70212e rowData isn't HeaderCommon 2023-02-10 10:25:38 -07:00
2481c2b3ff Removed HttpContext.Session 2023-02-09 22:58:49 -07:00
4514678556 Test Pinned via API || 2023-02-08 13:11:11 -07:00
8e471e278e Test Pinned via API 2023-02-08 10:53:51 -07:00
89 changed files with 1625 additions and 979 deletions

2
.gitignore vendored
View File

@ -52,7 +52,7 @@ BenchmarkDotNet.Artifacts/
project.lock.json project.lock.json
project.fragment.lock.json project.fragment.lock.json
artifacts/ artifacts/
**/Properties/launchSettings.json # **/Properties/launchSettings.json
# StyleCop # StyleCop
StyleCopReport.xml StyleCopReport.xml

46
.vscode/launch.json vendored
View File

@ -5,10 +5,10 @@
// Use IntelliSense to find out which attributes exist for C# debugging // Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes // Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (web)", "name": ".NET Core Launch (web) - Server",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "buildServer",
// If you have changed target frameworks, make sure to update the program path. // If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/Server/bin/Debug/net7.0/win-x64/OI.Metrology.Server.dll", "program": "${workspaceFolder}/Server/bin/Debug/net7.0/win-x64/OI.Metrology.Server.dll",
"args": [], "args": [],
@ -28,11 +28,49 @@
} }
}, },
{ {
"name": ".NET Core Attach", "name": ".NET Core Attach - Server",
"type": "coreclr", "type": "coreclr",
"request": "attach", "request": "attach",
"preLaunchTask": "watch", "preLaunchTask": "watchServer",
"processName": "OI.Metrology.Server.exe" "processName": "OI.Metrology.Server.exe"
},
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (web) - ClientHub",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "buildClientHub",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/ClientHub/bin/Debug/net7.0/win-x64/OI.Metrology.ClientHub.dll",
"args": [],
"cwd": "${workspaceFolder}/ClientHub",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
"uriFormat": "%s/swagger/index.html"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/ClientHub/Views"
}
},
{
"name": ".NET Core Attach - ClientHub",
"type": "coreclr",
"request": "attach",
"preLaunchTask": "watchClientHub",
"processName": "OI.Metrology.ClientHub.exe"
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
} }
] ]
} }

66
.vscode/tasks.json vendored
View File

@ -2,7 +2,7 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "build", "label": "buildServer",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
@ -14,7 +14,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "publish", "label": "publishServer",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
@ -38,13 +38,13 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "watch", "label": "watchServer",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
"watch", "watch",
"--launch-profile", "--launch-profile",
"https", "http",
"run", "run",
"--project", "--project",
"${workspaceFolder}/Server/OI.Metrology.Server.csproj", "${workspaceFolder}/Server/OI.Metrology.Server.csproj",
@ -70,6 +70,64 @@
"endsPattern": "^.*Application started.*" "endsPattern": "^.*Application started.*"
} }
} }
},
{
"label": "buildClientHub",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/ClientHub/OI.Metrology.ClientHub.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publishClientHub",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/ClientHub/OI.Metrology.ClientHub.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watchClientHub",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"--launch-profile",
"http",
"run",
"--project",
"${workspaceFolder}/ClientHub/OI.Metrology.ClientHub.csproj",
"--verbose"
],
"isBackground": true,
"dependsOn": [
"build"
],
"problemMatcher": {
"fileLocation": "relative",
"pattern": {
"regexp": "^([^\\s].*)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$",
"file": 1,
"location": 2,
"severity": 3,
"code": 4,
"message": 5
},
"background": {
"activeOnStart": true,
"beginsPattern": "^.*Shutdown requested.*",
"endsPattern": "^.*Application started.*"
}
}
} }
] ]
} }

View File

@ -14,7 +14,7 @@
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="Microsoft.NET.Runtime.WebAssembly.Sdk" Version="7.0.2" /> <PackageReference Include="Microsoft.NET.Runtime.WebAssembly.Sdk" Version="7.0.2" />
<PackageReference Include="MudBlazor" Version="6.1.7" /> <PackageReference Include="MudBlazor" Version="6.1.8" />
<PackageReference Include="Serilog.AspNetCore.Ingestion" Version="1.0.0-dev-00032" /> <PackageReference Include="Serilog.AspNetCore.Ingestion" Version="1.0.0-dev-00032" />
<PackageReference Include="Serilog.Sinks.BrowserConsole" Version="1.0.0" /> <PackageReference Include="Serilog.Sinks.BrowserConsole" Version="1.0.0" />
<PackageReference Include="Serilog.Sinks.BrowserHttp" Version="1.0.0-dev-00032" /> <PackageReference Include="Serilog.Sinks.BrowserHttp" Version="1.0.0-dev-00032" />

View File

@ -0,0 +1,25 @@
{
"profiles": {
"profileA": {},
"Phares-Development": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:7023;http://localhost:5027",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Phares-Production": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:7023;http://localhost:5027",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production"
}
}
}
}

View File

@ -1,4 +0,0 @@
namespace OI.Metrology.ClientHub;
public partial class App
{ }

View File

@ -1,12 +0,0 @@
namespace OI.Metrology.ClientHub.Data;
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}

View File

@ -1,19 +0,0 @@
namespace OI.Metrology.ClientHub.Data;
public class WeatherForecastService
{
private static readonly string[] _Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public Task<WeatherForecast[]> GetForecastAsync(DateOnly startDate)
{
return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = _Summaries[Random.Shared.Next(_Summaries.Length)]
}).ToArray());
}
}

View File

@ -6,12 +6,14 @@
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MudBlazor" Version="6.1.7" /> <PackageReference Include="MudBlazor" Version="6.1.8" />
<PackageReference Include="IgniteUI.Blazor" Version="22.2.24" />
<PackageReference Include="Serilog.Sinks.BrowserConsole" Version="1.0.0" /> <PackageReference Include="Serilog.Sinks.BrowserConsole" Version="1.0.0" />
<PackageReference Include="Serilog.Sinks.BrowserHttp" Version="1.0.0-dev-00032" /> <PackageReference Include="Serilog.Sinks.BrowserHttp" Version="1.0.0-dev-00032" />
<PackageReference Include="System.Net.Http.Json" Version="7.0.0" /> <PackageReference Include="System.Net.Http.Json" Version="7.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\OI.Metrology.Shared.csproj" /> <ProjectReference Include="..\Shared\OI.Metrology.Shared.csproj" />
<ProjectReference Include="..\View\OI.Metrology.View.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,71 +0,0 @@
@page "/"
@page "/AwaitingDisposition"
@using Microsoft.AspNetCore.Components.Web
@using MudBlazor
@namespace OI.Metrology.ClientHub.Pages
<PageTitle>Awaiting Disposition</PageTitle>
<h4>Awaiting Disposition</h4>
<div style="height: 450px;">
<table id="grid"></table>
</div>
<div class="row" style="margin-top: 10px; margin-bottom: 20px;">
<div class="col-xs-1">
<MudButton Variant="Variant.Filled" Color="Color.Info" id="OpenButton">Open</MudButton>
</div>
<div class="col-xs-1">
<MudButton Variant="Variant.Filled" Color="Color.Primary" id="RefreshButton" OnClick=RefreshClick>Refresh</MudButton>
</div>
<div class="col-xs-1">
<MudButton Variant="Variant.Filled" Color="Color.Default" OnClick=LoadClickAsync>View</MudButton>
</div>
</div>
@if (_Records == null)
{
<MudProgressCircular Color="Color.Default" Indeterminate="true" />
}
else if (_Records.Any())
{
<MudTable Items="_Records" FixedHeader="true" SortLabel="Sort By" Elevation="0" Dense="true" Hover="true" Bordered="true" Striped="true" Height="400px" Filter="new Func<Metrology.Shared.DataModels.AwaitingDisposition, bool>(FilterRecords)">
<ToolBarContent>
<MudTextField @bind-Value="@_ToolTypeFilter" Placeholder="Tool Type" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
<MudTextField @bind-Value="@_ToolFilter" Placeholder="Tool" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
<MudTextField @bind-Value="@_ReactorFilter" Placeholder="Reactor" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
<MudTextField @bind-Value="@_RdsFilter" Placeholder="RDS" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
<MudTextField @bind-Value="@_PSNFilter" Placeholder="PSN" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
<MudTextField @bind-Value="@_LayerFilter" Placeholder="Layer" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
<MudTextField @bind-Value="@_ZoneFilter" Placeholder="Zone" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
</ToolBarContent>
<HeaderContent>
<MudTh><MudTableSortLabel SortBy="new Func<OI.Metrology.Shared.DataModels.AwaitingDisposition, string?>(x=>x.ToolType)">ToolType</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<OI.Metrology.Shared.DataModels.AwaitingDisposition, string?>(x=>x.Tool)">Tool</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<OI.Metrology.Shared.DataModels.AwaitingDisposition, string?>(x=>x.Reactor)">Reactor</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<OI.Metrology.Shared.DataModels.AwaitingDisposition, string?>(x=>x.RDS)">RDS</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<OI.Metrology.Shared.DataModels.AwaitingDisposition, string?>(x=>x.PSN)">PSN</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<OI.Metrology.Shared.DataModels.AwaitingDisposition, string?>(x=>x.Layer)">Layer</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<OI.Metrology.Shared.DataModels.AwaitingDisposition, string?>(x=>x.Zone)">Zone</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<OI.Metrology.Shared.DataModels.AwaitingDisposition, object>(x=>x.InsertDate)">InsertDate</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<OI.Metrology.Shared.DataModels.AwaitingDisposition, object>(x=>x.Expiration)">Expiration</MudTableSortLabel></MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="ToolType">@context.ToolType</MudTd>
<MudTd DataLabel="Tool">@context.Tool</MudTd>
<MudTd DataLabel="Reactor">@context.Reactor</MudTd>
<MudTd DataLabel="RDS">@context.RDS</MudTd>
<MudTd DataLabel="PSN">@context.PSN</MudTd>
<MudTd DataLabel="Layer">@context.Layer</MudTd>
<MudTd DataLabel="Zone">@context.Zone</MudTd>
<MudTd DataLabel="InsertDate">@context.InsertDate</MudTd>
<MudTd DataLabel="Expiration">@context.Expiration</MudTd>
</RowTemplate>
</MudTable>
}
<script suppress-error="BL9992">
setInterval(function () { $("#RefreshButton").click(); }, 60000);
</script>

View File

@ -1,82 +0,0 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using OI.Metrology.ClientHub.Models;
using OI.Metrology.Shared.Models.Stateless;
namespace OI.Metrology.ClientHub.Pages;
public partial class AwaitingDisposition
{
[Inject] protected IJSRuntime? JSRuntime { get; set; }
[Inject] protected HttpClient? HttpClient { get; set; }
[Inject] protected AppSettings? AppSettings { get; set; }
[Inject] protected ILogger<AwaitingDisposition>? Logger { get; set; }
private string? _ToolTypeFilter;
private string? _ToolFilter;
private string? _ReactorFilter;
private string? _RdsFilter;
private string? _PSNFilter;
private string? _LayerFilter;
private string? _ZoneFilter;
private readonly List<Metrology.Shared.DataModels.AwaitingDisposition> _Records;
public AwaitingDisposition() => _Records = new();
protected override Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
if (JSRuntime is null)
throw new NullReferenceException(nameof(JSRuntime));
if (AppSettings is null)
throw new NullReferenceException(nameof(AppSettings));
return JSRuntime.InvokeVoidAsync("initAwaitingDisposition", AppSettings.ApiUrl).AsTask();
}
return Task.CompletedTask;
}
private bool FilterRecords(Metrology.Shared.DataModels.AwaitingDisposition? record)
{
bool? result = _ToolTypeFilter is not null ? record?.ToolType?.Contains(_ToolTypeFilter, StringComparison.CurrentCultureIgnoreCase) : null;
if (result is null || result.Value)
result = _ToolFilter is not null ? record?.Tool?.Contains(_ToolFilter, StringComparison.CurrentCultureIgnoreCase) : null;
if (result is null || result.Value)
result = _ReactorFilter is not null ? record?.Reactor?.Contains(_ReactorFilter, StringComparison.CurrentCultureIgnoreCase) : null;
if (result is null || result.Value)
result = _RdsFilter is not null ? record?.RDS?.Contains(_RdsFilter, StringComparison.CurrentCultureIgnoreCase) : null;
if (result is null || result.Value)
result = _PSNFilter is not null ? record?.PSN?.Contains(_PSNFilter, StringComparison.CurrentCultureIgnoreCase) : null;
if (result is null || result.Value)
result = _LayerFilter is not null ? record?.Layer?.Contains(_LayerFilter, StringComparison.CurrentCultureIgnoreCase) : null;
if (result is null || result.Value)
result = _ZoneFilter is not null ? record?.Zone?.Contains(_ZoneFilter, StringComparison.CurrentCultureIgnoreCase) : null;
result ??= true;
return result.Value;
}
private void RefreshClick() => _Records.Clear();
private async Task LoadClickAsync()
{
if (Logger is null)
throw new NullReferenceException(nameof(Logger));
if (HttpClient is null)
throw new NullReferenceException(nameof(HttpClient));
_Records.Clear();
string controllerName = IAwaitingDispoController<object>.GetRouteName();
try
{
Metrology.Shared.DataModels.AwaitingDisposition[]? collection = await HttpClient.GetFromJsonAsync<Metrology.Shared.DataModels.AwaitingDisposition[]>($"api/{controllerName}");
if (collection is not null)
_Records.AddRange(collection);
}
catch (Exception)
{
string json = await HttpClient.GetStringAsync($"api/{controllerName}");
Logger.LogInformation(message: json);
}
}
}

View File

@ -1 +0,0 @@


View File

@ -1,4 +1,4 @@
@page @page
@model OI.Metrology.ClientHub.Pages.ErrorModel @model OI.Metrology.ClientHub.Pages.ErrorModel
<!DOCTYPE html> <!DOCTYPE html>

View File

@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Diagnostics; using System.Diagnostics;

View File

@ -1 +0,0 @@


View File

@ -1,41 +0,0 @@
@page "/fetchdata"
@using OI.Metrology.ClientHub.Data
@using Microsoft.AspNetCore.Components.Web
@namespace OI.Metrology.ClientHub.Pages
<PageTitle>Weather forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from a service.</p>
@if (_WeatherForecasts is null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (WeatherForecast weatherForecast in _WeatherForecasts)
{
<tr>
<td>@weatherForecast.Date.ToShortDateString()</td>
<td>@weatherForecast.TemperatureC</td>
<td>@weatherForecast.TemperatureF</td>
<td>@weatherForecast.Summary</td>
</tr>
}
</tbody>
</table>
}

View File

@ -1,17 +0,0 @@
using Microsoft.AspNetCore.Components;
using OI.Metrology.ClientHub.Data;
namespace OI.Metrology.ClientHub.Pages;
public partial class FetchData
{
private WeatherForecast[]? _WeatherForecasts;
[Inject] protected WeatherForecastService? ForecastService { get; set; }
protected override async Task OnInitializedAsync()
{
if (ForecastService is null)
throw new NullReferenceException(nameof(ForecastService));
_WeatherForecasts = await ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
}
}

View File

@ -1,7 +0,0 @@
@page "/fetchServiceShoporders"
@using Microsoft.AspNetCore.Components.Web
@namespace OI.Metrology.ClientHub.Pages
<PageTitle>Service-Shop Orders</PageTitle>

View File

@ -1,4 +0,0 @@
namespace OI.Metrology.ClientHub.Pages;
public partial class FetchServiceShopOrders
{ }

View File

@ -1,7 +0,0 @@
@page "/Index"
@using Microsoft.AspNetCore.Components.Web
@namespace OI.Metrology.ClientHub.Pages
<PageTitle>Index</PageTitle>

View File

@ -1,4 +0,0 @@
namespace OI.Metrology.ClientHub.Pages;
public partial class Index
{ }

View File

@ -1,25 +0,0 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace OI.Metrology.ClientHub.Pages;
public partial class RunHeaders
{
[Inject] protected IJSRuntime? JSRuntime { get; set; }
[Inject] protected Models.AppSettings? AppSettings { get; set; }
protected override Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
if (JSRuntime is null)
throw new NullReferenceException(nameof(JSRuntime));
if (AppSettings is null)
throw new NullReferenceException(nameof(AppSettings));
return JSRuntime.InvokeVoidAsync("initRunHeaders", AppSettings.ApiUrl).AsTask();
}
return Task.CompletedTask;
}
}

View File

@ -1 +0,0 @@


View File

@ -1 +0,0 @@


View File

@ -25,6 +25,7 @@
<link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" /> <link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" />
<link rel="apple-touch-icon" sizes="192x192" href="icon-192.png" /> <link rel="apple-touch-icon" sizes="192x192" href="icon-192.png" />
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" /> <link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
<link href="_content/IgniteUI.Blazor/themes/light/bootstrap.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" /> <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
@ -47,7 +48,7 @@
</head> </head>
<body> <body>
<component type="typeof(App)" render-mode="ServerPrerendered" /> <component type="typeof(View.App)" render-mode="ServerPrerendered" />
<div id="blazor-error-ui"> <div id="blazor-error-ui">
<environment include="Staging,Production"> <environment include="Staging,Production">
@ -62,6 +63,7 @@
<script src="_framework/blazor.server.js"></script> <script src="_framework/blazor.server.js"></script>
<script src="_content/MudBlazor/MudBlazor.min.js"></script> <script src="_content/MudBlazor/MudBlazor.min.js"></script>
<script src="_content/IgniteUI.Blazor/app.bundle.js"></script>
<script src="js/bootstrap.min.js" type="text/javascript" asp-append-version="true"></script> <script src="js/bootstrap.min.js" type="text/javascript" asp-append-version="true"></script>
<script src="js/respond.min.js" type="text/javascript" asp-append-version="true"></script> <script src="js/respond.min.js" type="text/javascript" asp-append-version="true"></script>
</body> </body>

View File

@ -1,6 +1,6 @@
using IgniteUI.Blazor.Controls;
using OI.Metrology.View.Models;
using MudBlazor.Services; using MudBlazor.Services;
using OI.Metrology.ClientHub.Data;
using OI.Metrology.ClientHub.Models;
using Serilog; using Serilog;
using Serilog.Core; using Serilog.Core;
@ -21,16 +21,15 @@ internal class Program
Serilog.ILogger log = Log.ForContext<Program>(); Serilog.ILogger log = Log.ForContext<Program>();
try try
{ {
AppSettings appSettings = Models.Binder.AppSettings.Get(builder.Configuration); AppSettings appSettings = View.Models.Binder.AppSettings.Get(builder.Configuration);
// Add services to the container. // Add services to the container.
_ = builder.Services.AddRazorPages(); _ = builder.Services.AddRazorPages();
_ = builder.Services.AddMudServices(); _ = builder.Services.AddMudServices();
_ = builder.Services.AddIgniteUIBlazor(typeof(IgbIconModule));
_ = builder.Services.AddServerSideBlazor(); _ = builder.Services.AddServerSideBlazor();
_ = builder.Services.AddHttpContextAccessor(); _ = builder.Services.AddHttpContextAccessor();
_ = builder.Services.AddSingleton(_ => appSettings); _ = builder.Services.AddSingleton(_ => appSettings);
_ = builder.Services.AddSingleton<WeatherForecastService>();
_ = builder.Services.AddSingleton<WeatherForecastService>();
_ = builder.Services.AddScoped(serviceProvider => new HttpClient { BaseAddress = new Uri(appSettings.ApiUrl) }); _ = builder.Services.AddScoped(serviceProvider => new HttpClient { BaseAddress = new Uri(appSettings.ApiUrl) });
WebApplication app = builder.Build(); WebApplication app = builder.Build();

View File

@ -0,0 +1,22 @@
{
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5093",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7135;http://localhost:5093",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -1,35 +0,0 @@
using Microsoft.AspNetCore.Components;
using MudBlazor;
using System.Diagnostics;
namespace OI.Metrology.ClientHub.Shared;
public partial class MainLayout
{
bool _DrawerOpen = true;
private bool _IsDarkMode;
private string? _RequestId;
private MudThemeProvider? _MudThemeProvider;
[Inject] protected Models.AppSettings? AppSettings { get; set; }
[Inject] protected IHttpContextAccessor? HttpContextAccessor { get; set; }
void DrawerToggle() => _DrawerOpen = !_DrawerOpen;
protected override void OnParametersSet()
{
base.OnParametersSet();
_RequestId = Activity.Current?.Id ?? HttpContextAccessor?.HttpContext?.TraceIdentifier;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && _MudThemeProvider is not null)
{
_IsDarkMode = await _MudThemeProvider.GetSystemPreference();
StateHasChanged();
}
}
}

View File

@ -1,4 +0,0 @@
namespace OI.Metrology.ClientHub.Shared;
public partial class NavMenu
{ }

View File

@ -7,4 +7,3 @@
@using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using OI.Metrology.ClientHub @using OI.Metrology.ClientHub
@using OI.Metrology.ClientHub.Shared

View File

@ -546,3 +546,6 @@ function triggerFileDownload(fileName, url) {
anchorElement.click(); anchorElement.click();
anchorElement.remove(); anchorElement.remove();
} }
function initIndex(){
}

View File

@ -1,7 +1,6 @@
body { body {
padding-top: 50px; padding-top: 50px;
padding-bottom: 20px; padding-bottom: 20px;
background-color: darkgrey;
} }
/* Set padding to keep content from hitting the edges */ /* Set padding to keep content from hitting the edges */
@ -71,6 +70,25 @@ div.modal-content-warning {
background-color: red !important; background-color: red !important;
} }
.prod-database {
background-color: #d7d7d7 !important;
}
/* hover */
.ui-iggrid td.ui-state-hover,
.ui-iggrid .ui-ig-altrecord td.ui-state-hover,
.ui-iggrid .ui-ig-altrecord td.ui-state-default.ui-state-hover,
.ui-iggrid th.ui-iggrid-rowselector-class.ui-state-hover,
.ui-iggrid .ui-ig-altrecord th.ui-iggrid-rowselector-class.ui-state-hover,
.ui-iggrid .ui-ig-altrecord th.ui-iggrid-rowselector-class.ui-state-default.ui-state-hover,
.ui-iggrid-responsive-vertical tr > td.ui-state-hover:first-child,
.ui-iggrid-responsive-vertical tr.ui-ig-altrecord > td.ui-state-hover:first-child {
color: #333333;
background: #f5ff3b;
border-top: 1px solid transparent;
border-bottom: 1px solid #ddd;
}
.test-database .navbar-brand, .test-database .navbar-brand,
.test-database .navbar-text, .test-database .navbar-text,
.test-database .navbar-nav > li > a { .test-database .navbar-nav > li > a {

0
Server/.vscode/settings.json vendored Normal file
View File

View File

@ -44,7 +44,7 @@
"args": [ "args": [
"watch", "watch",
"--launch-profile", "--launch-profile",
"https", "http",
"run", "run",
"--project", "--project",
"${workspaceFolder}/OI.Metrology.Server.csproj", "${workspaceFolder}/OI.Metrology.Server.csproj",

View File

@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Mvc;
namespace OI.Metrology.Server.ApiControllers;
using OI.Metrology.Shared.Models.Stateless;
using System.Text.Json;
[Route("api/[controller]")]
public class PinController : Controller, IPinController<IActionResult>
{
private readonly IPinRepository _PinRepository;
private readonly IMetrologyRepository _MetrologyRepository;
public PinController(ILogger<InboundController> logger, IMetrologyRepository metrologyRepository, IPinRepository pinRepository)
{
_MetrologyRepository = metrologyRepository;
_PinRepository = pinRepository;
}
[HttpPost("{toolTypeId}/markAsPinned")]
public IActionResult MarkAsPinned(Shared.DataModels.HeaderCommon headerCommon)
{
_PinRepository.SetPinnedTable(headerCommon);
return Ok();
}
[HttpGet]
[Route("{toolTypeId}/pinned")]
public IActionResult GetPinnedTable(int toolTypeId, string? biorad_id = null, string? cde_id = null, string? rds = null) =>
Json(_PinRepository.GetPinnedTable(_MetrologyRepository, toolTypeId, biorad_id, cde_id, rds), new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
}

View File

@ -11,6 +11,8 @@ namespace OI.Metrology.Server.Controllers;
public class ExportController : Controller public class ExportController : Controller
{ {
private readonly string _ApiUrl;
private readonly ILogger _Logger; private readonly ILogger _Logger;
private readonly bool _IsTestDatabase; private readonly bool _IsTestDatabase;
private readonly AppSettings _AppSettings; private readonly AppSettings _AppSettings;
@ -22,6 +24,7 @@ public class ExportController : Controller
_AppSettings = appSettings; _AppSettings = appSettings;
_MetrologyRepository = metrologyRepository; _MetrologyRepository = metrologyRepository;
_IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase); _IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase);
_ApiUrl = string.IsNullOrEmpty(appSettings.ApiUrl) ? Url.Content("~/") : appSettings.ApiUrl[0] == '~' ? Url.Content(appSettings.ApiUrl) : appSettings.ApiUrl;
} }
public override void OnActionExecuted(ActionExecutedContext context) public override void OnActionExecuted(ActionExecutedContext context)
@ -41,6 +44,7 @@ public class ExportController : Controller
}; };
MonIn monIn = MonIn.GetInstance(); MonIn monIn = MonIn.GetInstance();
_ = monIn.SendStatus(_AppSettings.MonASite, _AppSettings.MonAResource, "Heartbeat", State.Up); _ = monIn.SendStatus(_AppSettings.MonASite, _AppSettings.MonAResource, "Heartbeat", State.Up);
ViewBag.ApiUrl = _ApiUrl;
return View(model); return View(model);
} }
@ -81,6 +85,7 @@ public class ExportController : Controller
_ = monIn.SendStatus(_AppSettings.MonASite, _AppSettings.MonAResource, "Heartbeat", State.Warning); _ = monIn.SendStatus(_AppSettings.MonASite, _AppSettings.MonAResource, "Heartbeat", State.Warning);
} }
} }
ViewBag.ApiUrl = _ApiUrl;
return View("Index", model); return View("Index", model);
} }

View File

@ -8,6 +8,8 @@ namespace OI.Metrology.Server.Controllers;
public class PagesController : Controller public class PagesController : Controller
{ {
private readonly string _ApiUrl;
private readonly bool _IsTestDatabase; private readonly bool _IsTestDatabase;
private readonly IMetrologyRepository _MetrologyRepository; private readonly IMetrologyRepository _MetrologyRepository;
@ -15,6 +17,7 @@ public class PagesController : Controller
{ {
_MetrologyRepository = metrologyRepository; _MetrologyRepository = metrologyRepository;
_IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase); _IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase);
_ApiUrl = string.IsNullOrEmpty(appSettings.ApiUrl) ? Url.Content("~/") : appSettings.ApiUrl[0] == '~' ? Url.Content(appSettings.ApiUrl) : appSettings.ApiUrl;
} }
public override void OnActionExecuted(ActionExecutedContext context) public override void OnActionExecuted(ActionExecutedContext context)
@ -25,14 +28,20 @@ public class PagesController : Controller
[HttpGet] [HttpGet]
[Route("/")] [Route("/")]
public IActionResult Index() => public IActionResult Index()
View("AwaitingDispo"); {
ViewBag.ApiUrl = _ApiUrl;
return View("AwaitingDispo");
}
[HttpGet] [HttpGet]
[Route("/AwaitingDispo")] [Route("/AwaitingDispo")]
[Route("/Metrology/AwaitingDispo")] [Route("/Metrology/AwaitingDispo")]
public IActionResult AwaitingDispo() => public IActionResult AwaitingDispo()
View(); {
ViewBag.ApiUrl = _ApiUrl;
return View();
}
[HttpGet] [HttpGet]
[Route("/RunInfo")] [Route("/RunInfo")]
@ -49,14 +58,18 @@ public class PagesController : Controller
{ {
m.HeaderAttachmentID = _MetrologyRepository.GetHeaderAttachmentID(tooltypeid, headerid); m.HeaderAttachmentID = _MetrologyRepository.GetHeaderAttachmentID(tooltypeid, headerid);
} }
ViewBag.ApiUrl = _ApiUrl;
return View(m); return View(m);
} }
[HttpGet] [HttpGet]
[Route("/RunHeaders")] [Route("/RunHeaders")]
[Route("/Metrology/RunHeaders")] [Route("/Metrology/RunHeaders")]
public IActionResult RunHeaders() => public IActionResult RunHeaders()
View(); {
ViewBag.ApiUrl = _ApiUrl;
return View();
}
[HttpGet] [HttpGet]
[Route("/Crash")] [Route("/Crash")]

View File

@ -0,0 +1,6 @@
{
{
"Results": [],
"TotalRows": 0
}
}

View File

@ -5,6 +5,7 @@ namespace OI.Metrology.Server.Models;
public record AppSettings(string ApiLoggingContentTypes, public record AppSettings(string ApiLoggingContentTypes,
string ApiLoggingPathPrefixes, string ApiLoggingPathPrefixes,
string ApiLogPath, string ApiLogPath,
string ApiUrl,
string AttachmentPath, string AttachmentPath,
string BuildNumber, string BuildNumber,
string Company, string Company,

View File

@ -11,6 +11,7 @@ public class AppSettings
[Display(Name = "Api Logging Content Types"), Required] public string ApiLoggingContentTypes { get; set; } [Display(Name = "Api Logging Content Types"), Required] public string ApiLoggingContentTypes { get; set; }
[Display(Name = "Api Logging Path Prefixes"), Required] public string ApiLoggingPathPrefixes { get; set; } [Display(Name = "Api Logging Path Prefixes"), Required] public string ApiLoggingPathPrefixes { get; set; }
[Display(Name = "Api Log Path"), Required] public string ApiLogPath { get; set; } [Display(Name = "Api Log Path"), Required] public string ApiLogPath { get; set; }
[Display(Name = "Api URL"), Required] public string ApiUrl { get; set; }
[Display(Name = "Attachment Path"), Required] public string AttachmentPath { get; set; } [Display(Name = "Attachment Path"), Required] public string AttachmentPath { get; set; }
[Display(Name = "Build Number"), Required] public string BuildNumber { get; set; } [Display(Name = "Build Number"), Required] public string BuildNumber { get; set; }
[Display(Name = "Company"), Required] public string Company { get; set; } [Display(Name = "Company"), Required] public string Company { get; set; }
@ -46,6 +47,8 @@ public class AppSettings
throw new NullReferenceException(nameof(ApiLoggingPathPrefixes)); throw new NullReferenceException(nameof(ApiLoggingPathPrefixes));
if (appSettings.ApiLogPath is null) if (appSettings.ApiLogPath is null)
throw new NullReferenceException(nameof(ApiLogPath)); throw new NullReferenceException(nameof(ApiLogPath));
if (appSettings.ApiUrl is null)
throw new NullReferenceException(nameof(ApiUrl));
if (appSettings.AttachmentPath is null) if (appSettings.AttachmentPath is null)
throw new NullReferenceException(nameof(AttachmentPath)); throw new NullReferenceException(nameof(AttachmentPath));
if (appSettings.BuildNumber is null) if (appSettings.BuildNumber is null)
@ -80,6 +83,7 @@ public class AppSettings
appSettings.ApiLoggingContentTypes, appSettings.ApiLoggingContentTypes,
appSettings.ApiLoggingPathPrefixes, appSettings.ApiLoggingPathPrefixes,
appSettings.ApiLogPath, appSettings.ApiLogPath,
appSettings.ApiUrl,
appSettings.AttachmentPath, appSettings.AttachmentPath,
appSettings.BuildNumber, appSettings.BuildNumber,
appSettings.Company, appSettings.Company,

View File

@ -97,6 +97,9 @@
<None Include="Data\Tests\GetIpAddressApi.json"> <None Include="Data\Tests\GetIpAddressApi.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Include="Data\Tests\GetPinnedTableApi.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Data\Tests\GetToolTypeMetadataApi.json"> <None Include="Data\Tests\GetToolTypeMetadataApi.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>

View File

@ -67,11 +67,12 @@ public class Program
_ = webApplicationBuilder.Services.AddSingleton(_ => appSettings); _ = webApplicationBuilder.Services.AddSingleton(_ => appSettings);
_ = webApplicationBuilder.Services.AddSingleton<IInboundRepository, InboundRepository>(); _ = webApplicationBuilder.Services.AddSingleton<IInboundRepository, InboundRepository>();
_ = webApplicationBuilder.Services.AddSingleton<IAppSettingsRepository<Models.Binder.AppSettings>>(_ => appSettingsRepository);
_ = webApplicationBuilder.Services.AddSingleton<IClientSettingsRepository>(_ => clientSettingsRepository); _ = webApplicationBuilder.Services.AddSingleton<IClientSettingsRepository>(_ => clientSettingsRepository);
_ = webApplicationBuilder.Services.AddSingleton<IServiceShopOrderRepository, ServiceShopOrderRepository>(); _ = webApplicationBuilder.Services.AddSingleton<IServiceShopOrderRepository, ServiceShopOrderRepository>();
_ = webApplicationBuilder.Services.AddSingleton<IPinRepository, PinRepository>(_ => new(appSettings.MockRoot));
_ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>(_ => sqlDbConnectionFactory); _ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>(_ => sqlDbConnectionFactory);
_ = webApplicationBuilder.Services.AddSingleton<IToolTypesRepository, ToolTypesRepository>(_ => new(appSettings.MockRoot)); _ = webApplicationBuilder.Services.AddSingleton<IToolTypesRepository, ToolTypesRepository>(_ => new(appSettings.MockRoot));
_ = webApplicationBuilder.Services.AddSingleton<IAppSettingsRepository<Models.Binder.AppSettings>>(_ => appSettingsRepository);
_ = webApplicationBuilder.Services.AddScoped<IAttachmentsService, AttachmentsService>(); _ = webApplicationBuilder.Services.AddScoped<IAttachmentsService, AttachmentsService>();
_ = webApplicationBuilder.Services.AddScoped<IInboundDataService, InboundDataService>(); _ = webApplicationBuilder.Services.AddScoped<IInboundDataService, InboundDataService>();
@ -101,6 +102,7 @@ public class Program
if (!webApplicationBuilder.Environment.IsDevelopment()) if (!webApplicationBuilder.Environment.IsDevelopment())
{ {
_ = webApplication.UseExceptionHandler("/Error"); _ = webApplication.UseExceptionHandler("/Error");
_ = webApplication.UseHttpsRedirection();
_ = webApplication.UseHsts(); _ = webApplication.UseHsts();
} }
else else
@ -119,7 +121,6 @@ public class Program
_ = webApplication.UseFileServer(enableDirectoryBrowsing: true); _ = webApplication.UseFileServer(enableDirectoryBrowsing: true);
_ = webApplication.UseStaticFiles(); _ = webApplication.UseStaticFiles();
_ = webApplication.UseSession(); _ = webApplication.UseSession();
_ = webApplication.UseHttpsRedirection();
_ = webApplication.UseMiddleware<ApiLoggingMiddleware>(); _ = webApplication.UseMiddleware<ApiLoggingMiddleware>();
_ = webApplication.MapControllers(); _ = webApplication.MapControllers();
log.Information("Starting Web Application"); log.Information("Starting Web Application");

View File

@ -0,0 +1,31 @@
{
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5126",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7130;http://localhost:5126",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https-prod": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7130;http://localhost:5126",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production"
}
}
}
}

View File

@ -0,0 +1,120 @@
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models.Stateless;
using System.Text.Json;
namespace OI.Metrology.Server.Repository;
public class PinRepository : IPinRepository
{
private readonly string _MockRoot;
private readonly Serilog.ILogger _Log;
private readonly Dictionary<string, Dictionary<long, HeaderCommon>> _RdsToHeaderCommonCollection;
public PinRepository(string mockRoot)
{
_MockRoot = mockRoot;
_RdsToHeaderCommonCollection = new();
_Log = Serilog.Log.ForContext<PinRepository>();
}
void IPinRepository.SetPinnedTable(HeaderCommon headerCommon)
{
Dictionary<long, HeaderCommon>? toolIdToHeader;
if (!string.IsNullOrEmpty(headerCommon.RDS))
{
if (!_RdsToHeaderCommonCollection.TryGetValue(headerCommon.RDS, out toolIdToHeader))
{
_RdsToHeaderCommonCollection.Add(headerCommon.RDS, new());
if (!_RdsToHeaderCommonCollection.TryGetValue(headerCommon.RDS, out toolIdToHeader))
throw new Exception();
}
if (toolIdToHeader.ContainsKey(headerCommon.ToolTypeID))
toolIdToHeader[headerCommon.ToolTypeID] = headerCommon;
else
toolIdToHeader.Add(headerCommon.ToolTypeID, headerCommon);
}
}
private (HeaderCommon?, HeaderCommon?) GetBoth(string rds, long bioRadId, long cdeId)
{
Dictionary<long, HeaderCommon>? toolIdToHeader;
if (!_RdsToHeaderCommonCollection.TryGetValue(rds, out toolIdToHeader))
{
_RdsToHeaderCommonCollection.Add(rds, new());
if (!_RdsToHeaderCommonCollection.TryGetValue(rds, out toolIdToHeader))
throw new Exception();
}
_ = toolIdToHeader.TryGetValue(cdeId, out HeaderCommon? cdeHeader);
_ = toolIdToHeader.TryGetValue(bioRadId, out HeaderCommon? bioRadHeader);
return new(bioRadHeader, cdeHeader);
}
private static Pinned? GetPinned(IMetrologyRepository metrologyRepository, HeaderCommon headerCommon, int points, int column)
{
Pinned? result;
List<string> values;
System.Data.DataTable dataTable = metrologyRepository.GetData((int)headerCommon.ToolTypeID, headerCommon.ID);
if (dataTable.Rows.Count <= points || dataTable.Columns.Count <= column)
result = null;
else
{
values = new();
for (int i = 0; i < dataTable.Rows.Count - 1; i++)
{
if (dataTable.Rows[i]?.ItemArray[column] is null)
break;
values.Add(string.Concat(dataTable.Rows[i].ItemArray[column]));
}
if (values.Count <= points)
result = null;
else
result = new(headerCommon, values);
}
return result;
}
Result<Pinned[]> IPinRepository.GetPinnedTable(IMetrologyRepository metrologyRepository, int id, string? biorad_id, string? cde_id, string? rds)
{
Result<Pinned[]>? r;
if (!string.IsNullOrEmpty(_MockRoot))
{
string json = File.ReadAllText(Path.Combine(string.Concat(AppContext.BaseDirectory, _MockRoot), "GetPinnedTableApi.json"));
r = JsonSerializer.Deserialize<Result<Pinned[]>>(json);
if (r is null)
throw new NullReferenceException(nameof(r));
}
else
{
if (string.IsNullOrEmpty(rds) || !long.TryParse(biorad_id, out long bioRadId) || !long.TryParse(cde_id, out long cdeId))
r = new() { Results = Array.Empty<Pinned>(), TotalRows = 0 };
else
{
const int points = 9;
List<Pinned> results = new();
(HeaderCommon? bioRadHeader, HeaderCommon? cdeHeader) = GetBoth(rds, bioRadId, cdeId);
if (bioRadHeader is not null)
{
const int thickness = 5;
Pinned? pinned = GetPinned(metrologyRepository, bioRadHeader, points, column: thickness);
if (pinned is not null)
results.Add(pinned);
}
if (cdeHeader is not null)
{
const int rs = 6;
Pinned? pinned = GetPinned(metrologyRepository, cdeHeader, points, column: rs);
if (pinned is not null)
results.Add(pinned);
}
r = new()
{
Results = results.ToArray(),
TotalRows = results.Count,
};
}
}
return r;
}
}

View File

@ -48,8 +48,10 @@
$(document).ready(function () { $(document).ready(function () {
var apiUrl = "@ViewBag.ApiUrl";
$("#ToolType").igCombo({ $("#ToolType").igCombo({
dataSource: '@Url.Content("~/api/tooltypes")', dataSource: apiUrl + '/tooltypes',
responseDataKey: "Results", responseDataKey: "Results",
textKey: "ToolTypeName", textKey: "ToolTypeName",
valueKey: "ID", valueKey: "ID",

View File

@ -18,59 +18,11 @@
</div> </div>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
$("#grid").igGrid({ initAwaitingDisposition("@ViewBag.ApiUrl");
autoGenerateColumns: false,
width: "70%",
height: "100%",
primaryKey: "PK",
columns: [
{ key: "PK", dataType: "string", hidden: true, },
{ key: "ID", dataType: "number", hidden: true, },
{ key: "ToolTypeID", dataType: "number", hidden: true, },
{ headerText: "Tool Type", key: "ToolType", dataType: "string", width: "15%" },
{ key: "Tool", dataType: "string", width: "10%" },
{ key: "Reactor", dataType: "string", width: "10%" },
{ key: "RDS", dataType: "string", width: "10%" },
{ key: "PSN", dataType: "string", width: "10%" },
{ key: "Layer", dataType: "string", width: "10%" },
{ key: "Zone", dataType: "string", width: "10%" },
{ key: "InsertDate", dataType: "date", width: "10%", format: "dateTime" },
{ key: "Expiration", dataType: "date", width: "10%", format: "dateTime" }
],
dataSource: "@Url.Content("~/api/awaitingdispo/")",
responseDataKey: "Results",
tabIndex: 1,
features: [
{ name: "Selection", mode: "row", multipleSelection: false },
{ name: "Filtering", type: "local" },
{ name: "Sorting", type: "local" },
]
}); });
function LoadRunInfo() {
var row = $("#grid").igGrid("selectedRow");
if (row == null)
return;
var data = $("#grid").igGrid("findRecordByKey", row.id);
if (data == null)
return;
var targetURL = "@Url.Action("RunInfo")?tooltypeid=" + data.ToolTypeID + "&headerid=" + data.ID;
window.location.href = targetURL;
}
$("#RefreshButton").click(function () {
$("#grid").igGrid("dataBind");
});
$("#OpenButton").click(LoadRunInfo);
$("#grid").on("dblclick", "tr", LoadRunInfo);
});
setInterval(function () {
$("#RefreshButton").click();
}, 60000);
</script> </script>

View File

@ -48,87 +48,10 @@
<script> <script>
function LoadHeaderGrid() {
var toolTypeID = $("#ToolType").igCombo("value");
var gridCreated = $("#HeaderGrid").data("igGrid");
if (gridCreated)
$("#HeaderGrid").igGrid("destroy");
ClearFieldsGrid();
var headerURL = "@Url.Content("~/api/tooltypes/")" + toolTypeID + "/headertitles";
$("#HeaderGrid").igGrid({
autoGenerateColumns: false,
primaryKey: "ID",
height: "100%",
width: "100%",
features: [
{ name: "Paging", type: "local", recordCountKey: "TotalRows", pageSize: 25, pageSizeUrlKey: "pageSize", "pageIndexUrlKey": "page", showPageSizeDropDown: false },
{ name: "Selection", mode: "row", rowSelectionChanged: HeaderSelectionChanged },
{ name: "Filtering", type: "local" }
],
columns: [
{ key: "ID", dataType: "number", hidden: true },
{ key: "Title", dataType: "string", width: "80%" },
{ key: "InsertDate", dataType: "date", format: "dateTime", width: "20%" }
],
dataSource: headerURL,
responseDataKey: "Results",
});
}
function ClearFieldsGrid() {
var gridCreated = $("#FieldsGrid").data("igGrid");
if (gridCreated)
$("#FieldsGrid").igGrid("destroy");
}
function HeaderSelectionChanged(evt, ui) {
var toolTypeID = $("#ToolType").igCombo("value");
ClearFieldsGrid();
var url = "@Url.Content("~/api/tooltypes/")" + toolTypeID + "/headers/" + ui.row.id + "/fields";
$("#FieldsGrid").igGrid({
autoGenerateColumns: false,
primaryKey: "Column",
height: "100%",
width: "100%",
features: [
{ name: 'Resizing' }
],
columns: [
{ key: "Column", dataType: "string", width: "20%", columnCssClass: "FieldTitle", },
{ key: "Value", dataType: "string", }
],
enableHoverStyles: false,
dataSource: url,
responseDataKey: "Results",
});
}
$(document).ready(function () { $(document).ready(function () {
$("#ToolType").igCombo({ initRunHeaders("@ViewBag.ApiUrl");
dataSource: '@Url.Content("~/api/tooltypes")',
responseDataKey: "Results",
textKey: "ToolTypeName",
valueKey: "ID",
mode: "dropdown",
width: 150,
dataBound: function (evt, ui) {
$("#ToolType").igCombo("index", 0);
LoadHeaderGrid();
},
selectionChanged: LoadHeaderGrid,
});
}); });
</script> </script>

View File

@ -49,6 +49,9 @@
<div class="col-xs-1"> <div class="col-xs-1">
<input type="button" class="btn" id="ReviewButton" value="Review" disabled /> <input type="button" class="btn" id="ReviewButton" value="Review" disabled />
</div> </div>
<div class="col-xs-1">
<input type="button" class="btn" id="PinButton" value="Pin" disabled />
</div>
</div> </div>
<div id="DetailsDiv" hidden> <div id="DetailsDiv" hidden>
@ -73,409 +76,9 @@
<script> <script>
var toolType = null;
var toolTypeMetaData = null;
function LoadHeaderGrid() {
var toolTypeID = $("#ToolType").igCombo("value");
$("#ToolTypeID").text(toolTypeID);
HideDetailsDiv();
DisableHeaderButtons();
$("#HeaderId").text("");
$("#HeaderAttachmentId").text("");
var gridCreated = $("#HeaderGrid").data("igGrid");
if (gridCreated)
$("#HeaderGrid").igGrid("destroy");
$.ajax({
type: "GET",
url: "@Url.Content("~/api/tooltypes/")" + toolTypeID + "?sortby=grid",
success: function (r) {
if ((r.Results == null) || (r.Results.ToolType == null) || (r.Results.Metadata == null))
ShowErrorMessage("Invalid tool type: " + toolTypeID);
else {
toolType = r.Results.ToolType;
toolTypeMetaData = r.Results.Metadata;
RequestHeaderData();
}
},
error: function (e) {
DisplayWSMessage("error", "There was an error getting tooltype info.", e);
}
});
}
function DisableHeaderButtons() {
$("#GetDataButton").prop("disabled", true);
$("#ReviewButton").prop("disabled", true);
}
function EnableHeaderButtons() {
$("#GetDataButton").prop("disabled", false);
$("#ReviewButton").prop("disabled", false);
}
function HideDetailsDiv() {
$("#DetailsDiv").prop("hidden", true);
$("#DataAttachmentFrame").prop("src", "");
}
function ShowDetailsDiv() {
$("#DetailsDiv").prop("hidden", false);
$("#ExportDiv").prop("hidden", true);
if ((toolType != null) && (toolType.OIExportSPName != null) && (toolType.OIExportSPName.length > 0)) {
$("#ExportDiv").prop("hidden", false);
$("#OIExportButton").prop("disabled", false);
$("#OIExportResult").text('');
}
$("#DataAttachmentFrame").prop("hidden", true);
$("#HeaderAttachmentFrame").prop("hidden", true);
if (toolType != null) {
var visibleFrames = 0;
if (toolType.DisplayDataAttachment && toolType.DisplayDataAttachment.length > 0) {
visibleFrames += 1;
$("#DataAttachmentFrame").prop("hidden", false);
}
if (toolType.DisplayHeaderAttachment && toolType.DisplayHeaderAttachment.length > 0) {
visibleFrames += 1;
$("#HeaderAttachmentFrame").prop("hidden", false);
}
var frameWidth = (98 / visibleFrames) + "%";
$("#DataAttachmentFrame,#HeaderAttachmentFrame").css('width', frameWidth);
}
}
function HeaderSelectionChanged(evt, ui) {
if (ui.row.index >= 0) {
if ($("#HeaderId").text() == ui.row.id) {
EnableHeaderButtons();
return;
}
}
DisableHeaderButtons();
HideDetailsDiv();
if (ui.row.index >= 0) {
EnableHeaderButtons();
$("#HeaderId").text(ui.row.id);
var rowData = ui.owner.grid.dataSource.dataView()[ui.row.index];
$("#HeaderAttachmentId").text(rowData.AttachmentID);
}
}
function CancelHandler(evt, ui) {
return false;
}
function DetailSelectionChanged(evt, ui) {
$("#DataAttachmentFrame").prop("src", "");
if (ui.row.index >= 0) {
var rowData = ui.owner.grid.dataSource.dataView()[ui.row.index];
var toolTypeID = $("#ToolTypeID").text();
var attachmentUrlBase = '@Url.Content("~/api/tooltypes/")' + toolTypeID;
var attachmentId = rowData.AttachmentID;
if ((attachmentId == null) || (attachmentId === ''))
return;
if ((toolType.DisplayDataAttachment == null) || (toolType.DisplayDataAttachment === ''))
return;
$("#DataAttachmentFrame").prop("src", attachmentUrlBase + "/data/files/" + attachmentId + "/" + toolType.DisplayDataAttachment);
}
}
function LoadHeaderAttachment() {
var toolTypeID = $("#ToolTypeID").text();
var attachmentId = $("#HeaderAttachmentId").text();
var attachmentUrlBase = '@Url.Content("~/api/tooltypes/")' + toolTypeID;
if ((attachmentId == null) || (attachmentId === '') || (toolType.DisplayHeaderAttachment == null) || (toolType.DisplayHeaderAttachment === '')) {
$("#HeaderAttachmentFrame").prop("src", "");
} else {
$("#HeaderAttachmentFrame").prop("src", attachmentUrlBase + "/header/files/" + attachmentId + "/" + toolType.DisplayHeaderAttachment);
}
$("#DataAttachmentFrame").prop("src", "");
}
function MarkAsReviewed() {
var toolTypeId = $("#ToolTypeID").text();
var headerId = $("#HeaderId").text();
$.ajax({
type: "POST",
url: "@Url.Content("~/api/awaitingdispo/markasreviewed")?tooltypeid=" + toolTypeId + "&headerid=" + headerId,
success: function () {
},
error: function (e, ajaxOptions, ex) {
DisplayWSMessage("error", "There was an error marking header as reviewed.", e, ex);
$("#ReviewButton").prop("disabled", false);
}
});
}
function LoadDetails() {
ShowDetailsDiv();
LoadHeaderAttachment();
var gridCreated = $("#DetailsGrid").data("igGrid");
if (gridCreated)
$("#DetailsGrid").igGrid("destroy");
var headerId = $("#HeaderId").text();
var toolTypeID = $("#ToolTypeID").text();
var detailsURL = "@Url.Content("~/api/tooltypes/")" + toolTypeID + "/headers/" + headerId + "/data";
var gridColumns = [
{ key: "AttachmentID", dataType: "string", hidden: true },
{ key: "Title", dataType: "string", hidden: true },
];
for (var i = 0; i < toolTypeMetaData.length; i++) {
var f = toolTypeMetaData[i];
if ((f.Header == false) && (f.GridDisplayOrder > 0)) {
var col = {
key: f.ColumnName,
headerText: f.DisplayTitle,
width: "150px",
};
if (f.GridAttributes != null)
jQuery.extend(col, JSON.parse(f.GridAttributes));
if (col.formatter != null) {
if (col.formatter == "boolToYesNo")
col.formatter = boolToYesNo;
else
col.formatter = null;
}
gridColumns.push(col);
}
}
var gridParms = {
autoGenerateColumns: false,
primaryKey: "ID",
features: [
{ name: "Selection", mode: "row", rowSelectionChanging: DetailSelectionChanged },
{ name: "Resizing" },
{ name: "Sorting", type: "local" }
],
columns: gridColumns,
dataSource: detailsURL,
responseDataKey: "Results",
dataBound: MarkAsReviewed,
};
if ((toolType != null) && (toolType.DataGridAttributes != null)) {
jQuery.extend(gridParms, JSON.parse(toolType.DataGridAttributes));
}
$("#DetailsGrid").igGrid(gridParms);
}
var initialHeaderId = @Model.HeaderID;
var initialHeaderAttachmentId = "@Model.HeaderAttachmentID";
function RequestHeaderData() {
var startDate = $("#StartDate").igDatePicker("value");
var startTime = $("#StartTime").igTimePicker("value");
var endDate = $("#EndDate").igDatePicker("value");
var endTime = $("#EndTime").igTimePicker("value");
var parms = {
datebegin: new Date(
startDate.getFullYear(), startDate.getMonth(), startDate.getDate(),
startTime.getHours(), startTime.getMinutes(), startTime.getSeconds()).toISOString(),
dateend: new Date(
endDate.getFullYear(), endDate.getMonth(), endDate.getDate(),
endTime.getHours(), endTime.getMinutes(), endTime.getSeconds()).toISOString(),
}
var headerId = 0;
if (initialHeaderId > 0) {
headerId = initialHeaderId;
parms.headerid = headerId;
$("#HeaderId").text(headerId);
$("#HeaderAttachmentId").text(initialHeaderAttachmentId);
initialHeaderId = -1;
}
var headerURL = "@Url.Content("~/api/tooltypes/")" + toolType.ID + "/headers?" + $.param(parms);
var gridColumns = [
{ key: "ID", dataType: "number", hidden: true },
{ key: "AttachmentID", dataType: "string", hidden: true },
{ key: "Title", dataType: "string", hidden: true },
];
for (var i = 0; i < toolTypeMetaData.length; i++) {
var f = toolTypeMetaData[i];
if ((f.Header == true) && (f.GridDisplayOrder > 0)) {
var col = {
key: f.ColumnName,
headerText: f.DisplayTitle,
width: "150px",
};
if (f.GridAttributes != null)
jQuery.extend(col, JSON.parse(f.GridAttributes));
if (col.formatter != null) {
if (col.formatter == "boolToYesNo")
col.formatter = boolToYesNo;
else
col.formatter = null;
}
gridColumns.push(col);
}
}
var gridParms = {
autoGenerateColumns: false,
primaryKey: "ID",
height: "100%",
width: "100%",
features: [
{ name: "Paging", type: "local", recordCountKey: "TotalRows", pageSize: 100, pageSizeList: [50, 100, 250, 500], pageSizeUrlKey: "pageSize", "pageIndexUrlKey": "page" },
{ name: "Selection", mode: "row", rowSelectionChanged: HeaderSelectionChanged },
{ name: "Filtering", type: "local" },
{ name: 'Resizing' },
{ name: "Sorting", type: "local" }
],
columns: gridColumns,
dataSource: headerURL,
responseDataKey: "Results",
};
if ((toolType != null) && (toolType.HeaderGridAttributes != null)) {
jQuery.extend(gridParms, JSON.parse(toolType.HeaderGridAttributes));
}
$("#HeaderGrid").igGrid(gridParms);
if (headerId > 0) {
LoadDetails();
}
}
function ReviewButton() {
var toolTypeId = $("#ToolTypeID").text();
var headerId = parseInt($("#HeaderId").text());
$("#ReviewButton").prop("disabled", true);
$.ajax({
type: "POST",
url: "@Url.Content("~/api/awaitingdispo/markasawaiting")?tooltypeid=" + toolTypeId + "&headerid=" + headerId,
success: function (e) {
DisplayWSMessage("info", "Marked as awaiting disposition", e);
$("#ReviewButton").prop("disabled", false);
},
error: function (e, ajaxOptions, ex) {
DisplayWSMessage("error", "There was an error marking header as awaiting disposition.", e, ex);
$("#ReviewButton").prop("disabled", false);
}
});
}
function OIExportButton() {
var headerId = $("#HeaderId").text();
var toolTypeID = $("#ToolTypeID").text();
$("#OIExportButton").prop("disabled", true);
$.ajax({
type: "POST",
url: "@Url.Content("~/api/tooltypes/")" + toolTypeID + "/headers/" + headerId + "/oiexport",
success: function (r) {
$("#OIExportResult").text("Exported!");
},
error: function (e, ajaxOptions, ex) {
DisplayWSMessage("error", "There was an error exporting.", e, ex);
$("#OIExportButton").prop("disabled", false);
}
});
}
function SetInitialDateTimes() {
var startTime = new Date(Date.now() - 6 * 60 * 60 * 1000);//6 hours back from now
$("#StartDate").igDatePicker({
dateInputFormat: "date",
value: startTime,
width: 125
});
$("#StartTime").igTimePicker({
dateInputFormat: "time",
value: startTime,
width: 110
});
var endTime = new Date(Date.now());
$("#EndDate").igDatePicker({
dateInputFormat: "date",
value: endTime,
width: 125
});
$("#EndTime").igTimePicker({
dateInputFormat: "time",
value: endTime,
width: 110
});
}
$(document).ready(function () { $(document).ready(function () {
$("#ToolType").igCombo({ initRunInfo("@ViewBag.ApiUrl", "@Model.ToolTypeID", "@Model.HeaderID", "@Model.HeaderAttachmentID");
dataSource: '@Url.Content("~/api/tooltypes")',
responseDataKey: "Results",
textKey: "ToolTypeName",
valueKey: "ID",
mode: "dropdown",
width: 150,
itemsRendered: function (evt, ui) {
LoadHeaderGrid();
},
selectionChanged: LoadHeaderGrid,
initialSelectedItems: [{ value: @Model.ToolTypeID }]
});
SetInitialDateTimes();
$("#HeaderGrid").on("dblclick", "tr", LoadDetails);
$("#LoadHeadersButton").click(LoadHeaderGrid);
$("#GetDataButton").click(LoadDetails);
$("#ReviewButton").click(ReviewButton);
$("#OIExportButton").click(OIExportButton);
setInterval(function () {
if ($("#chkAutoRefresh").is(':checked')) {
SetInitialDateTimes();
$("#LoadHeadersButton").click();
}
}, 180000);
}); });

View File

@ -21,6 +21,7 @@
<script src="~/igniteui/js/infragistics.dv.js" type="text/javascript" asp-append-version="true"></script> <script src="~/igniteui/js/infragistics.dv.js" type="text/javascript" asp-append-version="true"></script>
<script src="~/js/common.js" type="text/javascript" asp-append-version="true"></script> <script src="~/js/common.js" type="text/javascript" asp-append-version="true"></script>
<script src="~/js/site.js" type="text/javascript" asp-append-version="true"></script>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
if (location.pathname == "/") { if (location.pathname == "/") {

View File

@ -1,7 +1,13 @@
{ {
"xApiUrl": "http://messa010ec.ec.local:50301/api",
"ApiUrl": "http://localhost:5126/api",
"xxxApiUrl": "http://localhost:50301/api",
"xxxxApiUrl": "http://messa010ec.ec.local:50301/api",
"ConnectionString": "Data Source=MESSAD1001\\TEST1,59583;Integrated Security=True;Initial Catalog=Metrology;", "ConnectionString": "Data Source=MESSAD1001\\TEST1,59583;Integrated Security=True;Initial Catalog=Metrology;",
"xConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Integrated Security=True;Initial Catalog=Metrology;",
"IsDevelopment": true, "IsDevelopment": true,
"MockRoot": "/Data/Tests", "xMockRoot": "/Data/Tests",
"MockRoot": "",
"MonAResource": "OI_Metrology_Viewer_IFX", "MonAResource": "OI_Metrology_Viewer_IFX",
"Oi2SqlConnectionString": "Data Source=MESSAD1001\\TEST1,59583;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;", "Oi2SqlConnectionString": "Data Source=MESSAD1001\\TEST1,59583;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
"Serilog": { "Serilog": {

View File

@ -2,6 +2,7 @@
"AllowedHosts": "*", "AllowedHosts": "*",
"ApiLoggingContentTypes": "application/json", "ApiLoggingContentTypes": "application/json",
"ApiLoggingPathPrefixes": "/api/inbound", "ApiLoggingPathPrefixes": "/api/inbound",
"ApiUrl": "~/api",
"ApiLogPath": "D:\\Metrology\\MetrologyAPILogs", "ApiLogPath": "D:\\Metrology\\MetrologyAPILogs",
"AttachmentPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si\\MetrologyAttachments", "AttachmentPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si\\MetrologyAttachments",
"BuildNumber": "1", "BuildNumber": "1",

View File

@ -121,11 +121,21 @@ function ConstructMessageDialog() {
' </div> ' + ' </div> ' +
' <div class="modal-body"> ' + ' <div class="modal-body"> ' +
' <span id="spanMessageText"></span> ' + ' <span id="spanMessageText"></span> ' +
' <table id="ModalHeaderGrid"></table> ' +
' <table id="ModalBodyGrid"></table> ' +
' <textarea type="text" value="Hello World" id="textareaClipboard" style="display:none"></textarea> ' +
' </div> ' + ' </div> ' +
' <div class="modal-footer"> ' + ' <div class="modal-footer"> ' +
' <div class="row" style="margin-top: 10px; margin-bottom: 20px;"> ' +
' <div class="col-xs-1"> ' +
' <button type="button" data-dismiss="modal" onclick="copy()">Copy</button> ' +
' </div> ' +
' <div class="col-xs-1"> ' +
' <button type="button" data-dismiss="modal">OK</button> ' + ' <button type="button" data-dismiss="modal">OK</button> ' +
' </div> ' + ' </div> ' +
' </div> ' + ' </div> ' +
' </div> ' +
' </div> ' +
'</div>'; '</div>';
if ($("#MessageModal").length) { if ($("#MessageModal").length) {

637
Server/wwwroot/js/site.js Normal file
View File

@ -0,0 +1,637 @@
var _CdeId = null;
var _apiUrl = null;
var _BioRadId = null;
var _toolType = null;
var _initialHeaderId = null;
var _toolTypeMetaData = null;
var _initialHeaderAttachmentId = null;
$(document).ready(function () {
if (location.pathname == "/") {
route = "/AwaitingDispo";
}
else {
route = location.pathname;
}
$('ul.nav.navbar-nav').find('a[href="' + route + '"]')
.closest('li').addClass('alert-info');
});
function loadRunInfoAwaitingDisposition() {
var row = $("#grid").igGrid("selectedRow");
if (row == null)
return;
var data = $("#grid").igGrid("findRecordByKey", row.id);
if (data == null)
return;
var targetURL = "RunInfo?tooltypeid=" + data.ToolTypeID + "&headerid=" + data.ID;
window.location.href = targetURL;
}
function initAwaitingDisposition(apiUrl) {
_apiUrl = apiUrl;
$("#grid").igGrid({
autoGenerateColumns: false,
width: "70%",
height: "100%",
primaryKey: "PK",
columns: [
{ key: "PK", dataType: "string", hidden: true, },
{ key: "ID", dataType: "number", hidden: true, },
{ key: "ToolTypeID", dataType: "number", hidden: true, },
{ headerText: "Tool Type", key: "ToolType", dataType: "string", width: "15%" },
{ key: "Tool", dataType: "string", width: "10%" },
{ key: "Reactor", dataType: "string", width: "10%" },
{ key: "RDS", dataType: "string", width: "10%" },
{ key: "PSN", dataType: "string", width: "10%" },
{ key: "Layer", dataType: "string", width: "10%" },
{ key: "Zone", dataType: "string", width: "10%" },
{ key: "InsertDate", dataType: "date", width: "10%", format: "dateTime" },
{ key: "Expiration", dataType: "date", width: "10%", format: "dateTime" }
],
dataSource: _apiUrl + "/awaitingdispo/",
responseDataKey: "Results",
tabIndex: 1,
features: [
{ name: "Selection", mode: "row", multipleSelection: false },
{ name: "Filtering", type: "local" },
{ name: "Sorting", type: "local" },
]
});
$("#RefreshButton").click(function () {
$("#grid").igGrid("dataBind");
});
$("#OpenButton").click(loadRunInfoAwaitingDisposition);
$("#grid").on("dblclick", "tr", loadRunInfoAwaitingDisposition);
};
function initExport(apiUrl, startTimeValue, endTimeValue) {
_apiUrl = apiUrl;
var endTime = new Date(endTimeValue);
var startTime = new Date(startTimeValue);
$.getJSON(_apiUrl + '/tooltypes', function (data) {
$("#ToolType").igCombo({
dataSource: data,
responseDataKey: "Results",
textKey: "ToolTypeName",
valueKey: "ID",
mode: "dropdown",
width: 150
});
});
$("#StartDateControl").igDatePicker({
dateInputFormat: "date",
value: startTime,
width: 125,
inputName: "StartDate",
});
$("#StartTimeControl").igTimePicker({
dateInputFormat: "time",
value: startTime,
width: 110,
inputName: "StartTime",
});
$("#EndDateControl").igDatePicker({
dateInputFormat: "date",
value: endTime,
width: 125,
inputName: "EndDate",
});
$("#EndTimeControl").igTimePicker({
dateInputFormat: "time",
value: endTime,
width: 110,
inputName: "EndTime",
});
};
function loadHeaderGridRunHeaders() {
var toolTypeID = -1; // $("#ToolType").igCombo("value");
var gridCreated = $("#HeaderGrid").data("igGrid");
if (gridCreated)
$("#HeaderGrid").igGrid("destroy");
clearFieldsGridRunHeaders();
var headerURL = _apiUrl + "/tooltypes/" + toolTypeID + "/headertitles";
$("#HeaderGrid").igGrid({
autoGenerateColumns: false,
primaryKey: "ID",
height: "100%",
width: "100%",
features: [
{ name: "Paging", type: "local", recordCountKey: "TotalRows", pageSize: 25, pageSizeUrlKey: "pageSize", "pageIndexUrlKey": "page", showPageSizeDropDown: false },
{ name: "Selection", mode: "row", rowSelectionChanged: headerSelectionChangedRunHeaders },
{ name: "Filtering", type: "local" }
],
columns: [
{ key: "ID", dataType: "number", hidden: true },
{ key: "ToolTypeID", dataType: "number", hidden: true },
{ key: "ToolTypeName", dataType: "string", width: "10%" },
{ key: "Title", dataType: "string", width: "40%" },
{ key: "Reactor", dataType: "string", width: "10%" },
{ key: "RDS", dataType: "string", width: "10%" },
{ key: "PSN", dataType: "string", width: "10%" },
{ key: "InsertDate", dataType: "date", format: "dateTime", width: "20%" }
],
dataSource: headerURL,
responseDataKey: "Results",
});
}
function clearFieldsGridRunHeaders() {
var gridCreated = $("#FieldsGrid").data("igGrid");
if (gridCreated)
$("#FieldsGrid").igGrid("destroy");
}
function headerSelectionChangedRunHeaders(evt, ui) {
clearFieldsGridRunHeaders();
var rowData = ui.owner.grid.dataSource.dataView()[ui.row.index];
var url = _apiUrl + "/tooltypes/" + rowData.ToolTypeID + "/headers/" + ui.row.id + "/fields";
$("#FieldsGrid").igGrid({
autoGenerateColumns: false,
primaryKey: "Column",
height: "100%",
width: "100%",
features: [
{ name: 'Resizing' }
],
columns: [
{ key: "Column", dataType: "string", width: "20%", columnCssClass: "FieldTitle", },
{ key: "Value", dataType: "string", }
],
enableHoverStyles: false,
dataSource: url,
responseDataKey: "Results",
});
}
function loadRunInfoRunHeaders() {
var row = $("#HeaderGrid").igGrid("selectedRow");
if (row == null)
return;
var data = $("#HeaderGrid").igGrid("findRecordByKey", row.id);
if (data == null)
return;
var targetURL = "RunInfo?tooltypeid=" + data.ToolTypeID + "&headerid=" + data.ID;
window.location.href = targetURL;
}
function initRunHeaders(apiUrl) {
_apiUrl = apiUrl;
loadHeaderGridRunHeaders();
$("#RefreshButton").click(function () {
$("#HeaderGrid").igGrid("dataBind");
});
$("#OpenButton").click(loadRunInfoRunHeaders);
$("#HeaderGrid").on("dblclick", "tr", loadRunInfoRunHeaders);
}
function loadHeaderGridRunInfo() {
var toolTypeID = $("#ToolType").igCombo("value");
$("#ToolTypeID").text(toolTypeID);
hideDetailsDivRunInfo();
disableHeaderButtonsRunInfo();
$("#HeaderId").text("");
$("#HeaderAttachmentId").text("");
var gridCreated = $("#HeaderGrid").data("igGrid");
if (gridCreated)
$("#HeaderGrid").igGrid("destroy");
$.ajax({
type: "GET",
url: _apiUrl + "/tooltypes/" + toolTypeID + "?sortby=grid",
success: function (r) {
if ((r.Results == null) || (r.Results.ToolType == null) || (r.Results.Metadata == null))
ShowErrorMessage("Invalid tool type: " + toolTypeID);
else {
_toolType = r.Results.ToolType;
_toolTypeMetaData = r.Results.Metadata;
requestHeaderDataRunInfo();
}
},
error: function (e) {
DisplayWSMessage("error", "There was an error getting tooltype info.", e);
}
});
}
function disableHeaderButtonsRunInfo() {
$("#GetDataButton").prop("disabled", true);
$("#ReviewButton").prop("disabled", true);
$("#PinButton").prop("disabled", true);
}
function enableHeaderButtonsRunInfo() {
$("#GetDataButton").prop("disabled", false);
$("#ReviewButton").prop("disabled", false);
$("#PinButton").prop("disabled", false);
}
function hideDetailsDivRunInfo() {
$("#DetailsDiv").prop("hidden", true);
$("#DataAttachmentFrame").prop("src", "");
}
function showDetailsDivRunInfo() {
$("#DetailsDiv").prop("hidden", false);
$("#ExportDiv").prop("hidden", true);
if ((_toolType != null) && (_toolType.OIExportSPName != null) && (_toolType.OIExportSPName.length > 0)) {
$("#ExportDiv").prop("hidden", false);
$("#OIExportButton").prop("disabled", false);
$("#OIExportResult").text('');
}
$("#DataAttachmentFrame").prop("hidden", true);
$("#HeaderAttachmentFrame").prop("hidden", true);
if (_toolType != null) {
var visibleFrames = 0;
if (_toolType.DisplayDataAttachment && _toolType.DisplayDataAttachment.length > 0) {
visibleFrames += 1;
$("#DataAttachmentFrame").prop("hidden", false);
}
if (_toolType.DisplayHeaderAttachment && _toolType.DisplayHeaderAttachment.length > 0) {
visibleFrames += 1;
$("#HeaderAttachmentFrame").prop("hidden", false);
}
var frameWidth = (98 / visibleFrames) + "%";
$("#DataAttachmentFrame,#HeaderAttachmentFrame").css('width', frameWidth);
}
}
function headerSelectionChangedRunInfo(evt, ui) {
if (ui.row.index >= 0) {
if ($("#HeaderId").text() == ui.row.id) {
enableHeaderButtonsRunInfo();
return;
}
}
disableHeaderButtonsRunInfo();
hideDetailsDivRunInfo();
if (ui.row.index >= 0) {
enableHeaderButtonsRunInfo();
$("#HeaderId").text(ui.row.id);
var rowData = ui.owner.grid.dataSource.dataView()[ui.row.index];
$("#HeaderAttachmentId").text(rowData.AttachmentID);
}
}
function cancelHandlerRunInfo(evt, ui) {
return false;
}
function detailSelectionChangedRunInfo(evt, ui) {
$("#DataAttachmentFrame").prop("src", "");
if (ui.row.index >= 0) {
var rowData = ui.owner.grid.dataSource.dataView()[ui.row.index];
var toolTypeID = $("#ToolTypeID").text();
var attachmentUrlBase = _apiUrl + '/tooltypes/' + toolTypeID;
var attachmentId = rowData.AttachmentID;
if ((attachmentId == null) || (attachmentId === ''))
return;
if ((_toolType.DisplayDataAttachment == null) || (_toolType.DisplayDataAttachment === ''))
return;
$("#DataAttachmentFrame").prop("src", attachmentUrlBase + "/data/files/" + attachmentId + "/" + _toolType.DisplayDataAttachment);
}
}
function loadHeaderAttachmentRunInfo() {
var toolTypeID = $("#ToolTypeID").text();
var attachmentId = $("#HeaderAttachmentId").text();
var attachmentUrlBase = _apiUrl + '/tooltypes/' + toolTypeID;
if ((attachmentId == null) || (attachmentId === '') || (_toolType.DisplayHeaderAttachment == null) || (_toolType.DisplayHeaderAttachment === '')) {
$("#HeaderAttachmentFrame").prop("src", "");
} else {
$("#HeaderAttachmentFrame").prop("src", attachmentUrlBase + "/header/files/" + attachmentId + "/" + _toolType.DisplayHeaderAttachment);
}
$("#DataAttachmentFrame").prop("src", "");
}
function markAsReviewedRunInfo() {
var toolTypeId = $("#ToolTypeID").text();
var headerId = $("#HeaderId").text();
$.ajax({
type: "POST",
url: _apiUrl + "/awaitingdispo/markasreviewed?tooltypeid=" + toolTypeId + "&headerid=" + headerId,
success: function () {
},
error: function (e, ajaxOptions, ex) {
DisplayWSMessage("error", "There was an error marking header as reviewed.", e, ex);
$("#ReviewButton").prop("disabled", false);
}
});
}
function loadDetailsRunInfo() {
showDetailsDivRunInfo();
loadHeaderAttachmentRunInfo();
var gridCreated = $("#DetailsGrid").data("igGrid");
if (gridCreated)
$("#DetailsGrid").igGrid("destroy");
var headerId = $("#HeaderId").text();
var toolTypeID = $("#ToolTypeID").text();
var detailsURL = _apiUrl + "/tooltypes/" + toolTypeID + "/headers/" + headerId + "/data";
var gridColumns = [
{ key: "AttachmentID", dataType: "string", hidden: true },
{ key: "Title", dataType: "string", hidden: true },
];
for (var i = 0; i < _toolTypeMetaData.length; i++) {
var f = _toolTypeMetaData[i];
if ((f.Header == false) && (f.GridDisplayOrder > 0)) {
var col = {
key: f.ColumnName,
headerText: f.DisplayTitle,
width: "150px",
};
if (f.GridAttributes != null)
jQuery.extend(col, JSON.parse(f.GridAttributes));
if (col.formatter != null) {
if (col.formatter == "boolToYesNo")
col.formatter = boolToYesNo;
else
col.formatter = null;
}
gridColumns.push(col);
}
}
var gridParms = {
autoGenerateColumns: false,
primaryKey: "ID",
features: [
{ name: "Selection", mode: "row", rowSelectionChanging: detailSelectionChangedRunInfo },
{ name: "Resizing" },
{ name: "Sorting", type: "local" }
],
columns: gridColumns,
dataSource: detailsURL,
responseDataKey: "Results",
dataBound: markAsReviewedRunInfo,
};
if ((_toolType != null) && (_toolType.DataGridAttributes != null)) {
jQuery.extend(gridParms, JSON.parse(_toolType.DataGridAttributes));
}
$("#DetailsGrid").igGrid(gridParms);
}
function requestHeaderDataRunInfo() {
var startDate = $("#StartDate").igDatePicker("value");
var startTime = $("#StartTime").igTimePicker("value");
var endDate = $("#EndDate").igDatePicker("value");
var endTime = $("#EndTime").igTimePicker("value");
var parms = {
datebegin: new Date(
startDate.getFullYear(), startDate.getMonth(), startDate.getDate(),
startTime.getHours(), startTime.getMinutes(), startTime.getSeconds()).toISOString(),
dateend: new Date(
endDate.getFullYear(), endDate.getMonth(), endDate.getDate(),
endTime.getHours(), endTime.getMinutes(), endTime.getSeconds()).toISOString(),
}
var headerId = 0;
if (_initialHeaderId > 0) {
headerId = _initialHeaderId;
parms.headerid = headerId;
$("#HeaderId").text(headerId);
$("#HeaderAttachmentId").text(_initialHeaderAttachmentId);
_initialHeaderId = -1;
}
var headerURL = _apiUrl + "/tooltypes/" + _toolType.ID + "/headers?" + $.param(parms);
var gridColumns = [
{ key: "ID", dataType: "number", hidden: true },
{ key: "AttachmentID", dataType: "string", hidden: true },
{ key: "Title", dataType: "string", hidden: true },
];
for (var i = 0; i < _toolTypeMetaData.length; i++) {
var f = _toolTypeMetaData[i];
if ((f.Header == true) && (f.GridDisplayOrder > 0)) {
var col = {
key: f.ColumnName,
headerText: f.DisplayTitle,
width: "150px",
};
if (f.GridAttributes != null)
jQuery.extend(col, JSON.parse(f.GridAttributes));
if (col.formatter != null) {
if (col.formatter == "boolToYesNo")
col.formatter = boolToYesNo;
else
col.formatter = null;
}
gridColumns.push(col);
}
}
var gridParms = {
autoGenerateColumns: false,
primaryKey: "ID",
height: "100%",
width: "100%",
features: [
{ name: "Paging", type: "local", recordCountKey: "TotalRows", pageSize: 100, pageSizeList: [50, 100, 250, 500], pageSizeUrlKey: "pageSize", "pageIndexUrlKey": "page" },
{ name: "Selection", mode: "row", rowSelectionChanged: headerSelectionChangedRunInfo },
{ name: "Filtering", type: "local" },
{ name: 'Resizing' },
{ name: "Sorting", type: "local" }
],
columns: gridColumns,
dataSource: headerURL,
responseDataKey: "Results",
};
if ((_toolType != null) && (_toolType.HeaderGridAttributes != null)) {
jQuery.extend(gridParms, JSON.parse(_toolType.HeaderGridAttributes));
}
$("#HeaderGrid").igGrid(gridParms);
if (headerId > 0) {
loadDetailsRunInfo();
}
}
function reviewButtonRunInfo() {
var toolTypeId = $("#ToolTypeID").text();
var headerId = parseInt($("#HeaderId").text());
$("#ReviewButton").prop("disabled", true);
$.ajax({
type: "POST",
url: _apiUrl + "/awaitingdispo/markasawaiting?tooltypeid=" + toolTypeId + "&headerid=" + headerId,
success: function (e) {
DisplayWSMessage("info", "Marked as awaiting disposition", e);
$("#ReviewButton").prop("disabled", false);
},
error: function (e, ajaxOptions, ex) {
DisplayWSMessage("error", "There was an error marking header as awaiting disposition.", e, ex);
$("#ReviewButton").prop("disabled", false);
}
});
}
function pinButtonRunInfo() {
var toolTypeId = $("#ToolTypeID").text();
var selectedRow = $("#HeaderGrid").data("igGridSelection").selectedRow();
if (selectedRow !== null) {
$("#PinButton").prop("disabled", true);
var rowData = $("#HeaderGrid").data("igGrid").dataSource.dataView()[selectedRow.index];
var stringified = JSON.stringify(rowData);
stringified = stringified.replace(/"Tool":/gm, '"MesEntity":');
stringified = stringified.replace(/"Equipment ID":/gm, '"MesEntity":');
var jsonObject = JSON.parse(stringified);
$.ajax({
type: "POST",
url: _apiUrl + '/pin/' + toolTypeId + "/markAsPinned",
data: jsonObject,
success: function (e) {
DisplayWSMessage("info", "Marked as pinned", e);
// DisplayWSMessage("info", stringified, e);
$("#PinButton").prop("disabled", false);
$.getJSON(_apiUrl + '/pin/' + toolTypeId + "/pinned?biorad_id=" + _BioRadId + "&cde_id=" + _CdeId + "&rds=" + rowData.RDS, function (data) {
$("#ModalHeaderGrid").igGrid({
dataSource: data,
features: [
{ name: 'Resizing' }
],
columns: [
{ key: "ID", dataType: "number", hidden: true, },
{ key: "ToolTypeID", dataType: "number", hidden: true, },
{ headerText: "Tool", key: "MesEntity", dataType: "string", width: "10%" },
{ key: "Reactor", dataType: "string", width: "10%" },
{ key: "RDS", dataType: "string", width: "10%" },
{ key: "PSN", dataType: "string", width: "10%" },
{ key: "Layer", dataType: "string", width: "10%" },
{ key: "Zone", dataType: "string", width: "10%" }
],
responseDataKey: "Results",
});
var text = "";
for (var i = 0; i < data.Results.length; i++) {
text = text + data.Results[i].Point1 + "\t" + data.Results[i].Point2 + "\t" + data.Results[i].Point3 + "\t" + data.Results[i].Point4 + "\t" + data.Results[i].Point5 + "\t" + data.Results[i].Point6 + "\t" + data.Results[i].Point7 + "\t" + data.Results[i].Point8 + "\t" + data.Results[i].Point9 + "\r";
}
$("#textareaClipboard").val(text);
$("#ModalBodyGrid").igGrid({
dataSource: data,
features: [
{ name: 'Resizing' }
],
columns: [
{ key: "ID", dataType: "number", hidden: true, },
{ key: "ToolTypeID", dataType: "number", hidden: true, },
{ headerText: "Point 1", key: "Point1", dataType: "number", width: "10%" },
{ headerText: "Point 2", key: "Point2", dataType: "number", width: "10%" },
{ headerText: "Point 3", key: "Point3", dataType: "number", width: "10%" },
{ headerText: "Point 4", key: "Point4", dataType: "number", width: "10%" },
{ headerText: "Point 5", key: "Point5", dataType: "number", width: "10%" },
{ headerText: "Point 6", key: "Point6", dataType: "number", width: "10%" },
{ headerText: "Point 7", key: "Point7", dataType: "number", width: "10%" },
{ headerText: "Point 8", key: "Point8", dataType: "number", width: "10%" },
{ headerText: "Point 9", key: "Point9", dataType: "number", width: "10%" },
],
responseDataKey: "Results",
});
});
},
error: function (e, ajaxOptions, ex) {
DisplayWSMessage("error", "There was an error marking header as pinned.", e, ex);
$("#PinButton").prop("disabled", false);
}
});
}
}
function oiExportButtonRunInfo() {
var headerId = $("#HeaderId").text();
var toolTypeID = $("#ToolTypeID").text();
$("#OIExportButton").prop("disabled", true);
$.ajax({
type: "POST",
url: _apiUrl + "/tooltypes/" + toolTypeID + "/headers/" + headerId + "/oiexport",
success: function (r) {
$("#OIExportResult").text("Exported!");
},
error: function (e, ajaxOptions, ex) {
DisplayWSMessage("error", "There was an error exporting.", e, ex);
$("#OIExportButton").prop("disabled", false);
}
});
}
function setInitialDateTimesRunInfo() {
var startTime = new Date(Date.now() - 6 * 60 * 60 * 1000);//6 hours back from now
$("#StartDate").igDatePicker({
dateInputFormat: "date",
value: startTime,
width: 125
});
$("#StartTime").igTimePicker({
dateInputFormat: "time",
value: startTime,
width: 110
});
var endTime = new Date(Date.now());
$("#EndDate").igDatePicker({
dateInputFormat: "date",
value: endTime,
width: 125
});
$("#EndTime").igTimePicker({
dateInputFormat: "time",
value: endTime,
width: 110
});
}
function initRunInfo(apiUrl, initialToolTypeID, initialHeaderId, initialHeaderAttachmentId) {
_apiUrl = apiUrl;
_initialHeaderId = initialHeaderId;
_initialHeaderAttachmentId = initialHeaderAttachmentId;
$.getJSON(_apiUrl + '/tooltypes', function (data) {
for (var i = 0; i < data.Results.length; i++) {
if (data.Results[i].ToolTypeName === "CDE") {
_CdeId = data.Results[i].ID;
}
else if (data.Results[i].ToolTypeName === "BioRad") {
_BioRadId = data.Results[i].ID;
}
}
$("#ToolType").igCombo({
dataSource: data,
responseDataKey: "Results",
textKey: "ToolTypeName",
valueKey: "ID",
mode: "dropdown",
width: 150,
itemsRendered: function (evt, ui) {
loadHeaderGridRunInfo();
},
selectionChanged: loadHeaderGridRunInfo,
initialSelectedItems: [{ value: initialToolTypeID }]
});
});
setInitialDateTimesRunInfo();
$("#HeaderGrid").on("dblclick", "tr", loadDetailsRunInfo);
$("#LoadHeadersButton").click(loadHeaderGridRunInfo);
$("#GetDataButton").click(loadDetailsRunInfo);
$("#ReviewButton").click(reviewButtonRunInfo);
$("#PinButton").click(pinButtonRunInfo);
$("#OIExportButton").click(oiExportButtonRunInfo);
setInterval(function () {
if ($("#chkAutoRefresh").is(':checked')) {
setInitialDateTimesRunInfo();
$("#LoadHeadersButton").click();
}
}, 180000);
};
function triggerFileDownload(fileName, url) {
const anchorElement = document.createElement('a');
anchorElement.href = url;
anchorElement.download = fileName ?? '';
anchorElement.click();
anchorElement.remove();
}
function initIndex() {
}
function copy() {
var copyText = document.getElementById("textareaClipboard");
// Select the text field
copyText.select();
copyText.setSelectionRange(0, 99999); // For mobile devices
// Copy the text inside the text field
navigator.clipboard.writeText(copyText.value);
}

View File

@ -1,7 +1,7 @@
body { body {
padding-top: 50px; padding-top: 50px;
padding-bottom: 20px; padding-bottom: 20px;
background-color: #FAFAFA; background-color: #fafafa;
} }
/* Set padding to keep content from hitting the edges */ /* Set padding to keep content from hitting the edges */
@ -50,11 +50,11 @@ div.modal-content-warning {
} }
.history-deleted { .history-deleted {
background-color: #FFDDDD; background-color: #ffdddd;
} }
.k-alt.history-deleted { .k-alt.history-deleted {
background-color: #EECCCC !important; background-color: #eecccc !important;
} }
.error-highlight { .error-highlight {
@ -71,6 +71,10 @@ div.modal-content-warning {
background-color: red !important; background-color: red !important;
} }
.prod-database {
background-color: #478f7c !important;
}
.test-database .navbar-brand, .test-database .navbar-brand,
.test-database .navbar-text, .test-database .navbar-text,
.test-database .navbar-nav > li > a { .test-database .navbar-nav > li > a {
@ -100,3 +104,31 @@ div.modal-content-warning {
.icon-bar { .icon-bar {
background-color: black; background-color: black;
} }
@media screen and (min-width: 1024px) {
.modal-dialog {
right: auto;
left: 50%;
width: 768px;
padding-top: 30px;
padding-bottom: 30px;
}
.modal-content {
-webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
}
}
@media screen and (min-width: 1368px) {
.modal-dialog {
right: auto;
left: 50%;
width: 1280px;
padding-top: 30px;
padding-bottom: 30px;
}
.modal-content {
-webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
}
}

View File

@ -2,15 +2,31 @@
public class HeaderCommon public class HeaderCommon
{ {
public long ID { get; set; } public long ID { get; set; }
public DateTime InsertDate { get; set; } public DateTime InsertDate { get; set; }
public Guid AttachmentID { get; set; } public Guid AttachmentID { get; set; }
public string? Title { get; set; } public string? Title { get; set; }
public string? Recipe { get; set; }
public DateTime Date { get; set; } public DateTime Date { get; set; }
public long ToolTypeID { get; set; } public long ToolTypeID { get; set; }
public string? ToolTypeName { get; set; } public string? ToolTypeName { get; set; }
public string? Reactor { get; set; }
public string? RDS { get; set; } // [Newtonsoft.Json.JsonProperty("Tool")]
// [System.Text.Json.Serialization.JsonPropertyName("Tool")]
// public string? Tool { get; set; }
// [Newtonsoft.Json.JsonProperty("Equipment ID")]
// [System.Text.Json.Serialization.JsonPropertyName("Equipment ID")]
// public string? Equipment_ID { get; set; }
public string? MesEntity { get; set; }
public string? Employee { get; set; }
public string? Layer { get; set; }
public string? PSN { get; set; } public string? PSN { get; set; }
public string? RDS { get; set; }
public string? Reactor { get; set; }
public string? Recipe { get; set; }
public string? Zone { get; set; }
} }

View File

@ -0,0 +1,47 @@
namespace OI.Metrology.Shared.DataModels;
public class Pinned : HeaderCommon
{
public string Point1 { get; set; }
public string Point2 { get; set; }
public string Point3 { get; set; }
public string Point4 { get; set; }
public string Point5 { get; set; }
public string Point6 { get; set; }
public string Point7 { get; set; }
public string Point8 { get; set; }
public string Point9 { get; set; }
public Pinned(HeaderCommon headerCommon, List<string> values)
{
ID = headerCommon.ID;
InsertDate = headerCommon.InsertDate;
AttachmentID = headerCommon.AttachmentID;
Title = headerCommon.Title;
Date = headerCommon.Date;
ToolTypeID = headerCommon.ToolTypeID;
ToolTypeName = headerCommon.ToolTypeName;
MesEntity = headerCommon.MesEntity;
Employee = headerCommon.Employee;
Layer = headerCommon.Layer;
PSN = headerCommon.PSN;
RDS = headerCommon.RDS;
Reactor = headerCommon.Reactor;
Recipe = headerCommon.Recipe;
Zone = headerCommon.Zone;
Point1 = values[0];
Point2 = values[1];
Point3 = values[2];
Point4 = values[3];
Point5 = values[4];
Point6 = values[5];
Point7 = values[6];
Point8 = values[7];
Point9 = values[8];
}
}

View File

@ -0,0 +1,16 @@
namespace OI.Metrology.Shared.Models.Stateless;
public interface IPinController<T>
{
enum Action : int
{
Index = 0,
MarkAsPinned = 1
}
static string GetRouteName() => nameof(IPinController<T>)[1..^10];
T MarkAsPinned(DataModels.HeaderCommon headerCommon);
T GetPinnedTable(int toolTypeId, string? biorad_id = null, string? cde_id = null, string? rds = null);
}

View File

@ -0,0 +1,11 @@
using OI.Metrology.Shared.DataModels;
namespace OI.Metrology.Shared.Models.Stateless;
public interface IPinRepository
{
Result<Pinned[]> GetPinnedTable(IMetrologyRepository metrologyRepository, int id, string? biorad_id, string? cde_id, string? rds);
void SetPinnedTable(HeaderCommon headerCommon);
}

3
Tests/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"coverage-gutters.coverageBaseDir": "../.vscode/TestResults/**"
}

View File

@ -32,7 +32,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.2" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" /> <PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" /> <PackageReference Include="MSTest.TestFramework" Version="3.0.2" />

View File

@ -0,0 +1,63 @@
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models.Stateless;
using Serilog;
namespace OI.Metrology.Tests;
[TestClass]
public class UnitTestPinController
{
#pragma warning disable CS8618
private static ILogger _Logger;
private static string _ControllerName;
private static TestContext _TestContext;
private static WebApplicationFactory<Server.Program> _WebApplicationFactory;
#pragma warning restore
[ClassInitialize]
public static void ClassInitAsync(TestContext testContext)
{
_TestContext = testContext;
_Logger = Log.ForContext<UnitTestPinController>();
_WebApplicationFactory = new WebApplicationFactory<Server.Program>();
_ControllerName = nameof(Server.ApiControllers.PinController)[..^10];
}
[TestMethod]
public void TestControllerName()
{
_Logger.Information("Starting Web Application");
Assert.AreEqual(IPinController<string>.GetRouteName(), _ControllerName);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetPinnedTable()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
IPinRepository pinRepository = serviceProvider.GetRequiredService<IPinRepository>();
Result<Pinned[]> result = pinRepository.GetPinnedTable(metrologyRepository, id: 1, cde_id: null, biorad_id: null, rds: null);
Assert.IsNotNull(result?.Results);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetPinnedTableApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
string? json = await httpClient.GetStringAsync($"api/{_ControllerName}/-1/pinned");
File.WriteAllText(Path.Combine(AppContext.BaseDirectory, $"{nameof(GetPinnedTableApi)}.json"), json);
Result<Pinned[]>? result = System.Text.Json.JsonSerializer.Deserialize<Result<Pinned[]>>(json);
Assert.IsNotNull(result?.Results);
_Logger.Information($"{_TestContext?.TestName} completed");
}
}

View File

@ -1,4 +1,8 @@
@namespace OI.Metrology.ClientHub @using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using OI.Metrology.View.Shared
@namespace OI.Metrology.View
<Router AppAssembly="@typeof(App).Assembly"> <Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData"> <Found Context="routeData">

10
View/App.razor.cs Normal file
View File

@ -0,0 +1,10 @@
namespace OI.Metrology.View;
public partial class App : Microsoft.AspNetCore.Components.ComponentBase
{
public App()
{
}
}

View File

@ -1,6 +1,6 @@
using System.Text.Json; using System.Text.Json;
namespace OI.Metrology.ClientHub.Models; namespace OI.Metrology.View.Models;
public record AppSettings(string ApiUrl, public record AppSettings(string ApiUrl,
string BuildNumber, string BuildNumber,

View File

@ -1,7 +1,8 @@
using Microsoft.Extensions.Configuration;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Text.Json; using System.Text.Json;
namespace OI.Metrology.ClientHub.Models.Binder; namespace OI.Metrology.View.Models.Binder;
public class AppSettings public class AppSettings
{ {

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFrameworks>net7.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MudBlazor" Version="6.1.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="7.0.2" />
<PackageReference Include="IgniteUI.Blazor" Version="22.2.24" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.BrowserConsole" Version="1.0.0" />
<PackageReference Include="Serilog.Sinks.BrowserHttp" Version="1.0.0-dev-00032" />
<PackageReference Include="System.Net.Http.Json" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\OI.Metrology.Shared.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,23 @@
@page "/"
@page "/AwaitingDisposition"
@using MudBlazor
@using Microsoft.AspNetCore.Components.Web
@namespace OI.Metrology.View
<PageTitle>Awaiting Disposition</PageTitle>
<h4>Awaiting Disposition</h4>
<div style="height: 450px;">
<table id="grid"></table>
</div>
<div class="row" style="margin-top: 10px; margin-bottom: 20px;">
<MudChip Icon="@Icons.Material.Filled.FileOpen" Color="Color.Primary" Label="true" id="OpenButton">Open</MudChip>
<MudChip Icon="@Icons.Material.Filled.Refresh" Color="Color.Primary" Label="true" id="RefreshButton">Refresh</MudChip>
</div>
<script suppress-error="BL9992">
setInterval(function () { $("#RefreshButton").click(); }, 60000);
</script>

View File

@ -0,0 +1,45 @@
// using IgniteUI.Blazor.Controls;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
using OI.Metrology.View.Models;
namespace OI.Metrology.View;
public partial class AwaitingDisposition
{
// protected IgbIcon? OpenIconRef { get; set; }
// protected IgbIcon? RefreshIconRef { get; set; }
[Inject] protected IJSRuntime? JSRuntime { get; set; }
[Inject] protected HttpClient? HttpClient { get; set; }
[Inject] protected AppSettings? AppSettings { get; set; }
[Inject] protected ILogger<AwaitingDisposition>? Logger { get; set; }
protected override Task OnAfterRenderAsync(bool firstRender)
{
// if (firstRender && OpenIconRef is not null)
// {
// const string svg = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='512' height='512' aria-labelledby='gyjump-down-desc gyjump-down-title'><title id='gyjump-down-title'>Jump Down Icon</title><desc id='gyjump-down-desc'>A picture showing a bent arrow pointing down towards a line.</desc><path d='M21.5 18.5v2h-16v-2h16zm-8-15c1.6 0 3 .5 4.3 1.2l-1.5 1.5c-.8-.4-1.8-.7-2.8-.7-3.3 0-6 2.7-6 6h3l-4 4-4-4h3c0-1.5.4-2.9 1.2-4.2.6-1 1.4-1.8 2.4-2.5 1.2-.8 2.8-1.3 4.4-1.3z'/></svg>";
// _ = OpenIconRef.EnsureReady().ContinueWith(new Action<Task>((e) =>
// OpenIconRef.RegisterIconFromTextAsync("jump-down", svg, "material")));
// }
// if (firstRender && RefreshIconRef is not null)
// {
// const string svg = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='512' height='512' aria-labelledby='lzsystem-update-desc lzsystem-update-title'><title id='lzsystem-update-title'>System Update Icon</title><desc id='lzsystem-update-desc'>A picture depicting a computer screen with a reload symbol in the middle.</desc><path d='M20 2H4a2 2 0 00-2 2v12a2 2 0 002 2h6l-2 4h8l-2-4h6a2 2 0 002-2V4a2 2 0 00-2-2zm-8.194 2.923a5.077 5.077 0 104.724 6.923h.982a6.019 6.019 0 11-.237-4.277l.919-.2-.85 2.631-1.85-2.049.857-.184a5.1 5.1 0 00-4.545-2.844zM14 11.424l-.8.8-2-2V6.715h1.139v3.042z'/></svg>";
// _ = RefreshIconRef.EnsureReady().ContinueWith(new Action<Task>((e) =>
// RefreshIconRef.RegisterIconFromTextAsync("system-update", svg, "material")));
// }
if (firstRender)
{
if (JSRuntime is null)
throw new NullReferenceException(nameof(JSRuntime));
if (AppSettings is null)
throw new NullReferenceException(nameof(AppSettings));
return JSRuntime.InvokeVoidAsync("initAwaitingDisposition", AppSettings.ApiUrl).AsTask();
}
return Task.CompletedTask;
}
}

View File

@ -2,7 +2,7 @@
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web
@namespace OI.Metrology.ClientHub.Pages @namespace OI.Metrology.View.Pages
<PageTitle>Counter</PageTitle> <PageTitle>Counter</PageTitle>

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Components;
namespace OI.Metrology.ClientHub.Pages; namespace OI.Metrology.View.Pages;
public partial class Counter public partial class Counter
{ {

View File

@ -1,10 +1,10 @@
@page "/Export" @page "/Export"
@using Microsoft.AspNetCore.Components.Web
@using MudBlazor @using MudBlazor
@using Microsoft.AspNetCore.Components.Web
@using OI.Metrology.Shared.DataModels @using OI.Metrology.Shared.DataModels
@namespace OI.Metrology.ClientHub.Pages @namespace OI.Metrology.View
<PageTitle>Export Data</PageTitle> <PageTitle>Export Data</PageTitle>

View File

@ -1,11 +1,14 @@
using Microsoft.AspNetCore.Components; using IgniteUI.Blazor.Controls;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop; using Microsoft.JSInterop;
using MudBlazor; using MudBlazor;
using OI.Metrology.Shared.DataModels; using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models.Stateless; using OI.Metrology.Shared.Models.Stateless;
using System.Net; using System.Net;
using System.Net.Http.Json;
namespace OI.Metrology.ClientHub.Pages; namespace OI.Metrology.View;
public partial class Export public partial class Export
{ {

15
View/Pages/Index.razor Normal file
View File

@ -0,0 +1,15 @@
@page "/index"
@using Microsoft.AspNetCore.Components.Web
@using IgniteUI.Blazor.Controls
@namespace OI.Metrology.View
<PageTitle>Index</PageTitle>
<IgbChip Size="SizableComponentSize.Medium" Selectable="false" Removable="false">
<span slot="start">
<IgbIcon @ref="@BrushIconRef" IconName="brush" Collection="material" ></IgbIcon>
</span>
Start Slot
</IgbChip>

32
View/Pages/Index.razor.cs Normal file
View File

@ -0,0 +1,32 @@
using IgniteUI.Blazor.Controls;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace OI.Metrology.View;
public partial class Index
{
[Inject] protected IJSRuntime? JSRuntime { get; set; }
protected IgbIcon? BrushIconRef { get; set; }
protected override Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && BrushIconRef is not null)
{
string refreshIcon = "<svg width='24px' height='24px' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-refresh-ccw'><polyline points='1 4 1 10 7 10'></polyline><polyline points='23 20 23 14 17 14'></polyline><path d='M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15'></path></svg>";
string brushIcon = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' aria-labelledby='bqbrush-desc bqbrush-title'><title id='bqbrush-title'>Brush Icon</title><desc id='bqbrush-desc'>A picture showing a painting brush.</desc><path d='M13.093 6.743a1.074 1.074 0 011.306.251l.237.237-6.4 6.4-.242-.231a1.074 1.074 0 01-.251-1.306c.446-.693 1.553-2.516.515-3.554-1.584-1.585-2.225-.94-3.809-2.528S2.714 3 3.354 2.354s2.073-.489 3.658 1.095.943 2.225 2.527 3.809c1.038 1.042 2.861-.069 3.554-.515zm6.93 5.874L15.31 7.9 8.9 14.31l4.433 4.433c-.039.159-.084.327-.137.508 0 0-.8 2.749.8 2.749s.8-2.749.8-2.749a10.75 10.75 0 01-.272-1.14L16.2 16.44a8.944 8.944 0 00-2.072-3.314s.555-.545 3.323 2.063l.811-.811-1.54-2.5 2.5 1.539z'/></svg>";
_ = BrushIconRef.EnsureReady().ContinueWith(new Action<Task>((e) =>
BrushIconRef.RegisterIconFromTextAsync("brush", brushIcon, "material")));
}
if (firstRender)
{
if (JSRuntime is null)
throw new NullReferenceException(nameof(JSRuntime));
return JSRuntime.InvokeVoidAsync("initIndex").AsTask();
}
return Task.CompletedTask;
}
}

View File

@ -1,9 +1,8 @@
@page "/RunHeaders" @page "/RunHeaders"
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web
@using MudBlazor
@namespace OI.Metrology.ClientHub.Pages @namespace OI.Metrology.View
<PageTitle>Run Headers</PageTitle> <PageTitle>Run Headers</PageTitle>
@ -33,9 +32,9 @@
<div class="row" style="margin-top: 10px; margin-bottom: 20px;"> <div class="row" style="margin-top: 10px; margin-bottom: 20px;">
<div class="col-xs-1"> <div class="col-xs-1">
<MudButton Variant="Variant.Filled" Color="Color.Info" id="OpenButton">Open</MudButton> <input type="button" class="btn" id="OpenButton" value="Open" />
</div> </div>
<div class="col-xs-1"> <div class="col-xs-1">
<MudButton Variant="Variant.Filled" Color="Color.Primary" id="RefreshButton">Refresh</MudButton> <input type="button" class="btn" id="RefreshButton" value="Refresh" />
</div> </div>
</div> </div>

View File

@ -0,0 +1,34 @@
using IgniteUI.Blazor.Controls;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace OI.Metrology.View;
public partial class RunHeaders
{
protected IgbIcon? IconRef { get; set; }
[Inject] protected IJSRuntime? JSRuntime { get; set; }
[Inject] protected Models.AppSettings? AppSettings { get; set; }
protected override Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && IconRef is not null)
{
const string buildIcon = "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><path d='M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z'/></svg>";
_ = IconRef.EnsureReady().ContinueWith(new Action<Task>((e) =>
IconRef.RegisterIconFromTextAsync("build", buildIcon, "material")));
}
if (firstRender)
{
if (JSRuntime is null)
throw new NullReferenceException(nameof(JSRuntime));
if (AppSettings is null)
throw new NullReferenceException(nameof(AppSettings));
return JSRuntime.InvokeVoidAsync("initRunHeaders", AppSettings.ApiUrl).AsTask();
}
return Task.CompletedTask;
}
}

View File

@ -1,9 +1,8 @@
@page "/RunInfo/{ToolTypeId:int?}/{HeaderId:int?}" @page "/RunInfo/{ToolTypeId:int?}/{HeaderId:int?}"
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web
@using MudBlazor
@namespace OI.Metrology.ClientHub.Pages @namespace OI.Metrology.View
<PageTitle>Run Info</PageTitle> <PageTitle>Run Info</PageTitle>
@ -25,7 +24,7 @@
<div class="form-control mb-2 mr-sm-2" id="EndTime"></div> <div class="form-control mb-2 mr-sm-2" id="EndTime"></div>
</div>&nbsp;&nbsp; </div>&nbsp;&nbsp;
<div class="form-group"> <div class="form-group">
<MudButton Variant="Variant.Filled" Color="Color.Info" id="LoadHeadersButton">Load Headers</MudButton> <input class="btn btn-primary" type="button" value="Load Headers" id="LoadHeadersButton" />
</div>&nbsp;&nbsp; </div>&nbsp;&nbsp;
<div class="form-group"> <div class="form-group">
<label class="form-check-label" for="chkAutoRefresh"> <label class="form-check-label" for="chkAutoRefresh">
@ -42,10 +41,10 @@
<div class="row" style="margin-top: 10px; margin-bottom: 20px;"> <div class="row" style="margin-top: 10px; margin-bottom: 20px;">
<div class="col-xs-1"> <div class="col-xs-1">
<MudButton Variant="Variant.Filled" Color="Color.Info" id="GetDataButton" Disabled="true">Get Data</MudButton> <input type="button" class="btn" id="GetDataButton" value="Get Data" disabled />
</div> </div>
<div class="col-xs-1"> <div class="col-xs-1">
<MudButton Variant="Variant.Filled" Color="Color.Secondary" id="ReviewButton" Disabled="true">Review</MudButton> <input type="button" class="btn" id="ReviewButton" value="Review" disabled />
</div> </div>
</div> </div>
@ -58,7 +57,7 @@
</div> </div>
<div id="ExportDiv" style="margin-top: 10px;" hidden> <div id="ExportDiv" style="margin-top: 10px;" hidden>
<MudButton Variant="Variant.Filled" Color="Color.Warning" id="OIExportButton">Send to OpenInsight</MudButton> <input type="button" class="btn" value="Send to OpenInsight" id="OIExportButton" />
<span id="OIExportResult" style="margin-left: 10px; font-weight: bold; color: #366b02;"></span> <span id="OIExportResult" style="margin-left: 10px; font-weight: bold; color: #366b02;"></span>
</div> </div>

View File

@ -1,11 +1,14 @@
using Microsoft.AspNetCore.Components; using IgniteUI.Blazor.Controls;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop; using Microsoft.JSInterop;
namespace OI.Metrology.ClientHub.Pages; namespace OI.Metrology.View;
public partial class RunInfo public partial class RunInfo
{ {
protected IgbIcon? IconRef { get; set; }
[Parameter] public int? HeaderId { get; set; } [Parameter] public int? HeaderId { get; set; }
[Parameter] public int? ToolTypeId { get; set; } [Parameter] public int? ToolTypeId { get; set; }
@ -14,6 +17,12 @@ public partial class RunInfo
protected override Task OnAfterRenderAsync(bool firstRender) protected override Task OnAfterRenderAsync(bool firstRender)
{ {
if (firstRender && IconRef is not null)
{
const string buildIcon = "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><path d='M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z'/></svg>";
_ = IconRef.EnsureReady().ContinueWith(new Action<Task>((e) =>
IconRef.RegisterIconFromTextAsync("build", buildIcon, "material")));
}
if (firstRender) if (firstRender)
{ {
if (JSRuntime is null) if (JSRuntime is null)

View File

@ -1,14 +1,14 @@
@inherits LayoutComponentBase @inherits LayoutComponentBase
@namespace OI.Metrology.ClientHub.Shared @namespace OI.Metrology.View.Shared
@using MudBlazor @using MudBlazor
<MudDialogProvider /> <MudDialogProvider />
<MudSnackbarProvider /> <MudSnackbarProvider />
<MudThemeProvider @ref="@_MudThemeProvider" @bind-IsDarkMode="@_IsDarkMode" /> <MudThemeProvider Theme="_MyCustomTheme" />
<MudPaper Style="padding:1px;"> <MudPaper Style="padding:1px;">
<div class="navbar navbar-fixed-top @(AppSettings is not null && AppSettings.IsDevelopment ? "test-database" : "" )"> <div class="navbar navbar-fixed-top @_Database">
<div class="container-fluid"> <div class="container-fluid">
<div class="navbar-header"> <div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
@ -40,9 +40,12 @@
@Body @Body
<hr /> <hr />
<footer> <footer>
@if (AppSettings is not null && AppSettings.IsDevelopment)
{
<p class="navbar-text navbar-right"> <p class="navbar-text navbar-right">
<MudSwitch @bind-Checked="@_IsDarkMode" Color="Color.Primary" Class="ma-4" T="bool" Label="Toggle Light/Dark Mode" /> <MudSwitch @bind-Checked="@_IsDarkMode" Color="Color.Primary" Class="ma-4" T="bool" Label="Toggle Light/Dark Mode" />
</p> </p>
}
<p>&copy; @DateTime.Now.Year - Infineon Technologies</p> <p>&copy; @DateTime.Now.Year - Infineon Technologies</p>
@if (AppSettings is not null && AppSettings.IsDevelopment) @if (AppSettings is not null && AppSettings.IsDevelopment)
{ {

View File

@ -0,0 +1,48 @@
using Microsoft.AspNetCore.Components;
using MudBlazor;
using System.Diagnostics;
namespace OI.Metrology.View.Shared;
public partial class MainLayout
{
private bool _IsDarkMode;
private string? _Database;
private string? _RequestId;
private MudTheme? _MyCustomTheme;
private MudThemeProvider? _MudThemeProvider;
[Inject] protected Models.AppSettings? AppSettings { get; set; }
// [Inject] protected IHttpContextAccessor? HttpContextAccessor { get; set; }
protected override void OnParametersSet()
{
base.OnParametersSet();
_Database = AppSettings is not null && !AppSettings.IsDevelopment ? "test-database" : "prod-database";
_RequestId = Activity.Current?.Id ?? string.Empty; // HttpContextAccessor?.HttpContext?.TraceIdentifier;
_MyCustomTheme = new MudTheme()
{
Palette = new Palette()
{
Primary = "#478f7c",
Secondary = "#AB377A",
Success = "#AEC067",
Info = "#928285",
Warning = "#F07F3C",
Error = "#E30034",
AppbarBackground = "#478f7c",
},
};
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && _MudThemeProvider is not null && _MyCustomTheme is not null)
{
_IsDarkMode = await _MudThemeProvider.GetSystemPreference();
StateHasChanged();
}
}
}

View File

@ -1,4 +1,7 @@
@namespace OI.Metrology.ClientHub.Shared @using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Routing
@namespace OI.Metrology.View.Shared
<div class="top-row ps-3 navbar navbar-dark"> <div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid"> <div class="container-fluid">

View File

@ -0,0 +1,4 @@
namespace OI.Metrology.View.Shared;
public partial class NavMenu
{ }

View File

@ -77,10 +77,14 @@ steps:
workingDirectory: Server workingDirectory: Server
displayName: "Core Build - Server" displayName: "Core Build - Server"
- powershell: Get-ChildItem .\ -include TestResults -Recurse | foreach ($_) { remove-item $_.fullname -Force -Recurse }
workingDirectory: "$(System.DefaultWorkingDirectory)/.vscode"
displayName: 'PowerShell Script'
- script: "dotnet test --configuration $(Configuration)" - script: "dotnet test --configuration $(Configuration)"
workingDirectory: Tests workingDirectory: Tests
displayName: "Core Test" displayName: "Core Test"
enabled: false # enabled: false
- script: '"C:\program files\dotnet\dotnet.exe" tool restore' - script: '"C:\program files\dotnet\dotnet.exe" tool restore'
workingDirectory: Server workingDirectory: Server
@ -92,6 +96,22 @@ steps:
displayName: "Report Generator" displayName: "Report Generator"
enabled: false enabled: false
- task: PublishTestResults@2
displayName: "Publish Test Results **/*.trx"
inputs:
testResultsFormat: VSTest
testResultsFiles: "**/*.trx"
searchFolder: "$(System.DefaultWorkingDirectory)/.vscode"
- task: mspremier.CreateWorkItem.CreateWorkItem-task.CreateWorkItem@1
displayName: "Create work item"
inputs:
teamProject: "Mesa_FI"
workItemType: Bug
title: $(GitCommitSeven)-$(Build.BuildId)-$(Build.Repository.Name)-$(Configuration)
assignedTo: "$(Build.RequestedForId)"
enabled: false
- script: '"C:\program files\dotnet\dotnet.exe" publish --configuration $(Configuration) --runtime win-x64 --self-contained -o $(Build.ArtifactStagingDirectory)\Server --source $(NugetSource)' - script: '"C:\program files\dotnet\dotnet.exe" publish --configuration $(Configuration) --runtime win-x64 --self-contained -o $(Build.ArtifactStagingDirectory)\Server --source $(NugetSource)'
workingDirectory: Server workingDirectory: Server
displayName: "Core Publish" displayName: "Core Publish"