ngx-redi-core 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +16 -0
- package/.vscode/extensions.json +4 -0
- package/.vscode/launch.json +20 -0
- package/.vscode/tasks.json +42 -0
- package/README.md +27 -0
- package/angular.json +136 -0
- package/package.json +42 -0
- package/projects/ngx-redi-core/Helper/index.ts +2 -0
- package/projects/ngx-redi-core/Helper/ng-package.json +6 -0
- package/projects/ngx-redi-core/Helper/public-api.ts +1 -0
- package/projects/ngx-redi-core/Helper/src/helpers/csv.service.spec.ts +16 -0
- package/projects/ngx-redi-core/Helper/src/helpers/csv.service.ts +67 -0
- package/projects/ngx-redi-core/README.md +24 -0
- package/projects/ngx-redi-core/RediTable/index.ts +2 -0
- package/projects/ngx-redi-core/RediTable/ng-package.json +6 -0
- package/projects/ngx-redi-core/RediTable/public-api.ts +9 -0
- package/projects/ngx-redi-core/RediTable/src/models/interfaces/column-definition.ts +14 -0
- package/projects/ngx-redi-core/RediTable/src/models/interfaces/data-table.ts +28 -0
- package/projects/ngx-redi-core/RediTable/src/models/interfaces/row-action.ts +32 -0
- package/projects/ngx-redi-core/RediTable/src/models/types/event-table.type.spec.ts +7 -0
- package/projects/ngx-redi-core/RediTable/src/models/types/event-table.type.ts +3 -0
- package/projects/ngx-redi-core/RediTable/src/modules/redi-table/redi-table.component.css +106 -0
- package/projects/ngx-redi-core/RediTable/src/modules/redi-table/redi-table.component.html +70 -0
- package/projects/ngx-redi-core/RediTable/src/modules/redi-table/redi-table.component.spec.ts +162 -0
- package/projects/ngx-redi-core/RediTable/src/modules/redi-table/redi-table.component.ts +322 -0
- package/projects/ngx-redi-core/RediTable/src/modules/redi-table.module.ts +32 -0
- package/projects/ngx-redi-core/ng-package.json +7 -0
- package/projects/ngx-redi-core/package.json +12 -0
- package/projects/ngx-redi-core/src/lib/ngx-redi-core.component.spec.ts +23 -0
- package/projects/ngx-redi-core/src/lib/ngx-redi-core.component.ts +16 -0
- package/projects/ngx-redi-core/src/lib/ngx-redi-core.service.spec.ts +16 -0
- package/projects/ngx-redi-core/src/lib/ngx-redi-core.service.ts +9 -0
- package/projects/ngx-redi-core/src/public-api.ts +6 -0
- package/projects/ngx-redi-core/tsconfig.lib.json +14 -0
- package/projects/ngx-redi-core/tsconfig.lib.prod.json +10 -0
- package/projects/ngx-redi-core/tsconfig.spec.json +14 -0
- package/projects/ui-ngx-redi-core/src/app/app.component.html +28 -0
- package/projects/ui-ngx-redi-core/src/app/app.component.scss +53 -0
- package/projects/ui-ngx-redi-core/src/app/app.component.spec.ts +29 -0
- package/projects/ui-ngx-redi-core/src/app/app.component.ts +38 -0
- package/projects/ui-ngx-redi-core/src/app/app.config.ts +9 -0
- package/projects/ui-ngx-redi-core/src/app/app.routes.ts +12 -0
- package/projects/ui-ngx-redi-core/src/app/models/interfaces/componetDemo.interface.ts +6 -0
- package/projects/ui-ngx-redi-core/src/app/modules/demo/demo-routing.module.ts +18 -0
- package/projects/ui-ngx-redi-core/src/app/modules/demo/demo.module.ts +14 -0
- package/projects/ui-ngx-redi-core/src/app/modules/demo/redi-grid-demo/redi-grid-demo.component.html +1 -0
- package/projects/ui-ngx-redi-core/src/app/modules/demo/redi-grid-demo/redi-grid-demo.component.scss +0 -0
- package/projects/ui-ngx-redi-core/src/app/modules/demo/redi-grid-demo/redi-grid-demo.component.spec.ts +23 -0
- package/projects/ui-ngx-redi-core/src/app/modules/demo/redi-grid-demo/redi-grid-demo.component.ts +12 -0
- package/projects/ui-ngx-redi-core/src/app/modules/demo/redi-table-demo/redi-table-demo.component.html +2 -0
- package/projects/ui-ngx-redi-core/src/app/modules/demo/redi-table-demo/redi-table-demo.component.scss +0 -0
- package/projects/ui-ngx-redi-core/src/app/modules/demo/redi-table-demo/redi-table-demo.component.spec.ts +23 -0
- package/projects/ui-ngx-redi-core/src/app/modules/demo/redi-table-demo/redi-table-demo.component.ts +13 -0
- package/projects/ui-ngx-redi-core/src/app/services/components.service.spec.ts +16 -0
- package/projects/ui-ngx-redi-core/src/app/services/components.service.ts +22 -0
- package/projects/ui-ngx-redi-core/src/assets/.gitkeep +0 -0
- package/projects/ui-ngx-redi-core/src/assets/images/angular-white-transparent.png +0 -0
- package/projects/ui-ngx-redi-core/src/favicon.ico +0 -0
- package/projects/ui-ngx-redi-core/src/index.html +15 -0
- package/projects/ui-ngx-redi-core/src/main.ts +6 -0
- package/projects/ui-ngx-redi-core/src/styles.scss +16 -0
- package/projects/ui-ngx-redi-core/tsconfig.app.json +14 -0
- package/projects/ui-ngx-redi-core/tsconfig.spec.json +14 -0
- package/tsconfig.json +38 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<!-- Contenedor principal del componente -->
|
|
2
|
+
<div class="container">
|
|
3
|
+
<!-- Filtro de datos para la tabla -->
|
|
4
|
+
<div *ngIf="filtrarDatos">
|
|
5
|
+
<mat-icon class="icon"> search </mat-icon>
|
|
6
|
+
<input #filtroInput placeholder="Filtro" (keyup)="applyFilter(filtroInput.value)" />
|
|
7
|
+
</div>
|
|
8
|
+
<!-- Tabla de datos -->
|
|
9
|
+
<div class="section">
|
|
10
|
+
<table mat-table [dataSource]="dataSource" matSort>
|
|
11
|
+
<caption> RediTableComponent </caption>
|
|
12
|
+
<!-- Contenedor de selección -->
|
|
13
|
+
<ng-container *ngIf="seleccionarFilas" matColumnDef="select">
|
|
14
|
+
<!-- Encabezado de tabla con selección de registros -->
|
|
15
|
+
<th scope="col" mat-header-cell *matHeaderCellDef>
|
|
16
|
+
<!-- controles de selección -->
|
|
17
|
+
<mat-checkbox (change)="$event ? alternarSeleccion() : null"
|
|
18
|
+
[checked]="dataTable.seleccion.hasValue() && todoSeleccionado()"
|
|
19
|
+
[indeterminate]="dataTable.seleccion.hasValue() && !todoSeleccionado()">
|
|
20
|
+
</mat-checkbox>
|
|
21
|
+
</th>
|
|
22
|
+
<!-- Selector de fila -->
|
|
23
|
+
<td mat-cell *matCellDef="let row">
|
|
24
|
+
<mat-checkbox (change)="$event ? dataTable.seleccion.toggle(row) : null"
|
|
25
|
+
[checked]="dataTable.seleccion.isSelected(row)" [aria-label]="validarEtiqueta(row)">
|
|
26
|
+
</mat-checkbox>
|
|
27
|
+
</td>
|
|
28
|
+
</ng-container>
|
|
29
|
+
<!-- Ordenamiento de encabezados -->
|
|
30
|
+
<ng-container>
|
|
31
|
+
<ng-container [matColumnDef]="column.identificador" *ngFor="let column of datosColumna">
|
|
32
|
+
<!-- Definición de encabezado por columna -->
|
|
33
|
+
<th scope="col" mat-header-cell *matHeaderCellDef mat-sort-header
|
|
34
|
+
[attr.disabled]="ordenamientoActivo()">
|
|
35
|
+
{{column.etiqueta ||
|
|
36
|
+
column.identificador}} </th>
|
|
37
|
+
<!-- Creación de identificadores de tabla -->
|
|
38
|
+
<td mat-cell *matCellDef="let element"> {{element[column.identificador]}} </td>
|
|
39
|
+
</ng-container>
|
|
40
|
+
</ng-container>
|
|
41
|
+
<!-- Definición de acciones -->
|
|
42
|
+
<ng-container *ngIf="verAcciones()" matColumnDef="actions" stickyEnd>
|
|
43
|
+
<th scope="col" mat-header-cell *matHeaderCellDef aria-label="row actions"> </th>
|
|
44
|
+
<!-- Definición de acciones por fila -->
|
|
45
|
+
<td mat-cell *matCellDef="let element">
|
|
46
|
+
<!-- Configuración de botones de acción -->
|
|
47
|
+
<button mat-icon-button color="primary" *ngFor="let action of dataTable.acciones"
|
|
48
|
+
(click)="action?.emiter?.emit({target:element,source:dataSource})"
|
|
49
|
+
[disabled]="deshabilitarAccion(action,element)">
|
|
50
|
+
<!-- Icono dinámico de la acción -->
|
|
51
|
+
<mat-icon [ngClass]="deshabilitarAccion(action,element) ? 'disabled-button' : ''">
|
|
52
|
+
{{action.icono || 'apps'}}
|
|
53
|
+
</mat-icon>
|
|
54
|
+
</button>
|
|
55
|
+
</td>
|
|
56
|
+
</ng-container>
|
|
57
|
+
<!-- Definición de columnas -->
|
|
58
|
+
<tr mat-header-row *matHeaderRowDef="columnas; sticky:true"></tr>
|
|
59
|
+
<!-- Estilizados alternado de filas -->
|
|
60
|
+
<tr mat-row *matRowDef="let row; columns: columnas;let rowNum = index" [class.odd]="rowNum%2"
|
|
61
|
+
[class.even]="!(rowNum%2)" (click)="onRowSelect(row)"></tr>
|
|
62
|
+
</table>
|
|
63
|
+
</div>
|
|
64
|
+
<!-- Paginador de datos -->
|
|
65
|
+
<div [ngClass]="paginar ? 'visible' : 'hidden'">
|
|
66
|
+
<!-- Configuración de Paginador -->
|
|
67
|
+
<mat-paginator [pageSizeOptions]="[5,10,20,50,100]" showFirstLastButtons aria-label="Seleccione una pagina">
|
|
68
|
+
</mat-paginator>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { RediTableComponent } from './redi-table.component';
|
|
3
|
+
import { RediTableModule } from '../redi-table.module';
|
|
4
|
+
|
|
5
|
+
import { CUSTOM_ELEMENTS_SCHEMA, Component, SimpleChange } from '@angular/core';
|
|
6
|
+
|
|
7
|
+
import { MatPaginatorModule } from '@angular/material/paginator';
|
|
8
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
9
|
+
import { MatTableModule } from '@angular/material/table';
|
|
10
|
+
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
11
|
+
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
12
|
+
|
|
13
|
+
import { CommonModule } from '@angular/common';
|
|
14
|
+
|
|
15
|
+
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
|
16
|
+
|
|
17
|
+
import { DataTable } from '../../models/interfaces/data-table';
|
|
18
|
+
import { ColumnDefinition } from '../../models/interfaces/column-definition';
|
|
19
|
+
import { RowAction } from '../../models/interfaces/row-action';
|
|
20
|
+
import { SelectionModel } from '@angular/cdk/collections';
|
|
21
|
+
import { MatSort } from '@angular/material/sort';
|
|
22
|
+
|
|
23
|
+
describe('RediTableComponent', () => {
|
|
24
|
+
let component: RediTableComponent<Pais>;
|
|
25
|
+
let fixture: ComponentFixture<RediTableComponent<Pais>>;
|
|
26
|
+
|
|
27
|
+
interface Pais {
|
|
28
|
+
id: string;
|
|
29
|
+
nombre: string;
|
|
30
|
+
iso: string;
|
|
31
|
+
fechaAlta: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
beforeEach(async () => {
|
|
35
|
+
await TestBed.configureTestingModule({
|
|
36
|
+
declarations: [RediTableComponent],
|
|
37
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
38
|
+
imports: [
|
|
39
|
+
CommonModule,
|
|
40
|
+
MatPaginatorModule,
|
|
41
|
+
MatIconModule,
|
|
42
|
+
MatTableModule,
|
|
43
|
+
ScrollingModule,
|
|
44
|
+
MatCheckboxModule,
|
|
45
|
+
BrowserAnimationsModule]
|
|
46
|
+
})
|
|
47
|
+
.compileComponents();
|
|
48
|
+
fixture = TestBed.createComponent(RediTableComponent<Pais>);
|
|
49
|
+
component = fixture.componentInstance;
|
|
50
|
+
component.dataTable = {
|
|
51
|
+
dataSource: [
|
|
52
|
+
{ id: "01", nombre: "México", iso: "MX", fechaAlta: "13/10/2021" } as Pais,
|
|
53
|
+
{ id: "02", nombre: "Estados Unidos", iso: "EU", fechaAlta: "13/10/2021" } as Pais,
|
|
54
|
+
{ id: "03", nombre: "El Salvador", iso: "SV", fechaAlta: "13/10/2021" } as Pais,
|
|
55
|
+
{ id: "04", nombre: "Guatemala", iso: "GT", fechaAlta: "22/10/2021" } as Pais,
|
|
56
|
+
{ id: "05", nombre: "Puerto Rico", iso: "PR", fechaAlta: "15/10/2021" } as Pais,
|
|
57
|
+
{ id: "06", nombre: "República de Cuba", iso: "CU", fechaAlta: "15/10/2021" } as Pais,
|
|
58
|
+
{ id: "07", nombre: "Venezuela", iso: "VE", fechaAlta: "13/10/2021" } as Pais,
|
|
59
|
+
{ id: "08", nombre: "Colombia", iso: "COL", fechaAlta: "22/10/2021" } as Pais,
|
|
60
|
+
{ id: "09", nombre: "Argentina", iso: "ARG", fechaAlta: "15/10/2021" } as Pais,
|
|
61
|
+
{ id: "10", nombre: "Belice", iso: "BZ", fechaAlta: "15/10/2021" } as Pais
|
|
62
|
+
],
|
|
63
|
+
columnas: [{ identificador: 'id', etiqueta: 'ID' } as ColumnDefinition,
|
|
64
|
+
{ identificador: 'nombre', etiqueta: 'Nombre' } as ColumnDefinition,
|
|
65
|
+
{ identificador: 'iso', etiqueta: 'ISO' } as ColumnDefinition,
|
|
66
|
+
{ identificador: 'fechaAlta', etiqueta: 'Fecha de alta' } as ColumnDefinition],
|
|
67
|
+
acciones: [
|
|
68
|
+
{
|
|
69
|
+
icono: 'delete_outline',
|
|
70
|
+
accion: (itemRow, dataSource) => {
|
|
71
|
+
dataSource?.data.splice(dataSource?.data.indexOf(itemRow), 1);
|
|
72
|
+
dataSource?._updateChangeSubscription()
|
|
73
|
+
}
|
|
74
|
+
} as RowAction,
|
|
75
|
+
{
|
|
76
|
+
icono: 'edit',
|
|
77
|
+
accion: (itemRow, dataSource) => {
|
|
78
|
+
console.log(dataSource)
|
|
79
|
+
}
|
|
80
|
+
} as RowAction],
|
|
81
|
+
seleccion: new SelectionModel<Pais>(true, [])
|
|
82
|
+
} as DataTable<Pais>;
|
|
83
|
+
fixture.detectChanges();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should create', () => {
|
|
87
|
+
expect(component).toBeTruthy();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('cambio de estados', () => {
|
|
91
|
+
component.paginar = true;
|
|
92
|
+
component.ngOnChanges({ paginar: new SimpleChange(false, component.paginar, true) });
|
|
93
|
+
fixture.detectChanges();
|
|
94
|
+
|
|
95
|
+
component.filtrarDatos = true;
|
|
96
|
+
component.ngOnChanges({ filtrarDatos: new SimpleChange(false, component.filtrarDatos, true) });
|
|
97
|
+
fixture.detectChanges();
|
|
98
|
+
|
|
99
|
+
component.filtrarDatos = false;
|
|
100
|
+
component.ngOnChanges({ filtrarDatos: new SimpleChange(true, component.filtrarDatos, false) });
|
|
101
|
+
fixture.detectChanges();
|
|
102
|
+
|
|
103
|
+
component.ordenarDatos = true;
|
|
104
|
+
component.ngOnChanges({ ordenarDatos: new SimpleChange(false, component.ordenarDatos, true) });
|
|
105
|
+
fixture.detectChanges();
|
|
106
|
+
|
|
107
|
+
component.seleccionarFilas = true;
|
|
108
|
+
component.ngOnChanges({ seleccionarFilas: new SimpleChange(false, component.seleccionarFilas, true) });
|
|
109
|
+
fixture.detectChanges();
|
|
110
|
+
|
|
111
|
+
component.seleccionarFilas = false;
|
|
112
|
+
component.ngOnChanges({ seleccionarFilas: new SimpleChange(true, component.seleccionarFilas, false) });
|
|
113
|
+
fixture.detectChanges();
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
component.paginar = false;
|
|
117
|
+
component.ngOnChanges({ paginar: new SimpleChange(true, component.paginar, false) });
|
|
118
|
+
fixture.detectChanges();
|
|
119
|
+
expect(component.paginar).toBe(false);
|
|
120
|
+
|
|
121
|
+
component.filtrarDatos = false;
|
|
122
|
+
component.ngOnChanges({ filtrarDatos: new SimpleChange(true, component.filtrarDatos, false) });
|
|
123
|
+
fixture.detectChanges();
|
|
124
|
+
|
|
125
|
+
component.ordenarDatos = false;
|
|
126
|
+
component.sort = {} as MatSort;
|
|
127
|
+
component.ngOnChanges({ ordenarDatos: new SimpleChange(true, component.ordenarDatos, false) });
|
|
128
|
+
fixture.detectChanges();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('filtrar datos',()=>{
|
|
132
|
+
expect(component.applyFilter('Me'));
|
|
133
|
+
|
|
134
|
+
component.paginar = true;
|
|
135
|
+
component.ngOnChanges({ paginar: new SimpleChange(false, component.paginar, true) });
|
|
136
|
+
fixture.detectChanges();
|
|
137
|
+
expect(component.paginar).toBe(true);
|
|
138
|
+
|
|
139
|
+
expect(component.applyFilter('Me'));
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('seleccion de filas', () => {
|
|
143
|
+
expect(component.alternarSeleccion());
|
|
144
|
+
component.dataTable.seleccion.select(...component.dataTable.dataSource);
|
|
145
|
+
expect(component.alternarSeleccion());
|
|
146
|
+
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
it('metodos en general', () => {
|
|
151
|
+
expect(component.validarEtiqueta(false));
|
|
152
|
+
component.dataTable.columnas=[];
|
|
153
|
+
expect(component.ngAfterViewInit())
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
interface Pais {
|
|
160
|
+
id: number;
|
|
161
|
+
nombre: string;
|
|
162
|
+
}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/** Librerías angular */
|
|
2
|
+
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
|
|
3
|
+
import { MatPaginator } from '@angular/material/paginator';
|
|
4
|
+
import { MatSort } from '@angular/material/sort';
|
|
5
|
+
import { MatTableDataSource } from '@angular/material/table';
|
|
6
|
+
import { SelectionModel } from '@angular/cdk/collections';
|
|
7
|
+
|
|
8
|
+
/** Modelo */
|
|
9
|
+
import { DataTable } from '../../models/interfaces/data-table';
|
|
10
|
+
import { ColumnDefinition } from '../../models/interfaces/column-definition';
|
|
11
|
+
import { CsvService } from 'ngx-redi-core/Helper';
|
|
12
|
+
import { RowAction } from '../../models/interfaces/row-action';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Componente que muestra los datos en una tabla
|
|
16
|
+
* @decorators ´@Component´
|
|
17
|
+
*/
|
|
18
|
+
@Component({
|
|
19
|
+
selector: 'redi-table',
|
|
20
|
+
templateUrl: './redi-table.component.html',
|
|
21
|
+
styleUrls: ['./redi-table.component.css']
|
|
22
|
+
})
|
|
23
|
+
export class RediTableComponent<T extends object> implements OnInit, OnChanges {
|
|
24
|
+
/**
|
|
25
|
+
* Propiedad que indica si se pueden seleccionar las filas
|
|
26
|
+
*/
|
|
27
|
+
@Input()
|
|
28
|
+
public seleccionarFilas = false;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Propiedad que indica si se habilitan los filtros para la tabla
|
|
32
|
+
*/
|
|
33
|
+
@Input()
|
|
34
|
+
public filtrarDatos = false;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Propiedad que indica si se paginan los datos
|
|
38
|
+
*/
|
|
39
|
+
@Input()
|
|
40
|
+
public paginar = false;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Propiedad que indica si se habilita el ordenamiento de datos
|
|
44
|
+
*/
|
|
45
|
+
@Input()
|
|
46
|
+
public ordenarDatos = false;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Datos y configuración de la tabla
|
|
50
|
+
*/
|
|
51
|
+
@Input()
|
|
52
|
+
public dataTable: DataTable<T>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Origen de datos para el MatTable
|
|
56
|
+
*/
|
|
57
|
+
public dataSource: MatTableDataSource<T>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Objeto de la vista para el ordenamiento
|
|
61
|
+
*/
|
|
62
|
+
@ViewChild(MatSort) sort!: MatSort;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Objeto de la vista para la paginación
|
|
66
|
+
*/
|
|
67
|
+
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Contiene las columnas que se mostraran en la tabla
|
|
71
|
+
*/
|
|
72
|
+
public columnas: Array<string> = [];
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Contiene los datos de las columnas
|
|
76
|
+
*/
|
|
77
|
+
public datosColumna: Array<ColumnDefinition> = [];
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Crea un nuevo componente Tabla
|
|
82
|
+
*/
|
|
83
|
+
constructor(private csv: CsvService) {
|
|
84
|
+
this.dataTable = {
|
|
85
|
+
dataSource: [] as Array<T>,
|
|
86
|
+
acciones: [] as Array<RowAction<T>>
|
|
87
|
+
} as DataTable<T>;
|
|
88
|
+
this.dataSource = new MatTableDataSource();
|
|
89
|
+
this.dataSource.data = [];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Eventos que se ejecutan al inicias
|
|
94
|
+
*/
|
|
95
|
+
ngOnInit() {
|
|
96
|
+
this.limpiarColumnas();
|
|
97
|
+
if (this.dataTable) {
|
|
98
|
+
this.dataSource = new MatTableDataSource(this.dataTable.dataSource);
|
|
99
|
+
this.construiDatosColumna();
|
|
100
|
+
this.mostrarColumnas();
|
|
101
|
+
}
|
|
102
|
+
this.inicializarPaginador();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Construye los datos de las columnas para la tabla
|
|
107
|
+
*/
|
|
108
|
+
private construiDatosColumna() {
|
|
109
|
+
if (this.dataTable.columnas &&
|
|
110
|
+
this.dataTable.columnas.length > 0) {
|
|
111
|
+
this.datosColumna.push(...this.dataTable.columnas);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
if (this.dataTable.dataSource.length) {
|
|
115
|
+
this.datosColumna.push(...Object.keys(this.dataTable.dataSource[0])
|
|
116
|
+
.map(x => { return { identificador: x, etiqueta: x } as ColumnDefinition; }));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Activa las columnas que se van a mostrar
|
|
123
|
+
*/
|
|
124
|
+
private mostrarColumnas() {
|
|
125
|
+
this.columnas.push(...this.datosColumna
|
|
126
|
+
.map(item => { return item.identificador; }));
|
|
127
|
+
if (this.dataTable?.acciones && this.verAcciones()) {
|
|
128
|
+
this.columnas.push('actions');
|
|
129
|
+
}
|
|
130
|
+
this.dataSource.sort = this.sort;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Método que ejecuta los cambios en la selección de filas
|
|
135
|
+
* @param currentValue - Valor actual
|
|
136
|
+
*/
|
|
137
|
+
private changeSelection(currentValue: boolean): void {
|
|
138
|
+
if (currentValue) {
|
|
139
|
+
this.columnas.unshift('select');
|
|
140
|
+
this.dataTable.seleccion = this.dataTable.seleccion ?? new SelectionModel<T>(true, []);
|
|
141
|
+
} else {
|
|
142
|
+
const index = this.columnas.indexOf('select');
|
|
143
|
+
if (index > -1) {
|
|
144
|
+
this.columnas.splice(index, 1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Método que valida los cambios en los datos de entrada
|
|
151
|
+
* @param changer - Cambios realizados en la vista
|
|
152
|
+
*/
|
|
153
|
+
ngOnChanges(changes: SimpleChanges): void {
|
|
154
|
+
this.actualizarSeleccion(changes);
|
|
155
|
+
this.actualizarFiltro(changes);
|
|
156
|
+
this.actualizarPaginacion(changes);
|
|
157
|
+
this.actualizarDataTable(changes);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private actualizarSeleccion(cambios: SimpleChanges) {
|
|
161
|
+
const changeSelectedRow = cambios['seleccionarFilas'];
|
|
162
|
+
if (changeSelectedRow && this.dataTable) {
|
|
163
|
+
this.changeSelection(changeSelectedRow.currentValue);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private actualizarFiltro(cambios: SimpleChanges) {
|
|
168
|
+
const changeFilter = cambios['filtrarDatos'];
|
|
169
|
+
if (changeFilter && !changeFilter.currentValue) {
|
|
170
|
+
this.dataSource.filter = '';
|
|
171
|
+
this.reasignarPaginacion();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private reasignarPaginacion() {
|
|
176
|
+
if (this.paginar) {
|
|
177
|
+
this.dataSource.paginator = this.paginator;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
this.dataSource.paginator = null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private actualizarPaginacion(cambios: SimpleChanges) {
|
|
185
|
+
const changePagination = cambios['paginar'];
|
|
186
|
+
if (changePagination) {
|
|
187
|
+
if (changePagination.currentValue) {
|
|
188
|
+
this.dataSource.paginator = this.paginator;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
this.dataSource.paginator = null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
private actualizarDataTable(cambios: SimpleChanges) {
|
|
196
|
+
const datos = cambios['dataTable'];
|
|
197
|
+
if (datos && datos.currentValue) {
|
|
198
|
+
this.dataTable = datos.currentValue;
|
|
199
|
+
this.ngOnInit();
|
|
200
|
+
this.reasignarPaginacion();
|
|
201
|
+
this.changeSelection(this.seleccionarFilas);
|
|
202
|
+
this.dataTable.acciones = this.dataTable.acciones ?? [];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Método que aplica el filtro a los datos de la tabla
|
|
208
|
+
* @param filtro - Evento de filtrado
|
|
209
|
+
*/
|
|
210
|
+
public applyFilter(filtro: string) {
|
|
211
|
+
this.dataSource.filter = filtro.trim().toLowerCase();
|
|
212
|
+
if (this.dataSource.paginator) {
|
|
213
|
+
this.dataSource.paginator.firstPage();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private limpiarColumnas() {
|
|
218
|
+
this.datosColumna.splice(0);
|
|
219
|
+
this.columnas.splice(0);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Método que indica si se debe mostrar la columna de acciones
|
|
224
|
+
* @returns True si se debe mostrar las acciones
|
|
225
|
+
*/
|
|
226
|
+
public verAcciones(): boolean {
|
|
227
|
+
return this.dataTable && this.dataTable.acciones && this.dataTable.acciones.length > 0;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Método que inicializa el Paginador
|
|
232
|
+
*/
|
|
233
|
+
private inicializarPaginador() {
|
|
234
|
+
if (this.paginator) {
|
|
235
|
+
this.paginator._intl.itemsPerPageLabel = 'Elementos por pagina';
|
|
236
|
+
this.paginator._intl.firstPageLabel = 'Primera pagina';
|
|
237
|
+
this.paginator._intl.itemsPerPageLabel = 'Elementos por pagina';
|
|
238
|
+
this.paginator._intl.lastPageLabel = 'Ultima pagina';
|
|
239
|
+
this.paginator._intl.nextPageLabel = 'Siguiente pagina';
|
|
240
|
+
this.paginator._intl.previousPageLabel = 'Pagina anterior';
|
|
241
|
+
this.paginator._intl.getRangeLabel = (page: number, pageSize: number, length: number) => {
|
|
242
|
+
return `Pagina:${page + 1} de ${pageSize <= length ? Math.ceil(length / pageSize) : 1}`;
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Indica si el ordenamiento esta activo
|
|
249
|
+
*/
|
|
250
|
+
public ordenamientoActivo(): boolean {
|
|
251
|
+
if (!this.ordenarDatos && this.sort) {
|
|
252
|
+
this.sort.direction = '';
|
|
253
|
+
}
|
|
254
|
+
return !this.ordenarDatos;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** Alterna la selección de registros de la tabla */
|
|
258
|
+
public alternarSeleccion() {
|
|
259
|
+
if (this.todoSeleccionado()) {
|
|
260
|
+
this.dataTable.seleccion.clear();
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
this.dataTable.seleccion.select(...this.dataSource.data);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Indica si todo el contenido esta seleccionado
|
|
268
|
+
* @returns True si todo el contenido esta seleccionado
|
|
269
|
+
*/
|
|
270
|
+
public todoSeleccionado(): boolean {
|
|
271
|
+
const numSelected = this.dataTable.seleccion.selected.length;
|
|
272
|
+
const numRows = this.dataSource.data.length;
|
|
273
|
+
return numSelected === numRows;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Obtiene el estado de la etiqueta de seleccionado
|
|
278
|
+
* @param fila - Fila que se validara
|
|
279
|
+
* @returns Estado de selección en modo texto
|
|
280
|
+
*/
|
|
281
|
+
public validarEtiqueta(fila?: any): string {
|
|
282
|
+
if (!fila) {
|
|
283
|
+
return `${this.todoSeleccionado() ? 'deselect' : 'select'} all`;
|
|
284
|
+
}
|
|
285
|
+
return `${this.dataTable.seleccion.isSelected(fila) ? 'deselect' : 'select'} row ${Number(fila.position) + 1}`;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
public descargarCsv(archivo: string, soloSeleccionados?: boolean) {
|
|
290
|
+
if (!soloSeleccionados) {
|
|
291
|
+
this.csv.descargarCsv(archivo, this.dataTable.dataSource);
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
this.csv.descargarCsv(archivo, this.dataTable.seleccion.selected);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
public onRowSelect(event: T) {
|
|
299
|
+
this.onRowClick.emit(event);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
@Output()
|
|
303
|
+
public onRowClick = new EventEmitter<T>();
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
protected deshabilitarAccion(action: RowAction<T>, element: any) {
|
|
307
|
+
if (action.deshabilitar) {
|
|
308
|
+
return action.deshabilitar;
|
|
309
|
+
}
|
|
310
|
+
else if (action.desabilitarActionPorValores) {
|
|
311
|
+
const valor = element[action.desabilitarActionPorValores.columnaRef];
|
|
312
|
+
const valores = action.desabilitarActionPorValores.valoresADeshabilitar;
|
|
313
|
+
|
|
314
|
+
if (valores.length === 0) {
|
|
315
|
+
return false;
|
|
316
|
+
} else {
|
|
317
|
+
return valores.some(value => value === valor);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return false
|
|
321
|
+
}
|
|
322
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
import { MatPaginatorModule } from '@angular/material/paginator';
|
|
6
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
7
|
+
import { MatTableModule } from '@angular/material/table';
|
|
8
|
+
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
9
|
+
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
10
|
+
import { RediTableComponent } from './redi-table/redi-table.component';
|
|
11
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Modulo que contiene los componentes de la tabla
|
|
15
|
+
* @decorators ´@NgModule´
|
|
16
|
+
*/
|
|
17
|
+
@NgModule({
|
|
18
|
+
declarations: [RediTableComponent],
|
|
19
|
+
imports: [
|
|
20
|
+
CommonModule,
|
|
21
|
+
MatPaginatorModule,
|
|
22
|
+
MatIconModule,
|
|
23
|
+
MatTableModule,
|
|
24
|
+
ScrollingModule,
|
|
25
|
+
MatCheckboxModule,
|
|
26
|
+
MatButtonModule
|
|
27
|
+
],
|
|
28
|
+
exports: [
|
|
29
|
+
RediTableComponent
|
|
30
|
+
]
|
|
31
|
+
})
|
|
32
|
+
export class RediTableModule { }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
|
|
3
|
+
import { NgxRediCoreComponent } from './ngx-redi-core.component';
|
|
4
|
+
|
|
5
|
+
describe('NgxRediCoreComponent', () => {
|
|
6
|
+
let component: NgxRediCoreComponent;
|
|
7
|
+
let fixture: ComponentFixture<NgxRediCoreComponent>;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
await TestBed.configureTestingModule({
|
|
11
|
+
imports: [NgxRediCoreComponent]
|
|
12
|
+
})
|
|
13
|
+
.compileComponents();
|
|
14
|
+
|
|
15
|
+
fixture = TestBed.createComponent(NgxRediCoreComponent);
|
|
16
|
+
component = fixture.componentInstance;
|
|
17
|
+
fixture.detectChanges();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should create', () => {
|
|
21
|
+
expect(component).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Component } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Component({
|
|
4
|
+
selector: 'lib-ngx-redi-core',
|
|
5
|
+
standalone: true,
|
|
6
|
+
imports: [],
|
|
7
|
+
template: `
|
|
8
|
+
<p>
|
|
9
|
+
ngx-redi-core works!
|
|
10
|
+
</p>
|
|
11
|
+
`,
|
|
12
|
+
styles: ``
|
|
13
|
+
})
|
|
14
|
+
export class NgxRediCoreComponent {
|
|
15
|
+
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TestBed } from '@angular/core/testing';
|
|
2
|
+
|
|
3
|
+
import { NgxRediCoreService } from './ngx-redi-core.service';
|
|
4
|
+
|
|
5
|
+
describe('NgxRediCoreService', () => {
|
|
6
|
+
let service: NgxRediCoreService;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
TestBed.configureTestingModule({});
|
|
10
|
+
service = TestBed.inject(NgxRediCoreService);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should be created', () => {
|
|
14
|
+
expect(service).toBeTruthy();
|
|
15
|
+
});
|
|
16
|
+
});
|