Commit 2caeab90 authored by Sebastian Chicoma's avatar Sebastian Chicoma

Grilla principal - agentes

parent b0367de7
......@@ -20,6 +20,10 @@ const routes: Routes = [
{
path: 'settings', canLoad: [AuthGuard],
loadChildren: () => import('./modules/settings/settings.module').then(m => m.SettingsModule)
},
{
path: 'configuration', canLoad: [AuthGuard],
loadChildren: () => import('./modules/configuration/configuration.module').then(m => m.ConfigurationModule)
}
],
canActivate: [AuthGuard]
......
......@@ -31,6 +31,7 @@ import {
MAT_MOMENT_DATE_ADAPTER_OPTIONS,
} from '@angular/material-moment-adapter';
import { CustomProgramsFakeBackendInterceptor } from './interceptors/custom-programs-fake-backend.interceptor';
import { AgentFakeBackendInterceptor } from './interceptors/agent-fake-backend.interceptor';
const INITIAL_LANGUAGE = 'es';
......@@ -100,22 +101,22 @@ export function createTranslateLoader(http: HttpClient) {
{ provide: ResourceAuthGuard, useClass: ResourceAuthGuard},
// descomentar estas lineas para OAUTH
{ provide: AuthGuard, useClass: OAuthGuard},
{ provide: AuthenticationService, useClass: OAuthAuthenticationService },
{ provide: APP_INITIALIZER, useFactory: loginLoaderFactory, deps: [AuthenticationService], multi: true },
//{ provide: AuthGuard, useClass: OAuthGuard},
//{ provide: AuthenticationService, useClass: OAuthAuthenticationService },
//{ provide: APP_INITIALIZER, useFactory: loginLoaderFactory, deps: [AuthenticationService], multi: true },
// Para probar mantenimientos
// comentar estas lineas para OAUTH
// { provide: AuthGuard, useClass: AuthGuard},
// { provide: AuthenticationService, useClass: ByteAuthenticationService },
// { provide: HTTP_INTERCEPTORS, useClass: AuthenticationFakeBackendInterceptor, multi: true},
{ provide: AuthGuard, useClass: AuthGuard},
{ provide: AuthenticationService, useClass: ByteAuthenticationService },
{ provide: HTTP_INTERCEPTORS, useClass: AuthenticationFakeBackendInterceptor, multi: true},
{ provide: HTTP_INTERCEPTORS, useClass: SettingsFakeBackendInterceptor, multi: true},
{ provide: HTTP_INTERCEPTORS, useClass: CustomProgramsFakeBackendInterceptor, multi: true},
//{ provide: HTTP_INTERCEPTORS, useClass: EntidadFakeFakeBackendInterceptor, multi: true},
{ provide: HTTP_INTERCEPTORS, useClass: AgentFakeBackendInterceptor, multi: true },
{ provide: APP_INITIALIZER, useFactory: init_app, deps: [InitCommonsService, TranslateService], multi: true }
],
bootstrap: [AppComponent]
......
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthGuard } from '@xdf/security';
import { TemplateResolver, CrudDetailComponent, DirtyGuard, GridViewComponent, CrudGridComponent, RecordResolver } from '@xdf/gallery';
import { ResourceAuthGuard } from '@xdf/security';
import { UserRoleFormComponent, AccessDetailResolver } from '@xdf/settings';
import { AgentComponent } from './view/agent/agent.component';
const routes: Routes = [
{
path: 'agent', component: AgentComponent, canActivate: [AuthGuard, ResourceAuthGuard],
data: {
program: 'agent',
breadcrumb: 'breadcrumb.agent'
}
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ConfigurationRoutingModule { }
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { ConfigurationRoutingModule } from './configuration-routing.module';
import { AgentComponent } from './view/agent/agent.component';
import { XdfGalleryModule } from '@xdf/gallery';
import { MatProgressSpinnerModule, MatTableModule, MatSortModule, MatIconModule, MatTooltipModule, MatPaginatorModule, MatButtonModule } from '@angular/material';
@NgModule({
declarations: [
AgentComponent
],
imports: [
CommonModule,
ConfigurationRoutingModule,
FormsModule,
MatButtonModule,
MatIconModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatSortModule,
MatTableModule,
MatTooltipModule,
ReactiveFormsModule,
TranslateModule,
XdfGalleryModule
]
})
export class ConfigurationModule { }
import { TestBed } from '@angular/core/testing';
import { AgentService } from './agent.service';
describe('AgentService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: AgentService = TestBed.get(AgentService);
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import { DynaDataService } from '@xdf/gallery';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class AgentService extends DynaDataService {
serviceURL = './service/agent';
constructor(private httpClient: HttpClient) {
super(httpClient);
}
}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>{{'label.external.systems' | translate}}</h5>
</div>
<div class="ibox-content">
<div class="content">
<div class="grid-ibox-content">
<div class="filter-panel mat-elevation-z3">
<xdf-ngx-tags-input name="name" class="input-lg" [fields]="fieldFilters"
(filterEvent)="onFilter($event)"></xdf-ngx-tags-input>
</div>
<br />
<div class="grid-container mat-elevation-z3">
<div class="spinner-container" *ngIf="dataSource?.loading$ | async">
<mat-spinner diameter="40"></mat-spinner>
</div>
<table class="crud-table table table-striped table-hover" mat-table
[dataSource]="dataSource" matSort [matSortActive]="sortColumn"
[matSortDirection]="sortDirection" matSortDisableClear multiTemplateDataRows>
<ng-container matColumnDef="{{template.name}}"
*ngFor="let template of columnTemplateArray">
<div *ngIf="template.sortable">
<th mat-header-cell *matHeaderCellDef mat-sort-header>
{{ template.title | translate }}
<mat-icon *ngIf="sortColumn===template?.name">
<i class="fa fa-sort-amount-desc"
*ngIf="sortDirection === 'desc'"></i>
<i class="fa fa-sort-amount-asc"
*ngIf="sortDirection === 'asc'"></i>
</mat-icon>
</th>
</div>
<div *ngIf="!template.sortable">
<th mat-header-cell *matHeaderCellDef>{{ template.title | translate }}
</th>
</div>
<td mat-cell *matCellDef="let item"
[style.width]="template.width ? template.width : ''"
[ngClass]="{'td-view': !this.resourceAuth['view']}" (click)="view(item)">
<span *ngIf="template['name'] !== 'avatar'">{{ item[template['name']] }}</span>
<img *ngIf="template['name'] === 'avatar'" [src]="item[template['name']]" alt="Avatar" class="avatar">
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef></th>
<td class="text-center mat-cell cdk-column-actions mat-column-actions ng-star-inserted"
mat-cell="" role="gridcell" *matCellDef="let item">
<div class="btn-group">
<button class="btn btn-default btn-sm" (click)="edit(item)"
*ngIf="this.resourceAuth['edit']" type="button">
<i class="fa fa-edit"></i>
<span class="visible-md-inline visible-lg-inline visible-xl-inline">
{{'btn.edit' | translate}}
</span>
</button>
<button class="btn btn-default btn-sm" (click)="delete(item)"
*ngIf="this.resourceAuth['delete']" type="button">
<i class="fa fa-trash"></i>
<span class="visible-md-inline visible-lg-inline visible-xl-inline">
{{'btn.delete' | translate}}
</span>
</button>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<div class="status-button-bar pull-left">
<button type="button" mat-icon-button
matTooltip="{{ 'action.grid.refresh' | translate }}" (click)="onRefresh()">
<i class="fa fa-refresh"></i>
</button>
</div>
<mat-paginator [length]="pagination?.totalItems" [pageSize]="pagination?.itemsPerPage"
[pageSizeOptions]="[5, 10, 15]" [pageIndex]="pagination?.currentPage">
</mat-paginator>
</div>
</div>
<!--Boton de Nuevo-->
<div class="toolbar-option">
<button color="default" mat-mini-fab="" class="mat-mini-fab"
matTooltip="{{'btn.new' | translate}}" (click)="create()"
*ngIf="this.resourceAuth['new']">
<span><i class="fa fa-file-o"></i></span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
.toolbar-option {
margin-left: 10px;
margin-right: 10px;
}
$fontcolor: #676a6c;
.content {
width: 100%;
display: flex;
padding-right: 0px !important;
.grid-container,
.filter-panel {
.crud-table {
margin-bottom: 0px;
width: 100%;
}
.form {
padding: 10px 20px 10px 20px;
}
}
.filter-panel {
margin-bottom: 10px;
}
}
.grid-ibox-content {
width: 100%;
}
.btn-group {
.btn {
font-size: 10px;
}
}
.td-view{
cursor: auto !important
}
.mat-row-auth:hover {
background-color: #f8f9fa;
cursor: pointer !important;
}
.spinner-container {
height: 100%;
width: 100%;
padding-top: 50px;
position: fixed;
}
.spinner-container {
height: 100%;
width: 100%;
padding-top: 50px;
position: fixed;
}
.spinner-container mat-spinner {
margin: -10px auto 0 auto;
}
th.mat-column-actions {
width: 1px !important;
padding-right: 0px !important;
}
td.mat-column-actions {
min-width: 170px;
padding-right: 20px !important;
cursor: default !important;
}
td {
vertical-align: middle !important;
color: $fontcolor;
font-size: 12px;
}
th {
vertical-align: middle !important;
}
tr.mat-header-row {
height: 50px !important;
}
tr.mat-footer-row,
tr.mat-row {
height: 40px !important;
}
.table-toolbar {
right: 10px;
top: 10px;
button {
font-size: 12px;
}
}
.status-button-bar {
button {
font-size: 16px;
}
padding-top: 8px;
padding-left: 15px;
}
.mat-raised-button {
padding: 0px 10px;
}
.icon-centered-button span.mat-button-wrapper {
display: flex;
}
.icon-centered-button mat-icon {
font-size: 15px;
padding-top: 2px;
}
::ng-deep .mat-sort-header-arrow {
visibility: hidden;
}
::ng-deep .mat-sort-header-button {
.mat-icon {
padding-left: 10px;
font-size: 12px;
padding-top: 5px;
}
}
th {
background: rgb(242, 242, 242);
}
tr.example-detail-row {
height: 0 !important;
}
tr.example-element-row:not(.example-expanded-row):hover {
background: #dedede;
cursor: pointer;
}
tr.example-element-row:not(.example-expanded-row):active {
background: #efefef;
}
.example-element-row td {
border-bottom-width: 0;
}
.example-element-detail {
overflow: hidden;
display: flex;
}
.example-detail-row td {
padding-top: 0px;
padding-bottom: 0px;
border: none !important;
background-color: #f2f2f2;
}
i.state {
font-size: 1.3em;
}
i.fa-key.pull-left {
color: rgba(128, 128, 128, 0.33);
margin-right: 6px;
}
//////
table {
width: 100%;
}
tr.mat-header-row {
height: 25px;
}
tr.mat-footer-row,
tr.mat-row {
height: 40px;
}
.button-grid {
margin: 2px 5px;
mat-icon {
padding-top: 2px;
}
}
.btn-header-new {
margin-top: -4px;
}
.btn-grid-filter {
height: 36px;
width: 85px;
padding-left: 0px;
padding-top: 2px;
}
.btn-grid-action {
padding: 0 10px;
line-height: 0em;
}
.mat-row:hover {
cursor: pointer;
background-color: #f8f9fa;
}
.spinner-container {
height: 100%;
width: 100%;
padding-top: 50px;
position: fixed;
}
.spinner-container mat-spinner {
margin: -10px auto 0 auto;
}
.mat-raised-button {
padding: 0px 10px;
}
.icon-centered-button span.mat-button-wrapper {
display: flex;
}
.icon-centered-button mat-icon {
font-size: 15px;
padding-top: 2px;
}
.ibox-content {
padding-right: 0px;
}
.content {
width: 100%;
display: flex;
padding-right: 0px !important;
}
.grid-ibox-content {
width: 100%;
}
.avatar {
vertical-align: middle;
width: 35px;
height: 35px;
border-radius: 50%;
}
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AgentComponent } from './agent.component';
describe('AgentComponent', () => {
let component: AgentComponent;
let fixture: ComponentFixture<AgentComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AgentComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AgentComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit, ViewChild, ViewContainerRef, Input } from '@angular/core';
import { MatPaginator, MatSort } from '@angular/material';
import { ColumnTemplate, DynaDataSource, ConfirmationDialogService, extractRSQL, FieldFilter } from '@xdf/gallery';
import { Pagination, SortField, NotificationType, NotificationService } from '@xdf/commons';
import { Router, ActivatedRoute } from '@angular/router';
import { tap } from 'rxjs/operators';
import { TagFilter } from '@xdf/gallery/lib/views/gallery/ngx-tags-input/model/tag-filter';
import { TranslateService } from '@ngx-translate/core';
import { AgentService } from '../../services/agent.service';
const columnTemplateArray = [
{
name: 'avatar',
sortable: true,
title: 'etl_avatar',
visible: true,
filtable: true,
style: { width: 'auto' },
type: 'string',
aliasName: null,
queryName: null,
responsive: null,
styles: null,
values: null,
digitsInfo: null,
dateFormat: null,
colStyle: null
},
{
name: 'id',
sortable: true,
title: 'etl_code',
visible: true,
filtable: true,
style: { width: 'auto' },
type: 'number',
aliasName: null,
queryName: null,
responsive: null,
styles: null,
values: null,
digitsInfo: null,
dateFormat: null,
colStyle: null
},
{
name: 'name',
sortable: true,
title: 'etl_name',
visible: true,
filtable: true,
style: { width: 'auto' },
type: 'string',
aliasName: null,
queryName: null,
responsive: null,
styles: null,
values: null,
digitsInfo: null,
dateFormat: null,
colStyle: null
},
{
name: 'version',
sortable: true,
title: 'etl_version',
visible: true,
filtable: true,
style: { width: 'auto' },
type: 'string',
aliasName: null,
queryName: null,
responsive: null,
styles: null,
values: null,
digitsInfo: null,
dateFormat: null,
colStyle: null
},
{
name: 'status',
sortable: true,
title: 'etl_status',
visible: true,
filtable: true,
style: { width: 'auto' },
type: 'string',
aliasName: null,
queryName: null,
responsive: null,
styles: null,
values: null,
digitsInfo: null,
dateFormat: null,
colStyle: null
},
{
name: 'country',
sortable: true,
title: 'etl_country',
visible: true,
filtable: true,
style: { width: 'auto' },
type: 'string',
aliasName: null,
queryName: null,
responsive: null,
styles: null,
values: null,
digitsInfo: null,
dateFormat: null,
colStyle: null
},
{
name: 'timezone',
sortable: true,
title: 'etl_timezone',
visible: true,
filtable: true,
style: { width: 'auto' },
type: 'string',
aliasName: null,
queryName: null,
responsive: null,
styles: null,
values: null,
digitsInfo: null,
dateFormat: null,
colStyle: null
}
];
const fieldFilters = [
new FieldFilter('etl_code', 'id', 'id', 'number', undefined),
new FieldFilter('etl_abbreviation', 'abbreviation', 'abbreviation', 'string', undefined),
new FieldFilter('etl_name', 'name', 'name', 'string', undefined),
];
@Component({
selector: 'byte-agent',
templateUrl: './agent.component.html',
styleUrls: ['./agent.component.scss']
})
export class AgentComponent implements OnInit {
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator;
@ViewChild(MatSort, { static: false }) sort: MatSort;
sortColumn: string;
sortDirection: string;
statusQuickFilter: string;
pagingSize = 10;
programIdentifier = 'agent';
columnTemplateArray: ColumnTemplate[];
dataSource: DynaDataSource;
displayedColumns = new Array<string>();
fieldFilters: Array<FieldFilter> = fieldFilters;
filterTags = [];
pagination: Pagination;
public resourceAuth: any;
constructor(
private router: Router,
private route: ActivatedRoute,
private agentService: AgentService,
private notificationService: NotificationService,
private translateService: TranslateService,
protected confirmationDialogService: ConfirmationDialogService,
protected vcRef: ViewContainerRef
) { }
ngAfterViewInit(): void {
this.sort.sortChange.subscribe(() => {
if (!this.sort.disabled && this.sort.active) {
this.pagination.sortFields = new Array();
const sortField: SortField = new SortField();
sortField.direction = this.sortDirection = this.sort.direction;
sortField.field = this.sortColumn = this.sort.active;
this.pagination.sortFields.push(sortField);
}
this.paginator.pageIndex = 0;
this.dataSource.load(this.pagination);
});
this.paginator.page
.pipe(
tap(() => {
this.pagination.currentPage = this.paginator.pageIndex;
this.pagination.itemsPerPage = this.paginator.pageSize;
this.dataSource.load(this.pagination);
})
)
.subscribe();
}
ngOnInit() {
this.sortColumn = 'id';
this.sortDirection = 'asc';
const authList = this.route.snapshot.paramMap['authorization'];
if (authList) {
this.resourceAuth = new Object();
authList.forEach(option => {
this.resourceAuth[option] = true;
});
}
this.columnTemplateArray = columnTemplateArray;
this.dataSource = new DynaDataSource(this.agentService);
const previousState = JSON.parse(localStorage.getItem(this.programIdentifier + '-state'));
if (previousState) {
const PAG = 'pagination';
const FILTERS = 'filtersTags';
this.pagination = previousState[PAG];
this.filterTags = previousState[FILTERS];
localStorage.removeItem(this.programIdentifier + '-state');
} else {
// Paginación
this.pagination = new Pagination();
this.pagination.currentPage = 0;
this.pagination.itemsPerPage = this.pagingSize;
this.pagination.filterExpression = "id != 0";
// Ordenación por defecto
if (this.sortColumn && this.sortDirection) {
this.pagination.sortFields = new Array();
const sortField: SortField = new SortField();
sortField.direction = this.sortDirection;
sortField.field = this.sortColumn;
this.pagination.sortFields.push(sortField);
}
}
// calculando la columnas a pintar
this.columnTemplateArray.forEach(column => {
this.displayedColumns.push(column.name);
});
this.displayedColumns.push('actions');
this.dataSource.load(this.pagination);
}
onFilter(tags: Array<TagFilter>) {
this.filterTags = tags;
this.pagination.currentPage = 0;
// let tagsTemp = tags.slice();
const tagsTemp = tags.map(a => Object.assign({}, a));
for (let i = 0; i < tagsTemp.length; i++) {
if (tagsTemp[i].column !== 'id') {
tagsTemp[i].value = tagsTemp[i].value;
}
}
this.pagination.filterExpression = extractRSQL(tagsTemp);
if (this.pagination.filterExpression == null || this.pagination.filterExpression == undefined) {
this.pagination.filterExpression = "id != 0";
}
this.dataSource.load(this.pagination);
}
onRefresh() {
this.dataSource.load(this.pagination);
}
delete(item) {
this.confirmationDialogService.loadComponent(
this.vcRef,
'title.delete.confirmation',
'message.delete.confirmation').subscribe(result => {
if (result) {
this.agentService.delete(item.id).subscribe((rslt: any) => {
if (rslt.statusCode != 200) {
this.notificationService.showMessage(
this.translateService.instant(rslt.message), this.translateService.instant('label.error.message.title'), NotificationType.error);
} else {
this.dataSource.load(this.pagination);
}
}
);
}
});
}
edit(item) {
this.router.navigate(['/etl/external-system/detail/edit/' + item.id]);
}
view(item) {
this.router.navigate(['/etl/external-system/detail/view/' + item.id]);
}
create() {
this.router.navigate(['/etl/external-system/detail/new']);
}
}
......@@ -32,53 +32,23 @@
},
{
"id": 37,
"name": "piloto",
"label": "menu.piloto",
"name": "configuration",
"label": "menu.configuration",
"icon": "<i class=\"fa fa-cog\"></i>",
"fullPath": "/piloto",
"singlePath": "piloto",
"fullPath": "/configuration",
"singlePath": "configuration",
"isProgram": false,
"children": [
{
"id": 33,
"name": "entidades",
"label": "entidades.piloto",
"name": "agent",
"label": "configuration.agent",
"icon": null,
"fullPath": "/piloto/entidades",
"singlePath": "entidades",
"isProgram": true,
"children": []
},
{
"id": 34,
"name": "estados",
"label": "estados.piloto",
"icon": null,
"fullPath": "/piloto/estados",
"singlePath": "estados",
"isProgram": true,
"children": []
},
{
"id": 35,
"name": "motivos",
"label": "motivos.piloto",
"icon": null,
"fullPath": "/piloto/motivos",
"singlePath": "motivos",
"isProgram": true,
"children": []
},
{
"id": 36,
"name": "categoria_motivo",
"label": "categoria.motivo.piloto",
"icon": null,
"fullPath": "/piloto/categoria-motivo",
"singlePath": "categoria-motivo",
"fullPath": "/configuration/agent",
"singlePath": "agent",
"isProgram": true,
"children": []
}
]
}
]
]
\ No newline at end of file
......@@ -3,8 +3,5 @@
"valpos",
"user_role",
"user",
"entidades",
"estados",
"motivos",
"categoria_motivo"
"agent"
]
\ No newline at end of file
{
"home.subtitle": "Bienvenido al proyecto XDF",
"home.comments": "Este proyecto presenta una aplicación web típica. Puede usarlo como un marco de referencia para el desarrollo de sus aplicaciones web."
"home.comments": "Este proyecto presenta una aplicación web típica. Puede usarlo como un marco de referencia para el desarrollo de sus aplicaciones web.",
"etl_avatar": "Avatar",
"etl_code": "ID",
"etl_name": "Nombre",
"etl_version": "Versión",
"etl_status": "Estado",
"etl_country": "País",
"etl_timezone": "Zona horaria"
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment