mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-18 20:47:54 +00:00
Merge branch 'developer' of bitbucket.org:equilibriumito/gabinete-digital into developer
This commit is contained in:
@@ -5,6 +5,7 @@ import { HomeGuard } from '../guards/home.guard';
|
||||
import { LoginGuard } from '../guards/login.guard';
|
||||
import { GroupMessagesPage } from '../pages/chat/group-messages/group-messages.page';
|
||||
import { MessagesPage } from '../pages/chat/messages/messages.page';
|
||||
import { PendentesResolverService } from '../resolvers/pendentes-resolver.service';
|
||||
import { ProcessesResolverService } from '../resolvers/processes-resolver.service';
|
||||
import { UserDataResolver } from '../resolvers/userData.resolver';
|
||||
import { DiplomasPage } from '../shared/gabinete-digital/diplomas/diplomas.page';
|
||||
@@ -142,9 +143,6 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'gabinete-digital',
|
||||
resolve: {
|
||||
diplomas: ProcessesResolverService
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path:'',
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
export class EventRecurrence{
|
||||
Type: string;
|
||||
Day?: number;
|
||||
DayOfWeek?:number;
|
||||
Month?: number;
|
||||
LastOcurrence?: Date;
|
||||
|
||||
/* public EventRecurrence(){
|
||||
this.Type = "-1";
|
||||
} */
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EventRecurrence } from './agenda/eventrecurrence.model';
|
||||
import { EventBody } from './eventbody.model';
|
||||
import { EventPerson } from './eventperson.model';
|
||||
import { SearchDocument } from './search-document';
|
||||
|
||||
export class Event{
|
||||
ParentId?: string;
|
||||
@@ -20,8 +20,12 @@ export class Event{
|
||||
TimeZone: string;
|
||||
Organizer: string;
|
||||
Categories: string[];
|
||||
HasAttachments: boolean;
|
||||
// documents?: SearchDocument[]
|
||||
HasAttachments: boolean;
|
||||
EventRecurrence?: EventRecurrence;
|
||||
|
||||
/* public Event(){
|
||||
this.EventRecurrence = new EventRecurrence();
|
||||
} */
|
||||
}
|
||||
|
||||
export class EventToApproveEdit {
|
||||
|
||||
@@ -556,7 +556,7 @@ export class AgendaPage implements OnInit {
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
else if(this.loggeduser.Profile == 'PR') {
|
||||
this.eventService.getAllPrEvents(momentG(new Date(startTime),'yyyy-MM-dd HH:mm:ss'), momentG(new Date(endTime),'yyyy-MM-dd 23:59:59')).then(
|
||||
(response:any) => {
|
||||
|
||||
|
||||
@@ -151,24 +151,45 @@
|
||||
</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-refresh.svg"></ion-icon>
|
||||
</div>
|
||||
<div class="ion-input-class">
|
||||
<ion-select placeholder="Selecione repetição*"
|
||||
[(ngModel)]="postEvent.IsRecurring"
|
||||
selectedText="{{isRecurring}}"
|
||||
<div class="ion-input-class" [class.input-error]="Form?.get('Categories')?.invalid && validateFrom ">
|
||||
<ion-select placeholder="Selecione a repetição*"
|
||||
[(ngModel)]="selectedRecurringType"
|
||||
(ngModelChange)="onSelectedRecurringChanged($event)"
|
||||
interface="action-sheet"
|
||||
Cancel-text="Cancelar" required>
|
||||
<ion-select-option value="false">Não se repete</ion-select-option>
|
||||
<ion-select-option value="true">Repete</ion-select-option>
|
||||
<ion-select-option *ngFor="let recurring of recurringTypes" value="{{recurring.Code}}">{{recurring.Description}}</ion-select-option>
|
||||
</ion-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="selectedRecurringType != '-1'" 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
|
||||
placeholder="Última ocorrência"
|
||||
[(ngModel)]="postEvent.EventRecurrence.LastOcurrence"
|
||||
displayFormat="D MMM YYYY H:mm"
|
||||
minuteValues="0,15,30,45"
|
||||
monthShortNames="Jan, Fev, Mar, Abr, Mai, Jun, Jul, Aug, Sep, Out, Nov, Dez"
|
||||
min="2021"
|
||||
max="2025"
|
||||
>
|
||||
</ion-datetime>
|
||||
<!-- <ion-input placeholder="Data fim" [(ngModel)]="postData.EndDate"></ion-input> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-div width-100">
|
||||
<div (click)="addParticipants()" class="ion-item-class-2 cursor-pointer">
|
||||
<div class="ion-icon-class">
|
||||
|
||||
@@ -36,6 +36,8 @@ export class EditEventPage implements OnInit {
|
||||
minDate: string;
|
||||
initCalendarName: string;
|
||||
caller:string;
|
||||
recurringTypes: any;
|
||||
selectedRecurringType: any;
|
||||
|
||||
|
||||
loadedEventAttachments: Attachment[] = [];
|
||||
@@ -56,10 +58,10 @@ export class EditEventPage implements OnInit {
|
||||
private router: Router,
|
||||
) {
|
||||
|
||||
|
||||
|
||||
this.postEvent = new Event();
|
||||
this.isEventEdited = false;
|
||||
this.postEvent = this.navParams.get('event');
|
||||
this.postEvent.EventRecurrence = {Type:'-1'};
|
||||
this.caller = this.navParams.get('caller');
|
||||
this.initCalendarName = this.postEvent.CalendarName;
|
||||
|
||||
@@ -97,8 +99,7 @@ export class EditEventPage implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
console.log(this.caller);
|
||||
this.selectedRecurringType = "-1";
|
||||
|
||||
window.onresize = (event) => {
|
||||
// if not mobile remove all component
|
||||
@@ -109,6 +110,8 @@ export class EditEventPage implements OnInit {
|
||||
if(window.innerWidth > 800){
|
||||
this.showAttendees=true;
|
||||
}
|
||||
|
||||
this.getRecurrenceTypes();
|
||||
|
||||
}
|
||||
|
||||
@@ -121,6 +124,24 @@ export class EditEventPage implements OnInit {
|
||||
this.router.navigate(['/home',this.caller]);
|
||||
}
|
||||
|
||||
getRecurrenceTypes() {
|
||||
this.eventsService.getRecurrenceTypes().subscribe(res=>{
|
||||
console.log(res);
|
||||
this.recurringTypes = res;
|
||||
});
|
||||
}
|
||||
|
||||
onSelectedRecurringChanged(ev:any){
|
||||
console.log(ev);
|
||||
if(ev.length > 1){
|
||||
console.log(ev.filter(data => data != '-1'));
|
||||
this.selectedRecurringType = ev.filter(data => data != '-1');
|
||||
}
|
||||
if(ev.length == 0){
|
||||
this.selectedRecurringType = "-1";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
runValidation() {
|
||||
this.validateFrom = true
|
||||
@@ -162,6 +183,9 @@ export class EditEventPage implements OnInit {
|
||||
|
||||
this.postEvent.Attendees = this.taskParticipants.concat(this.taskParticipantsCc)
|
||||
try{
|
||||
console.log(this.postEvent);
|
||||
this.postEvent.EventRecurrence.Type = this.selectedRecurringType;
|
||||
|
||||
this.eventsService.editEvent(this.postEvent, 2, 3).subscribe(async () => {
|
||||
if(this.initCalendarName != this.postEvent.CalendarName){
|
||||
let body = {
|
||||
|
||||
@@ -154,20 +154,44 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-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-refresh.svg"></ion-icon>
|
||||
</div>
|
||||
<div class="ion-input-class">
|
||||
<ion-select placeholder="Selecione repetição*" value="false" interface="action-sheet" Cancel-text="Cancelar" required>
|
||||
<ion-select-option value="false">Não se repete</ion-select-option>
|
||||
<ion-select-option value="true">Repete</ion-select-option>
|
||||
<div class="ion-input-class" [class.input-error]="Form?.get('Categories')?.invalid && validateFrom ">
|
||||
<ion-select placeholder="Selecione a repetição*"
|
||||
[(ngModel)]="selectedRecurringType"
|
||||
(ngModelChange)="onSelectedRecurringChanged($event)"
|
||||
interface="action-sheet"
|
||||
Cancel-text="Cancelar" required>
|
||||
<ion-select-option *ngFor="let recurring of recurringTypes" value="{{recurring.Code}}">{{recurring.Description}}</ion-select-option>
|
||||
</ion-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="selectedRecurringType != '-1'" 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
|
||||
placeholder="Última ocorrência"
|
||||
[(ngModel)]="postEvent.EventRecurrence.LastOcurrence"
|
||||
displayFormat="D MMM YYYY H:mm"
|
||||
minuteValues="0,15,30,45"
|
||||
monthShortNames="Jan, Fev, Mar, Abr, Mai, Jun, Jul, Aug, Sep, Out, Nov, Dez"
|
||||
min="2021"
|
||||
max="2025"
|
||||
>
|
||||
</ion-datetime>
|
||||
<!-- <ion-input placeholder="Data fim" [(ngModel)]="postData.EndDate"></ion-input> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-div">
|
||||
<div class="ion-item-class-2">
|
||||
<div class="ion-icon-class">
|
||||
|
||||
@@ -14,6 +14,7 @@ import { AttendeesPageModal } from '../../events/attendees/attendees.page';
|
||||
import { SearchPage } from '../../search/search.page';
|
||||
import { ThemePalette } from '@angular/material/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { EventRecurrence } from 'src/app/models/agenda/eventrecurrence.model';
|
||||
|
||||
|
||||
@Component({
|
||||
@@ -47,6 +48,8 @@ export class NewEventPage implements OnInit {
|
||||
eventAttendees: EventPerson[];
|
||||
selectedSegment: string;
|
||||
selectedDate: Date;
|
||||
recurringTypes: any;
|
||||
selectedRecurringType: any;
|
||||
|
||||
adding: "intervenient" | "CC";
|
||||
|
||||
@@ -68,6 +71,7 @@ export class NewEventPage implements OnInit {
|
||||
) {
|
||||
this.loggeduser = userService.ValidatedUser;
|
||||
this.postEvent = new Event();
|
||||
this.postEvent.EventRecurrence = {Type:'-1'};
|
||||
this.eventBody = { BodyType : "1", Text : ""};
|
||||
this.postEvent.Body = this.eventBody;
|
||||
/* this.profile = this.navParams.get('profile'); */
|
||||
@@ -81,6 +85,8 @@ export class NewEventPage implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.selectedRecurringType = "-1";
|
||||
this.getRecurrenceTypes();
|
||||
|
||||
/* console.log(this.profile); */
|
||||
|
||||
@@ -108,6 +114,7 @@ export class NewEventPage implements OnInit {
|
||||
Organizer: '',
|
||||
Categories: ['Reunião'],
|
||||
HasAttachments: false,
|
||||
EventRecurrence: {Type:'-1'},
|
||||
};
|
||||
}
|
||||
else{
|
||||
@@ -129,6 +136,7 @@ export class NewEventPage implements OnInit {
|
||||
Organizer: '',
|
||||
Categories: ['Reunião'],
|
||||
HasAttachments: false,
|
||||
EventRecurrence: {Type:'-1'},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -144,6 +152,25 @@ export class NewEventPage implements OnInit {
|
||||
close(){
|
||||
this.modalController.dismiss();
|
||||
}
|
||||
|
||||
|
||||
getRecurrenceTypes() {
|
||||
this.eventService.getRecurrenceTypes().subscribe(res=>{
|
||||
console.log(res);
|
||||
this.recurringTypes = res;
|
||||
});
|
||||
}
|
||||
|
||||
onSelectedRecurringChanged(ev:any){
|
||||
console.log(ev);
|
||||
if(ev.length > 1){
|
||||
console.log(ev.filter(data => data != '-1'));
|
||||
this.selectedRecurringType = ev.filter(data => data != '-1');
|
||||
}
|
||||
if(ev.length == 0){
|
||||
this.selectedRecurringType = "-1";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
runValidation() {
|
||||
@@ -197,6 +224,9 @@ export class NewEventPage implements OnInit {
|
||||
if(this.documents.length >= 0) {
|
||||
this.postEvent.HasAttachments = true;
|
||||
}
|
||||
if(this.selectedRecurringType != '-1'){
|
||||
this.postEvent.EventRecurrence.Type = this.selectedRecurringType;
|
||||
}
|
||||
|
||||
let eventId: any;
|
||||
|
||||
@@ -204,6 +234,8 @@ export class NewEventPage implements OnInit {
|
||||
|
||||
if(this.loggeduser.Profile == 'MDGPR') {
|
||||
console.log(this.loggeduser.Profile);
|
||||
|
||||
console.log(this.postEvent);
|
||||
|
||||
eventId = await this.eventService.postEventMd(this.postEvent, this.postEvent.CalendarName).toPromise();
|
||||
console.log(eventId);
|
||||
|
||||
+1
@@ -246,6 +246,7 @@ export class BookMeetingModalPage implements OnInit {
|
||||
Organizer: null,
|
||||
Categories: null,
|
||||
HasAttachments: true,
|
||||
EventRecurrence: null,
|
||||
}
|
||||
|
||||
console.log(this.postData);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="title">
|
||||
<div class="thetitle"><ion-label >Expediente</ion-label></div>
|
||||
<div class="theicon btn-refresh">
|
||||
<button class="btn-no-color" (click)="doRefresh($event)">
|
||||
<button class="btn-no-color" (click)="refreshing()">
|
||||
<ion-icon slot="end" class="title-icon" name="reload-circle"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<div class="width-100">
|
||||
<div *ngIf="pendentesList">
|
||||
<div *ngIf="pendentesList" class="width-100">
|
||||
<div >
|
||||
<ion-list>
|
||||
<div
|
||||
class="expediente ion-no-padding ion-no-margin cursor-pointer"
|
||||
@@ -66,7 +66,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!pendentesList">
|
||||
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
<ion-thumbnail slot="end">
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { NavigationExtras, Router } from '@angular/router';
|
||||
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
|
||||
import { CalendarComponent } from 'ionic2-calendar';
|
||||
|
||||
import { removeDuplicate } from 'src/plugin/removeDuplicate.js'
|
||||
import { DailyWorkTask } from '../../../models/dailyworktask.model';
|
||||
import { ProcessesService } from 'src/app/services/processes.service';
|
||||
import { formatDate } from '@angular/common';
|
||||
import { ModalController, NavParams } from '@ionic/angular';
|
||||
import { AlertService } from 'src/app/services/alert.service';
|
||||
import { DespachoPage } from 'src/app/pages/gabinete-digital/despachos/despacho/despacho.page';
|
||||
import { AuthService } from 'src/app/services/auth.service';
|
||||
import { PedidoPage } from 'src/app/pages/gabinete-digital/pedidos/pedido/pedido.page';
|
||||
|
||||
|
||||
@Component({
|
||||
@@ -32,10 +28,9 @@ export class PendentesPage implements OnInit {
|
||||
|
||||
constructor(
|
||||
private processes:ProcessesService,
|
||||
private modalController: ModalController,
|
||||
private alertService: AlertService,
|
||||
private authService: AuthService,
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
) {
|
||||
this.profile = 'mdgpr';
|
||||
}
|
||||
@@ -43,11 +38,15 @@ export class PendentesPage implements OnInit {
|
||||
ngOnInit() {
|
||||
//Inicializar segment
|
||||
this.segment = "despachos";
|
||||
this.LoadList();
|
||||
this.router.events.forEach((event) => {
|
||||
if(event instanceof NavigationEnd && event.url == this.router.url) {
|
||||
this.refreshing();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
segmentChanged(ev: any) {
|
||||
this.LoadList();
|
||||
this.refreshing();
|
||||
}
|
||||
|
||||
goBack() {
|
||||
@@ -98,6 +97,7 @@ export class PendentesPage implements OnInit {
|
||||
"Status": element.workflowInstanceDataFields.Status,
|
||||
}
|
||||
this.pendentesList.push(task);
|
||||
this.pendentesList = removeDuplicate( this.pendentesList)
|
||||
},
|
||||
(error)=>{
|
||||
let task = {
|
||||
@@ -114,10 +114,17 @@ export class PendentesPage implements OnInit {
|
||||
"Status": element.workflowInstanceDataFields.Status,
|
||||
}
|
||||
this.pendentesList.push(task);
|
||||
this.pendentesList = removeDuplicate( this.pendentesList)
|
||||
});
|
||||
});
|
||||
this.showLoader = false;
|
||||
}
|
||||
|
||||
async refreshing() {
|
||||
setTimeout(() => {
|
||||
this.LoadList();
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
doRefresh(event) {
|
||||
this.LoadList();
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PendentesResolverService } from './pendentes-resolver.service';
|
||||
|
||||
describe('PendentesResolverService', () => {
|
||||
let service: PendentesResolverService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(PendentesResolverService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ProcessesService } from '../services/processes.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PendentesResolverService implements Resolve<any> {
|
||||
|
||||
constructor(
|
||||
private processesService: ProcessesService,
|
||||
) { }
|
||||
|
||||
async resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
|
||||
Promise<any> {
|
||||
|
||||
let despachos = await this.processesService.GetTasksList("Despacho", false).toPromise();
|
||||
let pareceres = await this.processesService.GetTasksList("Pedido de Parecer", false).toPromise();
|
||||
let deferimentos = await this.processesService.GetTasksList("Pedido de Deferimento", false).toPromise();
|
||||
let expedientes = await this.processesService.GetTasksList("Expediente", false).toPromise();
|
||||
let expedientes_pr = await this.processesService.GetTasksList("Expediente do Presidente", false).toPromise();
|
||||
|
||||
let pendentes = despachos.concat(pareceres, deferimentos, expedientes, expedientes_pr).filter(data => data.workflowInstanceDataFields.Status == "Pending");
|
||||
|
||||
return pendentes;
|
||||
}
|
||||
}
|
||||
@@ -200,6 +200,8 @@ export class EventsService {
|
||||
headers: this.headersSharedOficial,
|
||||
params: params
|
||||
};
|
||||
console.log(options);
|
||||
|
||||
return this.http.get<Event[]>(`${geturl}`, options);
|
||||
}
|
||||
|
||||
@@ -228,6 +230,14 @@ export class EventsService {
|
||||
});
|
||||
}
|
||||
|
||||
getRecurrenceTypes(): any{
|
||||
const geturl = environment.apiURL + 'Calendar/RecurrenceTypes';
|
||||
let options = {
|
||||
headers: this.headers,
|
||||
};
|
||||
return this.http.get<any>(`${geturl}`, options);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -173,6 +173,7 @@ export class NewEventPage implements OnInit {
|
||||
Organizer: '',
|
||||
Categories: ['Reunião'],
|
||||
HasAttachments: false,
|
||||
EventRecurrence: null,
|
||||
};
|
||||
}
|
||||
else{
|
||||
@@ -194,6 +195,7 @@ export class NewEventPage implements OnInit {
|
||||
Organizer: '',
|
||||
Categories: ['Reunião'],
|
||||
HasAttachments: false,
|
||||
EventRecurrence: null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,18 +2,13 @@
|
||||
<div class="title">
|
||||
<div class="thetitle"><ion-label >Expediente</ion-label></div>
|
||||
<div class="theicon">
|
||||
<button class="btn-no-color" (click)="doRefresh()">
|
||||
<button class="btn-no-color" (click)="refreshing()">
|
||||
<ion-icon slot="end" class="title-icon" name="reload-circle"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh()">
|
||||
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
|
||||
<ion-refresher-content>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<div class="width-100 overflow-y-auto height-100" *ngIf="taskslist.length >= 1">
|
||||
<ion-list>
|
||||
|
||||
@@ -117,9 +117,10 @@ export class ExpedientesPrPage implements OnInit {
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
doRefresh() {
|
||||
doRefresh(event) {
|
||||
this.LoadList();
|
||||
setTimeout(() => {
|
||||
event.target.complete();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user