Fix a bug with guard losing redirection. Add reorder in topics, categories, subcategories for Curators

This commit is contained in:
Konstantinos Triantafyllou 2022-07-14 17:44:53 +03:00
parent 3ffed87ad4
commit 4ece9a5b60
6 changed files with 279 additions and 112 deletions

View File

@ -39,7 +39,7 @@
</div> </div>
</div> </div>
</ng-template> </ng-template>
<div page-content> <div page-content [headerSticky]="true">
<div *ngIf="activeTopic && activeTopic.categories.length > 0" header> <div *ngIf="activeTopic && activeTopic.categories.length > 0" header>
<div class="uk-flex uk-flex-middle uk-margin-top info"> <div class="uk-flex uk-flex-middle uk-margin-top info">
<img [src]="stakeholder | logoUrl" class="uk-margin-right uk-blend-multiply"> <img [src]="stakeholder | logoUrl" class="uk-margin-right uk-blend-multiply">
@ -48,23 +48,17 @@
<h1 class="uk-h4 uk-margin-remove">{{stakeholder.name}}</h1> <h1 class="uk-h4 uk-margin-remove">{{stakeholder.name}}</h1>
</div> </div>
</div> </div>
</div> <ul *ngIf="stakeholder && status === errorCodes.DONE && activeTopic" class="uk-tab">
<div actions> <ng-template ngFor [ngForOf]="activeTopic.categories" let-category>
<div class="uk-margin-top"> <li *ngIf="isPublicOrIsMember(category.visibility)"
<div *ngIf="stakeholder && status === errorCodes.DONE && activeTopic"> [class.uk-active]="category.alias === activeCategory.alias">
<ul class="uk-tab"> <a [routerLink]="['/', stakeholder.alias, activeTopic.alias, category.alias]"
<ng-template ngFor [ngForOf]="activeTopic.categories" let-category> [queryParams]="queryParams">
<li *ngIf="isPublicOrIsMember(category.visibility)" <span class="title">{{category.name}}</span>
[class.uk-active]="category.alias === activeCategory.alias"> </a>
<a [routerLink]="['/', stakeholder.alias, activeTopic.alias, category.alias]" </li>
[queryParams]="queryParams"> </ng-template>
<span class="title">{{category.name}}</span> </ul>
</a>
</li>
</ng-template>
</ul>
</div>
</div>
</div> </div>
<div inner> <div inner>
<div *ngIf="activeCategory && countSubCategoriesToShow(activeCategory) > 1" class="uk-flex uk-flex-right uk-margin-top"> <div *ngIf="activeCategory && countSubCategoriesToShow(activeCategory) > 1" class="uk-flex uk-flex-right uk-margin-top">

@ -1 +1 @@
Subproject commit 013ce7d5f45dd64e28e82585451b2741c41f9d2e Subproject commit e3f082b8026053bc6095d29f4e2ac2d6922ef775

View File

@ -8,7 +8,8 @@
<div class="uk-width-auto"> <div class="uk-width-auto">
<icon class="menu-icon" name="west" [flex]="true"></icon> <icon class="menu-icon" name="west" [flex]="true"></icon>
</div> </div>
<span class="uk-width-expand uk-text-truncate uk-margin-small-left" [class.uk-hidden]="!open">Indicators</span> <span class="uk-width-expand uk-text-truncate uk-margin-small-left"
[class.uk-hidden]="!open">Indicators</span>
</div> </div>
</a> </a>
</li> </li>
@ -31,7 +32,8 @@
<span *ngIf="open" class="uk-invisible-hover" [class.uk-invisible-hover]="topicIndex !== i" <span *ngIf="open" class="uk-invisible-hover" [class.uk-invisible-hover]="topicIndex !== i"
(click)="$event.stopPropagation();$event.preventDefault()"> (click)="$event.stopPropagation();$event.preventDefault()">
<a class="uk-link-reset uk-flex uk-flex-middle"> <a class="uk-link-reset uk-flex uk-flex-middle">
<icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(topic.visibility)" ratio="0.6"></icon> <icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(topic.visibility)"
ratio="0.6"></icon>
<icon [flex]="true" name="more_vert"></icon> <icon [flex]="true" name="more_vert"></icon>
</a> </a>
<div #element uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0; flip: false"> <div #element uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0; flip: false">
@ -45,7 +47,7 @@
</div> </div>
</a> </a>
</li> </li>
<li class="uk-nav-divider"></li> <li *ngIf="i > 0 || i < stakeholder.topics.length - 1" class="uk-nav-divider"></li>
<li *ngIf="i > 0"> <li *ngIf="i > 0">
<a (click)="hide(element);moveTopic(i)"> <a (click)="hide(element);moveTopic(i)">
<div class="uk-flex uk-flex-middle"> <div class="uk-flex uk-flex-middle">
@ -70,13 +72,14 @@
<div class="uk-flex uk-flex-middle"> <div class="uk-flex uk-flex-middle">
<icon [flex]="true" [name]="v.icon" ratio="0.6"></icon> <icon [flex]="true" [name]="v.icon" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">{{v.label}}</span> <span class="uk-margin-small-left uk-width-expand">{{v.label}}</span>
<icon *ngIf="topic.visibility === v.value" [flex]="true" name="done" class="uk-text-secondary" ratio="0.8"></icon> <icon *ngIf="topic.visibility === v.value" [flex]="true" name="done"
class="uk-text-secondary" ratio="0.8"></icon>
</div> </div>
</a> </a>
</li> </li>
</ng-template> </ng-template>
<ng-container *ngIf="!topic.defaultId && isCurator"> <ng-container *ngIf="!topic.defaultId && isCurator">
<li class="uk-nav-divider"> <li class="uk-nav-divider">
<li> <li>
<a (click)="deleteTopicOpen(i, 'delete'); hide(element)"> <a (click)="deleteTopicOpen(i, 'delete'); hide(element)">
<div class="uk-flex uk-flex-middle"> <div class="uk-flex uk-flex-middle">
@ -136,34 +139,61 @@
</div> </div>
</div> </div>
</aside> </aside>
<div *ngIf="stakeholder && filters" page-content (stickyEmitter)="stickyPageHeader = $event"> <div *ngIf="stakeholder && filters" page-content>
<div header> <div header>
<div *ngIf="stakeholder.topics.length > 0 && stakeholder.topics[topicIndex]"> <div *ngIf="stakeholder.topics.length > 0 && stakeholder.topics[topicIndex]">
<div class="uk-width-expand uk-flex uk-margin-top uk-flex-middle info" [class.uk-active]="stickyPageHeader"> <div class="uk-flex uk-margin-top uk-flex-middle info">
<img [src]="stakeholder | logoUrl" class="uk-margin-right uk-blend-multiply"> <img [src]="stakeholder | logoUrl" class="uk-margin-right uk-blend-multiply">
<div> <div>
<div class="uk-margin-remove uk-text-background uk-text-bold uk-h6">Admin Dashboard - Manage Indicators</div> <div class="uk-margin-remove uk-text-background uk-text-bold uk-h6">Admin Dashboard - Manage Indicators</div>
<h1 class="uk-h4 uk-margin-remove">{{stakeholder.name}}</h1> <h1 class="uk-h4 uk-margin-remove">{{stakeholder.name}}</h1>
</div> </div>
</div> </div>
<div class="uk-margin-top"> </div>
<ul *ngIf="stakeholder.topics[topicIndex]" class="uk-tab"> </div>
<ng-template ngFor [ngForOf]="stakeholder.topics[topicIndex].categories" let-category let-i="index"> <div actions>
<li class="uk-visible-toggle uk-flex" [class.uk-active]="categoryIndex === i"> <div class="uk-margin-top uk-margin-bottom">
<ul *ngIf="stakeholder.topics[topicIndex]" #categories transition-group class="uk-tab">
<ng-template ngFor [ngForOf]="stakeholder.topics[topicIndex].categories" let-category let-i="index">
<li class="uk-visible-toggle uk-flex" [class.uk-active]="categoryIndex === i" transition-group-item>
<a (click)="chooseCategory(i)"> <a (click)="chooseCategory(i)">
<span class="title"> {{category.name}}</span> <span class="title"> {{category.name}}</span>
</a> </a>
<span class="uk-invisible-hover uk-flex uk-flex-column uk-flex-center uk-margin-small-left" [class.uk-invisible-hover]="categoryIndex !== i" <span class="uk-invisible-hover uk-flex uk-flex-column uk-flex-center uk-margin-small-left"
(click)="$event.stopPropagation();$event.preventDefault()"> [class.uk-invisible-hover]="categoryIndex !== i"
(click)="$event.stopPropagation();$event.preventDefault()">
<a class="uk-link-reset uk-flex uk-flex-middle"> <a class="uk-link-reset uk-flex uk-flex-middle">
<icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(category.visibility)" ratio="0.6"></icon> <icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(category.visibility)"
ratio="0.6"></icon>
<icon [flex]="true" name="more_vert"></icon> <icon [flex]="true" name="more_vert"></icon>
</a> </a>
<div #element uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0"> <div #element uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0">
<ul class="uk-nav uk-dropdown-nav"> <ul class="uk-nav uk-dropdown-nav">
<ng-container *ngIf="isCurator"> <ng-container *ngIf="isCurator">
<li> <li>
<a (click)="editCategoryOpen(i); hide(element)">Edit</a> <a (click)="editCategoryOpen(i); hide(element)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="edit" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Edit</span>
</div>
</a>
</li>
<li *ngIf="i > 0 || i < stakeholder.topics[topicIndex].categories.length - 1" class="uk-nav-divider"></li>
<li *ngIf="i > 0">
<a (click)="hide(element);moveCategory(i)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="west" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Move Left</span>
</div>
</a>
</li>
<li *ngIf="i < stakeholder.topics[topicIndex].categories.length - 1">
<a (click)="hide(element);moveCategory(i, i + 1)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="east" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Move Right</span>
</div>
</a>
</li> </li>
<li class="uk-nav-divider"></li> <li class="uk-nav-divider"></li>
</ng-container> </ng-container>
@ -173,101 +203,160 @@
<div class="uk-flex uk-flex-middle"> <div class="uk-flex uk-flex-middle">
<icon [flex]="true" [name]="v.icon" ratio="0.6"></icon> <icon [flex]="true" [name]="v.icon" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">{{v.label}}</span> <span class="uk-margin-small-left uk-width-expand">{{v.label}}</span>
<icon *ngIf="category.visibility === v.value" [flex]="true" name="done" class="uk-text-secondary" ratio="0.8"></icon> <icon *ngIf="category.visibility === v.value" [flex]="true" name="done"
class="uk-text-secondary" ratio="0.8"></icon>
</div> </div>
</a> </a>
</li> </li>
</ng-template> </ng-template>
<ng-container *ngIf="!category.defaultId && isCurator"> <ng-container *ngIf="!category.defaultId && isCurator">
<li class="uk-nav-divider"> <li class="uk-nav-divider">
<li><a (click)="deleteCategoryOpen(i, 'delete'); hide(element)">Delete</a></li> <li>
<a (click)="deleteCategoryOpen(i, 'delete'); hide(element)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="delete" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Delete</span>
</div>
</a>
</li>
</ng-container> </ng-container>
</ul> </ul>
</div> </div>
</span> </span>
</li> </li>
</ng-template> </ng-template>
<li *ngIf="isCurator"> <li *ngIf="isCurator">
<a (click)="editCategoryOpen(); $event.preventDefault()" class="uk-flex uk-flex-middle"> <a (click)="editCategoryOpen(); $event.preventDefault()" class="uk-flex uk-flex-middle">
<icon name="add" [flex]="true"></icon> <icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">Create new category</span> <span class="uk-margin-small-left">Create new category</span>
</a>
</li>
</ul>
</div>
</div>
</div>
<div inner>
<ul *ngIf="stakeholder.topics.length > 0 && stakeholder.topics[topicIndex].categories.length > 0 && stakeholder.topics[topicIndex].categories[categoryIndex]"
class="uk-subnav uk-subnav-pill uk-margin-top">
<ng-template ngFor [ngForOf]="stakeholder.topics[topicIndex].categories[categoryIndex].subCategories" let-subCategory let-i="index">
<li class="uk-visible-toggle uk-flex" [class.uk-active]="subCategoryIndex === i">
<a (click)="chooseSubcategory(i);$event.preventDefault()" class="uk-margin-small-left">
<span>{{subCategory.name}}</span>
</a> </a>
<span class="uk-invisible-hover uk-flex uk-flex-column uk-flex-center uk-margin-small-left" [class.uk-invisible-hover]="categoryIndex !== i" </li>
(click)="$event.stopPropagation();$event.preventDefault()"> </ul>
<ul *ngIf="stakeholder.topics.length > 0 && stakeholder.topics[topicIndex].categories.length > 0 && stakeholder.topics[topicIndex].categories[categoryIndex]"
#subCategories class="uk-subnav uk-subnav-pill uk-margin-medium-top" transition-group>
<ng-template ngFor [ngForOf]="stakeholder.topics[topicIndex].categories[categoryIndex].subCategories"
let-subCategory let-i="index">
<li class="uk-visible-toggle uk-flex" [class.uk-active]="subCategoryIndex === i" transition-group-item>
<a (click)="chooseSubcategory(i);$event.preventDefault()" class="uk-margin-small-left">
<span>{{subCategory.name}}</span>
</a>
<span class="uk-invisible-hover uk-flex uk-flex-column uk-flex-center uk-margin-small-left"
[class.uk-invisible-hover]="categoryIndex !== i"
(click)="$event.stopPropagation();$event.preventDefault()">
<a class="uk-link-reset uk-flex uk-flex-middle"> <a class="uk-link-reset uk-flex uk-flex-middle">
<icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(subCategory.visibility)" ratio="0.6"></icon> <icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(subCategory.visibility)"
ratio="0.6"></icon>
<icon [flex]="true" name="more_vert"></icon> <icon [flex]="true" name="more_vert"></icon>
</a> </a>
<div #element uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0"> <div #element uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0">
<ul class="uk-nav uk-dropdown-nav"> <ul class="uk-nav uk-dropdown-nav">
<ng-container *ngIf="isCurator"> <ng-container *ngIf="isCurator">
<li> <li>
<a (click)="editSubCategoryOpen(i); hide(element)">Edit</a> <a (click)="editSubCategoryOpen(i); hide(element)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="edit" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Edit</span>
</div>
</a>
</li>
<li *ngIf="i > 0 || i < stakeholder.topics[topicIndex].categories[categoryIndex].subCategories.length - 1" class="uk-nav-divider"></li>
<li *ngIf="i > 0">
<a (click)="hide(element);moveSubCategory(i)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="west" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Move Left</span>
</div>
</a>
</li>
<li *ngIf="i < stakeholder.topics[topicIndex].categories[categoryIndex].subCategories.length - 1">
<a (click)="hide(element);moveSubCategory(i, i + 1)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="east" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Move Right</span>
</div>
</a>
</li>
<li class="uk-nav-divider"></li>
<li *ngIf="indicators">
<a (click)=" indicators.exportIndicators();hide(element)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="download" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Export indicators</span>
</div>
</a>
</li>
<li *ngIf="indicators">
<a (click)="file.value = ''; this.index=i; file.click(); hide(element)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="upload" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Import indicators</span>
</div>
</a>
</li> </li>
<li *ngIf="indicators"><a (click)=" indicators.exportIndicators();hide(element)">Export indicators</a></li>
<li *ngIf="indicators"><a (click)="file.value = ''; this.index=i; file.click(); hide(element)">Import indicators</a></li>
<li class="uk-nav-divider"></li> <li class="uk-nav-divider"></li>
</ng-container> </ng-container>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v> <ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<li [class.uk-active]="subCategory.visibility === v.value"> <li [class.uk-active]="subCategory.visibility === v.value">
<a (click)="changeSubcategoryStatus(i, v.value)"> <a (click)="changeSubcategoryStatus(i, v.value)">
<div class="uk-flex uk-flex-middle"> <div class="uk-flex uk-flex-middle">
<icon [flex]="true" [name]="v.icon" ratio="0.6"></icon> <icon [flex]="true" [name]="v.icon" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">{{v.label}}</span> <span class="uk-margin-small-left uk-width-expand">{{v.label}}</span>
<icon *ngIf="subCategory.visibility === v.value" [flex]="true" name="done" class="uk-text-secondary" ratio="0.8"></icon> <icon *ngIf="subCategory.visibility === v.value" [flex]="true" name="done"
class="uk-text-secondary" ratio="0.8"></icon>
</div> </div>
</a> </a>
</li> </li>
</ng-template> </ng-template>
<ng-container *ngIf="!subCategory.defaultId && isCurator"> <ng-container *ngIf="!subCategory.defaultId && isCurator">
<li class="uk-nav-divider"> <li class="uk-nav-divider">
<li><a (click)="deleteSubcategoryOpen(i, 'delete'); hide(element)">Delete</a></li> <li>
<a (click)="deleteSubcategoryOpen(i, 'delete'); hide(element)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="delete" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Delete</span>
</div>
</a>
</li>
</ng-container> </ng-container>
</ul> </ul>
</div> </div>
</span> </span>
</li>
</ng-template>
<li *ngIf="isCurator">
<a (click)="editSubCategoryOpen(); $event.preventDefault()" class="uk-flex uk-flex-middle">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">Create new subcategory</span>
</a>
</li> </li>
</ng-template> </ul>
<li *ngIf="isCurator"> </div>
<a (click)="editSubCategoryOpen(); $event.preventDefault()" class="uk-flex uk-flex-middle"> </div>
<icon name="add" [flex]="true"></icon> <div inner>
<span class="uk-margin-small-left">Create new subcategory</span> <input #file id="import-file" type="file" class="uk-hidden"
</a> (change)="indicators.fileChangeEvent($event, this.index)"/>
</li>
</ul>
<input #file id="import-file" type="file" class="uk-hidden" (change)="indicators.fileChangeEvent($event, this.index)"/>
<indicators #indicators [topicIndex]="topicIndex" [categoryIndex]="categoryIndex" <indicators #indicators [topicIndex]="topicIndex" [categoryIndex]="categoryIndex"
[subcategoryIndex]="subCategoryIndex" [user]="user" [subcategoryIndex]="subCategoryIndex" [user]="user"
[stakeholder]="stakeholder" [changed]="change.asObservable()"></indicators> [stakeholder]="stakeholder" [changed]="change.asObservable()"></indicators>
</div> </div>
</div> </div>
<modal-alert #deleteModal classTitle="uk-background-primary uk-light" (alertOutput)="deleteElement()" [overflowBody]="false"> <modal-alert #deleteModal classTitle="uk-background-primary uk-light" (alertOutput)="deleteElement()"
[overflowBody]="false">
You are about to delete <span class="uk-text-bold" *ngIf="element">"{{element.name}}"</span> {{type}} permanently. You are about to delete <span class="uk-text-bold" *ngIf="element">"{{element.name}}"</span> {{type}} permanently.
<div *ngIf="elementChildrenActionOnDelete == 'delete'" class="uk-text-bold"> <div *ngIf="elementChildrenActionOnDelete == 'delete'" class="uk-text-bold">
{{getPluralTypeName()}} of all profiles based on this default {{type}}, will be deleted as well. {{getPluralTypeName()}} of all profiles based on this default {{type}}, will be deleted as well.
</div> </div>
Are you sure you want to proceed? Are you sure you want to proceed?
</modal-alert> </modal-alert>
<modal-alert #editModal classTitle="uk-background-primary uk-light" (alertOutput)="saveElement()" [okDisabled]="form && (form.invalid || form.pristine)"> <modal-alert #editModal classTitle="uk-background-primary uk-light" (alertOutput)="saveElement()"
[okDisabled]="form && (form.invalid || form.pristine)">
<div *ngIf="form" class="uk-grid uk-padding uk-padding-remove-horizontal uk-child-width-1-1" [formGroup]="form" <div *ngIf="form" class="uk-grid uk-padding uk-padding-remove-horizontal uk-child-width-1-1" [formGroup]="form"
uk-grid> uk-grid>
<div input [formInput]="form.get('name')" placeholder="Title"></div> <div input [formInput]="form.get('name')" placeholder="Title"></div>
<div input [formInput]="form.get('description')" placeholder="Description" type="textarea" rows="4"></div> <div input [formInput]="form.get('description')" placeholder="Description" type="textarea" rows="4"></div>
<div *ngIf="form.get('icon')" input [formInput]="form.get('icon')" placeholder="Icon(SVG)" type="textarea"></div> <div *ngIf="form.get('icon')" input [formInput]="form.get('icon')" placeholder="Icon(SVG)" type="textarea"></div>
<div input [formInput]="form.get('visibility')" placeholder="Status" [options]="stakeholderUtils.visibility" type="select"> <div input [formInput]="form.get('visibility')" placeholder="Status" [options]="stakeholderUtils.visibility"
type="select">
</div> </div>
</div> </div>
</modal-alert> </modal-alert>

View File

@ -1,4 +1,4 @@
import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core'; import {ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {Title} from '@angular/platform-browser'; import {Title} from '@angular/platform-browser';
import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties'; import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties';
@ -6,7 +6,7 @@ import {Category, Stakeholder, SubCategory, Topic, Visibility} from "../openaire
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service"; import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class"; import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class";
import {AlertModal} from "../openaireLibrary/utils/modal/alert"; import {AlertModal} from "../openaireLibrary/utils/modal/alert";
import {Subject, Subscriber, Subscription} from "rxjs"; import {BehaviorSubject, Subject, Subscriber, Subscription} from "rxjs";
import {FormBuilder, FormGroup, Validators} from "@angular/forms"; import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import {StakeholderUtils} from "../utils/indicator-utils"; import {StakeholderUtils} from "../utils/indicator-utils";
import {StringUtils} from "../openaireLibrary/utils/string-utils.class"; import {StringUtils} from "../openaireLibrary/utils/string-utils.class";
@ -27,12 +27,11 @@ declare var UIkit;
templateUrl: './topic.component.html', templateUrl: './topic.component.html',
}) })
export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent { export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
private topicSubscriptions: any[] = [];
private subscriptions: any[] = []; private subscriptions: any[] = [];
private paramsSub: any;
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public stakeholderUtils: StakeholderUtils = new StakeholderUtils(); public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public loading: boolean = true; public loading: boolean = true;
public stickyPageHeader: boolean = false;
public stakeholder: Stakeholder; public stakeholder: Stakeholder;
public user: User; public user: User;
/** /**
@ -42,14 +41,17 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
/** /**
* Current topic * Current topic
**/ **/
public topicIndexSubject: BehaviorSubject<number> = new BehaviorSubject<number>(0);
public topicIndex: number = 0; public topicIndex: number = 0;
/** /**
* Current category * Current category
*/ */
public categoryIndexSubject: BehaviorSubject<number> = new BehaviorSubject<number>(0);
public categoryIndex: number = 0; public categoryIndex: number = 0;
/** /**
* Current Subcategory * Current Subcategory
*/ */
public subCategoryIndexSubject: BehaviorSubject<number> = new BehaviorSubject<number>(0);
public subCategoryIndex: number = 0; public subCategoryIndex: number = 0;
/** /**
* Current element and index of topic, category or subcategory to be deleted. * Current element and index of topic, category or subcategory to be deleted.
@ -63,6 +65,8 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
@ViewChild('editModal', {static: true}) editModal: AlertModal; @ViewChild('editModal', {static: true}) editModal: AlertModal;
@ViewChild("topics") topics: TransitionGroupComponent; @ViewChild("topics") topics: TransitionGroupComponent;
@ViewChild("categories") categories: TransitionGroupComponent;
@ViewChild("subCategories") subCategories: TransitionGroupComponent;
public elementChildrenActionOnDelete: string; public elementChildrenActionOnDelete: string;
public filters: FormGroup; public filters: FormGroup;
@ -78,12 +82,45 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
private fb: FormBuilder, private fb: FormBuilder,
private stakeholderService: StakeholderService, private stakeholderService: StakeholderService,
private userManagementService: UserManagementService, private userManagementService: UserManagementService,
private layoutService: LayoutService) { private layoutService: LayoutService,
private cdr: ChangeDetectorRef) {
} }
public ngOnInit() { public ngOnInit() {
let subscription: Subscription; let subscription: Subscription;
this.paramsSub = this.route.params.subscribe(params => { this.subscriptions.push(this.topicIndexSubject.asObservable().subscribe(index => {
if(this.categories) {
this.categories.disable();
if(this.subCategories) {
this.subCategories.disable();
}
}
this.topicIndex = index;
this.cdr.detectChanges();
if(this.categories) {
this.categories.init();
this.categories.enable();
if(this.subCategories) {
this.subCategories.init();
this.subCategories.enable();
}
}
}));
this.subscriptions.push(this.categoryIndexSubject.asObservable().subscribe(index => {
if(this.subCategories) {
this.subCategories.disable();
}
this.categoryIndex = index;
this.cdr.detectChanges();
if(this.subCategories) {
this.subCategories.init();
this.subCategories.enable();
}
}));
this.subscriptions.push(this.subCategoryIndexSubject.asObservable().subscribe(index => {
this.subCategoryIndex = index;
this.cdr.detectChanges();
}));
this.subscriptions.push(this.route.params.subscribe(params => {
if (subscription) { if (subscription) {
subscription.unsubscribe(); subscription.unsubscribe();
} }
@ -91,12 +128,11 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
if (stakeholder) { if (stakeholder) {
this.stakeholder = stakeholder; this.stakeholder = stakeholder;
if (params['topic']) { if (params['topic']) {
this.topicIndex = this.stakeholder.topics.findIndex(topic => topic.alias === params['topic']); this.chooseTopic(this.stakeholder.topics.findIndex(topic => topic.alias === params['topic']));
} else { } else {
this.topicIndex = 0; this.chooseTopic(0);
} }
this.categoryIndex = 0; this.chooseCategory(0);
this.subCategoryIndex = 0;
this.filters = this.fb.group({ this.filters = this.fb.group({
chartType: this.fb.control('all'), chartType: this.fb.control('all'),
status: this.fb.control('all'), status: this.fb.control('all'),
@ -109,26 +145,28 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
} }
} }
}); });
this.subscriptions.push(subscription); this.topicSubscriptions.push(subscription);
}); }));
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { this.topicSubscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
this.user = user; this.user = user;
})) }))
} }
public ngOnDestroy() { public ngOnDestroy() {
this.topicSubscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();
}
});
this.subscriptions.forEach(value => { this.subscriptions.forEach(value => {
if (value instanceof Subscriber) { if (value instanceof Subscriber) {
value.unsubscribe(); value.unsubscribe();
} }
}); });
if (this.paramsSub instanceof Subscriber) {
this.paramsSub.unsubscribe();
}
} }
canExit(): boolean { canExit(): boolean {
this.subscriptions.forEach(value => { this.topicSubscriptions.forEach(value => {
if (value instanceof Subscriber) { if (value instanceof Subscriber) {
value.unsubscribe(); value.unsubscribe();
} }
@ -169,6 +207,10 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
} }
} }
public chooseTopic(topicIndex: number) {
this.topicIndexSubject.next(topicIndex);
}
private buildTopic(topic: Topic) { private buildTopic(topic: Topic) {
let topics = this.stakeholder.topics.filter(element => element._id !== topic._id); let topics = this.stakeholder.topics.filter(element => element._id !== topic._id);
this.form = this.fb.group({ this.form = this.fb.group({
@ -186,7 +228,7 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
categories: this.fb.control(topic.categories), categories: this.fb.control(topic.categories),
icon: this.fb.control(topic.icon) icon: this.fb.control(topic.icon)
}); });
this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => { this.topicSubscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
let i = 1; let i = 1;
value = this.stakeholderUtils.generateAlias(value); value = this.stakeholderUtils.generateAlias(value);
this.form.controls['alias'].setValue(value); this.form.controls['alias'].setValue(value);
@ -249,7 +291,7 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
this.stakeholder.topics[this.index]._id this.stakeholder.topics[this.index]._id
]; ];
let callback = (): void => { let callback = (): void => {
this.topicIndex = Math.max(0, this.index - 1); this.chooseTopic(Math.max(0, this.index - 1));
this.stakeholder.topics.splice(this.index, 1); this.stakeholder.topics.splice(this.index, 1);
this.topics.init(); this.topics.init();
}; };
@ -264,7 +306,9 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
this.stakeholderService.reorderElements(properties.monitorServiceAPIURL, path, ids).subscribe(() => { this.stakeholderService.reorderElements(properties.monitorServiceAPIURL, path, ids).subscribe(() => {
HelperFunctions.swap(this.stakeholder.topics, index, newIndex); HelperFunctions.swap(this.stakeholder.topics, index, newIndex);
if(this.topicIndex === index) { if(this.topicIndex === index) {
this.topicIndex = newIndex; this.chooseTopic(newIndex);
} else if(this.topicIndex === newIndex) {
this.chooseTopic(index);
} }
}, error => { }, error => {
NotificationHandler.rise(error.error.message) NotificationHandler.rise(error.error.message)
@ -272,8 +316,8 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
} }
public chooseCategory(index: number) { public chooseCategory(index: number) {
this.categoryIndex = index; this.categoryIndexSubject.next(index);
this.subCategoryIndex = 0; this.chooseSubcategory(0);
} }
private buildCategory(category: Category) { private buildCategory(category: Category) {
@ -292,7 +336,7 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
defaultId: this.fb.control(category.defaultId), defaultId: this.fb.control(category.defaultId),
subCategories: this.fb.control(category.subCategories) subCategories: this.fb.control(category.subCategories)
}); });
this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => { this.topicSubscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
let i = 1; let i = 1;
value = this.stakeholderUtils.generateAlias(value); value = this.stakeholderUtils.generateAlias(value);
this.form.controls['alias'].setValue(value); this.form.controls['alias'].setValue(value);
@ -320,6 +364,7 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
let callback = (category: Category): void => { let callback = (category: Category): void => {
if (this.index === -1) { if (this.index === -1) {
this.stakeholder.topics[this.topicIndex].categories.push(category); this.stakeholder.topics[this.topicIndex].categories.push(category);
this.categories.init();
} else { } else {
this.stakeholder.topics[this.topicIndex].categories[this.index] = HelperFunctions.copy(category); this.stakeholder.topics[this.topicIndex].categories[this.index] = HelperFunctions.copy(category);
} }
@ -343,7 +388,6 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
this.changeStatus(this.stakeholder.topics[this.topicIndex].categories[this.index], path, visibility); this.changeStatus(this.stakeholder.topics[this.topicIndex].categories[this.index], path, visibility);
} }
public deleteCategoryOpen(index: number, childrenAction: string = null) { public deleteCategoryOpen(index: number, childrenAction: string = null) {
this.type = 'category'; this.type = 'category';
this.index = index; this.index = index;
@ -358,12 +402,30 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
this.stakeholder.topics[this.topicIndex].categories[this.index]._id this.stakeholder.topics[this.topicIndex].categories[this.index]._id
]; ];
let callback = (): void => { let callback = (): void => {
this.categoryIndex = Math.max(0, this.index - 1); this.chooseCategory(Math.max(0, this.index - 1));
this.stakeholder.topics[this.topicIndex].categories.splice(this.index, 1); this.stakeholder.topics[this.topicIndex].categories.splice(this.index, 1);
this.categories.init();
}; };
this.delete('Category has been successfully be deleted', path, callback); this.delete('Category has been successfully be deleted', path, callback);
} }
public moveCategory(index: number, newIndex: number = index - 1) {
this.categories.init();
let path = [this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id];
let ids = this.stakeholder.topics[this.topicIndex].categories.map(category => category._id);
HelperFunctions.swap(ids, index, newIndex);
this.stakeholderService.reorderElements(properties.monitorServiceAPIURL, path, ids).subscribe(() => {
HelperFunctions.swap(this.stakeholder.topics[this.topicIndex].categories, index, newIndex);
if(this.categoryIndex === index) {
this.chooseCategory(newIndex);
} else if(this.categoryIndex === newIndex) {
this.chooseCategory(index);
}
}, error => {
NotificationHandler.rise(error.error.message)
});
}
private buildSubcategory(subCategory: SubCategory) { private buildSubcategory(subCategory: SubCategory) {
let subCategories = this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories.filter(element => element._id !== subCategory._id); let subCategories = this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories.filter(element => element._id !== subCategory._id);
this.form = this.fb.group({ this.form = this.fb.group({
@ -381,7 +443,7 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
charts: this.fb.control(subCategory.charts), charts: this.fb.control(subCategory.charts),
numbers: this.fb.control(subCategory.numbers) numbers: this.fb.control(subCategory.numbers)
}); });
this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => { this.topicSubscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
let i = 1; let i = 1;
value = this.stakeholderUtils.generateAlias(value); value = this.stakeholderUtils.generateAlias(value);
this.form.controls['alias'].setValue(value); this.form.controls['alias'].setValue(value);
@ -453,12 +515,29 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index]._id this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index]._id
]; ];
let callback = (): void => { let callback = (): void => {
this.subCategoryIndex = Math.max(0, this.index - 1); this.chooseSubcategory(Math.max(0, this.index - 1));
this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories.splice(this.index, 1); this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories.splice(this.index, 1);
}; };
this.delete('Subcategory has been successfully be deleted', path, callback); this.delete('Subcategory has been successfully be deleted', path, callback);
} }
public moveSubCategory(index: number, newIndex: number = index - 1) {
this.subCategories.init();
let path = [this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id];
let ids = this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories.map(subCategory => subCategory._id);
HelperFunctions.swap(ids, index, newIndex);
this.stakeholderService.reorderElements(properties.monitorServiceAPIURL, path, ids).subscribe(() => {
HelperFunctions.swap(this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories, index, newIndex);
if(this.subCategoryIndex === index) {
this.chooseSubcategory(newIndex);
} else if(this.subCategoryIndex === newIndex) {
this.chooseSubcategory(index);
}
}, error => {
NotificationHandler.rise(error.error.message)
});
}
private navigateToError() { private navigateToError() {
this.router.navigate([this.properties.errorLink], {queryParams: {'page': this.router.url}}); this.router.navigate([this.properties.errorLink], {queryParams: {'page': this.router.url}});
} }
@ -498,7 +577,7 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
} }
private save(message: string, path: string[], saveElement: any, callback: Function, redirect = false) { private save(message: string, path: string[], saveElement: any, callback: Function, redirect = false) {
this.subscriptions.push(this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, saveElement, path).subscribe(saveElement => { this.topicSubscriptions.push(this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, saveElement, path).subscribe(saveElement => {
callback(saveElement); callback(saveElement);
this.stakeholderChanged(); this.stakeholderChanged();
NotificationHandler.rise(message); NotificationHandler.rise(message);
@ -513,7 +592,7 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
} }
private delete(message: string, path: string[], callback: Function, redirect = false) { private delete(message: string, path: string[], callback: Function, redirect = false) {
this.subscriptions.push(this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path, this.elementChildrenActionOnDelete).subscribe(() => { this.topicSubscriptions.push(this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path, this.elementChildrenActionOnDelete).subscribe(() => {
callback(); callback();
this.stakeholderChanged(); this.stakeholderChanged();
NotificationHandler.rise(message); NotificationHandler.rise(message);
@ -526,7 +605,7 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
} }
private changeStatus(element: Topic | Category | SubCategory, path: string[], visibility: Visibility) { private changeStatus(element: Topic | Category | SubCategory, path: string[], visibility: Visibility) {
this.subscriptions.push(this.stakeholderService.changeVisibility(this.properties.monitorServiceAPIURL, path, visibility).subscribe(visibility => { this.topicSubscriptions.push(this.stakeholderService.changeVisibility(this.properties.monitorServiceAPIURL, path, visibility).subscribe(visibility => {
element.visibility = visibility; element.visibility = visibility;
NotificationHandler.rise(StringUtils.capitalize(this.type) + ' has been <b>successfully changed</b> to ' + element.visibility.toLowerCase()); NotificationHandler.rise(StringUtils.capitalize(this.type) + ' has been <b>successfully changed</b> to ' + element.visibility.toLowerCase());
}, error => { }, error => {
@ -541,7 +620,7 @@ export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
} }
chooseSubcategory(subcategoryIndex: number) { chooseSubcategory(subcategoryIndex: number) {
this.subCategoryIndex = subcategoryIndex; this.subCategoryIndexSubject.next(subcategoryIndex);
} }
public getPluralTypeName(): string { public getPluralTypeName(): string {

View File

@ -13,6 +13,7 @@ import {LoginErrorCodes} from "../openaireLibrary/login/utils/guardHelper.class"
import {Session} from "../openaireLibrary/login/utils/helper.class"; import {Session} from "../openaireLibrary/login/utils/helper.class";
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service"; import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
import {Observable, zip} from "rxjs"; import {Observable, zip} from "rxjs";
import {error} from "protractor";
@Injectable() @Injectable()
@ -24,15 +25,19 @@ export class AdminDashboardGuard implements CanActivate, CanActivateChild {
} }
check(path: string, alias: string): Observable<boolean> | boolean { check(path: string, alias: string): Observable<boolean> | boolean {
let errorCode = LoginErrorCodes.NOT_LOGIN;
return zip( return zip(
this.userManagementService.getUserInfo(false) this.userManagementService.getUserInfo(false)
,this.stakeholderService.getStakeholder(alias) ,this.stakeholderService.getStakeholder(alias)
).pipe(take(1),map(res => ).pipe(take(1),map(res => {
res[0] && res[1] && (Session.isPortalAdministrator(res[0]) || if(res[0]) {
errorCode = LoginErrorCodes.NOT_ADMIN;
}
return res[0] && res[1] && (Session.isPortalAdministrator(res[0]) ||
Session.isCurator(res[1].type, res[0]) || Session.isManager(res[1].type, res[1].alias, res[0])) Session.isCurator(res[1].type, res[0]) || Session.isManager(res[1].type, res[1].alias, res[0]))
),tap(authorized => { }),tap(authorized => {
if(!authorized){ if(!authorized){
this.router.navigate(['/user-info'], {queryParams: {'errorCode': LoginErrorCodes.NOT_ADMIN, 'redirectUrl':path}}); this.router.navigate(['/user-info'], {queryParams: {'errorCode': errorCode, 'redirectUrl':path}});
} }
})); }));
} }

@ -1 +1 @@
Subproject commit 00fc1f9e2b9158a6be224061d742cf80a043fab8 Subproject commit 6a92074076f71ee522120e9941e22a9caf16e6dc