diff --git a/connect/connectHelper.ts b/connect/connectHelper.ts index 14542fa2..1e8b32c4 100644 --- a/connect/connectHelper.ts +++ b/connect/connectHelper.ts @@ -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")) { diff --git a/dashboard/portal/portalHelper.ts b/dashboard/portal/portalHelper.ts index bc08cd2a..5239ecb4 100644 --- a/dashboard/portal/portalHelper.ts +++ b/dashboard/portal/portalHelper.ts @@ -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}, ]; } diff --git a/dashboard/sharedComponents/sidebar/sidebar-base.component.ts b/dashboard/sharedComponents/sidebar/sidebar-base.component.ts new file mode 100644 index 00000000..a7d23d1a --- /dev/null +++ b/dashboard/sharedComponents/sidebar/sidebar-base.component.ts @@ -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; + } +} diff --git a/login/utils/helper.class.ts b/login/utils/helper.class.ts index 8fdd6229..c58991ac 100644 --- a/login/utils/helper.class.ts +++ b/login/utils/helper.class.ts @@ -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 { diff --git a/monitor-admin/general/edit-stakeholder/edit-stakeholder.component.ts b/monitor-admin/general/edit-stakeholder/edit-stakeholder.component.ts index f84f197d..b9025f20 100644 --- a/monitor-admin/general/edit-stakeholder/edit-stakeholder.component.ts +++ b/monitor-admin/general/edit-stakeholder/edit-stakeholder.component.ts @@ -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: ` -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
+
+ +
+
+
+
+
+
-
+
- -
-
-
-
-
-
-
- -
-
-
-
- -
-
- OR +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+ OR +
+
-
+
+
+ +
+
+ +
+
+ +
+
+ +
{{uploadError}}
-
-
- -
-
- -
-
- +
+
+
+
+
+
+
+
+
+
+
+
+
+
- -
{{uploadError}}
-
-
-
-
-
-
- -
-
-
-
-
- -
+ +
+
`, 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; + } } diff --git a/monitor-admin/general/general.component.ts b/monitor-admin/general/general.component.ts index 611032b4..fda34d94 100644 --- a/monitor-admin/general/general.component.ts +++ b/monitor-admin/general/general.component.ts @@ -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(); - } - }); - } } diff --git a/monitor-admin/manageStakeholders/manageStakeholders.component.html b/monitor-admin/manageStakeholders/manageStakeholders.component.html index df98cce0..4c639c15 100644 --- a/monitor-admin/manageStakeholders/manageStakeholders.component.html +++ b/monitor-admin/manageStakeholders/manageStakeholders.component.html @@ -60,7 +60,7 @@
- +
@@ -71,8 +71,8 @@
  • Cache Indicators
  • -
  • - +
  • +
  • diff --git a/monitor-admin/manageStakeholders/manageStakeholders.component.ts b/monitor-admin/manageStakeholders/manageStakeholders.component.ts index 1ca980bc..7d0a7dc5 100644 --- a/monitor-admin/manageStakeholders/manageStakeholders.component.ts +++ b/monitor-admin/manageStakeholders/manageStakeholders.component.ts @@ -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; - } - } } diff --git a/monitor-admin/topic/indicators.component.html b/monitor-admin/topic/indicators.component.html index ecdc0cdb..e5723eb8 100644 --- a/monitor-admin/topic/indicators.component.html +++ b/monitor-admin/topic/indicators.component.html @@ -39,26 +39,28 @@
    - +
    • Edit
    • -
    • - -
    • - -
      - - {{v.label}} - -
      -
      -
    • -
      + +
    • + +
    • + +
      + + {{v.label}} + +
      +
      +
    • +
      +
    • Delete
    • @@ -136,26 +138,28 @@
      - +
      • Edit
      • -
      • - -
      • - -
        - - {{v.label}} - -
        -
        -
      • -
        + +
      • + +
      • + +
        + + {{v.label}} + +
        +
        +
      • +
        +
      • Delete
      • @@ -231,8 +235,8 @@
        -
        +
        @@ -346,8 +350,8 @@
        -
        +
        diff --git a/monitor-admin/topic/indicators.component.ts b/monitor-admin/topic/indicators.component.ts index d97f5f82..36b3e98f 100644 --- a/monitor-admin/topic/indicators.component.ts +++ b/monitor-admin/topic/indicators.component.ts @@ -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; 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(); diff --git a/monitor-admin/topic/topic.component.html b/monitor-admin/topic/topic.component.html index e11e98c5..9794d8f9 100644 --- a/monitor-admin/topic/topic.component.html +++ b/monitor-admin/topic/topic.component.html @@ -26,12 +26,11 @@ - -
        +
        • @@ -59,9 +58,10 @@
        -
      • - + +
      • +
      • +
      • @@ -103,7 +104,7 @@ - @@ -137,9 +138,11 @@
      • -
      • + - + +
      • +
      • +
      • @@ -191,8 +195,8 @@
      • -
        -
        +
        +
        -
      • - + +
      • +
      • +
      • @@ -348,8 +354,8 @@
        -
        +
        diff --git a/monitor-admin/topic/topic.component.ts b/monitor-admin/topic/topic.component.ts index 57f65930..51fe171d 100644 --- a/monitor-admin/topic/topic.component.ts +++ b/monitor-admin/topic/topic.component.ts @@ -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; diff --git a/monitor-admin/utils/indicator-utils.ts b/monitor-admin/utils/indicator-utils.ts index 4dae319c..5afa5b30 100644 --- a/monitor-admin/utils/indicator-utils.ts +++ b/monitor-admin/utils/indicator-utils.ts @@ -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 = new Map([ - ["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 = new Map(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 = new Map([ ['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 = new Map(); chartSources: Map = new Map(); - + 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)]) { diff --git a/monitor-admin/utils/stakeholder-base.component.ts b/monitor-admin/utils/stakeholder-base.component.ts new file mode 100644 index 00000000..df649417 --- /dev/null +++ b/monitor-admin/utils/stakeholder-base.component.ts @@ -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(); +} diff --git a/monitor/entities/stakeholder.ts b/monitor/entities/stakeholder.ts index 460144d4..0ccb2948 100644 --- a/monitor/entities/stakeholder.ts +++ b/monitor/entities/stakeholder.ts @@ -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} -]; diff --git a/monitor/indicators/indicator-themes.component.ts b/monitor/indicators/indicator-themes.component.ts index 4fb9e7e0..b2c4a2f5 100644 --- a/monitor/indicators/indicator-themes.component.ts +++ b/monitor/indicators/indicator-themes.component.ts @@ -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. We’ll keep enriching it as new requests and data are coming into the OpenAIRE Graph. We are at your disposal, should you have any recommendations!

        - Check out the indicator pages (for {{entities.FUNDERS}}, - {{entities.ORGANIZATIONS}} and - {{entities.RIS}}) + Check out the indicator pages (for {{entities.funders}}, + {{entities.organizations}} and + {{entities.ris}}) for the specific indicators for each type of dashboard, and the methodology and terminology page on how we produce the metrics.

      • @@ -65,44 +65,24 @@ import {StakeholderEntities} from "../entities/stakeholder";
        ` }) -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); - } } diff --git a/monitor/services/resources.service.ts b/monitor/services/resources.service.ts index 841ff3a4..8884ed22 100644 --- a/monitor/services/resources.service.ts +++ b/monitor/services/resources.service.ts @@ -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) { } diff --git a/notifications/notifications-sidebar/notifications-sidebar.component.ts b/notifications/notifications-sidebar/notifications-sidebar.component.ts index 83cc74cb..d07f1c6a 100644 --- a/notifications/notifications-sidebar/notifications-sidebar.component.ts +++ b/notifications/notifications-sidebar/notifications-sidebar.component.ts @@ -40,7 +40,7 @@ export class NotificationConfiguration { -
        Notifications
        + Notifications
        @@ -75,7 +75,7 @@ export class NotificationConfiguration { -
        {{notification.title}}
        + {{notification.title}}
        diff --git a/notifications/notify-form/notify-form.component.ts b/notifications/notify-form/notify-form.component.ts index 0072855c..8ad475a9 100644 --- a/notifications/notify-form/notify-form.component.ts +++ b/notifications/notify-form/notify-form.component.ts @@ -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: ` -
        +
        @@ -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(); diff --git a/sharedComponents/base/base.component.ts b/sharedComponents/base/base.component.ts index edc9eaca..d7667a53 100644 --- a/sharedComponents/base/base.component.ts +++ b/sharedComponents/base/base.component.ts @@ -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); diff --git a/utils/icons/icons.component.ts b/utils/icons/icons.component.ts index f7ad9f63..a6d42e41 100644 --- a/utils/icons/icons.component.ts +++ b/utils/icons/icons.component.ts @@ -47,11 +47,13 @@ export interface StopRule { @Component({ selector: 'icon', template: ` - - - {{icon.name}} - - {{visuallyHidden}} + + + + {{icon.name}} + + {{visuallyHidden}} + ` }) 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) { diff --git a/utils/properties/env-properties.ts b/utils/properties/env-properties.ts index 9f6b6db8..d656c1a9 100644 --- a/utils/properties/env-properties.ts +++ b/utils/properties/env-properties.ts @@ -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; diff --git a/utils/string-utils.class.ts b/utils/string-utils.class.ts index dff363ff..faff2fda 100644 --- a/utils/string-utils.class.ts +++ b/utils/string-utils.class.ts @@ -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; }