Merged PR 46: pagination & confirm-modal & validation
pagination & confirm-modal & validation
This commit is contained in:
		
						commit
						81dbc18cfe
					
				| @ -3,13 +3,16 @@ import { CommonModule } from '@angular/common'; | ||||
| import { ModalModule } from 'ngx-bootstrap/modal'; | ||||
| import { CommandModalDirective } from './directives/command-modal.directive'; | ||||
| import { CommandModalComponent } from './command-modal/command-modal.component'; | ||||
| import { InputValidatorDirective } from './directives/input-validator.directive'; | ||||
| import { FormsModule } from '@angular/forms'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|   imports: [ | ||||
|     CommonModule, | ||||
|     ModalModule.forRoot() | ||||
|     ModalModule.forRoot(), | ||||
|     FormsModule | ||||
|   ], | ||||
|   declarations: [CommandModalDirective, CommandModalComponent], | ||||
|   declarations: [CommandModalDirective, CommandModalComponent, InputValidatorDirective], | ||||
|   exports: [CommandModalDirective] | ||||
| }) | ||||
| export class CommandModalModule { } | ||||
|  | ||||
| @ -7,13 +7,12 @@ | ||||
| <div class="modal-body"> | ||||
|     <ng-container [ngTemplateOutlet]="template" | ||||
|         [ngTemplateOutletContext]="{ $implicit: commandModel, loading: loading }"></ng-container> | ||||
|     <div *ngIf="validationMessage" class="alert alert-danger mt-2" style="white-space: pre-wrap">{{validationMessage}}</div> | ||||
| </div> | ||||
| <div class="modal-footer"> | ||||
|     <button type="button" class="btn btn-light" (click)="modalRef.hide()" | ||||
|         [attr.disabled]="loading">{{ cancelText }}</button> | ||||
|     <button type="button" class="btn btn-primary" (click)="attemptSave()" | ||||
|         [attr.disabled]="loading">{{ commandText }}</button> | ||||
| 
 | ||||
|         [disabled]="loading">{{ cancelText }}</button> | ||||
|     <button type="button" class="btn btn-primary" [disabled]="loading" (click)="onSubmit()">{{ commandText }}</button> | ||||
|     <br> | ||||
| 
 | ||||
|     <div class="progress" style="width: 100%" *ngIf="loading"> | ||||
| @ -22,3 +21,4 @@ | ||||
|     </div> | ||||
| 
 | ||||
| </div> | ||||
| 
 | ||||
|  | ||||
| @ -0,0 +1,3 @@ | ||||
| .field-error{ | ||||
|     border: 1px solid red; | ||||
| } | ||||
| @ -3,6 +3,7 @@ import { IDataSource } from '@poweredsoft/data'; | ||||
| import { BsModalRef } from 'ngx-bootstrap/modal'; | ||||
| import { finalize} from 'rxjs/operators'; | ||||
| import { Subscription } from 'rxjs'; | ||||
| import { NgForm } from '@angular/forms'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'psbx-command-modal', | ||||
| @ -20,6 +21,8 @@ export class CommandModalComponent implements OnInit, OnDestroy { | ||||
|   loading: boolean; | ||||
|   commandText: string; | ||||
|   cancelText: string; | ||||
|   form:NgForm; | ||||
|   validationMessage:string ; | ||||
| 
 | ||||
|   private _notifyMessage: Subscription; | ||||
|   private _validationError: Subscription; | ||||
| @ -33,17 +36,26 @@ export class CommandModalComponent implements OnInit, OnDestroy { | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
|     this._notifyMessage = this.dataSource.notifyMessage$.subscribe(message => { | ||||
|        | ||||
|       if (message.type != 'info') | ||||
|         this.validationMessage = message.message; | ||||
|     }); | ||||
| 
 | ||||
|     this._validationError = this.dataSource.validationError$.subscribe(validatorErrors => {       | ||||
|       console.log(validatorErrors); | ||||
|       let validationSummary = ''; | ||||
|       Object.getOwnPropertyNames(validatorErrors.errors).forEach(property => { | ||||
|         const errors = validatorErrors.errors[property].join('\n'); | ||||
|         validationSummary += errors + '\n'; | ||||
|       }); | ||||
|       this.validationMessage = validationSummary.trim(); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   attemptSave() { | ||||
|     debugger; | ||||
|   onSubmit(){ | ||||
|      | ||||
| 
 | ||||
|     this.loading = true; | ||||
|     this.validationMessage = null; | ||||
| 
 | ||||
|     this.dataSource.executeCommandByName(this.command, this.commandModel) | ||||
|       .pipe( | ||||
|         finalize(() => { | ||||
| @ -60,4 +72,8 @@ export class CommandModalComponent implements OnInit, OnDestroy { | ||||
|       }); | ||||
|   } | ||||
| 
 | ||||
|   attemptSave() { | ||||
|      | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,19 @@ | ||||
| import { Directive } from '@angular/core'; | ||||
| import { Validator, AbstractControl, ValidationErrors, NG_VALIDATORS } from '@angular/forms'; | ||||
| 
 | ||||
| @Directive({ | ||||
|   selector: '[psbxInputValidator]', | ||||
|   providers: [{ provide: NG_VALIDATORS, useExisting: InputValidatorDirective, multi: true }] | ||||
| }) | ||||
| export class InputValidatorDirective implements Validator{     | ||||
| 
 | ||||
|   constructor() { } | ||||
| 
 | ||||
|   validate(control: AbstractControl): ValidationErrors { | ||||
|     throw new Error("Method not implemented."); | ||||
|   } | ||||
|   registerOnValidatorChange?(fn: () => void): void { | ||||
|     throw new Error("Method not implemented."); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,6 @@ | ||||
| <div class="modal-body text-center"> | ||||
|     <p>{{ message }}</p> | ||||
|     <button type="button" [ngClass]="yesButtonClass" (click)="confirm()">{{ yesText }}</button> | ||||
|       | ||||
|     <button type="button" [ngClass]="noButtonClass" (click)="decline()">{{ noText }}</button> | ||||
| </div> | ||||
| @ -0,0 +1,50 @@ | ||||
| import { Component, OnInit, TemplateRef } from '@angular/core'; | ||||
| import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal'; | ||||
| import { ConfirmModalService } from '../../confirm-modal.service'; | ||||
| import { Observer } from 'rxjs'; | ||||
| 
 | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'psbx-confirm-modal', | ||||
|   templateUrl: './confirm-modal.component.html', | ||||
|   styleUrls: ['./confirm-modal.component.scss'] | ||||
| }) | ||||
| export class ConfirmModalComponent implements OnInit { | ||||
| 
 | ||||
| 
 | ||||
|   yesText: string; | ||||
|   noText: string; | ||||
|   message: string; | ||||
|   yesClass: string; | ||||
|   noClass: string; | ||||
|   observer: Observer<boolean>; | ||||
| 
 | ||||
|   constructor(private modelRef: BsModalRef, private actionService: ConfirmModalService) { | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
|      | ||||
|   } | ||||
| 
 | ||||
|   get yesButtonClass() { | ||||
|     return `btn btn-sm btn-${this.yesClass}` | ||||
|   } | ||||
| 
 | ||||
|   get noButtonClass() { | ||||
|     return `btn btn-sm btn-${this.noClass}` | ||||
|   } | ||||
| 
 | ||||
|   confirm(): void { | ||||
|     this.modelRef.hide(); | ||||
|     this.observer.next(true); | ||||
|     this.observer.complete(); | ||||
|   } | ||||
|   | ||||
|   decline(): void { | ||||
|     this.modelRef.hide(); | ||||
|     this.observer.next(false); | ||||
|     this.observer.complete(); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,55 @@ | ||||
| import { Directive, Input, TemplateRef, HostListener } from '@angular/core'; | ||||
| import { ConfirmModalService } from './confirm-modal.service'; | ||||
| import { IDataSource } from '@poweredsoft/data'; | ||||
| 
 | ||||
| @Directive({ | ||||
|   selector: '[psbxConfirmModal]' | ||||
| }) | ||||
| export class ConfirmModalDirective { | ||||
| 
 | ||||
|   constructor(private confirmModalService: ConfirmModalService) { } | ||||
| 
 | ||||
| 
 | ||||
|   @Input() dataSource: IDataSource<any>; | ||||
|   @Input() command: string; | ||||
|   @Input() model: any; | ||||
|   @Input() template: TemplateRef<any>; | ||||
|   @Input() commandTitle: string; | ||||
|   @Input() refreshOnSuccess: boolean; | ||||
|   @Input() commandText: string; | ||||
|   @Input() cancelText: string; | ||||
|   @Input() animated: boolean; | ||||
|    | ||||
| 
 | ||||
|   @HostListener('click') | ||||
|   wasClicked() {             | ||||
|     this.dataSource.resolveCommandModelByName({ | ||||
|       command: this.command, | ||||
|       model: this.model | ||||
|     }).subscribe(commandModel => {  | ||||
|       this.confirmModalService.confirm({ | ||||
|         message: 'Do you want to delete this merchant?', | ||||
|         yesText: 'yes delete this merchant', | ||||
|         yesClass: 'danger', | ||||
|         noText: 'no please dont', | ||||
|         noClass: 'light' | ||||
|       }).subscribe(result => { | ||||
|         if(result){ | ||||
|           this.dataSource.executeCommandByName(this.command, commandModel).subscribe(       | ||||
|             res => { | ||||
|               this.dataSource.refresh(); | ||||
|             }, | ||||
|             err => { | ||||
|               console.log(err); | ||||
|               alert('failed'); | ||||
|             } | ||||
|           ); | ||||
|         } | ||||
|       }) | ||||
| 
 | ||||
|     }, error => { | ||||
| 
 | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { CommonModule } from '@angular/common'; | ||||
| import { ConfirmModalComponent } from './confirm-modal-components/confirm-modal/confirm-modal.component'; | ||||
| import { ModalModule } from 'ngx-bootstrap/modal'; | ||||
| import { ConfirmModalService } from './confirm-modal.service'; | ||||
| import { ConfirmModalDirective } from './confirm-modal.directive'; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @NgModule({ | ||||
|   declarations: [ConfirmModalComponent, ConfirmModalDirective], | ||||
|   imports: [ | ||||
|     CommonModule, | ||||
|     ModalModule.forRoot(), | ||||
|      | ||||
|   ], | ||||
|   exports:[ConfirmModalDirective], | ||||
|   providers: [ConfirmModalService] | ||||
| }) | ||||
| export class ConfirmModalModule { } | ||||
| @ -0,0 +1,40 @@ | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { BsModalService } from 'ngx-bootstrap/modal'; | ||||
| import { ConfirmModalComponent } from './confirm-modal-components/confirm-modal/confirm-modal.component'; | ||||
| import { Observable, Observer } from 'rxjs'; | ||||
| 
 | ||||
| export interface IConfirmModalOptions | ||||
| { | ||||
|   yesClass?: string; | ||||
|   noClass?: string; | ||||
|   message: string; | ||||
|   yesText?: string; | ||||
|   noText?: string; | ||||
| } | ||||
| 
 | ||||
| @Injectable() | ||||
| export class ConfirmModalService { | ||||
| 
 | ||||
|   constructor(private modalService: BsModalService) { } | ||||
| 
 | ||||
|   confirm(options: IConfirmModalOptions) : Observable<boolean> { | ||||
|     return Observable.create((o: Observer<boolean>) => { | ||||
| 
 | ||||
| 
 | ||||
|       const initialState = { | ||||
|         message: options.message, | ||||
|         yesText: options.yesText || 'yes', | ||||
|         noText: options.noText || 'no', | ||||
|         yesClass: options.yesClass || 'primary', | ||||
|         noClass: options.noClass || 'light', | ||||
|         observer: o | ||||
|       }; | ||||
| 
 | ||||
|       const modal = this.modalService.show(ConfirmModalComponent, { | ||||
|         initialState: initialState, | ||||
|         animated: true, | ||||
|         keyboard: false | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
| } | ||||
| @ -3,6 +3,7 @@ import { IDataSource } from '@poweredsoft/data'; | ||||
| import { BsModalService } from 'ngx-bootstrap/modal'; | ||||
| import { FormGroupCommandModalComponent } from '../form-group-command-modal/form-group-command-modal.component'; | ||||
| import { FormGroup } from '@angular/forms'; | ||||
| import { ConfirmModalComponent } from '../../confirm-modal/confirm-modal-components/confirm-modal/confirm-modal.component'; | ||||
| 
 | ||||
| export interface IModelFormCreateEvent | ||||
| { | ||||
| @ -28,7 +29,7 @@ export class FormGroupCommandModalDirective { | ||||
|   @Input() refreshOnSuccess: boolean; | ||||
|   @Input() commandText: string; | ||||
|   @Input() cancelText: string; | ||||
| 
 | ||||
|   @Input() isConfirmModal:boolean; | ||||
|   @Output() formCreate: EventEmitter<IModelFormCreateEvent> = new EventEmitter<IModelFormCreateEvent>(); | ||||
| 
 | ||||
|   constructor(private modalService: BsModalService) { } | ||||
| @ -39,9 +40,6 @@ export class FormGroupCommandModalDirective { | ||||
|       command: this.command, | ||||
|       model: this.model | ||||
|     }).subscribe(commandModel => { | ||||
| 
 | ||||
|        | ||||
| 
 | ||||
|       const event = <IModelFormCreateEvent>{ | ||||
|         commandName: this.command, | ||||
|         viewModel: this.model, | ||||
| @ -49,8 +47,26 @@ export class FormGroupCommandModalDirective { | ||||
|         shouldSetCommandModel: true | ||||
|       } | ||||
| 
 | ||||
|       this.formCreate.emit(event); | ||||
|       if(this.isConfirmModal){ | ||||
| 
 | ||||
|         const initialState = { | ||||
|           dataSource: this.dataSource, | ||||
|           command: this.command, | ||||
|           template: this.template, | ||||
|           title: this.commandTitle, | ||||
|           refreshOnSuccess: this.refreshOnSuccess === undefined ? true : this.refreshOnSuccess, | ||||
|           commandText: this.commandText || 'OK', | ||||
|           cancelText: this.cancelText || 'Cancel', | ||||
|           commandModel:commandModel | ||||
|         }; | ||||
|        | ||||
|         this.modalService.show(ConfirmModalComponent, { | ||||
|           animated: this.animated === undefined ? true : this.animated, | ||||
|           initialState | ||||
|         }); | ||||
| 
 | ||||
|       }else{ | ||||
|         this.formCreate.emit(event); | ||||
|         if (event.formGroup == null) | ||||
|           throw new Error('form group should be set, after form createEvent'); | ||||
| 
 | ||||
| @ -65,44 +81,62 @@ export class FormGroupCommandModalDirective { | ||||
|           refreshOnSuccess: this.refreshOnSuccess === undefined ? true : this.refreshOnSuccess, | ||||
|           commandText: this.commandText || 'OK', | ||||
|           cancelText: this.cancelText || 'Cancel', | ||||
|         modelForm: event.formGroup | ||||
|           modelForm: event.formGroup, | ||||
|           commandModel:commandModel | ||||
|         }; | ||||
|        | ||||
|         this.modalService.show(FormGroupCommandModalComponent, { | ||||
|           animated: this.animated === undefined ? true : this.animated, | ||||
|           initialState | ||||
|         }); | ||||
| 
 | ||||
|       } | ||||
|     }, error => { | ||||
| 
 | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   // @Input()
 | ||||
|   // set psbxFormGroupCommandModal(element:HTMLBaseElement){
 | ||||
|   //   element.addEventListener('click',()=>{
 | ||||
|   // @HostListener('click')
 | ||||
|   // wasClicked() {
 | ||||
|   //   this.dataSource.resolveCommandModelByName({
 | ||||
|   //     command: this.command,
 | ||||
|   //     model: this.model
 | ||||
|   //   }).subscribe(commandModel => {
 | ||||
|   //     debugger;
 | ||||
|   //     const event = <IModelFormCreateEvent>{
 | ||||
|   //       commandName: this.command,
 | ||||
|   //       viewModel: this.model,
 | ||||
|   //       commandModel: commandModel,
 | ||||
|   //       shouldSetCommandModel: true
 | ||||
|   //     }
 | ||||
| 
 | ||||
|   //     this.formCreate.emit(event);
 | ||||
| 
 | ||||
|   //     if (event.formGroup == null)
 | ||||
|   //       throw new Error('form group should be set, after form createEvent');
 | ||||
| 
 | ||||
|   //     if (event.shouldSetCommandModel)
 | ||||
|   //       event.formGroup.patchValue(commandModel);
 | ||||
| 
 | ||||
|   //     const initialState = {
 | ||||
|   //       dataSource: this.dataSource,
 | ||||
|   //       command: this.command,
 | ||||
|   //         commandModel: commandModel,
 | ||||
|   //       template: this.template,
 | ||||
|   //       title: this.commandTitle,
 | ||||
|   //       refreshOnSuccess: this.refreshOnSuccess === undefined ? true : this.refreshOnSuccess,
 | ||||
|   //       commandText: this.commandText || 'OK',
 | ||||
|   //         cancelText: this.cancelText || 'Cancel'
 | ||||
|   //       cancelText: this.cancelText || 'Cancel',
 | ||||
|   //       modelForm: event.formGroup,
 | ||||
|   //       commandModel:commandModel
 | ||||
|   //     };
 | ||||
|        | ||||
|   //     this.modalService.show(FormGroupCommandModalComponent, {
 | ||||
|   //       animated: this.animated === undefined ? true : this.animated,
 | ||||
|   //       initialState
 | ||||
|   //       })
 | ||||
|   //     },error => {
 | ||||
|   //     });
 | ||||
| 
 | ||||
|   //   }, error => {
 | ||||
| 
 | ||||
|   //   });
 | ||||
|   //   })
 | ||||
|   // }
 | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -11,17 +11,15 @@ | ||||
|         <ng-container [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{ $implicit: modelForm, loading: loading }"> | ||||
|         </ng-container> | ||||
| 
 | ||||
|         <div *ngIf="errorMessage" class="alert alert-danger mt-2"> | ||||
|             {{ errorMessage }} | ||||
|         </div> | ||||
|         <div *ngIf="errorMessage" class="alert alert-danger mt-2" style="white-space: pre-wrap">{{ errorMessage }}</div> | ||||
|     </div> | ||||
|    | ||||
|      | ||||
|      | ||||
|     <div class="modal-footer"> | ||||
|         <button type="button" class="btn btn-light" (click)="modalRef.hide()" | ||||
|             [attr.disabled]="loading">{{ cancelText }}</button> | ||||
|         <button type="button" class="btn btn-primary" (click)="attemptSave()" [attr.disabled]="loading">Creat</button> | ||||
|             [disabled]="loading">{{ cancelText }}</button> | ||||
|         <button type="button" class="btn btn-primary" (click)="attemptSave()" [disabled]="loading">{{commandText}}</button> | ||||
|         <br> | ||||
|      | ||||
|         <div class="progress" style="width: 100%" *ngIf="loading"> | ||||
|  | ||||
| @ -23,6 +23,7 @@ export class FormGroupCommandModalComponent implements OnInit { | ||||
|   commandText: string; | ||||
|   cancelText: string; | ||||
|   errorMessage: string; | ||||
|   commandModel:any;  | ||||
|    | ||||
|   private _notifyMessage: Subscription; | ||||
|   private _validationError: Subscription; | ||||
| @ -30,10 +31,8 @@ export class FormGroupCommandModalComponent implements OnInit { | ||||
|   constructor(public modalRef: BsModalRef) { } | ||||
| 
 | ||||
|   ngOnDestroy(): void { | ||||
|     /* | ||||
|     this._notifyMessage.unsubscribe(); | ||||
|     this._validationError.unsubscribe(); | ||||
|     */ | ||||
|   } | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
| @ -42,22 +41,29 @@ export class FormGroupCommandModalComponent implements OnInit { | ||||
|        | ||||
|     // });
 | ||||
|     | ||||
|     // this._validationError = this.dataSource.validationError$.subscribe(validatorErrors => {
 | ||||
|     //   console.log(validatorErrors);
 | ||||
|     // });
 | ||||
|     this._validationError = this.dataSource.validationError$.subscribe(validatorErrors => {       | ||||
|       let validationSummary = ''; | ||||
|       Object.getOwnPropertyNames(validatorErrors.errors).forEach(property => { | ||||
|         const errors = validatorErrors.errors[property].join('\n'); | ||||
|         validationSummary += errors + '\n'; | ||||
|       }); | ||||
|       this.errorMessage = validationSummary.trim(); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   attemptSave() { | ||||
| 
 | ||||
|     this.errorMessage = null; | ||||
|     if (!this.modelForm.valid) | ||||
|     { | ||||
|       this.errorMessage = 'Form is not valid, please enter all required fields'; | ||||
|       return; | ||||
|     } | ||||
|     // this.errorMessage = null;
 | ||||
|     // if (!this.modelForm.valid)
 | ||||
|     // {
 | ||||
|     //   this.errorMessage = 'Form is not valid, please enter all required fields';      
 | ||||
|     //   return;
 | ||||
|     // }
 | ||||
| 
 | ||||
|     const finalModel = this.modelForm.value;   | ||||
|     //this.modelForm.setValue(this.commandModel)
 | ||||
|     if(this.commandModel.id) | ||||
|     { | ||||
|       finalModel.id = this.commandModel.id; | ||||
|     } | ||||
|     this.loading = true; | ||||
|     this.dataSource.executeCommandByName(this.command, finalModel) | ||||
|       .pipe( | ||||
|  | ||||
| @ -0,0 +1,2 @@ | ||||
| <pagination [totalItems]="numberOfItems" [itemsPerPage]="pageSize" [(ngModel)]="dataSource.page" [maxSize]="10" | ||||
| [boundaryLinks]='true' previousText="‹" nextText="›" firstText="«" lastText="»"></pagination> | ||||
| @ -0,0 +1,35 @@ | ||||
| import { Component, OnInit, Input, OnDestroy, ChangeDetectorRef } from '@angular/core'; | ||||
| import { IDataSource } from '@poweredsoft/data'; | ||||
| import { Subscription } from 'rxjs'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'psbx-ds-pagination', | ||||
|   templateUrl: './data-source-pagination.component.html', | ||||
|   styleUrls: ['./data-source-pagination.component.scss'] | ||||
| }) | ||||
| export class DataSourcePaginationComponent implements OnInit, OnDestroy { | ||||
|    | ||||
| 
 | ||||
|   @Input() dataSource: IDataSource<any> | ||||
|   numberOfItems: number = 0; | ||||
|   private dataSubscription: Subscription; | ||||
| 
 | ||||
|   constructor(private cdf: ChangeDetectorRef) { } | ||||
|   ngOnDestroy(): void { | ||||
|     this.dataSubscription.unsubscribe(); | ||||
|   } | ||||
| 
 | ||||
|   get pageSize() { | ||||
|     return this.dataSource.pageSize; | ||||
|   } | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
|     this.dataSubscription = this.dataSource.data$.subscribe(latest => { | ||||
|       if (latest) | ||||
|         this.numberOfItems = latest.totalRecords; | ||||
|       else | ||||
|         this.numberOfItems = 0; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,17 @@ | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { CommonModule } from '@angular/common'; | ||||
| import { DataSourcePaginationComponent } from './data-source-pagination/data-source-pagination.component'; | ||||
| import { PaginationModule } from 'ngx-bootstrap/pagination'; | ||||
| import { FormsModule } from '@angular/forms'; | ||||
| 
 | ||||
| 
 | ||||
| @NgModule({ | ||||
|   declarations: [DataSourcePaginationComponent], | ||||
|   imports: [ | ||||
|     CommonModule, | ||||
|     PaginationModule.forRoot(), | ||||
|     FormsModule | ||||
|   ], | ||||
|   exports:[DataSourcePaginationComponent] | ||||
| }) | ||||
| export class psbxPaginationModule { } | ||||
| @ -0,0 +1,14 @@ | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { CommonModule } from '@angular/common'; | ||||
| import { SpinnerComponent } from './spinner/spinner.component'; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @NgModule({ | ||||
|   declarations: [SpinnerComponent], | ||||
|   imports: [ | ||||
|     CommonModule | ||||
|   ], | ||||
|   exports:[SpinnerComponent] | ||||
| }) | ||||
| export class SpinnerModule { } | ||||
| @ -0,0 +1,10 @@ | ||||
| <div class="center"> | ||||
|     <div class="spinner-grow text-primary" role="status"> | ||||
|     </div> | ||||
|     <div class="spinner-grow text-secondary" role="status"> | ||||
|     </div> | ||||
|     <div class="spinner-grow text-primary" role="status"> | ||||
|     </div> | ||||
|     <div class="spinner-grow text-secondary" role="status"> | ||||
|     </div> | ||||
| </div> | ||||
| @ -0,0 +1,6 @@ | ||||
| .center { | ||||
|     position: absolute; | ||||
|     top: 50%; | ||||
|     left: 50%; | ||||
|     transform: translate(-50%, -50%); | ||||
|   } | ||||
| @ -0,0 +1,15 @@ | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'psbx-spinner', | ||||
|   templateUrl: './spinner.component.html', | ||||
|   styleUrls: ['./spinner.component.scss'] | ||||
| }) | ||||
| export class SpinnerComponent implements OnInit { | ||||
| 
 | ||||
|   constructor() { } | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| @ -6,3 +6,10 @@ export * from './lib/command-modal/command-modal.module'; | ||||
| export * from './lib/command-modal/directives/command-modal.directive'; | ||||
| export * from './lib/form-group-command-modal/form-group-command-modal.module'; | ||||
| export * from './lib/form-group-command-modal/directives/form-group-command-modal.directive'; | ||||
| export * from './lib/pagination/psbxPagination.module'; | ||||
| export * from './lib/pagination/data-source-pagination/data-source-pagination.component'; | ||||
| export * from './lib/confirm-modal/confirm-modal.module'; | ||||
| export * from './lib/confirm-modal/confirm-modal.service'; | ||||
| export * from './lib/confirm-modal/confirm-modal.directive'; | ||||
| export * from './lib/spinner/spinner.module'; | ||||
| export * from './lib/spinner/spinner/spinner.component'; | ||||
| @ -6,18 +6,25 @@ import { DataGridColHeaderDirective } from './directives/data-grid-col-header.di | ||||
| import { DataGridCellDirective } from './directives/data-grid-cell.directive'; | ||||
| import { DataGridFooterDirective } from './directives/data-grid-footer.directive'; | ||||
| import { DataGridHeaderDirective } from './directives/data-grid-header.directive'; | ||||
| import { DataGridLoaderDirective } from './directives/data-grid-loader.directive'; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @NgModule({ | ||||
|   declarations: [DataGridComponent,DataGridColDirective,DataGridColHeaderDirective,DataGridCellDirective, DataGridFooterDirective, DataGridHeaderDirective, | ||||
|   declarations: [ | ||||
|     DataGridComponent,DataGridColDirective,DataGridColHeaderDirective, | ||||
|     DataGridCellDirective, DataGridFooterDirective, DataGridHeaderDirective,  | ||||
|     DataGridLoaderDirective, | ||||
|      | ||||
|   ], | ||||
|   imports: [ | ||||
|     CommonModule | ||||
|   ], | ||||
|   exports: [DataGridComponent,DataGridColDirective,DataGridColHeaderDirective,DataGridCellDirective,DataGridFooterDirective, DataGridHeaderDirective] | ||||
|   exports: [ | ||||
|     DataGridComponent,DataGridColDirective,DataGridColHeaderDirective, | ||||
|     DataGridCellDirective,DataGridFooterDirective, DataGridHeaderDirective, | ||||
|     DataGridLoaderDirective] | ||||
| }) | ||||
| export class DataGridModule { } | ||||
|  | ||||
| @ -1,4 +1,6 @@ | ||||
| <table [ngClass]="tableClasses"> | ||||
| <ng-container *ngIf="loading" [ngTemplateOutlet]="loadingTemplate"></ng-container>  | ||||
| 
 | ||||
| <table [ngClass]="tableClasses" style="min-height: 300px;"> | ||||
|   <thead> | ||||
|     <tr> | ||||
|       <th *ngFor="let header of gridHeaders" [attr.colspan]="columns.length"> | ||||
| @ -15,8 +17,7 @@ | ||||
|       </th> | ||||
|     </tr> | ||||
|   </thead> | ||||
| 
 | ||||
|   <tbody *ngIf="latestResult"> | ||||
|   <tbody *ngIf="!noData else noResultTemplate"> | ||||
|     <tr *ngFor="let rowModel of latestResult.data; let i = index"> | ||||
|       <td *ngFor="let column of columns"> | ||||
|         <ng-container *ngIf="hasCellTemplate(column)"> | ||||
| @ -40,3 +41,18 @@ | ||||
|     </tr> | ||||
|   </tfoot> | ||||
| </table> | ||||
| 
 | ||||
| <ng-template #loadingTemplate> | ||||
|   <ng-container *ngFor="let loader of loaders"> | ||||
|     <ng-container [ngTemplateOutlet]="loader.template"></ng-container> | ||||
|   </ng-container> | ||||
| </ng-template> | ||||
| <ng-template #noResultTemplate> | ||||
|   <tbody> | ||||
|     <tr> | ||||
|       <td [attr.colspan]="columns.length"> | ||||
|         <p style="text-align: center;">{{ noRecordsDisplayText }}</p> | ||||
|       </td> | ||||
|     </tr> | ||||
|   </tbody> | ||||
| </ng-template> | ||||
|  | ||||
| @ -1,27 +1,33 @@ | ||||
| import { Component, OnInit, ContentChildren, QueryList, Input, Output, EventEmitter } from '@angular/core'; | ||||
| import { Component, OnInit, ContentChildren, QueryList, Input, Output, EventEmitter, ContentChild, ChangeDetectorRef, OnDestroy } from '@angular/core'; | ||||
| import { IQueryExecutionResult, IQueryExecutionGroupResult, IDataSource } from '@poweredsoft/data'; | ||||
| import { DataGridColDirective } from '../directives/data-grid-col.directive'; | ||||
| import { DataGridHeaderDirective } from '../directives/data-grid-header.directive'; | ||||
| import { DataGridFooterDirective } from '../directives/data-grid-footer.directive'; | ||||
| import { DataGridLoaderDirective } from '../directives/data-grid-loader.directive'; | ||||
| import { Subscription } from 'rxjs'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'ps-data-grid', | ||||
|   templateUrl: './data-grid.component.html', | ||||
|   styleUrls: ['./data-grid.component.scss'] | ||||
| }) | ||||
| export class DataGridComponent implements OnInit { | ||||
| export class DataGridComponent implements OnInit, OnDestroy { | ||||
| 
 | ||||
|   latestResult: IQueryExecutionResult<any> & IQueryExecutionGroupResult<any>; | ||||
|   pages: any[]; | ||||
|   loading:boolean; | ||||
| 
 | ||||
|   @ContentChildren(DataGridColDirective) columnDefinitions: QueryList<DataGridColDirective>; | ||||
|   @ContentChildren(DataGridHeaderDirective) gridHeaders: QueryList<DataGridHeaderDirective>; | ||||
|   @ContentChildren(DataGridFooterDirective) gridFooters: QueryList<DataGridFooterDirective>; | ||||
|    | ||||
|   @ContentChildren(DataGridLoaderDirective) loaders: QueryList<DataGridLoaderDirective>; | ||||
|    | ||||
|   @Input() dataSource: IDataSource<any>; | ||||
|   @Input() tableClasses: any; | ||||
|   @Input() noRecordsText: string; | ||||
| 
 | ||||
|   private _columns: string[]; | ||||
|   private _dataSubscription: Subscription; | ||||
|   private _loadingSubscription: Subscription; | ||||
| 
 | ||||
|   @Input() set columns(value: string[]) { | ||||
|     this._columns = value; | ||||
| @ -33,19 +39,45 @@ export class DataGridComponent implements OnInit { | ||||
|   }   | ||||
| 
 | ||||
|   @Output() columnsChange:EventEmitter<string []> = new EventEmitter<string []>(); | ||||
|   constructor() { } | ||||
| 
 | ||||
|    | ||||
| 
 | ||||
|   get noData() { | ||||
|     return !this.latestResult || this.latestResult.totalRecords == 0;  | ||||
|   } | ||||
| 
 | ||||
|   get noRecordsDisplayText() { | ||||
|     return this.noRecordsText || 'No records'; | ||||
|   } | ||||
| 
 | ||||
|   constructor(private cdr: ChangeDetectorRef) {  | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   ngOnDestroy(): void { | ||||
|     this._dataSubscription.unsubscribe(); | ||||
|     this._loadingSubscription.unsubscribe(); | ||||
|   } | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
|     console.log(this.columnDefinitions); | ||||
|     this.dataSource.data$.subscribe(newData => { | ||||
|    | ||||
|     this._dataSubscription = this.dataSource.data$.subscribe(newData => { | ||||
|       this.latestResult = newData; | ||||
|       if (newData) | ||||
|         this.pages = new Array(newData.numberOfPages); | ||||
|     }); | ||||
| 
 | ||||
|     this._loadingSubscription = this.dataSource.loading$.subscribe(isLoading => { | ||||
|       this.loading = isLoading; | ||||
|       this.cdr.detectChanges(); | ||||
|     }); | ||||
| 
 | ||||
|     console.log(this.loaders); | ||||
|   } | ||||
| 
 | ||||
|   getColumn(columnName: string) { | ||||
|      | ||||
|     if (!this.columnDefinitions) | ||||
|       return null; | ||||
| 
 | ||||
|     const ret = this.columnDefinitions.find(t =>  | ||||
|     { | ||||
|       return t.columnName == columnName; | ||||
|  | ||||
| @ -0,0 +1,10 @@ | ||||
| import { Directive, TemplateRef } from '@angular/core'; | ||||
| 
 | ||||
| @Directive({ | ||||
|   selector: '[psDataGridLoader]' | ||||
| }) | ||||
| export class DataGridLoaderDirective { | ||||
| 
 | ||||
|   constructor(public template: TemplateRef<any>) { } | ||||
| 
 | ||||
| } | ||||
| @ -9,3 +9,4 @@ export * from './lib/data-grid/directives/data-grid-col.directive'; | ||||
| export * from './lib/data-grid/directives/data-grid-col-header.directive'; | ||||
| export * from './lib/data-grid/directives/data-grid-header.directive'; | ||||
| export * from './lib/data-grid/directives/data-grid-footer.directive'; | ||||
| export * from './lib/data-grid/directives/data-grid-loader.directive'; | ||||
| @ -23,6 +23,10 @@ const routes: Routes = [ | ||||
|   { | ||||
|     path: 'form-group', | ||||
|     loadChildren: () => import('./form-group-modal-demo/form-group-modal-demo.module').then(m => m.FormGroupModalDemoModule) | ||||
|   }, | ||||
|   { | ||||
|     path: 'pagination-demo', | ||||
|     loadChildren: ()=> import('./pagination-demo/pagination-demo.module').then(m => m.PaginationDemoModule) | ||||
|   } | ||||
| ]; | ||||
| 
 | ||||
|  | ||||
| @ -18,6 +18,9 @@ | ||||
|         <li class="nav-item"> | ||||
|           <a class="nav-link" routerLink="form-group">Form Group Modal</a> | ||||
|         </li> | ||||
|         <li class="nav-item"> | ||||
|           <a class="nav-link" routerLink="pagination-demo">pagination Demo</a> | ||||
|         </li> | ||||
|       </ul> | ||||
|     </div> | ||||
|     <div class="col-lg-10" style="padding-top: 5px"> | ||||
|  | ||||
| @ -5,7 +5,7 @@ import { CommandModalDemoRoutingModule } from './command-modal-demo-routing.modu | ||||
| import { DataGridModule } from '@poweredsoft/ngx-cdk-ui'; | ||||
| 
 | ||||
| import {FormsModule} from '@angular/forms'; | ||||
| import { CommandModalModule } from '@poweredsoft/ngx-bootstrap'; | ||||
| import { CommandModalModule, psbxPaginationModule, ConfirmModalModule } from '@poweredsoft/ngx-bootstrap'; | ||||
| @NgModule({ | ||||
|   declarations: [CommandModalDemoComponent], | ||||
|   imports: [ | ||||
| @ -13,7 +13,9 @@ import { CommandModalModule } from '@poweredsoft/ngx-bootstrap'; | ||||
|     CommandModalDemoRoutingModule, | ||||
|     DataGridModule, | ||||
|     CommandModalModule, | ||||
|     FormsModule | ||||
|     FormsModule, | ||||
|     psbxPaginationModule, | ||||
|     ConfirmModalModule | ||||
|   ] | ||||
| }) | ||||
| export class CommandModalDemoModule { } | ||||
|  | ||||
| @ -25,23 +25,32 @@ | ||||
|         <ng-container *psDataGridColHeader>Actions</ng-container> | ||||
|         <ng-container *psDataGridCell="let model"> | ||||
|             <button class="btn-primary btn" psbxCommandModal [commandTitle]="'Change ' + model.name + ' name'" commandText="Update" | ||||
|             [dataSource]="merchantDataSource" command="changeMerchantName" [model]="model" [template]="changeName">Change name</button> | ||||
|             [dataSource]="merchantDataSource" command="changeMerchant" [model]="model" [template]="changeName">Change</button> | ||||
| 
 | ||||
|             <button class="btn-danger btn" psbxConfirmModal [commandTitle]="'Are you sure you wnat to remove ' + model.name + '?'" commandText="Remove" | ||||
|             [dataSource]="merchantDataSource" command="removeMerchant" [model]="model" >RemoveIt</button> | ||||
|         </ng-container> | ||||
|     </ng-container> | ||||
|         <ng-container *psDataGridFooter> | ||||
|         <button class="btn-primary btn" psbxCommandModal commandTitle="Adding a new merchant" commandText="Add" | ||||
|             [dataSource]="merchantDataSource" command="addMerchant" [template]="theModal">Create a new record</button> | ||||
|             <psbx-ds-pagination [dataSource]="merchantDataSource"></psbx-ds-pagination>  | ||||
|         </ng-container> | ||||
| </ps-data-grid> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| <ng-template #changeName let-command let-loading="loading"> | ||||
|     New Name | ||||
|     <input type="text" [attr.disabled]="loading" [(ngModel)]="command.newName" placeholder="Entermerchant new name" class="form-control"> | ||||
|     <input type="text" [attr.disabled]="loading" [(ngModel)]="command.name" placeholder="Entermerchant new name" class="form-control"> | ||||
|     New Address | ||||
|     <input type="text" required [attr.disabled]="loading" [(ngModel)]="command.address" placeholder="Entermerchant new Address" class="form-control"> | ||||
| </ng-template> | ||||
| 
 | ||||
| <ng-template #theModal let-command let-loading="loading"> | ||||
|     <form ngNativeValidate  > | ||||
|         Name | ||||
|     <input type="text" [attr.disabled]="loading" [(ngModel)]="command.name" placeholder="Enter a merchant name" class="form-control"> | ||||
|         <input type="text" required [disabled]="loading" name="name" [(ngModel)]="command.name"  placeholder="Enter a merchant name" class="form-control" > | ||||
|         Address | ||||
|     <input type="text" [attr.disabled]="loading" [(ngModel)]="command.address" placeholder="Enter the merchant's address" class="form-control"> | ||||
|         <input type="text" required [disabled]="loading" name="address" [(ngModel)]="command.address"  placeholder="Enter the merchant's address" class="form-control" >         | ||||
|     </form> | ||||
|      | ||||
| </ng-template> | ||||
| @ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; | ||||
| import { IDataSource } from '@poweredsoft/data'; | ||||
| import { IMerchant } from 'src/app/data/services/IMerchant'; | ||||
| import { MerchantService } from 'src/app/data/services/merchant.service'; | ||||
| import { BsModalRef } from 'ngx-bootstrap/modal'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'ps-command-modal-demo', | ||||
| @ -10,7 +11,8 @@ import { MerchantService } from 'src/app/data/services/merchant.service'; | ||||
| }) | ||||
| export class CommandModalDemoComponent implements OnInit { | ||||
| 
 | ||||
|   columns = ['id','name', 'address', 'commands'] | ||||
|   columns = ['id','name', 'address', 'commands']; | ||||
|   pages:any; | ||||
|   merchantDataSource: IDataSource<IMerchant>;   | ||||
|   constructor(private  merchantService: MerchantService){ | ||||
|     this.merchantDataSource = this.createDataSource(); | ||||
| @ -37,14 +39,23 @@ export class CommandModalDemoComponent implements OnInit { | ||||
|   } | ||||
| 
 | ||||
|   ngOnInit() { | ||||
|     this.merchantDataSource.loading$.subscribe(isLoading => { | ||||
|       console.log('merchant data source event loading', isLoading); | ||||
|     }); | ||||
| 
 | ||||
|     this.merchantDataSource.data$.subscribe(receivedData => { | ||||
|       console.log('new data is coming from the server', receivedData); | ||||
|     }); | ||||
|     this.merchantDataSource.refresh(); | ||||
|     this.merchantDataSource.data$.subscribe(newData => {      | ||||
|       if (newData) | ||||
|         this.pages = new Array(newData.numberOfPages); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   message: string; | ||||
|   modalRef: BsModalRef; | ||||
|   confirm(): void { | ||||
|     this.message = 'Confirmed!'; | ||||
|     this.modalRef.hide(); | ||||
|   } | ||||
|   | ||||
|   decline(): void { | ||||
|     this.message = 'Declined!'; | ||||
|     this.modalRef.hide(); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -1,8 +1,13 @@ | ||||
| export interface IChangeMerchantNameCommand { | ||||
|   merchantId: string; | ||||
|   newName: string; | ||||
|   id: string; | ||||
|   name: string; | ||||
|   address: string; | ||||
| } | ||||
| export interface IAddMerchantCommand { | ||||
|   name: string; | ||||
|   address: string; | ||||
| } | ||||
| 
 | ||||
| export interface IRemoveMerchantCommand { | ||||
|   id: string; | ||||
| } | ||||
| @ -4,7 +4,7 @@ import { IDataSource, DataSource } from '@poweredsoft/data'; | ||||
| import { Apollo } from 'apollo-angular'; | ||||
| import  gql  from 'graphql-tag'; | ||||
| import { of } from 'rxjs'; | ||||
| import { IChangeMerchantNameCommand, IAddMerchantCommand } from './IChangeMerchantNameCommand'; | ||||
| import { IChangeMerchantNameCommand, IAddMerchantCommand, IRemoveMerchantCommand } from './IChangeMerchantNameCommand'; | ||||
| import { IMerchant } from './IMerchant'; | ||||
| 
 | ||||
| @Injectable({ | ||||
| @ -27,21 +27,21 @@ export class MerchantService { | ||||
|       (model) => model.id, | ||||
|       { | ||||
|         page: 1, | ||||
|         pageSize: 150, | ||||
|         pageSize: 15, | ||||
|       }, | ||||
|       true | ||||
|     ); | ||||
| 
 | ||||
|     builder.addMutation<IChangeMerchantNameCommand, string>( | ||||
|       'changeMerchantName', //<-- command name
 | ||||
|       'changeMerchantName', //<-- graph ql mutation name
 | ||||
|       'changeMerchant', //<-- command name
 | ||||
|       'changeMerchant', //<-- graph ql mutation name
 | ||||
|        | ||||
|       // implementation of the command.
 | ||||
|       command => { | ||||
|         return this.apollo.use('command').mutate<string>({ | ||||
|           mutation: gql` | ||||
|             mutation executeChangeName($command: changeMerchantNameInput) { | ||||
|               changeMerchantName(params: $command) | ||||
|             mutation executeChangeName($command: ChangeMerchantCommandInput) { | ||||
|               changeMerchant(params: $command) | ||||
|             } | ||||
|           `,
 | ||||
|           variables: { | ||||
| @ -52,8 +52,9 @@ export class MerchantService { | ||||
|        | ||||
|       // viewModel -> transform to the form model for that command -> IChangeMerchantName
 | ||||
|       e => of(<IChangeMerchantNameCommand>{ | ||||
|         merchantId: e.model.id, | ||||
|         newName: e.model.name, | ||||
|         id: e.model.id, | ||||
|         name: e.model.name, | ||||
|         address: e.model.address | ||||
|       }) | ||||
|     ); | ||||
| 
 | ||||
| @ -83,6 +84,31 @@ export class MerchantService { | ||||
|       }) | ||||
|     ); | ||||
| 
 | ||||
|     builder.addMutation<IRemoveMerchantCommand, string>( | ||||
|       'removeMerchant', //<-- command name
 | ||||
|       'removeMerchant', //<-- graph ql mutation name
 | ||||
|        | ||||
|       // implementation of the command.
 | ||||
|       command => { | ||||
|          | ||||
|         return this.apollo.use('command').mutate<string>({ | ||||
|           mutation: gql` | ||||
|             mutation executeAddMerchant($command: RemoveMerchantCommandInput) { | ||||
|               removeMerchant(params: $command) | ||||
|             } | ||||
|           `,
 | ||||
|           variables: { | ||||
|             command: command, | ||||
|           }, | ||||
|         }); | ||||
|       }, | ||||
|        | ||||
|       // viewModel -> transform to the form model for that command -> IChangeMerchantName
 | ||||
|       e => of(<IRemoveMerchantCommand>{ | ||||
|         id: e.model.id, //should be id?
 | ||||
|       }) | ||||
|     ); | ||||
| 
 | ||||
|     const options = builder.create(); | ||||
|     return new DataSource<IMerchant>(options); | ||||
|   } | ||||
|  | ||||
| @ -3,8 +3,9 @@ import { CommonModule } from '@angular/common'; | ||||
| import { FormGroupModalDemoComponent } from './form-group-modal-demo/form-group-modal-demo.component'; | ||||
| import { FormGroupModalDemoRoutingModule } from './form-group-modal-demo-routing.module' | ||||
| import { DataGridModule } from '@poweredsoft/ngx-cdk-ui'; | ||||
| import { FormGroupCommandModalModule,CommandModalModule } from '@poweredsoft/ngx-bootstrap'; | ||||
| import { FormGroupCommandModalModule,CommandModalModule, psbxPaginationModule } from '@poweredsoft/ngx-bootstrap'; | ||||
| import { ReactiveFormsModule } from '@angular/forms'; | ||||
| import { ConfirmModalModule } from 'projects/poweredsoft/ngx-bootstrap/src/public-api'; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -15,7 +16,9 @@ import { ReactiveFormsModule } from '@angular/forms'; | ||||
|     FormGroupModalDemoRoutingModule, | ||||
|     DataGridModule, | ||||
|     FormGroupCommandModalModule, | ||||
|     ReactiveFormsModule | ||||
|     ReactiveFormsModule, | ||||
|     psbxPaginationModule, | ||||
|     ConfirmModalModule, | ||||
|      | ||||
|   ] | ||||
| }) | ||||
|  | ||||
| @ -1,8 +1,10 @@ | ||||
| <h3>This is the demo for form-group modal!</h3> | ||||
| <ps-data-grid [dataSource]="merchantDataSource" [(columns)]="columns" tableClasses="table table-dark table-striped table-sm table-bordered"> | ||||
| <ps-data-grid [dataSource]="merchantDataSource" [(columns)]="columns"  | ||||
|               tableClasses="table table-dark table-striped table-sm table-bordered"> | ||||
|     <ng-container *psDataGridHeader> | ||||
|             <button class="btn-success btn" psbxFormGroupCommandModal commandTitle="Adding a new merchant" commandText="Add" | ||||
|             [dataSource]="merchantDataSource" command="addMerchant" (formCreate)="onFormCreate($event)" [template]="theModal">Create a new</button>    | ||||
|             <button class="btn-success btn" psbxFormGroupCommandModal commandTitle="Adding a new merchant" | ||||
|              commandText="Add" [dataSource]="merchantDataSource" command="addMerchant"  | ||||
|              (formCreate)="onFormCreate($event)" [template]="theModal">Create a new</button>    | ||||
|     </ng-container> | ||||
|     <ng-container psDataGridCol="id"> | ||||
|         <div *psDataGridColHeader>ID</div> | ||||
| @ -19,11 +21,23 @@ | ||||
|     <ng-container psDataGridCol="actions"> | ||||
|         <ng-container *psDataGridColHeader>Actions</ng-container> | ||||
|         <ng-container *psDataGridCell="let model"> | ||||
|             <button class="btn btn-primary mr-2">{{model.name}}</button> | ||||
|             <button class="btn-success btn" psbxFormGroupCommandModal [commandTitle]="'Change ' + model.name + ' name'" commandText="Update" | ||||
|             [dataSource]="merchantDataSource" command="changeMerchant" (formCreate)="onFormCreate($event)" [model]="model" [template]="theModal">Change</button> | ||||
| 
 | ||||
|             <button class="btn-danger btn" psbxConfirmModal [commandTitle]="'Are you sure you wnat to remove ' + model.name + '?'" commandText="Remove" | ||||
|             [dataSource]="merchantDataSource" command="removeMerchant" [model]="model" >Delete!</button> | ||||
| 
 | ||||
|             <!-- <button class="btn-danger btn" psbxExecuteCommand [dataSource]="merchantDataSource" [command]="removeMerchant" | ||||
|              [model]="model" [confirm]="true" [confirmMessage]="do you wish to delete the merchant `' + model.name + '`" [refresh]="false">Delete</button> --> | ||||
|         </ng-container> | ||||
|     </ng-container> | ||||
|     <ng-container *psDataGridFooter> | ||||
|         <psbx-ds-pagination [dataSource]="merchantDataSource"></psbx-ds-pagination>  | ||||
|     </ng-container> | ||||
| </ps-data-grid> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| <ng-template #theModal let-form let-loading="loading"> | ||||
|     <form [formGroup]="form"> | ||||
|         <div class="form-group"> | ||||
| @ -31,6 +45,11 @@ | ||||
|             <div class="col-sm-8"> | ||||
|                 <input id="name" type="text" class="form-control" formControlName="name"> | ||||
|             </div> | ||||
| 
 | ||||
|             <label for="address" class="col-sm-2 control-label">Address</label> | ||||
|             <div class="col-sm-8"> | ||||
|                 <input id="address" type="text" class="form-control" formControlName="address"> | ||||
|             </div> | ||||
|         </div> | ||||
|     </form> | ||||
| </ng-template> | ||||
| @ -16,7 +16,7 @@ export class FormGroupModalDemoComponent implements OnInit { | ||||
|     return this.merchantService.createDataSource(); | ||||
|   } | ||||
| 
 | ||||
|    | ||||
|   pages:any; | ||||
|   merchantDataSource: IDataSource<IMerchant>; | ||||
|   columns = ['id','name', 'address', 'actions']; | ||||
|   constructor(private merchantService: MerchantService, private fb: FormBuilder) { | ||||
| @ -25,28 +25,20 @@ export class FormGroupModalDemoComponent implements OnInit { | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
|     this.merchantDataSource.refresh(); | ||||
|     this.merchantDataSource.data$.subscribe(newData => {      | ||||
|       if (newData) | ||||
|         this.pages = new Array(newData.numberOfPages); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   onFormCreate(event: IModelFormCreateEvent) {     | ||||
|     event.shouldSetCommandModel = false; | ||||
|     event.formGroup = this.fb.group({ | ||||
|       'name': [event.commandModel.name, Validators.required] | ||||
|       'name': [event.commandModel.name, Validators.required], | ||||
|       'address': [event.commandModel.address, Validators.required] | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   newMerchant(name: string) { | ||||
|     this.merchantDataSource.executeCommandByName('addMerchant', { | ||||
|       name: name | ||||
|     }).subscribe( | ||||
|       res => { | ||||
|         alert('it worked!'); | ||||
|         this.merchantDataSource.refresh(); | ||||
|       }, | ||||
|       err => { | ||||
|         console.log(err); | ||||
|         alert('failed'); | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | ||||
							
								
								
									
										15
									
								
								src/app/pagination-demo/pagination-demo-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/app/pagination-demo/pagination-demo-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { Routes, RouterModule } from '@angular/router'; | ||||
| import { PaginationDemoComponent } from './pagination-demo/pagination/pagination-demo.component'; | ||||
| 
 | ||||
| 
 | ||||
| const routes: Routes = [{ | ||||
|   path: '', | ||||
|   component: PaginationDemoComponent | ||||
| }]; | ||||
| 
 | ||||
| @NgModule({ | ||||
|   imports: [RouterModule.forChild(routes)], | ||||
|   exports: [RouterModule] | ||||
| }) | ||||
| export class PaginationDemoRoutingModule { } | ||||
							
								
								
									
										28
									
								
								src/app/pagination-demo/pagination-demo.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/app/pagination-demo/pagination-demo.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { CommonModule } from '@angular/common'; | ||||
| 
 | ||||
| import { PaginationDemoRoutingModule } from './pagination-demo-routing.module'; | ||||
| import { PaginationDemoComponent } from './pagination-demo/pagination/pagination-demo.component'; | ||||
| import { DataGridModule } from '@poweredsoft/ngx-cdk-ui'; | ||||
| import { psbxPaginationModule, CommandModalModule, ConfirmModalModule,SpinnerModule } from '@poweredsoft/ngx-bootstrap'; | ||||
| import { FormsModule } from '@angular/forms'; | ||||
| import { ModalModule } from 'ngx-bootstrap/modal'; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @NgModule({ | ||||
|   declarations: [PaginationDemoComponent], | ||||
|   imports: [ | ||||
|     CommonModule, | ||||
|     PaginationDemoRoutingModule, | ||||
|     psbxPaginationModule, | ||||
|     DataGridModule, | ||||
|     CommandModalModule, | ||||
|     ConfirmModalModule, | ||||
|     FormsModule, | ||||
|     SpinnerModule | ||||
|         | ||||
|   ] | ||||
| }) | ||||
| export class PaginationDemoModule { } | ||||
| @ -0,0 +1,86 @@ | ||||
| 
 | ||||
|    | ||||
| <ps-data-grid [dataSource]="merchantDataSource" [(columns)]="columns" | ||||
|     tableClasses="table table-sm table-dark table-striped table-bordered"> | ||||
| 
 | ||||
| 
 | ||||
|      | ||||
| 
 | ||||
|     <psbx-spinner *psDataGridLoader></psbx-spinner> | ||||
| 
 | ||||
|     <ng-container *psDataGridHeader> | ||||
|         <button class="btn-warning btn" psbxCommandModal commandTitle="Adding a new merchant" commandText="Add" | ||||
|             [dataSource]="merchantDataSource" command="addMerchant" [template]="theModal">Create a new record</button> | ||||
|     </ng-container> | ||||
|   | ||||
|     <ng-container psDataGridCol="id"> | ||||
|         <div *psDataGridColHeader>ID</div> | ||||
|         <div *psDataGridCell="let model">{{model.id}}</div> | ||||
| 
 | ||||
|         <!-- <psfa-ds-sort-icon *psDataGridColSort [sortPath]="id" [dataSource]="merchantDataSource"> | ||||
| 
 | ||||
|         </psfa-ds-sort-icon>  --> | ||||
| 
 | ||||
|         <!-- <psbx-ds-text-filter *psDataGridCellFilter [dataSource]="merchantDataSource"></psbx-ds-text-filter> | ||||
|         <psdb-ds-date-filter *psDataGridCellFilter></psdb-ds-date-filter> | ||||
|         <psdb-ds-date-range-filter *psDataGridCellFilter></psdb-ds-date-range-filter> | ||||
|         <psbx-ds-number-filter *psDataGridCellFilter></psbx-ds-number-filter> | ||||
|         <psbx-ds-multi-select-filter [dataSource]="merchantDataSource" [selectDataSource]="selectDataSource" [valueField]="id"> | ||||
|             <ng-container *psSelectOption="let option">{{ option.name }}</ng-container> | ||||
|         </psbx-ds-multi-select-filter> --> | ||||
|     </ng-container> | ||||
| 
 | ||||
|     <ng-container psDataGridCol="name"> | ||||
|         <div *psDataGridColHeader>Name</div> | ||||
|         <div *psDataGridCell="let model">{{model.name}}</div>          | ||||
|     </ng-container> | ||||
|     | ||||
|     <ng-container psDataGridCol="address"> | ||||
|         <div *psDataGridColHeader>Address</div> | ||||
|         <div *psDataGridCell="let model">{{model.address}}</div> | ||||
|     </ng-container> | ||||
|     <ng-container psDataGridCol="commands"> | ||||
|         <ng-container *psDataGridColHeader>Actions</ng-container> | ||||
|         <ng-container *psDataGridCell="let model"> | ||||
|             <button class="btn-danger btn" psbxConfirmModal [commandTitle]="'Are you sure you wnat to remove ' + model.name + '?'" commandText="Remove" | ||||
|             [dataSource]="merchantDataSource" command="removeMerchant" [model]="model" >Remove</button> | ||||
|         </ng-container> | ||||
|     </ng-container> | ||||
| 
 | ||||
|     <ng-container *psDataGridFooter> | ||||
|         <psbx-ds-pagination [dataSource]="merchantDataSource"></psbx-ds-pagination>  | ||||
|     </ng-container> | ||||
| </ps-data-grid> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| <ng-template #confirm> | ||||
|     <div class="modal-body text-center"> | ||||
|       <p>Do you want to confirm?</p> | ||||
|       <button type="button" class="btn btn-default"  >Yes</button> | ||||
|       <button type="button" class="btn btn-primary"  >No</button> | ||||
|     </div> | ||||
|   </ng-template> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  <ng-template #theModal let-command let-loading="loading"> | ||||
|         <label for="name">Name</label> | ||||
|         <input type="text" required [attr.disabled]="loading" [(ngModel)]="command.name" placeholder="Enter a merchant name"  | ||||
|                class="form-control"  > | ||||
|         <label for="address">Address</label> | ||||
|         <input type="text" required [attr.disabled]="loading" [(ngModel)]="command.address" placeholder="Enter the merchant's address"  | ||||
|               class="form-control" > | ||||
|          | ||||
| </ng-template>  | ||||
| 
 | ||||
| <!-- <ng-template #theModal let-command let-form let-loading="loading"> | ||||
|     <label for="name">Name</label> | ||||
|     <input type="text" required [attr.disabled]="loading" [(ngModel)]="command.name" name="name" placeholder="Enter a merchant name"  | ||||
|            class="form-control"  #nameField="ngModel" [class.field-error]="form.submitted && form.invalid">  | ||||
|     <label for="address">Address</label> | ||||
|     <input type="text" required [attr.disabled]="loading" [(ngModel)]="command.address" name="address" placeholder="Enter the merchant's address"  | ||||
|           class="form-control" #addressField="ngModel" [class.field-error]="form.submitted && form.invalid"> | ||||
|      | ||||
|      | ||||
| </ng-template> --> | ||||
| @ -0,0 +1,3 @@ | ||||
| .ng-invalid:not(form).ng-touched{ | ||||
|     border: 1px solid red; | ||||
| }  | ||||
| @ -0,0 +1,61 @@ | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
| import { IDataSource } from '@poweredsoft/data'; | ||||
| import { IMerchant } from 'src/app/data/services/IMerchant'; | ||||
| import { MerchantService } from 'src/app/data/services/merchant.service'; | ||||
| import { FormBuilder, Validators } from '@angular/forms'; | ||||
| import { ConfirmModalService } from '@poweredsoft/ngx-bootstrap'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'ps-pagination', | ||||
|   templateUrl: './pagination-demo.component.html', | ||||
|   styleUrls: ['./pagination-demo.component.scss'] | ||||
| }) | ||||
| export class PaginationDemoComponent implements OnInit { | ||||
|   columns = ['id','name', 'address','commands'] | ||||
|   merchantDataSource: IDataSource<IMerchant>;   | ||||
|   constructor(private  merchantService: MerchantService, private confirmModalService: ConfirmModalService){ | ||||
|     this.merchantDataSource = this.createDataSource(); | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   pages:any; | ||||
| 
 | ||||
|   // removeMerchant(id:string) {
 | ||||
|   //   this.confirmModalService.confirm({
 | ||||
|   //     message: 'Do you want to delete this merchant?',
 | ||||
|   //     yesText: 'yes delete this merchant',
 | ||||
|   //     yesClass: 'danger',
 | ||||
|   //     noText: 'no please dont',
 | ||||
|   //     noClass: 'light'
 | ||||
|   //   }).subscribe(result => {
 | ||||
|   //     if(result){
 | ||||
|   //       this.merchantDataSource.executeCommandByName('removeMerchant', {
 | ||||
|   //         id: id
 | ||||
|   //       }).subscribe(      
 | ||||
|   //         res => {
 | ||||
|   //           this.merchantDataSource.refresh();
 | ||||
|   //         },
 | ||||
|   //         err => {
 | ||||
|   //           console.log(err);
 | ||||
|   //           alert('failed');
 | ||||
|   //         }
 | ||||
|   //       );
 | ||||
|   //     }
 | ||||
|   //   })
 | ||||
|   // }
 | ||||
| 
 | ||||
|    | ||||
|   createDataSource(): IDataSource<IMerchant> { | ||||
|     return this.merchantService.createDataSource(); | ||||
|   } | ||||
| 
 | ||||
|   ngOnInit() { | ||||
|     this.merchantDataSource.refresh(); | ||||
|     this.merchantDataSource.data$.subscribe(newData => {      | ||||
|       if (newData) | ||||
|         this.pages = new Array(newData.numberOfPages); | ||||
|     }); | ||||
|   } | ||||
|    | ||||
| 
 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user