remove unnecessary code

This commit is contained in:
Peter Maquiran
2024-10-18 12:12:55 +01:00
parent 8484b1b600
commit 3f41e9e9c0
102 changed files with 102 additions and 196 deletions
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ApproveEventPage } from './approve-event.page';
const routes: Routes = [
{
path: '',
component: ApproveEventPage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ApproveEventPageRoutingModule {}
@@ -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 { ApproveEventPageRoutingModule } from './approve-event-routing.module';
import { ApproveEventPage } from './approve-event.page';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
ApproveEventPageRoutingModule
],
declarations: [ApproveEventPage],
exports: [ApproveEventPage]
})
export class ApproveEventPageModule {}
@@ -0,0 +1,141 @@
<ion-content id="main-content">
<div class="main-content d-flex flex-column height-100" *ngIf="loadedEvent">
<div class="pl-20 pr-20 text-center d-flex justify-center align-center" style="width:100%; height: 30px; background-color: var(--Event-approve-header-color); border-top-right-radius: 25px;">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="right-icons font-28" src="assets/images/icons-received-event.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov'" class="right-icons font-28" src="assets/images/theme/gov/icons-received-event.svg"></ion-icon>
<!-- <ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="right-icons" src="assets/images/theme/gov/icons-received-event-selected.svg"></ion-icon> -->
<div style="color: black;">
Evento Pendente de Aprovação
</div>
<!-- List events to approve desktop -->
</div>
<div class="main-content d-flex height-100 width-100">
<div class="content d-flex flex-column">
<div class="header-content width-100 d-flex justify-space-between">
<div (click)="close()" class="header-icon-left cursor-pointer">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " 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' " src="assets/images/theme/gov/icons-calendar-arrow-left.svg"></ion-icon>
</div>
<div class="header-title flex-grow-1 cursor-pointer">
<label>{{loadedEvent.workflowInstanceDataFields.Subject}}</label>
</div>
<div (click)="editar(loadedEvent.serialNumber)" class="header-icon-right display-none-{{showAside}}" *ngIf="p.userPermission([p.permissionList.Agenda.creatEvent])">
<button class="btn-no-color">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/images/icons-edit.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/images/theme/gov/icons-edit.svg"></ion-icon>
</button>
</div>
<div (click)="rejectTask(loadedEvent.serialNumber)" class="header-icon-right display-none-{{showAside}}">
<button class="btn-no-color" >
<ion-icon class="delete" name="trash-sharp"></ion-icon>
</button>
</div>
</div>
<div class="upper-content d-flex flex-column">
<div class="content-location">
<p>
<span class="location">{{loadedEvent.workflowInstanceDataFields.Location}}</span>
<span class="event-type-{{loadedEvent.workflowInstanceDataFields.Agenda}}" *ngIf="loadedEvent.workflowDisplayName == 'Agenda Oficial MDGPR' " style="background-color: #ffb703;">
{{loadedEvent.workflowInstanceDataFields.Agenda}}
</span>
<span class="event-type-{{loadedEvent.workflowInstanceDataFields.Agenda}}" *ngIf="loadedEvent.workflowDisplayName == 'Agenda Pessoal MDGPR' " style="background-color: #f05d5e;">
{{loadedEvent.workflowInstanceDataFields.Agenda}}
</span>
<span class="event-type-{{loadedEvent.workflowInstanceDataFields.Agenda}}" *ngIf="loadedEvent.workflowDisplayName == 'Agenda Oficial PR' " style="background-color: #99e47b;">
{{loadedEvent.workflowInstanceDataFields.Agenda}}
</span>
<span class="event-type-{{loadedEvent.workflowInstanceDataFields.Agenda}}" *ngIf="loadedEvent.workflowDisplayName == 'Agenda Pessoal PR' " style="background-color: #958bfc;">
{{loadedEvent.workflowInstanceDataFields.Agenda}}
</span>
</p>
</div>
<div class="content-details">
<ion-label>
<p>{{customDate}}</p>
<p *ngIf="toDateString(loadedEvent.workflowInstanceDataFields.StartDate) == toDateString(loadedEvent.workflowInstanceDataFields.EndDate)">das {{loadedEvent.workflowInstanceDataFields.StartDate | date: 'HH:mm'}} às {{loadedEvent.workflowInstanceDataFields.EndDate | date: 'HH:mm'}}</p>
<p *ngIf="toDateString(loadedEvent.workflowInstanceDataFields.StartDate) != toDateString(loadedEvent.workflowInstanceDataFields.EndDate)">{{loadedEvent.workflowInstanceDataFields.StartDate | date: 'd/M/yy' }} - {{ loadedEvent.workflowInstanceDataFields.EndDate | date: 'dd/M/yy'}} </p>
<p>
<span *ngIf="loadedEvent.workflowInstanceDataFields.OccurrenceType == 0">Diário</span>
<span *ngIf="loadedEvent.workflowInstanceDataFields.OccurrenceType == 1">Semanal</span>
<span *ngIf="loadedEvent.workflowInstanceDataFields.OccurrenceType == 2">Mensal</span>
<span *ngIf="loadedEvent.workflowInstanceDataFields.OccurrenceType == 3">Anual</span>
<span *ngIf="loadedEvent.workflowInstanceDataFields.OccurrenceType == -1">(Não se repete)</span>
</p>
</ion-label>
</div>
</div>
<div class="line"></div>
<div class="overflow-y-auto">
<div class="middle-content">
<div *ngIf="loadedEvent.workflowInstanceDataFields.ParticipantsList">
<h5 class="font-17-rem">Intervenientes({{loadedEvent.workflowInstanceDataFields.ParticipantsList.length}})</h5>
<div *ngFor="let att of loadedEvent.workflowInstanceDataFields.ParticipantsList">
<ion-label>{{att.Name}}</ion-label>
</div>
<div class="line"></div>
</div>
<div *ngIf="loadedEvent.workflowInstanceDataFields.Body">
<h5 class="font-17-rem">Detalhes</h5>
<ion-item lines="none" class="ion-no-margin ion-no-padding">
<pre class="width-100 text">{{ loadedEvent.workflowInstanceDataFields.Body }} </pre>
</ion-item>
<div class="line"></div>
</div>
</div>
<div *ngIf="loadedAttachments" class="bottom-content width-100">
<ion-list>
<h5 class="font-17-rem">Documentos Anexados({{loadedAttachments.length}}) </h5>
<ion-item class="ion-no-margin ion-no-padding cursor-pointer"
*ngFor="let attachment of loadedAttachments"
(click)="viewDocument(attachment.DocId, attachment)">
<ion-label>
<p class="attach-title-item d-block">{{attachment.Description || 'Sem título'}}</p>
<p><span class="span-left">{{attachment.Stakeholders}}</span><span class="span-right">{{ attachment.CreateDate | date: 'dd-MM-yyyy HH:mm' }}</span></p>
</ion-label>
</ion-item>
</ion-list>
</div>
</div>
</div>
<div *ngIf="showAside" class="aside-right flex-column height-100 cursor-pointer">
<div class="aside-buttons">
<button (click)="approveTask(loadedEvent.serialNumber)" full class="btn-ok" shape="round" >Aprovar</button>
<button full class="btn-ok" shape="round" >Editar evento</button>
<button (click)="emendTask(loadedEvent.serialNumber)" class="btn-cancel" shape="round" >Enviar para Revisão</button>
<div class="solid"></div>
<button full class="btn-cancel" shape="round" (click)="editar(loadedEvent.serialNumber)" >Editar</button>
<button (click)="rejectTask(loadedEvent.serialNumber)" full class="btn-delete" shape="round" >Eliminar</button>
</div>
</div>
</div>
</div>
</ion-content>
<ion-footer *ngIf="loadedEvent" class="display-none-{{showAside}} ion-no-border">
<div class="buttons">
<button class="btn-cancel" shape="round" (click)="emendTask(loadedEvent.serialNumber)">Enviar para Revisão</button>
<button class="btn-cancel" shape="round" (click)="approveTask(loadedEvent.serialNumber)">Aprovar</button>
<!-- <button *ngIf="loadedEvent.activityInstanceName == 'Editar Evento'" full class="btn-cancel" shape="round" (click)="editar(loadedEvent.serialNumber)" >Editar</button>
<button *ngIf="loadedEvent.activityInstanceName == 'Editar Evento'" full class="btn-delete" shape="round" (click)="rejectTask(loadedEvent.serialNumber)" >Rejeitar</button> -->
</div>
</ion-footer>
@@ -0,0 +1,229 @@
@import '~src/function.scss';
.display-none-true{
display: none;
border: 1px solid red;
}
.header-content{
//margin: 25px auto;
.header-icon-left{
width: 36px;
font-size: rem(33);
color: #42b9fe;
float: left;
}
.header-icon-right{
width: rem(45);
font-size: rem(45);
float: left;
margin-left: 5px;
}
}
.header-title{
font-family: Roboto;
font-size: rem(25);
margin: 0 5px 0 5px;
padding: 0;
color:#000;
float: left;
}
.content{
padding: 30px 20px 0 20px !important;
overflow: auto;
width: 100%;
.upper-content{
margin-left: 40px;
font-size: rem(18);
.content-location{
margin-top: 0px !important;
width: 100%;
padding: 0;
}
.location{
float: left;
}
.event-type-Oficial{
font-family: Roboto;
border-radius: 20px;
background: var(--label-bg-color);
float: right !important;
padding: 5px 13.5px 5px 13.5px;
color: #fff;
}
.event-type-Pessoal{
font-family: Roboto;
border-radius: 20px;
background: #f05d5e;
float: right !important;
padding: 5px 13.5px 5px 13.5px;
color: #fff;
}
.button-edit-event {
width: 140px;
height: 44px;
border-radius: 22.5px;
--background: #e0e9ee;
--color:#061b52;
}
.content-details p{
font-size: rem(16);
}
}
.middle-conten{
.middle-content h3, .middle-content p{
font-size: rem(16);
}
}
.bottom-content{
margin: 0 auto;
.bottom-content h3{
font-size: rem(16);
margin: 0 0 0 10px;
}
.attach-document{
font-size: rem(15);
color: var(--title-text-color);
margin: 5px 5px 5px 10px;
padding: 5px;
float: left;
}
.attach-icon{
width: 37px;
font-size: rem(35);
float: left;
}
.attach-title-item{
width: 100%;
font-size: rem(15);
color:#0d89d1;
}
/* SPAN */
.span-left{
float: left;
font-size: rem(15);
}
.span-right{
text-align: right;
float: right;
font-size: rem(13);
}
}
}
.aside-right{
overflow: auto;
padding: 30px 20px 0 20px !important;
.arrow-right{
display: flex;
justify-content: flex-end;
margin-bottom: 20px;
/* .arrow-right-icon{
width: 37px;
float: right;
font-size: rem(35);
overflow: hidden;
} */
}
.aside-buttons{
width: 100% !important;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.btn-ok, .btn-cancel, .btn-delete{
height: auto !important;
font-size: rem(16) !important;
width: 100% !important;
margin-bottom: 10px !important;
padding: 15px !important;
}
}
.solid {
display: block;
width: 90%;
border-top: 1px solid #ebebeb;
margin: 0 auto !important;
margin-bottom: 10px !important;
}
}
.buttons{
display: flex;
justify-content: space-between;
overflow: auto;
padding: 5px;
.button-options {
height: 44px;
--color: #42b9fe;
/* opacity: 0; */
}
.button-approve {
width: 140px;
height: 44px;
border-radius: 22.5px;
--background: #42b9fe;
}
.button-reject {
width: 140px;
height: 44px;
--color: #d30a0a;
border-radius: 22.5px;
--background: #ffe0e0;
}
}
/* @media only screen and (max-width: 1140px) {
.content{
width: 100%;
}
.aside-right{
display: none;
}
} */
/* @media only screen and (min-width: 1140px) {
.div-icon{
display: none;
}
.content{
//width: 75%;
border-right: 1px solid #d8d8d8;
}
.aside-right{
width: 25%;
}
} */
.delete{
padding: 7px;
font-size: rem(21);
color:#fff;
background: #d30606;
border-radius: 20px;
}
.text {
text-transform: initial !important
}
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { ApproveEventPage } from './approve-event.page';
describe('ApproveEventPage', () => {
let component: ApproveEventPage;
let fixture: ComponentFixture<ApproveEventPage>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ApproveEventPage ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(ApproveEventPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,280 @@
import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';
import { NavigationExtras, Router } from '@angular/router';
import { ModalController, PopoverController } from '@ionic/angular';
import { Event } from 'src/app/models/event.model';
import { AttachmentsService } from 'src/app/services/attachments.service';
import { ProcessesService } from 'src/app/services/processes.service';
import { ToastService } from 'src/app/services/toast.service';
import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page';
import { ThemeService } from 'src/app/services/theme.service';
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
import { TaskService } from 'src/app/services/task.service'
import { AgendaDataRepositoryService } from 'src/app/module/agenda/data/repository/agenda-data-repository.service';
import { EventToApproveDetails } from 'src/app/models/entiry/agenda/eventToApproveDetails';
import { EventsService } from 'src/app/services/events.service';
import { isHttpError } from 'src/app/services/http.service';
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
import { PermissionService } from 'src/app/services/permission.service';
import { EventActionsPopoverPage } from 'src/app/ui/agenda/modal/event-actions-popover/event-actions-popover.page';
import { EmendMessageModalPage } from 'src/app/ui/agenda/modal/emend-message-modal/emend-message-modal.page';
@Component({
selector: 'app-approve-event',
templateUrl: './approve-event.page.html',
styleUrls: ['./approve-event.page.scss'],
})
export class ApproveEventPage implements OnInit {
event: Event;
@Input() loadedEvent: EventToApproveDetails;
loadedAttachments: any;
customDate: any;
today: any;
show: boolean = false;
months = ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"];
days = ["Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"];
@Input() serialNumber: string;
@Input() showComponent: string;
@Input() componentTransparent: any
@Input() InstanceId: string;
@Input() showAside: boolean;
@Output() approveEventDismiss = new EventEmitter<any>();
@Output() closeEventToApprove = new EventEmitter<any>();
@Output() AproveEventEditEvent = new EventEmitter<any>();
@Output() EditApproveEventDismiss = new EventEmitter<any>();
constructor(
private router: Router,
private modalController: ModalController,
private popoverController: PopoverController,
private toastService: ToastService,
public ThemeService: ThemeService,
private httpErroHandle: HttpErrorHandle,
public TaskService: TaskService,
private agendaDataRepository: AgendaDataRepositoryService,
public EventsService: EventsService,
private httpErrorHandle: HttpErrorHandle,
public p: PermissionService,
) {
// Event to approve list
window['edit-approve-event-desktop'] = () => {
this.getTask()
}
}
toDateString(e) {
return new Date(e).toDateString()
}
ngOnInit() {
this.getTask();
}
close() {
this.closeEventToApprove.emit();
this.modalController.dismiss();
}
@XTracerAsync({name:'ApproveEventPage/getTask', bugPrint: true})
async getTask(tracing?: TracingType) {
const res = await this.agendaDataRepository.getEventToApproveById(this.serialNumber, tracing)
if (res.isOk()) {
this.loadedEvent = res.value;
this.loadedAttachments = this.loadedEvent.Attachments
this.today = new Date(res.value.workflowInstanceDataFields.StartDate);
//
this.customDate = this.days[this.today.getDay()] + ", " + this.today.getDate() + " de " + (this.months[this.today.getMonth()]);
tracing.setAttribute('outcome', 'success')
} else {
tracing.setAttribute('eventId', this.serialNumber)
if(!isHttpError(res.error)) {
this.toastService._badRequest('Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico. #133')
console.log(res.error)
} else if (isHttpError(res.error)) {
if(res.error.status == 404) {
this.toastService._badRequest('Este evento já não existe')
} else {
this.httpErrorHandle.httpStatusHandle(res.error)
}
}
}
}
async approveTask(serialNumber: string) {
let body = { "serialNumber": serialNumber, "action": "Aprovar" }
const loader = this.toastService.loading()
const result = await this.agendaDataRepository.approveEvent(serialNumber)// .subscribe((value) => {
if(result.isOk()) {
console.log(result.value)
this.modalController.dismiss(serialNumber);
this.httpErroHandle.httpsSucessMessagge('Aprovar')
this.TaskService.loadEventosParaAprovacao();
} else {
console.log('aprove event error: ', result.error)
this.httpErroHandle.httpStatusHandle(result.error)
}
this.close()
loader.remove()
}
async rejectTask(serialNumber: string) {
let body = { "serialNumber": serialNumber, "action": "Rejeitar" }
const loader = this.toastService.loading()
const result = await this.agendaDataRepository.deleteEvent(serialNumber, true)//.subscribe((value) => {
if(result.isOk()) {
this.httpErroHandle.httpsSucessMessagge('delete event');
this.TaskService.loadEventosParaAprovacao();
this.close()
} else {
console.log('reject event error: ', result.error)
this.httpErroHandle.httpStatusHandle(result.error)
}
loader.remove()
}
async viewDocument(DocId: string, Document) {
const modal = await this.modalController.create({
component: ViewDocumentPage,
componentProps: {
trustedUrl: '',
file: {
title: Document.Description,
url: '',
title_link: '',
},
Document,
applicationId: Document.ApplicationId,
docId: Document.DocId || Document.SourceId,
// folderId: this.loadedEvent.FolderId,
task: this.loadedEvent
},
cssClass: 'modal modal-desktop'
});
await modal.present();
}
async openOptions(ev: any) {
const popover = await this.popoverController.create({
component: EventActionsPopoverPage,
componentProps: {
activityInstanceName: this.loadedEvent.activityInstanceName
},
cssClass: 'event-actions-popover',
event: ev,
translucent: true
});
return await popover.present().then(() => {
this.TaskService.loadEventosParaAprovacao()
this.getTask()
}, (error) => {
console.log(error)
})
}
async emendTask(serialNumber: string) {
const modal = await this.modalController.create({
component: EmendMessageModalPage,
componentProps: {
},
cssClass: 'emend-message-modal',
backdropDismiss: false
});
modal.onDidDismiss()
.then(async (res) => {
if (res.data.option == 'save') {
let body = {
"serialNumber": serialNumber,
"action": "Emendar",
"dataFields": {
"ReviewUserComment": res.data,
}
}
const loader = this.toastService.loading();
/* await this.processes.PostTaskAction(body).toPromise(); */
const result = await this.agendaDataRepository.eventToaprovalStatus(serialNumber, 'Revision', res.data.note)// .subscribe((value) => {
if(result.isOk()) {
this.httpErroHandle.httpsSucessMessagge('Rever')
this.TaskService.loadEventosParaAprovacao();
this.close();
} else {
console.log('send event to revision error: ', result.error)
this.httpErroHandle.httpStatusHandle(result.error)
}
loader.remove()
} else {
}
}, (error) => {
console.log(error)
});
await modal.present();
}
goToEventsToApprove() {
if (window.location.pathname.startsWith('/home/agenda')) {
this.close()
} else {
let navigationExtras: NavigationExtras = {
queryParams: {
"eventos": true,
}
};
this.router.navigate(['/home/gabinete-digital'], navigationExtras);
}
}
/** @description edit event to aprove */
async editar(serialNumber: string) {
this.EditApproveEventDismiss.emit();
}
}
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { EditEventToApprovePage } from './edit-event-to-approve.page';
const routes: Routes = [
{
path: '',
component: EditEventToApprovePage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class EditEventToApprovePageRoutingModule {}
@@ -0,0 +1,50 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { EditEventToApprovePageRoutingModule } from './edit-event-to-approve-routing.module';
import { EditEventToApprovePage } from './edit-event-to-approve.page';
import { MatNativeDateModule } from '@angular/material/core';
import {
NgxMatDatetimePickerModule,
NgxMatNativeDateModule,
NgxMatTimepickerModule
} from '@angular-material-components/datetime-picker';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatSelectModule } from '@angular/material/select';
import { NgxMatMomentModule } from '@angular-material-components/moment-adapter';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatInputModule } from '@angular/material/input';
import { MatDialogModule } from '@angular/material/dialog';
import { AttendeeModalPageModule } from 'src/app/shared/event/attendee-modal/attendee-modal.module';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
EditEventToApprovePageRoutingModule,
// Angular material
MatDatepickerModule,
MatInputModule,
MatNativeDateModule,
NgxMatDatetimePickerModule,
NgxMatTimepickerModule,
NgxMatNativeDateModule,
NgxMatMomentModule,
MatSelectModule,
MatButtonModule,
ReactiveFormsModule,
MatDialogModule,
AttendeeModalPageModule,
],
declarations: [EditEventToApprovePage],
exports: [EditEventToApprovePage]
})
export class EditEventToApprovePageModule {}
@@ -0,0 +1,332 @@
<ion-content>
<!-- Edit event for Inicio -->
<div class="main-content height-100 d-flex">
<div class="content d-flex flex-column width-md-100 height-100">
<div class="main-header pt-30 px-20 background-white pb-15">
<ion-header>
<div class="title-content">
<div class="middle">
<ion-label class="title">Editar evento por aprovar</ion-label> <br>
<i style="margin-top: -3px; font-size: 15px;" > Campos marcados com * são obrigatórios</i>
</div>
</div>
</ion-header>
</div>
<ion-item-sliding class="overflow-y-auto" >
<div class="px-20">
<div class="ion-item-container width-100" [class.input-error]="Form?.get('Subject')?.invalid && validateFrom ">
<ion-input autocomplete="on" autocorrect="on" spellcheck="true" placeholder="Assunto*" [(ngModel)]="eventProcess.workflowInstanceDataFields.Subject"></ion-input>
</div>
<div *ngIf="Form && validateFrom" >
<div *ngIf="Form.get('Subject').invalid " class="input-errror-message">
<div *ngIf="Form.get('Subject').errors?.required">
</div>
<div *ngIf="Form.get('Subject').errors?.minlength">
O campo deve ter pelo menos 4 caracteres.
</div>
</div>
</div>
<div class="container-div width-100">
<div class="ion-item-class-2">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-location.svg"></ion-icon>
</div>
<div class="ion-input-class" [class.input-error]="Form?.get('Location')?.invalid && validateFrom ">
<ion-input autocomplete="on" autocorrect="on" spellcheck="true" placeholder="Localização*" [(ngModel)]="eventProcess.workflowInstanceDataFields.Location"></ion-input>
</div>
</div>
</div>
<div *ngIf="Form && validateFrom" >
<div *ngIf="Form.get('Location').invalid " class="input-errror-message">
<div *ngIf="Form.get('Location').errors?.required">
</div>
</div>
</div>
<div class="container-div width-100">
<div class="ion-item-class-2">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class">
<ion-select placeholder="Selecione agenda*"
class="d-block d-md-none"
selectedText="{{eventProcess.workflowInstanceDataFields.Agenda}}"
[(ngModel)]="eventProcess.workflowInstanceDataFields.Agenda"
interface="action-sheet" Cancel-text="Cancelar"
required
[disabled]=true
>
<ion-select-option value="Oficial">Agenda Oficial</ion-select-option>
<ion-select-option value="Pessoal">Agenda Pessoal</ion-select-option>
</ion-select>
<mat-form-field appearance="none"
class="d-none d-md-block width-100" >
<mat-select placeholder="Selecione agenda"
[(ngModel)]="eventProcess.workflowInstanceDataFields.Agenda" >
<mat-option value="Oficial">
Oficial
</mat-option>
<mat-option value="Pessoal">
Pessoal
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div class="container-div width-100">
<div class="ion-item-class-2">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class" [class.input-error]="Form?.get('Categories')?.invalid && validateFrom ">
<ion-select placeholder="Selecione tipo de evento*"
class="d-block d-md-none"
[(ngModel)]="eventProcess.workflowInstanceDataFields.Category"
interface="action-sheet"
Cancel-text="Cancelar" required>
<ion-select-option value="Reunião">Reunião</ion-select-option>
<ion-select-option value="Viagem">Viagem</ion-select-option>
<ion-select-option value="Conferência">Conferência</ion-select-option>
<ion-select-option value="Encontro">Encontro</ion-select-option>
</ion-select>
<mat-form-field class="d-none d-md-block" appearance="none" class="width-100" placeholder="Sample Type" required>
<!-- <input matInput type="text" > -->
<mat-select [(ngModel)]="eventProcess.workflowInstanceDataFields.Category" >
<mat-option value="Meeting">
Reunião
</mat-option>
<mat-option value="Travel">
Viagem
</mat-option>
<mat-option value="Conference">
Conferência
</mat-option>
<mat-option value="Encontro">
Encontro
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div class="container-div width-100">
<div>
<ion-item>
<ion-label>Todo dia</ion-label>
<ion-checkbox [(ngModel)]="eventProcess.workflowInstanceDataFields.IsAllDayEvent" (ionChange)="onCheckboxChange($event)"></ion-checkbox>
</ion-item>
</div>
</div>
<div *ngIf="Form && validateFrom" >
<div *ngIf="Form.get('participantes').invalid " class="input-errror-message">
<div *ngIf="Form.get('participantes').errors?.required">
Adicionar participante
</div>
</div>
</div>
<div 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-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class width-100">
<ion-datetime
class="d-block d-md-none"
placeholder="Início"
[(ngModel)]="eventProcess.workflowInstanceDataFields.StartDate"
displayFormat="D MMM YYYY H:mm"
minuteValues="0,5,10,15,20,25,30,35,40,45,50,55"
monthShortNames="Jan, Fev, Mar, Abr, Mai, Jun, Jul, Aug, Sep, Out, Nov, Dez"
(ngModelChange)="onDateChange($event)"
>
</ion-datetime>
<mat-form-field appearance="none" class="width-100 date-hour-picker d-none d-md-block">
<input matInput [ngxMatDatetimePicker]="picker1"
placeholder="Choose a date"
[(ngModel)]="eventProcess.workflowInstanceDataFields.StartDate"
[disabled]="disabled"
(ngModelChange)="onDateChange($event)"
>
<mat-datepicker-toggle id="new-inicio" matSuffix [for]="picker1"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #picker1
[showSpinners]="showSpinners"
[showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute"
[stepSecond]="stepSecond"
[touchUi]="touchUi">
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div class="container-div width-100">
<div class="ion-item-class-2">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class">
<ion-datetime
class="d-none d-md-none"
placeholder="Fim"
[(ngModel)]="eventProcess.workflowInstanceDataFields.EndDate"
displayFormat="D MMM YYYY H:mm"
minuteValues="0,5,10,15,20,25,30,35,40,45,50,55"
monthShortNames="Jan, Fev, Mar, Abr, Mai, Jun, Jul, Aug, Sep, Out, Nov, Dez"
>
</ion-datetime>
<mat-form-field appearance="none" class="width-100 date-hour-picker d-none d-md-block">
<input matInput [ngxMatDatetimePicker]="fim"
placeholder="Choose a date"
[(ngModel)]="eventProcess.workflowInstanceDataFields.EndDate"
[min]="endMinDate" [max]="maxDate"
[disabled]="disabled"
>
<mat-datepicker-toggle id="new-fim" matSuffix [for]="fim"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #fim
[showSpinners]="showSpinners"
[showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute"
[stepSecond]="stepSecond"
[touchUi]="touchUi">
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div class="container-div width-100">
<div class="ion-item-class-2">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-person.svg"></ion-icon>
</div>
<div class="ion-input-class-no-height d-flex cursor-pointer" (click)="addParticipants()">
<div class="list-people flex-grow-1">
<ion-item lines="none">
<ion-list>
<ion-label *ngIf="taskParticipants?.length < 1" class="list-people-title">Adicionar Intervenientes*</ion-label>
<ion-label *ngFor="let participant of taskParticipants">{{participant.Name}}</ion-label>
</ion-list>
</ion-item>
</div>
<div class="add-people cursor-pointer" >
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="start" src="assets/images/icons-arrow-forward.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="start" src="assets/images/theme/gov/icons-arrow-forward.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="start" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-arrow-forward.svg"></ion-icon>
</div>
</div>
</div>
</div>
<div class="container-div width-100">
<div class="ion-item-class-2">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-people-cc.svg"></ion-icon>
</div>
<div class="ion-input-class-no-height d-flex cursor-pointer" (click)="addParticipantsCC()">
<div class="list-people flex-grow-1">
<ion-item lines="none">
<ion-list
style="
display: grid;
">
<ion-label *ngIf="taskParticipantsCc?.length < 1" class="list-people-title">Com Conhecimento</ion-label>
<ion-label *ngFor="let participant of taskParticipantsCc">{{participant.Name}}</ion-label>
</ion-list>
</ion-item>
</div>
<div class="add-people cursor-pointer" >
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="start" src="assets/images/icons-arrow-forward.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="start" src="assets/images/theme/gov/icons-arrow-forward.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="start" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-arrow-forward.svg"></ion-icon>
</div>
</div>
</div>
</div>
<div class="container-div d-flex width-100">
<div class="ion-item-class-2 d-flex width-100">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-description.svg"></ion-icon>
</div>
<div class="ion-input-class-no-height width-100 flex-grow-1">
<ion-textarea autoGrow="true" autocomplete="on" autocorrect="on" spellcheck="true" [(ngModel)]="eventProcess.workflowInstanceDataFields.Body" placeholder="Detalhes" rows="6" cols="20"></ion-textarea>
</div>
</div>
</div>
<div (click)="getDoc()" class="cursor-pointer d-flex container-div width-100 ion-item-container-no-border" >
<ion-label>
<div class="attach-icon">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/images/icons-attach-doc.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/images/theme/gov/icons-attach-doc.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " src="assets/images/theme/{{ThemeService.currentTheme}}/icons-attach-doc.svg"></ion-icon>
</div>
<div class="attach-document">
<ion-label>Adicionar documentos</ion-label>
</div>
</ion-label>
</div>
<div class="d-flex container-div width-100" >
<ion-list class="width-100 ">
<ion-item class="width-100" *ngFor="let document of loadedAttachments; let i = index">
<ion-label class="width-100 d-block list" >
<p class="d-flex ion-justify-content-between">
<span class="attach-title-item">{{document.subject || document.Description || document.SourceName || document.sourceName || 'Sem título'}}</span>
<span class="app-name" *ngIf="document.applicationId == 8 || document.ApplicationId == 8"> Correspondencia </span>
<span class="app-name" *ngIf="document.applicationId == 386 || document.ApplicationId == 386"> AccoesPresidenciais </span>
<span class="app-name" *ngIf="document.applicationId == 361 || document.ApplicationId == 361 "> ArquivoDespachoElect </span>
<span class="close-button text-black cursor-pointer" (click)="deleteAttachment(document, i)" >
<ion-icon class="font-20" src="assets/images/icons-delete-25.svg"></ion-icon>
</span>
</p>
<p><span class="span-left" *ngIf="document.Stakeholders != false">{{document.Stakeholders}}</span><span class="span-right" *ngIf="document.dateEntry != false"> {{document.dateEntry }} </span></p>
</ion-label>
</ion-item>
</ion-list>
</div>
</div>
</ion-item-sliding>
</div>
</div>
</ion-content>
<ion-footer class="background-whit">
<div class="buttons">
<button class="btn-ok cursor-pointer" shape="round" (click)="gravasAction()">Gravar</button>
<button class="btn-cancel cursor-pointer" shape="round" (click)="close()">Cancelar</button>
</div>
</ion-footer>
@@ -0,0 +1,204 @@
@import '~src/function.scss';
.title-content::after, .header-md::after{
display: none;
}
.content {
margin: 0;
float: left;
border-right: 1px solid #d8d8d8 !important;
}
.main-header{
font-family: Roboto;
background-color: #fff;
min-height: 86px;
overflow:hidden;
transform: translate3d(0, 1px, 0);
.title-content{
margin: 0px auto;
padding: 0 !important;
background: #fff;
.middle{
padding: 0!important;
float: left;
}
}
.title{
font-size: rem(25);
}
}
.ion-item-container{
margin: rem(15) auto;
border: 1px solid #ebebeb;
border-radius: 5px;
padding-left: 10px;
}
.ion-item-container-no-border{
width: 100%;
margin: 0px auto;
padding: 0 !important;
}
.container-div{
margin-bottom: 15px;
float: left;
}
.ion-item-class-2{
margin: 0px auto;
}
.ion-icon-class{
width: rem(45);
height: rem(45);
float: left;
padding: 10px;
font-size: rem(25);
}
ion-select{
padding-left: 5px;
margin-left: 0;
}
.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;
}
.ion-input-class-no-height{
width: calc(100% - 45px);
border: 1px solid #ebebeb;
border-radius: 5px;
}
.list-people{
float: left;
}
.add-people{
width: rem(45);
float: right;
overflow: auto;
font-size: rem(25);
height: rem(45);
display: flex;
}
.list-people-title{
/* font-size: rem(13); */
color: #797979;
}
.attach-document{
font-size: rem(15);
color: var(--title-text-color);
margin: 5px 5px 5px 10px;
padding: 5px;
float: left;
}
.attach-icon{
width: 37px;
font-size: rem(35);
float: left;
}
.attach-title-item{
width: 100%;
font-size: rem(15);
color:var(--title-text-color);
}
/* SPAN */
.span-left{
float: left;
font-size: rem(15);
}
.span-right{
text-align: right;
float: right;
font-size: rem(13);
}
.container-footer{
margin:0 auto;
overflow: auto;
}
.button-cancel {
width: rem(170);
height: rem(44);
border-radius: 22.5px;
--background: #e0e9ee;
--color: #061b52;
margin:10px;
}
.button-save {
width: rem(170);
height: rem(44);
border-radius: 22.5px;
--background: #42b9fe;
--color:#ffffff;
margin:10px;
}
.text-input{
width: 100%;
border: 1px solid #ebebeb;
margin: 0px 15px 15px 0px;
padding: 0 !important;
border-radius: 5px;
}
/* Error Messages */
.error{
color:red;
font-size: rem(12);
font-weight: bold;
padding-bottom: 20px;
}
.span-color{
color:red;
}
.buttons{
display: flex;
justify-content: space-between;
padding: 20px;
overflow: auto;
}
.app-name{
background: var(--title-text-color);
border-radius: 18px;
text-align: center;
display: flex;
align-items: center;
padding: 0px 5px;
color: white;
font-size: rem(12);
font-weight: 500;
height: 19px;
-webkit-border-radius: 18px;
-moz-border-radius: 18px;
-ms-border-radius: 18px;
-o-border-radius: 18px;
}
.close-button {
display: none;
height: 20px;
}
.list:hover {
.app-name {
display: none;
}
.close-button {
display: block !important;
}
}
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { EditEventToApprovePage } from './edit-event-to-approve.page';
describe('EditEventToApprovePage', () => {
let component: EditEventToApprovePage;
let fixture: ComponentFixture<EditEventToApprovePage>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ EditEventToApprovePage ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(EditEventToApprovePage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,790 @@
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { AlertController, ModalController } from '@ionic/angular';
import * as moment from 'moment';
import { Attachment } from 'src/app/models/attachment.model';
import { EventPerson } from 'src/app/models/eventperson.model';
import { SearchList } from 'src/app/models/search-document';
import { SearchPage } from 'src/app/pages/search/search.page';
import { AttachmentsService } from 'src/app/services/attachments.service';
import { EventsService } from 'src/app/services/events.service';
import { ProcessesService } from 'src/app/services/processes.service';
import { ToastService } from 'src/app/services/toast.service';
import { NgxMatDateFormats } from '@angular-material-components/datetime-picker';
import { removeDuplicate } from 'src/plugin/removeDuplicate.js'
import { EventToApproveEdit } from 'src/app/models/event.model';
import { ThemeService } from 'src/app/services/theme.service'
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
import { AgendaDataRepositoryService } from 'src/app/module/agenda/data/repository/agenda-data-repository.service';
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
import { AttendeesLIstChangeDetector } from 'src/app/module/agenda/data/async/change/attendeesLIstChangeDetector';
const CUSTOM_DATE_FORMATS: NgxMatDateFormats = {
parse: {
dateInput: "YYYY-MMMM-DD HH:mm"
},
display: {
dateInput: "DD MMM YYYY H:mm",
monthYearLabel: "MMM YYYY",
dateA11yLabel: "LL",
monthYearA11yLabel: "MMMM YYYY"
}
}
@Component({
selector: 'app-edit-event-to-approve',
templateUrl: './edit-event-to-approve.page.html',
styleUrls: ['./edit-event-to-approve.page.scss'],
})
export class EditEventToApprovePage implements OnInit {
public date: any;
public disabled = false;
public showSpinners = true;
public showSeconds = false;
public touchUi = false;
public enableMeridian = false;
public minDate = new Date()
public endMinDate = new Date(new Date().getTime() + 15 * 60000);
public maxDate: any;
public stepHour = 1;
public stepMinute = 15;
public stepSecond = 5;
public dateControlStart = new FormControl(moment("DD MM YYYY hh"));
public dateControlEnd = new FormControl(moment("DD MM YYYY hh"));
recurringTypes: any;
selectedRecurringType: any;
showLoader = false;
get dateStart() {
return this.dateControlStart.value
}
get dateEnd() {
return this.dateControlEnd.value
}
@ViewChild('picker') picker: any;
@ViewChild('fim') fim: any;
@ViewChild('inicio') inicio: any;
@ViewChild('picker1') picker1: any;
loadedAttachments: any[] = []
eventProcess = {
Attachments: [],
serialNumber: "",
taskStartDate: "",
activityInstanceName: "",
workflowInstanceDataFields: {
Body: "",
OccurrenceType: '',
Category: '',
LastOccurrence: new Date(),
IsRecurring: false,
ParticipantsList: [],
Agenda: '',
EndDate: '',
Location: '',
Subject: '',
InstanceId: '',
EventType: '',
StartDate: '',
MDEmail: '',
MDName: '',
IsAllDayEvent: false,
Message: '',
Status: ''
}
}
show = false
isRecurring: string;
isEventEdited: boolean;
profile: string;
eventAttendees: EventPerson[];
loadedEventAttachments: Attachment[];
adding: "intervenient" | "CC" = "intervenient";
showAttendees = false;
InstanceId: string;
Form: FormGroup;
validateFrom = false
addedAttachmentsList = [];
deletedAttachmentsList = [];
@Output() openAttendeesComponent = new EventEmitter<any>();
@Output() clearContact = new EventEmitter<any>();
@Output() setIntervenient = new EventEmitter<any>();
@Output() setIntervenientCC = new EventEmitter<any>();
@Output() closeComponent = new EventEmitter<any>();
@Output() closeEventToApprove = new EventEmitter<any>();
@Output() approveEventDismiss = new EventEmitter<any>();
@Input() saveData: any;
@Input() serialNumber: string
@Input() taskParticipants: EventPerson[];
@Input() taskParticipantsCc: EventPerson[];
constructor(
private modalController: ModalController,
private eventsService: EventsService,
public alertController: AlertController,
private attachmentsService: AttachmentsService,
private processes: ProcessesService,
private toastService: ToastService,
public ThemeService: ThemeService,
public httpErrorHandler: HttpErrorHandle,
private agendaDataRepository: AgendaDataRepositoryService,
private httpErroHalde: HttpErrorHandle,
) {
this.isEventEdited = false;
}
ngOnInit() {
console.log('here!!!')
if (this.restoreTemporaryData()) {
this.setOtherData()
} else {
this.getTask();
}
this.getRecurrenceTypes();
}
@XTracerAsync({name:'edit-event-approve/getTask', bugPrint: true})
async getTask(tracing?: TracingType) {
const res = await this.agendaDataRepository.getEventToApproveById(this.serialNumber)
if(res.isOk()) {
console.log('evento to apro to edit', res.value)
this.eventProcess = res.value as any;
this.eventProcess.workflowInstanceDataFields.LastOccurrence = new Date(this.eventProcess.workflowInstanceDataFields.LastOccurrence)
this.restoreDatepickerData()
// description
try {
let body: any = this.eventProcess.workflowInstanceDataFields?.Body?.replace(/<[^>]+>/g, '')
this.eventProcess.workflowInstanceDataFields.Body = body
} catch (error) {}
this.eventProcess.workflowInstanceDataFields.Category = this.setEventType(this.eventProcess.workflowInstanceDataFields.EventType)
this.InstanceId = this.eventProcess.workflowInstanceDataFields.InstanceId
this.loadedAttachments = res.value.Attachments;
console.log(this.loadedAttachments)
this.setOtherData()
this.saveTemporaryData()
tracing.setAttribute('outcome', 'success')
} else {
tracing.setAttribute('outcome', 'failed')
this.httpErroHalde.httpStatusHandle(res.error)
}
}
getRecurrenceTypes() {
this.eventsService.getRecurrenceTypes().subscribe(res => {
this.recurringTypes = res;
});
}
calculetedLastOccurrence(type: number) {
var valor;
var opcao: boolean;
if (type == 0) {
valor = 7;
opcao = true;
} else if (type == 1) {
valor = 30;
opcao = true;
} else if (type == 2) {
valor = 1;
opcao = false;
} else if (type == 3) {
valor = 5;
opcao = false;
}
this.defineLastOccurrence(valor, opcao);
}
onDateChange(e) {
const cloneDateStartDate = new Date(this.eventProcess.workflowInstanceDataFields.StartDate);
const cloneDateEndDate = new Date(this.eventProcess.workflowInstanceDataFields.EndDate);
if(cloneDateStartDate.getTime() >= cloneDateEndDate.getTime()) {
cloneDateStartDate.setHours(cloneDateStartDate.getHours() + 1);
this.eventProcess.workflowInstanceDataFields.EndDate = cloneDateStartDate as any
}
}
defineLastOccurrence(valor: number, opcao: boolean) {
var time = new Date(this.eventProcess.workflowInstanceDataFields.EndDate);
if (opcao == true) {
time.setDate(time.getDate() + valor);
this.eventProcess.workflowInstanceDataFields.LastOccurrence = time;
} else {
time = new Date(
time.getFullYear() + valor,
time.getMonth(),
time.getDate(),
time.getHours(),
time.getMinutes()
);
this.eventProcess.workflowInstanceDataFields.LastOccurrence = time;
}
}
setOtherData() {
if (this.eventProcess.workflowInstanceDataFields.ParticipantsList) {
this.eventProcess.workflowInstanceDataFields.ParticipantsList.forEach(e => {
console.log('intervenientes ', e)
if (e.IsRequired) {
this.taskParticipants.push(e);
} else {
this.taskParticipantsCc.push(e);
}
})
}
this.taskParticipants = removeDuplicate(this.taskParticipants)
this.taskParticipantsCc = removeDuplicate(this.taskParticipantsCc)
if (this.eventProcess.workflowInstanceDataFields.IsRecurring == false) {
this.isRecurring = "Não se repete";
}
else {
this.isRecurring = "Repete";
}
this.InstanceId = this.eventProcess.workflowInstanceDataFields.InstanceId
/* this.getAttachments() */
}
close() {
window['temp.path:/shared/agenda/edit-event-to-approve.ts'] = {};
this.closeEventToApprove.emit();
this.setIntervenient.emit([]);
this.setIntervenientCC.emit([]);
this.clearContact.emit();
this.approveEventDismiss.emit({
serialNumber: this.eventProcess.serialNumber,
action: "Aprovar",
saveData: this.eventProcess
});
}
runValidation() {
this.validateFrom = true
}
injectValidation() {
this.Form = new FormGroup({
Subject: new FormControl(this.eventProcess.workflowInstanceDataFields.Subject, [
Validators.required,
// Validators.minLength(4)
]),
Location: new FormControl(this.eventProcess.workflowInstanceDataFields.Location, [
Validators.required,
]),
//CalendarName: new FormControl(this.postEvent.CalendarName),
// Categories: new FormControl(this.postEvent.Categories, [
// Validators.required
// ]),
dateStart: new FormControl(this.dateStart, [
Validators.required
]),
dateEnd: new FormControl(this.dateEnd, [
Validators.required
]),
// IsRecurring: new FormControl(this.postEvent.IsRecurring, [
// Validators.required
// ]),
participantes: new FormControl(this.taskParticipants, [
// Validators.required
]),
})
}
@XTracerAsync({name:'desktop/edit-event', bugPrint: true, daley: 4000})
async save(tracing?: TracingType) {
this.injectValidation()
this.runValidation()
if (this.Form.invalid) return false
const serverCurrentList = this.eventProcess.workflowInstanceDataFields.ParticipantsList
this.dateControlStart = new FormControl(moment(new Date(this.eventProcess.workflowInstanceDataFields.StartDate)).add(1, 'hours'));
this.dateControlEnd = new FormControl(moment(new Date(this.eventProcess.workflowInstanceDataFields.EndDate)).add(1, 'hours'));
this.taskParticipantsCc.forEach(e => {
e.IsRequired = false
})
this.eventProcess.workflowInstanceDataFields.Subject = /* this.domSanitizeService.sanitizeInput( */this.eventProcess.workflowInstanceDataFields.Subject/* ) */;
this.eventProcess.workflowInstanceDataFields.Location = /* this.domSanitizeService.sanitizeInput( */this.eventProcess.workflowInstanceDataFields.Location/* ) */;
this.eventProcess.workflowInstanceDataFields.Body = /* this.domSanitizeService.sanitizeInput( */this.eventProcess.workflowInstanceDataFields.Body/* ) */;
this.eventProcess.workflowInstanceDataFields.ParticipantsList = this.taskParticipants.concat(this.taskParticipantsCc)
this.eventProcess.workflowInstanceDataFields.ParticipantsList.forEach(e => {
if (e.hasOwnProperty('$type')) {
delete e.$type
}
})
const event: EventToApproveEdit = {
SerialNumber: this.eventProcess.serialNumber,
Body: this.eventProcess.workflowInstanceDataFields.Body,
Location: this.eventProcess.workflowInstanceDataFields.Location,
Subject: this.eventProcess.workflowInstanceDataFields.Subject,
StartDate: this.dateControlStart.value,
EndDate: this.dateControlEnd.value,
ReviewUserComment: '',
Agenda: this.eventProcess.workflowInstanceDataFields.Agenda,
MDName: this.eventProcess.workflowInstanceDataFields.MDName,
MDEmail: this.eventProcess.workflowInstanceDataFields.MDEmail,
IsAllDayEvent: this.eventProcess.workflowInstanceDataFields.IsAllDayEvent,
Status: this.eventProcess.workflowInstanceDataFields.Status,
EventType: this.eventProcess.workflowInstanceDataFields.EventType,
IsRecurring: this.eventProcess.workflowInstanceDataFields.IsRecurring,
Message: this.eventProcess.workflowInstanceDataFields.Message,
EventRecurrence: {
Type: this.eventProcess.workflowInstanceDataFields.OccurrenceType || '-1',
LastOccurrence: this.eventProcess.workflowInstanceDataFields.LastOccurrence,
},
ParticipantsList: this.eventProcess.workflowInstanceDataFields.ParticipantsList,
Category: this.eventProcess.workflowInstanceDataFields.Category
}
try {
const calendar = await this.agendaDataRepository.getCalendarByUserId((this.eventProcess as any).owner.wxUserId)
if(calendar.isOk()) {
const value = await this.agendaDataRepository.updateEvent(this.eventProcess.serialNumber, event, true, calendar.value, tracing)
if(value.isOk()) {
console.log(value)
tracing.setAttribute('outcome', 'success')
} else {
console.log('edit event error: ', value.error)
tracing.setAttribute('outcome', 'failed')
}
console.log({serverCurrentList, list: this.eventProcess.workflowInstanceDataFields.ParticipantsList, e: this.eventProcess})
const { insert, remove } = AttendeesLIstChangeDetector(serverCurrentList as any, this.eventProcess.workflowInstanceDataFields.ParticipantsList as any)
console.log({insert, remove})
if(insert.length >= 1) {
try {
await this.agendaDataRepository.addEventAttendee(this.eventProcess.serialNumber, insert, tracing).toPromise()
} catch (error) {
console.log('add Attendee error: ', error)
tracing.setAttribute('failed.attendees', 'true')
}
// this.agendaDataRepository.addEventAttendee(this.eventProcess.serialNumber, insert, tracing).subscribe((value) => {
// console.log(value)
// }, ((error) => {
// console.log('add Attendee error: ', error)
// tracing.setAttribute('failed.attendees', 'true')
// }));
}
if(remove.length >= 1) {
try {
await this.agendaDataRepository.removeEventAttendee(this.eventProcess.serialNumber, remove).toPromise()
} catch (error) {
console.log('add Attendee error: ', error)
tracing.setAttribute('failed.attendees', 'true')
}
// this.agendaDataRepository.removeEventAttendee(this.eventProcess.serialNumber, remove).subscribe((value) => {
// }, ((error) => {
// console.log('add Attendee error: ', error)
// tracing.setAttribute('failed.attendees', 'true')
// }));
}
if (this.addedAttachmentsList.length > 0) {
try {
await this.agendaDataRepository.addEventAttachment(this.eventProcess.serialNumber, this.loadedAttachments, tracing).toPromise();
} catch (error) {
this.showLoader = false
console.log('add attachment error: ', error)
tracing.setAttribute('failed.add.attachment', 'true')
}
// this.agendaDataRepository.addEventAttachment(this.eventProcess.serialNumber, this.loadedAttachments, tracing).subscribe((value) => {
// console.log(value)
// }, ((error) => {
// this.showLoader = false
// console.log('add attachment error: ', error)
// tracing.setAttribute('failed.add.attachment', 'true')
// }));
}
if (this.deletedAttachmentsList.length > 0) {
try {
await this.agendaDataRepository.removeEventAttachment(this.eventProcess.serialNumber, { attachments: this.deletedAttachmentsList }).toPromise()
} catch (error) {
this.showLoader = false
console.log('remove attachment error: ', error)
tracing.setAttribute('failed.remove.attachment', 'true')
}
// this.agendaDataRepository.removeEventAttachment(this.eventProcess.serialNumber, { attachments: this.deletedAttachmentsList }).subscribe((value) => {
// console.log(value)
// }, ((error) => {
// this.showLoader = false
// console.log('remove attachment error: ', error)
// tracing.setAttribute('failed.remove.attachment', 'true')
// }));
}
this.close()
this.httpErrorHandler.httpsSucessMessagge('Editar evento');
}
} catch (e) {
this.httpErrorHandler.httpStatusHandle(e);
this.toastService._badRequest('Evento não editado');
}
// this.loadedAttachments.forEach((document: any) => {
// if (document['action'] == 'add') {
// delete document.action
// this.attachmentsService.setEventAttachmentById(document).subscribe(() => {
// window['edit-approve-event-desktop']()
// }, error => {
// this.toastService.badRequest();
// });
// } else if (document['action'] == 'delete') {
// delete document.action
// this.attachmentsService.deleteEventAttachmentById(document.Id).subscribe(res => {
// window['edit-approve-event-desktop']()
// }, error => {
// this.toastService.badRequest()
// })
// }
// })
}
documentAdded(documents: any[]) {
console.log('document added', documents)
return documents.map((element) => {
return {
docId: parseInt(element.SourceId),
sourceName: element.SourceName,
description: "",
applicationId: parseInt(element.ApplicationId)
};
});
}
atendeesSeletedType(type) {
var selectedType = {
'true': 1,
'false': 2,
'other': 3,
}
return selectedType[type];
}
attendeesAdded(taskParticipants: any[]) {
return taskParticipants.map((e) => {
return {
name: e.Name,
emailAddress: e.EmailAddress,
attendeeType: this.atendeesSeletedType(JSON.stringify(e.IsRequired)),
wxUserId: e.wxUserId,
}
});
}
async gravasAction() {
await this.save();
this.reenviar();
}
async reenviar() {
let body = {
serialNumber: this.eventProcess.serialNumber,
action: "Reenviar",
dataFields: {
ReviewUserComment: "",
}
}
const loader = this.toastService.loading();
try {
await this.processes.PostTaskAction(body).toPromise();
this.toastService._successMessage();
this.goToApproveEventList();
} catch (error) {
if (error.status == 0) {
this.toastService._badRequest('Sem acesso à internet. Por favor verifique sua conexão')
} else {
this.toastService._badRequest();
}
} finally {
loader.remove()
}
}
goToApproveEventList() {
this.closeEventToApprove.emit();
this.modalController.dismiss();
}
dynamicSetIntervenient({ taskParticipants, taskParticipantsCc }) {
this.taskParticipants = removeDuplicate(taskParticipants);
this.taskParticipantsCc = removeDuplicate(taskParticipantsCc);
}
onCheckboxChange(event: any) {
if (this.eventProcess.workflowInstanceDataFields.IsAllDayEvent) {
this.eventProcess.workflowInstanceDataFields.StartDate = this.setAlldayTime(this.eventProcess.workflowInstanceDataFields.StartDate)
this.eventProcess.workflowInstanceDataFields.EndDate = this.setAlldayTimeEndDate(this.eventProcess.workflowInstanceDataFields.EndDate)
console.log('Recurso ativado!!');
} else {
this.eventProcess.workflowInstanceDataFields.IsAllDayEvent = this.eventProcess.workflowInstanceDataFields.IsAllDayEvent;
this.eventProcess.workflowInstanceDataFields.EndDate = this.setAlldayTimeEndDateNotAlday(this.eventProcess.workflowInstanceDataFields.EndDate)
console.log('Recurso desativado');
}
}
setAlldayTime(timeToReturn) {
let date: any = new Date(timeToReturn) || new Date();
let newdate = new Date();
date.setHours(0)
date.setMinutes(0)
date.setSeconds(0);
return date
}
setAlldayTimeEndDate(timeToReturn) {
let date: any = new Date(timeToReturn) || new Date();
let newdate = new Date();
date.setHours(23)
date.setMinutes(59)
date.setSeconds(0);
return date
}
setAlldayTimeEndDateNotAlday(timeToReturn) {
let date: any = new Date(timeToReturn) || new Date();
let newdate = new Date();
date.setHours(23)
date.setMinutes(0)
date.setSeconds(0);
return date
}
async addParticipants() {
//this.saveTemporaryData();
this.openAttendeesComponent.emit({
type: "intervenient"
});
this.clearContact.emit();
}
async addParticipantsCC() {
this.openAttendeesComponent.emit({
type: "CC"
});
this.clearContact.emit();
}
saveTemporaryData() {
this.getDatepickerData()
window['temp.path:/shared/agenda/edit-event-to-approve.ts'] = {
eventProcess: this.eventProcess,
attachment: this.loadedAttachments
}
}
restoreTemporaryData(): boolean {
const restoredData = window['temp.path:/shared/agenda/edit-event-to-approve.ts']
if (JSON.stringify(restoredData) != "{}" && undefined != restoredData) {
this.eventProcess = restoredData.eventProcess,
this.loadedAttachments = restoredData.attachment
// restore dater for date and hours picker
this.restoreDatepickerData()
return true;
} else {
return false;
}
}
async getAttachments() {
let result: any;
try {
result = await this.attachmentsService.getAttachmentsById(this.InstanceId).toPromise();
} catch (error) {
console.error('getAttachment', error)
}
result.forEach((e) => {
e.action = false
})
this.loadedAttachments = result
//
}
deleteAttachment(attachment: Attachment, index) {
const id: any = this.loadedAttachments[index].id
console.log(this.loadedAttachments)
let update = this.removeItemById(this.loadedAttachments, id)
this.loadedAttachments = update;
this.deletedAttachmentsList.push(id)
}
removeItemById(array, id) {
return array.filter(item => item.id !== id);
}
async getDoc() {
const modal = await this.modalController.create({
component: SearchPage,
cssClass: 'modal-width-100-width-background modal',
componentProps: {
type: 'AccoesPresidenciais & ArquivoDespachoElect',
showSearchInput: true,
eventAgenda: true,
select: true,
}
});
await modal.present();
modal.onDidDismiss().then(async (res) => {
if (res) {
const data: SearchList = res.data.selected;
console.log(data)
/* const DocumentToSave: any = {
SourceTitle: data.Assunto,
ParentId: this.InstanceId,
Source: '1',
SourceId: data.Id,
ApplicationId: data.ApplicationType.toString(),
Id: '',
Link: '',
SerialNumber: '',
action: 'add',
CreateDate: data.Data,
Data: data.Data,
Description: data.DocTypeDesc,
SourceName: data.Assunto,
Stakeholders: data.EntidadeOrganicaNome,
}; */
this.loadedAttachments.push(data)
this.addedAttachmentsList.push(data)
// await this.attachmentsService.setEventAttachmentById(DocumentToSave).subscribe(()=>{
// this.getAttachments();
// });
}
});
}
restoreDatepickerData() {
this.dateControlStart = new FormControl(moment(new Date(this.eventProcess.workflowInstanceDataFields.StartDate)));
this.dateControlEnd = new FormControl(moment(new Date(this.eventProcess.workflowInstanceDataFields.EndDate)));
}
getDatepickerData() {
this.eventProcess.workflowInstanceDataFields.StartDate = this.dateStart
this.eventProcess.workflowInstanceDataFields.EndDate = this.dateEnd
}
setEventType(eventType) {
var selectedEventType = {
1: 'Meeting',
2: 'Travel',
3: 'Conference',
4: 'Encontro'
}
return selectedEventType[eventType];
}
}
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { EditEventPage } from './edit-event.page';
const routes: Routes = [
{
path: '',
component: EditEventPage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class EditEventPageRoutingModule {}
@@ -0,0 +1,49 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { EditEventPageRoutingModule } from './edit-event-routing.module';
import { EditEventPage } from './edit-event.page';
import { MatNativeDateModule } from '@angular/material/core';
import {
NgxMatDatetimePickerModule,
NgxMatNativeDateModule,
NgxMatTimepickerModule
} from '@angular-material-components/datetime-picker';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatSelectModule } from '@angular/material/select';
import { NgxMatMomentModule } from '@angular-material-components/moment-adapter';
import { MAT_DATE_LOCALE } from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatInputModule } from '@angular/material/input';
import { MatDialogModule } from '@angular/material/dialog';
import { MatMenuModule } from '@angular/material/menu';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
EditEventPageRoutingModule,
// Angular material
MatDatepickerModule,
MatInputModule,
MatNativeDateModule,
NgxMatDatetimePickerModule,
NgxMatTimepickerModule,
NgxMatNativeDateModule,
NgxMatMomentModule,
MatSelectModule,
MatButtonModule,
ReactiveFormsModule,
MatDialogModule,
],
providers: [
{ provide: MAT_DATE_LOCALE, useValue: 'pt' },
],
declarations: [EditEventPage],
exports: [EditEventPage]
})
export class EditEventPageModule {}
@@ -0,0 +1,448 @@
<ion-header class="ion-no-border">
<ion-toolbar class="header-toolbar">
<div class="main-header">
<div class="title-content">
<div class="middle">
<ion-label id="edit-event-desktop" class="title">Editar Evento</ion-label> <br>
<i style="margin-top: -3px; font-size: 15px;"> Campos marcados com * são obrigatórios</i>
</div>
</div>
<ion-progress-bar class="calendar-progress-bar" type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
</div>
</ion-toolbar>
</ion-header>
<ion-content>
<div class="main-content">
<div class="ion-item-container" [class.input-error]="Form?.get('Subject')?.invalid && validateFrom ">
<ion-input autocomplete="on" autocorrect="on" spellcheck="true" placeholder="Assunto*"
[(ngModel)]="_postEvent.Subject"></ion-input>
</div>
<div *ngIf="Form && validateFrom">
<div *ngIf="Form.get('Subject').invalid " class="input-errror-message">
<div *ngIf="Form.get('Subject').errors?.required">
</div>
<div *ngIf="Form.get('Subject').errors?.minlength">
O campo deve ter pelo menos 4 caracteres.
</div>
</div>
</div>
<div class="container-div">
<div class="ion-item-class-2 width-100 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-location.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1" [class.input-error]="Form?.get('Location')?.invalid && validateFrom ">
<ion-input autocomplete="on" autocorrect="on" spellcheck="true" placeholder="Localização*"
[(ngModel)]="_postEvent.Location"></ion-input>
</div>
</div>
<!-- Error messages -->
<!-- <span class="error ion-padding" >
Campo obrigatório
</span> -->
</div>
<div *ngIf="(sharedCalendar | async) as calendarData" class="container-div" >
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 justify-center align-center material-inputs " [class.input-error]="Form?.get('CalendarName')?.invalid && validateFrom ">
<mat-form-field appearance="none" class="width-100" color="ion-color-secondary" placeholder="Selecione agenda">
<div *ngIf="selectedUserCalendar == SessionStore.user.UserId && !hasChangeCalendar && SessionStore.user.Profile != 'PR' " style="margin-bottom: -20px;">
Minha agenda
</div>
<div *ngIf="!(selectedUserCalendar == SessionStore.user.UserId && SessionStore.user.Profile != 'PR' ) && !hasChangeCalendar" style="margin-bottom: -20px;">
PR
</div>
<mat-select [(value)]="selectedUserCalendar" (selectionChange)="changeAgenda();changeSegmentCalendar()">
<mat-option *ngFor="let calendars of calendarData" value="{{calendars.wxUserId}}">
<div *ngIf="calendars.roleId == RoleIdService.PRES">PR </div>
<div *ngIf="calendars.roleId == RoleIdService.MD && calendars.roleId != SessionStore.user.RoleID">AGENDA DO MDGPR</div>
<div *ngIf="calendars.roleId != RoleIdService.MD && calendars.roleId != RoleIdService.PRES && calendars.wxFullName && calendars.wxUserId != SessionStore.user.UserId"> Agenda do {{calendars.wxFullName}} </div>
<div *ngIf="calendars.wxUserId == SessionStore.user.UserId && SessionStore.user.Profile != 'PR'">
Minha agenda
</div>
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="Form && validateFrom">
<div *ngIf="Form.get('Location').invalid " class="input-errror-message">
<div *ngIf="Form.get('Location').errors?.required">
</div>
<div *ngIf="Form.get('Location').errors?.minlength">
O campo deve ter pelo menos 4 caracteres.
</div>
</div>
</div>
<div class="container-div">
<div class="ion-item-class-2 width-100 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1">
<mat-form-field appearance="none" floatLabel="never" class="width-100 ">
<mat-select placeholder="Selecione agenda*" [(ngModel)]="_postEvent.CalendarName" [disabled]=false>
<mat-option *ngFor="let calendars of CalendarNamesOptions" value="{{calendars}}">
Agenda {{ calendars }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div class="container-div">
<div class="ion-item-class-2 width-100 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1"
[class.input-error]="Form?.get('Categories')?.invalid && validateFrom ">
<mat-form-field appearance="none" floatLabel="never" class="width-100" required>
<!-- <input matInput type="text" > -->
<mat-select placeholder="Selecione o tipo de evento*" matInput [(ngModel)]="_postEvent.Category">
<mat-option value="Meeting">
Reunião
</mat-option>
<mat-option value="Travel">
Viagem
</mat-option>
<mat-option value="Conference">
Conferência
</mat-option>
<mat-option value="Encontro">
Encontro
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div class="container-div">
<div>
<ion-item>
<ion-label>Todo dia</ion-label>
<ion-checkbox [(ngModel)]="allDayCheck" (ionChange)="onCheckboxChange($event)"></ion-checkbox>
</ion-item>
</div>
</div>
<div class="container-div">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-reapet.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 justify-center align-center material-inputs">
<mat-form-field appearance="none" class="width-100" placeholder="Sample Type" required>
<!-- <input matInput type="text" > -->
<mat-select [(value)]="_postEvent.EventRecurrence.frequency" >
<mat-option value="never">
Nunca
</mat-option>
<mat-option value="daily">
Diário
</mat-option>
<mat-option value="weekly">
Semanalmente
</mat-option>
<mat-option value="monthly">
Mensal
</mat-option>
<mat-option value="yearly">
Anual
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<!-- <div *ngIf="_postEvent.EventRecurrence.frequency == 'weekly'" class="container-div ion-item-class-2 d-flex pl-45 pb-20 justify-content-between">
<div class="days-to-select">Seg</div>
<div class="days-to-select">Ter</div>
<div class="days-to-select">Qua</div>
<div class="days-to-select">Qui</div>
<div class="days-to-select">Sex</div>
<div class="days-to-select">Sab</div>
<div class="days-to-select">Dom</div>
</div> -->
<div *ngIf="_postEvent.EventRecurrence.frequency != 'never'" class="container-div">
<div class="ion-item-class-2 d-flex" >
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-reapet.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 justify-center align-center material-inputs materia-top" >
<mat-form-field appearance="none" class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="picker1"
placeholder="Data Fim de Recorrência*"
[(ngModel)]="postEvent.EventRecurrence.until"
[disabled]="disabled"
>
<mat-datepicker-toggle id="new-inicio" matSuffix [for]="picker1" ></mat-datepicker-toggle>
<ngx-mat-datetime-picker #picker1
[showSpinners]="showSpinners"
[showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute"
[stepSecond]="stepSecond"
[touchUi]="touchUi"
[hideTime]="true"
>
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="allDayCheck" class="container-div">
<div class="ion-item-class-2 width-100 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1" [class.input-error]="Form?.get('Date')?.invalid && validateFrom ">
<mat-form-field appearance="none" floatLabel="never" class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="picker1" placeholder="Choose a date"
[(ngModel)]="_postEvent.StartDate" [max]="maxDate" [disabled]="disabled"
(ngModelChange)="onDateChange($event)"
>
<mat-datepicker-toggle id="new-inicio" matSuffix [for]="picker1"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #picker1 [showSpinners]="showSpinners" [showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute" [stepSecond]="stepSecond" [touchUi]="touchUi" [hideTime]="true">
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="!allDayCheck" class="container-div">
<div class="ion-item-class-2 width-100 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1" [class.input-error]="Form?.get('Date')?.invalid && validateFrom ">
<mat-form-field appearance="none" floatLabel="never" class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="picker1" placeholder="Choose a date"
[(ngModel)]="_postEvent.StartDate" [max]="maxDate" [disabled]="disabled" (ngModelChange)="onDateChange($event)">
<mat-datepicker-toggle id="new-inicio" matSuffix [for]="picker1"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #picker1 [showSpinners]="showSpinners" [showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute" [stepSecond]="stepSecond" [touchUi]="touchUi" [hideTime]="false">
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="allDayCheck" class="container-div">
<div class="ion-item-class-2 width-100 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1" [class.input-error]="Form?.get('Date')?.invalid && validateFrom ">
<mat-form-field appearance="none" floatLabel="never" floatLabel="never" class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="fim" placeholder="Choose a date" [(ngModel)]="_postEvent.EndDate"
[max]="maxDate" [disabled]="disabled" [min]="_postEvent.StartDate" >
<mat-datepicker-toggle id="new-fim" matSuffix [for]="fim"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #fim [showSpinners]="showSpinners" [showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute" [stepSecond]="stepSecond" [hideTime]="true">
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="!allDayCheck" class="container-div">
<div class="ion-item-class-2 width-100 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1" [class.input-error]="Form?.get('Date')?.invalid && validateFrom ">
<mat-form-field appearance="none" floatLabel="never" floatLabel="never" class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="fim" placeholder="Choose a date" [(ngModel)]="_postEvent.EndDate"
[max]="maxDate" [disabled]="disabled" [min]="_postEvent.StartDate">
<mat-datepicker-toggle id="new-fim" matSuffix [for]="fim"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #fim [showSpinners]="showSpinners" [showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute" [stepSecond]="stepSecond" [hideTime]="false">
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="_postEvent.EventRecurrence.Type != '-1'" class="container-div width-100">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div (click)="openLastOccurrence()" class="ion-input-class flex-grow-1">
<mat-form-field class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="occurrrence" placeholder="Choose a date"
[(ngModel)]="_postEvent.EventRecurrence.LastOccurrence" [disabled]="disabled" [min]="_postEvent.EndDate">
<mat-datepicker-toggle id="last-occurrence" matSuffix [for]="occurrrence"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #occurrrence [showSpinners]="showSpinners" [showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute" [stepSecond]="stepSecond" [touchUi]="touchUi">
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div class=" d-flex width-100">
<div class="ion-item-class-2 width-100">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-person.svg"></ion-icon>
</div>
<div class="ion-input-class-no-height"
[class.input-error]="Form?.get('participantes')?.invalid && validateFrom">
<div class="list-people">
<ion-item lines="none">
<ion-list>
<div *ngIf="taskParticipants?.length < 1" class="list-people-title">Adicionar Intervenientes*</div>
<div *ngFor="let participant of taskParticipants">{{participant.Name}}</div>
</ion-list>
</ion-item>
</div>
<div class="add-people">
<button class="btn-no-color cursor-pointer" (click)="addParticipants()">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-35-rem" slot="start"
src="assets/images/icons-arrow-forward.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="font-35-rem" slot="start"
src="assets/images/theme/gov/icons-arrow-forward.svg"></ion-icon>
</button>
</div>
</div>
</div>
</div>
<div class=" d-flex width-100">
<div class="ion-item-class-2 width-100">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-people-cc.svg"></ion-icon>
</div>
<div class="ion-input-class-no-height"
[class.input-error]="Form?.get('participantes')?.invalid && validateFrom">
<div class="list-people">
<ion-item lines="none">
<ion-list>
<ion-label *ngIf="taskParticipantsCc?.length < 1" class="list-people-title">Com conhecimento</ion-label>
<ion-label *ngFor="let participant of taskParticipantsCc">{{participant.Name}}</ion-label>
</ion-list>
</ion-item>
</div>
<div class="add-people">
<button class="btn-no-color cursor-pointer" (click)="addParticipantsCc()">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="font-35-rem" slot="start"
src="assets/images/icons-arrow-forward.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="font-35-rem" slot="start"
src="assets/images/theme/gov/icons-arrow-forward.svg"></ion-icon>
</button>
</div>
</div>
</div>
</div>
<div class="container-div">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-description.svg"></ion-icon>
</div>
<div class="ion-input-class-no-height width-100">
<ion-textarea autocomplete="on" autocorrect="on" spellcheck="true" [(ngModel)]="_postEvent.Body.Text"
placeholder="Detalhes" rows="6" cols="20"></ion-textarea>
</div>
</div>
</div>
<div (click)="getDoc()" class="d-flex container-div width-100 ion-item-container-no-border cursor-pointer">
<ion-label>
<div class="attach-icon">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/images/icons-attach-doc.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' "
src="assets/images/theme/gov/icons-attach-doc.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' "
src="assets/images/theme/{{ThemeService.currentTheme}}/icons-attach-doc.svg"></ion-icon>
</div>
<div class="attach-document">
<ion-label>Adicionar documentos</ion-label>
</div>
</ion-label>
</div>
<div class="d-flex container-div width-100" *ngFor="let document of loadedEventAttachments; let i = index">
<ion-list class="width-100 list" *ngIf="!document.remove">
<ion-item class="width-100">
<ion-label class="width-100">
<p class="d-flex ion-justify-content-between">
<span class="attach-title-item">{{document.subject || document.sourceName || document.SourceName || 'Sem título'}}</span>
<span class="app-name" *ngIf="document.applicationId == 8 || document.ApplicationId == 8"> Correspondencia </span>
<span class="app-name" *ngIf="document.applicationId == 386 || document.ApplicationId == 386"> AccoesPresidenciais </span>
<span class="app-name" *ngIf="document.applicationId == 361 || document.ApplicationId == 361 "> ArquivoDespachoElect </span>
<span class="close-button text-black cursor-pointer" (click)="deleteAttachment(document.Id, i)">
<ion-icon class="font-20" src="assets/images/icons-delete-25.svg"></ion-icon>
</span>
</p>
<p><span class="span-left">{{document.Stakeholders}}</span><span class="span-right"> {{ document.dateEntry }} </span></p>
</ion-label>
</ion-item>
</ion-list>
</div>
</div>
</ion-content>
<ion-footer class="ion-no-border">
<ion-toolbar class="width-100 d-flex justify-space-between px-20">
<ion-buttons slot="start">
<button class="btn-ok" fill="clear" color="#fff" (click)="save_v2()">
<ion-label>Gravar</ion-label>
</button>
</ion-buttons>
<ion-title></ion-title>
<ion-buttons slot="end">
<button class="btn-cancel" fill="clear" color="#061b52" (click)="close()">
<ion-label>Cancelar</ion-label>
</button>
</ion-buttons>
</ion-toolbar>
</ion-footer>
@@ -0,0 +1,233 @@
@import '~src/function.scss';
ion-content{
--background:transparent;
}
.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);
.title-content{
margin: 0px auto;
padding: 0 !important;
background: #fff;
.middle{
padding: 0!important;
float: left;
margin: 2.5px 0 0 5px;
}
}
.title{
font-size: rem(25);
}
}
.main-content{
width: 100%; /* 400px */
height: 100%;
font-family: Roboto;
margin: 0 auto;
background-color: #fff;
padding: 15px 20px 0 20px;
.ion-item-container{
margin: rem(15) auto;
border: 1px solid #ebebeb;
border-radius: 5px;
padding-left: 10px;
}
.ion-item-container-no-border{
width: 100%;
margin: 0px auto;
padding: 0 !important;
}
.container-div{
margin-bottom: 15px;
}
.ion-item-class-2{
margin: 0px auto;
}
.ion-icon-class{
width: rem(45);
height: rem(45);
float: left;
padding: 10px;
font-size: rem(25);
}
ion-select{
padding-left: 5px;
margin-left: 0;
}
.ion-input-class{
height: rem(45);
border: 1px solid #ebebeb;
border-radius: 5px;
padding-left: 5px;
padding-right: 10px;
float: left;
}
.ion-input-class-no-height{
height: auto !important;
border: 1px solid #ebebeb;
border-radius: 5px;
margin-bottom: 15px;
overflow: auto;
}
.list-people{
float: left;
}
.add-people{
width: rem(45);
float: right;
font-size: rem(25);
height: rem(45);
display: flex;
}
.list-people-title{
/* font-size: rem(13); */
color: #a3a3a3;
}
.attach-document{
font-size: rem(15);
color: var(--title-text-color);
margin: 5px 5px 5px 10px;
padding: 5px;
float: left;
}
.attach-icon{
width: 37px;
font-size: rem(35);
float: left;
}
.attach-title-item{
width: 100%;
font-size: rem(15);
color: var(--title-text-color);
}
/* SPAN */
.span-left{
float: left;
font-size: rem(15);
}
.span-right{
text-align: right;
float: right;
font-size: rem(13);
}
.container-footer{
margin:0 auto;
}
.button-cancel {
width: 170px;
height: rem(44);
border-radius: 22.5px;
--background: #e0e9ee;
--color: #061b52;
margin:10px;
}
.button-save {
width: 170px;
height: rem(44);
border-radius: 22.5px;
--background: #42b9fe;
--color:#ffffff;
margin:10px;
}
.text-input{
width: 100%;
border: 1px solid #ebebeb;
margin: 0px 15px 15px 0px;
padding: 0 !important;
border-radius: 5px;
}
/* Error Messages */
.error{
color:red;
font-size: rem(12);
font-weight: bold;
padding-bottom: 20px;
}
.span-color{
color:red;
}
}
.app-name{
background: var(--title-text-color);
border-radius: 18px;
text-align: center;
display: flex;
align-items: center;
padding: 0px 5px;
color: white;
font-size: rem(12);
font-weight: 500;
height: 19px;
-webkit-border-radius: 18px;
-moz-border-radius: 18px;
-ms-border-radius: 18px;
-o-border-radius: 18px;
}
.close-button {
display: none;
height: 20px;
}
.list:hover {
.app-name {
display: none;
}
.close-button {
display: block !important;
height: 20px;
}
}
.materia-top {
padding-top: 7px;
}
.days-to-select{
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: #ebebeb;
border-radius: 50px;
box-shadow: 0px 0px 10px #f9f9f9;
border: 1px solid #d1d1d1;
cursor: pointer;
user-select: none;
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
-ms-border-radius: 50px;
-o-border-radius: 50px;
}
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { EditEventPage } from './edit-event.page';
describe('EditEventPage', () => {
let component: EditEventPage;
let fixture: ComponentFixture<EditEventPage>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ EditEventPage ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(EditEventPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,715 @@
import { Component, OnInit, Input, Output, EventEmitter, ViewChild } from '@angular/core';
import { ModalController } from '@ionic/angular';
import { EventBody } from 'src/app/models/eventbody.model';
import { EventPerson } from 'src/app/models/eventperson.model';
import { Event } from 'src/app/models/event.model';
import { AlertController } from '@ionic/angular';
import { removeDuplicate } from 'src/plugin/removeDuplicate.js'
import { SearchPage } from 'src/app/pages/search/search.page';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ParticipantsPipe } from 'src/app/pipes/participants.pipe';
import { ThemeService } from 'src/app/services/theme.service'
import { SessionStore } from 'src/app/store/session.service';
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
import { AgendaDataRepositoryService } from 'src/app/module/agenda/data/repository/agenda-data-repository.service';
import { SearchList_v2 } from 'src/app/models/search-document';
import { Utils } from 'src/app/module/agenda/utils';
import { Observable } from 'rxjs';
import { TableSharedCalendar } from 'src/app/module/agenda/data/data-source/agenda-local-data-source.service';
import { RoleIdService } from 'src/app/services/role-id.service'
import { XTracerAsync, TracingType } from 'src/app/services/monitoring/opentelemetry/tracer';
import { AttendeesLIstChangeDetector } from 'src/app/module/agenda/data/async/change/attendeesLIstChangeDetector';
import { EventRecurrenceComponentReturn, EventRecurrencePage } from 'src/app/modals/event-recurrence/event-recurrence.page';
@Component({
selector: 'app-edit-event',
templateUrl: './edit-event.page.html',
styleUrls: ['./edit-event.page.scss'],
})
export class EditEventPage implements OnInit {
stEvent: Event;
isRecurring: string;
isEventEdited: boolean;
loadedEvent: Event;
initCalendarName: string;
eventBody: EventBody;
segment: string = "true";
eventAttendees: EventPerson[];
// minDate: string;
loadedEventAttachments: any[] = [];
selectedRecurringType: any;
deletedAttachmentsList = [];
public date: any;
public disabled = false;
public showSpinners = true;
public showSeconds = false;
public touchUi = false;
public enableMeridian = false;
public minDate = new Date().toISOString().slice(0, 10)
public endMinDate = new Date(new Date().getTime() + 15 * 60000).toISOString().slice(0, 10)
public maxDate: any;
public stepHour = 1;
public stepMinute = 15;
public stepSecond = 15;
Form: FormGroup;
validateFrom = false
@Input() taskParticipants: EventPerson[];
@Input() taskParticipantsCc: EventPerson[];
@Input() profile: string;
@Input() selectedSegment: string;
@Input() postEvent: Event;
@Output() clearContact = new EventEmitter<any>();
@Output() openAttendeesComponent = new EventEmitter<any>();
@Output() closeComponent = new EventEmitter<any>();
@Output() setIntervenient = new EventEmitter<any>();
@Output() setIntervenientCC = new EventEmitter<any>();
@Output() clearPostEvent = new EventEmitter<any>();
showLoader = false
@ViewChild('picker') picker: any;
@ViewChild('fim') fim: any;
@ViewChild('inicio') inicio: any;
@ViewChild('picker1') picker1: any;
@Input() _postEvent: Event;
public options = [
{ value: true, label: 'True' },
{ value: false, label: 'False' }
];
public listColors = ['primary', 'accent', 'warn'];
public stepHours = [1, 2, 3, 4, 5];
public stepMinutes = [1, 5, 10, 15, 20, 25];
public stepSeconds = [1, 5, 10, 15, 20, 25];
private participantsPipe = new ParticipantsPipe()
SessionStore= SessionStore
allDayCheck: boolean = false;
addedAttachmentsList = [];
sharedCalendar: Observable<TableSharedCalendar[]>
hasChangeCalendar = false
selectedUserCalendar:any;
CalendarNamesOptions = ['Oficial', 'Pessoal']
dateDifference = 0
editAllEvent = false
constructor(
private modalController: ModalController,
public alertController: AlertController,
public ThemeService: ThemeService,
private httpErrorHandle: HttpErrorHandle,
private agendaDataRepository: AgendaDataRepositoryService,
private utils: Utils,
public RoleIdService: RoleIdService,
) {
this.sharedCalendar = this.agendaDataRepository.getShareCalendarItemsLiveWithOrder()
}
hasPrCalendar(data: TableSharedCalendar[]) {
for(const e of data) {
if(e.roleId == this.RoleIdService.PRES) {
return true
}
}
return false
}
changeSegmentCalendar() {
this.hasChangeCalendar = true
}
ngOnInit() {
this.selectedUserCalendar = this.postEvent.owner.wxUserId
this.loadedEventAttachments = this.postEvent.Attachments
this._postEvent = this.postEvent
this._postEvent.Category = this.setEventType(this._postEvent.Category)
if (!this._postEvent.IsRecurring) {
this._postEvent.EventRecurrence.frequency = 'never';
} else {
this._postEvent.EventRecurrence.frequency = this.utils.recurenceTypeSeleted(this.postEvent.EventRecurrence.frequency)
}
this.allDayCheck = this.postEvent.IsAllDayEvent;
if (!this.restoreTemporaryData()) {
this.validationEditAllEvent()
// clear
if (this._postEvent) {
if (this._postEvent.Body) {
if (typeof (this._postEvent.Body.Text) == 'string') {
this._postEvent.Body.Text = this._postEvent.Body.Text.replace(/<[^>]+>/g, '');
}
}
}
if (this._postEvent.Attendees != null) {
const result = this.participantsPipe.transform(this._postEvent.Attendees)
this.taskParticipants = result.taskParticipants
this.taskParticipantsCc = result.taskParticipantsCc
this.taskParticipants = removeDuplicate(this.taskParticipants);
this.taskParticipantsCc = removeDuplicate(this.taskParticipantsCc);
this.setIntervenient.emit(this.taskParticipants);
this.setIntervenientCC.emit(this.taskParticipantsCc);
}
}
this.initCalendarName = this._postEvent.CalendarName;
setTimeout(() => {
this._postEvent.EventRecurrence.Type = this._postEvent.EventRecurrence.Type.toString();
}, 500);
this.changeAgenda()
}
ngOnDestroy() {
clearInterval(this.myInterval)
}
myInterval = setInterval(() => {
document.querySelectorAll('.ngx-mat-timepicker input').forEach((e: any) => {
if (e) {
e.disabled = true;
}
})
}, 1000);
ngOnChanges(changes: any): void {
this.loadedEventAttachments = this._postEvent?.Attachments
}
close() {
this.closeComponent.emit();
this.setIntervenient.emit([]);
this.setIntervenientCC.emit([]);
this.clearContact.emit();
this.deleteTemporaryData();
}
runValidation() {
this.validateFrom = true
}
injectValidation() {
if (typeof (this._postEvent.EventRecurrence.Type) == 'number') {
const str: any = this._postEvent.EventRecurrence.Type.toString()
this._postEvent.EventRecurrence.Type = str
}
this.Form = new FormGroup({
Subject: new FormControl(this._postEvent.Subject, [
Validators.required,
// Validators.minLength(4)
]),
Location: new FormControl(this._postEvent.Location, [
Validators.required,
]),
CalendarName: new FormControl(this._postEvent.CalendarName),
Categories: new FormControl(this._postEvent.Category, [
Validators.required
]),
dateOccurrence: new FormControl(this._postEvent.EventRecurrence.Type.toString() == '-1' ? ['ok'] : this._postEvent.EventRecurrence.LastOccurrence && new Date(this._postEvent.EventRecurrence.LastOccurrence).getTime() > new Date(this._postEvent.EndDate).getTime() ? 'ok' : null, [
Validators.required
]),
participantes: new FormControl(this.taskParticipants, [
// Validators.required
]),
Date: new FormControl(true, [
Validators.required
]),
})
}
openInicio() {
let input: any = document.querySelector('#new-inicio')
if (input) {
input.click()
}
}
openFim() {
let input: any = document.querySelector('#new-fim')
if (input) {
input.click()
}
}
openLastOccurrence() {
let input: any = document.querySelector('#last-occurrence')
if (input) {
input.click()
}
}
roundTimeQuarterHour() {
let date = new Date();
const minutes = date.getMinutes();
date.setSeconds(0);
if (minutes % 15 != 0) {
if (minutes > 45) {
date.setMinutes(60)
} else if (minutes > 30) {
date.setMinutes(45)
} else if (minutes > 15) {
date.setMinutes(30)
} else if (minutes > 0) {
date.setMinutes(15)
}
}
return date
}
roundTimeQuarterHourPlus15(date: Date) {
const _date = new Date(date);
const minutes = _date.getMinutes();
_date.setMinutes(minutes + 15)
return _date
}
calculetedLastOccurrence(type: number) {
var valor;
var opcao: boolean;
if (type == 0) {
valor = 7;
opcao = true;
} else if (type == 1) {
valor = 30;
opcao = true;
} else if (type == 2) {
valor = 1;
opcao = false;
} else if (type == 3) {
valor = 5;
opcao = false;
}
this.defineLastOccurrence(valor, opcao);
}
defineLastOccurrence(valor: number, opcao: boolean) {
var time = new Date(this._postEvent.EndDate);
if (opcao == true) {
time.setDate(time.getDate() + valor);
this._postEvent.EventRecurrence.LastOccurrence = time;
} else {
time = new Date(
time.getFullYear() + valor,
time.getMonth(),
time.getDate(),
time.getHours(),
time.getMinutes()
);
this._postEvent.EventRecurrence.LastOccurrence = time;
}
}
async validationEditAllEvent() {
if (this.postEvent.IsRecurring ) {
const modal = await this.modalController.create({
component: EventRecurrencePage,
componentProps: {},
cssClass: 'event-recurrence-modal',
});
modal.onDidDismiss().then((res) => {
const data: EventRecurrenceComponentReturn = res.data
if(data =='EditAll') {
this.editAllEvent = true
} else if (data == 'EditOne') {
this.editAllEvent = false
} else if(data == 'Cancel') {
this.close()
} else {
this.close()
}
});
await modal.present();
}
}
@XTracerAsync({name:'desktop/edit-event', bugPrint: true, daley: 4000})
async save_v2(tracing?: TracingType) {
this.injectValidation()
this.runValidation()
if (this.Form.invalid) {
return false
}
const serverCurrentList = this._postEvent.Attendees
this._postEvent.Attendees = this.taskParticipants.concat(this.taskParticipantsCc);
try {
const calendar = await this.agendaDataRepository.getCalendarByUserId(this.selectedUserCalendar)
if(calendar.isOk()) {
this.showLoader = true;
const value = await this.agendaDataRepository.updateEvent(this._postEvent.EventId, this._postEvent, this.editAllEvent, calendar.value, tracing)
if(value.isOk()) {
console.log(value.value)
this.httpErrorHandle.httpsSucessMessagge('Editar evento')
this.clearPostEvent.emit();
this.deleteTemporaryData();
this.showLoader = false;
tracing
} else {
console.log('edit event error: ', value.error)
tracing.setAttribute('outcome', 'failed')
}
const { insert, remove } = AttendeesLIstChangeDetector(serverCurrentList as any, this._postEvent.Attendees as any)
console.log({ insert, remove });
if(insert.length >= 1) {
try {
await this.agendaDataRepository.addEventAttendee(this._postEvent.EventId, insert, tracing).toPromise()
} catch (error) {
tracing.setAttribute('failed.attendees', 'true')
console.log('add Attendee error: ', error)
}
// let a = this.agendaDataRepository.addEventAttendee(this._postEvent.EventId, insert, tracing).subscribe((value) => {
// console.log(value)
// }, ((error) => {
// tracing.setAttribute('failed.attendees', 'true')
// console.log('add Attendee error: ', error)
// }));
}
if(remove.length >= 1) {
try {
await this.agendaDataRepository.removeEventAttendee(this._postEvent.EventId, remove).toPromise()
} catch (error) {
tracing.setAttribute('failed.attendees', 'true')
console.log('add Attendee error: ', error)
}
// this.agendaDataRepository.removeEventAttendee(this._postEvent.EventId, remove).subscribe((value) => {
// console.log(value)
// }, ((error) => {
// tracing.setAttribute('failed.attendees', 'true')
// console.log('add Attendee error: ', error)
// }));
}
if (this.addedAttachmentsList.length >= 1) {
try {
await this.agendaDataRepository.addEventAttachment(this._postEvent.EventId, this.loadedEventAttachments, tracing).toPromise()
} catch (error) {
this.showLoader = false
tracing.setAttribute('failed.add.attachment', 'true')
console.log('add attachment error: ', error)
}
// this.agendaDataRepository.addEventAttachment(this._postEvent.EventId, this.loadedEventAttachments, tracing).subscribe((value) => {
// console.log(value)
// }, ((error) => {
// this.showLoader = false
// tracing.setAttribute('failed.add.attachment', 'true')
// console.log('add attachment error: ', error)
// }));
}
if (this.deletedAttachmentsList.length >= 1) {
try {
await this.agendaDataRepository.removeEventAttachment(this._postEvent.EventId, { attachments: this.deletedAttachmentsList }).toPromise()
} catch (error) {
this.showLoader = false
console.log('remove attachment error: ', error)
}
// this.agendaDataRepository.removeEventAttachment(this._postEvent.EventId, { attachments: this.deletedAttachmentsList }).subscribe((value) => {
// console.log(value)
// }, ((error) => {
// this.showLoader = false
// console.log('remove attachment error: ', error)
// }));
}
this.close();
} else {
console.log('this.selectedUserCalendar', this.selectedUserCalendar)
console.log(calendar.error)
}
} catch (error) {
this.httpErrorHandle.httpStatusHandle(error)
console.log('edit: ', error)
}
}
async addParticipants() {
this.saveTemporaryData();
this.openAttendeesComponent.emit({
type: "intervenient"
});
this.clearContact.emit();
}
async addParticipantsCc() {
this.saveTemporaryData();
this.openAttendeesComponent.emit({
type: "CC"
});
this.clearContact.emit();
}
onDateChange(e) {
const cloneDateStartDate = new Date(this._postEvent.StartDate);
const cloneDateEndDate = new Date(this._postEvent.EndDate);
if(cloneDateStartDate.getTime() >= cloneDateEndDate.getTime()) {
cloneDateStartDate.setHours(cloneDateStartDate.getHours() + 1);
this._postEvent.EndDate = cloneDateStartDate
}
}
saveTemporaryData() {
window['temp.path:/home/agenda/edit-event.component.ts'] = {
postEvent: this._postEvent,
eventBody: this.eventBody,
segment: this.segment,
loadedEventAttachments: this.loadedEventAttachments,
}
}
restoreTemporaryData(): boolean {
const restoredData = window['temp.path:/home/agenda/edit-event.component.ts']
if (JSON.stringify(restoredData) != "{}" && undefined != restoredData) {
this._postEvent = restoredData.postEvent
this.eventBody = restoredData.eventBody
this.segment = restoredData.segment
this.loadedEventAttachments = restoredData.loadedEventAttachments
return true;
} else {
return false;
}
}
deleteTemporaryData() {
window['temp.path:/home/agenda/edit-event.component.ts'] = {}
}
deleteAttachment(attachmentID: string, index) {
const indexToRemove = index; // Assuming you already know the index you want to remove
const DocumentId: any = this.loadedEventAttachments[index].Id
if (indexToRemove > -1 && indexToRemove < this.loadedEventAttachments.length) {
this.loadedEventAttachments.splice(indexToRemove, 1);
}
this.deletedAttachmentsList.push(DocumentId)
}
async getDoc() {
const modal = await this.modalController.create({
component: SearchPage,
cssClass: 'modal-width-100-width-background modal',
componentProps: {
type: 'AccoesPresidenciais & ArquivoDespachoElect',
eventAgenda: true,
showSearchInput: true,
select: true,
}
});
modal.onDidDismiss().then(async (res) => {
if (res) {
const data = res.data;
console.log('Get Doc', data.selected)
/* const ApplicationIdDocumentToSave: any = {
SourceName: data.selected.Assunto,
ParentId: this._postEvent.EventId,
SourceId: data.selected.Id,
Stakeholders: data.selected.EntidadeOrganicaNome | data.selected.Stakeholders,
ApplicationId: data.selected.ApplicationType.toString(),
CreateDate: data.selected.Data,
Id: 'add',
SourceTitle: data.selected.Assunto,
Source: '1',
Link: '',
SerialNumber: '',
}*/
console.log({data})
let newDocObject: SearchList_v2 & {ApplicationId: any} = {
docId: data.selected.docId,
sourceName: data.selected.sourceName,
description: data.selected.description,
applicationId: data.selected.applicationId,
classificator: data.selected.classificator,
dateEntry: data.selected.dateEntry,
docNumber: data.selected.docNumber,
subject: data.selected.subject,
userId: data.selected.userId,
ApplicationId: data.selected.applicationId
}
this.loadedEventAttachments.push(data.selected)
this.addedAttachmentsList.push(data.selected)
}
});
await modal.present();
}
async changeAgenda() {
const result = await this.agendaDataRepository.geCalendars()
const selectedCalendar = result.find(e => e.wxUserId == this.selectedUserCalendar)
if(selectedCalendar) {
if(selectedCalendar.shareType == 1) {
this.CalendarNamesOptions = ['Oficial']
} else if(selectedCalendar.shareType == 2) {
this.CalendarNamesOptions = ['Pessoal']
} else if (selectedCalendar.shareType == 3) {
this.CalendarNamesOptions = ['Oficial', 'Pessoal']
}
}
}
onCheckboxChange(event: any) {
console.log(this.postEvent.CalendarId)
if (this.allDayCheck) {
this.postEvent.IsAllDayEvent = this.allDayCheck;
this.postEvent.StartDate = this.setAlldayTime(this.postEvent.StartDate)
this.postEvent.EndDate = this.setAlldayTimeEndDate(this.postEvent.EndDate)
console.log('Recurso ativado!!');
} else {
this.postEvent.IsAllDayEvent = this.allDayCheck;
this.postEvent.EndDate = this.setAlldayTimeEndDateNotAlday(this.postEvent.EndDate)
console.log('Recurso desativado');
}
}
setAlldayTime(timeToReturn) {
let date: any = new Date(timeToReturn) || new Date();
let newdate = new Date();
date.setHours(0)
date.setMinutes(0)
date.setSeconds(0);
return date
}
setAlldayTimeEndDate(timeToReturn) {
let date: any = new Date(timeToReturn) || new Date();
let newdate = new Date();
date.setHours(23)
date.setMinutes(59)
date.setSeconds(0);
return date
}
setAlldayTimeEndDateNotAlday(timeToReturn) {
let date: any = new Date(timeToReturn) || new Date();
let newdate = new Date();
date.setHours(23)
date.setMinutes(0)
date.setSeconds(0);
return date
}
setEventType(eventType) {
if(typeof eventType == 'number') {
var selectedEventType = {
1: 'Meeting',
2: 'Travel',
3: 'Conference',
4: 'Encontro'
}
return selectedEventType[eventType];
} else {
return this._postEvent.Category
}
}
}
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { EventListPage } from './event-list.page';
const routes: Routes = [
{
path: '',
component: EventListPage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class EventListPageRoutingModule {}
@@ -0,0 +1,47 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { EventListPageRoutingModule } from './event-list-routing.module';
import { EventListPage } from './event-list.page';
import { MatInputModule } from '@angular/material/input';
import { MatNativeDateModule } from '@angular/material/core';
import {
NgxMatDatetimePickerModule,
NgxMatNativeDateModule,
NgxMatTimepickerModule
} from '@angular-material-components/datetime-picker';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatSelectModule } from '@angular/material/select';
import { NgxMatMomentModule } from '@angular-material-components/moment-adapter';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
EventListPageRoutingModule,
//
MatInputModule,
MatNativeDateModule,
NgxMatDatetimePickerModule,
NgxMatTimepickerModule,
NgxMatNativeDateModule,
NgxMatMomentModule,
MatSelectModule,
MatButtonModule,
],
declarations: [EventListPage],
exports: [EventListPage]
})
export class EventListPageModule {}
@@ -0,0 +1,80 @@
<ion-header class="ion-no-border">
<div class="header-content">
<div class="header-title d-flex align-center justify-between width-100">
<div class="flex-grow-1">Eventos para aprovação</div>
<div (click)="refreshing()">
<button title="Atualizar" class="btn-no-color" >
<ion-icon class=" font-45-em" src="assets/images/theme/gov/icon-reload.svg"></ion-icon>
</button>
</div>
</div>
<ion-toolbar *ngIf="(sharedCalendar | async) as calendarData">
<ion-segment [(ngModel)]="selectedUserCalendar" (ionChange)="segmentChanged($event)" *ngIf="SessionStore.user.RoleID !== 100000014">
<ion-segment-button *ngFor="let calendars of calendarData" value="{{calendars.wxUserId}}" >
<div *ngIf="environment.presidential">
<div *ngIf="calendars.roleId == RoleIdService.PRES">AGENDA DO PR </div>
<div *ngIf="calendars.roleId == RoleIdService.MD && calendars.roleId != SessionStore.user.RoleID">AGENDA DO MDGPR</div>
<div *ngIf="calendars.roleId != RoleIdService.MD && calendars.roleId != RoleIdService.PRES && calendars.wxFullName && calendars.wxUserId != SessionStore.user.UserId "> Agenda {{calendars.wxFullName}} </div>
<div *ngIf="calendars.wxUserId == SessionStore.user.UserId ">
Minha agenda
</div>
</div>
<div *ngIf="!environment.presidential">
<div *ngIf="calendars.roleId == RoleIdService.PRES">{{ environment.agendaPR}} </div>
<div *ngIf="calendars.roleId == RoleIdService.MD && calendars.roleId != SessionStore.user.RoleID">{{ environment.agendaVP}}</div>
<div *ngIf="calendars.roleId != RoleIdService.MD && calendars.roleId != RoleIdService.PRES && calendars.wxFullName && calendars.wxUserId != SessionStore.user.UserId "> Agenda {{calendars.wxFullName}} </div>
<div *ngIf="calendars.wxUserId == SessionStore.user.UserId ">
Minha agenda
</div>
</div>
</ion-segment-button>
</ion-segment>
</ion-toolbar>
</div>
</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 overflow-y-auto height-100" >
<!-- <div class="header-content width-100"> -->
<!-- </div> -->
<ion-list class="width-100">
<div class="width-100" >
<div
class="item ion-no-padding width-100 cursor-pointer"
*ngFor="let event of eventoaprovacaostore.get(selectedUserCalendar)"
(click)="openApproveModal(event.serialNumber, event)"
>
<div class="event-{{color}}-{{event.workflowInstanceDataFields.Agenda}} width-100">
<div *ngIf="!event.workflowInstanceDataFields.IsAllDayEvent" class="approve-event-time">
<p>{{event.workflowInstanceDataFields.StartDate | date: 'HH:mm'}}</p>
<p>{{event.workflowInstanceDataFields.EndDate | date: 'HH:mm'}}</p>
</div>
<div *ngIf="event.workflowInstanceDataFields.IsAllDayEvent" class="approve-event-time">
<p>Todo</p>
<p>o dia</p>
</div>
<div class="approve-event-detail">
<h3>{{event.workflowInstanceDataFields.Subject}}</h3>
<p *ngIf="toDateString(event.workflowInstanceDataFields.StartDate) != toDateString(event.workflowInstanceDataFields.EndDate)">{{event.workflowInstanceDataFields.StartDate | date: 'd/M/yy' }} - {{ event.workflowInstanceDataFields.EndDate | date: 'dd/M/yy'}} | {{event.workflowInstanceDataFields.Location}}</p>
<p *ngIf="toDateString(event.workflowInstanceDataFields.StartDate) == toDateString(event.workflowInstanceDataFields.EndDate)">{{event.workflowInstanceDataFields.StartDate | date: 'd/M/yy' }} | {{event.workflowInstanceDataFields.Location}}</p>
<div *ngIf="event.activityInstanceName">
<div class="label-event-type font-13-rem"> {{ event.activityInstanceName }} </div>
</div>
</div>
</div>
</div>
</div>
</ion-list>
</div>
</ion-content>
@@ -0,0 +1,121 @@
@import '~src/function.scss';
:host{
margin: 0;
}
.header-content{
overflow: auto;
margin: 0 auto;
padding: 30px 20px 0 20px !important;
}
.header-icon-left{
font-size: rem(33);
color: #42b9fe;
float: left;
}
.header-title{
font-family: Roboto;
font-size: rem(25);
padding: 0;
color:#000;
float: left;
}
.main-content{
padding: 0px 20px 0 20px !important;
margin-top: 20px;
.item{
--inner-padding-end: 0 !important;
--inner-padding-top: 10px;
--inner-padding-bottom:10px;
border-radius: 15px;
box-shadow: 0 0 10px 0 rgb(0 0 0 / 7%);
border: 1px solid #e9e9e9 !important;
background-color: var(--white);
margin-bottom: 10px !important;
padding: 15px;
}
.event-pr-Oficial{
background-color: var(--white);
border-radius: 5px;
border-right: 5px solid #99e47b;
overflow: auto;
}
.event-pr-Pessoal{
background-color: var(--white);
border-radius: 5px;
border-right: 5px solid #958bfc;
overflow: auto;
}
.event-mdgpr-Oficial{
border-radius: 5px;
border-right: 5px solid var(--label-bg-color);
overflow: auto;
}
.event-mdgpr-Pessoal{
border-radius: 5px;
border-right: 5px solid #f05d5e;
overflow: auto;
}
.approve-event-time{
float: left;
}
.approve-event-time p{
width: 33px;
font-family: Roboto;
font-size: rem(13);
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
color: var(--Antartic-grey);
margin: 0;
padding-bottom: 10px;
}
.approve-event-detail{
float: left;
margin-left: 10px;
}
.approve-event-detail p{
//width: 250px;
font-family: Roboto;
font-size: rem(13);
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
color: var(--black);
margin: 0;
padding-bottom: 10px;
}
.approve-event-detail h3{
width: 250px;
font-family: Roboto;
font-size: rem(15);
font-weight: bold;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-transform: none ;
color: var(--title-text-color);
margin: 0;
padding: 0;
max-width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.label-event-type {
padding: 1px 7px;
display: inline-block;
background: #f05d5e;
border-radius: 17px;
color: white;
font-size: rem(13);
}
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { EventListPage } from './event-list.page';
describe('EventListPage', () => {
let component: EventListPage;
let fixture: ComponentFixture<EventListPage>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ EventListPage ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(EventListPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,216 @@
import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';
import { EventBody } from 'src/app/models/eventbody.model';
import { EventPerson } from 'src/app/models/eventperson.model';
import { ProcessesService } from 'src/app/services/processes.service';
import { NavigationEnd, Router } from '@angular/router';
import { LoginUserRespose } from 'src/app/models/user.model';
import { SortService } from 'src/app/services/functions/sort.service';
import { SessionStore } from 'src/app/store/session.service';
import { EventsService } from 'src/app/services/events.service';
import { EventoAprovacaoStore } from 'src/app/store/eventoaprovacao-store.service';
import { environment } from 'src/environments/environment';
import { AgendaDataRepositoryService } from 'src/app/module/agenda/data/repository/agenda-data-repository.service';
import { EventToApproveList } from 'src/app/models/entiry/agenda/eventToApproveList';
import { RoleIdService } from 'src/app/services/role-id.service'
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { TableSharedCalendar } from 'src/app/module/agenda/data/data-source/agenda-local-data-source.service';
import { EEventFilterStatus } from 'src/app/module/agenda/data/dto/enums';
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
import { isHttpError } from 'src/app/services/http.service';
import { ToastService } from 'src/app/services/toast.service';
@Component({
selector: 'app-event-list',
templateUrl: './event-list.page.html',
styleUrls: ['./event-list.page.scss'],
})
export class EventListPage implements OnInit {
// [desktop] event list to approve
showLoader: boolean;
eventsList: EventToApproveList = []
eventPerson: EventPerson;
eventBody: EventBody;
categories: string[];
serialnumber:string;
loggeduser: LoginUserRespose;
segment:string;
eventoaprovacaostore = EventoAprovacaoStore;
environment = environment
color: 'pr' | 'mdgpr'
SessionStore = SessionStore;
@Input() profile:string;
@Input() showComponent:string;
@Output() cloneAllmobileComponent = new EventEmitter<any>();
@Output() approveEventDismiss = new EventEmitter<any>();
sharedCalendar: Observable<TableSharedCalendar[]>
selectedUserCalendar:any;
constructor(
private processes:ProcessesService,
private router: Router,
private sortService: SortService,
public eventService: EventsService,
public AgendaDataRepositoryService: AgendaDataRepositoryService,
public RoleIdService: RoleIdService,
private toastService: ToastService,
) {
this.loggeduser = SessionStore.user;
// Define the role priorities
const rolePriorities: { [key: number]: number } = {
100000014: 1, // Presidente da República
100000011: 2, // Vice Presidente (example role ID)
// Add other roles with their priorities here
};
this.sharedCalendar = this.AgendaDataRepositoryService.getShareCalendarItemsLive().pipe(
map(data => data.sort((a, b) => {
const priorityA = rolePriorities[a.roleId] || Infinity;
const priorityB = rolePriorities[b.roleId] || Infinity;
return priorityA - priorityB;
}))
)
this.setCalendarByDefault()
}
async setCalendarByDefault() {
const data = await this.AgendaDataRepositoryService.geCalendars()
const prObject = data.find(e => e?.roleId == 100000014)
if(prObject) {
this.selectedUserCalendar = prObject.wxUserId
} else {
this.selectedUserCalendar = SessionStore.user.UserId
}
}
ngAfterViewInit(): void {}
ngOnInit() {
const pathname = window.location.pathname
this.router.events.forEach((event) => {
if(event instanceof NavigationEnd && event.url == pathname) {
this.LoadToApproveEvents();
}
});
}
ngOnChanges() {
this.LoadToApproveEvents();
setTimeout(() => {
this.LoadToApproveEventsNoLoader();
}, 3000)
}
segmentChanged(ev: any) {
this.LoadToApproveEvents();
}
toDateString(e) {
return new Date(e).toDateString()
}
@XTracerAsync({name:'EventListPageShared/LoadToApproveEvents', bugPrint: true})
async LoadToApproveEvents(tracing?: TracingType) {
this.showLoader = true;
const segment = this.selectedUserCalendar
let userId;
if(this.selectedUserCalendar == SessionStore.user.UserId) {
// color
if(SessionStore.user.Profile == 'PR') {
this.color = 'pr'
} else {
this.color = 'mdgpr'
}
userId = SessionStore.user.UserId
} else if(segment) {
this.color = 'pr'
userId = this.selectedUserCalendar
}
if(userId) {
let allEvents = await this.AgendaDataRepositoryService.eventToApproveList({
userId,
status: EEventFilterStatus.Pending
}, tracing)
if(allEvents.isOk()) {
tracing.setAttribute('outcome', 'success')
if(allEvents.value.length >= 1) {
this.eventsList = this.sortService.sortArrayByDate(allEvents.value).reverse();
this.eventoaprovacaostore.save(this.selectedUserCalendar, this.eventsList)
} else {
this.eventoaprovacaostore.save(this.selectedUserCalendar, [])
}
} else {
tracing.setAttribute('outcome', 'failed')
if(!isHttpError(allEvents.error)) {
this.toastService._badRequest('Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico. #3')
console.log(allEvents.error)
}
this.eventsList = [];
}
this.showLoader = false;
} else {
tracing.setAttribute('run', 'to early')
console.warn('calling to early eventlistpageshared/loadtoapproveevents')
}
}
async LoadToApproveEventsNoLoader() {
this.LoadToApproveEvents()
}
async openApproveModal(eventSerialNumber, data) {
this.approveEventDismiss.emit({
"serialNumber": eventSerialNumber,
"action": "Aprovar",
"saveData": data
});
}
refreshing() {
this.LoadToApproveEvents();
}
doRefresh(event) {
this.LoadToApproveEvents();
setTimeout(() => {
try {
event?.target?.complete();
} catch(error) {}
}, 2000);
}
close() {
this.cloneAllmobileComponent.emit();
}
}
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { NewEventPage } from './new-event.page';
const routes: Routes = [
{
path: '',
component: NewEventPage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class NewEventPageRoutingModule {}
@@ -0,0 +1,69 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, NgControl } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { NewEventPageRoutingModule } from './new-event-routing.module';
import { NewEventPage } from './new-event.page';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatInputModule } from '@angular/material/input';
import { MatNativeDateModule } from '@angular/material/core';
import {
NgxMatDatetimePickerModule,
NgxMatNativeDateModule,
NgxMatTimepickerModule
} from '@angular-material-components/datetime-picker';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatSelectModule } from '@angular/material/select';
import { NgxMatMomentModule } from '@angular-material-components/moment-adapter';
import {
MAT_MOMENT_DATE_FORMATS,
MomentDateAdapter,
MAT_MOMENT_DATE_ADAPTER_OPTIONS
} from '@angular/material-moment-adapter';
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core';
import { AttendeeModalPageModule } from 'src/app/shared/event/attendee-modal/attendee-modal.module';
import { InputFilterDirective } from 'src/app/services/directives/input-filter.directive';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
NewEventPageRoutingModule,
NgbModule,
MatDatepickerModule,
MatInputModule,
MatNativeDateModule,
//
NgxMatDatetimePickerModule,
NgxMatTimepickerModule,
NgxMatNativeDateModule,
//
NgxMatMomentModule,
// BrowserAnimationsModule,
// MatRadioModule,
MatSelectModule,
//MatRadioModule,
//MatCheckboxModule,
MatButtonModule,
ReactiveFormsModule,
AttendeeModalPageModule
],
declarations: [NewEventPage],
providers: [
{ provide: MAT_DATE_LOCALE, useValue: 'pt' },
],
exports: [NewEventPage]
})
export class NewEventPageModule {}
@@ -0,0 +1,457 @@
<ion-header class="ion-no-border">
<ion-toolbar class="header-toolbar">
<div class="main-header">
<div class="title-content">
<div class="middle">
<ion-label class="title">Novo Evento</ion-label> <br>
<i style="margin-top: -3px; font-size: 15px;" > Campos marcados com * são obrigatórios</i>
</div>
</div>
<ion-progress-bar class="calendar-progress-bar" type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
</div>
</ion-toolbar>
</ion-header>
<ion-content>
<div class="main-content">
<div class="ion-item-container" [class.input-error]="Form?.get('Subject')?.invalid && validateFrom ">
<ion-input autocomplete="on" autocorrect="on" spellcheck="true" placeholder="Assunto*" [(ngModel)]="postEvent.Subject"></ion-input>
</div>
<div *ngIf="Form && validateFrom" >
<div *ngIf="Form.get('Subject').invalid " class="input-errror-message">
<div *ngIf="Form.get('Subject').errors?.required">
</div>
<div *ngIf="Form.get('Subject').errors?.minlength">
O campo deve ter pelo menos 4 caracteres.
</div>
</div>
</div>
<div *ngIf="(sharedCalendar | async) as calendarData" class="container-div" >
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 justify-center align-center material-inputs " [class.input-error]="Form?.get('CalendarName')?.invalid && validateFrom ">
<mat-form-field appearance="none" class="width-100" color="ion-color-secondary" placeholder="Selecione agenda">
<div *ngIf="hasPrCalendar(calendarData) && !hasChangeCalendar " style="margin-bottom: -20px;">PR</div>
<div *ngIf="selectedUserCalendar == SessionStore.user.UserId && !hasChangeCalendar && SessionStore.user.Profile != 'PR' " style="margin-bottom: -20px;">
Minha agenda
</div>
<mat-select [(value)]="selectedUserCalendar" (selectionChange)="changeAgenda();changeSegmentCalendar()">
<mat-option *ngFor="let calendars of calendarData" value="{{calendars.wxUserId}}">
<div *ngIf="calendars.roleId == RoleIdService.PRES">PR </div>
<div *ngIf="calendars.roleId == RoleIdService.MD && calendars.roleId != SessionStore.user.RoleID">AGENDA DO MDGPR</div>
<div *ngIf="calendars.roleId != RoleIdService.MD && calendars.roleId != RoleIdService.PRES && calendars.wxFullName && calendars.wxUserId != SessionStore.user.UserId"> Agenda do {{calendars.wxFullName}} </div>
<div *ngIf="calendars.wxUserId == SessionStore.user.UserId && SessionStore.user.Profile != 'PR'">
Minha agenda
</div>
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div class="container-div">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-location.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 width-100" [class.input-error]="Form?.get('Location')?.invalid && validateFrom " >
<ion-input autocomplete="on" autocorrect="on" spellcheck="true" type="text" placeholder="Localização*" [(ngModel)]="postEvent.Location"></ion-input>
</div>
</div>
</div>
<div class="container-div" >
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 justify-center align-center material-inputs " [class.input-error]="Form?.get('CalendarName')?.invalid && validateFrom ">
<mat-form-field appearance="none" class="width-100" color="ion-color-secondary" placeholder="Selecione agenda">
<mat-select [(value)]="postEvent.CalendarName" >
<mat-option *ngFor="let calendars of CalendarNamesOptions" value="{{calendars}}">
Calendário {{ calendars }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div class="container-div">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-description.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 justify-center align-center material-inputs">
<mat-form-field appearance="none" class="width-100" placeholder="Sample Type" required>
<!-- <input matInput type="text" > -->
<mat-select [(value)]="postEvent.Category" >
<mat-option value="Meeting">
Reunião
</mat-option>
<mat-option value="Travel">
Viagem
</mat-option>
<mat-option value="Conference">
Conferência
</mat-option>
<mat-option value="Encontro">
Encontro
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div class="container-div">
<div>
<ion-item>
<ion-label>Todo dia</ion-label>
<ion-checkbox [(ngModel)]="allDayCheck" (ionChange)="onCheckboxChange($event)"></ion-checkbox>
</ion-item>
</div>
</div>
<div class="container-div">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-reapet.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 justify-center align-center material-inputs">
<mat-form-field appearance="none" class="width-100" placeholder="Sample Type" required>
<!-- <input matInput type="text" > -->
<mat-select [(value)]="postEvent.EventRecurrence.frequency" >
<mat-option value="never">
Nunca
</mat-option>
<mat-option value="daily">
Diário
</mat-option>
<mat-option value="weekly">
Semanalmente
</mat-option>
<mat-option value="monthly">
Mensal
</mat-option>
<mat-option value="yearly">
Anual
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="postEvent.EventRecurrence.frequency != 'never'" class="container-div">
<div class="ion-item-class-2 d-flex" >
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-reapet.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 justify-center align-center material-inputs materia-top" >
<mat-form-field appearance="none" class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="picker1"
placeholder="Data Fim de Recorrência*"
[(ngModel)]="postEvent.EventRecurrence.until"
[disabled]="disabled"
>
<mat-datepicker-toggle id="new-inicio" matSuffix [for]="picker1" ></mat-datepicker-toggle>
<ngx-mat-datetime-picker #picker1
[showSpinners]="showSpinners"
[showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute"
[stepSecond]="stepSecond"
[touchUi]="touchUi"
[hideTime]="true"
>
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="allDayCheck" class="container-div">
<div class="ion-item-class-2 d-flex" >
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 justify-center align-center material-inputs materia-top" >
<mat-form-field appearance="none" class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="picker1"
placeholder="Data Inicio*"
[(ngModel)]="postEvent.StartDate"
[disabled]="disabled"
(ngModelChange)="onDateChange($event)"
>
<mat-datepicker-toggle id="new-inicio" matSuffix [for]="picker1" ></mat-datepicker-toggle>
<ngx-mat-datetime-picker #picker1
[showSpinners]="showSpinners"
[showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute"
[stepSecond]="stepSecond"
[touchUi]="touchUi"
[hideTime]="true"
>
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="!allDayCheck" class="container-div">
<div class="ion-item-class-2 d-flex" >
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<div class="ion-input-class flex-grow-1 justify-center align-center material-inputs materia-top" >
<mat-form-field appearance="none" class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="picker1"
placeholder="Data Inicio*"
[(ngModel)]="postEvent.StartDate"
[disabled]="disabled"
(ngModelChange)="onDateChange($event)"
>
<mat-datepicker-toggle id="new-inicio" matSuffix [for]="picker1" ></mat-datepicker-toggle>
<ngx-mat-datetime-picker #picker1
[showSpinners]="showSpinners"
[showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute"
[stepSecond]="stepSecond"
[touchUi]="touchUi"
[hideTime]="false"
>
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="allDayCheck" class="container-div">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<!--
[className]="Form?.get('Subject')?.invalid ? 'input-error ion-input-class flex-grow-1' : 'ion-input-class ion-input-class flex-grow-1' "
-->
<div (click)="openFim()" class="ion-input-class flex-grow-1 justify-center align-center materia-top" [class.input-error]="Form?.get('Date')?.invalid && validateFrom ">
<mat-form-field appearance="none" class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="fim"
placeholder="Data de fim*"
[(ngModel)]="postEvent.EndDate"
[disabled]="disabled"
[min]="postEvent.StartDate"
>
<mat-datepicker-toggle id="new-fim" matSuffix [for]="fim" ></mat-datepicker-toggle>
<ngx-mat-datetime-picker #fim
[showSpinners]="showSpinners"
[showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute"
[stepSecond]="stepSecond"
[hideTime]="true"
>
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="!allDayCheck" class="container-div">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
</div>
<!--
[className]="Form?.get('Subject')?.invalid ? 'input-error ion-input-class flex-grow-1' : 'ion-input-class ion-input-class flex-grow-1' "
-->
<div (click)="openFim()" class="ion-input-class flex-grow-1 justify-center align-center materia-top" [class.input-error]="Form?.get('Date')?.invalid && validateFrom ">
<mat-form-field appearance="none" class="date-hour-picker">
<input matInput [ngxMatDatetimePicker]="fim"
placeholder="Data de fim*"
[(ngModel)]="postEvent.EndDate"
[disabled]="disabled"
[min]="postEvent.StartDate"
>
<mat-datepicker-toggle id="new-fim" matSuffix [for]="fim" ></mat-datepicker-toggle>
<ngx-mat-datetime-picker #fim
[showSpinners]="showSpinners"
[showSeconds]="showSeconds"
[stepHour]="stepHour" [stepMinute]="stepMinute"
[stepSecond]="stepSecond"
[hideTime]="false"
>
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
</div>
</div>
<div class="container-div width-100">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-person.svg"></ion-icon>
</div>
<div class="ion-input-class-no-height flex-grow-1 cursor-pointer" (click)="addParticipants()" [class.input-error]="Form?.get('participantes')?.invalid && validateFrom">
<div class="list-people">
<ion-item lines="none">
<ion-list>
<ion-label *ngIf="taskParticipants.length ==0" class="list-people-title">Adicionar Intervenientes*</ion-label>
<ion-label *ngFor="let participant of taskParticipants">{{participant.Name}}</ion-label>
</ion-list>
</ion-item>
</div>
<div class="add-people cursor-pointer" >
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="start" src="assets/images/icons-arrow-forward.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="start" src="assets/images/theme/gov/icons-arrow-forward.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="start" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-arrow-forward.svg"></ion-icon>
</div>
</div>
</div>
</div>
<div class="container-div">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-people-cc.svg"></ion-icon>
</div>
<div class="ion-input-class-no-height flex-grow-1 cursor-pointer" [class.input-error]="Form?.get('participantes')?.invalid && validateFrom" (click)="addParticipantsCc()">
<div class="list-people">
<ion-item lines="none">
<ion-list>
<ion-label *ngIf="taskParticipantsCc.length ==0" class="list-people-title">Com conhecimento</ion-label>
<ion-label *ngFor="let participant of taskParticipantsCc">{{participant.Name}}</ion-label>
</ion-list>
</ion-item>
</div>
<div class="add-people cursor-pointer" >
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="start" src="assets/images/icons-arrow-forward.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="start" src="assets/images/theme/gov/icons-arrow-forward.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="start" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-arrow-forward.svg"></ion-icon>
</div>
</div>
</div>
</div>
<div class="container-div">
<div class="ion-item-class-2 d-flex">
<div class="ion-icon-class">
<ion-icon slot="start" src="assets/images/icons-description.svg"></ion-icon>
</div>
<div class="ion-input-class-no-height flex-grow-1">
<ion-textarea class="heigh-200" autocomplete="on" autocorrect="on" spellcheck="true" [(ngModel)]="postEvent.Body.Text" placeholder="Detalhes" autoGrow="true" ></ion-textarea>
</div>
</div>
</div>
<div class="ion-item-container-no-border cursor-pointer" (click)="getDoc()">
<ion-label>
<div class="attach-icon">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/images/icons-attach-doc.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/images/theme/gov/icons-attach-doc.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " src="assets/images/theme/{{ThemeService.currentTheme}}/icons-attach-doc.svg"></ion-icon>
</div>
<div class="attach-document">
<ion-label>Adicionar documentos</ion-label>
</div>
</ion-label>
</div>
<div class="list " *ngFor="let document of documents; let i = index" >
<ion-list>
<ion-item>
<ion-label>
<p class="d-flex ion-justify-content-between">
<span class="attach-title-item">{{document.subject}}</span>
<span class="app-name" *ngIf="document.applicationId == 8 || document.ApplicationId == 8"> Correspondência </span>
<span class="app-name" *ngIf="document.applicationId == 386 || document.ApplicationId == 386"> Acções Presidenciais </span>
<span class="app-name" *ngIf="document.applicationId == 361 || document.ApplicationId == 361 "> Arquivo Despacho Electrónico </span>
<span class="close-button text-black cursor-pointer" (click)="removeAttachment(i)" >
<ion-icon class="font-20" src="assets/images/icons-delete-25.svg"></ion-icon>
</span>
</p>
<p><span class="span-left">{{(document.EntidadeOrganicaNome || document.Sender)}}</span><span class="span-right"> {{(document.dateEntry) | date: 'dd-MM-yyyy HH:mm'}} </span></p>
</ion-label>
</ion-item>
</ion-list>
</div>
</div>
<!-- <div *ngIf="mostrarModal">
<app-attendee-modal [loggedAttendSon]="loggedAttendDad"></app-attendee-modal>
</div> -->
</ion-content>
<ion-footer class="ion-no-border">
<ion-toolbar class="footer-toolbar">
<ion-buttons slot="start">
<button class="btn-ok" fill="clear" color="#fff" (click)="save_v2()">
<ion-label>Gravar</ion-label>
</button>
</ion-buttons>
<ion-title></ion-title>
<ion-buttons slot="end">
<button class="btn-cancel" fill="clear" color="#061b52" (click)="close()">
<ion-label>Cancelar</ion-label>
</button>
</ion-buttons>
<!-- <app-new-event
[loggedAttend]="loggedAttend"
></app-new-event> -->
</ion-toolbar>
</ion-footer>
@@ -0,0 +1,222 @@
@import '~src/function.scss';
ion-content{
--background:transparent;
}
.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);
.title-content{
margin: 0px auto;
overflow: auto;
padding: 0 !important;
background: #fff;
.middle{
padding: 0!important;
float: left;
width: 300px;
margin: 2.5px 0 0 5px;
}
}
.title{
font-size: rem(25);
}
}
.main-content{
width: 100%; /* 400px */
height: 100%;
font-family: Roboto;
margin: 0 auto;
background-color: #fff;
overflow:auto;
padding: 15px 20px 0 20px;
.ion-item-container{
margin: rem(15) auto;
border: 1px solid #ebebeb;
border-radius: 5px;
padding-left: 10px;
}
.ion-item-container-no-border{
width: 100%;
margin: 0px auto;
padding: 0 !important;
overflow: auto;
}
.container-div{
margin-bottom: 15px;
}
.ion-item-class-2{
margin: 0px auto;
}
.ion-icon-class{
width: rem(45);
height: rem(45);
float: left;
padding: 10px;
font-size: rem(25);
}
ion-select{
padding-left: 5px;
margin-left: 0;
}
.ion-input-class{
height: rem(45);
border: 1px solid #ebebeb;
border-radius: 5px;
padding-left: 5px;
padding-right: 10px;
float: left;
}
.ion-input-class-no-height{
border: 1px solid #ebebeb;
border-radius: 5px;
overflow: auto;
}
.list-people{
width: 256px;
float: left;
}
.add-people{
width: rem(45);
float: right;
overflow: auto;
font-size: rem(25);
height: rem(45);
display: flex;
}
.list-people-title{
/* font-size: rem(13); */
color: #a3a3a3;
}
.attach-document{
font-size: rem(15);
color: var(--title-text-color);
margin: 5px 5px 5px 10px;
padding: 5px;
float: left;
}
.attach-icon{
width: 37px;
font-size: rem(35);
float: left;
}
.attach-title-item{
width: 100%;
font-size: rem(15);
color:#0d89d1;
}
/* SPAN */
.span-left{
float: left;
font-size: rem(15);
}
.span-right{
text-align: right;
float: right;
font-size: rem(13);
}
.container-footer{
margin:0 auto;
overflow: auto;
}
.button-cancel {
width: rem(170);
height: rem(44);
border-radius: 22.5px;
--background: #e0e9ee;
--color: #061b52;
margin:10px;
}
.button-save {
width: rem(170);
height: rem(44);
border-radius: 22.5px;
--background: #42b9fe;
--color:#ffffff;
margin:10px;
}
.text-input{
width: 100%;
border: 1px solid #ebebeb;
margin: 0px 15px 15px 0px;
padding: 0 !important;
border-radius: 5px;
}
/* Error Messages */
.error{
color:red;
font-size: rem(12);
font-weight: bold;
padding-bottom: 20px;
}
.span-color{
color:red;
}
}
.container-div {
ion-textarea {
// height: 81px;
}
}
.app-name{
background: var(--title-text-color);
border-radius: 18px;
text-align: center;
display: flex;
align-items: center;
padding: 0px 5px;
color: white;
font-size: rem(12);
font-weight: 500;
height: 19px;
-webkit-border-radius: 18px;
-moz-border-radius: 18px;
-ms-border-radius: 18px;
-o-border-radius: 18px;
}
.close-button {
display: none;
height: 20px;
}
.list:hover {
.app-name {
display: none;
}
.close-button {
display: block !important;
}
}
.materia-top {
padding-top: 7px;
}
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { NewEventPage } from './new-event.page';
describe('NewEventPage', () => {
let component: NewEventPage;
let fixture: ComponentFixture<NewEventPage>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ NewEventPage ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(NewEventPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,703 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { EventBody } from 'src/app/models/eventbody.model';
import { EventPerson } from 'src/app/models/eventperson.model';
import { EventsService } from 'src/app/services/events.service';
import { Event } from 'src/app/models/event.model';
import { ModalController } from '@ionic/angular';
import { removeDuplicate } from 'src/plugin/removeDuplicate.js'
import { SearchPage } from 'src/app/pages/search/search.page';
import { SearchList_v2 } from "src/app/models/search-document";
import { ToastService } from 'src/app/services/toast.service';
import { LoginUserRespose } from 'src/app/models/user.model';
import { DateAdapter } from '@angular/material/core';
import * as _moment from 'moment';
import * as _rollupMoment from 'moment';
import { FormControl } from '@angular/forms';
import { NgxMatDateFormats } from '@angular-material-components/datetime-picker';
import { ThemePalette } from '@angular/material/core';
import { ViewChild } from '@angular/core';
import { FormGroup, Validators } from '@angular/forms';
import { NGX_MAT_DATE_FORMATS } from '@angular-material-components/datetime-picker';
import { ThemeService } from 'src/app/services/theme.service'
import { SessionStore } from 'src/app/store/session.service';
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
import { environment } from 'src/environments/environment';
import { EventToAprove } from 'src/app/models/eventToAprove.model';
import { Observable } from 'rxjs';
import { TaskService } from 'src/app/services/task.service'
import { ChangeProfileService } from 'src/app/services/change-profile.service';
import { AgendaDataRepositoryService } from 'src/app/module/agenda/data/repository/agenda-data-repository.service';
import { RoleIdService } from 'src/app/services/role-id.service'
import { TableSharedCalendar } from 'src/app/module/agenda/data/data-source/agenda-local-data-source.service';
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
import { UserList } from 'src/app/models/entiry/agenda/contact';
import { AgendaService } from 'src/app/module/agenda/domain/agenda.service'
import { RoleId } from 'src/app/core/agenda/use-case/event-set-default-participants.service';
const CUSTOM_DATE_FORMATS: NgxMatDateFormats = {
parse: {
dateInput: "YYYY-MMMM-DD HH:mm"
},
display: {
dateInput: "DD MMM YYYY H:mm",
monthYearLabel: "MMM YYYY",
dateA11yLabel: "LL",
monthYearA11yLabel: "MMMM YYYY"
}
}
@Component({
selector: 'app-new-event',
templateUrl: './new-event.page.html',
styleUrls: ['./new-event.page.scss'],
providers: [
{ provide: NGX_MAT_DATE_FORMATS, useValue: CUSTOM_DATE_FORMATS },
]
})
export class NewEventPage implements OnInit {
eventBody: EventBody;
segment: string = "true";
public date: any;
public disabled = false;
public showSpinners = true;
public showSeconds = false;
public touchUi = false;
public enableMeridian = false;
public stepHour = 1;
public stepMinute = 15;
public stepSecond = 15;
currentDate = this.roundTimeQuarterHour();
public color: ThemePalette = 'primary';
recurringTypes = []
selectedRecurringType: any;
loggedAttendDad: boolean = true;
mostrarModal = false;
eventRecurence = 'never'
@Input() attendees: []
@Input() profile: string;
@Input() roomId: string;
@Input() selectedSegment: string;
@Input() selectedDate: Date;
@Input() CalendarDate: Date;
@Input() taskParticipants: UserList = [];
@Input() taskParticipantsCc: any = [];
@Output() setIntervenient = new EventEmitter<any>();
@Output() setIntervenientCC = new EventEmitter<any>();
postEvent: Event;
postEventToAprove: EventToAprove;
@Output() onAddEvent = new EventEmitter<any>();
@Output() openAttendeesComponent = new EventEmitter<any>();
@Output() clearContact = new EventEmitter<any>();
@Output() GoBackEditOrAdd = new EventEmitter<any>();
@Output() cloneAllmobileComponent = new EventEmitter<any>();
@Output() backToChat = new EventEmitter<any>();
documents: SearchList_v2[] = [];
loggeduser: LoginUserRespose;
@ViewChild('picker') picker: any;
@ViewChild('fim') fim: any;
@ViewChild('inicio') inicio: any;
@ViewChild('occurrence') occurrence: any;
@ViewChild('picker1') picker1: any;
Form: FormGroup;
validateFrom = false;
autoStartTime;
autoEndTime;
public options = [
{ value: true, label: 'True' },
{ value: false, label: 'False' }
];
public listColors = ['primary', 'accent', 'warn'];
public stepHours = [1, 2, 3, 4, 5];
public stepMinutes = [1, 5, 10, 15, 20, 25];
public stepSeconds = [1, 5, 10, 15, 20, 25];
showLoader = false
CalendarName;
CalendarNameShow = true
CalendarNamesOptions = ['Oficial', 'Pessoal']
environment = environment
eventPersons: UserList;
contacts: UserList = [];
allDayCheck: boolean = false;
sharedCalendar: Observable<TableSharedCalendar[]>
selectedUserCalendar:any;
SessionStore = SessionStore
hasChangeCalendar = false
constructor(
private modalController: ModalController,
public eventService: EventsService,
private toastService: ToastService,
private dateAdapter: DateAdapter<any>,
public ThemeService: ThemeService,
private hhtpErrorHandle: HttpErrorHandle,
public TaskService: TaskService,
private changeProfileService: ChangeProfileService,
private agendaDataRepository: AgendaDataRepositoryService,
public RoleIdService: RoleIdService,
private ContactRepositoryService: ContactRepositoryService,
private AgendaService: AgendaService
) {
this.dateAdapter.setLocale('pt');
this.loggeduser = SessionStore.user;
this.postEvent = new Event();
this.sharedCalendar = this.agendaDataRepository.getShareCalendarItemsLiveWithOrder()
}
hasPrCalendar(data: TableSharedCalendar[]) {
for(const e of data) {
if(e.roleId == this.RoleIdService.PRES) {
return true
}
}
return false
}
async setCalendarByDefault(force) {
if (!this.selectedUserCalendar || force) {
const data = await this.agendaDataRepository.geCalendars()
const prObject = data.find(e => e?.roleId == RoleId.PRES)
if(prObject) {
this.selectedUserCalendar = prObject.wxUserId
} else {
this.selectedUserCalendar = SessionStore.user.UserId
}
this.changeAgenda()
}
}
ngOnInit() {
this.changeProfileService.registerCallback(() => {
this.initializeData()
})
this.getRecurrenceTypes();
if (!this.restoreTemporaryData()) {
// clear
this.setCalendarByDefault(true)
this.eventBody = { BodyType: "1", Text: "" };
this.postEvent.Body = this.eventBody;
this.initializeData()
if (this.postEvent.Attendees != null) {
this.postEvent.Attendees.forEach(e => {
if (e.IsRequired) {
this.taskParticipants.push(e as any);
} else {
this.taskParticipantsCc.push(e);
}
})
}
console.log('Attendes', this.taskParticipants)
this.taskParticipants = removeDuplicate(this.taskParticipants);
this.taskParticipantsCc = removeDuplicate(this.taskParticipantsCc);
this.setIntervenient.emit(this.taskParticipants);
this.setIntervenientCC.emit(this.taskParticipantsCc);
this.setDefaultTime();
this.fetchContacts("")
}
this.injectValidation();
this.changeAgenda()
}
initializeData() {
this.postEvent = {
EventId: '',
Subject: '',
Body: this.eventBody,
Location: '',
CalendarId: '',
CalendarName: 'Oficial',
StartDate: this.autoStartTime,
EndDate: this.autoEndTime,
EventType: 'Reunião',
Attendees: this.attendees || null,
IsMeeting: false,
IsRecurring: false,
AppointmentState: 0,
TimeZone: '',
Organizer: '',
Category: 'Meeting',
HasAttachments: false,
EventRecurrence: {
frequency: this.eventRecurence, until: "",
Type: ''
},
}
}
setDefaultTime() {
this.postEvent.StartDate = this.roundTimeQuarterHour(this.CalendarDate);
this.postEvent.EndDate = this.roundTimeQuarterHourPlus15(this.postEvent.StartDate);
}
roundTimeQuarterHour(timeToReturn = new Date()): Date {
let date = new Date(timeToReturn) || new Date();
let newdate = new Date();
const minutes = newdate.getMinutes();
date.setHours(newdate.getHours())
date.setSeconds(0);
if (minutes % 15 != 0) {
if (minutes > 45) {
date.setMinutes(60)
} else if (minutes > 30) {
date.setMinutes(45)
} else if (minutes > 15) {
date.setMinutes(30)
} else if (minutes > 0) {
date.setMinutes(15)
}
}
return date
}
roundTimeQuarterHourPlus15(date: Date) {
const _date = new Date(date);
const minutes = _date.getMinutes();
_date.setMinutes(minutes + 15)
return _date
}
roundTimeQuarterHour1(timeToReturn) {
let date: any = new Date(timeToReturn) || new Date();
const minutes = date.getMinutes();
date.setSeconds(0);
if ((minutes % 15) != 0) {
let a = (Math.floor(minutes / 15) + 1) * 15
date.setMinutes(a)
}
return date
}
setStartDate() {
// this.postEvent.StartDate = this.roundTimeQuarterHour();
}
setEndDate() {
// this.postEvent.EndDate = this.postEvent.StartDate;
}
runValidation() {
this.validateFrom = true;
if (new Date(this.postEvent.StartDate).getTime() > new Date(this.postEvent.EndDate).getTime()) {
this.toastService._badRequest("A data de fim não pode ser inferior a data de início do evento")
}
}
injectValidation() {
/* if (typeof (this.postEvent.EventRecurrence.Type) == 'number') {
const str: any = this.postEvent.EventRecurrence.Type.toString()
this.postEvent.EventRecurrence.Type = str
} */
this.Form = new FormGroup({
Subject: new FormControl(this.postEvent.Subject, [
Validators.required,
// Validators.minLength(4)
]),
Location: new FormControl(this.postEvent.Location, [
Validators.required,
]),
CalendarName: new FormControl(this.postEvent.CalendarName),
Categories: new FormControl(this.postEvent.Category, [
Validators.required
]),
dateStart: new FormControl(this.postEvent.StartDate, [
Validators.required
]),
dateEnd: new FormControl(this.postEvent.EndDate, [
Validators.required
]),
/* dateOccurrence: new FormControl(this.postEvent.EventRecurrence.Type.toString() == '-1' ? ['ok'] : this.postEvent.EventRecurrence.LastOccurrence && new Date(this.postEvent.EventRecurrence.LastOccurrence).getTime() > new Date(this.postEvent.EndDate).getTime() ? 'ok' : null, [
Validators.required
]), */
participantes: new FormControl(this.taskParticipants, [
Validators.required
]),
Date: new FormControl(new Date(this.postEvent.StartDate).getTime() < new Date(this.postEvent.EndDate).getTime() ? 'ok' : null, [
Validators.required
]),
})
}
openFim() {
let input: any = document.querySelector('#new-fim')
if (input) {
input.click()
}
}
changeSegmentCalendar() {
this.hasChangeCalendar = true
}
async changeAgenda() {
this.CalendarNameShow = false
const result = await this.agendaDataRepository.geCalendars()
const selectedCalendar = result.find(e => e.wxUserId == this.selectedUserCalendar)
if(selectedCalendar) {
if(selectedCalendar.shareType == 1) {
this.CalendarNamesOptions = ['Oficial']
} else if(selectedCalendar.shareType == 2) {
this.CalendarNamesOptions = ['Pessoal']
} else if (selectedCalendar.shareType == 3) {
this.CalendarNamesOptions = ['Oficial', 'Pessoal']
}
}
}
// openLastOccurrence() {
// let input: any = document.querySelector('#last-occurrence')
// if (input) {
// input.click()
// }
// }
async getDoc() {
const modal = await this.modalController.create({
component: SearchPage,
cssClass: 'modal-width-100-width-background modal',
componentProps: {
type: 'AccoesPresidenciais & ArquivoDespachoElect',
eventAgenda: true,
showSearchInput: true,
select: true
}
});
modal.onDidDismiss().then((res) => {
if (res) {
const data = res.data;
/* let newDocObject: SearchList_v2 = {
docId: parseInt(data.selected.Id),
sourceName: data.selected.Assunto,
description: "",
applicationId: data.selected.ApplicationType
} */
console.log('get doc', data)
this.documents.push(data.selected);
console.log('pushed')
}
});
await modal.present();
}
close() {
this.deleteTemporaryData();
this.clearContact.emit();
this.setIntervenient.emit([]);
this.setIntervenientCC.emit([]);
// chat exit
this.backToChat.emit({ roomId: this.roomId })
// agenda exit
this.cloneAllmobileComponent.emit({})
}
getRecurrenceTypes() {
this.eventService.getRecurrenceTypes().subscribe(res => {
this.recurringTypes = res;
});
}
calculetedLastOccurrence(type: number) {
var valor;
var opcao: boolean;
if (type == 0) {
valor = 7;
opcao = true;
} else if (type == 1) {
valor = 30;
opcao = true;
} else if (type == 2) {
valor = 1;
opcao = false;
} else if (type == 3) {
valor = 5;
opcao = false;
}
this.defineLastOccurrence(valor, opcao);
}
defineLastOccurrence(valor: number, opcao: boolean) {
var time = new Date(this.postEvent.EndDate);
if (opcao == true) {
time.setDate(time.getDate() + valor);
this.postEvent.EventRecurrence.LastOccurrence = time;
} else {
time = new Date(
time.getFullYear() + valor,
time.getMonth(),
time.getDate(),
time.getHours(),
time.getMinutes()
);
this.postEvent.EventRecurrence.LastOccurrence = time;
}
}
@XTracerAsync({name:'desktop/create-event', bugPrint: true})
async save_v2(tracing?: TracingType) {
this.injectValidation()
this.runValidation()
if (this.Form.invalid) {
if (new Date(this.postEvent.StartDate).getTime() < new Date(this.postEvent.EndDate).getTime()) {
this.toastService._badRequest("Data de inicio menor que a data de fim")
}
return false
}
let loader = this.toastService.loading();
this.postEvent.Attendees = this.taskParticipants.concat(this.taskParticipantsCc) as any
this.postEvent.IsAllDayEvent = this.allDayCheck;
const calendar = await this.agendaDataRepository.getCalendarByUserId(this.selectedUserCalendar)
if(calendar.isOk()) {
const value = await this.agendaDataRepository.createEvent(this.postEvent, this.documents, calendar.value, tracing)
if(value.isOk()) {
console.log(value)
this.afterSave();
this.hhtpErrorHandle.httpsSucessMessagge('new event')
loader.remove();
tracing.setAttribute('outcome', 'success')
} else {
console.log('create event error: ', value.error)
tracing.setAttribute('outcome', 'failed')
loader.remove();
this.hhtpErrorHandle.httpStatusHandle(value.error.status)
}
} else {}
}
afterSave() {
this.deleteTemporaryData();
this.onAddEvent.emit(Object.assign(this.postEvent, {
roomId: this.roomId
}));
this.GoBackEditOrAdd.emit();
this.setIntervenient.emit([]);
this.setIntervenientCC.emit([]);
}
removeAttachment(index: number) {
this.documents = this.documents.filter((e, i) => index != i);
}
async addParticipants() {
this.saveTemporaryData();
this.openAttendeesComponent.emit({
type: "intervenient"
});
this.clearContact.emit();
this.mostrarModal = true;
}
async addParticipantsCc() {
this.saveTemporaryData();
this.openAttendeesComponent.emit({
type: "CC"
});
this.clearContact.emit();
}
saveTemporaryData() {
window['temp.path:/home/agenda/new-event.component.ts'] = {
postEvent: this.postEvent,
eventBody: this.eventBody,
allDayCheck: this.allDayCheck,
segment: this.segment,
CalendarName: this.CalendarName,
documents: this.documents,
selectedUserCalendar: this.selectedUserCalendar,
hasChangeCalendar: this.hasChangeCalendar
}
}
/**
*
* @description o pipeline já esta a funcionar tuda vez que nos fazer push na branch master e test o pipeline executa os teste, mas agora os teste temos que melhora para testar a app em tudos os pontos
* o pipeline já está a funcionar toda vez que nos fazer um push na branch master ou teste o pipeline executa os testes, mas agora os testes temos que melhorar para testar a app em todos os pontos
*/
restoreTemporaryData(): boolean {
const restoredData = window['temp.path:/home/agenda/new-event.component.ts']
if (JSON.stringify(restoredData) != "{}" && undefined != restoredData) {
this.postEvent = restoredData.postEvent
this.allDayCheck = restoredData.allDayCheck
this.eventBody = restoredData.eventBody
this.segment = restoredData.segment
this.CalendarName = restoredData.CalendarName
this.documents = restoredData.documents
this.selectedUserCalendar = restoredData.selectedUserCalendar
this.hasChangeCalendar = restoredData.hasChangeCalendar
// restore dater for date and hours picker
return true;
} else {
return false
}
}
deleteTemporaryData() {
window['temp.path:/home/agenda/new-event.component.ts'] = {}
}
async fetchContacts(filter: string) {
console.log(this.loggeduser.Profile)
//if(this.taskParticipants.length ==0) {
const result = await this.AgendaService.setDefaultParticipants()
if(result.isOk()) {
if(result.value) {
this.taskParticipants.push(result.value[0]);
this.setIntervenient.emit(result.value);
console.log('Attendes Email', result.value)
}
}
//}
}
onCheckboxChange(event: any) {
if (this.allDayCheck) {
this.postEvent.IsAllDayEvent = this.allDayCheck;
this.postEvent.StartDate = this.setAlldayTime(this.postEvent.StartDate)
this.postEvent.EndDate = this.setAlldayTimeEndDate(this.postEvent.EndDate)
console.log('Recurso ativado!!');
} else {
this.postEvent.IsAllDayEvent = this.allDayCheck;
this.postEvent.EndDate = this.setAlldayTimeEndDateNotAlday(this.postEvent.EndDate)
console.log('Recurso desativado');
}
}
setAlldayTime(timeToReturn) {
let date: any = new Date(timeToReturn) || new Date();
let newdate = new Date();
date.setHours(0)
date.setMinutes(0)
date.setSeconds(0);
return date
}
setAlldayTimeEndDate(timeToReturn) {
let date: any = new Date(timeToReturn) || new Date();
let newdate = new Date();
date.setHours(23)
date.setMinutes(59)
date.setSeconds(0);
return date
}
setAlldayTimeEndDateNotAlday(timeToReturn) {
let date: any = new Date(timeToReturn) || new Date();
let newdate = new Date();
date.setHours(23)
date.setMinutes(0)
date.setSeconds(0);
return date
}
onDateChange(e) {
const cloneDateStartDate = new Date(this.postEvent.StartDate);
const cloneDateEndDate = new Date(this.postEvent.EndDate);
if(cloneDateStartDate.getTime() >= cloneDateEndDate.getTime()) {
cloneDateStartDate.setHours(cloneDateStartDate.getHours() + 1);
this.postEvent.EndDate = cloneDateStartDate
}
}
}
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ViewEventPage } from './view-event.page';
const routes: Routes = [
{
path: '',
component: ViewEventPage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ViewEventPageRoutingModule {}
@@ -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 { ViewEventPageRoutingModule } from './view-event-routing.module';
import { ViewEventPage } from './view-event.page';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
ViewEventPageRoutingModule
],
declarations: [ViewEventPage],
exports: [ViewEventPage]
})
export class ViewEventPageModule {}
@@ -0,0 +1,147 @@
<ion-header class="ion-no-border">
<ion-toolbar class="header-toolbar" >
<div class="main-header px-20" style="overflow: unset !important;">
<div class="title-content d-flex">
<div class="left">
<button class="btn-no-color" (click)="close()">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end"
src='assets/images/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>
<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" (click)="openOptions()">
<p class="title">{{loadedEvent.Subject}}</p>
</div>
<div class="div-icon d-flex align-base">
<button class="btn-no-color" (click)="editEvent()" *ngIf="p.userPermission([p.permissionList.Agenda.creatEvent])">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="edit" slot="end"
src="assets/images/icons-edit.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="edit" slot="end"
src="assets/images/theme/gov/icons-edit.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="edit" slot="end"
src="assets/images/theme/{{ThemeService.currentTheme}}/icons-edit.svg"></ion-icon>
</button>
<button class="btn-no-color" (click)="deleteYesOrNo()">
<ion-icon class="delete" name="trash-sharp"></ion-icon>
</button>
<!-- <div class="div-icon" (click)="openOptions()">
<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>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " src="assets/images/theme/{{ThemeService.currentTheme}}/icons-menu.svg"></ion-icon>
</div>
<div *ngIf="loadedEvent.Subject">
<div (click)="editEvent()">Editar</div>
<div (click)="deleteYesOrNo()">Apagar</div>
<div id="desktop-create-chat-from-event" (click)="openNewGroupPage()">Criar Conversa</div>
</div> -->
</div>
</div>
</div>
</ion-toolbar>
</ion-header>
<ion-content>
<div class="main-content">
<div class="upper-content">
<div class="content-location">
<span class="date">{{loadedEvent.Location}}</span>
<div *ngIf="loadedEvent.Organizer">
<div *ngIf="loadedEvent.owner.wxUserId != sesseionStora.user.UserId || sesseionStora.user.Profile =='PR'">
<span class="label" *ngIf="loadedEvent.CalendarName == 'Oficial' "
style="background-color: #99e47b;">{{loadedEvent.CalendarName}}</span>
<span class="label" *ngIf="loadedEvent.CalendarName == 'Pessoal' "
style="background-color: #958bfc;">{{loadedEvent.CalendarName}}</span>
</div>
<div *ngIf="loadedEvent.owner.wxUserId == sesseionStora.user.UserId && sesseionStora.user.Profile !='PR'">
<span class="label" *ngIf="loadedEvent.CalendarName == 'Oficial' "
style="background-color: #ffb703;">{{loadedEvent.CalendarName}}</span>
<span class="label" *ngIf="loadedEvent.CalendarName == 'Pessoal' "
style="background-color: #f05d5e;">{{loadedEvent.CalendarName}}</span>
</div>
</div>
</div>
<div class="content-details">
<ion-label>
<p>{{customDate}}</p>
<p>{{TimeZoneString}}</p>
<p *ngIf="toDateString(loadedEvent.StartDate) == toDateString(loadedEvent.EndDate)">das
{{loadedEvent.StartDate | date: 'HH:mm'}} às {{loadedEvent.EndDate | date: 'HH:mm'}}</p>
<p *ngIf="toDateString(loadedEvent.StartDate) != toDateString(loadedEvent.EndDate)">{{loadedEvent.StartDate |
date: 'd/M/yy' }} - {{ loadedEvent.EndDate | date: 'dd/M/yy'}} </p>
<p *ngIf="loadedEvent.EventRecurrence">
<span *ngIf="stringToNumber(loadedEvent.EventRecurrence.frequency) == 1">Diário</span>
<span *ngIf="stringToNumber(loadedEvent.EventRecurrence.frequency) == 2">Semanal</span>
<span *ngIf="stringToNumber(loadedEvent.EventRecurrence.frequency) == 3">Mensal</span>
<span *ngIf="stringToNumber(loadedEvent.EventRecurrence.frequency) == 4">Anual</span>
<span *ngIf="!loadedEvent.IsRecurring">(Não se repete)</span>
</p>
<!-- <p >
{{ daysToEnd }} dias para terminar o evento
</p> -->
</ion-label>
</div>
</div>
<div class="line"></div>
<div class="middle-content">
<div *ngIf="loadedEvent.Attendees">
<h5 class="font-17-rem">Intervenientes({{ loadedEvent.Attendees.length }})</h5>
<ion-item class="ion-no-margin ion-no-padding">
<ion-label>
<div *ngFor="let attendee of loadedEvent.Attendees">
<p>{{attendee.Name}}</p>
</div>
</ion-label>
</ion-item>
</div>
<div *ngIf="loadedEvent.Body.Text">
<h5 class="font-17-rem">Detalhes</h5>
<ion-item lines="none" class="ion-no-margin ion-no-padding">
<pre class="text">{{ loadedEvent.Body.Text }} </pre>
</ion-item>
<div class="line"></div>
</div>
</div>
<div *ngIf="loadedEvent.Attachments" class="bottom-content width-100">
<h5 class="font-17-rem">Documentos Anexados({{ loadedEvent.Attachments.length }})</h5>
<ion-list class="width-100">
<li *ngFor="let attach of loadedEvent.Attachments; let i = index" class="width-100" lines="none"
class="ion-no-margin ion-no-padding pa-0">
<ion-label class="width-100 d-flex align-center">
<p class="flex-grow-1 cursor-pointer" (click)="docIndex(i);LoadDocumentDetails()">
<span class="attach-title-item d-block">{{attach.subject || attach.sourceName || attach.SourceName || 'Sem título'}}</span>
<span class="span-left d-block">{{attach.Stakeholders}}</span>
</p>
<div class="d-flex pr-10 cursor-pointer" (click)="docIndex(i);LoadDocumentDetails()">
<span class="span-right">{{ attach.dateEntry | date: 'dd-MM-yyyy HH:mm' }}</span>
</div>
<!-- <div (click)="docIndex(i);LoadDocumentDetails()" class="doc-options">
<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>
</div> -->
</ion-label>
</li>
</ion-list>
</div>
</div>
</ion-content>
@@ -0,0 +1,218 @@
@import '~src/function.scss';
ion-content{
--background:transparent;
--padding-top:0px;
--padding-start: 20px;
--padding-end: 20px;
font-size: rem(18);
overflow: auto;
}
.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;
padding: 30px 0px 0px 0px;
color:#000;
transform: translate3d(0, 1px, 0);
overflow: auto;
.title-content{
width: 100% !important;
margin: 0px auto;
padding: 0 !important;
background: #fff;
overflow: auto;
.left{
width: 37px;
float: left;
font-size: rem(35);
}
.middle{
width: calc(100% - 138.5px) !important;
padding: 0 !important;
float: left;
margin: 0 !important;
overflow: auto;
p{
margin: 0 !important;
}
}
.header-icon-right{
width: rem(45);
font-size: rem(45);
float: right;
}
.div-icon{
width: fit-content;
height: fit-content;
display: flex;
align-items: flex-start;
justify-content:flex-start;
float: right;
padding: 1px !important;
top: 0 !important;
margin: 0 0 0 15px !important;
}
.div-icon .edit{
font-size: rem(35);
float: left;
}
.div-icon .delete{
padding: 7px;
font-size: rem(21);
color:#fff;
background: #d30606;
border-radius: 20px;
margin-left: 10px;
}
}
.title{
font-size: rem(25);
}
}
.main-content{
width: 100%; /* 400px */
font-family: Roboto;
margin: 0 auto;
background-color: #fff;
padding: 15px 0px 0 0px;
overflow: auto !important;
.upper-content{
width: calc(100%-50px);
margin-left: 50px;
font-size: rem(18);
.content-location{
width: 100%;
margin: 0 auto !important;
padding: 0 !important;
overflow: auto;
.date{
width: calc(100% - 105px);
float: left;
}
.label{
width: fit-content;
border-radius: 20px;
background: var(--label-bg-color);
float: right !important;
padding: 5px 13.5px 5px 13.5px;
color: black;
font-size: rem(14);
}
}
.location-detail{
font-weight: 700;
font-size: rem(18);
float: left;
margin: 5px 5px 5px 0px;
}
.button-calendar-type ion-button{
height: rem(25);
}
.button-edit-event {
width: 140px;
height: 44px;
border-radius: 22.5px;
--background: #e0e9ee;
--color:#061b52;
}
.content-details p{
font-size: rem(16);
}
}
.line{
width: 100% !important;
margin-top: 15px;
border-top: 1px solid #d8d8d8;
}
.middle-content{
width: 100% !important;
overflow: auto;
.middle-content h3, .middle-content p{
font-size: rem(16);
}
}
.bottom-content{
margin: 0 auto;
.bottom-content h3{
font-size: rem(16);
margin: 0 0 0 10px;
}
.attach-document{
font-size: rem(15);
color: var(--title-text-color);
margin: 5px 5px 5px 10px;
padding: 5px;
float: left;
}
.attach-icon{
width: 37px;
font-size: rem(35);
float: left;
}
.attach-title-item{
width: 100%;
font-size: rem(15);
color:#0d89d1;
/* color:var(--title-text-color); */
}
/* SPAN */
.span-left{
float: left;
font-size: rem(15);
}
.span-right{
text-align: right;
float: right;
font-size: rem(13);
}
}
}
.chat-popover .popover-content {
width: 100% !important;
left: 0 !important;
bottom: 0 !important;
right: 0 !important;
bottom: 0px !important;
}
.doc-options {
cursor: pointer;
display: flex;
justify-content: center;
width: rem(35);
height: 41px;
align-items: center;
}
.text {
text-transform: initial !important
}
@@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { ViewEventPage } from './view-event.page';
describe('ViewEventPage', () => {
let component: ViewEventPage;
let fixture: ComponentFixture<ViewEventPage>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ViewEventPage ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(ViewEventPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,461 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { AlertController, ModalController, PopoverController } from '@ionic/angular';
import { Attachment } from 'src/app/models/attachment.model';
import { EventBody } from 'src/app/models/eventbody.model';
import { EventsService } from 'src/app/services/events.service';
import { Event } from 'src/app/models/event.model';
import { InAppBrowser } from '@ionic-native/in-app-browser/ngx';
import { ProcessesService } from 'src/app/services/processes.service';
import { ToastService } from 'src/app/services/toast.service';
import { EliminateEventPage } from 'src/app/modals/eliminate-event/eliminate-event.page';
import { ExpedientTaskModalPageNavParamsTask } from 'src/app/models/ExpedientTaskModalPage';
import { DocumentSetUpMeetingPage } from 'src/app/modals/document-set-up-meeting/document-set-up-meeting.page';
import { ExpedientTaskModalPage } from 'src/app/pages/gabinete-digital/expediente/expedient-task-modal/expedient-task-modal.page';
import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page';
import { ThemeService } from 'src/app/services/theme.service';
import { SessionStore } from 'src/app/store/session.service';
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service'
import { NavigationExtras, Router } from '@angular/router';
import { DateService } from 'src/app/services/date.service';
import { AgendaDataRepositoryService } from 'src/app/module/agenda/data/repository/agenda-data-repository.service';
import { SearchList_v2 } from 'src/app/models/search-document';
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
import { isHttpError } from 'src/app/services/http.service';
import { PermissionService } from 'src/app/services/permission.service';
import { DeleteEventRecurrencePage, EventDeleteRecurrenceComponentReturn } from 'src/app/modals/delete-event-recurrence/delete-event-recurrence.page';
@Component({
selector: 'app-view-event',
templateUrl: './view-event.page.html',
styleUrls: ['./view-event.page.scss'],
})
export class ViewEventPage implements OnInit {
loadedEvent: Event;
isEventEdited: boolean;
eventBody: EventBody;
loadedAttachments:any;
pageId: string;
showLoader: boolean;
task: ExpedientTaskModalPageNavParamsTask;
minDate: Date;
LoadedDocument:any = null;
customDate:any;
today:any;
months = ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"];
days = ["Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"];
documents: Attachment[] = [];
dicIndex = 0;
@Input() profile:string;
@Input() eventId: string;
@Input() CalendarId: string;
@Output() viewEventDetailDismiss = new EventEmitter<any>();
sesseionStora = SessionStore
TimeZoneString = ''
daysToEnd = 0
constructor(
public eventsService: EventsService,
public alertController: AlertController,
private iab: InAppBrowser,
private processes: ProcessesService,
private modalController: ModalController,
public popoverController: PopoverController,
private toastService: ToastService,
public ThemeService: ThemeService,
private httpErrorHandle: HttpErrorHandle,
private router: Router,
private dateService: DateService,
private agendaDataRepository: AgendaDataRepositoryService,
public p: PermissionService,
) {
this.isEventEdited = false;
this.loadedEvent = new Event();
this.eventBody = { BodyType : "1", Text : ""};
this.loadedEvent.Body = this.eventBody;
}
daysToEndWithJS(startDateStr: any, endDateStr: any) {
// Define the start and end dates
const startDate: any = new Date(startDateStr);
const endDate: any = new Date(endDateStr);
// Calculate the difference in milliseconds between the two dates
const differenceMs = Math.abs(endDate - startDate);
// Convert milliseconds to days
const millisecondsPerDay = 1000 * 60 * 60 * 24;
const differenceDays = Math.ceil(differenceMs / millisecondsPerDay);
console.log(`Number of days between the dates: ${differenceDays}`);
return differenceDays
}
deferenceBetweenDays(start: any, end: any) {
start.setHours(0, 0, 0, 0);
end.setHours(0, 0, 0, 0);
const diffTime = Math.abs(end - start);
return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}
ngOnInit() {
this.loadEvent();
}
doRefresh(ev) {
this.loadEvent();
ev.target.complete();
}
ngOnChanges(changes: any): void {
this.loadedEvent.Attachments = null;
this.loadEvent();
}
toDateString(e) {
return new Date(e).toString()
}
openOptions() {
}
docIndex(index: number) {
this.dicIndex = index;
}
close() {
this.viewEventDetailDismiss.emit({
type: 'close'
})
}
setTimeZone() {
this.TimeZoneString = this.loadedEvent.TimeZone
}
@XTracerAsync({name:'desktop/event-details', bugPrint: true})
async loadEvent(tracing?: TracingType) {
let res = await this.agendaDataRepository.getEventById(this.eventId, tracing)
if(res.isOk()) {
tracing.setAttribute('outcome', 'success')
/* let changeDate = this.dateService.fixDate(res.value as any) as any */
this.loadedEvent = res.value as any;
console.log('this.loadedEvent', this.loadedEvent)
if(new Date().getTime() <= new Date(this.loadedEvent.EndDate).getTime()) {
if(this.deferenceBetweenDays(new Date(), new Date(this.loadedEvent.EndDate))) {
this.daysToEnd = this.daysToEndWithJS(new Date(this.loadedEvent.StartDate), new Date(this.loadedEvent.EndDate))
} else {
this.daysToEnd = 0
}
} else {
this.daysToEnd = 0
}
this.setTimeZone()
} else {
tracing.setAttribute('eventId', this.eventId)
if(!isHttpError(res.error)) {
this.toastService._badRequest('Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico. #133')
console.log(res.error)
} else if (isHttpError(res.error)) {
if(res.error.status == 404) {
this.toastService._badRequest('Este evento já não existe')
} else {
this.httpErrorHandle.httpStatusHandle(res.error)
}
}
tracing.setAttribute('outcome', 'failed')
this.viewEventDetailDismiss.emit({
type: 'close'
})
}
}
async deleteYesOrNo() {
if (this.loadedEvent.IsRecurring) {
const modal = await this.modalController.create({
component: DeleteEventRecurrencePage,
componentProps: {},
cssClass: 'event-recurrence-modal',
});
modal.onDidDismiss().then((res) => {
const data: EventDeleteRecurrenceComponentReturn = res.data
if(data =='DeleteAll') {
this.deleteEvent_v2(true);
} else if (data == 'DeleteOne') {
this.deleteEvent_v2(false);
} else if(data == 'Cancel') {
this.close()
} else {
this.close()
}
});
await modal.present();
} else {
this.alertController.create({
header: 'Eliminar evento?',
message: '',
buttons: [
{
text: 'Sim',
handler: () => {
this.deleteEvent_v2(false);
}
},
{
text: 'Não',
handler: () => {
}
}
]
}).then(res => {
res.present();
})
}
}
async deleteEvent_v2(deleteAll) {
console.log(this.loadedEvent.EventId)
const loader = this.toastService.loading()
const value = await this.agendaDataRepository.deleteEvent(this.loadedEvent.EventId,deleteAll)//.subscribe(() => {
if(value.isOk()) {
console.log(value.value)
this.httpErrorHandle.httpsSucessMessagge('delete event')
this.close();
} else {
console.log('delete event error: ', value.error)
this.httpErrorHandle.httpStatusHandle(value.error)
}
loader.remove();
}
// async deleteEvent() {
// if (this.loadedEvent.IsRecurring) {
// const loader = this.toastService.loading()
// if(this.sesseionStora.user.Profile == 'MDGPR' || this.sesseionStora.user.Profile == 'PR') {
// this.eventsService.deleteEvent(this.loadedEvent.EventId, 0, this.loadedEvent.CalendarName).subscribe(async () => {
// this.httpErrorHandle.httpsSucessMessagge('delete event')
// this.close();
// },(error)=>{
// this.httpErrorHandle.httpStatusHandle(error)
// },
// ()=>{
// loader.remove();
// });
// } else {
// if(this.CalendarId) {
// this.eventsService.genericDeleteEvent(this.loadedEvent.EventId, 0, this.loadedEvent.CalendarName, this.CalendarId).subscribe(async () => {
// this.httpErrorHandle.httpsSucessMessagge('delete event');
// this.close();
// },(error)=>{
// this.httpErrorHandle.httpStatusHandle(error)
// },
// ()=>{
// loader.remove();
// });
// }
// }
// } else {
// const loader = this.toastService.loading()
// if(this.sesseionStora.user.Profile == 'MDGPR' || this.sesseionStora.user.Profile == 'PR') {
// this.eventsService.deleteEvent(this.loadedEvent.EventId, 0, this.loadedEvent.CalendarName).subscribe(async () => {
// this.httpErrorHandle.httpsSucessMessagge('delete event');
// this.close();
// },(error)=>{
// this.httpErrorHandle.httpStatusHandle(error)
// },
// ()=>{
// loader.remove();
// });
// } else {
// this.eventsService.genericDeleteEvent(this.loadedEvent.EventId, 0, this.loadedEvent.CalendarName, this.CalendarId).subscribe(async () => {
// this.httpErrorHandle.httpsSucessMessagge('delete event');
// this.close();
// },(error)=>{
// this.httpErrorHandle.httpStatusHandle(error)
// },
// ()=>{
// loader.remove();
// });
// }
// }
// }
async deleteRecurringEvent() {
const modal = await this.modalController.create({
component: EliminateEventPage,
componentProps: {},
cssClass: 'discart-expedient-modal',
});
modal.onDidDismiss().then((res) => {
});
await modal.present();
}
async editEvent() {
this.viewEventDetailDismiss.emit({
type: 'edit',
event: this.loadedEvent
})
}
viewDocument(sourceId) {
this.processes.GetDocumentUrl(sourceId, '8').subscribe(res=>{
const url: string = res.replace("webTRIX.Viewer","webTRIX.Viewer.Branch1");
const browser = this.iab.create(url,"_blank");
browser.show();
});
}
async LoadDocumentDetails() {
const docId = this.loadedEvent.Attachments[ this.dicIndex].SourceId
const applicationId: any = this.loadedEvent.Attachments[ this.dicIndex].ApplicationId
const selectedDoc = this.loadedEvent.Attachments[ this.dicIndex]
this.task = {
serialNumber: '',
taskStartDate: '',
isEvent: true,
workflowInstanceDataFields: {
FolderID: '',
Subject: selectedDoc.SourceName,
SourceSecFsID: selectedDoc.ApplicationId || selectedDoc['ApplicationID'],
SourceType: 'DOC',
SourceID: selectedDoc.SourceId,
DispatchNumber: ''
}
}
const modal = await this.modalController.create({
component: ViewDocumentPage,
componentProps: {
trustedUrl: '',
file: {
title: this.task.workflowInstanceDataFields.Subject,
url: '',
title_link: '',
},
Document: this.loadedEvent.Attachments[ this.dicIndex],
applicationId: this.task.workflowInstanceDataFields.SourceSecFsID,
docId: selectedDoc.SourceId,
folderId: '',
task: this.task
},
cssClass: 'modal modal-desktop'
});
await modal.present();
}
async openBookMeetingModal() {
let classs;
if( window.innerWidth < 701) {
classs = 'book-meeting-modal modal modal-desktop'
} else {
classs = 'modal modal-desktop showAsideOptions'
}
const modal = await this.modalController.create({
component: DocumentSetUpMeetingPage,
componentProps: {
subject: this.task.workflowInstanceDataFields.Subject,
document: this.loadedEvent.Attachments[ this.dicIndex],
},
cssClass: classs,
backdropDismiss: false
});
modal.onDidDismiss().then(res=>{
//this.RouteService.goBack();
});
await modal.present();
}
// efetuar despacho
async openExpedientActionsModal( taskAction: any) {
let classs;
if( window.innerWidth < 701) {
classs = 'modal modal-desktop'
} else {
classs = 'modal modal-desktop showAsideOptions'
}
const modal = await this.modalController.create({
component: ExpedientTaskModalPage,
componentProps: {
taskAction: taskAction,
task: this.task,
seachDocuments: this.loadedEvent.Attachments[ this.dicIndex],
aplicationId: this.loadedEvent.Attachments[ this.dicIndex].ApplicationId || this.loadedEvent.Attachments[ this.dicIndex]['ApplicationID']
},
cssClass: classs,
});
modal.onDidDismiss().then( async(res)=>{});
await modal.present();
}
stringToNumber(number: string) {
return parseInt(number)
}
}