[Library | Trunk]: Create subscriber invite and subscribers components.
git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-services-library/trunk/ng-openaire-library/src/app@60274 d315682c-612b-4755-9ff5-7f18f6832af3
This commit is contained in:
parent
83493a1abc
commit
7d147b89e7
|
@ -1,211 +1,252 @@
|
||||||
import { Injectable } from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {HttpClient, HttpHeaders} from "@angular/common/http";
|
import {HttpClient, HttpHeaders} from "@angular/common/http";
|
||||||
import { CommunityInfo } from './communityInfo';
|
import {CommunityInfo} from './communityInfo';
|
||||||
import {EnvProperties} from '../../utils/properties/env-properties';
|
import {EnvProperties} from '../../utils/properties/env-properties';
|
||||||
import {map} from "rxjs/operators";
|
import {map} from "rxjs/operators";
|
||||||
import {BehaviorSubject, from, Subscriber} from "rxjs";
|
import {BehaviorSubject, from, Subscriber} from "rxjs";
|
||||||
import {properties} from "../../../../environments/environment";
|
import {properties} from "../../../../environments/environment";
|
||||||
|
import {HelperFunctions} from "../../utils/HelperFunctions.class";
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({providedIn: 'root'})
|
||||||
export class CommunityService {
|
export class CommunityService {
|
||||||
|
|
||||||
public community: BehaviorSubject<CommunityInfo> = null;
|
public community: BehaviorSubject<CommunityInfo> = null;
|
||||||
private promise: Promise<boolean> = null;
|
private promise: Promise<boolean> = null;
|
||||||
|
private sub;
|
||||||
|
|
||||||
constructor(private http: HttpClient) {
|
constructor(private http: HttpClient) {
|
||||||
this.community = new BehaviorSubject(null);
|
this.community = new BehaviorSubject(null);
|
||||||
}
|
}
|
||||||
sub;
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.clearSubscriptions();
|
this.clearSubscriptions();
|
||||||
}
|
}
|
||||||
clearSubscriptions(){
|
|
||||||
|
clearSubscriptions() {
|
||||||
if (this.sub instanceof Subscriber) {
|
if (this.sub instanceof Subscriber) {
|
||||||
this.sub.unsubscribe();
|
this.sub.unsubscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Remove these functions
|
||||||
getCommunityByService(properties: EnvProperties, url: string) {
|
getCommunityByService(properties: EnvProperties, url: string) {
|
||||||
this.promise = new Promise<any>(resolve => {
|
this.promise = new Promise<any>(resolve => {
|
||||||
this.sub = this.getCommunity(properties, url).subscribe(res => {
|
this.sub = this.getCommunity(properties, url).subscribe(res => {
|
||||||
this.community.next(res);
|
this.community.next(res);
|
||||||
resolve();
|
resolve();
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.community.error(error);
|
this.community.error(error);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCommunityByStateAsync(properties: EnvProperties, url: string) {
|
async getCommunityByStateAsync(properties: EnvProperties, url: string) {
|
||||||
if(!this.promise) {
|
if (!this.promise) {
|
||||||
this.getCommunityByService(properties, url);
|
this.getCommunityByService(properties, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.promise;
|
await this.promise;
|
||||||
this.clearSubscriptions();
|
this.clearSubscriptions();
|
||||||
return this.community.getValue();
|
return this.community.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getCommunityAsObservable() {
|
||||||
|
return this.community.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
setCommunity(community: CommunityInfo) {
|
||||||
|
this.community.next(community);
|
||||||
|
}
|
||||||
|
|
||||||
|
private formalize(element: any) {
|
||||||
|
return HelperFunctions.copy(element);
|
||||||
|
}
|
||||||
|
|
||||||
getCommunityByState(properties: EnvProperties, url: string) {
|
getCommunityByState(properties: EnvProperties, url: string) {
|
||||||
return from(this.getCommunityByStateAsync(properties, url));
|
return from(this.getCommunityByStateAsync(properties, url));
|
||||||
}
|
}
|
||||||
|
|
||||||
getCommunity(properties: EnvProperties, url: string) {
|
getCommunity(properties: EnvProperties, url: string) {
|
||||||
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
|
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
|
||||||
.pipe(map(res => this.parseCommunity(res)));
|
.pipe(map(res => this.parseCommunity(res)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO remove NEW from function names
|
||||||
|
getCommunityNew(communityId: string) {
|
||||||
|
if(!this.community.value || this.community.value.communityId !== communityId) {
|
||||||
|
this.promise = new Promise<any>((resolve, reject) => {
|
||||||
|
this.sub = this.http.get<CommunityInfo>(properties.communityAPI + communityId)
|
||||||
|
.pipe(map(community => this.formalize(this.parseCommunity(community)))).subscribe(community => {
|
||||||
|
this.community.next(community);
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
this.community.next(null);
|
||||||
|
reject();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return from(this.getCommunityAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCommunityAsync() {
|
||||||
|
await this.promise;
|
||||||
|
this.clearSubscriptions();
|
||||||
|
return this.community.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
updateCommunity(url: string, community: any) {
|
updateCommunity(url: string, community: any) {
|
||||||
//const headers = new Headers({'Content-Type': 'application/json'});
|
//const headers = new Headers({'Content-Type': 'application/json'});
|
||||||
//const options = new RequestOptions({headers: headers});
|
//const options = new RequestOptions({headers: headers});
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
headers: new HttpHeaders({
|
headers: new HttpHeaders({
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
const body = JSON.stringify(community);
|
const body = JSON.stringify(community);
|
||||||
return this.http.post(url, body, options);
|
return this.http.post(url, body, options);
|
||||||
/*.map(res => res.json())*/
|
/*.map(res => res.json())*/
|
||||||
}
|
}
|
||||||
|
|
||||||
async isCommunityManagerByStateAsync(properties: EnvProperties, url: string, manager: string) {
|
async isCommunityManagerByStateAsync(properties: EnvProperties, url: string, manager: string) {
|
||||||
if(!this.promise) {
|
if (!this.promise) {
|
||||||
this.getCommunityByService(properties, url);
|
this.getCommunityByService(properties, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.promise;
|
await this.promise;
|
||||||
let community: CommunityInfo = this.community.getValue();
|
let community: CommunityInfo = this.community.getValue();
|
||||||
return (community.managers.indexOf(manager) !== -1);
|
return (community.managers.indexOf(manager) !== -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
isCommunityManagerByState(properties: EnvProperties, url: string, manager: string) {
|
isCommunityManagerByState(properties: EnvProperties, url: string, manager: string) {
|
||||||
return from(this.isCommunityManagerByStateAsync(properties, url, manager));
|
return from(this.isCommunityManagerByStateAsync(properties, url, manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
isCommunityManager(properties: EnvProperties, url: string, manager: string) {
|
isCommunityManager(properties: EnvProperties, url: string, manager: string) {
|
||||||
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
|
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
|
||||||
//.map(res => <any> res.json())
|
//.map(res => <any> res.json())
|
||||||
.pipe(map(res => this.parseCommunity(res)))
|
.pipe(map(res => this.parseCommunity(res)))
|
||||||
.pipe(map(community => community.managers.indexOf(manager) !== -1));
|
.pipe(map(community => community.managers.indexOf(manager) !== -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
async isTypeByStateAsync(properties: EnvProperties, url: string, type: string) {
|
async isTypeByStateAsync(properties: EnvProperties, url: string, type: string) {
|
||||||
if(!this.promise) {
|
if (!this.promise) {
|
||||||
this.getCommunityByService(properties, url);
|
this.getCommunityByService(properties, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.promise;
|
await this.promise;
|
||||||
let community: CommunityInfo = this.community.getValue();
|
let community: CommunityInfo = this.community.getValue();
|
||||||
return (community && community.type && community.type === type);
|
return (community && community.type && community.type === type);
|
||||||
}
|
}
|
||||||
|
|
||||||
isRITypeByState(properties: EnvProperties, url: string) {
|
isRITypeByState(properties: EnvProperties, url: string) {
|
||||||
return from(this.isTypeByStateAsync(properties, url, "ri"));
|
return from(this.isTypeByStateAsync(properties, url, "ri"));
|
||||||
}
|
}
|
||||||
|
|
||||||
isCommunityTypeByState(properties: EnvProperties, url: string) {
|
isCommunityTypeByState(properties: EnvProperties, url: string) {
|
||||||
return from(this.isTypeByStateAsync(properties, url, "community"));
|
return from(this.isTypeByStateAsync(properties, url, "community"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
isRIType(properties: EnvProperties, url: string) {
|
isRIType(properties: EnvProperties, url: string) {
|
||||||
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
|
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
|
||||||
//.map(res => <any> res.json())
|
//.map(res => <any> res.json())
|
||||||
.pipe(map(res => this.parseCommunity(res)))
|
.pipe(map(res => this.parseCommunity(res)))
|
||||||
.pipe(map(community => (community && community.type && community.type === 'ri')));
|
.pipe(map(community => (community && community.type && community.type === 'ri')));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
isCommunityType(properties: EnvProperties, url: string) {
|
isCommunityType(properties: EnvProperties, url: string) {
|
||||||
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
|
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
|
||||||
//.map(res => <any> res.json())
|
//.map(res => <any> res.json())
|
||||||
.pipe(map(res => this.parseCommunity(res)))
|
.pipe(map(res => this.parseCommunity(res)))
|
||||||
.pipe(map(community => (community && community.type && community.type === 'community')));
|
.pipe(map(community => (community && community.type && community.type === 'community')));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
isSubscribedToCommunity(pid: string, email: string, url: string) {
|
isSubscribedToCommunity(pid: string, email: string, url: string) {
|
||||||
return this.http.get(url + '/'+ properties.adminToolsPortalType +'/' + pid + '/subscribers')
|
return this.http.get(url + '/' + properties.adminToolsPortalType + '/' + pid + '/subscribers')
|
||||||
//.map(res => ((<any>res === '') ? {} : <any> res.json()))
|
//.map(res => ((<any>res === '') ? {} : <any> res.json()))
|
||||||
.pipe(map(res => {
|
.pipe(map(res => {
|
||||||
if (res['subscribers'] && res['subscribers'] != null) {
|
if (res['subscribers'] && res['subscribers'] != null) {
|
||||||
|
|
||||||
for (let i = 0; i < res['subscribers'].length; i++ ) {
|
for (let i = 0; i < res['subscribers'].length; i++) {
|
||||||
if (res['subscribers'][i] != null && res['subscribers'][i].email === email) {
|
if (res['subscribers'][i] != null && res['subscribers'][i].email === email) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private parseCommunity(data: any): CommunityInfo {
|
|
||||||
|
|
||||||
const resData = Array.isArray(data) ? data[0] : data;
|
|
||||||
|
|
||||||
const community: CommunityInfo = new CommunityInfo();
|
|
||||||
community['title'] = resData.name;
|
|
||||||
community['shortTitle'] = resData.shortName;
|
|
||||||
community['communityId'] = resData.id;
|
|
||||||
community['queryId'] = resData.queryId;
|
|
||||||
community['logoUrl'] = resData.logoUrl;
|
|
||||||
community['description'] = resData.description;
|
|
||||||
community['date'] = resData.creationDate;
|
|
||||||
community['zenodoCommunity'] = resData.zenodoCommunity;
|
|
||||||
community['status'] = 'all';
|
|
||||||
if (resData.hasOwnProperty('status')) {
|
|
||||||
community['status'] = resData.status;
|
|
||||||
const status = ['all', 'hidden', 'manager'];
|
|
||||||
if (status.indexOf(community['status']) === -1) {
|
|
||||||
community['status'] = 'hidden';
|
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
if (resData.type != null) {
|
|
||||||
community['type'] = resData.type;
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
if (resData.managers != null) {
|
|
||||||
if (community['managers'] === undefined) {
|
|
||||||
community['managers'] = new Array<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
const managers = resData.managers;
|
|
||||||
const length = Array.isArray(managers) ? managers.length : 1;
|
|
||||||
|
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
const manager = Array.isArray(managers) ? managers[i] : managers;
|
|
||||||
community.managers[i] = manager;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resData.subjects != null) {
|
|
||||||
if (community['subjects'] === undefined) {
|
|
||||||
community['subjects'] = new Array<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
const subjects = resData.subjects;
|
|
||||||
const length = Array.isArray(subjects) ? subjects.length : 1;
|
|
||||||
|
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
const subject = Array.isArray(subjects) ? subjects[i] : subjects;
|
|
||||||
community.subjects[i] = subject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return community;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private parseCommunity(data: any): CommunityInfo {
|
||||||
|
|
||||||
|
const resData = Array.isArray(data) ? data[0] : data;
|
||||||
|
|
||||||
|
const community: CommunityInfo = new CommunityInfo();
|
||||||
|
community['title'] = resData.name;
|
||||||
|
community['shortTitle'] = resData.shortName;
|
||||||
|
community['communityId'] = resData.id;
|
||||||
|
community['queryId'] = resData.queryId;
|
||||||
|
community['logoUrl'] = resData.logoUrl;
|
||||||
|
community['description'] = resData.description;
|
||||||
|
community['date'] = resData.creationDate;
|
||||||
|
community['zenodoCommunity'] = resData.zenodoCommunity;
|
||||||
|
community['status'] = 'all';
|
||||||
|
if (resData.hasOwnProperty('status')) {
|
||||||
|
community['status'] = resData.status;
|
||||||
|
const status = ['all', 'hidden', 'manager'];
|
||||||
|
if (status.indexOf(community['status']) === -1) {
|
||||||
|
community['status'] = 'hidden';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resData.type != null) {
|
||||||
|
community['type'] = resData.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resData.managers != null) {
|
||||||
|
if (community['managers'] === undefined) {
|
||||||
|
community['managers'] = new Array<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
const managers = resData.managers;
|
||||||
|
const length = Array.isArray(managers) ? managers.length : 1;
|
||||||
|
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
const manager = Array.isArray(managers) ? managers[i] : managers;
|
||||||
|
community.managers[i] = manager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resData.subjects != null) {
|
||||||
|
if (community['subjects'] === undefined) {
|
||||||
|
community['subjects'] = new Array<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
const subjects = resData.subjects;
|
||||||
|
const length = Array.isArray(subjects) ? subjects.length : 1;
|
||||||
|
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
const subject = Array.isArray(subjects) ? subjects[i] : subjects;
|
||||||
|
community.subjects[i] = subject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return community;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,16 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div [class.uk-invisible]="loadActive || loadPending" class="uk-width-1-5@l uk-width-1-3@m uk-width-1-1 uk-flex uk-flex-right@m uk-flex-center">
|
<div [class.uk-invisible]="loadActive || loadPending"
|
||||||
|
class="uk-width-1-5@l uk-width-1-3@m uk-width-1-1 uk-flex uk-flex-right@m uk-flex-center">
|
||||||
<a *ngIf="exists" class="uk-text-uppercase uk-flex uk-flex-middle" (click)="openInviteModal()">
|
<a *ngIf="exists" class="uk-text-uppercase uk-flex uk-flex-middle" (click)="openInviteModal()">
|
||||||
<button class="uk-icon-button large uk-button-secondary">
|
<button class="uk-icon-button large uk-button-secondary">
|
||||||
<icon name="person_add"></icon>
|
<icon name="person_add"></icon>
|
||||||
</button>
|
</button>
|
||||||
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">Invite {{role}}</button>
|
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">Invite {{role}}</button>
|
||||||
</a>
|
</a>
|
||||||
<a *ngIf="!exists && isPortalAdmin" class="uk-text-uppercase uk-flex uk-flex-middle" (click)="openCreateRoleModal()">
|
<a *ngIf="!exists && isPortalAdmin" class="uk-text-uppercase uk-flex uk-flex-middle"
|
||||||
|
(click)="openCreateRoleModal()">
|
||||||
<button class="uk-icon-button large uk-button-secondary">
|
<button class="uk-icon-button large uk-button-secondary">
|
||||||
<icon name="person_add"></icon>
|
<icon name="person_add"></icon>
|
||||||
</button>
|
</button>
|
||||||
|
@ -32,7 +34,7 @@
|
||||||
<div *ngIf="loadActive || loadPending" class="uk-margin-large-top">
|
<div *ngIf="loadActive || loadPending" class="uk-margin-large-top">
|
||||||
<loading></loading>
|
<loading></loading>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!loadActive && !loadPending" class="uk-margin-medium-top">
|
<div *ngIf="!loadActive && !loadPending">
|
||||||
<div *ngIf="(showActive && active.length == 0) || (!showActive && pending.length == 0)"
|
<div *ngIf="(showActive && active.length == 0) || (!showActive && pending.length == 0)"
|
||||||
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
|
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
|
||||||
<div *ngIf="showActive">No {{role}}s for {{name}}</div>
|
<div *ngIf="showActive">No {{role}}s for {{name}}</div>
|
||||||
|
|
|
@ -8,8 +8,6 @@ import {properties} from "../../../../../environments/environment";
|
||||||
import {Session, User} from "../../../login/utils/helper.class";
|
import {Session, User} from "../../../login/utils/helper.class";
|
||||||
import {UserManagementService} from "../../../services/user-management.service";
|
import {UserManagementService} from "../../../services/user-management.service";
|
||||||
import {Router} from "@angular/router";
|
import {Router} from "@angular/router";
|
||||||
import {LoginErrorCodes} from "../../../login/utils/guardHelper.class";
|
|
||||||
import {Composer} from "../../../utils/email/composer";
|
|
||||||
import {StringUtils} from "../../../utils/string-utils.class";
|
import {StringUtils} from "../../../utils/string-utils.class";
|
||||||
|
|
||||||
declare var UIkit;
|
declare var UIkit;
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {NgModule} from '@angular/core';
|
||||||
import {CommonModule} from '@angular/common';
|
import {CommonModule} from '@angular/common';
|
||||||
import {RoleUsersComponent} from './role-users.component';
|
import {RoleUsersComponent} from './role-users.component';
|
||||||
import {ReactiveFormsModule} from '@angular/forms';
|
import {ReactiveFormsModule} from '@angular/forms';
|
||||||
import {EmailService} from "../../../utils/email/email.service";
|
|
||||||
import {AlertModalModule} from "../../../utils/modal/alertModal.module";
|
import {AlertModalModule} from "../../../utils/modal/alertModal.module";
|
||||||
import {LoadingModule} from "../../../utils/loading/loading.module";
|
import {LoadingModule} from "../../../utils/loading/loading.module";
|
||||||
import {IconsService} from "../../../utils/icons/icons.service";
|
import {IconsService} from "../../../utils/icons/icons.service";
|
||||||
|
@ -15,8 +14,7 @@ import {SafeHtmlPipeModule} from "../../../utils/pipes/safeHTMLPipe.module";
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, AlertModalModule, ReactiveFormsModule, LoadingModule, IconsModule, InputModule, PageContentModule, SafeHtmlPipeModule],
|
imports: [CommonModule, AlertModalModule, ReactiveFormsModule, LoadingModule, IconsModule, InputModule, PageContentModule, SafeHtmlPipeModule],
|
||||||
declarations: [RoleUsersComponent],
|
declarations: [RoleUsersComponent],
|
||||||
exports: [RoleUsersComponent],
|
exports: [RoleUsersComponent]
|
||||||
providers: [EmailService]
|
|
||||||
})
|
})
|
||||||
export class RoleUsersModule {
|
export class RoleUsersModule {
|
||||||
constructor(private iconsService: IconsService) {
|
constructor(private iconsService: IconsService) {
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
<div page-content>
|
||||||
|
<div header>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
<div [class.uk-invisible]="loading" class="uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle uk-grid" uk-grid>
|
||||||
|
<div search-input [control]="filterForm.controls.keyword" [showSearch]="false" placeholder="Search"
|
||||||
|
[bordered]="true" colorClass="uk-text-secondary" toggleTitle="locate subscribers"></div>
|
||||||
|
<div>
|
||||||
|
<a *ngIf="exists" class="uk-text-uppercase uk-flex uk-flex-middle" [class.uk-disabled]="!subscriberInvite || subscriberInvite.loading" (click)="openInviteModal()">
|
||||||
|
<button class="uk-icon-button large uk-button-secondary">
|
||||||
|
<icon name="person_add"></icon>
|
||||||
|
</button>
|
||||||
|
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">Invite Subscribers</button>
|
||||||
|
</a>
|
||||||
|
<a *ngIf="!exists && isPortalAdmin" class="uk-text-uppercase uk-flex uk-flex-middle" (click)="openCreateRoleModal()">
|
||||||
|
<button class="uk-icon-button large uk-button-secondary">
|
||||||
|
<icon name="person_add"></icon>
|
||||||
|
</button>
|
||||||
|
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">Create Group</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div inner>
|
||||||
|
<div *ngIf="loading" class="uk-margin-large-top">
|
||||||
|
<loading></loading>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!loading">
|
||||||
|
<div *ngIf="showSubscribers.length == 0"
|
||||||
|
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
|
||||||
|
<div>No subscribers for {{name}}</div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="showSubscribers.length > 0">
|
||||||
|
<no-load-paging *ngIf="showSubscribers.length > pageSize" [type]="'subscribers'"
|
||||||
|
(pageChange)="updatePage($event)"
|
||||||
|
[page]="page" [pageSize]="pageSize"
|
||||||
|
[totalResults]="showSubscribers.length">
|
||||||
|
</no-load-paging>
|
||||||
|
<div class="uk-margin-medium-top uk-margin-medium-bottom">
|
||||||
|
<div class="uk-card uk-card-default uk-card-body uk-text-small uk-margin-bottom"
|
||||||
|
*ngFor="let item of showSubscribers.slice((page - 1)*pageSize, page*pageSize)">
|
||||||
|
<div class="uk-grid uk-grid-divider uk-flex uk-flex-middle" uk-grid>
|
||||||
|
<div class="uk-width-3-4@l uk-width-1-2@m">
|
||||||
|
<div class="uk-padding-small uk-padding-remove-horizontal">
|
||||||
|
<span class="uk-text-muted">Email: </span>
|
||||||
|
<span class="uk-text-bold">{{item.email}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-width-expand">
|
||||||
|
<div class="uk-padding-small uk-padding-remove-horizontal uk-flex uk-flex-center">
|
||||||
|
<a (click)="openDeleteModal(item)" class="uk-button action uk-flex uk-flex-middle">
|
||||||
|
<icon name="remove_circle_outline" ratio="0.7" [flex]="true"></icon>
|
||||||
|
<span class="uk-margin-small-left">Remove subscriber</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<no-load-paging *ngIf="showSubscribers.length > pageSize" [type]="'subscribers'"
|
||||||
|
(pageChange)="updatePage($event)"
|
||||||
|
[page]="page" [pageSize]="pageSize"
|
||||||
|
[totalResults]="showSubscribers.length">
|
||||||
|
</no-load-paging>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<modal-alert *ngIf="user" #inviteModal (alertOutput)="subscriberInvite.invite()" [okDisabled]="!subscriberInvite.valid" [large]="true">
|
||||||
|
<div class="uk-padding uk-padding-remove-horizontal">
|
||||||
|
<subscriber-invite #subscriberInvite [user]="user"></subscriber-invite>
|
||||||
|
</div>
|
||||||
|
</modal-alert>
|
||||||
|
<modal-alert #deleteModal (alertOutput)="deleteSubscriber()">
|
||||||
|
<div *ngIf="selectedUser" class="uk-padding-small uk-padding-remove-horizontal">
|
||||||
|
Are you sure you want to remove <span class="uk-text-bold">{{selectedUser}}</span> from subscribers?
|
||||||
|
</div>
|
||||||
|
</modal-alert>
|
||||||
|
<modal-alert #createRoleModal (alertOutput)="createGroup()" [okDisabled]="roleFb && roleFb.invalid">
|
||||||
|
<div *ngIf="roleFb" class="uk-padding uk-padding-remove-horizontal">
|
||||||
|
<div class="uk-grid" uk-grid [formGroup]="roleFb">
|
||||||
|
<div dashboard-input [formInput]="roleFb.get('name')"
|
||||||
|
label="Name"
|
||||||
|
placeholder="Write a name..." class="uk-width-1-1"></div>
|
||||||
|
<div dashboard-input [formInput]="roleFb.get('description')"
|
||||||
|
label="Description"
|
||||||
|
type="textarea"
|
||||||
|
placeholder="Write a description..." class="uk-width-1-1"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</modal-alert>
|
|
@ -0,0 +1,184 @@
|
||||||
|
import {Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChild} from '@angular/core';
|
||||||
|
import {Subscription} from 'rxjs/Rx';
|
||||||
|
import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';
|
||||||
|
import {AlertModal} from "../../../utils/modal/alert";
|
||||||
|
import {UserRegistryService} from "../../../services/user-registry.service";
|
||||||
|
import {EnvProperties} from "../../../utils/properties/env-properties";
|
||||||
|
import {properties} from "../../../../../environments/environment";
|
||||||
|
import {Session, User} from "../../../login/utils/helper.class";
|
||||||
|
import {UserManagementService} from "../../../services/user-management.service";
|
||||||
|
import {Router} from "@angular/router";
|
||||||
|
import {Composer} from "../../../utils/email/composer";
|
||||||
|
import {SubscriberInviteComponent} from "../../../sharedComponents/subscriber-invite/subscriber-invite.component";
|
||||||
|
|
||||||
|
declare var UIkit;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'subscribers',
|
||||||
|
templateUrl: 'subscribers.component.html'
|
||||||
|
})
|
||||||
|
export class SubscribersComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
public id: string;
|
||||||
|
@Input()
|
||||||
|
public type: string;
|
||||||
|
@Input()
|
||||||
|
public name: string;
|
||||||
|
@Input()
|
||||||
|
public link: string;
|
||||||
|
@Input()
|
||||||
|
public message: string = null;
|
||||||
|
public user: User = null;
|
||||||
|
public subscribers: any[];
|
||||||
|
public showSubscribers: any[];
|
||||||
|
public subs: any[] = [];
|
||||||
|
public loading: boolean = true;
|
||||||
|
public selectedUser: string = null;
|
||||||
|
public properties: EnvProperties = properties;
|
||||||
|
public exists: boolean = true;
|
||||||
|
public roleFb: FormGroup;
|
||||||
|
/* Paging */
|
||||||
|
page: number = 1;
|
||||||
|
pageSize: number = 10;
|
||||||
|
/* Search */
|
||||||
|
filterForm: FormGroup;
|
||||||
|
@ViewChild('inviteModal') inviteModal: AlertModal;
|
||||||
|
@ViewChild('deleteModal') deleteModal: AlertModal;
|
||||||
|
@ViewChild('createRoleModal') createRoleModal: AlertModal;
|
||||||
|
@ViewChild('subscriberInvite') subscriberInvite: SubscriberInviteComponent;
|
||||||
|
|
||||||
|
constructor(private userRegistryService: UserRegistryService,
|
||||||
|
private userManagementService: UserManagementService,
|
||||||
|
private router: Router,
|
||||||
|
private fb: FormBuilder) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.filterForm = this.fb.group({
|
||||||
|
keyword: this.fb.control('')
|
||||||
|
});
|
||||||
|
this.subs.push(this.filterForm.get('keyword').valueChanges.subscribe(value => {
|
||||||
|
this.filterBySearch(value);
|
||||||
|
}));
|
||||||
|
this.updateList();
|
||||||
|
this.userManagementService.getUserInfo().subscribe(user => {
|
||||||
|
this.user = user;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
if (changes.role) {
|
||||||
|
this.updateList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.subs.forEach(sub => {
|
||||||
|
if (sub instanceof Subscription) {
|
||||||
|
sub.unsubscribe();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateList() {
|
||||||
|
this.loading = true;
|
||||||
|
this.subs.push(this.userRegistryService.getActiveEmail(this.type, this.id, 'member').subscribe(users => {
|
||||||
|
this.subscribers = users;
|
||||||
|
this.filterBySearch(this.filterForm.value.keyword);
|
||||||
|
this.loading = false;
|
||||||
|
this.exists = true;
|
||||||
|
}, error => {
|
||||||
|
this.subscribers = [];
|
||||||
|
this.showSubscribers = [];
|
||||||
|
if (error.status === 404) {
|
||||||
|
this.exists = false;
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
openDeleteModal(item: any) {
|
||||||
|
this.selectedUser = item.email;
|
||||||
|
this.deleteModal.alertTitle = 'Delete subscriber';
|
||||||
|
this.deleteModal.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
openInviteModal() {
|
||||||
|
if(this.subscriberInvite && !this.subscriberInvite.loading) {
|
||||||
|
this.inviteModal.alertTitle = 'Invite users to subscribe';
|
||||||
|
this.inviteModal.okButtonLeft = false;
|
||||||
|
this.inviteModal.okButtonText = 'Send';
|
||||||
|
this.subscriberInvite.reset();
|
||||||
|
this.inviteModal.open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openCreateRoleModal() {
|
||||||
|
this.createRoleModal.alertTitle = 'Create group';
|
||||||
|
this.createRoleModal.okButtonLeft = false;
|
||||||
|
this.createRoleModal.okButtonText = 'create';
|
||||||
|
this.roleFb = this.fb.group({
|
||||||
|
name: this.fb.control(Session.mapType(this.type) + '.' + this.id, Validators.required),
|
||||||
|
description: this.fb.control('', Validators.required)
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
this.roleFb.get('name').disable();
|
||||||
|
}, 0);
|
||||||
|
this.createRoleModal.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSubscriber() {
|
||||||
|
this.loading = true;
|
||||||
|
this.userRegistryService.remove(this.type, this.id, this.selectedUser, 'member').subscribe(() => {
|
||||||
|
this.subscribers = this.subscribers.filter(user => user.email != this.selectedUser);
|
||||||
|
this.filterBySearch(this.filterForm.value.keyword);
|
||||||
|
this.userManagementService.updateUserInfo();
|
||||||
|
UIkit.notification(this.selectedUser + ' <b>is no longer</b> subscribed to ' + this.name + ' Dashboard', {
|
||||||
|
status: 'success',
|
||||||
|
timeout: 6000,
|
||||||
|
pos: 'bottom-right'
|
||||||
|
});
|
||||||
|
this.loading = false;
|
||||||
|
}, error => {
|
||||||
|
UIkit.notification('An error has occurred. Please try again later', {
|
||||||
|
status: 'danger',
|
||||||
|
timeout: 6000,
|
||||||
|
pos: 'bottom-right'
|
||||||
|
});
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createGroup() {
|
||||||
|
this.loading = true;
|
||||||
|
this.roleFb.get('name').enable();
|
||||||
|
this.userRegistryService.createRole(this.type, this.id, this.roleFb.value).subscribe(() => {
|
||||||
|
UIkit.notification('Group has been <b> successfully created</b>', {
|
||||||
|
status: 'success',
|
||||||
|
timeout: 6000,
|
||||||
|
pos: 'bottom-right'
|
||||||
|
});
|
||||||
|
this.updateList();
|
||||||
|
}, error => {
|
||||||
|
UIkit.notification('An error has occurred. Please try again later', {
|
||||||
|
status: 'danger',
|
||||||
|
timeout: 6000,
|
||||||
|
pos: 'bottom-right'
|
||||||
|
});
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isPortalAdmin() {
|
||||||
|
return Session.isPortalAdministrator(this.user) || Session.isCurator(this.type, this.user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public updatePage($event) {
|
||||||
|
this.page = $event.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private filterBySearch(value: any) {
|
||||||
|
this.showSubscribers = this.subscribers.filter(subscriber => !value || subscriber.email.includes(value));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {CommonModule} from '@angular/common';
|
||||||
|
import {SubscribersComponent} from './subscribers.component';
|
||||||
|
import {ReactiveFormsModule} from '@angular/forms';
|
||||||
|
import {AlertModalModule} from "../../../utils/modal/alertModal.module";
|
||||||
|
import {LoadingModule} from "../../../utils/loading/loading.module";
|
||||||
|
import {IconsService} from "../../../utils/icons/icons.service";
|
||||||
|
import {person_add, remove_circle_outline} from "../../../utils/icons/icons";
|
||||||
|
import {IconsModule} from "../../../utils/icons/icons.module";
|
||||||
|
import {InputModule} from "../../../sharedComponents/input/input.module";
|
||||||
|
import {PageContentModule} from "../../sharedComponents/page-content/page-content.module";
|
||||||
|
import {SafeHtmlPipeModule} from "../../../utils/pipes/safeHTMLPipe.module";
|
||||||
|
import {NoLoadPaging} from "../../../searchPages/searchUtils/no-load-paging.module";
|
||||||
|
import {SearchInputModule} from "../../../sharedComponents/search-input/search-input.module";
|
||||||
|
import {SubscriberInviteModule} from "../../../sharedComponents/subscriber-invite/subscriber-invite.module";
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [CommonModule, AlertModalModule, ReactiveFormsModule, LoadingModule, IconsModule, InputModule, PageContentModule, SafeHtmlPipeModule, NoLoadPaging, SearchInputModule, SubscriberInviteModule],
|
||||||
|
declarations: [SubscribersComponent],
|
||||||
|
exports: [SubscribersComponent]
|
||||||
|
})
|
||||||
|
export class SubscribersModule {
|
||||||
|
constructor(private iconsService: IconsService) {
|
||||||
|
this.iconsService.registerIcons([remove_circle_outline, person_add]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,10 @@
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uk-grid-small .left {
|
||||||
|
left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.left + .input-box {
|
.left + .input-box {
|
||||||
padding-left: 41px;
|
padding-left: 41px;
|
||||||
}
|
}
|
||||||
|
@ -23,3 +27,8 @@
|
||||||
.right + .input-box {
|
.right + .input-box {
|
||||||
padding-right: 41px;
|
padding-right: 41px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input-message {
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ export interface Option {
|
||||||
template: `
|
template: `
|
||||||
<div *ngIf="label && type != 'checkbox'" class="uk-text-bold uk-form-label uk-margin-small-bottom">{{label + (required ? ' *' : '')}}</div>
|
<div *ngIf="label && type != 'checkbox'" class="uk-text-bold uk-form-label uk-margin-small-bottom">{{label + (required ? ' *' : '')}}</div>
|
||||||
<div *ngIf="hint" class="uk-margin-bottom uk-text-small uk-form-hint">{{hint}}</div>
|
<div *ngIf="hint" class="uk-margin-bottom uk-text-small uk-form-hint">{{hint}}</div>
|
||||||
<div class="uk-grid uk-flex uk-flex-middle" uk-grid>
|
<div class="uk-grid uk-flex uk-flex-middle" [class.uk-grid-small]="gridSmall" uk-grid>
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
<div [class.uk-hidden]="hideControl" class="uk-width-expand@m uk-position-relative" [class.uk-flex-first]="!extraLeft">
|
<div [class.uk-hidden]="hideControl" class="uk-width-expand uk-position-relative" [class.uk-flex-first]="!extraLeft">
|
||||||
<ng-template [ngIf]="icon && formControl.enabled">
|
<ng-template [ngIf]="icon && formControl.enabled">
|
||||||
<span class="uk-text-muted" [ngClass]="iconLeft?('left'):'right'">
|
<span class="uk-text-muted" [ngClass]="iconLeft?('left'):'right'">
|
||||||
<icon [name]="icon"></icon>
|
<icon [name]="icon"></icon>
|
||||||
|
@ -52,8 +52,9 @@ export interface Option {
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<span *ngIf="formControl.invalid && formControl.errors.error" class="uk-text-small uk-text-danger">{{formControl.errors.error}}</span>
|
<span *ngIf="formControl.invalid && formControl.errors.error" class="uk-text-danger input-message">{{formControl.errors.error}}</span>
|
||||||
<span *ngIf="warning" class="uk-text-small uk-text-warning">{{warning}}</span>
|
<span *ngIf="warning" class="uk-text-warning input-message">{{warning}}</span>
|
||||||
|
<span *ngIf="note" class="input-message">{{note}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<mat-checkbox *ngIf="type === 'checkbox'" [formControl]="formControl">{{label}}</mat-checkbox>
|
<mat-checkbox *ngIf="type === 'checkbox'" [formControl]="formControl">{{label}}</mat-checkbox>
|
||||||
|
@ -70,10 +71,12 @@ export class InputComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
@Input('placeholder') placeholder = '';
|
@Input('placeholder') placeholder = '';
|
||||||
@ViewChild('select') select: MatSelect;
|
@ViewChild('select') select: MatSelect;
|
||||||
@Input() extraLeft: boolean = true;
|
@Input() extraLeft: boolean = true;
|
||||||
|
@Input() gridSmall: boolean = false;
|
||||||
@Input() hideControl: boolean = false;
|
@Input() hideControl: boolean = false;
|
||||||
@Input() icon: string = null;
|
@Input() icon: string = null;
|
||||||
@Input() iconLeft: boolean = false;
|
@Input() iconLeft: boolean = false;
|
||||||
@Input() warning: string = null;
|
@Input() warning: string = null;
|
||||||
|
@Input() note: string = null;
|
||||||
public required: boolean = false;
|
public required: boolean = false;
|
||||||
private initValue: any;
|
private initValue: any;
|
||||||
private subscriptions: any[] = [];
|
private subscriptions: any[] = [];
|
||||||
|
|
|
@ -40,14 +40,14 @@ import {MatAutocompleteTrigger} from '@angular/material/autocomplete';
|
||||||
<span [ngClass]="colorClass" class="icon-bg">
|
<span [ngClass]="colorClass" class="icon-bg">
|
||||||
<icon class="uk-position-center" name="search"></icon>
|
<icon class="uk-position-center" name="search"></icon>
|
||||||
</span>
|
</span>
|
||||||
<span class="uk-text-uppercase overlay">search</span>
|
<span class="uk-text-uppercase overlay">{{toggleTitle}}</span>
|
||||||
</button>
|
</button>
|
||||||
<button [disabled]="loading" class="search uk-flex uk-flex-middle uk-hidden@m"
|
<button [disabled]="loading" class="search uk-flex uk-flex-middle uk-hidden@m"
|
||||||
(mousedown)="$event.preventDefault()" (click)="search()">
|
(mousedown)="$event.preventDefault()" (click)="search()">
|
||||||
<span [ngClass]="colorClass" class="icon-bg">
|
<span [ngClass]="colorClass" class="icon-bg">
|
||||||
<icon class="uk-position-center" name="search"></icon>
|
<icon class="uk-position-center" name="search"></icon>
|
||||||
</span>
|
</span>
|
||||||
<span class="uk-text-uppercase overlay">search</span>
|
<span class="uk-text-uppercase overlay">{{toggleTitle}}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>`
|
</div>`
|
||||||
})
|
})
|
||||||
|
@ -68,6 +68,8 @@ export class SearchInputComponent {
|
||||||
colorClass: string = 'portal-color';
|
colorClass: string = 'portal-color';
|
||||||
@Input()
|
@Input()
|
||||||
bordered: boolean = false;
|
bordered: boolean = false;
|
||||||
|
@Input()
|
||||||
|
toggleTitle: string = 'search';
|
||||||
@ViewChild('input') input: ElementRef;
|
@ViewChild('input') input: ElementRef;
|
||||||
@ViewChild(MatAutocompleteTrigger) trigger: MatAutocompleteTrigger;
|
@ViewChild(MatAutocompleteTrigger) trigger: MatAutocompleteTrigger;
|
||||||
@Output()
|
@Output()
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
.field-label {
|
||||||
|
width: 100px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
import {Component, Input, OnDestroy, OnInit} from "@angular/core";
|
||||||
|
import {AbstractControl, FormBuilder, FormGroup, ValidationErrors, Validators} from "@angular/forms";
|
||||||
|
import {Subscriber} from "rxjs";
|
||||||
|
import {StringUtils} from "../../utils/string-utils.class";
|
||||||
|
import {Email} from "../../utils/email/email";
|
||||||
|
import {Body} from "../../utils/email/body";
|
||||||
|
import {CommunityService} from "../../connect/community/community.service";
|
||||||
|
import {Composer} from "../../utils/email/composer";
|
||||||
|
import {User} from "../../login/utils/helper.class";
|
||||||
|
import {EmailService} from "../../utils/email/email.service";
|
||||||
|
import {properties} from "../../../../environments/environment";
|
||||||
|
|
||||||
|
declare var UIkit;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'subscriber-invite',
|
||||||
|
template: `
|
||||||
|
<div class="uk-grid uk-child-width-1-1" uk-grid [formGroup]="inviteForm">
|
||||||
|
<div dashboard-input [formInput]="inviteForm.get('name')" [gridSmall]="true">
|
||||||
|
<div class="uk-text-bold field-label">
|
||||||
|
From *:
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div dashboard-input [formInput]="inviteForm.get('recipients')" [gridSmall]="true" note="Separate multiple emails with a comma">
|
||||||
|
<div class="uk-text-bold field-label uk-margin-bottom">
|
||||||
|
To *:
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-grid uk-grid-small" uk-grid>
|
||||||
|
<div class="uk-text-bold field-label">
|
||||||
|
Message *:
|
||||||
|
</div>
|
||||||
|
<div class="uk-width-expand">
|
||||||
|
<ckeditor class="form-control" formControlName="message" id="message"
|
||||||
|
debounce="400"
|
||||||
|
[config]="{ extraAllowedContent: '* [uk-*](*) ; span', disallowedContent: 'script; *[on*]', removeButtons: 'Save,NewPage,DocProps,Preview,Print',
|
||||||
|
extraPlugins: 'divarea'}"></ckeditor>
|
||||||
|
<div class="uk-margin-top">
|
||||||
|
{{body.signature}}
|
||||||
|
<span *ngIf="body.fromName == ''" class="uk-text-muted">
|
||||||
|
<i>{{body.fromMessage}}...</i>
|
||||||
|
</span>
|
||||||
|
<span *ngIf="body.fromName !=''">
|
||||||
|
{{body.fromMessage}}
|
||||||
|
<b>{{body.fromName}}</b>
|
||||||
|
</span><br>
|
||||||
|
<a href="https://www.openaire.eu">www.openaire.eu</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
styleUrls: ['subscriber-invite.component.css']
|
||||||
|
})
|
||||||
|
export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
||||||
|
@Input()
|
||||||
|
public user: User;
|
||||||
|
public inviteForm: FormGroup;
|
||||||
|
public email: Email;
|
||||||
|
public body: Body;
|
||||||
|
public loading: boolean = false;
|
||||||
|
private subscriptions: any[] = [];
|
||||||
|
|
||||||
|
constructor(private fb: FormBuilder,
|
||||||
|
private emailService: EmailService,
|
||||||
|
private communityService: CommunityService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsubscribe() {
|
||||||
|
this.subscriptions.forEach(subscription => {
|
||||||
|
if(subscription instanceof Subscriber) {
|
||||||
|
subscription.unsubscribe();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.unsubscribe();
|
||||||
|
this.inviteForm = this.fb.group({
|
||||||
|
name: this.fb.control('', Validators.required),
|
||||||
|
recipients: this.fb.control('', [Validators.required, this.emailsValidator]),
|
||||||
|
message: this.fb.control('', Validators.required)
|
||||||
|
});
|
||||||
|
this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(community => {
|
||||||
|
this.inviteForm.get('name').enable();
|
||||||
|
this.inviteForm.get('name').setValue(this.user.fullname);
|
||||||
|
this.inviteForm.get('name').disable();
|
||||||
|
this.body = Composer.initializeInvitationsBody(community.communityId, community.title, this.user.fullname);
|
||||||
|
this.email = Composer.initializeInvitationsEmail(community.title);
|
||||||
|
this.inviteForm.get('message').setValue(this.body.paragraphs);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
emailsValidator(control: AbstractControl): ValidationErrors | null {
|
||||||
|
if (control.value === '' || !control.value || StringUtils.validateEmails(control.value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return { emails: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
invite() {
|
||||||
|
this.loading = true;
|
||||||
|
this.parseRecipients();
|
||||||
|
this.body.paragraphs = this.inviteForm.value.message;
|
||||||
|
this.email.body = Composer.formatEmailBodyForInvitation(this.body);
|
||||||
|
this.subscriptions.push(this.emailService.sendEmail(properties, this.email).subscribe(res => {
|
||||||
|
if(res['success']) {
|
||||||
|
UIkit.notification('Invitation to subscribe has been <b>sent</b>', {
|
||||||
|
status: 'success',
|
||||||
|
timeout: 6000,
|
||||||
|
pos: 'bottom-right'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
UIkit.notification('An error has occurred. Please try again later', {
|
||||||
|
status: 'danger',
|
||||||
|
timeout: 6000,
|
||||||
|
pos: 'bottom-right'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
},error => {
|
||||||
|
UIkit.notification('An error has occurred. Please try again later', {
|
||||||
|
status: 'danger',
|
||||||
|
timeout: 6000,
|
||||||
|
pos: 'bottom-right'
|
||||||
|
});
|
||||||
|
this.loading = false;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public parseRecipients() {
|
||||||
|
// remove spaces
|
||||||
|
let emails = this.inviteForm.get('recipients').value.replace(/\s/g, '');
|
||||||
|
// remove commas
|
||||||
|
emails = emails.split(",");
|
||||||
|
|
||||||
|
// remove empty fields
|
||||||
|
for (let i = 0; i < emails.length; i++) {
|
||||||
|
if (!(emails[i] == "")) {
|
||||||
|
this.email.recipients.push(emails[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get valid() {
|
||||||
|
return this.inviteForm && this.inviteForm.valid;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import {NgModule} from "@angular/core";
|
||||||
|
import {CommonModule} from "@angular/common";
|
||||||
|
import {SubscriberInviteComponent} from "./subscriber-invite.component";
|
||||||
|
import {InputModule} from "../input/input.module";
|
||||||
|
import {CKEditorModule} from "ng2-ckeditor";
|
||||||
|
import {ReactiveFormsModule} from "@angular/forms";
|
||||||
|
import {EmailService} from "../../utils/email/email.service";
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [CommonModule, InputModule, CKEditorModule, ReactiveFormsModule],
|
||||||
|
declarations: [SubscriberInviteComponent],
|
||||||
|
exports: [SubscriberInviteComponent],
|
||||||
|
providers: [EmailService]
|
||||||
|
})
|
||||||
|
export class SubscriberInviteModule {
|
||||||
|
|
||||||
|
}
|
|
@ -242,4 +242,23 @@ export class Composer {
|
||||||
email.recipient = recipient;
|
email.recipient = recipient;
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static composeEmailForCommunityDashboard(name: string, recipient: string, role: "manager" | "member") {
|
||||||
|
let email: Email = new Email();
|
||||||
|
email.subject = 'OpenAIRE Monitor Dashboard | ' + name;
|
||||||
|
email.body = '<p>Dear ((__user__)),</p>' +
|
||||||
|
'<p>You have been invited to be a ' + role +' of the OpenAIRE Monitor Dashboard for the ' + name + '.</p>' +
|
||||||
|
'<p>Click <a href="((__link__))">this URL</a> and use the verification code below to accept the invitation.</p>' +
|
||||||
|
'<p>The verification code is <b>((__code__))</b>.</p>' +
|
||||||
|
(role === "manager"?
|
||||||
|
'<p>As a manager of the OpenAIRE Monitor Dashboard, you will have access to the administration part of the dashboard, ' +
|
||||||
|
'where you will be able to customize and manage the profile of the ' + name + '.</p>':
|
||||||
|
'<p>As a member of the OpenAIRE Monitor Dashboard, you will have access to the restricted access areas of the profile for the ' + name + '.') +
|
||||||
|
'<p>Please contact us at <a href="mailto:' + properties.helpdeskEmail+'">' + properties.helpdeskEmail +
|
||||||
|
'</a> if you have any questions or concerns.</p>' +
|
||||||
|
'<p>Kind Regards<br>The OpenAIRE Team</p>' +
|
||||||
|
'<p><a href="' + properties.domain + '">OpenAIRE Monitor</a></p>'
|
||||||
|
email.recipient = recipient;
|
||||||
|
return email;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {UrlSegment} from '@angular/router';
|
import {UrlSegment} from '@angular/router';
|
||||||
import {ValidatorFn, Validators} from "@angular/forms";
|
import {AbstractControl, ValidatorFn, Validators} from "@angular/forms";
|
||||||
|
|
||||||
export class Dates {
|
export class Dates {
|
||||||
public static yearMin = 1800;
|
public static yearMin = 1800;
|
||||||
|
@ -214,6 +214,12 @@ export class StringUtils {
|
||||||
return decodeURIComponent(params);
|
return decodeURIComponent(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static validateEmails(emails: string): boolean {
|
||||||
|
return (emails.split(',')
|
||||||
|
.map(email => Validators.email(<AbstractControl>{ value: email.trim() }))
|
||||||
|
.find(_ => _ !== null) === undefined);
|
||||||
|
}
|
||||||
|
|
||||||
public static b64DecodeUnicode(str) {
|
public static b64DecodeUnicode(str) {
|
||||||
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
|
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
|
||||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
||||||
|
|
Loading…
Reference in New Issue