1+ import { ComponentRef } from '@angular/core' ;
12import { HttpInterceptor , HttpHandler , HttpRequest , HttpResponse , HttpEvent , HttpErrorResponse } from '@angular/common/http' ;
23
34import { Observable } from 'rxjs' ;
45import { tap } from 'rxjs/operators' ;
56
7+ import { PoComponentInjectorService } from '../../services/po-component-injector/po-component-injector.service' ;
8+ import { PoHttpInterceptorDetail } from './po-http-interceptor-detail/po-http-interceptor-detail.interface' ;
9+ import { PoHttpInterceptorDetailComponent } from './po-http-interceptor-detail/po-http-interceptor-detail.component' ;
10+
11+ // DEPRECATED 4.x.x
612const NO_ERROR_HEADER_PARAM = 'X-Portinari-No-Error' ;
13+ const NO_MESSAGE_HEADER_PARAM = 'X-Portinari-No-Message' ;
714
815/**
916 * @description
@@ -15,31 +22,40 @@ const NO_ERROR_HEADER_PARAM = 'X-Portinari-No-Error';
1522 * Ao analisar o objeto `_messages` retornado pela requisição, o serviço exibirá notificações com mensagens na tela.
1623 * Os retornos de erros com códigos 4xx e 5xx são tratados automaticamente, sem a necessidade de incluir o `_messages`.
1724 *
18- * Também existe a possibilidade de não apresentar a notificação quando houver algum erro com códigos 4xx e 5xx,
19- * utilizando o parâmetro `X-Portinari-No-Error` que foi definido conforme o
20- * [**Guia de implementação das APIs TOTVS**](http://tdn.totvs.com/pages/viewpage.action?pageId=484701395) (em Cabeçalhos Customizados).
21- * O parâmetro `X-Portinari-No-Error` deve ser informado no cabeçalho da requisição com o valor `'true'` para funcionar corretamente,
22- * por exemplo:
25+ * É possível dispensar a notificação para o usuário utilizando-se no cabeçalho da requisição os parâmetros listados abaixo com o valor
26+ * igual a `true`:
27+ *
28+ * - `X-Portinari-No-Message`: Não exibe notificações de erro e/ou sucesso.
29+ *
30+ * - **Depreciado** `X-Portinari-No-Error`: não mostra notificações de erro com códigos `4xx` e `5xx`.
2331 *
2432 * ```
2533 * ...
26- * const headers = { 'X-Portinari-No-Error ': 'true' };
34+ * const headers = { 'X-Portinari-No-Message ': 'true' };
2735 *
2836 * this.http.get(`/customers/1`, { headers: headers });
2937 * ...
3038 *
3139 * ```
32- * > Após a validação no interceptor, o parâmetro será removido do cabeçalho da requisição.
40+ *
41+ * Mais detalhes no tópico sobre cabeçalhos customizados no
42+ * [**Guia de implementação das APIs TOTVS**](http://tdn.totvs.com/pages/viewpage.action?pageId=484701395)
43+ *
44+ * > Após a validação no interceptor, os parâmetros serão removidos do cabeçalho da requisição.
3345 *
3446 * O `Content-Type` deve ser `application/json` e a estrutura de mensagem recebida pelo serviço deve seguir o
3547 * [**Guia de implementação das APIs TOTVS**](http://tdn.totvs.com/pages/viewpage.action?pageId=484701395)
3648 * (em Mensagens de sucesso para coleções), exemplo:
37- * - _messages: lista de mensagens de erro ou informativo resultante do serviço.
38- * - type: success, warning, error, e information;
49+ * - _messages: lista de mensagens ou objeto de mensagem, resultante do serviço.
50+ * - type: success, warning, error, e information (será exibido a `tag` apenas se esta propriedade possuir valor) ;
3951 * - code: título ou código da mensagem;
4052 * - message: texto da mensagem;
4153 * - detailedMessage: detalhamento do erro ou informativo;
4254 *
55+ * Ao clicar na ação 'Detalhes' no
56+ * [`po-notification`](/documentation/po-notification) os detalhes das mensagens de sucesso e de erro são apresentados em
57+ * um [`po-modal`](/documentation/po-modal) com um [`po-accordion`](/documentation/po-accordion) que possui um item por mensagem.
58+ *
4359 * Ao importar o módulo `PoModule` na aplicação, o `po-http-interceptor` é automaticamente configurado sem a necessidade
4460 * de qualquer configuração extra.
4561 *
@@ -69,18 +85,20 @@ export abstract class PoHttpInterceptorBaseService implements HttpInterceptor {
6985
7086 notificationTypes = [ 'success' , 'warning' , 'error' , 'information' ] ;
7187
72- constructor ( private notification : any , private dialog : any ) { }
88+ private httpInterceptorDetailComponent : ComponentRef < PoHttpInterceptorDetailComponent > = undefined ;
89+
90+ constructor ( private componentInjector : PoComponentInjectorService , private notification : any ) { }
7391
7492 intercept ( request : HttpRequest < any > , next : HttpHandler ) : Observable < HttpEvent < any > > {
7593 const cloneRequest = request . clone ( ) ;
7694
77- request = request . headers . has ( NO_ERROR_HEADER_PARAM ) ? this . cloneRequestWithoutNoErrorHeaderParam ( request ) : request ;
95+ request = request && this . hasParameters ( request ) ? this . cloneRequestWithoutParameters ( request ) : request ;
7896
7997 return next . handle ( request ) . pipe ( tap ( ( response : HttpEvent < any > ) => {
8098
8199 if ( response instanceof HttpResponse ) {
82100
83- this . processResponse ( response ) ;
101+ this . processResponse ( response , cloneRequest ) ;
84102
85103 }
86104 } , ( error : HttpErrorResponse ) => {
@@ -90,13 +108,15 @@ export abstract class PoHttpInterceptorBaseService implements HttpInterceptor {
90108 } ) ) ;
91109 }
92110
93- processResponse ( response : HttpResponse < any > ) {
94- if ( response . body && response . body . _messages ) {
111+ processResponse ( response : HttpResponse < any > , request : HttpRequest < any > ) {
112+ const hasNoMessageParam = this . hasNoMessageParam ( request ) ;
113+
114+ if ( ! hasNoMessageParam && response . body && response . body . _messages ) {
95115
96116 const messages = response . body . _messages ;
97117
98118 if ( messages instanceof Array ) {
99- messages . forEach ( ( message : any ) => {
119+ messages . forEach ( ( message : PoHttpInterceptorDetail ) => {
100120 this . showNotification ( message ) ;
101121 } ) ;
102122 } else {
@@ -111,15 +131,41 @@ export abstract class PoHttpInterceptorBaseService implements HttpInterceptor {
111131 : { code : 0 , message : 'Servidor não está respondendo.' , detailedMessage : response . message } ;
112132
113133 const hasNoErrorParam = this . hasNoErrorParam ( request ) ;
134+ const hasNoMessageParam = this . hasNoMessageParam ( request ) ;
114135
115- // not show the notification when has NoError parameter on header of request.
116- if ( errorResponse && errorResponse . message && ! hasNoErrorParam ) {
136+ if ( errorResponse && errorResponse . message && ! hasNoErrorParam && ! hasNoMessageParam ) {
117137 this . showNotification ( { ...errorResponse , type : 'error' } ) ;
118138 }
119139 }
120140
121- private cloneRequestWithoutNoErrorHeaderParam ( request : HttpRequest < any > ) : HttpRequest < any > {
122- return request && request . clone ( { headers : request . headers . delete ( NO_ERROR_HEADER_PARAM ) } ) ;
141+ private cloneRequestWithoutParameters ( request : HttpRequest < any > ) : HttpRequest < any > {
142+ const headers = request . headers
143+ . delete ( NO_ERROR_HEADER_PARAM )
144+ . delete ( NO_MESSAGE_HEADER_PARAM ) ;
145+
146+ return request . clone ( { headers } ) ;
147+ }
148+
149+ private createModal ( responseMessage : PoHttpInterceptorDetail ) {
150+ const details = responseMessage . details ? [ responseMessage , ...responseMessage . details ] : [ responseMessage ] ;
151+
152+ this . httpInterceptorDetailComponent = this . componentInjector . createComponentInApplication ( PoHttpInterceptorDetailComponent ) ;
153+ this . httpInterceptorDetailComponent . instance . detail = details ;
154+ this . httpInterceptorDetailComponent . instance . closed . subscribe ( ( ) => this . destroyModal ( ) ) ;
155+ this . httpInterceptorDetailComponent . instance . open ( ) ;
156+ }
157+
158+ private destroyModal ( ) {
159+ if ( this . httpInterceptorDetailComponent ) {
160+ this . componentInjector . destroyComponentInApplication ( this . httpInterceptorDetailComponent ) ;
161+ this . httpInterceptorDetailComponent = undefined ;
162+ }
163+ }
164+
165+ private hasMessage ( responseMessage : PoHttpInterceptorDetail ) {
166+ const hasMessageProperties = responseMessage . message ;
167+
168+ return responseMessage && hasMessageProperties ;
123169 }
124170
125171 private hasNoErrorParam ( request : HttpRequest < any > ) : boolean {
@@ -128,7 +174,22 @@ export abstract class PoHttpInterceptorBaseService implements HttpInterceptor {
128174 return noErrorParam && noErrorParam . toString ( ) . toLocaleLowerCase ( ) === 'true' ;
129175 }
130176
177+ private hasNoMessageParam ( request : HttpRequest < any > ) : boolean {
178+ const noMessageParam = request && request . headers . get ( NO_MESSAGE_HEADER_PARAM ) ;
179+
180+ return noMessageParam && noMessageParam . toString ( ) . toLocaleLowerCase ( ) === 'true' ;
181+ }
182+
183+ private hasParameters ( request : HttpRequest < any > ) {
184+ return request . headers . has ( NO_ERROR_HEADER_PARAM ) || request . headers . has ( NO_MESSAGE_HEADER_PARAM ) ;
185+ }
186+
131187 private showNotification ( response : any ) {
188+
189+ if ( ! this . hasMessage ( response ) ) {
190+ return ;
191+ }
192+
132193 const typeNotification = this . notificationTypes . includes ( response . type ) ? response . type : 'information' ;
133194
134195 const notificationAction = this . generateNotificationAction ( response ) ;
@@ -140,26 +201,26 @@ export abstract class PoHttpInterceptorBaseService implements HttpInterceptor {
140201 } ) ;
141202 }
142203
143- private generateNotificationAction ( errorResponse : any ) {
204+ private generateDetailModal ( responseMessage : any ) {
205+ return ( ) => {
206+ if ( ! this . httpInterceptorDetailComponent ) {
207+ this . createModal ( responseMessage ) ;
208+ }
209+ } ;
210+ }
211+
212+ private generateNotificationAction ( responseMessage : any ) {
144213
145214 let notificationAction ;
146215 let notificationLabel ;
147216
148- let notificationMessage = errorResponse . message . concat ( ` ${ errorResponse . detailedMessage } ` ) ;
149-
150- if ( errorResponse . details && errorResponse . details instanceof Array ) {
151- errorResponse . details . forEach ( ( detailError : any ) => {
152- notificationMessage += `\n${ detailError . message } ` ;
153- } ) ;
154- }
155-
156- if ( errorResponse . helpUrl && ! ( errorResponse . detailedMessage || errorResponse . details ) ) {
217+ if ( responseMessage . helpUrl && ! ( responseMessage . detailedMessage || responseMessage . details ) ) {
157218 notificationLabel = 'Ajuda' ;
158- notificationAction = this . generateUrlHelpFunction ( errorResponse . helpUrl ) ;
219+ notificationAction = this . generateUrlHelpFunction ( responseMessage . helpUrl ) ;
159220
160- } else if ( errorResponse . detailedMessage || errorResponse . details ) {
221+ } else if ( responseMessage . detailedMessage || responseMessage . details ) {
161222 notificationLabel = 'Detalhes' ;
162- notificationAction = this . generateDialogDetailFunction ( errorResponse , notificationMessage ) ;
223+ notificationAction = this . generateDetailModal ( responseMessage ) ;
163224 }
164225 return { label : notificationLabel , action : notificationAction } ;
165226 }
@@ -168,13 +229,4 @@ export abstract class PoHttpInterceptorBaseService implements HttpInterceptor {
168229 return ( ) => { window . open ( helpUrl , '_blank' ) ; } ;
169230 }
170231
171- private generateDialogDetailFunction ( errorResponse : any , notificationMessage : string ) {
172- return ( ) => {
173- this . dialog . alert ( {
174- title : errorResponse . code ,
175- message : notificationMessage ,
176- ok : errorResponse . helpUrl ? this . generateUrlHelpFunction ( errorResponse . helpUrl ) : undefined
177- } ) ;
178- } ;
179- }
180232}
0 commit comments