requirements - grouping and filtering

This commit is contained in:
Stoyan Zlatev
2025-01-16 11:11:41 +01:00
parent 98ead9cbee
commit ea8d86b9cf
20 changed files with 758 additions and 204 deletions
@@ -1,13 +1,21 @@
namespace LaaProduction.Data.Cordonel.Interfaces
{
using System;
using LaaPackages.Features.Cordonel.Models;
using System.Collections.Generic;
public interface ISpecialRequirementsRepository<T> : IRepository<T>
{
T FirstOrDefaultByPO(string ponr);
void Approve(int id, string name, string comment);
SpecialRequiremetnsFilter Filter();
IEnumerable<T> Filter(SpecialRequiremetnsFilter filter);
T Find(CordonelSpecialRequirement model);
T FirstOrDefaultByPO(string ponr);
void Unapprove(int id);
}
}
@@ -8,7 +8,7 @@
{
void Approve(int id, string name, string comment);
StandardRequiremetnsFilter CreateFilter();
StandardRequiremetnsFilter Filter();
IEnumerable<T> Filter(StandardRequiremetnsFilter filter);
@@ -7,6 +7,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
public class SpecialRequirementsRepository : ISpecialRequirementsRepository<CordonelSpecialRequirement>
{
@@ -130,6 +132,175 @@
public CordonelSpecialRequirement Delete(object id)
=> throw new NotImplementedException($"{nameof(CordonelSpecialRequirement)} could not be deleted");
public SpecialRequiremetnsFilter Filter()
{
var xmlFilter = this.sqlConnection
.CreateCommand($@"
DECLARE @spl TABLE(
Region VARCHAR(20)
, MeterSize VARCHAR(20)
, ProductionOrder INT
, PcbId INT
, IsActive BIT
, IsApproved BIT)
INSERT INTO @spl
SELECT std.Region
, std.MeterSize
, spl.ProductionOrderNo
, spl.PcbId
, spl.IsActive
, CAST(CASE WHEN spl.ApprovedDate IS NOT NULL THEN 1 ELSE 0 END AS BIT)
FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Version DESC) AS RowNr
FROM Cordonel_Special_Requirements) AS spl
JOIN Cordonel_Standard_Requirements AS std
ON spl.StandardId = std.Id
AND spl.StandardVersion = std.Version
WHERE spl.RowNr = 1
SELECT CAST((SELECT (SELECT DISTINCT Region AS 'Region/@Value'
FROM @spl
FOR XML PATH(''), TYPE) AS Regions
, (SELECT DISTINCT MeterSize AS 'MeterSize/@Value'
FROM @spl
FOR XML PATH(''), TYPE) AS MeterSizes
, (SELECT DISTINCT ProductionOrder AS 'ProductionOrder/@Value'
FROM @spl
FOR XML PATH(''), TYPE) AS ProductionOrders
, (SELECT DISTINCT PcbId AS 'PcbId/@Value'
FROM @spl
FOR XML PATH(''), TYPE) AS PcbIds
, (SELECT DISTINCT IsActive AS 'Active/@Value'
FROM @spl
FOR XML PATH(''), TYPE) AS ActiveRequirements
, (SELECT DISTINCT IsApproved AS 'Approved/@Value'
FROM @spl
FOR XML PATH(''), TYPE) AS ApprovedRequirements
FOR XML PATH(''), ROOT('SpecialRequiremetnsFilter'), TYPE) AS XML)")
.FirstOrDefault(x => x.GetValue<string>(0));
var filter = default(SpecialRequiremetnsFilter);
if (!string.IsNullOrWhiteSpace(xmlFilter))
{
var xmlSerializer = new XmlSerializer(typeof(SpecialRequiremetnsFilter));
var xmlReader = new StringReader(xmlFilter);
try
{
filter = xmlSerializer.Deserialize(xmlReader) as SpecialRequiremetnsFilter;
}
catch // TODO: (Exception e)
{
}
}
return filter ?? new SpecialRequiremetnsFilter();
}
public IEnumerable<CordonelSpecialRequirement> Filter(SpecialRequiremetnsFilter filter)
{
var query = $@"
SELECT *
FROM (SELECT [Latest].[Id]
, [Latest].[Version]
, [Latest].[StandardId]
, [Latest].[StandardVersion]
, [Standards].[Key]
, [Standards].[Region]
, [Standards].[MeterSize]
, [Latest].[ProductionOrderNo]
, [Latest].[PcbId]
, [Latest].[FwVersion]
, [Latest].[LutCrc]
, [Latest].[SkipCalibration]
, [Latest].[SkipRadioCheck]
, [Latest].[RequiredLifeTimeYearsAssembly]
, [Latest].[RequiredLifeTimeYearsShipping]
, [Latest].[MaxDrainedBatteryLoadPercentAssembly]
, [Latest].[MaxDrainedBatteryLoadPercentShipping]
, [Latest].[MaxStorageMonths]
, [Latest].[MaxStorageMonthsBigOrders]
, [Latest].[QuiescentCurrent_uA]
, [Latest].[EstimatedProductionBatteryLoadPercent]
, [Latest].[Timestamp]
, [Latest].[CreatedBy]
, [Latest].[ApprovedBy]
, [Latest].[ApprovedDate]
, [Latest].[Comment]
, [Latest].[IsActive]
, [Standards].[ProductGroup]
FROM (SELECT *, RANK() OVER (PARTITION BY [Id]
ORDER BY [Version] DESC) AS [RowNr]
FROM [Cordonel_Special_Requirements])
AS [Latest]
LEFT JOIN [Cordonel_Standard_Requirements]
AS [Standards]
ON [Standards].[Id] = [Latest].[StandardId]
AND [Standards].[Version] = [Latest].[StandardVersion]
WHERE [Latest].[RowNr] = 1)
AS [req]
{filter?.SqlConditions("req", "WHERE")}
ORDER BY [req].[ProductGroup] ASC
, LEN(SUBSTRING([req].[MeterSize], 1, CASE WHEN CHARINDEX(' ', [req].[MeterSize]) > 0 THEN CHARINDEX(' ', [req].[MeterSize]) - 1 ELSE LEN([req].[MeterSize]) END))
, SUBSTRING([req].[MeterSize], 1, CASE WHEN CHARINDEX(' ', [req].[MeterSize]) > 0 THEN CHARINDEX(' ', [req].[MeterSize]) - 1 ELSE LEN([req].[MeterSize]) END)
, [req].[MeterSize]";
return this.sqlConnection
.CreateCommand(query)
.ExecuteReader(this.ParseSpecialRequirement);
}
public CordonelSpecialRequirement Find(CordonelSpecialRequirement model)
{
var requirement = this.sqlConnection
.CreateCommand($@"
SELECT [Special].[Id]
, [Special].[Version]
, [Special].[StandardId]
, [Special].[StandardVersion]
, [Standard].[Key]
, [Standard].[Region]
, [Standard].[MeterSize]
, [Special].[ProductionOrderNo]
, [Special].[PcbId]
, [Special].[FwVersion]
, [Special].[LutCrc]
, [Special].[SkipCalibration]
, [Special].[SkipRadioCheck]
, [Special].[RequiredLifeTimeYearsAssembly]
, [Special].[RequiredLifeTimeYearsShipping]
, [Special].[MaxDrainedBatteryLoadPercentAssembly]
, [Special].[MaxDrainedBatteryLoadPercentShipping]
, [Special].[MaxStorageMonths]
, [Special].[MaxStorageMonthsBigOrders]
, [Special].[QuiescentCurrent_uA]
, [Special].[EstimatedProductionBatteryLoadPercent]
, [Special].[Timestamp]
, [Special].[CreatedBy]
, [Special].[ApprovedBy]
, [Special].[ApprovedDate]
, [Special].[Comment]
, [Special].[IsActive]
, [Standard].[ProductGroup]
FROM [Cordonel_Special_Requirements] AS [Special]
LEFT JOIN [Cordonel_Standard_Requirements] AS [Standard]
ON [Standard].[Id] = [Special].[StandardId]
AND [Standard].[Version] = [Special].[StandardVersion]
WHERE ISNULL([Special].[ProductionOrderNo], '') = ISNULL(@{nameof(model.ProductionOrderNr)}, '')
AND ISNULL([Special].[PcbId], '') = ISNULL(@{nameof(model.PcbId)}, '')
ORDER BY [Special].[Version] DESC")
.SetParameter(nameof(model.ProductionOrderNr), model.ProductionOrderNr)
.SetParameter(nameof(model.PcbId), model.PcbId)
.FirstOrDefault(this.ParseSpecialRequirement);
if (requirement != null)
{
requirement.StandardRequirement = this.StandardRequirement(requirement.StandardId);
requirement.History = this.Hostory(requirement.Id, requirement.Version);
}
return requirement;
}
public CordonelSpecialRequirement FirstOrDefault(object id)
{
var requirement = this.sqlConnection
@@ -344,16 +344,16 @@
.SetParameter(nameof(requirementId), requirementId)
.ExecuteNonQuery();
public StandardRequiremetnsFilter CreateFilter()
public StandardRequiremetnsFilter Filter()
{
var xmlFilter = this.sqlConnection
.CreateCommand($@"
SELECT CAST((SELECT (SELECT DISTINCT Region AS 'Region/@Value'
FROM Cordonel_Standard_Requirements
FROM Cordonel_Standard_Requirements
FOR XML PATH(''), TYPE) AS Regions
, (SELECT DISTINCT MeterSize AS 'MeterSize/@Value'
FROM Cordonel_Standard_Requirements
FOR XML PATH(''), TYPE) AS MeterSizes
, (SELECT DISTINCT MeterSize AS 'MeterSize/@Value'
FROM Cordonel_Standard_Requirements
FOR XML PATH(''), TYPE) AS MeterSizes
, (SELECT DISTINCT IsActive AS 'Active/@Value'
FROM Cordonel_Standard_Requirements
FOR XML PATH(''), TYPE) AS ActiveRequirements
@@ -385,39 +385,42 @@
public IEnumerable<CordonelStandardRequirement> Filter(StandardRequiremetnsFilter filter)
{
var query = $@"
SELECT [Id]
, [Version]
, [Key]
, [Region]
, [ProductGroup]
, [MeterSize]
, [FwVersion]
, [LutCrc]
, [SkipCalibration]
, [SkipRadioCheck]
, [RequiredLifeTimeYearsAssembly]
, [RequiredLifeTimeYearsShipping]
, [MaxDrainedBatteryLoadPercentAssembly]
, [MaxDrainedBatteryLoadPercentShipping]
, [MaxStorageMonths]
, [MaxStorageMonthsBigOrders]
, [QuiescentCurrent_uA]
, [EstimatedProductionBatteryLoadPercent]
, [Timestamp]
, [CreatedBy]
, [ApprovedBy]
, [ApprovedDate]
, [Comment]
, [IsActive]
FROM (SELECT *, RANK() OVER (PARTITION BY [Id]
ORDER BY [Version] DESC) AS [RowNr]
FROM [Cordonel_Standard_Requirements] {filter?.SqlConditions()})
AS [Latest]
WHERE [Latest].[RowNr] = 1
ORDER BY [ProductGroup] ASC
, LEN(SUBSTRING([MeterSize], 1, CASE WHEN CHARINDEX(' ', [MeterSize]) > 0 THEN CHARINDEX(' ', [MeterSize]) - 1 ELSE LEN([MeterSize]) END))
, SUBSTRING([MeterSize], 1, CASE WHEN CHARINDEX(' ', [MeterSize]) > 0 THEN CHARINDEX(' ', [MeterSize]) - 1 ELSE LEN([MeterSize]) END)
, [MeterSize] ASC";
SELECT *
FROM (SELECT [Id]
, [Version]
, [Key]
, [Region]
, [ProductGroup]
, [MeterSize]
, [FwVersion]
, [LutCrc]
, [SkipCalibration]
, [SkipRadioCheck]
, [RequiredLifeTimeYearsAssembly]
, [RequiredLifeTimeYearsShipping]
, [MaxDrainedBatteryLoadPercentAssembly]
, [MaxDrainedBatteryLoadPercentShipping]
, [MaxStorageMonths]
, [MaxStorageMonthsBigOrders]
, [QuiescentCurrent_uA]
, [EstimatedProductionBatteryLoadPercent]
, [Timestamp]
, [CreatedBy]
, [ApprovedBy]
, [ApprovedDate]
, [Comment]
, [IsActive]
FROM (SELECT *, RANK() OVER (PARTITION BY [Id]
ORDER BY [Version] DESC) AS [RowNr]
FROM [Cordonel_Standard_Requirements])
AS [Latest]
WHERE [Latest].[RowNr] = 1)
AS [req]
{filter?.SqlConditions("req", "WHERE")}
ORDER BY [req].[ProductGroup] ASC
, LEN(SUBSTRING([req].[MeterSize], 1, CASE WHEN CHARINDEX(' ', [req].[MeterSize]) > 0 THEN CHARINDEX(' ', [req].[MeterSize]) - 1 ELSE LEN([req].[MeterSize]) END))
, SUBSTRING([req].[MeterSize], 1, CASE WHEN CHARINDEX(' ', [req].[MeterSize]) > 0 THEN CHARINDEX(' ', [req].[MeterSize]) - 1 ELSE LEN([req].[MeterSize]) END)
, [req].[MeterSize] ASC";
return this.sqlConnection
.CreateCommand(query)
@@ -4,8 +4,7 @@
using LaaProduction.Data.Cordonel;
using LaaProduction.Personalization;
using LaaProductionWeb.App_Infrastructure;
using System;
using System.Web.Http;
[RoutePrefix(RoutePrefixes.API_CORDONEL_SPECIALREQUIREMENTS)]
@@ -57,7 +56,12 @@
return this.BadRequest();
}
var result = this.cordonels.SpecialRequirements.Add(model);
var result = this.cordonels.SpecialRequirements.Find(model);
if (result is null)
{
result = this.cordonels.SpecialRequirements.Add(model);
}
return this.Json(result);
}
@@ -97,5 +101,23 @@
return this.Ok(id);
}
[HttpGet]
[Route(nameof(Filter))]
public IHttpActionResult Filter()
{
var result = this.cordonels.SpecialRequirements.Filter();
return this.Ok(result);
}
[HttpPost]
[Route(nameof(Filter))]
public IHttpActionResult Filter(SpecialRequiremetnsFilter filter)
{
var result = this.cordonels.SpecialRequirements.Filter(filter);
return this.Ok(result);
}
}
}
@@ -122,7 +122,7 @@
[Route(nameof(Filter))]
public IHttpActionResult Filter()
{
var result = this.cordonels.StandardRequirements.CreateFilter();
var result = this.cordonels.StandardRequirements.Filter();
return this.Ok(result);
}
@@ -62,7 +62,7 @@
}
else if (token.Errors != null)
{
this.ModelState.AddModelErrors(token.Errors);
this.ModelState.AddModelError(nameof(token.Errors), "Invalid login attempt!");
}
}
else
@@ -27,6 +27,28 @@
return this.View(requirements);
}
[HttpGet]
public ActionResult TBody()
{
var requirements = this.http
.Get<List<CordonelSpecialRequirement>>(x => x.SetPath(RoutePrefixes.API_CORDONEL_SPECIALREQUIREMENTS.ToURL()))
.Value ?? new List<CordonelSpecialRequirement>();
return this.PartialView(requirements);
}
[HttpPost]
public ActionResult TBody(SpecialRequiremetnsFilter filter)
{
var requirements = this.http
.Post<List<CordonelSpecialRequirement>>(x => x
.SetPath(RoutePrefixes.API_CORDONEL_SPECIALREQUIREMENTS.ToURL("Filter"))
.SetJsonBody(filter))
.Value ?? new List<CordonelSpecialRequirement>();
return this.PartialView(requirements);
}
[HttpGet]
public ActionResult Create()
{
@@ -59,6 +81,9 @@
{
if (this.ModelState.IsValid)
{
model.Timestamp = DateTime.UtcNow;
model.CreatedBy = this.User.FullName();
var requirement = this.http
.Post<CordonelSpecialRequirement>(request => request
.SetPath(RoutePrefixes.API_CORDONEL_SPECIALREQUIREMENTS.ToURL())
@@ -144,7 +169,6 @@
[HttpGet]
[HttpUpdateRequirement]
[Route("SpecialRequirements/Update/{id}")]
public ActionResult Update(string id)
{
var requirement = this.http
@@ -172,6 +196,26 @@
return this.PartialView(requirement);
}
[HttpGet]
[HttpUpdateRequirement]
[Route("SpecialRequirements/Version/{id}/{version}")]
public ActionResult Version(string id, string version)
{
var requirement = this.http
.Get<CordonelSpecialRequirement>(x => x
.SetPath(RoutePrefixes.API_CORDONEL_SPECIALREQUIREMENTS.ToURL($"{id}/{version}")))
.Value ?? new CordonelSpecialRequirement();
if (requirement is null)
{
requirement = new CordonelSpecialRequirement();
this.ModelState.AddModelError("Error", "Requirement not found!");
}
return this.PartialView(nameof(this.Update), requirement);
}
[HttpPost]
[HttpUpdateRequirement]
[Route("SpecialRequirements/Update")]
@@ -221,37 +265,37 @@
return this.PartialView(requirement);
}
[HttpGet]
public ActionResult SpecialRequirements()
{
var requirements = this.http
.Get<IEnumerable<CordonelSpecialRequirement>>(x => x.SetPath(RoutePrefixes.API_CORDONEL_SPECIALREQUIREMENTS.ToURL()))
.Value ?? new List<CordonelSpecialRequirement>();
return this.PartialView(requirements);
}
[HttpPost]
[AllowedRoles(EmployeesRoles.WEB_Requirements_Approve)]
public ActionResult Approve(string id, string comment)
{
var response = this.http
.SetBearer(this.bearer)
.Put(x => x.SetPath(RoutePrefixes.API_CORDONEL_STANDARDREQUIREMENTS.ToURL($"Approve/{id}"))
.Put(x => x.SetPath(RoutePrefixes.API_CORDONEL_SPECIALREQUIREMENTS.ToURL($"Approve/{id}"))
.SetJsonBody(comment));
return this.RedirectToAction(nameof(Update), "SpecialRequirements", new { id });
return this.Redirect($"/LaaProductionWeb/SpecialRequirements/Update/{id}");
}
[HttpGet]
[Route("SpecialRequirements/Unapprove/{id}/")]
[HttpPost]
public ActionResult Unapprove(string id)
{
var response = this.http
.SetBearer(this.bearer)
.Put(x => x.SetPath(RoutePrefixes.API_CORDONEL_SPECIALREQUIREMENTS.ToURL($"Unapprove/{id}")));
return this.Redirect(this.HttpContext.GetUrlReferer());
return this.Redirect($"/LaaProductionWeb/SpecialRequirements/Update/{id}");
}
[HttpGet]
public ActionResult Filter()
{
var filter = this.http
.SetBearer(this.bearer)
.Get<SpecialRequiremetnsFilter>(x => x.SetPath(RoutePrefixes.API_CORDONEL_SPECIALREQUIREMENTS.ToURL("Filter")))
.Value ?? new SpecialRequiremetnsFilter();
return this.PartialView(filter);
}
}
}
@@ -16,7 +16,7 @@
public StandardRequirementsController()
=> this.http = WebApiApplication.GetService<HttpLaaProductionConnection>();
[HttpGet]
public ActionResult Index()
{
@@ -107,8 +107,6 @@
var requirement = this.http
.Get<CordonelStandardRequirement>(x => x.SetPath(RoutePrefixes.API_CORDONEL_STANDARDREQUIREMENTS.ToURL($"{id}/{nr}")))
.Value ?? new CordonelStandardRequirement();
requirement.CreatedBy = this.User.FullName();
requirement.Timestamp = DateTime.UtcNow;
return this.PartialView(nameof(Update), requirement);
}
@@ -356,6 +356,8 @@
<Content Include="Views\StandardRequirements\TrContent.cshtml" />
<Content Include="Views\StandardRequirements\TBody.cshtml" />
<Content Include="Views\StandardRequirements\Filter.cshtml" />
<Content Include="Views\SpecialRequirements\TBody.cshtml" />
<Content Include="Views\SpecialRequirements\Filter.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="App_Content\css\bootstrap.min.css.map" />
@@ -0,0 +1,201 @@
@using LaaPackages.Features.Cordonel.Models
@using LaaProductionWeb.Resources
@using System.Text.RegularExpressions
@model SpecialRequiremetnsFilter
<form id="filter_form">
<h5 class="mt-3 mb-0 small">@UITranslations.Requirements_Region_Name</h5>
<hr class="mb-0 mt-1" />
@if (this.Model?.Regions?.Count > 0)
{
var regions = this.Model.Regions;
var regionsCount = regions.Count;
for (int i = 0; i < regionsCount; i++)
{
var region = regions[i];
var idSelected = $"{nameof(this.Model.Regions)}_{i}_{nameof(region.Selected)}";
<div class="form-check dark">
<input id="@($"{nameof(this.Model.Regions)}_{i}_{nameof(region.Value)}")"
type="hidden"
value="@region.Value"
name="@($"{nameof(this.Model.Regions)}[{i}].{nameof(region.Value)}")">
<input id="@idSelected"
name="@($"{nameof(this.Model.Regions)}[{i}].{nameof(region.Selected)}")"
class="form-check-input form-check-input-dark"
type="checkbox"
value="true"
checked="@region.Selected"
onchange="filterRequirements(this.form);">
<label for="@idSelected" class="form-check-label">@region.Value</label>
</div>
}
}
<h5 class="mt-3 mb-0 small">@UITranslations.Requirements_MeterSize_Name</h5>
<hr class="mb-0 mt-1" />
@if (this.Model?.MeterSizes?.Count > 0)
{
var meterSizes = this.Model.MeterSizes.OrderBy(x =>
{
var matches = Regex.Matches($"{x.Value}", @"\d+");
var value = default(int);
foreach (Match match in matches)
{
_ = match.Success && int.TryParse(match.Value, out value);
break;
}
return value;
})
.ToList();
var meterSizesCount = meterSizes.Count;
for (int i = 0; i < meterSizesCount; i++)
{
var meterSize = meterSizes[i];
var idSelected = $"{nameof(this.Model.MeterSizes)}_{i}_{nameof(meterSize.Selected)}";
<div class="form-check dark">
<input id="@($"{nameof(this.Model.MeterSizes)}_{i}_{nameof(meterSize.Value)}")"
type="hidden"
value="@meterSize.Value"
name="@($"{nameof(this.Model.MeterSizes)}[{i}].{nameof(meterSize.Value)}")">
<input id="@idSelected"
name="@($"{nameof(this.Model.MeterSizes)}[{i}].{nameof(meterSize.Selected)}")"
class="form-check-input form-check-input-dark"
type="checkbox"
value="true"
checked="@meterSize.Selected"
onchange="filterRequirements(this.form);">
<label for="@idSelected" class="form-check-label">@meterSize.Value</label>
</div>
}
}
<h5 class="mt-3 mb-0 small">@UITranslations.Requirements_IsActive_Name</h5>
<hr class="mb-0 mt-1" />
@if (this.Model?.ActiveRequirements?.Count > 0)
{
var activeRequirements = this.Model.ActiveRequirements;
var activeRequirementsCount = activeRequirements.Count;
for (int i = 0; i < activeRequirementsCount; i++)
{
var state = activeRequirements[i];
var idSelected = $"{nameof(this.Model.ActiveRequirements)}_{i}_{nameof(state.Selected)}";
<div class="form-check dark">
<input id="@($"{nameof(this.Model.ActiveRequirements)}_{i}_{nameof(state.Value)}")"
type="hidden"
value="@state.Value.ToString().ToLower()"
name="@($"{nameof(this.Model.ActiveRequirements)}[{i}].{nameof(state.Value)}")">
<input id="@idSelected"
name="@($"{nameof(this.Model.ActiveRequirements)}[{i}].{nameof(state.Selected)}")"
class="form-check-input form-check-input-dark"
type="checkbox"
value="true"
checked="@state.Selected"
onchange="filterRequirements(this.form);">
<label for="@idSelected" class="form-check-label">@(state.Value ? "Aktiv" : "Nicht Aktiv")</label>
</div>
}
}
<h5 class="mt-3 mb-0 small">@UITranslations.RequirementApproved_Title</h5>
<hr class="mb-0 mt-1" />
@if (this.Model?.ApprovedRequirements?.Count > 0)
{
var approvedRequirements = this.Model.ApprovedRequirements;
var approvedRequirementsCount = approvedRequirements.Count;
for (int i = 0; i < approvedRequirementsCount; i++)
{
var approved = approvedRequirements[i];
var idSelected = $"{nameof(this.Model.ApprovedRequirements)}_{i}_{nameof(approved.Selected)}";
<div class="form-check dark">
<input id="@($"{nameof(this.Model.ApprovedRequirements)}_{i}_{nameof(approved.Value)}")"
type="hidden"
value="@approved.Value.ToString().ToLower()"
name="@($"{nameof(this.Model.ApprovedRequirements)}[{i}].{nameof(approved.Value)}")">
<input id="@idSelected"
name="@($"{nameof(this.Model.ApprovedRequirements)}[{i}].{nameof(approved.Selected)}")"
class="form-check-input form-check-input-dark"
type="checkbox"
value="true"
checked="@approved.Selected"
onchange="filterRequirements(this.form);">
<label for="@idSelected" class="form-check-label">@(approved.Value ? "Genemigt" : "Nicht Genemigt")</label>
</div>
}
}
<h5 class="mt-3 mb-0 small">@UITranslations.Requirements_ProductionOrderNr_Name</h5>
<hr class="mb-0 mt-1" />
@if (this.Model?.ProductionOrders?.Count > 0)
{
var productionOrders = this.Model.ProductionOrders;
var productionOrdersCount = productionOrders.Count;
for (int i = 0; i < productionOrdersCount; i++)
{
var productionOrder = productionOrders[i];
var idSelected = $"{nameof(this.Model.ProductionOrders)}_{i}_{nameof(productionOrder.Selected)}";
<div class="form-check dark">
<input id="@($"{nameof(this.Model.ProductionOrders)}_{i}_{nameof(productionOrder.Value)}")"
type="hidden"
value="@productionOrder.Value"
name="@($"{nameof(this.Model.ProductionOrders)}[{i}].{nameof(productionOrder.Value)}")">
<input id="@idSelected"
name="@($"{nameof(this.Model.ProductionOrders)}[{i}].{nameof(productionOrder.Selected)}")"
class="form-check-input form-check-input-dark"
type="checkbox"
value="true"
checked="@productionOrder.Selected"
onchange="filterRequirements(this.form);">
<label for="@idSelected" class="form-check-label">@productionOrder.Value</label>
</div>
}
}
<h5 class="mt-3 mb-0 small">@UITranslations.Requirements_PcbId_Name</h5>
<hr class="mb-0 mt-1" />
@if (this.Model?.PcbIds?.Count > 0)
{
var pcbs = this.Model.PcbIds;
var pcbsCount = pcbs.Count;
for (int i = 0; i < pcbsCount; i++)
{
var pcb = pcbs[i];
var idSelected = $"{nameof(this.Model.PcbIds)}_{i}_{nameof(pcb.Selected)}";
<div class="form-check dark">
<input id="@($"{nameof(this.Model.PcbIds)}_{i}_{nameof(pcb.Value)}")"
type="hidden"
value="@pcb.Value"
name="@($"{nameof(this.Model.PcbIds)}[{i}].{nameof(pcb.Value)}")">
<input id="@idSelected"
name="@($"{nameof(this.Model.PcbIds)}[{i}].{nameof(pcb.Selected)}")"
class="form-check-input form-check-input-dark"
type="checkbox"
value="true"
checked="@pcb.Selected"
onchange="filterRequirements(this.form);">
<label for="@idSelected" class="form-check-label">@pcb.Value</label>
</div>
}
}
</form>
@@ -5,61 +5,60 @@
@model List<CordonelSpecialRequirement>
<div class="table-responsive h-100">
<table class="table table-sm table-bordered mb-0">
<thead class="bg-light position-sticky top-0" style="z-index: 1025 !important">
<div class="table-responsive h-100 table-secondary">
<table class="table table-sm table-bordered border-dark mb-0 table-secondary small">
<thead class="position-sticky top-0" style="z-index: 1025 !important">
<tr>
<th class="text-nowrap px-2 py-1" colspan="100">
<a href="~/StandardRequirements" class="text-smallcaps fs-5 fw-normal text-decoration-none text-secondary">@UITranslations.StandardRequirements_Title</a>
<label class="text-smallcaps fs-5 text-dark ps-5">@UITranslations.SpecialRequirements_Title</label>
<a href="~/StandardRequirements" class="fs-6 fw-normal text-decoration-none text-secondary me-3">@UITranslations.StandardRequirements_Title</a>
<label class="text-dark fs-6 me-3">@UITranslations.SpecialRequirements_Title</label>
@if (this.User.IsInRole(EmployeesRoles.WEB_Approvals))
{
<button class="btn btn-link" onclick="createSpecialRequirement();">
@UITranslations.SpecialRequirements_New_LinkTitle
</button>
<label class="text-primary fw-normal cursor-pointer text-decoration-underline" onclick="createSpecialRequirement();">
<i class="bi bi-node-plus"></i> @UITranslations.SpecialRequirements_New_LinkTitle
</label>
}
</th>
</tr>
<tr>
<th class="text-nowrap px-2 py-1" colspan="100">
<button class="btn btn-link p-0 fs-6 lh-1 text-decoration-none text-dark" data-bs-toggle="offcanvas" data-bs-target="#filter" aria-controls="filter">
<i class="bi bi-bold bi-filter"></i> <span class="small fw-semibold">Filter</span>
</button>
</th>
</tr>
<tr>
@{
var model = new LaaPackages.Features.Cordonel.Models.CordonelSpecialRequirement();
var model = new CordonelSpecialRequirement();
}
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.Version)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.StandardId)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.Region)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MeterSize)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.ProductionOrderNr)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.PcbId)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.IsActive)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.FwVersion)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.LutCrc)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.SkipCalibration)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.SkipRadioCheck)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.RequiredLifeTimeYearsAssembly)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.RequiredLifeTimeYearsShipping)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxDrainedBatteryLoadPercentAssembly)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxDrainedBatteryLoadPercentShipping)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxStorageMonths)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.MaxStorageMonthsBigOrders)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.QuiescentCurrent_uA)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.EstimatedProductionBatteryLoadPercent)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.CreatedBy)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.Timestamp)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.ApprovedBy)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.ApprovedDate)</th>
<th class="text-smallcaps small p-2">@Html.DisplayNameFor(_ => model.Comment)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.Version)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.StandardId)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.Region)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.MeterSize)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.ProductionOrderNr)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.PcbId)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.IsActive)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.FwVersion)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.LutCrc)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.SkipCalibration)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.SkipRadioCheck)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.RequiredLifeTimeYearsAssembly)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.RequiredLifeTimeYearsShipping)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.MaxDrainedBatteryLoadPercentAssembly)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.MaxDrainedBatteryLoadPercentShipping)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.MaxStorageMonths)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.MaxStorageMonthsBigOrders)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.QuiescentCurrent_uA)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.EstimatedProductionBatteryLoadPercent)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.CreatedBy)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.Timestamp)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.ApprovedBy)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.ApprovedDate)</th>
<th class="small p-2">@Html.DisplayNameFor(_ => model.Comment)</th>
</tr>
</thead>
<tbody>
@if (Model != null && Model.Any())
{
foreach (var x in this.Model)
{
<tr id="@x.Id" class="tr-hover" onclick="location.hash = @x.Id">
@Html.Partial("TrContent", x)
</tr>
}
}
@{ Html.RenderPartial("TBody", this.Model); }
</tbody>
</table>
</div>
@@ -76,23 +75,54 @@
</div>
</div>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="filter" aria-labelledby="filterLabel" style="background: #e2e3e5">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="filterLabel"><i class="bi bi-bold bi-filter"></i> @UITranslations.SpecialRequirements_Title</h5>
<button type="button" class="btn bg-transparent border-0 px-0 ms-auto" data-bs-dismiss="offcanvas" aria-label="Close">
<i class="bi bi-arrow-left bi-bold"></i>
</button>
</div>
<div class="offcanvas-body small">
@{
Html.RenderAction("Filter");
}
</div>
</div>
@section scripts {
<script>
let modal = document.querySelector('div[id="modal"]');
modal.addEventListener('hide.bs.modal', () => {
fetch(`@this.Url.Action("Filter", "SpecialRequirements")`)
.then(response2Text)
.then(text => document.querySelector('.offcanvas-body').innerHTML = text);
});
modal.addEventListener('hidden.bs.modal', () => {
location.hash = '';
});
function autocompletePO (e) {
const value = `${e.target.value}`;
fetch(`@this.Url.Action("ProductionOrders", "SpecialRequirements")/${value}`)
.then(response => response.text())
.then(text => document
.getElementById('ProductionOrders')
.innerHTML = text);
function response2Text(response) {
return response.text();
}
function loadModalContent(text, show) {
function updateTBody(text) {
document.querySelector('tbody').innerHTML = text;
}
function reloadSpecialRequirements() {
fetch(`@this.Url.Action("TBody", "SpecialRequirements")`)
.then(response2Text)
.then(updateTBody);
}
function autocompletePO (e) {
fetch(`@this.Url.Action("ProductionOrders", "SpecialRequirements")/${e.target.value}`)
.then(response => response.text())
.then(text => document.getElementById('ProductionOrders').innerHTML = text);
}
function loadModalContent(text) {
let content = modal.querySelector('.modal-content');
content.innerHTML = text;
@@ -107,9 +137,11 @@
}
let productionOrderNr = content.querySelector('#ProductionOrderNr');
productionOrderNr.oninput = autocompletePO;
if (productionOrderNr) {
productionOrderNr.oninput = autocompletePO;
}
if (show) {
if (!modal.classList.contains('show')) {
let trigger = document.getElementById('modal_toggler');
trigger.click();
}
@@ -128,19 +160,17 @@
const form = document.querySelector('form');
fetch(`@this.Url.Action("UpdatePO", "SpecialRequirements")`, { method: 'POST', body: new FormData(form) })
.then(response => response.text())
.then(text => loadModalContent(text, false))
.then(response2Text)
.then(loadModalContent)
.then(() => fetch(`@this.Url.Action("Pcbids", "SpecialRequirements")/${ponr}`)
.then(response => response.text())
.then(text => document
.getElementById('PcbId')
.innerHTML = text));
.then(response2Text)
.then(text => document.getElementById('PcbId').innerHTML = text));
}
function createSpecialRequirement() {
fetch(`@this.Url.Action("Create", "SpecialRequirements")`)
.then(response => response.text())
.then(text => loadModalContent(text, true));
.then(response2Text)
.then(loadModalContent);
}
function submitCreateSpecialRequirement(e) {
@@ -148,23 +178,15 @@
e.stopPropagation();
fetch(`@this.Url.Action("Create", "SpecialRequirements")`, { method: 'POST', body: new FormData(e.target) })
.then(response => response.text())
.then(text => {
loadModalContent(text, false);
})
.then(() => {
fetch(`@this.Url.Action("SpecialRequirements", "SpecialRequirements")`)
.then(response => response.text())
.then(text => {
document.querySelector('tbody').innerHTML = text;
});
});
.then(response2Text)
.then(loadModalContent)
.then(reloadSpecialRequirements);
}
function loadSpecialRequirement(id) {
fetch(`@this.Url.Action("Update", "SpecialRequirements")/${id}`)
.then(response => response.text())
.then(text => loadModalContent(text, true));
.then(response2Text)
.then(loadModalContent);
}
function submitUpdateSpecialRequirement(e) {
@@ -172,21 +194,15 @@
e.stopPropagation();
fetch(`@this.Url.Action("Update", "SpecialRequirements")`, { method: 'POST', body: new FormData(e.target) })
.then(response => response.text())
.then(text => {
loadModalContent(text, false);
fetch(`@this.Url.Action("SpecialRequirements", "SpecialRequirements")`)
.then(response => response.text())
.then(text => document
.querySelector('tbody')
.innerHTML = text);
});
.then(response2Text)
.then(loadModalContent)
.then(reloadSpecialRequirements);
}
function loadStandardRequirementVersion(id, nr) {
fetch(`@this.Url.Action("Update", "SpecialRequirements")/${id}/${nr}`)
.then(response => response.text())
.then(text => loadModalContent(text, false));
function loadSpecialRequirementVersion(id, nr) {
fetch(`@this.Url.Action("Version", "SpecialRequirements")/${id}/${nr}`)
.then(response2Text)
.then(loadModalContent);
}
function approveRequirement() {
@@ -201,11 +217,39 @@
method: 'post'
})
.then(response2Text)
.then(setModalInnerHTML);
.then(loadModalContent)
.then(reloadSpecialRequirements);
}
}
}
function unapproveRequirement() {
if (modal) {
let id = modal.querySelector('input[id="@nameof(CordonelStandardRequirement.Id)"]').value;
if (id) {
fetch(`@this.Url.Action("Unapprove", "SpecialRequirements")`, {
credentials: 'same-origin',
body: JSON.stringify({ id: id }),
headers: { 'Content-Type': 'application/json' },
method: 'post'
})
.then(response2Text)
.then(loadModalContent)
.then(reloadSpecialRequirements);
}
}
}
function filterRequirements(form) {
fetch(`@this.Url.Action("TBody", "SpecialRequirements")`, {
credentials: 'same-origin',
body: new FormData(form),
method: 'post'
})
.then(response2Text)
.then(updateTBody);
}
window.addEventListener('hashchange', () => {
let id = location.hash.substring(1);
if (id) {
@@ -0,0 +1,53 @@
@using LaaPackages.Features.Cordonel.Models
@using LaaProductionWeb.Resources
@model List<CordonelSpecialRequirement>
@if (this.Model != null && this.Model.Any())
{
var requirements = this.Model.Where(x => x.ApprovedBy != null);
if (requirements.Any())
{
<tr class="table-success border-bottom border-dark">
<td colspan="100">@UITranslations.RequirementApproved_Title</td>
</tr>
foreach (var x in requirements)
{
<tr id="@x.Id" class="tr-hover table-success" onclick="location.hash = @x.Id">
@Html.Partial("TrContent", x)
</tr>
}
}
requirements = this.Model.Where(x => x.IsActive && x.ApprovedBy is null);
if (requirements.Any())
{
<tr class="table-warning border-bottom border-dark">
<td colspan="100">@UITranslations.RequirementPendingApproval_Title</td>
</tr>
foreach (var x in requirements)
{
<tr id="@x.Id" class="tr-hover table-warning" onclick="location.hash = @x.Id">
@Html.Partial("TrContent", x)
</tr>
}
}
requirements = this.Model.Where(x => !x.IsActive);
if (requirements.Any())
{
<tr class="table-danger border-bottom border-dark">
<td colspan="100">@UITranslations.RequirementDisabled_Title</td>
</tr>
foreach (var x in requirements)
{
<tr id="@x.Id" class="tr-hover table-danger" onclick="location.hash = @x.Id">
@Html.Partial("TrContent", x)
</tr>
}
}
}
@@ -2,43 +2,29 @@
<th class="text-nowrap small px-2 py-1">@($"{Model.Id}.{Model.Version}")</th>
<td class="text-nowrap small px-2 py-1">@($"{Model.StandardId}.{Model.StandardVersion}")</td>
<td class="text-nowrap small px-2 py-1">@Model.Region | @Model.ProductGroup</td>
<td class="text-nowrap small px-2 py-1">@Model.Region</td>
<td class="text-nowrap small px-2 py-1">@Model.MeterSize</td>
<td class="text-nowrap small px-2 py-1">@Model.ProductionOrderNr</td>
<td class="text-nowrap small px-2 py-1">@Model.PcbId</td>
<td class="text-nowrap small px-2 py-1 text-center">
@if (Model.IsActive)
{
<i class="bi bi-bold bi-check text-success"></i>
if (Model.ApprovedBy != null)
if (Model.ApprovedDate is null)
{
<i class="bi bi-bold bi-check text-success"></i>
<i class="bi bi-bold bi-check text-warning"></i>
}
else
{
<i class="bi bi-bold bi-check text-secondary opacity-50"></i>
<i class="bi bi-bold bi-check text-success"></i>
}
}
else
{
<i class="bi bi-bold bi-x text-danger"></i>
if (Model.ApprovedBy != null)
{
<i class="bi bi-bold bi-x text-success"></i>
}
else
{
<i class="bi bi-bold bi-x text-secondary opacity-50"></i>
}
}
</td>
<td class="text-nowrap small px-2 py-1">@Model.FwVersion</td>
<td class="text-nowrap small px-2 py-1">@Model.LutCrc</td>
<td class="text-nowrap small px-2 py-1 text-center">
@if (Model.SkipCalibration == true)
{
@@ -49,7 +35,6 @@
<i class="bi bi-bold bi-x text-danger"></i>
}
</td>
<td class="text-nowrap small px-2 py-1 text-center">
@if (Model.SkipRadioCheck == true)
{
@@ -60,7 +45,6 @@
<i class="bi bi-bold bi-x text-danger"></i>
}
</td>
<td class="text-nowrap small px-2 py-1 text-end">@Model.RequiredLifeTimeYearsAssembly</td>
<td class="text-nowrap small px-2 py-1 text-end">@Model.RequiredLifeTimeYearsShipping</td>
<td class="text-nowrap small px-2 py-1 text-end">@Model.MaxDrainedBatteryLoadPercentAssembly</td>
@@ -14,7 +14,7 @@
@Html.HiddenFor(x => x.StandardId)
@Html.HiddenFor(x => x.StandardVersion)
<div class="modal-header border-0 px-0 pt-0">
<h5 class="modal-title text-smallcaps">@UITranslations.SpecialRequirements_Update_Title</h5>
<h5 class="modal-title text-smallcaps">@UITranslations.SpecialRequirements_Update_Title <span class="small text-dark opacity-50">(@this.Model.Id.@this.Model.Version)</span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="row p-0 small text-danger">
@@ -97,7 +97,7 @@
<ul class="dropdown-menu w-100" style="max-height: 300px; overflow-x: hidden; overflow-y: auto">
@foreach (var change in Model.History)
{
<li class="card card-body mb-2 mx-2 border-0 bg-light cursor-pointer" onclick="loadStandardRequirementVersion('@change.Id', '@change.Version')">
<li class="card card-body mb-2 mx-2 border-0 bg-light cursor-pointer" onclick="loadSpecialRequirementVersion('@change.Id', '@change.Version')">
<p class="text-smallcaps fw-bold mb-0 small">
@($"V.{change.Id}.{change.Version}") -
@if (change.IsActive)
@@ -243,9 +243,9 @@
}
else if (this.ViewData["CanUnapprove"] is bool canUnapprove && canUnapprove)
{
<a href="~/SpecialRequirements/Unapprove/@this.Model.Id" class="btn btn-danger">
<button type="button" class="btn btn-danger" onclick="unapproveRequirement();">
<i class="bi bi-x"></i> @UITranslations.Requirements_Unapprove
</a>
</button>
}
</div>
</form>
@@ -259,7 +259,7 @@ else
@Html.HiddenFor(x => x.StandardId)
@Html.HiddenFor(x => x.StandardVersion)
<div class="modal-header border-0 px-0 pt-0">
<h5 class="modal-title text-smallcaps">@UITranslations.SpecialRequirements_Update_Title</h5>
<h5 class="modal-title text-smallcaps">@UITranslations.SpecialRequirements_Update_Title <span class="small text-dark opacity-50">(@this.Model.Id.@this.Model.Version)</span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="row p-0 small text-danger">
@@ -279,7 +279,10 @@ else
<div class="form-floating position-relative mb-3">
<div class="form-control d-flex py-0 align-items-center">
<div class="pb-0 m-0">
@Html.CheckBox(nameof(Model.SkipCalibration), Model.SkipCalibration ?? false, new { @class = "form-check-input", autocomplete = "off", @readonly = "readonly" })
@{
var _checked = Model.SkipCalibration == true ? "checked" : "";
}
<input class="form-check-input" checked="@_checked" readonly="readonly" />
@Html.LabelFor(x => x.SkipCalibration, new { @class = "form-check-label" })
</div>
</div>
@@ -288,7 +291,10 @@ else
<div class="form-floating position-relative mb-3">
<div class="form-control d-flex py-0 align-items-center">
<div class="pb-0 m-0">
@Html.CheckBox(nameof(Model.SkipRadioCheck), Model.SkipRadioCheck ?? false, new { @class = "form-check-input", autocomplete = "off", @readonly = "readonly" })
@{
_checked = Model.SkipRadioCheck == true ? "checked" : "";
}
<input class="form-check-input" checked="@_checked" readonly="readonly" />
@Html.LabelFor(x => x.SkipRadioCheck, new { @class = "form-check-label" })
</div>
</div>
@@ -297,7 +303,10 @@ else
<div class="form-floating position-relative mb-3">
<div class="form-control d-flex py-0 align-items-center">
<div class="pb-0 m-0">
@Html.CheckBoxFor(x => x.IsActive, new { @class = "form-check-input", autocomplete = "off", @readonly = "readonly" })
@{
_checked = Model.IsActive == true ? "checked" : "";
}
<input class="form-check-input" checked="@_checked" readonly="readonly" />
@Html.LabelFor(x => x.IsActive, new { @class = "form-check-label" })
</div>
</div>
@@ -337,7 +346,7 @@ else
<ul class="dropdown-menu w-100" style="max-height: 300px; overflow-x: hidden; overflow-y: auto">
@foreach (var change in Model.History)
{
<li class="card card-body mb-2 mx-2 border-0 bg-light cursor-pointer" onclick="loadStandardRequirementVersion('@change.Id', '@change.Version')">
<li class="card card-body mb-2 mx-2 border-0 hover-light cursor-pointer" onclick="loadSpecialRequirementVersion('@change.Id', '@change.Version')">
<p class="text-smallcaps fw-bold mb-0 small">
@($"V.{change.Id}.{change.Version}") -
@if (change.IsActive)
@@ -361,7 +370,7 @@ else
<div class="row">
<div class="col pe-0">
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.CreatedBy, new { @class = "form-control bg-light", placeholder = "...", @readonly = "readonly", autocomplete = "off" })
@Html.TextBoxFor(x => x.CreatedBy, new { @class = "form-control bg-light", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.CreatedBy)
@Html.PopoverFor(x => x.CreatedBy)
@Html.ValidationMessageFor(x => x.CreatedBy, null, new { @class = "small text-danger" })
@@ -369,7 +378,7 @@ else
</div>
<div class="col">
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.ApprovedBy, new { @class = "form-control bg-light", placeholder = "...", @readonly = "readonly", autocomplete = "off" })
@Html.TextBoxFor(x => x.ApprovedBy, new { @class = "form-control bg-light", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.ApprovedBy)
@Html.PopoverFor(x => x.ApprovedBy)
@Html.ValidationMessageFor(x => x.ApprovedBy, null, new { @class = "small text-danger" })
@@ -379,7 +388,7 @@ else
<div class="row">
<div class="col pe-0">
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.Timestamp, new { @class = "form-control bg-light", placeholder = "...", @readonly = "readonly", autocomplete = "off" })
@Html.TextBoxFor(x => x.Timestamp, new { @class = "form-control bg-light", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.Timestamp)
@Html.PopoverFor(x => x.Timestamp)
@Html.ValidationMessageFor(x => x.Timestamp, null, new { @class = "small text-danger" })
@@ -387,7 +396,7 @@ else
</div>
<div class="col">
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.ApprovedDate, new { @class = "form-control bg-light", placeholder = "...", @readonly = "readonly", autocomplete = "off" })
@Html.TextBoxFor(x => x.ApprovedDate, new { @class = "form-control bg-light", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.ApprovedDate)
@Html.PopoverFor(x => x.ApprovedDate)
@Html.ValidationMessageFor(x => x.ApprovedDate, null, new { @class = "small text-danger" })
@@ -397,52 +406,52 @@ else
</div>
<div class="col">
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.FwVersion, new { @class = "form-control", placeholder = "...", autocomplete = "off", @readonly = "readonly" })
@Html.TextBoxFor(x => x.FwVersion, new { @class = "form-control", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.FwVersion)
@Html.PopoverFor(x => x.FwVersion)
</div>
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.LutCrc, new { @class = "form-control", placeholder = "...", autocomplete = "off", @readonly = "readonly" })
@Html.TextBoxFor(x => x.LutCrc, new { @class = "form-control", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.LutCrc)
@Html.PopoverFor(x => x.LutCrc)
</div>
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.RequiredLifeTimeYearsAssembly, new { @class = "form-control", placeholder = "...", autocomplete = "off", @readonly = "readonly" })
@Html.TextBoxFor(x => x.RequiredLifeTimeYearsAssembly, new { @class = "form-control", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.RequiredLifeTimeYearsAssembly)
@Html.PopoverFor(x => x.RequiredLifeTimeYearsAssembly)
</div>
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.RequiredLifeTimeYearsShipping, new { @class = "form-control", placeholder = "...", autocomplete = "off", @readonly = "readonly" })
@Html.TextBoxFor(x => x.RequiredLifeTimeYearsShipping, new { @class = "form-control", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.RequiredLifeTimeYearsShipping)
@Html.PopoverFor(x => x.RequiredLifeTimeYearsShipping)
</div>
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.MaxDrainedBatteryLoadPercentAssembly, new { @class = "form-control", placeholder = "...", autocomplete = "off", @readonly = "readonly" })
@Html.TextBoxFor(x => x.MaxDrainedBatteryLoadPercentAssembly, new { @class = "form-control", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.MaxDrainedBatteryLoadPercentAssembly)
@Html.PopoverFor(x => x.MaxDrainedBatteryLoadPercentAssembly)
</div>
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.MaxDrainedBatteryLoadPercentShipping, new { @class = "form-control", placeholder = "...", autocomplete = "off", @readonly = "readonly" })
@Html.TextBoxFor(x => x.MaxDrainedBatteryLoadPercentShipping, new { @class = "form-control", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.MaxDrainedBatteryLoadPercentShipping)
@Html.PopoverFor(x => x.MaxDrainedBatteryLoadPercentShipping)
</div>
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.MaxStorageMonths, new { @class = "form-control", placeholder = "...", autocomplete = "off", @readonly = "readonly" })
@Html.TextBoxFor(x => x.MaxStorageMonths, new { @class = "form-control", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.MaxStorageMonths)
@Html.PopoverFor(x => x.MaxStorageMonths)
</div>
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.MaxStorageMonthsBigOrders, new { @class = "form-control", placeholder = "...", autocomplete = "off", @readonly = "readonly" })
@Html.TextBoxFor(x => x.MaxStorageMonthsBigOrders, new { @class = "form-control", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.MaxStorageMonthsBigOrders)
@Html.PopoverFor(x => x.MaxStorageMonthsBigOrders)
</div>
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.QuiescentCurrent_uA, new { @class = "form-control", placeholder = "...", autocomplete = "off", @readonly = "readonly" })
@Html.TextBoxFor(x => x.QuiescentCurrent_uA, new { @class = "form-control", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.QuiescentCurrent_uA)
@Html.PopoverFor(x => x.QuiescentCurrent_uA)
</div>
<div class="form-floating mb-3">
@Html.TextBoxFor(x => x.EstimatedProductionBatteryLoadPercent, new { @class = "form-control", placeholder = "...", autocomplete = "off", @readonly = "readonly" })
@Html.TextBoxFor(x => x.EstimatedProductionBatteryLoadPercent, new { @class = "form-control", placeholder = "...", @readonly = "readonly" })
@Html.LabelFor(x => x.EstimatedProductionBatteryLoadPercent)
@Html.PopoverFor(x => x.EstimatedProductionBatteryLoadPercent)
</div>
@@ -1,5 +1,6 @@
@using LaaPackages.Features.Cordonel.Models
@using LaaProductionWeb.Resources
@using System.Text.RegularExpressions
@model StandardRequiremetnsFilter
@@ -40,7 +41,20 @@
@if (this.Model?.MeterSizes?.Count > 0)
{
var meterSizes = this.Model.MeterSizes;
var meterSizes = this.Model.MeterSizes.OrderBy(x =>
{
var matches = Regex.Matches($"{x.Value}", @"\d+");
var value = default(int);
foreach (Match match in matches)
{
_ = match.Success && int.TryParse(match.Value, out value);
break;
}
return value;
})
.ToList();
var meterSizesCount = meterSizes.Count;
for (int i = 0; i < meterSizesCount; i++)
@@ -47,7 +47,7 @@
</tr>
</thead>
<tbody>
@{ Html.RenderPartial("TBody", this.Model); }
@{ this.Html.RenderPartial("TBody", this.Model); }
</tbody>
</table>
</div>
@@ -73,7 +73,7 @@
</div>
<div class="offcanvas-body small">
@{
Html.RenderAction("Filter");
this.Html.RenderAction("Filter");
}
</div>
</div>
@@ -302,7 +302,8 @@ else
name="Version"
placeholder="..."
readonly="readonly"
type="text" value="@Model.Version">
type="text"
value="@Model.Version">
@Html.LabelFor(x => x.Version)
@Html.PopoverFor(x => x.Version)
</div>
@@ -369,7 +370,7 @@ else
<ul class="dropdown-menu w-100" style="max-height: 300px; overflow-x: hidden; overflow-y: auto">
@foreach (var change in Model.History)
{
<li class="card card-body mb-2 mx-2 border-0">
<li class="card card-body mb-2 mx-2 border-0 cursor-pointer hover-light" onclick="loadStandardRequirementVersion('@change.Id', '@change.Version')">
<p class="text-smallcaps fw-bold mb-0 small">
@($"V.{change.Id}.{change.Version}") -
@if (change.IsActive)
+2 -2
View File
@@ -6,8 +6,8 @@
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<!--<add key="APIURL" value="http://sla12iis01.emea.sensus.net" />-->
<add key="APIURL" value="http://localhost:52822" />
<add key="APIURL" value="http://sla12iis01.emea.sensus.net" />
<!--<add key="APIURL" value="http://localhost:52822" />-->
<add key="APIPrefix" value="/LaaProductionWeb" />
<add key="ConnectionString" value="Server=SLASQL01.emea.sensus.net; Database=Auftrag; User ID=sa; Password=sqlserver;" />
<add key="LoginTimeout" value="30" />