Sicherung vor Urlaub

This commit is contained in:
Maier Stephan SI
2023-09-29 15:00:54 +02:00
parent ccb6128c72
commit 032b2747b6
14 changed files with 264 additions and 105 deletions

View File

@@ -1,5 +1,6 @@
using FSI.Prj.Mgt.Data;
using FSI.Prj.Mgt.Models;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
@@ -10,6 +11,7 @@ namespace FSI.Prj.Mgt.Controllers
{
public class OrganizationController : Controller
{
private readonly ApplicationDbContext _context;
public OrganizationController(ApplicationDbContext context)
@@ -19,10 +21,8 @@ namespace FSI.Prj.Mgt.Controllers
public async Task<IActionResult> Index(string searchString, int? page)
{
IQueryable<Organization> items = _context.Organizations.Include(x => x.Parent);
if (!string.IsNullOrEmpty(searchString))
{
items = items.Where(x => x.Name!.Contains(searchString) || x.Description!.Contains(searchString));
@@ -33,46 +33,179 @@ namespace FSI.Prj.Mgt.Controllers
List<TreeViewNode> nodes = new();
//////List<TreeViewNode> nodes = new();
// Loop and add the Parent Nodes
foreach (Organization organization in _context.Organizations)
//////// Loop and add the Parent Nodes
//////foreach (Organization organization in _context.Organizations)
//////{
////// if (organization.ParentId == null)
////// {
////// nodes.Add(new TreeViewNode
////// {
////// id = organization.Id.ToString(),
////// parent = "#",
////// text = organization.Name,
////// });
////// }
////// else
////// {
////// nodes.Add(new TreeViewNode
////// {
////// id = organization.Id.ToString(),
////// parent = organization.ParentId.ToString(),
////// text = organization.Name,
////// });
////// }
//////}
//////ViewBag.Json = JsonConvert.SerializeObject(nodes);
}
public async Task<IActionResult> AddOrEdit(int id = 0)
{
if (id == 0)
{
if (organization.ParentId == null)
{
nodes.Add(new TreeViewNode
{
id = organization.Id.ToString(),
parent = "#",
text = organization.Name,
});
}
else
{
nodes.Add(new TreeViewNode
{
id = organization.Id.ToString(),
parent = organization.ParentId.ToString(),
text = organization.Name,
});
}
}
ViewBag.Json = JsonConvert.SerializeObject(nodes);
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)
{
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 IActionResult Index (string selectedItems)
public async Task<IActionResult> AddOrEdit(int id, Organization item)
{
if (selectedItems != null)
{
List<TreeViewNode> items = JsonConvert.DeserializeObject<List<TreeViewNode>>(selectedItems);
}
ModelState.Remove("Parent");
ModelState.Remove("Parents");
ModelState.Remove("FullShortName");
return RedirectToAction("Index", "Organization");
if (ModelState.IsValid)
{
if (item.ParentId == 0)
{
item.ParentId = null;
}
if (id == 0) // Insert
{
_context.Add(item);
await _context.SaveChangesAsync();
}
else // Update
{
try
{
_context.Update(item);
_context.Update(item);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
}
}
return Json(new { isValid = true, html = Helper.RenderRazorViewToString(this, "_ViewAll", await ((IQueryable<Organization>)_context.Organizations).ToPagedListAsync(1, 10)) });
}
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> DeleteConfirmed(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 ((IQueryable<Organization>)_context.Organizations).ToPagedListAsync(1, 10)) });
}
//[HttpPost]
//public IActionResult Index(string selectedItems)
//{
// if (selectedItems != null)
// {
// List<TreeViewNode> items = JsonConvert.DeserializeObject<List<TreeViewNode>>(selectedItems);
// }
// return RedirectToAction("Index", "Organization");
//}
public async void UpdateFullShortName()
{
foreach (var organization in _context.Organizations)
{
foreach (var item in _context.Organizations)
{
item.FullShortName = GetFullShortName(_context.Organizations.ToList(), item.ParentId, item.ShortName);
_context.Update(item);
await _context.SaveChangesAsync();
}
}
}
private string GetFullShortName(List<Organization> items, int? parentId, string? name)
{
foreach (var item in items)
{
if (item.Id == parentId)
{
if (item.ParentId.HasValue)
{
return GetFullShortName(items, item.ParentId.Value, item.ShortName + " " + name);
}
else
{
return item.ShortName + name + " ";
}
}
}
return string.Empty;
}
}

View File

@@ -1,5 +1,6 @@
using FSI.Prj.Mgt.Data;
using FSI.Prj.Mgt.Models;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
@@ -21,7 +22,6 @@ namespace FSI.Prj.Mgt.Controllers
{
IQueryable<Project> items = _context.Projects.Include(x => x.Plant);
if (!string.IsNullOrEmpty(searchString))
{
items = items.Where(x => x.No!.ToString().Contains(searchString) || x.Name!.Contains(searchString) || x.Description!.Contains(searchString));
@@ -33,8 +33,6 @@ namespace FSI.Prj.Mgt.Controllers
public async Task<IActionResult> AddOrEdit(int id = 0)
{
// ViewBag.Plants = _context.Plants;
if (id == 0)
{
var item = new Project();
@@ -46,7 +44,6 @@ namespace FSI.Prj.Mgt.Controllers
{
var item = await _context.Projects.FindAsync(id);
if (item == null)
{
return NotFound();
@@ -58,17 +55,18 @@ namespace FSI.Prj.Mgt.Controllers
}
[HttpPost]
//[ValidateAntiForgeryToken]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddOrEdit(int id, Project item)
{
ModelState.Remove("Plants");
ModelState.Remove("Plant");
ModelState.Remove("Plants");
if (ModelState.IsValid)
{
if (id == 0) // Insert
{
_context.Add(item);
await _context.SaveChangesAsync();
}
@@ -79,17 +77,18 @@ namespace FSI.Prj.Mgt.Controllers
_context.Update(item);
await _context.SaveChangesAsync();
}
catch(DbUpdateConcurrencyException)
catch (DbUpdateConcurrencyException)
{
}
}
return Json(new { isValid = true, html = Helper.RenderRazorViewToString(this, "_ViewAll", _context.Projects.ToList()) });
return Json(new { isValid = true, html = Helper.RenderRazorViewToString(this, "_ViewAll", await ((IQueryable<Project>)_context.Projects).ToPagedListAsync(1, 10)) });
}
else
{
var errors = ModelState.SelectMany(x => x.Value.Errors.Select(z => z.Exception));
}
item.Plants = (_context.Plants.ToList());
return Json(new { isValid = false, html = Helper.RenderRazorViewToString(this, "AddOrEdit", item) });
}

View File

@@ -12,8 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace FSI.Prj.Mgt.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20230928130340_Initial")]
partial class Initial
[Migration("20230929113426_Init")]
partial class Init
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -34,6 +34,9 @@ namespace FSI.Prj.Mgt.Data.Migrations
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("FullShortName")
.IsRequired()
.HasColumnType("nvarchar(max)");
@@ -329,7 +332,7 @@ namespace FSI.Prj.Mgt.Data.Migrations
modelBuilder.Entity("FSI.Prj.Mgt.Models.Organization", b =>
{
b.HasOne("FSI.Prj.Mgt.Models.Organization", "Parent")
.WithMany("Organizations")
.WithMany("Parents")
.HasForeignKey("ParentId");
b.Navigation("Parent");
@@ -404,7 +407,7 @@ namespace FSI.Prj.Mgt.Data.Migrations
modelBuilder.Entity("FSI.Prj.Mgt.Models.Organization", b =>
{
b.Navigation("Organizations");
b.Navigation("Parents");
});
modelBuilder.Entity("FSI.Prj.Mgt.Models.Project", b =>

View File

@@ -5,7 +5,7 @@
namespace FSI.Prj.Mgt.Data.Migrations
{
/// <inheritdoc />
public partial class Initial : Migration
public partial class Init : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
@@ -18,9 +18,10 @@ namespace FSI.Prj.Mgt.Data.Migrations
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
ShortName = table.Column<string>(type: "nvarchar(max)", nullable: false),
Description = table.Column<string>(type: "nvarchar(max)", nullable: false),
Description = table.Column<string>(type: "nvarchar(max)", nullable: true),
ParentId = table.Column<int>(type: "int", nullable: true),
Type = table.Column<int>(type: "int", nullable: false)
Type = table.Column<int>(type: "int", nullable: false),
FullShortName = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{

View File

@@ -31,6 +31,9 @@ namespace FSI.Prj.Mgt.Data.Migrations
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("FullShortName")
.IsRequired()
.HasColumnType("nvarchar(max)");
@@ -326,7 +329,7 @@ namespace FSI.Prj.Mgt.Data.Migrations
modelBuilder.Entity("FSI.Prj.Mgt.Models.Organization", b =>
{
b.HasOne("FSI.Prj.Mgt.Models.Organization", "Parent")
.WithMany("Organizations")
.WithMany("Parents")
.HasForeignKey("ParentId");
b.Navigation("Parent");
@@ -401,7 +404,7 @@ namespace FSI.Prj.Mgt.Data.Migrations
modelBuilder.Entity("FSI.Prj.Mgt.Models.Organization", b =>
{
b.Navigation("Organizations");
b.Navigation("Parents");
});
modelBuilder.Entity("FSI.Prj.Mgt.Models.Project", b =>

View File

@@ -1,4 +1,6 @@
using System.ComponentModel;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.EntityFrameworkCore.Storage;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
@@ -6,30 +8,38 @@ namespace FSI.Prj.Mgt.Models
{
public class Organization
{
public Organization()
{
Parents = new HashSet<Organization>();
}
[Key]
public int Id { get; set; }
[DisplayName("Name")]
[Required(ErrorMessage = "Dieses Feld wird benötigt.")]
[Required(ErrorMessage = "Namen eingeben.")]
public string Name { get; set; }
[DisplayName("Kurzname")]
[Required(ErrorMessage = "Dieses Feld wird benötigt.")]
[Required(ErrorMessage = "Kurznamen eingeben.")]
public string ShortName { get; set; }
[DisplayName("Beschreibung")]
public string Description { get; set; }
public string? Description { get; set; }
[ForeignKey("Id")]
[DisplayName("übergeordnetes Element")]
public int? ParentId { get; set; }
public virtual Organization Parent { get; set; }
public virtual List<Organization> Parents{ get; set; }
public virtual Organization? Parent { get; set; }
public virtual ICollection<Organization> Parents { get; set; }
[DisplayName("Type")]
[Required(ErrorMessage = "Dieses Feld wird benötigt.")]
public OrganizationType Type { get; set; }
[DisplayName("vollständiger Kurzname")]
public virtual string FullShortName { get; set; }
}
public enum OrganizationType

View File

@@ -34,7 +34,6 @@ namespace FSI.Prj.Mgt.Models
[ForeignKey("Id")]
[DisplayName("Anlage, Teilanlage, ...")]
public int? PlantId { get; set; }
public virtual Plant Plant { get; set; }
public virtual ICollection<Plant> Plants { get; set; }

View File

@@ -5,19 +5,16 @@
@model FSI.Prj.Mgt.Models.Organization
<div class="row">
<div asp-validation-summary="All" class="text-danger"></div>
<form asp-action="AddOrEdit" asp-route-id="@Model.Id" onsubmit="return jQueryAjaxPost(this);">
<input hidden asp-for="Id" placeholder="ID" class="form-control" />
<input hidden asp-for="Id" class="form-control" />
<input hidden asp-for="FullShortName" class="form-control" />
<div class="form-group">
<label asp-for="ShortName" class="control-label"></label>
<input asp-for="ShortName" placeholder="Kurzname" class="form-control" />
<input asp-for="ShortName" class="form-control" />
<span asp-validation-for="ShortName" class="text-danger"></span>
</div>
@@ -41,7 +38,7 @@
<div class="form-group">
<label asp-for="ParentId" class="control-label"></label>
<select asp-for="ParentId" asp-items="@(new SelectList(Model.Parents, "Id", "OutSh"))" class="form-control"></select>
<select asp-for="ParentId" asp-items="@(new SelectList(Model.Parents, "Id", "Name"))" class="form-control" ></select>
</div>
<div class="form-group">

View File

@@ -8,7 +8,7 @@
ViewData["Title"] = "Organisationen";
}
<h1> Projekt-Übersicht</h1>
<h1> Organisationen</h1>
<hr />
@@ -41,7 +41,7 @@
@*
@@ -105,3 +105,4 @@
</script>
}
*@

View File

@@ -22,12 +22,15 @@
@Html.DisplayNameFor(x => x.GetEnumerator().Current.Type)
</th>
<th>
@Html.DisplayNameFor(x => x.GetEnumerator().Current.Parent)
@Html.DisplayNameFor(x => x.GetEnumerator().Current.ParentId)
</th>
<th>
<a onclick="showInPopup('@Url.Action("AddOrEdit", "Organization", null, Context.Request.Scheme)','neue Organisation erstellen')" class="btn btn-success text-white">
@Html.DisplayNameFor(x => x.GetEnumerator().Current.FullShortName)
</th>
<th>
<a onclick="showInPopup('@Url.Action("AddOrEdit", "Organization", new {id = 0}, Context.Request.Scheme)','neue Organisation')" class="btn btn-success text-white">
<i class="bi bi-plus-square"></i>
neues Organisation
neue
</a>
</th>
</tr>
@@ -54,16 +57,19 @@
@Html.DisplayFor(modelItem => @item.Type)
</td>
<td>
@Html.DisplayFor(modelItem => @item.Parent.Name) @Html.DisplayFor(modelItem => @item.Parent.ShortName)
@Html.DisplayFor(modelItem => @item.Parent.Name) @(item.Parent == null ? "" : "(")@Html.DisplayFor(modelItem => @item.Parent.ShortName)@(item.Parent == null ? "" : ")")
</td>
<td>
@Html.DisplayFor(modelItem => @item.FullShortName)
</td>
<td>
<div class="btn-group" style="flex-direction:row">
<a onclick="showInPopup('@Url.Action("AddOrEdit", "Project",new {id = item.Id}, Context.Request.Scheme)','Projekt bearbeiten')" class="btn btn-success text-white">
<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>
<a asp-action="Delete" asp-asp-route-id="@item.Id"><i class="bi bi-trash"></i></a>
@* <button class="btn btn-success" onclick="location.href='@Url.Action("CreateEdit", new {@item.Id})'"><i class="bi bi-pencil-square"></i></button>
<button class="btn btn-danger" onclick="location.href='@Url.Action("DeleteProject", new {@item.Id})'"><i class="bi bi-trash"></i></button>*@
<form asp-action="Delete" asp-route-id="@item.Id" onsubmit="return jQueryAjaxDelete(this)" class="d-inline">
<input type="submit" value="Delete" class="btn btn-danger" />
</form>
</div>
</td>
</tr>
@@ -73,17 +79,3 @@
</table>
<nav>
@Html.PagedListPager(Model, page => Url.Action("index", new { page = page }), new PagedListRenderOptions()
{
ActiveLiElementClass = "active",
PageClasses = new[]{ "page-link"},
LiElementClasses=new[] { "page-item" },
UlElementClasses = new[] { "pagination","justify-content-center", "mt-3" },
LinkToNextPageFormat = ">",
LinkToPreviousPageFormat = "<",
DisplayLinkToPreviousPage = PagedListDisplayMode.Always,
DisplayLinkToNextPage = PagedListDisplayMode.Always
})
</nav>

View File

@@ -4,7 +4,6 @@
@model IPagedList<Plant>
<table class="table table-striped table-hover"
data-filter-control="true"
data-show-search-clear-button="true">
@@ -80,4 +79,4 @@
DisplayLinkToPreviousPage = PagedListDisplayMode.Always,
DisplayLinkToNextPage = PagedListDisplayMode.Always
})
</nav> *
</nav>

View File

@@ -5,7 +5,6 @@
@model FSI.Prj.Mgt.Models.Project
<div class="row">
<div asp-validation-summary="All" class="text-danger"></div>
@@ -14,7 +13,6 @@
<input hidden asp-for="Id" placeholder="ID" class="form-control" />
<div class="form-group">
<label asp-for="No" class="control-label"></label>
<input asp-for="No" placeholder="Projekt-Nr." class="form-control" />

View File

@@ -25,7 +25,7 @@
@Html.DisplayNameFor(x => x.GetEnumerator().Current.Status)
</th>
<th>
<a onclick="showInPopup('@Url.Action("AddOrEdit", "Project",null, Context.Request.Scheme)','neues Projekt')" class="btn btn-success text-white">
<a onclick="showInPopup('@Url.Action("AddOrEdit", "Project",null, Context.Request.Scheme)','neu')" class="btn btn-success text-white">
<i class="bi bi-plus-square"></i>
neues Projekt erstellen
</a>

View File

@@ -32,7 +32,6 @@ jQueryAjaxPost = form => {
}
else
$("#form-modal .modal-body").html(res.html);
},
error: function (err) {
console.log(err)
@@ -44,3 +43,28 @@ jQueryAjaxPost = form => {
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;
}