leandro 0639685c79
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (pull_request) Successful in 9m3s
feat(ui): Optimizacion de componentes con agente
2026-06-09 00:59:58 -03:00

407 lines
16 KiB
Plaintext

@if( Data is not null && Data.Any())
{
<div class="container">
<div class="row">
<!-- TITULO TABLA-->
<div class="col-md-10">
@if (ShowQuickSearch)
{
<div class="row mb-3">
<div class="col-md-6">
<InputText type="text" class="form-control" placeholder="Búsqueda rápida..." @bind-Value="SearchTerm"/>
</div>
</div>
}
</div>
<!-- CONTROLES DE PAGINACION-->
<div class="col-md-2">
@if (ShowPageButtons)
{
<nav aria-label="Page Navigation">
<ul class="pagination justify-content-end">
<li class="page-item @(CurrentPage == 1 ? "disabled" : "")">
<a class="page-link" href="#" tabindex="-1" @onclick:preventDefault @onclick="GoToPreviousPage">Anterior</a>
</li>
@if(TotalPages<=10)
{
@for (int i = 1; i <=TotalPages; i++ )
{
int pageNumber = i;
<li class="page-item @(i==CurrentPage ? "active" : "")">
<a class="page-link" href="#" @onclick:preventDefault @onclick="(()=>ChangePage(pageNumber))">@i</a>
</li>
}
}
else
{
int maxVIsiblePages = 4;
int startPage = Math.Max(1, CurrentPage - maxVIsiblePages / 2);
int endPage = Math.Min(TotalPages, startPage + maxVIsiblePages - 1);
if (CurrentPage > maxVIsiblePages / 2)
{
<li class="page-item">
<a class="page-link" href="#" @onclick:preventDefault @onclick="(()=>ChangePage(1))">1</a>
</li>
<li class="page-item disabled">
<span class="page-link">...</span>
</li>
}
@for (int i = startPage; i<=endPage; i++)
{
int pageNumber = i;
<li class="page-item @(i==CurrentPage ? "active" : "")">
<a class="page-link" href="#" @onclick:preventDefault @onclick="(()=>ChangePage(pageNumber))">@i</a>
</li>
}
if (endPage<TotalPages)
{
<li class="page-item disabled">
<span class="page-link">...</span>
</li>
<li class="page-item">
<a class="page-link" href="#" @onclick:preventDefault @onclick="(()=>ChangePage(TotalPages))">@TotalPages</a>
</li>
}
}
<li class="page-item @(CurrentPage == TotalPages ? "disabled" : "")">
<a class="page-link" href="#" @onclick:preventDefault @onclick="GoToNextPage">Siguiente</a>
</li>
</ul>
</nav>
}
</div>
</div>
</div>
<!-- RENDERIZACION DE TABLA-->
<table class="table table-sm table-hover">
<!-- RENDERIZAR ENCABEZADOS-->
<thead>
<tr>
<!-- RENDERIZAR ENCABEZADO DE COLUMNA TIPO SELECT-->
@if (RenderSelect)
{
<th class="ph-header">
<input type="checkbox" @bind="SelectAll" @onclick="ToggleSelectAll" />
</th>
}
<!-- RENDERIZAR ENCABEZADOS DE COLUMNA TIPO DATOS-->
@foreach (var column in Columns)
{
if (!column.Contains("Hide:"))
{
<th @onclick="()=>SortbyColumn(column)" style="cursor:pointer;user-select:none;" class="ph-header">
@column
@if (column==SortedColumn)
{
<span>@(new MarkupString(GetSortIcon(column)))</span>
}
</th>
}
}
<!-- RENDERIZAR ENCABEZADO DE COLUMNA TIPO BUTTON-->
@if (RenderButtons)
{
<th style="cursor:default; user-select:none;" class="ph-header">Acciones</th>
}
</tr>
</thead>
<!-- RENDERIZACION DE DATOS-->
<tbody>
<!-- RENDERIZAR DATOS POR PAGINA-->
@foreach (var item in PaginatedData)
{
<tr>
<!-- RENDERIZAR COLUMNA DE SELECCION-->
@if (RenderSelect)
{
<td>
@{
string rowId = string.Empty;
if (item.TryGetValue(SelectionField, out var idObj) && idObj is not null)
{
rowId = idObj.ToString() ?? string.Empty;
}
}
<input type="checkbox" checked="@SelectedRowIndexes.Contains(rowId)" @onclick="() => ToggleRowSelection(rowId)" />
</td>
}
<!-- RENDERIZAR COLUMNAS DE DATOS-->
@foreach (var column in Columns)
{
<!-- RENDERIZAR COLUMNA DE DESCARGA-->
if(column.Contains("Descarga:"))
{
@* <td>
@if (!string.IsNullOrEmpty(item[column]?.ToString()))
{
@foreach (var link in item[column].ToString().Split('|'))
{
<a href="@link" download><span class="oi oi-file largertext" aria-hidden="true"></span></a>
}
}
else
{
<span class="oi oi-file glowinfo" aria-hidden="true">&nbsp;Sin Archivos</span>
}
</td>
*@
}
<!-- NO RENDERIZAR COLUMNA OCULTA-->
else if (column.Contains("Hide:"))
{
}
<!-- RENDERIZAR COLUMNA DE DATOS ESTANDAR-->
else
{
<td>@item[column]</td>
}
}
<!-- RENDERIZAR COLUMNA DE BOTONES-->
@if (RenderButtons)
{
<td>
@foreach (var button in Buttons)
{
<!-- RENDERIZAR BOTON TIPO HREF-->
string cUrlAction = string.Empty;
@if (!string.IsNullOrEmpty(button.UrlAction))
{
cUrlAction = button.UrlAction;
@if (!string.IsNullOrEmpty(SelectionField))
{
cUrlAction = @button.UrlAction + item[SelectionField].ToString();
}
}
<!-- RENDERIZAR BOTON TIPO ONCLICK-->
@if (button.OnClickAction is not null)
{
@* <a class="@button.ElementClass" @onclick="async () => button?.OnClickAction(item[SelectionField].ToString())" style="zoom:@button.ElementZoom">@button.Caption</a>
*@
@if (item[SelectionField] != null)
{
<a class="@button.ElementClass"
@onclick='async () => button?.OnClickAction(item[SelectionField]?.ToString() ?? "")'
style="zoom:@button.ElementZoom">
@((MarkupString)button.Caption)
</a>
}
}
else
{
<a class="@button.ElementClass" href="@cUrlAction" style="zoom:@button.ElementZoom">@button.Caption</a>
}
}
</td>
}
</tr>
}
</tbody>
</table>
}
@code {
#region Parameters
[Parameter]
public List<string> Columns { get; set; } = new List<string>();
[Parameter]
public List<Dictionary<string, object>> Data { get; set; } = new List<Dictionary<string, object>>();
[Parameter]
public bool ShowQuickSearch { get; set; } = true;
[Parameter]
public bool RenderButtons { get; set; } = false;
[Parameter]
public List<ButtonOptions> Buttons { get; set; } = new List<ButtonOptions>();
[Parameter]
public bool RenderSelect {get;set;} =false;
[Parameter]
public List<string> SorteableCols { get; set; } = new List<string>();
[Parameter]
public int RowsPerPage { get; set; } = 10;
[Parameter]
public bool ShowPageButtons { get; set; } = true;
[Parameter]
public string SelectionField { get; set; } = string.Empty;
[Parameter]
public string TableTitle { get; set; } = string.Empty;
// [Parameter]
// public string HeaderColorScheme { get; set; } = "#f7f7f7";
#endregion
#region Declarations
private string SearchTerm { get; set; } = string.Empty;
private int CurrentPage { get; set; } = 1;
private int TotalPages => (int)Math.Ceiling((double)Data.Count/RowsPerPage);
public string SortedColumn { get; set; } = null!;
public bool SortDirection { get; set; }
public bool SelectAll { get; set; } = false;
public Dictionary<string, bool> SortDirections { get; set; } = new Dictionary<string, bool>();
private List<Dictionary<string, object>> PaginatedData { get; set; } = new List<Dictionary<string, object>>();
private HashSet<string> SelectedRowIndexes = new HashSet<string>();
private List<Dictionary<string, object>> SelectRows => GetSelectedRows();
public event Action<List<Dictionary<string, object>>>? OnGetSelectedRows;
#endregion
#region Sort Procedures
private void SortbyColumn(string column)
{
if (SorteableCols.Contains(column))
{
if (SortedColumn == column)
{
SortDirection = !SortDirection;
}
else
{
SortedColumn = column;
SortDirection = true;
}
if (SortDirections.ContainsKey(column))
{
SortDirections[column] = !SortDirections[column];
}
else
{
SortDirections[column] = true;
}
if (SortDirections[column])
{
PaginatedData = PaginatedData.OrderBy(_ => _[column]).ToList();
}
else
{
PaginatedData = PaginatedData.OrderByDescending(_ => _[column]).ToList();
}
}
}
private string GetSortIcon(string column)
{
if (SortDirections.ContainsKey(column) && column == SortedColumn)
{
if (SortDirection)
{
return "&#8593";
}
else
{
return "&#8595";
}
}
return string.Empty;
}
#endregion
#region Selection Procedures
private void ToggleSelectAll()
{
SelectAll = !SelectAll;
if (SelectAll)
{
foreach (var item in Data)
{
if (item.TryGetValue(SelectionField, out var idObj) && idObj is not null)
{
var rowId = idObj.ToString();
if (rowId is not null && !SelectedRowIndexes.Contains(rowId))
{
SelectedRowIndexes.Add(rowId);
}
}
}
}
else
{
SelectedRowIndexes.Clear();
}
OnGetSelectedRows?.Invoke(GetSelectedRows());
}
private List<Dictionary<string, object>> GetSelectedRows()
{
List<Dictionary<string, object>> selectedRows = new List<Dictionary<string, object>>();
foreach (var item in Data)
{
string? rowId = item[SelectionField]?.ToString(); // Usa el operador null-conditional
if (rowId != null && SelectedRowIndexes.Contains(rowId))
{
selectedRows.Add(item);
}
}
return selectedRows;
}
private void ToggleRowSelection (string rowIndex)
{
if (SelectedRowIndexes.Contains(rowIndex))
{
SelectedRowIndexes.Remove(rowIndex);
}
else
{
SelectedRowIndexes.Add(rowIndex);
}
OnGetSelectedRows?.Invoke(GetSelectedRows());
}
#endregion
#region Pagination Procedures
protected override void OnParametersSet()
{
PaginateData();
}
private void PaginateData()
{
IEnumerable<Dictionary<string, object>> source = Data ?? Enumerable.Empty<Dictionary<string, object>>();
if (!string.IsNullOrWhiteSpace(SearchTerm) && Columns?.Count > 0)
{
var term = SearchTerm;
source = source.Where(row => Columns.Any(col => {
if (!row.TryGetValue(col, out var val) || val is null) return false;
return val.ToString().IndexOf(term, StringComparison.OrdinalIgnoreCase) >= 0;
}));
}
if (!string.IsNullOrEmpty(SortedColumn))
{
bool asc = SortDirections.ContainsKey(SortedColumn) ? SortDirections[SortedColumn] : true;
source = asc ? source.OrderBy(_ => _[SortedColumn]) : source.OrderByDescending(_ => _[SortedColumn]);
}
int startIndex = (CurrentPage - 1) * RowsPerPage;
PaginatedData = source.Skip(startIndex).Take(RowsPerPage).ToList();
}
private void ChangePage(int pageNumber)
{
CurrentPage = pageNumber;
PaginateData();
}
private void GoToNextPage()
{
if (CurrentPage < TotalPages)
{
CurrentPage++;
PaginateData();
}
}
private void GoToPreviousPage()
{
if (CurrentPage > 1)
{
CurrentPage--;
PaginateData();
}
}
#endregion
#region Elements Configuration
public class ButtonOptions
{
public string Caption { get; set; } = string.Empty;
public string UrlAction { get; set; } = string.Empty;
public string ElementClass { get; set; } = string.Empty;
public string ElementZoom { get; set; } = "100%";
public Func<string, Task> OnClickAction { get; set; } = _ => Task.CompletedTask;
}
#endregion
public void UpdateSearchTerm()
{
CurrentPage = 1; // Resetear la página a 1 al cambiar el término de búsqueda
PaginateData(); // Volver a paginar los datos con el nuevo término de búsqueda
StateHasChanged(); // Forzar la actualización de la interfaz de usuario
}
}