mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-19 21:06:06 +00:00
merge chat
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ChatPage } from './chat.page';
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ChatPage,
|
||||
},
|
||||
{
|
||||
path: 'new-group',
|
||||
loadChildren: () => import('./modal/new-group/new-group.module').then( m => m.NewGroupPageModule)
|
||||
},
|
||||
{
|
||||
path: 'group-messages',
|
||||
loadChildren: () => import('./modal/group-messages/group-messages.module').then( m => m.GroupMessagesPageModule)
|
||||
},
|
||||
{
|
||||
path: 'messages',
|
||||
outlet:'message',
|
||||
loadChildren: () => import('./modal/messages/messages.module').then( m => m.MessagesPageModule)
|
||||
},
|
||||
{
|
||||
path: 'edit-group',
|
||||
loadChildren: () => import('./modal/edit-group/edit-group.module').then( m => m.EditGroupPageModule)
|
||||
},
|
||||
{
|
||||
path: 'chat-options-popover',
|
||||
loadChildren:() => import('./modal/chat-options-popover/chat-options-popover.module').then( m => m.ChatOptionsPopoverPageModule)
|
||||
},
|
||||
{
|
||||
path: 'chat-debugging',
|
||||
loadChildren: () => import('./modal/chat-debugging/chat-debugging.module').then( m => m.ChatDebuggingPageModule)
|
||||
},
|
||||
{
|
||||
path: 'chat-message-debugging',
|
||||
loadChildren: () => import('./modal/chat-message-debugging/chat-message-debugging.module').then( m => m.ChatMessageDebuggingPageModule)
|
||||
},
|
||||
{
|
||||
path: 'empty-chat',
|
||||
loadChildren: () => import('./component/empty-chat/empty-chat.module').then( m => m.EmptyChatPageModule)
|
||||
},
|
||||
{
|
||||
path: 'edit-group',
|
||||
loadChildren: () => import('./component/edit-group/edit-group.module').then( m => m.EditGroupPageModule)
|
||||
},
|
||||
{
|
||||
path: 'set-room-owner',
|
||||
loadChildren: () => import('./modal/set-room-owner/set-room-owner.module').then( m => m.SetRoomOwnerPageModule)
|
||||
},
|
||||
{
|
||||
path: 'contacts',
|
||||
loadChildren: () => import('./component/contacts/contacts.module').then( m => m.ContactsPageModule)
|
||||
},
|
||||
{
|
||||
path: 'view-onces',
|
||||
loadChildren: () => import('./modal/view-onces/view-onces.module').then( m => m.ViewOncesPageModule)
|
||||
},
|
||||
{
|
||||
path: 'room-info',
|
||||
loadChildren: () => import('./modal/room-info/room-info.module').then( m => m.RoomInfoPageModule)
|
||||
},
|
||||
{
|
||||
path: 'edit-message',
|
||||
loadChildren: () => import('./modal/edit-message/edit-message.module').then( m => m.EditMessagePageModule)
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ChatPageRoutingModule {}
|
||||
@@ -0,0 +1,56 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatPageRoutingModule } from './chat-routing.module';
|
||||
|
||||
import { ChatPage } from './chat.page';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { PipesModule } from 'src/app/pipes/pipes.module';
|
||||
import { NewEventPageModule } from 'src/app/shared/agenda/new-event/new-event.module';
|
||||
import { AttendeeModalPageModule } from 'src/app/shared/event/attendee-modal/attendee-modal.module';
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||
import { ImageCropperModule } from 'ngx-image-cropper';
|
||||
import { EmptyChatPageModule } from './component/empty-chat/empty-chat.module';
|
||||
import { EditGroupPageModule } from './component/edit-group/edit-group.module';
|
||||
import { GroupContactsPageModule } from './component/group-messages/group-contacts/group-contacts.module';
|
||||
import { GroupMessagesPageModule } from './component/group-messages/group-messages.module';
|
||||
import { MessagesPageModule } from './component/messages/messages.module';
|
||||
import { ContactsPageModule } from './component/contacts/contacts.module';
|
||||
import { NewGroupPageModule } from './component/new-group/new-group.module';
|
||||
import { ChatModule } from 'src/app/module/chat/chat.module';
|
||||
import { IBoldLocalRepository } from 'src/app/core/chat/repository/bold/bold-local-repository';
|
||||
import { BoldLocalRepository } from 'src/app/module/chat/data/repository/bold/bold-local-repository';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
FontAwesomeModule,
|
||||
PipesModule,
|
||||
ChatPageRoutingModule,
|
||||
RouterModule,
|
||||
MessagesPageModule,
|
||||
ContactsPageModule,
|
||||
GroupMessagesPageModule,
|
||||
NewGroupPageModule,
|
||||
EditGroupPageModule,
|
||||
GroupContactsPageModule,
|
||||
EmptyChatPageModule,
|
||||
NewEventPageModule,
|
||||
ImageCropperModule,
|
||||
AttendeeModalPageModule
|
||||
],
|
||||
providers: [
|
||||
|
||||
],
|
||||
declarations: [
|
||||
ChatPage
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
entryComponents: []
|
||||
})
|
||||
export class ChatPageModule {}
|
||||
@@ -0,0 +1,191 @@
|
||||
<ion-content class="height-100 container-wrapper">
|
||||
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
|
||||
|
||||
<ion-refresher-content>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<div class="main-content d-flex height-100 border-t-radius viewport-font-size">
|
||||
<!-- Aside left -->
|
||||
<div class="aside-wrapper d-flex flex-column flex-grow-1">
|
||||
<!-- <p class="text-center mt-0 aside-title px-20">Chat</p> -->
|
||||
<!-- <ion-progress-bar type="indeterminate" ></ion-progress-bar> -->
|
||||
<div class="title-content">
|
||||
<div class="div-title">
|
||||
<ion-label class="title font-25-em">Chat</ion-label>
|
||||
</div>
|
||||
<div class="div-icon">
|
||||
|
||||
<button title="Nova Conversa Individual" class="btn-no-color" (click)="openContactsPage()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src="assets/images/icons-chat-new-conversation.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src="assets/images/theme/gov/icons-chat-new-conversation.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="end" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-chat-new-conversation.svg"></ion-icon>
|
||||
</button>
|
||||
<button id="cy-create-group" title="Novo Grupo" class="btn-no-color" (click)="openNewGroupPage()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src="assets/images/icons-chat-new-group.svg" ></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src="assets/images/theme/gov/icons-chat-new-group.svg" ></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="end" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-chat-new-group.svg" ></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ion-toolbar [class.block-button]="showNewEvent || showNewGroup || showContacts">
|
||||
<ion-segment [(ngModel)]="segment">
|
||||
<ion-segment-button value="{{RoomType.Direct}}" class="font-14-em">
|
||||
Conversas
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="{{RoomType.Group}}" class="font-14-em">
|
||||
Grupos
|
||||
</ion-segment-button>
|
||||
</ion-segment>
|
||||
</ion-toolbar>
|
||||
<div class=" aside overflow-y-auto d-flex flex-wrap flex-grow-1">
|
||||
<div class="width-100">
|
||||
<div class="item item-hover width-100 d-flex ion-no-padding ion-no-margin"
|
||||
*ngFor="let room of rooms"
|
||||
[class.item-active]="room.id == idSelected" [class.hide-room]="room.roomType != segment">
|
||||
<div class="item-icon">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' && room.id != idSelected && room.roomType == RoomType.Group " class="icon" slot="start" src="assets/images/theme/gov/icons-chat-chat-40.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' && room.id == idSelected && room.roomType == RoomType.Group" class="icon" slot="start" src="assets/images/theme/gov/icons-chat-chat-40-hover.svg"></ion-icon>
|
||||
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' && room.roomType == RoomType.Direct" class="icon" slot="start" src="assets/images/icons-chat-group-chat-40.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' && room.id != idSelected && room.roomType == RoomType.Direct" class="icon" slot="start" src="assets/images/theme/gov/icons-chat-group-chat-40.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' && room.id == idSelected && room.roomType == RoomType.Direct" class="icon" slot="start" src="assets/images/theme/gov/icons-chat-group-chat-40-hover.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' && room.id != idSelected && room.roomType == RoomType.Direct" class="icon" slot="start" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-chat-group-chat-40.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' && room.id == idSelected && room.roomType == RoomType.Direct" class="icon" slot="start" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-chat-group-chat-40-hover.svg"></ion-icon>
|
||||
</div>
|
||||
<div
|
||||
(click)="openMessagesPage(room.id)" class="item-content flex-grow-1 cursor-pointer"><!-- (click)="openMessages(dm)" -->
|
||||
<div class="item-title-time">
|
||||
<div class="item-title add-ellipsis" [class.item-title-active]="room.id == idSelected">
|
||||
<ion-label >
|
||||
<span >
|
||||
<div >
|
||||
<div class="font-15-em add-ellipsis" [class.bold-message]="boldTable?.[room.id]?.bold">
|
||||
{{room.roomName}}
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</ion-label>
|
||||
</div>
|
||||
<div class="item-date font-13-em" [class.item-date-active]="room.id == idSelected">
|
||||
{{ room.displayDate }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-date font-13-em" [class.item-date-active]="room.id == idSelected">
|
||||
<!-- {{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : 'No expiration' }} -->
|
||||
{{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : '' }}
|
||||
</div>
|
||||
<div *ngIf="room?.messages?.length >= 1 && room.messages[0].isDeleted!=true" class="item-description d-flex align-items-center" [class.item-description-active]="room.id ==idSelected">
|
||||
<!-- -->
|
||||
<!-- <div *ngIf="room?.messages?.[0]?.message" class="item-description d-flex align-items-center" [class.item-description-active]="room.id ==idSelected"> -->
|
||||
<!-- <div class="item-message" *ngIf="group.otherUserType == false">{{room?.messages?.[0]?.message.u.name}}: {{room?.messages?.[0]?.message.msg}} </div> -->
|
||||
<div class="item-message font-13-em add-ellipsis white-space-nowrap"> {{room.messages[0].message}} </div>
|
||||
<!-- <div *ngIf="group.otherUserType == true">{{group.userThatIsTyping}} está escrever ...</div> -->
|
||||
|
||||
<div class="item-files add-ellipsis" *ngIf="room.messages[0]?.attachments?.length >= 1">
|
||||
|
||||
<fa-icon *ngIf="room.lastMessageDocument" icon="file-alt" class="file-icon" [class.set-active-item-font-to-white]="room.id == idSelected"></fa-icon>
|
||||
<fa-icon *ngIf="room?.messages?.[0]?.attachments[0]?.mimeType == 'application/audio'" icon="file-audio" class="file-icon" [class.set-active-item-font-to-white]="room.id == idSelected"></fa-icon>
|
||||
<span *ngIf="room?.messages?.[0]?.attachments[0]?.mimeType == 'application/audio'" class="item-files-title"> audio </span>
|
||||
<fa-icon *ngIf="room?.messages?.[0]?.attachments[0]?.mimeType == 'application/meeting'" icon="calendar-alt" class="file-icon" [class.set-active-item-font-to-white]="room.id == idSelected"></fa-icon>
|
||||
<fa-icon *ngIf="room.lastMessageImage" icon="image"></fa-icon>
|
||||
<span class="pl-2 font-13-em add-ellipsis">{{ room.messages[0].attachments[0].description }}</span>
|
||||
</div>
|
||||
|
||||
<!-- <div class="item-files" *ngIf="room.attachments">
|
||||
<div *ngIf="room.value.lastMessage.attachments[0].image_url">
|
||||
<fa-icon icon="image" class="file-icon" [class.set-active-item-font-to-white]="room.id == idSelected"></fa-icon>
|
||||
<span> Fotografia</span>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div *ngIf="room?.messages?.length >= 1 && room.messages[0].isDeleted==true">
|
||||
<div class="item-message font-13-em add-ellipsis white-space-nowrap"> Mensagem foi eliminada </div>
|
||||
</div>
|
||||
<!-- -->
|
||||
|
||||
<!-- <div class="item-message font-13-em add-ellipsis white-space-nowrap" *ngIf="room.otherUserType == false"> {{room.messages[0].message}} </div> -->
|
||||
<!-- <div class="font-13-em" *ngIf="room.otherUserType == true">está escrever ...</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="width-100" [ngSwitch]="segment">
|
||||
|
||||
</div>
|
||||
|
||||
<!-- <button (click)="sendMsg()" style="height: 41px;">Send message</button> -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- Aside right -->
|
||||
<div class="aside-content d-none flex-column height-100">
|
||||
|
||||
<app-empty-chat [texto]="emptyTextDescription"
|
||||
class="height-100 flex-column"
|
||||
[style.display]="showEmptyComponent && !showContacts && !showNewGroup && !showEditGroup && !showGroupContacts && !showGroupMessages && !showNewEvent ? 'flex' : 'none'"
|
||||
#messagecontainer>
|
||||
</app-empty-chat>
|
||||
|
||||
<app-messages class=" height-100 flex-column"
|
||||
[room]="RoomSelected"
|
||||
*ngIf="showMessages"
|
||||
[style.display]="showMessages ? 'flex' : 'none'"
|
||||
(closeAllDesktopComponents)="closeAllDesktopComponents()"
|
||||
(showEmptyContainer)="showEmptyContainer()"
|
||||
(showEmptyContainer)="showEmptyContainer()"
|
||||
|
||||
(openGroupContacts)="openGroupContactsPage($event)"
|
||||
(openEditGroupPage)="openEditGroupPage($event)"
|
||||
|
||||
[style.display]="showMessages ? 'flex' : 'none'"
|
||||
[roomId]="roomId"
|
||||
[showMessages]="showMessages" #messagecontainer>
|
||||
|
||||
</app-messages>
|
||||
|
||||
<app-contacts
|
||||
(openMessage)="openMessagesPage($event)"
|
||||
(backToChat)="backToChat($event)"
|
||||
(emptyTextDescriptionOpen)="emptyTextDescriptionOpen()"
|
||||
(closeAllDesktopComponents)="closeAllDesktopComponents()"
|
||||
*ngIf="showContacts"
|
||||
[roomId]="roomId"
|
||||
[style.display]="showContacts ? 'flex' : 'none'"
|
||||
class=" height-100 flex-column">
|
||||
</app-contacts>
|
||||
|
||||
<app-new-group
|
||||
(addGroupMessage)="openGroupContactsPage($event)"
|
||||
[roomId]="roomId"
|
||||
(backToChat)="backToChat($event)"
|
||||
(closeAllDesktopComponents)="closeAllDesktopComponents()"
|
||||
(openGroupContacts)="openGroupContactsPage($event)"
|
||||
(openEditGroupPage)="openEditGroupPage($event)"
|
||||
|
||||
|
||||
*ngIf="showNewGroup"
|
||||
class=" height-100 flex-column d-flex">
|
||||
|
||||
</app-new-group>
|
||||
|
||||
<app-edit-group [roomId]="roomId"
|
||||
(closeAllDesktopComponents)="closeAllDesktopComponents()"
|
||||
(openGroupMessage)="openMessagesPage($event)"
|
||||
*ngIf="showEditGroup"
|
||||
[style.display]="showEditGroup ? 'flex' : 'none'"
|
||||
class="height-100 flex-column">
|
||||
</app-edit-group>
|
||||
|
||||
<app-group-contacts
|
||||
(openGroupMessage)="openMessagesPage($event)"
|
||||
*ngIf="showGroupContacts"
|
||||
[style.display]="showGroupContacts ? 'flex' : 'none'"
|
||||
[roomId]="groupRoomId" class=" height-100 flex-column"
|
||||
(backToChat)="backToChat($event)"
|
||||
>
|
||||
</app-group-contacts>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,193 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
ion-content{
|
||||
--background: transparent;
|
||||
}
|
||||
:host{
|
||||
// background: #0782c9;
|
||||
}
|
||||
|
||||
.title-content{
|
||||
width: 100%;
|
||||
margin-bottom: 15px;
|
||||
padding: 0 !important;
|
||||
background: #fff;
|
||||
|
||||
.div-title{
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
}
|
||||
.div-icon{
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
float: right;
|
||||
font-size: em(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.main-content{
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
|
||||
overflow: auto;
|
||||
|
||||
.aside-wrapper{
|
||||
margin: 0 !important;
|
||||
overflow: auto;
|
||||
|
||||
.title-content{
|
||||
padding: 30px 20px 0 20px !important;
|
||||
}
|
||||
|
||||
.aside{
|
||||
padding: 0 !important;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.iconschatnew-group{
|
||||
width: rem(30);
|
||||
height: 30px;
|
||||
object-fit: contain;
|
||||
margin: 0 5px 0 5px;
|
||||
}
|
||||
.iconschatnew-conversation{
|
||||
width: rem(30);
|
||||
height: 30px;
|
||||
object-fit: contain;
|
||||
margin: 0 5px 0 5px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.item{
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
padding: 0px 20px 0 20px !important;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
|
||||
|
||||
.item-icon{
|
||||
width: em(40);
|
||||
float: left;
|
||||
|
||||
.icon{
|
||||
margin-top: 10px;
|
||||
font-size: em(40);
|
||||
}
|
||||
}
|
||||
.item-content{
|
||||
//width: 317px;
|
||||
float:right;
|
||||
width: 88%;
|
||||
}
|
||||
|
||||
.item-title-time{
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.item-title{
|
||||
float: left;
|
||||
color: var(--title-text-color);
|
||||
}
|
||||
.item-title-active{
|
||||
color: #fff;
|
||||
}
|
||||
.item-date{
|
||||
float: right;
|
||||
color: #797979;
|
||||
text-align: right;
|
||||
}
|
||||
.item-date-active{
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.item-description{
|
||||
color: #000;
|
||||
overflow: auto;
|
||||
|
||||
.item-message{
|
||||
float: left;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.item-files{
|
||||
float: left;
|
||||
overflow: auto;
|
||||
|
||||
.item-files-title{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-description-active{
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.item-active{
|
||||
color: #fff !important;
|
||||
background-color: var(--gabinete-active-hove-background) !important;
|
||||
}
|
||||
@media only screen and (min-width: 701px) {
|
||||
.main-content{
|
||||
|
||||
.aside-wrapper{
|
||||
width: 35%;
|
||||
border-right: 1px solid #d8d8d8;
|
||||
.aside-title{
|
||||
font-size: em(25);
|
||||
}
|
||||
}
|
||||
/* .aside{
|
||||
width: 340px;
|
||||
} */
|
||||
.aside-content{
|
||||
width: 65%;
|
||||
display: flex !important;
|
||||
background-color: white;
|
||||
}
|
||||
.item{
|
||||
.item-icon{
|
||||
width: 10%;
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
.item-content{
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: #fff !important;
|
||||
background-color: #42b9fe !important;
|
||||
}
|
||||
|
||||
|
||||
.bold-message {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.block-button {
|
||||
pointer-events: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.hide-room{
|
||||
display: none !important;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatPage } from './chat.page';
|
||||
|
||||
describe('ChatPage', () => {
|
||||
let component: ChatPage;
|
||||
let fixture: ComponentFixture<ChatPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChatPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ChatPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,512 @@
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { ModalController } from '@ionic/angular';
|
||||
import { GroupMessagesPage } from './modal/group-messages/group-messages.page';
|
||||
import { ContactsPage } from './modal/./messages/contacts/contacts.page';
|
||||
import { MessagesPage } from './modal/./messages/messages.page';
|
||||
import { NewGroupPage } from './modal/./new-group/new-group.page';
|
||||
import { Observable, Subject } from "rxjs/Rx";
|
||||
import { Router, NavigationEnd } from '@angular/router';
|
||||
import { TimeService } from 'src/app/services/functions/time.service';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
import { DataService } from 'src/app/services/data.service';
|
||||
import { RouteService } from 'src/app/services/route.service';
|
||||
import { EditGroupPage } from './modal/edit-group/edit-group.page';
|
||||
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service'
|
||||
import { RoomLocalRepository } from 'src/app/module/chat/data/repository/room/room-local-repository.service'
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { BehaviorSubject, interval, Subscription } from 'rxjs';
|
||||
import { RoomTable } from 'src/app/infra/database/dexie/instance/chat/schema/room';
|
||||
import { RoomType } from 'src/app/core/chat/entity/group';
|
||||
import { BoldLocalRepository } from 'src/app/module/chat/data/repository/bold/bold-local-repository'
|
||||
import { BoldTable } from 'src/app/infra/database/dexie/instance/chat/schema/bold';
|
||||
import { RoomViewModel } from './store/model/room';
|
||||
import { MessageLocalDataSourceService } from 'src/app/module/chat/data/repository/message/message-local-data-source.service'
|
||||
@Component({
|
||||
selector: 'app-chat',
|
||||
templateUrl: './chat.page.html',
|
||||
styleUrls: ['./chat.page.scss'],
|
||||
})
|
||||
export class ChatPage implements OnInit {
|
||||
|
||||
showLoader: boolean;
|
||||
segment: RoomType = RoomType.Direct
|
||||
idSelected: string;
|
||||
|
||||
roomId: any;
|
||||
groupRoomId: any;
|
||||
showEmptyComponent = true;
|
||||
showMessages = false;
|
||||
showContacts = false;
|
||||
showNewGroup = false;
|
||||
showEditGroup = false;
|
||||
showGroupMessages = false;
|
||||
showGroupContacts = false;
|
||||
showNewEvent = false;
|
||||
showAttendees = false;
|
||||
emptyTextDescription = 'Sem conversa selecionada';
|
||||
|
||||
subject: any;
|
||||
public messages: Subject<any>;
|
||||
hideRefreshBtn = true;
|
||||
|
||||
routerSubscription
|
||||
|
||||
// count$: Observable<RoomRemoteDataSourceState>;
|
||||
//items$!: DexieObservable<RoomTable[]>;
|
||||
items$!: Observable<RoomTable[]>;
|
||||
rooms: RoomViewModel[] = [];
|
||||
private subscription: Subscription;
|
||||
expirationDate = {}
|
||||
private intervalSubscription: Subscription;
|
||||
|
||||
RoomType = RoomType
|
||||
|
||||
boldTable: {[key: string]: BoldTable} = {}
|
||||
private roomListSubject = new BehaviorSubject<{ id: string, name: string }[]>([]);
|
||||
roomsWithLastMessages: { name: string, lastMessage: any }[] = [];
|
||||
private subscription1: Subscription;
|
||||
|
||||
RoomSelected!: RoomViewModel;
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
private timeService: TimeService,
|
||||
public ThemeService: ThemeService,
|
||||
private dataService: DataService,
|
||||
private router: Router,
|
||||
public RouteService: RouteService,
|
||||
private ChatServiceService: ChatServiceService,
|
||||
private roomLocalDataSourceService: RoomLocalRepository,
|
||||
private boldLocalRepository: BoldLocalRepository,
|
||||
private MessageLocalDataSourceService: MessageLocalDataSourceService
|
||||
) {
|
||||
|
||||
window.onresize = (event) => {
|
||||
if (window.innerWidth > 701) {
|
||||
this.modalController.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
this.showLoader = true;
|
||||
|
||||
this.boldLocalRepository.listen().subscribe((data) => {
|
||||
const distributionObject: {[key: string]: BoldTable} = {};
|
||||
|
||||
for (const distribution of data) {
|
||||
distributionObject[distribution.roomId] = distribution;
|
||||
}
|
||||
|
||||
this.boldTable = distributionObject
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
updatemessage(sortedRooms) {
|
||||
this.rooms = sortedRooms
|
||||
|
||||
this.rooms.sort((a, b) =>
|
||||
new Date(b.messages?.[0]?.sentAt as string).getTime() -
|
||||
new Date(a.messages?.[0]?.sentAt as string).getTime()
|
||||
);
|
||||
|
||||
|
||||
// this.RoomSelected = this.rooms.filter(e => e.id == this.idSelected)[0]
|
||||
}
|
||||
ngOnInit() {
|
||||
// this.subscription = this.roomListSubject.pipe(
|
||||
// switchMap(roomList =>
|
||||
// this.MessageLocalDataSourceService.getLastMessageForRooms(roomList.map(room => room.id))
|
||||
// )
|
||||
// ).subscribe(lastMessages => {
|
||||
// this.roomsWithLastMessages = this.roomListSubject.value.map(room => ({
|
||||
// name: room.name,
|
||||
// lastMessage: lastMessages.find(msg => msg.roomId === room.id)?.message || null
|
||||
// }));
|
||||
// this.roomsWithLastMessages.sort((a, b) =>
|
||||
// new Date(b.lastMessage.messages?.[0]?.sentAt as unknown as string) as unknown as number -
|
||||
// (new Date(a.lastMessage.messages?.[0]?.sentAt as unknown as string) as any) as unknown as number
|
||||
// )
|
||||
// });
|
||||
|
||||
// // Initialize room list (can be loaded from a service, API, etc.)
|
||||
// this.roomListSubject.next([
|
||||
// { id: '1135e73c-af8e-416c-a51f-1602b4770cf7', name: 'Room 1' }
|
||||
// // Add more rooms as needed
|
||||
// ]);
|
||||
|
||||
this.roomLocalDataSourceService.getItemsLive().pipe(
|
||||
map((roomList) => roomList.map((room)=> new RoomViewModel(room))),
|
||||
tap((roomList) => {
|
||||
|
||||
roomList.sort((a, b) =>
|
||||
new Date(b.messages?.[0]?.sentAt as string).getTime() -
|
||||
new Date(a.messages?.[0]?.sentAt as string).getTime()
|
||||
);
|
||||
|
||||
console.log('update')
|
||||
|
||||
this.updatemessage(roomList)
|
||||
})
|
||||
).subscribe()
|
||||
|
||||
// Create the interval observable
|
||||
const interval$ = interval(1000).pipe(
|
||||
tap(() => {
|
||||
for (const room of this.rooms) {
|
||||
this.expirationDate[room.id] = this.getSecondsLeft(room.expirationDate);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Subscribe to the interval observable
|
||||
this.intervalSubscription = interval$.subscribe();
|
||||
|
||||
// this.ChatServiceService.getRoomList()
|
||||
|
||||
this.hideRefreshButton();
|
||||
|
||||
this.router.events.forEach((event) => {
|
||||
if (event instanceof NavigationEnd && event.url == '/home/chat' ||
|
||||
event instanceof NavigationEnd && event.url == "/home/chat?gbCreateGroup=true") {
|
||||
this.checkCreateGroup();
|
||||
}
|
||||
});
|
||||
|
||||
this.routerSubscription = this.router.events.subscribe((event) => {
|
||||
if (event instanceof NavigationEnd && event.url.startsWith('/home/chat')) {
|
||||
this.routeCheck()
|
||||
// this.ChatServiceService.getRoomList()
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
onSegmentChange() {}
|
||||
|
||||
getSecondsLeft(expirationDate: any): number | null {
|
||||
if (!expirationDate) return null;
|
||||
const now = new Date().getTime();
|
||||
const expTime = new Date(expirationDate).getTime();
|
||||
return Math.max(Math.floor((expTime - now) / 1000), 0);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
// this.setStatus('offline');
|
||||
this.routerSubscription?.unsubscribe();
|
||||
// Unsubscribe from the interval to prevent memory leaks
|
||||
this.intervalSubscription?.unsubscribe();
|
||||
}
|
||||
|
||||
|
||||
firstEnter = true
|
||||
|
||||
routeCheck() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const roomId = urlParams.get('roomId');
|
||||
|
||||
if (roomId) {
|
||||
|
||||
if (this.firstEnter) {
|
||||
this.firstEnter = false
|
||||
|
||||
let delay = this.RouteService.liveHistory.find((item) => {
|
||||
return ['/home/publications', '/home/agenda', '/home/gabinete', '/home/events'].filter(x => {
|
||||
return item.includes(x)
|
||||
}).length >= 1
|
||||
})
|
||||
if (!delay) {
|
||||
console.log("delay")
|
||||
setTimeout(() => {
|
||||
this.openChat(roomId)
|
||||
}, 2000)
|
||||
} else {
|
||||
console.log("no dalay")
|
||||
this.openChat(roomId)
|
||||
}
|
||||
} else {
|
||||
this.openChat(roomId)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
openFailed = 0
|
||||
openChat(roomId) {
|
||||
// const room = this.ChatSystemService.getRoomById(roomId);
|
||||
if (roomId) {
|
||||
//this.openFailed = 0
|
||||
//if (room.isGroup) {
|
||||
// this.segment = 'Grupos'
|
||||
// this.openGroupMessagesPage(roomId)
|
||||
//} else {
|
||||
// this.segment = 'Contactos'
|
||||
this.openMessagesPage(roomId)
|
||||
//}
|
||||
} else {
|
||||
if (this.openFailed <= 3) {
|
||||
this.openFailed++
|
||||
|
||||
setTimeout(() => {
|
||||
this.openChat(roomId)
|
||||
}, 1000)
|
||||
} else {
|
||||
this.openFailed = 0
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
checkCreateGroup() {
|
||||
if (this.dataService.get("newGroup")) {
|
||||
this.openNewGroupPage();
|
||||
}
|
||||
else {
|
||||
this.closeAllDesktopComponents();
|
||||
this.showEmptyComponent = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
numSequence(n: number): Array<number> {
|
||||
return Array(n);
|
||||
}
|
||||
|
||||
setStatus(status: string) {
|
||||
let body = {
|
||||
message: '',
|
||||
status: status,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
hideRefreshButton() {
|
||||
window.onresize = (event) => {
|
||||
if (window.innerWidth < 701) {
|
||||
this.idSelected = '';
|
||||
this.hideRefreshBtn = false;
|
||||
this.closeAllDesktopComponents()
|
||||
|
||||
// this.ChatSystemService.getRoomById(this.roomId)?.roomLeave()
|
||||
}
|
||||
else {
|
||||
this.hideRefreshBtn = true;
|
||||
if (this.idSelected == '') {
|
||||
this.showEmptyComponent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (window.innerWidth < 701) {
|
||||
this.idSelected = '';
|
||||
this.hideRefreshBtn = false;
|
||||
}
|
||||
}
|
||||
|
||||
closeAllDesktopComponents() {
|
||||
this.showMessages = false;
|
||||
this.showContacts = false;
|
||||
this.showNewGroup = false;
|
||||
this.showEditGroup = false;
|
||||
this.showGroupMessages = false;
|
||||
this.showEmptyComponent = false;
|
||||
this.showGroupContacts = false;
|
||||
this.showNewEvent = false;
|
||||
this.showAttendees = false;
|
||||
|
||||
}
|
||||
|
||||
showEmptyContainer() {
|
||||
this.idSelected = '';
|
||||
this.showEmptyComponent = true;
|
||||
}
|
||||
openGroupContactsPage(roomId) {
|
||||
this.idSelected = '';
|
||||
this.groupRoomId = roomId;
|
||||
this.RoomSelected = this.rooms.filter(e => e.id == roomId)[0]
|
||||
this.closeAllDesktopComponents();
|
||||
if (window.innerWidth < 701) {
|
||||
|
||||
}
|
||||
else {
|
||||
this.showGroupContacts = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
openMessagesPage(roomId) {
|
||||
// this.chatService.refreshtoken();
|
||||
this.roomId = roomId;
|
||||
this.RoomSelected = this.rooms.filter(e => e.id == roomId)[0]
|
||||
|
||||
if (window.innerWidth < 701) {
|
||||
this.openMessagesModal(roomId);
|
||||
}
|
||||
else {
|
||||
this.idSelected = roomId;
|
||||
this.closeAllDesktopComponents();
|
||||
this.showEmptyComponent = false;
|
||||
this.showMessages = true;
|
||||
}
|
||||
|
||||
}
|
||||
openContactsPage() {
|
||||
this.segment = RoomType.Direct;
|
||||
this.idSelected = '';
|
||||
this.closeAllDesktopComponents();
|
||||
|
||||
if (window.innerWidth < 701) {
|
||||
this.selectContact();
|
||||
}
|
||||
else {
|
||||
this.showEmptyComponent = false;
|
||||
this.showContacts = true;
|
||||
}
|
||||
}
|
||||
openNewGroupPage() {
|
||||
this.segment = RoomType.Group;
|
||||
|
||||
this.idSelected = '';
|
||||
if (window.innerWidth < 701) {
|
||||
this.newGroup();
|
||||
}
|
||||
else {
|
||||
this.closeAllDesktopComponents();
|
||||
this.showEmptyComponent = false;
|
||||
this.showNewGroup = true;
|
||||
}
|
||||
}
|
||||
|
||||
openEditGroupPage(rid) {
|
||||
if (window.innerWidth < 701) {
|
||||
this.editGroup(rid);
|
||||
}
|
||||
else {
|
||||
this.closeAllDesktopComponents();
|
||||
this.showEditGroup = true;
|
||||
}
|
||||
}
|
||||
|
||||
doRefresh(event) {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
event?.target?.complete();
|
||||
} catch (error) { }
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
showDateDuration(start: any) {
|
||||
return this.timeService.showDateDuration(start);
|
||||
}
|
||||
|
||||
countDownDate(date: any, roomId: string) {
|
||||
return this.timeService.countDownDate(date, roomId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
async emptyTextDescriptionOpen() {
|
||||
this.closeAllDesktopComponents()
|
||||
this.showEmptyComponent = true
|
||||
}
|
||||
|
||||
|
||||
async selectContact() {
|
||||
const modal = await this.modalController.create({
|
||||
component: ContactsPage,
|
||||
cssClass: 'modal modal-desktop',
|
||||
});
|
||||
|
||||
modal.onDidDismiss().then((Data) => {
|
||||
|
||||
// let data = Data.data
|
||||
// let roomId = data.roomId
|
||||
// this.openMessagesPage(roomId);
|
||||
|
||||
});
|
||||
|
||||
await modal.present();
|
||||
|
||||
}
|
||||
|
||||
async newGroup() {
|
||||
const modal = await this.modalController.create({
|
||||
component: NewGroupPage,
|
||||
cssClass: 'modal modal-desktop',
|
||||
});
|
||||
await modal.present();
|
||||
modal.onDidDismiss();
|
||||
}
|
||||
|
||||
async editGroup(roomId) {
|
||||
const modal = await this.modalController.create({
|
||||
component: EditGroupPage,
|
||||
cssClass: 'modal modal-desktop',
|
||||
componentProps: {
|
||||
roomId: roomId,
|
||||
},
|
||||
});
|
||||
|
||||
modal.onDidDismiss().then((res) => {
|
||||
|
||||
this.modalController.dismiss(res.data);
|
||||
});
|
||||
|
||||
await modal.present();
|
||||
}
|
||||
|
||||
async openMessagesModal(roomId: any) {
|
||||
this.closeAllDesktopComponents();
|
||||
|
||||
//
|
||||
|
||||
const modal = await this.modalController.create({
|
||||
component: MessagesPage,
|
||||
cssClass: 'modal modal-desktop isMessagesChatOpened',
|
||||
componentProps: {
|
||||
roomId: roomId,
|
||||
},
|
||||
});
|
||||
await modal.present();
|
||||
modal.onDidDismiss();
|
||||
}
|
||||
|
||||
|
||||
backToChat({ roomId }) {
|
||||
|
||||
//const room = this.ChatSystemService.getRoomById(roomId);
|
||||
|
||||
//if (room.isGroup) {
|
||||
// this.segment = "Grupos"
|
||||
// this.openGroupMessagesPage(room.id);
|
||||
//} else {
|
||||
// this.segment = RoomType.Direct
|
||||
this.openMessagesPage(roomId);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
async openGroupMessagesModal(roomId: any) {
|
||||
|
||||
const modal = await this.modalController.create({
|
||||
component: GroupMessagesPage,
|
||||
cssClass: 'modal modal-desktop isGroupChatOpened',
|
||||
componentProps: {
|
||||
roomId: roomId,
|
||||
},
|
||||
});
|
||||
|
||||
modal.onDidDismiss().then(() => {
|
||||
// this.ChatSystemService.currentRoom.roomLeave()
|
||||
});
|
||||
await modal.present();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ContactsPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ContactsPageRoutingModule {}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ContactsPageRoutingModule } from './contacts-routing.module';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
import { BtnSeguintePageModule } from 'src/app/shared/btn-seguinte/btn-seguinte.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ContactsPageRoutingModule,
|
||||
BtnSeguintePageModule,
|
||||
],
|
||||
declarations: [ContactsPage],
|
||||
exports: [ContactsPage]
|
||||
})
|
||||
export class ContactsPageModule {}
|
||||
@@ -0,0 +1,49 @@
|
||||
<ion-header class="ion-no-border">
|
||||
<ion-toolbar class="header-toolbar">
|
||||
<div class="main-header">
|
||||
<div class="title-content">
|
||||
<div class="back-icon cursor-pointer">
|
||||
<button class="btn-no-color" (click)="close(roomId)">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="div-title">
|
||||
<!-- Create direct message -->
|
||||
<ion-label class="title">Contactos</ion-label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar class="toolbar-search">
|
||||
<div class="search">
|
||||
<ion-searchbar search-icon="undefined" (ionChange)="onChange($event)" placeholder="Pesquisar por contacto" ></ion-searchbar>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
|
||||
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
|
||||
<ion-progress-bar type="indeterminate" *ngIf="loading"></ion-progress-bar>
|
||||
<ion-refresher-content>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<div class="main-content">
|
||||
<ion-progress-bar class="position-absolute" type="indeterminate" *ngIf="loading"></ion-progress-bar>
|
||||
<div *ngFor="let userContainer of userContainer | keyvalue;" >
|
||||
|
||||
<div class="item-divider">
|
||||
<ion-label>{{ userContainer.key }}</ion-label>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let user of userContainer.value; let i = index" class="d-flex px-20 align-center" (click)="select(user)">
|
||||
<ion-checkbox [(ngModel)]="user.isChecked" color="primary"></ion-checkbox>
|
||||
<ion-label class="flex-grow-1 px-10">{{user.wxFullName}}</ion-label>
|
||||
<div class="icon"><ion-icon name="ellipse"></ion-icon></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ion-content>
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header{
|
||||
width: 100%; /* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
border-top-left-radius: 25px;
|
||||
border-top-right-radius: 25px;
|
||||
background-color: #fff;
|
||||
overflow:hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.title-content{
|
||||
margin: 0px auto;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.back-icon{
|
||||
width: 37px;
|
||||
float: left;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
|
||||
}
|
||||
.div-title{
|
||||
width: 221px;
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
}
|
||||
.toolbar-search{
|
||||
--padding-top:0 !important;
|
||||
--padding-bottom:0 !important;
|
||||
--padding-start:0 !important;
|
||||
--padding-end:0 !important;
|
||||
|
||||
.search{
|
||||
border: 1px solid #ebebeb;
|
||||
margin: 5px 20px 5px 20px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.search ion-searchbar{
|
||||
/* border: 1px solid green; */
|
||||
width: 100%;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
--border-radius: 5px;
|
||||
--box-shadow: none;
|
||||
overflow: auto;
|
||||
--icon-color:#0d89d1;
|
||||
}
|
||||
|
||||
}
|
||||
ion-content{
|
||||
--background:transparent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.main-content{
|
||||
//width: 100%;
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
padding: 0 0 0 0;
|
||||
overflow:auto;
|
||||
|
||||
.members{
|
||||
padding: 15px 20px 0 20px !important;
|
||||
|
||||
.members-list{
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.members-label{
|
||||
//margin: 10px 20px 10px 20px !important;
|
||||
/* font-size: rem(15); */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.members-checkbox{
|
||||
display: flex;
|
||||
//margin: 0px 20px 0px 20px !important;
|
||||
overflow: auto;
|
||||
align-items: center;
|
||||
|
||||
.detele-item-icon{
|
||||
display: none;
|
||||
width: rem(30);
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.detele-item-icon ion-icon{
|
||||
font-size: rem(20) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.members-checkbox:hover{
|
||||
.detele-item-icon{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.item-divider{
|
||||
background: #ebebeb;
|
||||
font-size: rem(15);
|
||||
margin: 10px 0 10px 0;
|
||||
padding:5px 0 5px 20px;
|
||||
|
||||
}
|
||||
|
||||
.item-checkbox{
|
||||
display: flex;
|
||||
margin: 10px 20px 10px 20px !important;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.item-checkbox ion-checkbox, .members-checkbox ion-checkbox{
|
||||
--border-color: var(--title-text-color);
|
||||
--background-checked:var(--title-text-color);
|
||||
float: left;
|
||||
}
|
||||
|
||||
.item-checkbox ion-label, .members-checkbox p{
|
||||
padding-left: 10px;
|
||||
font-size: rem(15);
|
||||
color: var(--title-text-color);
|
||||
float: left;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.icon, .members-checkbox ion-icon{
|
||||
font-size: rem(10);
|
||||
}
|
||||
.online{
|
||||
color:#99e47b !important;
|
||||
}
|
||||
.offline{
|
||||
color:#cbced1 !important;
|
||||
}
|
||||
.away{
|
||||
color:#ffd21f !important;
|
||||
}
|
||||
.invisible{
|
||||
color:#cbced1 !important;
|
||||
}
|
||||
.busy{
|
||||
color:#f5455c !important;
|
||||
}
|
||||
}
|
||||
|
||||
.inactive {
|
||||
opacity: 0.7;
|
||||
button {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
|
||||
describe('ContactsPage', () => {
|
||||
let component: ContactsPage;
|
||||
let fixture: ComponentFixture<ContactsPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ContactsPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ContactsPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,183 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { ModalController } from '@ionic/angular';
|
||||
import { GroupMessagesPage } from '../group-messages/group-messages.page';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
import { UserContacts } from 'src/app/services/Repositorys/contacts/data-source/contacts-data-source.service';
|
||||
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
|
||||
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service';
|
||||
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { MessageEntity } from 'src/app/core/chat/entity/message';
|
||||
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service'
|
||||
import { RoomType } from "src/app/core/chat/entity/group";
|
||||
|
||||
@Component({
|
||||
selector: 'app-contacts',
|
||||
templateUrl: './contacts.page.html',
|
||||
styleUrls: ['./contacts.page.scss'],
|
||||
})
|
||||
export class ContactsPage implements OnInit {
|
||||
options:any;
|
||||
|
||||
loading = false
|
||||
userList: UserContacts[] = []
|
||||
currentMembers:UserContacts[];
|
||||
allChatUsers: UserContacts[] = [];
|
||||
userContainer: {[key: string]: ( UserContacts & {isChecked: boolean})[] } = {}
|
||||
|
||||
@Output() openMessage: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() emptyTextDescriptionOpen: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() backToChat: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() closeAllDesktopComponents: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
@Input() roomId: string;
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
public ThemeService: ThemeService,
|
||||
private contactsRepositoryService: ContactRepositoryService,
|
||||
private httpErrorHandle: HttpErrorHandle,
|
||||
private toastService: ToastService,
|
||||
private chatServiceService: ChatServiceService
|
||||
)
|
||||
{}
|
||||
|
||||
ngOnInit() {
|
||||
this.loadUsers();
|
||||
|
||||
}
|
||||
|
||||
async loadUsers() {
|
||||
|
||||
this.loading = true
|
||||
const getallChatUsers = await this.contactsRepositoryService.getUsers()
|
||||
|
||||
if(getallChatUsers.isOk()) {
|
||||
|
||||
this.allChatUsers = getallChatUsers.value.data.result.sort((a,b) => {
|
||||
if(a.wxFullName < b.wxFullName) {
|
||||
return -1;
|
||||
}
|
||||
if(a.wxFullName > b.wxFullName) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
|
||||
for(const user of this.allChatUsers) {
|
||||
const firstLetter = user.wxFullName.charAt(0)
|
||||
|
||||
if(!this.userContainer[firstLetter]) {
|
||||
user['isChecked'] = false
|
||||
this.userContainer[firstLetter] = [user as any]
|
||||
} else {
|
||||
const userIds = this.userContainer[firstLetter].map( e => e.wxUserId)
|
||||
if(!userIds.includes(user.wxUserId)) {
|
||||
user['isChecked'] = false
|
||||
this.userContainer[firstLetter].push(user as any)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (getallChatUsers.isErr() ) {
|
||||
console.log(getallChatUsers.error)
|
||||
} else {
|
||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||
}
|
||||
|
||||
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
separateLetter(record, recordIndex, records){
|
||||
|
||||
if(recordIndex == 0){
|
||||
return record.first[0];
|
||||
}
|
||||
|
||||
let first_prev = records[recordIndex - 1].first[0];
|
||||
let first_current = record.first[0];
|
||||
|
||||
if(first_prev != first_current){
|
||||
return first_current;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
doRefresh(event){
|
||||
|
||||
}
|
||||
close(roomId) {
|
||||
if (roomId) {
|
||||
this.backToChat.emit({ roomId: roomId });
|
||||
} else {
|
||||
this.closeAllDesktopComponents.emit();
|
||||
}
|
||||
}
|
||||
|
||||
onChange(event) {
|
||||
const textSearch = event.detail.value;
|
||||
|
||||
const filteredUserList: (UserContacts & {isChecked: boolean})[] = this.FilterUserListedByTextSearch(textSearch) as any
|
||||
|
||||
const userContainer = {}
|
||||
for(const user of filteredUserList) {
|
||||
const firstLetter = user.wxFullName.charAt(0)
|
||||
if(!userContainer[firstLetter]) {
|
||||
userContainer[firstLetter] = [user]
|
||||
} else {
|
||||
userContainer[firstLetter].push(user)
|
||||
}
|
||||
}
|
||||
this.userContainer = userContainer
|
||||
}
|
||||
|
||||
|
||||
FilterUserListedByTextSearch(textSearch: string) {
|
||||
return this.allChatUsers.filter( e => e.wxFullName.toLowerCase().includes(textSearch.toLowerCase())).sort((a,b) => {
|
||||
if(a.wxFullName < b.wxFullName) {
|
||||
return -1;
|
||||
}
|
||||
if(a.wxFullName > b.wxFullName) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
clicked() {}
|
||||
|
||||
|
||||
selectOnce = true
|
||||
async select(user: UserContacts) {
|
||||
|
||||
const message = new MessageEntity();
|
||||
|
||||
message.sender = {
|
||||
userPhoto: '',
|
||||
wxeMail: SessionStore.user.Email,
|
||||
wxFullName: SessionStore.user.FullName,
|
||||
wxUserId: SessionStore.user.UserId
|
||||
}
|
||||
|
||||
message.receiverId = user.wxUserId
|
||||
message.message = 'hello'
|
||||
|
||||
const result = await this.chatServiceService.sendMessage(message, RoomType.Direct)
|
||||
|
||||
|
||||
console.log('result', result);
|
||||
|
||||
if(result.isOk()) {
|
||||
await this.chatServiceService.getRoomById(result.value.roomId)
|
||||
this.close(result.value.roomId)
|
||||
} else {
|
||||
console.log(result.error)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { EditGroupPage } from './edit-group.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: EditGroupPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class EditGroupPageRoutingModule {}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { EditGroupPageRoutingModule } from './edit-group-routing.module';
|
||||
|
||||
import { EditGroupPage } from './edit-group.page';
|
||||
import { BtnSeguintePageModule } from 'src/app/shared/btn-seguinte/btn-seguinte.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
|
||||
EditGroupPageRoutingModule,
|
||||
BtnSeguintePageModule,
|
||||
],
|
||||
exports: [EditGroupPage],
|
||||
declarations: [EditGroupPage]
|
||||
})
|
||||
export class EditGroupPageModule {}
|
||||
@@ -0,0 +1,44 @@
|
||||
<ion-header class="ion-no-border">
|
||||
<ion-toolbar class="header-toolbar">
|
||||
<div class="main-header">
|
||||
<div class="title-content">
|
||||
<div class="left">
|
||||
<button class="btn-no-color" (click)="close()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " src="assets/images/theme/doneIt/icons-calendar-arrow-left.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/iassets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="middle">
|
||||
<ion-label class="title">Alterar assunto</ion-label>
|
||||
</div>
|
||||
<app-btn-seguinte (click)="changeGroupName()"></app-btn-seguinte>
|
||||
</div>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="width-100">
|
||||
<div class="main-content d-flex width-100">
|
||||
<div class="item-container d-flex flex-column width-100">
|
||||
<ion-input [(ngModel)]="groupName" placeholder="Título"></ion-input>
|
||||
</div>
|
||||
<div *ngIf="false" class="item-container-no-border">
|
||||
<ion-checkbox (ionChange)="_ionChange($event)" color="primary"></ion-checkbox>
|
||||
<ion-label>Grupo Ultra-secreto</ion-label>
|
||||
</div>
|
||||
|
||||
<div *ngIf="showDuration" class="container-div width-100">
|
||||
<div class="ion-item-class-2 width-100">
|
||||
<div class="ion-icon-class">
|
||||
<ion-icon slot="start" src="assets/images/icons-duration.svg"></ion-icon>
|
||||
</div>
|
||||
<div class="ion-input-class">
|
||||
<ion-input (click)="showPicker()" [(ngModel)]="displayDuration" placeholder="Duração"></ion-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,151 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
ion-content{
|
||||
--background:transparent;
|
||||
}
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
}
|
||||
.div-top-header{
|
||||
//width: 400px;
|
||||
margin: 0 auto;
|
||||
background-color: #0782c9;
|
||||
overflow: auto;
|
||||
padding-top: 15px;
|
||||
border: 0!important;
|
||||
|
||||
.div-search{
|
||||
font-size: rem(45);
|
||||
float: left;
|
||||
margin: 0 0 0 10px
|
||||
}
|
||||
.div-logo{
|
||||
background: transparent;
|
||||
width: 140px;
|
||||
margin: 5px 0 0px 71px;
|
||||
float: left;
|
||||
}
|
||||
.div-logo img{
|
||||
width: 100%;
|
||||
}
|
||||
.div-profile{
|
||||
font-size: rem(45);
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
.main-header{
|
||||
width: 100%; /* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
border-top-left-radius: 25px;
|
||||
border-top-right-radius: 25px;
|
||||
background-color: #fff;
|
||||
overflow:hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.title-content{
|
||||
//width: 360px;
|
||||
margin: 0px auto;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
background: #fff;
|
||||
|
||||
.left{
|
||||
width: 37px;
|
||||
float: left;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
}
|
||||
.middle{
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
width: 221px;
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.right{
|
||||
padding: 0!important;
|
||||
float: right;
|
||||
font-size: rem(15);
|
||||
color: #0782c9;
|
||||
margin: 8px 0 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
}
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
.main-content{
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
overflow:auto;
|
||||
padding: 15px 20px 0 20px;
|
||||
|
||||
.item-container{
|
||||
//width: 360px;
|
||||
margin: 15px auto;
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 5px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.item-container-no-border{
|
||||
display: flex;
|
||||
//width: 360px;
|
||||
margin: 25px auto;
|
||||
border-radius: 5px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-container-no-border ion-label{
|
||||
padding-left: 10px;
|
||||
font-size: rem(12);
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.container-div{
|
||||
margin-bottom: 15px;
|
||||
overflow: auto;
|
||||
|
||||
.ion-item-class-2{
|
||||
//width: 360px;
|
||||
margin: 0px auto;
|
||||
|
||||
.ion-icon-class{
|
||||
width: rem(45);
|
||||
height: rem(45);
|
||||
float: left;
|
||||
padding: 10px;
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
.ion-input-class{
|
||||
width: calc(100% - 45px);
|
||||
height: rem(45);
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 5px;
|
||||
padding-left: 5px;
|
||||
padding-right: 10px;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { EditGroupPage } from './edit-group.page';
|
||||
|
||||
describe('EditGroupPage', () => {
|
||||
let component: EditGroupPage;
|
||||
let fixture: ComponentFixture<EditGroupPage>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ EditGroupPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(EditGroupPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,219 @@
|
||||
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { ModalController, PickerController } from '@ionic/angular';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { HttpResponse } from '@microsoft/signalr';
|
||||
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { ZodError } from 'zod';
|
||||
|
||||
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-edit-group',
|
||||
templateUrl: './edit-group.page.html',
|
||||
styleUrls: ['./edit-group.page.scss'],
|
||||
})
|
||||
export class EditGroupPage implements OnInit {
|
||||
showLoader: boolean;
|
||||
displayDuration: any;
|
||||
showDuration: boolean;
|
||||
selectedDuration = ['','',''];
|
||||
groupName:string;
|
||||
room:any;
|
||||
loggedUser: any;
|
||||
@Input() roomId:string;
|
||||
@Output() openGroupContacts:EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() openGroupMessage:EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() closeAllDesktopComponents:EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
private pickerController: PickerController,
|
||||
public ThemeService: ThemeService,
|
||||
private httpErrorHandle: HttpErrorHandle,
|
||||
private toastService: ToastService,
|
||||
private chatServiceService: ChatServiceService,
|
||||
) {
|
||||
this.loggedUser = SessionStore.user.ChatData['data'];
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
// this.chatService.refreshtoken();
|
||||
this.getRoomInfo();
|
||||
}
|
||||
|
||||
getRoomInfo(){
|
||||
// this.chatService.getRoomInfo(this.roomId).subscribe(room=>{
|
||||
// this.room = room['room'];
|
||||
|
||||
// try {
|
||||
// this.groupName = this.room.name.split('-').join(' ');
|
||||
// } catch (error) {
|
||||
// this.groupName = this.room.name;
|
||||
// }
|
||||
|
||||
// });
|
||||
}
|
||||
|
||||
close() {
|
||||
//this.modalController.dismiss();
|
||||
this.closeAllDesktopComponents.emit();
|
||||
this.openGroupMessage.emit(this.roomId);
|
||||
}
|
||||
|
||||
async changeGroupName() {
|
||||
|
||||
this.showLoader = true
|
||||
const result = await this.chatServiceService.updateRoomById({
|
||||
roomId: this.roomId,
|
||||
roomName: this.groupName,
|
||||
roomType: 0
|
||||
})
|
||||
|
||||
if(result.isOk()) {
|
||||
this.openGroupMessage.emit(this.roomId);
|
||||
} else if (result.error instanceof HttpResponse) {
|
||||
this.httpErrorHandle.httpStatusHandle(result.error)
|
||||
} else if (result.error instanceof ZodError) {
|
||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||
console.log(result.error.errors)
|
||||
} else {
|
||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||
console.log(result.error)
|
||||
}
|
||||
|
||||
this.showLoader = false
|
||||
|
||||
}
|
||||
|
||||
updateGroup() {
|
||||
this.showLoader = true;
|
||||
// this.chatService.getRoomInfo(this.roomId).subscribe(room=>{
|
||||
// this.room = room['room'];
|
||||
// this.showLoader = false;
|
||||
// this.openGroupMessage.emit(this.room._id);
|
||||
// });
|
||||
}
|
||||
|
||||
_ionChange(event){
|
||||
this.showDuration = event.detail.checked;
|
||||
}
|
||||
async showPicker(){
|
||||
const picker = await this.pickerController.create({
|
||||
cssClass: '',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancelar', role: 'cancel', cssClass: 'btn-cancel'
|
||||
},
|
||||
{
|
||||
text: 'Ok',
|
||||
cssClass: 'btn-cancel',
|
||||
handler:(value:any)=>{
|
||||
|
||||
this.selectedDuration = [
|
||||
value.days.value,
|
||||
value.hours.value,
|
||||
value.minutes.value,
|
||||
]
|
||||
|
||||
if(value.days.value != null && value.hours.value != null && value.minutes.value != null){
|
||||
if(value.days.value > 0){
|
||||
if(value.days.value == 1){
|
||||
if(value.hours.value == 1){
|
||||
this.displayDuration = value.days.value + " day " +
|
||||
value.hours.value + " hora " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
else{
|
||||
this.displayDuration = value.days.value + " days " +
|
||||
value.hours.value + " horas " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(value.hours.value == 1){
|
||||
this.displayDuration = value.days.value + " days " +
|
||||
value.hours.value + " hora " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
else{
|
||||
this.displayDuration = value.days.value + " days " +
|
||||
value.hours.value + " horas " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(value.hours.value == 1){
|
||||
this.displayDuration = value.hours.value + " hora " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
else{
|
||||
this.displayDuration = value.hours.value + " horas " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
name: 'days',
|
||||
prefix: 'Dias',
|
||||
options: [
|
||||
{ text: '0', value: 0 },
|
||||
{ text: '1', value: 1 },
|
||||
{ text: '2', value: 2 },
|
||||
{ text: '3', value: 3 },
|
||||
{ text: '4', value: 4 },
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'hours',
|
||||
prefix: 'Horas',
|
||||
options: [
|
||||
{ text: '0', value: 0 },
|
||||
{ text: '1', value: 1 },
|
||||
{ text: '2', value: 2 },
|
||||
{ text: '3', value: 3 },
|
||||
{ text: '4', value: 4 },
|
||||
{ text: '5', value: 5 },
|
||||
{ text: '6', value: 6 },
|
||||
{ text: '7', value: 7 },
|
||||
{ text: '8', value: 8 },
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'minutes',
|
||||
prefix: 'Minutos',
|
||||
selectedIndex: 0,
|
||||
options: [
|
||||
{ text: '5', value: 5 },
|
||||
{ text: '10', value: 10 },
|
||||
{ text: '15', value: 15 },
|
||||
{ text: '20', value: 20 },
|
||||
{ text: '25', value: 25 },
|
||||
{ text: '30', value: 30 },
|
||||
{ text: '35', value: 35 },
|
||||
{ text: '45', value: 45 },
|
||||
{ text: '50', value: 50 },
|
||||
{ text: '55', value: 55 },
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
await picker.present();
|
||||
picker.onDidDismiss().then(async data =>{
|
||||
let day = await picker.getColumn('days');
|
||||
let hour = await picker.getColumn('hours');
|
||||
let minutes = await picker.getColumn('minutes');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { EmptyChatPage } from './empty-chat.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: EmptyChatPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class EmptyChatPageRoutingModule {}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { EmptyChatPageRoutingModule } from './empty-chat-routing.module';
|
||||
|
||||
import { EmptyChatPage } from './empty-chat.page';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
EmptyChatPageRoutingModule
|
||||
],
|
||||
exports: [EmptyChatPage],
|
||||
declarations: [EmptyChatPage]
|
||||
})
|
||||
export class EmptyChatPageModule {}
|
||||
@@ -0,0 +1,5 @@
|
||||
<ion-content>
|
||||
<div class="center height-100">
|
||||
<p>{{texto}}</p>
|
||||
</div>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,5 @@
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { EmptyChatPage } from './empty-chat.page';
|
||||
|
||||
describe('EmptyChatPage', () => {
|
||||
let component: EmptyChatPage;
|
||||
let fixture: ComponentFixture<EmptyChatPage>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ EmptyChatPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(EmptyChatPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-empty-chat',
|
||||
templateUrl: './empty-chat.page.html',
|
||||
styleUrls: ['./empty-chat.page.scss'],
|
||||
})
|
||||
export class EmptyChatPage implements OnInit {
|
||||
@Input() texto:string;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { GroupContactsPage } from './group-contacts.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: GroupContactsPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class GroupContactsPageRoutingModule {}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupContactsPageRoutingModule } from './group-contacts-routing.module';
|
||||
|
||||
import { GroupContactsPage } from './group-contacts.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
import { PipesModule } from 'src/app/pipes/pipes.module';
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
|
||||
GroupContactsPageRoutingModule,
|
||||
PipesModule,
|
||||
],
|
||||
exports: [GroupContactsPage],
|
||||
declarations: [GroupContactsPage]
|
||||
})
|
||||
export class GroupContactsPageModule {}
|
||||
@@ -0,0 +1,66 @@
|
||||
<ion-header class="ion-no-border">
|
||||
<ion-toolbar class="header-toolbar">
|
||||
<div class="main-header width-100">
|
||||
<div class="title-content width-100">
|
||||
<div class="back-icon cursor-pointer">
|
||||
<button title="Retroceder" class="btn-no-color" (click)="openGroupMessagesPage()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " src="assets/images/theme/doneIt/icons-calendar-arrow-left.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="div-title">
|
||||
<ion-label class="title">Contactos</ion-label>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn-no-color adicionar" (click)="updateGroup()">
|
||||
<ion-label>Adicionar</ion-label>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar class="toolbar-search">
|
||||
<div class="search">
|
||||
<ion-searchbar search-icon="undefined" debounce="500" (ionChange)="onChange($event)" placeholder="Pesquisar por contacto" ></ion-searchbar>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="width-100">
|
||||
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
|
||||
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
|
||||
<ion-refresher-content>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<div class="main-content width-100">
|
||||
<div class="members" *ngIf="currentMembers">
|
||||
<ion-label class="members-label">Contactos selecção:</ion-label>
|
||||
<ion-list class="members-list" *ngFor="let user of currentMembers">
|
||||
<div class="members-checkbox" [class.inactive]="SessionStore.user.UserName == user.username">
|
||||
<ion-checkbox disabled checked color="primary"></ion-checkbox>
|
||||
<p class="ma-0">{{user.wxFullName }}</p>
|
||||
<ion-icon name="ellipse"></ion-icon>
|
||||
<button (click)="deleteMember(user)" class="btn-no-color detele-item-icon">
|
||||
<ion-icon color="danger" name="close"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
</ion-list>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let userContainer of userContainer | keyvalue;" >
|
||||
|
||||
<div class="item-divider">
|
||||
<ion-label>{{ userContainer.key }}</ion-label>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let user of userContainer.value; let i = index" class="d-flex px-20 align-center">
|
||||
<ion-checkbox [(ngModel)]="user.isChecked" (ionChange)="onChangeCheckBox(user)" color="primary"></ion-checkbox>
|
||||
<ion-label class="flex-grow-1 px-10">{{user.wxFullName}}</ion-label>
|
||||
<div class="icon"><ion-icon name="ellipse"></ion-icon></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,184 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header{
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
background-color: #fff;
|
||||
overflow:hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.title-content{
|
||||
margin: 0px auto;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.back-icon{
|
||||
width: 37px;
|
||||
float: left;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
|
||||
}
|
||||
.div-title{
|
||||
width: 221px;
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.adicionar{
|
||||
padding: 0!important;
|
||||
float: right;
|
||||
font-size: rem(15);
|
||||
color: var(--font-awesome);
|
||||
margin: 8px 5px 0 5px;
|
||||
}
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
}
|
||||
.toolbar-search{
|
||||
--padding-top:0 !important;
|
||||
--padding-bottom:0 !important;
|
||||
--padding-start:0 !important;
|
||||
--padding-end:0 !important;
|
||||
|
||||
.search{
|
||||
border: 1px solid #ebebeb;
|
||||
margin: 5px 20px 5px 20px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.search ion-searchbar{
|
||||
width: 100%;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
--border-radius: 5px;
|
||||
--box-shadow: none;
|
||||
overflow: hidden;
|
||||
--icon-color:var(--font-awesome);
|
||||
}
|
||||
}
|
||||
|
||||
ion-content{
|
||||
--background:transparent;
|
||||
}
|
||||
|
||||
.main-content{
|
||||
//width: 100%;
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
padding: 0 0 0 0;
|
||||
overflow:auto;
|
||||
|
||||
.members{
|
||||
padding: 15px 20px 0 20px !important;
|
||||
|
||||
.members-list{
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.members-label{
|
||||
//margin: 10px 20px 10px 20px !important;
|
||||
/* font-size: rem(15); */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.members-checkbox{
|
||||
display: flex;
|
||||
//margin: 0px 20px 0px 20px !important;
|
||||
overflow: auto;
|
||||
align-items: center;
|
||||
|
||||
.detele-item-icon{
|
||||
display: none;
|
||||
width: rem(30);
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.detele-item-icon ion-icon{
|
||||
font-size: rem(20) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.members-checkbox:hover{
|
||||
.detele-item-icon{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.item-divider{
|
||||
background: #ebebeb;
|
||||
font-size: rem(15);
|
||||
margin: 10px 0 10px 0;
|
||||
padding:5px 0 5px 20px;
|
||||
|
||||
}
|
||||
|
||||
.item-checkbox{
|
||||
display: flex;
|
||||
margin: 10px 20px 10px 20px !important;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.item-checkbox ion-checkbox, .members-checkbox ion-checkbox{
|
||||
--border-color: var(--title-text-color);
|
||||
--background-checked:var(--title-text-color);
|
||||
float: left;
|
||||
}
|
||||
|
||||
.item-checkbox ion-label, .members-checkbox p{
|
||||
padding-left: 10px;
|
||||
font-size: rem(15);
|
||||
color: var(--title-text-color);
|
||||
float: left;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.icon, .members-checkbox ion-icon{
|
||||
font-size: rem(10);
|
||||
}
|
||||
.online{
|
||||
color:#99e47b !important;
|
||||
}
|
||||
.offline{
|
||||
color:#cbced1 !important;
|
||||
}
|
||||
.away{
|
||||
color:#ffd21f !important;
|
||||
}
|
||||
.invisible{
|
||||
color:#cbced1 !important;
|
||||
}
|
||||
.busy{
|
||||
color:#f5455c !important;
|
||||
}
|
||||
}
|
||||
|
||||
.inactive {
|
||||
opacity: 0.7;
|
||||
button {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupContactsPage } from './group-contacts.page';
|
||||
|
||||
describe('GroupContactsPage', () => {
|
||||
let component: GroupContactsPage;
|
||||
let fixture: ComponentFixture<GroupContactsPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ GroupContactsPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(GroupContactsPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,226 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
|
||||
import { UserContacts } from 'src/app/services/Repositorys/contacts/data-source/contacts-data-source.service';
|
||||
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { HttpRequest } from '@angular/common/http';
|
||||
import { ZodError } from 'zod';
|
||||
import { HttpResponse } from '@microsoft/signalr';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service';
|
||||
import { MemberListLocalRepository } from 'src/app/module/chat/data/repository/member/member-list-local-repository.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-group-contacts',
|
||||
templateUrl: './group-contacts.page.html',
|
||||
styleUrls: ['./group-contacts.page.scss'],
|
||||
})
|
||||
export class GroupContactsPage implements OnInit {
|
||||
|
||||
showLoader: boolean;
|
||||
textSearch:string;
|
||||
|
||||
@Input() roomId:string;
|
||||
@Output() openGroupMessage:EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() openGroupContacts:EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
currentMembers:UserContacts[];
|
||||
allChatUsers: UserContacts[] = [];
|
||||
userContainer: {[key: string]: ( UserContacts & {isChecked: boolean})[] } = {}
|
||||
|
||||
selectedUsers: number[] =[]
|
||||
SessionStore = SessionStore
|
||||
|
||||
constructor(
|
||||
public ThemeService: ThemeService,
|
||||
private contactsRepositoryService: ContactRepositoryService,
|
||||
private httpErrorHandle: HttpErrorHandle,
|
||||
private toastService: ToastService,
|
||||
private chatServiceService: ChatServiceService,
|
||||
private MemberListLocalRepository: MemberListLocalRepository,
|
||||
){}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadUsers()
|
||||
}
|
||||
|
||||
get hasMemberToUpload() {
|
||||
return this.selectedUsers.length >= 1
|
||||
}
|
||||
|
||||
async updateGroup() {
|
||||
|
||||
if(this.hasMemberToUpload) {
|
||||
this.showLoader = true;
|
||||
const addMembers = await this.chatServiceService.addMemberToRoom({
|
||||
id: this.roomId,
|
||||
members: this.selectedUsers
|
||||
})
|
||||
|
||||
|
||||
if(addMembers.isOk()) {
|
||||
// this.addContacts(this.roomId);
|
||||
this.openGroupMessage.emit(this.roomId);
|
||||
this.chatServiceService.getRoomById(this.roomId);
|
||||
} else if(addMembers.error instanceof HttpRequest) {
|
||||
this.httpErrorHandle.httpStatusHandle(addMembers.error)
|
||||
}
|
||||
} else {
|
||||
this.openGroupMessage.emit(this.roomId);
|
||||
}
|
||||
|
||||
this.showLoader = false;
|
||||
}
|
||||
|
||||
openGroupMessagesPage() {
|
||||
this.openGroupMessage.emit(this.roomId)
|
||||
}
|
||||
|
||||
async loadUsers() {
|
||||
|
||||
const getallChatUsers = await this.contactsRepositoryService.getUsers()
|
||||
const getRoomById = await this.chatServiceService.getRoomById(this.roomId)
|
||||
|
||||
console.log({getallChatUsers, getRoomById})
|
||||
|
||||
if(getallChatUsers.isOk() && getRoomById.isOk()) {
|
||||
|
||||
this.allChatUsers = getallChatUsers.value.data.result.sort((a,b) => {
|
||||
if(a.wxFullName < b.wxFullName) {
|
||||
return -1;
|
||||
}
|
||||
if(a.wxFullName > b.wxFullName) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const currentMemberToMap = await this.MemberListLocalRepository.getRoomMemberById(this.roomId)
|
||||
|
||||
console.log({currentMemberToMap})
|
||||
|
||||
this.currentMembers = currentMemberToMap.map((e)=> ({
|
||||
userPhoto: e.userPhoto,
|
||||
wxeMail: e.wxeMail,
|
||||
wxFullName: e.wxFullName,
|
||||
wxUserId: e.wxUserId
|
||||
}))
|
||||
|
||||
|
||||
const currentMemberIds = this.currentMembers.map(e => e.wxUserId)
|
||||
|
||||
const allSelectableUsers = this.allChatUsers.filter(e => !currentMemberIds.includes(e.wxUserId))
|
||||
|
||||
for(const user of allSelectableUsers) {
|
||||
const firstLetter = user.wxFullName.charAt(0)
|
||||
|
||||
if(!this.userContainer[firstLetter]) {
|
||||
user['isChecked'] = false
|
||||
this.userContainer[firstLetter] = [user as any]
|
||||
} else {
|
||||
const userIds = this.userContainer[firstLetter].map( e => e.wxUserId)
|
||||
if(!userIds.includes(user.wxUserId)) {
|
||||
user['isChecked'] = false
|
||||
this.userContainer[firstLetter].push(user as any)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (getRoomById.isErr() && getRoomById.error instanceof HttpResponse) {
|
||||
this.httpErrorHandle.httpStatusHandle(getRoomById.error)
|
||||
} else if (getallChatUsers.isErr() && getallChatUsers.error instanceof HttpResponse) {
|
||||
this.httpErrorHandle.httpStatusHandle(getallChatUsers.error)
|
||||
} else if (getRoomById.isErr() ) {
|
||||
console.log(getRoomById.error)
|
||||
} else if (getallChatUsers.isErr() ) {
|
||||
console.log(getallChatUsers.error)
|
||||
} else {
|
||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||
}
|
||||
|
||||
|
||||
this.showLoader = false;
|
||||
}
|
||||
|
||||
doRefresh(ev) {
|
||||
ev.target.complete();
|
||||
}
|
||||
|
||||
FilterUserListedByTextSearch() {
|
||||
return this.allChatUsers.filter( e => e.wxFullName.toLowerCase().includes(this.textSearch.toLowerCase())).sort((a,b) => {
|
||||
if(a.wxFullName < b.wxFullName) {
|
||||
return -1;
|
||||
}
|
||||
if(a.wxFullName > b.wxFullName) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
onChangeCheckBox(user: UserContacts & {isChecked: boolean}) {
|
||||
if(user.isChecked) {
|
||||
this.selectedUsers.push(user.wxUserId)
|
||||
} else {
|
||||
this.selectedUsers = this.selectedUsers.filter(e => e!= user.wxUserId)
|
||||
}
|
||||
}
|
||||
|
||||
onChange(event) {
|
||||
this.textSearch = event.detail.value;
|
||||
|
||||
const filteredUserList: (UserContacts & {isChecked: boolean})[] = this.FilterUserListedByTextSearch() as any
|
||||
|
||||
const userContainer = {}
|
||||
for(const user of filteredUserList) {
|
||||
const firstLetter = user.wxFullName.charAt(0)
|
||||
|
||||
if(!userContainer[firstLetter]) {
|
||||
user.isChecked = this.selectedUsers.includes(user.wxUserId)
|
||||
userContainer[firstLetter] = [user]
|
||||
} else {
|
||||
user.isChecked = this.selectedUsers.includes(user.wxUserId)
|
||||
userContainer[firstLetter].push(user)
|
||||
}
|
||||
|
||||
}
|
||||
this.userContainer = userContainer
|
||||
}
|
||||
|
||||
|
||||
async deleteMember(user: UserContacts) {
|
||||
this.showLoader = true;
|
||||
|
||||
const result = await this.chatServiceService.removeMemberToRoom({
|
||||
id: this.roomId,
|
||||
members: [ user.wxUserId]
|
||||
})
|
||||
|
||||
if(result.isOk()) {
|
||||
this.currentMembers = this.currentMembers.filter( e => e.wxUserId != user.wxUserId)
|
||||
|
||||
const firstLetter = user.wxFullName.charAt(0)
|
||||
|
||||
if(!this.userContainer[firstLetter]) {
|
||||
user['isChecked'] = false
|
||||
this.userContainer[firstLetter] = [user as any]
|
||||
} else {
|
||||
user['isChecked'] = false
|
||||
this.userContainer[firstLetter].push(user as any)
|
||||
}
|
||||
|
||||
} else if(result.error instanceof HttpRequest) {
|
||||
this.httpErrorHandle.httpStatusHandle(result.error)
|
||||
} else if(result.error instanceof ZodError) {
|
||||
console.log(result.error.issues)
|
||||
}
|
||||
|
||||
this.showLoader = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { GroupMessagesPage } from './group-messages.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: GroupMessagesPage
|
||||
},
|
||||
{
|
||||
path: 'group-contacts',
|
||||
loadChildren: () => import('./group-contacts/group-contacts.module').then( m => m.GroupContactsPageModule)
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
@@ -0,0 +1,36 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupMessagesPageRoutingModule } from './group-messages-routing.module';
|
||||
|
||||
import { GroupMessagesPage } from './group-messages.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||
import {MatMenuModule} from '@angular/material/menu';
|
||||
import { LettersAvatarModule } from "ngx-letters-avatar";
|
||||
import { PipesModule } from 'src/app/pipes/pipes.module';
|
||||
import { SafehtmlPipe } from 'src/app/pipes/safehtml.pipe';
|
||||
import { ChatPopoverPageModule } from '../../modal/chat-popover/chat-popover.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
FontAwesomeModule,
|
||||
ChatPopoverPageModule,
|
||||
GroupMessagesPageRoutingModule,
|
||||
MatMenuModule,
|
||||
LettersAvatarModule,
|
||||
PipesModule,
|
||||
//
|
||||
],
|
||||
exports: [GroupMessagesPage],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
declarations: [GroupMessagesPage]
|
||||
})
|
||||
export class GroupMessagesPageModule {}
|
||||
@@ -0,0 +1,350 @@
|
||||
@import '~src/function.scss';
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow:auto;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
//transform: translate3d(0, 1px, 0);
|
||||
|
||||
.header-top{
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
background: #fff;
|
||||
.middle{
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
width:calc(100% - 77px);
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.right{
|
||||
padding: 0!important;
|
||||
float: right;
|
||||
font-size: rem(25);
|
||||
color: #0782c9;
|
||||
margin: 5px 0 0 0;
|
||||
}
|
||||
}
|
||||
.header-bottom{
|
||||
width: 98%;
|
||||
overflow: auto;
|
||||
|
||||
.header-bottom-icon{
|
||||
width: rem(30);
|
||||
font-size: rem(25);
|
||||
float: left;
|
||||
padding: 2px;
|
||||
|
||||
}
|
||||
.header-bottom-contacts{
|
||||
width: calc(100% - 40px);
|
||||
font-size: rem(15);
|
||||
color: #797979;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
float: left;
|
||||
padding: 5px;
|
||||
margin: 1px;
|
||||
|
||||
.contacts-list{
|
||||
white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
float: left;
|
||||
}
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-delete-recording{
|
||||
margin-left: 20px !important;
|
||||
}
|
||||
|
||||
ion-content{
|
||||
.welcome-text{
|
||||
/* width: 322px; */
|
||||
//width: em(422px);
|
||||
background: #ebebeb;
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #797979;
|
||||
padding: 10px;
|
||||
margin: 0 auto !important;
|
||||
line-height: 1.2rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.info-text{
|
||||
/* width: 322px; */
|
||||
width: em(422px);
|
||||
background: var(--chat-alert-msg-color);
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #262420;
|
||||
padding: 10px;
|
||||
margin: 10px auto;
|
||||
line-height: 1.2rem;
|
||||
/* margin: 15px 0px 15px 0px; */
|
||||
border-radius: 8px;
|
||||
}
|
||||
.info-text-leave{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
padding: 10px;
|
||||
background: #e0e9ee;
|
||||
border-radius: 8px;
|
||||
margin: 10px auto;
|
||||
color: #797979 !important;
|
||||
font-size: rem(13) !important;
|
||||
/* margin: 15px 0px 15px 0px; */
|
||||
|
||||
.info-text-leave ion-label{
|
||||
font-size: rem(13) !important;
|
||||
line-height: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.info-meeting{
|
||||
/* width: 322px; */
|
||||
width: em(422px);
|
||||
background: var(--chat-alert-msg-color);
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #262420;
|
||||
padding: 10px;
|
||||
margin: 10px auto;
|
||||
line-height: 1.2rem;
|
||||
/* margin: 15px 0px 15px 0px; */
|
||||
border-radius: 8px;
|
||||
|
||||
.info-meeting-small{
|
||||
font-size: rem(10);
|
||||
font-style: italic;
|
||||
}
|
||||
.info-meeting-medium{
|
||||
font-size: rem(12);
|
||||
}
|
||||
.info-meeting-normal{
|
||||
font-weight: 700;
|
||||
}
|
||||
.info-meeting-normal:hover{
|
||||
text-decoration: underline;
|
||||
color: #0782c9;
|
||||
}
|
||||
}
|
||||
.messages{
|
||||
font-size: rem(13);
|
||||
font-family: Roboto;
|
||||
overflow: auto;
|
||||
|
||||
//set scroll do bottom
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
word-wrap: break-word;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
.incoming-true, .incoming-false{
|
||||
padding: 15px 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.incoming-true{
|
||||
margin: 10px 75px 10px 20px;
|
||||
background: #ebebeb;
|
||||
float: left;
|
||||
}
|
||||
.container-width-100{
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
.incoming-false{
|
||||
margin: 10px 20px 10px 75px;
|
||||
background: var(--chat-incoming-msg-color);
|
||||
float: right;
|
||||
}
|
||||
.title{
|
||||
display: inline;
|
||||
color: var(--title-text-color);
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.time{
|
||||
color: #797979;
|
||||
text-align: right;
|
||||
margin-left: 10px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
.message{
|
||||
.message-attachments{
|
||||
.file{
|
||||
align-items: center;
|
||||
|
||||
.file-details{
|
||||
width: 100%;
|
||||
|
||||
.file-title{
|
||||
color: #000;
|
||||
text-decoration: underline;
|
||||
white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
.file-title:hover{
|
||||
color: #0782c9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ion-footer{
|
||||
padding-top: 7.5px;
|
||||
padding-bottom: 7.5px;
|
||||
|
||||
.container{
|
||||
justify-content: center;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.chat-icon-options{
|
||||
display:block !important;
|
||||
font-size: rem(35);
|
||||
float: right !important;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.chat-icon-send{
|
||||
font-size: rem(45);
|
||||
margin: 0 auto;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.type-message{
|
||||
display: flex;
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 25px;
|
||||
padding-left: 15px;
|
||||
margin: 0 15px 0 75px;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
|
||||
ion-textarea{
|
||||
margin: 0 !important;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-send{
|
||||
padding-right: 20px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.typing {
|
||||
position: relative;
|
||||
top: -25px;
|
||||
height: 0px;
|
||||
left: 0px;
|
||||
margin-left: 22px;
|
||||
display: flex;
|
||||
font-size: rem(12);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.typing ngx-letters-avatar {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
|
||||
.float-status{
|
||||
position: relative !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
}
|
||||
|
||||
.float-status-image{
|
||||
position: relative !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
top: -15px;
|
||||
}
|
||||
|
||||
.float-status-webtrix {
|
||||
position: relative !important;
|
||||
top: 0px !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
}
|
||||
|
||||
.float-status-all {
|
||||
font-size: 10pt !important;
|
||||
}
|
||||
|
||||
|
||||
.try {
|
||||
color: red;
|
||||
background: #f3414159;
|
||||
padding: 6px;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.dateLabel {
|
||||
background: #ebebeb !important;
|
||||
float: unset !important;
|
||||
margin: 0px auto !important;
|
||||
width: 111px !important;
|
||||
text-align: center;
|
||||
margin-top: 10px !important;
|
||||
padding: 15px 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.lido,
|
||||
.enviado {
|
||||
font-size: rem(11);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupMessagesPage } from './group-messages.page';
|
||||
|
||||
describe('GroupMessagesPage', () => {
|
||||
let component: GroupMessagesPage;
|
||||
let fixture: ComponentFixture<GroupMessagesPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ GroupMessagesPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(GroupMessagesPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ContactsPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ContactsPageRoutingModule {}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ContactsPageRoutingModule } from './contacts-routing.module';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
import { FilterPipe } from 'src/app/pipes/filter.pipe';
|
||||
import { PipesModule } from 'src/app/pipes/pipes.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ContactsPageRoutingModule,
|
||||
PipesModule,
|
||||
],
|
||||
exports: [ContactsPage],
|
||||
declarations: [ContactsPage]
|
||||
})
|
||||
export class ContactsPageModule {}
|
||||
@@ -0,0 +1,49 @@
|
||||
<ion-header class="ion-no-border">
|
||||
<ion-toolbar class="header-toolbar">
|
||||
<div class="main-header">
|
||||
<div class="title-content">
|
||||
<div class="back-icon cursor-pointer" (click)="close()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " src="assets/images/theme/doneIt/icons-calendar-arrow-left.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||
</div>
|
||||
<div class="div-title">
|
||||
<!-- Desktop -->
|
||||
<ion-label class="title">Nova Conversa</ion-label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar class="toolbar-search">
|
||||
<div class="search">
|
||||
<ion-searchbar search-icon="undefined" debounce="500" (ionChange)="onChange($event)" placeholder="Pesquisar por contacto" ></ion-searchbar>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
|
||||
<!-- <ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar> -->
|
||||
<ion-refresher-content>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<div class="main-content">
|
||||
<ion-progress-bar class="position-absolute" type="indeterminate" *ngIf="loading"></ion-progress-bar>
|
||||
<ion-virtual-scroll [items]="userList" approxItemHeight="70px" [headerFn]="separateLetter">
|
||||
|
||||
<div class="item-divider" *virtualHeader="let header">
|
||||
<ion-label>{{ header }}</ion-label>
|
||||
</div>
|
||||
|
||||
<div (click)="openMessagesPage(user.wxFullName, user.wxUserId)" *virtualItem="let user" class="item-user cursor-pointer">
|
||||
<p>{{ user.wxFullName }}</p>
|
||||
<span class="icon">
|
||||
<ion-icon [class]="user.status" slot="end" name="ellipse"></ion-icon>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</ion-virtual-scroll>
|
||||
</div>
|
||||
|
||||
</ion-content>
|
||||
@@ -0,0 +1,136 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
border-top-left-radius: 25px;
|
||||
border-top-right-radius: 25px;
|
||||
background-color: #fff;
|
||||
overflow:hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.title-content{
|
||||
margin: 0px auto;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.back-icon{
|
||||
width: 37px;
|
||||
float: left;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
|
||||
}
|
||||
.div-title{
|
||||
width: 221px;
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
}
|
||||
.toolbar-search{
|
||||
--padding-top:0 !important;
|
||||
--padding-bottom:0 !important;
|
||||
--padding-start:0 !important;
|
||||
--padding-end:0 !important;
|
||||
|
||||
.search{
|
||||
border: 1px solid #ebebeb;
|
||||
margin: 5px 20px 5px 20px;
|
||||
border-radius: 5px;
|
||||
height: auto;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.search ion-searchbar{
|
||||
/* border: 1px solid green; */
|
||||
width: 100%;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
--border-radius: 5px;
|
||||
--box-shadow: none;
|
||||
overflow: hidden;
|
||||
--icon-color:var( --font-awesome);
|
||||
}
|
||||
|
||||
}
|
||||
ion-content{
|
||||
--background:transparent;
|
||||
}
|
||||
.main-content{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
padding: 0 0 0 0;
|
||||
overflow:auto;
|
||||
|
||||
.item-divider{
|
||||
background: #ebebeb;
|
||||
font-size: rem(15);
|
||||
margin: 10px 0 10px 0;
|
||||
padding:5px 0 5px 20px;
|
||||
|
||||
}
|
||||
|
||||
.item-user{
|
||||
display: flex;
|
||||
margin: 10px 20px 10px 20px !important;
|
||||
overflow: auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-user p{
|
||||
display: block;
|
||||
margin: 0 !important;
|
||||
width: 90%;
|
||||
font-size: rem(15);
|
||||
color: var(--title-text-color);
|
||||
float: left;
|
||||
}
|
||||
.item-user .icon{
|
||||
width: 10%;
|
||||
font-size: rem(10);
|
||||
display: block;
|
||||
text-align: right;
|
||||
overflow: auto;
|
||||
}
|
||||
.online{
|
||||
color:#99e47b;
|
||||
}
|
||||
.offline{
|
||||
color:#cbced1;
|
||||
}
|
||||
.away{
|
||||
color:#ffd21f;
|
||||
}
|
||||
.invisible{
|
||||
color:#cbced1;
|
||||
}
|
||||
.busy{
|
||||
color:#f5455c;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
|
||||
describe('ContactsPage', () => {
|
||||
let component: ContactsPage;
|
||||
let fixture: ComponentFixture<ContactsPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ContactsPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ContactsPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,203 @@
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { ModalController } from '@ionic/angular';
|
||||
import { MessagesPage } from '../messages.page';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service'
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
|
||||
import { UserContacts } from 'src/app/services/Repositorys/contacts/data-source/contacts-data-source.service';
|
||||
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service'
|
||||
|
||||
|
||||
class UserToSelect {
|
||||
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-contacts',
|
||||
templateUrl: './contacts.page.html',
|
||||
styleUrls: ['./contacts.page.scss'],
|
||||
})
|
||||
export class ContactsPage implements OnInit {
|
||||
loggedUser: any;
|
||||
|
||||
headers: HttpHeaders;
|
||||
options: any;
|
||||
textSearch: string;
|
||||
room: any;
|
||||
dm: any;
|
||||
sessionStore = SessionStore
|
||||
loading = false
|
||||
@Input() roomId: string;
|
||||
|
||||
@Output() openMessage: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() emptyTextDescriptionOpen: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() backToChat: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() closeAllDesktopComponents: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
userList: UserContacts[];
|
||||
originalUserList: any[] = [];
|
||||
|
||||
CoolList = []
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
public ThemeService: ThemeService,
|
||||
// public ChatSystemService: ChatSystemService,
|
||||
private contactsRepositoryService: ContactRepositoryService,
|
||||
private httpErrorHandle: HttpErrorHandle,
|
||||
private toastService: ToastService,
|
||||
private ChatServiceService: ChatServiceService
|
||||
) {
|
||||
this.loggedUser = SessionStore.user.ChatData['data'];
|
||||
this.textSearch = "";
|
||||
this.dm = null;
|
||||
this.room = null;
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
|
||||
this.loadUsers();
|
||||
}
|
||||
|
||||
onChange(event) {
|
||||
this.textSearch = event.detail.value.toLowerCase();
|
||||
this.userList = this.originalUserList.filter((e) => {
|
||||
const username = e.wxFullName.toLowerCase();
|
||||
return username.includes(this.textSearch);
|
||||
});
|
||||
|
||||
this.userList.sort((a, b) => a.wxFullName.toLowerCase().localeCompare(b.wxFullName.toLowerCase()));
|
||||
}
|
||||
|
||||
openMessagesPage(username: string, wxUserId: number) {
|
||||
this.createRoom(username, wxUserId);
|
||||
/* if (window.innerWidth < 701) {
|
||||
this.createRoom(username);
|
||||
}
|
||||
else {
|
||||
let body = {
|
||||
username: username,
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
this.chatService.createRoom(body).subscribe(res => {
|
||||
this.room = res['room'];
|
||||
|
||||
this.ChatSystemService.getAllRooms(() => {
|
||||
this.openMessage.emit(this.room._id);
|
||||
|
||||
this.loading = false
|
||||
}, this.room._id);
|
||||
|
||||
}, () => {
|
||||
this.loading = false
|
||||
});
|
||||
}*/
|
||||
}
|
||||
|
||||
async loadUsers() {
|
||||
try {
|
||||
let users = await this.contactsRepositoryService.getUsers();
|
||||
if (users.isOk()) {
|
||||
const userData = users.value.data.result;
|
||||
console.log(userData)
|
||||
this.originalUserList = userData;
|
||||
this.userList = [...this.originalUserList];
|
||||
this.userList.sort((a, b) => a.wxFullName.toLowerCase().localeCompare(b.wxFullName.toLowerCase()));
|
||||
console.log('User data loaded successfully:', this.originalUserList);
|
||||
} else {
|
||||
console.error('Failed to fetch users:', users.error);
|
||||
}
|
||||
this.loading = false;
|
||||
} catch (error) {
|
||||
console.error('Error loading users', error);
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
separateLetter(record, recordIndex, records) {
|
||||
const normalize = (str) => str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
||||
|
||||
if (recordIndex == 0) {
|
||||
return normalize(record.wxFullName[0]).toUpperCase();
|
||||
}
|
||||
|
||||
let firstPrev = normalize(records[recordIndex - 1].wxFullName[0]).toUpperCase();
|
||||
let firstCurrent = normalize(record.wxFullName[0]).toUpperCase();
|
||||
|
||||
if (firstPrev !== firstCurrent) {
|
||||
return firstCurrent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
doRefresh(event) {
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.roomId) {
|
||||
this.backToChat.emit({ roomId: this.roomId });
|
||||
} else {
|
||||
this.closeAllDesktopComponents.emit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
clicked() {
|
||||
|
||||
}
|
||||
|
||||
async createRoom(username: string, wxUserId: number) {
|
||||
const result = await this.ChatServiceService.createRoom({
|
||||
roomName: username,
|
||||
createdBy: SessionStore.user.UserId,
|
||||
roomType: 0,
|
||||
expirationDate: null,
|
||||
members: [wxUserId]
|
||||
})
|
||||
|
||||
|
||||
console.log(result)
|
||||
|
||||
if(result.isOk()) {
|
||||
await this.ChatServiceService.getRoomById(result.value.id);
|
||||
this.openMessage.emit(result.value.id);
|
||||
|
||||
} else if(result.error instanceof HttpErrorResponse) {
|
||||
this.httpErrorHandle.httpStatusHandle(result.error)
|
||||
} else {
|
||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||
console.log(result.error)
|
||||
}
|
||||
/* this.chatService.createRoom(body).subscribe(res => {
|
||||
|
||||
this.room = res['room'];
|
||||
this.openMessagesModal(this.room._id);
|
||||
this.ChatSystemService.getAllRooms()
|
||||
}); */
|
||||
}
|
||||
|
||||
async openMessagesModal(roomId: any) {
|
||||
|
||||
|
||||
|
||||
const modal = await this.modalController.create({
|
||||
component: MessagesPage,
|
||||
cssClass: 'modal modal-desktop isMessagesChatOpened',
|
||||
componentProps: {
|
||||
roomId: roomId,
|
||||
},
|
||||
});
|
||||
|
||||
modal.onDidDismiss();
|
||||
await modal.present();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { MessagesPage } from './messages.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: MessagesPage
|
||||
},
|
||||
{
|
||||
path: 'contacts',
|
||||
loadChildren: () => import('./contacts/contacts.module').then( m => m.ContactsPageModule)
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
@@ -0,0 +1,35 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { MessagesPageRoutingModule } from './messages-routing.module';
|
||||
|
||||
import { MessagesPage } from './messages.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import {MatMenuModule} from '@angular/material/menu';
|
||||
import { LettersAvatarModule } from "ngx-letters-avatar";
|
||||
import { PipesModule } from 'src/app/pipes/pipes.module';
|
||||
import { SafehtmlPipe } from 'src/app/pipes/safehtml.pipe';
|
||||
import { ScrollingModule } from '@angular/cdk/scrolling';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
FontAwesomeModule,
|
||||
MessagesPageRoutingModule,
|
||||
MatButtonModule,
|
||||
MatMenuModule,
|
||||
LettersAvatarModule,
|
||||
PipesModule,
|
||||
ScrollingModule,
|
||||
],
|
||||
exports: [MessagesPage],
|
||||
declarations: [MessagesPage]
|
||||
})
|
||||
export class MessagesPageModule {}
|
||||
@@ -0,0 +1,262 @@
|
||||
<ion-header class="ion-no-border" >
|
||||
<ion-toolbar class="header-toolbar" >
|
||||
<div class="main-header">
|
||||
<div class="header-top">
|
||||
<div class="middle" >
|
||||
<!-- <ion-label class="title" *ngIf="(roomData$ | async) === null"> {{ room.roomName }}</ion-label> -->
|
||||
<ion-label class="title" *ngIf="roomData$ | async as roomData"> {{ roomData.roomName }}</ion-label>
|
||||
<!-- <button (click)="ChatMessageDebuggingPage()">Dev</button> -->
|
||||
<span *ngIf="roomStatus$ | async as roomStatus"><ion-icon *ngIf="roomStatus" class="online" name="ellipse"></ion-icon></span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button title="Menu" class="btn-no-color" (click)="_openMessagesOptions()" *ngIf="roomType == RoomTypeEnum.Group">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/images/theme/blue/icons-menu.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/images/theme/gov/icons-menu.svg">
|
||||
</ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex header-bottom" >
|
||||
<div class="header-bottom-icon" *ngIf="roomType == RoomTypeEnum.Group">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/icon/icons-user.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/icon/theme/gov/icons-user.svg"></ion-icon>
|
||||
</div>
|
||||
|
||||
<ion-list class="header-bottom-contacts" *ngIf="roomMembers$ | async as memberList" >
|
||||
<ng-container *ngFor="let user of memberList; let i = index">
|
||||
<span *ngIf="roomType == RoomTypeEnum.Group"> {{ user.wxFullName }}<ng-container *ngIf="i < memberList.length - 1">, </ng-container> </span>
|
||||
</ng-container>
|
||||
</ion-list>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
|
||||
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
|
||||
<ion-refresher-content>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content >
|
||||
|
||||
<div class="messages height-100 width-100 d-flex flex-column rotate-div" #scrollMe >
|
||||
|
||||
<div
|
||||
*ngFor="let message of messages1[roomId]; let messageIndex = index" class="messages-list-item-wrapper px-10-em"
|
||||
[ngClass]="{
|
||||
'info-meeting': message.messageType == IMessageType.information && !message.ballon,
|
||||
'info-ballon': message.ballon == true,
|
||||
'my-message': message.messageType == IMessageType.normal && message?.sender?.wxUserId === SessionStore.user.UserId && !message.ballon,
|
||||
'other-message': message.messageType == IMessageType.normal && message?.sender?.wxUserId !== SessionStore.user.UserId && !message.ballon
|
||||
}"
|
||||
>
|
||||
<!-- Emoji Picker -->
|
||||
<div *ngIf="selectedMessage === message" class="emoji-picker mr-20" [ngStyle]="{'bottom': '0', 'right': '0'}">
|
||||
<span *ngFor="let emoji of emojis" (click)="addReaction(message, emoji)" class="emoji-icon">
|
||||
{{ emoji }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="message-container rotate-div" *ngIf="message.showMessage">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>
|
||||
<div style="white-space: pre-line;">
|
||||
{{ message.message }}
|
||||
</div>
|
||||
|
||||
<div *ngFor="let attachment of message.attachments; let i = index">
|
||||
<div *ngIf="attachment.source == MessageAttachmentFileSource.Webtrix">
|
||||
|
||||
<ion-icon src="assets/icon/webtrix.svg" class="file-icon font-25"></ion-icon>
|
||||
<!-- <ion-label>{{ attachment.fileName}}</ion-label> -->
|
||||
<!-- <ion-icon *ngIf="ThemeService.currentTheme == 'default' && attachment.type != 'webtrix' && !( msg.downloadLoader == true || msg.uploadingFile == true ) " class="icon-download" src="assets/icon/theme/default/icons-download.svg" slot="end"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' && attachment.type != 'webtrix' && !( msg.downloadLoader == true || msg.uploadingFile == true ) " class="icon-download" src="assets/icon/theme/gov/icons-download.svg" slot="end"></ion-icon>
|
||||
<ion-icon *ngIf="( msg.downloadLoader == true || msg.uploadingFile == true )" class="icon-download" src="assets/gif/theme/{{ThemeService.currentTheme}}/Blocks-loader.svg" slot="end"></ion-icon> -->
|
||||
|
||||
</div>
|
||||
|
||||
<div *ngIf="attachment.fileType == MessageAttachmentFileType.Image">
|
||||
<img
|
||||
*ngIf="message.oneShot != true && attachment.blobURl != true"
|
||||
[src]="attachment.safeFile"
|
||||
(load)="onImageLoad(message, messageIndex)"
|
||||
(error)="onImageError()"
|
||||
>
|
||||
|
||||
<img
|
||||
*ngIf="message.oneShot != true && attachment.blobURl"
|
||||
[src]="attachment.safeFile|safehtml"
|
||||
(load)="onImageLoad(message, messageIndex)"
|
||||
(error)="onImageError()"
|
||||
>
|
||||
|
||||
<div *ngIf="SessionStore.user.UserId == message.sender.wxUserId && message.oneShot == true">
|
||||
Mandou uma mensagen com visualização única
|
||||
</div>
|
||||
|
||||
<div *ngIf="SessionStore.user.UserId != message.sender.wxUserId && message.oneShot == true">
|
||||
<!-- <div *ngIf="message.oneShot == true" class="cursor-pointer"> -->
|
||||
<div (click)="viewOnce($event, message, i)">
|
||||
Abrir a visualização única
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div *ngIf="attachment.fileType == MessageAttachmentFileType.Audio">
|
||||
<audio [src]="attachment.safeFile|safehtml" preload="metadata" class="flex-grow-1" controls controlsList="nodownload noplaybackrate"></audio>
|
||||
</div>
|
||||
|
||||
<div *ngIf="attachment.fileType == MessageAttachmentFileType.Doc" class="d-flex" (click)="openPreview(message)">
|
||||
<fa-icon *ngIf="attachment.mimeType == 'application/pdf'" icon="file-pdf" class="pdf-icon"></fa-icon>
|
||||
<fa-icon *ngIf="attachment.mimeType == 'application/word'" icon="file-word" class="word-icon">
|
||||
</fa-icon>
|
||||
<fa-icon *ngIf="attachment.mimeType == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'" icon="file-word" class="word-icon"></fa-icon>
|
||||
<fa-icon
|
||||
*ngIf="attachment.mimeType == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'"
|
||||
icon="file-word" class="excel-icon"></fa-icon>
|
||||
<ion-icon *ngIf="attachment.mimeType == 'application/webtrix'" src="assets/icon/webtrix.svg">
|
||||
</ion-icon>
|
||||
<ion-icon *ngIf="attachment.mimeType == 'application/meeting'" src="assets/icon/webtrix.svg">
|
||||
</ion-icon>
|
||||
|
||||
<ion-label>{{ attachment?.fileName || attachment?.description }}</ion-label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<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>
|
||||
<mat-menu #beforeMenu="matMenu" xPosition="before">
|
||||
<button (click)="messageDelete(message)" class="menuButton">Apagar mensagem</button>
|
||||
<button *ngIf="!message.hasAttachment" (click)="editMessage(message)" class="menuButton">Editar mensagem</button>
|
||||
<button (click)="toggleEmojiPicker(message)" class="menuButton">Reagir mensagem</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="text-align: end;">
|
||||
|
||||
<div *ngIf="totalMembers != 0 && SessionStore.user.UserId == message.sender.wxUserId">
|
||||
<ion-icon *ngIf="messageStatus(message) == 'enviar'" src="assets/images/clock-regular.svg"></ion-icon>
|
||||
<ion-icon *ngIf="messageStatus(message) == 'enviado'" src="assets/images/check-solid.svg"></ion-icon>
|
||||
<ion-icon *ngIf="messageStatus(message) == 'allReceived'" src="assets/images/check-double-solid.svg"></ion-icon>
|
||||
<ion-icon *ngIf="messageStatus(message) == 'allViewed'" src="assets/images/check-double-solid -viewed.svg"></ion-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="message-container rotate-div" *ngIf="message.isDeleted == true">
|
||||
Mensagem foi eliminada
|
||||
</div>
|
||||
<div *ngIf="message.messageType == IMessageType.information && !message.ballon" class="text-center">
|
||||
{{ message.message }}
|
||||
</div>
|
||||
<div *ngIf="message.ballon" class="text-center ballon">
|
||||
{{ message.message }}
|
||||
</div>
|
||||
<div class="rotate-div emoji-container" *ngIf="message.isDeleted != true && message.messageType != IMessageType.information && message.ballon != true">
|
||||
<span *ngFor="let reaction of message.reactions" class="emoji-icon">
|
||||
{{ reaction.reaction }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<ion-fab horizontal="start" vertical="bottom" slot="fixed">
|
||||
|
||||
<div #array>
|
||||
|
||||
</div>
|
||||
</ion-fab>
|
||||
|
||||
</ion-content>
|
||||
|
||||
|
||||
<!-- <ion-footer (click)="ChatSystemService.getDmRoom(roomId).sendReadMessage()"> -->
|
||||
<ion-footer (click)="sendReadMessage()">
|
||||
|
||||
<!-- <div class="typing" *ngIf="ChatSystemService.getDmRoom(roomId).otherUserType == true" >
|
||||
<ngx-letters-avatar *ngIf="showAvatar"
|
||||
[avatarName]= "ChatSystemService.getDmRoom(roomId).name"
|
||||
[width]="30"
|
||||
[circular]="true"
|
||||
fontFamily="Roboto"></ngx-letters-avatar>
|
||||
está a escrever...
|
||||
</div> -->
|
||||
<div class="width-100 pl-20 pr-20">
|
||||
<span >{{durationDisplay}}</span>
|
||||
<div class=" audioDiv d-flex width-100 mt-10 mb-10" *ngIf="lastAudioRecorded">
|
||||
<div (click)="start(audioRecordedSafe)" *ngIf="!isPlaying" > <ion-icon slot="icon-only" name="play"></ion-icon> </div>
|
||||
<div (click)="togglePlayer(isPlaying)" *ngIf="isPlaying"> <ion-icon slot="icon-only" name="pause"></ion-icon> </div>
|
||||
<ion-range #range [(ngModel)]="audioProgress" max="100" (mouseup)="seek()"></ion-range>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container width-100 d-flex">
|
||||
<div>
|
||||
<ion-fab *ngIf="!recording && !lastAudioRecorded && allowTyping" horizontal="start" vertical="bottom" slot="fixed">
|
||||
<ion-fab-button color="light" size="small">
|
||||
<ion-icon name="add"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="top">
|
||||
<!-- <ion-fab-button *ngIf="p.userPermission([p.permissionList.Agenda.access])" title="Nova Reunião" (click)="bookMeeting()" color="light">
|
||||
<ion-icon name="calendar"></ion-icon>
|
||||
</ion-fab-button> -->
|
||||
<ion-fab-button title="Adicionar Documento" (click)="addFile()" color="light">
|
||||
<ion-icon name="document"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button title="Anexar Fotografia" (click)="pickPicture()" color="light">
|
||||
<ion-icon name="image"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button title="Tirar Fotografia" (click)="takePictureMobile()" color="light">
|
||||
<ion-icon name="camera"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button title="Documento da Gestão Documental" (click)="addFileWebtrix()" color="light">
|
||||
<ion-icon src="assets/icon/webtrix.svg"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
<button *ngIf="recording || lastAudioRecorded || !allowTyping" class="btn-no-color" (click)="deleteRecording()">
|
||||
<fa-icon class="icon-size-27" icon="trash"></fa-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="width-100">
|
||||
<div *ngIf="!recording && !lastAudioRecorded" class="type-message">
|
||||
<ion-textarea *ngIf="allowTyping" (keyup.enter)="sendMessage()" clearOnEdit="true" placeholder="Escrever uma mensagem" class="message-input" rows="1" [(ngModel)]="textField" (ionChange)="sendTyping()" (click)="sendReadAt()"></ion-textarea>
|
||||
</div>
|
||||
<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">
|
||||
<ion-icon class="icon-size-45" name="stop-circle-outline" color="danger"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="btn-send">
|
||||
<button #recordbtn *ngIf="textField == '' && !lastAudioRecorded" (click)="startRecording()" class="btn-no-color">
|
||||
<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 *ngIf="textField != ''" 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>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon>
|
||||
</button>
|
||||
<button *ngIf="textField == '' && lastAudioRecorded" class="btn-no-color" (click)="sendAudio(lastAudioRecorded)">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ion-footer>
|
||||
@@ -0,0 +1,547 @@
|
||||
@import "~src/function.scss";
|
||||
|
||||
.header-toolbar {
|
||||
--background: transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header {
|
||||
width: 100%;
|
||||
/* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
//padding: 0px 20px 0px 20px;
|
||||
color: #000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
padding: 30px 20px 0 20px !important;
|
||||
|
||||
.header-top {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
//padding: 0 !important;
|
||||
background: #fff;
|
||||
|
||||
.middle {
|
||||
//padding: 0!important;
|
||||
float: left;
|
||||
width: calc(100% - 77px);
|
||||
margin: 2px 0 0 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.right {
|
||||
padding: 0 !important;
|
||||
float: right;
|
||||
font-size: rem(25);
|
||||
color: #0782c9;
|
||||
margin: 5px 0 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.header-bottom {
|
||||
width: 95%;
|
||||
overflow: auto;
|
||||
|
||||
.header-bottom-icon {
|
||||
width: rem(30);
|
||||
font-size: rem(25);
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.header-bottom-contacts {
|
||||
font-size: rem(15);
|
||||
color: #797979;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding: 5px;
|
||||
margin: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: rem(25);
|
||||
white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.div-icon {
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.div-icon ion-icon {
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ion-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 30px 20px 0 20px !important;
|
||||
|
||||
.welcome-text {
|
||||
/* width: 322px; */
|
||||
/* width: em(422px); */
|
||||
width: 100%;
|
||||
background: #ebebeb;
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #797979;
|
||||
padding: 10px;
|
||||
margin: 0 auto !important;
|
||||
line-height: 1.2rem;
|
||||
//margin: 20px 39px 25px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
.info-meeting {
|
||||
/* width: 322px; */
|
||||
width: em(422px);
|
||||
background: var(--chat-alert-msg-color);
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #262420;
|
||||
padding: 10px;
|
||||
margin: 10px auto;
|
||||
line-height: 1.2rem;
|
||||
/* margin: 15px 0px 15px 0px; */
|
||||
border-radius: 8px;
|
||||
|
||||
.info-meeting-small {
|
||||
font-size: rem(10);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.info-meeting-medium {
|
||||
font-size: rem(12);
|
||||
}
|
||||
|
||||
.info-meeting-normal {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.info-meeting-normal:hover {
|
||||
text-decoration: underline;
|
||||
color: #0782c9;
|
||||
}
|
||||
}
|
||||
|
||||
.info-ballon {
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #262420;
|
||||
padding: 10px;
|
||||
margin: 10px auto;
|
||||
line-height: 2.2rem;
|
||||
border-radius: 8px;
|
||||
.ballon {
|
||||
background: var(--chat-alert-msg-color);
|
||||
padding: 0px 10px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.messages {
|
||||
font-size: rem(13);
|
||||
font-family: Roboto;
|
||||
overflow: auto;
|
||||
|
||||
//set scroll do bottom
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// overflow-x: hidden;
|
||||
// overflow-y: auto;
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// word-wrap: break-word;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
|
||||
.other-message,
|
||||
.my-message {
|
||||
|
||||
.message-container {
|
||||
padding: 15px 20px;
|
||||
margin: 10px 20px 10px 75px;
|
||||
background: var(--chat-incoming-msg-color);
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.other-message {
|
||||
display: flex;
|
||||
/* justify-content: flex-end; */
|
||||
align-items: start;
|
||||
flex-direction: column;
|
||||
// float: left;
|
||||
// Styles for incoming messages from other users
|
||||
justify-content: flex-start;
|
||||
.message-container {
|
||||
padding: 15px 20px;
|
||||
margin: 10px 75px 10px 20px;
|
||||
background: #ebebeb;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.my-message {
|
||||
|
||||
display: flex;
|
||||
/* justify-content: flex-end; */
|
||||
align-items: end;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.message-bubble {
|
||||
// Styles for the message bubble
|
||||
background-color: #e2e2e2; // Example background color
|
||||
padding: 10px; // Adjust as needed
|
||||
border-radius: 10px; // Adjust as needed
|
||||
}
|
||||
|
||||
.title {
|
||||
display: inline;
|
||||
color: var(--title-text-color);
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.time {
|
||||
color: #797979;
|
||||
text-align: right;
|
||||
margin-left: 10px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
.message-attachments {
|
||||
.file {
|
||||
align-items: center;
|
||||
|
||||
.file-details {
|
||||
width: 100%;
|
||||
|
||||
.file-title {
|
||||
color: #000;
|
||||
text-decoration: underline;
|
||||
white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
|
||||
.file-title:hover {
|
||||
color: #0782c9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ion-footer {
|
||||
padding-top: 7.5px;
|
||||
padding-bottom: 7.5px;
|
||||
|
||||
.container {
|
||||
justify-content: center;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.chat-icon-options {
|
||||
display: block !important;
|
||||
font-size: rem(35);
|
||||
float: right !important;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.chat-icon-send {
|
||||
font-size: rem(45);
|
||||
margin: 0 auto;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.chat-icon-download {
|
||||
font-size: 95px;
|
||||
margin: 0 auto;
|
||||
margin-top: 4px;
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
.type-message {
|
||||
display: flex;
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 25px;
|
||||
padding-left: 15px;
|
||||
margin: 0 15px 0 60px;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
|
||||
ion-textarea {
|
||||
margin: 0 !important;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text-color-blue {
|
||||
font-size: rem(15);
|
||||
color: #0782c9;
|
||||
font-weight: 500;
|
||||
letter-spacing: normal;
|
||||
}
|
||||
|
||||
.user-status-online {
|
||||
display: block;
|
||||
float: left;
|
||||
color: #99e47b;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.online {
|
||||
display: block;
|
||||
float: left;
|
||||
color: #99e47b;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.offline {
|
||||
color: #cbced1;
|
||||
display: block;
|
||||
float: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.away {
|
||||
color: #ffd21f;
|
||||
display: block;
|
||||
float: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
color: #cbced1;
|
||||
display: block;
|
||||
float: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.busy {
|
||||
color: #f5455c;
|
||||
display: block;
|
||||
float: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.float-status {
|
||||
position: relative !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
}
|
||||
|
||||
.float-status-image {
|
||||
position: relative !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
top: -15px;
|
||||
}
|
||||
|
||||
.float-status-webtrix {
|
||||
position: relative !important;
|
||||
top: 0px !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
}
|
||||
|
||||
.float-status-all {
|
||||
font-size: 10pt !important;
|
||||
}
|
||||
|
||||
.typing {
|
||||
position: relative;
|
||||
top: -25px;
|
||||
height: 0px;
|
||||
left: 0px;
|
||||
margin-left: 22px;
|
||||
display: flex;
|
||||
font-size: rem(12);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.typing ngx-letters-avatar {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.div-do-audio {
|
||||
border: 1px solid red !important;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.message-box {
|
||||
flex: auto;
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
||||
.divColor {
|
||||
color: #000;
|
||||
width: 10ch;
|
||||
height: 10ch;
|
||||
}
|
||||
|
||||
.audioDiv {
|
||||
border-radius: 25px;
|
||||
background: #cbced1;
|
||||
padding: 20px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.audioButtonPlay {
|
||||
margin-bottom: 100%;
|
||||
right: 50%;
|
||||
}
|
||||
|
||||
.try {
|
||||
color: red;
|
||||
background: #f3414159;
|
||||
padding: 6px;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.red-top {
|
||||
border-top: 1px solid red !important;
|
||||
}
|
||||
.red {
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
.lido,
|
||||
.enviado {
|
||||
font-size: rem(11);
|
||||
}
|
||||
|
||||
|
||||
.dateLabel {
|
||||
background: #ebebeb !important;
|
||||
float: unset !important;
|
||||
margin: 0px auto !important;
|
||||
width: 111px !important;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.message-item-options {
|
||||
//display: none !important; /* Hide the options by default */
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
.message-container:hover .message-item-options {
|
||||
//display: block !important; /* Show the options on hover */
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.message-item-options {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.emoji-picker {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background: white;
|
||||
border: 1px solid #ccc;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-ms-border-radius: 5px;
|
||||
-o-border-radius: 5px;
|
||||
}
|
||||
|
||||
.emoji-icon {
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.modal img {
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
}
|
||||
|
||||
.modal button {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
.view-file {
|
||||
span {}
|
||||
|
||||
img {}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// .rotate-div {
|
||||
// transform: rotate(180deg);
|
||||
// -webkit-transform: rotate(180deg);
|
||||
// -moz-transform: rotate(180deg);
|
||||
// -ms-transform: rotate(180deg);
|
||||
// -o-transform: rotate(180deg);
|
||||
// }
|
||||
.emoji-container{
|
||||
padding: 0px 20px;
|
||||
/* margin-bottom: -10px; */
|
||||
position: relative;
|
||||
top: -10px;
|
||||
margin-bottom: -15px;
|
||||
}
|
||||
|
||||
|
||||
.emoji-picker {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.emoji-picker button {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
margin: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.emoji-picker button:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { MessagesPage } from './messages.page';
|
||||
|
||||
describe('MessagesPage', () => {
|
||||
let component: MessagesPage;
|
||||
let fixture: ComponentFixture<MessagesPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ MessagesPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MessagesPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { NewGroupPage } from './new-group.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: NewGroupPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class NewGroupPageRoutingModule {}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { NewGroupPageRoutingModule } from './new-group-routing.module';
|
||||
|
||||
import { NewGroupPage } from './new-group.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
NewGroupPageRoutingModule
|
||||
],
|
||||
exports: [NewGroupPage],
|
||||
declarations: [NewGroupPage]
|
||||
})
|
||||
export class NewGroupPageModule {}
|
||||
@@ -0,0 +1,46 @@
|
||||
<ion-header class="ion-no-border">
|
||||
<ion-toolbar class="header-toolbar">
|
||||
<div class="main-header">
|
||||
<div class="title-content">
|
||||
<div class="left">
|
||||
<button class="btn-no-color" (click)="close()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="middle">
|
||||
<ion-label class="title">Novo Grupo</ion-label>
|
||||
</div>
|
||||
<div *ngIf="groupName">
|
||||
<button id="create" class="btn-no-color btn-criar" (click)="createGroup()">
|
||||
Criar grupo
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<div class="main-content width-100">
|
||||
<div class="item-container">
|
||||
<ion-input [(ngModel)]="groupName" placeholder="Título"></ion-input>
|
||||
</div>
|
||||
|
||||
<div class="item-container-no-border">
|
||||
<ion-checkbox (ionChange)="onDateExpirationChange($event)" color="primary"></ion-checkbox>
|
||||
<ion-label>Grupo Ultra-secreto</ion-label>
|
||||
</div>
|
||||
|
||||
<div *ngIf="showDuration" class="container-div">
|
||||
<div class="ion-item-class-2">
|
||||
<div class="ion-icon-class">
|
||||
<ion-icon slot="start" src="assets/images/icons-duration.svg"></ion-icon>
|
||||
</div>
|
||||
<div class="ion-input-class">
|
||||
<ion-input (click)="showPicker()" [(ngModel)]="displayDuration" placeholder="Duração"></ion-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,162 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
ion-content{
|
||||
--background:transparent;
|
||||
}
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
}
|
||||
.div-top-header{
|
||||
width: 400px;
|
||||
margin: 0 auto;
|
||||
background-color: #0782c9;
|
||||
overflow: auto;
|
||||
padding-top: 15px;
|
||||
border: 0!important;
|
||||
|
||||
.div-search{
|
||||
font-size: rem(45);
|
||||
float: left;
|
||||
margin: 0 0 0 10px
|
||||
}
|
||||
.div-logo{
|
||||
background: transparent;
|
||||
width: 140px;
|
||||
margin: 5px 0 0px 71px;
|
||||
float: left;
|
||||
}
|
||||
.div-logo img{
|
||||
width: 100%;
|
||||
}
|
||||
.div-profile{
|
||||
font-size: rem(45);
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
.main-header{
|
||||
width: 100%; /* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
border-top-left-radius: 25px;
|
||||
border-top-right-radius: 25px;
|
||||
background-color: #fff;
|
||||
overflow:hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.title-content{
|
||||
//width: 360px;
|
||||
margin: 0px auto;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
background: #fff;
|
||||
|
||||
.left{
|
||||
width: 37px;
|
||||
float: left;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
}
|
||||
.middle{
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
width: 221px;
|
||||
//margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.btn-criar{
|
||||
padding: 0!important;
|
||||
float: right;
|
||||
font-size: rem(15);
|
||||
color: var(--font-awesome);
|
||||
margin: 8px 5px 0 5px;
|
||||
}
|
||||
.right{
|
||||
padding: 0!important;
|
||||
float: right;
|
||||
font-size: rem(15);
|
||||
color: #0782c9;
|
||||
margin: 8px 0 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
}
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
.main-content{
|
||||
width: 100%; /* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
overflow:auto;
|
||||
padding: 15px 20px 0 20px;
|
||||
|
||||
.item-container{
|
||||
//width: 360px;
|
||||
margin: 15px auto;
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 5px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.item-container-no-border{
|
||||
display: flex;
|
||||
//width: 360px;
|
||||
margin: 25px auto;
|
||||
border-radius: 5px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-container-no-border ion-label{
|
||||
padding-left: 10px;
|
||||
font-size: rem(12);
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.container-div{
|
||||
width: 100%;
|
||||
margin-bottom: 15px;
|
||||
overflow: auto;
|
||||
|
||||
.ion-item-class-2{
|
||||
width: 100%;
|
||||
margin: 0px auto;
|
||||
|
||||
.ion-icon-class{
|
||||
width: 5%;
|
||||
height: rem(45);
|
||||
float: left;
|
||||
padding: 10px;
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
.ion-input-class{
|
||||
width: 93%;
|
||||
height: rem(45);
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 5px;
|
||||
padding-left: 5px;
|
||||
padding-right: 10px;
|
||||
margin-left: 2%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { NewGroupPage } from './new-group.page';
|
||||
|
||||
describe('NewGroupPage', () => {
|
||||
let component: NewGroupPage;
|
||||
let fixture: ComponentFixture<NewGroupPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ NewGroupPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(NewGroupPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,326 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output,ViewContainerRef } from '@angular/core';
|
||||
import { PickerController, PopoverController } from '@ionic/angular';
|
||||
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service';
|
||||
import { DataService } from 'src/app/services/data.service';
|
||||
import { GroupDurationPage } from 'src/app/shared/popover/group-duration/group-duration.page';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { ThemeService } from 'src/app/services/theme.service';
|
||||
import { RouteService } from 'src/app/services/route.service';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
|
||||
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service'
|
||||
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service'
|
||||
import { UDate } from 'src/app/utils/date';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-new-group',
|
||||
templateUrl: './new-group.page.html',
|
||||
styleUrls: ['./new-group.page.scss'],
|
||||
})
|
||||
export class NewGroupPage implements OnInit{
|
||||
isGroupCreated:boolean;
|
||||
showLoader: boolean;
|
||||
displayDuration: any;
|
||||
showDuration: boolean;
|
||||
expirationDate:Date = null;
|
||||
_day:any;
|
||||
selectedDuration = ['','',''];
|
||||
countDownTime:any;
|
||||
task:any;
|
||||
event: any
|
||||
link = ''
|
||||
documents: any;
|
||||
loggedUserChat: any;
|
||||
contact: {
|
||||
Email: string
|
||||
DisplayName: string
|
||||
}[]
|
||||
|
||||
@Input() roomId: string;
|
||||
|
||||
@Input() groupName:string;
|
||||
@Output() addGroupMessage:EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() closeAllDesktopComponents:EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() backToChat:EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
|
||||
constructor(
|
||||
private pickerController: PickerController,
|
||||
private popoverController: PopoverController,
|
||||
private dataService:DataService,
|
||||
// public ChatSystemService: ChatSystemService,
|
||||
public ThemeService: ThemeService,
|
||||
private RouteService: RouteService,
|
||||
private viewContainerRef: ViewContainerRef,
|
||||
private httpErrorHandle: HttpErrorHandle,
|
||||
private ChatServiceService: ChatServiceService,
|
||||
private toastService: ToastService,
|
||||
)
|
||||
{
|
||||
this.loggedUserChat = SessionStore.user.ChatData['data'];
|
||||
this.isGroupCreated = false;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
this.task = this.dataService.get("task");
|
||||
this.event = this.dataService.get("event");
|
||||
|
||||
if(this.task && this.dataService.get("newGroup")) {
|
||||
this.link = this.dataService.get("link");
|
||||
this.groupName = this.task.Folio;
|
||||
this.documents = this.dataService.get("documents");
|
||||
this.dataService.set("newGroup", false);
|
||||
this.dataService.set("link", false);
|
||||
} else if (this.event && this.dataService.get("newGroup")) {
|
||||
//
|
||||
this.link = this.dataService.get("link");
|
||||
this.groupName = this.event.Subject;
|
||||
this.documents = this.dataService.get("documents");
|
||||
this.contact = this.dataService.get("contacts");
|
||||
//
|
||||
this.dataService.set("newGroup", false);
|
||||
this.dataService.set("link", false);
|
||||
|
||||
} else {
|
||||
this.dataService.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onDateExpirationChange(event) {
|
||||
|
||||
this.showDuration = event.detail.checked;
|
||||
|
||||
if(event.detail.checked) {
|
||||
this.expirationDate = new Date();
|
||||
}
|
||||
else {
|
||||
this.expirationDate = null;
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
if(this.link) {
|
||||
this.viewContainerRef.clear();
|
||||
this.RouteService.goBack();
|
||||
this.dataService.set("link", false);
|
||||
} else {
|
||||
if(this.roomId) {
|
||||
this.backToChat.emit({roomId: this.roomId});
|
||||
this.viewContainerRef.clear();
|
||||
} else {
|
||||
this.viewContainerRef.clear();
|
||||
this.closeAllDesktopComponents.emit();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async createGroup() {
|
||||
this.createGroup1()
|
||||
}
|
||||
|
||||
async createGroup1() {
|
||||
const result = await this.ChatServiceService.createRoom({
|
||||
roomName: this.groupName,
|
||||
createdBy: SessionStore.user.UserId,
|
||||
roomType: 0,
|
||||
expirationDate: this.expirationDate?.toISOString() ? UDate.GetDateWithTimeZone(this.expirationDate) : null,
|
||||
members: []
|
||||
})
|
||||
|
||||
if(result.isOk()) {
|
||||
await this.ChatServiceService.getRoomById(result.value.id)
|
||||
this.addGroupMessage.emit(result.value.id);
|
||||
} else if(result.error instanceof HttpErrorResponse) {
|
||||
this.httpErrorHandle.httpStatusHandle(result.error)
|
||||
} else {
|
||||
this.toastService._badRequest('Por favor, contacta um administrador.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
createGroupWithAttachmentsCath(res: any) {
|
||||
// if(!this.ChatSystemService.getGroupRoom(res.result.rid)) {
|
||||
// setTimeout(() => {
|
||||
// this.createGroupWithAttachmentsCath(res)
|
||||
// }, 1500)
|
||||
// } else {
|
||||
// this.createGroupWithAttachments(res)
|
||||
// }
|
||||
}
|
||||
|
||||
createGroupWithAttachments(res: any) {
|
||||
// this.ChatSystemService.getGroupRoom(res.result.rid).hasLoadHistory = true;
|
||||
|
||||
// if(this.documents) {
|
||||
// this.documents.forEach(element => {
|
||||
// this.ChatSystemService.getGroupRoom(res.result.rid).send({
|
||||
// file: {
|
||||
// "name": element.Assunto,
|
||||
// "type": "application/webtrix",
|
||||
// "ApplicationId": element.ApplicationId,
|
||||
// "DocId": element.DocId,
|
||||
// "Assunto": element.Assunto,
|
||||
// },
|
||||
// temporaryData: {
|
||||
// data: {
|
||||
// selected: {
|
||||
// Id: element.DocId,
|
||||
// ApplicationType: element.ApplicationId
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// attachments: [{
|
||||
// "title": element.Assunto,
|
||||
// "description": element.Assunto,
|
||||
// "title_link_download": true,
|
||||
// "type": "webtrix",
|
||||
// "text": element.Assunto,
|
||||
// "thumb_url": "https://static.ichimura.ed.jp/uploads/2017/10/pdf-icon.png",
|
||||
// }],
|
||||
// })
|
||||
// });
|
||||
// }
|
||||
|
||||
|
||||
// this.ChatSystemService.getAllRooms();
|
||||
|
||||
// setTimeout(() => {
|
||||
// this.groupName = ""
|
||||
// }, 150);
|
||||
}
|
||||
|
||||
|
||||
async setDuration(ev: any) {
|
||||
const popover = await this.popoverController.create({
|
||||
component: GroupDurationPage,
|
||||
cssClass: 'group-duration',
|
||||
event: ev,
|
||||
translucent: true
|
||||
});
|
||||
return await popover.present();
|
||||
}
|
||||
|
||||
async showPicker() {
|
||||
const picker = await this.pickerController.create({
|
||||
cssClass: '',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancelar', role: 'cancel', cssClass: 'btn-cancel'
|
||||
},
|
||||
{
|
||||
text: 'Ok',
|
||||
cssClass: 'btn-cancel',
|
||||
handler:(value:any)=>{
|
||||
|
||||
let now = new Date();
|
||||
this.expirationDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() + value.days.value, now.getHours() + value.hours.value, now.getMinutes() + value.minutes.value, now.getSeconds(), now.getMilliseconds())
|
||||
|
||||
this.selectedDuration = [
|
||||
value.days.value,
|
||||
value.hours.value,
|
||||
value.minutes.value,
|
||||
]
|
||||
|
||||
if(value.days.value != null && value.hours.value != null && value.minutes.value != null){
|
||||
if(value.days.value > 0){
|
||||
if(value.days.value == 1){
|
||||
if(value.hours.value == 1){
|
||||
this.displayDuration = value.days.value + " day " +
|
||||
value.hours.value + " hora " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
else{
|
||||
this.displayDuration = value.days.value + " days " +
|
||||
value.hours.value + " horas " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(value.hours.value == 1){
|
||||
this.displayDuration = value.days.value + " days " +
|
||||
value.hours.value + " hora " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
else{
|
||||
this.displayDuration = value.days.value + " days " +
|
||||
value.hours.value + " horas " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(value.hours.value == 1){
|
||||
this.displayDuration = value.hours.value + " hora " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
else{
|
||||
this.displayDuration = value.hours.value + " horas " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
name: 'days',
|
||||
prefix: 'Dias',
|
||||
options: [
|
||||
{ text: '0', value: 0 },
|
||||
{ text: '1', value: 1 },
|
||||
{ text: '2', value: 2 },
|
||||
{ text: '3', value: 3 },
|
||||
{ text: '4', value: 4 },
|
||||
{ text: '5', value: 5 },
|
||||
{ text: '6', value: 6 },
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'hours',
|
||||
prefix: 'Horas',
|
||||
options: [
|
||||
{ text: '0', value: 0 },
|
||||
{ text: '1', value: 1 },
|
||||
{ text: '2', value: 2 },
|
||||
{ text: '3', value: 3 },
|
||||
{ text: '4', value: 4 },
|
||||
{ text: '5', value: 5 },
|
||||
{ text: '6', value: 6 },
|
||||
{ text: '7', value: 7 },
|
||||
{ text: '8', value: 8 },
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'minutes',
|
||||
prefix: 'Minutos',
|
||||
selectedIndex: 0,
|
||||
options: [
|
||||
{ text: '5', value: 5 },
|
||||
{ text: '10', value: 10 },
|
||||
{ text: '15', value: 15 },
|
||||
{ text: '20', value: 20 },
|
||||
{ text: '25', value: 25 },
|
||||
{ text: '30', value: 30 },
|
||||
{ text: '35', value: 35 },
|
||||
{ text: '45', value: 45 },
|
||||
{ text: '50', value: 50 },
|
||||
{ text: '55', value: 55 },
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
await picker.present();
|
||||
picker.onDidDismiss().then(async data => {
|
||||
let day = await picker.getColumn('days');
|
||||
let hour = await picker.getColumn('hours');
|
||||
let minutes = await picker.getColumn('minutes');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ChatDebuggingPage } from './chat-debugging.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ChatDebuggingPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ChatDebuggingPageRoutingModule {}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatDebuggingPageRoutingModule } from './chat-debugging-routing.module';
|
||||
|
||||
import { ChatDebuggingPage } from './chat-debugging.page';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ChatDebuggingPageRoutingModule
|
||||
],
|
||||
declarations: [ChatDebuggingPage]
|
||||
})
|
||||
export class ChatDebuggingPageModule {}
|
||||
@@ -0,0 +1,9 @@
|
||||
<!-- <ion-content>
|
||||
<ul>
|
||||
<li>Chat login</li>
|
||||
<li>Chat user list {{ ChatSystemService.users | json }}</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li *ngFor="let room of ChatSystemService._dm">chat Name: {{room.name}}; subcribe: {{room.status.receive.message}}; </li>
|
||||
</ul>
|
||||
</ion-content> -->
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatDebuggingPage } from './chat-debugging.page';
|
||||
|
||||
describe('ChatDebuggingPage', () => {
|
||||
let component: ChatDebuggingPage;
|
||||
let fixture: ComponentFixture<ChatDebuggingPage>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChatDebuggingPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ChatDebuggingPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-chat-debugging',
|
||||
templateUrl: './chat-debugging.page.html',
|
||||
styleUrls: ['./chat-debugging.page.scss'],
|
||||
})
|
||||
export class ChatDebuggingPage implements OnInit {
|
||||
|
||||
constructor(
|
||||
// public ChatSystemService: ChatSystemService
|
||||
) { }
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ChatMessageDebuggingPage } from './chat-message-debugging.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ChatMessageDebuggingPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ChatMessageDebuggingPageRoutingModule {}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatMessageDebuggingPageRoutingModule } from './chat-message-debugging-routing.module';
|
||||
|
||||
import { ChatMessageDebuggingPage } from './chat-message-debugging.page';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ChatMessageDebuggingPageRoutingModule
|
||||
],
|
||||
declarations: [ChatMessageDebuggingPage]
|
||||
})
|
||||
export class ChatMessageDebuggingPageModule {}
|
||||
@@ -0,0 +1,10 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>chatMessageDebugging</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<button (click)="loadHistory()">Load History</button>
|
||||
</ion-content>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatMessageDebuggingPage } from './chat-message-debugging.page';
|
||||
|
||||
describe('ChatMessageDebuggingPage', () => {
|
||||
let component: ChatMessageDebuggingPage;
|
||||
let fixture: ComponentFixture<ChatMessageDebuggingPage>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChatMessageDebuggingPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ChatMessageDebuggingPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { NavParams } from '@ionic/angular';
|
||||
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-chat-message-debugging',
|
||||
templateUrl: './chat-message-debugging.page.html',
|
||||
styleUrls: ['./chat-message-debugging.page.scss'],
|
||||
})
|
||||
export class ChatMessageDebuggingPage implements OnInit {
|
||||
|
||||
roomId: string
|
||||
|
||||
constructor(
|
||||
// public ChatSystemService: ChatSystemService,
|
||||
private navParams: NavParams
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.roomId = this.navParams.get('roomId')
|
||||
|
||||
|
||||
}
|
||||
|
||||
loadHistory() {
|
||||
// this.ChatSystemService.getDmRoom(this.roomId).loadHistory({});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ChatOptionsPopoverPage } from './chat-options-popover.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ChatOptionsPopoverPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ChatOptionsPopoverPageRoutingModule {}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatOptionsPopoverPageRoutingModule } from './chat-options-popover-routing.module';
|
||||
|
||||
import { ChatOptionsPopoverPage } from './chat-options-popover.page';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ChatOptionsPopoverPageRoutingModule
|
||||
],
|
||||
declarations: [ChatOptionsPopoverPage],
|
||||
exports: [ChatOptionsPopoverPage]
|
||||
})
|
||||
export class ChatOptionsPopoverPageModule {}
|
||||
@@ -0,0 +1,19 @@
|
||||
<ion-content class="container">
|
||||
<div class="arrow-right">
|
||||
<button class="btn-no-color" (click)="close()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' "slot="end" class="arrow-right-icon" src='assets/images/icons-arrow-arrow-right.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" class="arrow-right-icon" src='assets/images/theme/gov/icons-calendar-arrow-right.svg'></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<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)="anexarFoto()" full class="btn-ok" shape="round" >Anexar Fotografia</button>
|
||||
<button (click)="addDocGestaoDocumental()" class="btn-ok" shape="round" >Gestão Documental</button>
|
||||
<div class="solid"></div>
|
||||
|
||||
<!-- <button *ngIf="p.userPermission([p.permissionList.Agenda.access]) == true " (click)="bookMeeting()" class="btn-ok" shape="round" >Novo Evento</button> -->
|
||||
<button (click)="close()" full class="btn-cancel" shape="round" >Cancelar</button>
|
||||
</div>
|
||||
|
||||
</ion-content>
|
||||
@@ -0,0 +1,50 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
|
||||
.container{
|
||||
--padding-top:20px !important;
|
||||
--padding-bottom:20px !important;
|
||||
--padding-start:20px !important;
|
||||
--padding-end:20px !important;
|
||||
}
|
||||
.arrow-right{
|
||||
display: none;
|
||||
margin-bottom: 20px;
|
||||
.arrow-right-icon{
|
||||
width: 37px;
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
.buttons{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
.btn-ok, .btn-cancel, .btn-delete{
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
}
|
||||
.solid {
|
||||
display: none;
|
||||
width: 90%;
|
||||
border-top: 1px solid #bbb;
|
||||
margin: 0 auto !important;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@media only screen and (min-width: 1024px) {
|
||||
.arrow-right{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.btn-cancel{
|
||||
display: none;
|
||||
}
|
||||
.btn-ok{
|
||||
width: 100% !important;
|
||||
}
|
||||
.mobile-only{
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatOptionsPopoverPage } from './chat-options-popover.page';
|
||||
|
||||
describe('ChatOptionsPopoverPage', () => {
|
||||
let component: ChatOptionsPopoverPage;
|
||||
let fixture: ComponentFixture<ChatOptionsPopoverPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChatOptionsPopoverPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ChatOptionsPopoverPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,133 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ModalController, NavParams, PopoverController } from '@ionic/angular';
|
||||
import { EventPerson } from 'src/app/models/eventperson.model';
|
||||
import { SearchList } from 'src/app/models/search-document';
|
||||
import { NewEventPage } from 'src/app/pages/agenda/new-event/new-event.page';
|
||||
import { SearchPage } from 'src/app/pages/search/search.page';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
import { PermissionService } from 'src/app/services/permission.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-chat-options-popover',
|
||||
templateUrl: './chat-options-popover.page.html',
|
||||
styleUrls: ['./chat-options-popover.page.scss'],
|
||||
})
|
||||
export class ChatOptionsPopoverPage implements OnInit {
|
||||
|
||||
documents:SearchList[] = [];
|
||||
members: any;
|
||||
attendees: EventPerson[] = [];
|
||||
|
||||
constructor(
|
||||
private popoverController: PopoverController,
|
||||
private modalController: ModalController,
|
||||
private navParams: NavParams,
|
||||
public ThemeService: ThemeService,
|
||||
public p: PermissionService,
|
||||
) {
|
||||
|
||||
this.members = this.navParams.get('members');
|
||||
|
||||
if(this.members) {
|
||||
this.attendees = this.navParams.get('members').map((val)=>{
|
||||
return {
|
||||
Name: val.name,
|
||||
EmailAddress: val.username+"@"+environment.domain,
|
||||
IsRequired: "true",
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
takePicture(){
|
||||
if( window.innerWidth < 701){
|
||||
this.popoverController.dismiss('take-picture');
|
||||
}
|
||||
else{
|
||||
this.modalController.dismiss('take-picture');
|
||||
}
|
||||
}
|
||||
|
||||
addFile(){
|
||||
if( window.innerWidth < 701){
|
||||
this.popoverController.dismiss('add-document');
|
||||
}
|
||||
else{
|
||||
this.modalController.dismiss('add-document');
|
||||
}
|
||||
}
|
||||
|
||||
anexarFoto(){
|
||||
if( window.innerWidth < 701){
|
||||
this.popoverController.dismiss('add-picture');
|
||||
}
|
||||
else{
|
||||
this.modalController.dismiss('add-picture');
|
||||
}
|
||||
}
|
||||
|
||||
addDocGestaoDocumental(){
|
||||
if( window.innerWidth < 701){
|
||||
this.popoverController.dismiss('documentoGestaoDocumental');
|
||||
}
|
||||
else{
|
||||
this.modalController.dismiss('documentoGestaoDocumental');
|
||||
}
|
||||
}
|
||||
|
||||
close(){
|
||||
if( window.innerWidth < 701){
|
||||
this.popoverController.dismiss();
|
||||
}
|
||||
else{
|
||||
this.modalController.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
attachDocument(){
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
async getDoc(){
|
||||
const modal = await this.modalController.create({
|
||||
component: SearchPage,
|
||||
cssClass: 'group-messages modal-desktop search-modal search-modal-to-desktop',
|
||||
componentProps: {
|
||||
type: 'AccoesPresidenciais & ArquivoDespachoElect',
|
||||
select: true,
|
||||
showSearchInput: true,
|
||||
}
|
||||
});
|
||||
|
||||
modal.onDidDismiss().then((res)=>{
|
||||
if(res) {
|
||||
const data = res.data;
|
||||
this.documents.push(data.selected);
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
await modal.present();
|
||||
}
|
||||
|
||||
async bookMeeting() {
|
||||
|
||||
if( window.innerWidth < 701){
|
||||
this.popoverController.dismiss('meeting');
|
||||
}
|
||||
else{
|
||||
this.modalController.dismiss('meeting');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ChatPopoverPage } from './chat-popover.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ChatPopoverPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ChatPopoverPageRoutingModule {}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatPopoverPageRoutingModule } from './chat-popover-routing.module';
|
||||
|
||||
import { ChatPopoverPage } from './chat-popover.page';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ChatPopoverPageRoutingModule
|
||||
],
|
||||
exports: [ChatPopoverPage],
|
||||
declarations: [ChatPopoverPage]
|
||||
})
|
||||
export class ChatPopoverPageModule {}
|
||||
@@ -0,0 +1,32 @@
|
||||
<ion-content class="options-container">
|
||||
<div class="arrow-right header-fix">
|
||||
<button class="btn-no-color" (click)="close('cancel')">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" class="arrow-right-icon"
|
||||
src='assets/images/icons-arrow-arrow-right.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" class="arrow-right-icon"
|
||||
src='assets/images/theme/gov/icons-calendar-arrow-right.svg'></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<!-- <button *ngIf="isAdmin" (click)="addUser()" class="btn-cancel" shape="round">Adicionar</button>
|
||||
<button (click)="leaveGroup()" class="btn-cancel" shape="round">Sair do Grupo</button>
|
||||
<button *ngIf="isAdmin" (click)="openChangeGroupName()" class="btn-cancel btn-cancel mt-10" shape="round" style="min-width: 192px;">Alterar
|
||||
nome do grupo</button>
|
||||
<div class="solid"></div>
|
||||
<button (click)="close('cancel')" full class="btn-cancel mobile-only" shape="round">Cancelar</button>
|
||||
<button *ngIf="isAdmin" (click)="deleteGroup()" class="btn-delete" shape="round">Apagar grupo</button>
|
||||
-->
|
||||
|
||||
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
|
||||
<br *ngIf="showLoader">
|
||||
<button (click)="details()" class="btn-cancel" shape="round">Detalhes</button>
|
||||
<button *ngIf="isAdmin && roomType == EnumRoomType.Group" (click)="addUser()" class="btn-cancel" shape="round">Adicionar</button>
|
||||
<button *ngIf="roomType == EnumRoomType.Group" (click)="leaveGroup()" class="btn-cancel" shape="round">Sair do Grupo</button>
|
||||
<button *ngIf="isAdmin && roomType == EnumRoomType.Group" (click)="openChangeGroupName()" class="btn-cancel btn-cancel mt-10" shape="round" style="min-width: 192px;">Alterar
|
||||
nome do grupo</button>
|
||||
<button *ngIf="isAdmin && roomType == EnumRoomType.Group" (click)="setRoomOwner()" class="btn-cancel" shape="round">Adicionar admin</button>
|
||||
<div class="solid"></div>
|
||||
<button (click)="close('cancel')" full class="btn-cancel mobile-only" shape="round">Cancelar</button>
|
||||
<button *ngIf="isAdmin && roomType == EnumRoomType.Group" (click)="deleteGroup()" class="btn-delete" shape="round">Apagar grupo</button>
|
||||
</div>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,58 @@
|
||||
.options-container{
|
||||
--padding-top:20px !important;
|
||||
--padding-bottom:20px !important;
|
||||
--padding-start:20px !important;
|
||||
--padding-end:20px !important;
|
||||
}
|
||||
.arrow-right{
|
||||
display: none;
|
||||
margin-bottom: 20px;
|
||||
.arrow-right-icon{
|
||||
width: 37px;
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.solid {
|
||||
display: block;
|
||||
width: 90%;
|
||||
border-top: 1px solid #bbb;
|
||||
margin: 10px auto !important;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 701px) {
|
||||
.arrow-right{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.btn-cancel{
|
||||
//display: none;
|
||||
width: 100% !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
.btn-cancel:hover, .btn-delete:hover{
|
||||
background-color: var(--button-hover);
|
||||
color: #fff !important;
|
||||
}
|
||||
.btn-ok{
|
||||
width: 100% !important;
|
||||
}
|
||||
.btn-delete{
|
||||
width: 100% !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
.solid{
|
||||
display: block;
|
||||
}
|
||||
.mobile-only{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatPopoverPage } from './chat-popover.page';
|
||||
|
||||
describe('ChatPopoverPage', () => {
|
||||
let component: ChatPopoverPage;
|
||||
let fixture: ComponentFixture<ChatPopoverPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChatPopoverPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ChatPopoverPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,171 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ModalController, NavParams, PopoverController } from '@ionic/angular';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
import { SetRoomOwnerPage } from 'src/app/ui/chat/modal/set-room-owner/set-room-owner.page';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { ZodError } from 'zod';
|
||||
|
||||
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service'
|
||||
import { RoomInfoPage } from '../room-info/room-info.page';
|
||||
import { RoomType } from 'src/app/core/chat/entity/group';
|
||||
import { isHttpResponse } from 'src/app/infra/http/http.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-chat-popover',
|
||||
templateUrl: './chat-popover.page.html',
|
||||
styleUrls: ['./chat-popover.page.scss'],
|
||||
})
|
||||
export class ChatPopoverPage implements OnInit {
|
||||
roomId:string;
|
||||
room: any;
|
||||
isAdmin = false;
|
||||
isGroupCreated: boolean;
|
||||
showLoader = false
|
||||
EnumRoomType = RoomType
|
||||
roomType!: RoomType
|
||||
|
||||
constructor(
|
||||
private popoverController: PopoverController,
|
||||
private modalController: ModalController,
|
||||
private navParams: NavParams,
|
||||
private toastService: ToastService,
|
||||
public ThemeService: ThemeService,
|
||||
private ChatServiceService: ChatServiceService
|
||||
) {
|
||||
this.roomId = this.navParams.get('roomId');
|
||||
this.isAdmin = this.navParams.get('isAdmin');
|
||||
this.roomType = this.navParams.get('roomType');
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
// this.chatService.refreshtoken();
|
||||
}
|
||||
|
||||
close(action:any){
|
||||
if( window.innerWidth < 701){
|
||||
this.popoverController.dismiss(action);
|
||||
}
|
||||
else{
|
||||
this.modalController.dismiss(action)
|
||||
}
|
||||
}
|
||||
|
||||
//Top menu options
|
||||
//Close
|
||||
|
||||
async setRoomOwner() {
|
||||
let classs;
|
||||
if (window.innerWidth < 701) {
|
||||
classs = 'modal modal-desktop'
|
||||
} else {
|
||||
classs = 'centered-rounded-modal'
|
||||
}
|
||||
const modal = await this.modalController.create({
|
||||
component: SetRoomOwnerPage,
|
||||
cssClass: classs,
|
||||
backdropDismiss: true,
|
||||
componentProps: {
|
||||
roomId: this.roomId,
|
||||
isAdmin: this.isAdmin
|
||||
}
|
||||
});
|
||||
await modal.present();
|
||||
modal.onDidDismiss().then((res)=>{
|
||||
if(res.data == 'success'){
|
||||
this.leaveGroup();
|
||||
//this.ChatSystemService.hidingRoom(this.roomId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
setAdmin() {
|
||||
this.setRoomOwner();
|
||||
}
|
||||
|
||||
async leaveGroup() {
|
||||
|
||||
//this.setRoomOwner();
|
||||
this.showLoader = true
|
||||
const result = await this.ChatServiceService.leaveRoom({
|
||||
id: this.roomId,
|
||||
members: [SessionStore.user.UserId]
|
||||
})
|
||||
|
||||
|
||||
if(result.isOk()) {
|
||||
this.close('leave');
|
||||
// this.openGroupMessage.emit(this.roomId);
|
||||
} else if (isHttpResponse(result.error)) {
|
||||
if(result.error.status == 404) {
|
||||
this.close('leave');
|
||||
}
|
||||
// this.httpErrorHandle.httpStatusHandle(result.error)
|
||||
} else if (result.error instanceof ZodError) {
|
||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||
console.log(result.error.errors)
|
||||
} else {
|
||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||
console.log(result.error)
|
||||
}
|
||||
|
||||
this.showLoader = false
|
||||
}
|
||||
|
||||
//Delete
|
||||
async deleteGroup() {
|
||||
this.showLoader = true
|
||||
|
||||
const result = await this.ChatServiceService.deleteRoomById(this.roomId)
|
||||
|
||||
|
||||
if(result.isOk()) {
|
||||
this.close('delete');
|
||||
// this.openGroupMessage.emit(this.roomId);
|
||||
} else if (isHttpResponse(result.error)) {
|
||||
if(result.error.status == 404) {
|
||||
this.close('close');
|
||||
}
|
||||
} else if (result.error instanceof ZodError) {
|
||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||
console.log(result.error.errors)
|
||||
} else {
|
||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||
console.log(result.error)
|
||||
}
|
||||
|
||||
this.showLoader = false
|
||||
|
||||
}
|
||||
|
||||
async openChangeGroupName(){
|
||||
this.close('edit');
|
||||
}
|
||||
|
||||
|
||||
async addUser() {
|
||||
this.close('addUser');
|
||||
}
|
||||
|
||||
|
||||
async details() {
|
||||
const modal = await this.modalController.create({
|
||||
component: RoomInfoPage,
|
||||
cssClass: 'modal-aside',
|
||||
backdropDismiss: true,
|
||||
componentProps: {
|
||||
roomId: this.roomId
|
||||
}
|
||||
});
|
||||
await modal.present();
|
||||
modal.onDidDismiss().then((res)=>{
|
||||
if(res.data == 'success') {
|
||||
this.leaveGroup();
|
||||
//this.ChatSystemService.hidingRoom(this.roomId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { EditGroupPage } from './edit-group.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: EditGroupPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class EditGroupPageRoutingModule {}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { EditGroupPageRoutingModule } from './edit-group-routing.module';
|
||||
|
||||
import { EditGroupPage } from './edit-group.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
|
||||
import { BtnSeguintePageModule } from 'src/app/shared/btn-seguinte/btn-seguinte.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
|
||||
EditGroupPageRoutingModule,
|
||||
BtnSeguintePageModule,
|
||||
],
|
||||
declarations: [EditGroupPage]
|
||||
})
|
||||
export class EditGroupPageModule {}
|
||||
@@ -0,0 +1,44 @@
|
||||
<ion-header class="ion-no-border">
|
||||
<ion-toolbar class="header-toolbar">
|
||||
<div class="main-header">
|
||||
<div class="title-content width-100">
|
||||
<div class="left">
|
||||
<button class="btn-no-color" (click)="close()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="end" src='assets/images/theme/{{ThemeService.currentTheme}}/icons-calendar-arrow-left.svg'></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="middle">
|
||||
<ion-label class="title">Alterar assunto</ion-label>
|
||||
</div>
|
||||
<app-btn-seguinte *ngIf="groupName" (click)="changeGroupName()"></app-btn-seguinte>
|
||||
</div>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<div class="main-content">
|
||||
<div class="item-container">
|
||||
<ion-input [(ngModel)]="groupName" placeholder="Título"></ion-input>
|
||||
</div>
|
||||
<div *ngIf="false" class="item-container-no-border">
|
||||
<ion-checkbox (ionChange)="_ionChange($event)" color="primary"></ion-checkbox>
|
||||
<ion-label>Grupo Ultra-secreto</ion-label>
|
||||
</div>
|
||||
|
||||
<div *ngIf="showDuration" class="container-div">
|
||||
<div class="ion-item-class-2">
|
||||
<div class="ion-icon-class">
|
||||
<ion-icon slot="start" src="assets/images/icons-duration.svg"></ion-icon>
|
||||
</div>
|
||||
<div class="ion-input-class">
|
||||
<ion-input (click)="showPicker()" [(ngModel)]="displayDuration" placeholder="Duração"></ion-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ion-content>
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
ion-content{
|
||||
--background:transparent;
|
||||
}
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
}
|
||||
.div-top-header{
|
||||
width: 400px;
|
||||
margin: 0 auto;
|
||||
background-color: #0782c9;
|
||||
overflow: auto;
|
||||
padding-top: 15px;
|
||||
border: 0!important;
|
||||
|
||||
.div-search{
|
||||
font-size: rem(45);
|
||||
float: left;
|
||||
margin: 0 0 0 10px
|
||||
}
|
||||
.div-logo{
|
||||
background: transparent;
|
||||
width: 140px;
|
||||
margin: 5px 0 0px 71px;
|
||||
float: left;
|
||||
}
|
||||
.div-logo img{
|
||||
width: 100%;
|
||||
}
|
||||
.div-profile{
|
||||
font-size: rem(45);
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
.main-header{
|
||||
width: 100%; /* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
border-top-left-radius: 25px;
|
||||
border-top-right-radius: 25px;
|
||||
background-color: #fff;
|
||||
overflow:hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.title-content{
|
||||
margin: 0px auto;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
background: #fff;
|
||||
|
||||
.left{
|
||||
width: 37px;
|
||||
float: left;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
}
|
||||
.middle{
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
width: 221px;
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.right{
|
||||
padding: 0!important;
|
||||
float: right;
|
||||
font-size: rem(15);
|
||||
color: #0782c9;
|
||||
margin: 8px 0 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
}
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
.main-content{
|
||||
width: 100%; /* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
overflow:auto;
|
||||
padding: 15px 20px 0 20px;
|
||||
|
||||
.item-container{
|
||||
width: 360px;
|
||||
margin: 15px auto;
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 5px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.item-container-no-border{
|
||||
display: flex;
|
||||
width: 360px;
|
||||
margin: 25px auto;
|
||||
border-radius: 5px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-container-no-border ion-label{
|
||||
padding-left: 10px;
|
||||
font-size: rem(12);
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.container-div{
|
||||
margin-bottom: 15px;
|
||||
overflow: auto;
|
||||
|
||||
.ion-item-class-2{
|
||||
width: 360px;
|
||||
margin: 0px auto;
|
||||
|
||||
.ion-icon-class{
|
||||
width: rem(45);
|
||||
height: rem(45);
|
||||
float: left;
|
||||
padding: 10px;
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
.ion-input-class{
|
||||
width: 315px;
|
||||
height: rem(45);
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 5px;
|
||||
padding-left: 5px;
|
||||
padding-right: 10px;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { EditGroupPage } from './edit-group.page';
|
||||
|
||||
describe('EditGroupPage', () => {
|
||||
let component: EditGroupPage;
|
||||
let fixture: ComponentFixture<EditGroupPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ EditGroupPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(EditGroupPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,171 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ModalController, NavParams, PickerController } from '@ionic/angular';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-edit-group',
|
||||
templateUrl: './edit-group.page.html',
|
||||
styleUrls: ['./edit-group.page.scss'],
|
||||
})
|
||||
export class EditGroupPage implements OnInit {
|
||||
showLoader: boolean;
|
||||
displayDuration: any;
|
||||
showDuration: boolean;
|
||||
selectedDuration = ['','',''];
|
||||
groupName:string;
|
||||
room:any;
|
||||
roomId:string;
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
private pickerController: PickerController,
|
||||
private navParams: NavParams,
|
||||
public ThemeService: ThemeService
|
||||
) {
|
||||
this.roomId = this.navParams.get('roomId');
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
// this.chatService.refreshtoken();
|
||||
this.getRoomInfo();
|
||||
}
|
||||
|
||||
getRoomInfo(){
|
||||
|
||||
}
|
||||
|
||||
close(){
|
||||
this.modalController.dismiss();
|
||||
}
|
||||
|
||||
changeGroupName(){
|
||||
if(this.groupName.trim().length > 1){
|
||||
let name = this.groupName.split(' ').join('-');
|
||||
let body = {
|
||||
"roomId": this.room._id,
|
||||
"name": name,
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
}
|
||||
}
|
||||
_ionChange(event){
|
||||
this.showDuration = event.detail.checked;
|
||||
}
|
||||
async showPicker(){
|
||||
const picker = await this.pickerController.create({
|
||||
cssClass: '',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancelar', role: 'cancel', cssClass: 'btn-cancel'
|
||||
},
|
||||
{
|
||||
text: 'Ok',
|
||||
cssClass: 'btn-cancel',
|
||||
handler:(value:any)=>{
|
||||
|
||||
this.selectedDuration = [
|
||||
value.days.value,
|
||||
value.hours.value,
|
||||
value.minutes.value,
|
||||
]
|
||||
|
||||
if(value.days.value != null && value.hours.value != null && value.minutes.value != null){
|
||||
if(value.days.value > 0){
|
||||
if(value.days.value == 1){
|
||||
if(value.hours.value == 1){
|
||||
this.displayDuration = value.days.value + " day " +
|
||||
value.hours.value + " hora " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
else{
|
||||
this.displayDuration = value.days.value + " days " +
|
||||
value.hours.value + " horas " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(value.hours.value == 1){
|
||||
this.displayDuration = value.days.value + " days " +
|
||||
value.hours.value + " hora " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
else{
|
||||
this.displayDuration = value.days.value + " days " +
|
||||
value.hours.value + " horas " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(value.hours.value == 1){
|
||||
this.displayDuration = value.hours.value + " hora " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
else{
|
||||
this.displayDuration = value.hours.value + " horas " +
|
||||
value.minutes.value + " minutos";
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
name: 'days',
|
||||
prefix: 'Dias',
|
||||
options: [
|
||||
{ text: '0', value: 0 },
|
||||
{ text: '1', value: 1 },
|
||||
{ text: '2', value: 2 },
|
||||
{ text: '3', value: 3 },
|
||||
{ text: '4', value: 4 },
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'hours',
|
||||
prefix: 'Horas',
|
||||
options: [
|
||||
{ text: '0', value: 0 },
|
||||
{ text: '1', value: 1 },
|
||||
{ text: '2', value: 2 },
|
||||
{ text: '3', value: 3 },
|
||||
{ text: '4', value: 4 },
|
||||
{ text: '5', value: 5 },
|
||||
{ text: '6', value: 6 },
|
||||
{ text: '7', value: 7 },
|
||||
{ text: '8', value: 8 },
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'minutes',
|
||||
prefix: 'Minutos',
|
||||
selectedIndex: 0,
|
||||
options: [
|
||||
{ text: '5', value: 5 },
|
||||
{ text: '10', value: 10 },
|
||||
{ text: '15', value: 15 },
|
||||
{ text: '20', value: 20 },
|
||||
{ text: '25', value: 25 },
|
||||
{ text: '30', value: 30 },
|
||||
{ text: '35', value: 35 },
|
||||
{ text: '45', value: 45 },
|
||||
{ text: '50', value: 50 },
|
||||
{ text: '55', value: 55 },
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
await picker.present();
|
||||
picker.onDidDismiss().then(async data =>{
|
||||
let day = await picker.getColumn('days');
|
||||
let hour = await picker.getColumn('hours');
|
||||
let minutes = await picker.getColumn('minutes');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { EditMessagePage } from './edit-message.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: EditMessagePage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class EditMessagePageRoutingModule {}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { EditMessagePageRoutingModule } from './edit-message-routing.module';
|
||||
|
||||
import { EditMessagePage } from './edit-message.page';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
EditMessagePageRoutingModule
|
||||
],
|
||||
declarations: [EditMessagePage]
|
||||
})
|
||||
export class EditMessagePageModule {}
|
||||
@@ -0,0 +1,49 @@
|
||||
<ion-header class="ion-no-border">
|
||||
<ion-toolbar class="header-toolbar">
|
||||
<div class="main-header">
|
||||
<div class="title-content width-100">
|
||||
<div class="back-icon">
|
||||
<button class="btn-no-color cursor-pointer" (click)="dismiss()" >
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="end" src='assets/images/theme/{{ThemeService.currentTheme}}/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="div-title">
|
||||
<ion-label class="title">Editar Mensagem</ion-label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
|
||||
<div class="main-content">
|
||||
|
||||
<div class="old-message-container d-flex justify-center">
|
||||
<div class="old-message" style="white-space: pre-line;">{{ oldMessage }}</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="d-flex align-center mt-40-em mb-40-em mr-20">
|
||||
<div class="type-message flex-1 ml-30 mr-20">
|
||||
<ion-textarea
|
||||
#messageInput
|
||||
placeholder="Escrever uma mensagem"
|
||||
class="message-input "
|
||||
rows="1"
|
||||
autoGrow="true"
|
||||
[(ngModel)]="message"
|
||||
(keyup.enter)="save()"
|
||||
clearOnEdit="false"
|
||||
></ion-textarea>
|
||||
</div>
|
||||
<button class="btn-no-color" (click)="save()">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header{
|
||||
width: 100%; /* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
border-top-left-radius: 25px;
|
||||
border-top-right-radius: 25px;
|
||||
background-color: #fff;
|
||||
overflow:hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.title-content{
|
||||
margin: 0px auto;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.back-icon{
|
||||
width: 37px;
|
||||
float: left;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
|
||||
}
|
||||
.div-title{
|
||||
width: calc(100% - 45px);
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ion-content{
|
||||
--background:transparent;
|
||||
}
|
||||
.main-content{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
overflow:auto;
|
||||
padding: 0 0 0 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.type-message {
|
||||
display: flex;
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 25px;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.old-message-container {
|
||||
padding: 40px;
|
||||
}
|
||||
.old-message {
|
||||
font-size: rem(13);
|
||||
font-family: Roboto;
|
||||
overflow: auto;
|
||||
background: var(--chat-incoming-msg-color);
|
||||
border-radius: 10px;
|
||||
display: inline;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { EditMessagePage } from './edit-message.page';
|
||||
|
||||
describe('EditMessagePage', () => {
|
||||
let component: EditMessagePage;
|
||||
let fixture: ComponentFixture<EditMessagePage>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ EditMessagePage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(EditMessagePage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Component, OnInit, Input, ViewChild, ElementRef } from '@angular/core';
|
||||
import { ModalController, PopoverController } from '@ionic/angular';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-edit-message',
|
||||
templateUrl: './edit-message.page.html',
|
||||
styleUrls: ['./edit-message.page.scss'],
|
||||
})
|
||||
export class EditMessagePage implements OnInit {
|
||||
|
||||
@ViewChild('messageInput', { static: false }) messageInput!: ElementRef<HTMLIonTextareaElement>;
|
||||
@Input() message: string;
|
||||
@Input() roomId: any;
|
||||
|
||||
oldMessage: string
|
||||
|
||||
constructor(
|
||||
public popoverController: PopoverController,
|
||||
public ThemeService: ThemeService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.oldMessage = this.message
|
||||
}
|
||||
ngAfterViewInit() {
|
||||
// Focus the textarea once the view has been initialized
|
||||
// this.messageInput.nativeElement.focus();
|
||||
}
|
||||
|
||||
dismiss() {
|
||||
this.popoverController.dismiss();
|
||||
}
|
||||
|
||||
save() {
|
||||
this.popoverController.dismiss({
|
||||
'message': this.message
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { GroupDurationPage } from './group-duration.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: GroupDurationPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class GroupDurationPageRoutingModule {}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupDurationPageRoutingModule } from './group-duration-routing.module';
|
||||
|
||||
import { GroupDurationPage } from './group-duration.page';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
GroupDurationPageRoutingModule
|
||||
],
|
||||
declarations: [GroupDurationPage]
|
||||
})
|
||||
export class GroupDurationPageModule {}
|
||||
@@ -0,0 +1,19 @@
|
||||
<ion-content>
|
||||
<div class="p-header">
|
||||
<h3>Duração</h3>
|
||||
</div>
|
||||
<div class="picker">
|
||||
|
||||
</div>
|
||||
<div class="p-buttons">
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<button (click)="close()" full class="btn-cancel" shape="round" >Cancelar</button>
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
<button class="btn-ok" shape="round" >Ok</button>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</div>
|
||||
|
||||
</ion-content>
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupDurationPage } from './group-duration.page';
|
||||
|
||||
describe('GroupDurationPage', () => {
|
||||
let component: GroupDurationPage;
|
||||
let fixture: ComponentFixture<GroupDurationPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ GroupDurationPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(GroupDurationPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PopoverController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-group-duration',
|
||||
templateUrl: './group-duration.page.html',
|
||||
styleUrls: ['./group-duration.page.scss'],
|
||||
})
|
||||
export class GroupDurationPage implements OnInit {
|
||||
|
||||
constructor(
|
||||
public popoverController: PopoverController,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
close(){
|
||||
this.popoverController.dismiss();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { GroupContactsPage } from './group-contacts.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: GroupContactsPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class GroupContactsPageRoutingModule {}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupContactsPageRoutingModule } from './group-contacts-routing.module';
|
||||
|
||||
import { GroupContactsPage } from './group-contacts.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
import { PipesModule } from 'src/app/pipes/pipes.module';
|
||||
|
||||
import { BtnSeguintePageModule } from 'src/app/shared/btn-seguinte/btn-seguinte.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
|
||||
PipesModule,
|
||||
GroupContactsPageRoutingModule,
|
||||
BtnSeguintePageModule,
|
||||
],
|
||||
declarations: [GroupContactsPage]
|
||||
})
|
||||
export class GroupContactsPageModule {}
|
||||
@@ -0,0 +1,65 @@
|
||||
<ion-header class="ion-no-border">
|
||||
<ion-toolbar class="header-toolbar">
|
||||
<div class="main-header">
|
||||
<div class="title-content width-100">
|
||||
<div class="back-icon">
|
||||
<button class="btn-no-color cursor-pointer" (click)="close()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " src="assets/images/theme/doneIt/icons-calendar-arrow-left.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="div-title">
|
||||
<ion-label class="title">Contactos</ion-label>
|
||||
</div>
|
||||
<app-btn-seguinte (click)="updateGroup()"></app-btn-seguinte>
|
||||
</div>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar class="toolbar-search">
|
||||
<div class="search">
|
||||
<ion-searchbar search-icon="undefined" debounce="500" (ionChange)="onChange($event)" placeholder="Pesquisar por contacto" ></ion-searchbar>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
|
||||
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
|
||||
<ion-refresher-content>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<div class="main-content">
|
||||
<div *ngIf="members">
|
||||
<ion-label class="members-label">Contactos selecção:</ion-label>
|
||||
<div class="members-list" *ngFor="let user of members">
|
||||
<ion-item-sliding [class.inactive]="sessionStore.user.UserName == user.username">
|
||||
<ion-item lines="none" class="members-checkbox ion-no-border ion-no-padding">
|
||||
<ion-checkbox checked disabled color="primary"></ion-checkbox>
|
||||
<p>{{user.name}}</p>
|
||||
<ion-icon class="{{user.status}}" name="ellipse"></ion-icon>
|
||||
</ion-item>
|
||||
<ion-item-options (click)="deleteMember(user)" class="members-options" side="end">
|
||||
<ion-item-option color="danger">Apagar</ion-item-option>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div *ngFor="let userContainer of userContainer | keyvalue;" >
|
||||
|
||||
<div class="item-divider">
|
||||
<ion-label>{{ userContainer.key }}</ion-label>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let user of userContainer.value" class="d-flex px-20 align-center">
|
||||
<ion-checkbox [(ngModel)]="user.isChecked" color="primary" (click)="selectedContact(user)"></ion-checkbox>
|
||||
<ion-label class="flex-grow-1 px-10">{{user.name}}</ion-label>
|
||||
<div class="icon"><ion-icon class="{{user.status}}" name="ellipse"></ion-icon></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,173 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header{
|
||||
width: 100%; /* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
border-top-left-radius: 25px;
|
||||
border-top-right-radius: 25px;
|
||||
background-color: #fff;
|
||||
overflow:hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.title-content{
|
||||
margin: 0px auto;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.back-icon{
|
||||
width: 37px;
|
||||
float: left;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
|
||||
}
|
||||
.div-title{
|
||||
width: 221px;
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
}
|
||||
.toolbar-search{
|
||||
--padding-top:0 !important;
|
||||
--padding-bottom:0 !important;
|
||||
--padding-start:0 !important;
|
||||
--padding-end:0 !important;
|
||||
|
||||
.search{
|
||||
border: 1px solid #ebebeb;
|
||||
margin: 5px 20px 5px 20px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.search ion-searchbar{
|
||||
/* border: 1px solid green; */
|
||||
width: 100%;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
--border-radius: 5px;
|
||||
--box-shadow: none;
|
||||
overflow: auto;
|
||||
--icon-color: var(--font-awesome);
|
||||
}
|
||||
|
||||
}
|
||||
ion-content{
|
||||
--background:transparent;
|
||||
}
|
||||
.main-content{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
overflow:auto;
|
||||
padding: 0 0 0 0;
|
||||
|
||||
.members-label{
|
||||
margin: 10px 20px 10px 20px !important;
|
||||
/* font-size: rem(15); */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.members-checkbox{
|
||||
display: flex;
|
||||
margin: 0px 20px 0px 20px !important;
|
||||
overflow: auto;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
}
|
||||
|
||||
.members-options{
|
||||
margin: 0px 20px 0px 19px !important;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.item-divider{
|
||||
background: #ebebeb;
|
||||
font-size: rem(15);
|
||||
margin: 10px 0 10px 0;
|
||||
padding:5px 0 5px 20px;
|
||||
|
||||
}
|
||||
|
||||
.item-checkbox{
|
||||
display: flex;
|
||||
margin: 10px 20px 10px 20px !important;
|
||||
overflow: auto;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
.members-checkbox ion-checkbox{
|
||||
--border-color: var(--title-text-color);
|
||||
--background-checked:var(--title-text-color);
|
||||
float: left;
|
||||
}
|
||||
|
||||
.item-checkbox ion-checkbox{
|
||||
--border-color: var(--title-text-color);
|
||||
--background-checked:var(--title-text-color);
|
||||
float: left;
|
||||
}
|
||||
|
||||
.item-checkbox p, .members-checkbox p{
|
||||
display: block;
|
||||
margin: 0 !important;
|
||||
|
||||
padding-left: 10px;
|
||||
font-size: rem(15);
|
||||
color: var(--title-text-color);
|
||||
float: left;
|
||||
}
|
||||
.item-checkbox ion-icon, .members-checkbox ion-icon{
|
||||
font-size: rem(10);
|
||||
float: left;
|
||||
color:#99e47b;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.online{
|
||||
color:#99e47b !important;
|
||||
}
|
||||
.offline{
|
||||
color:#cbced1 !important;
|
||||
}
|
||||
.away{
|
||||
color:#ffd21f !important;
|
||||
}
|
||||
.invisible{
|
||||
color:#cbced1 !important;
|
||||
}
|
||||
.busy{
|
||||
color:#f5455c !important;
|
||||
}
|
||||
}
|
||||
|
||||
.inactive {
|
||||
opacity: 0.7;
|
||||
ion-item-options {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user