[Trunk|Admin]: 1. Add properties for delete and download url. 2. Add a new module for sticky ok and cancel button. 3. Add new page for curator edit personal info.

git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-admin-portal/trunk@55946 d315682c-612b-4755-9ff5-7f18f6832af3
This commit is contained in:
k.triantafyllou 2019-06-02 18:55:56 +00:00
parent c168efa0f8
commit 6099d02f2e
9 changed files with 548 additions and 3 deletions

View File

@ -168,6 +168,12 @@ export class AppComponent implements OnInit{
items: [],
ukIcon: 'home'
});
this.sideMenuItems.push({
rootItem: new MenuItem('personalInfo', 'Personal Info', '/personal',
'/personal', false, [], [], {communityId: this.communityId}),
items: [],
ukIcon: 'user'
});
if (this.isPortalAdministrator) {
const adminTools: SideMenuItem = {
rootItem: new MenuItem('adminTools', 'Admin Tools', '/communities',

View File

@ -28,6 +28,11 @@ const appRoutes: Routes = [
loadChildren: './pages/usernotifications/manage-user-notifications.module#ManageUserNotificationsModule',
resolve: {envSpecific: EnvironmentSpecificResolver}
},
{
path: 'personal',
loadChildren: './pages/curator/curator.module#CuratorModule',
resolve: { envSpecific: EnvironmentSpecificResolver }
},
{
path: 'communities',
loadChildren: './pages/community/communities.module#CommunitiesModule',

View File

@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {RouterModule} from '@angular/router';
import {CuratorComponent} from './curator.component';
import {IsCommunity} from '../../openaireLibrary/connect/communityGuard/isCommunity.guard';
import {ConnectAdminLoginGuard} from '../../openaireLibrary/connect/communityGuard/connectAdminLoginGuard.guard';
@NgModule({
imports: [
RouterModule.forChild([
{ path: '', canActivate: [IsCommunity, ConnectAdminLoginGuard], component: CuratorComponent}
])
]
})
export class CuratorRoutingModule { }

View File

@ -0,0 +1,134 @@
<div class="uk-padding uk-padding-remove-top uk-text-large uk-text-center uk-width">Edit Personal Info</div>
<div class="uk-flex uk-grid-divider" uk-grid>
<div *ngIf="showLoading" class="uk-animation-fade uk-width-1-1" role="alert">
<span class="loading-gif uk-align-center"></span>
</div>
<table *ngIf="curatorId != null && curator != null && !showLoading" class="uk-width-1-2 uk-align-center">
<tbody class="uk-table uk-align-center">
<tr *ngIf="curator.email != null" >
<td for="email" class="uk-text-bold uk-text-right">E-mail:</td>
<td class="uk-text-left">
{{curator.email}}
</td>
</tr>
<tr *ngIf="curator.name != null">
<td for="name" class="uk-text-bold uk-text-right">
Name
<span class="uk-text-danger uk-text-bold">
*
</span>
:
</td>
<td class="uk-text-left">
<div *ngIf="!curator.name || curator.name === ''" class=" uk-text-danger uk-text-small style=display:none"> Please add name. </div>
<input type="text"
class="form-control uk-input uk-width-large@l uk-width-medium@s" id="name"
[(ngModel)]="curator.name" (input)="onNameChange()" #name="ngModel" required>
</td>
</tr>
<tr *ngIf="photo != null">
<td for="photo" class="uk-text-bold uk-align-right">Photo:</td>
<td class="uk-text-left">
<div class="uk-flex uk-flex-middle">
<div class="uk-width-1-3">
<img class="uk-border-circle curator-photo" src="{{photo}}" alt="Curator Photo">
</div>
<div uk-form-custom>
<input id="photo" type="file" (change)="fileChangeEvent($event)" (input)="change()"/>
<button class="uk-button portal-button" type="button" tabindex="-1">
Update your photo
</button>
</div>
</div>
</td>
</tr>
<tr *ngIf="curator.bio != null">
<td for="bio" class="uk-text-bold uk-text-right">Biography:</td>
<td class="uk-text-left">
<textarea placeholder={{curator.bio}} type="text"
class="form-control uk-textarea uk-width-large@l uk-width-medium@s" rows="6"
id="bio"
[(ngModel)]="curator.bio"
(input)="change()">
</textarea>
</td>
</tr>
<tr *ngIf="curator.bio != null">
<td class="uk-text-right"></td>
<td class="uk-text-left">
<div class="uk-text-danger uk-text-bold">
* Required fields
</div>
</td>
</tr>
<tr>
<td class="uk-text-right"></td>
<td>
<div *ngIf="updateErrorMessage" class="uk-alert uk-alert-danger" role="alert">{{updateErrorMessage}}</div>
<div *ngIf="warning" class="uk-alert uk-alert-warning" role="alert">{{warning}}</div>
<div *ngIf="successfulSaveMessage" class="uk-alert uk-alert-success" role="alert">{{successfulSaveMessage}}</div>
<div *ngIf="successfulResetMessage" class="uk-alert uk-alert-warning" role="alert">{{successfulResetMessage}}</div>
</tr>
</tbody>
</table>
<div *ngIf="curatorId != null && curator != null && !showLoading" class="uk-width-1-2">
<div class="uk-margin uk-flex uk-flex-middle" uk-grid>
<h3 class="uk-h3 uk-width-2-5">My Affiliations
</h3>
<div class="uk-width-expand ">
<button class="uk-button portal-button uk-align-right" (click)="initAffiliation()">
<span uk-icon="plus"></span>
Add new Affiliation
</button>
</div>
</div>
<ul class="uk-list uk-list-divider uk-margin uk-height-max-large uk-overflow-auto">
<li *ngFor="let result of curator.affiliations; let i=index" class="uk-animation-fade uk-margin-auto uk-height-small uk-flex uk-flex-middle" uk-grid>
<div class="uk-width-1-5 uk-card uk-card-default uk-card-body affiliation-card uk-inline">
<img class="uk-border-rounded uk-position-center" src="{{result.logoUrl}}" width="80" height="80" alt="{{result.name}}">
</div>
<div class="uk-width-3-5">
<h3 class="uk-h3">{{result.name}}</h3>
<a href="{{result.websiteUrl}}" class="uk-margin-auto-top">{{result.websiteUrl}}</a>
</div>
<div class="uk-width-1-5 uk-card">
<button class="uk-icon-button uk-icon uk-button-secondary" title="Edit" uk-icon="pencil" (click)="chooseAffiliation(i, 'edit')"></button>
<button class="uk-icon-button uk-icon uk-button-danger" title="Remove" uk-icon="minus" (click)="chooseAffiliation(i)"></button>
</div>
</li>
</ul>
</div>
</div>
<sticky [enabled]="hasChanged && !!enabled" (save)="updateCurator()" (cancel)="resetForm()"></sticky>
<modal-alert #affiliationModal [okDisabled]="isEmptyAffiliation()" (alertOutput)="addAffiliation()">
<table>
<tbody class="uk-table uk-align-center">
<tr>
<td for="name" class="uk-text-bold uk-text-right">Name:</td>
<td class="uk-text-left">
<input type="text"
class="form-control uk-input uk-width-large@l uk-width-medium@s" id="afname"
[(ngModel)]="affiliation.name" >
</td>
</tr>
<tr>
<td for="name" class="uk-text-bold uk-text-right">Logo Url:</td>
<td class="uk-text-left">
<input type="text"
class="form-control uk-input uk-width-large@l uk-width-medium@s" id="logourl"
[(ngModel)]="affiliation.logoUrl">
</td>
</tr>
<tr>
<td for="name" class="uk-text-bold uk-text-right">Website Url:</td>
<td class="uk-text-left">
<input type="text"
class="form-control uk-input uk-width-large@l uk-width-medium@s" id="websiteurl"
[(ngModel)]="affiliation.websiteUrl">
</td>
</tr>
</tbody>
</table>
</modal-alert>
<modal-alert #removeAffiliationModal [okDisabled]="isEmptyAffiliation()" (alertOutput)="removeAffiliation()">
</modal-alert>

View File

@ -0,0 +1,303 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {EnvProperties} from '../../openaireLibrary/utils/properties/env-properties';
import {Session} from '../../openaireLibrary/login/utils/helper.class';
import {LoginErrorCodes} from '../../openaireLibrary/login/utils/guardHelper.class';
import {CuratorService} from '../../openaireLibrary/connect/curators/curator.service';
import {Affiliation, Curator} from '../../openaireLibrary/utils/entities/CuratorInfo';
import {HelperFunctions} from '../../openaireLibrary/utils/HelperFunctions.class';
import {AlertModal} from '../../openaireLibrary/utils/modal/alert';
import {CuratorPhotoService} from '../../openaireLibrary/services/curatorPhoto.service';
@Component({
selector: 'curator',
templateUrl: './curator.component.html',
})
export class CuratorComponent implements OnInit {
@ViewChild('affiliationModal') affiliationModal: AlertModal;
@ViewChild('removeAffiliationModal') removeAffiliationModal: AlertModal;
public showLoading = true;
public updateErrorMessage = '';
public warning = '';
public successfulSaveMessage = '';
public successfulResetMessage = '';
public hasChanged = false;
public curatorId = null;
public curator: Curator = null;
public affiliation: Affiliation = new Affiliation();
public photo: any = null;
public properties: EnvProperties = null;
private file: File = null;
private enabled = true;
private index = 0;
constructor(private element: ElementRef,
private route: ActivatedRoute,
private _router: Router,
private curatorService: CuratorService,
private curatorPhotoService: CuratorPhotoService) {
}
ngOnInit() {
this.route.data.subscribe((data: { envSpecific: EnvProperties }) => {
this.properties = data.envSpecific;
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {'errorCode': LoginErrorCodes.NOT_VALID, 'redirectUrl': this._router.url}
});
} else {
this.showLoading = true;
this.updateErrorMessage = '';
this.warning = '';
this.curatorId = Session.getUser().id;
this.curatorService.getCurator(this.properties,
this.properties.adminToolsAPIURL + 'curator/' + this.curatorId).subscribe(
curator => {
if (curator) {
this.curator = curator;
this.curator.email = Session.getUserEmail();
if (this.curator.photo) {
this.photo = this.properties.downloadUrl + '/' + this.curator.photo;
} else {
this.photo = '../../../assets/common-assets/curator-default.png';
}
this.showLoading = false;
HelperFunctions.scroll();
}
},
error => {
this.curator = new Curator();
this.curator._id = this.curatorId;
this.curator.email = Session.getUserEmail();
this.curator.name = Session.getUserFullName();
this.curator.affiliations = [];
this.curator.bio = '';
this.curator.photo = null;
this.handleWarning('No personal info has been found!');
this.photo = '../../../assets/common-assets/curator-default.png';
this.showLoading = false;
HelperFunctions.scroll();
}
);
}
});
}
initAffiliation(affiliation: Affiliation = null) {
this.affiliation = new Affiliation();
if (affiliation) {
this.affiliation.name = affiliation.name;
this.affiliation.logoUrl = affiliation.logoUrl;
this.affiliation.websiteUrl = affiliation.websiteUrl;
this.affiliationModal.okButtonText = 'Edit Affiliation';
} else {
this.index = -1;
this.affiliationModal.okButtonText = 'Add new Affiliation';
}
this.affiliationModal.okButtonLeft = false;
this.affiliationModal.open();
}
public resetForm() {
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams:
{'errorCode': LoginErrorCodes.NOT_VALID, 'redirectUrl': this._router.url}
});
} else {
if (this.curatorId != null && this.curatorId !== '') {
this.showLoading = true;
this.updateErrorMessage = '';
this.warning = '';
this.curatorService.getCurator(this.properties,
this.properties.adminToolsAPIURL + 'curator/' + this.curatorId).subscribe(
curator => {
if (curator) {
this.curator = curator;
this.curator.email = Session.getUserEmail();
this.handleSuccessfulReset('Your Personal Info has been reset!');
if (this.curator.photo) {
this.photo = this.properties.downloadUrl + '/' + this.curator.photo;
} else {
this.photo = '../../../assets/common-assets/curator-default.png';
}
this.showLoading = false;
HelperFunctions.scroll();
}
},
error => {
this.curator = new Curator();
this.curator._id = this.curatorId;
this.curator.email = Session.getUserEmail();
this.curator.name = Session.getUserFullName();
this.curator.affiliations = [];
this.curator.bio = '';
this.curator.photo = null;
this.handleWarning('No personal info has been found!');
this.photo = '../../../assets/common-assets/curator-default.png';
this.showLoading = false;
HelperFunctions.scroll();
}
);
}
this.resetChange();
}
}
private change() {
this.hasChanged = true;
}
private resetChange() {
this.hasChanged = false;
}
private resetMessages() {
this.successfulSaveMessage = '';
this.successfulResetMessage = '';
this.updateErrorMessage = '';
}
public chooseAffiliation(index: number, action: string = 'delete') {
this.index = index;
const affiliation: Affiliation = this.curator.affiliations[index];
if (action === 'delete') {
this.removeAffiliationModal.message = 'Do you want to remove ' +
affiliation.name + ' from your Affiliations?';
this.removeAffiliationModal.okButtonText = 'Yes';
this.removeAffiliationModal.cancelButtonText = 'No';
this.removeAffiliationModal.open();
} else if (action === 'edit') {
this.initAffiliation(affiliation);
}
}
handleUpdateError(message: string, error) {
this.resetMessages();
this.updateErrorMessage = message;
console.log('Server responded: ' + error);
this.showLoading = false;
}
handleWarning(message: string) {
this.warning = message;
this.showLoading = false;
HelperFunctions.scroll();
}
handleSuccessfulSave(message) {
this.resetMessages();
this.showLoading = false;
HelperFunctions.scroll();
this.successfulSaveMessage = message;
}
handleSuccessfulReset(message) {
this.resetMessages();
this.showLoading = false;
HelperFunctions.scroll();
this.successfulResetMessage = message;
}
fileChangeEvent(event) {
this.showLoading = true;
if (event.target.files && event.target.files[0]) {
this.file = event.target.files[0];
if (this.file.type !== 'image/png' && this.file.type !== 'image/jpeg') {
this.handleUpdateError('You must choose a photo!', null);
this.file = null;
} else {
this.updateErrorMessage = '';
const reader = new FileReader();
reader.readAsDataURL(this.file);
reader.onload = () => {
this.photo = reader.result;
this.showLoading = false;
HelperFunctions.scroll();
};
}
}
}
updateCurator() {
if (this.hasChanged && this.curator && this.curator.name && this.curator.name !== '') {
this.showLoading = true;
if (this.file) {
this.curatorPhotoService.uploadPhoto(this.properties.uploadService + '/' + this.curator._id, this.file).subscribe((res) => {
if (this.curator.photo && this.curator.photo !== '') {
this.curatorPhotoService.deletePhoto(this.properties.deleteUrl + '/' + this.curator.photo).subscribe();
}
this.curator.photo = res.filename;
this.curatorService.updateCurator(this.properties.adminToolsAPIURL + 'curator',
this.curator).subscribe((curator) => {
if (curator) {
this.handleSuccessfulSave('Your data has been saved successfully!');
this.resetChange();
}
},
error => {
this.handleUpdateError('An error has occurred. Try again later!', error);
this.resetChange();
});
}, error => {
this.handleWarning('An error has occurred during photo uploading.');
}
);
} else {
this.curatorService.updateCurator(this.properties.adminToolsAPIURL + 'curator',
this.curator).subscribe((curator) => {
if (curator) {
this.handleSuccessfulSave('Your data has been saved successfully!');
this.resetChange();
}
},
error => {
this.handleUpdateError('An error has occurred. Try again later!', error);
this.resetChange();
});
}
}
}
isEmptyAffiliation(): boolean {
return ((!this.affiliation.name || this.affiliation.name === '') &&
(!this.affiliation.logoUrl || this.affiliation.logoUrl === '') &&
(!this.affiliation.websiteUrl || this.affiliation.websiteUrl === ''));
}
addAffiliation() {
if (!this.isEmptyAffiliation()) {
if (this.index === -1) {
this.curator.affiliations.push(this.affiliation);
} else {
this.curator.affiliations[this.index] = this.affiliation;
}
this.change();
}
}
removeAffiliation() {
this.curator.affiliations.splice(this.index, 1);
this.change();
}
onNameChange() {
this.hasChanged = true;
if (!this.curator.name || this.curator.name === '') {
this.enabled = false;
} else {
this.enabled = true;
}
}
}

View File

@ -0,0 +1,32 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {RouterModule} from '@angular/router';
import {CuratorComponent} from './curator.component';
import {CuratorRoutingModule} from './curator-routing.module';
import {IsCommunity} from '../../openaireLibrary/connect/communityGuard/isCommunity.guard';
import {ConnectAdminLoginGuard} from '../../openaireLibrary/connect/communityGuard/connectAdminLoginGuard.guard';
import {CuratorService} from '../../openaireLibrary/connect/curators/curator.service';
import {AlertModalModule} from '../../openaireLibrary/utils/modal/alertModal.module';
import {StickyModule} from '../../utils/stickyButton/sticky.module';
import {CuratorPhotoService} from '../../openaireLibrary/services/curatorPhoto.service';
@NgModule({
imports: [
CuratorRoutingModule, CommonModule, FormsModule, RouterModule,
AlertModalModule, StickyModule
],
declarations: [
CuratorComponent
],
providers: [
CuratorService, CuratorPhotoService, IsCommunity, ConnectAdminLoginGuard
],
exports: [
CuratorComponent
]
})
export class CuratorModule { }

View File

@ -0,0 +1,30 @@
import {Component, EventEmitter, Input, Output} from '@angular/core';
@Component({
selector: 'sticky',
template: `
<div class="uk-float-right" style="z-index: 100; bottom: 10%; position: fixed; right: 2%">
<button class="uk-button" (click)="onCancel()">Cancel</button>
<button *ngIf="enabled" class="uk-button uk-button-primary" (click)="onSave()">Save</button>
<button *ngIf="!enabled" class="uk-button uk-button-default" disabled>Save</button>
</div>
`
})
export class StickyComponent {
@Output() public save: EventEmitter<any> = new EventEmitter();
@Output() public cancel: EventEmitter<any> = new EventEmitter();
@Input() public enabled: boolean;
constructor () {}
public onSave() {
this.save.emit(true);
}
public onCancel() {
this.cancel.emit(true);
}
}

View File

@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { CommonModule} from '@angular/common';
import { FormsModule } from '@angular/forms';
import {StickyComponent} from './sticky.component';
@NgModule({
imports: [
CommonModule,
FormsModule
],
declarations: [
StickyComponent
],
exports: [
StickyComponent
]
})
export class StickyModule { }

View File

@ -8,7 +8,7 @@
"claimsAPIURL" : "http://scoobydoo.di.uoa.gr:8080/dnet-claims-service-2.0.0-SNAPSHOT/rest/claimsService/",
"statisticsAPIURL" : "https://beta.services.openaire.eu/stats-api/",
"statisticsFrameAPIURL":"https://beta.openaire.eu/stats/",
"searchAPIURLLAst" : "https://beta.services.openaire.eu/search/v2/api/",
"searchAPIURLLAst" : "https://beta.services.openaire.eu/search/v2/api/",
"searchResourcesAPIURL" : "https://beta.services.openaire.eu/search/v2/api/resources",
"openCitationsAPIURL" : "https://services.openaire.eu/opencitations/getCitations?id=",
"csvAPIURL" : "http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2/reports",
@ -28,7 +28,9 @@
"h2020Guidlines" : "https://www.openaire.eu/oa-publications/h2020/open-access-in-horizon-2020",
"ercGuidlines" : "http://erc.europa.eu/sites/default/files/document/file/ERC_Open_Access_Guidelines-revised_2014.pdf",
"helpdesk" : "https://www.openaire.eu/support/helpdesk",
"uploadService" : "http://scoobydoo.di.uoa.gr:8000/upload",
"uploadService" : "http://mpagasas.di.uoa.gr:8000/upload",
"downloadUrl" : "http://mpagasas.di.uoa.gr:8000/download",
"deleteUrl" : "http://mpagasas.di.uoa.gr:8000/delete",
"vocabulariesAPI" :"https://beta.services.openaire.eu/provision/mvc/vocabularies/",
@ -49,7 +51,7 @@
"cacheUrl" :"http://scoobydoo.di.uoa.gr:3000/get?url=",
"adminToolsAPIURL" :"http://duffy.di.uoa.gr:8080/uoa-admin-tools/",
"adminToolsAPIURL" :"http://mpagasas.di.uoa.gr:8080/uoa-admin-tools/",
"adminToolsCommunity" :"openaire",
"communityAPI": "https://dev-openaire.d4science.org/openaire/community/",