Merged PR 48: filtering sorting and select
filtering sorting and select need comments for naming i.e. NgSelectorModule => NgSelectModule GridFilterModule => DataSourceFilterModule ??
This commit is contained in:
		
						commit
						397d6753f2
					
				
							
								
								
									
										41
									
								
								angular.json
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								angular.json
									
									
									
									
									
								
							| @ -28,6 +28,7 @@ | |||||||
|               "src/assets" |               "src/assets" | ||||||
|             ], |             ], | ||||||
|             "styles": [ |             "styles": [ | ||||||
|  |               "node_modules/bootstrap/dist/css/bootstrap.min.css", | ||||||
|               "src/styles.scss" |               "src/styles.scss" | ||||||
|             ], |             ], | ||||||
|             "scripts": [] |             "scripts": [] | ||||||
| @ -203,6 +204,46 @@ | |||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |     }, | ||||||
|  |     "@poweredsoft/ng-select": { | ||||||
|  |       "projectType": "library", | ||||||
|  |       "root": "projects/poweredsoft/ng-select", | ||||||
|  |       "sourceRoot": "projects/poweredsoft/ng-select/src", | ||||||
|  |       "prefix": "ps-ng", | ||||||
|  |       "architect": { | ||||||
|  |         "build": { | ||||||
|  |           "builder": "@angular-devkit/build-ng-packagr:build", | ||||||
|  |           "options": { | ||||||
|  |             "tsConfig": "projects/poweredsoft/ng-select/tsconfig.lib.json", | ||||||
|  |             "project": "projects/poweredsoft/ng-select/ng-package.json" | ||||||
|  |           }, | ||||||
|  |           "configurations": { | ||||||
|  |             "production": { | ||||||
|  |               "tsConfig": "projects/poweredsoft/ng-select/tsconfig.lib.prod.json" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "test": { | ||||||
|  |           "builder": "@angular-devkit/build-angular:karma", | ||||||
|  |           "options": { | ||||||
|  |             "main": "projects/poweredsoft/ng-select/src/test.ts", | ||||||
|  |             "tsConfig": "projects/poweredsoft/ng-select/tsconfig.spec.json", | ||||||
|  |             "karmaConfig": "projects/poweredsoft/ng-select/karma.conf.js" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "lint": { | ||||||
|  |           "builder": "@angular-devkit/build-angular:tslint", | ||||||
|  |           "options": { | ||||||
|  |             "tsConfig": [ | ||||||
|  |               "projects/poweredsoft/ng-select/tsconfig.lib.json", | ||||||
|  |               "projects/poweredsoft/ng-select/tsconfig.spec.json" | ||||||
|  |             ], | ||||||
|  |             "exclude": [ | ||||||
|  |               "**/node_modules/**" | ||||||
|  |             ] | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|     }}, |     }}, | ||||||
|   "defaultProject": "ngx-cdk-ui" |   "defaultProject": "ngx-cdk-ui" | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										20
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1644,6 +1644,14 @@ | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "@ng-select/ng-select": { | ||||||
|  |       "version": "4.0.1", | ||||||
|  |       "resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-4.0.1.tgz", | ||||||
|  |       "integrity": "sha512-f5NzrKRvswOvxa8BzBgAUOpzl0B8SrlVQHQLB2zPymuZlzC2dWUi9mUhgu6s2igwdClmrZ8bysNBBNpgqHskyA==", | ||||||
|  |       "requires": { | ||||||
|  |         "tslib": "^1.10.0" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "@ngtools/webpack": { |     "@ngtools/webpack": { | ||||||
|       "version": "9.1.7", |       "version": "9.1.7", | ||||||
|       "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-9.1.7.tgz", |       "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-9.1.7.tgz", | ||||||
| @ -1668,9 +1676,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "@poweredsoft/data": { |     "@poweredsoft/data": { | ||||||
|       "version": "0.0.26", |       "version": "0.0.30", | ||||||
|       "resolved": "https://registry.npmjs.org/@poweredsoft/data/-/data-0.0.26.tgz", |       "resolved": "https://registry.npmjs.org/@poweredsoft/data/-/data-0.0.30.tgz", | ||||||
|       "integrity": "sha512-JogKJQ01w4hTQr4EDSoYp2KfJzBbzC8trc7iHCxw7tjF6kB9nqWxu8gvRxX5pqzDK6ORz0Ieuw7i0hEZusW+ww==", |       "integrity": "sha512-lKojW+yCKPSrdohqhuoEUTo196Z1cHs+SkOZ9N43N7MUcbIR0SA6Uz6k4QZtbmbXmR5AvDKPrDp37nqPXGZFYA==", | ||||||
|       "requires": { |       "requires": { | ||||||
|         "tslib": "^1.9.0" |         "tslib": "^1.9.0" | ||||||
|       } |       } | ||||||
| @ -1684,9 +1692,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "@poweredsoft/ngx-data-apollo": { |     "@poweredsoft/ngx-data-apollo": { | ||||||
|       "version": "0.0.8", |       "version": "0.0.10", | ||||||
|       "resolved": "https://registry.npmjs.org/@poweredsoft/ngx-data-apollo/-/ngx-data-apollo-0.0.8.tgz", |       "resolved": "https://registry.npmjs.org/@poweredsoft/ngx-data-apollo/-/ngx-data-apollo-0.0.10.tgz", | ||||||
|       "integrity": "sha512-8nIlvHTnbLyG9aNxkSYOHIbNBBSjj92v0BeFTq4xkttp3UmYzhOO7lkgo1cEIDUuYo+ITAYoZbKwrd4CbnBgcA==", |       "integrity": "sha512-0HjJthjXstNXS/T9u6t9VTWtQO/LUzGsbT/m0tjj8y0YuivMzfK76EyQldvjGXDYGfIL12kEhsKEbiOPXyCXcA==", | ||||||
|       "requires": { |       "requires": { | ||||||
|         "tslib": "^1.9.0" |         "tslib": "^1.9.0" | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -23,9 +23,10 @@ | |||||||
|     "@angular/platform-browser": "~9.1.4", |     "@angular/platform-browser": "~9.1.4", | ||||||
|     "@angular/platform-browser-dynamic": "~9.1.4", |     "@angular/platform-browser-dynamic": "~9.1.4", | ||||||
|     "@angular/router": "~9.1.4", |     "@angular/router": "~9.1.4", | ||||||
|     "@poweredsoft/data": "0.0.26", |     "@ng-select/ng-select": "^4.0.1", | ||||||
|  |     "@poweredsoft/data": "0.0.30", | ||||||
|     "@poweredsoft/ngx-data": "0.0.13", |     "@poweredsoft/ngx-data": "0.0.13", | ||||||
|     "@poweredsoft/ngx-data-apollo": "0.0.8", |     "@poweredsoft/ngx-data-apollo": "0.0.10", | ||||||
|     "apollo-angular": "^1.8.0", |     "apollo-angular": "^1.8.0", | ||||||
|     "apollo-angular-link-http": "^1.9.0", |     "apollo-angular-link-http": "^1.9.0", | ||||||
|     "apollo-cache-inmemory": "^1.6.0", |     "apollo-cache-inmemory": "^1.6.0", | ||||||
|  | |||||||
							
								
								
									
										24
									
								
								projects/poweredsoft/ng-select/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								projects/poweredsoft/ng-select/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | # NgSelect | ||||||
|  | 
 | ||||||
|  | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.1.9. | ||||||
|  | 
 | ||||||
|  | ## Code scaffolding | ||||||
|  | 
 | ||||||
|  | Run `ng generate component component-name --project ng-select` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ng-select`. | ||||||
|  | > Note: Don't forget to add `--project ng-select` or else it will be added to the default project in your `angular.json` file.  | ||||||
|  | 
 | ||||||
|  | ## Build | ||||||
|  | 
 | ||||||
|  | Run `ng build ng-select` to build the project. The build artifacts will be stored in the `dist/` directory. | ||||||
|  | 
 | ||||||
|  | ## Publishing | ||||||
|  | 
 | ||||||
|  | After building your library with `ng build ng-select`, go to the dist folder `cd dist/ng-select` and run `npm publish`. | ||||||
|  | 
 | ||||||
|  | ## Running unit tests | ||||||
|  | 
 | ||||||
|  | Run `ng test ng-select` to execute the unit tests via [Karma](https://karma-runner.github.io). | ||||||
|  | 
 | ||||||
|  | ## Further help | ||||||
|  | 
 | ||||||
|  | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). | ||||||
							
								
								
									
										32
									
								
								projects/poweredsoft/ng-select/karma.conf.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								projects/poweredsoft/ng-select/karma.conf.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | |||||||
|  | // Karma configuration file, see link for more information
 | ||||||
|  | // https://karma-runner.github.io/1.0/config/configuration-file.html
 | ||||||
|  | 
 | ||||||
|  | module.exports = function (config) { | ||||||
|  |   config.set({ | ||||||
|  |     basePath: '', | ||||||
|  |     frameworks: ['jasmine', '@angular-devkit/build-angular'], | ||||||
|  |     plugins: [ | ||||||
|  |       require('karma-jasmine'), | ||||||
|  |       require('karma-chrome-launcher'), | ||||||
|  |       require('karma-jasmine-html-reporter'), | ||||||
|  |       require('karma-coverage-istanbul-reporter'), | ||||||
|  |       require('@angular-devkit/build-angular/plugins/karma') | ||||||
|  |     ], | ||||||
|  |     client: { | ||||||
|  |       clearContext: false // leave Jasmine Spec Runner output visible in browser
 | ||||||
|  |     }, | ||||||
|  |     coverageIstanbulReporter: { | ||||||
|  |       dir: require('path').join(__dirname, '../../../coverage/poweredsoft/ng-select'), | ||||||
|  |       reports: ['html', 'lcovonly', 'text-summary'], | ||||||
|  |       fixWebpackSourcePaths: true | ||||||
|  |     }, | ||||||
|  |     reporters: ['progress', 'kjhtml'], | ||||||
|  |     port: 9876, | ||||||
|  |     colors: true, | ||||||
|  |     logLevel: config.LOG_INFO, | ||||||
|  |     autoWatch: true, | ||||||
|  |     browsers: ['Chrome'], | ||||||
|  |     singleRun: false, | ||||||
|  |     restartOnFileChange: true | ||||||
|  |   }); | ||||||
|  | }; | ||||||
							
								
								
									
										7
									
								
								projects/poweredsoft/ng-select/ng-package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								projects/poweredsoft/ng-select/ng-package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | { | ||||||
|  |   "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", | ||||||
|  |   "dest": "../../../dist/poweredsoft/ng-select", | ||||||
|  |   "lib": { | ||||||
|  |     "entryFile": "src/public-api.ts" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								projects/poweredsoft/ng-select/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								projects/poweredsoft/ng-select/package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | { | ||||||
|  |   "name": "@poweredsoft/ng-select", | ||||||
|  |   "version": "0.0.1", | ||||||
|  |   "peerDependencies": { | ||||||
|  |     "@angular/common": "^9.1.9", | ||||||
|  |     "@angular/core": "^9.1.9" | ||||||
|  |   }, | ||||||
|  |   "dependencies": { | ||||||
|  |     "tslib": "^1.10.0" | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,11 @@ | |||||||
|  | import { Directive, TemplateRef } from '@angular/core'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @Directive({ | ||||||
|  |   selector: '[psNgNotFoundTemplate]' | ||||||
|  | }) | ||||||
|  | export class NotFoundTemplateDirective { | ||||||
|  | 
 | ||||||
|  |   constructor(public template: TemplateRef<any>) { } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | import { Directive, TemplateRef } from '@angular/core'; | ||||||
|  | 
 | ||||||
|  | @Directive({ | ||||||
|  |   selector: '[psNgSelectLabel]' | ||||||
|  | }) | ||||||
|  | export class SelectLabelTemplateDirective { | ||||||
|  |   constructor(public template: TemplateRef<any>) { } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,10 @@ | |||||||
|  | import { Directive, TemplateRef } from '@angular/core'; | ||||||
|  | 
 | ||||||
|  | @Directive({ | ||||||
|  |   selector: '[psNgSelectOption]' | ||||||
|  | }) | ||||||
|  | export class SelectOptionTemplateDirective { | ||||||
|  | 
 | ||||||
|  |   constructor(public template: TemplateRef<any>) { } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,29 @@ | |||||||
|  | <ng-select [items]="data$ |async" | ||||||
|  |            [bindLabel]="bindLabel"     | ||||||
|  |            [bindValue]="bindValue"        | ||||||
|  |            autofocus | ||||||
|  |            [typeahead] = "searchInput$" | ||||||
|  |            [trackByFn]="trackFn"    | ||||||
|  |            [searchable]="true"    | ||||||
|  |            [multiple]="true"  | ||||||
|  |            (change)="valueChanged($event)"> | ||||||
|  |            <ng-container *ngIf="hasOptionTemplate"> | ||||||
|  |                <ng-template ng-option-tmp let-item="item" let-index="index"> | ||||||
|  |                 <ng-container [ngTemplateOutlet]="selectOptionTemplate" | ||||||
|  |                     [ngTemplateOutletContext]="{ | ||||||
|  |                     $implicit: item, | ||||||
|  |                     index: index        | ||||||
|  |                     }"></ng-container> | ||||||
|  |                </ng-template> | ||||||
|  |            </ng-container> | ||||||
|  | 
 | ||||||
|  |            <ng-container *ngIf="hasLabelTemplate"> | ||||||
|  |             <ng-template ng-label-tmp let-item="item" let-index="index" let-clear="clear"> | ||||||
|  |                 <span class="ng-value-label"> | ||||||
|  |                     <ng-container [ngTemplateOutlet]="selectLabelTemplate" | ||||||
|  |                     [ngTemplateOutletContext]="{ $implicit: item, index: index, clear: clear }"></ng-container> | ||||||
|  |                 </span> | ||||||
|  |                 <span class="ng-value-icon right" (click)="clear(item)" aria-hidden="true">×</span> | ||||||
|  |             </ng-template> | ||||||
|  |         </ng-container> | ||||||
|  | </ng-select> | ||||||
| @ -0,0 +1,153 @@ | |||||||
|  | import { Component, OnInit, ContentChild, ViewChild, Input, Output, EventEmitter, ChangeDetectorRef, forwardRef, OnDestroy } from '@angular/core'; | ||||||
|  | import { SelectLabelTemplateDirective } from '../directives/select-label-template.directive'; | ||||||
|  | import { IDataSource, ISimpleFilter } from '@poweredsoft/data'; | ||||||
|  | import { Observable, Subject, Subscription } from 'rxjs'; | ||||||
|  | import { map, distinctUntilChanged, debounceTime } from 'rxjs/operators'; | ||||||
|  | import { NgSelectComponent as SelectComponent } from '@ng-select/ng-select'; | ||||||
|  | import { NG_VALUE_ACCESSOR } from '@angular/forms'; | ||||||
|  | import { SelectOptionTemplateDirective } from '../directives/select-option-template.directive'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   selector: 'ps-ng-multi-select', | ||||||
|  |   templateUrl: './multi-select.component.html', | ||||||
|  |   providers: [{ | ||||||
|  |     provide: NG_VALUE_ACCESSOR, | ||||||
|  |     useExisting: forwardRef(() => MultiSelectComponent), | ||||||
|  |     multi: true | ||||||
|  | }], | ||||||
|  |   styleUrls: ['./multi-select.component.scss'] | ||||||
|  | }) | ||||||
|  | export class MultiSelectComponent implements OnInit,OnDestroy { | ||||||
|  | 
 | ||||||
|  |    | ||||||
|  |   @ContentChild(SelectOptionTemplateDirective) optionTemplate: SelectOptionTemplateDirective; | ||||||
|  |   @ContentChild(SelectLabelTemplateDirective) labelTemplate: SelectLabelTemplateDirective; | ||||||
|  | 
 | ||||||
|  |   @ViewChild(SelectComponent, { static: true }) selectComponent: SelectComponent; | ||||||
|  |   @Input() dataSource: IDataSource<any>; | ||||||
|  |   @Input() searchPath: string; | ||||||
|  |   @Input() searchType: string; | ||||||
|  |   @Input() sortingPath: string; | ||||||
|  |   @Input() serverFiltering:boolean; | ||||||
|  |   @Input() bindLabel:string; | ||||||
|  |   @Input() bindValue: string; | ||||||
|  | 
 | ||||||
|  |   @Output('change') changeEvent = new EventEmitter(); | ||||||
|  | 
 | ||||||
|  |   trackFn: (item: any) => any; | ||||||
|  |   data$ : Observable<any[]>; | ||||||
|  |   isLoading:boolean = false; | ||||||
|  |   searchInput$ = new Subject<string>(); | ||||||
|  | 
 | ||||||
|  |   private _loadingSubscription: Subscription;   | ||||||
|  | 
 | ||||||
|  |   constructor(private cdr: ChangeDetectorRef) {     | ||||||
|  |     this.trackFn = this.trackBy.bind(this); | ||||||
|  |    | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   trackBy(item: any) { | ||||||
|  |     return this.dataSource.resolveIdField(item); | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   valueChanged(event) { | ||||||
|  |     this.changeEvent.emit(event); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   writeValue(obj: any): void { | ||||||
|  |     this.selectComponent.writeValue(obj); | ||||||
|  |   } | ||||||
|  |   registerOnChange(fn: any): void { | ||||||
|  |     this.selectComponent.registerOnChange(fn); | ||||||
|  |   } | ||||||
|  |   registerOnTouched(fn: any): void { | ||||||
|  |     this.selectComponent.registerOnTouched(fn); | ||||||
|  |   } | ||||||
|  |   setDisabledState?(isDisabled: boolean): void { | ||||||
|  |     if (this.selectComponent.setDisabledState) | ||||||
|  |       this.selectComponent.setDisabledState(isDisabled); | ||||||
|  |   } | ||||||
|  |   ngOnDestroy(): void { | ||||||
|  |     this._loadingSubscription.unsubscribe(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ngOnInit(): void { | ||||||
|  |     this.dataFetching();     | ||||||
|  |     this.detectLoading(); | ||||||
|  |     if(this.serverFiltering){ | ||||||
|  |       this.searchOnServer(); | ||||||
|  |     }else{ | ||||||
|  |       this.refreshDataSource(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   dataFetching(){ | ||||||
|  |     this.data$ = this.dataSource.data$.pipe( | ||||||
|  |       map(t => { | ||||||
|  |         if (t == null)         | ||||||
|  |           return []; | ||||||
|  |         return t.data; | ||||||
|  |       }) | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   detectLoading(){ | ||||||
|  |     this._loadingSubscription = this.dataSource.loading$.subscribe(loading => {       | ||||||
|  |       this.isLoading = loading; | ||||||
|  |       this.cdr.detectChanges(); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   searchOnServer(){ | ||||||
|  |     this.searchInput$.pipe( | ||||||
|  |       distinctUntilChanged(), // emit the difference from previous input
 | ||||||
|  |       debounceTime(500)  // this is for delaying searching speed
 | ||||||
|  |     ).subscribe(searchTerm => this.refreshDataSource(searchTerm, 1, 100)); // page: 1, pageSize: 50
 | ||||||
|  | 
 | ||||||
|  |     this.refreshDataSource(); //send the query to server to sorting & filtering by default
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get selectedModel() { | ||||||
|  |     return this.selectComponent.selectedItems.map(t => t.value); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   refreshDataSource(searchTerm:any = null, page:number = null, pageSize:number = null){ | ||||||
|  |     let searchfilters:ISimpleFilter[] = null; | ||||||
|  |     if(searchTerm){ | ||||||
|  |       searchfilters = [<ISimpleFilter>{ | ||||||
|  |         path: this.searchPath || this.bindLabel,       | ||||||
|  |         type: this.searchType || 'Contains', // Default: Contains
 | ||||||
|  |         value: searchTerm | ||||||
|  |       }] | ||||||
|  |     } | ||||||
|  |     this.dataSource.query({ | ||||||
|  |       page: page, | ||||||
|  |       pageSize: pageSize, | ||||||
|  |       filters:searchfilters, | ||||||
|  |       sorts:[ | ||||||
|  |         {path: this.sortingPath || this.bindLabel, ascending: true}  | ||||||
|  |       ] | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get hasOptionTemplate() {     | ||||||
|  |     return this.optionTemplate ? true : false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get selectOptionTemplate(){ | ||||||
|  |     if (this.optionTemplate)     | ||||||
|  |       return this.optionTemplate.template; | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get hasLabelTemplate() { | ||||||
|  |     return this.labelTemplate ? true : false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get selectLabelTemplate(){ | ||||||
|  |     if (this.labelTemplate)     | ||||||
|  |       return this.labelTemplate.template; | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,36 @@ | |||||||
|  | <ng-select [items]="data$ |async" | ||||||
|  |            [bindLabel]="bindLabel"     | ||||||
|  |            [bindValue]="bindValue"        | ||||||
|  |            autofocus | ||||||
|  |            [typeahead] = "searchInput$" | ||||||
|  |            [trackByFn]="trackFn"        | ||||||
|  |            (change)="valueChanged($event)"> | ||||||
|  |            <ng-container *ngIf="hasOptionTemplate"> | ||||||
|  |                <ng-template ng-option-tmp let-item="item" let-index="index"> | ||||||
|  |                 <ng-container [ngTemplateOutlet]="selectOptionTemplate" | ||||||
|  |                     [ngTemplateOutletContext]="{ | ||||||
|  |                     $implicit: item, | ||||||
|  |                     index: index        | ||||||
|  |                     }"></ng-container> | ||||||
|  |                </ng-template> | ||||||
|  |            </ng-container> | ||||||
|  | 
 | ||||||
|  |            <ng-container *ngIf="hasLabelTemplate"> | ||||||
|  |             <ng-template ng-label-tmp let-item="item" let-index="index"> | ||||||
|  |              <ng-container [ngTemplateOutlet]="selectLabelTemplate" | ||||||
|  |                  [ngTemplateOutletContext]="{ | ||||||
|  |                  $implicit: item, | ||||||
|  |                  index: index        | ||||||
|  |                  }"></ng-container> | ||||||
|  |             </ng-template> | ||||||
|  |             </ng-container> | ||||||
|  | 
 | ||||||
|  |         <ng-container *ngIf="hasNotFoundTemplate"> | ||||||
|  |             <ng-template ng-notfound-tmp let-searchTerm="searchTerm"> | ||||||
|  |                 <ng-container [ngTemplateOutlet]="selectNotFoundTemplate" | ||||||
|  |                 [ngTemplateOutletContext]="{ | ||||||
|  |                 $implicit: searchTerm                     | ||||||
|  |                 }"></ng-container> | ||||||
|  |             </ng-template> | ||||||
|  |         </ng-container> | ||||||
|  | </ng-select> | ||||||
| @ -0,0 +1,170 @@ | |||||||
|  | import { Component, OnInit, ContentChild, ViewChild, Input, Output, EventEmitter, ChangeDetectorRef, forwardRef, OnDestroy } from '@angular/core'; | ||||||
|  | import { SelectLabelTemplateDirective } from '../directives/select-label-template.directive'; | ||||||
|  | import { IDataSource, ISimpleFilter } from '@poweredsoft/data'; | ||||||
|  | import { Observable, Subject, Subscription } from 'rxjs'; | ||||||
|  | import { map, distinctUntilChanged, debounceTime } from 'rxjs/operators'; | ||||||
|  | import { NgSelectComponent as SelectComponent } from '@ng-select/ng-select'; | ||||||
|  | import { NG_VALUE_ACCESSOR } from '@angular/forms'; | ||||||
|  | import { SelectOptionTemplateDirective } from '../directives/select-option-template.directive'; | ||||||
|  | import { NotFoundTemplateDirective } from '../directives/not-found-template.directive'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   selector: 'ps-ng-select', | ||||||
|  |   templateUrl: './ng-select.component.html', | ||||||
|  |   providers: [{ | ||||||
|  |     provide: NG_VALUE_ACCESSOR, | ||||||
|  |     useExisting: forwardRef(() => NgSelectComponent), | ||||||
|  |     multi: true | ||||||
|  | }], | ||||||
|  |   styleUrls: ['./ng-select.component.scss'] | ||||||
|  | }) | ||||||
|  | export class NgSelectComponent implements OnInit,OnDestroy { | ||||||
|  | 
 | ||||||
|  |   @ContentChild(SelectOptionTemplateDirective) optionTemplate: SelectOptionTemplateDirective; | ||||||
|  |   @ContentChild(SelectLabelTemplateDirective) labelTemplate: SelectLabelTemplateDirective; | ||||||
|  |   @ContentChild(NotFoundTemplateDirective) notFoundTemplate: NotFoundTemplateDirective; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |    | ||||||
|  |   @ViewChild(SelectComponent, { static: true }) selectComponent: SelectComponent; | ||||||
|  |   @Input() dataSource: IDataSource<any>; | ||||||
|  |   @Input() searchPath: string; | ||||||
|  |   @Input() searchType: string; | ||||||
|  |   @Input() sortingPath: string; | ||||||
|  |   @Input() serverFiltering:boolean; | ||||||
|  |   @Input() bindLabel:string; | ||||||
|  |   @Input() bindValue: string; | ||||||
|  | 
 | ||||||
|  |   @Output('change') changeEvent = new EventEmitter(); | ||||||
|  | 
 | ||||||
|  |   trackFn: (item: any) => any; | ||||||
|  |   data$ : Observable<any[]>; | ||||||
|  |   isLoading:boolean = false; | ||||||
|  |   searchInput$ = new Subject<string>(); | ||||||
|  | 
 | ||||||
|  |   private _loadingSubscription: Subscription;   | ||||||
|  | 
 | ||||||
|  |   constructor(private cdr: ChangeDetectorRef) {     | ||||||
|  |     this.trackFn = this.trackBy.bind(this); | ||||||
|  |    | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ngOnInit(): void { | ||||||
|  |     this.dataFetching();     | ||||||
|  |     this.detectLoading(); | ||||||
|  | 
 | ||||||
|  |     if(this.serverFiltering){ | ||||||
|  |       this.searchOnServer(); | ||||||
|  |     }else{ | ||||||
|  |       this.refreshDataSource(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   | ||||||
|  |   valueChanged(event) { | ||||||
|  |     this.changeEvent.emit(event); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   writeValue(obj: any): void { | ||||||
|  |     this.selectComponent.writeValue(obj); | ||||||
|  |   } | ||||||
|  |   registerOnChange(fn: any): void { | ||||||
|  |     this.selectComponent.registerOnChange(fn); | ||||||
|  |   } | ||||||
|  |   registerOnTouched(fn: any): void { | ||||||
|  |     this.selectComponent.registerOnTouched(fn); | ||||||
|  |   } | ||||||
|  |   setDisabledState?(isDisabled: boolean): void { | ||||||
|  |     if (this.selectComponent.setDisabledState) | ||||||
|  |       this.selectComponent.setDisabledState(isDisabled); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   trackBy(item: any) { | ||||||
|  |     return this.dataSource.resolveIdField(item); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ngOnDestroy(): void { | ||||||
|  |     this._loadingSubscription.unsubscribe(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   dataFetching(){ | ||||||
|  |     this.data$ = this.dataSource.data$.pipe( | ||||||
|  |       map(t => { | ||||||
|  |         if (t == null)         | ||||||
|  |           return []; | ||||||
|  |         return t.data; | ||||||
|  |       }) | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   detectLoading(){ | ||||||
|  |     this._loadingSubscription = this.dataSource.loading$.subscribe(loading => {       | ||||||
|  |       this.isLoading = loading; | ||||||
|  |       this.cdr.detectChanges(); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   searchOnServer(){ | ||||||
|  |     this.searchInput$.pipe( | ||||||
|  |       distinctUntilChanged(), // emit the difference from previous input
 | ||||||
|  |       debounceTime(500)  // this is for delaying searching speed
 | ||||||
|  |     ).subscribe(searchTerm => this.refreshDataSource(searchTerm, 1, 100)); // page: 1, pageSize: 50
 | ||||||
|  | 
 | ||||||
|  |     this.refreshDataSource(); //send the query to server to sorting & filtering by default
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get selectedModel() {     | ||||||
|  |     return this.selectComponent.hasValue ? this.selectComponent.selectedItems[0] : null; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   refreshDataSource(searchTerm:any = null, page:number = null, pageSize:number = null){ | ||||||
|  |     let searchfilters:ISimpleFilter[] = null; | ||||||
|  |     if(searchTerm){ | ||||||
|  |       searchfilters = [<ISimpleFilter>{ | ||||||
|  |         path: this.searchPath || this.bindLabel,       | ||||||
|  |         type: this.searchType || 'Contains', // Default: Contains
 | ||||||
|  |         value: searchTerm | ||||||
|  |       }] | ||||||
|  |     } | ||||||
|  |     this.dataSource.query({ | ||||||
|  |       page: page, | ||||||
|  |       pageSize: pageSize, | ||||||
|  |       filters:searchfilters, | ||||||
|  |       sorts:[ | ||||||
|  |         {path: this.sortingPath || this.bindLabel, ascending: true}  | ||||||
|  |       ] | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get hasOptionTemplate() {     | ||||||
|  |     return this.optionTemplate ? true : false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get selectOptionTemplate(){ | ||||||
|  |     if (this.optionTemplate)     | ||||||
|  |       return this.optionTemplate.template; | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get hasLabelTemplate() { | ||||||
|  |     return this.labelTemplate ? true : false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get selectLabelTemplate(){ | ||||||
|  |     if (this.labelTemplate)     | ||||||
|  |       return this.labelTemplate.template; | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get hasNotFoundTemplate() { | ||||||
|  |     return this.notFoundTemplate ? true : false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get selectNotFoundTemplate(){ | ||||||
|  |     if(this.notFoundTemplate) | ||||||
|  |       return this.notFoundTemplate.template; | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,28 @@ | |||||||
|  | import { NgModule } from '@angular/core'; | ||||||
|  | import { CommonModule } from '@angular/common'; | ||||||
|  | import { NgSelectComponent } from './ng-select/ng-select.component'; | ||||||
|  | import { MultiSelectComponent } from './multi-select/multi-select.component'; | ||||||
|  | import { FormsModule } from '@angular/forms'; | ||||||
|  | import { NgSelectModule } from '@ng-select/ng-select'; | ||||||
|  | import { SelectLabelTemplateDirective } from './directives/select-label-template.directive'; | ||||||
|  | import { SelectOptionTemplateDirective } from './directives/select-option-template.directive'; | ||||||
|  | import { NotFoundTemplateDirective } from './directives/not-found-template.directive'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |   declarations: [NgSelectComponent, MultiSelectComponent, SelectLabelTemplateDirective, SelectOptionTemplateDirective, NotFoundTemplateDirective], | ||||||
|  |   imports: [ | ||||||
|  |     CommonModule, | ||||||
|  |     FormsModule, | ||||||
|  |     NgSelectModule, | ||||||
|  |   ], | ||||||
|  |   exports:[ | ||||||
|  |     NgSelectComponent, | ||||||
|  |     MultiSelectComponent, | ||||||
|  |     SelectLabelTemplateDirective, | ||||||
|  |     SelectOptionTemplateDirective, | ||||||
|  |     NotFoundTemplateDirective | ||||||
|  |   ] | ||||||
|  | }) | ||||||
|  | export class PsNgSelectModule { }//NGSELECT
 | ||||||
							
								
								
									
										10
									
								
								projects/poweredsoft/ng-select/src/public-api.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								projects/poweredsoft/ng-select/src/public-api.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | /* | ||||||
|  |  * Public API Surface of ng-select | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | export * from './lib/ps-ng-select/ps-ng-select.module'; | ||||||
|  | export * from './lib/ps-ng-select/ng-select/ng-select.component'; | ||||||
|  | export * from './lib/ps-ng-select/multi-select/multi-select.component'; | ||||||
|  | export * from './lib/ps-ng-select/directives/select-label-template.directive'; | ||||||
|  | export * from './lib/ps-ng-select/directives/select-option-template.directive'; | ||||||
|  | export * from './lib/ps-ng-select/directives/not-found-template.directive'; | ||||||
							
								
								
									
										26
									
								
								projects/poweredsoft/ng-select/src/test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								projects/poweredsoft/ng-select/src/test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
 | ||||||
|  | 
 | ||||||
|  | import 'zone.js/dist/zone'; | ||||||
|  | import 'zone.js/dist/zone-testing'; | ||||||
|  | import { getTestBed } from '@angular/core/testing'; | ||||||
|  | import { | ||||||
|  |   BrowserDynamicTestingModule, | ||||||
|  |   platformBrowserDynamicTesting | ||||||
|  | } from '@angular/platform-browser-dynamic/testing'; | ||||||
|  | 
 | ||||||
|  | declare const require: { | ||||||
|  |   context(path: string, deep?: boolean, filter?: RegExp): { | ||||||
|  |     keys(): string[]; | ||||||
|  |     <T>(id: string): T; | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // First, initialize the Angular testing environment.
 | ||||||
|  | getTestBed().initTestEnvironment( | ||||||
|  |   BrowserDynamicTestingModule, | ||||||
|  |   platformBrowserDynamicTesting() | ||||||
|  | ); | ||||||
|  | // Then we find all the tests.
 | ||||||
|  | const context = require.context('./', true, /\.spec\.ts$/); | ||||||
|  | // And load the modules.
 | ||||||
|  | context.keys().map(context); | ||||||
							
								
								
									
										23
									
								
								projects/poweredsoft/ng-select/tsconfig.lib.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								projects/poweredsoft/ng-select/tsconfig.lib.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | { | ||||||
|  |   "extends": "../../../tsconfig.json", | ||||||
|  |   "compilerOptions": { | ||||||
|  |     "outDir": "../../../out-tsc/lib", | ||||||
|  |     "target": "es2015", | ||||||
|  |     "declaration": true, | ||||||
|  |     "inlineSources": true, | ||||||
|  |     "types": [], | ||||||
|  |     "lib": [ | ||||||
|  |       "dom", | ||||||
|  |       "es2018" | ||||||
|  |     ] | ||||||
|  |   }, | ||||||
|  |   "angularCompilerOptions": { | ||||||
|  |     "skipTemplateCodegen": true, | ||||||
|  |     "strictMetadataEmit": true, | ||||||
|  |     "enableResourceInlining": true | ||||||
|  |   }, | ||||||
|  |   "exclude": [ | ||||||
|  |     "src/test.ts", | ||||||
|  |     "**/*.spec.ts" | ||||||
|  |   ] | ||||||
|  | } | ||||||
							
								
								
									
										6
									
								
								projects/poweredsoft/ng-select/tsconfig.lib.prod.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								projects/poweredsoft/ng-select/tsconfig.lib.prod.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | { | ||||||
|  |   "extends": "./tsconfig.lib.json", | ||||||
|  |   "angularCompilerOptions": { | ||||||
|  |     "enableIvy": false | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								projects/poweredsoft/ng-select/tsconfig.spec.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								projects/poweredsoft/ng-select/tsconfig.spec.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | { | ||||||
|  |   "extends": "../../../tsconfig.json", | ||||||
|  |   "compilerOptions": { | ||||||
|  |     "outDir": "../../../out-tsc/spec", | ||||||
|  |     "types": [ | ||||||
|  |       "jasmine", | ||||||
|  |       "node" | ||||||
|  |     ] | ||||||
|  |   }, | ||||||
|  |   "files": [ | ||||||
|  |     "src/test.ts" | ||||||
|  |   ], | ||||||
|  |   "include": [ | ||||||
|  |     "**/*.spec.ts", | ||||||
|  |     "**/*.d.ts" | ||||||
|  |   ] | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								projects/poweredsoft/ng-select/tslint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								projects/poweredsoft/ng-select/tslint.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | { | ||||||
|  |   "extends": "../../../tslint.json", | ||||||
|  |   "rules": { | ||||||
|  |     "directive-selector": [ | ||||||
|  |       true, | ||||||
|  |       "attribute", | ||||||
|  |       "lib", | ||||||
|  |       "camelCase" | ||||||
|  |     ], | ||||||
|  |     "component-selector": [ | ||||||
|  |       true, | ||||||
|  |       "element", | ||||||
|  |       "lib", | ||||||
|  |       "kebab-case" | ||||||
|  |     ] | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "@poweredsoft/ngx-bootstrap", |   "name": "@poweredsoft/ngx-bootstrap", | ||||||
|   "version": "0.0.1", |   "version": "0.0.3", | ||||||
|   "peerDependencies": { |   "peerDependencies": { | ||||||
|     "@angular/common": "^9.1.9", |     "@angular/common": "^9.1.9", | ||||||
|     "@angular/core": "^9.1.9", |     "@angular/core": "^9.1.9", | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'; | |||||||
| import { ModalModule } from 'ngx-bootstrap/modal'; | import { ModalModule } from 'ngx-bootstrap/modal'; | ||||||
| import { CommandModalDirective } from './directives/command-modal.directive'; | import { CommandModalDirective } from './directives/command-modal.directive'; | ||||||
| import { CommandModalComponent } from './command-modal/command-modal.component'; | import { CommandModalComponent } from './command-modal/command-modal.component'; | ||||||
| import { InputValidatorDirective } from './directives/input-validator.directive'; | 
 | ||||||
| import { FormsModule } from '@angular/forms'; | import { FormsModule } from '@angular/forms'; | ||||||
| 
 | 
 | ||||||
| @NgModule({ | @NgModule({ | ||||||
| @ -12,7 +12,7 @@ import { FormsModule } from '@angular/forms'; | |||||||
|     ModalModule.forRoot(), |     ModalModule.forRoot(), | ||||||
|     FormsModule |     FormsModule | ||||||
|   ], |   ], | ||||||
|   declarations: [CommandModalDirective, CommandModalComponent, InputValidatorDirective], |   declarations: [CommandModalDirective, CommandModalComponent], | ||||||
|   exports: [CommandModalDirective] |   exports: [CommandModalDirective] | ||||||
| }) | }) | ||||||
| export class CommandModalModule { } | export class CommandModalModule { } | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ | |||||||
| <div class="modal-footer"> | <div class="modal-footer"> | ||||||
|     <button type="button" class="btn btn-light" (click)="modalRef.hide()" |     <button type="button" class="btn btn-light" (click)="modalRef.hide()" | ||||||
|         [disabled]="loading">{{ cancelText }}</button> |         [disabled]="loading">{{ cancelText }}</button> | ||||||
|     <button type="button" class="btn btn-primary" [disabled]="loading" (click)="onSubmit()">{{ commandText }}</button> |     <button type="button" class="btn btn-{{btnClass}}" [disabled]="loading" (click)="onSubmit()">{{ commandText }}</button> | ||||||
|     <br> |     <br> | ||||||
| 
 | 
 | ||||||
|     <div class="progress" style="width: 100%" *ngIf="loading"> |     <div class="progress" style="width: 100%" *ngIf="loading"> | ||||||
|  | |||||||
| @ -1,25 +0,0 @@ | |||||||
| import { async, ComponentFixture, TestBed } from '@angular/core/testing'; |  | ||||||
| 
 |  | ||||||
| import { CommandModalComponent } from './command-modal.component'; |  | ||||||
| 
 |  | ||||||
| describe('CommandModalComponent', () => { |  | ||||||
|   let component: CommandModalComponent; |  | ||||||
|   let fixture: ComponentFixture<CommandModalComponent>; |  | ||||||
| 
 |  | ||||||
|   beforeEach(async(() => { |  | ||||||
|     TestBed.configureTestingModule({ |  | ||||||
|       declarations: [ CommandModalComponent ] |  | ||||||
|     }) |  | ||||||
|     .compileComponents(); |  | ||||||
|   })); |  | ||||||
| 
 |  | ||||||
|   beforeEach(() => { |  | ||||||
|     fixture = TestBed.createComponent(CommandModalComponent); |  | ||||||
|     component = fixture.componentInstance; |  | ||||||
|     fixture.detectChanges(); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should create', () => { |  | ||||||
|     expect(component).toBeTruthy(); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @ -1,4 +1,4 @@ | |||||||
| import { Component, OnInit, TemplateRef, OnDestroy } from '@angular/core'; | import { Component, OnInit, TemplateRef, OnDestroy, EventEmitter } from '@angular/core'; | ||||||
| import { IDataSource } from '@poweredsoft/data'; | import { IDataSource } from '@poweredsoft/data'; | ||||||
| import { BsModalRef } from 'ngx-bootstrap/modal'; | import { BsModalRef } from 'ngx-bootstrap/modal'; | ||||||
| import { finalize} from 'rxjs/operators'; | import { finalize} from 'rxjs/operators'; | ||||||
| @ -23,6 +23,8 @@ export class CommandModalComponent implements OnInit, OnDestroy { | |||||||
|   cancelText: string; |   cancelText: string; | ||||||
|   form:NgForm; |   form:NgForm; | ||||||
|   validationMessage:string ; |   validationMessage:string ; | ||||||
|  |   btnClass:string; | ||||||
|  |   successEmitter: EventEmitter<any>;  | ||||||
| 
 | 
 | ||||||
|   private _notifyMessage: Subscription; |   private _notifyMessage: Subscription; | ||||||
|   private _validationError: Subscription; |   private _validationError: Subscription; | ||||||
| @ -62,11 +64,12 @@ export class CommandModalComponent implements OnInit, OnDestroy { | |||||||
|           this.loading = false; |           this.loading = false; | ||||||
|         }) |         }) | ||||||
|       ) |       ) | ||||||
|       .subscribe(success => { |       .subscribe(commandResult => { | ||||||
|         if (this.refreshOnSuccess) |         if (this.refreshOnSuccess) | ||||||
|           this.dataSource.refresh(); |           this.dataSource.refresh(); | ||||||
| 
 | 
 | ||||||
|         this.modalRef.hide(); |         this.modalRef.hide(); | ||||||
|  |         this.successEmitter.emit(commandResult); | ||||||
|       }, fail => { |       }, fail => { | ||||||
|         // you do not want to close on failure.. so just ignore..
 |         // you do not want to close on failure.. so just ignore..
 | ||||||
|       }); |       }); | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { Directive, HostListener, Input, TemplateRef } from '@angular/core'; | import { Directive, HostListener, Input, TemplateRef, Output, EventEmitter } from '@angular/core'; | ||||||
| import { IDataSource } from '@poweredsoft/data'; | import { IDataSource } from '@poweredsoft/data'; | ||||||
| import { BsModalService } from 'ngx-bootstrap/modal'; | import { BsModalService } from 'ngx-bootstrap/modal'; | ||||||
| import { CommandModalComponent } from '../command-modal/command-modal.component'; | import { CommandModalComponent } from '../command-modal/command-modal.component'; | ||||||
| @ -20,6 +20,9 @@ export class CommandModalDirective { | |||||||
|   @Input() commandText: string; |   @Input() commandText: string; | ||||||
|   @Input() cancelText: string; |   @Input() cancelText: string; | ||||||
|   @Input() animated: boolean; |   @Input() animated: boolean; | ||||||
|  |   @Input() btnClass:string; | ||||||
|  | 
 | ||||||
|  |   @Output() success: EventEmitter<any> = new EventEmitter<any>(); | ||||||
| 
 | 
 | ||||||
|   @HostListener('click') |   @HostListener('click') | ||||||
|   wasClicked() {             |   wasClicked() {             | ||||||
| @ -35,7 +38,9 @@ export class CommandModalDirective { | |||||||
|         title: this.commandTitle, |         title: this.commandTitle, | ||||||
|         refreshOnSuccess: this.refreshOnSuccess === undefined ? true : this.refreshOnSuccess, |         refreshOnSuccess: this.refreshOnSuccess === undefined ? true : this.refreshOnSuccess, | ||||||
|         commandText: this.commandText || 'OK', |         commandText: this.commandText || 'OK', | ||||||
|         cancelText: this.cancelText || 'Cancel' |         cancelText: this.cancelText || 'Cancel', | ||||||
|  |         successEmitter: this.success, | ||||||
|  |         btnClass: this.btnClass || 'primary' | ||||||
|       }; |       }; | ||||||
|       this.modalService.show(CommandModalComponent, { |       this.modalService.show(CommandModalComponent, { | ||||||
|         animated: this.animated === undefined ? true : this.animated, |         animated: this.animated === undefined ? true : this.animated, | ||||||
|  | |||||||
| @ -1,19 +0,0 @@ | |||||||
| 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,16 @@ | |||||||
|  | import { NgModule } from '@angular/core'; | ||||||
|  | import { CommonModule } from '@angular/common'; | ||||||
|  | import { CommandDirective } from './directives/command.directive'; | ||||||
|  | import { ConfirmModalModule } from '../confirm-modal/confirm-modal.module'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |   declarations: [CommandDirective], | ||||||
|  |   imports: [ | ||||||
|  |     CommonModule, | ||||||
|  |     ConfirmModalModule | ||||||
|  |   ], | ||||||
|  |   exports:[CommandDirective] | ||||||
|  | }) | ||||||
|  | export class CommandModule { } | ||||||
| @ -0,0 +1,70 @@ | |||||||
|  | import { Directive, Input, TemplateRef, HostListener, Output, EventEmitter } from '@angular/core'; | ||||||
|  | import { IDataSource } from '@poweredsoft/data'; | ||||||
|  | import { ConfirmModalService } from '../../confirm-modal/confirm-modal.service'; | ||||||
|  | 
 | ||||||
|  | @Directive({ | ||||||
|  |   selector: '[psbxCommand]' | ||||||
|  | }) | ||||||
|  | export class CommandDirective { | ||||||
|  | 
 | ||||||
|  |   constructor(private confirmModalService: ConfirmModalService) { } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   @Input() dataSource: IDataSource<any>; | ||||||
|  |   @Input() command: string; | ||||||
|  |   @Input() model: any; | ||||||
|  |   @Input() refreshOnSuccess: boolean; | ||||||
|  |   @Input() animated: boolean; | ||||||
|  | 
 | ||||||
|  |   @Input() confirm: boolean; | ||||||
|  |   @Input() confirmMessage: string; | ||||||
|  |   @Input() yesText: string; | ||||||
|  |   @Input() noText: string; | ||||||
|  |   @Input() yesClass: string; | ||||||
|  |   @Input() noClass: string; | ||||||
|  | 
 | ||||||
|  |   @Output() success: EventEmitter<any> = new EventEmitter<any>(); | ||||||
|  |   @Output() failure: EventEmitter<any> = new EventEmitter<any>(); | ||||||
|  | 
 | ||||||
|  |   private doCommand() { | ||||||
|  |     this.dataSource.resolveCommandModelByName({ | ||||||
|  |       command: this.command, | ||||||
|  |       model: this.model | ||||||
|  |     }).subscribe(commandModel => { | ||||||
|  |       this.dataSource.executeCommandByName(this.command, commandModel).subscribe( | ||||||
|  |         commandResult => { | ||||||
|  |           if (this.refreshOnSuccess !== false) | ||||||
|  |             this.dataSource.refresh(); | ||||||
|  | 
 | ||||||
|  |           this.success.emit(commandResult); | ||||||
|  |         }, | ||||||
|  |         commandError => { | ||||||
|  |           this.failure.emit(commandError); | ||||||
|  |         } | ||||||
|  |       ); | ||||||
|  |     }, resolveCommandError => { | ||||||
|  |       this.failure.emit(resolveCommandError); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   @HostListener('click') | ||||||
|  |   wasClicked() { | ||||||
|  | 
 | ||||||
|  |     if (this.confirm) { | ||||||
|  |       this.confirmModalService.confirm({ | ||||||
|  |         message: this.confirmMessage, | ||||||
|  |         yesText: this.yesText || 'yes', | ||||||
|  |         yesClass: this.yesClass || 'danger', | ||||||
|  |         noText: this.noText || 'no', | ||||||
|  |         noClass: this.noClass || 'light', | ||||||
|  |       }).subscribe(result => { | ||||||
|  |         if (result) | ||||||
|  |           this.doCommand(); | ||||||
|  |       }) | ||||||
|  |     } else { | ||||||
|  |       this.doCommand(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -1,6 +1,5 @@ | |||||||
| import { Component, OnInit, TemplateRef } from '@angular/core'; | import { Component, OnInit, TemplateRef, EventEmitter } from '@angular/core'; | ||||||
| import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal'; | import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal'; | ||||||
| import { ConfirmModalService } from '../../confirm-modal.service'; |  | ||||||
| import { Observer } from 'rxjs'; | import { Observer } from 'rxjs'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -19,7 +18,7 @@ export class ConfirmModalComponent implements OnInit { | |||||||
|   noClass: string; |   noClass: string; | ||||||
|   observer: Observer<boolean>; |   observer: Observer<boolean>; | ||||||
| 
 | 
 | ||||||
|   constructor(private modelRef: BsModalRef, private actionService: ConfirmModalService) { |   constructor(private modelRef: BsModalRef) { | ||||||
| 
 | 
 | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -28,11 +27,11 @@ export class ConfirmModalComponent implements OnInit { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   get yesButtonClass() { |   get yesButtonClass() { | ||||||
|     return `btn btn-sm btn-${this.yesClass}` |     return `btn btn-${this.yesClass}` | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   get noButtonClass() { |   get noButtonClass() { | ||||||
|     return `btn btn-sm btn-${this.noClass}` |     return `btn btn-${this.noClass}` | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   confirm(): void { |   confirm(): void { | ||||||
|  | |||||||
| @ -1,55 +0,0 @@ | |||||||
| 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 => { |  | ||||||
| 
 |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -3,18 +3,20 @@ import { CommonModule } from '@angular/common'; | |||||||
| import { ConfirmModalComponent } from './confirm-modal-components/confirm-modal/confirm-modal.component'; | import { ConfirmModalComponent } from './confirm-modal-components/confirm-modal/confirm-modal.component'; | ||||||
| import { ModalModule } from 'ngx-bootstrap/modal'; | import { ModalModule } from 'ngx-bootstrap/modal'; | ||||||
| import { ConfirmModalService } from './confirm-modal.service'; | import { ConfirmModalService } from './confirm-modal.service'; | ||||||
| import { ConfirmModalDirective } from './confirm-modal.directive'; | import { CommandModule } from '../command/command.module'; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @NgModule({ | @NgModule({ | ||||||
|   declarations: [ConfirmModalComponent, ConfirmModalDirective], |   declarations: [ConfirmModalComponent], | ||||||
|   imports: [ |   imports: [ | ||||||
|     CommonModule, |     CommonModule, | ||||||
|  |     //CommandModule,
 | ||||||
|     ModalModule.forRoot(), |     ModalModule.forRoot(), | ||||||
|      |      | ||||||
|   ], |   ], | ||||||
|   exports:[ConfirmModalDirective], |   exports:[], | ||||||
|   providers: [ConfirmModalService] |   providers: [ConfirmModalService] | ||||||
| }) | }) | ||||||
| export class ConfirmModalModule { } | export class ConfirmModalModule { } | ||||||
|  | |||||||
| @ -0,0 +1,27 @@ | |||||||
|  | import { NgModule } from '@angular/core'; | ||||||
|  | import { CommonModule } from '@angular/common'; | ||||||
|  | import { DataSourceTextFilterComponent } from './text-filter/data-source-text-filter.component'; | ||||||
|  | import { FormsModule } from '@angular/forms'; | ||||||
|  | import { DataSourceNumberFilterComponent } from './number-filter/data-source-number-filter.component'; | ||||||
|  | import { DataSourceDatetimeFilterComponent } from './datetime-filter/data-source-datetime-filter.component'; | ||||||
|  | import { BsDatepickerModule } from 'ngx-bootstrap/datepicker'; | ||||||
|  | import { PopoverModule } from 'ngx-bootstrap/popover'; | ||||||
|  | import { BsDropdownModule } from 'ngx-bootstrap/dropdown'; | ||||||
|  | import { TooltipModule } from 'ngx-bootstrap/tooltip'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |   declarations: [DataSourceTextFilterComponent, DataSourceNumberFilterComponent,DataSourceDatetimeFilterComponent], | ||||||
|  |   imports: [ | ||||||
|  |     CommonModule, | ||||||
|  |     FormsModule,     | ||||||
|  |     BsDatepickerModule.forRoot(), | ||||||
|  |     PopoverModule.forRoot(), | ||||||
|  |     BsDropdownModule.forRoot(), | ||||||
|  |     TooltipModule.forRoot() | ||||||
|  |   ], | ||||||
|  |   exports: [DataSourceTextFilterComponent, DataSourceNumberFilterComponent,DataSourceDatetimeFilterComponent] | ||||||
|  | }) | ||||||
|  | export class DataSourceFilterModule { } | ||||||
| @ -0,0 +1,76 @@ | |||||||
|  | <ng-template #popTemplate> | ||||||
|  |   <form (ngSubmit)="applyFilter()" novalidate> | ||||||
|  |     <div class="container" > | ||||||
|  |       <div class="row"> | ||||||
|  |         <select class="custom-select" title="Choose one of the following..." [(ngModel)]="filterType" [ngModelOptions]="{standalone: true}"> | ||||||
|  |             <option *ngFor="let filter of filterTypes" [value]="filter.value">{{filter.key}}</option> | ||||||
|  |         </select>     | ||||||
|  |     </div> | ||||||
|  |       <div class="row mt-1 mb-1"> | ||||||
|  |           <input *ngIf="!isRangeFilter"  | ||||||
|  |                  type="text" | ||||||
|  |                  placeholder="Datepicker" | ||||||
|  |                  class="form-control" | ||||||
|  |                  bsDatepicker [(ngModel)]="filterValue" [ngModelOptions]="{standalone: true}">  | ||||||
|  |       </div> | ||||||
|  |        | ||||||
|  |       <div class="row mt-1 mb-1"> | ||||||
|  |         <input *ngIf="isRangeFilter" type="text" | ||||||
|  |         placeholder="Daterangepicker" | ||||||
|  |         class="form-control" | ||||||
|  |         bsDaterangepicker [(ngModel)]="filterValue" [ngModelOptions]="{standalone: true}">        | ||||||
|  |     </div> | ||||||
|  |      | ||||||
|  |       <div class="row mt-2"> | ||||||
|  |         <button class="btn btn-primary mr-1" type="submit" >Filter</button> | ||||||
|  |         <button type="button" class="btn btn-warning" *ngIf="!isFiltering" (click)="pop.hide()">Hide</button> | ||||||
|  |         <button type="button" class="btn btn-dark" *ngIf="isFiltering" (click)="clearFilter()">Clear</button> | ||||||
|  |       </div> | ||||||
|  |   </div> | ||||||
|  |   </form> | ||||||
|  | 
 | ||||||
|  |    | ||||||
|  | </ng-template> | ||||||
|  | 
 | ||||||
|  | <button [popover]="popTemplate" class="btn btn-default" [(isOpen)]="filterPopUpOpened" [outsideClick]="true" #pop="bs-popover"> | ||||||
|  |     <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||||
|  | 	 viewBox="0 0 477.875 477.875" style="enable-background:new 0 0 477.875 477.875;" xml:space="preserve" fill-opacity="0.5" [tooltip]="showTooltip()" [tooltipEnable]="!filterPopUpOpened" width="13px" height="13px" [ngStyle]="{'fill': isFiltering ? 'red': 'black', 'fill-opacity': isFiltering ? '1': '0.5'}"> | ||||||
|  | <g> | ||||||
|  | 	<g> | ||||||
|  | 		<path d="M460.804,0H17.071C7.645,0,0.004,7.641,0.004,17.067V102.4c-0.004,4.842,2.05,9.458,5.649,12.698l165.018,148.514V460.8 | ||||||
|  | 			c-0.004,9.426,7.633,17.07,17.059,17.075c2.651,0.001,5.266-0.615,7.637-1.8l102.4-51.2c5.786-2.891,9.441-8.806,9.438-15.275 | ||||||
|  | 			V263.612l165.018-148.48c3.608-3.247,5.662-7.878,5.649-12.732V17.067C477.871,7.641,470.23,0,460.804,0z"/> | ||||||
|  | 	</g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
|  | </button> | ||||||
| @ -0,0 +1,150 @@ | |||||||
|  | import { Component, OnInit, Input, Output, EventEmitter} from '@angular/core'; | ||||||
|  | import { IDataSource, ISimpleFilter, ICompositeFilter, IFilter,FilterType } from '@poweredsoft/data'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   selector: 'psbx-ds-datetime-filter', | ||||||
|  |   templateUrl: './data-source-datetime-filter.component.html', | ||||||
|  |   styleUrls: ['./data-source-datetime-filter.component.scss'] | ||||||
|  | }) | ||||||
|  | export class DataSourceDatetimeFilterComponent implements OnInit { | ||||||
|  | 
 | ||||||
|  |   @Input() path: string; | ||||||
|  |   @Input() dataSource : IDataSource<any>;  | ||||||
|  |   @Input() filterType: string; | ||||||
|  |   @Output() filterTypeChanged: EventEmitter<string> = new EventEmitter<string>(); | ||||||
|  | 
 | ||||||
|  |   filterPopUpOpened: boolean = false;  | ||||||
|  |   isFiltering: boolean; | ||||||
|  |   filterValue: Date = null;  | ||||||
|  |   filterTypes = [ | ||||||
|  |     {key:'Equal', value: 'Equal'}, | ||||||
|  |     {key:'Greater Than', value: 'GreaterThan'}, | ||||||
|  |     {key:'Less Than', value: 'LessThan'},     | ||||||
|  |     {key:'Greater Than Equal', value: 'GreaterThanOrEqual'}, | ||||||
|  |     {key:'Less Than Equal', value: 'LessThanOrEqual'},     | ||||||
|  |     {key:'Range', value: FilterType.COMPOSITE } | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   bsInlineValue = new Date(); | ||||||
|  |   bsInlineRangeValue: Date[]; | ||||||
|  |   maxDate = new Date(); | ||||||
|  |   | ||||||
|  |   constructor() { | ||||||
|  |     this.maxDate.setDate(this.maxDate.getDate() + 7); | ||||||
|  |     this.bsInlineRangeValue = [this.bsInlineValue, this.maxDate]; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get isRangeFilter() { | ||||||
|  |     return this.filterType == FilterType.COMPOSITE; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ngOnInit(): void { | ||||||
|  |     if (!this.filterType) | ||||||
|  |       this.filterType = 'Equal'; | ||||||
|  |   } | ||||||
|  |   showTooltip(){ | ||||||
|  |     return "Filter by "+ this.path; | ||||||
|  |   } | ||||||
|  |   clearFilter() { | ||||||
|  |      | ||||||
|  |     this.filterValue = null; | ||||||
|  |     this.isFiltering = false; | ||||||
|  |     const existingFilter = this.dataSource.filters.find(t => (t as ISimpleFilter).path == this.path) as ISimpleFilter;     | ||||||
|  |     if (existingFilter) { | ||||||
|  |       this.dataSource.query({ | ||||||
|  |         page: 1, | ||||||
|  |         filters: this.dataSource.filters.filter(t => t != existingFilter) | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     if (this.isRangeFilter){ | ||||||
|  |       | ||||||
|  |       let existingFilter2 = this.dataSource.filters.find(t=> t.type == 'Composite'); | ||||||
|  |       this.dataSource.query({ | ||||||
|  |         page: 1, | ||||||
|  |         filters: this.dataSource.filters.filter(t => t != existingFilter2) | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   applyFilter(){ | ||||||
|  | 
 | ||||||
|  |     this.isFiltering = true; | ||||||
|  |     const filters = this.dataSource.filters; | ||||||
|  |     let compositeF: any = null; | ||||||
|  |     let freshFilter: ISimpleFilter = null; | ||||||
|  |     let startDate:Date; | ||||||
|  |     let endDate:Date; | ||||||
|  | 
 | ||||||
|  |     // TODO create filter here.
 | ||||||
|  |     if(Array.isArray(this.filterValue)){ //check if it's a dateRange value 
 | ||||||
|  |       startDate = this.filterValue[0]; | ||||||
|  |       endDate = this.filterValue[1]; | ||||||
|  |       compositeF = { | ||||||
|  |         type: FilterType.COMPOSITE, | ||||||
|  |         filters: [ | ||||||
|  |           { | ||||||
|  |             path: this.path, | ||||||
|  |             type: 'GREATERTHANOREQUAL', | ||||||
|  |             value: startDate,  | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             and: true, | ||||||
|  |             path: this.path, | ||||||
|  |             type: 'LESSTHANOREQUAL', | ||||||
|  |             value: endDate, | ||||||
|  |           } | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |       | ||||||
|  |     }else{ | ||||||
|  |       freshFilter = { | ||||||
|  |         type: this.filterType, | ||||||
|  |         and: true, | ||||||
|  |         path: this.path, | ||||||
|  |         value: this.filterValue | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // TODO???
 | ||||||
|  |     // set this for gql better handling of variant.
 | ||||||
|  |     //(freshFilter as IGraphQLFilter).__gqlVariantType = 'DATETIME';
 | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  |     const existingFilterIndex = filters.findIndex(t => { | ||||||
|  |         if (t.type == 'COMPOSITE') { | ||||||
|  |           const compositeFilter = t as ICompositeFilter; | ||||||
|  |           return compositeFilter.filters && compositeFilter.filters.length  | ||||||
|  |             && compositeFilter[0].path == this.path; | ||||||
|  |         } else { | ||||||
|  |           return (t as ISimpleFilter).path == this.path; | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     if (existingFilterIndex == -1) { | ||||||
|  |       // create it.
 | ||||||
|  |       if(compositeF){                         | ||||||
|  |         filters.push(compositeF); | ||||||
|  |       }else{ | ||||||
|  |         filters.push(freshFilter); | ||||||
|  |       } | ||||||
|  |       | ||||||
|  |     } else { | ||||||
|  |       // replace it.
 | ||||||
|  |       if(compositeF){ | ||||||
|  |         filters[existingFilterIndex] = compositeF; | ||||||
|  |       }else{ | ||||||
|  |         filters[existingFilterIndex] = freshFilter; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     this.dataSource.query({ | ||||||
|  |       filters: filters, | ||||||
|  |       page: 1 | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,64 @@ | |||||||
|  | <ng-template #popTemplate> | ||||||
|  |     <form (ngSubmit)="applyFilter()" novalidate> | ||||||
|  |         <div class="container" > | ||||||
|  |             <div class="row"> | ||||||
|  |                 <select class="custom-select" title="Choose one of the following..." [(ngModel)]="filterType" [ngModelOptions]="{standalone: true}"> | ||||||
|  |                     <option *ngFor="let filter of filterTypes" [value]="filter.value">{{filter.key}}</option> | ||||||
|  |                 </select>     | ||||||
|  |             </div> | ||||||
|  |             | ||||||
|  |             <div class="row mt-1 mb-1"> | ||||||
|  |                 <input type="number" class="form-control" placeholder="Value" aria-label="number" | ||||||
|  |             aria-describedby="basic-addon1" [(ngModel)]="filterValue" [ngModelOptions]="{standalone: true}"> | ||||||
|  |             </div> | ||||||
|  |              | ||||||
|  |             <button class="btn btn-primary mr-1">Filter</button> | ||||||
|  |             <button type="button" class="btn btn-warning" *ngIf="!isFiltering" (click)="pop.hide()">Hide</button> | ||||||
|  |             <button type="button" class="btn btn-dark" *ngIf="isFiltering" (click)="clearFilter()">Clear</button> | ||||||
|  |              | ||||||
|  |         </div> | ||||||
|  |     </form> | ||||||
|  | </ng-template> | ||||||
|  | 
 | ||||||
|  | <button [popover]="popTemplate" class="btn btn-default" [(isOpen)]="filterIsOpenned"  [outsideClick]="true" #pop="bs-popover"> | ||||||
|  |     <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||||
|  | 	 viewBox="0 0 477.875 477.875" style="enable-background:new 0 0 477.875 477.875;" xml:space="preserve" fill-opacity="0.5" [tooltip]="showTooltip()" [tooltipEnable]="!filterIsOpenned" width="13px" height="13px" [ngStyle]="{'fill': isFiltering ? 'red': 'black', 'fill-opacity': isFiltering ? '1': '0.5'}"> | ||||||
|  | <g> | ||||||
|  | 	<g> | ||||||
|  | 		<path d="M460.804,0H17.071C7.645,0,0.004,7.641,0.004,17.067V102.4c-0.004,4.842,2.05,9.458,5.649,12.698l165.018,148.514V460.8 | ||||||
|  | 			c-0.004,9.426,7.633,17.07,17.059,17.075c2.651,0.001,5.266-0.615,7.637-1.8l102.4-51.2c5.786-2.891,9.441-8.806,9.438-15.275 | ||||||
|  | 			V263.612l165.018-148.48c3.608-3.247,5.662-7.878,5.649-12.732V17.067C477.871,7.641,470.23,0,460.804,0z"/> | ||||||
|  | 	</g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
|  | </button> | ||||||
| @ -0,0 +1,71 @@ | |||||||
|  | import { Component, OnInit, Input, Output, EventEmitter, ElementRef, ViewChild } from '@angular/core'; | ||||||
|  | import { IDataSource,IFilter, ISimpleFilter } from '@poweredsoft/data'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   selector: 'psbx-ds-number-filter', | ||||||
|  |   templateUrl: './data-source-number-filter.component.html', | ||||||
|  |   styleUrls: ['./data-source-number-filter.component.scss'] | ||||||
|  | }) | ||||||
|  | export class DataSourceNumberFilterComponent implements OnInit { | ||||||
|  |   @Input() dataSource : IDataSource<any>;    | ||||||
|  |   @Input() path:string; | ||||||
|  |   | ||||||
|  |   filterType: string = 'Equal'; | ||||||
|  |   filterValue: number = 0;  | ||||||
|  |   isFiltering: boolean; | ||||||
|  |   filterTypes = [     | ||||||
|  |     {key:'Equals', value: 'Equal'},  | ||||||
|  |     {key:'Greater Than', value: 'GreaterThan'}, | ||||||
|  |     {key:'Less Than', value: 'LessThan'},     | ||||||
|  |     {key:'Greater Than Equal', value: 'GreaterThanOrEqual'}, | ||||||
|  |     {key:'Less Than Equal', value: 'LessThanOrEqual'},     | ||||||
|  |   ]; | ||||||
|  |   filterIsOpenned: boolean = false; | ||||||
|  | 
 | ||||||
|  |   constructor() { } | ||||||
|  |   | ||||||
|  | 
 | ||||||
|  |   ngOnInit(): void { | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   clearFilter() { | ||||||
|  |     this.filterValue = 0; | ||||||
|  |     this.isFiltering = false; | ||||||
|  |     const existingFilter = this.dataSource.filters.find(t => (t as ISimpleFilter).path == this.path) as ISimpleFilter; | ||||||
|  |     if (existingFilter) { | ||||||
|  |       this.dataSource.query({ | ||||||
|  |         page: 1, | ||||||
|  |         filters: this.dataSource.filters.filter(t => t != existingFilter) | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   applyFilter(){ | ||||||
|  |     this.isFiltering = true; | ||||||
|  |     const filters = this.dataSource.filters; | ||||||
|  |     const existingFilter = filters.find(t => (t as ISimpleFilter).path == this.path) as ISimpleFilter; | ||||||
|  |     if (existingFilter) { | ||||||
|  |       existingFilter.type = this.filterType; | ||||||
|  |       existingFilter.value =this.filterValue.toString(); | ||||||
|  |     } else { | ||||||
|  |       filters.push(<ISimpleFilter>{ | ||||||
|  |         and: true, | ||||||
|  |         type: this.filterType, | ||||||
|  |         path: this.path,  | ||||||
|  |         value: this.filterValue.toString() | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     this.dataSource.query({ | ||||||
|  |       filters: filters, | ||||||
|  |       page: 1 | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   showTooltip(){ | ||||||
|  |     return "Filter by "+ this.path; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,66 @@ | |||||||
|  | <ng-template #popTemplate> | ||||||
|  | 
 | ||||||
|  |     <form (ngSubmit)="applyFilter(pop)" novalidate> | ||||||
|  |          | ||||||
|  |         <div class="container" > | ||||||
|  |             <div class="row"> | ||||||
|  |                 <select class="custom-select" title="Choose one of the following..." [(ngModel)]="filterType" [ngModelOptions]="{standalone: true}"> | ||||||
|  |                     <option *ngFor="let filter of filterTypes" [value]="filter.value">{{filter.key}}</option> | ||||||
|  |                 </select>     | ||||||
|  |             </div> | ||||||
|  |          | ||||||
|  |             <div class="row mt-1 mb-1"> | ||||||
|  |                 <input type="text" class="form-control" placeholder="Value" aria-label="Username" | ||||||
|  |             aria-describedby="basic-addon1" [(ngModel)]="filterValue" [ngModelOptions]="{standalone: true}" > | ||||||
|  |             </div> | ||||||
|  |              | ||||||
|  |             <button class="btn btn-primary mr-1" type="submit">Filter</button> | ||||||
|  |             <button type="button" class="btn btn-warning" *ngIf="!isFiltering" (click)="pop.hide()">Hide</button> | ||||||
|  |             <button type="button" class="btn btn-dark" *ngIf="isFiltering" (click)="clearFilter()">Clear</button> | ||||||
|  |              | ||||||
|  |         </div> | ||||||
|  |     </form> | ||||||
|  | </ng-template> | ||||||
|  | 
 | ||||||
|  | <button [popover]="popTemplate" class="btn btn-default" [(isOpen)]="filterIsOpenned"  [outsideClick]="true" #pop="bs-popover"> | ||||||
|  |     <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||||
|  | 	 viewBox="0 0 477.875 477.875" style="enable-background:new 0 0 477.875 477.875;" xml:space="preserve" fill-opacity="0.5" [tooltip]="showTooltip()" [tooltipEnable]="!filterIsOpenned" width="13px" height="13px" [ngStyle]="{'fill': isFiltering ? 'red': 'black', 'fill-opacity': isFiltering ? '1': '0.5'}"> | ||||||
|  | <g> | ||||||
|  | 	<g> | ||||||
|  | 		<path d="M460.804,0H17.071C7.645,0,0.004,7.641,0.004,17.067V102.4c-0.004,4.842,2.05,9.458,5.649,12.698l165.018,148.514V460.8 | ||||||
|  | 			c-0.004,9.426,7.633,17.07,17.059,17.075c2.651,0.001,5.266-0.615,7.637-1.8l102.4-51.2c5.786-2.891,9.441-8.806,9.438-15.275 | ||||||
|  | 			V263.612l165.018-148.48c3.608-3.247,5.662-7.878,5.649-12.732V17.067C477.871,7.641,470.23,0,460.804,0z"/> | ||||||
|  | 	</g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
|  | </button> | ||||||
| @ -0,0 +1,75 @@ | |||||||
|  | import { Component, OnInit, Input } from '@angular/core'; | ||||||
|  | import { IDataSource} from '@poweredsoft/data'; | ||||||
|  | import { ISimpleFilter } from '@poweredsoft/data'; | ||||||
|  | import { PopoverDirective } from 'ngx-bootstrap/popover'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   selector: 'psbx-ds-text-filter', | ||||||
|  |   templateUrl: './data-source-text-filter.component.html', | ||||||
|  |   styleUrls: ['./data-source-text-filter.component.scss'] | ||||||
|  | }) | ||||||
|  | export class DataSourceTextFilterComponent implements OnInit { | ||||||
|  | 
 | ||||||
|  |   @Input() dataSource : IDataSource<any>;    | ||||||
|  |   @Input() path:string; | ||||||
|  |   | ||||||
|  |   filterType: string = 'Contains'; | ||||||
|  |   filterValue: string = null;  | ||||||
|  |   isFiltering: boolean; | ||||||
|  |   filterTypes = [ | ||||||
|  |     {key:'Contains', value: 'Contains'},  | ||||||
|  |     {key:'Equals', value: 'Equal'},  | ||||||
|  |     {key:'Starts With', value: 'startsWith'}, | ||||||
|  |     {key:'Ends With', value: 'endsWith'} | ||||||
|  |   ]; | ||||||
|  |   filterIsOpenned: boolean = false; | ||||||
|  | 
 | ||||||
|  |   constructor() { } | ||||||
|  |   | ||||||
|  | 
 | ||||||
|  |   ngOnInit(): void { | ||||||
|  |      | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   clearFilter() { | ||||||
|  |     this.filterValue = ''; | ||||||
|  |     this.isFiltering = false; | ||||||
|  |     const existingFilter = this.dataSource.filters.find(t => (t as ISimpleFilter).path == this.path) as ISimpleFilter; | ||||||
|  |     if (existingFilter) { | ||||||
|  |       this.dataSource.query({ | ||||||
|  |         page: 1, | ||||||
|  |         filters: this.dataSource.filters.filter(t => t != existingFilter) | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   applyFilter(pop: PopoverDirective = null){ | ||||||
|  |     this.isFiltering = true; | ||||||
|  |     const filters = this.dataSource.filters; | ||||||
|  |     const existingFilter = filters.find(t => (t as ISimpleFilter).path == this.path) as ISimpleFilter; | ||||||
|  |     if (existingFilter) { | ||||||
|  |       existingFilter.type = this.filterType; | ||||||
|  |       existingFilter.value = this.filterValue; | ||||||
|  |     } else { | ||||||
|  |       filters.push(<ISimpleFilter>{ | ||||||
|  |         and: true, | ||||||
|  |         type: this.filterType, | ||||||
|  |         path: this.path,  | ||||||
|  |         value: this.filterValue | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     this.dataSource.query({ | ||||||
|  |       filters: filters, | ||||||
|  |       page: 1 | ||||||
|  |     }) | ||||||
|  | 
 | ||||||
|  |     if (pop)  | ||||||
|  |       pop.hide(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   showTooltip(){ | ||||||
|  |     return "Filter by "+ this.path; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,14 @@ | |||||||
|  | import { NgModule } from '@angular/core'; | ||||||
|  | import { CommonModule } from '@angular/common'; | ||||||
|  | import { DataSourceSortingComponent } from './ds-sorting/data-source-sorting.component'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |   declarations: [DataSourceSortingComponent], | ||||||
|  |   imports: [ | ||||||
|  |     CommonModule | ||||||
|  |   ], | ||||||
|  |   exports:[DataSourceSortingComponent] | ||||||
|  | }) | ||||||
|  | export class DataSourceSortingModule { } | ||||||
| @ -0,0 +1,3 @@ | |||||||
|  | <span> | ||||||
|  |     <span class="caret dropdown-toggle" [class.not-sorting-state]="!isSorting" [class.sort-desc]="!isAscending" (click)="sorting()"></span>     | ||||||
|  | </span> | ||||||
| @ -0,0 +1,16 @@ | |||||||
|  | :host span.dropdown-toggle.sort-desc{ | ||||||
|  |     transform: rotate(180deg); | ||||||
|  |     display: inline-block; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | :host span{ | ||||||
|  |     margin: 10px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | :host .not-sorting-state{ | ||||||
|  |     opacity: 0.3; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | :host .not-sorting-state:hover{ | ||||||
|  |     opacity: 1; | ||||||
|  | } | ||||||
| @ -0,0 +1,38 @@ | |||||||
|  | import { Component, OnInit, Input } from '@angular/core'; | ||||||
|  | import { IDataSource } from '@poweredsoft/data'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   selector: 'psbx-ds-sorting', | ||||||
|  |   templateUrl: './data-source-sorting.component.html', | ||||||
|  |   styleUrls: ['./data-source-sorting.component.scss'] | ||||||
|  | }) | ||||||
|  | export class DataSourceSortingComponent implements OnInit { | ||||||
|  | 
 | ||||||
|  |   @Input() dataSource : IDataSource<any>; | ||||||
|  |   @Input() path:string;  | ||||||
|  |   isSorting: boolean =false;  | ||||||
|  |   isAscending:boolean = false;   | ||||||
|  |   constructor() { } | ||||||
|  | 
 | ||||||
|  |   ngOnInit(): void { | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   sorting(){ | ||||||
|  |     this.isSorting = true; | ||||||
|  |     this.isAscending = !this.isAscending; | ||||||
|  |     const existingSort = this.dataSource.sorts.find(t => t.path == this.path); | ||||||
|  |     if (existingSort){ | ||||||
|  |       existingSort.ascending = (this.isAscending)? true : false; | ||||||
|  |     }else{ | ||||||
|  |       this.dataSource.sorts.push({ | ||||||
|  |         path: this.path, | ||||||
|  |         ascending: (this.isAscending)? true : false  | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  |     this.dataSource.query({ | ||||||
|  |       sorts: this.dataSource.sorts, | ||||||
|  |       page: 1 | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -29,9 +29,10 @@ export class FormGroupCommandModalDirective { | |||||||
|   @Input() refreshOnSuccess: boolean; |   @Input() refreshOnSuccess: boolean; | ||||||
|   @Input() commandText: string; |   @Input() commandText: string; | ||||||
|   @Input() cancelText: string; |   @Input() cancelText: string; | ||||||
|   @Input() isConfirmModal:boolean; |  | ||||||
|   @Output() formCreate: EventEmitter<IModelFormCreateEvent> = new EventEmitter<IModelFormCreateEvent>(); |   @Output() formCreate: EventEmitter<IModelFormCreateEvent> = new EventEmitter<IModelFormCreateEvent>(); | ||||||
| 
 | 
 | ||||||
|  |   @Output() success: EventEmitter<any> = new EventEmitter<any>(); | ||||||
|  | 
 | ||||||
|   constructor(private modalService: BsModalService) { } |   constructor(private modalService: BsModalService) { } | ||||||
| 
 | 
 | ||||||
|   @HostListener('click') |   @HostListener('click') | ||||||
| @ -47,25 +48,6 @@ export class FormGroupCommandModalDirective { | |||||||
|         shouldSetCommandModel: true |         shouldSetCommandModel: true | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       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); |         this.formCreate.emit(event); | ||||||
|         if (event.formGroup == null) |         if (event.formGroup == null) | ||||||
|           throw new Error('form group should be set, after form createEvent'); |           throw new Error('form group should be set, after form createEvent'); | ||||||
| @ -82,61 +64,18 @@ export class FormGroupCommandModalDirective { | |||||||
|           commandText: this.commandText || 'OK', |           commandText: this.commandText || 'OK', | ||||||
|           cancelText: this.cancelText || 'Cancel', |           cancelText: this.cancelText || 'Cancel', | ||||||
|           modelForm: event.formGroup, |           modelForm: event.formGroup, | ||||||
|           commandModel:commandModel |           commandModel:commandModel, | ||||||
|  |           successEmitter: this.success | ||||||
|         }; |         }; | ||||||
|        |        | ||||||
|         this.modalService.show(FormGroupCommandModalComponent, { |         this.modalService.show(FormGroupCommandModalComponent, { | ||||||
|           animated: this.animated === undefined ? true : this.animated, |           animated: this.animated === undefined ? true : this.animated, | ||||||
|           initialState |           initialState | ||||||
|         }); |         }); | ||||||
|       } | 
 | ||||||
|     }, error => { |     }, error => { | ||||||
| 
 | 
 | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // @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,
 |  | ||||||
|   //       template: this.template,
 |  | ||||||
|   //       title: this.commandTitle,
 |  | ||||||
|   //       refreshOnSuccess: this.refreshOnSuccess === undefined ? true : this.refreshOnSuccess,
 |  | ||||||
|   //       commandText: this.commandText || 'OK',
 |  | ||||||
|   //       cancelText: this.cancelText || 'Cancel',
 |  | ||||||
|   //       modelForm: event.formGroup,
 |  | ||||||
|   //       commandModel:commandModel
 |  | ||||||
|   //     };
 |  | ||||||
|        |  | ||||||
|   //     this.modalService.show(FormGroupCommandModalComponent, {
 |  | ||||||
|   //       animated: this.animated === undefined ? true : this.animated,
 |  | ||||||
|   //       initialState
 |  | ||||||
|   //     });
 |  | ||||||
| 
 |  | ||||||
|   //   }, error => {
 |  | ||||||
| 
 |  | ||||||
|   //   });
 |  | ||||||
|   // }
 |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { Component, OnInit, TemplateRef } from '@angular/core'; | import { Component, OnInit, TemplateRef, OnDestroy, EventEmitter } from '@angular/core'; | ||||||
| import { BsModalRef } from 'ngx-bootstrap/modal'; | import { BsModalRef } from 'ngx-bootstrap/modal'; | ||||||
| import { IDataSource } from '@poweredsoft/data'; | import { IDataSource } from '@poweredsoft/data'; | ||||||
| import { finalize } from 'rxjs/operators'; | import { finalize } from 'rxjs/operators'; | ||||||
| @ -10,7 +10,7 @@ import { FormGroup, FormControl } from '@angular/forms'; | |||||||
|   templateUrl: './form-group-command-modal.component.html', |   templateUrl: './form-group-command-modal.component.html', | ||||||
|   styleUrls: ['./form-group-command-modal.component.scss'] |   styleUrls: ['./form-group-command-modal.component.scss'] | ||||||
| }) | }) | ||||||
| export class FormGroupCommandModalComponent implements OnInit { | export class FormGroupCommandModalComponent implements OnInit, OnDestroy { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|   modelForm: FormGroup; |   modelForm: FormGroup; | ||||||
| @ -24,10 +24,13 @@ export class FormGroupCommandModalComponent implements OnInit { | |||||||
|   cancelText: string; |   cancelText: string; | ||||||
|   errorMessage: string; |   errorMessage: string; | ||||||
|   commandModel:any;  |   commandModel:any;  | ||||||
|  |   successEmitter: EventEmitter<any>; | ||||||
| 
 | 
 | ||||||
|   private _notifyMessage: Subscription; |   private _notifyMessage: Subscription; | ||||||
|   private _validationError: Subscription; |   private _validationError: Subscription; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|   constructor(public modalRef: BsModalRef) { } |   constructor(public modalRef: BsModalRef) { } | ||||||
| 
 | 
 | ||||||
|   ngOnDestroy(): void { |   ngOnDestroy(): void { | ||||||
| @ -37,9 +40,9 @@ export class FormGroupCommandModalComponent implements OnInit { | |||||||
| 
 | 
 | ||||||
|   ngOnInit(): void { |   ngOnInit(): void { | ||||||
|     this.errorMessage = null; |     this.errorMessage = null; | ||||||
|     // this._notifyMessage = this.dataSource.notifyMessage$.subscribe(message => {
 |     this._notifyMessage = this.dataSource.notifyMessage$.subscribe(message => { | ||||||
|        |        | ||||||
|     // });
 |     }); | ||||||
|     |     | ||||||
|     this._validationError = this.dataSource.validationError$.subscribe(validatorErrors => {       |     this._validationError = this.dataSource.validationError$.subscribe(validatorErrors => {       | ||||||
|       let validationSummary = ''; |       let validationSummary = ''; | ||||||
| @ -71,11 +74,12 @@ export class FormGroupCommandModalComponent implements OnInit { | |||||||
|           this.loading = false; |           this.loading = false; | ||||||
|         }) |         }) | ||||||
|       ) |       ) | ||||||
|       .subscribe(success => { |       .subscribe(commandResult => { | ||||||
|         if (this.refreshOnSuccess) |         if (this.refreshOnSuccess) | ||||||
|           this.dataSource.refresh(); |           this.dataSource.refresh(); | ||||||
| 
 | 
 | ||||||
|         this.modalRef.hide(); |         this.modalRef.hide(); | ||||||
|  |         this.successEmitter.emit(commandResult); | ||||||
|       }, fail => { |       }, fail => { | ||||||
|         // you do not want to close on failure.. so just ignore..
 |         // you do not want to close on failure.. so just ignore..
 | ||||||
|       }); |       }); | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| import { NgModule } from '@angular/core'; | import { NgModule } from '@angular/core'; | ||||||
| import { CommonModule } from '@angular/common'; | import { CommonModule } from '@angular/common'; | ||||||
| import { DataSourcePaginationComponent } from './data-source-pagination/data-source-pagination.component'; | import { DataSourcePaginationComponent } from './data-source-pagination/data-source-pagination.component'; | ||||||
| import { PaginationModule } from 'ngx-bootstrap/pagination'; | import { PaginationModule as ValorPaginationModule } from 'ngx-bootstrap/pagination'; | ||||||
| import { FormsModule } from '@angular/forms'; | import { FormsModule } from '@angular/forms'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -9,9 +9,9 @@ import { FormsModule } from '@angular/forms'; | |||||||
|   declarations: [DataSourcePaginationComponent], |   declarations: [DataSourcePaginationComponent], | ||||||
|   imports: [ |   imports: [ | ||||||
|     CommonModule, |     CommonModule, | ||||||
|     PaginationModule.forRoot(), |     ValorPaginationModule.forRoot(), | ||||||
|     FormsModule |     FormsModule | ||||||
|   ], |   ], | ||||||
|   exports:[DataSourcePaginationComponent] |   exports:[DataSourcePaginationComponent] | ||||||
| }) | }) | ||||||
| export class psbxPaginationModule { } | export class PaginationModule { } | ||||||
| @ -6,10 +6,17 @@ export * from './lib/command-modal/command-modal.module'; | |||||||
| export * from './lib/command-modal/directives/command-modal.directive'; | 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/form-group-command-modal.module'; | ||||||
| export * from './lib/form-group-command-modal/directives/form-group-command-modal.directive'; | export * from './lib/form-group-command-modal/directives/form-group-command-modal.directive'; | ||||||
| export * from './lib/pagination/psbxPagination.module'; | export * from './lib/pagination/Pagination.module'; | ||||||
| export * from './lib/pagination/data-source-pagination/data-source-pagination.component'; | 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.module'; | ||||||
| export * from './lib/confirm-modal/confirm-modal.service'; | 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.module'; | ||||||
| export * from './lib/spinner/spinner/spinner.component'; | export * from './lib/spinner/spinner/spinner.component'; | ||||||
|  | export * from './lib/data-source-filter/data-source-filter.module'; | ||||||
|  | export * from './lib/data-source-filter/text-filter/data-source-text-filter.component'; | ||||||
|  | export * from './lib/data-source-filter/number-filter/data-source-number-filter.component'; | ||||||
|  | export * from './lib/data-source-filter/datetime-filter/data-source-datetime-filter.component'; | ||||||
|  | export * from './lib/data-source-sorting/data-source-sorting.module'; | ||||||
|  | export * from './lib/data-source-sorting/ds-sorting/data-source-sorting.component'; | ||||||
|  | export * from './lib/command/command.module'; | ||||||
|  | export * from './lib/command/directives/command.directive'; | ||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "@poweredsoft/ngx-cdk-ui", |   "name": "@poweredsoft/ngx-cdk-ui", | ||||||
|   "version": "0.0.1", |   "version": "0.0.2", | ||||||
|   "peerDependencies": { |   "peerDependencies": { | ||||||
|     "@angular/common": "^9.1.9", |     "@angular/common": "^9.1.9", | ||||||
|     "@angular/core": "^9.1.9" |     "@angular/core": "^9.1.9" | ||||||
|  | |||||||
| @ -7,6 +7,8 @@ import { DataGridCellDirective } from './directives/data-grid-cell.directive'; | |||||||
| import { DataGridFooterDirective } from './directives/data-grid-footer.directive'; | import { DataGridFooterDirective } from './directives/data-grid-footer.directive'; | ||||||
| import { DataGridHeaderDirective } from './directives/data-grid-header.directive'; | import { DataGridHeaderDirective } from './directives/data-grid-header.directive'; | ||||||
| import { DataGridLoaderDirective } from './directives/data-grid-loader.directive'; | import { DataGridLoaderDirective } from './directives/data-grid-loader.directive'; | ||||||
|  | import { DataGridCellFilterDirective } from './directives/data-grid-cell-filter.directive'; | ||||||
|  | import { DataGridColSortDirective } from './directives/data-grid-col-sort.directive'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -16,7 +18,7 @@ import { DataGridLoaderDirective } from './directives/data-grid-loader.directive | |||||||
|   declarations: [ |   declarations: [ | ||||||
|     DataGridComponent,DataGridColDirective,DataGridColHeaderDirective, |     DataGridComponent,DataGridColDirective,DataGridColHeaderDirective, | ||||||
|     DataGridCellDirective, DataGridFooterDirective, DataGridHeaderDirective,  |     DataGridCellDirective, DataGridFooterDirective, DataGridHeaderDirective,  | ||||||
|     DataGridLoaderDirective, |     DataGridLoaderDirective, DataGridCellFilterDirective, DataGridColSortDirective, | ||||||
|      |      | ||||||
|   ], |   ], | ||||||
|   imports: [ |   imports: [ | ||||||
| @ -25,6 +27,6 @@ import { DataGridLoaderDirective } from './directives/data-grid-loader.directive | |||||||
|   exports: [ |   exports: [ | ||||||
|     DataGridComponent,DataGridColDirective,DataGridColHeaderDirective, |     DataGridComponent,DataGridColDirective,DataGridColHeaderDirective, | ||||||
|     DataGridCellDirective,DataGridFooterDirective, DataGridHeaderDirective, |     DataGridCellDirective,DataGridFooterDirective, DataGridHeaderDirective, | ||||||
|     DataGridLoaderDirective] |     DataGridLoaderDirective,DataGridCellFilterDirective,DataGridColSortDirective] | ||||||
| }) | }) | ||||||
| export class DataGridModule { } | export class DataGridModule { } | ||||||
|  | |||||||
| @ -2,18 +2,34 @@ | |||||||
| 
 | 
 | ||||||
| <table [ngClass]="tableClasses" style="min-height: 300px;"> | <table [ngClass]="tableClasses" style="min-height: 300px;"> | ||||||
|   <thead> |   <thead> | ||||||
|     <tr> |     <tr *ngFor="let header of gridHeaders" > | ||||||
|       <th *ngFor="let header of gridHeaders" [attr.colspan]="columns.length"> |       <th [attr.colspan]="columns.length"> | ||||||
|         <ng-container [ngTemplateOutlet]="header.template"></ng-container> |         <ng-container [ngTemplateOutlet]="header.template"></ng-container> | ||||||
|       </th> |       </th> | ||||||
|     </tr> |     </tr> | ||||||
|     <tr> |     <tr> | ||||||
|       <th *ngFor="let column of columns"> |       <th *ngFor="let column of columns"> | ||||||
|         <ng-container *ngIf="hasHeaderTemplate(column)"> |         <div class="flex-container"> | ||||||
|  |           <div class="flex-item"> | ||||||
|  |             <ng-container *ngIf="hasHeaderTemplate(column)" > | ||||||
|               <ng-container |               <ng-container | ||||||
|                 [ngTemplateOutlet]="getColumnHeaderTemplate(column)" |                 [ngTemplateOutlet]="getColumnHeaderTemplate(column)" | ||||||
|               ></ng-container> |               ></ng-container> | ||||||
|             </ng-container> |             </ng-container> | ||||||
|  |           </div> | ||||||
|  |    | ||||||
|  |           <div class="flex-item"> | ||||||
|  |           | ||||||
|  |               <ng-container *ngIf="hasSortingTemplate(column)"> | ||||||
|  |                 <ng-container [ngTemplateOutlet]="getSortingTemplate(column)"></ng-container> | ||||||
|  |               </ng-container> | ||||||
|  |    | ||||||
|  |               <ng-container *ngIf="hasFilterTemplate(column)"> | ||||||
|  |                 <ng-container [ngTemplateOutlet]="getFilterTemplate(column)"></ng-container> | ||||||
|  |               </ng-container> | ||||||
|  |             </div> | ||||||
|  |             | ||||||
|  |         </div> | ||||||
|       </th> |       </th> | ||||||
|     </tr> |     </tr> | ||||||
|   </thead> |   </thead> | ||||||
|  | |||||||
| @ -0,0 +1,10 @@ | |||||||
|  | :host  .flex-container{ | ||||||
|  |     display: flex; | ||||||
|  |     justify-content: space-between; | ||||||
|  |     align-items: center; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | :host .flex-item{ | ||||||
|  |     margin-right: 1px; | ||||||
|  |     height: 100%; | ||||||
|  | } | ||||||
| @ -5,6 +5,8 @@ import { DataGridHeaderDirective } from '../directives/data-grid-header.directiv | |||||||
| import { DataGridFooterDirective } from '../directives/data-grid-footer.directive'; | import { DataGridFooterDirective } from '../directives/data-grid-footer.directive'; | ||||||
| import { DataGridLoaderDirective } from '../directives/data-grid-loader.directive'; | import { DataGridLoaderDirective } from '../directives/data-grid-loader.directive'; | ||||||
| import { Subscription } from 'rxjs'; | import { Subscription } from 'rxjs'; | ||||||
|  | import { DataGridCellFilterDirective } from '../directives/data-grid-cell-filter.directive'; | ||||||
|  | import { DataGridColSortDirective } from '../directives/data-grid-col-sort.directive'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'ps-data-grid', |   selector: 'ps-data-grid', | ||||||
| @ -23,12 +25,15 @@ export class DataGridComponent implements OnInit, OnDestroy { | |||||||
|    |    | ||||||
|   @Input() dataSource: IDataSource<any>; |   @Input() dataSource: IDataSource<any>; | ||||||
|   @Input() tableClasses: any; |   @Input() tableClasses: any; | ||||||
|  |   @Input() headerClasses: any; | ||||||
|   @Input() noRecordsText: string; |   @Input() noRecordsText: string; | ||||||
| 
 | 
 | ||||||
|   private _columns: string[]; |   private _columns: string[]; | ||||||
|   private _dataSubscription: Subscription; |   private _dataSubscription: Subscription; | ||||||
|   private _loadingSubscription: Subscription; |   private _loadingSubscription: Subscription; | ||||||
| 
 | 
 | ||||||
|  |   _fiters:any | ||||||
|  | 
 | ||||||
|   @Input() set columns(value: string[]) { |   @Input() set columns(value: string[]) { | ||||||
|     this._columns = value; |     this._columns = value; | ||||||
|     this.columnsChange.emit(value); |     this.columnsChange.emit(value); | ||||||
| @ -70,7 +75,22 @@ export class DataGridComponent implements OnInit, OnDestroy { | |||||||
|       this.cdr.detectChanges(); |       this.cdr.detectChanges(); | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     console.log(this.loaders); |   } | ||||||
|  | 
 | ||||||
|  |   getSortingTemplate(columnName){ | ||||||
|  |     const ret = this.getColumn(columnName); | ||||||
|  |     if (ret && ret.sortTemplate)  | ||||||
|  |       return ret.sortTemplate.template; | ||||||
|  | 
 | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   getFilterTemplate(columnName){ | ||||||
|  |     const ret = this.getColumn(columnName); | ||||||
|  |     if (ret && ret.filterTemplate)  | ||||||
|  |       return ret.filterTemplate.template; | ||||||
|  | 
 | ||||||
|  |     return null; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   getColumn(columnName: string) { |   getColumn(columnName: string) { | ||||||
| @ -86,6 +106,7 @@ export class DataGridComponent implements OnInit, OnDestroy { | |||||||
|     return ret; |     return ret; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|   getColumnHeaderTemplate(columnName: string) { |   getColumnHeaderTemplate(columnName: string) { | ||||||
|     const ret = this.getColumn(columnName); |     const ret = this.getColumn(columnName); | ||||||
|     if (ret && ret.headerTemplate)  |     if (ret && ret.headerTemplate)  | ||||||
| @ -110,5 +131,13 @@ export class DataGridComponent implements OnInit, OnDestroy { | |||||||
|     return this.getColumnCellTemplate(columnName) ? true :false; |     return this.getColumnCellTemplate(columnName) ? true :false; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   hasFilterTemplate(columnName: string) { | ||||||
|  |     return this.getFilterTemplate(columnName) ? true :false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   hasSortingTemplate(columnName: string) { | ||||||
|  |     return this.getSortingTemplate(columnName) ? true :false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,10 @@ | |||||||
|  | import { Directive, TemplateRef } from '@angular/core'; | ||||||
|  | 
 | ||||||
|  | @Directive({ | ||||||
|  |   selector: '[psDataGridCellFilter]' | ||||||
|  | }) | ||||||
|  | export class DataGridCellFilterDirective { | ||||||
|  | 
 | ||||||
|  |   constructor(public template: TemplateRef<any>) { } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,10 @@ | |||||||
|  | import { Directive, TemplateRef } from '@angular/core'; | ||||||
|  | 
 | ||||||
|  | @Directive({ | ||||||
|  |   selector: '[psDataGridColSort]' | ||||||
|  | }) | ||||||
|  | export class DataGridColSortDirective { | ||||||
|  | 
 | ||||||
|  |   constructor(public template: TemplateRef<any>) { } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -1,6 +1,9 @@ | |||||||
| import { Directive, Input, ContentChild } from '@angular/core'; | import { Directive, Input, ContentChild, ContentChildren } from '@angular/core'; | ||||||
| import { DataGridColHeaderDirective } from './data-grid-col-header.directive'; | import { DataGridColHeaderDirective } from './data-grid-col-header.directive'; | ||||||
| import { DataGridCellDirective } from './data-grid-cell.directive'; | import { DataGridCellDirective } from './data-grid-cell.directive'; | ||||||
|  | import { DataGridCellFilterDirective } from './data-grid-cell-filter.directive'; | ||||||
|  | import { DataGridColSortDirective } from './data-grid-col-sort.directive'; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @Directive({ | @Directive({ | ||||||
|   selector: '[psDataGridCol]' |   selector: '[psDataGridCol]' | ||||||
| @ -10,6 +13,8 @@ export class DataGridColDirective { | |||||||
|   @Input('psDataGridCol') columnName:string; |   @Input('psDataGridCol') columnName:string; | ||||||
|   @ContentChild(DataGridColHeaderDirective) headerTemplate:DataGridColHeaderDirective; |   @ContentChild(DataGridColHeaderDirective) headerTemplate:DataGridColHeaderDirective; | ||||||
|   @ContentChild(DataGridCellDirective) cellTemplate:DataGridCellDirective;   |   @ContentChild(DataGridCellDirective) cellTemplate:DataGridCellDirective;   | ||||||
|  |   @ContentChild(DataGridCellFilterDirective) filterTemplate: DataGridCellFilterDirective; | ||||||
|  |   @ContentChild(DataGridColSortDirective) sortTemplate: DataGridColSortDirective; | ||||||
| 
 | 
 | ||||||
|   constructor() { } |   constructor() { } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -10,3 +10,6 @@ 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-header.directive'; | ||||||
| export * from './lib/data-grid/directives/data-grid-footer.directive'; | export * from './lib/data-grid/directives/data-grid-footer.directive'; | ||||||
| export * from './lib/data-grid/directives/data-grid-loader.directive'; | export * from './lib/data-grid/directives/data-grid-loader.directive'; | ||||||
|  | export * from './lib/data-grid/directives/data-grid-cell-filter.directive'; | ||||||
|  | export * from './lib/data-grid/directives/data-grid-col-sort.directive'; | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -27,6 +27,14 @@ const routes: Routes = [ | |||||||
|   { |   { | ||||||
|     path: 'pagination-demo', |     path: 'pagination-demo', | ||||||
|     loadChildren: ()=> import('./pagination-demo/pagination-demo.module').then(m => m.PaginationDemoModule) |     loadChildren: ()=> import('./pagination-demo/pagination-demo.module').then(m => m.PaginationDemoModule) | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     path: 'grid-filter', | ||||||
|  |     loadChildren: ()=> import('./grid-filter&sorting-demo/grid-filter-demo.module').then(m => m.GridFilterDemoModule) | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     path: 'select', | ||||||
|  |     loadChildren: ()=> import('./ng-select-demo/ng-select-demo.module').then(m => m.NgSelectDemoModule) | ||||||
|   } |   } | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -21,9 +21,15 @@ | |||||||
|         <li class="nav-item"> |         <li class="nav-item"> | ||||||
|           <a class="nav-link" routerLink="pagination-demo">pagination Demo</a> |           <a class="nav-link" routerLink="pagination-demo">pagination Demo</a> | ||||||
|         </li> |         </li> | ||||||
|  |         <li class="nav-item"> | ||||||
|  |           <a class="nav-link" routerLink="grid-filter">Fitering Demo</a> | ||||||
|  |         </li> | ||||||
|  |         <li class="nav-item"> | ||||||
|  |           <a class="nav-link" routerLink="select">NG-select</a> | ||||||
|  |         </li> | ||||||
|       </ul> |       </ul> | ||||||
|     </div> |     </div> | ||||||
|     <div class="col-lg-10" style="padding-top: 5px"> |     <div class="col-lg-10" style="padding-top: 5px;"> | ||||||
|       <router-outlet></router-outlet> |       <router-outlet></router-outlet> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
|  | |||||||
| @ -10,6 +10,8 @@ import { HttpLink, HttpLinkModule } from 'apollo-angular-link-http'; | |||||||
| import { DefaultOptions } from 'apollo-client'; | import { DefaultOptions } from 'apollo-client'; | ||||||
| import { InMemoryCache } from 'apollo-cache-inmemory'; | import { InMemoryCache } from 'apollo-cache-inmemory'; | ||||||
| import { HttpClientModule } from '@angular/common/http'; | import { HttpClientModule } from '@angular/common/http'; | ||||||
|  | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| export function app_Init(apollo: Apollo, httpLink: HttpLink) { | export function app_Init(apollo: Apollo, httpLink: HttpLink) { | ||||||
|   return async () => { |   return async () => { | ||||||
| @ -49,6 +51,7 @@ export function app_Init(apollo: Apollo, httpLink: HttpLink) { | |||||||
|   declarations: [ |   declarations: [ | ||||||
|     AppComponent, |     AppComponent, | ||||||
|     HomeComponent, |     HomeComponent, | ||||||
|  |     //SelectLabelTemplateDirective,
 | ||||||
|      |      | ||||||
|   ], |   ], | ||||||
|   imports: [ |   imports: [ | ||||||
| @ -56,7 +59,8 @@ export function app_Init(apollo: Apollo, httpLink: HttpLink) { | |||||||
|     AppRoutingModule, |     AppRoutingModule, | ||||||
|     HttpClientModule, |     HttpClientModule, | ||||||
|     ApolloModule, |     ApolloModule, | ||||||
|     HttpLinkModule |     HttpLinkModule, | ||||||
|  |     BrowserAnimationsModule | ||||||
|   ], |   ], | ||||||
|   providers: [ |   providers: [ | ||||||
|     { |     { | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ import { CommandModalDemoRoutingModule } from './command-modal-demo-routing.modu | |||||||
| import { DataGridModule } from '@poweredsoft/ngx-cdk-ui'; | import { DataGridModule } from '@poweredsoft/ngx-cdk-ui'; | ||||||
| 
 | 
 | ||||||
| import {FormsModule} from '@angular/forms'; | import {FormsModule} from '@angular/forms'; | ||||||
| import { CommandModalModule, psbxPaginationModule, ConfirmModalModule } from '@poweredsoft/ngx-bootstrap'; | import { CommandModalModule, PaginationModule, ConfirmModalModule,CommandModule } from '@poweredsoft/ngx-bootstrap'; | ||||||
| @NgModule({ | @NgModule({ | ||||||
|   declarations: [CommandModalDemoComponent], |   declarations: [CommandModalDemoComponent], | ||||||
|   imports: [ |   imports: [ | ||||||
| @ -14,8 +14,9 @@ import { CommandModalModule, psbxPaginationModule, ConfirmModalModule } from '@p | |||||||
|     DataGridModule, |     DataGridModule, | ||||||
|     CommandModalModule, |     CommandModalModule, | ||||||
|     FormsModule, |     FormsModule, | ||||||
|     psbxPaginationModule, |     PaginationModule, | ||||||
|     ConfirmModalModule |     ConfirmModalModule, | ||||||
|  |     CommandModule | ||||||
|   ] |   ] | ||||||
| }) | }) | ||||||
| export class CommandModalDemoModule { } | export class CommandModalDemoModule { } | ||||||
|  | |||||||
| @ -4,8 +4,10 @@ | |||||||
| <ps-data-grid [dataSource]="merchantDataSource" [(columns)]="columns" | <ps-data-grid [dataSource]="merchantDataSource" [(columns)]="columns" | ||||||
|     tableClasses="table table-sm table-dark table-striped table-bordered"> |     tableClasses="table table-sm table-dark table-striped table-bordered"> | ||||||
|     <ng-container *psDataGridHeader> |     <ng-container *psDataGridHeader> | ||||||
|         <button class="btn-primary btn" psbxCommandModal commandTitle="Adding a new merchant" commandText="Add" |         <button class="btn-primary btn" psbxCommandModal  | ||||||
|             [dataSource]="merchantDataSource" command="addMerchant" [template]="theModal">Create a new record</button> |         commandTitle="Adding a new merchant" commandText="Add" | ||||||
|  |             [dataSource]="merchantDataSource" command="addMerchant"  | ||||||
|  |             [template]="theModal">Create a new record</button> | ||||||
| 
 | 
 | ||||||
|     </ng-container> |     </ng-container> | ||||||
|     <ng-container psDataGridCol="id"> |     <ng-container psDataGridCol="id"> | ||||||
| @ -24,11 +26,26 @@ | |||||||
|     <ng-container psDataGridCol="commands"> |     <ng-container psDataGridCol="commands"> | ||||||
|         <ng-container *psDataGridColHeader>Actions</ng-container> |         <ng-container *psDataGridColHeader>Actions</ng-container> | ||||||
|         <ng-container *psDataGridCell="let model"> |         <ng-container *psDataGridCell="let model"> | ||||||
|  |             <div class="btn-group"> | ||||||
|  | 
 | ||||||
|  |          | ||||||
|             <button class="btn-primary btn" psbxCommandModal [commandTitle]="'Change ' + model.name + ' name'" commandText="Update" |             <button class="btn-primary btn" psbxCommandModal [commandTitle]="'Change ' + model.name + ' name'" commandText="Update" | ||||||
|             [dataSource]="merchantDataSource" command="changeMerchant" [model]="model" [template]="changeName">Change</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" |             <button class="btn-danger btn" psbxCommand  | ||||||
|             [dataSource]="merchantDataSource" command="removeMerchant" [model]="model" >RemoveIt</button> |             [dataSource]="merchantDataSource"  | ||||||
|  |             command="removeMerchant"  | ||||||
|  |             [model]="model"  | ||||||
|  |             [confirm]="true" | ||||||
|  |             confirmMessage="Are you sure you want to delete this merchant?" | ||||||
|  |              | ||||||
|  |             >RemoveIt</button> | ||||||
|  | 
 | ||||||
|  |             <button class="btn-warning btn" psbxCommand  | ||||||
|  |             [dataSource]="merchantDataSource"  | ||||||
|  |             command="removeMerchant"  | ||||||
|  |             [model]="model"              | ||||||
|  |             >Remove Without confirmation</button>    </div> | ||||||
|         </ng-container> |         </ng-container> | ||||||
|     </ng-container> |     </ng-container> | ||||||
|         <ng-container *psDataGridFooter> |         <ng-container *psDataGridFooter> | ||||||
| @ -46,11 +63,13 @@ | |||||||
| </ng-template> | </ng-template> | ||||||
| 
 | 
 | ||||||
| <ng-template #theModal let-command let-loading="loading"> | <ng-template #theModal let-command let-loading="loading"> | ||||||
|     <form ngNativeValidate  > |     <form   > | ||||||
|         Name |         Name | ||||||
|         <input type="text" required [disabled]="loading" name="name" [(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 |         Address | ||||||
|         <input type="text" required [disabled]="loading" name="address" [(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" >         | ||||||
|  |         Date | ||||||
|  |         <input type="text" required [disabled]="loading" name="address" [(ngModel)]="command.address"  placeholder="Enter the merchant's address" class="form-control" >         | ||||||
|     </form> |     </form> | ||||||
|      |      | ||||||
| </ng-template> | </ng-template> | ||||||
| @ -1,23 +1,28 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||||||
| import { IDataSource } from '@poweredsoft/data'; | import { IDataSource } from '@poweredsoft/data'; | ||||||
| import { IMerchant } from 'src/app/data/services/IMerchant'; | import { IMerchant } from 'src/app/data/services/IMerchant'; | ||||||
| import { MerchantService } from 'src/app/data/services/merchant.service'; | import { MerchantService } from 'src/app/data/services/merchant.service'; | ||||||
| import { BsModalRef } from 'ngx-bootstrap/modal'; | import { BsModalRef } from 'ngx-bootstrap/modal'; | ||||||
|  | import { Subscription } from 'rxjs'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'ps-command-modal-demo', |   selector: 'ps-command-modal-demo', | ||||||
|   templateUrl: './command-modal-demo.component.html', |   templateUrl: './command-modal-demo.component.html', | ||||||
|   styleUrls: ['./command-modal-demo.component.scss'] |   styleUrls: ['./command-modal-demo.component.scss'] | ||||||
| }) | }) | ||||||
| export class CommandModalDemoComponent implements OnInit { | export class CommandModalDemoComponent implements OnInit,OnDestroy { | ||||||
| 
 | 
 | ||||||
|   columns = ['id','name', 'address', 'commands']; |   columns = ['id','name', 'address', 'commands']; | ||||||
|   pages:any; |   pages:any; | ||||||
|   merchantDataSource: IDataSource<IMerchant>;   |   merchantDataSource: IDataSource<IMerchant>;   | ||||||
|  |   private _dataSubscription: Subscription; | ||||||
|   constructor(private  merchantService: MerchantService){ |   constructor(private  merchantService: MerchantService){ | ||||||
|     this.merchantDataSource = this.createDataSource(); |     this.merchantDataSource = this.createDataSource(); | ||||||
| 
 | 
 | ||||||
|   } |   } | ||||||
|  |   ngOnDestroy(): void { | ||||||
|  |     this._dataSubscription.unsubscribe(); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   newMerchant(name: string) { |   newMerchant(name: string) { | ||||||
|     this.merchantDataSource.executeCommandByName('addMerchant', { |     this.merchantDataSource.executeCommandByName('addMerchant', { | ||||||
| @ -40,7 +45,7 @@ export class CommandModalDemoComponent implements OnInit { | |||||||
| 
 | 
 | ||||||
|   ngOnInit() { |   ngOnInit() { | ||||||
|     this.merchantDataSource.refresh(); |     this.merchantDataSource.refresh(); | ||||||
|     this.merchantDataSource.data$.subscribe(newData => {      |     this._dataSubscription = this.merchantDataSource.data$.subscribe(newData => {      | ||||||
|       if (newData) |       if (newData) | ||||||
|         this.pages = new Array(newData.numberOfPages); |         this.pages = new Array(newData.numberOfPages); | ||||||
|     }); |     }); | ||||||
|  | |||||||
| @ -2,14 +2,11 @@ | |||||||
|     This is a demo for a grid. |     This is a demo for a grid. | ||||||
| </h1> | </h1> | ||||||
| 
 | 
 | ||||||
|     <ps-data-grid [dataSource]="merchantDataSource" [(columns)]="columns" tableClasses="table table-sm table-bordered" > |     <ps-data-grid [dataSource]="merchantDataSource" [(columns)]="columns"  | ||||||
|  |     tableClasses="table table-sm table-bordered" > | ||||||
| 
 | 
 | ||||||
|         <ng-container *psDataGridHeader> |         <ng-container *psDataGridHeader> | ||||||
|             <h1>Hey! </h1> |             Some header | ||||||
|             <p>Welcome to my Grid!</p> |  | ||||||
|             <label>New merchant name</label> |  | ||||||
|             <input class="form-control" #newMerchantName/> |  | ||||||
|             <button class="btn btn-primary btn-sm" (click)="newMerchant(newMerchantName.value)">Add</button> |  | ||||||
|         </ng-container> |         </ng-container> | ||||||
|         <ng-container psDataGridCol="id"> |         <ng-container psDataGridCol="id"> | ||||||
|             <div *psDataGridColHeader>ID</div> |             <div *psDataGridColHeader>ID</div> | ||||||
| @ -27,11 +24,10 @@ | |||||||
|         <ng-container psDataGridCol="commands"> |         <ng-container psDataGridCol="commands"> | ||||||
|             <ng-container *psDataGridColHeader>Actions</ng-container> |             <ng-container *psDataGridColHeader>Actions</ng-container> | ||||||
|             <ng-container *psDataGridCell="let model"> |             <ng-container *psDataGridCell="let model"> | ||||||
|                 <button class="btn btn-primary mr-2">{{model.name}}</button> |                 <button class="btn btn-primary mr-2">Some Actions</button> | ||||||
|             </ng-container> |             </ng-container> | ||||||
|         </ng-container> |         </ng-container> | ||||||
|         <ng-container *psDataGridFooter> |         <ng-container *psDataGridFooter> | ||||||
|              |  | ||||||
|             <strong>Footer works!</strong> |             <strong>Footer works!</strong> | ||||||
|         </ng-container> |         </ng-container> | ||||||
|     </ps-data-grid> |     </ps-data-grid> | ||||||
| @ -1,22 +1,29 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||||||
| import { DataSource, IDataSource, IQueryExecutionResult, IQueryExecutionGroupResult } from '@poweredsoft/data'; | import { DataSource, IDataSource, IQueryExecutionResult, IQueryExecutionGroupResult } from '@poweredsoft/data'; | ||||||
| import { IMerchant } from 'src/app/data/services/IMerchant'; | import { IMerchant } from 'src/app/data/services/IMerchant'; | ||||||
| import { MerchantService } from 'src/app/data/services/merchant.service'; | import { MerchantService } from 'src/app/data/services/merchant.service'; | ||||||
|  | import { Subscription } from 'rxjs'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'ps-data-grid-demo-home', |   selector: 'ps-data-grid-demo-home', | ||||||
|   templateUrl: './data-grid-demo-home.component.html', |   templateUrl: './data-grid-demo-home.component.html', | ||||||
|   styleUrls: ['./data-grid-demo-home.component.scss'] |   styleUrls: ['./data-grid-demo-home.component.scss'] | ||||||
| }) | }) | ||||||
| export class DataGridDemoHomeComponent implements OnInit { | export class DataGridDemoHomeComponent implements OnInit, OnDestroy { | ||||||
| 
 | 
 | ||||||
|   title = 'cdkDemo'; |   title = 'cdkDemo'; | ||||||
|   columns = ['id','name', 'address', 'commands'] |   columns = ['id','name', 'address', 'commands'] | ||||||
|   merchantDataSource: IDataSource<IMerchant>;   |   merchantDataSource: IDataSource<IMerchant>;   | ||||||
|  |   private _dataSubscription: Subscription; | ||||||
|  |   private _loading: Subscription; | ||||||
|   constructor(private  merchantService: MerchantService){ |   constructor(private  merchantService: MerchantService){ | ||||||
|     this.merchantDataSource = this.createDataSource(); |     this.merchantDataSource = this.createDataSource(); | ||||||
| 
 | 
 | ||||||
|   } |   } | ||||||
|  |   ngOnDestroy(): void { | ||||||
|  |     this._dataSubscription.unsubscribe(); | ||||||
|  |     this._loading.unsubscribe(); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|    |    | ||||||
| 
 | 
 | ||||||
| @ -41,11 +48,11 @@ export class DataGridDemoHomeComponent implements OnInit { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   ngOnInit() { |   ngOnInit() { | ||||||
|     this.merchantDataSource.loading$.subscribe(isLoading => { |     this._loading = this.merchantDataSource.loading$.subscribe(isLoading => { | ||||||
|       console.log('merchant data source event loading', isLoading); |       console.log('merchant data source event loading', isLoading); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     this.merchantDataSource.data$.subscribe(receivedData => { |     this._dataSubscription = this.merchantDataSource.data$.subscribe(receivedData => { | ||||||
|       console.log('new data is coming from the server', receivedData); |       console.log('new data is coming from the server', receivedData); | ||||||
|     }); |     }); | ||||||
|     this.merchantDataSource.refresh(); |     this.merchantDataSource.refresh(); | ||||||
|  | |||||||
| @ -1,11 +1,13 @@ | |||||||
| export interface IChangeMerchantNameCommand { | export interface IChangeMerchantCommand { | ||||||
|   id: string; |   id: string; | ||||||
|   name: string; |   name: string; | ||||||
|   address: string; |   address: string; | ||||||
|  |   ordering: number; | ||||||
| } | } | ||||||
| export interface IAddMerchantCommand { | export interface IAddMerchantCommand { | ||||||
|   name: string; |   name: string; | ||||||
|   address: string; |   address: string; | ||||||
|  |   ordering: number; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface IRemoveMerchantCommand { | export interface IRemoveMerchantCommand { | ||||||
| @ -2,4 +2,6 @@ export interface IMerchant { | |||||||
|   id: string; |   id: string; | ||||||
|   name: string; |   name: string; | ||||||
|   address: string; |   address: string; | ||||||
|  |   ordering:number; | ||||||
|  |   openDate: Date; | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ import { IDataSource, DataSource } from '@poweredsoft/data'; | |||||||
| import { Apollo } from 'apollo-angular'; | import { Apollo } from 'apollo-angular'; | ||||||
| import  gql  from 'graphql-tag'; | import  gql  from 'graphql-tag'; | ||||||
| import { of } from 'rxjs'; | import { of } from 'rxjs'; | ||||||
| import { IChangeMerchantNameCommand, IAddMerchantCommand, IRemoveMerchantCommand } from './IChangeMerchantNameCommand'; | import { IChangeMerchantCommand as IChangeMerchantCommand, IAddMerchantCommand, IRemoveMerchantCommand } from './IChangeMerchantCommand'; | ||||||
| import { IMerchant } from './IMerchant'; | import { IMerchant } from './IMerchant'; | ||||||
| 
 | 
 | ||||||
| @Injectable({ | @Injectable({ | ||||||
| @ -23,7 +23,7 @@ export class MerchantService { | |||||||
|     >( |     >( | ||||||
|       'merchants', |       'merchants', | ||||||
|       'GraphQLAdvanceQueryOfMerchantInput', |       'GraphQLAdvanceQueryOfMerchantInput', | ||||||
|       'id, name, address', |       'id, name, address, ordering, openDate', | ||||||
|       (model) => model.id, |       (model) => model.id, | ||||||
|       { |       { | ||||||
|         page: 1, |         page: 1, | ||||||
| @ -32,7 +32,7 @@ export class MerchantService { | |||||||
|       true |       true | ||||||
|     ); |     ); | ||||||
|     |     | ||||||
|     builder.addMutation<IChangeMerchantNameCommand, string>( |     builder.addMutation<IChangeMerchantCommand, string>( | ||||||
|       'changeMerchant', //<-- command name
 |       'changeMerchant', //<-- command name
 | ||||||
|       'changeMerchant', //<-- graph ql mutation name
 |       'changeMerchant', //<-- graph ql mutation name
 | ||||||
|        |        | ||||||
| @ -51,10 +51,11 @@ export class MerchantService { | |||||||
|       }, |       }, | ||||||
|        |        | ||||||
|       // viewModel -> transform to the form model for that command -> IChangeMerchantName
 |       // viewModel -> transform to the form model for that command -> IChangeMerchantName
 | ||||||
|       e => of(<IChangeMerchantNameCommand>{ |       e => of(<IChangeMerchantCommand>{ | ||||||
|         id: e.model.id, |         id: e.model.id, | ||||||
|         name: e.model.name, |         name: e.model.name, | ||||||
|         address: e.model.address |         address: e.model.address, | ||||||
|  |         ordering:e.model.ordering, | ||||||
|       }) |       }) | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -80,7 +81,8 @@ export class MerchantService { | |||||||
|       // viewModel -> transform to the form model for that command -> IChangeMerchantName
 |       // viewModel -> transform to the form model for that command -> IChangeMerchantName
 | ||||||
|       e => of(<IAddMerchantCommand>{ |       e => of(<IAddMerchantCommand>{ | ||||||
|         name: 'A New merchant', |         name: 'A New merchant', | ||||||
|         address: '' |         address: '', | ||||||
|  |         ordering: 11 | ||||||
|       }) |       }) | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'; | |||||||
| import { FormGroupModalDemoComponent } from './form-group-modal-demo/form-group-modal-demo.component'; | import { FormGroupModalDemoComponent } from './form-group-modal-demo/form-group-modal-demo.component'; | ||||||
| import { FormGroupModalDemoRoutingModule } from './form-group-modal-demo-routing.module' | import { FormGroupModalDemoRoutingModule } from './form-group-modal-demo-routing.module' | ||||||
| import { DataGridModule } from '@poweredsoft/ngx-cdk-ui'; | import { DataGridModule } from '@poweredsoft/ngx-cdk-ui'; | ||||||
| import { FormGroupCommandModalModule,CommandModalModule, psbxPaginationModule } from '@poweredsoft/ngx-bootstrap'; | import { FormGroupCommandModalModule, PaginationModule, CommandModule } from '@poweredsoft/ngx-bootstrap'; | ||||||
| import { ReactiveFormsModule } from '@angular/forms'; | import { ReactiveFormsModule } from '@angular/forms'; | ||||||
| import { ConfirmModalModule } from 'projects/poweredsoft/ngx-bootstrap/src/public-api'; | import { ConfirmModalModule } from 'projects/poweredsoft/ngx-bootstrap/src/public-api'; | ||||||
| 
 | 
 | ||||||
| @ -17,8 +17,9 @@ import { ConfirmModalModule } from 'projects/poweredsoft/ngx-bootstrap/src/publi | |||||||
|     DataGridModule, |     DataGridModule, | ||||||
|     FormGroupCommandModalModule, |     FormGroupCommandModalModule, | ||||||
|     ReactiveFormsModule, |     ReactiveFormsModule, | ||||||
|     psbxPaginationModule, |     PaginationModule, | ||||||
|     ConfirmModalModule, |     ConfirmModalModule, | ||||||
|  |     CommandModule | ||||||
|      |      | ||||||
|   ] |   ] | ||||||
| }) | }) | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ | |||||||
|     <ng-container *psDataGridHeader> |     <ng-container *psDataGridHeader> | ||||||
|             <button class="btn-success btn" psbxFormGroupCommandModal commandTitle="Adding a new merchant" |             <button class="btn-success btn" psbxFormGroupCommandModal commandTitle="Adding a new merchant" | ||||||
|              commandText="Add" [dataSource]="merchantDataSource" command="addMerchant"  |              commandText="Add" [dataSource]="merchantDataSource" command="addMerchant"  | ||||||
|              (formCreate)="onFormCreate($event)" [template]="theModal">Create a new</button>    |              (formCreate)="onFormCreate($event)" [template]="theModal">Create New Records</button>    | ||||||
|     </ng-container> |     </ng-container> | ||||||
|     <ng-container psDataGridCol="id"> |     <ng-container psDataGridCol="id"> | ||||||
|         <div *psDataGridColHeader>ID</div> |         <div *psDataGridColHeader>ID</div> | ||||||
| @ -19,16 +19,32 @@ | |||||||
|         <div *psDataGridCell="let model">{{model.address}}</div> |         <div *psDataGridCell="let model">{{model.address}}</div> | ||||||
|     </ng-container> |     </ng-container> | ||||||
|     <ng-container psDataGridCol="actions"> |     <ng-container psDataGridCol="actions"> | ||||||
|  |      | ||||||
|         <ng-container *psDataGridColHeader>Actions</ng-container> |         <ng-container *psDataGridColHeader>Actions</ng-container> | ||||||
|         <ng-container *psDataGridCell="let model"> |         <ng-container *psDataGridCell="let model"> | ||||||
|             <button class="btn-success btn" psbxFormGroupCommandModal [commandTitle]="'Change ' + model.name + ' name'" commandText="Update" |             <div class="btn-group"> | ||||||
|             [dataSource]="merchantDataSource" command="changeMerchant" (formCreate)="onFormCreate($event)" [model]="model" [template]="theModal">Change</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" |             <button class="btn-danger btn"  | ||||||
|             [dataSource]="merchantDataSource" command="removeMerchant" [model]="model" >Delete!</button> |             psbxCommand  | ||||||
| 
 |             [dataSource]="merchantDataSource"  | ||||||
|             <!-- <button class="btn-danger btn" psbxExecuteCommand [dataSource]="merchantDataSource" [command]="removeMerchant" |             command="removeMerchant"  | ||||||
|              [model]="model" [confirm]="true" [confirmMessage]="do you wish to delete the merchant `' + model.name + '`" [refresh]="false">Delete</button> --> |             [model]="model"  | ||||||
|  |             [confirm]="true" | ||||||
|  |             yesClass="warning" | ||||||
|  |             noClass = "secondary" | ||||||
|  |             noText = "Cancel Delete" | ||||||
|  |             yesText = "Delete It" | ||||||
|  |             confirmMessage="Are you sure you want to delete this merchant?" | ||||||
|  |             >RemoveIt</button> | ||||||
|  |             </div> | ||||||
|         </ng-container> |         </ng-container> | ||||||
|     </ng-container> |     </ng-container> | ||||||
|     <ng-container *psDataGridFooter> |     <ng-container *psDataGridFooter> | ||||||
|  | |||||||
| @ -1,16 +1,18 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||||||
| import { IDataSource } from '@poweredsoft/data'; | import { IDataSource } from '@poweredsoft/data'; | ||||||
| import { IMerchant } from 'src/app/data/services/IMerchant'; | import { IMerchant } from 'src/app/data/services/IMerchant'; | ||||||
| import { MerchantService } from 'src/app/data/services/merchant.service'; | import { MerchantService } from 'src/app/data/services/merchant.service'; | ||||||
| import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms'; | import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms'; | ||||||
| import { IModelFormCreateEvent } from 'projects/poweredsoft/ngx-bootstrap/src/public-api'; | import { IModelFormCreateEvent } from 'projects/poweredsoft/ngx-bootstrap/src/public-api'; | ||||||
|  | import { Subscription } from 'rxjs'; | ||||||
|  | import { THIS_EXPR } from '@angular/compiler/src/output/output_ast'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'ps-form-group-modal-demo', |   selector: 'ps-form-group-modal-demo', | ||||||
|   templateUrl: './form-group-modal-demo.component.html', |   templateUrl: './form-group-modal-demo.component.html', | ||||||
|   styleUrls: ['./form-group-modal-demo.component.scss'] |   styleUrls: ['./form-group-modal-demo.component.scss'] | ||||||
| }) | }) | ||||||
| export class FormGroupModalDemoComponent implements OnInit { | export class FormGroupModalDemoComponent implements OnInit,OnDestroy { | ||||||
|   |   | ||||||
|   createDataSource(): IDataSource<IMerchant> { |   createDataSource(): IDataSource<IMerchant> { | ||||||
|     return this.merchantService.createDataSource(); |     return this.merchantService.createDataSource(); | ||||||
| @ -18,14 +20,18 @@ export class FormGroupModalDemoComponent implements OnInit { | |||||||
| 
 | 
 | ||||||
|   pages:any; |   pages:any; | ||||||
|   merchantDataSource: IDataSource<IMerchant>; |   merchantDataSource: IDataSource<IMerchant>; | ||||||
|  |   private _dataSubscription: Subscription; | ||||||
|   columns = ['id','name', 'address', 'actions']; |   columns = ['id','name', 'address', 'actions']; | ||||||
|   constructor(private merchantService: MerchantService, private fb: FormBuilder) { |   constructor(private merchantService: MerchantService, private fb: FormBuilder) { | ||||||
|     this.merchantDataSource = this.createDataSource(); |     this.merchantDataSource = this.createDataSource(); | ||||||
|    } |    } | ||||||
|  |   ngOnDestroy(): void { | ||||||
|  |     this._dataSubscription.unsubscribe(); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   ngOnInit(): void { |   ngOnInit(): void { | ||||||
|     this.merchantDataSource.refresh(); |     this.merchantDataSource.refresh(); | ||||||
|     this.merchantDataSource.data$.subscribe(newData => {      |     this._dataSubscription = this.merchantDataSource.data$.subscribe(newData => {      | ||||||
|       if (newData) |       if (newData) | ||||||
|         this.pages = new Array(newData.numberOfPages); |         this.pages = new Array(newData.numberOfPages); | ||||||
|     }); |     }); | ||||||
|  | |||||||
| @ -0,0 +1,15 @@ | |||||||
|  | import { NgModule } from '@angular/core'; | ||||||
|  | import { Routes, RouterModule } from '@angular/router'; | ||||||
|  | import { GridFilterDemoComponent } from './grid-filter-demo/grid-filter-demo.component'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | const routes: Routes = [{ | ||||||
|  |   path: '', | ||||||
|  |   component: GridFilterDemoComponent | ||||||
|  | }]; | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |   imports: [RouterModule.forChild(routes)], | ||||||
|  |   exports: [RouterModule] | ||||||
|  | }) | ||||||
|  | export class GridFilterDemoRoutingModule { } | ||||||
							
								
								
									
										26
									
								
								src/app/grid-filter&sorting-demo/grid-filter-demo.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/app/grid-filter&sorting-demo/grid-filter-demo.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | import { NgModule } from '@angular/core'; | ||||||
|  | import { CommonModule } from '@angular/common'; | ||||||
|  | 
 | ||||||
|  | import { GridFilterDemoRoutingModule } from './grid-filter-demo-routing.module'; | ||||||
|  | import { GridFilterDemoComponent } from './grid-filter-demo/grid-filter-demo.component'; | ||||||
|  | import { DataSourceFilterModule, PaginationModule, CommandModalModule, ConfirmModalModule, SpinnerModule, DataSourceSortingModule, CommandModule } from '@poweredsoft/ngx-bootstrap'; | ||||||
|  | import { DataGridModule } from '@poweredsoft/ngx-cdk-ui'; | ||||||
|  | import { FormsModule } from '@angular/forms'; | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |   declarations: [GridFilterDemoComponent], | ||||||
|  |   imports: [ | ||||||
|  |     CommonModule, | ||||||
|  |     GridFilterDemoRoutingModule, | ||||||
|  |     DataSourceFilterModule,     | ||||||
|  |     PaginationModule, | ||||||
|  |     DataGridModule, | ||||||
|  |     CommandModalModule, | ||||||
|  |     ConfirmModalModule, | ||||||
|  |     FormsModule, | ||||||
|  |     SpinnerModule, | ||||||
|  |     DataSourceSortingModule, | ||||||
|  |     CommandModule | ||||||
|  |   ] | ||||||
|  | }) | ||||||
|  | export class GridFilterDemoModule { } | ||||||
| @ -0,0 +1,105 @@ | |||||||
|  | <h2>grid-filter-demo works!</h2> | ||||||
|  | 
 | ||||||
|  | <ps-data-grid [dataSource]="merchantDataSource" [(columns)]="columns" | ||||||
|  |     tableClasses="table table-sm table-striped table-bordered"> | ||||||
|  |     <psbx-spinner *psDataGridLoader></psbx-spinner> | ||||||
|  |     <ng-container *psDataGridHeader> | ||||||
|  |         <button class="btn-info btn" psbxCommandModal commandTitle="Adding a new merchant" commandText="Add" | ||||||
|  |             [dataSource]="merchantDataSource" command="addMerchant" [template]="theModal">Create Record</button> | ||||||
|  |     </ng-container> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     <ng-container psDataGridCol="id"> | ||||||
|  |         <ng-container *psDataGridColHeader>ID</ng-container> | ||||||
|  |         <psbx-ds-text-filter *psDataGridCellFilter [dataSource]="merchantDataSource" path="id"></psbx-ds-text-filter> | ||||||
|  |         <psbx-ds-sorting *psDataGridColSort [dataSource]="merchantDataSource" path="id"></psbx-ds-sorting> | ||||||
|  |         <ng-container *psDataGridCell="let model">{{model.id}}</ng-container>       | ||||||
|  |     </ng-container> | ||||||
|  | 
 | ||||||
|  |     <ng-container psDataGridCol="name"> | ||||||
|  |         <ng-container *psDataGridColHeader>Name</ng-container> | ||||||
|  |         <psbx-ds-text-filter *psDataGridCellFilter [dataSource]="merchantDataSource" path="name"></psbx-ds-text-filter> | ||||||
|  |         <psbx-ds-sorting *psDataGridColSort [dataSource]="merchantDataSource" path="name"></psbx-ds-sorting> | ||||||
|  |         <ng-container *psDataGridCell="let model">{{model.name}}</ng-container> | ||||||
|  |     </ng-container> | ||||||
|  | 
 | ||||||
|  |     <ng-container psDataGridCol="address"> | ||||||
|  |         <ng-container *psDataGridColHeader>Address</ng-container> | ||||||
|  |         <ng-container *psDataGridCell="let model">{{model.address}}</ng-container> | ||||||
|  |         <psbx-ds-text-filter *psDataGridCellFilter [dataSource]="merchantDataSource" path="address"> | ||||||
|  |         </psbx-ds-text-filter> | ||||||
|  |         <psbx-ds-sorting *psDataGridColSort [dataSource]="merchantDataSource" path="address"></psbx-ds-sorting> | ||||||
|  |     </ng-container> | ||||||
|  | 
 | ||||||
|  |     <ng-container psDataGridCol="ordering"> | ||||||
|  |         <ng-container *psDataGridColHeader>Priority</ng-container> | ||||||
|  |         <ng-container *psDataGridCell="let model">{{model.ordering}}</ng-container> | ||||||
|  |         <psbx-ds-number-filter *psDataGridCellFilter [dataSource]="merchantDataSource" path="ordering"> | ||||||
|  |         </psbx-ds-number-filter> | ||||||
|  |         <psbx-ds-sorting *psDataGridColSort [dataSource]="merchantDataSource" path="ordering"></psbx-ds-sorting> | ||||||
|  |     </ng-container> | ||||||
|  | 
 | ||||||
|  |     <ng-container psDataGridCol="openDate"> | ||||||
|  |         <ng-container *psDataGridColHeader>Open Date</ng-container> | ||||||
|  |         <ng-container *psDataGridCell="let model">{{model.openDate}}</ng-container> | ||||||
|  |         <psbx-ds-datetime-filter *psDataGridCellFilter [dataSource]="merchantDataSource" path="openDate"> | ||||||
|  |         </psbx-ds-datetime-filter> | ||||||
|  |         <psbx-ds-sorting *psDataGridColSort [dataSource]="merchantDataSource" path="openDate"></psbx-ds-sorting> | ||||||
|  |     </ng-container> | ||||||
|  | 
 | ||||||
|  |     <ng-container psDataGridCol="commands"> | ||||||
|  |         <ng-container *psDataGridColHeader>Actions</ng-container> | ||||||
|  |         <ng-container *psDataGridCell="let model"> | ||||||
|  |             <div class="btn-group"> | ||||||
|  |                 <button class="btn-info btn" psbxCommandModal [commandTitle]="'Change ' + model.name + ' name'" | ||||||
|  |                 commandText="Update" [dataSource]="merchantDataSource" command="changeMerchant" [model]="model" | ||||||
|  |                 [template]="theModal">Change</button> | ||||||
|  |                 <button class="btn-danger btn"  | ||||||
|  |                 psbxCommand  | ||||||
|  |                 [dataSource]="merchantDataSource"  | ||||||
|  |                 command="removeMerchant"  | ||||||
|  |                 [model]="model"  | ||||||
|  |                 [confirm]="true" | ||||||
|  |                 yesClass="warning" | ||||||
|  |                 noClass = "secondary" | ||||||
|  |                 noText = "Cancel Delete" | ||||||
|  |                 yesText = "Delete It" | ||||||
|  |                 confirmMessage="Are you sure you want to delete this merchant?" | ||||||
|  |                 >RemoveIt</button></div> | ||||||
|  |              | ||||||
|  |         </ng-container> | ||||||
|  |     </ng-container> | ||||||
|  |     <ng-container *psDataGridFooter> | ||||||
|  |         <psbx-ds-pagination [dataSource]="merchantDataSource"></psbx-ds-pagination> | ||||||
|  |     </ng-container> | ||||||
|  | </ps-data-grid> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | <ng-template #theModal let-command let-loading="loading"> | ||||||
|  |     <label for="name">Name</label> | ||||||
|  |     <input type="text" required  [(ngModel)]="command.name" placeholder="Enter a merchant name" | ||||||
|  |         class="form-control"> | ||||||
|  |     <label for="address">Address</label> | ||||||
|  |     <input type="text" required  [(ngModel)]="command.address" | ||||||
|  |         placeholder="Enter the merchant's address" class="form-control"> | ||||||
|  |     <label for="address">Priority</label> | ||||||
|  |     <input type="number" required  [(ngModel)]="command.ordering" | ||||||
|  |         placeholder="Enter the merchant's Priority" class="form-control"> | ||||||
|  |     <label for="address">Priority</label> | ||||||
|  |     <input type="date" required  [(ngModel)]="command.openDate" | ||||||
|  |         placeholder="Enter the merchant's Priority" class="form-control"> | ||||||
|  | 
 | ||||||
|  | </ng-template> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | <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> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,35 @@ | |||||||
|  | import { Component, OnInit } from '@angular/core'; | ||||||
|  | import { IDataSource, ISimpleFilter } from '@poweredsoft/data'; | ||||||
|  | import { IMerchant } from 'src/app/data/services/IMerchant'; | ||||||
|  | import { MerchantService } from 'src/app/data/services/merchant.service'; | ||||||
|  | import { ConfirmModalService } from '@poweredsoft/ngx-bootstrap'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   selector: 'ps-grid-filter-demo', | ||||||
|  |   templateUrl: './grid-filter-demo.component.html', | ||||||
|  |   styleUrls: ['./grid-filter-demo.component.scss'] | ||||||
|  | }) | ||||||
|  | export class GridFilterDemoComponent implements OnInit { | ||||||
|  | 
 | ||||||
|  |   columns = ['id','name', 'address', 'ordering','openDate', 'commands'] | ||||||
|  |   merchantDataSource: IDataSource<IMerchant>;   | ||||||
|  |   constructor(private  merchantService: MerchantService){ | ||||||
|  |     this.merchantDataSource = this.createDataSource(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   pages:any; | ||||||
|  |   filteredResults:any; | ||||||
|  |   somefilter:any; | ||||||
|  |    | ||||||
|  |   createDataSource(): IDataSource<IMerchant> { | ||||||
|  |     return this.merchantService.createDataSource(); | ||||||
|  |     | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ngOnInit() { | ||||||
|  |     this.merchantDataSource.refresh(); | ||||||
|  |      | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |    | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								src/app/ng-select-demo/ng-select-demo-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/app/ng-select-demo/ng-select-demo-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | import { NgModule } from "@angular/core"; | ||||||
|  | import { RouterModule, Routes } from '@angular/router'; | ||||||
|  | import { NgSelectDemoComponent } from './ng-select-demo/ng-select-demo.component'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | const routes: Routes =[ | ||||||
|  |     { | ||||||
|  |         path: '', | ||||||
|  |         component: NgSelectDemoComponent | ||||||
|  |     } | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |     imports: [RouterModule.forChild(routes)], | ||||||
|  |     exports: [RouterModule] | ||||||
|  | }) | ||||||
|  | export class NgSelectDemoRoutingModule { | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								src/app/ng-select-demo/ng-select-demo.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/app/ng-select-demo/ng-select-demo.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | import { NgModule } from '@angular/core'; | ||||||
|  | import { CommonModule } from '@angular/common'; | ||||||
|  | import { NgSelectDemoComponent } from './ng-select-demo/ng-select-demo.component'; | ||||||
|  | import { NgSelectDemoRoutingModule } from './ng-select-demo-routing.module'; | ||||||
|  | import { NgSelectModule } from '@ng-select/ng-select'; | ||||||
|  | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; | ||||||
|  | import { PsNgSelectModule } from '@poweredsoft/ng-select'; | ||||||
|  | import { CommandModule, CommandModalModule } from '@poweredsoft/ngx-bootstrap'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |   declarations: [NgSelectDemoComponent], | ||||||
|  |   imports: [ | ||||||
|  |     CommonModule, | ||||||
|  |     NgSelectModule, | ||||||
|  |     FormsModule, | ||||||
|  |     ReactiveFormsModule, | ||||||
|  |     NgSelectDemoRoutingModule, | ||||||
|  |     PsNgSelectModule, | ||||||
|  |     CommandModule, | ||||||
|  |     CommandModalModule | ||||||
|  |   ] | ||||||
|  | }) | ||||||
|  | export class NgSelectDemoModule { } | ||||||
| @ -0,0 +1,69 @@ | |||||||
|  | <h2>Single Select Demo | ngModel | option template</h2> | ||||||
|  | <ps-ng-select [dataSource]="merchantDataSource" bindLabel="name" bindValue="id" [(ngModel)]="myValue"> | ||||||
|  |     <div *psNgSelectOption="let item"> | ||||||
|  |        {{ item.name }} - {{ item.address }}        | ||||||
|  |     </div> | ||||||
|  | </ps-ng-select> | ||||||
|  | 
 | ||||||
|  | selected: {{ myValue | json }}  | ||||||
|  | 
 | ||||||
|  | <h2>Single Select With Form | formGroup | option template</h2> | ||||||
|  | <form #form [formGroup]="myForm"> | ||||||
|  |     <ps-ng-select [dataSource]="merchantDataSource2" bindLabel="name" bindValue="id" formControlName="merchantId" [serverFiltering]="true"> | ||||||
|  |         <div *psNgSelectOption="let item"> | ||||||
|  |            <span>Merchant:</span>  {{ item.name }} - <span>Address: </span>{{ item.address }} | ||||||
|  |         </div> | ||||||
|  |     </ps-ng-select> | ||||||
|  | </form> | ||||||
|  | selected:  {{ myForm.value | json }} | ||||||
|  | 
 | ||||||
|  | <h2>Single Select Demo | label Template</h2> | ||||||
|  | <ps-ng-select [dataSource]="merchantDataSource3" bindLabel="name" bindValue="id" [(ngModel)]="myValue3" [serverFiltering]="true"> | ||||||
|  |     <div *psNgSelectOption="let item"> | ||||||
|  |         <span>Merchant:</span>  {{ item.name }} - <span>Address: </span>{{ item.address }} | ||||||
|  |      </div> | ||||||
|  |      | ||||||
|  |     <div  *psNgSelectLabel="let item"> | ||||||
|  |         <img src="assets/32x32-blue.png"><span>Name: </span>{{ item.name }} - <span> Address: </span>{{item.address }} | ||||||
|  |     </div> | ||||||
|  | </ps-ng-select> | ||||||
|  | selected: {{ myValue3 | json }}  | ||||||
|  | 
 | ||||||
|  | <h2>Single Select Demo | notFound Template</h2> | ||||||
|  | <ps-ng-select [dataSource]="merchantDataSource3" bindLabel="name" bindValue="id" [(ngModel)]="myValue2" [serverFiltering]="false"> | ||||||
|  |     <div  *psNgNotFoundTemplate="let searchTerm"> | ||||||
|  |         <div class="ng-option disabled"> | ||||||
|  |             No data found for "{{searchTerm}}" | ||||||
|  |                 <button class="btn-primary btn"  | ||||||
|  |                 psbxCommandModal  | ||||||
|  |                 commandTitle="Adding a new {{searchTerm}}"  | ||||||
|  |                 commandText="Add" | ||||||
|  |                 [dataSource]="merchantDataSource"  | ||||||
|  |                 command="addMerchant"  | ||||||
|  |                 cancelText="Abort" | ||||||
|  |                 [template]="theModal" | ||||||
|  |                 (success)="myValue2 = $event"> Create New {{searchTerm}}</button> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  | </ps-ng-select> | ||||||
|  | selected: {{ myValue2 | json }}  | ||||||
|  | 
 | ||||||
|  |  <h2>Multi-Select Demo</h2> | ||||||
|  | <ps-ng-multi-select [dataSource]="merchantDataSource4" bindLabel="name" bindValue="id"  [serverFiltering]="true" [(ngModel)]="myValue4" > | ||||||
|  |     <div   *psNgSelectOption="let item"> | ||||||
|  |         <img src="assets/32x32-blue.png"><span>Name: </span>{{ item.name }} - <span> Address: </span>{{item.address }} | ||||||
|  |     </div> | ||||||
|  |     <ng-container  *psNgSelectLabel="let item;"> | ||||||
|  |         {{ item.name }} | ||||||
|  |     </ng-container> | ||||||
|  | </ps-ng-multi-select> | ||||||
|  | selected: {{ myValue4 | json }}  | ||||||
|  | 
 | ||||||
|  | <ng-template #theModal let-command let-loading="loading"> | ||||||
|  |     <form   > | ||||||
|  |         Name | ||||||
|  |         <input type="text" required [disabled]="loading" name="name" [(ngModel)]="command.name"  placeholder="Enter a merchant name" class="form-control" > | ||||||
|  |         Address | ||||||
|  |         <input type="text" required [disabled]="loading" name="address" [(ngModel)]="command.address"  placeholder="Enter the merchant's address" class="form-control" >                 | ||||||
|  |     </form> | ||||||
|  | </ng-template> | ||||||
| @ -0,0 +1,47 @@ | |||||||
|  | import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; | ||||||
|  | import { MerchantService } from 'src/app/data/services/merchant.service'; | ||||||
|  | 
 | ||||||
|  | import { IMerchant } from 'src/app/data/services/IMerchant'; | ||||||
|  | import { Observable, Subject } from 'rxjs'; | ||||||
|  | import { map, distinctUntilChanged, debounceTime } from 'rxjs/operators'; | ||||||
|  | import { IDataSource, ISimpleFilter } from '@poweredsoft/data'; | ||||||
|  | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   selector: 'ps-ng-select-demo', | ||||||
|  |   templateUrl: './ng-select-demo.component.html', | ||||||
|  |   styleUrls: ['./ng-select-demo.component.scss'] | ||||||
|  | }) | ||||||
|  | export class NgSelectDemoComponent implements OnInit { | ||||||
|  | 
 | ||||||
|  |   merchantDataSource: IDataSource<IMerchant>; | ||||||
|  |   merchantDataSource2: IDataSource<IMerchant>;  | ||||||
|  |   merchantDataSource3: IDataSource<IMerchant>;  | ||||||
|  |   merchantDataSource4: IDataSource<IMerchant>;    | ||||||
|  |    | ||||||
|  |   selectedValue: IMerchant; | ||||||
|  | 
 | ||||||
|  |   myForm: FormGroup; | ||||||
|  |   myValue: string; | ||||||
|  |   myValue2: string; | ||||||
|  |   myValue3: string; | ||||||
|  |   myValue4: string; | ||||||
|  | 
 | ||||||
|  |   constructor(private merchantService: MerchantService, private fb: FormBuilder | ||||||
|  |               ) { | ||||||
|  |     this.merchantDataSource = merchantService.createDataSource(); //Assign the dataSource
 | ||||||
|  |     this.merchantDataSource2 = merchantService.createDataSource();  | ||||||
|  |     this.merchantDataSource3 = merchantService.createDataSource();  | ||||||
|  |     this.merchantDataSource4 = merchantService.createDataSource();  | ||||||
|  |     this.myForm = fb.group({ | ||||||
|  |       'merchantId': [null] | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ngOnInit(): void { | ||||||
|  |      | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |    | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -4,7 +4,7 @@ import { CommonModule } from '@angular/common'; | |||||||
| import { PaginationDemoRoutingModule } from './pagination-demo-routing.module'; | import { PaginationDemoRoutingModule } from './pagination-demo-routing.module'; | ||||||
| import { PaginationDemoComponent } from './pagination-demo/pagination/pagination-demo.component'; | import { PaginationDemoComponent } from './pagination-demo/pagination/pagination-demo.component'; | ||||||
| import { DataGridModule } from '@poweredsoft/ngx-cdk-ui'; | import { DataGridModule } from '@poweredsoft/ngx-cdk-ui'; | ||||||
| import { psbxPaginationModule, CommandModalModule, ConfirmModalModule,SpinnerModule } from '@poweredsoft/ngx-bootstrap'; | import { PaginationModule, CommandModalModule, ConfirmModalModule,SpinnerModule, CommandModule } from '@poweredsoft/ngx-bootstrap'; | ||||||
| import { FormsModule } from '@angular/forms'; | import { FormsModule } from '@angular/forms'; | ||||||
| import { ModalModule } from 'ngx-bootstrap/modal'; | import { ModalModule } from 'ngx-bootstrap/modal'; | ||||||
| 
 | 
 | ||||||
| @ -16,12 +16,13 @@ import { ModalModule } from 'ngx-bootstrap/modal'; | |||||||
|   imports: [ |   imports: [ | ||||||
|     CommonModule, |     CommonModule, | ||||||
|     PaginationDemoRoutingModule, |     PaginationDemoRoutingModule, | ||||||
|     psbxPaginationModule, |     PaginationModule, | ||||||
|     DataGridModule, |     DataGridModule, | ||||||
|     CommandModalModule, |     CommandModalModule, | ||||||
|     ConfirmModalModule, |     ConfirmModalModule, | ||||||
|     FormsModule, |     FormsModule, | ||||||
|     SpinnerModule |     SpinnerModule, | ||||||
|  |     CommandModule | ||||||
|         |         | ||||||
|   ] |   ] | ||||||
| }) | }) | ||||||
|  | |||||||
| @ -16,18 +16,6 @@ | |||||||
|     <ng-container psDataGridCol="id"> |     <ng-container psDataGridCol="id"> | ||||||
|         <div *psDataGridColHeader>ID</div> |         <div *psDataGridColHeader>ID</div> | ||||||
|         <div *psDataGridCell="let model">{{model.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> | ||||||
| 
 | 
 | ||||||
|     <ng-container psDataGridCol="name"> |     <ng-container psDataGridCol="name"> | ||||||
| @ -42,8 +30,29 @@ | |||||||
|     <ng-container psDataGridCol="commands"> |     <ng-container psDataGridCol="commands"> | ||||||
|         <ng-container *psDataGridColHeader>Actions</ng-container> |         <ng-container *psDataGridColHeader>Actions</ng-container> | ||||||
|         <ng-container *psDataGridCell="let model"> |         <ng-container *psDataGridCell="let model"> | ||||||
|             <button class="btn-danger btn" psbxConfirmModal [commandTitle]="'Are you sure you wnat to remove ' + model.name + '?'" commandText="Remove" |             <div class="btn-group"> | ||||||
|             [dataSource]="merchantDataSource" command="removeMerchant" [model]="model" >Remove</button> |                 <button class="btn-warning btn" psbxCommandModal  | ||||||
|  |                 commandTitle="Update {{model.name}}"  | ||||||
|  |                 commandText="Save" | ||||||
|  |                 [dataSource]="merchantDataSource"  | ||||||
|  |                 command="changeMerchant" | ||||||
|  |                 [model]="model"   | ||||||
|  |                 [template]="theModal">Update</button> | ||||||
|  | 
 | ||||||
|  |                 <button class="btn-danger btn"  | ||||||
|  |                 psbxCommand  | ||||||
|  |                 [dataSource]="merchantDataSource"  | ||||||
|  |                 command="removeMerchant"  | ||||||
|  |                 [model]="model"  | ||||||
|  |                 [confirm]="true" | ||||||
|  |                 yesClass="warning" | ||||||
|  |                 noClass = "secondary" | ||||||
|  |                 noText = "Cancel Delete" | ||||||
|  |                 yesText = "Delete It" | ||||||
|  |                 confirmMessage="Are you sure you want to delete this merchant?" | ||||||
|  |                 >Remove</button> | ||||||
|  |             </div> | ||||||
|  | 
 | ||||||
|         </ng-container> |         </ng-container> | ||||||
|     </ng-container> |     </ng-container> | ||||||
| 
 | 
 | ||||||
| @ -63,7 +72,6 @@ | |||||||
|   </ng-template> |   </ng-template> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|  <ng-template #theModal let-command let-loading="loading"> |  <ng-template #theModal let-command let-loading="loading"> | ||||||
|         <label for="name">Name</label> |         <label for="name">Name</label> | ||||||
|         <input type="text" required [attr.disabled]="loading" [(ngModel)]="command.name" placeholder="Enter a merchant name"  |         <input type="text" required [attr.disabled]="loading" [(ngModel)]="command.name" placeholder="Enter a merchant name"  | ||||||
|  | |||||||
| @ -1,57 +1,37 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||||||
| import { IDataSource } from '@poweredsoft/data'; | import { IDataSource } from '@poweredsoft/data'; | ||||||
| import { IMerchant } from 'src/app/data/services/IMerchant'; | import { IMerchant } from 'src/app/data/services/IMerchant'; | ||||||
| import { MerchantService } from 'src/app/data/services/merchant.service'; | import { MerchantService } from 'src/app/data/services/merchant.service'; | ||||||
| import { FormBuilder, Validators } from '@angular/forms'; | import { FormBuilder, Validators } from '@angular/forms'; | ||||||
| import { ConfirmModalService } from '@poweredsoft/ngx-bootstrap'; | import { ConfirmModalService } from '@poweredsoft/ngx-bootstrap'; | ||||||
|  | import { Subscription } from 'rxjs'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'ps-pagination', |   selector: 'ps-pagination', | ||||||
|   templateUrl: './pagination-demo.component.html', |   templateUrl: './pagination-demo.component.html', | ||||||
|   styleUrls: ['./pagination-demo.component.scss'] |   styleUrls: ['./pagination-demo.component.scss'] | ||||||
| }) | }) | ||||||
| export class PaginationDemoComponent implements OnInit { | export class PaginationDemoComponent implements OnInit, OnDestroy { | ||||||
|   columns = ['id','name', 'address','commands'] |   columns = ['id','name', 'address','commands'] | ||||||
|   merchantDataSource: IDataSource<IMerchant>;   |   merchantDataSource: IDataSource<IMerchant>;   | ||||||
|  |   private _dataSubscription: Subscription; | ||||||
|   constructor(private  merchantService: MerchantService, private confirmModalService: ConfirmModalService){ |   constructor(private  merchantService: MerchantService, private confirmModalService: ConfirmModalService){ | ||||||
|     this.merchantDataSource = this.createDataSource(); |     this.merchantDataSource = this.createDataSource(); | ||||||
| 
 | 
 | ||||||
|   } |   } | ||||||
|  |   ngOnDestroy(): void { | ||||||
|  |     this._dataSubscription.unsubscribe(); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   pages:any; |   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> { |   createDataSource(): IDataSource<IMerchant> { | ||||||
|     return this.merchantService.createDataSource(); |     return this.merchantService.createDataSource(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   ngOnInit() { |   ngOnInit() { | ||||||
|     this.merchantDataSource.refresh(); |     this.merchantDataSource.refresh(); | ||||||
|     this.merchantDataSource.data$.subscribe(newData => {      |     this._dataSubscription = this.merchantDataSource.data$.subscribe(newData => {      | ||||||
|       if (newData) |       if (newData) | ||||||
|         this.pages = new Array(newData.numberOfPages); |         this.pages = new Array(newData.numberOfPages); | ||||||
|     }); |     }); | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								src/assets/32x32-blue.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/32x32-blue.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/avatar.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/avatar.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 194 B | 
| @ -1,2 +1,4 @@ | |||||||
| /* You can add global styles to this file, and also import other style files */ | /* You can add global styles to this file, and also import other style files */ | ||||||
| @import '~bootstrap/scss/bootstrap'; | @import '~bootstrap/scss/bootstrap'; | ||||||
|  | @import '~ngx-bootstrap/datepicker/bs-datepicker.css'; | ||||||
|  | @import "~@ng-select/ng-select/themes/default.theme.css"; | ||||||
| @ -23,6 +23,10 @@ | |||||||
|       "@poweredsoft/ngx-bootstrap": [ |       "@poweredsoft/ngx-bootstrap": [ | ||||||
|         "dist/poweredsoft/ngx-bootstrap/poweredsoft-ngx-bootstrap", |         "dist/poweredsoft/ngx-bootstrap/poweredsoft-ngx-bootstrap", | ||||||
|         "dist/poweredsoft/ngx-bootstrap" |         "dist/poweredsoft/ngx-bootstrap" | ||||||
|  |       ], | ||||||
|  |       "@poweredsoft/ng-select": [ | ||||||
|  |         "dist/poweredsoft/ng-select/poweredsoft-ng-select", | ||||||
|  |         "dist/poweredsoft/ng-select" | ||||||
|       ] |       ] | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user