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 { HttpClient, HttpResponse } from "@angular/common/http"; | ||||||
| import { DataSource, IDataSource, IDataSourceCommandAdapterOptions, IDataSourceError, IDataSourceErrorMessage, IDataSourceOptions, IDataSourceQueryAdapterOptions, IDataSourceTransportOptions, IDataSourceValidationError, IQueryCriteria, IQueryExecutionGroupResult, IQueryExecutionResult, IResolveCommandModelEvent } from "@poweredsoft/data"; | import { IQueryCriteria, IQueryExecutionGroupResult, IQueryExecutionResult } from "@poweredsoft/data"; | ||||||
| import { Observable, of, throwError } from "rxjs"; | import { Observable, of } from "rxjs"; | ||||||
| import { catchError, switchMap } from "rxjs/operators"; | import { switchMap } from "rxjs/operators"; | ||||||
|  | import { BaseHttpDataSourceOptionsBuilder } from "./BaseHttpDataSourceOptionsBuilder"; | ||||||
| 
 | 
 | ||||||
| 
 | export class HttpDataSourceOptionsBuilder<TModel, TKey>  | ||||||
| 
 |     extends BaseHttpDataSourceOptionsBuilder<TModel, TKey> | ||||||
| export class HttpDataSourceOptionsBuilder<TModel, TKey> { | { | ||||||
| 
 |  | ||||||
|     private _commands: { [key: string]: IDataSourceCommandAdapterOptions<any> } = {}; |  | ||||||
|     private _beforeRead: (TQuery: IQueryCriteria) => Observable<IQueryCriteria>; |     private _beforeRead: (TQuery: IQueryCriteria) => Observable<IQueryCriteria>; | ||||||
|     private _keyResolver: (model: TModel) => TKey; |  | ||||||
|     private _defaultCriteria: IQueryCriteria; |  | ||||||
|     private _query: IDataSourceQueryAdapterOptions<TModel>; |  | ||||||
| 
 | 
 | ||||||
|     constructor(private http: HttpClient) { |  | ||||||
| 
 | 
 | ||||||
|     } |     constructor(http: HttpClient) { | ||||||
| 
 |         super(http); | ||||||
|     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; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public beforeRead<TDynamicQuery extends IQueryCriteria>(beforeRead: (query: TDynamicQuery) => Observable<TDynamicQuery>) { |     public beforeRead<TDynamicQuery extends IQueryCriteria>(beforeRead: (query: TDynamicQuery) => Observable<TDynamicQuery>) { | ||||||
| @ -84,87 +55,6 @@ export class HttpDataSourceOptionsBuilder<TModel, TKey> { | |||||||
|         return this; |         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) { |     defaultCriteria(criteria: IQueryCriteria) { | ||||||
|         this._defaultCriteria = criteria; |         this._defaultCriteria = criteria; | ||||||
|         return this; |         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