This commit is contained in:
Eudes Inácio
2022-04-08 16:49:14 +01:00
17 changed files with 149 additions and 102 deletions
+51 -2
View File
@@ -5,7 +5,7 @@ import { AuthService } from '../services/auth.service';
import { PermissionService } from '../services/permission.service'; import { PermissionService } from '../services/permission.service';
import { LocalstoreService } from '../store/localstore.service'; import { LocalstoreService } from '../store/localstore.service';
import { SessionStore } from '../store/session.service'; import { SessionStore } from '../store/session.service';
import { RouteService } from 'src/app/services/route.service'
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
@@ -15,6 +15,7 @@ export class AuthGuard implements CanActivate {
private localstoreService: LocalstoreService, private localstoreService: LocalstoreService,
private authService: AuthService, private authService: AuthService,
public p: PermissionService, public p: PermissionService,
private RouteService: RouteService
){} ){}
canActivate( canActivate(
@@ -31,11 +32,59 @@ export class AuthGuard implements CanActivate {
this.router.navigate(['/']); this.router.navigate(['/']);
return false return false
} else { } else {
if(this.p.userPermission(this.p.permissionList.Chat.access) == true){ if(this.p.userPermission(this.p.permissionList.Chat.access) == true) {
this.authService.loginChat(); this.authService.loginChat();
} }
const pathname = state.url
if(pathname.startsWith('/home/agenda')) {
if(this.p.userPermission(this.p.permissionList.Agenda.access)) {
return true; return true;
} else {
this.router.navigate(['/login']);
return false;
}
} else if ( pathname.startsWith('/home/gabinete-digital')) {
if(this.p.userPermission(this.p.permissionList.Gabinete.access)) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
else if(pathname.startsWith('/home/chat')) {
if(this.p.userPermission(this.p.permissionList.Chat.access)) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
} else if(pathname.startsWith('/home/publications')) {
if(this.p.userPermission(this.p.permissionList.Actions.access)) {
return true
} else {
this.router.navigate(['/login']);
return false
}
} else if (pathname.startsWith('/home/events')) {
if(SessionStore.user.OwnerCalendars.length >= 1 || this.p.userPermission([this.p.permissionList.Gabinete.access])) {
return true
} else {
this.router.navigate(['/login']);
return false
}
} else if (pathname == '/') {
this.router.navigate(['/login']);
return false
} else {
this.router.navigate(['/login']);
return false
}
} }
} }
+21 -5
View File
@@ -24,14 +24,22 @@ export class InactivityGuard implements CanActivate {
if (this.platform.is('desktop') || this.platform.is('mobileweb')) { if (this.platform.is('desktop') || this.platform.is('mobileweb')) {
if(this.p.userPermission(this.p.permissionList.Agenda.access) || this.p.userPermission(this.p.permissionList.Gabinete.access)){ if(this.p.userPermission(this.p.permissionList.Agenda.access) || this.p.userPermission(this.p.permissionList.Gabinete.access)){
//When user has got access to Agenda but does not have their own calendar, goes to Agenda
if(this.p.userPermission(this.p.permissionList.Agenda.access) && SessionStore.user.OwnerCalendars.length == 0){
this.router.navigate(['/home/agenda']);
}
else{
this.router.navigate(['/home/events']); this.router.navigate(['/home/events']);
} }
else if(this.p.userPermission(this.p.permissionList.Chat.access) && this.p.userPermission(this.p.permissionList.Actions.access)){ }
//If user has access permission to both Chat and Action, goes to Chat by default.
else if((this.p.userPermission(this.p.permissionList.Chat.access) && this.p.userPermission(this.p.permissionList.Actions.access)) || this.p.userPermission(this.p.permissionList.Chat.access)){
this.router.navigate(['/home/chat']); this.router.navigate(['/home/chat']);
} }
else if(this.p.userPermission(this.p.permissionList.Actions.access)){ else if(this.p.userPermission(this.p.permissionList.Actions.access)) {
this.router.navigate(['/home/publications']); this.router.navigate(['/home/publications']);
} else { }
else {
this.alertController.create({ this.alertController.create({
cssClass: 'my-custom-class', cssClass: 'my-custom-class',
@@ -57,14 +65,22 @@ export class InactivityGuard implements CanActivate {
else { else {
if(this.p.userPermission(this.p.permissionList.Agenda.access) || this.p.userPermission(this.p.permissionList.Gabinete.access)){ if(this.p.userPermission(this.p.permissionList.Agenda.access) || this.p.userPermission(this.p.permissionList.Gabinete.access)){
//When user has got access to Agenda but does not have their own calendar, goes to Agenda
if(this.p.userPermission(this.p.permissionList.Agenda.access) && SessionStore.user.OwnerCalendars.length == 0){
this.router.navigate(['/home/agenda']);
}
else{
this.router.navigate(['/home/events']); this.router.navigate(['/home/events']);
} }
else if(this.p.userPermission(this.p.permissionList.Chat.access) && this.p.userPermission(this.p.permissionList.Actions.access)){ }
//If user has access permission to both Chat and Action, goes to Chat by default.
else if((this.p.userPermission(this.p.permissionList.Chat.access) && this.p.userPermission(this.p.permissionList.Actions.access)) || this.p.userPermission(this.p.permissionList.Chat.access)){
this.router.navigate(['/home/chat']); this.router.navigate(['/home/chat']);
} }
else if(this.p.userPermission(this.p.permissionList.Actions.access)){ else if(this.p.userPermission(this.p.permissionList.Actions.access)){
this.router.navigate(['/home/publications']); this.router.navigate(['/home/publications']);
} else { }
else {
this.alertController.create({ this.alertController.create({
cssClass: 'my-custom-class', cssClass: 'my-custom-class',
header: 'Utilizador sem acesso a aplicação', header: 'Utilizador sem acesso a aplicação',
+6 -1
View File
@@ -3,12 +3,16 @@ import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Rout
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { SessionStore } from '../store/session.service'; import { SessionStore } from '../store/session.service';
import { Platform } from '@ionic/angular'; import { Platform } from '@ionic/angular';
import { RouteService } from 'src/app/services/route.service'
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class LoginGuard implements CanActivate { export class LoginGuard implements CanActivate {
constructor( private router:Router, private platform: Platform,) { constructor(
private router:Router,
private platform: Platform,
private RouteService: RouteService ) {
} }
canActivate( canActivate(
@@ -27,6 +31,7 @@ export class LoginGuard implements CanActivate {
} else if(SessionStore.exist && !SessionStore.user.Inactivity && SessionStore.user.LoginPreference == 'Pin' && !this.platform.is('desktop') && !this.platform.is('mobileweb')) { } else if(SessionStore.exist && !SessionStore.user.Inactivity && SessionStore.user.LoginPreference == 'Pin' && !this.platform.is('desktop') && !this.platform.is('mobileweb')) {
this.router.navigate(['/inactivity']); this.router.navigate(['/inactivity']);
return false return false
} else { } else {
return true return true
} }
+4 -1
View File
@@ -1,6 +1,7 @@
<ion-tabs class="tab" > <ion-tabs class="tab" >
<ion-tab-bar *ngIf="p.userPermissionCount([permissionList.Agenda.access, permissionList.Gabinete.access, permissionList.Actions.access, permissionList.Chat.access]) >= 2 || p.userPermission([permissionList.Agenda.access]) || p.userPermission([permissionList.Gabinete.access])" class="bottoms" slot="bottom">
<ion-tab-bar *ngIf="p.userPermissionCount([permissionList.Agenda.access, permissionList.Gabinete.access, permissionList.Actions.access, permissionList.Chat.access]) >= 2 || (p.userPermission([permissionList.Agenda.access]) && loggeduser.OwnerCalendars.length != 0) || p.userPermission([permissionList.Gabinete.access])" class="bottoms" slot="bottom">
<ion-tab-button *ngIf="loggeduser.OwnerCalendars.length >= 1 || p.userPermission([permissionList.Gabinete.access])" tab="events" [class.active]="pathname === '/home/events'"> <ion-tab-button *ngIf="loggeduser.OwnerCalendars.length >= 1 || p.userPermission([permissionList.Gabinete.access])" tab="events" [class.active]="pathname === '/home/events'">
<!-- <ion-icon name="home"></ion-icon> --> <!-- <ion-icon name="home"></ion-icon> -->
@@ -39,5 +40,7 @@
</ion-tab-button> </ion-tab-button>
</ion-tab-bar> </ion-tab-bar>
</ion-tabs> </ion-tabs>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
+2 -3
View File
@@ -15,7 +15,6 @@ import { SessionStore } from '../store/session.service';
import { StorageService } from '../services/storage.service'; import { StorageService } from '../services/storage.service';
import { File } from '@ionic-native/file/ngx'; import { File } from '@ionic-native/file/ngx';
/* import { WebNotificationPopupService } from '../services/notification/web-notification-popup.service'; */ /* import { WebNotificationPopupService } from '../services/notification/web-notification-popup.service'; */
import { DocumentCounterService } from '../services/worker/document-counter.service';
import { PermissionService } from '../services/permission.service'; import { PermissionService } from '../services/permission.service';
import { BackgroundService } from 'src/app/services/background.service'; import { BackgroundService } from 'src/app/services/background.service';
import { OfflineManagerService } from 'src/app/services/offline-manager.service'; import { OfflineManagerService } from 'src/app/services/offline-manager.service';
@@ -36,6 +35,7 @@ import { LoginUserRespose } from 'src/app/models/user.model';
import { AuthService } from 'src/app/services/auth.service'; import { AuthService } from 'src/app/services/auth.service';
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
templateUrl: './home.page.html', templateUrl: './home.page.html',
@@ -93,11 +93,10 @@ export class HomePage implements OnInit {
private router: Router, private router: Router,
public modalCtrl: AlertController, public modalCtrl: AlertController,
private notificationsService: NotificationsService, private notificationsService: NotificationsService,
private platform: Platform, public platform: Platform,
private activeroute: ActivatedRoute, private activeroute: ActivatedRoute,
/* private webnotification: WebNotificationsService, */ /* private webnotification: WebNotificationsService, */
public p: PermissionService, public p: PermissionService,
public documentCounterService: DocumentCounterService,
private despachoRule: DespachoService, private despachoRule: DespachoService,
private inativityService: InativityService, private inativityService: InativityService,
private storageService: StorageService, private storageService: StorageService,
+2 -2
View File
@@ -111,7 +111,7 @@
</ion-item-sliding> </ion-item-sliding>
</ion-list> </ion-list>
<ion-list *ngSwitchCase="'Grupos'"> <ion-list *ngSwitchCase="'Grupos'">
<ion-item-sliding *ngIf="!wsChatMethodsService.loadingWholeList"> <ion-item-sliding >
<div *ngFor="let group of wsChatMethodsService._group" <div *ngFor="let group of wsChatMethodsService._group"
[class.item-active]="group.id ==idSelected" [class.item-active]="group.id ==idSelected"
class="item item-hover d-flex"> class="item item-hover d-flex">
@@ -150,7 +150,7 @@
</div> </div>
</div> </div>
</ion-item-sliding> </ion-item-sliding>
<ion-item-sliding *ngIf="wsChatMethodsService.loadingWholeList || wsChatMethodsService.groupCount < 1"> <ion-item-sliding *ngIf="wsChatMethodsService.groupCount < 1">
<div *ngFor="let n of numSequence(8); let i = index;" class="item item-hover width-100 d-flex ion-no-padding ion-no-margin"> <div *ngFor="let n of numSequence(8); let i = index;" class="item item-hover width-100 d-flex ion-no-padding ion-no-margin">
<div class="item-icon"><ion-icon class="icon" slot="start" src="assets/icon/icons-group-chat-grey.svg"></ion-icon></div> <div class="item-icon"><ion-icon class="icon" slot="start" src="assets/icon/icons-group-chat-grey.svg"></ion-icon></div>
<div class="item-content flex-grow-1 cursor-pointer"> <div class="item-content flex-grow-1 cursor-pointer">
@@ -650,7 +650,6 @@ export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy {
temporaryData: formData, temporaryData: formData,
attachments: [{ attachments: [{
"title": capturedImageTitle, "title": capturedImageTitle,
//"image_url": capturedImage, // rocketchat
"text": "description", "text": "description",
"title_link_download": false, "title_link_download": false,
}] }]
@@ -15,7 +15,7 @@
</div> </div>
<ion-toolbar> <ion-toolbar>
<ion-segment [(ngModel)]="segment" (ionChange)="segmentChanged($event)"> <ion-segment [(ngModel)]="segment" (ionChange)="segmentChanged($event)">
<ion-segment-button value="validar"> <ion-segment-button value="validar" *ngIf="p.userPermission([p.permissionList.Gabinete.md_tasks])">
Por validar ... Por validar ...
</ion-segment-button> </ion-segment-button>
<ion-segment-button value="assinados"> <ion-segment-button value="assinados">
@@ -33,7 +33,7 @@
<div class="width-100" [ngSwitch]="segment"> <div class="width-100" [ngSwitch]="segment">
<ion-progress-bar type="indeterminate" *ngIf="skeletonLoader"></ion-progress-bar> <ion-progress-bar type="indeterminate" *ngIf="skeletonLoader"></ion-progress-bar>
<div *ngIf="diplomasList"> <div *ngIf="diplomasList && p.userPermission([p.permissionList.Gabinete.md_tasks])">
<ion-list *ngSwitchCase="'validar'"> <ion-list *ngSwitchCase="'validar'">
<ion-item <ion-item
+17 -3
View File
@@ -205,9 +205,16 @@ export class InactivityPage implements OnInit {
setTimeout(()=>{ setTimeout(()=>{
if(this.p.userPermission(this.p.permissionList.Agenda.access) || this.p.userPermission(this.p.permissionList.Gabinete.access)){ if(this.p.userPermission(this.p.permissionList.Agenda.access) || this.p.userPermission(this.p.permissionList.Gabinete.access)){
this.router.navigate(['/home/events'], {replaceUrl: true}); //When user has got access to Agenda but does not have their own calendar, goes to Agenda
if(this.p.userPermission(this.p.permissionList.Agenda.access) && SessionStore.user.OwnerCalendars.length == 0){
this.router.navigate(['/home/agenda']);
} }
else if(this.p.userPermission(this.p.permissionList.Chat.access) && this.p.userPermission(this.p.permissionList.Actions.access)){ else{
this.router.navigate(['/home/events']);
}
}
//If user has access permission to both Chat and Action, goes to Chat by default.
else if((this.p.userPermission(this.p.permissionList.Chat.access) && this.p.userPermission(this.p.permissionList.Actions.access)) || this.p.userPermission(this.p.permissionList.Chat.access)){
this.router.navigate(['/home/chat']); this.router.navigate(['/home/chat']);
} }
else if(this.p.userPermission(this.p.permissionList.Actions.access)){ else if(this.p.userPermission(this.p.permissionList.Actions.access)){
@@ -228,9 +235,16 @@ export class InactivityPage implements OnInit {
SessionStore.setPin(code); SessionStore.setPin(code);
if(this.p.userPermission(this.p.permissionList.Agenda.access) || this.p.userPermission(this.p.permissionList.Gabinete.access)){ if(this.p.userPermission(this.p.permissionList.Agenda.access) || this.p.userPermission(this.p.permissionList.Gabinete.access)){
//When user has got access to Agenda but does not have their own calendar, goes to Agenda
if(this.p.userPermission(this.p.permissionList.Agenda.access) && SessionStore.user.OwnerCalendars.length == 0){
this.router.navigate(['/home/agenda']);
}
else{
this.router.navigate(['/home/events']); this.router.navigate(['/home/events']);
} }
else if(this.p.userPermission(this.p.permissionList.Chat.access) && this.p.userPermission(this.p.permissionList.Actions.access)){ }
//If user has access permission to both Chat and Action, goes to Chat by default.
else if((this.p.userPermission(this.p.permissionList.Chat.access) && this.p.userPermission(this.p.permissionList.Actions.access)) || this.p.userPermission(this.p.permissionList.Chat.access)){
this.router.navigate(['/home/chat']); this.router.navigate(['/home/chat']);
} }
else if(this.p.userPermission(this.p.permissionList.Actions.access)){ else if(this.p.userPermission(this.p.permissionList.Actions.access)){
+8 -1
View File
@@ -163,9 +163,16 @@ export class LoginPage implements OnInit {
this.router.navigate([pathName]); this.router.navigate([pathName]);
} else { } else {
if(this.p.userPermission(this.p.permissionList.Agenda.access) || this.p.userPermission(this.p.permissionList.Gabinete.access)){ if(this.p.userPermission(this.p.permissionList.Agenda.access) || this.p.userPermission(this.p.permissionList.Gabinete.access)){
//When user has got access to Agenda but does not have their own calendar, goes to Agenda
if(this.p.userPermission(this.p.permissionList.Agenda.access) && SessionStore.user.OwnerCalendars.length == 0){
this.router.navigate(['/home/agenda']);
}
else{
this.router.navigate(['/home/events']); this.router.navigate(['/home/events']);
} }
else if(this.p.userPermission(this.p.permissionList.Chat.access) && this.p.userPermission(this.p.permissionList.Actions.access)){ }
//If user has access permission to both Chat and Action, goes to Chat by default.
else if((this.p.userPermission(this.p.permissionList.Chat.access) && this.p.userPermission(this.p.permissionList.Actions.access)) || this.p.userPermission(this.p.permissionList.Chat.access)){
this.router.navigate(['/home/chat']); this.router.navigate(['/home/chat']);
} }
else if(this.p.userPermission(this.p.permissionList.Actions.access)){ else if(this.p.userPermission(this.p.permissionList.Actions.access)){
@@ -33,7 +33,7 @@ export class WsChatMethodsService {
_dm: RoomService[] = [] _dm: RoomService[] = []
_group: RoomService[] = [] _group: RoomService[] = []
loadingWholeList = false loadingWholeList = false;
dmCount = 0; dmCount = 0;
groupCount = 0; groupCount = 0;
@@ -121,7 +121,7 @@ export class WsChatMethodsService {
this._dm = [] this._dm = []
this._group = [] this._group = []
this.loadingWholeList = false this.loadingWholeList = false;
this.dmCount = 0; this.dmCount = 0;
this.groupCount = 0; this.groupCount = 0;
+9
View File
@@ -88,4 +88,13 @@ export class RouteService {
} }
getLastRoute() {
return this.history[this.history.length - 1]
}
getLastRouteA() {
return this.history[this.history.length - 2]
}
} }
@@ -1,16 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { DocumentCounterService } from './document-counter.service';
describe('DocumentCounterService', () => {
let service: DocumentCounterService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(DocumentCounterService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -1,39 +0,0 @@
import { Injectable } from '@angular/core';
import { DespachoStore } from 'src/app/store/despacho-store.service';
import { EventoAprovacaoStore } from 'src/app/store/eventoaprovacao-store.service';
import { ExpedienteGdStore } from 'src/app/store/expedientegd-store.service';
import { PendentesStore } from 'src/app/store/pendestes-store.service';
import { PedidosStore } from 'src/app/store/pedidos-store.service';
import { DespachosprStore } from 'src/app/store/despachospr-store.service';
import { DeplomasStore } from 'src/app/store/deplomas.service';
@Injectable({
providedIn: 'root'
})
export class DocumentCounterService {
expedienteGbStore = ExpedienteGdStore;
pendentesStore = PendentesStore;
despachoStore = DespachoStore;
eventoAprovacaoStore = EventoAprovacaoStore;
pedidosStore = PedidosStore;
// expedientePrStore = ExpedienteprStore;
despachoPrStore = DespachosprStore;
deplomasStore = DeplomasStore
constructor() { }
// falta a contagem dos deplomas
get mdTotalDocument(): number {
return this.despachoStore.count + /** this.expedientePrStore.count + */ this.pedidosStore.countdeferimento
+ this.pedidosStore.countparecer + this.expedienteGbStore.count + this.despachoPrStore.count + this.pendentesStore.count
+ this.eventoAprovacaoStore.count + this.deplomasStore.diplomasListCount + this.deplomasStore.countDiplomasAssinadoListCount + this.deplomasStore.deplomasReviewCount
}
get prTotalDocument(): number {
return this.despachoStore.count + /** this.expedientePrStore.count + */ this.pedidosStore.countdeferimento
+ this.pedidosStore.countparecer + this.expedienteGbStore.count + this.despachoPrStore.count + this.pendentesStore.count
+ this.eventoAprovacaoStore.count + this.deplomasStore.diplomasListCount + this.deplomasStore.countDiplomasAssinadoListCount + this.deplomasStore.deplomasReviewCount
}
}
@@ -10,7 +10,7 @@
</div> </div>
<ion-toolbar> <ion-toolbar>
<ion-segment [(ngModel)]="segment" (ionChange)="segmentChanged($event)"> <ion-segment [(ngModel)]="segment" (ionChange)="segmentChanged($event)">
<ion-segment-button value="validar"> <ion-segment-button value="validar" *ngIf="p.userPermission([p.permissionList.Gabinete.md_tasks])">
Diplomas por validar Diplomas por validar
</ion-segment-button> </ion-segment-button>
<ion-segment-button value="assinados"> <ion-segment-button value="assinados">
@@ -23,7 +23,7 @@
<div class="main-container width-100 overflow-y-auto height-100" [ngSwitch]="segment"> <div class="main-container width-100 overflow-y-auto height-100" [ngSwitch]="segment">
<div *ngIf="deplomasStore.diplomasList.length >= 1"> <div *ngIf="deplomasStore.diplomasList.length >= 1 && p.userPermission([p.permissionList.Gabinete.md_tasks])">
<ion-list *ngSwitchCase="'validar'"> <ion-list *ngSwitchCase="'validar'">
<div <div
class="expediente item-hover ion-no-padding ion-no-margin cursor-pointer" class="expediente item-hover ion-no-padding ion-no-margin cursor-pointer"
+2 -1
View File
@@ -64,7 +64,7 @@
</div> </div>
</div> </div>
<div class="d-flex flex-1 pr-20 pl-50" *ngIf="p.userPermissionCount([permissionList.Agenda.access, permissionList.Gabinete.access, permissionList.Actions.access, permissionList.Chat.access]) >= 2"> <div class="d-flex flex-1 pr-20 pl-50" *ngIf="p.userPermissionCount([permissionList.Agenda.access, permissionList.Gabinete.access, permissionList.Actions.access, permissionList.Chat.access]) >= 2 || (p.userPermission([permissionList.Agenda.access]) && loggeduser.OwnerCalendars.length != 0) || p.userPermission([permissionList.Gabinete.access])">
<div *ngIf="p.userPermission([permissionList.Agenda.access]) || p.userPermission([permissionList.Gabinete.access])" class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/events')" <div *ngIf="p.userPermission([permissionList.Agenda.access]) || p.userPermission([permissionList.Gabinete.access])" class="tab mr-20 d-flex align-center cursor-pointer" (click)="changeRoute('/home/events')"
[class.active]="locationPathname() == '/home/events'"> [class.active]="locationPathname() == '/home/events'">
@@ -169,6 +169,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="header-bottom-line"></div> <div class="header-bottom-line"></div>
<!-- {{ RouteService.history | json }} --> <!-- {{ RouteService.history | json }} -->
+1 -1
View File
@@ -39,7 +39,7 @@ export class HeaderPage implements OnInit {
private modalController: ModalController, private modalController: ModalController,
private animationController: AnimationController, private animationController: AnimationController,
private storageservice: StorageService, private storageservice: StorageService,
private platform: Platform, public platform: Platform,
//private notificationsService: NotificationsService, //private notificationsService: NotificationsService,
private eventrigger: EventTrigger, private eventrigger: EventTrigger,
public ThemeService: ThemeService, public ThemeService: ThemeService,