Merge branch 'feature/viewer-attachment' of https://bitbucket.org/equilibriumito/gabinete-digital-fo into feature/viewer-attachment

This commit is contained in:
Equilibrium ITO
2024-03-05 09:29:44 +01:00
12 changed files with 185 additions and 26 deletions
+3 -1
View File
@@ -87,6 +87,7 @@ import { LoggingInterceptorService } from './services/logging-interceptor.servic
import { PopupQuestionPipe } from './modals/popup-question.pipe'; import { PopupQuestionPipe } from './modals/popup-question.pipe';
import '@teamhive/capacitor-video-recorder'; import '@teamhive/capacitor-video-recorder';
import { tokenInterceptor } from './interceptors/token.interceptors'; import { tokenInterceptor } from './interceptors/token.interceptors';
import { ChatTokenInterceptor } from './interceptors/chatToken.interceptor';
import { InputFilterDirective } from './services/directives/input-filter.directive'; import { InputFilterDirective } from './services/directives/input-filter.directive';
import { VisibilityDirective } from './services/directives/visibility.directive'; import { VisibilityDirective } from './services/directives/visibility.directive';
@@ -216,7 +217,8 @@ import { FirebaseX } from '@ionic-native/firebase-x/ngx'; */
DocumentViewer, DocumentViewer,
FFMpeg, FFMpeg,
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptorService, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptorService, multi: true },
tokenInterceptor tokenInterceptor,
/* ChatTokenInterceptor */
], ],
bootstrap: [AppComponent], bootstrap: [AppComponent],
@@ -0,0 +1,152 @@
import { Injectable } from '@angular/core';
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpEvent,
HttpErrorResponse,
HTTP_INTERCEPTORS,
HttpHeaders,
} from '@angular/common/http';
import { Observable, throwError, BehaviorSubject } from 'rxjs';
import { catchError, switchMap, filter, take } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { SessionStore } from '../store/session.service';
import { environment } from "src/environments/environment";
import { PermissionService } from '../services/permission.service';
import { NetworkServiceService , ConnectionStatus} from 'src/app/services/network-service.service';
import { RochetChatConnectorService } from 'src/app/services/chat/rochet-chat-connector.service';
@Injectable()
export class ChatTokenInterceptor implements HttpInterceptor {
private isRefreshing = false;
headers: HttpHeaders;
options: any;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(
null
);
private excludedDomain = 'https://gdchat-dev.dyndns.info';// Add other domains as needed
constructor(private http: HttpClient, private router: Router,private p: PermissionService,private NetworkServiceService: NetworkServiceService,
private RochetChatConnectorService: RochetChatConnectorService) {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (this.shouldExcludeDomain(request)) {
return next.handle(request);
}
return next.handle(request).pipe(
catchError((error) => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle401Error(request, next);
} else {
return throwError(error);
}
})
);
}
private shouldExcludeDomain(request: HttpRequest<any>): boolean {
const url = request.url.toLowerCase();
return !url.includes(this.excludedDomain.toLowerCase());
}
private handle401Error(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.refreshToken().pipe(
switchMap((token: any) => {
this.isRefreshing = false;
let data = {
status: token['status'],
data: {
userId: token['data'].userId,
authToken: token['data'].authToken
}
}
SessionStore.user.ChatData = data
SessionStore.save()
this.setheader()
this.refreshTokenSubject.next(token.Authorization);
return next.handle(this.addToken(request, token.Authorization));
})
);
} else {
return this.refreshTokenSubject.pipe(
filter((token) => token != null),
take(1),
switchMap((jwt) => {
return next.handle(this.addToken(request, jwt));
})
);
}
}
private addToken(request: HttpRequest<any>, token: string) {
return request.clone({
/* setHeaders: {
Authorization: `Bearer ${token}`,
}, */
});
}
private refreshToken(): Observable<any> {
return this.http
.get<any>(environment.apiURL + 'UserAuthentication/RegenereChatToken', {
/* refreshToken: SessionStore.user.RefreshToken, */
})
.pipe(
catchError((error) => {
// Handle token refresh failure
console.log('ChatToken refresh failed:', error);
return throwError(error);
})
);
}
setheader() {
try {
if (this.p.userPermission(this.p.permissionList.Chat.access) && SessionStore.user.ChatData) {
this.headers = new HttpHeaders();;
if (this.p.userPermission(this.p.permissionList.Chat.access)) {
//
this.headers = this.headers.set('X-User-Id', SessionStore.user.ChatData.data.userId);
this.headers = this.headers.set('X-Auth-Token', SessionStore.user.ChatData.data.authToken);
this.options = {
headers: this.headers,
};
}
}
} catch (error) {
}
}
}
export const tokenInterceptor = {
provide: HTTP_INTERCEPTORS,
useClass: ChatTokenInterceptor,
multi: true
};
+5 -3
View File
@@ -14,6 +14,7 @@ import { catchError, filter, take, switchMap, tap } from "rxjs/operators";
import { SessionStore } from '../store/session.service'; import { SessionStore } from '../store/session.service';
import { environment } from "src/environments/environment"; import { environment } from "src/environments/environment";
import { Router } from "@angular/router"; import { Router } from "@angular/router";
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
@Injectable() @Injectable()
export class TokenInterceptor implements HttpInterceptor { export class TokenInterceptor implements HttpInterceptor {
@@ -24,7 +25,7 @@ export class TokenInterceptor implements HttpInterceptor {
private excludedDomains = ['Login', environment.apiChatUrl]; // Add the domains you want to exclude private excludedDomains = ['Login', environment.apiChatUrl]; // Add the domains you want to exclude
constructor(private http: HttpClient, private router: Router,) { } constructor(private http: HttpClient, private router: Router,private httpErrorHandle: HttpErrorHandle,) { }
intercept( intercept(
@@ -119,8 +120,9 @@ export class TokenInterceptor implements HttpInterceptor {
window.location.pathname = '/auth' window.location.pathname = '/auth'
} else { } else {
/* const pathBeforeGoOut = window.location.pathname */ /* const pathBeforeGoOut = window.location.pathname */
this.router.navigateByUrl('/auth', { replaceUrl: true }); this.router.navigateByUrl('/auth', { replaceUrl: true }).then(() =>{
this.httpErrorHandle.httpsSucessMessagge('sessonExpired')
})
} }
return of(false); return of(false);
}) })
@@ -68,6 +68,7 @@ iframe {
.container-img { .container-img {
background-image: url(/assets/gif/theme/gov/Blocks-loader.svg); background-image: url(/assets/gif/theme/gov/Blocks-loader.svg);
background-size: 100px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position-x: center; background-position-x: center;
background-position-y: center; background-position-y: center;
@@ -223,7 +223,9 @@ export class HttpErrorHandle {
case 'new event to aprove': case 'new event to aprove':
this.toastService._successMessage('Enviado para os eventos para aprovação!'); this.toastService._successMessage('Enviado para os eventos para aprovação!');
break; break;
case 'sessonExpired':
this.toastService._successMessage('Sessão expirada, por favor efectuar login novamente!');
break;
default: default:
this.toastService._successMessage('Processo efetuado!') this.toastService._successMessage('Processo efetuado!')
break; break;
@@ -123,12 +123,12 @@
<div [ngClass]="{'header-fix': !dropButton}" style="border-radius: 50px;position: relative;top: 3px;left: 25px;"> <div [ngClass]="{'header-fix': !dropButton}" style="border-radius: 50px;position: relative;top: 3px;left: 25px;">
<ion-row class="timeline-date align-center pr-10 visionMobile-flex" > <ion-row class="timeline-date align-center pr-10 visionMobile-flex" >
<button class="no-color" [ngClass]="{'d-item': !dropButton}" (click)="changeDropButton()" > <button style="z-index: 99;" class="no-color" [ngClass]="{'d-item': !dropButton}" (click)="changeDropButton()" >
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="collaps font-25" src="assets/images/icons-collaps-up.svg" ></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="collaps font-25" src="assets/images/icons-collaps-up.svg" ></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="collaps font-25" src="assets/images/theme/gov/icons-collaps-up.svg" ></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="collaps font-25" src="assets/images/theme/gov/icons-collaps-up.svg" ></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="collaps font-25" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-collaps-up.svg"></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="collaps font-25" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-collaps-up.svg"></ion-icon>
</button> </button>
<button class="no-color visionMobile-flex" *ngIf="!dropButton" (click)="changeDropButton()"> <button style="z-index: 99;" class="no-color visionMobile-flex" *ngIf="!dropButton" (click)="changeDropButton()">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="collaps font-25" src="assets/images/icons-collaps-down.svg" ></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="collaps font-25" src="assets/images/icons-collaps-down.svg" ></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="collaps font-25" src="assets/images/theme/gov/icons-collaps-down.svg" ></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="collaps font-25" src="assets/images/theme/gov/icons-collaps-down.svg" ></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="collaps font-25" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-collaps-down.svg" ></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="collaps font-25" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-collaps-down.svg" ></ion-icon>
@@ -215,7 +215,7 @@ export class DiplomaOptionsPage implements OnInit {
"ActionTypeId": 99999842, "ActionTypeId": 99999842,
"FolderId": this.task.FolderID, "FolderId": this.task.FolderID,
"dataFields": { "dataFields": {
"ReviewUserComment": note, "ReviewUserComment": "",
"InstanceIDNew": this.task.InstanceID, "InstanceIDNew": this.task.InstanceID,
"DraftIds": "", "DraftIds": "",
}, },
@@ -115,7 +115,7 @@ export class OptsExpedientePage implements OnInit {
component: SearchPage, component: SearchPage,
cssClass: 'modal-width-100-width-background modal', cssClass: 'modal-width-100-width-background modal',
componentProps: { componentProps: {
type: 'AccoesPresidenciais & ArquivoDespachoElect', type: 'Correspondencia',
showSearchInput: true, showSearchInput: true,
select: true select: true
} }
@@ -214,7 +214,7 @@ export class NewPublicationPage implements OnInit {
FileType: 'image' FileType: 'image'
} }
) )
newAttachment.needUpload(); //newAttachment.needUpload();
this.publicationFormMV.form.Files.push(newAttachment) this.publicationFormMV.form.Files.push(newAttachment)
}); });
@@ -252,7 +252,7 @@ export class NewPublicationPage implements OnInit {
} }
) )
newAttachment.needUpload() // newAttachment.needUpload()
this.publicationFormMV.form.Files.push(newAttachment) this.publicationFormMV.form.Files.push(newAttachment)
this.filecontent = true; this.filecontent = true;
@@ -368,7 +368,7 @@ export class NewPublicationPage implements OnInit {
const publication: any = Object.assign({}, this.publicationFormMV.form) const publication: any = Object.assign({}, this.publicationFormMV.form)
publication.Files = publication.Files.map( (e:PublicationAttachmentEntity) => ({ publication.Files = publication.Files.map( (e:PublicationAttachmentEntity) => ({
FileBase64: e.Base64, FileBase64: e.url,
FileExtension: e.FileExtension, FileExtension: e.FileExtension,
OriginalFileName: e.OriginalFileName || 'foto' OriginalFileName: e.OriginalFileName || 'foto'
})) }))
@@ -420,7 +420,7 @@ export class NewPublicationPage implements OnInit {
const publication: any = Object.assign({}, this.publicationFormMV.form) const publication: any = Object.assign({}, this.publicationFormMV.form)
publication.Files = publication.Files.map( (e:PublicationAttachmentEntity) => ({ publication.Files = publication.Files.map( (e:PublicationAttachmentEntity) => ({
FileBase64: e.Base64, FileBase64: e.url,
FileExtension: e.FileExtension, FileExtension: e.FileExtension,
OriginalFileName: e.OriginalFileName || 'foto' OriginalFileName: e.OriginalFileName || 'foto'
})) }))
@@ -148,14 +148,14 @@ export class PublicationAttachmentEntity {
const sanitizer : DomSanitizer = window["sanitizer"] const sanitizer : DomSanitizer = window["sanitizer"]
if(this.FileType == 'image' ) { if(this.FileType == 'image' ) {
if(!this.Base64.startsWith('data:')) { if(!this.Base64.includes('data:')) {
this.url = 'data:image/jpg;base64,' + this.Base64 this.url = 'data:image/jpg;base64,' + this.Base64
// this.url = sanitizer.bypassSecurityTrustUrl('data:image/jpg;base64,' + this.Base64) as any // this.url = sanitizer.bypassSecurityTrustUrl('data:image/jpg;base64,' + this.Base64) as any
} else { } else {
this.url = this.Base64 this.url = this.Base64
} }
} else if (this.FileType == 'video' ) { } else if (this.FileType == 'video' ) {
if(!this.Base64.startsWith('data:') && !this.Base64.startsWith('http')) { if(!this.Base64.includes('data:') && !this.Base64.startsWith('http')) {
this.url = 'data:video/mp4;base64,' + this.Base64 this.url = 'data:video/mp4;base64,' + this.Base64
// this.url = sanitizer.bypassSecurityTrustUrl('data:video/mp4;base64,' + this.Base64) as any // this.url = sanitizer.bypassSecurityTrustUrl('data:video/mp4;base64,' + this.Base64) as any
} else { } else {
+1 -1
View File
@@ -4,4 +4,4 @@ import { environment as doneITProd } from './suport/doneIt'
import { DevDev } from './suport/dev' import { DevDev } from './suport/dev'
export const environment: Environment = oaprProd; export const environment: Environment = DevDev;