Sicherung

This commit is contained in:
Stephan Maier
2024-10-18 09:09:38 +02:00
parent e791920907
commit 37ec8a0ded
23 changed files with 133200 additions and 10 deletions

View File

@@ -0,0 +1,141 @@
using FSI.BT.IR.Plc.Settings.Log.Data;
using FSI.BT.IR.Plc.Settings.Log.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace FSI.BT.IR.Plc.Settings.Log.Controllers
{
public class OrganizationController : Controller
{
private readonly ApplicationDbContext _context;
private readonly DataManager _dataManager;
public OrganizationController(ApplicationDbContext context)
{
_context = context;
_dataManager = new(context);
}
public async Task<IActionResult> IndexAsync()
{
Task<List<Organization>> data = _dataManager.LoadOrganizationsAsync();
return View(await data);
}
public async Task<IActionResult> AddOrEditAsync(int id = 0)
{
if (id == 0)
{
var item = new Organization();
item.Parents = _context.Organizations.OrderBy(x => x.Name).ToList();
item.Parents.Add(new Organization());
if (item.ParentId == null)
{
item.ParentId = 0;
}
return View(item);
}
else
{
var item = await _context.Organizations.FindAsync(id);
if (item == null) // kein Fund
{
return NotFound();
}
item.Parents = _context.Organizations.ToList();
item.Parents.Add(new Organization()); // neue & leere Organisation einfügen
item.Parents.Remove(item); // eingene Organisation entfernen
item.Parents.OrderBy(x => x.Name); // sortieren
if (item.ParentId == null)
{
item.ParentId = 0;
}
return View(item);
}
}
[HttpPost]
public async Task<IActionResult> AddOrEditAsync(int id, Organization item)
{
ModelState.Remove(nameof(item.Parent));
ModelState.Remove(nameof(item.Parents));
ModelState.Remove(nameof(item.FullShortName));
if (string.IsNullOrEmpty(item.FullShortName))
{
item.FullShortName = _dataManager.GetOrganizationFullShortName(_context.Organizations.ToList(), item.ParentId, item.ShortName);
}
item.ModificationTimeStamp = DateTime.Now; // Zeitstempel für Modifikation
if (ModelState.IsValid)
{
if (item.ParentId == 0)
{
item.ParentId = null;
}
if (id == 0) // Insert
{
try
{
item.CreationTimeStamp = item.ModificationTimeStamp; // Zeitstempel für Erstellung
_context.Add(item);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
}
}
else // Update
{
try
{
_context.Update(item);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
}
}
return Json(new { isValid = true, html = Helper.RenderRazorViewToString(this, "_ViewAll", await _dataManager.LoadOrganizationsAsync()) });
}
else
{
var errors = ModelState.SelectMany(x => x.Value.Errors.Select(z => z.Exception));
}
item.Parents.Add(new Organization());
return Json(new { isValid = false, html = Helper.RenderRazorViewToString(this, "AddOrEdit", item) });
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmedAsync(int id)
{
await _context.Organizations
.Where(x => x.ParentId == id)
.ForEachAsync(x => x.ParentId = null); // Parent Ids auf null sezten
var item = await _context.Organizations.FindAsync(id);
_context.Organizations.Remove(item);
await _context.SaveChangesAsync();
return Json(new { html = Helper.RenderRazorViewToString(this, "_ViewAll", await _dataManager.LoadOrganizationsAsync()) });
}
}
}

View File

@@ -10,6 +10,8 @@ namespace FSI.BT.IR.Plc.Settings.Log.Data
{
}
public DbSet<Models.Organization> Organizations { get; set; }
public DbSet<Models.Plc> Plcs { get; set; }
public DbSet<Models.Parameter> Parameters { get; set; }

View File

@@ -0,0 +1,76 @@
using FSI.BT.IR.Plc.Settings.Log.Data;
using FSI.BT.IR.Plc.Settings.Log.Models;
using Microsoft.EntityFrameworkCore;
namespace FSI.BT.IR.Plc.Settings.Log
{
public class DataManager
{
private readonly ApplicationDbContext _context;
public DataManager(ApplicationDbContext context)
{
_context = context;
}
private ApplicationDbContext Context { get { return _context; } }
#region Organization
public async Task<List<Organization>> LoadOrganizationsAsync()
{
await UpdateOrganizationFullShortNameAsync(await _context.Organizations.ToListAsync()); // Kurznamen aktualisieren
var task = Task.Factory.StartNew(() =>
{
return _context.Organizations.Include(x => x.Parent).ToList();
});
var result = await task;
return result;
}
public async Task UpdateOrganizationFullShortNameAsync(List<Organization> organizations)
{
foreach (var organization in organizations)
{
foreach (var item in organizations)
{
item.FullShortName = GetOrganizationFullShortName(organizations, item.ParentId, item.ShortName);
_context.Update(item);
}
}
await _context.SaveChangesAsync();
}
public string GetOrganizationFullShortName(List<Organization> items, int? parentId, string? name)
{
foreach (var item in items)
{
if (item.Id == parentId)
{
if (item.ParentId.HasValue)
{
return GetOrganizationFullShortName(items, item.ParentId.Value, item.ShortName + " " + name);
}
else
{
return item.ShortName + name + " ";
}
}
}
return name;
}
#endregion
}
}

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
@@ -12,6 +12,7 @@
<Compile Include="..\..\worker\FSI.BT.IR.Plc.Settings.Log\Models\Logging.cs" Link="Models\Logging.cs" />
<Compile Include="..\..\worker\FSI.BT.IR.Plc.Settings.Log\Models\Parameter.cs" Link="Models\Parameter.cs" />
<Compile Include="..\..\worker\FSI.BT.IR.Plc.Settings.Log\Models\Plc.cs" Link="Models\Plc.cs" />
<Compile Include="..\..\worker\FSI.BT.IR.Plc.Settings.Log\Models\Organization.cs" Link="Models\Plc.cs" />
</ItemGroup>
<ItemGroup>
@@ -26,4 +27,8 @@
</PackageReference>
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\lib\datatable\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc;
namespace FSI.BT.IR.Plc.Settings.Log
{
public class Helper
{
public static string RenderRazorViewToString(Controller controller, string viewName, object model = null)
{
controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
IViewEngine viewEngine = controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
ViewEngineResult viewResult = viewEngine.FindView(controller.ControllerContext, viewName, false);
ViewContext viewContext = new ViewContext(
controller.ControllerContext,
viewResult.View,
controller.ViewData,
controller.TempData,
sw,
new HtmlHelperOptions()
);
viewResult.View.RenderAsync(viewContext);
return sw.GetStringBuilder().ToString();
}
}
}
}

View File

@@ -0,0 +1,54 @@
@{
Layout = null;
}
@model Organization
<div class="row">
<form asp-action="AddOrEdit" asp-route-id="@Model.Id" onsubmit="return jQueryAjaxPost(this);">
<input hidden asp-for="Id" class="form-control" />
<input hidden asp-for="FullShortName" class="form-control" />
<input hidden asp-for="CreationTimeStamp" class="form-control" />
<input hidden asp-for="ModificationTimeStamp" class="form-control" />
<div class="form-group">
<label asp-for="ShortName" class="control-label"></label>
<input asp-for="ShortName" class="form-control" id="ctrlToFocus" />
<span asp-validation-for="ShortName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Type" class="control-label"></label>
<select asp-for="Type" asp-items="Html.GetEnumSelectList<FSI.BT.IR.Plc.Settings.Log.Models.OrganizationType>()" class="form-control"></select>
<span asp-validation-for="Type" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ParentId" class="control-label"></label>
<select asp-for="ParentId" asp-items="@(new SelectList(from x in Model.Parents orderby x.ShortName select new { Value= x.Id, Text = x.FullShortName + " - " + x.Name} , "Value", "Text"))" class="form-control"></select>
</div>
<hr />
<div class="form-group">
<input type="submit" value="Submit" class="btn btn-primary btn-block" />
</div>
</form>
</div>

View File

@@ -0,0 +1,15 @@
@model IEnumerable<Organization>
@{
ViewData["Title"] = "Organisation";
}
<h1>@ViewData["Title"]</h1>
<hr />
<script type="text/javascript" language="javascript" src="~/lib/jquery/dist/jquery.min.js"></script>
<div id="view-all">
@await Html.PartialAsync("_ViewAll", Model)
</div>

View File

@@ -0,0 +1,147 @@
@model IEnumerable<Organization>
<table id="dtMain" class="display" style="width:100%">
<thead>
<tr>
<th>
@Html.DisplayNameFor(x => x.GetEnumerator().Current.FullShortName)
</th>
<th>
@Html.DisplayNameFor(x => x.GetEnumerator().Current.ShortName)
</th>
<th>
@Html.DisplayNameFor(x => x.GetEnumerator().Current.Name)
</th>
<th>
@Html.DisplayNameFor(x => x.GetEnumerator().Current.Description)
</th>
<th>
@Html.DisplayNameFor(x => x.GetEnumerator().Current.Type)
</th>
<th>
@Html.DisplayNameFor(x => x.GetEnumerator().Current.ParentId)
</th>
<th>
Bearbeitung
</th>
</tr>
</thead>
<tbody>
@{
foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => @item.FullShortName)
</td>
<td>
@Html.DisplayFor(modelItem => item.ShortName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@(string.IsNullOrEmpty(item.Description) ? "-" : @Html.DisplayFor(modelItem => item.Description))
</td>
<td>
@Html.DisplayFor(modelItem => @item.Type)
</td>
<td>
@Html.DisplayFor(modelItem => @item.Parent.Name) @(item.Parent == null ? "" : "(")@Html.DisplayFor(modelItem => @item.Parent.ShortName)@(item.Parent == null ? "" : ")")
</td>
<td>
<div class="btn-group" style="flex-direction:row">
<!-- bearbeiten -->
<a onclick="showInPopup('@Url.Action("AddOrEdit", "Organization",new {id = item.Id}, Context.Request.Scheme)','Organisation bearbeiten')" class="btn btn-success text-white">
<i class="bi bi-pencil-square"></i>
</a>
<!-- löschen -->
<form asp-action="Delete" asp-route-id="@item.Id" onsubmit="return jQueryAjaxDelete(this)" class="d-inline">
<button type="submit" value="bi bi-trash" class="btn btn-danger text-white">
<i class="bi bi-trash"></i>
</button>
</form>
</div>
</td>
</tr>
}
}
</tbody>
</table>
<script type="text/javascript">
$(document).ready(function () {
$("#dtMain").DataTable({
dom: "Blfrtip",
buttons: [
{
text: "<i class='bi bi-plus-square'></i> Neu",
className: "btn-dark",
key: {
shiftKey: true,
key: 'n'
},
action: function (e, dt, node, conf) {
showInPopup("@Url.Action("AddOrEdit", "Organization", new {id = 0}, Context.Request.Scheme)", "neue Organisation erstellen");
},
},
{
extend: "spacer",
},
{
extend: "spacer",
},
"searchBuilder",
{
extend: "collection",
text: "Export",
autoClose: true,
buttons: [
{
extend: "copyHtml5",
text: "<i class='bi bi-copy'></i> kopieren",
titleAttr: "Copy"
},
{
extend: "excelHtml5",
autoFilter: true,
text: "<i class='bi bi-file-earmark-excel'></i> Excel",
titleAttr: "Excel"
},
{
extend: "csvHtml5",
text: "<i class='bi bi-filetype-csv'></i> csv-Datei",
titleAttr: "CSV"
},
{
extend: "pdfHtml5",
text: "<i class='bi bi-file-earmark-pdf'> Pdf</i>",
titleAttr: "PDF"
},
]
},
{
extend: "colvis",
collectionLayout: "fixed columns",
collectionTitle: "Column visibility control"
},
{
extend: "spacer",
},
],
lengthMenu: [
[10, 25, 50, -1],
[10, 25, 50, 'All']
]
});
});
</script>

View File

@@ -7,6 +7,10 @@
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/FSI.BT.IR.Plc.Settings.Log.styles.css" asp-append-version="true" />
<link href="~/lib/datatable/datatables.css" rel="stylesheet" />
<link href="~/lib/datatable/datatables.min.css" rel="stylesheet" />
</head>
<body>
<header>
@@ -25,6 +29,9 @@
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Organization" asp-action="Index">Home</a>
</li>
</ul>
<partial name="_LoginPartial" />
</div>
@@ -37,6 +44,19 @@
</main>
</div>
<div class="modal" tabindex="-1" role="dialog" id="form-modal" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
</div>
</div>
</div>
</div>
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2024 - FSI.BT.IR.Plc.Settings.Log - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
@@ -45,6 +65,10 @@
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script src="~/lib/datatable/datatables.min.js"></script>
<script src="~/lib/datatable/datatables.js"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>

View File

@@ -2,3 +2,106 @@
// for details on configuring this project to bundle and minify static web assets.
// Write your JavaScript code.
// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
// for details on configuring this project to bundle and minify static web assets.
// Write your JavaScript code.
showInPopup = (url, title) => {
$.ajax({
type: "GET",
url: url,
success: function (res) {
$("#form-modal .modal-body").html(res);
$("#form-modal .modal-title").html(title);
$("#form-modal").modal("show");
}
})
$(document).on("shown.bs.modal", "#form-modal", function () {
$("#ctrlToFocus").focus();
});
}
jQueryAjaxPost = form => {
try {
$.ajax({
type: 'POST',
url: form.action,
data: new FormData(form),
contentType: false,
processData: false,
success: function (res) {
if (res.isValid) {
$("#form-modal .modal-body").html('');
$("#form-modal .modal-title").html('');
$("#form-modal").modal("hide");
$("#view-all").serialize();
$("#view-all").html(res.html);
$("example").DataTable().ajax.reload();
}
else
$("#form-modal .modal-body").html(res.html);
},
error: function (err) {
console.log(err)
}
})
//to prevent default form submit event
return false;
} catch (ex) {
console.log(ex)
}
}
jQueryAjaxDelete = form => {
if (confirm('Soll der Datensatz gelöscht werden?')) {
try {
$.ajax({
type: 'POST',
url: form.action,
data: new FormData(form),
contentType: false,
processData: false,
success: function (res) {
$('#view-all').html(res.html);
},
error: function (err) {
console.log(err)
}
})
} catch (ex) {
console.log(ex)
}
}
//prevent default form submit event
return false;
}
jQueryAjaxUpdate = form => {
try {
$.ajax({
type: 'POST',
url: form.action,
data: new FormData(form),
contentType: false,
processData: false,
success: function (res) {
$('#view-all').html(res.html);
},
error: function (err) {
console.log(err)
}
})
} catch (ex) {
console.log(ex)
}
//prevent default form submit event
return false;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long