Add indicators page for monitor. Add tooltip in page/class content form and change container size. Add parentClass parame in theme page in order to view a specific style. Change admin login guard in order to allow curators to have access in some pages. Enable isPageEnabled method in configuration page in order to check if a specific page in specific portal isEnabled.

This commit is contained in:
Konstantinos Triantafyllou 2022-07-27 12:34:10 +03:00
parent 3eba038893
commit e04d825c03
12 changed files with 1005 additions and 950 deletions

View File

@ -13,7 +13,7 @@
</div>
</div>
<div actions>
<div class="uk-section-xsmall uk-container uk-container-small">
<div class="uk-section-xsmall uk-container">
<div class="uk-flex uk-flex-center uk-flex-right@m">
<button class="uk-button uk-button-default uk-margin-right"
(click)="resetCustom()" [class.uk-disabled]="!myForm.dirty"
@ -26,7 +26,7 @@
</div>
</div>
<div inner>
<div class="uk-container uk-container-small">
<div class="uk-container">
<div *ngIf="myForm" style="min-height: 60vh"
class="uk-section uk-section-small uk-position-relative">
<div *ngIf="showLoading" class="uk-position-center">
@ -38,28 +38,35 @@
<span class="uk-text-bold uk-margin-small-right">Select Status (Enable/ disable)</span>
<mat-slide-toggle [checked]="myForm.get('isActive').value"
(change)="changeStatus()"
uk-tooltip="title:<div class='uk-padding-small uk-width-large'><div class='uk-text-bold '> Enable or disable help text to show or hide it from the dashboard</div></div>"
uk-tooltip="title:<div><div class='uk-text-bold'> Enable or disable help text to show or hide it from the dashboard</div></div>"
></mat-slide-toggle>
</div>
<div class="form-group uk-margin-large-top"
[ngClass]="{'has-error':!myForm.controls.content.valid &&
myForm.controls.content.dirty}" >
<div class="uk-text-bold uk-margin-bottom">Content</div>
<div>
<div class="uk-text-bold uk-margin-bottom uk-flex uk-flex-middle">
<span class="uk-margin-small-right">Content</span>
<button class="uk-button uk-button-link uk-text-normal"><icon name="info" type="outlined" [flex]="true"></icon></button>
<div class="uk-dropdown uk-text-normal uk-width-medium uk-padding-small" uk-dropdown>
OpenAIRE style guide is based on <a href="https://getuikit.com/docs/introduction" target="_blank" class="uk-link custom-external">UIKit</a>.
You can find some usage examples <a routerLink="/theme" [queryParams]="parentClass?{parentClass: parentClass}:null" target="_blank" class="uk-link custom-external">here</a>
in order to style your content.
</div>
</div>
<div [ngClass]="parentClass">
<ckeditor (change)="contentChanged()"
[readonly]="false"
debounce="500"
[formControl]="myForm.get('content')"
formControlName="content"
[config]="{ extraAllowedContent: '* [uk-*](*) ; span', disallowedContent: 'script; *[on*]',
removeButtons: 'Save,NewPage,DocProps,Preview,Print,' +
'Form,Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField,' +
'CreateDiv,Flash,PageBreak,' +
'Subscript,Superscript,Anchor,Smiley,Iframe,Styles,Font,About,Language',
extraPlugins: 'divarea'}">
extraPlugins: 'divarea', height: 500}">
</ckeditor>
</div>
</div>
<input type="hidden" formControlName="_id">
</form>
</div>
</div>

View File

@ -18,6 +18,7 @@ export class ClassContentFormComponent implements OnInit {
myForm: FormGroup;
portal: string;
parentClass: string;
pageId: string;
pageContentId: string;
page: Page;
@ -32,8 +33,8 @@ export class ClassContentFormComponent implements OnInit {
}
ngOnInit() {
this.subs.push(this.route.params.subscribe(params => {
this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param];
this.parentClass = this.route.snapshot.data.parentClass;
this.subs.push(this.route.queryParams.subscribe(params => {
this.pageId = params['pageId'];
this.myForm = this.form;
@ -43,7 +44,6 @@ export class ClassContentFormComponent implements OnInit {
}
this.getInfo(this.pageId);
}));
}));
}
ngOnDestroy() {

View File

@ -13,7 +13,7 @@
</div>
</div>
<div actions>
<div class="uk-section-xsmall uk-container uk-container-small">
<div class="uk-section-xsmall uk-container">
<div class="uk-flex uk-flex-center uk-flex-right@m">
<button class="uk-button uk-button-default uk-margin-right"
(click)="resetCustom()" [class.uk-disabled]="!myForm.dirty"
@ -26,7 +26,7 @@
</div>
</div>
<div inner>
<div class="uk-container uk-container-small">
<div class="uk-container">
<div *ngIf="myForm" style="min-height: 60vh"
class="uk-section uk-section-small uk-position-relative">
<div *ngIf="showLoading" class="uk-position-center">
@ -48,23 +48,29 @@
<div class="form-group uk-margin-large-top"
[ngClass]="{'has-error':!myForm.controls.content.valid &&
myForm.controls.content.dirty}">
<div class="uk-text-bold uk-margin-bottom">Content</div>
<div>
<div class="uk-text-bold uk-margin-bottom uk-flex uk-flex-middle">
<span class="uk-margin-small-right">Content</span>
<button class="uk-button uk-button-link uk-text-normal"><icon name="info" type="outlined" [flex]="true"></icon></button>
<div class="uk-dropdown uk-text-normal uk-width-medium uk-padding-small" uk-dropdown>
OpenAIRE style guide is based on <a href="https://getuikit.com/docs/introduction" target="_blank" class="uk-link custom-external">UIKit</a>.
You can find some usage examples <a routerLink="/theme" [queryParams]="parentClass?{parentClass: parentClass}:null" target="_blank" class="uk-link custom-external">here</a>
in order to style your content.
</div>
</div>
<div [ngClass]="parentClass">
<ckeditor (change)="contentChanged()"
[readonly]="false"
debounce="500"
[formControl]="myForm.get('content')"
formControlName="content"
[config]="{ extraAllowedContent: '* [uk-*](*) ; span', disallowedContent: 'script; *[on*]',
removeButtons: 'Save,NewPage,DocProps,Preview,Print,' +
'Form,Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField,' +
'CreateDiv,Flash,PageBreak,' +
'Subscript,Superscript,Anchor,Smiley,Iframe,Styles,Font,About,Language',
extraPlugins: 'divarea'}">
extraPlugins: 'divarea', height: 500}">
</ckeditor>
</div>
</div>
<input type="hidden" formControlName="_id">
</form>
</div>
</div>

View File

@ -19,6 +19,7 @@ export class PageContentFormComponent implements OnInit {
myForm: FormGroup;
portal: string;
parentClass: string;
pageId: string;
pageContentId: string;
page: Page;
@ -34,8 +35,8 @@ export class PageContentFormComponent implements OnInit {
}
ngOnInit() {
this.subs.push(this.route.params.subscribe(params => {
this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param];
this.parentClass = this.route.snapshot.data.parentClass;
this.subs.push(this.route.queryParams.subscribe(params => {
HelperFunctions.scroll();
this.pageId = params['pageId'];
@ -46,7 +47,6 @@ export class PageContentFormComponent implements OnInit {
}
this.getInfo(this.pageId);
}));
}));
}
ngOnDestroy() {
@ -86,47 +86,6 @@ export class PageContentFormComponent implements OnInit {
}
/*private getPage(pageId: string) {
this.subs.push(this._helpContentService.getPageByPortal(pageId,this.properties.adminToolsAPIURL, this.communityPid).subscribe(
page => {
if(this.properties.adminToolsPortalType != page.portalType) {
this._router.navigate(['../'], {relativeTo: this.route});
} else {
this.page = page;
this.getPageContents(pageId);
}
},
error => this.handleError('System error retrieving page with id: '+pageId, error)
));
}
private getPageContents(pageId: string) {
this.subs.push(this._helpContentService.getCommunityPageHelpContents(this.communityPid, this.properties.adminToolsAPIURL).subscribe(
pageHelpContents => {
let countPageContents = 1;
for (let content of (pageHelpContents as Array<PageHelpContent>)) {
if(content.page['_id'] == pageId){
countPageContents++;
}
}
this.setOptions(this.page, countPageContents);
if(!this.pageContentId) {
this.showLoading = false;
this.initFormWithSelectOptions();
}
},
error => this.handleError('System error retrieving page contents with id: ', error)
));
}
private getPageHelpContent(pageContentId: string) {
this.showLoading = true;
this.subs.push(this._helpContentService.getPageHelpContent(pageContentId as string, this.properties.adminToolsAPIURL, this.communityPid).subscribe(
pageHelpContent => {
this.updateForm(pageHelpContent);
this.showLoading = false;
},
error => this.handleError('System error retrieving page help content', error)));
}*/
private updateForm(pageHelpContent: PageHelpContent) {
this.pageHelpContent = pageHelpContent;
this.myForm = this.form;
@ -228,10 +187,6 @@ export class PageContentFormComponent implements OnInit {
}
}
public cancelCustom() {
this._router.navigate(['../'], {queryParams: {"pageId": this.pageId}, relativeTo: this.route});
}
public resetCustom() {
this.showLoading = true;
this.updateForm(this.pageHelpContent);

View File

@ -6,14 +6,12 @@ import {CheckPage, Page} from '../../utils/entities/adminTool/page';
import {Entity} from '../../utils/entities/adminTool/entity';
import {EnvProperties} from '../../utils/properties/env-properties';
import {Session} from '../../login/utils/helper.class';
import {LoginErrorCodes} from '../../login/utils/guardHelper.class';
import {UserManagementService} from '../../services/user-management.service';
import {Subscriber} from 'rxjs';
import {PortalUtils} from '../portal/portalHelper';
import {properties} from '../../../../environments/environment';
import {Option} from '../../sharedComponents/input/input.component';
import {AlertModal} from '../../utils/modal/alert';
import {SearchInputComponent} from '../../sharedComponents/search-input/search-input.component';
import {Title} from '@angular/platform-browser';
import {StringUtils} from '../../utils/string-utils.class';
import {StakeholderService} from '../../monitor/services/stakeholder.service';

View File

@ -2,7 +2,7 @@ import {Injectable} from '@angular/core';
import {
ActivatedRouteSnapshot,
CanActivate,
CanActivateChild,
CanActivateChild, Data,
Router,
RouterStateSnapshot,
UrlTree
@ -20,13 +20,15 @@ export class AdminLoginGuard implements CanActivate, CanActivateChild {
private userManagementService: UserManagementService) {
}
check(path: string): Observable<boolean> {
check(data: Data, path: string): Observable<boolean> {
let errorCode = LoginErrorCodes.NOT_LOGIN;
return this.userManagementService.getUserInfo(false).pipe(map(user => {
if (user) {
errorCode = LoginErrorCodes.NOT_ADMIN;
}
return Session.isPortalAdministrator(user);
return Session.isPortalAdministrator(user) ||
(data.monitorCurator && Session.isMonitorCurator(user)) ||
(data.communityCurator && Session.isCommunityCurator(user))
}),tap(isAdmin => {
if(!isAdmin) {
this.router.navigate(['/user-info'], {
@ -41,11 +43,11 @@ export class AdminLoginGuard implements CanActivate, CanActivateChild {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.check(state.url);
return this.check(route.data, state.url);
}
canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.check(state.url);
return this.check(childRoute.data, state.url);
}
}

View File

@ -0,0 +1,60 @@
import {Component, OnDestroy, OnInit} from "@angular/core";
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {ActivatedRoute, Router} from "@angular/router";
import {HelperService} from "../../utils/helper/helper.service";
import {StakeholderService} from "../services/stakeholder.service";
import {ConfigurationService} from "../../utils/configuration/configuration.service";
@Component({
selector: 'indicators-page',
template: `<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0" [texts]="pageContents['top']"></helper>`
})
export class IndicatorsComponent implements OnInit, OnDestroy {
private subscriptions: any[] = [];
public properties = properties;
public pageContents;
constructor(private helper: HelperService,
private configurationService: ConfigurationService,
private router: Router,
private stakeholderService: StakeholderService,
private route: ActivatedRoute) {
}
ngOnInit() {
this.subscriptions.push(this.route.params.subscribe(params => {
if(params['stakeholder']) {
this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
this.getPageContents(stakeholder.type);
}));
} else if(params['type']){
this.getPageContents(params['type']);
}
}))
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
public getPageContents(type: string) {
this.subscriptions.push(this.configurationService.isPageEnabled('monitor', '/indicators/' + type, 'monitor').subscribe(isEnabled => {
if(isEnabled) {
this.subscriptions.push(this.helper.getPageHelpContents(this.properties, 'monitor', '/indicators/' + type, 'monitor').subscribe(contents => {
this.pageContents = contents;
}));
} else {
this.navigateToError();
}
}));
}
private navigateToError() {
this.router.navigate([this.properties.errorLink], {queryParams: {'page': this.properties.baseLink + this.router.url}});
}
}

View File

@ -0,0 +1,19 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {RouterModule} from "@angular/router";
import {IndicatorsComponent} from "./indicators.component";
import {PreviousRouteRecorder} from "../../utils/piwik/previousRouteRecorder.guard";
import {HelperModule} from "../../utils/helper/helper.module";
@NgModule({
imports: [CommonModule, RouterModule.forChild([
{
path: '',
component: IndicatorsComponent,
canDeactivate: [PreviousRouteRecorder]
},
]), HelperModule],
declarations: [IndicatorsComponent],
exports: [IndicatorsComponent]
})
export class IndicatorsModule {}

View File

@ -5,22 +5,23 @@ import {map} from 'rxjs/operators';
import {EnvProperties} from "../properties/env-properties";
import {Portal} from "../entities/adminTool/portal";
import {Page} from "../entities/adminTool/page";
import {properties} from "../../../../environments/environment";
@Injectable({ providedIn: 'root' })
export class ConfigurationService{
@Injectable({providedIn: 'root'})
export class ConfigurationService {
private communityInformation: BehaviorSubject<Portal> = new BehaviorSubject(null);
private sub: Subscription = null;
private source: Observable<Portal> = null;
private promise: Promise<boolean> = null;
constructor(private http: HttpClient ) {}
constructor(private http: HttpClient) {
}
ngOnDestroy() {
this.clearSubscriptions();
}
clearSubscriptions() {
if(this.sub) {
if (this.sub) {
this.sub.unsubscribe();
}
}
@ -28,8 +29,8 @@ export class ConfigurationService{
/**
* @deprecated
*/
getCommunityInformation(properties:EnvProperties, community:string){
let url = properties.adminToolsAPIURL +"/"+properties.adminToolsPortalType+"/" + community + '/full';
getCommunityInformation(properties: EnvProperties, community: string) {
let url = properties.adminToolsAPIURL + "/" + properties.adminToolsPortalType + "/" + community + '/full';
return this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url);
//.map(res => res.json());
}
@ -40,15 +41,12 @@ export class ConfigurationService{
resolve();
}));
}
public initCommunityInformation(properties:EnvProperties, community:string) {
if(community == null) return;
let url = properties.adminToolsAPIURL +"/" + properties.adminToolsPortalType + "/" + community + "/full";
public initCommunityInformation(properties: EnvProperties, community: string) {
if (community == null) return;
let url = properties.adminToolsAPIURL + "/" + properties.adminToolsPortalType + "/" + community + "/full";
this.promise = new Promise<any>((resolve => {
this.source = this.http.get<Portal>((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url);
this.sub = this.source
.subscribe(
this.sub = this.http.get<Portal>((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url).subscribe(
(communityInformation: Portal) => {
this.communityInformation.next(communityInformation);
resolve();
@ -68,9 +66,9 @@ export class ConfigurationService{
/**
* @deprecated
*/
isEntityEnabled(APIUrl:string, community:string,entity: string){
isEntityEnabled(APIUrl: string, community: string, entity: string) {
//console.log("isEntityEnabled: "+entity);
let url = "isEntityEnabled-"+entity;
let url = "isEntityEnabled-" + entity;
// if(entity == "publication" || entity == "dataset" || entity == "datasource"){
// return Observable.of(new Object()).mapTo(false);
@ -80,40 +78,33 @@ export class ConfigurationService{
.pipe(map(res => true));
}
/**
* @deprecated
*/
isPageEnabled(properties:EnvProperties, community:string,router: string){
let page_route: string = router.split('?')[0].substring(1);
let url = properties.adminToolsAPIURL + "/"+properties.adminToolsPortalType+"/" + community+"/pages?page_route="+page_route;
isPageEnabled(portal: string, route: string, portalType = properties.adminToolsPortalType) {
let url = properties.adminToolsAPIURL + "/" + portalType + "/" + portal + "/pages?page_route=" + route;
return this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
//.map(res => res.json())
.pipe(map(res => {
let result = false;
if(res['length'] >0 && res[0].route == page_route){
if (res['length'] > 0 && res[0].route == route) {
result = res[0].isEnabled;
}
return result;
}));//.do(res => {console.log("Route "+page_route +" is "+res)});
}));
}
async isPageEnabledByStateAsync(properties: EnvProperties, community:string, page_route: string) {
if(!this.promise) {
this.initCommunityInformation(properties, community);
async isPageEnabledByStateAsync(properties: EnvProperties, portal: string, page_route: string) {
if (!this.promise || portal !== this.communityInformation.getValue().pid) {
this.initCommunityInformation(properties, portal);
}
await this.promise;
if(this.sub){
if (this.sub) {
this.sub.unsubscribe();
}
return this.filtering(page_route);
}
isPageEnabledByState(properties: EnvProperties, community:string, router: string): Observable<boolean> {
isPageEnabledByState(properties: EnvProperties, portal: string, router: string): Observable<boolean> {
let page_route: string = router.split('?')[0].substring(1);
return from(this.isPageEnabledByStateAsync(properties, community, page_route));
return from(this.isPageEnabledByStateAsync(properties, portal, page_route));
}
filtering(page_route: string) {
@ -130,7 +121,7 @@ export class ConfigurationService{
/**
* @deprecated
*/
getMainPageContent(APIUrl:string, community:string,){
getMainPageContent(APIUrl: string, community: string,) {
return this.http.get(APIUrl + "/page")
.pipe(map(res => true));
}
@ -138,7 +129,7 @@ export class ConfigurationService{
/**
* @deprecated
*/
getSpecialAnouncementContent(APIUrl:string, community:string,){
getSpecialAnouncementContent(APIUrl: string, community: string,) {
return this.http.get(APIUrl + "/page")
.pipe(map(res => ""));
}
@ -146,10 +137,11 @@ export class ConfigurationService{
/**
* @deprecated
*/
getHelpPageContent(APIUrl:string, community:string, router:string){
getHelpPageContent(APIUrl: string, community: string, router: string) {
return this.http.get(APIUrl + "/page")
.pipe(map(res => true));
}
// private handleError (error: Response) {
// // in a real world app, we may send the error to some remote logging infrastructure
// // instead of just logging it to the console

View File

@ -30,18 +30,18 @@ export class HelperService {
}
getPageHelpContents(properties:EnvProperties, communityId:string, router: string):any {
if(!communityId) {
communityId = properties.adminToolsCommunity;
getPageHelpContents(properties:EnvProperties, portal:string, router: string, portalType = properties.adminToolsPortalType):any {
if(!portal) {
portal = properties.adminToolsCommunity;
}
if(!communityId) {
communityId = 'openaire';
if(!portal) {
portal = 'openaire';
}
if(typeof properties.useHelpTexts == "undefined" || properties.useHelpTexts) {
let page_route: string = router.split('?')[0].substring(0);
let url = properties.adminToolsAPIURL;
url += '/' + properties.adminToolsPortalType + '/' + communityId + '/pagehelpcontent/grouped?active=true&page=' +
((page_route.indexOf("/"+communityId+"/")!=-1 ) ? ("/" + page_route.split("/"+communityId+"/")[1]) : page_route);
url += '/' + portalType + '/' + portal + '/pagehelpcontent/grouped?active=true&page=' +
((page_route.indexOf("/"+portal+"/")!=-1 ) ? ("/" + page_route.split("/"+portal+"/")[1]) : page_route);
return this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url);
}else {
return of(null);

View File

@ -1,5 +1,5 @@
<div class="uk-offcanvas-content">
<div [ngClass]="parentClass">
<div class="uk-offcanvas-content">
<nav class="uk-navbar-container">
<div class="uk-container">
<div uk-navbar="" class="uk-navbar">
@ -42,7 +42,6 @@
</div>
</div>
</nav>
<div class="uk-section uk-section-default">
<div class="uk-container">
@ -667,7 +666,6 @@
</div>
</div>
<div class="uk-section uk-padding-remove-vertical">
<div class="uk-child-width-1-2@s uk-child-width-1-4@l uk-grid-collapse uk-grid-match uk-grid" uk-grid="">
<div class="uk-first-column">
@ -684,7 +682,6 @@
</div>
</div>
</div>
<div class="uk-section uk-section-default">
<div class="uk-container">
@ -699,7 +696,6 @@
</div>
</div>
<div class="uk-section uk-section-muted">
<div class="uk-container">
@ -714,7 +710,6 @@
</div>
</div>
<div class="uk-section uk-section-primary">
<div class="uk-container">
@ -729,7 +724,6 @@
</div>
</div>
<div class="uk-section uk-section-secondary">
<div class="uk-container">
@ -744,7 +738,6 @@
</div>
</div>
<div id="modal" uk-modal="" class="uk-modal">
<div class="uk-modal-dialog">
<div class="uk-modal-header uk-flex uk-flex-middle uk-flex-between uk-background-primary-opacity">
@ -762,7 +755,6 @@
</div>
</div>
</div>
<div id="modal-search" class="uk-modal-full uk-modal" uk-modal="">
<div class="uk-modal-dialog uk-flex uk-flex-center uk-flex-middle" uk-height-viewport="">
@ -787,4 +779,5 @@
</div>
</div>
</div>
</div>

View File

@ -1,6 +1,8 @@
import {Component} from '@angular/core';
import {Component, OnDestroy, OnInit} from '@angular/core';
import {ValidatorFn, Validators} from "@angular/forms";
import {StringUtils} from "../string-utils.class";
import {ActivatedRoute} from "@angular/router";
import {Subscriber} from "rxjs";
@Component({
@ -8,9 +10,30 @@ import {StringUtils} from "../string-utils.class";
templateUrl: 'theme.component.html',
})
export class ThemeComponent {
export class ThemeComponent implements OnInit, OnDestroy {
url: string = 'https://example.com';
logoURL: string = 'https://example.com/test.png';
parentClass: string;
private subscriptions: any[] = [];
required: ValidatorFn = Validators.required;
urlValidator: ValidatorFn = StringUtils.urlValidator;
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
this.subscriptions.push(this.route.queryParams.subscribe(params => {
if(params['parentClass']) {
this.parentClass = params['parentClass'];
}
}));
}
ngOnDestroy() {
this.subscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();
}
});
}
}