All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 6m50s
384 lines
15 KiB
Plaintext
384 lines
15 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.Where(row => string.IsNullOrWhiteSpace(SearchTerm) || Columns.Any(col => row[col]?.ToString()?.IndexOf(SearchTerm, StringComparison.OrdinalIgnoreCase) >= 0)))
|
|
{
|
|
int index = PaginatedData.IndexOf(item);
|
|
<tr>
|
|
<!-- RENDERIZAR COLUMNA DE SELECCION-->
|
|
@if (RenderSelect)
|
|
{
|
|
<td>
|
|
<input type="checkbox" checked="@SelectedRowIndexes.Contains(item[SelectionField].ToString()??string.Empty)" @onclick="() => ToggleRowSelection(item[SelectionField].ToString()??string.Empty)" />
|
|
</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"> 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">
|
|
@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 List<string> SelectedRowIndexes = new List<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 "↑";
|
|
}
|
|
else
|
|
{
|
|
return "↓";
|
|
}
|
|
}
|
|
return string.Empty;
|
|
}
|
|
#endregion
|
|
#region Selection Procedures
|
|
private void ToggleSelectAll()
|
|
{
|
|
SelectAll = !SelectAll;
|
|
if (SelectAll)
|
|
{
|
|
foreach (var item in Data)
|
|
{
|
|
string? rowId = item[SelectionField]?.ToString();
|
|
if (rowId != 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()
|
|
{
|
|
int startIndex = (CurrentPage - 1) * RowsPerPage;
|
|
PaginatedData = Data.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
|
|
|
|
}
|
|
} |