Commit 88149dfd0f7078f132684804678a66a44f00ca7f

Authored by Eric Fernandez
Exists in master and in 1 other branch validar_pve

Merge branch 'master' into 'master'

Master(mpuebla)

See merge request !64
src/app/app.module.ts
... ... @@ -7,6 +7,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
7 7 import { TooltipModule } from 'ngx-bootstrap/tooltip';
8 8 import { PopoverModule } from 'ngx-bootstrap/popover';
9 9 import { CarouselModule } from 'ngx-bootstrap/carousel';
  10 +import { PaginationModule } from 'ngx-bootstrap/pagination';
10 11 //#endregion
11 12  
12 13 //#region Keyboard
... ... @@ -61,7 +62,8 @@ import { MensajeFinalComponent } from './components/mensaje-final/mensaje-final.
61 62 BrowserAnimationsModule,
62 63 MatKeyboardModule,
63 64 MatButtonModule,
64   - CarouselModule.forRoot()
  65 + CarouselModule.forRoot(),
  66 + PaginationModule.forRoot()
65 67 ],
66 68 providers: [],
67 69 bootstrap: [AppComponent]
src/app/components/amb-imagenes/amb-imagenes.component.html
... ... @@ -3,11 +3,11 @@
3 3 <div class="container-fluid">
4 4 <div class="row m-3">
5 5 <div class="col">
6   - <p class="h2">Configuración imágenes</p>
  6 + <p class="h2">Configuración de imágenes</p>
7 7 </div>
8 8 </div>
9 9  
10   - <div class="row search">
  10 + <div class="row mx-3 search">
11 11 <div class="col">
12 12 <span class="fa fa-search form-control-lg form-control-search pl-3"></span>
13 13 <input
... ... @@ -19,30 +19,85 @@
19 19 </div>
20 20 </div>
21 21  
22   - <div class="row m-3 vh-70 overflow-scroll">
  22 + <div class="row m-3 vh-60 overflow-scroll">
23 23 <div class="col">
24 24 <h5>Productos</h5>
25   - <table class="table">
  25 + <table class="table table-striped table-hover table-borderless shadow">
26 26 <thead>
27   - <tr class="text-center">
  27 + <tr class="bg-primary text-center text-white shadow-sm">
28 28 <th>Nombre</th>
29   - <th>Descripción</th>
30 29 <th colspan="2">Imagen</th>
31 30 </tr>
32 31 </thead>
33 32 <tbody>
34   - <tr *ngFor="let articulo of auxProductos">
35   - <td>{{articulo.DET_LAR}}</td>
36   - <td>{{articulo.DET_LAR}}</td>
  33 + <tr class="shadow-sm" *ngFor="let articulo of auxProductos">
  34 + <td class="align-middle">
  35 + <p class="m-0">{{articulo.DET_LAR}}</p>
  36 + <p class="m-0"><small>Descripción: {{articulo.DET_LAR}}</small></p>
  37 + <p class="m-0"><small>Sector: {{articulo.CodSec}}</small></p>
  38 + <p class="m-0"><small>Código: {{articulo.CodArt}}</small></p>
  39 + </td>
37 40 <td>
38   - <img *ngIf="articulo.imagenes.length" src="{{apiUrl}}/imagenes/{{articulo.imagenes[0].imagen}}">
39   - <img id="{{articulo.CodSec + articulo.CodArt}}" [hidden]="articulo.imagenes.length">
  41 + <img
  42 + *ngIf="articulo.imagenes.length == 0"
  43 + class="fade-in w-100 mx-auto img-fluid"
  44 + src="{{apiUrl}}/imagenes/noImage.jpg">
  45 + <carousel [interval]="false">
  46 + <slide *ngFor="let item of articulo.imagenes; let index = index">
  47 + <img
  48 + *ngIf="!item.fromGallery"
  49 + class="fade-in img-fluid w-100"
  50 + src="{{apiUrl}}/imagenes/{{item.imagen}}">
  51 + <img
  52 + *ngIf="item.fromGallery"
  53 + class="fade-in img-fluid w-100"
  54 + src="{{item.imagen}}">
  55 + <button
  56 + (click)="deleteImage(articulo.imagenes, index)"
  57 + type="button"
  58 + class="btn btn-light btn-delete-image position-absolute close">
  59 + <span aria-hidden="true">&times;</span>
  60 + </button>
  61 + </slide>
  62 + </carousel>
  63 + </td>
  64 + <td class="align-middle text-center">
  65 + <div class="custom-file">
  66 + <input
  67 + type="file"
  68 + class="custom-file-input"
  69 + id="customFileLang"
  70 + accept="image/*"
  71 + (change)="onFileSelected($event, articulo)"
  72 + lang="es"
  73 + multiple>
  74 + <label class="custom-file-label text-left pr-5" for="customFileLang">
  75 + <small>Seleccionar archivo</small>
  76 + </label>
  77 + </div>
40 78 </td>
41   - <td><input type="file" accept="image/*" (change)="onFileSelected($event, articulo)"></td>
42 79 </tr>
43 80 </tbody>
44 81 </table>
45 82 </div>
46 83 </div>
47 84  
  85 + <div class="row" *ngIf="paginationData">
  86 + <div class="col">
  87 + <pagination
  88 + [rotate]="false"
  89 + [(ngModel)]="paginationData.page"
  90 + [totalItems]="paginationData.rowCount"
  91 + [maxSize]="paginationData.pageCount"
  92 + [itemsPerPage]="paginationData.pageSize"
  93 + (pageChanged)="pageChanged($event)"
  94 + [boundaryLinks]="true"
  95 + previousText="&lsaquo;"
  96 + nextText="&rsaquo;"
  97 + firstText="&laquo;"
  98 + lastText="&raquo;"
  99 + ></pagination>
  100 + </div>
  101 + </div>
  102 +
48 103 </div>
src/app/components/amb-imagenes/amb-imagenes.component.scss
... ... @@ -7,3 +7,12 @@
7 7 color: #aaa;
8 8 line-height: inherit;
9 9 }
  10 +
  11 +.custom-file-input:lang(es) ~ .custom-file-label::after {
  12 + content: "Elegir";
  13 +}
  14 +
  15 +.btn-delete-image {
  16 + top: 0;
  17 + left: 95%;
  18 +}
src/app/components/amb-imagenes/amb-imagenes.component.ts
... ... @@ -16,51 +16,62 @@ export class AmbImagenesComponent implements OnInit {
16 16 articulos: Producto[] = [];
17 17 private auxProductos: Producto[] = [];
18 18 private searchTerm: string = '';
  19 + private paginationData: any;
19 20  
20   - constructor(private productoService: ProductoService, private http: HttpClient) {}
  21 + constructor(private productoService: ProductoService, private http: HttpClient) { }
21 22  
22 23 ngOnInit() {
23 24  
24   - this.productoService.getAll().subscribe((productos: Producto[]) => {
25   - this.articulos = productos;
26   - this.filterItems();
27   - });
28   - }
  25 + this.productoService.getAllWithPaginator()
  26 + .subscribe((res) => {
29 27  
30   - onFileSelected(event, articulo) {
  28 + this.articulos = res.data;
  29 + this.paginationData = res.pagination;
  30 + this.filterItems();
  31 + }, error => console.error(error));
  32 + }
31 33  
32   - let file: File = event.target.files[0];
  34 + onFileSelected(event, articulo: Producto) {
33 35  
34   - this.onLoad(file)
35   - .then(result => {
  36 + let auxFiles: FileList = event.target.files;
  37 + Array.from(auxFiles).forEach(file => {
36 38  
37   - articulo.imagenes = [];
  39 + this.onLoad(file)
  40 + .then(result => {
38 41  
39   - document.getElementById(articulo.CodSec + articulo.CodArt)['src'] = result;
  42 + articulo.imagenes.push({
  43 + name: file.name,
  44 + fromGallery: true,
  45 + imagen: result,
  46 + id_articulo: articulo.id
  47 + });
40 48  
41   - this.saveInBase({
42   - name: file.name,
43   - base64: result,
44   - codigo: articulo.CodArt,
45   - sector: articulo.CodSec
  49 + this.saveInBase({
  50 + name: file.name,
  51 + base64: result,
  52 + codigo: articulo.CodArt,
  53 + sector: articulo.CodSec
  54 + });
46 55 });
47   - });
  56 + })
48 57 }
49 58  
50 59 filterItems() {
51 60  
52 61 this.auxProductos = this.articulos.filter(x => {
53   - return x.DET_LAR.toLowerCase().includes(this.searchTerm.toLowerCase())
  62 + return x.DET_LAR.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
  63 + x.CodArt.toString().includes(this.searchTerm.toLowerCase()) ||
  64 + x.CodSec.toString().includes(this.searchTerm.toLowerCase());
54 65 });
55 66 }
56 67  
57 68  
58 69 saveInBase(img) {
59 70  
60   - this.http.post(`${appSettings.apiUrl}/imagenes/guardar`, img)
  71 + this.productoService.saveInBase(img)
61 72 .subscribe(data => {
62   - console.log(data);
63   - });
  73 +
  74 + }, error => console.error(error));
64 75 }
65 76  
66 77 onLoad(file) {
... ... @@ -69,7 +80,7 @@ export class AmbImagenesComponent implements OnInit {
69 80  
70 81 var fr = new FileReader();
71 82  
72   - fr.onload = function() {
  83 + fr.onload = function () {
73 84  
74 85 resolve(fr.result);
75 86 };
... ... @@ -78,4 +89,30 @@ export class AmbImagenesComponent implements OnInit {
78 89 });
79 90  
80 91 }
  92 +
  93 + deleteImage(imagenes, index: number) {
  94 +
  95 + if (!imagenes[index].name) {
  96 + imagenes[index].name = imagenes[index].imagen;
  97 + }
  98 +
  99 + this.productoService.deleteImage(imagenes[index])
  100 + .subscribe(res => {
  101 +
  102 + if (res) {
  103 + imagenes.splice(index, 1);
  104 + }
  105 + }, error => console.error(error));
  106 + }
  107 +
  108 + pageChanged(event: any): void {
  109 + this.productoService.getAllWithPaginator(event.page)
  110 + .subscribe((res) => {
  111 +
  112 + this.articulos = res.data;
  113 + this.paginationData = res.pagination;
  114 + this.filterItems();
  115 + }, error => console.error(error));
  116 + }
  117 +
81 118 }
src/app/services/producto.service.ts
... ... @@ -21,9 +21,14 @@ export class ProductoService {
21 21 return this.http.get(`${appSettings.apiUrl}/articulos/${id}`);
22 22 }
23 23  
24   - getAll(): Observable<any> {
  24 + getAll(page: number = 1): Observable<any> {
25 25  
26   - return this.http.get(`${appSettings.apiUrl}/articulos`);
  26 + return this.http.get(`${appSettings.apiUrl}/articulos/`);
  27 + }
  28 +
  29 + getAllWithPaginator(page: number = 1): Observable<any> {
  30 +
  31 + return this.http.get(`${appSettings.apiUrl}/articulos/${page}`);
27 32 }
28 33  
29 34 setProductos(producto: Producto) {
... ... @@ -69,10 +74,14 @@ export class ProductoService {
69 74 return this.http.get(url);
70 75 }
71 76  
72   - updateImages(body): Observable<any> {
  77 + saveInBase(body): Observable<any> {
73 78 return this.http.post(`${appSettings.apiUrl}/imagenes/guardar`, body);
74 79 }
75 80  
  81 + deleteImage(body): Observable<any> {
  82 + return this.http.post(`${appSettings.apiUrl}/imagen/borrar`, body);
  83 + }
  84 +
76 85 getCategorias() {
77 86 return this.http.get(`${appSettings.apiUrl}/categorias`);
78 87 }
... ... @@ -158,3 +158,8 @@ body {
158 158 .min-h-55 {
159 159 min-height: 55px;
160 160 }
  161 +
  162 +.pagination {
  163 + justify-content: center !important;
  164 + display: flex !important;
  165 +}