[angular-16-irish-monitor | WIP]: Add base components for stakeholder, indicators and sidebar. Deprecated StakeholderEntities.

This commit is contained in:
Konstantinos Triantafyllou 2023-11-13 15:00:05 +02:00
parent 1ff833ed8a
commit e80f73f9a9
23 changed files with 521 additions and 461 deletions

View File

@ -6,6 +6,9 @@ import {CommunityInfo} from "./community/communityInfo";
export class ConnectHelper {
public static getCommunityFromDomain(domain: string): string{
if(properties.adminToolsPortalType === 'irish') {
return properties.adminToolsCommunity;
}
if(properties.environment == "development" &&
(properties.adminToolsPortalType == "connect" || properties.adminToolsPortalType == "community"
|| properties.adminToolsPortalType == "aggregator" || properties.adminToolsPortalType == "eosc")) {

View File

@ -1,17 +1,17 @@
import {Option} from "../../sharedComponents/input/input.component";
import {StakeholderEntities} from "../../monitor/entities/stakeholder";
import {StakeholderConfiguration} from "../../monitor-admin/utils/indicator-utils";
export class PortalUtils{
export class PortalUtils {
portalTypes: Option[] = [
{value: 'explore', label: 'Explore Portal'},
{value: 'connect', label: 'Connect portal'},
{value: 'monitor', label: 'Monitor portal'},
{value: 'community', label: 'Community Gateway'},
{value: 'funder', label: StakeholderEntities.FUNDER + ' Dashboard'},
{value: 'ri', label: StakeholderEntities.RI + ' Dashboard'},
{value: 'organization', label: StakeholderEntities.ORGANIZATION + ' Dashboard'},
{value: 'project', label: StakeholderEntities.PROJECT + ' Dashboard'}
{value: 'funder', label: StakeholderConfiguration.ENTITIES.funder + ' ' + StakeholderConfiguration.ENTITIES.stakeholder},
{value: 'ri', label: StakeholderConfiguration.ENTITIES.ri + ' ' + StakeholderConfiguration.ENTITIES.stakeholder},
{value: 'organization', label: StakeholderConfiguration.ENTITIES.organization + ' ' + StakeholderConfiguration.ENTITIES.stakeholder},
{value: 'project', label: StakeholderConfiguration.ENTITIES.project + ' ' + StakeholderConfiguration.ENTITIES.stakeholder},
];
}

View File

@ -0,0 +1,42 @@
import {ChangeDetectorRef, Directive, OnInit} from "@angular/core";
import {BaseComponent} from "../../../sharedComponents/base/base.component";
import {MenuItem} from "../../../sharedComponents/menu";
import {LayoutService} from "./layout.service";
@Directive()
export class SidebarBaseComponent extends BaseComponent implements OnInit {
hasSidebar: boolean = false;
hasInternalSidebar: boolean = false;
/**
* Menu Items
* */
sideBarItems: MenuItem[] = [];
backItem: MenuItem = null;
protected layoutService: LayoutService;
protected cdr: ChangeDetectorRef;
constructor() {
super();
}
ngOnInit() {
this.subscriptions.push(this.layoutService.hasSidebar.subscribe(hasSidebar => {
this.hasSidebar = hasSidebar;
this.cdr.detectChanges();
}));
this.subscriptions.push(this.layoutService.hasInternalSidebar.subscribe(hasInternalSidebar => {
this.hasInternalSidebar = hasInternalSidebar;
this.cdr.detectChanges();
}));
this.layoutService.setOpen(true);
}
public get open() {
return this.layoutService.open;
}
public get hover() {
return this.layoutService.hover;
}
}

View File

@ -1,4 +1,5 @@
import {stakeholderTypes} from "../../monitor/entities/stakeholder";
import {StakeholderConfiguration} from "../../monitor-admin/utils/indicator-utils";
export class User {
email: string;
@ -100,7 +101,7 @@ export class Session {
}
public static isMonitorCurator(user: User): boolean {
return stakeholderTypes.filter(stakeholderType => this.isTypeCurator(stakeholderType.value, user)).length > 0;
return StakeholderConfiguration.TYPES.filter(stakeholderType => this.isTypeCurator(stakeholderType.value, user)).length > 0;
}
public static isCommunityCurator(user: User): boolean {
@ -112,7 +113,7 @@ export class Session {
}
public static isCurator(type: string, user: User): boolean {
return (type === 'community' || stakeholderTypes.find(stakeholderType => stakeholderType.value == type)) && this.isTypeCurator(type, user);
return (type === 'community' || StakeholderConfiguration.TYPES.find(stakeholderType => stakeholderType.value == type)) && this.isTypeCurator(type, user);
}
public static isPortalAdministrator(user: User): boolean {

View File

@ -1,11 +1,8 @@
import {Component, Input, OnDestroy, ViewChild} from "@angular/core";
import {Component, Input, ViewChild} from "@angular/core";
import {Stakeholder} from "../../../monitor/entities/stakeholder";
import {UntypedFormBuilder, UntypedFormGroup, Validators} from "@angular/forms";
import {StakeholderUtils} from "../../utils/indicator-utils";
import {Option} from "../../../sharedComponents/input/input.component";
import {Subscription} from "rxjs";
import {EnvProperties} from "../../../utils/properties/env-properties";
import {properties} from "src/environments/environment";
import {StakeholderService} from "../../../monitor/services/stakeholder.service";
import {UtilitiesService} from "../../../services/utilities.service";
import {Role, Session, User} from "../../../login/utils/helper.class";
@ -16,121 +13,132 @@ import {NotificationUtils} from "../../../notifications/notification-utils";
import {Notification} from "../../../notifications/notifications";
import {NotificationHandler} from "../../../utils/notification-handler";
import {StatsProfilesService} from "../../utils/services/stats-profiles.service";
import {StakeholderBaseComponent} from "../../utils/stakeholder-base.component";
@Component({
selector: 'edit-stakeholder',
template: `
<form *ngIf="stakeholderFb" [formGroup]="stakeholderFb">
<div class="uk-grid uk-grid-large" uk-grid>
<div class="uk-width-1-2@m">
<div input id="name" [formInput]="stakeholderFb.get('name')"
placeholder="Name"></div>
</div>
<div class="uk-width-1-2@m">
<div input [formInput]="stakeholderFb.get('alias')"
placeholder="URL Alias"></div>
</div>
<div class="uk-width-1-3@m">
<div input [formInput]="stakeholderFb.get('index_id')"
placeholder="Index ID"></div>
</div>
<div class="uk-width-1-3@m">
<div input [formInput]="stakeholderFb.get('index_name')"
placeholder="Index Name"></div>
</div>
<div class="uk-width-1-3@m">
<div input [formInput]="stakeholderFb.get('index_shortName')"
placeholder="Index Short Name"></div>
</div>
<ng-container *ngIf="isCurator">
<div class="uk-width-1-3@m">
<div *ngIf="statsProfiles" input [formInput]="stakeholderFb.get('statsProfile')" [type]="'select'"
[options]="statsProfiles"
placeholder="Stats Profile"></div>
<div class="uk-margin-medium-bottom">
<form *ngIf="stakeholderFb" [formGroup]="stakeholderFb">
<div class="uk-grid uk-grid-large" uk-grid>
<div class="uk-width-1-2@m">
<div input id="name" [formInput]="stakeholderFb.get('name')"
placeholder="Name"></div>
</div>
<div class="uk-width-1-2@m">
<div input [formInput]="stakeholderFb.get('alias')"
placeholder="URL Alias"></div>
</div>
<div class="uk-width-1-3@m">
<div input [formInput]="stakeholderFb.get('projectUpdateDate')" [type]="'date'"
placeholder="Last Project Update"></div>
<div input [formInput]="stakeholderFb.get('index_id')"
placeholder="Index ID"></div>
</div>
</ng-container>
<div class="uk-width-1-3@m">
<div input [formInput]="stakeholderFb.get('locale')" [type]="'select'"
[options]="stakeholderUtils.locales"
placeholder="Locale"></div>
</div>
<div class="uk-width-1-1">
<div input [type]="'textarea'" placeholder="Description"
[rows]="4" [formInput]="stakeholderFb.get('description')"></div>
</div>
<div class="uk-width-1-1">
<input #file id="photo" type="file" class="uk-hidden" (change)="fileChangeEvent($event)"/>
<div *ngIf="!stakeholderFb.get('isUpload').value" class="uk-grid uk-grid-column-large" uk-grid>
<div class="uk-margin-top uk-width-auto@l uk-width-1-1">
<div class="uk-grid uk-grid-column-large uk-flex-middle" uk-grid>
<div class="uk-width-auto@l uk-width-1-1 uk-flex uk-flex-center">
<button class="uk-button uk-button-primary uk-flex uk-flex-middle uk-flex-wrap"
(click)="file.click()">
<icon name="cloud_upload" [flex]="true"></icon>
<span class="uk-margin-small-left">Upload a file</span>
</button>
</div>
<div class="uk-text-center uk-text-bold uk-width-expand">
OR
<div class="uk-width-1-3@m">
<div input [formInput]="stakeholderFb.get('index_name')"
placeholder="Index Name"></div>
</div>
<div class="uk-width-1-3@m">
<div input [formInput]="stakeholderFb.get('index_shortName')"
placeholder="Index Short Name"></div>
</div>
<ng-container *ngIf="isCurator">
<div class="uk-width-1-3@m">
<div *ngIf="statsProfiles" input [formInput]="stakeholderFb.get('statsProfile')"
[type]="'select'"
[options]="statsProfiles"
placeholder="Stats Profile"></div>
</div>
<div class="uk-width-1-3@m">
<div input [formInput]="stakeholderFb.get('projectUpdateDate')" [type]="'date'"
placeholder="Last Project Update"></div>
</div>
</ng-container>
<div class="uk-width-1-3@m">
<div input [formInput]="stakeholderFb.get('locale')" [type]="'select'"
[options]="stakeholderUtils.locales"
placeholder="Locale"></div>
</div>
<div class="uk-width-1-1">
<div input [type]="'textarea'" placeholder="Description"
[rows]="4" [formInput]="stakeholderFb.get('description')"></div>
</div>
<div class="uk-width-1-1">
<input #file id="photo" type="file" class="uk-hidden" (change)="fileChangeEvent($event)"/>
<div *ngIf="!stakeholderFb.get('isUpload').value" class="uk-grid uk-grid-column-large" uk-grid>
<div class="uk-margin-xsmall-top uk-width-auto@l uk-width-1-1">
<div class="uk-grid uk-grid-column-large uk-flex-middle" uk-grid>
<div class="uk-width-auto@l uk-width-1-1 uk-flex uk-flex-center">
<button class="uk-button uk-button-primary uk-flex uk-flex-middle uk-flex-wrap"
(click)="file.click()">
<icon name="cloud_upload" [flex]="true"></icon>
<span class="uk-margin-small-left">Upload a file</span>
</button>
</div>
<div class="uk-text-center uk-text-bold uk-width-expand">
OR
</div>
</div>
</div>
<div input class="uk-width-expand" type="logoURL" [placeholder]="'Link to the logo'"
[formInput]="stakeholderFb.get('logoUrl')"></div>
</div>
<div input class="uk-width-expand" type="logoURL" [placeholder]="'Link to the logo'"
[formInput]="stakeholderFb.get('logoUrl')"></div>
<div *ngIf="stakeholderFb.get('isUpload').value" class="uk-width-1-1 uk-flex uk-flex-middle">
<div class="uk-card uk-card-default uk-text-center uk-border-circle">
<img class="uk-position-center uk-blend-multiply" [src]="photo">
</div>
<div class="uk-margin-left">
<button (click)="remove()" class="uk-button-danger uk-icon-button uk-icon-button-small">
<icon [flex]="true" ratio="0.8" name="delete"></icon>
</button>
</div>
<div class="uk-margin-small-left">
<button class="uk-button-secondary uk-icon-button uk-icon-button-small"
(click)="file.click()">
<icon [flex]="true" ratio="0.8" name="edit"></icon>
</button>
</div>
</div>
<!-- Full width error message -->
<div *ngIf="uploadError"
class="uk-text-danger uk-margin-small-top uk-width-1-1">{{uploadError}}</div>
</div>
<div *ngIf="stakeholderFb.get('isUpload').value" class="uk-width-1-1 uk-flex uk-flex-middle">
<div class="uk-card uk-card-default uk-text-center uk-border-circle">
<img class="uk-position-center uk-blend-multiply" [src]="photo">
</div>
<div class="uk-margin-left">
<button (click)="remove()" class="uk-button-danger uk-icon-button uk-icon-button-small">
<icon [flex]="true" ratio="0.8" name="delete"></icon>
</button>
</div>
<div class="uk-margin-small-left">
<button class="uk-button-secondary uk-icon-button uk-icon-button-small"
(click)="file.click()">
<icon [flex]="true" ratio="0.8" name="edit"></icon>
</button>
<div class="uk-width-1-1">
<div class="uk-grid uk-child-width-expand@m uk-child-width-1-1" uk-grid>
<div *ngIf="showVisibility">
<div input [formInput]="stakeholderFb.get('visibility')"
[placeholder]="'Select a status'"
[options]="stakeholderUtils.visibilities" type="select"></div>
</div>
<div [class.uk-width-1-2@m]="!showVisibility && !showFunderType && !canChooseTemplate">
<div input [formInput]="stakeholderFb.get('type')"
[placeholder]="'Select a type of ' + entities.stakeholder"
[options]="typesByRole" type="select"></div>
</div>
<div *ngIf="showFunderType">
<div input [formInput]="stakeholderFb.get('funderType')"
[placeholder]="'Select a type of ' + entities.funder"
[options]="stakeholderUtils.funderTypes" type="select"></div>
</div>
<div *ngIf="canChooseTemplate">
<div [placeholder]="'Select a template'"
input [formInput]="stakeholderFb.get('defaultId')"
[options]="defaultStakeholdersOptions" type="select"></div>
</div>
</div>
</div>
<!-- Full width error message -->
<div *ngIf="uploadError" class="uk-text-danger uk-margin-small-top uk-width-1-1">{{uploadError}}</div>
</div>
<div [class]="canChooseTemplate ? 'uk-width-1-3@m' : 'uk-width-1-2@m'">
<div input [formInput]="stakeholderFb.get('visibility')"
[placeholder]="'Select a status'"
[options]="stakeholderUtils.statuses" type="select"></div>
</div>
<div [class]="canChooseTemplate ? 'uk-width-1-3@m' : 'uk-width-1-2@m'">
<div input [formInput]="stakeholderFb.get('type')"
[placeholder]="'Select a type'"
[options]="types" type="select"></div>
</div>
<ng-container *ngIf="canChooseTemplate">
<div class="uk-width-1-3@m">
<div [placeholder]="'Select a template'"
input [formInput]="stakeholderFb.get('defaultId')"
[options]="defaultStakeholdersOptions" type="select"></div>
</div>
</ng-container>
</div>
</form>
<div #notify [class.uk-hidden]="!stakeholderFb" notify-form
class="uk-width-1-1 uk-margin-large-top uk-margin-medium-bottom"></div>
</form>
<div #notify [class.uk-hidden]="!stakeholderFb" notify-form
class="uk-width-1-1 uk-margin-large-top"></div>
</div>
`,
styleUrls: ['edit-stakeholder.component.less']
})
export class EditStakeholderComponent implements OnDestroy {
export class EditStakeholderComponent extends StakeholderBaseComponent {
@Input()
public disableAlias: boolean = false;
public stakeholderFb: UntypedFormGroup;
public secure: boolean = false;
public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public defaultStakeholdersOptions: Option[];
public defaultStakeholders: Stakeholder[];
public alias: string[];
@ -138,10 +146,8 @@ export class EditStakeholderComponent implements OnDestroy {
public isDefault: boolean;
public isNew: boolean;
public loading: boolean = false;
public types: Option[];
public typesByRole: Option[];
public statsProfiles: string[];
public properties: EnvProperties = properties;
private subscriptions: any[] = [];
/**
* Photo upload
* */
@ -153,21 +159,26 @@ export class EditStakeholderComponent implements OnDestroy {
user: User;
@ViewChild('notify', {static: true}) notify: NotifyFormComponent;
private notification: Notification;
constructor(private fb: UntypedFormBuilder,
private stakeholderService: StakeholderService,
private statsProfileService: StatsProfilesService,
private utilsService: UtilitiesService, private userManagementService: UserManagementService,) {
super();
}
ngOnDestroy() {
this.reset();
super.ngOnDestroy();
}
public init(stakeholder: Stakeholder, alias: string[], defaultStakeholders: Stakeholder[], isDefault: boolean, isNew: boolean) {
this.reset();
this.deleteCurrentPhoto = false;
this.stakeholder = stakeholder;
if (this.stakeholderUtils.defaultValue(this.stakeholderUtils.visibilities)) {
this.stakeholder.visibility = this.stakeholderUtils.defaultValue(this.stakeholderUtils.visibilities);
}
this.alias = alias;
this.defaultStakeholders = defaultStakeholders;
this.isDefault = isDefault;
@ -183,7 +194,7 @@ export class EditStakeholderComponent implements OnDestroy {
} else {
this.statsProfiles = [];
}
this.types = this.stakeholderUtils.getTypesByUserRoles(this.user, this.stakeholder.alias);
this.typesByRole = this.stakeholderUtils.getTypesByUserRoles(this.user, this.stakeholder.alias);
this.stakeholderFb = this.fb.group({
_id: this.fb.control(this.stakeholder._id),
defaultId: this.fb.control(this.stakeholder.defaultId),
@ -197,15 +208,16 @@ export class EditStakeholderComponent implements OnDestroy {
projectUpdateDate: this.fb.control(this.stakeholder.projectUpdateDate),
creationDate: this.fb.control(this.stakeholder.creationDate),
alias: this.fb.control(this.stakeholder.alias,
[
Validators.required,
this.stakeholderUtils.aliasValidatorString(
this.alias.filter(alias => alias !== this.stakeholder.alias)
)]
[
Validators.required,
this.stakeholderUtils.aliasValidatorString(
this.alias.filter(alias => alias !== this.stakeholder.alias)
)]
),
isDefault: this.fb.control((this.isDefault)),
visibility: this.fb.control(this.stakeholder.visibility, Validators.required),
type: this.fb.control(this.stakeholder.type, Validators.required),
funderType: this.fb.control(this.stakeholder.funderType),
topics: this.fb.control(this.stakeholder.topics),
isUpload: this.fb.control(this.stakeholder.isUpload),
logoUrl: this.fb.control(this.stakeholder.logoUrl),
@ -234,7 +246,7 @@ export class EditStakeholderComponent implements OnDestroy {
this.subscriptions.push(this.stakeholderFb.get('type').valueChanges.subscribe(value => {
this.onTypeChange(value, defaultStakeholders);
}));
this.stakeholderFb.setControl('defaultId', this.fb.control(stakeholder.defaultId, (this.isDefault && !this.isNew)?[]:Validators.required));
this.stakeholderFb.setControl('defaultId', this.fb.control(stakeholder.defaultId, (this.isDefault && !this.isNew) ? [] : Validators.required));
if (!this.isNew) {
this.notification = NotificationUtils.editStakeholder(this.user.firstname + ' ' + this.user.lastname, this.stakeholder.name);
this.notify.reset(this.notification.message);
@ -269,29 +281,29 @@ export class EditStakeholderComponent implements OnDestroy {
}
}));
}
public get isAdmin() {
return Session.isPortalAdministrator(this.user);
}
public get isCurator() {
return this.stakeholder && (this.isAdmin || Session.isCurator(this.stakeholder.type, this.user));
}
public get disabled(): boolean {
return (this.stakeholderFb && this.stakeholderFb.invalid) ||
(this.stakeholderFb && this.stakeholderFb.pristine && !this.isNew && !this.file) ||
(this.uploadError && this.uploadError.length > 0);
(this.stakeholderFb && this.stakeholderFb.pristine && !this.isNew && !this.file) ||
(this.uploadError && this.uploadError.length > 0);
}
public get dirty(): boolean {
return this.stakeholderFb && this.stakeholderFb.dirty;
}
public get canChooseTemplate(): boolean {
return this.isNew && this.stakeholderFb.get('type').valid && !!this.defaultStakeholdersOptions;
}
reset() {
this.uploadError = null;
this.stakeholderFb = null;
@ -301,9 +313,9 @@ export class EditStakeholderComponent implements OnDestroy {
}
});
}
onTypeChange(value, defaultStakeholders: Stakeholder[]) {
this.stakeholderFb.setControl('defaultId', this.fb.control(this.stakeholder.defaultId, (this.isDefault && !this.isNew)?[]:Validators.required));
this.stakeholderFb.setControl('defaultId', this.fb.control(this.stakeholder.defaultId, (this.isDefault && !this.isNew) ? [] : Validators.required));
this.defaultStakeholdersOptions = [{
label: 'New blank profile',
value: '-1'
@ -315,7 +327,7 @@ export class EditStakeholderComponent implements OnDestroy {
})
});
}
public save(callback: Function, errorCallback: Function = null) {
this.loading = true;
if (this.file) {
@ -335,14 +347,14 @@ export class EditStakeholderComponent implements OnDestroy {
this.saveStakeholder(callback, errorCallback);
}
}
public saveStakeholder(callback: Function, errorCallback: Function = null) {
if (this.isNew) {
let defaultStakeholder = this.defaultStakeholders.find(value => value._id === this.stakeholderFb.getRawValue().defaultId);
this.stakeholderFb.setValue(this.stakeholderUtils.createFunderFromDefaultProfile(this.stakeholderFb.getRawValue(),
(defaultStakeholder ? defaultStakeholder.topics : []), this.stakeholderFb.getRawValue().isDefault));
(defaultStakeholder ? defaultStakeholder.topics : []), this.stakeholderFb.getRawValue().isDefault));
this.removePhoto();
if(this.stakeholderFb.getRawValue().isDefault) {
if (this.stakeholderFb.getRawValue().isDefault) {
this.stakeholderFb.get('defaultId').setValue(null);
}
this.subscriptions.push(this.stakeholderService.buildStakeholder(this.properties.monitorServiceAPIURL,
@ -381,7 +393,7 @@ export class EditStakeholderComponent implements OnDestroy {
}));
}
}
fileChangeEvent(event) {
if (event.target.files && event.target.files[0]) {
this.file = event.target.files[0];
@ -407,13 +419,13 @@ export class EditStakeholderComponent implements OnDestroy {
}
}
}
initPhoto() {
if (this.stakeholderFb.getRawValue().isUpload) {
this.photo = this.properties.utilsService + "/download/" + this.stakeholderFb.get('logoUrl').value;
}
}
removePhoto() {
if (this.file) {
if (typeof document != 'undefined') {
@ -423,7 +435,7 @@ export class EditStakeholderComponent implements OnDestroy {
this.file = null;
}
}
remove() {
this.stakeholderFb.get('isUpload').setValue(false);
this.stakeholderFb.get('isUpload').markAsDirty();
@ -433,11 +445,15 @@ export class EditStakeholderComponent implements OnDestroy {
this.deleteCurrentPhoto = true;
}
}
public deletePhoto() {
if (this.stakeholder.logoUrl && this.stakeholder.isUpload) {
this.subscriptions.push(this.utilsService.deletePhoto(this.properties.utilsService + '/delete/' +
encodeURIComponent(this.stakeholder.type) + "/" + encodeURIComponent(this.stakeholder.alias) + "/" + this.stakeholder.logoUrl).subscribe());
encodeURIComponent(this.stakeholder.type) + "/" + encodeURIComponent(this.stakeholder.alias) + "/" + this.stakeholder.logoUrl).subscribe());
}
}
get showFunderType() {
return super.showFunderType && this.stakeholderFb?.get('type').value === 'funder' && !this.isDefault;
}
}

View File

@ -1,29 +1,28 @@
import {ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild} from "@angular/core";
import {ChangeDetectorRef, Component, OnInit, ViewChild} from "@angular/core";
import {StakeholderService} from "../../monitor/services/stakeholder.service";
import {EnvProperties} from "../../utils/properties/env-properties";
import {Stakeholder} from "../../monitor/entities/stakeholder";
import { Subscription, zip} from "rxjs";
import {zip} from "rxjs";
import {EditStakeholderComponent} from "./edit-stakeholder/edit-stakeholder.component";
import {properties} from "src/environments/environment";
import {Title} from "@angular/platform-browser";
import {BaseComponent} from "../../sharedComponents/base/base.component";
import {ActivatedRoute} from "@angular/router";
@Component({
selector: 'general',
templateUrl: "./general.component.html"
})
export class GeneralComponent implements OnInit, OnDestroy {
export class GeneralComponent extends BaseComponent implements OnInit {
public stakeholder: Stakeholder;
public alias: string[];
public properties: EnvProperties = properties;
public defaultStakeholders: Stakeholder[];
public loading: boolean = false;
private subscriptions: any[] = [];
@ViewChild('editStakeholderComponent') editStakeholderComponent: EditStakeholderComponent;
constructor(private stakeholderService: StakeholderService,
private cdr: ChangeDetectorRef,
private title: Title) {
protected _route: ActivatedRoute,
protected _title: Title) {
super();
}
ngOnInit() {
@ -32,7 +31,8 @@ export class GeneralComponent implements OnInit, OnDestroy {
this.stakeholder = stakeholder;
this.cdr.detectChanges();
if(this.stakeholder) {
this.title.setTitle(this.stakeholder.name + " | General");
this.title = this.stakeholder.name + " | General";
this.setMetadata();
let data = zip(
this.stakeholderService.getDefaultStakeholders(this.properties.monitorServiceAPIURL),
this.stakeholderService.getAlias(this.properties.monitorServiceAPIURL)
@ -51,10 +51,9 @@ export class GeneralComponent implements OnInit, OnDestroy {
this.editStakeholderComponent.init(this.stakeholder, this.alias, this.defaultStakeholders, this.stakeholder.defaultId == null, false)
}
public save() {
this.loading = true;
this.editStakeholderComponent.save((stakeholder) => {
this.editStakeholderComponent.save(stakeholder => {
this.stakeholder = stakeholder;
this.stakeholderService.setStakeholder(this.stakeholder);
this.reset();
@ -64,12 +63,4 @@ export class GeneralComponent implements OnInit, OnDestroy {
this.loading = false;
});
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if(subscription instanceof Subscription) {
subscription.unsubscribe();
}
});
}
}

View File

@ -60,7 +60,7 @@
<div class="uk-card uk-card-default uk-card-body uk-position-relative" [ngClass]="stakeholder.type">
<div class="uk-position-top-right uk-margin-small-right uk-margin-small-top">
<a class="uk-link-reset uk-flex uk-flex-middle">
<icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(stakeholder.visibility)" ratio="0.6"></icon>
<icon *ngIf="showVisibility" [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(stakeholder.visibility)" ratio="0.6"></icon>
<icon [flex]="true" name="more_vert"></icon>
</a>
<div #element class="uk-dropdown" uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0;">
@ -71,8 +71,8 @@
<li *ngIf="isCurator">
<a (click)="createReport(stakeholder);hide(element)">Cache Indicators</a>
</li>
<li class="uk-nav-divider"></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<li *ngIf="showVisibility" class="uk-nav-divider"></li>
<ng-template *ngIf="showVisibility" ngFor [ngForOf]="stakeholderUtils.visibilities" let-v>
<li [class.uk-active]="stakeholder.visibility === v.value">
<a (click)="changeStakeholderStatus(stakeholder, v.value);hide(element)">
<div class="uk-flex uk-flex-middle">

View File

@ -1,9 +1,7 @@
import {Component, OnDestroy, OnInit, ViewChild} from "@angular/core";
import {StakeholderService} from "../../monitor/services/stakeholder.service";
import {EnvProperties} from "../../utils/properties/env-properties";
import {Stakeholder, StakeholderEntities, Visibility} from "../../monitor/entities/stakeholder";
import {Subscriber, zip} from "rxjs";
import {StakeholderUtils} from "../utils/indicator-utils";
import {Stakeholder, Visibility} from "../../monitor/entities/stakeholder";
import {zip} from "rxjs";
import {UntypedFormBuilder, UntypedFormGroup} from "@angular/forms";
import {AlertModal} from "../../utils/modal/alert";
import {Option} from "../../sharedComponents/input/input.component";
@ -11,11 +9,10 @@ import {Title} from "@angular/platform-browser";
import {UserManagementService} from "../../services/user-management.service";
import {Session} from "../../login/utils/helper.class";
import {EditStakeholderComponent} from "../general/edit-stakeholder/edit-stakeholder.component";
import {properties} from "src/environments/environment";
import {ActivatedRoute} from "@angular/router";
import {CacheIndicatorsService} from "../utils/cache-indicators/cache-indicators.service";
import {NotificationHandler} from "../../utils/notification-handler";
import {BaseComponent} from "../../sharedComponents/base/base.component";
import {StakeholderBaseComponent} from "../utils/stakeholder-base.component";
type Tab = 'all' | 'templates'| 'profiles';
@ -26,10 +23,9 @@ declare var UIkit;
templateUrl: "./manageStakeholders.component.html",
styleUrls: ["./manageStakeholders.component.less"]
})
export class ManageStakeholdersComponent extends BaseComponent implements OnInit, OnDestroy {
export class ManageStakeholdersComponent extends StakeholderBaseComponent implements OnInit, OnDestroy {
public loading: boolean = true;
public deleteLoading: boolean = false;
public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public defaultStakeholders: Stakeholder[];
public stakeholders: Stakeholder[];
public alias: string[];
@ -283,17 +279,4 @@ export class ManageStakeholdersComponent extends BaseComponent implements OnInit
return this.stakeholderUtils.types.slice(0, this.stakeholderUtils.types.length - 1).map(type => type.label).join(', ') +
' or ' + this.stakeholderUtils.types[this.stakeholderUtils.types.length - 1].label
}
private isTab(tab: Tab): boolean {
switch (tab) {
case "all":
return true;
case "profiles":
return true;
case "templates":
return true;
default:
return false;
}
}
}

View File

@ -39,26 +39,28 @@
<div *ngIf="!dragging"
class="uk-position-top-right uk-margin-small-right uk-margin-small-top">
<a class="uk-link-reset uk-flex uk-flex-middle" [class.uk-disabled]="editing">
<icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)" ratio="0.6"></icon>
<icon *ngIf="showVisibility" [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)" ratio="0.6"></icon>
<icon [flex]="true" name="more_vert"></icon>
</a>
<div #element class="uk-dropdown" uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0">
<ul class="uk-nav uk-dropdown-nav">
<ng-container *ngIf="isCurator">
<li><a (click)="editNumberIndicatorOpen(number, indicator._id); hide(element)">Edit</a></li>
<li class="uk-nav-divider"></li>
</ng-container>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<li>
<a (click)="changeIndicatorStatus(number._id, indicator, v.value);hide(element)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" [name]="v.icon" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">{{v.label}}</span>
<icon *ngIf="indicator.visibility === v.value" [flex]="true" name="done" class="uk-text-secondary" ratio="0.8"></icon>
</div>
</a>
</li>
</ng-template>
<ng-container *ngIf="showVisibility">
<li *ngIf="isCurator" class="uk-nav-divider"></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibilities" let-v>
<li>
<a (click)="changeIndicatorStatus(number._id, indicator, v.value);hide(element)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" [name]="v.icon" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">{{v.label}}</span>
<icon *ngIf="indicator.visibility === v.value" [flex]="true" name="done" class="uk-text-secondary" ratio="0.8"></icon>
</div>
</a>
</li>
</ng-template>
</ng-container>
<ng-container *ngIf="!indicator.defaultId && !editing && isCurator">
<li class="uk-nav-divider">
<li><a (click)="deleteIndicatorOpen(number, indicator._id, 'number', 'delete');hide(element)">Delete</a></li>
@ -136,26 +138,28 @@
<div *ngIf="!dragging"
class="uk-position-top-right uk-margin-small-right uk-margin-small-top">
<a class="uk-link-reset uk-flex uk-flex-middle" [class.uk-disabled]="editing">
<icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)" ratio="0.6"></icon>
<icon *ngIf="showVisibility" [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)" ratio="0.6"></icon>
<icon [flex]="true" name="more_vert"></icon>
</a>
<div #element class="uk-dropdown" uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0">
<ul class="uk-nav uk-dropdown-nav">
<ng-container *ngIf="isCurator">
<li><a (click)="editChartIndicatorOpen(chart, indicator._id); hide(element)">Edit</a></li>
<li class="uk-nav-divider"></li>
</ng-container>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<li>
<a (click)="changeIndicatorStatus(chart._id, indicator, v.value);">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" [name]="v.icon" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">{{v.label}}</span>
<icon *ngIf="indicator.visibility === v.value" [flex]="true" name="done" class="uk-text-secondary" ratio="0.8"></icon>
</div>
</a>
</li>
</ng-template>
<ng-container *ngIf="showVisibility">
<li *ngIf="isCurator" class="uk-nav-divider"></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibilities" let-v>
<li>
<a (click)="changeIndicatorStatus(chart._id, indicator, v.value);">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" [name]="v.icon" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">{{v.label}}</span>
<icon *ngIf="indicator.visibility === v.value" [flex]="true" name="done" class="uk-text-secondary" ratio="0.8"></icon>
</div>
</a>
</li>
</ng-template>
</ng-container>
<ng-container *ngIf="!indicator.defaultId && !editing && isCurator">
<li class="uk-nav-divider">
<li><a (click)="deleteIndicatorOpen(chart, indicator._id, 'chart', 'delete');hide(element)">Delete</a></li>
@ -231,8 +235,8 @@
<div input class="uk-width-1-1" *ngIf="stakeholder.defaultId" [formInput]="numberIndicatorFb.get('additionalDescription')"
placeholder="Description" type="textarea">
</div>
<div input class="uk-width-1-2@m" [formInput]="numberIndicatorFb.get('visibility')"
placeholder="Visibility" [options]="stakeholderUtils.visibility" type="select">
<div *ngIf="showVisibility" input class="uk-width-1-2@m" [formInput]="numberIndicatorFb.get('visibility')"
placeholder="Visibility" [options]="stakeholderUtils.visibilities" type="select">
</div>
<div input class="uk-width-1-2@m" [formInput]="numberIndicatorFb.get('width')"
placeholder="Number Size" [options]="indicatorUtils.indicatorSizes" type="select">
@ -346,8 +350,8 @@
<div *ngIf="stakeholder.defaultId" input class="uk-width-1-1" [formInput]="chartIndicatorFb.get('additionalDescription')"
placeholder="Description" type="textarea">
</div>
<div input class="uk-width-1-2@m" [formInput]="chartIndicatorFb.get('visibility')"
placeholder="Status" [options]="stakeholderUtils.visibility" type="select">
<div *ngIf="showVisibility" input class="uk-width-1-2@m" [formInput]="chartIndicatorFb.get('visibility')"
placeholder="Status" [options]="stakeholderUtils.visibilities" type="select">
</div>
<div input class="uk-width-1-2@m" [formInput]="chartIndicatorFb.get('width')" placeholder="Chart width"
[options]="indicatorUtils.indicatorSizes" type="select">

View File

@ -5,7 +5,6 @@ import {
HostListener,
Input,
OnChanges,
OnDestroy,
OnInit,
SimpleChanges,
ViewChild
@ -20,7 +19,6 @@ import {
Stakeholder,
Visibility
} from "../../monitor/entities/stakeholder";
import {IndicatorUtils, StakeholderUtils} from "../utils/indicator-utils";
import {
AbstractControl,
UntypedFormArray,
@ -34,7 +32,6 @@ import {StatisticsService} from "../utils/services/statistics.service";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser";
import {Reorder, StakeholderService} from "../../monitor/services/stakeholder.service";
import {EnvProperties} from "../../utils/properties/env-properties";
import {Observable, Subscriber} from "rxjs";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {Router} from "@angular/router";
@ -44,8 +41,8 @@ import {Notification} from "../../notifications/notifications";
import {NotificationUtils} from "../../notifications/notification-utils";
import {NotifyFormComponent} from "../../notifications/notify-form/notify-form.component";
import {NotificationService} from "../../notifications/notification.service";
import {properties} from "src/environments/environment";
import {NotificationHandler} from "../../utils/notification-handler";
import {IndicatorStakeholderBaseComponent} from "../utils/stakeholder-base.component";
declare var UIkit;
@ -54,10 +51,9 @@ declare var UIkit;
templateUrl: './indicators.component.html',
styleUrls: ['indicators.component.less']
})
export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
export class IndicatorsComponent extends IndicatorStakeholderBaseComponent implements OnInit, OnChanges, AfterViewInit {
filesToUpload: Array<File>;
errorMessage = "";
public properties: EnvProperties = properties;
@Input()
public topicIndex: number = 0;
@Input()
@ -71,8 +67,6 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
@Input()
public user: User = null;
public preview: string;
public indicatorUtils: IndicatorUtils = new IndicatorUtils();
public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public numberIndicatorFb: UntypedFormGroup;
public chartIndicatorFb: UntypedFormGroup;
public chartSections: UntypedFormArray;
@ -118,7 +112,6 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
/**
* Subscriptions
**/
private subscriptions: any[] = [];
private urlSubscriptions: any[] = [];
private numberSubscription: any[] = [];
@ -127,9 +120,10 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
private statisticsService: StatisticsService,
private notificationService: NotificationService,
private fb: UntypedFormBuilder,
private router: Router,
protected _router: Router,
private cdr: ChangeDetectorRef,
private sanitizer: DomSanitizer) {
super()
this.filesToUpload = [];
}
@ -146,13 +140,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
}
ngOnDestroy(): void {
this.subscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();
} else if (value instanceof Function) {
value();
}
});
super.ngOnDestroy();
this.urlSubscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();

View File

@ -26,12 +26,11 @@
<span class="uk-margin-xsmall-left hide-on-close" [class.uk-invisible-hover]="topicIndex !== i"
(click)="$event.stopPropagation();$event.preventDefault()">
<a class="uk-link-reset uk-flex uk-flex-middle">
<icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(topic.visibility)"
<icon *ngIf="showVisibility" [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(topic.visibility)"
ratio="0.6"></icon>
<icon [flex]="true" name="more_vert"></icon>
</a>
<div #element
uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0; flip: false; container: body">
<div #element uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0; flip: false; container: body">
<ul class="uk-nav uk-dropdown-nav">
<ng-container *ngIf="isCurator">
<li>
@ -59,9 +58,10 @@
</div>
</a>
</li>
<li class="uk-nav-divider"></li>
</ng-container>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<ng-container *ngIf="showVisibility">
<li *ngIf="isCurator" class="uk-nav-divider"></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibilities" let-v>
<li [class.uk-active]="topic.visibility === v.value">
<a (click)="openVisibilityModal(i, v.value, 'topic'); hide(element)">
<div class="uk-flex uk-flex-middle">
@ -73,6 +73,7 @@
</a>
</li>
</ng-template>
</ng-container>
<ng-container *ngIf="!topic.defaultId && isCurator">
<li class="uk-nav-divider">
<li>
@ -103,7 +104,7 @@
<span class="uk-margin-xsmall-left hide-on-close" [class.uk-invisible-hover]="categoryIndex !== j"
(click)="$event.stopPropagation();$event.preventDefault()">
<a class="uk-link-reset uk-flex uk-flex-middle">
<icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(category.visibility)"
<icon *ngIf="showVisibility" [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(category.visibility)"
ratio="0.6"></icon>
<icon [flex]="true" name="more_vert"></icon>
</a>
@ -137,9 +138,11 @@
</div>
</a>
</li>
<li class="uk-nav-divider"></li>
</ng-container>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<ng-container *ngIf="showVisibility">
<li *ngIf="isCurator" class="uk-nav-divider"></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibilities" let-v>
<li [class.uk-active]="category.visibility === v.value">
<a (click)="openVisibilityModal(j, v.value, 'category'); hide(element)">
<div class="uk-flex uk-flex-middle">
@ -151,6 +154,7 @@
</a>
</li>
</ng-template>
</ng-container>
<ng-container *ngIf="!category.defaultId && isCurator">
<li class="uk-nav-divider">
<li>
@ -191,8 +195,8 @@
</div>
</aside>
<div #pageContent *ngIf="stakeholder && filters" class="uk-width-1-1" page-content>
<div actions>
<div *ngIf="stakeholder.topics.length > 0" class="uk-flex uk-flex-center uk-margin-medium-top uk-flex-right@m uk-width-1-1">
<div actions class="uk-margin-medium-top">
<div *ngIf="stakeholder.topics.length > 0 && showVisibility" class="uk-flex uk-flex-center uk-flex-right@m uk-width-1-1">
<button class="uk-button uk-button-primary uk-flex uk-flex-middle">
<icon name="visibility" [flex]="true"></icon>
<span class="uk-margin-small-left uk-margin-small-right">Preview</span>
@ -229,7 +233,7 @@
[class.uk-invisible-hover]="subCategoryIndex !== i"
(click)="$event.stopPropagation();$event.preventDefault()">
<a class="uk-link-reset uk-flex uk-flex-middle">
<icon [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(subCategory.visibility)"
<icon *ngIf="showVisibility" [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(subCategory.visibility)"
ratio="0.6"></icon>
<icon [flex]="true" name="more_vert"></icon>
</a>
@ -279,9 +283,10 @@
</div>
</a>
</li>
<li class="uk-nav-divider"></li>
</ng-container>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<ng-container *ngIf="showVisibility">
<li *ngIf="isCurator" class="uk-nav-divider"></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibilities" let-v>
<li [class.uk-active]="subCategory.visibility === v.value">
<a (click)="openVisibilityModal(i, v.value, 'subcategory'); hide(element)">
<div class="uk-flex uk-flex-middle">
@ -293,6 +298,7 @@
</a>
</li>
</ng-template>
</ng-container>
<ng-container *ngIf="!subCategory.defaultId && isCurator">
<li class="uk-nav-divider">
<li>
@ -348,8 +354,8 @@
<div *ngIf="form" [class.uk-hidden]="loading"
class="uk-grid uk-padding uk-padding-remove-horizontal uk-child-width-1-1" [formGroup]="form" uk-grid>
<div input [formInput]="form.get('name')" class="uk-width-1-2@m" placeholder="Title"></div>
<div input [formInput]="form.get('visibility')" class="uk-width-1-2@m" placeholder="Status"
[options]="stakeholderUtils.visibility" type="select"></div>
<div *ngIf="showVisibility" input [formInput]="form.get('visibility')" class="uk-width-1-2@m" placeholder="Status"
[options]="stakeholderUtils.visibilities" type="select"></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>

View File

@ -1,32 +1,32 @@
import {
AfterViewInit,
ChangeDetectorRef,
Component, Inject,
Component,
Inject,
OnDestroy,
OnInit, PLATFORM_ID,
OnInit,
PLATFORM_ID,
QueryList,
ViewChild,
ViewChildren
} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Title} from '@angular/platform-browser';
import {EnvProperties} from '../../utils/properties/env-properties';
import {Category, Stakeholder, SubCategory, Topic, Visibility} from "../../monitor/entities/stakeholder";
import {StakeholderService} from "../../monitor/services/stakeholder.service";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {AlertModal} from "../../utils/modal/alert";
import {BehaviorSubject, Subject, Subscriber, Subscription} from "rxjs";
import {UntypedFormBuilder, UntypedFormGroup, Validators} from "@angular/forms";
import {StakeholderUtils} from "../utils/indicator-utils";
import {StringUtils} from "../../utils/string-utils.class";
import {IDeactivateComponent} from "../../utils/can-exit.guard";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {Option} from "../../sharedComponents/input/input.component";
import {properties} from "src/environments/environment";
import {Session, User} from "../../login/utils/helper.class";
import {UserManagementService} from "../../services/user-management.service";
import {TransitionGroupComponent} from "../../utils/transition-group/transition-group.component";
import {NotificationHandler} from "../../utils/notification-handler";
import {StakeholderBaseComponent} from "../utils/stakeholder-base.component";
declare var UIkit;
@ -34,12 +34,9 @@ declare var UIkit;
selector: 'topic',
templateUrl: './topic.component.html',
})
export class TopicComponent implements OnInit, OnDestroy, AfterViewInit, IDeactivateComponent {
export class TopicComponent extends StakeholderBaseComponent implements OnInit, OnDestroy, AfterViewInit, IDeactivateComponent {
private topicSubscriptions: any[] = [];
private subscriptions: any[] = [];
public properties: EnvProperties = properties;
public offset: number;
public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public loading: boolean = false;
public stakeholder: Stakeholder;
public user: User;
@ -84,15 +81,15 @@ export class TopicComponent implements OnInit, OnDestroy, AfterViewInit, IDeacti
};
constructor(
private route: ActivatedRoute,
private router: Router,
private title: Title,
protected _route: ActivatedRoute,
protected _router: Router,
protected _title: Title,
private fb: UntypedFormBuilder,
private stakeholderService: StakeholderService,
private userManagementService: UserManagementService,
private layoutService: LayoutService,
private cdr: ChangeDetectorRef,
protected cdr: ChangeDetectorRef,
@Inject(PLATFORM_ID) private platformId) {
super();
}
public ngOnInit() {
@ -115,7 +112,7 @@ export class TopicComponent implements OnInit, OnDestroy, AfterViewInit, IDeacti
this.subCategoryIndex = index;
});
}));
this.subscriptions.push(this.route.params.subscribe(params => {
this.subscriptions.push(this._route.params.subscribe(params => {
if (subscription) {
subscription.unsubscribe();
}
@ -136,7 +133,8 @@ export class TopicComponent implements OnInit, OnDestroy, AfterViewInit, IDeacti
if (this.topicIndex === -1) {
this.navigateToError();
} else {
this.title.setTitle(stakeholder.name + " | Indicators");
this.title = stakeholder.name + " | Indicators"
this.setMetadata();
}
}
});
@ -146,7 +144,7 @@ export class TopicComponent implements OnInit, OnDestroy, AfterViewInit, IDeacti
this.user = user;
}))
}
ngAfterViewInit() {
if(this.topics) {
let activeIndex = UIkit.nav(this.topics.element.nativeElement).items.findIndex(item => item.classList.contains('uk-open'));
@ -163,16 +161,12 @@ export class TopicComponent implements OnInit, OnDestroy, AfterViewInit, IDeacti
}
public ngOnDestroy() {
super.ngOnDestroy();
this.topicSubscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();
}
});
this.subscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();
}
});
}
canExit(): boolean {
@ -666,7 +660,7 @@ export class TopicComponent implements OnInit, OnDestroy, AfterViewInit, IDeacti
}
private navigateToError() {
this.router.navigate([this.properties.errorLink], {queryParams: {'page': this.router.url}});
this._router.navigate([this.properties.errorLink], {queryParams: {'page': this._router.url}});
}
get isCurator(): boolean {
@ -714,8 +708,8 @@ export class TopicComponent implements OnInit, OnDestroy, AfterViewInit, IDeacti
this.editModal.cancel();
NotificationHandler.rise(message);
if (redirect) {
this.router.navigate(['../' + saveElement.alias], {
relativeTo: this.route
this._router.navigate(['../' + saveElement.alias], {
relativeTo: this._route
});
}
}, error => {
@ -758,8 +752,8 @@ export class TopicComponent implements OnInit, OnDestroy, AfterViewInit, IDeacti
}
back() {
this.router.navigate(['../'], {
relativeTo: this.route
this._router.navigate(['../'], {
relativeTo: this._route
});
}
@ -774,19 +768,6 @@ export class TopicComponent implements OnInit, OnDestroy, AfterViewInit, IDeacti
return this.type;
}
}
public get isSmallScreen() {
return this.layoutService.isSmallScreen;
}
public get open() {
return this.layoutService.open;
}
public toggleOpen(event: MouseEvent) {
event.preventDefault();
this.layoutService.setOpen(!this.open);
}
public openVisibilityModal(index: number, visibility: Visibility, type: any) {
this.index = index;

View File

@ -7,11 +7,9 @@ import {
IndicatorPathType,
IndicatorType,
SourceType,
Stakeholder,
StakeholderEntities,
SubCategory,
Topic, stakeholderTypes,
Visibility
Stakeholder, SubCategory,
Topic,
Visibility,
} from "../../monitor/entities/stakeholder";
import {AbstractControl, ValidatorFn, Validators} from "@angular/forms";
import {Option} from "../../sharedComponents/input/input.component";
@ -19,35 +17,72 @@ import {Session} from "../../login/utils/helper.class";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {properties} from "src/environments/environment";
export class StakeholderUtils {
statuses: Option[] = [
{value: 'PUBLIC', label: 'Public'},
{value: 'RESTRICTED', label: 'Restricted'},
{value: 'PRIVATE', label: 'Private'}
class Entities {
stakeholder = 'Dashboard';
funder = 'Funder';
ri = 'Research Initiative';
organization = 'Research Institution';
project = 'Project';
country = 'National';
stakeholders = 'Dashboards';
funders = 'Funders';
ris = 'Research Initiatives';
organizations = 'Research Institutions';
projects = 'Projects';
}
export class StakeholderConfiguration {
public static ENTITIES: Entities = new Entities();
public static TYPES: Option[] = [
{value: 'funder', label: StakeholderConfiguration.ENTITIES.funder},
{value: 'ri', label: StakeholderConfiguration.ENTITIES.ri},
{value: 'organization', label: StakeholderConfiguration.ENTITIES.organization},
{value: 'project', label: StakeholderConfiguration.ENTITIES.project}
];
types: Option[] = [
...stakeholderTypes
public static LOCALES: Option[] = [
{value: "en", label: 'English'},
{value: "eu", label: 'Europe'}
];
visibility: Option[] = [
public static FUNDER_TYPES: Option[] = [];
public static VISIBILITIES: Option[] = [
{icon: 'earth', value: "PUBLIC", label: 'Public'},
{icon: 'restricted', value: "RESTRICTED", label: 'Restricted'},
{icon: 'incognito', value: "PRIVATE", label: 'Private'},
];
locales: Option[] = [
{value: "en", label: 'English'},
{value: "eu", label: 'Europe'}
];
visibilityIcon: Map<Visibility, string> = new Map<Visibility, string>([
["PUBLIC", 'earth'],
["PRIVATE", 'incognito'],
["RESTRICTED", 'restricted']
]);
}
export class StakeholderUtils {
get entities() {
return StakeholderConfiguration.ENTITIES;
}
get types() {
return StakeholderConfiguration.TYPES
}
get funderTypes() {
return StakeholderConfiguration.FUNDER_TYPES;
}
get locales() {
return StakeholderConfiguration.LOCALES;
}
get visibilities() {
return StakeholderConfiguration.VISIBILITIES;
}
visibilityIcon: Map<Visibility, string> = new Map<Visibility, string>(this.visibilities.map(option => [option.value, option.icon]));
defaultValue(options: Option[]) {
return options.length === 1?options[0].value:null;
}
showField(options: Option[]) {
return options.length > 1;
}
getTypesByUserRoles(user, id: string = null): Option[] {
let types = [];
for (let type of this.types) {
@ -57,7 +92,7 @@ export class StakeholderUtils {
}
return types;
}
public createFunderFromDefaultProfile(funder: Stakeholder, defaultTopics: Topic[], isDefault: boolean = false): Stakeholder {
funder.topics = HelperFunctions.copy(defaultTopics);
for (let topic of funder.topics) {
@ -105,36 +140,36 @@ export class StakeholderUtils {
indicator._id = null;
}
}
}
category.subCategories = subTokeep;
}
}
return funder;
}
aliasValidatorString(elements: string[]): ValidatorFn {
return (control: AbstractControl): { [key: string]: string } | null => {
if (control.value && elements.find(element =>
element === control.value
element === control.value
)) {
return {'error': 'Alias already in use'};
}
return null;
}
}
aliasValidator(elements: any[]): ValidatorFn {
return (control: AbstractControl): { [key: string]: string } | null => {
if (control.value && elements.find(element =>
element.alias === control.value
element.alias === control.value
)) {
return {'error': 'Alias already in use'};
}
return null;
}
}
generateAlias(name: string): string {
let alias = name.toLowerCase();
while (alias.includes('/') || alias.includes(' ')) {
@ -147,7 +182,7 @@ export class StakeholderUtils {
}
export class IndicatorUtils {
allChartTypes: Option[] = [
{value: 'pie', label: 'Pie'},
{value: 'table', label: 'Table'},
@ -163,64 +198,64 @@ export class IndicatorUtils {
{value: 'medium', label: 'Medium'},
{value: 'large', label: 'Large'}
];
allSourceTypes: Option[] = [
{value: 'search', label: 'Search'},
{value: 'statistics', label: 'Statistics'},
{value: 'stats-tool', label: 'Statistics tool'}
];
formats: Option[] = [
{value: "NUMBER", label: "Number"},
{value: "PERCENTAGE", label: "Percentage"}
];
sourceTypes: Option[] = [
{value: 'stats-tool', label: 'Statistics tool'}
];
isActive: Option[] = [
{icon: 'brightness_1', iconClass: '', value: true, label: 'Active'},
{icon: 'brightness_1', value: false, label: 'Inactive'},
];
parametersValidators: Map<string, any> = new Map<string, any>([
['start_year', [Validators.required, Validators.pattern('^\\d+$')]],
['end_year', [Validators.required, Validators.pattern('^\\d+$')]]
]);
ignoredParameters = ['index_name', 'index_id', 'index_shortName'];
statsProfileParameter = 'profile';
numberSources: Map<SourceType, string[]> = new Map<SourceType, string[]>();
chartSources: Map<SourceType, string[]> = new Map<SourceType, string[]>();
constructor() {
this.numberSources.set('statistics', [properties.statisticsAPIURL]);
this.numberSources.set('search', [properties.searchAPIURLLAst]);
this.numberSources.set('stats-tool', [properties.monitorStatsFrameUrl, "http://marilyn.athenarc.gr:8080/stats-api/", "http://88.197.53.71:8080/stats-api/", "https://stats.madgik.di.uoa.gr/stats-api/","https://beta.services.openaire.eu/stats-tool/","https://services.openaire.eu/stats-tool/","https://services.openaire.eu/monitor-stats-tool/"]);
this.chartSources.set('stats-tool', [properties.monitorStatsFrameUrl, "http://marilyn.athenarc.gr:8080/stats-api/", "http://88.197.53.71:8080/stats-api/", "https://stats.madgik.di.uoa.gr/stats-api/","https://beta.services.openaire.eu/stats-tool/","https://services.openaire.eu/stats-tool/","https://services.openaire.eu/monitor-stats-tool/"]);
this.numberSources.set('stats-tool', [properties.monitorStatsFrameUrl, "http://marilyn.athenarc.gr:8080/stats-api/", "http://88.197.53.71:8080/stats-api/", "https://stats.madgik.di.uoa.gr/stats-api/", "https://beta.services.openaire.eu/stats-tool/", "https://services.openaire.eu/stats-tool/", "https://services.openaire.eu/monitor-stats-tool/"]);
this.chartSources.set('stats-tool', [properties.monitorStatsFrameUrl, "http://marilyn.athenarc.gr:8080/stats-api/", "http://88.197.53.71:8080/stats-api/", "https://stats.madgik.di.uoa.gr/stats-api/", "https://beta.services.openaire.eu/stats-tool/", "https://services.openaire.eu/stats-tool/", "https://services.openaire.eu/monitor-stats-tool/"]);
this.chartSources.set('old', [properties.statisticsFrameAPIURL]);
this.chartSources.set('image', [""]);
}
getSourceType(source:string): SourceType{
getSourceType(source: string): SourceType {
let sourceType: SourceType = 'search';
this.numberSources.forEach((values, key) => {
if(key == source) {
if (key == source) {
sourceType = key;
}
});
return sourceType;
}
getChartUrl(source: SourceType, url: string): string {
return this.chartSources.get(source)[0] + url;
}
getNumberUrl(source: SourceType, url: string): string {
return this.numberSources.get(this.getSourceType(source))[0] + url;
}
getNumberSource(url: string): SourceType {
let source: SourceType = 'search';
this.numberSources.forEach((values, key) => {
@ -232,7 +267,7 @@ export class IndicatorUtils {
});
return source;
}
getChartSource(url: string): SourceType {
let source: SourceType = 'image';
this.chartSources.forEach((values, key) => {
@ -244,7 +279,7 @@ export class IndicatorUtils {
});
return source;
}
getChartTypes(initialType) {
let types: Option[] = [];
if (this.basicChartTypes.indexOf(initialType) != -1) {
@ -265,7 +300,7 @@ export class IndicatorUtils {
return this.allChartTypes;
}
}
public getFullUrl(stakeholder: Stakeholder, indicatorPath: IndicatorPath, fundingL0: string = null, startYear: string = null, endYear: string = null): string {
let replacedUrl = indicatorPath.chartObject ? indicatorPath.chartObject : indicatorPath.url;
if (stakeholder.statsProfile) {
@ -289,7 +324,7 @@ export class IndicatorUtils {
if (key == "index_shortName") {
replacedValue = stakeholder.index_shortName.toLowerCase();
}
replacedUrl = replacedUrl.split(ChartHelper.prefix + key + ChartHelper.suffix).join(replacedValue)
});
}
@ -307,7 +342,7 @@ export class IndicatorUtils {
}
if (startYear && indicatorPath.filters["start_year"]) {
let newJsonObject = JSON.parse(replacedUrl);
for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) {
if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) {
queries["query"]["filters"] = [];
@ -328,7 +363,7 @@ export class IndicatorUtils {
}
replacedUrl = JSON.stringify(newJsonObject);
}
}
//For numbers (e.g. from stats-api , search service, etc)
if (replacedUrl.indexOf(ChartHelper.prefix + 'index_id' + ChartHelper.suffix) != -1) {
@ -342,7 +377,7 @@ export class IndicatorUtils {
}
return (indicatorPath.chartObject ? indicatorPath.url + encodeURIComponent(replacedUrl) : replacedUrl);
}
public getFullUrlWithFilters(stakeholder: Stakeholder, indicatorPath: IndicatorPath, fundingL0: string = null, startYear: string = null, endYear: string = null, coFunded: boolean = false): string {
indicatorPath.filtersApplied = 0;
let replacedUrl = indicatorPath.chartObject ? indicatorPath.chartObject : indicatorPath.url;
@ -371,7 +406,7 @@ export class IndicatorUtils {
if (key == "index_shortName") {
replacedValue = stakeholder.index_shortName.toLowerCase();
}
replacedUrl = replacedUrl.split(ChartHelper.prefix + key + ChartHelper.suffix).join(replacedValue)
});
}
@ -403,7 +438,7 @@ export class IndicatorUtils {
indicatorPath.filtersApplied += filterResults.filtersApplied;
}
}
//For numbers
if (replacedUrl.indexOf(ChartHelper.prefix + 'index_id' + ChartHelper.suffix) != -1) {
replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_id' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_id));
@ -416,9 +451,9 @@ export class IndicatorUtils {
}
//Check apply enhancements return this.applySchemaEnhancements( ..);
return (indicatorPath.chartObject ? indicatorPath.url + encodeURIComponent(replacedUrl) : replacedUrl);
}
private addFilter(replacedUrl, filterType: FilterType, filterValue) {
let newJsonObject = JSON.parse(replacedUrl);
let filterApplied: boolean = false;
@ -426,7 +461,7 @@ export class IndicatorUtils {
for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) {
/*Chart with Named Queries*/
if (queries["query"]["name"] && !queries["query"]["select"]) {
if (queries["query"]["name"].indexOf("monitor.") == -1 || !queries["query"]["parameters"]) {
continue;
}
@ -537,7 +572,7 @@ export class IndicatorUtils {
}
return {"url": JSON.stringify(newJsonObject), "filtersApplied": (filterApplied) ? 1 : 0};
}
isComparingChart(newJsonObject, filter,) {
let queriesCount = this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)].length : newJsonObject[this.getDescriptionObjectName(newJsonObject)].length;
let values = [];
@ -554,10 +589,10 @@ export class IndicatorUtils {
}
return values.length > 1;
}
generateIndicatorByForm(form: any, indicatorPaths: IndicatorPath[], type: IndicatorType, addParameters: boolean = true): Indicator {
let indicator: Indicator = new Indicator(form.name, form.description, form.additionalDescription, type,
form.width, form.height, form.visibility, indicatorPaths, form.defaultId);
form.width, form.height, form.visibility, indicatorPaths, form.defaultId);
indicator._id = form._id;
form.indicatorPaths.forEach((indicatorPath, index) => {
indicator.indicatorPaths[index].type = indicatorPath.type;
@ -573,7 +608,7 @@ export class IndicatorUtils {
});
return indicator;
}
generateIndicatorByNumberUrl(source: SourceType, url: string, stakeholder: Stakeholder, jsonPath = [], sourceServices: string[] = []): IndicatorPath {
let indicatorPath = new IndicatorPath(null, source, url, null, jsonPath);
if (source === 'stats-tool') {
@ -611,7 +646,7 @@ export class IndicatorUtils {
}
return indicatorPath;
}
generateIndicatorByChartUrl(source: SourceType, url: string, type: IndicatorPathType = null, stakeholder: Stakeholder): IndicatorPath {
let indicatorPath = new IndicatorPath(type, source, null, null, []);
try {
@ -621,13 +656,13 @@ export class IndicatorUtils {
indicatorPath.chartObject = decodeURIComponent(url.split("json=")[1]);
let chart = JSON.parse(indicatorPath.chartObject);
if (indicatorPath.url == "chart?json=") {
if (chart["library"] && (chart["library"] == "HighCharts" || chart["library"] == "eCharts" || chart["library"] == "HighMaps")) {
indicatorPath.type = this.extractType(chart, indicatorPath);
} else {
indicatorPath.type = this.defaultChartType;
}
this.extractTitle(chart, indicatorPath);
this.extractSubTitle(chart, indicatorPath);
this.extractXTitle(chart, indicatorPath);
@ -667,7 +702,7 @@ export class IndicatorUtils {
}
return indicatorPath;
}
private getQueryObjectName(obj) {
if ((obj[this.getDescriptionObjectName(obj)]).hasOwnProperty("queriesInfo")) {
return "queriesInfo";
@ -675,7 +710,7 @@ export class IndicatorUtils {
return "queries";
}
}
private getDescriptionObjectName(obj) {
if (obj.hasOwnProperty("mapDescription")) {
return "mapDescription";
@ -687,7 +722,7 @@ export class IndicatorUtils {
return "series";
}
}
private extractType(obj, indicatorPath: IndicatorPath): IndicatorPathType {
let type = (obj[this.getDescriptionObjectName(obj)] && obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)][0]["type"]) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)][0]["type"] : "";
if (this.basicChartTypes.indexOf(type) == -1) {
@ -698,13 +733,13 @@ export class IndicatorUtils {
}
return type;
}
private extractStakeHolders(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
this.extractFunder(obj, indicatorPath, stakeholder);
this.extractRI(obj, indicatorPath, stakeholder);
this.extractOrganization(obj, indicatorPath, stakeholder);
}
private extractFunder(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
if (stakeholder.type != "funder") {
return;
@ -733,7 +768,7 @@ export class IndicatorUtils {
}
}
}
private extractRI(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
if (stakeholder.type != "ri") {
return;
@ -758,7 +793,7 @@ export class IndicatorUtils {
}
}
}
private extractOrganization(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
// works for publication.project.organization.name
// and publication.organization.name
@ -785,7 +820,7 @@ export class IndicatorUtils {
}
}
}
private extractStartYear(obj, indicatorPath: IndicatorPath) {
let start_year;
for (let query of obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) {
@ -803,7 +838,7 @@ export class IndicatorUtils {
}
}
}
private extractEndYear(obj, indicatorPath: IndicatorPath) {
let end_year;
for (let query of obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) {
@ -821,7 +856,7 @@ export class IndicatorUtils {
}
}
}
private parameterizeDefaultQuery(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
let name = "";
for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) {
@ -843,7 +878,7 @@ export class IndicatorUtils {
} else if (name.split('.')[0] == "monitor" && parameters.length > 0 && name.split('.')[1] == stakeholder.type) {
// new parameterized queries
//monitor.{{type}}.{{queryname}}.{{param1 - id }}.{{param2 result-type}}.{{fl0}} --> params [start year, end year, id, result type, fl0]
let index = (name.split('.').slice(3).length + 2 == parameters.length) ? [2] : ((name.split('.').slice(3).length * 2 + 4 == parameters.length) ? [2, name.split('.').slice(3).length + 4] : [0]);
for (let i of index) {
if (name.split('.').length > 3 && name.split('.')[3] == "id") {
@ -861,7 +896,7 @@ export class IndicatorUtils {
}
}
}
private extractDataTitle(obj, indicatorPath: IndicatorPath) {
let index = 0;
if (!obj[this.getDescriptionObjectName(obj)] || !obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) {
@ -876,7 +911,7 @@ export class IndicatorUtils {
index++;
}
}
private extractTitle(obj, indicatorPath: IndicatorPath) {
let title = "";
if (obj[this.getDescriptionObjectName(obj)]["title"]) {
@ -888,7 +923,7 @@ export class IndicatorUtils {
}
indicatorPath.parameters["title"] = title ? title : "";
}
private extractSubTitle(obj, indicatorPath: IndicatorPath) {
let subtitle = "";
if (obj[this.getDescriptionObjectName(obj)]["subtitle"]) {
@ -901,7 +936,7 @@ export class IndicatorUtils {
indicatorPath.parameters["subtitle"] = subtitle ? subtitle : "";
}
}
private extractXTitle(obj, indicatorPath: IndicatorPath) {
let title = "";
if (obj[this.getDescriptionObjectName(obj)]["xAxis"] && obj[this.getDescriptionObjectName(obj)]["xAxis"]["title"]) {
@ -916,7 +951,7 @@ export class IndicatorUtils {
}
indicatorPath.parameters["xAxisTitle"] = title ? title : "";
}
private extractYTitle(obj, indicatorPath: IndicatorPath) {
let title = "";
if (obj[this.getDescriptionObjectName(obj)]["yAxis"] && obj[this.getDescriptionObjectName(obj)]["yAxis"]["title"]) {
@ -931,17 +966,17 @@ export class IndicatorUtils {
}
indicatorPath.parameters["yAxisTitle"] = title ? title : "";
}
private extractOldToolTitle(obj, indicatorPath: IndicatorPath) {
let title = "";
if (obj["title"]) {
title = obj["title"];
obj["title"] = ChartHelper.prefix + "title" + ChartHelper.suffix;
indicatorPath.parameters["title"] = title;
}
}
private extractOldToolXTitle(obj, indicatorPath: IndicatorPath) {
let title = "";
if (obj["xaxistitle"]) {
@ -950,7 +985,7 @@ export class IndicatorUtils {
indicatorPath.parameters["xAxisTitle"] = title;
}
}
private extractOldToolYTitle(obj, indicatorPath: IndicatorPath) {
let title = "";
if (obj["fieldsheaders"]) {
@ -963,11 +998,11 @@ export class IndicatorUtils {
indicatorPath.parameters["yAxisTitle"] = title;
}
}
public checkForSchemaEnhancements(url: string): boolean {
return url != this.applySchemaEnhancements(url);
}
public applySchemaEnhancements(url: string): string {
let resultEnhancements = [
[".project.acronym", ".project acronym"],
@ -986,7 +1021,7 @@ export class IndicatorUtils {
}
}
}
if (url.split('json=').length > 1) {
let obj = JSON.parse(decodeURIComponent(url.split('json=')[1]));
for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) {

View File

@ -0,0 +1,35 @@
import {Directive} from "@angular/core";
import {BaseComponent} from "../../sharedComponents/base/base.component";
import {IndicatorUtils, StakeholderUtils} from "./indicator-utils";
@Directive()
export abstract class StakeholderBaseComponent extends BaseComponent {
stakeholderUtils: StakeholderUtils = new StakeholderUtils();
get entities() {
return this.stakeholderUtils.entities;
}
get showVisibility() {
return this.stakeholderUtils.showField(this.stakeholderUtils.visibilities);
}
get showType() {
return this.stakeholderUtils.showField(this.stakeholderUtils.types);
}
get showFunderType() {
return this.stakeholderUtils.showField(this.stakeholderUtils.funderTypes);
}
get showLocale() {
return this.stakeholderUtils.showField(this.stakeholderUtils.locales);
}
}
@Directive()
export abstract class IndicatorStakeholderBaseComponent extends StakeholderBaseComponent {
indicatorUtils: IndicatorUtils = new IndicatorUtils();
}

View File

@ -1,7 +1,6 @@
import {SafeResourceUrl} from "@angular/platform-browser";
import {properties} from "../../../../environments/environment";
import {Session, User} from "../../login/utils/helper.class";
import {Option} from "../../sharedComponents/input/input.component";
export const ChartHelper = {
prefix: "((__",
@ -19,6 +18,7 @@ export type Visibility = 'PUBLIC' | 'PRIVATE' | 'RESTRICTED';
export class Stakeholder {
_id: string;
type: StakeholderType;
funderType: string;
name: string;
index_id;
index_name: string;
@ -37,7 +37,7 @@ export class Stakeholder {
description: string;
topics: any[];
constructor(_id: string, type: StakeholderType, index_id, index_name: string, index_shortName: string, alias: string, visibility: Visibility, logoUrl: string, defaultId: string = null, description: string = null) {
constructor(_id: string, type: StakeholderType, index_id: string, index_name: string, index_shortName: string, alias: string, visibility: Visibility, logoUrl: string, defaultId: string = null, description: string = null) {
this._id = _id;
this.type = type;
this.index_id = index_id;
@ -297,6 +297,11 @@ export class IndicatorFilterUtils {
}
}
/**
* @deprecated
*
* TODO: Remove after merge with develop
* */
export enum StakeholderEntities {
STAKEHOLDER = 'Dashboard',
FUNDER = 'Funder',
@ -311,10 +316,3 @@ export enum StakeholderEntities {
ORGANIZATIONS = 'Research Institutions',
PROJECTS = 'Projects'
}
export let stakeholderTypes: Option[] = [
{value: 'funder', label: StakeholderEntities.FUNDER},
{value: 'ri', label: StakeholderEntities.RI},
{value: 'organization', label: StakeholderEntities.ORGANIZATION},
{value: 'project', label: StakeholderEntities.PROJECT}
];

View File

@ -5,7 +5,7 @@ import {Meta, Title} from "@angular/platform-browser";
import {SEOService} from "../../sharedComponents/SEO/SEO.service";
import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
import {Subscriber} from "rxjs";
import {StakeholderEntities} from "../entities/stakeholder";
import {StakeholderBaseComponent} from "../../monitor-admin/utils/stakeholder-base.component";
@Component({
selector: 'indicator-themes-page',
@ -54,9 +54,9 @@ import {StakeholderEntities} from "../entities/stakeholder";
This is the current set of indicator themes we cover. Well keep enriching it as new requests and data are coming into the <a href="https://graph.openaire.eu" class="text-graph" target="_blank">OpenAIRE Graph</a>. We are at your disposal, should you have any recommendations!
</p>
<p>
Check out the indicator pages (for <a [routerLink]="['../funder']" [relativeTo]="route" class="uk-text-lowercase">{{entities.FUNDERS}}</a>,
<a [routerLink]="['../organization']" [relativeTo]="route" class="uk-text-lowercase">{{entities.ORGANIZATIONS}}</a> and
<a [routerLink]="['../ri']" [relativeTo]="route" class="uk-text-lowercase">{{entities.RIS}}</a>)
Check out the indicator pages (for <a [routerLink]="['../funder']" [relativeTo]="route" class="uk-text-lowercase">{{entities.funders}}</a>,
<a [routerLink]="['../organization']" [relativeTo]="route" class="uk-text-lowercase">{{entities.organizations}}</a> and
<a [routerLink]="['../ri']" [relativeTo]="route" class="uk-text-lowercase">{{entities.ris}}</a>)
for the specific indicators for each type of dashboard, and the <a [routerLink]="['../../methodology']" [relativeTo]="route">methodology and terminology</a> page on how we produce the metrics.
</p>
</div>
@ -65,44 +65,24 @@ import {StakeholderEntities} from "../entities/stakeholder";
</div>
`
})
export class IndicatorThemesComponent implements OnInit, OnDestroy {
private subscriptions: any[] = [];
public properties = properties;
public entities = StakeholderEntities;
export class IndicatorThemesComponent extends StakeholderBaseComponent implements OnInit {
public breadcrumbs: Breadcrumb[] = [{name: 'home', route: '/'}, {name: 'Resources - Themes'}];
constructor(private router: Router,
private meta: Meta,
private title: Title,
private seoService: SEOService,
public route: ActivatedRoute) {
constructor(protected _router: Router,
protected _meta: Meta,
protected _title: Title,
protected seoService: SEOService,
protected _route: ActivatedRoute) {
super();
}
ngOnInit() {
this.subscriptions.push(this.route.params.subscribe(params => {
const description = "Monitor | Indicator Themes";
const title = "Monitor | Indicator Themes";
this.metaTags(title, description);
this.subscriptions.push(this._route.params.subscribe(params => {
this.title = "Monitor | Indicator Themes";
this.description = "Monitor | Indicator Themes";
this.setMetadata();
this.breadcrumbs[0].route = '/' + (params['stakeholder']?params['stakeholder']:'');
this.breadcrumbs[0].name = (params['stakeholder']?'dashboard':'home');
}));
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
metaTags(title, description) {
const url = properties.domain + properties.baseLink + this.router.url;
this.seoService.createLinkForCanonicalURL(url, false);
this.meta.updateTag({content: url}, "property='og:url'");
this.meta.updateTag({content: description}, "name='description'");
this.meta.updateTag({content: description}, "property='og:description'");
this.meta.updateTag({content: title}, "property='og:title'");
this.title.setTitle(title);
}
}

View File

@ -1,12 +1,12 @@
import {Injectable} from "@angular/core";
import {MenuItem} from "../../sharedComponents/menu";
import {Option} from "../../sharedComponents/input/input.component";
import {StakeholderEntities} from "../entities/stakeholder";
import {from, Subscription} from "rxjs";
import {HttpClient} from "@angular/common/http";
import {properties} from "../../../../environments/environment";
import {Page} from "../../utils/entities/adminTool/page";
import {map} from "rxjs/operators";
import {StakeholderConfiguration} from "../../monitor-admin/utils/indicator-utils";
@Injectable({
providedIn: 'root'
@ -16,12 +16,7 @@ export class ResourcesService {
private subscription: Subscription;
private routes = ResourcesService.types.map(type => '/indicators/' + type.value);
public static readonly types: Option[] = [
{value: 'funder', label: StakeholderEntities.FUNDERS},
{value: 'ri', label: StakeholderEntities.RIS},
{value: 'project', label: StakeholderEntities.PROJECTS},
{value: 'organization', label: StakeholderEntities.ORGANIZATIONS}
];
public static readonly types: Option[] = StakeholderConfiguration.TYPES;
constructor(private http: HttpClient) {
}

View File

@ -40,7 +40,7 @@ export class NotificationConfiguration {
<span *ngIf="mobile" class="uk-margin-right">
<icon ratio="1.5" name="west" visuallyHidden="back" [flex]="true"></icon>
</span>
<div class="uk-text-bold">Notifications</div>
<span class="uk-text-bold">Notifications</span>
</h4>
<div class="uk-flex uk-flex-right@m uk-flex-center uk-padding uk-padding-remove-vertical">
<button [disabled]="unreadCount === 0" (click)="readAll()" class="uk-button uk-button-link">Mark As Read ({{unreadCount}})</button>
@ -75,7 +75,7 @@ export class NotificationConfiguration {
<span class="uk-margin-right">
<icon ratio="1.5" name="west" visuallyHidden="back" [flex]="true"></icon>
</span>
<div *ngIf="notification.title" class="uk-text-bold">{{notification.title}}</div>
<span *ngIf="notification.title" class="uk-text-bold">{{notification.title}}</span>
</h4>
<div class="uk-flex uk-flex-middle uk-margin-medium-bottom">
<notification-user [name]="notification.name" [surname]="notification.surname" colorClass="uk-text-secondary" [outline]="true"></notification-user>

View File

@ -7,11 +7,12 @@ import {NotificationService} from "../notification.service";
import {Notification} from "../notifications";
import {InputComponent, Option} from "../../sharedComponents/input/input.component";
import {NotificationHandler} from "../../utils/notification-handler";
import {BaseComponent} from "../../sharedComponents/base/base.component";
@Component({
selector: '[notify-form]',
template: `
<form *ngIf="user && form" [formGroup]="form">
<form *ngIf="user && form && properties.notificationsAPIURL" [formGroup]="form">
<ng-template [ngIf]="form.get('notify')">
<label><input name="notify" type="checkbox" class="uk-checkbox" formControlName="notify"><span class="uk-margin-small-left">{{label}}</span></label>
<div [class.uk-hidden]="!form.get('notify').value" class="uk-position-relative uk-margin-medium-top">
@ -44,7 +45,7 @@ import {NotificationHandler} from "../../utils/notification-handler";
styleUrls: ['notify-form.component.less'],
encapsulation: ViewEncapsulation.None
})
export class NotifyFormComponent implements OnInit, OnDestroy {
export class NotifyFormComponent extends BaseComponent implements OnInit {
@Input()
public label: string = 'Notify Managers';
public form: UntypedFormGroup;
@ -57,13 +58,13 @@ export class NotifyFormComponent implements OnInit, OnDestroy {
public focused: boolean = false;
@ViewChild('recipients', { static: false }) recipients: InputComponent;
private notification: Notification;
private subscriptions: any[] = [];
public sending: boolean = false;
constructor(private fb: UntypedFormBuilder,
private cdr: ChangeDetectorRef,
private userManagementService: UserManagementService,
private notificationService: NotificationService) {
super();
}
@Input()
@ -79,14 +80,6 @@ export class NotifyFormComponent implements OnInit, OnDestroy {
}));
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) {
subscription.unsubscribe();
}
})
}
reset(message: string = null) {
if (!this.availableGroups) {
this.form = this.fb.group({
@ -162,16 +155,12 @@ export class NotifyFormComponent implements OnInit, OnDestroy {
}
get message(): string {
if ((this.form.get('notify') && !this.form.get('notify').value) || (this.groupsAsFromArray && this.groupsAsFromArray.length === 0)) {
if (!this.properties.notificationsAPIURL || (this.form.get('notify') && !this.form.get('notify').value) || (this.groupsAsFromArray && this.groupsAsFromArray.length === 0)) {
return null;
}
return this.form.get('message').value;
}
onFocus(event: boolean) {
this.focused = event;
}
focus(event) {
this.focused = true;
event.stopPropagation();

View File

@ -43,7 +43,7 @@ export abstract class BaseComponent implements OnDestroy {
}
/**
* Initialize router params and data (should be called in the constructor)
* Initialize router params and data (should be called in the constructor of a component with router-outlet)
* */
initRouterParams(route: ActivatedRoute = null) {
if (route) {
@ -55,6 +55,16 @@ export abstract class BaseComponent implements OnDestroy {
while (r.firstChild) {
r = r.firstChild;
}
let data = r.snapshot.data;
let params = r.snapshot.params;
let current = r.snapshot;
while (current.parent) {
data = {...current.parent.data, ...data};
params = {...current.parent.params, ...params};
current = current.parent;
}
r.snapshot.data = data;
r.snapshot.params = params;
this.paramsResolved = true;
this.params.next(r.snapshot.params);
this.data.next(r.snapshot.data);

View File

@ -47,11 +47,13 @@ export interface StopRule {
@Component({
selector: 'icon',
template: `
<span #svgIcon *ngIf="icon.data" class="uk-icon" [class.uk-preserve]="gradient || icon.preserveColor" [class.uk-flex]="flex" [ngClass]="customClass" [ngStyle]="style" [innerHTML]="icon.data | safeHtml"></span>
<span *ngIf="!icon.data && icon.name" [class.uk-flex]="flex" [ngClass]="customClass" [class.uk-display-inline-block]="!flex">
<span class="material-icons" [ngClass]="type?type:icon.type" [ngStyle]="style">{{icon.name}}</span>
</span>
<span *ngIf="visuallyHidden" class="visually-hidden">{{visuallyHidden}}</span>
<ng-container *ngIf="icon">
<span #svgIcon *ngIf="icon.data" class="uk-icon" [class.uk-preserve]="gradient || icon.preserveColor" [class.uk-flex]="flex" [ngClass]="customClass" [ngStyle]="style" [innerHTML]="icon.data | safeHtml"></span>
<span *ngIf="!icon.data && icon.name" [class.uk-flex]="flex" [ngClass]="customClass" [class.uk-display-inline-block]="!flex">
<span class="material-icons" [ngClass]="type?type:icon.type" [ngStyle]="style">{{icon.name}}</span>
</span>
<span *ngIf="visuallyHidden" class="visually-hidden">{{visuallyHidden}}</span>
</ng-container>
`
})
export class IconsComponent implements AfterViewInit, OnChanges {
@ -149,7 +151,7 @@ export class IconsComponent implements AfterViewInit, OnChanges {
}
initIcon() {
if(this.icon.data && this.svgIcon) {
if(this.icon?.data && this.svgIcon) {
this.cdr.detectChanges();
let svg: Element = this.svgIcon.nativeElement.getElementsByTagName('svg').item(0);
if(!this.defaultSize && svg) {

View File

@ -1,7 +1,7 @@
export type Environment = "development" | "test" | "beta" | "production";
export type Dashboard = "explore" | "connect" | "monitor" | "aggregator" | "eosc" | "developers" | "faircore4eosc";
export type PortalType = "explore" | "connect" | "community" | "monitor" | "funder" | "ri" | "project" | "organization" | "aggregator" | "eosc" | "faircore4eosc";
export type PortalType = "explore" | "connect" | "community" | "monitor" | "funder" | "ri" | "project" | "organization" | "aggregator" | "eosc" | "faircore4eosc" | "irish";
export interface EnvProperties {
environment?: Environment;

View File

@ -1,9 +1,10 @@
import {UrlSegment} from '@angular/router';
import {AbstractControl, UntypedFormGroup, ValidationErrors, ValidatorFn, Validators} from "@angular/forms";
import {Stakeholder, StakeholderEntities} from "../monitor/entities/stakeholder";
import {Stakeholder} from "../monitor/entities/stakeholder";
import {CommunityInfo} from "../connect/community/communityInfo";
import {properties} from "../../../environments/environment";
import {OpenaireEntities} from "./properties/searchFields";
import {StakeholderConfiguration} from "../monitor-admin/utils/indicator-utils";
export class Dates {
public static yearMin = 1800;
@ -524,13 +525,13 @@ export class StringUtils {
public static getStakeholderType(stakeholderType: string, plural: boolean = false): string {
if(stakeholderType == "funder") {
return plural ? StakeholderEntities.FUNDERS : StakeholderEntities.FUNDER;
return plural ? StakeholderConfiguration.ENTITIES.funders : StakeholderConfiguration.ENTITIES.funders;
} else if(stakeholderType == "ri") {
return plural ? StakeholderEntities.RIS : StakeholderEntities.RI;
return plural ?StakeholderConfiguration.ENTITIES.ris : StakeholderConfiguration.ENTITIES.ri;
} else if(stakeholderType == "organization") {
return plural ? StakeholderEntities.ORGANIZATIONS : StakeholderEntities.ORGANIZATION;
return plural ? StakeholderConfiguration.ENTITIES.organizations : StakeholderConfiguration.ENTITIES.organization;
} else if(stakeholderType == "project") {
return plural ? StakeholderEntities.PROJECTS : StakeholderEntities.PROJECT;
return plural ? StakeholderConfiguration.ENTITIES.projects: StakeholderConfiguration.ENTITIES.project;
}
return stakeholderType;
}