From e38a772bf379611e91b78164ed6137f20fa4dcbd Mon Sep 17 00:00:00 2001 From: "k.triantafyllou" Date: Thu, 2 Nov 2023 11:30:59 +0200 Subject: [PATCH] [develop | DONE]: Move manage stakeholders to library --- .../manageStakeholders-routing.module.ts | 18 + .../manageStakeholders.component.html | 138 ++++++++ .../manageStakeholders.component.less | 23 ++ .../manageStakeholders.component.ts | 311 ++++++++++++++++++ .../manageStakeholders.module.ts | 50 +++ monitor/entities/stakeholder.ts | 4 +- 6 files changed, 542 insertions(+), 2 deletions(-) create mode 100644 monitor-admin/manageStakeholders/manageStakeholders-routing.module.ts create mode 100644 monitor-admin/manageStakeholders/manageStakeholders.component.html create mode 100644 monitor-admin/manageStakeholders/manageStakeholders.component.less create mode 100644 monitor-admin/manageStakeholders/manageStakeholders.component.ts create mode 100644 monitor-admin/manageStakeholders/manageStakeholders.module.ts diff --git a/monitor-admin/manageStakeholders/manageStakeholders-routing.module.ts b/monitor-admin/manageStakeholders/manageStakeholders-routing.module.ts new file mode 100644 index 00000000..03c01a41 --- /dev/null +++ b/monitor-admin/manageStakeholders/manageStakeholders-routing.module.ts @@ -0,0 +1,18 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {PreviousRouteRecorder} from '../../utils/piwik/previousRouteRecorder.guard'; +import {ManageStakeholdersComponent} from "./manageStakeholders.component"; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + path: '', + component: ManageStakeholdersComponent, + canDeactivate: [PreviousRouteRecorder] + } + ]) + ] +}) +export class ManageStakeholdersRoutingModule { +} diff --git a/monitor-admin/manageStakeholders/manageStakeholders.component.html b/monitor-admin/manageStakeholders/manageStakeholders.component.html new file mode 100644 index 00000000..5b981cde --- /dev/null +++ b/monitor-admin/manageStakeholders/manageStakeholders.component.html @@ -0,0 +1,138 @@ +
+
+ +
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+

Profile Templates

+
+ + + +
+ +
+
+
+
+

+ No profiles to manage yet +

+
+
+

Profiles

+
+ + + +
+ +
+
+
+
+
+
+
+ + +
+ +
+
+ + +
+
+ {{text}} +
+
+ + + +
+
+
+
+ +
+ +
+
+ +
+
+ +
+ +
+
+ This stakeholder will permanently be deleted. Are you sure you want to proceed? +
+
diff --git a/monitor-admin/manageStakeholders/manageStakeholders.component.less b/monitor-admin/manageStakeholders/manageStakeholders.component.less new file mode 100644 index 00000000..ee701579 --- /dev/null +++ b/monitor-admin/manageStakeholders/manageStakeholders.component.less @@ -0,0 +1,23 @@ +@import (reference) "~src/assets/openaire-theme/less/color.less"; + +.setType(@color) { + border-bottom: 4px solid fade(@color, 30%); + + & .type { + color: @color; + } +} + +.uk-card { + &.funder { + .setType(@funder-color); + } + + &.ri { + .setType(@ri-color); + } + + &.organization { + .setType(@organization-color); + } +} diff --git a/monitor-admin/manageStakeholders/manageStakeholders.component.ts b/monitor-admin/manageStakeholders/manageStakeholders.component.ts new file mode 100644 index 00000000..5e637b3e --- /dev/null +++ b/monitor-admin/manageStakeholders/manageStakeholders.component.ts @@ -0,0 +1,311 @@ +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 {UntypedFormBuilder, UntypedFormGroup} from "@angular/forms"; +import {AlertModal} from "../../utils/modal/alert"; +import {Option} from "../../sharedComponents/input/input.component"; +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"; + +type Tab = 'all' | 'templates'| 'profiles'; + +declare var UIkit; + +@Component({ + selector: 'home', + templateUrl: "./manageStakeholders.component.html", + styleUrls: ["./manageStakeholders.component.less"] +}) +export class ManageStakeholdersComponent implements OnInit, OnDestroy { + + public properties: EnvProperties; + public loading: boolean = true; + public deleteLoading: boolean = false; + public stakeholderUtils: StakeholderUtils = new StakeholderUtils(); + public defaultStakeholders: Stakeholder[]; + public stakeholders: Stakeholder[]; + public alias: string[]; + public stakeholder: Stakeholder; + public index: number; + public user = null; + public tab: Tab = 'all'; + /** + * Filtered Stakeholders + */ + public displayDefaultStakeholders: Stakeholder[]; + public displayStakeholders: Stakeholder[]; + /** + * Top filters + */ + public filters: UntypedFormGroup; + public all: Option = { + value: 'all', + label: 'All' + }; + + public callback: Function; + + /** + * Grid or List View + */ + private subscriptions: any[] = []; + @ViewChild('editStakeholderModal', { static: true }) editStakeholderModal: AlertModal; + @ViewChild('deleteStakeholderModal', { static: true }) deleteStakeholderModal: AlertModal; + @ViewChild('editStakeholderComponent', { static: true }) editStakeholderComponent: EditStakeholderComponent; + + constructor(private stakeholderService: StakeholderService, + private cacheIndicatorsService: CacheIndicatorsService, + private userManagementService: UserManagementService, + private route: ActivatedRoute, + private title: Title, + private fb: UntypedFormBuilder) { + } + + ngOnInit(): void { + this.buildFilters(); + this.properties = properties; + this.title.setTitle('Manage profiles'); + this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { + this.user = user; + })); + let data = zip( + this.stakeholderService.getDefaultStakeholders(this.properties.monitorServiceAPIURL), + this.stakeholderService.getMyStakeholders(this.properties.monitorServiceAPIURL), + this.stakeholderService.getAlias(this.properties.monitorServiceAPIURL) + ); + this.subscriptions.push(data.subscribe(res => { + this.defaultStakeholders = res[0]; + this.stakeholders = res[1]; + this.displayDefaultStakeholders = res[0]; + this.displayStakeholders = res[1]; + this.alias = res[2]; + this.loading = false; + }, error => { + this.loading = false; + })); + } + + ngOnDestroy(): void { + this.subscriptions.forEach(value => { + if (value instanceof Subscriber) { + value.unsubscribe(); + } else if (value instanceof Function) { + value(); + } + }); + } + + hide(element: any) { + UIkit.dropdown(element).hide(); + } + + + private buildFilters() { + this.filters = this.fb.group({ + status: this.fb.control('all'), + keyword: this.fb.control('') + }); + this.subscriptions.push(this.filters.get('status').valueChanges.subscribe(value => { + this.onStatusChange(value); + })); + this.subscriptions.push(this.filters.get('keyword').valueChanges.subscribe(value => { + this.onKeywordChange(value); + })); + } + + onStatusChange(value) { + this.displayDefaultStakeholders = this.filterStatus(this.defaultStakeholders, value); + this.displayStakeholders = this.filterStatus(this.stakeholders, value); + } + + onKeywordChange(value) { + this.displayDefaultStakeholders = this.filterByKeyword(this.defaultStakeholders, value); + this.displayStakeholders = this.filterByKeyword(this.stakeholders, value); + } + + private filterStatus(stakeholders: Stakeholder[], value): Stakeholder[] { + if (value === 'all') { + return stakeholders; + } else { + return stakeholders.filter(stakeholder => stakeholder.visibility == value); + } + } + + private filterByKeyword(stakeholders: Stakeholder[], value): Stakeholder[] { + if (!value) { + return stakeholders; + } else { + return stakeholders.filter(stakeholder => + stakeholder.name && stakeholder.name.toLowerCase().includes(value.toLowerCase()) || + stakeholder.type && stakeholder.type.toLowerCase().includes(value.toLowerCase()) || + stakeholder.index_id && stakeholder.index_id.toLowerCase().includes(value.toLowerCase()) || + stakeholder.index_shortName && stakeholder.index_shortName.toLowerCase().includes(value.toLowerCase()) || + stakeholder.index_name && stakeholder.index_name.toLowerCase().includes(value.toLowerCase()) + ); + } + } + + public editStakeholder(stakeholder: Stakeholder = null, isDefault: boolean = false) { + if (isDefault) { + this.index = (stakeholder) ? this.defaultStakeholders.findIndex(value => value._id === stakeholder._id) : -1; + } else { + this.index = (stakeholder) ? this.stakeholders.findIndex(value => value._id === stakeholder._id) : -1; + } + if (!stakeholder) { + this.stakeholder = new Stakeholder(null, null, null, + null, null, null, null, null); + } else { + this.stakeholder = stakeholder; + } + this.editStakeholderComponent.init(this.stakeholder, this.alias, this.defaultStakeholders, isDefault, this.index === -1); + if (this.index !== -1) { + this.callback = (stakeholder: Stakeholder) => { + let index: number; + if (stakeholder.defaultId == null) { + index = this.alias.findIndex(value => value == this.defaultStakeholders[this.index].alias); + this.defaultStakeholders[this.index] = stakeholder; + } else { + index = this.alias.findIndex(value => value == this.stakeholders[this.index].alias); + this.stakeholders[this.index] = stakeholder; + } + if(index != -1) { + this.alias[index] = stakeholder.alias; + } + this.editStakeholderModal.cancel(); + }; + this.editStakeholderModal.alertTitle = 'Edit ' + this.stakeholder.name; + this.editStakeholderModal.okButtonText = 'Save Changes'; + } else { + this.callback = (stakeholder: Stakeholder) => { + if (stakeholder.defaultId === null) { + this.defaultStakeholders.push(stakeholder); + } else { + this.stakeholders.push(stakeholder); + } + this.alias.push(stakeholder.alias); + this.editStakeholderModal.cancel(); + }; + this.editStakeholderModal.alertTitle = 'Create a new ' + (isDefault?'Default ':'') + 'Profile'; + this.editStakeholderModal.okButtonText = 'Create'; + } + this.editStakeholderModal.cancelButtonText = 'Cancel'; + this.editStakeholderModal.okButtonLeft = false; + this.editStakeholderModal.alertMessage = false; + this.editStakeholderModal.stayOpen = true; + this.editStakeholderModal.open(); + } + + public createReport(stakeholder: Stakeholder) { + this.cacheIndicatorsService.createReport(stakeholder.alias).subscribe(report => { + NotificationHandler.rise('A caching process for ' + stakeholder.name + ' has been started.' ) + }, error => { + console.log(error); + NotificationHandler.rise(error.message(), 'danger'); + }); + } + + public deleteStakeholderOpen(stakeholder: Stakeholder) { + this.stakeholder = stakeholder; + this.deleteStakeholderModal.alertTitle = 'Delete ' + this.stakeholder.index_name; + this.deleteStakeholderModal.cancelButtonText = 'No'; + this.deleteStakeholderModal.okButtonText = 'Yes'; + this.deleteStakeholderModal.alertMessage = false; + this.deleteStakeholderModal.stayOpen = true; + this.deleteStakeholderModal.open(); + } + + public deleteStakeholder() { + this.deleteLoading = true; + if (!this.stakeholder.defaultId) { + this.index = (this.stakeholder) ? this.defaultStakeholders.findIndex(value => value._id === this.stakeholder._id) : -1; + } else { + this.index = (this.stakeholder) ? this.stakeholders.findIndex(value => value._id === this.stakeholder._id) : -1; + } + this.subscriptions.push(this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, [this.stakeholder._id]).subscribe(() => { + UIkit.notification(this.stakeholder.name+ ' has been successfully deleted', { + status: 'success', + timeout: 6000, + pos: 'bottom-right' + }); + if (!this.stakeholder.defaultId) { + this.defaultStakeholders.splice(this.index, 1); + } else { + this.stakeholders.splice(this.index, 1); + } + this.alias = this.alias.filter(item => item !== this.stakeholder.alias); + this.deleteLoading = false; + this.deleteStakeholderModal.cancel(); + }, error => { + UIkit.notification('An error has occurred. Please try again later', { + status: 'danger', + timeout: 6000, + pos: 'bottom-right' + }); + this.deleteLoading = false; + this.deleteStakeholderModal.cancel(); + })); + } + + changeStakeholderStatus(stakeholder: Stakeholder, visibility: Visibility) { + let path = [ + stakeholder._id + ]; + this.subscriptions.push(this.stakeholderService.changeVisibility(this.properties.monitorServiceAPIURL, path, visibility).subscribe(returnedElement => { + stakeholder.visibility = returnedElement.visibility; + UIkit.notification(stakeholder.name+ '\'s status has been successfully changed to ' + stakeholder.visibility.toLowerCase(), { + status: 'success', + timeout: 6000, + pos: 'bottom-right' + }); + }, error => { + UIkit.notification('An error has occurred. Please try again later', { + status: 'danger', + timeout: 6000, + pos: 'bottom-right' + }); + })); + } + + public isManager(): boolean { + return this.isCurator() || (Session.isKindOfMonitorManager(this.user)); + } + + public isProfileManager(stakeholder: Stakeholder): boolean { + return this.isCurator() || (Session.isManager(stakeholder.type, stakeholder.alias, this.user)); + } + + public isCurator(): boolean { + return this.isAdmin() || Session.isMonitorCurator(this.user); + } + + public isAdmin(): boolean { + return Session.isPortalAdministrator(this.user); + } + + get typesAsString() { + 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/manageStakeholders/manageStakeholders.module.ts b/monitor-admin/manageStakeholders/manageStakeholders.module.ts new file mode 100644 index 00000000..41847068 --- /dev/null +++ b/monitor-admin/manageStakeholders/manageStakeholders.module.ts @@ -0,0 +1,50 @@ +import {NgModule} from "@angular/core"; +import {ManageStakeholdersComponent} from "./manageStakeholders.component"; +import {ManageStakeholdersRoutingModule} from "./manageStakeholders-routing.module"; +import {PreviousRouteRecorder} from "../../utils/piwik/previousRouteRecorder.guard"; +import {CommonModule} from "@angular/common"; +import {RouterModule} from "@angular/router"; +import {InputModule} from "../../sharedComponents/input/input.module"; +import {LoadingModule} from "../../utils/loading/loading.module"; +import {AlertModalModule} from "../../utils/modal/alertModal.module"; +import {ReactiveFormsModule} from "@angular/forms"; +import {IconsModule} from "../../utils/icons/icons.module"; +import {IconsService} from "../../utils/icons/icons.service"; +import {earth, incognito, restricted} from "../../utils/icons/icons"; +import {PageContentModule} from "../../dashboard/sharedComponents/page-content/page-content.module"; +import {LogoUrlPipeModule} from "../../utils/pipes/logoUrlPipe.module"; +import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module"; +import { + SidebarMobileToggleModule +} from "../../dashboard/sharedComponents/sidebar/sidebar-mobile-toggle/sidebar-mobile-toggle.module"; +import {SliderTabsModule} from "../../sharedComponents/tabs/slider-tabs.module"; +import {EditStakeholderModule} from "../general/edit-stakeholder/edit-stakeholder.module"; + +@NgModule({ + declarations: [ManageStakeholdersComponent], + imports: [ + ManageStakeholdersRoutingModule, + CommonModule, + RouterModule, + InputModule, + LoadingModule, + AlertModalModule, + ReactiveFormsModule, + EditStakeholderModule, + IconsModule, + PageContentModule, + LogoUrlPipeModule, + SearchInputModule, + SidebarMobileToggleModule, + SliderTabsModule + ], + providers: [ + PreviousRouteRecorder, + ], + exports: [ManageStakeholdersComponent] +}) +export class ManageStakeholdersModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([earth, incognito, restricted]); + } +} diff --git a/monitor/entities/stakeholder.ts b/monitor/entities/stakeholder.ts index 13ed58cf..357f42ab 100644 --- a/monitor/entities/stakeholder.ts +++ b/monitor/entities/stakeholder.ts @@ -314,6 +314,6 @@ export enum StakeholderEntities { export let stakeholderTypes: Option[] = [ {value: 'funder', label: StakeholderEntities.FUNDER}, {value: 'ri', label: StakeholderEntities.RI}, - {value: 'project', label: StakeholderEntities.PROJECT}, - {value: 'organization', label: StakeholderEntities.ORGANIZATION} + {value: 'organization', label: StakeholderEntities.ORGANIZATION}, + {value: 'project', label: StakeholderEntities.PROJECT} ];