Breadcrumb

This commit is contained in:
2026-01-30 16:05:12 +01:00
parent 1443740c4e
commit 1a07542233
8 changed files with 177 additions and 34 deletions

View File

@ -1,15 +1,18 @@
@page "/anagrafiche"
@using Microsoft.EntityFrameworkCore
@using TecniStamp.Components.Widget
@using TecniStamp.Domain
@using TecniStamp.Model.Common
@using TecniStamp.Utils
<Breadcrumb Items="BreadcrumbList" />
<main role="main">
<div class="container-fluid h-100 mt-10">
<div class="row justify-content-start">
@foreach (var item in TileList)
{
<HomeTile Text="@item.Nome" Icon="@item.Icona" Url="@item.Url" Blank="@item.Blank" />
<HomeTile Model="@item" />
}
</div>
</div>
@ -17,23 +20,41 @@
@code {
public List<Sezione> TileList { get; set; } = new();
public List<TileViewModel> TileList { get; set; } = new();
public List<BreadcrumbViewModel> BreadcrumbList { get; set; } = new();
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
var roleId = await MembershipUtils.GetRoleId(_auth);
var parentSection = await _managerService.SezioneService.RicercaPer(x => x.Nome == "Anagrafiche");
var subSection = (await _managerService.SezioneService.RicercaQueryable(x => x.ParentId == parentSection.Id))
.Select(x => x.Id);
var permissionList = (await _managerService.PermissionService.RicercaQueryable(
x => x.RuoloId == roleId && subSection.Contains(x.Feature.Sezione.Id),
includi: x => x.Include(y => y.Feature).ThenInclude(z => z.Sezione),
ordinamento: x => x.OrderBy(y => y.Feature.Sezione.Ordinamento)));
var parentSection = await _managerService.SezioneService
.RicercaPer(x => x.Nome == "Anagrafiche");
var subSectionIds = await (await _managerService.SezioneService
.RicercaQueryable(x => x.ParentId == parentSection.Id))
.Select(x => x.Id)
.ToListAsync();
var permissionList = await (await _managerService.PermissionService
.RicercaQueryable(
x => x.RuoloId == roleId &&
subSectionIds.Contains(x.Feature.Sezione.Id),
includi: x => x
.Include(y => y.Feature)
.ThenInclude(z => z.Sezione)
))
.ToListAsync();
TileList = permissionList
.Select(x => x.Feature.Sezione).Distinct().ToList();
.Select(x => x.Feature.Sezione)
.DistinctBy(x => x.Id)
.OrderBy(x => x.Ordinamento)
.Select(x => new TileViewModel(x))
.ToList();
BreadcrumbList = BreadcrumbUtils.BuildBreadcrumb(parentSection);
}
}

View File

@ -0,0 +1,7 @@
@page "/anagrafiche/ruoli"
@code {
}

View File

@ -4,40 +4,51 @@
@using Microsoft.AspNetCore.Authorization
@using Microsoft.EntityFrameworkCore
@using TecniStamp.Components.Widget
@using TecniStamp.Domain
@using TecniStamp.Model.Common
@using TecniStamp.Utils
<div class="card bg-primary-lt position-fixed w-100 rounded-0 shadow-sm" style="top: 58px; left:0; z-index: 100;">
<div class="card-body py-2">
<ol class="breadcrumb breadcrumb-arrows ">
</ol>
</div>
</div>
<Breadcrumb Items="BreadcrumbList" />
<main role="main">
<div class="container-fluid h-100 mt-10">
<div class="row justify-content-start">
@foreach (var item in TileList)
{
<HomeTile Text="@item.Nome" Icon="@item.Icona" Url="@item.Url" Blank="@item.Blank" />
<HomeTile Model="item" />
}
</div>
</div>
</main>
@code {
public List<Sezione> TileList { get; set; } = new();
public List<TileViewModel> TileList { get; set; } = new();
public List<BreadcrumbViewModel> BreadcrumbList { get; set; } = new();
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
var roleId = await MembershipUtils.GetRoleId(_auth);
TileList = (await _managerService.PermissionService.RicercaQueryable(
var sezioniList = await (await _managerService.PermissionService
.RicercaQueryable(
x => x.RuoloId == roleId &&
(x.Feature.Sezione.ParentId == null || x.Feature.Sezione.Parent.ParentId == null),
includi:x => x.Include(y => y.Feature).ThenInclude(z => z.Sezione),
ordinamento:x => x.OrderBy(y => y.Feature.Sezione.Ordinamento)))
.Select(x => x.Feature.Sezione.Parent ?? x.Feature.Sezione).Distinct().ToList();
(x.Feature.Sezione.ParentId == null ||
x.Feature.Sezione.Parent.ParentId == null),
includi: x => x
.Include(y => y.Feature)
.ThenInclude(z => z.Sezione)
.ThenInclude(s => s.Parent)
))
.ToListAsync();
TileList = sezioniList
.Select(x => x.Feature.Sezione.Parent ?? x.Feature.Sezione)
.DistinctBy(x => x.Id)
.OrderBy(x => x.Ordinamento)
.Select(x => new TileViewModel(x))
.ToList();
BreadcrumbList = BreadcrumbUtils.BuildBreadcrumb(null);
}
}

View File

@ -0,0 +1,26 @@
@using TecniStamp.Model.Common
<div class="card bg-primary-lt position-fixed w-100 rounded-0 shadow-sm" style="top: 58px; left:0; z-index: 100;">
<div class="card-body py-2">
<ol class="breadcrumb breadcrumb-arrows">
@foreach (var item in Items)
{
if (item.IsActive)
{
<li class="breadcrumb-item active" aria-current="page">
@item.Text
</li>
}
else
{
<li class="breadcrumb-item">
<a href="@item.Url">@item.Text</a>
</li>
}
}
</ol>
</div>
</div>
@code {
[Parameter, EditorRequired]
public IReadOnlyList<BreadcrumbViewModel> Items { get; set; } = [];
}

View File

@ -1,20 +1,18 @@
<div class="col-md-3 col-sm-6 col-12 mb-4">
@using TecniStamp.Model.Common
<div class="col-md-3 col-sm-6 col-12 mb-4">
<div class="card cards custom-card card-link py-4 shadow-sm border-2 rounded-3 hover-effect position-relative">
<a class="stretched-link text-decoration-none text-dark" href="@Url" @(Blank ? "target=\"_blank\"" : "") ></a>
<a class="stretched-link text-decoration-none text-dark" href="@Model.Url" @(Model.Blank ? "target=\"_blank\"" : "") ></a>
<div class="card-body">
<h1 class="text-center mb-2">
<i class="@Icon" style="font-size:65px;"></i>
<i class="@Model.Icon" style="font-size:65px;"></i>
</h1>
<h1 class="mb-0 text-center">
@Text
@Model.Text
</h1>
</div>
</div>
</div>
@code {
[Parameter] public string Url { get; set; }
[Parameter] public bool Blank { get; set; } = false;
[Parameter] public string Icon { get; set; }
[Parameter] public string Text { get; set; }
[Parameter] public TileViewModel Model { get; set; } = new();
}

View File

@ -0,0 +1,8 @@
namespace TecniStamp.Model.Common;
public class BreadcrumbViewModel
{
public string Text { get; set; }
public string? Url { get; set; }
public bool IsActive { get; set; }
}

View File

@ -0,0 +1,27 @@
using TecniStamp.Domain;
namespace TecniStamp.Model.Common;
public class TileViewModel
{
public Guid Id { get; set; }
public string Url { get; set; }
public bool Blank { get; set; } = false;
public string Icon { get; set; }
public string Text { get; set; }
public int Ordinamento { get; set; }
public TileViewModel()
{
}
public TileViewModel(Sezione model)
{
Id = model.Id;
Url = model.Url;
Blank = model.Blank;
Icon = model.Icona;
Text = model.Nome;
}
}

View File

@ -0,0 +1,45 @@
using TecniStamp.Domain;
using TecniStamp.Model.Common;
namespace TecniStamp.Utils;
public static class BreadcrumbUtils
{
public static List<BreadcrumbViewModel> BuildBreadcrumb(Sezione sezione)
{
var stack = new Stack<Sezione>();
var current = sezione;
while (current != null)
{
stack.Push(current);
current = current.Parent;
}
var breadcrumb = new List<BreadcrumbViewModel>
{
new()
{
Text = "Home",
Url = "/",
IsActive = false
}
};
while (stack.Any())
{
var s = stack.Pop();
breadcrumb.Add(new BreadcrumbViewModel
{
Text = s.Nome,
Url = s.Url,
IsActive = false
});
}
breadcrumb.Last().IsActive = true;
breadcrumb.Last().Url = null;
return breadcrumb;
}
}