conflit soved after merge

This commit is contained in:
Eudes Inácio
2022-03-31 16:48:53 +01:00
53 changed files with 978 additions and 618 deletions
+3 -3
View File
@@ -6240,9 +6240,9 @@
} }
}, },
"beast-orm": { "beast-orm": {
"version": "1.0.0", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/beast-orm/-/beast-orm-1.0.0.tgz", "resolved": "https://registry.npmjs.org/beast-orm/-/beast-orm-1.0.3.tgz",
"integrity": "sha512-wSholUbFMteq50U3QM0o4H3xY9IpevpG9MPlq0ZK8yRtRkIuKf/YoZW4QUwFOfY72PJbNzp68z7Ln/iFhpOxDg==" "integrity": "sha512-kSTc8Sosm1CbLjSGc+nA1s9i4QmGQoF1rfWDmhTrHOvH+uZAtRXbZAypzscMmF67g04mK5XAuB+TUoKV5XmNiQ=="
}, },
"big-integer": { "big-integer": {
"version": "1.6.49", "version": "1.6.49",
+1 -1
View File
@@ -100,7 +100,7 @@
"angular-svg-icon": "^12.0.0", "angular-svg-icon": "^12.0.0",
"angular-tag-cloud-module": "^5.2.2", "angular-tag-cloud-module": "^5.2.2",
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"beast-orm": "^1.0.0", "beast-orm": "^1.0.3",
"bootstrap": "^4.5.0", "bootstrap": "^4.5.0",
"build": "0.1.4", "build": "0.1.4",
"capacitor-voice-recorder": "^2.0.0", "capacitor-voice-recorder": "^2.0.0",
+1 -1
View File
@@ -6,7 +6,7 @@ import { ProcessesService } from '../services/processes.service';
import { DespachoStore } from '../store/despacho-store.service'; import { DespachoStore } from '../store/despacho-store.service';
import { LoaderService } from 'src/app/store/loader.service' import { LoaderService } from 'src/app/store/loader.service'
import { SessionStore } from '../store/session.service'; import { SessionStore } from '../store/session.service';
import { PermissionService } from '../services/worker/permission.service'; import { PermissionService } from '../services/permission.service';
import { SortService } from '../services/functions/sort.service'; import { SortService } from '../services/functions/sort.service';
@Injectable({ @Injectable({
+1 -1
View File
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ProcessesService } from '../services/processes.service'; import { ProcessesService } from '../services/processes.service';
import { PermissionService } from '../services/worker/permission.service'; import { PermissionService } from '../services/permission.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
+23 -1
View File
@@ -3,15 +3,20 @@ import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTr
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { SessionStore } from '../store/session.service'; import { SessionStore } from '../store/session.service';
import { AlertController, Platform } from '@ionic/angular'; import { AlertController, Platform } from '@ionic/angular';
import { PermissionService } from '../services/permission.service';
import { PermissionList } from '../models/permissionList';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class InactivityGuard implements CanActivate { export class InactivityGuard implements CanActivate {
permissionList = new PermissionList();
constructor( constructor(
private router:Router, private router:Router,
private platform: Platform, private platform: Platform,
public permissionService: PermissionService,
){} ){}
canActivate( canActivate(
@@ -19,14 +24,31 @@ export class InactivityGuard implements CanActivate {
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (this.platform.is('desktop') || this.platform.is('mobileweb')) { if (this.platform.is('desktop') || this.platform.is('mobileweb')) {
if(this.permissionService.userPermission(this.permissionList.Agenda) || this.permissionService.userPermission(this.permissionList.Gabinete)){
this.router.navigate(['/home/events']); this.router.navigate(['/home/events']);
}
else if(this.permissionService.userPermission(this.permissionList.Chat)){
this.router.navigate(['/home/chat']);
}
else if(this.permissionService.userPermission(this.permissionList.Actions)){
this.router.navigate(['/home/publications']);
}
return false return false
} else if(SessionStore.exist && SessionStore.user.Inactivity && !SessionStore.hasPin ) { } else if(SessionStore.exist && SessionStore.user.Inactivity && !SessionStore.hasPin ) {
return true return true
} else if(SessionStore.exist && !SessionStore.user.Inactivity) { } else if(SessionStore.exist && !SessionStore.user.Inactivity) {
return true return true
} else { }//Mobile or Tablet without session
else {
if(this.permissionService.userPermission(this.permissionList.Agenda) || this.permissionService.userPermission(this.permissionList.Gabinete)){
this.router.navigate(['/home/events']); this.router.navigate(['/home/events']);
}
else if(this.permissionService.userPermission(this.permissionList.Chat)){
this.router.navigate(['/home/chat']);
}
else if(this.permissionService.userPermission(this.permissionList.Actions)){
this.router.navigate(['/home/publications']);
}
return false return false
} }
+8 -5
View File
@@ -1,7 +1,8 @@
<ion-tabs class="tab"> <ion-tabs class="tab">
<ion-tab-bar class="bottoms" slot="bottom"> <ion-tab-bar class="bottoms" slot="bottom">
<ion-tab-button tab="events" [class.active]="pathname === '/home/events' ">
<ion-tab-button *ngIf="p.userPermission([permissionList.Agenda]) || p.userPermission([permissionList.Gabinete])" tab="events" [class.active]="pathname === '/home/events'">
<!-- <ion-icon name="home"></ion-icon> --> <!-- <ion-icon name="home"></ion-icon> -->
<ion-icon *ngIf="pathname != '/home/events'" class="nav-icon" src="assets/images/icons-nav-home.svg"></ion-icon> <ion-icon *ngIf="pathname != '/home/events'" class="nav-icon" src="assets/images/icons-nav-home.svg"></ion-icon>
<ion-icon *ngIf="pathname == '/home/events'" class="nav-icon" src="assets/images/nav-hover/icons-nav-home-active.svg"></ion-icon> <ion-icon *ngIf="pathname == '/home/events'" class="nav-icon" src="assets/images/nav-hover/icons-nav-home-active.svg"></ion-icon>
@@ -9,13 +10,14 @@
<ion-label>Início</ion-label> <ion-label>Início</ion-label>
</ion-tab-button> </ion-tab-button>
<ion-tab-button tab="agenda" [class.active]="pathname === '/home/agenda' "> <ion-tab-button *ngIf="p.userPermission([permissionList.Agenda])" tab="agenda" [class.active]="pathname === '/home/agenda' ">
<!-- <ion-icon name="calendar"></ion-icon> --> <!-- <ion-icon name="calendar"></ion-icon> -->
<ion-icon *ngIf="pathname != '/home/agenda'" class="nav-icon" src="assets/images/icons-nav-calendar.svg"></ion-icon> <ion-icon *ngIf="pathname != '/home/agenda'" class="nav-icon" src="assets/images/icons-nav-calendar.svg"></ion-icon>
<ion-icon *ngIf="pathname == '/home/agenda'" class="nav-icon" src="assets/images/nav-hover/icons-nav-agenda-active.svg"></ion-icon> <ion-icon *ngIf="pathname == '/home/agenda'" class="nav-icon" src="assets/images/nav-hover/icons-nav-agenda-active.svg"></ion-icon>
<ion-label style="margin-bottom: 2px;" class="overflow-visible">Agenda</ion-label> <ion-label style="margin-bottom: 2px;" class="overflow-visible">Agenda</ion-label>
</ion-tab-button> </ion-tab-button>
<ion-tab-button (click)="goto('/home/gabinete-digital')" [class.active]="pathname === '/home/gabinete-digital' ">
<ion-tab-button *ngIf="p.userPermission([permissionList.Gabinete])" (click)="goto('/home/gabinete-digital')" [class.active]="pathname === '/home/gabinete-digital' ">
<!-- <ion-icon name="file-tray-stacked"></ion-icon> --> <!-- <ion-icon name="file-tray-stacked"></ion-icon> -->
<ion-icon *ngIf="pathname != '/home/gabinete-digital'" class="nav-icon" src="assets/images/icons-nav-gabinete-inactive.svg"></ion-icon> <ion-icon *ngIf="pathname != '/home/gabinete-digital'" class="nav-icon" src="assets/images/icons-nav-gabinete-inactive.svg"></ion-icon>
<ion-icon *ngIf="pathname == '/home/gabinete-digital'" class="nav-icon" src="assets/images/nav-hover/icons-nav-gabinete-active.svg"></ion-icon> <ion-icon *ngIf="pathname == '/home/gabinete-digital'" class="nav-icon" src="assets/images/nav-hover/icons-nav-gabinete-active.svg"></ion-icon>
@@ -24,12 +26,13 @@
<ion-label>Gabinete</ion-label> <ion-label>Gabinete</ion-label>
</ion-tab-button> </ion-tab-button>
<ion-tab-button tab="publications" [class.active]="pathname === '/home/publications' "> <ion-tab-button *ngIf="p.userPermission([permissionList.Actions])" tab="publications" [class.active]="pathname === '/home/publications' ">
<ion-icon *ngIf="pathname != '/home/publications'" class="nav-icon" src="assets/images/icons-nav-actions.svg"></ion-icon> <ion-icon *ngIf="pathname != '/home/publications'" class="nav-icon" src="assets/images/icons-nav-actions.svg"></ion-icon>
<ion-icon *ngIf="pathname == '/home/publications'" class="nav-icon" src="assets/images/nav-hover/icons-nav-actions-active.svg"></ion-icon> <ion-icon *ngIf="pathname == '/home/publications'" class="nav-icon" src="assets/images/nav-hover/icons-nav-actions-active.svg"></ion-icon>
<ion-label style="margin-bottom: 2px;" class="overflow-visible">Ações</ion-label> <ion-label style="margin-bottom: 2px;" class="overflow-visible">Ações</ion-label>
</ion-tab-button> </ion-tab-button>
<ion-tab-button tab="chat" [class.active]="pathname === '/home/chat' ">
<ion-tab-button *ngIf="p.userPermission([permissionList.Actions])" tab="chat" [class.active]="pathname === '/home/chat' ">
<ion-icon *ngIf="pathname != '/home/chat'" class="nav-icon" src="assets/images/icons-nav-chat-inactive.svg"></ion-icon> <ion-icon *ngIf="pathname != '/home/chat'" class="nav-icon" src="assets/images/icons-nav-chat-inactive.svg"></ion-icon>
<ion-icon *ngIf="pathname == '/home/chat'" class="nav-icon" src="assets/images/nav-hover/icons-nav-chat-active.svg"></ion-icon> <ion-icon *ngIf="pathname == '/home/chat'" class="nav-icon" src="assets/images/nav-hover/icons-nav-chat-active.svg"></ion-icon>
<ion-label>Chat</ion-label> <ion-label>Chat</ion-label>
+11 -2
View File
@@ -16,7 +16,7 @@ import { StorageService } from '../services/storage.service';
import { File } from '@ionic-native/file/ngx'; import { File } from '@ionic-native/file/ngx';
/* import { WebNotificationPopupService } from '../services/notification/web-notification-popup.service'; */ /* import { WebNotificationPopupService } from '../services/notification/web-notification-popup.service'; */
import { DocumentCounterService } from '../services/worker/document-counter.service'; import { DocumentCounterService } from '../services/worker/document-counter.service';
import { PermissionService } from '../services/worker/permission.service'; import { PermissionService } from '../services/permission.service';
import { BackgroundService } from 'src/app/services/background.service'; import { BackgroundService } from 'src/app/services/background.service';
import { OfflineManagerService } from 'src/app/services/offline-manager.service'; import { OfflineManagerService } from 'src/app/services/offline-manager.service';
import { Storage } from '@ionic/storage'; import { Storage } from '@ionic/storage';
@@ -30,6 +30,8 @@ import { WsChatService } from 'src/app/services/chat/ws-chat.service';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { NativeNotificationService } from 'src/app/services/native-notification.service'; import { NativeNotificationService } from 'src/app/services/native-notification.service';
import { UserSession } from '../models/user.model';
import { PermissionList } from '../models/permissionList';
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
@@ -79,6 +81,8 @@ export class HomePage implements OnInit {
status: string = ""; status: string = "";
audioName: string = ""; audioName: string = "";
public user: UserSession;
permissionList = new PermissionList();
constructor( constructor(
private router: Router, private router: Router,
@@ -102,7 +106,12 @@ export class HomePage implements OnInit {
private sqliteservice: SqliteService, private sqliteservice: SqliteService,
public RouteService: RouteService, public RouteService: RouteService,
private WsChatService: WsChatService, private WsChatService: WsChatService,
private NativeNotificationService: NativeNotificationService,) { private NativeNotificationService: NativeNotificationService,
) {
if (SessionStore.exist) {
this.user = SessionStore.user;
}
/* this.webNotificationPopupService.askNotificationPermission() */ /* this.webNotificationPopupService.askNotificationPermission() */
@@ -16,7 +16,7 @@ import { ToastService } from 'src/app/services/toast.service';
import { FormControl, FormGroup, Validators } from '@angular/forms'; import { FormControl, FormGroup, Validators } from '@angular/forms';
import { NgxMatDateFormats } from '@angular-material-components/datetime-picker'; import { NgxMatDateFormats } from '@angular-material-components/datetime-picker';
import { NGX_MAT_DATE_FORMATS } from '@angular-material-components/datetime-picker'; import { NGX_MAT_DATE_FORMATS } from '@angular-material-components/datetime-picker';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { DespachoService } from 'src/app/Rules/despacho.service'; import { DespachoService } from 'src/app/Rules/despacho.service';
import { PedidoService } from 'src/app/Rules/pedido.service' import { PedidoService } from 'src/app/Rules/pedido.service'
import { fullTask } from 'src/app/models/dailyworktask.model'; import { fullTask } from 'src/app/models/dailyworktask.model';
@@ -7,7 +7,7 @@ import { ExpedientTaskModalPage } from 'src/app/pages/gabinete-digital/expedient
import { DocumentSetUpMeetingPage } from '../document-set-up-meeting/document-set-up-meeting.page'; import { DocumentSetUpMeetingPage } from '../document-set-up-meeting/document-set-up-meeting.page';
import { SearchDocumentDetails, SearchFolderDetails } from 'src/app/models/search-document'; import { SearchDocumentDetails, SearchFolderDetails } from 'src/app/models/search-document';
import { ExpedientTaskModalPageNavParamsTask } from 'src/app/models/ExpedientTaskModalPage'; import { ExpedientTaskModalPageNavParamsTask } from 'src/app/models/ExpedientTaskModalPage';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { SearchedDocumentOptionsPage } from 'src/app/shared/popover/searched-document-options/searched-document-options.page'; import { SearchedDocumentOptionsPage } from 'src/app/shared/popover/searched-document-options/searched-document-options.page';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { ViewDocumentPage } from '../view-document/view-document.page'; import { ViewDocumentPage } from '../view-document/view-document.page';
+12 -11
View File
@@ -10,28 +10,26 @@ export class MessageModel extends models.Model {
mentions = ArrayField() mentions = ArrayField()
msg = models.CharField() msg = models.CharField()
rid = models.CharField() rid = models.CharField()
ts = models.CharField() ts = JsonField({blank:true})
u = JsonField() u = JsonField()
_id = models.CharField({unique:true}) _id = models.CharField({blank:true})
_updatedAt = models.CharField() _updatedAt = models.IntegerField()
messageSend = models.BooleanField() messageSend = models.BooleanField()
offline = models.BooleanField() offline = models.BooleanField()
viewed = ArrayField() viewed = ArrayField({blank:true})
received = ArrayField() received = ArrayField({blank:true})
localReference = models.CharField({blank:true}) localReference = models.CharField({blank:true})
attachments = ArrayField() attachments = ArrayField({blank:true})
file = ArrayField() file = JsonField({blank:true})
} }
export class DeleteMessageModel extends models.Model { export class DeleteMessageModel extends models.Model {
messageId = models.IntegerField() messageId = models.CharField()
rid = models.CharField() rid = models.CharField()
ts = models.CharField()
u = JsonField() u = JsonField()
needToReceiveBy = ArrayField() needToReceiveBy = ArrayField()
} }
@@ -39,6 +37,9 @@ export class DeleteMessageModel extends models.Model {
models.register({ models.register({
databaseName: 'chat-storage', databaseName: 'chat-storage',
type: 'indexedDB', type: 'indexedDB',
version: 1, version: 4,
models: [MessageModel, DeleteMessageModel] models: [MessageModel, DeleteMessageModel]
}) })
window['MessageModel'] = MessageModel
+6
View File
@@ -0,0 +1,6 @@
export class PermissionList{
Agenda = 530;
Gabinete = 531;
Actions = 534;
Chat = 541;
}
+3 -1
View File
@@ -30,6 +30,7 @@ export class LoginUserRespose {
}[] }[]
UserName: string UserName: string
Profile: any; Profile: any;
UserPermissions: any;
} }
@@ -63,5 +64,6 @@ export class UserSession {
LoginPreference: 'None' | 'Password' | 'Pin' | null; LoginPreference: 'None' | 'Password' | 'Pin' | null;
PIN: string PIN: string
Inactivity: boolean Inactivity: boolean
UrlBeforeInactivity: string UrlBeforeInactivity: string;
UserPermissions: any;
} }
@@ -102,7 +102,10 @@
<div class="message"> <div class="message">
<div *ngIf="msg.attachments" class="message-attachments"> <div *ngIf="msg.attachments" class="message-attachments">
<div *ngFor="let file of msg.attachments"> <div *ngFor="let file of msg.attachments">
<div *ngIf="msg.file.type == 'application/img'" (click)="openPreview(msg)"> <div *ngIf="msg.file.type == 'application/img' && !msg.attachments[0].image_url">
NOT UPLOADED
</div>
<div *ngIf="msg.file.type == 'application/img' && msg.attachments[0].image_url" (click)="openPreview(msg)">
<img *ngIf="msg.attachments[0].image_url" src="{{msg.attachments[0].image_url}}" alt="image" > <img *ngIf="msg.attachments[0].image_url" src="{{msg.attachments[0].image_url}}" alt="image" >
<ion-icon *ngIf="msg.attachments[0].image_url == null" name="download-outline"></ion-icon> <ion-icon *ngIf="msg.attachments[0].image_url == null" name="download-outline"></ion-icon>
</div> </div>
@@ -118,7 +121,15 @@
<ion-label class="file-title">{{file.title}}</ion-label> <ion-label class="file-title">{{file.title}}</ion-label>
</div> </div>
</div> </div>
<div *ngIf="msg.file.type == 'application/audio'"> <div class="audio-contentainer" *ngIf="msg.file.type == 'application/audio' && !file.title_link">
<ion-item class="add-attachment-bg-color" shape="round" lines="none" type="button">
<ion-icon name="mic-outline" class="file-icon"></ion-icon>
<ion-label>{{file.title}}</ion-label>
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="icon-download" src="assets/icon/theme/default/icons-download.svg" slot="end"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="icon-download" src="assets/icon/theme/gov/icons-download.svg" slot="end"></ion-icon>
</ion-item>
</div>
<div class="audio-contentainer" *ngIf="msg.file.type == 'application/audio' && file.title_link">
<audio [src]="file.title_link|safehtml" preload="metadata" class="d-flex width-100" controls controlsList="nodownload noplaybackrate"></audio> <audio [src]="file.title_link|safehtml" preload="metadata" class="d-flex width-100" controls controlsList="nodownload noplaybackrate"></audio>
</div> </div>
<div class="file-details-optional add-attachment-bg-color"> <div class="file-details-optional add-attachment-bg-color">
@@ -35,6 +35,7 @@ import { ProcessesService } from 'src/app/services/processes.service';
import { VoiceRecorder, VoiceRecorderPlugin, RecordingData, GenericResponse, CurrentRecordingStatus } from 'capacitor-voice-recorder'; import { VoiceRecorder, VoiceRecorderPlugin, RecordingData, GenericResponse, CurrentRecordingStatus } from 'capacitor-voice-recorder';
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem'; import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { MessageService } from 'src/app/services/chat/message.service';
@Component({ @Component({
selector: 'app-group-messages', selector: 'app-group-messages',
@@ -43,8 +44,6 @@ import { DomSanitizer } from '@angular/platform-browser';
}) })
export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy { export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy {
showLoader: boolean; showLoader: boolean;
isGroupCreated: boolean; isGroupCreated: boolean;
loggedUser: any; loggedUser: any;
@@ -252,15 +251,49 @@ export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy {
this.lastAudioRecorded = fileName; this.lastAudioRecorded = fileName;
}) })
try {
this.storage.get('recordData').then((recordData) => { this.storage.get('recordData').then((recordData) => {
console.log(recordData); console.log(recordData);
if(recordData.value.recordDataBase64.includes('data:audio')){ if(recordData?.value?.recordDataBase64.includes('data:audio')){
this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(recordData.value.recordDataBase64); this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(recordData?.value?.recordDataBase64);
} }
else{ else{
this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(`data:${recordData.value.mimeType};base64,${recordData.value.recordDataBase64}`); this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(`data:${recordData.value.mimeType};base64,${recordData?.value?.recordDataBase64}`);
} }
}); });
} catch (error) {}
}
stopRecording() {
this.deleteRecording();
this.allowTyping = false;
console.log('Stop');
if (!this.recording) {
return;
}
this.recording = false;
VoiceRecorder.stopRecording().then(async (result: RecordingData) => {
console.log('==================================',result);
this.recording = false;
if (result.value && result.value.recordDataBase64) {
const recordData = result.value.recordDataBase64;
//console.log(recordData);
const fileName = new Date().getTime() + ".mp3";
//Save file
await this.storage.set('fileName',fileName)
this.storage.set('recordData',result).then(() => {
console.log('Audio recorded saved', result);
setTimeout(async () => {
this.loadFiles();
}, 1000);
})
}
})
} }
startRecording() { startRecording() {
@@ -274,32 +307,7 @@ export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy {
this.calculateDuration(); this.calculateDuration();
} }
stopRecording() {
this.deleteRecording();
this.allowTyping = false;
console.log('Stop');
if (!this.recording) {
return;
}
this.recording = false;
VoiceRecorder.stopRecording().then(async (result: RecordingData) => {
console.log(result);
this.recording = false;
if (result.value && result.value.recordDataBase64) {
const recordData = result.value.recordDataBase64;
//console.log(recordData);
const fileName = new Date().getTime() + ".mp3";
//Save file
this.storage.set('fileName',fileName);
this.storage.set('recordData',result).then(() => {
console.log('Audio recorded saved');
})
}
})
setTimeout(async () => {
this.loadFiles();
}, 1000);
}
async deleteRecording(){ async deleteRecording(){
this.storage.remove('fileName'); this.storage.remove('fileName');
@@ -364,7 +372,6 @@ export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy {
} }
async getChatMembers() { async getChatMembers() {
//return await this.chatService.getMembers(roomId).toPromise();
this.chatService.getAllUsers().subscribe(res => { this.chatService.getAllUsers().subscribe(res => {
console.log(res); console.log(res);
@@ -428,41 +435,64 @@ export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy {
this.wsChatMethodsService.getGroupRoom(this.roomId).send({}) this.wsChatMethodsService.getGroupRoom(this.roomId).send({})
} }
base64toBlob(base64Data, contentType) {
contentType = contentType || '';
var sliceSize = 1024;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}
async sendAudio(fileName) { async sendAudio(fileName) {
const roomId = this.roomId const roomId = this.roomId
let audioFile;
this.storage.get('recordData').then((recordData) => { this.storage.get('recordData').then((recordData) => {
console.log(recordData); console.log(recordData);
if(recordData.value.recordDataBase64.includes('data:audio')){ audioFile = recordData;
this.audioRecorded = recordData.value.recordDataBase64; if(recordData?.value?.recordDataBase64.includes('data:audio')){
this.audioRecorded = recordData?.value?.recordDataBase64;
} }
else{ else{
this.audioRecorded = `data:${recordData.value.mimeType};base64,${recordData.value.recordDataBase64}`; this.audioRecorded = `data:${recordData.value.mimeType};base64,${recordData?.value?.recordDataBase64}`;
} }
});
//Converting base64 to blob //Converting base64 to blob
const base64Response = await fetch(this.audioRecorded); const encodedData = btoa(this.audioRecorded);
const blob = await base64Response.blob(); const blob = this.base64toBlob(encodedData, recordData.value.mimeType)
console.log(blob)
const formData = new FormData(); const formData = new FormData();
formData.append("blobFile", blob); formData.append("blobFile", blob);
this.wsChatMethodsService.getGroupRoom(roomId).send({ this.wsChatMethodsService.getGroupRoom(roomId).send({
file: { file: {
"type": "application/audio", "type": "application/audio",
/* "guid": '', */ "msDuration":audioFile.value.msDuration,
"mimeType":audioFile.value.mimeType,
}, },
attachments: [{ attachments: [{
"title": fileName , "title": fileName ,
"title_link": this.audioRecorded,
"title_link_download": true, "title_link_download": true,
"type": "file" "type": "audio"
}], }],
temporaryData: formData temporaryData: formData
}) })
this.deleteRecording();
});
this.deleteRecording();
} }
@@ -950,40 +980,11 @@ export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy {
card.el.style['z-index'] = 11; card.el.style['z-index'] = 11;
} }
downloadFileMsg(msg) { downloadFileMsg(msg: MessageService) {
console.log('FILE TYPE', msg.file.type) msg.downloadFileMsg()
this.downloadFile = "";
// if (msg.file.type == "application/img") {
this.AttachmentsService.downloadFile(msg.file.guid).subscribe(async (event) => {
console.log('FILE TYPE 22', msg.file.guid)
var name = msg.file.guid;
if (event.type === HttpEventType.DownloadProgress) {
//this.downloadProgess = Math.round((100 * event.loaded) / event.total);
console.log('FILE TYPE 33', msg.file.type)
} else if (event.type === HttpEventType.Response) {
if (msg.file.type == "application/img") {
this.downloadFile = 'data:image/jpeg;base64,' + btoa(new Uint8Array(event.body).reduce((data, byte) => data + String.fromCharCode(byte), ''));
} else {
this.downloadFile = event.body;
} }
msg.attachments[0] = { async openPreview(msg: MessageService) {
image_url: this.downloadFile,
name: msg.attachments[0].name,
title: msg.attachments[0].title,
title_link_download: msg.attachments[0].title_link_download,
ts: msg.attachments[0].ts
}
this.sqlservice.updateChatMsg(msg._id, this.downloadFile);
}
});
console.log('FILE TYPE 44', this.downloadFile)
//}
}
async openPreview(msg) {
if (!msg.attachments[0].image_url ||msg.attachments[0].image_url === null || msg.attachments[0].image_url === '') { if (!msg.attachments[0].image_url ||msg.attachments[0].image_url === null || msg.attachments[0].image_url === '') {
this.downloadFileMsg(msg) this.downloadFileMsg(msg)
@@ -1003,5 +1004,12 @@ export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy {
} }
} }
async audioPreview(msg) {
console.log(msg);
if (!msg.attachments[0].title_link || msg.attachments[0].title_link === null || msg.attachments[0].title_link === '') {
this.downloadFileMsg(msg)
} else {}
}
} }
+78 -32
View File
@@ -26,7 +26,8 @@
<div hidden class="right"> <div hidden class="right">
<button class="btn-no-color" (click)="openMessagesOptions()"> <button class="btn-no-color" (click)="openMessagesOptions()">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/images/icons-menu.svg"></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/images/icons-menu.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/images/theme/gov/icons-menu.svg"></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/images/theme/gov/icons-menu.svg">
</ion-icon>
</button> </button>
</div> </div>
</div> </div>
@@ -51,8 +52,11 @@
</ion-refresher-content> </ion-refresher-content>
</ion-refresher> --> </ion-refresher> -->
<div (click)="handleClick()" class="messages" #scrollMe> <div (click)="handleClick()" class="messages" #scrollMe>
<div class="messages-list-item-wrapper container-width-100" *ngFor="let msg of wsChatMethodsService.getDmRoom(this.roomId).messages; let last = last" [class.messages-list-item-wrapper-active]="msg._id == selectedMsgId" > <div class="messages-list-item-wrapper container-width-100"
<div (press)="handlePress(msg._id)" class='message-container incoming-{{msg.u.username!=loggedUser.me.username}}' (click)="downloadFileMsg(msg)" *ngIf="msg.msg !=''"> *ngFor="let msg of wsChatMethodsService.getDmRoom(this.roomId).messages; let last = last"
[class.messages-list-item-wrapper-active]="msg._id == selectedMsgId">
<div (press)="handlePress(msg._id)" class='message-container incoming-{{msg.u.username!=loggedUser.me.username}}'
*ngIf="msg.msg !=''">
<div class="title"> <div class="title">
<ion-label (click)="hkellor()">{{msg.u.name}}</ion-label> <ion-label (click)="hkellor()">{{msg.u.name}}</ion-label>
<span class="time">{{msg.duration}}</span> <span class="time">{{msg.duration}}</span>
@@ -83,21 +87,35 @@
<div (click)="docIndex(i); openPreview(msg)" class="file-details add-ellipsis cursor-pointer" *ngIf="msg.file"> <div (click)="docIndex(i); openPreview(msg)" class="file-details add-ellipsis cursor-pointer" *ngIf="msg.file">
<span *ngIf="msg.file.type"> <span *ngIf="msg.file.type">
<fa-icon *ngIf="msg.file.type == 'application/pdf'" icon="file-pdf" class="pdf-icon"></fa-icon> <fa-icon *ngIf="msg.file.type == 'application/pdf'" icon="file-pdf" class="pdf-icon"></fa-icon>
<fa-icon *ngIf="msg.file.type == 'application/word'" icon="file-word" class="word-icon"></fa-icon> <fa-icon *ngIf="msg.file.type == 'application/word'" icon="file-word" class="word-icon">
<fa-icon *ngIf="msg.file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'" icon="file-word" class="excel-icon"></fa-icon> </fa-icon>
<ion-icon *ngIf="msg.file.type == 'application/webtrix'" src="assets/icon/webtrix.svg"></ion-icon> <fa-icon
*ngIf="msg.file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'"
icon="file-word" class="excel-icon"></fa-icon>
<ion-icon *ngIf="msg.file.type == 'application/webtrix'" src="assets/icon/webtrix.svg">
</ion-icon>
</span> </span>
<ion-label class="file-title">{{file.title}}</ion-label> <ion-label class="file-title">{{file.title}}</ion-label>
</div> </div>
</div> </div>
<div *ngIf="msg.file.type == 'application/audio'"> <div class="audio-contentainer" *ngIf="msg.file.type == 'application/audio' && !file.title_link">
<audio [src]="file.title_link|safehtml" preload="metadata" class="d-flex width-100" controls controlsList="nodownload noplaybackrate"></audio> <ion-item class="add-attachment-bg-color" shape="round" lines="none" type="button">
<ion-icon name="mic-outline" class="file-icon"></ion-icon>
<ion-label>{{file.title}}</ion-label>
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="icon-download" src="assets/icon/theme/default/icons-download.svg" slot="end"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="icon-download" src="assets/icon/theme/gov/icons-download.svg" slot="end"></ion-icon>
</ion-item>
</div>
<div class="audio-contentainer" *ngIf="msg.file.type == 'application/audio' && file.title_link">
<audio [src]="file.title_link|safehtml" preload="metadata" class="d-flex width-100" controls
controlsList="nodownload noplaybackrate"></audio>
</div> </div>
<div class="file-details-optional add-attachment-bg-color"> <div class="file-details-optional add-attachment-bg-color">
<ion-label *ngIf="msg.file && msg.file != ''"> <ion-label *ngIf="msg.file && msg.file != ''">
<span *ngIf="file.description">{{file.description}}</span> <span *ngIf="file.description">{{file.description}}</span>
<span *ngIf="file.description && msg.file.type != 'application/webtrix'"></span> <span *ngIf="file.description && msg.file.type != 'application/webtrix'"></span>
<span *ngIf="msg.file.type != 'application/webtrix' && msg.file.type != 'application/audio'">{{msg.displayType}}</span> <span
*ngIf="msg.file.type != 'application/webtrix' && msg.file.type != 'application/audio'">{{msg.displayType}}</span>
</ion-label> </ion-label>
</div> </div>
</div> </div>
@@ -108,9 +126,17 @@
</div> </div>
<div *ngIf="msg.file.type == 'application/meeting'" class="info-meeting"> <div *ngIf="msg.file.type == 'application/meeting'" class="info-meeting">
<ion-label class="info-meeting-small">{{msg.u.name}} criou esta reunião</ion-label><br /> <ion-label class="info-meeting-small">{{msg.u.name}} criou esta reunião</ion-label><br />
<button (click)="goToEvent(msg.file.id)" class="btn-no-color info-meeting-normal"><ion-label class="info-meeting-normal">{{msg.file.subject}}</ion-label></button><br /> <button (click)="goToEvent(msg.file.id)" class="btn-no-color info-meeting-normal">
<ion-label class="info-meeting-medium"><ion-icon name="calendar-outline"></ion-icon> De {{showDateDuration(msg.file.start_date)}} a {{showDateDuration(msg.file.end_date)}}</ion-label><br /> <ion-label class="info-meeting-normal">{{msg.file.subject}}</ion-label>
<ion-label class="info-meeting-medium"><ion-icon></ion-icon><ion-icon name="location-outline"></ion-icon> {{msg.file.venue}}</ion-label><br /> </button><br />
<ion-label class="info-meeting-medium">
<ion-icon name="calendar-outline"></ion-icon> De {{showDateDuration(msg.file.start_date)}} a
{{showDateDuration(msg.file.end_date)}}
</ion-label><br />
<ion-label class="info-meeting-medium">
<ion-icon></ion-icon>
<ion-icon name="location-outline"></ion-icon> {{msg.file.venue}}
</ion-label><br />
</div> </div>
</div> </div>
@@ -118,9 +144,17 @@
<div *ngIf="msg.file && msg.delate == false"> <div *ngIf="msg.file && msg.delate == false">
<div *ngIf="msg.file.type == 'application/meeting'" class="info-meeting"> <div *ngIf="msg.file.type == 'application/meeting'" class="info-meeting">
<ion-label class="info-meeting-small">{{msg.u.name}} criou esta reunião</ion-label><br /> <ion-label class="info-meeting-small">{{msg.u.name}} criou esta reunião</ion-label><br />
<button (click)="goToEvent(msg.file.id)" class="btn-no-color info-meeting-normal"><ion-label class="info-meeting-normal">{{msg.file.subject}}</ion-label></button><br /> <button (click)="goToEvent(msg.file.id)" class="btn-no-color info-meeting-normal">
<ion-label class="info-meeting-medium"><ion-icon name="calendar-outline"></ion-icon> De {{showDateDuration(msg.file.start_date)}} a {{showDateDuration(msg.file.end_date)}}</ion-label><br /> <ion-label class="info-meeting-normal">{{msg.file.subject}}</ion-label>
<ion-label class="info-meeting-medium"><ion-icon></ion-icon><ion-icon name="location-outline"></ion-icon> {{msg.file.venue}}</ion-label><br /> </button><br />
<ion-label class="info-meeting-medium">
<ion-icon name="calendar-outline"></ion-icon> De {{showDateDuration(msg.file.start_date)}} a
{{showDateDuration(msg.file.end_date)}}
</ion-label><br />
<ion-label class="info-meeting-medium">
<ion-icon></ion-icon>
<ion-icon name="location-outline"></ion-icon> {{msg.file.venue}}
</ion-label><br />
</div> </div>
{{last ? scrollToBottom() : ''}} {{last ? scrollToBottom() : ''}}
</div> </div>
@@ -165,23 +199,23 @@
<div class="typing" *ngIf="wsChatMethodsService.getDmRoom(roomId).otherUserType == true"> <div class="typing" *ngIf="wsChatMethodsService.getDmRoom(roomId).otherUserType == true">
<ngx-letters-avatar <ngx-letters-avatar [avatarName]="wsChatMethodsService.getGroupRoom(roomId).name" [width]="30" [circular]="true"
[avatarName]= "wsChatMethodsService.getGroupRoom(roomId).name"
[width]="30"
[circular]="true"
fontFamily="Roboto"></ngx-letters-avatar> fontFamily="Roboto"></ngx-letters-avatar>
está a escrever ... está a escrever ...
</div> </div>
<div class="width-100 pl-20 pr-20"> <div class="width-100 pl-20 pr-20">
<span *ngIf="!lastAudioRecorded">{{durationDisplay}}</span> <span *ngIf="!lastAudioRecorded">{{durationDisplay}}</span>
<audio [src]="audioRecorded" class="d-flex width-100 mt-10 mb-10" *ngIf="lastAudioRecorded" controls controlsList="nodownload noplaybackrate"></audio> <audio [src]="audioRecorded" class="d-flex width-100 mt-10 mb-10" *ngIf="lastAudioRecorded" controls
controlsList="nodownload noplaybackrate"></audio>
</div> </div>
<div class="container width-100 d-flex"> <div class="container width-100 d-flex">
<div> <div>
<button *ngIf="!recording && !lastAudioRecorded && allowTyping" class="btn-no-color" (click)="openChatOptions()"> <button *ngIf="!recording && !lastAudioRecorded && allowTyping" class="btn-no-color" (click)="openChatOptions()">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-options" src="assets/images/icons-add.svg"></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-options"
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-options" src="assets/images/theme/gov/icons-add.svg"></ion-icon> src="assets/images/icons-add.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-options"
src="assets/images/theme/gov/icons-add.svg"></ion-icon>
</button> </button>
<button *ngIf="recording || lastAudioRecorded || !allowTyping" class="btn-no-color" (click)="deleteRecording()"> <button *ngIf="recording || lastAudioRecorded || !allowTyping" class="btn-no-color" (click)="deleteRecording()">
<fa-icon class="icon-size-27" icon="trash"></fa-icon> <fa-icon class="icon-size-27" icon="trash"></fa-icon>
@@ -189,7 +223,10 @@
</div> </div>
<div class="width-70 message-container"> <div class="width-70 message-container">
<div *ngIf="!recording && !lastAudioRecorded" class="type-message"> <div *ngIf="!recording && !lastAudioRecorded" class="type-message">
<ion-textarea *ngIf="allowTyping" autocomplete="on" autocorrect="on" spellcheck="true" clearOnEdit="true" placeholder="Escrever uma mensagem" auto-grow class="message-input" rows="1" [(ngModel)]="wsChatMethodsService.getDmRoom(roomId).message" (ionChange)="wsChatMethodsService.getDmRoom(roomId).sendTyping()"></ion-textarea> <ion-textarea *ngIf="allowTyping" autocomplete="on" autocorrect="on" spellcheck="true" clearOnEdit="true"
placeholder="Escrever uma mensagem" auto-grow class="message-input" rows="1"
[(ngModel)]="wsChatMethodsService.getDmRoom(roomId).message"
(ionChange)="wsChatMethodsService.getDmRoom(roomId).sendTyping()"></ion-textarea>
</div> </div>
<div *ngIf="recording" class="d-flex align-items-center justify-content-center"> <div *ngIf="recording" class="d-flex align-items-center justify-content-center">
<button (click)="stopRecording()" class="btn-no-color d-flex align-items-center justify-content-center"> <button (click)="stopRecording()" class="btn-no-color d-flex align-items-center justify-content-center">
@@ -198,17 +235,26 @@
</div> </div>
</div> </div>
<div> <div>
<button #recordbtn *ngIf="!wsChatMethodsService.getDmRoom(roomId).message && !lastAudioRecorded" (click)="startRecording()" class="btn-no-color"> <button #recordbtn *ngIf="!wsChatMethodsService.getDmRoom(roomId).message && !lastAudioRecorded"
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send" src="assets/icon/theme/default/icons-chat-record-audio.svg"></ion-icon> (click)="startRecording()" class="btn-no-color">
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-record-audio.svg"></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send"
src="assets/icon/theme/default/icons-chat-record-audio.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send"
src="assets/icon/theme/gov/icons-chat-record-audio.svg"></ion-icon>
</button> </button>
<button *ngIf="wsChatMethodsService.getDmRoom(roomId).message" class="btn-no-color" (click)="sendMessage()" class="btn-no-color"> <button *ngIf="wsChatMethodsService.getDmRoom(roomId).message" class="btn-no-color" (click)="sendMessage()"
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon> class="btn-no-color">
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send"
src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send"
src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon>
</button> </button>
<button *ngIf="!wsChatMethodsService.getDmRoom(roomId).message && lastAudioRecorded" (click)="sendAudio(lastAudioRecorded)" class="btn-no-color"> <button *ngIf="!wsChatMethodsService.getDmRoom(roomId).message && lastAudioRecorded"
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon> (click)="sendAudio(lastAudioRecorded)" class="btn-no-color">
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send"
src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send"
src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon>
</button> </button>
</div> </div>
</div> </div>
+51 -37
View File
@@ -219,15 +219,19 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
this.lastAudioRecorded = fileName; this.lastAudioRecorded = fileName;
}) })
try {
this.storage.get('recordData').then((recordData) => { this.storage.get('recordData').then((recordData) => {
console.log(recordData); console.log(recordData);
if(recordData.value.recordDataBase64.includes('data:audio')){ if(recordData?.value?.recordDataBase64.includes('data:audio')){
this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(recordData.value.recordDataBase64); this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(recordData?.value?.recordDataBase64);
} }
else{ else{
this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(`data:${recordData.value.mimeType};base64,${recordData.value.recordDataBase64}`); this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(`data:${recordData.value.mimeType};base64,${recordData?.value?.recordDataBase64}`);
} }
}); });
} catch (error) {}
} }
startRecording() { startRecording() {
@@ -380,41 +384,65 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
this.wsChatMethodsService.getDmRoom(this.roomId).send({}) this.wsChatMethodsService.getDmRoom(this.roomId).send({})
} }
async sendAudio(fileName) { base64toBlob(base64Data, contentType) {
contentType = contentType || '';
var sliceSize = 1024;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}
async sendAudio(fileName) {
const roomId = this.roomId const roomId = this.roomId
let audioFile;
this.storage.get('recordData').then((recordData) => { this.storage.get('recordData').then((recordData) => {
console.log(recordData);
if(recordData.value.recordDataBase64.includes('data:audio')){ audioFile = recordData;
this.audioRecorded = recordData.value.recordDataBase64; if(recordData?.value?.recordDataBase64.includes('data:audio')){
this.audioRecorded = recordData?.value?.recordDataBase64;
} }
else{ else{
this.audioRecorded = `data:${recordData.value.mimeType};base64,${recordData.value.recordDataBase64}`; this.audioRecorded = `data:${recordData.value.mimeType};base64,${recordData?.value?.recordDataBase64}`;
} }
});
console.log(this.audioRecorded);
//Converting base64 to blob //Converting base64 to blob
const base64Response = await fetch(this.audioRecorded); const encodedData = btoa(this.audioRecorded);
const blob = await base64Response.blob(); const blob = this.base64toBlob(encodedData, recordData.value.mimeType)
console.log(blob)
const formData = new FormData(); const formData = new FormData();
formData.append("blobFile", blob); formData.append("blobFile", blob);
this.wsChatMethodsService.getDmRoom(roomId).send({ this.wsChatMethodsService.getDmRoom(roomId).send({
file: { file: {
"type": "application/audio", "type": "application/audio",
/* "guid": '', */ "msDuration":audioFile.value.msDuration,
"mimeType":audioFile.value.mimeType,
}, },
attachments: [{ attachments: [{
"title": fileName , "title": fileName ,
"title_link": this.audioRecorded,
"title_link_download": true, "title_link_download": true,
"type": "file" "type": "audio"
}], }],
temporaryData: formData temporaryData: formData
}) })
this.deleteRecording();
});
this.deleteRecording();
} }
@@ -824,27 +852,6 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
} }
base64toBlob(base64Data, contentType) {
contentType = contentType || '';
var sliceSize = 1024;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}
getBase64(file) { getBase64(file) {
var reader = this.getFileReader(); var reader = this.getFileReader();
reader.readAsDataURL(file); reader.readAsDataURL(file);
@@ -1081,6 +1088,13 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
} }
async audioPreview(msg) {
console.log(msg);
if (!msg.attachments[0].title_link || msg.attachments[0].title_link === null || msg.attachments[0].title_link === '') {
this.downloadFileMsg(msg)
} else {}
}
imageSize(img) { imageSize(img) {
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
@@ -16,7 +16,7 @@ import { DespachoService } from 'src/app/Rules/despacho.service'
import { Location } from '@angular/common' import { Location } from '@angular/common'
import { fullTask } from 'src/app/models/dailyworktask.model'; import { fullTask } from 'src/app/models/dailyworktask.model';
import { AttachmentList } from 'src/app/models/Excludetask'; import { AttachmentList } from 'src/app/models/Excludetask';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page'; import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page';
import { SqliteService } from 'src/app/services/sqlite.service'; import { SqliteService } from 'src/app/services/sqlite.service';
@@ -22,7 +22,7 @@ import { ExpedienteService } from 'src/app/Rules/expediente.service';
import { expedienteTask } from 'src/app/models/dailyworktask.model'; import { expedienteTask } from 'src/app/models/dailyworktask.model';
import { TaskService } from 'src/app/Rules/task.service'; import { TaskService } from 'src/app/Rules/task.service';
import { DocumentViewerPage } from 'src/app/modals/document-viewer/document-viewer.page'; import { DocumentViewerPage } from 'src/app/modals/document-viewer/document-viewer.page';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page'; import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page';
import { ThemeService } from 'src/app/services/theme.service' import { ThemeService } from 'src/app/services/theme.service'
@@ -22,7 +22,7 @@ import { CustomTaskPipe } from 'src/app/pipes/custom-task.pipe';
//import { NotificationsService } from 'src/app/services/notifications.service'; //import { NotificationsService } from 'src/app/services/notifications.service';
import { DespachoService } from 'src/app/Rules/despacho.service'; import { DespachoService } from 'src/app/Rules/despacho.service';
import { ChangeProfileService } from 'src/app/services/change-profile.service'; import { ChangeProfileService } from 'src/app/services/change-profile.service';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { ThemeService } from 'src/app/services/theme.service' import { ThemeService } from 'src/app/services/theme.service'
@@ -115,6 +115,9 @@ export class GabineteDigitalPage implements OnInit, DoCheck {
customTaskPipe = new CustomTaskPipe() customTaskPipe = new CustomTaskPipe()
permissions = {
Agenda: 530
}
@ViewChild(ExpedientsPage) expedientesPage: ExpedientsPage; @ViewChild(ExpedientsPage) expedientesPage: ExpedientsPage;
@ViewChild(PendentesPage) pendentesListPage: PendentesPage; @ViewChild(PendentesPage) pendentesListPage: PendentesPage;
@ViewChild(EventsToApprovePage) eventsToApprove: EventsToApprovePage; @ViewChild(EventsToApprovePage) eventsToApprove: EventsToApprovePage;
@@ -23,7 +23,7 @@ import { PedidoService } from 'src/app/Rules/pedido.service';
import { SqliteService } from 'src/app/services/sqlite.service'; import { SqliteService } from 'src/app/services/sqlite.service';
import { BackgroundService } from 'src/app/services/background.service'; import { BackgroundService } from 'src/app/services/background.service';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page'; import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page';
import { ThemeService } from 'src/app/services/theme.service' import { ThemeService } from 'src/app/services/theme.service'
import { DataService } from 'src/app/services/data.service'; import { DataService } from 'src/app/services/data.service';
+23 -8
View File
@@ -12,6 +12,8 @@ import { ChangeProfileService } from 'src/app/services/change-profile.service';
import { ThemeService } from 'src/app/services/theme.service'; import { ThemeService } from 'src/app/services/theme.service';
import { StorageService } from 'src/app/services/storage.service'; import { StorageService } from 'src/app/services/storage.service';
import { ChatService } from 'src/app/services/chat.service'; import { ChatService } from 'src/app/services/chat.service';
import { PermissionService } from 'src/app/services/permission.service';
import { PermissionList } from 'src/app/models/permissionList';
@Component({ @Component({
selector: 'app-login', selector: 'app-login',
@@ -29,7 +31,8 @@ export class LoginPage implements OnInit {
hasPin: boolean hasPin: boolean
loginPreference: string loginPreference: string
sessionStore = SessionStore sessionStore = SessionStore;
permissionList = new PermissionList();
constructor( constructor(
private notificatinsservice: NotificationsService, private notificatinsservice: NotificationsService,
@@ -40,7 +43,8 @@ export class LoginPage implements OnInit {
private clearStoreService: ClearStoreService, private clearStoreService: ClearStoreService,
private changeProfileService: ChangeProfileService, private changeProfileService: ChangeProfileService,
public ThemeService: ThemeService, public ThemeService: ThemeService,
private storageservice: StorageService private storageservice: StorageService,
public permissionService: PermissionService,
) {} ) {}
ngOnInit() { ngOnInit() {
@@ -101,26 +105,29 @@ export class LoginPage implements OnInit {
// login to API successfully // login to API successfully
if (attempt) { if (attempt) {
if (attempt.UserId == SessionStore.user.UserId) { if (attempt.UserId == SessionStore.user.UserId) {
await this.authService.SetSession(attempt, this.userattempt); await this.authService.SetSession(attempt, this.userattempt);
await this.authService.loginChat(); await this.authService.loginChat();
await this.authService.loginToChatWs() await this.authService.loginToChatWs();
this.getToken(); this.getToken();
SessionStore.setInativity(true); SessionStore.setInativity(true);
this.goback() this.goback();
} else { } else {
this.clearStoreService.clear() this.clearStoreService.clear();
SessionStore.delete() SessionStore.delete();
window.localStorage.clear(); window.localStorage.clear();
await this.authService.SetSession(attempt, this.userattempt); await this.authService.SetSession(attempt, this.userattempt);
this.changeProfileService.run() this.changeProfileService.run();
await this.authService.loginChat(); await this.authService.loginChat();
await this.authService.loginToChatWs() await this.authService.loginToChatWs();
this.getToken(); this.getToken();
this.router.navigateByUrl('/pin', { replaceUrl: true }); this.router.navigateByUrl('/pin', { replaceUrl: true });
} }
} }
else{ else{
@@ -141,8 +148,16 @@ export class LoginPage implements OnInit {
if(pathName) { if(pathName) {
this.router.navigate([pathName]); this.router.navigate([pathName]);
} else { } else {
if(this.permissionService.userPermission(this.permissionList.Agenda) || this.permissionService.userPermission(this.permissionList.Gabinete)){
this.router.navigate(['/home/events']); this.router.navigate(['/home/events']);
} }
else if(this.permissionService.userPermission(this.permissionList.Chat)){
this.router.navigate(['/home/chat']);
}
else if(this.permissionService.userPermission(this.permissionList.Actions)){
this.router.navigate(['/home/publications']);
}
}
} }
@@ -33,7 +33,9 @@
</ion-refresher> --> </ion-refresher> -->
<div class="main-container background-white height-100 overflow-y-auto"> <div class="main-container background-white height-100 overflow-y-auto">
<ion-content> <ion-content>
<ion-card *ngFor="let publication of getpublication let i = index"> <ion-card *ngFor="let publication of getpublication let i = index"
(click)="goToPublicationDetail(publication.DocumentId)"
>
<ion-card-content> <ion-card-content>
<div class="post-img"> <div class="post-img">
<img [lazyLoad]="publication.FileBase64"> <img [lazyLoad]="publication.FileBase64">
+12 -2
View File
@@ -18,6 +18,7 @@ import { ProcessesService } from 'src/app/services/processes.service';
import { AttachmentsService } from 'src/app/services/attachments.service'; import { AttachmentsService } from 'src/app/services/attachments.service';
import { RoomService } from './chat/room.service'; import { RoomService } from './chat/room.service';
import { Storage } from '@ionic/storage'; import { Storage } from '@ionic/storage';
import { InitialsService } from './functions/initials.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -44,7 +45,8 @@ export class AuthService {
private NfService:NfService, private NfService:NfService,
private processesService: ProcessesService, private processesService: ProcessesService,
private AttachmentsService: AttachmentsService, private AttachmentsService: AttachmentsService,
private storage: Storage ) { private storage: Storage,
private initialsService: InitialsService ) {
this.headers = new HttpHeaders(); this.headers = new HttpHeaders();
@@ -74,6 +76,8 @@ export class AuthService {
try { try {
response = await this.http.post<LoginUserRespose>(environment.apiURL + "UserAuthentication/Login", '', this.opts).toPromise(); response = await this.http.post<LoginUserRespose>(environment.apiURL + "UserAuthentication/Login", '', this.opts).toPromise();
console.log(response);
if(saveSession) { if(saveSession) {
this.SetSession(response, user) this.SetSession(response, user)
} }
@@ -94,6 +98,9 @@ export class AuthService {
} else if(session.RoleID == 100000011) { } else if(session.RoleID == 100000011) {
session.Profile = 'MDGPR' session.Profile = 'MDGPR'
} }
else{
session.Profile = this.initialsService.getInitials(session.FullName);
}
session.Password = user.password session.Password = user.password
session.RochetChatUser = user.username.split('@')[0] session.RochetChatUser = user.username.split('@')[0]
@@ -124,7 +131,6 @@ export class AuthService {
let responseChat = await this.httpService.post('login', postData).toPromise(); let responseChat = await this.httpService.post('login', postData).toPromise();
if(responseChat) { if(responseChat) {
console.log('Login to Rocket chat OK', responseChat); console.log('Login to Rocket chat OK', responseChat);
this.ValidatedUserChat = responseChat; this.ValidatedUserChat = responseChat;
localStorage.setItem('userChat', JSON.stringify(responseChat)); localStorage.setItem('userChat', JSON.stringify(responseChat));
@@ -169,11 +175,15 @@ export class AuthService {
try { try {
let guid: any = await this.AttachmentsService.uploadFile(formData).toPromise() let guid: any = await this.AttachmentsService.uploadFile(formData).toPromise()
message.file.guid = guid.path message.file.guid = guid.path
console.log('========================================',guid)
// await this.storage.set(guid.path, message.file.image_url).then(() => { // await this.storage.set(guid.path, message.file.image_url).then(() => {
// console.log('add picture to chat IMAGE SAVED') // console.log('add picture to chat IMAGE SAVED')
// // message.getFileFromDb() // // message.getFileFromDb()
// }); // });
message.downloadFileMsg()
return true return true
} catch(e) { } catch(e) {
console.log('failed to upload to server', e) console.log('failed to upload to server', e)
+46 -28
View File
@@ -10,6 +10,8 @@ import { ChatStorageService } from './chat-storage.service'
import { ChatMethodsService } from './chat-methods.service' import { ChatMethodsService } from './chat-methods.service'
import { MessageModel, DeleteMessageModel } from '../../models/beast-orm' import { MessageModel, DeleteMessageModel } from '../../models/beast-orm'
import { AESEncrypt } from '../aesencrypt.service' import { AESEncrypt } from '../aesencrypt.service'
import { HttpClient, HttpEventType } from '@angular/common/http';
import { AttachmentsService } from 'src/app/services/attachments.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -59,7 +61,8 @@ export class MessageService {
private WsChatService: WsChatService, private WsChatService: WsChatService,
private ChatStorageService: ChatStorageService, private ChatStorageService: ChatStorageService,
private ChatMethodsService: ChatMethodsService, private ChatMethodsService: ChatMethodsService,
private AESEncrypt: AESEncrypt) { private AESEncrypt: AESEncrypt,
private AttachmentsService: AttachmentsService,) {
} }
setData({customFields = {}, channels, mentions, msg ,rid ,ts, u, t, _id, id, _updatedAt, file, attachments, temporaryData, localReference , viewed = [], received = [], delate = false, delateRequest =false, }:Message) { setData({customFields = {}, channels, mentions, msg ,rid ,ts, u, t, _id, id, _updatedAt, file, attachments, temporaryData, localReference , viewed = [], received = [], delate = false, delateRequest =false, }:Message) {
@@ -74,17 +77,21 @@ export class MessageService {
this._id = _id this._id = _id
this._updatedAt = _updatedAt || new Date().getTime() this._updatedAt = _updatedAt || new Date().getTime()
this.file = file this.file = file
this.attachments = attachments
this.temporaryData = temporaryData this.temporaryData = temporaryData
this.localReference = localReference || null this.localReference = localReference || null
this.id = id this.id = id
this.delate = delate this.delate = delate
this.delateRequest = delateRequest this.delateRequest = delateRequest
if(this.attachments?.length >= 1 && attachments?.length >= 1) {
this.attachments[0] = Object.assign(this.attachments[0], attachments[0])
} else {
this.attachments = attachments
}
this.viewed = [...new Set([...viewed,...this.viewed])]; this.viewed = [...new Set([...viewed,...this.viewed])];
this.received = [...new Set([...received,...this.received])]; this.received = [...new Set([...received,...this.received])];
if(!this.ts) { if(!this.ts) {
this.offline = true this.offline = true
this.messageSend = false this.messageSend = false
@@ -102,7 +109,6 @@ export class MessageService {
} }
if(this.hasFile) { if(this.hasFile) {
// this.getFileFromDb()
if(this.file.type != 'application/webtrix') { if(this.file.type != 'application/webtrix') {
this.displayType = this.file.type.replace('application/','').toUpperCase() this.displayType = this.file.type.replace('application/','').toUpperCase()
} }
@@ -118,19 +124,6 @@ export class MessageService {
return firstName + ' ' + lastName return firstName + ' ' + lastName
} }
// getFileFromDb() {
// if(this.hasFile) {
// if (this.file.guid) {
// this.storage.get(this.file.guid).then((image) => {
// if(image != null) {
// this.file.image_url = image
// }
// });
// }
// }
// }
async send(): Promise<any> { async send(): Promise<any> {
this.sendAttempt++; this.sendAttempt++;
@@ -152,7 +145,7 @@ export class MessageService {
this.uploadingFile = false this.uploadingFile = false
if(uploadSuccessfully || this.hasSendAttachment == false) { if(uploadSuccessfully) {
this.hasSendAttachment = true this.hasSendAttachment = true
this.errorUploadingAttachment = false this.errorUploadingAttachment = false
this.temporaryData = {} this.temporaryData = {}
@@ -186,6 +179,11 @@ export class MessageService {
} }
async sendRequest(params) { async sendRequest(params) {
if(params?.attachments?.image_url) {
delete params?.attachments?.image_url
}
this.ChatMethodsService.send(params).subscribe( this.ChatMethodsService.send(params).subscribe(
(response: any) => { (response: any) => {
const ChatMessage = response.message const ChatMessage = response.message
@@ -198,12 +196,7 @@ export class MessageService {
type: 'reConnect', type: 'reConnect',
funx: async ()=> { funx: async ()=> {
this.WsChatService.send(params).then(({message, requestId}) => { this.send()
let ChatMessage = message.result
this.messageSend = true
this.redefinedMessage(ChatMessage)
})
return true return true
} }
}) })
@@ -222,12 +215,37 @@ export class MessageService {
await this.save() await this.save()
} }
async downloadFileMsg() { downloadFileMsg() {
const result = await this.NfService.beforeSendAttachment(this)
if(result) {
let downloadFile = "";
this.AttachmentsService.downloadFile(this.file.guid).subscribe(async (event) => {
if (event.type === HttpEventType.DownloadProgress) {
} else if (event.type === HttpEventType.Response) {
if (this.file.type == "application/img") {
downloadFile = 'data:image/jpeg;base64,' + btoa(new Uint8Array(event.body).reduce((data, byte) => data + String.fromCharCode(byte), ''));
} else if (this.file.type === 'application/pdf') {
downloadFile = event.body as any;
} else if (this.file.type == 'application/audio') {
downloadFile = new Uint8Array(event.body).reduce((data, byte) => data + String.fromCharCode(byte), '');
} }
this.attachments[0] = {
image_url: downloadFile,
name: this.attachments[0].name,
title: this.attachments[0].title,
title_link: downloadFile,
title_link_download: this.attachments[0].title_link_download,
ts: this.attachments[0].ts
}
// save the changes to the storage
this.save()
}
});
} }
private calDateDuration(date = null) { private calDateDuration(date = null) {
@@ -242,7 +260,6 @@ export class MessageService {
async delateDB() { async delateDB() {
// alert('delete data')
const message = await MessageModel.get({_id: this._id}) const message = await MessageModel.get({_id: this._id})
await message.delete() await message.delete()
@@ -294,6 +311,7 @@ export class MessageService {
async save() { async save() {
const message = this.getChatObj() const message = this.getChatObj()
console.log(message);
await MessageModel.update(message) await MessageModel.update(message)
+54 -37
View File
@@ -21,6 +21,7 @@ import { ChatMethodsService } from './chat-methods.service'
import { DeleteMessageModel, MessageModel } from '../../models/beast-orm' import { DeleteMessageModel, MessageModel } from '../../models/beast-orm'
import { AESEncrypt } from '../aesencrypt.service' import { AESEncrypt } from '../aesencrypt.service'
import { IncomingChatMessage, ChatMessageInterface, falseTypingMethod } from 'src/app/models/message.model'; import { IncomingChatMessage, ChatMessageInterface, falseTypingMethod } from 'src/app/models/message.model';
import { AttachmentsService } from 'src/app/services/attachments.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -75,7 +76,8 @@ export class RoomService {
private NfService: NfService, private NfService: NfService,
private ChatStorageService: ChatStorageService, private ChatStorageService: ChatStorageService,
private ChatMethodsService: ChatMethodsService, private ChatMethodsService: ChatMethodsService,
private AESEncrypt: AESEncrypt private AESEncrypt: AESEncrypt,
private AttachmentsService: AttachmentsService
) { ) {
this.NativeNotificationService.askForPermission() this.NativeNotificationService.askForPermission()
@@ -143,7 +145,7 @@ export class RoomService {
} }
} }
setData({members, u, customFields = {}, id, name, t, lastMessage = new MessageService(this.storage, this.NfService, this.WsChatService, this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt), _updatedAt }) { setData({members, u, customFields = {}, id, name, t, lastMessage = new MessageService(this.storage, this.NfService, this.WsChatService, this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt, this.AttachmentsService), _updatedAt }) {
this.customFields = customFields this.customFields = customFields
this.id = id this.id = id
this.name = name this.name = name
@@ -236,7 +238,6 @@ export class RoomService {
const args = message.fields.args const args = message.fields.args
// alert(JSON.stringify(args))
if (typeof args[1] != 'object') { if (typeof args[1] != 'object') {
@@ -269,7 +270,12 @@ export class RoomService {
getRoomMembersIds(): string[] { getRoomMembersIds(): string[] {
try {
return this.members.map((user)=> user._id) return this.members.map((user)=> user._id)
} catch(error) {
return []
}
} }
getAllMemberThatIsNotOffline(): string[] { getAllMemberThatIsNotOffline(): string[] {
@@ -357,37 +363,46 @@ export class RoomService {
* @description delete message in the view * @description delete message in the view
* @param id message ID * @param id message ID
*/ */
async deleteMessage(id) { async deleteMessage(_id) {
await this.messages.forEach(async(message, index) => {
if(message._id == id) {
this.messages.splice(index, 1) const id = _id
for (let i =0; i <= this.messages.length; i++) {
if(this.messages[i]?._id == id ) {
if (SessionStore.user.RochetChatUser == message.u.username) {
//Get previous last message from room
const previousLastMessage = this.messages.slice(-1)[0];
this.lastMessage = previousLastMessage;
this.calDateDuration(previousLastMessage._updatedAt)
this.sortRoomList()
if (SessionStore.user.RochetChatUser == this.messages[i]?.u?.username) {
const allMemberThatIsOffline = this.getAllMemberThatIsOffline() const allMemberThatIsOffline = this.getAllMemberThatIsOffline()
await DeleteMessageModel.create({ DeleteMessageModel.create({
messageId: message._id, messageId: this.messages[i]._id,
rid: message.rid, rid: this.messages[i].rid,
ts: message.ts, ts: this.messages[i].ts,
u: message.u, u: this.messages[i].u,
needToReceiveBy: allMemberThatIsOffline needToReceiveBy: allMemberThatIsOffline
}) })
} }
message.delateStatusFalse() this.messages[i]?.delateDB()
message.delateDB()
//Get previous last message from room // console.log(_id,'==',this.messages[i]?._id, true)
const previousLastMessage = this.messages.slice(-1)[0]; this.messages.splice(i, 1)
this.lastMessage = previousLastMessage; return true
this.calDateDuration(previousLastMessage._updatedAt)
this.sortRoomList()
} else {
// console.log(_id,'==',this.messages[i]?._id, false)
}
} }
})
} }
@@ -411,22 +426,26 @@ export class RoomService {
async sendDeleteRequest(msgId) { async sendDeleteRequest(msgId) {
const message = this.messages.find((e)=>e._id = msgId) const message = this.messages.find((e)=>e._id == msgId)
message.delateStatusFalse() await message.delateStatusFalse()
this.ChatMethodsService.deleteMessage({_id:msgId, msgId:msgId, roomId:message.rid}).subscribe( this.ChatMethodsService.deleteMessage({_id:msgId, msgId:msgId, roomId:message.rid}).subscribe(
(response: any) => { async (response: any) => {
message.delateRequest = true
message.save()
this.deleteMessage(msgId)
},
(response) => {
if (response.error.error.startsWith('No message found with the id of')) { message.delateRequest = true
// alert('not found') await message.save()
this.deleteMessage(msgId) this.deleteMessage(msgId)
},
async (response) => {
if (response?.error?.error.startsWith('No message found with the id of')) {
this.deleteMessage(msgId)
message.delateRequest = true
await message.save()
} else { } else {
// this.deleteMessage(DeletedMessageId)
this.WsChatService.registerCallback({ this.WsChatService.registerCallback({
type: 'reConnect', type: 'reConnect',
funx: async ()=> { funx: async ()=> {
@@ -666,7 +685,7 @@ export class RoomService {
message = this.fix_updatedAt(message) message = this.fix_updatedAt(message)
const wewMessage = new MessageService(this.storage, this.NfService, this.WsChatService, this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt) const wewMessage = new MessageService(this.storage, this.NfService, this.WsChatService, this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt, this.AttachmentsService)
wewMessage.setData(message) wewMessage.setData(message)
wewMessage.loadHistory = this.hasLoadHistory wewMessage.loadHistory = this.hasLoadHistory
@@ -694,8 +713,6 @@ export class RoomService {
} }
async ChatMessageIsPresentInTheView(ChatMessage:ChatMessageInterface) { async ChatMessageIsPresentInTheView(ChatMessage:ChatMessageInterface) {
let foundIndex; let foundIndex;
@@ -725,7 +742,7 @@ export class RoomService {
async prepareCreate({message, save = true}): Promise<MessageService> { async prepareCreate({message, save = true}): Promise<MessageService> {
message = this.fix_updatedAt(message) message = this.fix_updatedAt(message)
const wewMessage = new MessageService(this.storage, this.NfService, this.WsChatService, this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt) const wewMessage = new MessageService(this.storage, this.NfService, this.WsChatService, this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt, this.AttachmentsService)
wewMessage.setData(message) wewMessage.setData(message)
wewMessage.loadHistory = this.hasLoadHistory wewMessage.loadHistory = this.hasLoadHistory
@@ -737,7 +754,7 @@ export class RoomService {
simplePrepareMessage(message) { simplePrepareMessage(message) {
message = this.fix_updatedAt(message) message = this.fix_updatedAt(message)
const wewMessage = new MessageService(this.storage, this.NfService, this.WsChatService, this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt) const wewMessage = new MessageService(this.storage, this.NfService, this.WsChatService, this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt, this.AttachmentsService)
wewMessage.setData(message) wewMessage.setData(message)
wewMessage.loadHistory = this.hasLoadHistory wewMessage.loadHistory = this.hasLoadHistory
@@ -19,6 +19,7 @@ import { AuthService } from '../auth.service';
import { ChatStorageService } from './chat-storage.service' import { ChatStorageService } from './chat-storage.service'
import { ChatMethodsService } from './chat-methods.service' import { ChatMethodsService } from './chat-methods.service'
import { AESEncrypt } from '../aesencrypt.service' import { AESEncrypt } from '../aesencrypt.service'
import { AttachmentsService } from 'src/app/services/attachments.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -55,7 +56,8 @@ export class WsChatMethodsService {
private authService: AuthService, private authService: AuthService,
private ChatStorageService: ChatStorageService, private ChatStorageService: ChatStorageService,
private ChatMethodsService:ChatMethodsService, private ChatMethodsService:ChatMethodsService,
private AESEncrypt: AESEncrypt private AESEncrypt: AESEncrypt,
private AttachmentsService:AttachmentsService
) { ) {
this.loggedUser = authService.ValidatedUserChat['data']; this.loggedUser = authService.ValidatedUserChat['data'];
@@ -158,7 +160,10 @@ export class WsChatMethodsService {
} catch(e){} } catch(e){}
setTimeout(()=>{
this.sortRoomList() this.sortRoomList()
}, 1000)
} }
async getAllRooms () { async getAllRooms () {
@@ -202,7 +207,11 @@ export class WsChatMethodsService {
console.log('save rooms', rooms) console.log('save rooms', rooms)
await this.storage.set('Rooms', rooms); await this.storage.set('Rooms', rooms);
setTimeout(()=>{
this.sortRoomList() this.sortRoomList()
}, 1000)
this.loadingWholeList = false this.loadingWholeList = false
} }
@@ -305,7 +314,7 @@ export class WsChatMethodsService {
// create room // create room
if(!this.roomExist(roomId)) { if(!this.roomExist(roomId)) {
let room:RoomService = new RoomService(this.WsChatService, new MessageService(this.storage, this.NfService, this.WsChatService, this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt), this.storage, this.platform, this.sqlservice, this.NativeNotificationService, this.sortService, this.ChatService, this.NfService , this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt) let room:RoomService = new RoomService(this.WsChatService, new MessageService(this.storage, this.NfService, this.WsChatService, this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt, this.AttachmentsService), this.storage, this.platform, this.sqlservice, this.NativeNotificationService, this.sortService, this.ChatService, this.NfService , this.ChatStorageService, this.ChatMethodsService, this.AESEncrypt, this.AttachmentsService)
room.setData(setData) room.setData(setData)
room.receiveMessage() room.receiveMessage()
room.getAllUsers = this.getUsers room.getAllUsers = this.getUsers
+1 -1
View File
@@ -728,7 +728,7 @@ export class WsChatService {
this.wsMsgQueue[requestId] = {message, requestId, loginRequired} this.wsMsgQueue[requestId] = {message, requestId, loginRequired}
} else { } else {
let messageStr = JSON.stringify(message) let messageStr = JSON.stringify(message)
console.log('messageStr', messageStr) // console.log('messageStr', messageStr)
this.socket.send(messageStr) this.socket.send(messageStr)
} }
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { InitialsService } from './initials.service';
describe('InitialsService', () => {
let service: InitialsService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(InitialsService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,18 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class InitialsService {
constructor() { }
getInitials(name:string){
let names = name.split(' '),
initials = names[0].substring(0, 1).toUpperCase();
if (names.length > 1) {
initials += names[names.length - 1].substring(0, 1).toUpperCase();
}
return initials;
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { PermissionService } from './worker/permission.service'; import { PermissionService } from './permission.service';
describe('PermissionService', () => { describe('PermissionService', () => {
let service: PermissionService; let service: PermissionService;
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { SessionStore } from '../../store/session.service'; import { SessionStore } from '../store/session.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -19,6 +19,22 @@ export class PermissionService {
return args.includes(this.SessionStore.user.Profile) return args.includes(this.SessionStore.user.Profile)
} }
userPermission(args) {
if(!Array.isArray(args)) {
args = [args]
}
for(let permission of (this.SessionStore.user.UserPermissions || [])){
if (args.includes(permission)){
return true;
}
}
return false;
}
role(args: any) { role(args: any) {
let UserRoleIsValid = this.userRole(args) let UserRoleIsValid = this.userRole(args)
+1 -1
View File
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AttachmentsService } from '../attachments.service'; import { AttachmentsService } from '../attachments.service';
import { EventsService } from '../events.service'; import { EventsService } from '../events.service';
import { PermissionService } from '../worker/permission.service'; import { PermissionService } from '../permission.service';
@@ -60,7 +60,7 @@
</div> </div>
</div> </div>
<div *ngIf="msg.file && msg.delate == false"> <div *ngIf="msg.file">
<div class="message-item incoming-{{msg.u.username!=loggedUser.me.username}} max-width-45" *ngIf="msg.t != 'r' && msg.t != 'ul' && msg.t != 'au' && msg.t != 'ru' && msg.file.type != 'application/meeting'" > <div class="message-item incoming-{{msg.u.username!=loggedUser.me.username}} max-width-45" *ngIf="msg.t != 'r' && msg.t != 'ul' && msg.t != 'au' && msg.t != 'ru' && msg.file.type != 'application/meeting'" >
<div *ngIf="msg.file.type != 'application/meeting'"> <div *ngIf="msg.file.type != 'application/meeting'">
<div class="message-item-options d-flex justify-content-end"> <div class="message-item-options d-flex justify-content-end">
@@ -76,7 +76,11 @@
<div class="message"> <div class="message">
<div *ngIf="msg.attachments" class="message-attachments"> <div *ngIf="msg.attachments" class="message-attachments">
<div *ngFor="let file of msg.attachments"> <div *ngFor="let file of msg.attachments">
<div *ngIf="msg.file.type == 'application/img'" (click)="openPreview(msg)"> <div *ngIf="msg.file.type == 'application/img' && !msg.attachments[0].image_url">
NOT UPLOADED
</div>
<div *ngIf="msg.file.type == 'application/img' &&
msg.attachments[0].image_url" (click)="openPreview(msg)">
<img *ngIf="msg.attachments[0].image_url" src="{{msg.attachments[0].image_url}}" alt="image"> <img *ngIf="msg.attachments[0].image_url" src="{{msg.attachments[0].image_url}}" alt="image">
<ion-icon *ngIf="msg.attachments[0].image_url == null" name="download-outline"></ion-icon> <ion-icon *ngIf="msg.attachments[0].image_url == null" name="download-outline"></ion-icon>
</div> </div>
@@ -92,7 +96,15 @@
<ion-label class="file-title">{{file.title}}</ion-label> <ion-label class="file-title">{{file.title}}</ion-label>
</div> </div>
</div> </div>
<div class="audio-contentainer" *ngIf="msg.file.type == 'application/audio'"> <div (click)="audioPreview(msg)" class="audio-contentainer" *ngIf="msg.file.type == 'application/audio' && !file.title_link">
<ion-item class="add-attachment-bg-color" shape="round" lines="none" type="button">
<ion-icon name="mic-outline" class="file-icon"></ion-icon>
<ion-label>{{file.title}}</ion-label>
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="icon-download" src="assets/icon/theme/default/icons-download.svg" slot="end"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="icon-download" src="assets/icon/theme/gov/icons-download.svg" slot="end"></ion-icon>
</ion-item>
</div>
<div class="audio-contentainer" *ngIf="msg.file.type == 'application/audio' && file.title_link">
<audio [src]="file.title_link|safehtml" preload="metadata" controls controlsList="nodownload noplaybackrate"></audio> <audio [src]="file.title_link|safehtml" preload="metadata" controls controlsList="nodownload noplaybackrate"></audio>
</div> </div>
<div class="file-details-optional add-attachment-bg-color"> <div class="file-details-optional add-attachment-bg-color">
@@ -116,9 +128,6 @@
<ion-label class="info-meeting-medium"><ion-icon></ion-icon><ion-icon name="location-outline"></ion-icon> {{msg.file.venue}}</ion-label><br /> <ion-label class="info-meeting-medium"><ion-icon></ion-icon><ion-icon name="location-outline"></ion-icon> {{msg.file.venue}}</ion-label><br />
</div> </div>
</div> </div>
<div *ngIf="msg.file && msg.delate == true">
Apagou a mensagem
</div>
<div *ngIf="msg.t == 'r'" class="info-text"> <div *ngIf="msg.t == 'r'" class="info-text">
@@ -208,9 +217,9 @@
<ion-fab-button title="Nova Reunião" (click)="bookMeeting()" color="light"> <ion-fab-button title="Nova Reunião" (click)="bookMeeting()" color="light">
<ion-icon name="calendar"></ion-icon> <ion-icon name="calendar"></ion-icon>
</ion-fab-button> </ion-fab-button>
<ion-fab-button title="Adicionar Documento" (click)="addFile()" color="light"> <!-- <ion-fab-button title="Adicionar Documento" (click)="addFile()" color="light">
<ion-icon name="document"></ion-icon> <ion-icon name="document"></ion-icon>
</ion-fab-button> </ion-fab-button> -->
<ion-fab-button title="Anexar Fotografia" (click)="addImage()" color="light"> <ion-fab-button title="Anexar Fotografia" (click)="addImage()" color="light">
<ion-icon name="image"></ion-icon> <ion-icon name="image"></ion-icon>
</ion-fab-button> </ion-fab-button>
@@ -274,20 +274,23 @@ export class GroupMessagesPage implements OnInit, OnChanges, AfterViewInit, OnDe
} }
async loadFiles() { async loadFiles() {
try {
this.storage.get('fileName').then((fileName) => { this.storage.get('fileName').then((fileName) => {
this.lastAudioRecorded = fileName; this.lastAudioRecorded = fileName;
}) })
this.storage.get('recordData').then((recordData) => { this.storage.get('recordData').then((recordData) => {
console.log(recordData); console.log(recordData);
if(recordData.value.recordDataBase64.includes('data:audio')){ if(recordData?.value?.recordDataBase64.includes('data:audio')){
this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(recordData.value.recordDataBase64); this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(recordData?.value?.recordDataBase64);
} }
else{ else{
this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(`data:${recordData.value.mimeType};base64,${recordData.value.recordDataBase64}`); this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(`data:${recordData.value.mimeType};base64,${recordData?.value?.recordDataBase64}`);
} }
}); });
} catch (error) {}
} }
startRecording() { startRecording() {
@@ -417,41 +420,64 @@ export class GroupMessagesPage implements OnInit, OnChanges, AfterViewInit, OnDe
this.wsChatMethodsService.getGroupRoom(this.roomId).send({}) this.wsChatMethodsService.getGroupRoom(this.roomId).send({})
} }
async sendAudio(fileName) { base64toBlob(base64Data, contentType) {
contentType = contentType || '';
var sliceSize = 1024;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}
async sendAudio(fileName) {
const roomId = this.roomId const roomId = this.roomId
let audioFile;
this.storage.get('recordData').then((recordData) => { this.storage.get('recordData').then((recordData) => {
console.log(recordData); console.log(recordData);
if(recordData.value.recordDataBase64.includes('data:audio')){ audioFile = recordData;
this.audioRecorded = recordData.value.recordDataBase64; if(recordData?.value?.recordDataBase64.includes('data:audio')){
this.audioRecorded = recordData?.value?.recordDataBase64;
} }
else{ else{
this.audioRecorded = `data:${recordData.value.mimeType};base64,${recordData.value.recordDataBase64}`; this.audioRecorded = `data:${recordData.value.mimeType};base64,${recordData?.value?.recordDataBase64}`;
} }
});
//Converting base64 to blob //Converting base64 to blob
const base64Response = await fetch(this.audioRecorded); const encodedData = btoa(this.audioRecorded);
const blob = await base64Response.blob(); const blob = this.base64toBlob(encodedData, recordData.value.mimeType)
console.log(blob)
const formData = new FormData(); const formData = new FormData();
formData.append("blobFile", blob); formData.append("blobFile", blob);
this.wsChatMethodsService.getGroupRoom(roomId).send({ this.wsChatMethodsService.getGroupRoom(roomId).send({
file: { file: {
"type": "application/audio", "type": "application/audio",
/* "guid": '', */ "msDuration":audioFile.value.msDuration,
"mimeType":audioFile.value.mimeType,
}, },
attachments: [{ attachments: [{
"title": fileName , "title": fileName ,
"title_link": this.audioRecorded,
"title_link_download": true, "title_link_download": true,
"type": "file" "type": "audio"
}], }],
temporaryData: formData temporaryData: formData
}) })
this.deleteRecording();
});
this.deleteRecording();
} }
deleteMessage(msgId: string) { deleteMessage(msgId: string) {
@@ -971,41 +997,7 @@ export class GroupMessagesPage implements OnInit, OnChanges, AfterViewInit, OnDe
downloadFileMsg(msg: MessageService) { downloadFileMsg(msg: MessageService) {
console.log('FILE TYPE', msg.file.type) msg.downloadFileMsg()
this.downloadFile = "";
if (msg.file.type == "application/img") {
this.AttachmentsService.downloadFile(msg.file.guid).subscribe(async (event) => {
console.log('FILE TYPE 22', msg.file.guid)
var name = msg.file.guid;
if (event.type === HttpEventType.DownloadProgress) {
//this.downloadProgess = Math.round((100 * event.loaded) / event.total);
console.log('FILE TYPE 33', msg.file.type)
} else if (event.type === HttpEventType.Response) {
if (msg.file.type == "application/img") {
this.downloadFile = 'data:image/jpeg;base64,' + btoa(new Uint8Array(event.body).reduce((data, byte) => data + String.fromCharCode(byte), ''));
} else if (msg.file.type === 'application/pdf') {
this.downloadFile = event.body;
}
msg.attachments[0] = {
image_url: this.downloadFile,
name: msg.attachments[0].name,
title: msg.attachments[0].title,
title_link_download: msg.attachments[0].title_link_download,
ts: msg.attachments[0].ts
}
await this.storage.set(msg.file.guid, this.downloadFile).then(() => {
console.log('IMAGE SAVED')
});
}
});
}
} }
async openPreview(msg) { async openPreview(msg) {
@@ -1029,5 +1021,12 @@ export class GroupMessagesPage implements OnInit, OnChanges, AfterViewInit, OnDe
} }
async audioPreview(msg) {
console.log(msg);
if (!msg.attachments[0].title_link || msg.attachments[0].title_link === null || msg.attachments[0].title_link === '') {
this.downloadFileMsg(msg)
} else {}
}
} }
+22 -13
View File
@@ -35,7 +35,7 @@
</ion-refresher> </ion-refresher>
<div class="messages" #scrollMe> <div class="messages" #scrollMe>
<div class="messages-list-item-wrapper container-width-100" <div class="messages-list-item-wrapper container-width-100"
*ngFor="let msg of wsChatMethodsService.getDmRoom(roomId).messages; let last = last"> *ngFor="let msg of wsChatMethodsService.getDmRoom(roomId).messages; index as i; let last = last">
<div class='message-item incoming-{{msg.u.username!=loggedUser.me.username}} max-width-45' *ngIf="msg.msg !=''"> <div class='message-item incoming-{{msg.u.username!=loggedUser.me.username}} max-width-45' *ngIf="msg.msg !=''">
<div class="message-item-options d-flex justify-content-end"> <div class="message-item-options d-flex justify-content-end">
<fa-icon [matMenuTriggerFor]="beforeMenu" icon="chevron-down" class="message-options-icon cursor-pointer"> <fa-icon [matMenuTriggerFor]="beforeMenu" icon="chevron-down" class="message-options-icon cursor-pointer">
@@ -50,7 +50,7 @@
</div> </div>
<div class="d-flex justify-space-between"> <div class="d-flex justify-space-between">
<ion-label *ngIf="msg.delate == false" class="flex-0">{{msg.msg}}</ion-label> <ion-label *ngIf="msg.delate == false" class="flex-0">{{msg.msg}} </ion-label>
<ion-label *ngIf="msg.delate == true" class="flex-0">Apagou a mensagem</ion-label> <ion-label *ngIf="msg.delate == true" class="flex-0">Apagou a mensagem</ion-label>
<ion-label class="float-status-all float-status" > <ion-label class="float-status-all float-status" >
@@ -84,7 +84,6 @@
<div *ngIf="msg.file.type == 'application/img'" (click)="openPreview(msg)" dfsdvsvs> <div *ngIf="msg.file.type == 'application/img'" (click)="openPreview(msg)" dfsdvsvs>
<img src={{msg.attachments[0].image_url}} alt="image"> <img src={{msg.attachments[0].image_url}} alt="image">
<ion-label class="float-status-all float-status" > <ion-label class="float-status-all float-status" >
<ion-icon *ngIf="msg.messageSend == false" src="assets/images/clock-regular.svg"></ion-icon> <ion-icon *ngIf="msg.messageSend == false" src="assets/images/clock-regular.svg"></ion-icon>
<ion-icon *ngIf="msg.messageSend == true && msg.received.length == 0" src="assets/images/check-solid.svg"></ion-icon> <ion-icon *ngIf="msg.messageSend == true && msg.received.length == 0" src="assets/images/check-solid.svg"></ion-icon>
<ion-icon *ngIf="msg.messageSend && msg.received.length >= 1 && msg.viewed.length == 0" src="assets/images/check-double-solid.svg"></ion-icon> <ion-icon *ngIf="msg.messageSend && msg.received.length >= 1 && msg.viewed.length == 0" src="assets/images/check-double-solid.svg"></ion-icon>
@@ -109,7 +108,15 @@
<ion-label class="file-title">{{file.title}}</ion-label> <ion-label class="file-title">{{file.title}}</ion-label>
</div> </div>
</div> </div>
<div class="audio-contentainer" *ngIf="msg.file.type == 'application/audio'"> <div (click)="audioPreview(msg)" class="audio-contentainer" *ngIf="msg.file.type == 'application/audio' && !file.title_link">
<ion-item class="add-attachment-bg-color" shape="round" lines="none" type="button">
<ion-icon name="mic-outline" class="file-icon"></ion-icon>
<ion-label>{{file.title}}</ion-label>
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="icon-download" src="assets/icon/theme/default/icons-download.svg" slot="end"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="icon-download" src="assets/icon/theme/gov/icons-download.svg" slot="end"></ion-icon>
</ion-item>
</div>
<div class="audio-contentainer" *ngIf="msg.file.type == 'application/audio' && file.title_link">
<audio [src]="file.title_link|safehtml" preload="metadata" class="flex-grow-1" controls controlsList="nodownload noplaybackrate"></audio> <audio [src]="file.title_link|safehtml" preload="metadata" class="flex-grow-1" controls controlsList="nodownload noplaybackrate"></audio>
</div> </div>
<div class="file-details-optional add-attachment-bg-color"> <div class="file-details-optional add-attachment-bg-color">
@@ -133,24 +140,26 @@
</div> </div>
</div> </div>
<div class="info-meeting" *ngIf="msg.file.type == 'application/meeting'"> <div class="info-meeting" *ngIf="msg.file.type == 'application/meeting'">
<ion-label class="info-meeting-small">{{msg.u.name}} criou esta reunião</ion-label><br />
<button (click)="goToEvent(msg.file.id)" class="btn-no-color info-meeting-normal"> <ion-label *ngIf="msg.delate == true" class="info-meeting-small">Apagou a mensagem</ion-label><br />
<ion-label *ngIf="msg.delate == false" class="info-meeting-small">{{msg.u.name}} criou esta reunião</ion-label><br />
<button *ngIf="msg.delate == false" (click)="goToEvent(msg.file.id)" class="btn-no-color info-meeting-normal">
<ion-label class="info-meeting-normal">{{msg.file.subject}}</ion-label> <ion-label class="info-meeting-normal">{{msg.file.subject}}</ion-label>
</button><br /> </button><br />
<ion-label class="info-meeting-medium"> <ion-label *ngIf="msg.delate == false" class="info-meeting-medium">
<ion-icon name="calendar-outline"></ion-icon> De {{showDateDuration(msg.file.start_date)}} a <ion-icon name="calendar-outline"></ion-icon> De {{showDateDuration(msg.file.start_date)}} a
{{showDateDuration(msg.file.end_date)}} {{showDateDuration(msg.file.end_date)}}
</ion-label><br /> </ion-label><br />
<ion-label class="info-meeting-medium"> <ion-label *ngIf="msg.delate == false" class="info-meeting-medium">
<ion-icon></ion-icon> <ion-icon></ion-icon>
<ion-icon name="location-outline"></ion-icon> {{msg.file.venue}} <ion-icon name="location-outline"></ion-icon> {{msg.file.venue}}
</ion-label><br /> </ion-label><br />
</div> </div>
</div> </div>
<div *ngIf="msg.file && msg.delate == true">
Apagou a mensagem
</div>
</div> </div>
</div> </div>
@@ -189,9 +198,9 @@
<ion-fab-button title="Nova Reunião" (click)="bookMeeting()" color="light"> <ion-fab-button title="Nova Reunião" (click)="bookMeeting()" color="light">
<ion-icon name="calendar"></ion-icon> <ion-icon name="calendar"></ion-icon>
</ion-fab-button> </ion-fab-button>
<ion-fab-button title="Adicionar Documento" (click)="addFile()" color="light"> <!-- <ion-fab-button title="Adicionar Documento" (click)="addFile()" color="light">
<ion-icon name="document"></ion-icon> <ion-icon name="document"></ion-icon>
</ion-fab-button> </ion-fab-button> -->
<ion-fab-button title="Anexar Fotografia" (click)="addImage()" color="light"> <ion-fab-button title="Anexar Fotografia" (click)="addImage()" color="light">
<ion-icon name="image"></ion-icon> <ion-icon name="image"></ion-icon>
</ion-fab-button> </ion-fab-button>
@@ -227,6 +227,13 @@
margin-top: 4px; margin-top: 4px;
} }
.chat-icon-download{
font-size: 95px;
margin: 0 auto;
margin-top: 4px;
border: 1px solid red;
}
.type-message{ .type-message{
display: flex; display: flex;
border: 1px solid #ebebeb; border: 1px solid #ebebeb;
@@ -329,3 +336,8 @@ display: block;
.typing ngx-letters-avatar { .typing ngx-letters-avatar {
padding-right: 5px; padding-right: 5px;
} }
.div-do-audio{
border: 1px solid red !important;
overflow: auto;
}
+32 -30
View File
@@ -25,7 +25,6 @@ import { WsChatMethodsService } from 'src/app/services/chat/ws-chat-methods.serv
import { WsChatService } from 'src/app/services/chat/ws-chat.service' import { WsChatService } from 'src/app/services/chat/ws-chat.service'
import { MessageService } from 'src/app/services/chat/message.service'; import { MessageService } from 'src/app/services/chat/message.service';
import { AttachmentsService } from 'src/app/services/attachments.service'; import { AttachmentsService } from 'src/app/services/attachments.service';
import { CameraService } from 'src/app/services/camera.service'; import { CameraService } from 'src/app/services/camera.service';
import { FileType } from 'src/app/models/fileType'; import { FileType } from 'src/app/models/fileType';
import { SearchPage } from 'src/app/pages/search/search.page'; import { SearchPage } from 'src/app/pages/search/search.page';
@@ -250,11 +249,23 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
} }
async loadFiles() { async loadFiles() {
try {
this.storage.get('fileName').then((fileName) => { this.storage.get('fileName').then((fileName) => {
this.lastAudioRecorded = fileName; this.lastAudioRecorded = fileName;
}) })
this.storage.get('recordData').then((recordData) => {
console.log(recordData);
if (recordData?.value?.recordDataBase64.includes('data:audio')) {
this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(recordData?.value?.recordDataBase64);
}
else {
this.audioRecorded = this.sanitiser.bypassSecurityTrustResourceUrl(`data:${recordData.value.mimeType};base64,${recordData?.value?.recordDataBase64}`);
}
});
} catch (error) { }
this.storage.get('recordData').then((recordData) => { this.storage.get('recordData').then((recordData) => {
console.log(recordData); console.log(recordData);
if (recordData.value.recordDataBase64.includes('data:audio')) { if (recordData.value.recordDataBase64.includes('data:audio')) {
@@ -267,7 +278,6 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
} }
startRecording() { startRecording() {
console.log('Recording');
if (this.recording) { if (this.recording) {
return; return;
@@ -354,64 +364,49 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
this.wsChatMethodsService.getDmRoom(this.roomId).send({}) this.wsChatMethodsService.getDmRoom(this.roomId).send({})
} }
async sendAudio(fileName) {
async sendAudio(fileName) {
const roomId = this.roomId const roomId = this.roomId
let audioFile; let audioFile;
this.storage.get('recordData').then((recordData) => { this.storage.get('recordData').then((recordData) => {
console.log(recordData); console.log(recordData);
audioFile = recordData; audioFile = recordData;
if (recordData.value.recordDataBase64.includes('data:audio')) { if (recordData.value.recordDataBase64.includes('data:audio')) {
this.audioRecorded = recordData.value.recordDataBase64; this.audioRecorded = recordData.value.recordDataBase64;
} }
else { else{
this.audioRecorded = `data:${recordData.value.mimeType};base64,${recordData.value.recordDataBase64}`; this.audioRecorded = `data:${recordData.value.mimeType};base64,${recordData?.value?.recordDataBase64}`;
} }
});
//Converting base64 to blob //Converting base64 to blob
const base64Response = await fetch(this.audioRecorded); const encodedData = btoa(this.audioRecorded);
const blob = await base64Response.blob(); const blob = this.base64toBlob(encodedData, recordData.value.mimeType)
console.log(blob)
const formData = new FormData(); const formData = new FormData();
formData.append("blobFile", blob); formData.append("blobFile", blob);
this.wsChatMethodsService.getDmRoom(roomId).send({ this.wsChatMethodsService.getDmRoom(roomId).send({
file: { file: {
"type": "application/audio", "type": "application/audio",
/* "guid": '', */
"msDuration": audioFile.value.msDuration, "msDuration": audioFile.value.msDuration,
"mimeType": audioFile.value.mimeType, "mimeType": audioFile.value.mimeType,
}, },
attachments: [{ attachments: [{
"title": fileName, "title": fileName,
"title_link": this.audioRecorded,
"title_link_download": true, "title_link_download": true,
"type": "audio" "type": "audio"
}], }],
temporaryData: formData temporaryData: formData
}) })
this.deleteRecording();
});
this.deleteRecording();
} }
deleteMessage(msgId: string, msg: MessageService) { deleteMessage(msgId: string, msg: MessageService) {
this.wsChatMethodsService.getDmRoom(this.roomId).sendDeleteRequest(msgId)
/* msg.delateStatusFalse() if (msg.file.type == "application/webtrix") {
this.wsChatMethodsService.getDmRoom(this.roomId).sendDeleteRequest(msgId) */
}
async viewDocument(msg: any, url?: string) {
if (msg.file.type == "application/img") {
let response: any = await this.AttachmentsService.getFile(msg.file.guid).toPromise();
console.log(response);
alert(response);
//this.openPreview(msg);
}
else if (msg.file.type == "application/webtrix") {
this.openViewDocumentModal(msg.file); this.openViewDocumentModal(msg.file);
} }
else { else {
@@ -955,6 +950,13 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
DocumentViewer.viewDocument DocumentViewer.viewDocument
} }
async audioPreview(msg) {
console.log(msg);
if (!msg.attachments[0].title_link || msg.attachments[0].title_link === null || msg.attachments[0].title_link === '') {
this.downloadFileMsg(msg)
} else { }
}
async openPreview(msg) { async openPreview(msg) {
console.log(msg); console.log(msg);
+5 -5
View File
@@ -66,7 +66,7 @@
<div class="d-flex flex-1 pr-20 pl-50"> <div class="d-flex flex-1 pr-20 pl-50">
<div class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/events')" <div *ngIf="p.userPermission([permissionList.Agenda]) || p.userPermission([permissionList.Gabinete])" class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/events')"
[class.active]="locationPathname() == '/home/events'"> [class.active]="locationPathname() == '/home/events'">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-40" src='assets/images/icons-nav-home-active-black.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-40" src='assets/images/icons-nav-home-active-black.svg'></ion-icon>
@@ -76,7 +76,7 @@
<span>Início</span> <span>Início</span>
</div> </div>
<div class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/agenda')" <div *ngIf="p.userPermission([permissionList.Agenda])" class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/agenda')"
[class.active]="locationPathname() == '/home/agenda'"> [class.active]="locationPathname() == '/home/agenda'">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-40" src='assets/images/icons-nav-agenda-inactive.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-40" src='assets/images/icons-nav-agenda-inactive.svg'></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="font-40" src='assets/images/theme/gov/icons-nav-agenda-inactive.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="font-40" src='assets/images/theme/gov/icons-nav-agenda-inactive.svg'></ion-icon>
@@ -85,7 +85,7 @@
<span>Agenda</span> <span>Agenda</span>
</div> </div>
<div class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/gabinete-digital')" <div *ngIf="p.userPermission([permissionList.Gabinete])" class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/gabinete-digital')"
[class.active]="locationPathname() == '/home/gabinete-digital'"> [class.active]="locationPathname() == '/home/gabinete-digital'">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-40" src='assets/images/icons-nav-home-dk.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-40" src='assets/images/icons-nav-home-dk.svg'></ion-icon>
@@ -94,7 +94,7 @@
<span>Gabinete</span> <span>Gabinete</span>
</div> </div>
<div class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/publications')" <div *ngIf="p.userPermission([permissionList.Actions])" class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/publications')"
[class.active]="locationPathname() == '/home/publications'"> [class.active]="locationPathname() == '/home/publications'">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-40" src='assets/images/icons-nav-a-es-inactive.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-40" src='assets/images/icons-nav-a-es-inactive.svg'></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="font-40" src='assets/images/theme/gov/icons-nav-a-es-inactive.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="font-40" src='assets/images/theme/gov/icons-nav-a-es-inactive.svg'></ion-icon>
@@ -102,7 +102,7 @@
<span>Acções</span> <span>Acções</span>
</div> </div>
<div class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/chat')" <div *ngIf="p.userPermission([permissionList.Chat])" class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/chat')"
[class.active]="locationPathname() == '/home/chat'"> [class.active]="locationPathname() == '/home/chat'">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-40" src='assets/images/icons-nav-grupos-inactive-dk-white.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-40" src='assets/images/icons-nav-grupos-inactive-dk-white.svg'></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="font-40" src='assets/images/theme/gov/icons-nav-grupos-inactive-dk-white.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="font-40" src='assets/images/theme/gov/icons-nav-grupos-inactive-dk-white.svg'></ion-icon>
+5 -2
View File
@@ -6,12 +6,13 @@ import { LoginUserRespose } from 'src/app/models/user.model';
import { ProfilePage } from 'src/app/modals/profile/profile.page'; import { ProfilePage } from 'src/app/modals/profile/profile.page';
import { StorageService } from '../../services/storage.service'; import { StorageService } from '../../services/storage.service';
import { SessionStore } from 'src/app/store/session.service'; import { SessionStore } from 'src/app/store/session.service';
//import { NotificationsService } from '../../services/notifications.service';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { EventTrigger } from '../../services/eventTrigger.service'; import { EventTrigger } from '../../services/eventTrigger.service';
import { ThemeService } from '../../services/theme.service'; import { ThemeService } from '../../services/theme.service';
import { interval } from 'rxjs'; import { interval } from 'rxjs';
import { RouteService } from 'src/app/services/route.service'; import { RouteService } from 'src/app/services/route.service';
import { PermissionList } from 'src/app/models/permissionList';
import { PermissionService } from 'src/app/services/permission.service';
@Component({ @Component({
selector: 'app-header', selector: 'app-header',
@@ -29,6 +30,7 @@ export class HeaderPage implements OnInit {
notificationLength: 0; notificationLength: 0;
SessionStore = SessionStore SessionStore = SessionStore
check: boolean; check: boolean;
permissionList = new PermissionList();
production = environment.production production = environment.production
@@ -41,7 +43,8 @@ export class HeaderPage implements OnInit {
//private notificationsService: NotificationsService, //private notificationsService: NotificationsService,
private eventrigger: EventTrigger, private eventrigger: EventTrigger,
public ThemeService: ThemeService, public ThemeService: ThemeService,
public RouteService: RouteService public RouteService: RouteService,
public p: PermissionService,
) { ) {
this.loggeduser = SessionStore.user; this.loggeduser = SessionStore.user;
router.events.subscribe((val) => { router.events.subscribe((val) => {
@@ -7,7 +7,7 @@
</div> </div>
<div class="buttons"> <div class="buttons">
<button (click)="takePicture()" full class="btn-ok" shape="round" >Tirar Fotografia</button> <button (click)="takePicture()" full class="btn-ok" shape="round" >Tirar Fotografia</button>
<button (click)="addFile()" class="btn-ok" shape="round" >Anexar Documento</button> <!-- <button (click)="addFile()" class="btn-ok" shape="round" >Anexar Documento</button> -->
<button (click)="anexarFoto()" full class="btn-ok" shape="round" >Anexar Fotografia</button> <button (click)="anexarFoto()" full class="btn-ok" shape="round" >Anexar Fotografia</button>
<button (click)="addDocGestaoDocumental()" class="btn-ok" shape="round" >Gestão Documental</button> <button (click)="addDocGestaoDocumental()" class="btn-ok" shape="round" >Gestão Documental</button>
<div class="solid"></div> <div class="solid"></div>
@@ -9,7 +9,7 @@ import { BookMeetingModalPage } from 'src/app/pages/gabinete-digital/expediente/
import { DiscartExpedientModalPage } from 'src/app/pages/gabinete-digital/discart-expedient-modal/discart-expedient-modal.page'; import { DiscartExpedientModalPage } from 'src/app/pages/gabinete-digital/discart-expedient-modal/discart-expedient-modal.page';
import { ToastService } from 'src/app/services/toast.service'; import { ToastService } from 'src/app/services/toast.service';
import { customTask, fullTask } from 'src/app/models/dailyworktask.model'; import { customTask, fullTask } from 'src/app/models/dailyworktask.model';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { ThemeService } from 'src/app/services/theme.service' import { ThemeService } from 'src/app/services/theme.service'
import { Location } from '@angular/common' import { Location } from '@angular/common'
import { RouteService } from 'src/app/services/route.service'; import { RouteService } from 'src/app/services/route.service';
@@ -9,7 +9,7 @@ import { BookMeetingModalPage } from 'src/app/pages/gabinete-digital/expediente/
import { DiscartExpedientModalPage } from 'src/app/pages/gabinete-digital/discart-expedient-modal/discart-expedient-modal.page'; import { DiscartExpedientModalPage } from 'src/app/pages/gabinete-digital/discart-expedient-modal/discart-expedient-modal.page';
import { ToastService } from 'src/app/services/toast.service'; import { ToastService } from 'src/app/services/toast.service';
import { Location } from '@angular/common' import { Location } from '@angular/common'
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { ThemeService } from 'src/app/services/theme.service' import { ThemeService } from 'src/app/services/theme.service'
import { RouteService } from 'src/app/services/route.service'; import { RouteService } from 'src/app/services/route.service';
@@ -7,7 +7,7 @@ import { ToastService } from 'src/app/services/toast.service';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { TaskService } from 'src/app/Rules/task.service' import { TaskService } from 'src/app/Rules/task.service'
import { ExpedienteService } from 'src/app/Rules/expediente.service'; import { ExpedienteService } from 'src/app/Rules/expediente.service';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
@Component({ @Component({
selector: 'app-event-details-documents-options', selector: 'app-event-details-documents-options',
@@ -15,7 +15,7 @@ import { ToastService } from 'src/app/services/toast.service';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { TaskService } from 'src/app/Rules/task.service' import { TaskService } from 'src/app/Rules/task.service'
import { ExpedienteService } from 'src/app/Rules/expediente.service'; import { ExpedienteService } from 'src/app/Rules/expediente.service';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { ThemeService } from 'src/app/services/theme.service' import { ThemeService } from 'src/app/services/theme.service'
import { NewGroupPage } from 'src/app/pages/chat/new-group/new-group.page'; import { NewGroupPage } from 'src/app/pages/chat/new-group/new-group.page';
import { RouteService } from 'src/app/services/route.service'; import { RouteService } from 'src/app/services/route.service';
@@ -9,7 +9,7 @@ import { BookMeetingModalPage } from 'src/app/pages/gabinete-digital/expediente/
import { ProcessesService } from 'src/app/services/processes.service'; import { ProcessesService } from 'src/app/services/processes.service';
import { ToastService } from 'src/app/services/toast.service'; import { ToastService } from 'src/app/services/toast.service';
import { PedidoService } from 'src/app/Rules/pedido.service'; import { PedidoService } from 'src/app/Rules/pedido.service';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { DataService } from 'src/app/services/data.service'; import { DataService } from 'src/app/services/data.service';
import { NewGroupPage } from 'src/app/pages/chat/new-group/new-group.page'; import { NewGroupPage } from 'src/app/pages/chat/new-group/new-group.page';
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {PopoverController } from '@ionic/angular'; import {PopoverController } from '@ionic/angular';
import { PermissionService } from 'src/app/services/worker/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
@Component({ @Component({
selector: 'app-searched-document-options', selector: 'app-searched-document-options',
@@ -0,0 +1,18 @@
<svg width="55" height="55" viewBox="0 0 55 55" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_223_29)">
<path d="M49.5 27.5C49.5 39.6503 39.6503 49.5 27.5 49.5C15.3497 49.5 5.5 39.6503 5.5 27.5C5.5 15.3497 15.3497 5.5 27.5 5.5C39.6503 5.5 49.5 15.3497 49.5 27.5Z" stroke="#797979"/>
</g>
<path d="M49.5 27.5C49.5 39.6503 39.6503 49.5 27.5 49.5C15.3497 49.5 5.5 39.6503 5.5 27.5C5.5 15.3497 15.3497 5.5 27.5 5.5C39.6503 5.5 49.5 15.3497 49.5 27.5Z" stroke="#797979"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.4327 31.208H20.3764C20.6649 31.208 20.9402 31.3245 21.1401 31.532L23.3285 33.7963C23.5285 34.0028 23.8037 34.1198 24.0923 34.1198H31.0456C31.3336 34.1198 31.6094 34.0033 31.8094 33.7963L33.9972 31.532C34.1972 31.325 34.473 31.208 34.7609 31.208H37.5879C38.1734 31.208 38.6487 31.6818 38.6487 32.2668V35.9727C38.6487 36.5577 38.1734 37.0315 37.5879 37.0315H17.4333C16.8472 37.0315 16.3725 36.5577 16.3725 35.9727V32.2668C16.3725 31.6818 16.8472 31.208 17.4333 31.208H17.4327ZM29.6316 19.0358V26.1214L30.8186 26.087C31.1114 26.0785 31.3559 26.3094 31.3644 26.6011C31.3686 26.7609 31.3007 26.9134 31.1798 27.0177L27.5329 30.1471L23.8859 27.0834C23.6621 26.8949 23.6335 26.5608 23.8223 26.3369C23.9231 26.2172 24.0726 26.1484 24.2296 26.1489L25.3811 26.1526V19.0321C25.3811 18.4471 25.8563 17.9732 26.4419 17.9732H26.4445L28.5735 17.9769C29.1585 17.9785 29.6316 18.4518 29.6316 19.0358V19.0358Z" stroke="#797979" stroke-linejoin="round"/>
<defs>
<filter id="filter0_d_223_29" x="0" y="0" width="55" height="55" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="2.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_223_29"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_223_29" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,18 @@
<svg width="55" height="55" viewBox="0 0 55 55" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_223_29)">
<path d="M49.5 27.5C49.5 39.6503 39.6503 49.5 27.5 49.5C15.3497 49.5 5.5 39.6503 5.5 27.5C5.5 15.3497 15.3497 5.5 27.5 5.5C39.6503 5.5 49.5 15.3497 49.5 27.5Z" stroke="#797979"/>
</g>
<path d="M49.5 27.5C49.5 39.6503 39.6503 49.5 27.5 49.5C15.3497 49.5 5.5 39.6503 5.5 27.5C5.5 15.3497 15.3497 5.5 27.5 5.5C39.6503 5.5 49.5 15.3497 49.5 27.5Z" stroke="#797979"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.4327 31.208H20.3764C20.6649 31.208 20.9402 31.3245 21.1401 31.532L23.3285 33.7963C23.5285 34.0028 23.8037 34.1198 24.0923 34.1198H31.0456C31.3336 34.1198 31.6094 34.0033 31.8094 33.7963L33.9972 31.532C34.1972 31.325 34.473 31.208 34.7609 31.208H37.5879C38.1734 31.208 38.6487 31.6818 38.6487 32.2668V35.9727C38.6487 36.5577 38.1734 37.0315 37.5879 37.0315H17.4333C16.8472 37.0315 16.3725 36.5577 16.3725 35.9727V32.2668C16.3725 31.6818 16.8472 31.208 17.4333 31.208H17.4327ZM29.6316 19.0358V26.1214L30.8186 26.087C31.1114 26.0785 31.3559 26.3094 31.3644 26.6011C31.3686 26.7609 31.3007 26.9134 31.1798 27.0177L27.5329 30.1471L23.8859 27.0834C23.6621 26.8949 23.6335 26.5608 23.8223 26.3369C23.9231 26.2172 24.0726 26.1484 24.2296 26.1489L25.3811 26.1526V19.0321C25.3811 18.4471 25.8563 17.9732 26.4419 17.9732H26.4445L28.5735 17.9769C29.1585 17.9785 29.6316 18.4518 29.6316 19.0358V19.0358Z" stroke="#797979" stroke-linejoin="round"/>
<defs>
<filter id="filter0_d_223_29" x="0" y="0" width="55" height="55" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="2.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_223_29"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_223_29" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,33 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="173" height="178" viewBox="0 0 173 178">
<defs>
<ellipse id="37ng76i1qb" cx="42.422" cy="42.5" rx="42.422" ry="42.5"/>
<filter id="7z30ci9zua" width="117.7%" height="117.6%" x="-8.8%" y="-8.8%" filterUnits="objectBoundingBox">
<feOffset in="SourceAlpha" result="shadowOffsetOuter1"/>
<feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="2.5"/>
<feColorMatrix in="shadowBlurOuter1" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
</filter>
</defs>
<g fill="none" fill-rule="evenodd">
<g>
<g>
<path fill="#42B9FE" fill-opacity=".3" d="M78.031 168c48.523 0 113.902-43.009 86.32-95.233C136.77 20.542 136.033 7 93.437 7 50.841 7 .905 28.222.905 90.687.905 153.152 29.508 168 78.03 168z" transform="translate(-661 -387) translate(661 387)"/>
<g>
<g transform="translate(-661 -387) translate(661 387) translate(1.905) rotate(-15 97.339 11.047)">
<rect width="89.361" height="112.826" x=".165" y="5.209" fill="#0782C9" fill-opacity=".5" rx="2"/>
<rect width="89.361" height="112.826" x="4.716" y=".233" fill="#FFF" stroke="#0782C9" stroke-linejoin="round" stroke-width="2" rx="2"/>
<rect width="52.804" height="4.964" x="24.04" y="32.43" fill="#0782C9" rx="2.482"/>
<rect width="52.804" height="4.964" x="26.63" y="53.977" fill="#0782C9" rx="2.482"/>
<rect width="36.557" height="4.964" x="24.523" y="76.287" fill="#0782C9" rx="2.482"/>
</g>
<g>
<g transform="translate(-661 -387) translate(661 387) translate(1.905) translate(80.654 88.496)">
<use fill="#000" filter="url(#7z30ci9zua)" xlink:href="#37ng76i1qb"/>
<use fill="#42B9FE" xlink:href="#37ng76i1qb"/>
</g>
<path stroke="#FFF" stroke-linejoin="round" stroke-width="2" d="M23.441 49.504h5.55c.544 0 1.063.22 1.44.612l4.126 4.277c.377.39.896.611 1.44.611h13.11c.543 0 1.063-.22 1.44-.611l4.125-4.277c.377-.391.897-.612 1.44-.612h5.33c1.104 0 2 .895 2 2v7c0 1.105-.896 2-2 2h-38c-1.105 0-2-.895-2-2v-7c0-1.105.895-2 2-2zM46.441 26.512v13.384h0l2.238-.065c.552-.016 1.013.42 1.029.971.008.302-.12.59-.348.787L42.484 47.5h0l-6.876-5.787c-.422-.356-.476-.987-.12-1.41.19-.226.472-.356.768-.355l2.171.007h0v-13.45c0-1.105.896-2 2-2h.005l4.014.007c1.103.003 1.995.897 1.995 2z" transform="translate(-661 -387) translate(661 387) translate(1.905) translate(80.654 88.496)"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

+4 -1
View File
@@ -1,8 +1,11 @@
export const environment = { export const environment = {
production: true,
apiURL: 'https://gabinetedigital.dyndns.info/GabineteDigital.Services/V5/api/', apiURL: 'https://gabinetedigital.dyndns.info/GabineteDigital.Services/V5/api/',
apiChatUrl: 'https://gabinetedigitalchat.dyndns.info/api/v1/', apiChatUrl: 'https://gabinetedigitalchat.dyndns.info/api/v1/',
apiWsChatUrl: 'wss://gabinetedigitalchat.dyndns.info/websocket', apiWsChatUrl: 'wss://gabinetedigitalchat.dyndns.info/websocket',
//apiChatUrl: 'https://www.tabularium.pt/api/v1/',
production: true,
domain: 'gabinetedigital.local', domain: 'gabinetedigital.local',
defaultuser: '',//paulo.pinto paulo.pinto@gabinetedigital.local defaultuser: '',//paulo.pinto paulo.pinto@gabinetedigital.local
defaultuserpwd: '', //tabteste@006, defaultuserpwd: '', //tabteste@006,
+10 -2
View File
@@ -1148,9 +1148,16 @@ ngx-mat-datetime-content{
} }
} }
.audio-contentainer{ .audio-contentainer{
width: 200px !important; min-width: 200px !important;
display: flex; display: flex;
overflow: auto !important; overflow: auto !important;
.icon-download{
font-size:35px !important;
}
.item-prior-download{
--background:#000000e7;
}
} }
.title{ .title{
@@ -1190,7 +1197,8 @@ ngx-mat-datetime-content{
} }
.add-attachment-bg-color{ .add-attachment-bg-color{
background-color: #42b9fe13; background-color: #42b9fe13 !important;
--background: #42b9fe0a !important;
} }
.message-attachments{ .message-attachments{