single object data source.
This commit is contained in:
		
							parent
							
								
									2972b38a1a
								
							
						
					
					
						commit
						2485bdb835
					
				| @ -0,0 +1,128 @@ | ||||
| import { HttpClient, HttpErrorResponse } from "@angular/common/http"; | ||||
| import { DataSource, IDataSource, IDataSourceCommandAdapterOptions, IDataSourceError, IDataSourceErrorMessage, IDataSourceOptions, IDataSourceQueryAdapterOptions, IDataSourceTransportOptions, IDataSourceValidationError, IQueryCriteria, IResolveCommandModelEvent } from "@poweredsoft/data"; | ||||
| import { Observable, of, throwError } from "rxjs"; | ||||
| import { catchError, switchMap } from "rxjs/operators"; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| export abstract class BaseHttpDataSourceOptionsBuilder<TModel, TKey> { | ||||
|     protected _commands: { [key: string]: IDataSourceCommandAdapterOptions<any>; } = {}; | ||||
|     protected _keyResolver: (model: TModel) => TKey; | ||||
|     protected _defaultCriteria: IQueryCriteria; | ||||
|     protected _query: IDataSourceQueryAdapterOptions<TModel>; | ||||
| 
 | ||||
|     constructor(protected http: HttpClient) { | ||||
|     } | ||||
| 
 | ||||
|     createDataSource(): IDataSource<TModel> { | ||||
|         return new DataSource<TModel>(this.createOptions()); | ||||
|     } | ||||
| 
 | ||||
|     protected createTransport(): IDataSourceTransportOptions<TModel> { | ||||
|         let ret: IDataSourceTransportOptions<TModel> = { | ||||
|             query: this._query, | ||||
|             commands: this._commands | ||||
|         }; | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     public keyResolver(resolver: (model: TModel) => TKey) { | ||||
|         this._keyResolver = resolver; | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     createOptions(): IDataSourceOptions<TModel> { | ||||
|         let ret: IDataSourceOptions<TModel> = { | ||||
|             resolveIdField: this._keyResolver, | ||||
|             defaultCriteria: this._defaultCriteria, | ||||
|             transport: this.createTransport() | ||||
|         }; | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     private _messageErrorHandler(err: HttpErrorResponse) { | ||||
| 
 | ||||
|         if (typeof err.error == "object") { | ||||
|             // if status not okay then its an exception error
 | ||||
|             if (err.error.hasOwnProperty('Message') && typeof (err.error['Message']) == "string") { | ||||
|                 return throwError(<IDataSourceErrorMessage>{ | ||||
|                     type: 'message', | ||||
|                     message: err.error['Message'] | ||||
|                 }); | ||||
|             } | ||||
|             else if (err.error.hasOwnProperty('message') && typeof (err.error['message']) == "string") { | ||||
|                 return throwError(<IDataSourceErrorMessage>{ | ||||
|                     type: 'message', | ||||
|                     message: err.error['message'] | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // general error message
 | ||||
|         if (typeof (err.error) == "string") { | ||||
|             return throwError(<IDataSourceErrorMessage>{ | ||||
|                 type: 'message', | ||||
|                 message: err.error | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         return throwError(<IDataSourceErrorMessage>{ | ||||
|             type: 'message', | ||||
|             message: 'UNEXPECTED_ERROR_MESSAGE' | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private _handleErrorPipe(err: HttpErrorResponse): Observable<IDataSourceError> { | ||||
| 
 | ||||
|         if (err.status == 400) { | ||||
|             if (err.error && err.error.errors) | ||||
|                 return throwError(<IDataSourceValidationError>{ | ||||
|                     type: 'validation', | ||||
|                     errors: err.error.errors | ||||
|                 }); | ||||
|         } | ||||
| 
 | ||||
|         return this._messageErrorHandler(err); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     public addCommandByCallback<TCommand, TCommandResult>(name: string, commandHandler: (command: TCommand) => Observable<TCommandResult>, resolveCommandModel?: (event: IResolveCommandModelEvent<TModel>) => Observable<TCommand & any>) { | ||||
|         const handleWrapper = command => { | ||||
|             return commandHandler(command).pipe(catchError(err => this._handleErrorPipe.bind(this))); | ||||
|         }; | ||||
| 
 | ||||
|         this._commands[name] = <IDataSourceCommandAdapterOptions<TModel>>{ | ||||
|             adapter: { | ||||
|                 handle: handleWrapper | ||||
|             }, | ||||
|             resolveCommandModel: resolveCommandModel | ||||
|         }; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public addCommandByUrl<TCommand, TCommandResult>(name: string, url: string, resolveCommandModel?: (event: IResolveCommandModelEvent<TModel>) => Observable<TCommand & any>, beforeCommand?: (command: TCommand) => Observable<TCommand>) { | ||||
|         const handleWrapper = command => { | ||||
|             const finalBeforeCommand = beforeCommand || (_ => of(command)); | ||||
|             return finalBeforeCommand(command) | ||||
|                 .pipe( | ||||
|                     switchMap(finalCommand => { | ||||
|                         return this.http.post<TCommandResult>(url, finalCommand).pipe(catchError(this._handleErrorPipe.bind(this))); | ||||
|                     }) | ||||
|                 ); | ||||
|         }; | ||||
| 
 | ||||
|         this._commands[name] = <IDataSourceCommandAdapterOptions<TModel>>{ | ||||
|             adapter: { | ||||
|                 handle: handleWrapper | ||||
|             }, | ||||
|             resolveCommandModel: resolveCommandModel | ||||
|         }; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,46 +1,17 @@ | ||||
| import { HttpClient, HttpErrorResponse, HttpResponse } from "@angular/common/http"; | ||||
| import { DataSource, IDataSource, IDataSourceCommandAdapterOptions, IDataSourceError, IDataSourceErrorMessage, IDataSourceOptions, IDataSourceQueryAdapterOptions, IDataSourceTransportOptions, IDataSourceValidationError, IQueryCriteria, IQueryExecutionGroupResult, IQueryExecutionResult, IResolveCommandModelEvent } from "@poweredsoft/data"; | ||||
| import { Observable, of, throwError } from "rxjs"; | ||||
| import { catchError, switchMap } from "rxjs/operators"; | ||||
| import { HttpClient, HttpResponse } from "@angular/common/http"; | ||||
| import { IQueryCriteria, IQueryExecutionGroupResult, IQueryExecutionResult } from "@poweredsoft/data"; | ||||
| import { Observable, of } from "rxjs"; | ||||
| import { switchMap } from "rxjs/operators"; | ||||
| import { BaseHttpDataSourceOptionsBuilder } from "./BaseHttpDataSourceOptionsBuilder"; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| export class HttpDataSourceOptionsBuilder<TModel, TKey> { | ||||
| 
 | ||||
|     private _commands: { [key: string]: IDataSourceCommandAdapterOptions<any> } = {}; | ||||
| export class HttpDataSourceOptionsBuilder<TModel, TKey>  | ||||
|     extends BaseHttpDataSourceOptionsBuilder<TModel, TKey> | ||||
| { | ||||
|     private _beforeRead: (TQuery: IQueryCriteria) => Observable<IQueryCriteria>; | ||||
|     private _keyResolver: (model: TModel) => TKey; | ||||
|     private _defaultCriteria: IQueryCriteria; | ||||
|     private _query: IDataSourceQueryAdapterOptions<TModel>; | ||||
| 
 | ||||
|     constructor(private http: HttpClient) { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     createOptions(): IDataSourceOptions<TModel> { | ||||
|         let ret: IDataSourceOptions<TModel> = { | ||||
|             resolveIdField: this._keyResolver, | ||||
|             defaultCriteria: this._defaultCriteria, | ||||
|             transport: this.createTransport() | ||||
|         }; | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     createDataSource(): IDataSource<TModel> { | ||||
|         return new DataSource<TModel>(this.createOptions()); | ||||
|     } | ||||
| 
 | ||||
|     protected createTransport(): IDataSourceTransportOptions<TModel> { | ||||
|         let ret: IDataSourceTransportOptions<TModel> = { | ||||
|             query: this._query, | ||||
|             commands: this._commands | ||||
|         }; | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     public keyResolver(resolver: (model: TModel) => TKey) { | ||||
|         this._keyResolver = resolver; | ||||
|         return this; | ||||
|     constructor(http: HttpClient) { | ||||
|         super(http); | ||||
|     } | ||||
| 
 | ||||
|     public beforeRead<TDynamicQuery extends IQueryCriteria>(beforeRead: (query: TDynamicQuery) => Observable<TDynamicQuery>) { | ||||
| @ -84,87 +55,6 @@ export class HttpDataSourceOptionsBuilder<TModel, TKey> { | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     private _messageErrorHandler(err: HttpErrorResponse) { | ||||
| 
 | ||||
|         if (typeof err.error == "object") { | ||||
|             // if status not okay then its an exception error
 | ||||
|             if (err.error.hasOwnProperty('Message') && typeof (err.error['Message']) == "string") { | ||||
|                 return throwError(<IDataSourceErrorMessage>{ | ||||
|                     type: 'message', | ||||
|                     message: err.error['Message'] | ||||
|                 }); | ||||
|             } | ||||
|             else if (err.error.hasOwnProperty('message') && typeof (err.error['message']) == "string") { | ||||
|                 return throwError(<IDataSourceErrorMessage>{ | ||||
|                     type: 'message', | ||||
|                     message: err.error['message'] | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // general error message
 | ||||
|         if (typeof (err.error) == "string") { | ||||
|             return throwError(<IDataSourceErrorMessage>{ | ||||
|                 type: 'message', | ||||
|                 message: err.error | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         return throwError(<IDataSourceErrorMessage>{ | ||||
|             type: 'message', | ||||
|             message: 'UNEXPECTED_ERROR_MESSAGE' | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private _handleErrorPipe(err: HttpErrorResponse): Observable<IDataSourceError> { | ||||
| 
 | ||||
|         if (err.status == 400) { | ||||
|             if (err.error && err.error.errors) | ||||
|                 return throwError(<IDataSourceValidationError>{ | ||||
|                     type: 'validation', | ||||
|                     errors: err.error.errors | ||||
|                 }); | ||||
|         } | ||||
| 
 | ||||
|         return this._messageErrorHandler(err); | ||||
|     } | ||||
| 
 | ||||
|     public addCommandByCallback<TCommand, TCommandResult>(name: string, commandHandler: (command: TCommand) => Observable<TCommandResult>, resolveCommandModel?: (event: IResolveCommandModelEvent<TModel>) => Observable<TCommand & any>) { | ||||
|         const handleWrapper = command => { | ||||
|             return commandHandler(command).pipe(catchError(err => this._handleErrorPipe.bind(this))); | ||||
|         }; | ||||
| 
 | ||||
|         this._commands[name] = <IDataSourceCommandAdapterOptions<TModel>>{ | ||||
|             adapter: { | ||||
|                 handle: handleWrapper | ||||
|             }, | ||||
|             resolveCommandModel: resolveCommandModel | ||||
|         }; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public addCommandByUrl<TCommand, TCommandResult>(name: string, url: string, resolveCommandModel?: (event: IResolveCommandModelEvent<TModel>) => Observable<TCommand & any>, beforeCommand?: (command: TCommand) => Observable<TCommand>) { | ||||
|         const handleWrapper = command => { | ||||
|             const finalBeforeCommand = beforeCommand || (_ => of(command)); | ||||
|             return finalBeforeCommand(command) | ||||
|                 .pipe( | ||||
|                     switchMap(finalCommand => { | ||||
|                         return this.http.post<TCommandResult>(url, finalCommand).pipe(catchError(this._handleErrorPipe.bind(this))); | ||||
|                     }) | ||||
|                 ); | ||||
|         }; | ||||
| 
 | ||||
|         this._commands[name] = <IDataSourceCommandAdapterOptions<TModel>>{ | ||||
|             adapter: { | ||||
|                 handle: handleWrapper | ||||
|             }, | ||||
|             resolveCommandModel: resolveCommandModel | ||||
|         }; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     defaultCriteria(criteria: IQueryCriteria) { | ||||
|         this._defaultCriteria = criteria; | ||||
|         return this; | ||||
|  | ||||
| @ -0,0 +1,103 @@ | ||||
| import { HttpClient, HttpResponse } from "@angular/common/http"; | ||||
| import { Query } from "@angular/core"; | ||||
| import { IQueryCriteria, IQueryExecutionGroupResult, IQueryExecutionResult, IQueryExecutionResultPaging } from "@poweredsoft/data"; | ||||
| import { Observable, of } from "rxjs"; | ||||
| import { map, switchMap } from "rxjs/operators"; | ||||
| import { BaseHttpDataSourceOptionsBuilder } from "./BaseHttpDataSourceOptionsBuilder"; | ||||
| 
 | ||||
| export class SingleDataSourceOptionsBuilder<TQuery, TModel, TKey>  | ||||
|     extends BaseHttpDataSourceOptionsBuilder<TModel, TKey> | ||||
| { | ||||
|     private _beforeRead: (query: IQueryCriteria) => Observable<TQuery>; | ||||
|      | ||||
|     constructor(http: HttpClient) { | ||||
|         super(http); | ||||
|     } | ||||
| 
 | ||||
|     public queryUrlWithGet(url: string) { | ||||
|         this._query = { | ||||
|             adapter: { | ||||
|                 handle: (query: IQueryCriteria) => { | ||||
|                     const finalBeforeRead = this._beforeRead || ((query: IQueryCriteria) => of(<TQuery>{})); | ||||
|                     return finalBeforeRead(query) | ||||
|                         .pipe( | ||||
|                             switchMap(finalQuery => { | ||||
|                                 return this.http.get<TModel>(url, { | ||||
|                                     params: this.convertToParams(finalQuery) | ||||
|                                 }).pipe( | ||||
|                                     map(result => { | ||||
|                                         return <IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>> | ||||
|                                         { | ||||
|                                             totalRecords: result == null ? 0 : 1, | ||||
|                                             data: [result] | ||||
|                                         }; | ||||
|                                     }) | ||||
|                                 ) | ||||
|                             }) | ||||
|                         ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     protected convertToParams(finalQuery: TQuery)  | ||||
|     { | ||||
|         return Object.keys(finalQuery).reduce((prev, key) => { | ||||
|             prev[key] = finalQuery[key]; | ||||
|             return prev; | ||||
|         }, {} as { [param: string]: string | string[]; }); | ||||
|     } | ||||
| 
 | ||||
|     public queryPostUrl(url: string) { | ||||
|         this._query = { | ||||
|             adapter: { | ||||
|                 handle: (query: IQueryCriteria) => { | ||||
|                     const finalBeforeRead = this._beforeRead || ((_: IQueryCriteria) => of(<TQuery>{})); | ||||
|                     return finalBeforeRead(query) | ||||
|                         .pipe( | ||||
|                             switchMap(finalQuery => { | ||||
|                                 return this.http.post<TModel>(url, finalQuery).pipe( | ||||
|                                     map(result => { | ||||
|                                         return <IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>> | ||||
|                                         { | ||||
|                                             totalRecords: result == null ? 0 : 1, | ||||
|                                             data: [result] | ||||
|                                         }; | ||||
|                                     }) | ||||
|                                 ) | ||||
|                             }) | ||||
|                         ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public queryHandler(queryHandler: (query: IQueryCriteria) => Observable<TModel>) { | ||||
|         this._query = { | ||||
|             adapter: { | ||||
|                 handle: (query: TQuery) => { | ||||
|                     const finalBeforeRead = this._beforeRead || (t => of({})); | ||||
|                     return finalBeforeRead(query) | ||||
|                         .pipe( | ||||
|                             switchMap(finalQuery => { | ||||
|                                 return queryHandler(finalQuery).pipe( | ||||
|                                     map(result => { | ||||
|                                         return <IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>>{ | ||||
|                                             totalRecords: result == null ? 0 : 1, | ||||
|                                             data: [result] | ||||
|                                         }; | ||||
|                                     }) | ||||
|                                 ) | ||||
|                             }) | ||||
|                         ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user