diff --git a/connect/affiliations/affiliations.component.html b/connect/affiliations/affiliations.component.html new file mode 100644 index 00000000..1a971187 --- /dev/null +++ b/connect/affiliations/affiliations.component.html @@ -0,0 +1,69 @@ + +
+ +
+

+ {{organization.name}} +

+
+
+
+ + + +
+
+
+
+ + + + + + +
+
+
+
+ +
+
+

+ Supporting
Organizations +

+ + + Browse all + + +
+
+
+
+ + + + + + +
+
+
+
+
+ + + + diff --git a/connect/affiliations/affiliations.component.less b/connect/affiliations/affiliations.component.less new file mode 100644 index 00000000..e7fcafc5 --- /dev/null +++ b/connect/affiliations/affiliations.component.less @@ -0,0 +1,18 @@ +.affiliationCard { + width: 260px !important; + height: 260px !important; +} + +.supportingOrganizations a { + img, svg { + -webkit-filter: grayscale(1); + filter: grayscale(1); + transition-duration: 0.3s; + } + + &:hover img, svg { + -webkit-filter: grayscale(0); + filter: grayscale(0); + transition-duration: 0.3s; + } +} diff --git a/connect/affiliations/affiliations.component.ts b/connect/affiliations/affiliations.component.ts new file mode 100644 index 00000000..395f052a --- /dev/null +++ b/connect/affiliations/affiliations.component.ts @@ -0,0 +1,68 @@ +import {Component, Input} from '@angular/core'; +import {ActivatedRoute} from '@angular/router'; +import {EnvProperties} from '../../utils/properties/env-properties'; +import {AffiliationService} from "./affiliation.service"; +import {Affiliation} from "../../utils/entities/CuratorInfo"; +import {ConnectHelper} from "../connectHelper"; +import {Subscriber} from "rxjs"; +import {properties} from "../../../../environments/environment"; +import {ConfigurationService} from "../../utils/configuration/configuration.service"; +import {CommunityService} from "../community/community.service"; + +@Component({ + selector: 'affiliations', + templateUrl: './affiliations.component.html', + styleUrls: ['./affiliations.component.less'] +}) +export class AffiliationsComponent { + @Input() getAffiliationsFromAPI: boolean = false; + @Input() longView: boolean = false; + @Input() communityFirstPage: boolean = false; + @Input() affiliationsInSlider: number = 5; + @Input() affiliations: Affiliation[] = []; + @Input() sliderOptions = ''; + @Input() arrows = true; + + public showLoading: boolean = false; + public communityId: string; + public properties: EnvProperties = properties; + private subscriptions = []; + + constructor(private route: ActivatedRoute, private affiliationService: AffiliationService, private config: ConfigurationService) { + } + + public ngOnInit() { + this.subscriptions.push(this.config.portalAsObservable.subscribe( + res => { + // this.portal = res; + this.communityId = res.pid + }, + error => { + console.log(error); + } + )); + if (this.getAffiliationsFromAPI) { + this.showLoading = true; + this.affiliationService.initAffiliations(this.communityId); + this.subscriptions.push(this.affiliationService.affiliations.subscribe( + affiliations => { + this.affiliations = affiliations.filter((affiliation) => this.longView || !!affiliation['logo_url']); + this.showLoading = false; + }, + error => { + console.error("Affiliations Component: Error getting affiliations for community with id: " + this.communityId, error); + this.showLoading = false; + } + )); + } + } + + ngOnDestroy() { + this.subscriptions.forEach(subscription => { + if (subscription instanceof Subscriber) { + subscription.unsubscribe(); + } + }); + this.affiliationService.clearSubscriptions(); + } +} diff --git a/connect/affiliations/affiliations.module.ts b/connect/affiliations/affiliations.module.ts new file mode 100644 index 00000000..053cfa5d --- /dev/null +++ b/connect/affiliations/affiliations.module.ts @@ -0,0 +1,26 @@ +import {NgModule} from '@angular/core'; + +import {PreviousRouteRecorder} from '../../utils/piwik/previousRouteRecorder.guard'; +import {IsRouteEnabled} from '../../error/isRouteEnabled.guard' +import {RouterModule} from '@angular/router'; + +import {AffiliationsComponent} from './affiliations.component'; +import {CommonModule} from "@angular/common"; +import {UrlPrefixModule} from "../../utils/pipes/url-prefix.module"; +import {AffiliationService} from "./affiliation.service"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, UrlPrefixModule + ], + declarations: [ + AffiliationsComponent + ], + providers:[PreviousRouteRecorder, IsRouteEnabled, AffiliationService], + exports: [ + AffiliationsComponent + ] +}) + + +export class AffiliationsModule{} diff --git a/connect/community/community.service.ts b/connect/community/community.service.ts index 06d222e0..9d11ef0e 100644 --- a/connect/community/community.service.ts +++ b/connect/community/community.service.ts @@ -92,6 +92,8 @@ export class CommunityService { const community: CommunityInfo = new CommunityInfo(); community.title = resData.name; community.shortTitle = resData.shortName; + community.displayTitle = resData.displayName?resData.displayName:resData.name; + community.displayShortTitle = resData.displayShortName?resData.displayShortName:resData.shortName; community.communityId = resData.id; community.queryId = resData.queryId; community.logoUrl = resData.logoUrl; @@ -102,6 +104,7 @@ export class CommunityService { community.claim = resData.claim; community.membership = resData.membership; community.type = resData.type; + community.plan = resData.plan?resData.plan:"Default"; community.otherZenodoCommunities = resData.otherZenodoCommunities; if (resData.hasOwnProperty('status')) { community.status = resData.status; diff --git a/connect/community/communityInfo.ts b/connect/community/communityInfo.ts index 8a8469ce..8b124785 100644 --- a/connect/community/communityInfo.ts +++ b/connect/community/communityInfo.ts @@ -4,6 +4,8 @@ import {SelectionCriteria} from "../../utils/entities/contentProvider"; export class CommunityInfo { title: string; shortTitle:string; + displayTitle: string; + displayShortTitle:string; communityId: string; queryId: string; type: string; @@ -24,7 +26,8 @@ export class CommunityInfo { fos: string[] = []; sdg: string[] = [] selectionCriteria: SelectionCriteria; - + plan: "Standard" | "Advanced" | "Premium" | "National" | "Default" ; + public static checkIsUpload(response: CommunityInfo | CommunityInfo[]): any | any[] { if (Array.isArray(response)) { response.forEach(value => { diff --git a/connect/components/curators/curators-routing.module.ts b/connect/components/curators/curators-routing.module.ts new file mode 100644 index 00000000..39c74dd6 --- /dev/null +++ b/connect/components/curators/curators-routing.module.ts @@ -0,0 +1,15 @@ +import { NgModule} from '@angular/core'; +import { RouterModule } from '@angular/router'; +import {CuratorsComponent} from "./curators.component"; +import {IsRouteEnabled} from "../../../error/isRouteEnabled.guard"; +import {PreviousRouteRecorder} from "../../../utils/piwik/previousRouteRecorder.guard"; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { path: '', component: CuratorsComponent, canActivate: [IsRouteEnabled], canDeactivate: [PreviousRouteRecorder]} + ]) + ] +}) +export class CuratorsRoutingModule { +} diff --git a/connect/components/curators/curators.component.html b/connect/components/curators/curators.component.html new file mode 100644 index 00000000..6298a533 --- /dev/null +++ b/connect/components/curators/curators.component.html @@ -0,0 +1,152 @@ + + +
+
+
+ +
+
+
+
+ +
+
+

+ Curators +

+
+ + +
+
+
+
+
+
+ Curator Photo + Curator Photo +
+
+
+

{{curator.name}}

+
+
+ Biography +
+
+
{{format(curator.bio)}}
+
{{curator.bio}}
+ +
+
+
+
+
+
+
+ Affiliations +
+
+
+ + + + + + +
+
+
+
+
+
+
+
+ + +
+
+
+
+ + + +
+ + Curated by: + + +
+
+ +
+
+
+
+

+ {{curatorInModal.name}} +

+ Curator Photo + Curator Photo +
+
+ +
    +
  • +
    + Biography +
    +
    + {{curatorInModal.bio}} +
    +
  • +
  • +
    +
    + + + + + + +
    +
    +
  • +
+
+
+
+
+
diff --git a/connect/components/curators/curators.component.ts b/connect/components/curators/curators.component.ts new file mode 100644 index 00000000..4423168f --- /dev/null +++ b/connect/components/curators/curators.component.ts @@ -0,0 +1,155 @@ +import {Component, Input, ViewChild} from '@angular/core'; +import {EnvProperties} from '../../../utils/properties/env-properties'; +import {CuratorService} from "../../curators/curator.service"; +import {Curator} from "../../../utils/entities/CuratorInfo"; +import {ActivatedRoute, Router} from "@angular/router"; +import {CommunityService} from "../../community/community.service"; +import {HelperService} from "../../../utils/helper/helper.service"; +import {Meta, Title} from "@angular/platform-browser"; +import {SEOService} from "../../../sharedComponents/SEO/SEO.service"; +import {PiwikService} from "../../../utils/piwik/piwik.service"; +import {Breadcrumb} from "../../../utils/breadcrumbs/breadcrumbs.component"; +import {Subscription} from "rxjs"; +import {properties} from "../../../../../environments/environment"; +import {UserRegistryService} from "../../../services/user-registry.service"; +import {FullScreenModalComponent} from '../../../utils/modal/full-screen-modal/full-screen-modal.component'; +import {CommunityInfo} from "../../community/communityInfo"; + +@Component({ + selector: 'curators', + templateUrl: './curators.component.html' + +}) +export class CuratorsComponent { + @Input() longView = true; + community: CommunityInfo; + public downloadUrl = null; + public showLoading = true; + + public curators: Curator[] = []; + + public curatorsLimit: number = 5; + public numberOfCurators: number = 5; + + public showMore = []; + public maxCharacters = 450; + public viewingMore: boolean = false; + public curatorInModal; + + public properties: EnvProperties; + public pageContents = null; + public divContents = null; + + public url: string = null; + public pageTitle: string = "Curators"; + + public breadcrumbs: Breadcrumb[] = [{name: 'Home', route: '/'}, {name: 'About - Curators'}]; + + subs: Subscription[] = []; + + @ViewChild('fsModal', { static: true }) fsModal: FullScreenModalComponent; + + constructor(private route: ActivatedRoute, + private curatorsService: CuratorService, + private communityService: CommunityService, + private userRegistryService: UserRegistryService, + private _router: Router, + private helper: HelperService, + private _meta: Meta, + private _title: Title, + private seoService: SEOService, + private _piwikService: PiwikService) { + } + + ngOnInit() { + this.showLoading = true; + this.properties = properties; + this.downloadUrl = this.properties.utilsService + '/download/'; + //if (properties.environment !== 'development') { + if (!this.longView) { + this.subs.push(this.communityService.getCommunityAsObservable().subscribe(community => { + if (community) { + this.community = community; + this.getCurators(); + } + })); + } else { + this.subs.push(this.communityService.getCommunityAsObservable().subscribe(community => { + if (community) { + this.community = community; + this.subs.push(this._piwikService.trackView(this.properties, this.pageTitle).subscribe()); + this.url = this.properties.domain + this._router.url; + this.seoService.createLinkForCanonicalURL(this.url); + this.updateUrl(this.url); + this.updateTitle(this.pageTitle); + this.updateDescription("OpenAIRE - Connect, Community Gateway, research community"); + //this.getDivContents(); + this.getPageContents(); + this.getCurators(); + } + })); + } + } + + ngOnDestroy() { + for (let sub of this.subs) { + sub.unsubscribe(); + } + } + + private getCurators() { + this.subs.push(this.curatorsService.getCurators(this.properties, this.community.communityId).subscribe(curators => { + this.curators = curators; + this.showLoading = false; + }, error => { + console.error(error); + this.curators = []; + this.showLoading = false; + })); + } + + private getPageContents() { + this.subs.push(this.helper.getPageHelpContents(this.properties, this.community.communityId, this._router.url).subscribe(contents => { + this.pageContents = contents; + })); + } + + private getDivContents() { + this.subs.push(this.helper.getDivHelpContents(this.properties, this.community.communityId, this._router.url).subscribe(contents => { + this.divContents = contents; + })); + } + + format(name: string) { + if (name) { + return (((name).length > this.maxCharacters) ? (name.substring(0, (this.maxCharacters - ('...').length)) + '...') : name); + } else { + return null; + } + } + + public viewMore() { + this.viewingMore = !this.viewingMore; + } + + public openFsModal(curator) { + this.curatorInModal = curator; + this.fsModal.title = this.community.shortTitle + ' Curator'; + this.fsModal.open(); + } + + private updateDescription(description: string) { + this._meta.updateTag({content: description}, "name='description'"); + this._meta.updateTag({content: description}, "property='og:description'"); + } + + private updateTitle(title: string) { + var _title = ((title.length > 50) ? title.substring(0, 50) : title); + this._title.setTitle(_title); + this._meta.updateTag({content: _title}, "property='og:title'"); + } + + private updateUrl(url: string) { + this._meta.updateTag({content: url}, "property='og:url'"); + } +} diff --git a/connect/components/curators/curators.module.ts b/connect/components/curators/curators.module.ts new file mode 100644 index 00000000..475e26be --- /dev/null +++ b/connect/components/curators/curators.module.ts @@ -0,0 +1,35 @@ +import { NgModule} from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; + +import {CuratorsComponent} from './curators.component'; +import {CuratorService} from "../../curators/curator.service"; +import {CuratorsRoutingModule} from "./curators-routing.module"; +import {HelperModule} from "../../../utils/helper/helper.module"; +import {Schema2jsonldModule} from "../../../sharedComponents/schema2jsonld/schema2jsonld.module"; +import {SEOServiceModule} from "../../../sharedComponents/SEO/SEOService.module"; +import {PiwikServiceModule} from "../../../utils/piwik/piwikService.module"; +import {BreadcrumbsModule} from "../../../utils/breadcrumbs/breadcrumbs.module"; +import {UrlPrefixModule} from "../../../utils/pipes/url-prefix.module"; +import {LoadingModule} from '../../../utils/loading/loading.module'; +import {FullScreenModalModule} from '../../../utils/modal/full-screen-modal/full-screen-modal.module'; +import {AffiliationsModule} from "../../affiliations/affiliations.module"; + +@NgModule({ + imports: [ + CommonModule, FormsModule, RouterModule, + CuratorsRoutingModule, AffiliationsModule, HelperModule, + Schema2jsonldModule, SEOServiceModule, PiwikServiceModule, + BreadcrumbsModule, UrlPrefixModule, LoadingModule, + FullScreenModalModule + ], + declarations: [ + CuratorsComponent + ], + providers: [CuratorService], + exports: [ + CuratorsComponent + ] +}) +export class CuratorsModule {} diff --git a/connect/contentProviders/searchDataproviders.service.ts b/connect/contentProviders/searchDataproviders.service.ts index cbf7e76b..7e2fcbdd 100644 --- a/connect/contentProviders/searchDataproviders.service.ts +++ b/connect/contentProviders/searchDataproviders.service.ts @@ -6,13 +6,13 @@ import {map} from "rxjs/operators"; @Injectable() export class SearchCommunityDataprovidersService { constructor(private http: HttpClient ) {} - searchDataproviders (properties:EnvProperties, pid: string):any { - let url = properties.communityAPI+pid+"/contentproviders"; + searchDataproviders (properties:EnvProperties, pid: string, deposit = false):any { + let url = properties.communityAPI+pid+"/datasources" + (deposit?'?deposit=true':''); return this.http.get((properties.useCache)? (properties.cacheUrl+encodeURIComponent(url)): url); } countTotalDataproviders(properties:EnvProperties,pid:string) { - let url = properties.communityAPI+pid+"/contentproviders"; + let url = properties.communityAPI+pid+"/datasources"; return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) .pipe(map(res => res['length'])); } diff --git a/connect/zenodoCommunities/zenodo-communities.service.ts b/connect/zenodoCommunities/zenodo-communities.service.ts index 296f41bb..0fee55b8 100644 --- a/connect/zenodoCommunities/zenodo-communities.service.ts +++ b/connect/zenodoCommunities/zenodo-communities.service.ts @@ -42,7 +42,7 @@ export class ZenodoCommunitiesService { var result: ZenodoCommunityInfo = new ZenodoCommunityInfo(); let metadata = resData["metadata"]; result['title'] = metadata.title; - result['id'] = resData.id; + result['id'] = resData.slug; result['description'] = metadata.description; result['link'] = resData.links.self_html; result['logoUrl'] = resData.links.logo; diff --git a/connect/zenodoCommunities/zenodoCommunityInfo.ts b/connect/zenodoCommunities/zenodoCommunityInfo.ts index 5fb7df3f..ed3263fd 100644 --- a/connect/zenodoCommunities/zenodoCommunityInfo.ts +++ b/connect/zenodoCommunities/zenodoCommunityInfo.ts @@ -6,4 +6,5 @@ export class ZenodoCommunityInfo { logoUrl: string; date: Date; page: string; + master:boolean = false; } diff --git a/dashboard/divId/divIds.component.ts b/dashboard/divId/divIds.component.ts index 28908c8b..2c3d964c 100644 --- a/dashboard/divId/divIds.component.ts +++ b/dashboard/divId/divIds.component.ts @@ -143,7 +143,7 @@ export class DivIdsComponent implements OnInit { this.deleteDivIdsFromArray(this.selectedDivIds); NotificationHandler.rise('Classes have been successfully deleted'); this.showLoading = false; - this._clearCacheService.clearCache("Class ids deleted"); + //this._clearCacheService.clearCache("Class ids deleted"); }, error => this.handleUpdateError('System error deleting the selected classes', error) )); @@ -195,7 +195,7 @@ export class DivIdsComponent implements OnInit { divId => { this.divIdSavedSuccessfully(divId); NotificationHandler.rise('Class ' + divId.name + ' has been successfully created'); - this._clearCacheService.clearCache("Class id saved"); + //this._clearCacheService.clearCache("Class id saved"); }, error => this.handleUpdateError("System error creating class", error) )); @@ -204,7 +204,7 @@ export class DivIdsComponent implements OnInit { divId => { this.divIdUpdatedSuccessfully(divId); NotificationHandler.rise('Class ' + divId.name + ' has been successfully updated'); - this._clearCacheService.clearCache("Class id updated"); + //this._clearCacheService.clearCache("Class id updated"); }, error => this.handleUpdateError("System error updating class", error) )); diff --git a/dashboard/divhelpcontent/class-help-content-form.component.ts b/dashboard/divhelpcontent/class-help-content-form.component.ts index e24c876e..6ce4d961 100644 --- a/dashboard/divhelpcontent/class-help-content-form.component.ts +++ b/dashboard/divhelpcontent/class-help-content-form.component.ts @@ -166,7 +166,7 @@ export class ClassContentFormComponent implements OnInit { this._router.navigate(['../'], {queryParams: {"pageId": this.pageId}, relativeTo: this.route}); NotificationHandler.rise('Page content has been successfully updated'); this.showLoading = false; - this._clearCacheService.clearCache("Class help text saved or updated"); + this._clearCacheService.clearCacheInRoute("Class help text saved or updated",this.portal, this.page.route); }, err => this.handleUpdateError('System error saving page content', err) )); diff --git a/dashboard/divhelpcontent/class-help-contents.component.ts b/dashboard/divhelpcontent/class-help-contents.component.ts index d59cd7d9..cbf8a6ff 100644 --- a/dashboard/divhelpcontent/class-help-contents.component.ts +++ b/dashboard/divhelpcontent/class-help-contents.component.ts @@ -155,7 +155,7 @@ export class ClassHelpContentsComponent implements OnInit { this.deletePageHelpContentsFromArray(this.selectedPageContents); NotificationHandler.rise('Page content(s) has been successfully deleted'); this.showLoading = false; - this._clearCacheService.clearCache("Class text texts deleted"); + this._clearCacheService.clearCacheInRoute("Class text texts deleted",this.portal, this.page.route); }, error => this.handleUpdateError('System error deleting the selected page content(s)', error) )); @@ -198,7 +198,7 @@ export class ClassHelpContentsComponent implements OnInit { this.countClassHelpContents(); this.applyCheck(false); NotificationHandler.rise('Page content(s) has been successfully updated'); - this._clearCacheService.clearCache("class help text's status changed"); + this._clearCacheService.clearCacheInRoute("class help text's status changed",this.portal, this.page.route); }, error => this.handleUpdateError('System error changing the status of the selected page content(s)', error) )); diff --git a/dashboard/entity/entities.component.ts b/dashboard/entity/entities.component.ts index 38fa4c6d..4abf71a4 100644 --- a/dashboard/entity/entities.component.ts +++ b/dashboard/entity/entities.component.ts @@ -202,8 +202,8 @@ export class EntitiesComponent implements OnInit { this.deleteEntitiesFromArray(this.selectedEntities); NotificationHandler.rise('Entities have been successfully deleted'); this.showLoading = false; - this._clearCacheService.clearCache("entities deleted"); - this._clearCacheService.purgeBrowserCache("entities deleted", this.portal); + // this._clearCacheService.clearCache("entities deleted"); + // this._clearCacheService.purgeBrowserCache("entities deleted", this.portal); }, error => this.handleUpdateError('System error deleting the selected entities', error) ); @@ -244,8 +244,8 @@ export class EntitiesComponent implements OnInit { entity => { this.entityUpdatedSuccessfully(entity); NotificationHandler.rise('Entity ' + entity.name + ' has been successfully updated'); - this._clearCacheService.clearCache("entity updated"); - this._clearCacheService.purgeBrowserCache("entity updated", this.portal); + // this._clearCacheService.clearCache("entity updated"); + // this._clearCacheService.purgeBrowserCache("entity updated", this.portal); }, error => this.handleUpdateError('System error updating entity', error) ); @@ -254,8 +254,8 @@ export class EntitiesComponent implements OnInit { entity => { this.entitySavedSuccessfully(entity); NotificationHandler.rise('Entity ' + entity.name + ' has been successfully created'); - this._clearCacheService.clearCache("entity saved"); - this._clearCacheService.purgeBrowserCache("entity saved", this.portal) + // this._clearCacheService.clearCache("entity saved"); + // this._clearCacheService.purgeBrowserCache("entity saved", this.portal) }, error => this.handleUpdateError('System error creating entity', error) ); @@ -345,7 +345,7 @@ export class EntitiesComponent implements OnInit { this.checkboxes[i].entity.isEnabled = this.toggleStatus; } this.applyCheck(false); - this._clearCacheService.clearCache("entity's status changed"); + this._clearCacheService.clearCacheInRoute("entity's status changed", this.portal, "/"); this._clearCacheService.purgeBrowserCache("entity's status changed", this.portal); }, error => this.handleUpdateError('System error changing the status of the selected entity(-ies)', error) diff --git a/dashboard/helpTexts/page-help-content-form.component.html b/dashboard/helpTexts/page-help-content-form.component.html index bae2f90b..030e7434 100644 --- a/dashboard/helpTexts/page-help-content-form.component.html +++ b/dashboard/helpTexts/page-help-content-form.component.html @@ -34,9 +34,9 @@
-
-
+
Select Status (Enable/ disable) diff --git a/dashboard/helpTexts/page-help-content-form.component.ts b/dashboard/helpTexts/page-help-content-form.component.ts index 5cba1d54..60af26c9 100644 --- a/dashboard/helpTexts/page-help-content-form.component.ts +++ b/dashboard/helpTexts/page-help-content-form.component.ts @@ -199,7 +199,7 @@ export class PageContentFormComponent implements OnInit { NotificationHandler.rise('Page content has been successfully ' + (this.pageContentId ? 'updated' : 'created') + ''); this._router.navigate(['../'], {queryParams: {"pageId": this.pageId}, relativeTo: this.route}); this.showLoading = false; - this._clearCacheService.clearCache("page help content saved"); + this._clearCacheService.clearCacheInRoute("page help content saved",this.portal, this.page.route); }, err => this.handleUpdateError('System error saving page content', err) )); diff --git a/dashboard/helpTexts/page-help-contents.component.ts b/dashboard/helpTexts/page-help-contents.component.ts index deba6ebd..0d8458d0 100644 --- a/dashboard/helpTexts/page-help-contents.component.ts +++ b/dashboard/helpTexts/page-help-contents.component.ts @@ -165,7 +165,7 @@ export class PageHelpContentsComponent implements OnInit { this.deletePageHelpContentsFromArray(this.selectedPageContents); NotificationHandler.rise('Page content(s) has been successfully deleted'); this.showLoading = false; - this._clearCacheService.clearCache("Help texts deleted"); + this._clearCacheService.clearCacheInRoute("Help texts deleted",this.portal, this.page.route); }, error => this.handleUpdateError('System error deleting the selected page content(s)', error) )); @@ -210,7 +210,7 @@ export class PageHelpContentsComponent implements OnInit { NotificationHandler.rise('Page content(s) has been successfully updated'); this.countPageHelpContents(); this.applyCheck(false); - this._clearCacheService.clearCache("Help text's status changed"); + this._clearCacheService.clearCacheInRoute("Help text's status changed",this.portal, this.page.route); }, error => this.handleUpdateError('System error changing the status of the selected page content(s)', error) )); diff --git a/dashboard/menu/menu.component.ts b/dashboard/menu/menu.component.ts index d756a77f..11914b6c 100644 --- a/dashboard/menu/menu.component.ts +++ b/dashboard/menu/menu.component.ts @@ -271,8 +271,8 @@ export class MenuComponent implements OnInit { this.deleteMenuItemFromArray(this.selectedMenuItem, this.isChild); NotificationHandler.rise("Menu item have been successfully deleted"); this.showLoading = false; - this._clearCacheService.clearCache("Menu item deleted"); - this._clearCacheService.purgeBrowserCache("Menu item deleted", this.portal); + this._clearCacheService.clearCacheInRoute("Menu item deleted",this.portal, "/"); + }, error => this.handleError("Server error deleting menu item", error) ) @@ -313,8 +313,7 @@ export class MenuComponent implements OnInit { menuItem => { this.menuItemSavedSuccessfully(menuItem, true); NotificationHandler.rise('Menu item ' + menuItem.title + ' has been successfully created'); - this._clearCacheService.clearCache("Menu item saved"); - this._clearCacheService.purgeBrowserCache("Menu item saved", this.portal); + this._clearCacheService.clearCacheInRoute("Menu item saved",this.portal, "/"); }, error => this.handleError("System error creating menu item", error) ) @@ -325,8 +324,7 @@ export class MenuComponent implements OnInit { menuItem => { this.menuItemSavedSuccessfully(menuItem, false); NotificationHandler.rise('Menu item ' + menuItem.title + ' has been successfully updated'); - this._clearCacheService.clearCache("Menu item updated"); - this._clearCacheService.purgeBrowserCache("Menu item updated", this.portal); + this._clearCacheService.clearCacheInRoute("Menu item updated",this.portal, "/"); }, error => this.handleError("System error updating menu item", error) ) @@ -392,8 +390,7 @@ export class MenuComponent implements OnInit { HelperFunctions.swap(temp, index, newIndex); this._helpContentService.reorderMenuItems(temp, this.portal).subscribe(() => { HelperFunctions.swap(this.featuredMenuItems, index, newIndex); - this._clearCacheService.clearCache("Menu items reordered"); - this._clearCacheService.purgeBrowserCache("Menu items reordered", this.portal); + this._clearCacheService.clearCacheInRoute("Menu items reordered",this.portal, "/"); }, error => { this.handleError("System error reordering menu items", error); }); @@ -405,8 +402,7 @@ export class MenuComponent implements OnInit { HelperFunctions.swap(temp, index, newIndex); this._helpContentService.reorderMenuItems(temp, this.portal).subscribe(() => { HelperFunctions.swap(children && children.length ? children : this.normalMenuItems, index, newIndex); - this._clearCacheService.clearCache("Menu items reordered"); - this._clearCacheService.purgeBrowserCache("Menu items reordered", this.portal); + this._clearCacheService.clearCacheInRoute("Menu items reordered",this.portal, "/"); }, error => { this.handleError("System error reordering menu items", error); }); @@ -421,8 +417,7 @@ export class MenuComponent implements OnInit { } else { this.showNormalMenu = status; } - this._clearCacheService.clearCache("Menu toggled"); - this._clearCacheService.purgeBrowserCache("Menu toggled", this.portal); + this._clearCacheService.clearCacheInRoute("Menu toggled",this.portal, "/"); NotificationHandler.rise("Menu has been successfully toggled to be "+(status?"visible":"hidden")+""); }, error => { this.handleError("System error toggling menu", error); @@ -434,8 +429,7 @@ export class MenuComponent implements OnInit { this.subscriptions.push( this._helpContentService.alignMenu(MenuAlignment[alignment], this.portal).subscribe(() => { this.featuredAlignment = alignment; - this._clearCacheService.clearCache("Menu aligned"); - this._clearCacheService.purgeBrowserCache("Menu aligned", this.portal); + this._clearCacheService.clearCacheInRoute("Menu aligned",this.portal, "/"); NotificationHandler.rise("Menu has been successfully "+alignment.toLowerCase()+" aligned"); }, error => { this.handleError("System error aligning menu to the "+alignment.toLowerCase(), error); diff --git a/dashboard/page/pages.component.html b/dashboard/page/pages.component.html index 24296b20..e925ff12 100644 --- a/dashboard/page/pages.component.html +++ b/dashboard/page/pages.component.html @@ -88,14 +88,23 @@ @@ -122,6 +130,16 @@ +
+ +
+
+
+ +
+ + + + +
+ +
+
+ +
+
+
+ + + +
+ +
Link #{{j + 1}}
+
+ +
+
+ +
+
+
+
+ + `, + + +}) +export class PluginCardInfoFormComponent extends PluginBaseFormComponent { + selectedIndex = -1; + @Input() editSubmenuOpen; + + constructor() { + super() + } + + ngOnChanges(changes: SimpleChanges) { + if (this.editSubmenuOpen == false && this.selectedIndex > -1) { + this.close(); + } + } + + cardShowChanged(i, $event: PluginEditEvent) { + this.pluginObject.cardInfoArray[i].show = $event.value; + $event.value = this.pluginObject.cardInfoArray; + this.valuesChanged.emit({field: $event.field, value: $event.value, type: 'parent'}) + } + + cardValueChanged(i, $event: PluginEditEvent) { + this.pluginObject.cardInfoArray[i][$event.field] = $event.value; + $event.value = this.pluginObject.cardInfoArray + this.valuesChanged.emit({field: "cardInfoArray", value: $event.value, type: 'parent'}) + } + + cardUrlValueChanged(i, j, $event: PluginEditEvent) { + if (this.editTemplate) { + this.pluginObject.cardInfoArray[i].urlsArray[j][$event.field] = $event.value; + $event.value = this.pluginObject.cardInfoArray; + } else { + this.pluginObject.cardInfoArray[i].urlsArray[j][$event.field] = $event.value; + $event.value = this.pluginObject.cardInfoArray; + } + + this.valuesChanged.emit({field: "cardInfoArray", value: $event.value, type: 'parent'}) + } + + edit(i) { + this.selectedIndex = i; + this.toggleSubMenu(true); + } + + close() { + this.selectedIndex = -1; + this.toggleSubMenu(false); + } +} diff --git a/dashboard/plugins/components/card-info/plugin-card-info.component.html b/dashboard/plugins/components/card-info/plugin-card-info.component.html new file mode 100644 index 00000000..cef8227f --- /dev/null +++ b/dashboard/plugins/components/card-info/plugin-card-info.component.html @@ -0,0 +1,31 @@ +
+

+ {{pluginObject.title}} +

+

{{pluginObject.description}}

+
+
+ + +
+
+ +
+
+ {{card.title}} +
+
+ {{card.description}} +
+ + {{url.linkText}} + +
+
+
+
+
+
diff --git a/dashboard/plugins/components/card-info/plugin-card-info.component.ts b/dashboard/plugins/components/card-info/plugin-card-info.component.ts new file mode 100644 index 00000000..016c08e7 --- /dev/null +++ b/dashboard/plugins/components/card-info/plugin-card-info.component.ts @@ -0,0 +1,24 @@ +import {Component} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo, PluginInfoCards, PluginURL} from "../../utils/base-plugin.component"; +export class PluginCardInfo extends PluginBaseInfo{ + title:string ="Lorem ipsum"; + description:string = "Lorem ipsum"; + cardInfoArray: PluginInfoCards[] = [ + {title: "Card 1", description: "Lorem ipsum", icon:"description", urlsArray:[ new PluginURL("https://exapmle.com","View all")], show:true}, + {title: "Card 2", description: "Lorem ipsum", icon:"description", urlsArray:[ new PluginURL("https://exapmle.com","")/*, new PluginURL("","Guide for the managers")*/], show:true}, + {title: "Card 3", description: "Lorem ipsum", icon:"description", urlsArray:[ new PluginURL("https://exapmle.com","View all")], show:true} + ]; + compare(oldObject){ + oldObject = super.compare(oldObject) + return oldObject; + } +} +@Component({ + selector: 'plugin-card-info', + templateUrl: 'plugin-card-info.component.html' +}) +export class PluginCardInfoComponent extends PluginBaseComponent{ + constructor() { + super() + } +} diff --git a/dashboard/plugins/components/card-info/plugin-card-info.module.ts b/dashboard/plugins/components/card-info/plugin-card-info.module.ts new file mode 100644 index 00000000..19c04b43 --- /dev/null +++ b/dashboard/plugins/components/card-info/plugin-card-info.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {IconsModule} from "../../../../utils/icons/icons.module"; +import {NumberRoundModule} from "../../../../utils/pipes/number-round.module"; +import {IconsService} from "../../../../utils/icons/icons.service"; +import {SearchResearchResultsServiceModule} from "../../../../services/searchResearchResultsService.module"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; +import {PluginCardInfoComponent} from "./plugin-card-info.component"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, IconsModule, NumberRoundModule, SearchResearchResultsServiceModule, PluginFieldEditModule + ], + providers:[PluginsService], + declarations: [PluginCardInfoComponent], + exports: [PluginCardInfoComponent] +}) +export class PluginCardInfoModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([]) + } +} diff --git a/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.component.html b/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.component.html new file mode 100644 index 00000000..dd72bf7a --- /dev/null +++ b/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.component.html @@ -0,0 +1,18 @@ +
+

+ {{pluginObject.title}} +

+ +
+ No subcommunities available +
+
+ No community info available +
+
diff --git a/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.component.ts b/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.component.ts new file mode 100644 index 00000000..3c41ee8d --- /dev/null +++ b/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.component.ts @@ -0,0 +1,31 @@ +import {Component} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo} from "../../utils/base-plugin.component"; +import {HttpClient} from "@angular/common/http"; +import {CommunityService} from "../../../../connect/community/community.service"; +export class PluginDiscoverBySubcommunity extends PluginBaseInfo{ + title:string ="Discover content by sub-community"; +} +@Component({ + selector: 'plugin-discover-by-subcommunity', + templateUrl: 'plugin-discover-by-subcommunity.component.html' +}) +export class PluginDiscoverBySubcommunityComponent extends PluginBaseComponent{ + subcommunities = null; + community; + constructor(http:HttpClient, private communityService: CommunityService) { + super() + this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe( + community => { + this.community = community; + if(community) { + this.subscriptions.push(http.get(this.properties.communityAPI + community.communityId + + "/subcommunities?all=false").subscribe(res => { + console.log(res) + this.subcommunities = res ? res : [] /* = res.splice(0,15)*/; + + })); + } + })); + + } +} diff --git a/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.form.component.ts b/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.form.component.ts new file mode 100644 index 00000000..eb4bb8de --- /dev/null +++ b/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.form.component.ts @@ -0,0 +1,21 @@ +import {Component} from '@angular/core'; +import {PluginDiscoverBySubcommunity} from "./plugin-discover-by-subcommunity.component"; +import {PluginBaseFormComponent} from "../../utils/base-plugin.form.component"; + +@Component({ + selector: 'plugin-discover-by-subcommunity-form', + template: ` +
+ +
+ + `, + + +}) +export class PluginDiscoverBySubcommunityFormComponent extends PluginBaseFormComponent { + constructor() { + super() + } +} diff --git a/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.module.ts b/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.module.ts new file mode 100644 index 00000000..744c8ae5 --- /dev/null +++ b/dashboard/plugins/components/discover-by-subcommunity/plugin-discover-by-subcommunity.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {IconsModule} from "../../../../utils/icons/icons.module"; +import {NumberRoundModule} from "../../../../utils/pipes/number-round.module"; +import {IconsService} from "../../../../utils/icons/icons.service"; +import {SearchResearchResultsServiceModule} from "../../../../services/searchResearchResultsService.module"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; +import {PluginDiscoverBySubcommunityComponent} from './plugin-discover-by-subcommunity.component'; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, IconsModule, NumberRoundModule, SearchResearchResultsServiceModule, PluginFieldEditModule + ], + providers:[PluginsService], + declarations: [PluginDiscoverBySubcommunityComponent], + exports: [PluginDiscoverBySubcommunityComponent] +}) +export class PluginDiscoverBySubcommunityModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([]) + } +} diff --git a/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.component.html b/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.component.html new file mode 100644 index 00000000..89575301 --- /dev/null +++ b/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.component.html @@ -0,0 +1,37 @@ + diff --git a/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.component.ts b/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.component.ts new file mode 100644 index 00000000..657f216a --- /dev/null +++ b/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.component.ts @@ -0,0 +1,71 @@ +import {Component, SimpleChanges} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo} from "../../utils/base-plugin.component"; +import {FetchResearchResults} from "../../../../utils/fetchEntitiesClasses/fetchResearchResults.class"; +import {SearchResearchResultsService} from "../../../../services/searchResearchResults.service"; +import {properties} from "../../../../../../environments/environment"; +import {ResultPreview} from "../../../../utils/result-preview/result-preview"; + +export class PluginFeaturedDatasets extends PluginBaseInfo{ + title: string = "Featured datasets"; + textLine1: string = "Here are listed some of the most important energy datasets as selected by energy experts."; + textLine2: string = "Check them if you want to easily explore and visualize the European energy landscape, using only well-known datasets which you can trust."; + +} + +@Component({ + selector: 'plugin-featured-datasets', + templateUrl: 'plugin-featured-datasets.component.html' +}) + +export class PluginFeaturedDatasetsComponent extends PluginBaseComponent { + default = new PluginFeaturedDatasets(); + // public fetchFeaturedDatasets: FetchResearchResults; + page = 1; + size = 3; + slides = 1; + slideItems = 3; + totalNum = null; + results: ResultPreview[] = null; + constructor(private _searchResearchResultsService: SearchResearchResultsService) { + super() + // this.fetchFeaturedDatasets = new FetchResearchResults(this._searchResearchResultsService); + // this.fetchFeaturedDatasets.searchUtils.size = this.size; + // this.fetchFeaturedDatasets.getAllResultsForCommunity("dataset", "enermaps", 1, 50, this.properties, "enermaps::selection"); + this.subscriptions.push(this._searchResearchResultsService.advancedSearchResults("dataset", null, 1, 50, null, properties, "&type=results&fq=communityid=enermaps&fq=categoryid=" + encodeURIComponent("enermaps::selection")).subscribe( + data => { + console.log(data); + + this.totalNum = data[0]; + this.results = data[1].map( res => { + let resultPreview = ResultPreview.searchResultConvert(res, 'dataset') + resultPreview.hostedBy_collectedFrom = null; + resultPreview.measure = null; + return resultPreview + }) ; + console.log(this.totalNum = data[0], this.results); + + if(this.results && this.results.length>0) { + this.calculatePages(); + } + }, + err => { + + } + )); + } +/* ngOnChanges(changes: SimpleChanges) { + if(this.results) { + this.calculatePages(); + } + }*/ + calculatePages(){ + this.slides = 1; + if (this.results.length > this.slideItems) { + this.slides = parseInt('' + (this.results.length / this.slideItems)); + if(this.slides< (this.results.length / this.slideItems)){ + this.slides++; + } + } + } + +} diff --git a/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.form.component.ts b/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.form.component.ts new file mode 100644 index 00000000..ffd510b9 --- /dev/null +++ b/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.form.component.ts @@ -0,0 +1,37 @@ +import {Component} from '@angular/core'; +import {OpenaireEntities} from "../../../../utils/properties/searchFields"; +import {PluginFeaturedDatasets} from "./plugin-featured-datasets.component"; +import {PluginBaseFormComponent} from "../../utils/base-plugin.form.component"; + +@Component({ + selector: 'plugin-featured-datasets-form', + template: ` +
+
+ + +
+
+ +
+
+ +
+
+ `, + + +}) +export class PluginFeaturedDatasetsFormComponent extends PluginBaseFormComponent { + selectedIndex = null; + openaireEntities = OpenaireEntities; + + constructor() { + super() + + } + +} diff --git a/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.module.ts b/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.module.ts new file mode 100644 index 00000000..13d7bd6c --- /dev/null +++ b/dashboard/plugins/components/featured-datasets/plugin-featured-datasets.module.ts @@ -0,0 +1,29 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {IconsModule} from "../../../../utils/icons/icons.module"; +import {NumberRoundModule} from "../../../../utils/pipes/number-round.module"; +import {IconsService} from "../../../../utils/icons/icons.service"; +import {SearchResearchResultsServiceModule} from "../../../../services/searchResearchResultsService.module"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; +import {PluginFeaturedDatasetsComponent} from './plugin-featured-datasets.component'; +import {NoLoadPaging} from "../../../../searchPages/searchUtils/no-load-paging.module"; +import {SearchResultsModule} from "../../../../searchPages/searchUtils/searchResults.module"; +import {ResultPreviewModule} from "../../../../utils/result-preview/result-preview.module"; +import {PagingModule} from "../../../../utils/paging.module"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, IconsModule, NumberRoundModule, SearchResearchResultsServiceModule, ResultPreviewModule, PagingModule + ], + providers:[PluginsService], + declarations: [PluginFeaturedDatasetsComponent], + exports: [PluginFeaturedDatasetsComponent] +}) +export class PluginFeaturedDatasetsModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([]) + } +} diff --git a/dashboard/plugins/components/gateway-information/plugin-gateway-information.component.html b/dashboard/plugins/components/gateway-information/plugin-gateway-information.component.html new file mode 100644 index 00000000..a1ca5c4d --- /dev/null +++ b/dashboard/plugins/components/gateway-information/plugin-gateway-information.component.html @@ -0,0 +1,229 @@ +
+ No community info available +
+
+
+ +
+
+ {{community.displayShortTitle}} +
+

+ {{community.displayTitle}} +

+ +
+
+ + +
+
+
+ + +
+
+
+
+
+ {{ pluginObject.title}} +
+ + +
+ +
+
+ Created: {{community.date | date:'dd-MMM-yyyy'}} +
+
+
+ +
+ + {{contentProviderTotal|number}} + + + {{openaireEntities.DATASOURCES}} + + + + +
+
+ +
+
+
+ +
+ +
+
+
diff --git a/dashboard/plugins/components/gateway-information/plugin-gateway-information.component.less b/dashboard/plugins/components/gateway-information/plugin-gateway-information.component.less new file mode 100644 index 00000000..099bd4a1 --- /dev/null +++ b/dashboard/plugins/components/gateway-information/plugin-gateway-information.component.less @@ -0,0 +1,16 @@ +.plugin-gateway-information { + overflow: hidden; + position: relative; + .plugin-background { + object-fit: cover; + opacity: 0.3; + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + } + .plugin-content { + position: relative; + } +} \ No newline at end of file diff --git a/dashboard/plugins/components/gateway-information/plugin-gateway-information.component.ts b/dashboard/plugins/components/gateway-information/plugin-gateway-information.component.ts new file mode 100644 index 00000000..9a03ea69 --- /dev/null +++ b/dashboard/plugins/components/gateway-information/plugin-gateway-information.component.ts @@ -0,0 +1,275 @@ +import {ChangeDetectorRef, Component} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo} from "../../utils/base-plugin.component"; +import {ConfigurationService} from '../../../../../openaireLibrary/utils/configuration/configuration.service'; +import {CommunityService} from '../../../../../openaireLibrary/connect/community/community.service'; +import {SearchCommunityProjectsService} from '../../../../../openaireLibrary/connect/projects/searchProjects.service'; +import {SearchCommunityDataprovidersService} from '../../../../../openaireLibrary/connect/contentProviders/searchDataproviders.service'; +import {ZenodoCommunitiesService} from '../../../../../openaireLibrary/connect/zenodoCommunities/zenodo-communities.service'; +import {User} from '../../../../../openaireLibrary/login/utils/helper.class'; +import {RouterHelper} from "../../../../utils/routerHelper.class"; +import {OpenaireEntities} from "../../../../utils/properties/searchFields"; +import {HttpClient} from "@angular/common/http"; +import {Filter} from "../../../../searchPages/searchUtils/searchHelperClasses.class"; +import {Router} from "@angular/router"; +import {SearchResearchResultsService} from "../../../../services/searchResearchResults.service"; +import {CustomizationService} from "../../../../services/customization.service"; + +export class PluginGatewayInformation extends PluginBaseInfo{ + showTitle:boolean = true; + showShortTitle:boolean = false; + description:boolean = false; + sdgs:boolean = false; + fos:boolean = false; + searchbar:boolean = false; + title:string ="Gateway Information"; + curators:boolean = true; + date:boolean = true; + communities:boolean = true; + projects:boolean = true; + organizations:boolean = true; + datasources:boolean = true; + subjects:boolean = true; + publications:boolean = true; + datasets:boolean = true; + software:boolean = true; + other:boolean = true; + + compare(oldObject): any { + let newObj= super.compare(oldObject); + return newObj; + } +} +@Component({ + selector: 'plugin-gateway-information', + templateUrl: 'plugin-gateway-information.component.html', + styleUrls: ['plugin-gateway-information.component.less'] +}) +export class PluginGatewayInformationComponent extends PluginBaseComponent{ + default = new PluginGatewayInformation(); + community = null; + portal = null; + params: any = {}; + + projectTotal = null; + contentProviderTotal = null; + projectsCalculated: boolean = false; + contentProvidersCalculated: boolean = false; + zenodoCommunityIdS = []; + masterZenodoCommunity = null; + + searchLinkToProjects: string = null; + searchLinkToDataProviders: string = null; + shareInZenodoPage: string = null; + + displayedAllSubjects = []; + displayedSubjects = []; + displayedSdg = []; + displayedFos = []; + resultCounts = null; + private user: User; + searchLinkToResults: string = null; + public routerHelper: RouterHelper = new RouterHelper(); + openaireEntities= OpenaireEntities; + + selectedEntity = 'result'; + selectedEntitySimpleUrl; + selectedEntityAdvancedUrl; + resultTypes: Filter = { + values: [], + filterId: "type", + countSelectedValues: 0, + filterType: 'checkbox', + originalFilterId: "", + valueIsExact: true, + title: "Type", + filterOperator: "or" + }; + + keyword: string = ""; + // customFilter; + placeholderText = "Search by title, author, abstract, DOI, orcid... "; + resultsQuickFilter: { filter: Filter, selected: boolean, filterId: string, value: string } = { + filter: null, + selected: true, + filterId: "resultbestaccessright", + value: "Open Access" + }; + disableSelect: boolean = true; + constructor(private http:HttpClient, + private config: ConfigurationService, + private communityService: CommunityService, + private searchCommunityProjectsService: SearchCommunityProjectsService, + private searchCommunityDataprovidersService: SearchCommunityDataprovidersService, + private zenodoCommunitiesService: ZenodoCommunitiesService, private _router: Router, + private _searchResearchResultsService: SearchResearchResultsService, + private cdr: ChangeDetectorRef, protected layoutService: CustomizationService) { + super(); + this.searchLinkToResults = this.properties.searchLinkToResults; + this.searchLinkToProjects = this.properties.searchLinkToProjects; + this.searchLinkToDataProviders = this.properties.searchLinkToDataProviders; + this.shareInZenodoPage = this.properties.shareInZenodoPage; + + this.subscriptions.push(this.config.portalAsObservable.subscribe( + res => { + this.portal = res; + }, + error => { + console.log(error); + } + )); + this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe( + community => { + this.community = community; + if (community) { + this.displayedSubjects = community.subjects; + this.displayedSdg = community.sdg; + this.displayedFos = community.fos; + this.displayedSubjects.forEach(element => { + this.displayedAllSubjects.push({value: element, type: 'resultsubject'}); + }); + this.displayedSdg.forEach(element => { + this.displayedAllSubjects.push({value: element, type: 'sdg'}); + }); + this.displayedFos.forEach(element => { + this.displayedAllSubjects.push({value: element, type: 'fos'}); + }); + if (this.properties.environment == "development") { + this.params = {communityId: community.communityId}; + } + if (this.community.zenodoCommunity) { + this.subscriptions.push(this.zenodoCommunitiesService.getZenodoCommunityById(this.properties, this.community.zenodoCommunity).subscribe( + res => { + this.masterZenodoCommunity = res; + }, + error => { + console.log(error); + } + )); + } + this.zenodoCommunityIdS = this.community.otherZenodoCommunities; + + // Double check below: is `this.community.communityId` correct? the other way was through @input communityID from ConnectHelper service - domain + this.subscriptions.push(this.searchCommunityProjectsService.countTotalProjects(this.properties, this.community.communityId).subscribe( + res => { + this.projectTotal = res; + }, + error => { + console.log(error); + }, + () => { + this.projectsCalculated = true; + } + )); + // Double check below: is `this.community.communityId` correct? the other way was through @input communityID from ConnectHelper service - domain + this.subscriptions.push(this.searchCommunityDataprovidersService.countTotalDataproviders(this.properties, this.community.communityId).subscribe( + res => { + this.contentProviderTotal = res; + }, + error => { + console.log(error); + }, + () => { + this.contentProvidersCalculated = true; + } + )); + this.subscriptions.push(this._searchResearchResultsService.countResults("communityid", this.community.communityId).subscribe(res => { + this.resultCounts = res; + })); + } + } + )); + + } + + ngOnInit() { + if (this.community) { + this.getLayout(this.community.communityId); + } + } + isEntityEnabled(entity: string) { + return this.portal.entities.some(x => x['pid'] == entity && x['isEnabled'] === true); + } + + isRouteEnabled(route: string) { + return this.portal && this.portal.pages.some(x => x['route'] == route && x['isEnabled'] === true); + } + + buildProjectsTooltip(): string { + let tooltipContent: string = "
"; + + if (this.projectTotal != null && this.projectTotal > 0 && this.isEntityEnabled('project') && this.isRouteEnabled(this.searchLinkToProjects)) { + tooltipContent += "Projects"; + } + + tooltipContent += " have been selected as relevant for your community by the gateway curators."; + tooltipContent += "
"; + + return tooltipContent; + } + + public buildContentProvidersTooltip(): string { + let tooltipContent: string = "
"; + + if (this.contentProviderTotal != null && this.contentProviderTotal > 0 && this.isEntityEnabled('datasource') && this.isRouteEnabled(this.searchLinkToDataProviders)) { + tooltipContent += "Data sources"; + } + + tooltipContent += " have been selected as relevant for your community by the gateway curators."; + tooltipContent += "
"; + + return tooltipContent; + } + + public buildZenodoCommunitiesTooltip(): string { + let tooltipContent: string = "
"; + + tooltipContent += "Zenodo is a catch-all repository for OpenAIRE."; + tooltipContent += "
A Zenodo Community is created and curated by Zenodo users.
"; + tooltipContent += "
"; + + return tooltipContent; + } + public getParamsForSearchLink(type: string = "") { + if (type) { + return this.routerHelper.createQueryParams(['type', 'qf', 'sortBy'], [type, 'false', 'resultdateofacceptance,descending']); + } else { + return {}; + } + } + + + entityChanged($event) { + this.selectedEntity = $event.entity; + this.selectedEntitySimpleUrl = $event.simpleUrl; + this.selectedEntityAdvancedUrl = $event.advancedUrl; + if (this.selectedEntity == 'result') { + this.placeholderText = "Search by title, author, abstract, DOI, orcid... "; + } else if (this.selectedEntity == 'project') { + this.placeholderText = "Search by project title, grant id, funder..."; + } else if (this.selectedEntity == 'dataprovider') { + this.placeholderText = "Search by name..."; + } else { + this.placeholderText = "Search community content"; + } + } + + goTo(simple: boolean) { + let url = (simple) ? this.selectedEntitySimpleUrl : this.selectedEntityAdvancedUrl; + let parameterNames = []; + let parameterValues = []; + + if (this.keyword.length > 0) { + parameterNames.push("fv0"); + parameterValues.push(this.keyword); + parameterNames.push("f0"); + parameterValues.push("q"); + } + this._router.navigate([url], {queryParams: this.routerHelper.createQueryParams(parameterNames, parameterValues)}); + } + + disableSelectChange(event: boolean) { + this.disableSelect = event; + this.cdr.detectChanges(); + } + +} diff --git a/dashboard/plugins/components/gateway-information/plugin-gateway-information.form.component.ts b/dashboard/plugins/components/gateway-information/plugin-gateway-information.form.component.ts new file mode 100644 index 00000000..b9250902 --- /dev/null +++ b/dashboard/plugins/components/gateway-information/plugin-gateway-information.form.component.ts @@ -0,0 +1,168 @@ +import {Component} from '@angular/core'; +import {PluginGatewayInformation} from "./plugin-gateway-information.component"; +import {OpenaireEntities} from "../../../../utils/properties/searchFields"; +import {PluginBaseFormComponent} from "../../utils/base-plugin.form.component"; + +@Component({ + selector: 'plugin-gateway-information-form', + template: ` +
+ +
+ Show or hide the following information: +
+
+ Community info +
+ +
+
+ + + Title + +
+
+ + + Short title + +
+
+ + + Description + +
+
+ + + Curated by + +
+
+ + Created + +
+
+ + + + {{openaireEntities.PROJECTS}} +
+
+ + + + Linked Zenodo communities +
+
+ + + + + {{openaireEntities.DATASOURCES}} +
+
+ + + + Subjects +
+
Manage community info here.
+
+ Pages & menus +
+
+ + + Search bar +
+
+ + + Browse by FOS +
+
+ + + Browse by SDGs +
+
+ + + {{openaireEntities.PUBLICATIONS}} +
+
+ + + + {{openaireEntities.DATASETS}} +
+
+ + + + {{openaireEntities.SOFTWARE}} +
+
+ + + + {{openaireEntities.OTHER}} +
+
+ +
If some information is enabled here, + but still not visible, please check related entity or page. +
+
+ Change the custom section background options here. +
+
+ `, + + +}) +export class PluginGatewayInformationFormComponent extends PluginBaseFormComponent { + openaireEntities= OpenaireEntities; + constructor() { + super() + + } + +} diff --git a/dashboard/plugins/components/gateway-information/plugin-gateway-information.module.ts b/dashboard/plugins/components/gateway-information/plugin-gateway-information.module.ts new file mode 100644 index 00000000..6370b0c5 --- /dev/null +++ b/dashboard/plugins/components/gateway-information/plugin-gateway-information.module.ts @@ -0,0 +1,37 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {IconsModule} from "../../../../utils/icons/icons.module"; +import {NumberRoundModule} from "../../../../utils/pipes/number-round.module"; +import {IconsService} from "../../../../utils/icons/icons.service"; +import {SearchResearchResultsServiceModule} from "../../../../services/searchResearchResultsService.module"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; +import {PluginGatewayInformationComponent} from './plugin-gateway-information.component'; +import {CuratorsModule} from '../../../../connect/components/curators/curators.module'; +import {SearchCommunityProjectsService} from '../../../../../openaireLibrary/connect/projects/searchProjects.service'; +import {SearchCommunityDataprovidersService} from '../../../../../openaireLibrary/connect/contentProviders/searchDataproviders.service'; +import {ZenodoCommunitiesService} from '../../../../../openaireLibrary/connect/zenodoCommunities/zenodo-communities.service'; +import {AdvancedSearchInputModule} from "../../../../sharedComponents/advanced-search-input/advanced-search-input.module"; +import {EntitiesSelectionModule} from "../../../../searchPages/searchUtils/entitiesSelection.module"; +import {QuickSelectionsModule} from "../../../../searchPages/searchUtils/quick-selections.module"; +import {InputModule} from "../../../../sharedComponents/input/input.module"; +import {CustomizationServiceModule} from "../../../../services/customizationService.module"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, IconsModule, NumberRoundModule, SearchResearchResultsServiceModule, PluginFieldEditModule, + CuratorsModule, AdvancedSearchInputModule, EntitiesSelectionModule, QuickSelectionsModule, InputModule, CustomizationServiceModule + ], + providers: [ + PluginsService, SearchCommunityProjectsService, SearchCommunityDataprovidersService, ZenodoCommunitiesService + ], + declarations: [PluginGatewayInformationComponent], + exports: [PluginGatewayInformationComponent] +}) +export class PluginGatewayInformationModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([]) + } +} diff --git a/dashboard/plugins/components/html-section/plugin-html-section.component.ts b/dashboard/plugins/components/html-section/plugin-html-section.component.ts new file mode 100644 index 00000000..ba1ca982 --- /dev/null +++ b/dashboard/plugins/components/html-section/plugin-html-section.component.ts @@ -0,0 +1,28 @@ +import {Component} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo, PluginURL} from "../../utils/base-plugin.component"; + +export class HTMLSection extends PluginBaseInfo{ + title:string ="Lorem ipsum" + html:string = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`; + fullWidth:boolean = true; + compare(oldObject): any { + let newObj= super.compare(oldObject); + return newObj; + } +} +@Component({ + selector: 'plugin-html-section', + template: ` +
+

{{pluginObject.title}}

+
+
+
+ ` +}) +export class PluginHtmlSectionComponent extends PluginBaseComponent{ + constructor() { + super(); + } + +} diff --git a/dashboard/plugins/components/html-section/plugin-html-section.form.component.ts b/dashboard/plugins/components/html-section/plugin-html-section.form.component.ts new file mode 100644 index 00000000..518a22bb --- /dev/null +++ b/dashboard/plugins/components/html-section/plugin-html-section.form.component.ts @@ -0,0 +1,33 @@ +import {Component} from '@angular/core'; +import {PluginBaseFormComponent, PluginEditEvent} from "../../utils/base-plugin.form.component"; +import {HTMLSection} from "./plugin-html-section.component"; + +@Component({ + selector: 'plugin-html-section-form', + template: ` +
+ + +
+ +
+
+ + Full width +
+
+ + `, + + +}) +export class PluginHtmlSectionFormComponent extends PluginBaseFormComponent { + constructor() { + super() + + } +} diff --git a/dashboard/plugins/components/html-section/plugin-html-section.module.ts b/dashboard/plugins/components/html-section/plugin-html-section.module.ts new file mode 100644 index 00000000..534e8d91 --- /dev/null +++ b/dashboard/plugins/components/html-section/plugin-html-section.module.ts @@ -0,0 +1,22 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; +import {InputModule} from "../../../../sharedComponents/input/input.module"; +import {PluginHtmlSectionComponent} from "./plugin-html-section.component"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, PluginFieldEditModule, InputModule + ], + providers: [ + PluginsService + ], + declarations: [PluginHtmlSectionComponent], + exports: [PluginHtmlSectionComponent] +}) +export class PluginHtmlSectionModule { + +} diff --git a/dashboard/plugins/components/openaireProducts/plugin-openaire-products.component.ts b/dashboard/plugins/components/openaireProducts/plugin-openaire-products.component.ts new file mode 100644 index 00000000..42bfe15c --- /dev/null +++ b/dashboard/plugins/components/openaireProducts/plugin-openaire-products.component.ts @@ -0,0 +1,97 @@ +import {Component, SimpleChanges} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo} from "../../utils/base-plugin.component"; +import {HttpClient} from "@angular/common/http"; + +export class PluginOpenAIREProducts extends PluginBaseInfo{ + title:string ="OpenAIRE services for your community"; + serviceIdsArray = ["argos","zenodo","amnesia"]; + compare(oldObject): any { + return super.compare(oldObject); + } +} +@Component({ + selector: 'plugin-openaire-products', + template: ` +
+

{{pluginObject.title}}

+ +
+
    +
  • +
    +
    +
    +
    + +
    +
    +
    {{service.name}}
    +
    {{service.tagline}}
    +
    + Read more +
    +
    +
    + +
    +
  • +
+
    +
    +
    + No products info available + +
    +
    + + `, + + +}) +export class PluginOpenaireProductsComponent extends PluginBaseComponent{ + services = null; + excludedServiceIds = ["openaire_login","research_community_dashboard"] + servicesToShow = null; + slides = 1; + slideItems = 3; + api= "https://catalogue.openaire.eu/api/catalogue-resources?from=0&quantity=100&order=asc&orderField=name"; + showErrorMessage = false; + constructor(private http:HttpClient) { + super() + } + ngOnInit(): void { + super.ngOnInit(); + if(!this.services) { + this.subscriptions.push(this.http.get( this.properties.cacheUrl + encodeURIComponent(this.api)).subscribe(res =>{ + this.services = res["results"].map( x=> { + if(x.id.indexOf("openaire.")!=-1){ + x.id = x.id.split("openaire.")[1] + } + return x; + }); + this.services = this.services.filter(x=> this.excludedServiceIds.indexOf(x.id) ==-1); + this.calculatePages(); + }, error => { + this.showErrorMessage = true; + })) + }else{ + this.calculatePages(); + } + } + + ngOnChanges(changes: SimpleChanges) { + if(this.services) { + this.calculatePages(); + } + } + calculatePages(){ + this.slides = 1; + this.servicesToShow = this.services.filter(x => this.pluginObject.serviceIdsArray.indexOf(x.id) != -1); + if (this.servicesToShow.length > this.slideItems) { + this.slides = parseInt('' + (this.servicesToShow.length / this.slideItems)); + if(this.slides< (this.servicesToShow.length / this.slideItems)){ + this.slides++; + } + } + } +} diff --git a/dashboard/plugins/components/openaireProducts/plugin-openaire-products.form.component.ts b/dashboard/plugins/components/openaireProducts/plugin-openaire-products.form.component.ts new file mode 100644 index 00000000..7dfc5292 --- /dev/null +++ b/dashboard/plugins/components/openaireProducts/plugin-openaire-products.form.component.ts @@ -0,0 +1,70 @@ +import {Component} from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {PluginOpenAIREProducts} from "./plugin-openaire-products.component"; +import {PluginBaseFormComponent, PluginEditEvent} from "../../utils/base-plugin.form.component"; + +@Component({ + selector: 'plugin-openaire-products-form', + template: ` +
    + + +
    + Select services: +
    + + +
    + + + {{service.name}} +
    +
    +
    + No products info available + +
    + +
    + + `, + + +}) +//TODO make it extend PluginOpenaireProductsComponent (to avoid call in constructor..) +export class PluginOpenaireProductsFormComponent extends PluginBaseFormComponent{ + default = new PluginOpenAIREProducts(); + services = []; + excludedServiceIds = ["openaire_login","research_community_dashboard"] + api= "https://catalogue.openaire.eu/api/catalogue-resources?from=0&quantity=100&order=asc&orderField=name"; + showErrorMessage = false; + constructor(http:HttpClient) { + super() + this.subscriptions.push(http.get( this.properties.cacheUrl + encodeURIComponent(this.api)).subscribe(res =>{ + this.services = res["results"].map( x=> { + x.id = x.id.split("openaire.")[1] + return x; + }); + this.services = this.services.filter(x=> this.excludedServiceIds.indexOf(x.id) ==-1); + }, error => { + this.showErrorMessage = true; + })) + + } + + serviceChanged(id,$event:PluginEditEvent){ + let index = this.pluginObject.serviceIdsArray.indexOf(id); + if(index !=-1){ + this.pluginObject.serviceIdsArray.splice(index,1); + }else{ + this.pluginObject.serviceIdsArray.push(id); + } + $event.value =this.pluginObject.serviceIdsArray; + + this.valuesChanged.emit({field:$event.field, value: $event.value, type: 'parent'}) + } + +} diff --git a/dashboard/plugins/components/openaireProducts/plugin-openaire-products.module.ts b/dashboard/plugins/components/openaireProducts/plugin-openaire-products.module.ts new file mode 100644 index 00000000..af6231f1 --- /dev/null +++ b/dashboard/plugins/components/openaireProducts/plugin-openaire-products.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {IconsModule} from "../../../../utils/icons/icons.module"; +import {NumberRoundModule} from "../../../../utils/pipes/number-round.module"; +import {IconsService} from "../../../../utils/icons/icons.service"; +import {SearchResearchResultsServiceModule} from "../../../../services/searchResearchResultsService.module"; +import {PluginOpenaireProductsComponent} from "./plugin-openaire-products.component"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, IconsModule, NumberRoundModule, SearchResearchResultsServiceModule, PluginFieldEditModule + ], + providers:[PluginsService], + declarations: [PluginOpenaireProductsComponent], + exports: [PluginOpenaireProductsComponent] +}) +export class PluginOpenaireProductsModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([]) + } +} diff --git a/dashboard/plugins/components/organizations/plugin-organizations.component.html b/dashboard/plugins/components/organizations/plugin-organizations.component.html new file mode 100644 index 00000000..a6f00c7d --- /dev/null +++ b/dashboard/plugins/components/organizations/plugin-organizations.component.html @@ -0,0 +1,7 @@ + +
    + No community info available +
    diff --git a/dashboard/plugins/components/organizations/plugin-organizations.component.ts b/dashboard/plugins/components/organizations/plugin-organizations.component.ts new file mode 100644 index 00000000..307299b7 --- /dev/null +++ b/dashboard/plugins/components/organizations/plugin-organizations.component.ts @@ -0,0 +1,34 @@ +import {Component} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo} from "../../utils/base-plugin.component"; +import {ConfigurationService} from "../../../../utils/configuration/configuration.service"; + +export class PluginOrganizations extends PluginBaseInfo{ + title: string = "Supporting Organizations"; + +} + +@Component({ + selector: 'plugin-organizations', + templateUrl: 'plugin-organizations.component.html' +}) + +export class PluginOrganizationsComponent extends PluginBaseComponent { + portal; + constructor(private config: ConfigurationService) { + super() + this.subscriptions.push(this.config.portalAsObservable.subscribe( + res => { + this.portal = res; + }, + error => { + console.log(error); + } + )); + } + + isRouteEnabled(route: string) { + return this.portal && this.portal.pages.some(x => x['route'] == route && x['isEnabled'] === true); + } + + +} diff --git a/dashboard/plugins/components/organizations/plugin-organizations.form.component.ts b/dashboard/plugins/components/organizations/plugin-organizations.form.component.ts new file mode 100644 index 00000000..468e7f6a --- /dev/null +++ b/dashboard/plugins/components/organizations/plugin-organizations.form.component.ts @@ -0,0 +1,24 @@ +import {Component} from '@angular/core'; +import {PluginOrganizations} from "./plugin-organizations.component"; +import {PluginBaseFormComponent} from "../../utils/base-plugin.form.component"; + +@Component({ + selector: 'plugin-organizations-form', + template: ` +
    + + +
    Manage community organizations here.
    +
    + `, + + +}) +export class PluginOrganizationsFormComponent extends PluginBaseFormComponent { + constructor() { + super() + + } + +} diff --git a/dashboard/plugins/components/organizations/plugin-organizations.module.ts b/dashboard/plugins/components/organizations/plugin-organizations.module.ts new file mode 100644 index 00000000..00d0c084 --- /dev/null +++ b/dashboard/plugins/components/organizations/plugin-organizations.module.ts @@ -0,0 +1,22 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {IconsService} from "../../../../utils/icons/icons.service"; +import {PluginOrganizationsComponent} from './plugin-organizations.component'; +import {AffiliationsModule} from "../../../../connect/affiliations/affiliations.module"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, AffiliationsModule, + ], + providers:[PluginsService], + declarations: [PluginOrganizationsComponent], + exports: [PluginOrganizationsComponent] +}) +export class PluginOrganizationsModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([]) + } +} diff --git a/dashboard/plugins/components/paragraph-info/plugin-graph-info.component.html b/dashboard/plugins/components/paragraph-info/plugin-graph-info.component.html new file mode 100644 index 00000000..8d8f17bf --- /dev/null +++ b/dashboard/plugins/components/paragraph-info/plugin-graph-info.component.html @@ -0,0 +1,34 @@ +
    +
    +
    +
    +
    +
    +
    +

    {{pluginObject.title}}

    +
    +
    +
    +
    +
    + Graph nodes +
    +
    +
    +
    + +
    diff --git a/dashboard/plugins/components/paragraph-info/plugin-graph-info.component.ts b/dashboard/plugins/components/paragraph-info/plugin-graph-info.component.ts new file mode 100644 index 00000000..46fe0595 --- /dev/null +++ b/dashboard/plugins/components/paragraph-info/plugin-graph-info.component.ts @@ -0,0 +1,24 @@ +import {Component} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo, PluginURL} from "../../utils/base-plugin.component"; + +export class ParagraphInfo extends PluginBaseInfo{ + title:string ="Lorem ipsum" + paragraph1:string = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`; + paragraph2:string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + url:PluginURL= new PluginURL("https://example.com","Lorem ipsum") + image:string = "https://admin.connect.openaire.eu/assets/common-assets/placeholder.png" + compare(oldObject): any { + let newObj= super.compare(oldObject); + return newObj; + } +} +@Component({ + selector: 'plugin-graph-info', + templateUrl: 'plugin-graph-info.component.html' +}) +export class PluginGraphInfoComponent extends PluginBaseComponent{ + constructor() { + super(); + } + +} diff --git a/dashboard/plugins/components/paragraph-info/plugin-graph-info.form.component.ts b/dashboard/plugins/components/paragraph-info/plugin-graph-info.form.component.ts new file mode 100644 index 00000000..29bec860 --- /dev/null +++ b/dashboard/plugins/components/paragraph-info/plugin-graph-info.form.component.ts @@ -0,0 +1,52 @@ +import {Component} from '@angular/core'; +import {PluginBaseFormComponent, PluginEditEvent} from "../../utils/base-plugin.form.component"; +import {ParagraphInfo} from "./plugin-graph-info.component"; + +@Component({ + selector: 'plugin-graph-info-form', + template: ` +
    + +
    + +
    +
    + +
    +
    + +
    +
    Link
    +
    + +
    +
    + +
    +
    + `, + + +}) +export class PluginGraphInfoFormComponent extends PluginBaseFormComponent { + constructor() { + super() + + } + + urlValueChanged($event: PluginEditEvent) { + + this.pluginObject.url[$event.field] = $event.value; + $event.value = this.pluginObject.url; + this.valuesChanged.emit({field: "url", value: $event.value, type: 'parent'}) + } + +} diff --git a/dashboard/plugins/components/paragraph-info/plugin-graph-info.module.ts b/dashboard/plugins/components/paragraph-info/plugin-graph-info.module.ts new file mode 100644 index 00000000..6670d184 --- /dev/null +++ b/dashboard/plugins/components/paragraph-info/plugin-graph-info.module.ts @@ -0,0 +1,22 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; +import {InputModule} from "../../../../sharedComponents/input/input.module"; +import {PluginGraphInfoComponent} from "./plugin-graph-info.component"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, PluginFieldEditModule, InputModule + ], + providers: [ + PluginsService + ], + declarations: [PluginGraphInfoComponent], + exports: [PluginGraphInfoComponent] +}) +export class PluginGraphInfoModule { + +} diff --git a/dashboard/plugins/components/search-bar/plugin-search-bar.component.ts b/dashboard/plugins/components/search-bar/plugin-search-bar.component.ts new file mode 100644 index 00000000..efc1fb63 --- /dev/null +++ b/dashboard/plugins/components/search-bar/plugin-search-bar.component.ts @@ -0,0 +1,137 @@ +import {ChangeDetectorRef, Component} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo} from "../../utils/base-plugin.component"; +import {OpenaireEntities} from "../../../../utils/properties/searchFields"; +import {CustomizationService} from "../../../../services/customization.service"; +import {CommunityService} from "../../../../connect/community/community.service"; +import {Filter} from "../../../../searchPages/searchUtils/searchHelperClasses.class"; +import {Router} from "@angular/router"; +import {RouterHelper} from "../../../../utils/routerHelper.class"; + +export class PluginSearchBar extends PluginBaseInfo{ + alternativeTitle:string =""; + showTitle:boolean = true; + showShortTitle:boolean = false; + + compare(oldObject): any { + let newObj= super.compare(oldObject); + return newObj; + } +} +@Component({ + selector: 'plugin-search-bar', + template: ` +
    + No community info available +
    +
    + +
    +
    +

    + {{community.displayShortTitle}} +

    +

    + {{pluginObject.alternativeTitle}} +

    +
    + {{community.displayTitle}} +
    + +
    + + +
    +
    +
    +
    +
    +
    + + ` +}) +export class PluginSearchBarComponent extends PluginBaseComponent{ + disableSelect: boolean = true; + openaireEntities= OpenaireEntities; + + selectedEntity = 'result'; + selectedEntitySimpleUrl; + selectedEntityAdvancedUrl; + keyword: string = ""; + // customFilter; + placeholderText = "Search by title, author, abstract, DOI, orcid... "; + resultTypes: Filter = { + values: [], + filterId: "type", + countSelectedValues: 0, + filterType: 'checkbox', + originalFilterId: "", + valueIsExact: true, + title: "Type", + filterOperator: "or" + }; + community = null; + + public routerHelper: RouterHelper = new RouterHelper(); + + constructor(private communityService: CommunityService, protected layoutService: CustomizationService, private cdr: ChangeDetectorRef, private _router: Router,) { + super() + + this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe( + community => { + this.community = community; + if(community) { + this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe( + community => { + this.getLayout(community.communityId); + + })); + } + } + )); + } + ngOnInit() { + this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe( + community => { + if(community) { + this.getLayout(community.communityId); + } + })); + } + + goTo(simple: boolean) { + let url = (simple) ? this.selectedEntitySimpleUrl : this.selectedEntityAdvancedUrl; + let parameterNames = []; + let parameterValues = []; + + + if (this.keyword.length > 0) { + parameterNames.push("fv0"); + parameterValues.push(this.keyword); + parameterNames.push("f0"); + parameterValues.push("q"); + } + this._router.navigate([url], {queryParams: this.routerHelper.createQueryParams(parameterNames, parameterValues)}); + } + disableSelectChange(event: boolean) { + this.disableSelect = event; + this.cdr.detectChanges(); + } + entityChanged($event) { + this.selectedEntity = $event.entity; + this.selectedEntitySimpleUrl = $event.simpleUrl; + this.selectedEntityAdvancedUrl = $event.advancedUrl; + if (this.selectedEntity == 'result') { + this.placeholderText = "Search by title, author, abstract, DOI, orcid... "; + } else if (this.selectedEntity == 'project') { + this.placeholderText = "Search by project title, grant id, funder..."; + } else if (this.selectedEntity == 'dataprovider') { + this.placeholderText = "Search by name..."; + } else { + this.placeholderText = "Search community content"; + } + } +} diff --git a/dashboard/plugins/components/search-bar/plugin-search-bar.form.component.ts b/dashboard/plugins/components/search-bar/plugin-search-bar.form.component.ts new file mode 100644 index 00000000..fc196e8e --- /dev/null +++ b/dashboard/plugins/components/search-bar/plugin-search-bar.form.component.ts @@ -0,0 +1,47 @@ +import {Component} from '@angular/core'; +import {OpenaireEntities} from "../../../../utils/properties/searchFields"; +import {PluginBaseFormComponent} from "../../utils/base-plugin.form.component"; +import {PluginSearchBar} from "./plugin-search-bar.component"; + +@Component({ + selector: 'plugin-search-bar-form', + template: ` +
    + +
    + Show or hide the following information: +
    +
    +
    + + + Title + +
    +
    + + + Short title + +
    + +
    Manage community info here.
    +
    +
    + `, + + +}) +export class PluginSearchBarFormComponent extends PluginBaseFormComponent { + openaireEntities= OpenaireEntities; + constructor() { + super() + + } + +} diff --git a/dashboard/plugins/components/search-bar/plugin-search-bar.module.ts b/dashboard/plugins/components/search-bar/plugin-search-bar.module.ts new file mode 100644 index 00000000..ca9a5a4c --- /dev/null +++ b/dashboard/plugins/components/search-bar/plugin-search-bar.module.ts @@ -0,0 +1,30 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {IconsModule} from "../../../../utils/icons/icons.module"; +import {NumberRoundModule} from "../../../../utils/pipes/number-round.module"; +import {SearchResearchResultsServiceModule} from "../../../../services/searchResearchResultsService.module"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; +import {CuratorsModule} from '../../../../connect/components/curators/curators.module'; +import {AdvancedSearchInputModule} from "../../../../sharedComponents/advanced-search-input/advanced-search-input.module"; +import {EntitiesSelectionModule} from "../../../../searchPages/searchUtils/entitiesSelection.module"; +import {QuickSelectionsModule} from "../../../../searchPages/searchUtils/quick-selections.module"; +import {InputModule} from "../../../../sharedComponents/input/input.module"; +import {PluginSearchBarComponent} from "./plugin-search-bar.component"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, IconsModule, NumberRoundModule, SearchResearchResultsServiceModule, PluginFieldEditModule, + CuratorsModule, AdvancedSearchInputModule, EntitiesSelectionModule, QuickSelectionsModule, InputModule, + ], + providers: [ + PluginsService + ], + declarations: [PluginSearchBarComponent], + exports: [PluginSearchBarComponent] +}) +export class PluginSearchBarModule { + +} diff --git a/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.component.html b/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.component.html new file mode 100644 index 00000000..7c844e1b --- /dev/null +++ b/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.component.html @@ -0,0 +1,41 @@ +
    +
    +
    +

    + {{pluginObject.title}}. +

    +
    + + + + + +
    {{card.tag}}
    +
    + {{card.title}} +
    +
    {{card.description}}
    + + {{url.linkText}} + +
    +
    +
    + + + ipad + + + + + + + +
    +
    +
    +
    diff --git a/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.component.less b/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.component.less new file mode 100644 index 00000000..d64f48be --- /dev/null +++ b/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.component.less @@ -0,0 +1,7 @@ +//slider-column slider-nav-item .uk-active{ +// border-left: solid 2px @primary-color; +//} + + +@slider-nav-item-background-active: white; +@slider-nav-item-action-background: rgba(255, 255, 255, 0.50); diff --git a/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.component.ts b/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.component.ts new file mode 100644 index 00000000..76872444 --- /dev/null +++ b/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.component.ts @@ -0,0 +1,53 @@ +import {Component} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo, PluginInfoCards, PluginURL} from "../../utils/base-plugin.component"; +import {OpenaireEntities} from "../../../../utils/properties/searchFields"; +import {properties} from "../../../../../../environments/environment"; +import {CustomizationService} from "../../../../services/customization.service"; +import {CommunityService} from "../../../../connect/community/community.service"; +export class PluginSearchDepositLink extends PluginBaseInfo{ + title:string ="Search, link and deposit your research in one place"; + cardInfoArray: PluginInfoCards[] = [ + {tag: "SEARCH & BROWSE", title: "Discover research products in your community.", description: + "A view of the OpenAIRE Graph, configured by experts of your research community, who want to help you out with the data and literature deluge.", + urlsArray:[ new PluginURL("/search/find/research-outcomes","Start searching", null, true)], + image:'https://' + (properties.environment == 'production'?'':'beta.') + + 'connect.openaire.eu/assets/connect-assets/home/4.png',show:true}, + {tag: "DEPOSIT YOUR RESEARCH OUTCOME", title: "Publish your research in Open Access.", description:"" + , urlsArray:[ new PluginURL("/participate/deposit/learn-how","Deposit your research", null, true)], + image:'https://' + (properties.environment == 'production'?'':'beta.') + + 'connect.openaire.eu/assets/connect-assets/home/1.png',show:true}, + {tag: "LINK YOUR RESEARCH", title: "Contribute to your community.", description:"" + , urlsArray:[ new PluginURL("/participate/claim","Link your Research searching", null, true)], + image:'https://' + (properties.environment == 'production'?'':'beta.') + + 'connect.openaire.eu/assets/connect-assets/home/2.png',show:true}, + ]; + + compare(oldObject): any { + let newObj= super.compare(oldObject); + return newObj; + } +} +@Component({ + selector: 'plugin-search-deposit-link', + templateUrl: 'plugin-search-deposit-link.component.html', + styleUrls:[`plugin-search-deposit-link.component.less`] +}) +export class PluginSearchDepositLinkComponent extends PluginBaseComponent{ + entities= OpenaireEntities; + + constructor(private communityService: CommunityService, protected layoutService: CustomizationService) { + super() + } + ngOnInit() { + this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe( + community => { + if(community) { + this.getLayout(community.communityId); + } + })); + } + + get activeCards(){ + return this.pluginObject.cardInfoArray.filter( card => card.show); + } +} diff --git a/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.form.component.ts b/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.form.component.ts new file mode 100644 index 00000000..1bf696a2 --- /dev/null +++ b/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.form.component.ts @@ -0,0 +1,133 @@ +import {Component, Input, SimpleChanges} from '@angular/core'; +import {PluginSearchDepositLink} from "./plugin-search-deposit-link.component"; +import {PluginBaseFormComponent, PluginEditEvent} from "../../utils/base-plugin.form.component"; + +@Component({ + selector: 'plugin-search-deposit-link-form', + template: ` +
    + + + +
    + Cards: +
    + + +
    +
    + + {{card.tag?card.tag:card.title}} +
    + +
    + +
    +
    + +
    +
    + Change the custom section background options here. +
    +
    + + +
    + +
    +
    + +
    +
    + +
    + +
    Link #{{j + 1}}
    +
    + +
    +
    + +
    +
    +
    +
    + + + `, + + +}) +export class PluginSearchDepositLinkFormComponent extends PluginBaseFormComponent /*implements OnChanges*/ { + selectedIndex = -1; + @Input() editSubmenuOpen; + + constructor() { + super() + } + + + ngOnChanges(changes: SimpleChanges) { + if (this.editSubmenuOpen == false && this.selectedIndex > -1) { + this.close(); + } + } + + cardShowChanged(i, $event: PluginEditEvent) { + this.pluginObject.cardInfoArray[i].show = $event.value; + $event.value = this.pluginObject.cardInfoArray; + this.valuesChanged.emit({field: $event.field, value: $event.value, type: 'parent'}) + } + + cardValueChanged(i, $event: PluginEditEvent) { + this.pluginObject.cardInfoArray[i][$event.field] = $event.value; + $event.value = this.pluginObject.cardInfoArray; + this.valuesChanged.emit({field: "cardInfoArray", value: $event.value, type: 'parent'}) + } + cardUrlValueChanged(i, j, $event: PluginEditEvent) { + if (this.editTemplate) { + this.pluginObject.cardInfoArray[i].urlsArray[j][$event.field] = $event.value; + $event.value = this.pluginObject.cardInfoArray; + } else { + this.pluginObject.cardInfoArray[i].urlsArray[j][$event.field] = $event.value; + $event.value = this.pluginObject.cardInfoArray; + } + + this.valuesChanged.emit({field: "cardInfoArray", value: $event.value, type: 'parent'}) + } + + edit(i) { + this.selectedIndex = i; + this.toggleSubMenu(true); + } + + close() { + this.selectedIndex = -1; + this.toggleSubMenu(false); + } +} diff --git a/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.module.ts b/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.module.ts new file mode 100644 index 00000000..edcce0db --- /dev/null +++ b/dashboard/plugins/components/search-deposit-link/plugin-search-deposit-link.module.ts @@ -0,0 +1,27 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {IconsModule} from "../../../../utils/icons/icons.module"; +import {NumberRoundModule} from "../../../../utils/pipes/number-round.module"; +import {IconsService} from "../../../../utils/icons/icons.service"; +import {SearchResearchResultsServiceModule} from "../../../../services/searchResearchResultsService.module"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; +import {PluginSearchDepositLinkComponent} from './plugin-search-deposit-link.component'; +import {SliderUtilsModule} from "../../../../sharedComponents/slider-utils/slider-utils.module"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, IconsModule, NumberRoundModule, SearchResearchResultsServiceModule, + PluginFieldEditModule, SliderUtilsModule + ], + providers:[PluginsService], + declarations: [PluginSearchDepositLinkComponent], + exports: [PluginSearchDepositLinkComponent] +}) +export class PluginSearchDepositLinkModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([]) + } +} diff --git a/dashboard/plugins/components/stats/monitor.component.html b/dashboard/plugins/components/stats/monitor.component.html new file mode 100644 index 00000000..5cab53c6 --- /dev/null +++ b/dashboard/plugins/components/stats/monitor.component.html @@ -0,0 +1,196 @@ + +
    + +
    +
      + + +
    • + +
      + + +
      +
      +
      +
      + {{indicator.name + " "}} +
      + + +
      + +
      + +
      + +
      +
      +
      +
      + +
      +
      +

      + {{indicator.description}} +

      +

      + {{indicator.additionalDescription}} +

      +
      +
      +
      +
      +
      +
      + +
      +
      +
      <iframe width="500" height="500" 
      src="{{chartsActiveType.get(i + '-' + j).safeResourceUrl.changingThisBreaksApplicationSecurity}}"
      allowfullscreen="true" mozallowfullscreen="true">
      </iframe>
      +
      +
      + + + +
      +
      +
      +
      +
      +
      +
      +
      +
      +
    • +
      +
    +
      + +
      +
      + + +
      + +
      + No community info available +
      +
      diff --git a/dashboard/plugins/components/stats/monitor.component.ts b/dashboard/plugins/components/stats/monitor.component.ts new file mode 100644 index 00000000..f3fbf200 --- /dev/null +++ b/dashboard/plugins/components/stats/monitor.component.ts @@ -0,0 +1,102 @@ +import {ChangeDetectorRef, Component, Input} from "@angular/core"; +import {MonitorIndicatorStakeholderBaseComponent} from "src/app/openaireLibrary/monitor/monitor-indicator-stakeholder-base.component"; +import {map} from "rxjs/operators"; +import {StatisticsService} from "../../../../monitor-admin/utils/services/statistics.service"; +import {ActivatedRoute, Router} from "@angular/router"; +import {PiwikService} from "../../../../utils/piwik/piwik.service"; +import {DomSanitizer, Meta, Title} from "@angular/platform-browser"; +import {SEOService} from "../../../../sharedComponents/SEO/SEO.service"; +import {SearchResearchResultsService} from "../../../../services/searchResearchResults.service"; +import {HttpClient} from "@angular/common/http"; +import {IndicatorPath, Section, Visibility} from "../../../../monitor/entities/stakeholder"; +import {LayoutService} from "../../../sharedComponents/sidebar/layout.service"; +import {CommunityService} from "../../../../connect/community/community.service"; +import {PluginStats} from "./plugin-stats.component"; + +@Component({ + selector: 'plugin-stats-monitor', + templateUrl: 'monitor.component.html' +}) +export class MonitorComponent extends MonitorIndicatorStakeholderBaseComponent { + activeChartSectionIndex: number = 0; + stakeholder = null; + @Input() pluginObject: PluginStats; + profiles; + constructor(protected _route: ActivatedRoute, + protected _router: Router, + protected _meta: Meta, + protected _title: Title, + protected _piwikService: PiwikService, + protected seoService: SEOService, + protected sanitizer: DomSanitizer, + protected cdr: ChangeDetectorRef, + protected layoutService: LayoutService, + protected statisticsService: StatisticsService, + protected searchResearchResultsService: SearchResearchResultsService, + private communityService: CommunityService, + private http: HttpClient) { + super(); + } + + + ngOnInit() { + super.ngOnInit(); + this.requireLogin = false; + this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(communityInfo => { + + if (communityInfo) { + this.subscriptions.push(this.http.get(this.properties.monitorStatsFrameUrl+"/schema/profiles").subscribe((profiles:any[]) => { + this.profiles = profiles.map( (profile) => profile.name); + let profile = PluginStats.getDefaultProfile(); + if(this.profiles.indexOf("monitor_"+communityInfo.communityId.replace("-","_"))!=-1){ + profile = this.profiles[this.profiles.indexOf("monitor_"+communityInfo.communityId.replace("-","_"))]; + }else if(communityInfo.type == "ri" && this.profiles.indexOf("monitor_ris_tail")!=-1){ + profile = "monitor_ris_tail"; + } + this.init(communityInfo, profile); + }, error => { + let profile = + this.init(communityInfo, PluginStats.getDefaultProfile()); + })) + + + } + })); + } + public init(communityInfo, profile){ + console.log(profile) + this.loading = true; + this.stakeholder = PluginStats.getMockStakeholder(); + this.stakeholder.statsProfile = profile; + this.stakeholder.index_id = communityInfo.communityId + this.stakeholder.index_name = communityInfo.title; + this.stakeholder.index_shortName = communityInfo.shortTitle; + this.title = this.stakeholder.name; + this.description = this.stakeholder.name; + this.loading = true; + this.activeTopic = null; + this.activeCategory = null; + this.activeSubCategory = null; + this.numberResults = new Map(); + this.setView({}); + let ids = []; + for (let section of this.activeSubCategory.charts) { + for (let indicator of section.indicators) { + ids.push(indicator._id) + } + } + } + public showSection(section: Section): boolean { + for (let indicator of section.indicators) { + if (this.showIndicator(indicator)) { + return true; + } + } + return false; + + } + + public showIndicator(indicator): boolean { + return this.pluginObject.disabledIndicators.indexOf(indicator._id) == -1; + } +} diff --git a/dashboard/plugins/components/stats/monitor.module.ts b/dashboard/plugins/components/stats/monitor.module.ts new file mode 100644 index 00000000..35c900e7 --- /dev/null +++ b/dashboard/plugins/components/stats/monitor.module.ts @@ -0,0 +1,29 @@ +import {NgModule} from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {RouterModule} from "@angular/router"; +import {MonitorComponent} from "./monitor.component"; +import {PageContentModule} from "../../../../dashboard/sharedComponents/page-content/page-content.module"; +import {SliderTabsModule} from "../../../../sharedComponents/tabs/slider-tabs.module"; +import {NumberRoundModule} from "../../../../utils/pipes/number-round.module"; +import {IconsModule} from "../../../../utils/icons/icons.module"; +import {ClickModule} from "../../../../utils/click/click.module"; +import {RangeFilterModule} from "../../../../utils/rangeFilter/rangeFilter.module"; +import {SearchFilterModule} from "../../../../searchPages/searchUtils/searchFilter.module"; +import {IconsService} from "../../../../utils/icons/icons.service"; +import {filters} from "../../../../utils/icons/icons"; +import {SliderUtilsModule} from "../../../../sharedComponents/slider-utils/slider-utils.module"; +import {LoadingModule} from "../../../../utils/loading/loading.module"; + + +@NgModule({ + imports: [CommonModule, PageContentModule, SliderTabsModule, NumberRoundModule, IconsModule, ClickModule, RangeFilterModule, SearchFilterModule, SliderUtilsModule, LoadingModule], + declarations: [MonitorComponent], + exports: [ + MonitorComponent + ] +}) +export class MonitorModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([ filters]); + } +} diff --git a/dashboard/plugins/components/stats/plugin-stats.component.html b/dashboard/plugins/components/stats/plugin-stats.component.html new file mode 100644 index 00000000..580d04f4 --- /dev/null +++ b/dashboard/plugins/components/stats/plugin-stats.component.html @@ -0,0 +1,9 @@ +
      +

      {{pluginObject.title}}

      + + {{pluginObject.url.linkText}} + + + +
      diff --git a/dashboard/plugins/components/stats/plugin-stats.component.ts b/dashboard/plugins/components/stats/plugin-stats.component.ts new file mode 100644 index 00000000..78854773 --- /dev/null +++ b/dashboard/plugins/components/stats/plugin-stats.component.ts @@ -0,0 +1,35 @@ +import {Component} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo, PluginURL} from "../../utils/base-plugin.component"; +import {HttpClient} from "@angular/common/http"; + +export class PluginStats extends PluginBaseInfo{ + title = "Indicators" + disabledIndicators = []; + url:PluginURL = new PluginURL("123", "More","_blank", false); + + + compare(oldObject): any { + let newObj= super.compare(oldObject); + return newObj; + } + public static getMockStakeholder() { + let betaProfile = `{"type":"ri","projectUpdateDate":null,"index_id":"covid-19","index_name":"COVID-19","index_shortName":"COVID-19","statsProfile":"monitor","logoUrl":null,"isUpload":false,"name":"CONNECT","alias":"connect-template","description":null,"defaultId":null,"locale":"eu","visibility":"PUBLIC","funderType":null,"creationDate":1710257208064,"updateDate":1710314157384,"topics":[{"name":"Overview","alias":"overview","description":null,"icon":null,"visibility":"PUBLIC","creationDate":1710257226776,"updateDate":1710257226776,"defaultId":null,"categories":[{"name":"Overview","alias":"overview","description":null,"visibility":"PUBLIC","creationDate":1710257236271,"updateDate":1710257236271,"isOverview":false,"defaultId":null,"subCategories":[{"name":"Overview","alias":"overview","description":null,"visibility":"PUBLIC","creationDate":1710257236271,"updateDate":1710257236271,"defaultId":null,"charts":[{"title":"","defaultId":null,"stakeholderAlias":"connect-template","type":"chart","creationDate":1710257247165,"updateDate":1710257257995,"indicators":[{"name":"","description":"","additionalDescription":"","type":"chart","width":"medium","height":"medium","tags":null,"visibility":"RESTRICTED","creationDate":1710257247161,"updateDate":1710257247161,"defaultId":null,"indicatorPaths":[{"type":"bar","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighCharts\\",\\"chartDescription\\":{\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"((__type__))\\",\\"color\\":\\"#0500a5c7\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"result\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"result.concept.category.context.name\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"result.type\\",\\"type\\":\\"=\\",\\"values\\":[\\"publication\\"]},{\\"field\\":\\"result.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"result.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Open Access\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"result\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_1__))\\",\\"type\\":\\"bar\\",\\"color\\":\\"#705acfff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"result\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"result.concept.category.context.name\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"result.type\\",\\"type\\":\\"=\\",\\"values\\":[\\"publication\\"]},{\\"field\\":\\"result.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"result.access mode\\",\\"type\\":\\"!=\\",\\"values\\":[\\"Open Access\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"result\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}}],\\"colors\\":[\\"#0500a5c7\\",\\"#705acfff\\",\\"#2f7ed8\\",\\"#0d233a\\",\\"#8bbc21\\",\\"#910000\\",\\"#1aadce\\",\\"#492970\\",\\"#f28f43\\",\\"#77a1e5\\",\\"#c42525\\",\\"#a6c96a\\"],\\"series\\":[{\\"stacking\\":\\"percent\\"},{\\"stacking\\":\\"percent\\"}],\\"chart\\":{\\"type\\":\\"line\\",\\"polar\\":true,\\"backgroundColor\\":\\"#FFFFFFFF\\",\\"borderColor\\":\\"#335cadff\\",\\"borderRadius\\":0,\\"borderWidth\\":0,\\"plotBorderColor\\":\\"#ccccccff\\",\\"plotBorderWidth\\":0,\\"zoomType\\":\\"xy\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"margin\\":15,\\"align\\":\\"center\\"},\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"align\\":\\"center\\",\\"text\\":\\"((__subtitle__))\\"},\\"yAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__yAxisTitle__))\\"},\\"zoomEnabled\\":false,\\"reversedStacks\\":false},\\"xAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__xAxisTitle__))\\"},\\"zoomEnabled\\":false},\\"lang\\":{\\"noData\\":\\"No Data available for the Query\\"},\\"exporting\\":{\\"enabled\\":true},\\"plotOptions\\":{\\"series\\":{\\"dataLabels\\":{\\"enabled\\":false,\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0}},\\"stacking\\":\\"percent\\"}},\\"legend\\":{\\"layout\\":\\"horizontal\\",\\"align\\":\\"center\\",\\"verticalAlign\\":\\"bottom\\",\\"enabled\\":true},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"tooltip\\":{\\"style\\":{},\\"pointFormat\\":\\"{point.percentage:.1f}%25 ({point.y})\\"}}}","parameters":{"type":"bar","title":"% of OA publications","subtitle":"","xAxisTitle":"","yAxisTitle":"","data_title_0":"OA Publications","data_title_1":"Non OA Publications","index_name":"Aurora Universities Network","statsProfile":null},"filters":{}}],"_id":"65f0745f6e006565e5546e46"},{"name":"","description":"","additionalDescription":"","type":"chart","width":"medium","height":"medium","tags":null,"visibility":"RESTRICTED","creationDate":1710257247161,"updateDate":1710257247161,"defaultId":null,"indicatorPaths":[{"type":"bar","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighCharts\\",\\"chartDescription\\":{\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"((__type__))\\",\\"color\\":\\"#0500a5c7\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"result\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"result.concept.category.context.name\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"result.type\\",\\"type\\":\\"=\\",\\"values\\":[\\"dataset\\"]},{\\"field\\":\\"result.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"result.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Open Access\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"result\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_1__))\\",\\"type\\":\\"bar\\",\\"color\\":\\"#705acfff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"result\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"result.concept.category.context.name\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"result.type\\",\\"type\\":\\"=\\",\\"values\\":[\\"dataset\\"]},{\\"field\\":\\"result.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"result.access mode\\",\\"type\\":\\"!=\\",\\"values\\":[\\"Open Access\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"result\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}}],\\"colors\\":[\\"#0500a5c7\\",\\"#705acfff\\",\\"#2f7ed8\\",\\"#0d233a\\",\\"#8bbc21\\",\\"#910000\\",\\"#1aadce\\",\\"#492970\\",\\"#f28f43\\",\\"#77a1e5\\",\\"#c42525\\",\\"#a6c96a\\"],\\"series\\":[{\\"stacking\\":\\"percent\\"},{\\"stacking\\":\\"percent\\"}],\\"chart\\":{\\"type\\":\\"line\\",\\"polar\\":true,\\"backgroundColor\\":\\"#FFFFFFFF\\",\\"borderColor\\":\\"#335cadff\\",\\"borderRadius\\":0,\\"borderWidth\\":0,\\"plotBorderColor\\":\\"#ccccccff\\",\\"plotBorderWidth\\":0,\\"zoomType\\":\\"xy\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"margin\\":15,\\"align\\":\\"center\\"},\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"align\\":\\"center\\",\\"text\\":\\"((__subtitle__))\\"},\\"yAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__yAxisTitle__))\\"},\\"zoomEnabled\\":false,\\"reversedStacks\\":false},\\"xAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__xAxisTitle__))\\"},\\"zoomEnabled\\":false},\\"lang\\":{\\"noData\\":\\"No Data available for the Query\\"},\\"exporting\\":{\\"enabled\\":true},\\"plotOptions\\":{\\"series\\":{\\"dataLabels\\":{\\"enabled\\":false,\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0}},\\"stacking\\":\\"percent\\"}},\\"legend\\":{\\"layout\\":\\"horizontal\\",\\"align\\":\\"center\\",\\"verticalAlign\\":\\"bottom\\",\\"enabled\\":true},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"tooltip\\":{\\"style\\":{},\\"pointFormat\\":\\"{point.percentage:.1f}%25 ({point.y})\\"}}}","parameters":{"type":"bar","title":"% of OA Datasets","subtitle":"","xAxisTitle":"","yAxisTitle":"","data_title_0":"OA Datasets","data_title_1":"Non OA datasets","index_name":"Aurora Universities Network","statsProfile":null},"filters":{}}],"_id":"65f0745f6e006565e5546e47"}],"_id":"65f0745f6e006565e5546e45"},{"title":"","defaultId":null,"stakeholderAlias":"connect-template","type":"chart","creationDate":1710257247186,"updateDate":1710257270262,"indicators":[{"name":"","description":"","additionalDescription":"","type":"chart","width":"large","height":"large","tags":null,"visibility":"RESTRICTED","creationDate":1710257247161,"updateDate":1710257247161,"defaultId":null,"indicatorPaths":[{"type":"other","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighMaps\\",\\"mapDescription\\":{\\"chart\\":{\\"map\\":\\"custom/world-robinson-highres\\"},\\"colorAxis\\":{\\"min\\":null,\\"max\\":null,\\"type\\":\\"linear\\",\\"minColor\\":\\"#E6EBF5\\",\\"maxColor\\":\\"#003399\\"},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"exporting\\":{\\"enabled\\":true},\\"legend\\":{\\"layout\\":\\"horizontal\\",\\"align\\":\\"center\\",\\"verticalAlign\\":\\"bottom\\",\\"enabled\\":true},\\"mapNavigation\\":{\\"enabled\\":false},\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"world\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.organization.country\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"300\\"}}],\\"series\\":[{\\"data\\":[],\\"keys\\":[\\"iso-a2\\",\\"value\\"],\\"joinBy\\":\\"iso-a2\\",\\"dataLabels\\":{\\"enabled\\":false,\\"format\\":\\"{point.name}\\",\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0}},\\"name\\":\\"publications\\"}],\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"text\\":\\"((__subtitle__))\\",\\"align\\":\\"center\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"align\\":\\"center\\",\\"margin\\":15},\\"zoomTo\\":{\\"zoomValue\\":1}}}","parameters":{"title":"Publications","subtitle":"per country","xAxisTitle":"","yAxisTitle":"","data_title_0":"publications","index_name":"Aurora Universities Network","statsProfile":null},"filters":{}}],"_id":"65f0745f6e006565e5546e49"}],"_id":"65f0745f6e006565e5546e48"},{"title":"","defaultId":null,"stakeholderAlias":"connect-template","type":"chart","creationDate":1710257247201,"updateDate":1710257277981,"indicators":[{"name":"","description":"","additionalDescription":"","type":"chart","width":"medium","height":"large","tags":null,"visibility":"RESTRICTED","creationDate":1710257247161,"updateDate":1710257247161,"defaultId":null,"indicatorPaths":[{"type":"column","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighCharts\\",\\"chartDescription\\":{\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"((__type__))\\",\\"color\\":\\"#5aadcfff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"dataset\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"dataset.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"dataset.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"dataset.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"dataset.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"dataset\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_1__))\\",\\"type\\":\\"line\\",\\"color\\":\\"#7a7a7aff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"dataset\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"dataset.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"dataset.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"dataset.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"dataset.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]},{\\"field\\":\\"dataset.pid type\\",\\"type\\":\\"!=\\",\\"values\\":[\\"0\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"dataset\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}}],\\"colors\\":[\\"#5aadcfff\\",\\"#7a7a7aff\\",\\"#2f7ed8\\",\\"#0d233a\\",\\"#8bbc21\\",\\"#910000\\",\\"#1aadce\\",\\"#492970\\",\\"#f28f43\\",\\"#77a1e5\\",\\"#c42525\\",\\"#a6c96a\\"],\\"series\\":[{},{}],\\"chart\\":{\\"type\\":\\"line\\",\\"polar\\":false,\\"backgroundColor\\":\\"#FFFFFFFF\\",\\"borderColor\\":\\"#335cadff\\",\\"borderRadius\\":0,\\"borderWidth\\":0,\\"plotBorderColor\\":\\"#ccccccff\\",\\"plotBorderWidth\\":0,\\"zoomType\\":\\"xy\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"margin\\":15,\\"align\\":\\"center\\"},\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"text\\":\\"((__subtitle__))\\",\\"align\\":\\"center\\"},\\"yAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__yAxisTitle__))\\"},\\"zoomEnabled\\":false,\\"reversedStacks\\":false},\\"xAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__xAxisTitle__))\\"},\\"zoomEnabled\\":false},\\"lang\\":{\\"noData\\":\\"No Data available for the Query\\"},\\"exporting\\":{\\"enabled\\":true},\\"plotOptions\\":{\\"series\\":{\\"dataLabels\\":{\\"enabled\\":true,\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0,\\"color\\":\\"#000000ff\\"}}}},\\"legend\\":{\\"layout\\":\\"horizontal\\",\\"align\\":\\"center\\",\\"verticalAlign\\":\\"bottom\\",\\"enabled\\":true},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"tooltip\\":{\\"style\\":{}}}}","parameters":{"type":"column","title":"Datasets with a PID","subtitle":"over time","xAxisTitle":"","yAxisTitle":"datasets","data_title_0":"all datasets","data_title_1":"with PID","index_name":"Aurora Universities Network","start_year":"2007","end_year":"2022","statsProfile":null},"filters":{}}],"_id":"65f0745f6e006565e5546e4b"},{"name":"","description":"","additionalDescription":"","type":"chart","width":"medium","height":"large","tags":null,"visibility":"RESTRICTED","creationDate":1710257247161,"updateDate":1710257247161,"defaultId":null,"indicatorPaths":[{"type":"line","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighCharts\\",\\"chartDescription\\":{\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"((__type__))\\",\\"color\\":\\"#705acfff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"indi_pub_downloads_year.no_downloads\\",\\"aggregate\\":\\"sum\\"},{\\"field\\":\\"indi_pub_downloads_year.publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"indi_pub_downloads_year.publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"indi_pub_downloads_year.publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"indi_pub_downloads_year.publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"indi_pub_downloads_year\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"0\\"}}],\\"colors\\":[\\"#705acfff\\",\\"#2f7ed8\\",\\"#0d233a\\",\\"#8bbc21\\",\\"#910000\\",\\"#1aadce\\",\\"#492970\\",\\"#f28f43\\",\\"#77a1e5\\",\\"#c42525\\",\\"#a6c96a\\"],\\"series\\":[{}],\\"chart\\":{\\"type\\":\\"line\\",\\"polar\\":false,\\"backgroundColor\\":\\"#FFFFFFFF\\",\\"borderColor\\":\\"#335cadff\\",\\"borderRadius\\":0,\\"borderWidth\\":0,\\"plotBorderColor\\":\\"#ccccccff\\",\\"plotBorderWidth\\":0,\\"zoomType\\":\\"xy\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"margin\\":15,\\"align\\":\\"center\\"},\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"text\\":\\"((__subtitle__))\\",\\"align\\":\\"center\\"},\\"yAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__yAxisTitle__))\\"},\\"zoomEnabled\\":false,\\"reversedStacks\\":false},\\"xAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__xAxisTitle__))\\"},\\"zoomEnabled\\":false},\\"lang\\":{\\"noData\\":\\"No Data available for the Query\\"},\\"exporting\\":{\\"enabled\\":true},\\"plotOptions\\":{\\"series\\":{\\"dataLabels\\":{\\"enabled\\":false,\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0}}}},\\"legend\\":{\\"enabled\\":false},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"tooltip\\":{\\"style\\":{}}}}","parameters":{"type":"line","title":"Total Downloads","subtitle":"over time (year of publication)","xAxisTitle":"year","yAxisTitle":"downloads","data_title_0":"downloads","index_name":"Aurora Universities Network","start_year":"2002","end_year":"2022","statsProfile":null},"filters":{}}],"_id":"65f0745f6e006565e5546e4c"}],"_id":"65f0745f6e006565e5546e4a"},{"title":"","defaultId":null,"stakeholderAlias":"connect-template","type":"chart","creationDate":1710257247221,"updateDate":1710257284216,"indicators":[{"name":"","description":"","additionalDescription":"","type":"chart","width":"large","height":"large","tags":null,"visibility":"RESTRICTED","creationDate":1710257247161,"updateDate":1710257247161,"defaultId":null,"indicatorPaths":[{"type":"column","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighCharts\\",\\"chartDescription\\":{\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"((__type__))\\",\\"color\\":\\"#0500a5c7\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"publication.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Open Access\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_1__))\\",\\"type\\":\\"column\\",\\"color\\":\\"#9b81efff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"publication.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Embargo\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_2__))\\",\\"type\\":\\"column\\",\\"color\\":\\"#ff7171ff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"publication.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Restricted\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_3__))\\",\\"type\\":\\"column\\",\\"color\\":\\"#bd0202ff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"publication.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Closed Access\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_4__))\\",\\"type\\":\\"column\\",\\"color\\":\\"#b0b0b0ff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"publication.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"not available\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}}],\\"colors\\":[\\"#0500a5c7\\",\\"#9b81efff\\",\\"#ff7171ff\\",\\"#bd0202ff\\",\\"#b0b0b0ff\\",\\"#2f7ed8\\",\\"#0d233a\\",\\"#8bbc21\\",\\"#910000\\",\\"#1aadce\\",\\"#492970\\",\\"#f28f43\\",\\"#77a1e5\\",\\"#c42525\\",\\"#a6c96a\\"],\\"series\\":[{\\"stacking\\":\\"normal\\"},{\\"stacking\\":\\"normal\\"},{\\"stacking\\":\\"normal\\"},{\\"stacking\\":\\"normal\\"},{\\"stacking\\":\\"normal\\"}],\\"chart\\":{\\"type\\":\\"line\\",\\"polar\\":false,\\"backgroundColor\\":\\"#FFFFFFFF\\",\\"borderColor\\":\\"#335cadff\\",\\"borderRadius\\":0,\\"borderWidth\\":0,\\"plotBorderColor\\":\\"#ccccccff\\",\\"plotBorderWidth\\":0,\\"zoomType\\":\\"xy\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"margin\\":15,\\"align\\":\\"center\\"},\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"text\\":\\"((__subtitle__))\\",\\"align\\":\\"center\\"},\\"yAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__yAxisTitle__))\\"},\\"zoomEnabled\\":false,\\"reversedStacks\\":false},\\"xAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__xAxisTitle__))\\"},\\"zoomEnabled\\":false},\\"lang\\":{\\"noData\\":\\"No Data available for the Query\\"},\\"exporting\\":{\\"enabled\\":true},\\"plotOptions\\":{\\"series\\":{\\"dataLabels\\":{\\"enabled\\":false,\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0}},\\"stacking\\":\\"normal\\"}},\\"legend\\":{\\"layout\\":\\"horizontal\\",\\"align\\":\\"center\\",\\"verticalAlign\\":\\"bottom\\",\\"enabled\\":true},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"tooltip\\":{\\"style\\":{}}}}","parameters":{"type":"column","title":"Publications","subtitle":"by access rights, over time","xAxisTitle":"","yAxisTitle":"","data_title_0":"Open Access","data_title_1":"Embargo","data_title_2":"Restricted","data_title_3":"Closed Access","data_title_4":"not available","index_name":"Aurora Universities Network","start_year":"2007","end_year":"2022","statsProfile":null},"filters":{}}],"_id":"65f0745f6e006565e5546e4e"}],"_id":"65f0745f6e006565e5546e4d"}],"numbers":[],"_id":"65f074546e006565e5546e43"}],"_id":"65f074546e006565e5546e44"}],"_id":"65f0744a6e006565e5546e42"}],"_id":"65f074386e006565e5546e3f"}`; + let prodProfile = `{"type":"ri","projectUpdateDate":null,"index_id":"aurora","index_name":"Aurora Universities Network","index_shortName":"Aurora Universities Network","statsProfile":"monitor_aurora","logoUrl":null,"isUpload":false,"name":"CONNECT","alias":"connect-template","description":"Template profiles with the indicators to be embedded in CONNECT","defaultId":null,"locale":"eu","visibility":"PUBLIC","funderType":null,"creationDate":1710171610370,"updateDate":1711613628625,"topics":[{"name":"Overview","alias":"overview","description":null,"icon":null,"visibility":"PUBLIC","creationDate":1710171645832,"updateDate":1710171645832,"defaultId":null,"categories":[{"name":"Overview","alias":"overview","description":null,"visibility":"PUBLIC","creationDate":1710171681587,"updateDate":1710171681587,"isOverview":false,"defaultId":null,"subCategories":[{"name":"Overview","alias":"overview","description":null,"visibility":"PUBLIC","creationDate":1710171681587,"updateDate":1710171681587,"defaultId":null,"charts":[{"title":null,"defaultId":null,"stakeholderAlias":"connect-template","type":"chart","creationDate":1710256912328,"updateDate":1710256912328,"indicators":[{"name":"","description":"","additionalDescription":"","type":"chart","width":"medium","height":"medium","tags":null,"visibility":"PUBLIC","creationDate":null,"updateDate":1711612659389,"defaultId":null,"indicatorPaths":[{"type":"bar","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighCharts\\",\\"chartDescription\\":{\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"((__type__))\\",\\"color\\":\\"#0500a5c7\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"result\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"result.concept.category.context.name\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"result.type\\",\\"type\\":\\"=\\",\\"values\\":[\\"publication\\"]},{\\"field\\":\\"result.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"result.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Open Access\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"result\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_1__))\\",\\"type\\":\\"bar\\",\\"color\\":\\"#717171ff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"result\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"result.concept.category.context.name\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"result.type\\",\\"type\\":\\"=\\",\\"values\\":[\\"publication\\"]},{\\"field\\":\\"result.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"result.access mode\\",\\"type\\":\\"!=\\",\\"values\\":[\\"Open Access\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"result\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}}],\\"colors\\":[\\"#0500a5c7\\",\\"#717171ff\\",\\"#2f7ed8\\",\\"#0d233a\\",\\"#8bbc21\\",\\"#910000\\",\\"#1aadce\\",\\"#492970\\",\\"#f28f43\\",\\"#77a1e5\\",\\"#c42525\\",\\"#a6c96a\\"],\\"series\\":[{\\"stacking\\":\\"percent\\"},{\\"stacking\\":\\"percent\\"}],\\"chart\\":{\\"type\\":\\"line\\",\\"polar\\":true,\\"backgroundColor\\":\\"#FFFFFFFF\\",\\"borderColor\\":\\"#335cadff\\",\\"borderRadius\\":0,\\"borderWidth\\":0,\\"plotBorderColor\\":\\"#ccccccff\\",\\"plotBorderWidth\\":0,\\"zoomType\\":\\"xy\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"margin\\":15,\\"align\\":\\"center\\"},\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"align\\":\\"center\\",\\"text\\":\\"((__subtitle__))\\"},\\"yAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__yAxisTitle__))\\"},\\"zoomEnabled\\":false,\\"reversedStacks\\":false},\\"xAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__xAxisTitle__))\\"},\\"zoomEnabled\\":false},\\"lang\\":{\\"noData\\":\\"No Data available for the Query\\"},\\"exporting\\":{\\"enabled\\":true},\\"plotOptions\\":{\\"series\\":{\\"dataLabels\\":{\\"enabled\\":false,\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0}},\\"stacking\\":\\"percent\\"}},\\"legend\\":{\\"layout\\":\\"horizontal\\",\\"align\\":\\"center\\",\\"verticalAlign\\":\\"bottom\\",\\"enabled\\":true},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"tooltip\\":{\\"style\\":{},\\"pointFormat\\":\\"{point.percentage:.1f}%25 ({point.y})\\"}}}","parameters":{"type":"bar","title":"%25 of OA Publications","subtitle":"","xAxisTitle":"","yAxisTitle":"%25","data_title_0":"OA Publications","data_title_1":"Non OA Publications","index_name":"Aurora Universities Network"},"filters":{}}],"_id":"65f072eb6c2043760abba9a4"},{"name":"","description":"","additionalDescription":"","type":"chart","width":"medium","height":"medium","tags":null,"visibility":"PUBLIC","creationDate":null,"updateDate":1711612456266,"defaultId":null,"indicatorPaths":[{"type":"bar","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighCharts\\",\\"chartDescription\\":{\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"((__type__))\\",\\"color\\":\\"#0500a5c7\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"result\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"result.concept.category.context.name\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"result.type\\",\\"type\\":\\"=\\",\\"values\\":[\\"dataset\\"]},{\\"field\\":\\"result.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"result.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Open Access\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"result\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_1__))\\",\\"type\\":\\"bar\\",\\"color\\":\\"#717171ff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"result\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"result.concept.category.context.name\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"result.type\\",\\"type\\":\\"=\\",\\"values\\":[\\"dataset\\"]},{\\"field\\":\\"result.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"result.access mode\\",\\"type\\":\\"!=\\",\\"values\\":[\\"Open Access\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"result\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}}],\\"colors\\":[\\"#0500a5c7\\",\\"#717171ff\\",\\"#2f7ed8\\",\\"#0d233a\\",\\"#8bbc21\\",\\"#910000\\",\\"#1aadce\\",\\"#492970\\",\\"#f28f43\\",\\"#77a1e5\\",\\"#c42525\\",\\"#a6c96a\\"],\\"series\\":[{\\"stacking\\":\\"percent\\"},{\\"stacking\\":\\"percent\\"}],\\"chart\\":{\\"type\\":\\"line\\",\\"polar\\":true,\\"backgroundColor\\":\\"#FFFFFFFF\\",\\"borderColor\\":\\"#335cadff\\",\\"borderRadius\\":0,\\"borderWidth\\":0,\\"plotBorderColor\\":\\"#ccccccff\\",\\"plotBorderWidth\\":0,\\"zoomType\\":\\"xy\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"margin\\":15,\\"align\\":\\"center\\"},\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"align\\":\\"center\\",\\"text\\":\\"((__subtitle__))\\"},\\"yAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__yAxisTitle__))\\"},\\"zoomEnabled\\":false,\\"reversedStacks\\":false},\\"xAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__xAxisTitle__))\\"},\\"zoomEnabled\\":false},\\"lang\\":{\\"noData\\":\\"No Data available for the Query\\"},\\"exporting\\":{\\"enabled\\":true},\\"plotOptions\\":{\\"series\\":{\\"dataLabels\\":{\\"enabled\\":false,\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0}},\\"stacking\\":\\"percent\\"}},\\"legend\\":{\\"layout\\":\\"horizontal\\",\\"align\\":\\"center\\",\\"verticalAlign\\":\\"bottom\\",\\"enabled\\":true},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"tooltip\\":{\\"style\\":{},\\"pointFormat\\":\\"{point.percentage:.1f}%25 ({point.y})\\"}}}","parameters":{"type":"bar","title":"%25 of OA Datasets","subtitle":"","xAxisTitle":"","yAxisTitle":"%25","data_title_0":"OA Datasets","data_title_1":"Non OA datasets","index_name":"Aurora Universities Network"},"filters":{}}],"_id":"65f072bc7a76717ea88e49f7"}],"_id":"65f073106c2043760abba9a5"},{"title":null,"defaultId":null,"stakeholderAlias":"connect-template","type":"chart","creationDate":1710241327847,"updateDate":1710241327847,"indicators":[{"name":"","description":"","additionalDescription":"","type":"chart","width":"large","height":"large","tags":null,"visibility":"PUBLIC","creationDate":null,"updateDate":1711613602263,"defaultId":null,"indicatorPaths":[{"type":"other","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighMaps\\",\\"mapDescription\\":{\\"chart\\":{\\"map\\":\\"custom/world-robinson-highres\\"},\\"colorAxis\\":{\\"min\\":null,\\"max\\":null,\\"type\\":\\"linear\\",\\"minColor\\":\\"#E6EBF5\\",\\"maxColor\\":\\"#003399\\"},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"exporting\\":{\\"enabled\\":true},\\"legend\\":{\\"layout\\":\\"horizontal\\",\\"align\\":\\"center\\",\\"verticalAlign\\":\\"bottom\\",\\"enabled\\":true},\\"mapNavigation\\":{\\"enabled\\":false},\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"world\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.organization.country\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"300\\"}}],\\"series\\":[{\\"data\\":[],\\"keys\\":[\\"iso-a2\\",\\"value\\"],\\"joinBy\\":\\"iso-a2\\",\\"dataLabels\\":{\\"enabled\\":false,\\"format\\":\\"{point.name}\\",\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0}},\\"name\\":\\"publications\\"}],\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"text\\":\\"((__subtitle__))\\",\\"align\\":\\"center\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"align\\":\\"center\\",\\"margin\\":15},\\"zoomTo\\":{\\"zoomValue\\":1}}}","parameters":{"title":"Publications","subtitle":"per country","xAxisTitle":"","yAxisTitle":"","data_title_0":"publications","index_name":"Aurora Universities Network"},"filters":{}}],"_id":"65ef26647a76717ea88e49b9"}],"_id":"65f0362f7a76717ea88e49c5"},{"title":"","defaultId":null,"stakeholderAlias":"connect-template","type":"chart","creationDate":1710171748876,"updateDate":1710172326046,"indicators":[{"name":"","description":"","additionalDescription":"","type":"chart","width":"medium","height":"large","tags":null,"visibility":"PUBLIC","creationDate":null,"updateDate":1711613555808,"defaultId":null,"indicatorPaths":[{"type":"column","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighCharts\\",\\"chartDescription\\":{\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"((__type__))\\",\\"color\\":\\"#5aadcfff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"dataset\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"dataset.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"dataset.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"dataset.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"dataset.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"dataset\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_1__))\\",\\"type\\":\\"line\\",\\"color\\":\\"#7a7a7aff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"dataset\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"dataset.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"dataset.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"dataset.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"dataset.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]},{\\"field\\":\\"dataset.pid type\\",\\"type\\":\\"!=\\",\\"values\\":[\\"0\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"dataset\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}}],\\"colors\\":[\\"#5aadcfff\\",\\"#7a7a7aff\\",\\"#2f7ed8\\",\\"#0d233a\\",\\"#8bbc21\\",\\"#910000\\",\\"#1aadce\\",\\"#492970\\",\\"#f28f43\\",\\"#77a1e5\\",\\"#c42525\\",\\"#a6c96a\\"],\\"series\\":[{},{}],\\"chart\\":{\\"type\\":\\"line\\",\\"polar\\":false,\\"backgroundColor\\":\\"#FFFFFFFF\\",\\"borderColor\\":\\"#335cadff\\",\\"borderRadius\\":0,\\"borderWidth\\":0,\\"plotBorderColor\\":\\"#ccccccff\\",\\"plotBorderWidth\\":0,\\"zoomType\\":\\"xy\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"margin\\":15,\\"align\\":\\"center\\"},\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"text\\":\\"((__subtitle__))\\",\\"align\\":\\"center\\"},\\"yAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__yAxisTitle__))\\"},\\"zoomEnabled\\":false,\\"reversedStacks\\":false},\\"xAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__xAxisTitle__))\\"},\\"zoomEnabled\\":false},\\"lang\\":{\\"noData\\":\\"No Data available for the Query\\"},\\"exporting\\":{\\"enabled\\":true},\\"plotOptions\\":{\\"series\\":{\\"dataLabels\\":{\\"enabled\\":true,\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0,\\"color\\":\\"#000000ff\\"}}}},\\"legend\\":{\\"layout\\":\\"horizontal\\",\\"align\\":\\"center\\",\\"verticalAlign\\":\\"bottom\\",\\"enabled\\":true},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"tooltip\\":{\\"style\\":{}}}}","parameters":{"type":"column","title":"Datasets with a PID","subtitle":"over time","xAxisTitle":"","yAxisTitle":"datasets","data_title_0":"all datasets","data_title_1":"with PID","index_name":"Aurora Universities Network","start_year":"2007","end_year":"2023"},"filters":{}}],"_id":"65ef26a67a76717ea88e49bf"},{"name":"","description":"","additionalDescription":"","type":"chart","width":"medium","height":"large","tags":null,"visibility":"PUBLIC","creationDate":null,"updateDate":1711613539118,"defaultId":null,"indicatorPaths":[{"type":"line","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighCharts\\",\\"chartDescription\\":{\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"((__type__))\\",\\"color\\":\\"#705acfff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"indi_pub_downloads_year.no_downloads\\",\\"aggregate\\":\\"sum\\"},{\\"field\\":\\"indi_pub_downloads_year.publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"indi_pub_downloads_year.publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"indi_pub_downloads_year.publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"indi_pub_downloads_year.publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"indi_pub_downloads_year\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"0\\"}}],\\"colors\\":[\\"#705acfff\\",\\"#2f7ed8\\",\\"#0d233a\\",\\"#8bbc21\\",\\"#910000\\",\\"#1aadce\\",\\"#492970\\",\\"#f28f43\\",\\"#77a1e5\\",\\"#c42525\\",\\"#a6c96a\\"],\\"series\\":[{}],\\"chart\\":{\\"type\\":\\"line\\",\\"polar\\":false,\\"backgroundColor\\":\\"#FFFFFFFF\\",\\"borderColor\\":\\"#335cadff\\",\\"borderRadius\\":0,\\"borderWidth\\":0,\\"plotBorderColor\\":\\"#ccccccff\\",\\"plotBorderWidth\\":0,\\"zoomType\\":\\"xy\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"margin\\":15,\\"align\\":\\"center\\"},\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"text\\":\\"((__subtitle__))\\",\\"align\\":\\"center\\"},\\"yAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__yAxisTitle__))\\"},\\"zoomEnabled\\":false,\\"reversedStacks\\":false},\\"xAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__xAxisTitle__))\\"},\\"zoomEnabled\\":false},\\"lang\\":{\\"noData\\":\\"No Data available for the Query\\"},\\"exporting\\":{\\"enabled\\":true},\\"plotOptions\\":{\\"series\\":{\\"dataLabels\\":{\\"enabled\\":false,\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0}}}},\\"legend\\":{\\"enabled\\":false},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"tooltip\\":{\\"style\\":{}}}}","parameters":{"type":"line","title":"Total Downloads","subtitle":"over time (year of publication)","xAxisTitle":"year","yAxisTitle":"downloads","data_title_0":"downloads","index_name":"Aurora Universities Network","start_year":"2002","end_year":"2023"},"filters":{}}],"_id":"65ef26e96c2043760abba98a"}],"_id":"65ef26647a76717ea88e49b8"},{"title":null,"defaultId":null,"stakeholderAlias":"connect-template","type":"chart","creationDate":1710241367664,"updateDate":1710241367664,"indicators":[{"name":"","description":"","additionalDescription":"","type":"chart","width":"large","height":"large","tags":null,"visibility":"PUBLIC","creationDate":null,"updateDate":1711613512246,"defaultId":null,"indicatorPaths":[{"type":"column","format":"NUMBER","source":"stats-tool","url":"chart?json=","jsonPath":[],"chartObject":"{\\"library\\":\\"HighCharts\\",\\"chartDescription\\":{\\"queries\\":[{\\"name\\":\\"((__data_title_0__))\\",\\"type\\":\\"((__type__))\\",\\"color\\":\\"#0500a5c7\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"publication.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Open Access\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_1__))\\",\\"type\\":\\"column\\",\\"color\\":\\"#9b81efff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"publication.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Embargo\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_2__))\\",\\"type\\":\\"column\\",\\"color\\":\\"#ff7171ff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"publication.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Restricted\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_3__))\\",\\"type\\":\\"column\\",\\"color\\":\\"#bd0202ff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"publication.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"Closed Access\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}},{\\"name\\":\\"((__data_title_4__))\\",\\"type\\":\\"column\\",\\"color\\":\\"#b0b0b0ff\\",\\"query\\":{\\"parameters\\":[],\\"select\\":[{\\"field\\":\\"publication\\",\\"aggregate\\":\\"count\\"},{\\"field\\":\\"publication.year\\",\\"aggregate\\":null}],\\"filters\\":[{\\"groupFilters\\":[{\\"field\\":\\"publication.concept.category.context.name\\",\\"type\\":\\"=\\",\\"values\\":[\\"((__index_name__))\\"]},{\\"field\\":\\"publication.access mode\\",\\"type\\":\\"=\\",\\"values\\":[\\"not available\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\">=\\",\\"values\\":[\\"((__start_year__))\\"]},{\\"field\\":\\"publication.year\\",\\"type\\":\\"<=\\",\\"values\\":[\\"((__end_year__))\\"]}],\\"op\\":\\"AND\\"}],\\"entity\\":\\"publication\\",\\"profile\\":\\"((__profile__))\\",\\"limit\\":\\"30\\"}}],\\"colors\\":[\\"#0500a5c7\\",\\"#9b81efff\\",\\"#ff7171ff\\",\\"#bd0202ff\\",\\"#b0b0b0ff\\",\\"#2f7ed8\\",\\"#0d233a\\",\\"#8bbc21\\",\\"#910000\\",\\"#1aadce\\",\\"#492970\\",\\"#f28f43\\",\\"#77a1e5\\",\\"#c42525\\",\\"#a6c96a\\"],\\"series\\":[{\\"stacking\\":\\"normal\\"},{\\"stacking\\":\\"normal\\"},{\\"stacking\\":\\"normal\\"},{\\"stacking\\":\\"normal\\"},{\\"stacking\\":\\"normal\\"}],\\"chart\\":{\\"type\\":\\"line\\",\\"polar\\":false,\\"backgroundColor\\":\\"#FFFFFFFF\\",\\"borderColor\\":\\"#335cadff\\",\\"borderRadius\\":0,\\"borderWidth\\":0,\\"plotBorderColor\\":\\"#ccccccff\\",\\"plotBorderWidth\\":0,\\"zoomType\\":\\"xy\\"},\\"title\\":{\\"style\\":{\\"color\\":\\"#333333FF\\",\\"fontSize\\":\\"18px\\"},\\"text\\":\\"((__title__))\\",\\"margin\\":15,\\"align\\":\\"center\\"},\\"subtitle\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"12px\\"},\\"text\\":\\"((__subtitle__))\\",\\"align\\":\\"center\\"},\\"yAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__yAxisTitle__))\\"},\\"zoomEnabled\\":false,\\"reversedStacks\\":false},\\"xAxis\\":{\\"title\\":{\\"style\\":{\\"color\\":\\"#666666FF\\",\\"fontSize\\":\\"11px\\"},\\"text\\":\\"((__xAxisTitle__))\\"},\\"zoomEnabled\\":false},\\"lang\\":{\\"noData\\":\\"No Data available for the Query\\"},\\"exporting\\":{\\"enabled\\":true},\\"plotOptions\\":{\\"series\\":{\\"dataLabels\\":{\\"enabled\\":false,\\"style\\":{\\"textOutline\\":\\"2px contrast\\",\\"stroke-width\\":0}},\\"stacking\\":\\"normal\\"}},\\"legend\\":{\\"layout\\":\\"horizontal\\",\\"align\\":\\"center\\",\\"verticalAlign\\":\\"bottom\\",\\"enabled\\":true},\\"credits\\":{\\"enabled\\":false,\\"href\\":null},\\"tooltip\\":{\\"style\\":{}}}}","parameters":{"type":"column","title":"Publications","subtitle":"by access rights, over time","xAxisTitle":"","yAxisTitle":"","data_title_0":"Open Access","data_title_1":"Embargo","data_title_2":"Restricted","data_title_3":"Closed Access","data_title_4":"not available","index_name":"Aurora Universities Network","start_year":"2007","end_year":"2023"},"filters":{}}],"_id":"65ef27bf6c2043760abba997"}],"_id":"65f036576c2043760abba9a3"},{"title":null,"defaultId":null,"stakeholderAlias":"connect-template","type":"chart","creationDate":1710256788215,"updateDate":1710256788215,"indicators":[],"_id":"65f072947a76717ea88e49f6"}],"numbers":[],"_id":"65ef26217a76717ea88e49b6"}],"_id":"65ef26217a76717ea88e49b7"}],"_id":"65ef25fd6c2043760abba985"}],"_id":"65ef25da6c2043760abba982"}`; + // return JSON.parse(properties.environment == 'production'?prodProfile:betaProfile) + return JSON.parse(prodProfile); + } + public static getDefaultProfile() { + return "monitor_ris_tail"; + } + +} +@Component({ + selector: 'plugin-stats', + templateUrl: 'plugin-stats.component.html' +}) +export class PluginStatsComponent extends PluginBaseComponent{ + constructor(private http: HttpClient ) { + super(); + } + +} diff --git a/dashboard/plugins/components/stats/plugin-stats.form.component.ts b/dashboard/plugins/components/stats/plugin-stats.form.component.ts new file mode 100644 index 00000000..a3770b27 --- /dev/null +++ b/dashboard/plugins/components/stats/plugin-stats.form.component.ts @@ -0,0 +1,81 @@ +import {Component} from '@angular/core'; +import {PluginBaseFormComponent, PluginEditEvent} from "../../utils/base-plugin.form.component"; +import {PluginStats} from "./plugin-stats.component"; + +@Component({ + selector: 'plugin-stats-form', + template: ` +
      + +
      External Link
      +
      + +
      +
      + +
      + + + + + + + + + + + + + + +
      Chart indicators
      + + + +
      + + + {{indicator.indicatorPaths[0].name?indicator.name:(indicator.indicatorPaths[0].parameters['title'] )}} + + {{ indicator.indicatorPaths[0].parameters['subtitle']? ' ' + indicator.indicatorPaths[0].parameters['subtitle']:''}} + +
      +
      +
      +
      + `, + + +}) +export class PluginStatsFormComponent extends PluginBaseFormComponent { + stakeholder = PluginStats.getMockStakeholder(); + constructor() { + super() + } + + indicatorsChanged(id,$event:PluginEditEvent ){ + console.log("before", id,this.pluginObject.disabledIndicators) + let index = this.pluginObject.disabledIndicators.indexOf(id); + if(index !=-1){ + this.pluginObject.disabledIndicators.splice(index,1); + }else{ + this.pluginObject.disabledIndicators.push(id); + } + $event.value =this.pluginObject.disabledIndicators; + console.log("after",this.pluginObject.disabledIndicators) + this.valuesChanged.emit({field:$event.field, value: $event.value, type: 'parent'}) + } + + urlValueChanged($event:PluginEditEvent){ + console.log($event.field,$event.value) + this.pluginObject['url'][$event.field]=$event.value; + $event.field = "url"; + $event.value = this.pluginObject['url']; + this.valuesChanged.emit($event) + } +} diff --git a/dashboard/plugins/components/stats/plugin-stats.module.ts b/dashboard/plugins/components/stats/plugin-stats.module.ts new file mode 100644 index 00000000..97519496 --- /dev/null +++ b/dashboard/plugins/components/stats/plugin-stats.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; +import {InputModule} from "../../../../sharedComponents/input/input.module"; +import {PluginStatsComponent} from "./plugin-stats.component"; +import {MonitorModule} from "./monitor.module"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, PluginFieldEditModule, InputModule, MonitorModule + ], + providers: [ + PluginsService + ], + declarations: [PluginStatsComponent], + exports: [PluginStatsComponent] +}) +export class PluginStatsModule { + +} diff --git a/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.component.html b/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.component.html new file mode 100644 index 00000000..1ad99a59 --- /dev/null +++ b/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.component.html @@ -0,0 +1,47 @@ +
      + No community info available +
      +
      +
      +

      + + {{pluginObject.title}} +

      + +
      +
      + +
      + No datasources available +
      + +
      + +
        +
        +
        diff --git a/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.component.ts b/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.component.ts new file mode 100644 index 00000000..e6d46a87 --- /dev/null +++ b/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.component.ts @@ -0,0 +1,59 @@ +import {Component} from '@angular/core'; +import {PluginBaseComponent, PluginBaseInfo} from "../../utils/base-plugin.component"; +import {SearchCommunityDataprovidersService} from "../../../../connect/contentProviders/searchDataproviders.service"; +import {ConfigurationService} from "../../../../utils/configuration/configuration.service"; +import {CommunityService} from "../../../../connect/community/community.service"; +export class PluginSuggestedRepositories extends PluginBaseInfo{ + title:string ="Suggested repositories & journals"; + description:string = ""; + compare(oldObject): any { + return super.compare(oldObject); + } +} +@Component({ + selector: 'plugin-suggested-repositories', + templateUrl: 'plugin-suggested-repositories.component.html' +}) +export class PluginSuggestedRepositoriesComponent extends PluginBaseComponent{ + portal; + community; + contentProviders; + slides = 0; + constructor(private searchCommunityDataprovidersService: SearchCommunityDataprovidersService, + private config: ConfigurationService, + private communityService: CommunityService) { + super() + this.subscriptions.push(this.config.portalAsObservable.subscribe( + res => { + this.portal = res; + }, + error => { + console.log(error); + } + )); + this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe( + community => { + this.community = community; + if (community) { + this.subscriptions.push(this.searchCommunityDataprovidersService.searchDataproviders(this.properties, this.community.communityId, true).subscribe( + res => { + this.slides =1; + this.contentProviders = res; + if(this.contentProviders.length > 2){ + this.slides = parseInt('' + (this.contentProviders.length/2)); + } + if(this.slides< (this.contentProviders.length / 2)){ + this.slides++; + } + }, + error => { + console.log(error); + } + )); + + } + } + )); + + } +} diff --git a/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.form.component.ts b/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.form.component.ts new file mode 100644 index 00000000..45e2f597 --- /dev/null +++ b/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.form.component.ts @@ -0,0 +1,26 @@ +import {Component} from '@angular/core'; +import {PluginBaseFormComponent} from "../../utils/base-plugin.form.component"; +import {PluginSuggestedRepositories} from "./plugin-suggested-repositories.component"; + +@Component({ + selector: 'plugin-suggested-repositories-form', + template: ` +
        + + +
        Manage the content providers list in + Community info by adding them in deposit.
        +
        + `, + + +}) +export class PluginSuggestedRepositoriesFormComponent extends PluginBaseFormComponent { + constructor() { + super() + + } + +} diff --git a/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.module.ts b/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.module.ts new file mode 100644 index 00000000..ab061bd3 --- /dev/null +++ b/dashboard/plugins/components/suggested-repositories/plugin-suggested-repositories.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginsService} from "../../../../services/plugins.service"; +import {IconsModule} from "../../../../utils/icons/icons.module"; +import {NumberRoundModule} from "../../../../utils/pipes/number-round.module"; +import {IconsService} from "../../../../utils/icons/icons.service"; +import {SearchResearchResultsServiceModule} from "../../../../services/searchResearchResultsService.module"; +import {PluginFieldEditModule} from "../../utils/plugin-field-edit.module"; +import {PluginSuggestedRepositoriesComponent} from './plugin-suggested-repositories.component'; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, IconsModule, NumberRoundModule, SearchResearchResultsServiceModule, PluginFieldEditModule + ], + providers:[PluginsService], + declarations: [PluginSuggestedRepositoriesComponent], + exports: [PluginSuggestedRepositoriesComponent] +}) +export class PluginSuggestedRepositoriesModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([]) + } +} diff --git a/dashboard/plugins/plugins-form/pluginsForm-routing.module.ts b/dashboard/plugins/plugins-form/pluginsForm-routing.module.ts new file mode 100644 index 00000000..72e376f4 --- /dev/null +++ b/dashboard/plugins/plugins-form/pluginsForm-routing.module.ts @@ -0,0 +1,13 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {PluginsFormComponent} from "./pluginsForm.component"; + + +@NgModule({ + imports: [ + RouterModule.forChild([ + { path: '', component: PluginsFormComponent} + ]) + ] +}) +export class PluginsFormRoutingModule { } diff --git a/dashboard/plugins/plugins-form/pluginsForm.component.html b/dashboard/plugins/plugins-form/pluginsForm.component.html new file mode 100644 index 00000000..676af549 --- /dev/null +++ b/dashboard/plugins/plugins-form/pluginsForm.component.html @@ -0,0 +1,105 @@ +
        + + +
        +
        +
        + +
        + +
        + +
        +
        +
        +
        + diff --git a/dashboard/plugins/plugins-form/pluginsForm.component.ts b/dashboard/plugins/plugins-form/pluginsForm.component.ts new file mode 100644 index 00000000..c0ec0d16 --- /dev/null +++ b/dashboard/plugins/plugins-form/pluginsForm.component.ts @@ -0,0 +1,251 @@ +import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {ActivatedRoute, Router} from "@angular/router"; +import {HelpContentService} from "../../../services/help-content.service"; +import {FormArray, UntypedFormBuilder, UntypedFormGroup, ValidatorFn, Validators} from "@angular/forms"; +import {Page} from "../../../utils/entities/adminTool/page"; +import {EnvProperties} from '../../../utils/properties/env-properties'; +import {HelperFunctions} from "../../../utils/HelperFunctions.class"; +import {Subscriber} from "rxjs"; +import {properties} from "../../../../../environments/environment"; +import {Title} from "@angular/platform-browser"; +import {ClearCacheService} from "../../../services/clear-cache.service"; +import {NotificationHandler} from "../../../utils/notification-handler"; +import {PluginsService} from "../../../services/plugins.service"; +import {Plugin} from "../../../utils/entities/adminTool/plugin"; +import {StringUtils} from "../../../utils/string-utils.class"; +import {Portal} from "../../../utils/entities/adminTool/portal"; +import {PluginTemplate} from "../../../utils/entities/adminTool/pluginTemplate"; +import {PluginUtils} from "../utils/pluginUtils"; +import {CommunityService} from "../../../connect/community/community.service"; +import {CommunityInfo} from "../../../connect/community/communityInfo"; +import {PluginEditEvent} from "../utils/base-plugin.form.component"; +import {AlertModal} from "../../../utils/modal/alert"; + +@Component({ + selector: 'plugins-form', + templateUrl: './pluginsForm.component.html', +}) +export class PluginsFormComponent implements OnInit { + public selectedTemplate: PluginTemplate = null; + public selectedPlugin: Plugin = null; + public templateForm: UntypedFormGroup; + urlValidator: ValidatorFn = StringUtils.urlValidator; + public properties: EnvProperties = properties; + public showLoading: boolean = true; + private subscriptions: any[] = []; + public pluginUtils = new PluginUtils(); + selectedCommunityPid = null; + public portal: string; + public selectedPageId: string; + public selectedTemplateId: string; + public selectedPluginId: string; + public community: Portal; + public page: Page; + public template; + public selectedPlacementView = "all"; + communityInfo:CommunityInfo = null; + editSubmenuOpen = false; + @ViewChild('backAlert') backAlert: AlertModal; + + constructor(private element: ElementRef, private route: ActivatedRoute, private _router: Router, + private communityService: CommunityService, + private title: Title, private _helpContentService: HelpContentService, + private _pluginsService: PluginsService, private _fb: UntypedFormBuilder, + private _clearCacheService: ClearCacheService) { + } + + ngOnInit() { + this.title.setTitle('Administrator Dashboard | Plugins'); + this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe( + community => { + this.communityInfo = community; + })); + this.subscriptions.push(this.route.params.subscribe(params => { + + this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param]; + this.selectedCommunityPid = params.community; + + this.subscriptions.push(this.route.queryParams.subscribe(params => { + HelperFunctions.scroll(); + this.selectedPageId = params['pageId']; + this.selectedPluginId = params['pluginId']; + this.selectedTemplateId = params['templateId']; + + if (this.portal && this.selectedPageId) { + this.getPage(this.selectedPageId); + } + if (!this.selectedPageId) { + this._router.navigate(['../'], {relativeTo: this.route}); + } + })); + })); + + } + + ngOnDestroy(): void { + this.subscriptions.forEach(value => { + if (value instanceof Subscriber) { + value.unsubscribe(); + } else if (value instanceof Function) { + value(); + } + }); + } + + getPage(pageId: string) { + this.showLoading = true; + this.subscriptions.push(this._helpContentService.getPageByPortal(pageId, this.properties.adminToolsAPIURL, this.portal).subscribe( + page => { + if (this.properties.adminToolsPortalType != page.portalType) { + this._router.navigate(['..'],{ relativeTo: this.route}); + } else { + this.page = page; + this.getPluginAndTemplate(); + } + }, + error => this.handleError('System error retrieving page', error))); + } + + getPluginAndTemplate(){ + if(this.selectedTemplateId){ + this.subscriptions.push(this._pluginsService.getPluginTemplateById(this.properties.adminToolsAPIURL, this.selectedTemplateId).subscribe(template => { + this.selectedTemplate = template; + if(this.selectedPluginId){ + this.subscriptions.push(this._pluginsService.getPluginById(this.properties.adminToolsAPIURL, this.selectedPluginId).subscribe(plugin => { + this.selectedPlugin = plugin; + this.edit(this.selectedPlugin, this.selectedTemplate); + })); + }else{ + this.selectedPlugin = new Plugin(this.page._id,this.selectedCommunityPid, template); + // this.selectedPlugin.order = this.pluginsByPlacement.get(this.selectedPlacementView).length; + this.selectedPlugin.object = PluginUtils.initializeObjectAndCompare(template.code,null); + this.edit(this.selectedPlugin, this.selectedTemplate); + + } + }, error =>{ + this._router.navigate(['../'], {queryParams: {pageId:this.selectedPageId}, relativeTo: this.route}); + })); + + }else{ + this._router.navigate(['../'], {queryParams: {pageId:this.selectedPageId}, relativeTo: this.route}); + } + } + public edit(plugin:Plugin, template:PluginTemplate) { + this.templateForm = this._fb.group({ + _id: this._fb.control(plugin._id), + pid: this._fb.control(plugin.pid), + page: this._fb.control(plugin.page), + templateCode: this._fb.control(plugin.templateCode, Validators.required), + templateId: this._fb.control(plugin.templateId, Validators.required), + placement: this._fb.control(plugin.placement), + order: this._fb.control(plugin.order), + active: this._fb.control(plugin.active), + values: this._fb.array([]), + }); + + if (template.settings) { + for (let attrKey of Object.keys(template.settings)) { + (this.templateForm.get("values") as FormArray).push(this._fb.group({ + 'key': this._fb.control(attrKey), + 'value': this._fb.control(plugin.settingsValues[attrKey]?plugin.settingsValues[attrKey]:template.settings[attrKey].value) + } + )); + } + } + this.showLoading = false; + } + + public saveConfirmed() { + this.showLoading = true; + let plugin: Plugin = this.templateForm.getRawValue(); + plugin.object = this.selectedPlugin.object; + plugin.settingsValues = new Map(); + for (let fields of this.templateForm.getRawValue().values) { + plugin.settingsValues[fields.key] = fields.value; + } + let update = (plugin._id) ? true : false; + this.savePlugin(plugin,update) + } + public savePlugin(plugin, update){ + this.subscriptions.push(this._pluginsService.savePlugin(plugin, this.properties.adminToolsAPIURL,this.selectedCommunityPid ).subscribe( + saved => { + this._clearCacheService.purgeBrowserCache(null, this.selectedCommunityPid) + this.edit(saved, this.selectedTemplate) + + }, + error => this.handleUpdateError("System error creating template", error) + )); + } + + + + + handleUpdateError(message: string, error = null) { + if (error) { + console.log('Server responded: ' + error); + } + NotificationHandler.rise(message, 'danger'); + this.showLoading = false; + } + + handleError(message: string, error = null) { + if (error) { + console.log('Server responded: ' + error); + } + NotificationHandler.rise(message, 'danger'); + this.showLoading = false; + } + + get attrFormArray() { + + return this.templateForm.get("values") as FormArray; + + } + + attributeTypeChanged(form) { + let type = form.get("value").get("type"); + form.get("value").setValue(""); + if (type == "boolean") { + form.get("value").setValue(false); + } + } + + + getKeys(obj) { + return obj?Object.keys(obj):[]; + } + + reset() { + this.edit(this.selectedPlugin, this.selectedTemplate) + } + + pluginFieldChanged($event:PluginEditEvent){ + if($event.type == "open-submenu"){ + this.editSubmenuOpen = true; + return; + } + if($event.type == "close-submenu"){ + + this.editSubmenuOpen = false; + return; + } + this.selectedPlugin.object[$event.field]=$event.value; + this.templateForm.markAsDirty(); + } + + promtToGoBack() { + if(this.templateForm.dirty) { + this.backAlert.alertTitle = 'Leave page'; + this.backAlert.message = 'Are you sure you want to leave the page?'; + this.backAlert.okButtonText = 'Yes'; + this.backAlert.open(); + }else{ + this.confirmGoBack(); + } + + } + + confirmGoBack() { + this._router.navigate(["../"],{queryParams:{pageId:this.selectedPageId},relativeTo:this.route}) + } +} diff --git a/dashboard/plugins/plugins-form/pluginsForm.module.ts b/dashboard/plugins/plugins-form/pluginsForm.module.ts new file mode 100644 index 00000000..99b45ec8 --- /dev/null +++ b/dashboard/plugins/plugins-form/pluginsForm.module.ts @@ -0,0 +1,42 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {AdminToolServiceModule} from "../../../services/adminToolService.module"; +import {InputModule} from "../../../sharedComponents/input/input.module"; + + +import {MatAutocompleteModule} from '@angular/material/autocomplete'; +import {MatCheckboxModule} from "@angular/material/checkbox"; +import {MatFormFieldModule} from "@angular/material/form-field"; + + +import {MatChipsModule} from '@angular/material/chips'; +import {AdminTabsModule} from "../../sharedComponents/admin-tabs/admin-tabs.module"; +import {PageContentModule} from "../../sharedComponents/page-content/page-content.module"; +import {SearchInputModule} from "../../../sharedComponents/search-input/search-input.module"; +import {IconsModule} from "../../../utils/icons/icons.module"; +import {LoadingModule} from "../../../utils/loading/loading.module"; +import {PluginsService} from "../../../services/plugins.service"; +import {CKEditorModule} from "ng2-ckeditor"; +import {MatSlideToggleModule} from "@angular/material/slide-toggle"; +import {PluginWrapperModule} from "../wrapper/plugin-wrapper.module"; +import {SideBarModule} from "../../sharedComponents/sidebar/sideBar.module"; +import {PluginEditWrapperModule} from "../wrapper/plugin-edit-wrapper.module"; +import {PluginsFormComponent} from "./pluginsForm.component"; +import {PluginsFormRoutingModule} from "./pluginsForm-routing.module"; +import {AlertModalModule} from "../../../utils/modal/alertModal.module"; + + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, + ReactiveFormsModule, AdminToolServiceModule, InputModule, MatAutocompleteModule, MatFormFieldModule, MatChipsModule, + MatCheckboxModule, AdminTabsModule, PageContentModule, PluginsFormRoutingModule, SearchInputModule, IconsModule, LoadingModule, CKEditorModule, + MatSlideToggleModule, PluginWrapperModule, SideBarModule, PluginEditWrapperModule, AlertModalModule + ], + providers:[PluginsService], + declarations: [PluginsFormComponent], + exports: [PluginsFormComponent] +}) +export class PluginsFormModule {} diff --git a/dashboard/plugins/plugins-routing.module.ts b/dashboard/plugins/plugins-routing.module.ts new file mode 100644 index 00000000..2bb00912 --- /dev/null +++ b/dashboard/plugins/plugins-routing.module.ts @@ -0,0 +1,14 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {PluginsComponent} from "./plugins.component"; + + +@NgModule({ + imports: [ + RouterModule.forChild([ + { path: '', component: PluginsComponent}, + { path: ':templateCode', component: PluginsComponent, data: {templateView:true}} + ]) + ] +}) +export class PluginsRoutingModule { } diff --git a/dashboard/plugins/plugins.component.html b/dashboard/plugins/plugins.component.html new file mode 100644 index 00000000..ee0a4b50 --- /dev/null +++ b/dashboard/plugins/plugins.component.html @@ -0,0 +1,203 @@ + +
        + +
        +
        + +
        + +
        + +
        + Show active +
        + +
        +
        +
        No plugins found
        +
        + + + +
        {{placement.value}}
        +
        + + +
        +
        +
        + +
        {{pluginGroup.template.name}}
        +
        {{pluginGroup.plugin.object && pluginGroup.plugin.object.title?pluginGroup.plugin.object.title:pluginGroup.template.name}}
        + +
        + {{pluginGroup.template.description}} +
        + +
        +
        + Placement: {{pluginGroup.plugin.placement}} +
        + + + + +
        +
        + +
        +
        +
        +
        +
        + +
        +
        +
        +
        + + diff --git a/dashboard/plugins/plugins.component.ts b/dashboard/plugins/plugins.component.ts new file mode 100644 index 00000000..3010aa8c --- /dev/null +++ b/dashboard/plugins/plugins.component.ts @@ -0,0 +1,373 @@ +import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {ActivatedRoute, Router} from "@angular/router"; +import {HelpContentService} from "../../services/help-content.service"; +import {FormArray, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, ValidatorFn} from "@angular/forms"; +import {Page} from "../../utils/entities/adminTool/page"; +import {EnvProperties} from '../../utils/properties/env-properties'; +import {HelperFunctions} from "../../utils/HelperFunctions.class"; +import {Subscriber} from "rxjs"; +import {properties} from "../../../../environments/environment"; +import {PortalUtils} from "../portal/portalHelper"; +import {Option} from "../../sharedComponents/input/input.component"; +import {Title} from "@angular/platform-browser"; +import {ClearCacheService} from "../../services/clear-cache.service"; +import {NotificationHandler} from "../../utils/notification-handler"; +import {PluginsService} from "../../services/plugins.service"; +import {Plugin} from "../../utils/entities/adminTool/plugin"; +import {StringUtils} from "../../utils/string-utils.class"; +import {Portal} from "../../utils/entities/adminTool/portal"; +import {PluginTemplate} from "../../utils/entities/adminTool/pluginTemplate"; +import {PluginUtils} from "./utils/pluginUtils"; +import {CommunityService} from "../../connect/community/community.service"; +import {CommunityInfo} from "../../connect/community/communityInfo"; +import {AlertModal} from "../../utils/modal/alert"; + +@Component({ + selector: 'plugins', + templateUrl: './plugins.component.html', +}) +export class PluginsComponent implements OnInit { + public pluginsByPlacement: Map = new Map(); + public plugins: Plugin[] = []; + public pluginTemplates: PluginTemplate[] = []; + public selectedTemplate: PluginTemplate = null; + public selectedPlugin: Plugin = null; + // public editView = false; + // public selectTemplateView = false; + // public templateForm: UntypedFormGroup; + // public pagesCtrl: UntypedFormArray; + urlValidator: ValidatorFn = StringUtils.urlValidator; + private searchText: RegExp = new RegExp(''); + public keyword: string = ""; + public properties: EnvProperties = properties; + // public formPages: Page[] = []; + public showLoading: boolean = true; + private subscriptions: any[] = []; + public allPages: Option[] = []; + public pluginUtils = new PluginUtils(); + selectedCommunityPid = null; + public portalUtils: PortalUtils = new PortalUtils(); + private index: number; + public portal: string; + public selectedPageId: string; + public community: Portal; + public page: Page; + public templateView = false; + // public templateCode: string = null; + // public template; + public selectedPlacementView = "all"; + public selectedPluginIndex = null; + public sinlgePlacementAvailable = false; + communityInfo: CommunityInfo = null; + // editSubmenuOpen = false; + filterActive = false; + @ViewChild('deleteModal') deleteModal: AlertModal; + + constructor(private element: ElementRef, private route: ActivatedRoute, private _router: Router, + private communityService: CommunityService, + private title: Title, private _helpContentService: HelpContentService, + private _pluginsService: PluginsService, private _fb: UntypedFormBuilder, + private _clearCacheService: ClearCacheService) { + } + + ngOnInit() { + this.title.setTitle('Administrator Dashboard | Plugins'); + this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe( + community => { + this.communityInfo = community; + })); + this.subscriptions.push(this.route.params.subscribe(params => { + + this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param]; + this.selectedCommunityPid = params.community; + + this.subscriptions.push(this.route.queryParams.subscribe(params => { + HelperFunctions.scroll(); + this.selectedPageId = params['pageId']; + if (this.portal && this.selectedPageId) { + this.getPage(this.selectedPageId); + } + if (!this.selectedPageId && !this.templateView) { + this._router.navigate(['../pages'], {relativeTo: this.route}); + } + })); + })); + + } + + ngOnDestroy(): void { + this.subscriptions.forEach(value => { + if (value instanceof Subscriber) { + value.unsubscribe(); + } else if (value instanceof Function) { + value(); + } + }); + } + + getTemplateById(id) { + for (let template of this.pluginTemplates) { + if (template._id == id) { + return template; + } + } + return null; + } + + getPage(pageId: string) { + this.showLoading = true; + this.subscriptions.push(this._helpContentService.getPageByPortal(pageId, this.properties.adminToolsAPIURL, this.portal).subscribe( + page => { + if (this.properties.adminToolsPortalType != page.portalType) { + this._router.navigate(['./pageContents']); + } else { + this.page = page; + this.getPagePlugins(); + } + }, + error => this.handleError('System error retrieving page', error))); + } + + getPagePlugins() { + this.showLoading = true; + this.subscriptions.push(this._pluginsService.getPluginTemplatesByPage(this.properties.adminToolsAPIURL, this.selectedCommunityPid, this.selectedPageId).subscribe( + templates => { + this.pluginTemplates = templates; + + this.subscriptions.push(this._pluginsService.getPluginsByPage(this.properties.adminToolsAPIURL, this.selectedCommunityPid, this.selectedPageId).subscribe( + plugins => { + this.plugins = plugins; + this.pluginsByPlacement = new Map(); + for (let pos of this.pluginUtils.placementsOptions) { + this.pluginsByPlacement.set(pos.value, []); + } + let self = this; + this.pluginTemplates.forEach(_ => { + let plugin: Plugin = null; + if(!_.custom) { + + + for (let pl of plugins) { + if (pl.templateId == _._id) { + plugin = pl; + } + } + if (!plugin) { + plugin = new Plugin(this.selectedPageId, this.selectedCommunityPid, _); + this.plugins.push(plugin); + } + + if (plugin) { + plugin.object = PluginUtils.initializeObjectAndCompare(_.code, plugin.object) + this.pluginsByPlacement.get(plugin.placement).push({plugin: plugin, template: _, openPreview: false}); + } + } + }); + //add custom plugins in the list + this.plugins.forEach(_ => { + + if(_.custom){ + let customTemplate = null; + this.pluginTemplates.forEach(template => { + if (_.templateId == template._id) { + customTemplate = template; + } + }); + if(customTemplate && customTemplate.custom){ + this.pluginsByPlacement.get(customTemplate.placement).push({plugin: _, template: customTemplate, openPreview: false}); + } + } + }); + let availablePlacements = []; + for (let placement of this.pluginUtils.placementsOptions) { + if (this.pluginsByPlacement.get(placement.value).length > 0) { + availablePlacements.push(placement.value); + } + this.pluginsByPlacement.get(placement.value).sort(function (a, b) { + return a.plugin.order - b.plugin.order; + }) + } + if (availablePlacements.length == 1) { + this.selectedPlacementView = availablePlacements[0]; + this.sinlgePlacementAvailable = true + } + this.showLoading = false; + }, + error => this.handleError('System error retrieving plugins', error))); + + }, + error => this.handleError('System error retrieving templates', error))); + } + + public savePlugin(plugin, update, index) { + this.subscriptions.push(this._pluginsService.savePlugin(plugin, this.properties.adminToolsAPIURL, this.selectedCommunityPid).subscribe( + saved => { + this.savedSuccessfully(saved, update, index); + this.selectedTemplate = null; + this.selectedPlugin = null; + this.clearCache(); + if (plugin.custom) { + this._router.navigate(["./edit"], { + queryParams: { + 'pageId': this.selectedPageId, + pluginId: saved._id, + templateId: saved.templateId + }, relativeTo: this.route + }) + } + }, + error => this.handleUpdateError("System error creating template", error) + )); + } + + public savedSuccessfully(plugin: Plugin, update: boolean, index) { + console.log(plugin.placement, index, update) + if (update) { + this.pluginsByPlacement.get(plugin.placement)[index].plugin = plugin; + } else { + this.plugins.push(plugin); + } + this.showLoading = false; + } + + public filterPlugins(plugin: Plugin, template: PluginTemplate): boolean { + let values = []; + for (let key of this.getKeys(plugin.settingsValues)) { + values.push(plugin.settingsValues[key]); + } + return this.searchText.toString() == '' || (plugin.templateCode + ' ' + values.join(' ') + (template ? (template.name + ' ' + template.description) : '')).match(this.searchText) != null; + } + + + handleUpdateError(message: string, error = null) { + if (error) { + console.log('Server responded: ' + error); + } + NotificationHandler.rise(message, 'danger'); + this.showLoading = false; + } + + handleError(message: string, error = null) { + if (error) { + console.log('Server responded: ' + error); + } + NotificationHandler.rise(message, 'danger'); + this.showLoading = false; + } + + getPages() { + this.showLoading = true; + this.subscriptions.push(this._helpContentService.getAllPages(this.properties.adminToolsAPIURL).subscribe( + pages => { + this.allPages = []; + pages.forEach(page => { + this.allPages.push({ + label: page.name + " [" + page.portalType + "]", + value: page + }); + }); + this.showLoading = false; + }, + error => this.handleError('System error retrieving pages', error) + )); + } + + attributeTypeChanged(form) { + let type = form.get("value").get("type"); + form.get("value").setValue(""); + if (type == "boolean") { + form.get("value").setValue(false); + } + } + + + getKeys(obj) { + return obj ? Object.keys(obj) : []; + } + + + public togglePlugin(status: boolean, id: string, i, placement) { + this.index = i; + this.selectedTemplate = this.pluginsByPlacement.get(placement)[i].template; + if (id) { + this.subscriptions.push(this._pluginsService.togglePlugin(id, status, this.properties.adminToolsAPIURL, this.selectedCommunityPid).subscribe( + () => { + + this.pluginsByPlacement.get(placement)[i].plugin.active = status; + this.clearCache(); + }, + error => this.handleUpdateError('System error changing the status of Plugin', error) + )); + } else { + let plugin = this.pluginsByPlacement.get(placement)[i].plugin; + plugin.active = status; + this.savePlugin(plugin, true, i); + } + } + + public swap(pluginToMoveUp, pluginToMoveDown, placement) { + this.showLoading = true; + let moveUpGroup = this.pluginsByPlacement.get(placement)[pluginToMoveUp]; + let moveDownGroup = this.pluginsByPlacement.get(placement)[pluginToMoveDown]; + this.pluginsByPlacement.get(placement)[pluginToMoveUp] = moveDownGroup; + this.pluginsByPlacement.get(placement)[pluginToMoveDown] = moveUpGroup; + this.move(moveUpGroup.plugin, true, pluginToMoveDown, placement); + this.move(moveDownGroup.plugin, false, pluginToMoveUp, placement); + this.showLoading = false; + } + + public move(plugin: Plugin, up: boolean, index, placement) { + if (plugin._id) { + this.subscriptions.push(this._pluginsService.updatePluginOrder(plugin, this.properties.adminToolsAPIURL, up ? -1 : 1, this.selectedCommunityPid).subscribe( + saved => { + this.pluginsByPlacement.get(placement)[index].plugin = saved; + this.clearCache(); + }, + error => this.handleUpdateError("System error saving plugin", error) + )); + } else { + + plugin.order = plugin.order + (up ? -1 : 1) + this.savePlugin(plugin, true, index); + } + + + } + + clearCache() { + // this._clearCacheService.clearCacheInRoute(null, this.selectedCommunityPid, this.getPageById(this.selectedPageId).route) + this._clearCacheService.purgeBrowserCache(null, this.selectedCommunityPid) + } + + addNewCustomPlugin(template: PluginTemplate) { + let plugin = new Plugin(this.page._id, this.selectedCommunityPid, template); + plugin.order = this.pluginsByPlacement.get(this.selectedPlacementView).length; + plugin.object = PluginUtils.initializeObjectAndCompare(template.code, null); + plugin.custom = true; + this.savePlugin(plugin, false, this.pluginsByPlacement.get(this.selectedPlacementView).length); + } + + promtToDelete(i, placement) { + this.selectedPlugin = this.pluginsByPlacement.get(placement)[i].plugin; + this.selectedPlacementView = placement; + this.selectedPluginIndex = i; + this.deleteModal.alertTitle = 'Delete Confirmation'; + this.deleteModal.message = 'Are you sure you want to delete the selected plugin?'; + this.deleteModal.okButtonText = 'Yes'; + this.deleteModal.open(); + + } + + confirmDelete() { + this.showLoading = true; + + this.subscriptions.push(this._pluginsService.deletePlugin(this.selectedPlugin._id, this.properties.adminToolsAPIURL).subscribe( + deleted => { + this.pluginsByPlacement.get(this.selectedPlacementView).splice(this.selectedPluginIndex, 1); + this.clearCache(); + }, + error => this.handleUpdateError("System error creating template", error) + )); + this.showLoading = false; + } +} diff --git a/dashboard/plugins/plugins.module.ts b/dashboard/plugins/plugins.module.ts new file mode 100644 index 00000000..063aaa85 --- /dev/null +++ b/dashboard/plugins/plugins.module.ts @@ -0,0 +1,43 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {AlertModalModule} from '../../utils/modal/alertModal.module'; +import {PluginsComponent} from './plugins.component'; +import {AdminToolServiceModule} from "../../services/adminToolService.module"; +import {InputModule} from "../../sharedComponents/input/input.module"; + + +import {MatAutocompleteModule} from '@angular/material/autocomplete'; +import { MatCheckboxModule } from "@angular/material/checkbox"; +import { MatFormFieldModule } from "@angular/material/form-field"; + + +import {MatChipsModule} from '@angular/material/chips'; +import {AdminTabsModule} from "../sharedComponents/admin-tabs/admin-tabs.module"; +import {PageContentModule} from "../sharedComponents/page-content/page-content.module"; +import {PluginsRoutingModule} from "./plugins-routing.module"; +import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module"; +import {IconsModule} from "../../utils/icons/icons.module"; +import {LoadingModule} from "../../utils/loading/loading.module"; +import {PluginsService} from "../../services/plugins.service"; +import {CKEditorModule} from "ng2-ckeditor"; +import {MatSlideToggleModule} from "@angular/material/slide-toggle"; +import {PluginWrapperModule} from "./wrapper/plugin-wrapper.module"; +import {SideBarModule} from "../sharedComponents/sidebar/sideBar.module"; +import {PluginEditWrapperModule} from "./wrapper/plugin-edit-wrapper.module"; +import {TransitionGroupModule} from "../../utils/transition-group/transition-group.module"; + + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, + AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule, MatAutocompleteModule, MatFormFieldModule, MatChipsModule, + MatCheckboxModule, AdminTabsModule, PageContentModule, PluginsRoutingModule, SearchInputModule, IconsModule, LoadingModule, CKEditorModule, + MatSlideToggleModule, PluginWrapperModule, SideBarModule, PluginEditWrapperModule, TransitionGroupModule + ], + providers:[PluginsService], + declarations: [PluginsComponent], + exports: [PluginsComponent] +}) +export class PluginsModule {} diff --git a/dashboard/plugins/pluginsComponent.module.ts b/dashboard/plugins/pluginsComponent.module.ts new file mode 100644 index 00000000..ad4d536c --- /dev/null +++ b/dashboard/plugins/pluginsComponent.module.ts @@ -0,0 +1,40 @@ +/* +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {AlertModalModule} from '../../utils/modal/alertModal.module'; +import {PluginsComponent} from './plugins.component'; +import {AdminToolServiceModule} from "../../services/adminToolService.module"; +import {InputModule} from "../../sharedComponents/input/input.module"; + + +import {MatAutocompleteModule} from '@angular/material/autocomplete'; +import { MatCheckboxModule } from "@angular/material/checkbox"; +import { MatFormFieldModule } from "@angular/material/form-field"; + + +import {MatChipsModule} from '@angular/material/chips'; +import {AdminTabsModule} from "../sharedComponents/admin-tabs/admin-tabs.module"; +import {PageContentModule} from "../sharedComponents/page-content/page-content.module"; +import {PluginsRoutingModule} from "./plugins-routing.module"; +import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module"; +import {IconsModule} from "../../utils/icons/icons.module"; +import {LoadingModule} from "../../utils/loading/loading.module"; +import {PluginsService} from "../../services/plugins.service"; +import {CKEditorModule} from "ng2-ckeditor"; +import {MatSlideToggleModule} from "@angular/material/slide-toggle"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, + AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule, MatAutocompleteModule, MatFormFieldModule, MatChipsModule, + MatCheckboxModule, AdminTabsModule, PageContentModule, SearchInputModule, IconsModule, LoadingModule, CKEditorModule, + MatSlideToggleModule + ], + providers:[PluginsService], + declarations: [PluginsComponent], + exports: [PluginsComponent] +}) +export class PluginsComponentModule {} +*/ diff --git a/dashboard/plugins/templates/pluginTemplates-routing.module.ts b/dashboard/plugins/templates/pluginTemplates-routing.module.ts new file mode 100644 index 00000000..6adc4e63 --- /dev/null +++ b/dashboard/plugins/templates/pluginTemplates-routing.module.ts @@ -0,0 +1,13 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {PluginTemplatesComponent} from "./pluginTemplates.component"; + + +@NgModule({ + imports: [ + RouterModule.forChild([ + { path: '', component: PluginTemplatesComponent} + ]) + ] +}) +export class PluginTemplatesRoutingModule { } diff --git a/dashboard/plugins/templates/pluginTemplates.component.html b/dashboard/plugins/templates/pluginTemplates.component.html new file mode 100644 index 00000000..8e9412c1 --- /dev/null +++ b/dashboard/plugins/templates/pluginTemplates.component.html @@ -0,0 +1,242 @@ +
        + +
        +
        +
        + +
        + +
        +
        +
        +
        +
        +
        +
        + +
        + + +
        + + + +
        {{placement.value}}
        +
        +
        +
        +
        +
        {{template.name}}
        +
        + Plan: {{template.plan}} + Communities: {{template.portalSpecific.join(', ')}} + Default status: Active +
        +
        + {{template.description}} +
        +
        + Page: {{getPageAsString(template.page)}} - + Placement: {{template.placement}} - + Order: {{template.order}} +
        +
        + Portal type: {{template.portalType}} +
        + +
        +
        + +
        + + +
        + +
        +
        +
        +
        +
        +
        +
        + +
        +
        +
        +
        Plugin + options +
        + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        Default Status + +
        + + +
        + + +
        +
        +
        Setting #{{i + 1}}
        +
        + Remove +
        + +
        +
        +
        +
        +
        + +
        +
        +
        +
        + + +
        +
        +
        + +
        +
        +
        Plugin preview
        + + +
        +
        +
        +
        + diff --git a/dashboard/plugins/templates/pluginTemplates.component.ts b/dashboard/plugins/templates/pluginTemplates.component.ts new file mode 100644 index 00000000..31041916 --- /dev/null +++ b/dashboard/plugins/templates/pluginTemplates.component.ts @@ -0,0 +1,382 @@ +import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {ActivatedRoute, Router} from "@angular/router"; +import {HelpContentService} from "../../../services/help-content.service"; +import {FormArray, FormGroup, UntypedFormBuilder, UntypedFormGroup, ValidatorFn, Validators} from "@angular/forms"; +import {Page} from "../../../utils/entities/adminTool/page"; +import {EnvProperties} from '../../../utils/properties/env-properties'; +import {HelperFunctions} from "../../../utils/HelperFunctions.class"; +import {Subscriber} from "rxjs"; +import {properties} from "../../../../../environments/environment"; +import {PortalUtils} from "../../portal/portalHelper"; +import {AlertModal} from "../../../utils/modal/alert"; +import {Option} from "../../../sharedComponents/input/input.component"; +import {Title} from "@angular/platform-browser"; +import {ClearCacheService} from "../../../services/clear-cache.service"; +import {NotificationHandler} from "../../../utils/notification-handler"; +import {PluginsService} from "../../../services/plugins.service"; +import {PluginTemplate} from "../../../utils/entities/adminTool/pluginTemplate"; +import {StringUtils} from "../../../utils/string-utils.class"; +import {PluginUtils} from "../utils/pluginUtils"; +import {PluginEditEvent} from "../utils/base-plugin.form.component"; + +@Component({ + selector: 'plugin-templates', + templateUrl: './pluginTemplates.component.html', +}) +export class PluginTemplatesComponent implements OnInit { + @ViewChild('editModal') editModal: AlertModal; + @ViewChild('deleteModal') deleteModal: AlertModal; + public templatesByPlacement: Map = new Map(); + public templateForm: UntypedFormGroup; + urlValidator: ValidatorFn = StringUtils.urlValidator; + private searchText: RegExp = new RegExp(''); + public keyword: string = ""; + public properties: EnvProperties = properties; + public formPages: Page[] = []; + public showLoading: boolean = true; + public filterForm: UntypedFormGroup; + private subscriptions: any[] = []; + public allPages: Option[] = []; + public allPagesByPortal: Map = new Map(); + public pluginUtils = new PluginUtils(); + public portalUtils: PortalUtils = new PortalUtils(); + private selectedTemplate: PluginTemplate; + public selectedPageId: string; + public selectedPortalPid: string; + public page: Page; + editSubmenuOpen = false; + constructor(private element: ElementRef, private route: ActivatedRoute, private _router: Router, + private title: Title, private _helpContentService: HelpContentService, + private _pluginsService: PluginsService, private _fb: UntypedFormBuilder, + private _clearCacheService: ClearCacheService) { + } + + ngOnInit() { + this.title.setTitle('Administrator Dashboard | Classes'); + this.filterForm = this._fb.group({ + keyword: [''], + position: ['all', Validators.required] + }); + this.subscriptions.push(this.filterForm.get('keyword').valueChanges.subscribe(value => { + this.searchText = new RegExp(value, 'i'); + })); + + this.subscriptions.push(this.route.queryParams.subscribe(params => { + HelperFunctions.scroll(); + this.selectedPageId = params['pageId']; + this.selectedPortalPid = params['portalPid']; + if (this.selectedPageId) { + this.getPage(this.selectedPageId); + this.getTemplates(this.selectedPageId); + + } else { + this.getPages(); + this.getTemplates(); + + } + })); + + } + + ngOnDestroy(): void { + this.subscriptions.forEach(value => { + if (value instanceof Subscriber) { + value.unsubscribe(); + } else if (value instanceof Function) { + value(); + } + }); + } + + getPage(pageId: string) { + this.showLoading = true; + this.subscriptions.push(this._helpContentService.getPageById(pageId, this.properties.adminToolsAPIURL).subscribe( + page => { + this.page = page; + this.allPages = []; + this.allPagesByPortal = new Map(); + let option = { + label: page.name + " [" + page.portalType + "]", + value: page + }; + this.allPages.push(option); + this.allPagesByPortal.set(page.portalType, []) + this.allPagesByPortal.get(page.portalType).push(option) + }, + error => this.handleError('System error retrieving page', error))); + } + + getTemplates(pageId = null) { + this.showLoading = true; + this.subscriptions.push(this._pluginsService.getPluginTemplates(this.properties.adminToolsAPIURL, pageId).subscribe( + templates => { + for(let pos of this.pluginUtils.placementsOptions){ + this.templatesByPlacement.set(pos.value,[]); + } + for(let template of templates){ + template.object = PluginUtils.initializeObjectAndCompare(template.code,template.object) + this.templatesByPlacement.get(template.placement).push(template); + } + let self = this; + this.showLoading = false; + }, + error => this.handleError('System error retrieving classes', error))); + } + + private deleteFromArray(template:PluginTemplate): void { + + let i = this.templatesByPlacement.get(template.placement).findIndex(_ => _._id == template._id); + this.templatesByPlacement.get(template.placement).splice(i, 1); + + } + + public confirmDelete(template:PluginTemplate) { + this.selectedTemplate = template; + this.confirmModalOpen(); + } + + + private confirmModalOpen() { + this.deleteModal.alertTitle = "Delete Confirmation"; + this.deleteModal.message = "Are you sure you want to delete the selected template(s)?"; + this.deleteModal.okButtonText = "Yes"; + this.deleteModal.open(); + } + + public confirmedDelete() { + this.showLoading = true; + this.subscriptions.push(this._pluginsService.deletePluginTemplate(this.selectedTemplate._id, this.properties.adminToolsAPIURL).subscribe( + _ => { + this.deleteFromArray(this.selectedTemplate); + NotificationHandler.rise('Template have been successfully deleted'); + this.showLoading = false; + // this._clearCacheService.clearCache("Template id deleted"); + }, + error => this.handleUpdateError('System error deleting the selected Template', error) + )); + } + + public edit(pluginTemplate) { + this.selectedTemplate = JSON.parse(JSON.stringify(pluginTemplate)); // deep copy object with nested objects + this.templateForm = this._fb.group({ + _id: this._fb.control(pluginTemplate._id), + name: this._fb.control(pluginTemplate.name), + page: this._fb.control(this.getPageById(pluginTemplate.page)), + custom: this._fb.control(pluginTemplate.custom), + portalType: this._fb.control(pluginTemplate.portalType, Validators.required), + + code: this._fb.control(pluginTemplate.code, Validators.required), + description: this._fb.control(pluginTemplate.description), + plan: this._fb.control(pluginTemplate.plan, Validators.required), + placement: this._fb.control(pluginTemplate.placement, Validators.required), + order: this._fb.control(pluginTemplate.order), + portalSpecific: this._fb.control(pluginTemplate.portalSpecific?pluginTemplate.portalSpecific.join(','):''), + defaultIsActive: this._fb.control(pluginTemplate.defaultIsActive), + settings: this._fb.array([]), + }); + this.templateForm.get('portalType').disable(); + if (pluginTemplate.settings) { + for (let attrKey of Object.keys(pluginTemplate.settings)) { + (this.templateForm.get("settings") as FormArray).push(this._fb.group({ + key: this._fb.control(attrKey, Validators.required), + name: this._fb.control(pluginTemplate.settings[attrKey].name, Validators.required), + type: this._fb.control(pluginTemplate.settings[attrKey].type, Validators.required), + value: this._fb.control(pluginTemplate.settings[attrKey].value) + })); + } + } + this.modalOpen("Edit Template", "Save Changes"); + } + + public newPlugin() { + this.selectedTemplate = null; + if (this.templateForm) { + this.templateForm.get('portalType').enable(); + } + this.templateForm = this._fb.group({ + _id: this._fb.control(null), + name: this._fb.control(''), + code: this._fb.control('', Validators.required), + plan: this._fb.control('Standard', Validators.required), + description: this._fb.control(''), + page: this._fb.control(this.page?this.getPageById(this.page):'', Validators.required), + portalType: this._fb.control('community', Validators.required), + placement: this._fb.control('top', Validators.required), + order: this._fb.control(''), + custom: this._fb.control(false), + portalSpecific: this._fb.control(''), + defaultIsActive: this._fb.control(false), + settings: this._fb.array([]), + object: this._fb.control({}) + }); + // this.addNewAttr(); + this.modalOpen("Create template", "Create"); + } + + private modalOpen(title: string, yesBtn: string) { + this.editModal.okButtonLeft = false; + this.editModal.alertTitle = title; + this.editModal.okButtonText = yesBtn; + this.editModal.open(); + } + + public swap(templateToMoveUp, templateToMoveDown, placement) { + let moveUpTemplate = this.templatesByPlacement.get(placement)[templateToMoveUp]; + let moveDownTemplate = this.templatesByPlacement.get(placement)[templateToMoveDown]; + this.templatesByPlacement.get(placement)[templateToMoveUp] = moveDownTemplate; + this.templatesByPlacement.get(placement)[templateToMoveDown] = moveUpTemplate; + this.move(moveUpTemplate, true, templateToMoveDown, placement); + this.move(moveDownTemplate, false, templateToMoveUp, placement); + } + + public move(template: PluginTemplate, up: boolean, index, placement) { + this.subscriptions.push(this._pluginsService.updatePluginTemplateOrder(template, this.properties.adminToolsAPIURL, up ? -1 : 1).subscribe( + saved => { + this.templatesByPlacement.get(placement)[index] = saved; + }, + error => this.handleUpdateError("System error creating template", error) + )); + } + + public saveConfirmed(data: any) { + this.showLoading = true; + let template: PluginTemplate = this.templateForm.getRawValue(); + template.page = this.templateForm.getRawValue().page._id + template.portalSpecific = this.templateForm.getRawValue().portalSpecific.length > 0? this.templateForm.getRawValue().portalSpecific.split(','):[]; + template.object = this.selectedTemplate?this.selectedTemplate.object:PluginUtils.initializeObjectAndCompare(template.code); + template.settings = new Map(); + this.editSubmenuOpen = false; + if(!template._id){ + template.order = this.templatesByPlacement.get(template.placement).length > 0 ? this.templatesByPlacement.get(template.placement).length:0; + } + for (let attr of this.templateForm.getRawValue().settings) { + template.settings[attr.key] = {name: attr.name, type: attr.type, value: attr.value}; + } + let update = template._id ? true : false; + this.subscriptions.push(this._pluginsService.savePluginTemplate(template, this.properties.adminToolsAPIURL).subscribe( + saved => { + this.selectedTemplate = saved; + this.savedSuccessfully(saved, update); + NotificationHandler.rise('Template ' + saved.name + ' has been successfully' + (update ? ' updated ' : ' created ') + ''); + // this._clearCacheService.clearCache("Template id saved"); + }, + error => this.handleUpdateError("System error creating template", error) + )); + } + + public savedSuccessfully(template: PluginTemplate, update: boolean) { + if (update) { + let index = this.templatesByPlacement.get(this.selectedTemplate.placement).findIndex(value => value._id === template._id); + this.templatesByPlacement.get(this.selectedTemplate.placement)[index] = template; + // TODO sort + // this.templatesByPlacement.get(this.selectedTemplate.placement) = this.templatesByPlacement.get(this.selectedTemplate.placement).sort() + } else { + template.object = PluginUtils.initializeObjectAndCompare(template.code, template.object) + this.templatesByPlacement.get(this.selectedTemplate.placement).push(template); + } + + this.showLoading = false; + } + + public filter(plugin: PluginTemplate): boolean { + return this.searchText.toString() == '' || (plugin.name + ' ' + plugin.portalType).match(this.searchText) != null; + } + + handleUpdateError(message: string, error = null) { + if (error) { + console.log('Server responded: ' + error); + } + NotificationHandler.rise(message, 'danger'); + this.showLoading = false; + } + + handleError(message: string, error = null) { + if (error) { + console.log('Server responded: ' + error); + } + NotificationHandler.rise(message, 'danger'); + this.showLoading = false; + } + + getPages() { + this.showLoading = true; + this.subscriptions.push(this._helpContentService.getAllPages(this.properties.adminToolsAPIURL).subscribe( + pages => { + this.allPages = []; + this.allPagesByPortal = new Map(); + pages.forEach(page => { + let option = { + label: page.name + " [" + page.portalType + "]", + value: page + }; + this.allPages.push(option); + if (!this.allPagesByPortal.has(page.portalType)) { + this.allPagesByPortal.set(page.portalType, []) + } + this.allPagesByPortal.get(page.portalType).push(option) + }); + this.showLoading = false; + }, + error => this.handleError('System error retrieving pages', error) + )); + } + + addNewAttr() { + (this.templateForm.get("settings") as FormArray).push(this._fb.group({ + key: this._fb.control("", Validators.required), + name: this._fb.control("", Validators.required), + type: this._fb.control("text", Validators.required), + value: this._fb.control("") + })); + } + + removeAttr(index) { + this.attrFormArray.removeAt(index); + this.attrFormArray.markAsDirty(); + } + + get attrFormArray() { + + return this.templateForm.get("settings") as FormArray; + + } + + attributeTypeChanged(form) { + let type = form.get("value").get("type"); + form.get("value").setValue(""); + if (type == "boolean") { + form.get("value").setValue(false); + } + } + + public getPageAsString(pageId): string { + return this.allPages.filter(option => option.value._id == pageId).map((option => option.value.name + " [" + option.value.portalType + "]")).join(","); + } + + public getPageById(pageId) { + for (let option of this.allPages) { + if (option.value._id == pageId) { + return option.value; + } + } + return pageId; + } + + + pluginFieldChanged($event:PluginEditEvent){ + if($event.type == "open-submenu"){ + this.editSubmenuOpen = true; + return; + } + if($event.type == "close-submenu"){ + + this.editSubmenuOpen = false; + return; + } + this.selectedTemplate.object[$event.field]=$event.value; + this.templateForm.markAsDirty(); + } + public getPagesByPortal(portal) { + return this.allPages.filter(option => option.value.portalType == portal); + } +} diff --git a/dashboard/plugins/templates/pluginTemplates.module.ts b/dashboard/plugins/templates/pluginTemplates.module.ts new file mode 100644 index 00000000..4790450a --- /dev/null +++ b/dashboard/plugins/templates/pluginTemplates.module.ts @@ -0,0 +1,39 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {AlertModalModule} from '../../../utils/modal/alertModal.module'; +import {PluginTemplatesComponent} from './pluginTemplates.component'; +import {AdminToolServiceModule} from "../../../services/adminToolService.module"; +import {InputModule} from "../../../sharedComponents/input/input.module"; + + +import {MatAutocompleteModule} from '@angular/material/autocomplete'; +import {MatCheckboxModule} from "@angular/material/checkbox"; +import {MatFormFieldModule} from "@angular/material/form-field"; + + +import {MatChipsModule} from '@angular/material/chips'; +import {AdminTabsModule} from "../../sharedComponents/admin-tabs/admin-tabs.module"; +import {PageContentModule} from "../../sharedComponents/page-content/page-content.module"; +import {PluginTemplatesRoutingModule} from "./pluginTemplates-routing.module"; +import {SearchInputModule} from "../../../sharedComponents/search-input/search-input.module"; +import {IconsModule} from "../../../utils/icons/icons.module"; +import {LoadingModule} from "../../../utils/loading/loading.module"; +import {PluginsService} from "../../../services/plugins.service"; +import {CKEditorModule} from "ng2-ckeditor"; +import {PluginWrapperModule} from "../wrapper/plugin-wrapper.module"; +import {PluginEditWrapperModule} from "../wrapper/plugin-edit-wrapper.module"; +import {MatSlideToggleModule} from "@angular/material/slide-toggle"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, + AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule, MatAutocompleteModule, MatFormFieldModule, MatChipsModule, + MatCheckboxModule, AdminTabsModule, PageContentModule, PluginTemplatesRoutingModule, SearchInputModule, IconsModule, LoadingModule, CKEditorModule, PluginWrapperModule, PluginEditWrapperModule, MatSlideToggleModule + ], + providers:[PluginsService], + declarations: [PluginTemplatesComponent], + exports: [PluginTemplatesComponent] +}) +export class PluginTemplatesModule {} diff --git a/dashboard/plugins/utils/base-plugin.component.ts b/dashboard/plugins/utils/base-plugin.component.ts new file mode 100644 index 00000000..a56b8232 --- /dev/null +++ b/dashboard/plugins/utils/base-plugin.component.ts @@ -0,0 +1,118 @@ +import {Directive, Input, OnDestroy} from '@angular/core'; +import {Plugin} from "../../../utils/entities/adminTool/plugin"; +import {PluginTemplate} from "../../../utils/entities/adminTool/pluginTemplate"; +import {EnvProperties} from "../../../utils/properties/env-properties"; +import {properties} from 'src/environments/environment'; +import {Subscriber} from "rxjs"; +import {CustomizationOptions, Layout} from "../../../connect/community/CustomizationOptions"; +import {CustomizationService} from "../../../services/customization.service"; + +export class PluginBaseInfo { + title: string = "Lorem ipsum"; + + constructor() { + } + + compare(oldObject) { + if (!oldObject) { + oldObject = Object.assign(this) + } else { + for (let attrKey of Object.keys(this)) { + if (!oldObject[attrKey] && oldObject[attrKey] != false) { + if (typeof this[attrKey] === "string" || typeof this[attrKey] === "boolean") { + oldObject[attrKey] = this[attrKey]; + } else { + oldObject[attrKey] = Object.assign(this[attrKey]) + } + } + } + } + return oldObject; + } +} + +export class PluginURL { + url: string; + linkText: string; + target: string; + route: boolean; + + constructor(url, linkText, target = "_blank", route = false) { + this.url = url; + this.linkText = linkText; + this.target = target; + this.route = route; + } + +} + +export class PluginInfoCards { + tag?: string; + title: string; + description: string; + urlsArray: PluginURL[]; + image?: string; + icon?:string; + show: boolean; +} + +@Directive() +export abstract class PluginBaseComponent implements OnDestroy { + public properties: EnvProperties = properties; + @Input() plugin: Plugin; + @Input() pluginTemplate: PluginTemplate; + @Input() pluginObject: T; + @Input() previewInAdmin: boolean = false; + subscriptions = []; + + customizationOptions: CustomizationOptions; + style:string =''; + fontsDarkMode:boolean = true; + protected layoutService: CustomizationService + constructor( ) { + } + + ngOnInit(): void { + } + + ngOnDestroy() { + this.subscriptions.forEach(subscription => { + if (subscription instanceof Subscriber) { + subscription.unsubscribe() + } else if (subscription instanceof Function) { + subscription(); + } else if (typeof IntersectionObserver !== 'undefined' && subscription instanceof IntersectionObserver) { + subscription.disconnect(); + } else if (typeof ResizeObserver !== 'undefined' && subscription instanceof ResizeObserver) { + subscription.disconnect(); + } + }); + } + + isVisible(field) { + return (this.plugin && this.pluginObject && this.pluginObject[field] == true) /* plugin is on anyway */ + || (!this.plugin && this.pluginTemplate && this.pluginObject && this.pluginObject[field] == true) /* template is on */ + } + + getLayout(communityId) { + if (this.previewInAdmin) { + let defaultCustomizationOptions = new CustomizationOptions(CustomizationOptions.getIdentity(communityId).mainColor, CustomizationOptions.getIdentity(communityId).secondaryColor); + this.subscriptions.push(this.layoutService.getLayout(this.properties, communityId).subscribe(layout => { + layout = (layout ? layout : new Layout(communityId, defaultCustomizationOptions)); + this.customizationOptions = (layout ? CustomizationOptions.checkForObsoleteVersion(layout.layoutOptions, communityId) : Object.assign({}, defaultCustomizationOptions)); + this.setStyle() + }, error => { + this.customizationOptions = defaultCustomizationOptions; + this.setStyle(); + })); + } + } + + setStyle() { + this.style = `background-color: ` + this.customizationOptions.backgrounds.form.color + `; + background-image: ` + (this.customizationOptions.backgrounds.form.imageFile ? (Layout.getUrl(properties.utilsService + '/download/' + this.customizationOptions.backgrounds.form.imageFile)) : 'none') + `; + background-position:` + this.customizationOptions.backgrounds.form.position + `;` + this.fontsDarkMode = this.customizationOptions.backgrounds.form.fontsDarkMode; + + } +} diff --git a/dashboard/plugins/utils/base-plugin.form.component.ts b/dashboard/plugins/utils/base-plugin.form.component.ts new file mode 100644 index 00000000..aa2e0592 --- /dev/null +++ b/dashboard/plugins/utils/base-plugin.form.component.ts @@ -0,0 +1,43 @@ +import {Directive, EventEmitter, Input, OnDestroy, Output} from '@angular/core'; +import {Plugin} from "../../../utils/entities/adminTool/plugin"; +import {PluginTemplate} from "../../../utils/entities/adminTool/pluginTemplate"; +import {EnvProperties} from "../../../utils/properties/env-properties"; +import {properties} from 'src/environments/environment'; +import {PluginBaseComponent, PluginBaseInfo} from "./base-plugin.component"; + +export class PluginEditEvent { + field:string; + type:"text" | "HTML" | "boolean" | 'parent' |'open-submenu' | 'close-submenu'; + value?:any; + constructor(field: string, type: "text" | "HTML" | "boolean" | 'parent' |'open-submenu' | 'close-submenu', value= null) { + this.field = field; + this.type = type; + this.value = value; + } +} + +@Directive() + export abstract class PluginBaseFormComponent extends PluginBaseComponent implements OnDestroy { + public properties: EnvProperties = properties; + @Input() editMode =false; + @Input() plugin:Plugin; + @Input() pluginTemplate:PluginTemplate; + @Input() editTemplate:boolean = false; + @Input() pluginObject:T; + @Output() valuesChanged:EventEmitter = new EventEmitter(); + subscriptions = []; + pluginEditEvent:PluginEditEvent; + + valueChanged($event:PluginEditEvent){ + this.pluginObject[$event.field]=$event.value; + this.valuesChanged.emit($event) + } + toggleSubMenu(open:boolean){ + this.valuesChanged.emit(new PluginEditEvent(null,open?'open-submenu':'close-submenu')) + } + isVisible(field){ + return (this.plugin && this.pluginObject && this.pluginObject[field] == true) /* plugin is on anyway */ + || (!this.plugin && this.pluginTemplate && this.pluginObject && this.pluginObject[field] == true) /* template is on */ + } + +} diff --git a/dashboard/plugins/utils/plugin-field-edit.component.ts b/dashboard/plugins/utils/plugin-field-edit.component.ts new file mode 100644 index 00000000..1b545016 --- /dev/null +++ b/dashboard/plugins/utils/plugin-field-edit.component.ts @@ -0,0 +1,86 @@ +import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core'; +import {PluginEditEvent} from "./base-plugin.form.component"; +import {AlertModal} from "../../../utils/modal/alert"; +import {UntypedFormBuilder, UntypedFormGroup} from "@angular/forms"; + + +@Component({ + selector: 'plugin-field-edit', + template: ` + + + + + +
        +
        + + open editor + +
        +
        +
        + +
        +
        + + + + + `, + styles: [` + :host >>> textarea.input { + border: solid 1px #3e3e3e3e !important; + } + `] + +}) +export class PluginFieldEditComponent { + @Input() type; + @Input() value; + @Input() field; + @Input() placeholder; + @Input() switchToHTMLEditor; + @Output() editClicked: EventEmitter = new EventEmitter(); + @Output() changed: EventEmitter = new EventEmitter(); + htmlEditorView = false; + @ViewChild('HTMLEditorModal') HTMLEditorModal: AlertModal; + HTMLForm: UntypedFormGroup = this._fb.group({ + value: this._fb.control("") + }); + + constructor(private _fb: UntypedFormBuilder) { + } + + updateObject(value) { + console.log(value) + this.value = value; + this.changed.emit({field: this.field, value: this.value, type: this.type}); + } + + openHTMLEditor() { + this.HTMLForm.get('value').setValue(this.value) + this.htmlEditorView = true; + this.HTMLEditorModal.alertTitle = "HTML Editor"; + this.HTMLEditorModal.open(); + } + + closeHTMLEditor() { + this.htmlEditorView = false; + this.updateObject(this.HTMLForm.get('value').value) + } +} diff --git a/dashboard/plugins/utils/plugin-field-edit.module.ts b/dashboard/plugins/utils/plugin-field-edit.module.ts new file mode 100644 index 00000000..2d8a9a55 --- /dev/null +++ b/dashboard/plugins/utils/plugin-field-edit.module.ts @@ -0,0 +1,22 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {PluginFieldEditComponent} from "./plugin-field-edit.component"; +import {InputModule} from "../../../sharedComponents/input/input.module"; +import {MatSlideToggleModule} from "@angular/material/slide-toggle"; +import {CKEditorModule} from "ng2-ckeditor"; +import {AlertModalModule} from "../../../utils/modal/alertModal.module"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, InputModule, MatSlideToggleModule, CKEditorModule, AlertModalModule, FormsModule, ReactiveFormsModule + ], + declarations: [PluginFieldEditComponent], + exports: [PluginFieldEditComponent] +}) +export class PluginFieldEditModule { + /*constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([]) + }*/ +} diff --git a/dashboard/plugins/utils/pluginUtils.ts b/dashboard/plugins/utils/pluginUtils.ts new file mode 100644 index 00000000..66c18c67 --- /dev/null +++ b/dashboard/plugins/utils/pluginUtils.ts @@ -0,0 +1,164 @@ +import {Option} from "../../../sharedComponents/input/input.component"; +import {PluginOpenAIREProducts} from "../components/openaireProducts/plugin-openaire-products.component"; +import {PluginDiscoverBySubcommunity} from "../components/discover-by-subcommunity/plugin-discover-by-subcommunity.component"; +import {PluginBaseInfo, PluginInfoCards, PluginURL} from "./base-plugin.component"; +import {PluginGatewayInformation} from "../components/gateway-information/plugin-gateway-information.component"; +import {PluginFeaturedDatasets} from "../components/featured-datasets/plugin-featured-datasets.component"; +import {PluginSearchDepositLink} from "../components/search-deposit-link/plugin-search-deposit-link.component"; +import {PluginOrganizations} from "../components/organizations/plugin-organizations.component"; +import {PluginSuggestedRepositories} from "../components/suggested-repositories/plugin-suggested-repositories.component"; +import {ParagraphInfo} from "../components/paragraph-info/plugin-graph-info.component"; +import {PluginStats} from "../components/stats/plugin-stats.component"; +import {PluginCardInfo} from "../components/card-info/plugin-card-info.component"; +import {PluginSearchBar} from "../components/search-bar/plugin-search-bar.component"; +import {HTMLSection} from "../components/html-section/plugin-html-section.component"; + +export class PluginUtils{ + public attrTypeOptions: Option[] = [ + {label:"Text", value:"text"}, + {label:"HTML", value:"HTML"}, + {label:"Boolean", value:"boolean"}, + {label:"URL", value:"URL"}, + ]; + + public availablePluginCodesOptions: Option[] = [ + {label:"OpenAIRE products", value:"openaire-products"}, + {label:"Discover by subcommunity", value:"discover-by-subcommunity"}, + {label:"Gateway information", value:"gateway-information"}, + {label:"Search/ deposit/ link", value:"search-deposit-link"}, + {label:"Learn and Connect", value:"learn-and-connect"}, + {label:"How to use", value:"how-to-use"}, + {label:"Suggested Repositories", value:"suggested-repositories"}, + {label:"Featured Datasets", value:"featured-datasets"}, + {label:"Organizations", value:"organizations"}, + {label:"Graph info", value:"graph-info"}, + {label:"Statistics", value:"stats"}, + {label:"Search Bar", value:"search-bar"}, + {label:"Card info", value:"card-info"}, + {label:"Paragraph info", value:"paragraph-info"}, + {label:"HTML section", value:"html-section"}, + ]; + public customOptions: Option[] = [ + {label:"Yes", value:"true"}, + {label:"no", value:"false"} + ]; + public availablePluginCodes: string[] = ["openaire-products", "discover-by-subcommunity", "gateway-information", "search-deposit-link", "learn-and-connect", "how-to-use", "suggested-repositories", "featured-datasets", "organizations", "graph-info", "organizations", "stats", "search-bar","card-info", "paragraph-info", "html-section"]; + public placementsOptions: Option[] = [ + {label:"Right", value:"right"}, + {label:"Top", value:"top"}, + // {label:"Top Right", value:"top-right"}, + // {label:"Center", value:"center"}, + {label:"Bottom", value:"bottom"}, + {label:"Left", value:"left"}, + ]; + public planOptions: Option[] = [ + {value: 'Default', label: 'Default'}, + {value: 'Standard', label: 'Standard'}, + {value: 'Advanced', label: 'Advanced'}, + {value: 'Premium', label: 'Premium'}, + {value: 'National', label: 'National'} + ]; + + + public static initializeObjectAndCompare(code, oldObject = null){ + switch(code) { + case 'openaire-products': { + return (new PluginOpenAIREProducts()).compare(oldObject); + } + case 'discover-by-subcommunity': { + return (new PluginDiscoverBySubcommunity()).compare(oldObject); + } + case 'gateway-information': { + return (new PluginGatewayInformation()).compare(oldObject); + } + case 'search-deposit-link': { + return (new PluginSearchDepositLink()).compare(oldObject); + } + case 'suggested-repositories': { + return (new PluginSuggestedRepositories()).compare(oldObject); + } + case 'featured-datasets': { + return (new PluginFeaturedDatasets()).compare(oldObject); + } + case 'organizations': { + return (new PluginOrganizations()).compare(oldObject); + } + case 'graph-info': { + return (new PluginGraphInfo()).compare(oldObject); + } + case 'paragraph-info': { + return (new ParagraphInfo()).compare(oldObject); + } + case 'html-section': { + return (new HTMLSection()).compare(oldObject); + } + case 'stats': { + return (new PluginStats()).compare(oldObject); + } + case 'learn-and-connect': { + return (new PluginCardInfo()).compare(oldObject); + } + case 'how-to-use': { + return (new PluginCardInfo()).compare(oldObject); + } + case 'card-info': { + return (new PluginCardInfo()).compare(oldObject); + } + case 'search-bar': { + return (new PluginSearchBar()).compare(oldObject); + } + default: { + return (new PluginBaseInfo()).compare(oldObject); + } + } + } + // + public static updateExistingObject(oldObject, object ){ + if(!oldObject) { + oldObject = Object.assign(object) + }else{ + for (let attrKey of Object.keys(object)) { + if (!oldObject[attrKey] && oldObject[attrKey] != false) { + oldObject[attrKey] = Object.assign(object[attrKey]) + } + } + } + return oldObject; + } +} + +export class PluginHowToUse extends PluginCardInfo{ + title:string ="How to use the gateway?"; + cardInfoArray: PluginInfoCards[] = [ + {title: "Tutorials", description: "Mini-video tutorials for gateway managers", urlsArray:[ new PluginURL("https://www.youtube.com/playlist?list=PL0c4IRNUxuKcyRUQ_J9BH_EE1amXU6kgp","View all")], show:true}, + {title: "Guides", description: "Textual guides on gateway functionalities.", urlsArray:[ new PluginURL("https://www.openaire.eu/research-community-gateway-guide","Guide for the users")/*, new PluginURL("","Guide for the managers")*/], show:true}, + {title: "Webinars", description: "Recordings and slides of webinars on different aspects of Open Science.", urlsArray:[ new PluginURL("","View all")], show:true} + ]; + compare(oldObject){ + oldObject = super.compare(oldObject) + + for(let card of this.cardInfoArray){ + + } + return oldObject; + } +} + +export class PluginLearnAndConnect extends PluginCardInfo{ + title:string ="Learn & Connect with Open Science"; + cardInfoArray:PluginInfoCards[] = [ + {title: "OS Practices", description: "Open Science best practices for your community, policies and mandates.", + urlsArray:[ new PluginURL("","")], show:true}, + {title: "OS Guides for beginners", description: "New to Open Science? Learn the basics!",urlsArray:[ new PluginURL("https://www.openaire.eu/guides","Learn more")], show:true}, + {title: "Webinars", description: "Recordings and slides of webinars on different aspects of Open Science.",urlsArray:[ new PluginURL("https://www.openaire.eu/support/webinars","Learn more")], show:true} + ]; +} + + +export class PluginGraphInfo extends ParagraphInfo{ + title:string ="How? It's about open data and collaboration" + paragraph1:string = `This gateway is built on the OpenAIRE Graph, one of the largest open scholarly record collections worldwide. Conceived as a public and transparent good, populated out of data sources trusted by scientists, the OpenAIRE Graph brings discovery, monitoring, and assessment of science back in the hands of the scientific community.`; + paragraph2:string = "Within a constantly emerging scholarly communication environment, the OpenAIRE Graph is a moving target, continuously integrating new sources, new types of research objects, and embedding impact and usage indicators. We therefore welcome the community to work with us to improve all its aspects: its coverage (geographic and thematic), quality (disambiguation and semantics) and access (APIs)."; + url:PluginURL= new PluginURL("https://graph.openaire.eu","Learn more") + image:string = "assets/common-assets/common/graph-nodes.svg" +} diff --git a/dashboard/plugins/wrapper/edit-plugin.css b/dashboard/plugins/wrapper/edit-plugin.css new file mode 100644 index 00000000..35a895e6 --- /dev/null +++ b/dashboard/plugins/wrapper/edit-plugin.css @@ -0,0 +1,9 @@ +.pluginEditMode{ + border:2px solid grey; + padding:10px; +} +:host ::ng-deep .fieldEditMode{ + border:1px dashed lightblue; + padding:1px; + margin-bottom: 5px; +} diff --git a/dashboard/plugins/wrapper/plugin-edit-wrapper.component.ts b/dashboard/plugins/wrapper/plugin-edit-wrapper.component.ts new file mode 100644 index 00000000..f89137a5 --- /dev/null +++ b/dashboard/plugins/wrapper/plugin-edit-wrapper.component.ts @@ -0,0 +1,73 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {Plugin} from "../../../utils/entities/adminTool/plugin"; +import {PluginTemplate} from "../../../utils/entities/adminTool/pluginTemplate"; +import {PluginEditEvent} from "../utils/base-plugin.form.component"; +import {PluginUtils} from "../utils/pluginUtils"; + +@Component({ + selector: 'plugin-wrapper-form', + template: ` +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + No plugin available +
        +
        +
        + + `, + styleUrls: ["edit-plugin.css"] +}) +export class PluginEditWrapperComponent implements OnInit { + + @Input() plugin:Plugin; + @Input() pluginTemplate:PluginTemplate; + @Input() editTemplate:boolean; + @Input() pluginObject; + @Output() changed:EventEmitter = new EventEmitter(); + @Input() editSubmenuOpen; + pluginUtils = new PluginUtils(); + + ngOnInit(): void { + } + +} diff --git a/dashboard/plugins/wrapper/plugin-edit-wrapper.module.ts b/dashboard/plugins/wrapper/plugin-edit-wrapper.module.ts new file mode 100644 index 00000000..29df723c --- /dev/null +++ b/dashboard/plugins/wrapper/plugin-edit-wrapper.module.ts @@ -0,0 +1,35 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {PluginEditWrapperComponent} from "./plugin-edit-wrapper.component"; +import {PluginOpenaireProductsFormComponent} from "../components/openaireProducts/plugin-openaire-products.form.component"; +import {PluginFieldEditModule} from "../utils/plugin-field-edit.module"; +import {PluginDiscoverBySubcommunityFormComponent} from "../components/discover-by-subcommunity/plugin-discover-by-subcommunity.form.component"; +import {PluginFeaturedDatasetsFormComponent} from "../components/featured-datasets/plugin-featured-datasets.form.component"; +import {PluginGatewayInformationFormComponent} from "../components/gateway-information/plugin-gateway-information.form.component"; +import {PluginSearchDepositLinkFormComponent} from "../components/search-deposit-link/plugin-search-deposit-link.form.component"; +import {PluginOrganizationsFormComponent} from "../components/organizations/plugin-organizations.form.component"; +import {IconsModule} from "../../../utils/icons/icons.module"; +import {PluginSuggestedRepositoriesFormComponent} from "../components/suggested-repositories/plugin-suggested-repositories.form.component"; +import {PluginGraphInfoFormComponent} from "../components/paragraph-info/plugin-graph-info.form.component"; +import {PluginStatsFormComponent} from "../components/stats/plugin-stats.form.component"; +import {PluginSearchBarFormComponent} from "../components/search-bar/plugin-search-bar.form.component"; +import {PluginCardInfoFormComponent} from "../components/card-info/plugin-card-info-form.component"; +import {CKEditorModule} from "ng2-ckeditor"; +import {InputModule} from "../../../sharedComponents/input/input.module"; +import {PluginHtmlSectionFormComponent} from "../components/html-section/plugin-html-section.form.component"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, + ReactiveFormsModule, InputModule, + FormsModule, PluginFieldEditModule, IconsModule, CKEditorModule, + ], + declarations: [PluginEditWrapperComponent, PluginOpenaireProductsFormComponent, PluginDiscoverBySubcommunityFormComponent, PluginDiscoverBySubcommunityFormComponent, PluginDiscoverBySubcommunityFormComponent, PluginDiscoverBySubcommunityFormComponent, PluginDiscoverBySubcommunityFormComponent, PluginDiscoverBySubcommunityFormComponent, PluginFeaturedDatasetsFormComponent, PluginGatewayInformationFormComponent, PluginSearchDepositLinkFormComponent, PluginOrganizationsFormComponent, PluginSuggestedRepositoriesFormComponent, PluginGraphInfoFormComponent, PluginStatsFormComponent, PluginSearchBarFormComponent, PluginCardInfoFormComponent, PluginHtmlSectionFormComponent], + exports: [PluginEditWrapperComponent] + +}) +export class PluginEditWrapperModule { + +} diff --git a/dashboard/plugins/wrapper/plugin-wrapper.component.ts b/dashboard/plugins/wrapper/plugin-wrapper.component.ts new file mode 100644 index 00000000..e5f2d36f --- /dev/null +++ b/dashboard/plugins/wrapper/plugin-wrapper.component.ts @@ -0,0 +1,65 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {Plugin} from "../../../utils/entities/adminTool/plugin"; +import {PluginTemplate} from "../../../utils/entities/adminTool/pluginTemplate"; +import {PluginUtils} from "../utils/pluginUtils"; + +@Component({ + selector: 'plugin-wrapper', + template: ` + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        + No plugin available +
        +
        +
        + ` +}) +export class PluginWrapperComponent implements OnInit { + @Input() plugin:Plugin; + @Input() pluginObject; + @Input() pluginTemplate:PluginTemplate; + @Input() previewInAdmin:boolean = false; + pluginUtils = new PluginUtils(); + ngOnInit(): void { + + } +} diff --git a/dashboard/plugins/wrapper/plugin-wrapper.module.ts b/dashboard/plugins/wrapper/plugin-wrapper.module.ts new file mode 100644 index 00000000..bd3e2d59 --- /dev/null +++ b/dashboard/plugins/wrapper/plugin-wrapper.module.ts @@ -0,0 +1,30 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {PluginWrapperComponent} from "./plugin-wrapper.component"; +import {PluginOpenaireProductsModule} from "../components/openaireProducts/plugin-openaire-products.module"; +import {PluginDiscoverBySubcommunityModule} from '../components/discover-by-subcommunity/plugin-discover-by-subcommunity.module'; +import {PluginGatewayInformationModule} from '../components/gateway-information/plugin-gateway-information.module'; +import {PluginSearchDepositLinkModule} from '../components/search-deposit-link/plugin-search-deposit-link.module'; +import {PluginSuggestedRepositoriesModule} from '../components/suggested-repositories/plugin-suggested-repositories.module'; +import {PluginFeaturedDatasetsModule} from '../components/featured-datasets/plugin-featured-datasets.module'; +import {PluginOrganizationsModule} from "../components/organizations/plugin-organizations.module"; +import {PluginStatsModule} from "../components/stats/plugin-stats.module"; +import {PluginSearchBarModule} from "../components/search-bar/plugin-search-bar.module"; +import {PluginCardInfoModule} from "../components/card-info/plugin-card-info.module"; +import {PluginHtmlSectionModule} from "../components/html-section/plugin-html-section.module"; +import {PluginGraphInfoModule} from "../components/paragraph-info/plugin-graph-info.module"; + +@NgModule({ + imports: [ + CommonModule, RouterModule, FormsModule, PluginOpenaireProductsModule, + PluginDiscoverBySubcommunityModule, PluginSearchDepositLinkModule, PluginSuggestedRepositoriesModule, PluginFeaturedDatasetsModule, PluginGatewayInformationModule, PluginOrganizationsModule, PluginHtmlSectionModule, PluginStatsModule, PluginSearchBarModule, PluginCardInfoModule, PluginGraphInfoModule + ], + declarations: [PluginWrapperComponent], + exports: [PluginWrapperComponent] + +}) +export class PluginWrapperModule { + +} diff --git a/dashboard/portal/portals.component.ts b/dashboard/portal/portals.component.ts index d9dec3ec..69b08fe9 100644 --- a/dashboard/portal/portals.component.ts +++ b/dashboard/portal/portals.component.ts @@ -137,7 +137,7 @@ export class PortalsComponent implements OnInit { this.deletePortalsFromArray(this.selectedPortals); NotificationHandler.rise('Portals have been successfully deleted'); this.showLoading = false; - this._clearCacheService.clearCache("Portals deleted"); + // this._clearCacheService.clearCache("Portals deleted"); }, error => this.handleUpdateError('System error deleting the selected communities', error) )); @@ -188,7 +188,7 @@ export class PortalsComponent implements OnInit { portal => { this.portalUpdatedSuccessfully(portal); NotificationHandler.rise('Portal ' + portal.name + ' has been successfully updated'); - this._clearCacheService.clearCache("Portal updated"); + //this._clearCacheService.clearCache("Portal updated"); }, error => this.handleUpdateError('System error updating portal', error) )); @@ -198,7 +198,7 @@ export class PortalsComponent implements OnInit { portal => { this.portalSavedSuccessfully(portal); NotificationHandler.rise('Portal ' + portal.name + ' has been successfully created'); - this._clearCacheService.clearCache("Portal saved"); + //this._clearCacheService.clearCache("Portal saved"); }, error => this.handleUpdateError('System error creating portal', error) )); diff --git a/dashboard/sharedComponents/admin-tabs/admin-tabs.component.ts b/dashboard/sharedComponents/admin-tabs/admin-tabs.component.ts index 99677e59..4e5a107e 100644 --- a/dashboard/sharedComponents/admin-tabs/admin-tabs.component.ts +++ b/dashboard/sharedComponents/admin-tabs/admin-tabs.component.ts @@ -13,6 +13,7 @@ import {ActivatedRoute} from "@angular/router";
      • Entities
      • Menus
      • Classes
      • +
      • Templates
      • Customization
      • ` @@ -25,7 +26,7 @@ export class AdminTabsComponent implements OnInit { @Input() public user: User; @Input() - public tab: "portal" | "page" | "entity" | "menu" | "class" | "customization" = 'page'; + public tab: "portal" | "page" | "entity" | "menu" | "class" | "customization" | "template" = 'page'; private subscriptions: any[] = []; constructor(private route: ActivatedRoute, private userManagementService: UserManagementService) { diff --git a/dashboard/sharedComponents/page-content/page-content.component.ts b/dashboard/sharedComponents/page-content/page-content.component.ts index c46e7114..b6019b8e 100644 --- a/dashboard/sharedComponents/page-content/page-content.component.ts +++ b/dashboard/sharedComponents/page-content/page-content.component.ts @@ -41,7 +41,7 @@ declare var UIkit; -
        +
        @@ -61,6 +61,8 @@ export class PageContentComponent implements OnInit, AfterViewInit, OnDestroy { public headerSticky: boolean = false; @Input() public border: boolean = true; + @Input() + public fullWidth: boolean = false; public offset: number; public shouldSticky: boolean = true; public isMobile: boolean = false; diff --git a/dashboard/users/role-users/role-users.component.ts b/dashboard/users/role-users/role-users.component.ts index 20da5b23..0b7f524a 100644 --- a/dashboard/users/role-users/role-users.component.ts +++ b/dashboard/users/role-users/role-users.component.ts @@ -231,7 +231,8 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges { } this.filterActiveBySearch(this.filterForm.value.active); this.userManagementService.updateUserInfo(); - this.clearCacheService.clearCache(this.role + 's of ' + this.id + ' have been updated'); + this.clearCacheService.clearCacheInRoute(this.role + 's of ' + this.id + ' have been updated',this.id, "/"); + this.clearCacheService.clearCacheInRoute(this.role + 's of ' + this.id + ' have been updated',this.id, "/curators"); NotificationHandler.rise(this.selectedUser + ' is no longer ' + this.role + ' of ' + this.name + ' Dashboard'); this.loadActive = false; }, error => { diff --git a/deposit/depositFirstPage.component.ts b/deposit/depositFirstPage.component.ts index 03704688..278bc4df 100644 --- a/deposit/depositFirstPage.component.ts +++ b/deposit/depositFirstPage.component.ts @@ -104,8 +104,8 @@ import {FullScreenModalComponent} from '../utils/modal/full-screen-modal/full-sc

        Find the appropriate repository.

        -
        -
        +
        +
        OpenAIRE logo @@ -120,7 +120,7 @@ import {FullScreenModalComponent} from '../utils/modal/full-screen-modal/full-sc
        -
        +
        Zenodo logo @@ -141,6 +141,22 @@ import {FullScreenModalComponent} from '../utils/modal/full-screen-modal/full-sc
        +
        +
        +
        + Suggested Repositories +
        + Select a repository suggested by the community curators. +
        +
        + + +
        +
        diff --git a/deposit/depositFirstPage.module.ts b/deposit/depositFirstPage.module.ts index 197b0ff3..d33ac8f4 100644 --- a/deposit/depositFirstPage.module.ts +++ b/deposit/depositFirstPage.module.ts @@ -12,6 +12,7 @@ import {DepositFirstPageComponent} from "./depositFirstPage.component"; import {BreadcrumbsModule} from "../utils/breadcrumbs/breadcrumbs.module"; import {SearchInputModule} from "../sharedComponents/search-input/search-input.module"; import {FullScreenModalModule} from '../utils/modal/full-screen-modal/full-screen-modal.module'; +import {IsPageEnabledModule} from "../utils/isPageEnabled/isPageEnabled.module"; @NgModule({ imports: [ @@ -19,7 +20,7 @@ import {FullScreenModalModule} from '../utils/modal/full-screen-modal/full-scree RouterModule, HelperModule, Schema2jsonldModule, SEOServiceModule, BreadcrumbsModule, SearchInputModule, - FullScreenModalModule + FullScreenModalModule, IsPageEnabledModule ], declarations: [ DepositFirstPageComponent diff --git a/deposit/searchDataprovidersToDeposit.component.ts b/deposit/searchDataprovidersToDeposit.component.ts index 79322525..eb4dcc48 100644 --- a/deposit/searchDataprovidersToDeposit.component.ts +++ b/deposit/searchDataprovidersToDeposit.component.ts @@ -32,14 +32,31 @@ import {SearchForm} from "../searchPages/searchUtils/newSearchPage.component";
        diff --git a/deposit/searchDataprovidersToDeposit.module.ts b/deposit/searchDataprovidersToDeposit.module.ts index d7959e48..75b153fc 100644 --- a/deposit/searchDataprovidersToDeposit.module.ts +++ b/deposit/searchDataprovidersToDeposit.module.ts @@ -12,14 +12,15 @@ import {SearchFormModule} from '../searchPages/searchUtils/searchForm.module'; import {SearchDataProvidersModule} from "../searchPages/searchDataProviders.module"; import {BreadcrumbsModule} from "../utils/breadcrumbs/breadcrumbs.module"; import {SearchInputModule} from "../sharedComponents/search-input/search-input.module"; +import {IsPageEnabledModule} from "../utils/isPageEnabled/isPageEnabled.module"; @NgModule({ imports: [ CommonModule, FormsModule, RouterModule, DataProvidersServiceModule, - SearchFormModule, SearchResultsModule, SearchDataProvidersModule, BreadcrumbsModule, SearchInputModule - + SearchFormModule, SearchResultsModule, SearchDataProvidersModule, BreadcrumbsModule, SearchInputModule, IsPageEnabledModule + ], declarations: [ SearchDataprovidersToDepositComponent diff --git a/deposit/searchResultsInDeposit.component.html b/deposit/searchResultsInDeposit.component.html index d622be32..6a01fbdb 100644 --- a/deposit/searchResultsInDeposit.component.html +++ b/deposit/searchResultsInDeposit.component.html @@ -5,7 +5,7 @@

        The OpenAIRE Catch-all repository hosted at CERN cloud infrastructure. Whatever your field of research is, you can deposit any type of research product, select the proper license, ask for a DOI and link it to the funding projects for easy reporting.

        - Related zenodo communities diff --git a/deposit/searchResultsInDeposit.module.ts b/deposit/searchResultsInDeposit.module.ts index 846219cb..987dc40d 100644 --- a/deposit/searchResultsInDeposit.module.ts +++ b/deposit/searchResultsInDeposit.module.ts @@ -7,12 +7,13 @@ import {ErrorMessagesModule} from '../utils/errorMessages.module'; import {SearchResultsInDepositComponent} from './searchResultsInDeposit.component'; import {ApprovedByCommunityModule} from '../connect/approvedByCommunity/approved.module'; import {ResultPreviewModule} from "../utils/result-preview/result-preview.module"; +import {IsPageEnabledModule} from "../utils/isPageEnabled/isPageEnabled.module"; @NgModule({ imports: [ CommonModule, FormsModule, RouterModule, ErrorMessagesModule, - ApprovedByCommunityModule, ResultPreviewModule + ApprovedByCommunityModule, ResultPreviewModule, IsPageEnabledModule ], declarations: [ SearchResultsInDepositComponent diff --git a/deposit/utils/zenodoInformation.class.ts b/deposit/utils/zenodoInformation.class.ts index 87a88914..74f6aed9 100644 --- a/deposit/utils/zenodoInformation.class.ts +++ b/deposit/utils/zenodoInformation.class.ts @@ -2,4 +2,5 @@ export class ZenodoInformationClass{ name: string = ""; url: string = ""; shareInZenodoUrl: string = ""; + hasSuggestedRepositories:boolean = false; } diff --git a/role-verification/role-verification.component.ts b/role-verification/role-verification.component.ts index 524388fe..5d8c7faf 100644 --- a/role-verification/role-verification.component.ts +++ b/role-verification/role-verification.component.ts @@ -201,7 +201,7 @@ export class RoleVerificationComponent extends BaseComponent implements OnInit, public verifyManager() { this.loading = true; this.subscriptions.push(this.userRegistryService.verify(this.verification.id, this.code.value).subscribe(() => { - this.clearCacheService.clearCache('Managers updated'); + // this.clearCacheService.clearCache('Managers updated'); this.managerModal.cancel(); this.error = null; if(this.service === "irish" || this.service === "monitor") { @@ -209,17 +209,17 @@ export class RoleVerificationComponent extends BaseComponent implements OnInit, this.userManagementService.login(properties.domain + '/admin/' + this.verification.entity); } else { this.subscriptions.push(this.emailService.notifyManagers(this.id, 'manager', - Composer.composeEmailToInformOldManagersForTheNewOnes(this.name, this.id)).subscribe(() => { + Composer.composeEmailToInformOldManagersForTheNewOnes(this.name, this.id)).subscribe(() => { this.subscriptions.push(this.emailService.notifyNewManager(Composer.composeEmailForNewManager(this.id, this.name)).subscribe( - () => { - this.loading = false; - window.location.href = properties.adminPortalURL + '/' + this.verification.entity; - }, - error1 => { - console.error(error1); - this.loading = false; - window.location.href = properties.adminPortalURL + '/' + this.verification.entity; - } + () => { + this.loading = false; + window.location.href = properties.adminPortalURL + '/' + this.verification.entity; + }, + error1 => { + console.error(error1); + this.loading = false; + window.location.href = properties.adminPortalURL + '/' + this.verification.entity; + } )); }, error => { console.error(error); @@ -235,16 +235,16 @@ export class RoleVerificationComponent extends BaseComponent implements OnInit, public verifyMember() { this.loading = true; - this.subscriptions.push(this.userRegistryService.verify(this.verification.id, this.code.value, "member").subscribe(() => { - this.clearCacheService.clearCache('Members updated'); - this.memberModal.cancel(); - this.loading = false; - this.error = null; - window.location.href = window.location.href.split('?')[0]; - }, error => { - this.loading = false; - this.error = 'The verification code is invalid'; - })); + this.subscriptions.push(this.userRegistryService.verify(this.verification.id, this.code.value, "member").subscribe(() => { + // this.clearCacheService.clearCache('Members updated'); + this.memberModal.cancel(); + this.loading = false; + this.error = null; + window.location.href = window.location.href.split('?')[0]; + }, error => { + this.loading = false; + this.error = 'The verification code is invalid'; + })); } public reset() { diff --git a/sdg/sdg.component.html b/sdg/sdg.component.html index c1f431fe..5cb7f807 100644 --- a/sdg/sdg.component.html +++ b/sdg/sdg.component.html @@ -17,8 +17,7 @@ Laying the foundation for new approaches and solutions.
        +
        diff --git a/sdg/sdg.component.ts b/sdg/sdg.component.ts index 2c648dcb..a7360ec1 100644 --- a/sdg/sdg.component.ts +++ b/sdg/sdg.component.ts @@ -31,6 +31,7 @@ export class SdgComponent implements OnInit, OnDestroy { properties: EnvProperties = properties; openaireEntities = OpenaireEntities; @Input() customFilter = null; + @Input() pageContents = null; public breadcrumbs: Breadcrumb[] = [{name: 'home', route: '/'}, {name: 'Sustainable Development Goals'}]; subscriptions: Subscription[] = []; diff --git a/sdg/sdg.module.ts b/sdg/sdg.module.ts index 1888b381..748729b7 100644 --- a/sdg/sdg.module.ts +++ b/sdg/sdg.module.ts @@ -9,13 +9,14 @@ import {Schema2jsonldModule} from "../sharedComponents/schema2jsonld/schema2json import {SEOServiceModule} from "../sharedComponents/SEO/SEOService.module"; import {SdgRoutingModule} from './sdg-routing.module'; import {SdgComponent} from './sdg.component'; +import {HelperModule} from "../utils/helper/helper.module"; @NgModule({ - imports: [ - CommonModule, FormsModule, RouterModule, - SdgRoutingModule, BreadcrumbsModule, RefineFieldResultsServiceModule, - LoadingModule, Schema2jsonldModule, SEOServiceModule - ], + imports: [ + CommonModule, FormsModule, RouterModule, + SdgRoutingModule, BreadcrumbsModule, RefineFieldResultsServiceModule, + LoadingModule, Schema2jsonldModule, SEOServiceModule, HelperModule + ], declarations: [ SdgComponent ], @@ -26,4 +27,4 @@ import {SdgComponent} from './sdg.component'; }) export class SdgModule { -} \ No newline at end of file +} diff --git a/searchPages/searchUtils/entitiesSelection.component.ts b/searchPages/searchUtils/entitiesSelection.component.ts index 73388a0c..5ac17587 100644 --- a/searchPages/searchUtils/entitiesSelection.component.ts +++ b/searchPages/searchUtils/entitiesSelection.component.ts @@ -40,7 +40,7 @@ export class EntitiesSelectionComponent { /** TODO change conditions base on PortalType instead of customFilter */ ngOnInit() { - if ((this.customFilter && this.customFilter.queryFieldName == "communityId") || (['explore', 'aggregator', 'eosc', 'faircore4eosc'].includes(this.properties.adminToolsPortalType))) { + if ( (['explore', 'aggregator', 'eosc', 'faircore4eosc', "community"].includes(this.properties.adminToolsPortalType))) { this.subscriptions.push(this.config.portalAsObservable.subscribe(data => { if (data) { let showEntity = {}; @@ -104,8 +104,7 @@ export class EntitiesSelectionComponent { this.disableSelectEmitter.emit(this.entities.length == 1); } })); - } else if ((this.customFilter && this.customFilter.queryFieldName == "community") || - (this.customFilter && (this.customFilter.queryFieldName == "relfunder" || this.customFilter.queryFieldName == "funder")) || + } else if ((this.customFilter && (this.customFilter.queryFieldName == "relfunder" || this.customFilter.queryFieldName == "funder")) || (this.customFilter && this.customFilter.queryFieldName == "relorganizationid") || this.properties.dashboard == "irish") { this.entities.push({label: OpenaireEntities.RESULTS, value: 'result'}); diff --git a/services/adminToolService.module.ts b/services/adminToolService.module.ts index 1aafe365..737d6b86 100644 --- a/services/adminToolService.module.ts +++ b/services/adminToolService.module.ts @@ -1,6 +1,7 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import {HelpContentService} from "./help-content.service"; +import {PluginsService} from "./plugins.service"; @NgModule({ @@ -8,7 +9,7 @@ import {HelpContentService} from "./help-content.service"; CommonModule, ], declarations:[ ], - providers: [HelpContentService], + providers: [HelpContentService, PluginsService], }) diff --git a/services/clear-cache.service.ts b/services/clear-cache.service.ts index d925d5a7..d776554e 100644 --- a/services/clear-cache.service.ts +++ b/services/clear-cache.service.ts @@ -1,5 +1,5 @@ import {Injectable} from "@angular/core"; -import {HttpClient} from "@angular/common/http"; +import {HttpClient, HttpHeaders} from "@angular/common/http"; import {properties} from "../../../environments/environment"; import {CustomOptions} from "./servicesUtils/customOptions.class"; @@ -10,14 +10,33 @@ export class ClearCacheService { constructor(private http: HttpClient) {} - clearCache(message: string = null) { + + clearCache(message: string = null, url:string = null) { if(properties.deleteCacheUrl) { - this.http.get(properties.deleteCacheUrl).subscribe( + this.http.get(properties.deleteCacheUrl + (url?'?url='+url:'')).subscribe( res => console.log((message ? message + ": " : "") + "Cache cleared!"), err => console.log((message ? message + ": " : "") + "Cache could not be cleared ", err) ); } } + clearCacheInRoute(message: string = null, pid:string, route:string = "/") { + let domain = properties.connectPortalUrl; + if(properties.environment == 'production' || properties.environment == 'beta') { + domain = 'https://' + (properties.environment == 'production' ? '' : 'beta.') + pid + '.openaire.eu'; + } + this.http.get(domain + route + '?forceCacheReload=true', + { + headers: new HttpHeaders({ + 'Cache-Control': 'no-cache, no-store, must-revalidate', + 'Pragma': 'no-cache', + 'Expires': '0', + }) + }).subscribe( + res => console.log((message ? message + ": " : "") + "Cache cleared!"), + err => console.log((message ? message + ": " : "") + "Cache could not be cleared ", err) + ); + + } purgeBrowserCache(message: string = null, pid: string) { if(properties.deleteBrowserCacheUrl) { diff --git a/services/customizationService.module.ts b/services/customizationService.module.ts new file mode 100644 index 00000000..a3759734 --- /dev/null +++ b/services/customizationService.module.ts @@ -0,0 +1,17 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {CustomizationService} from "./customization.service"; + + +@NgModule({ + imports: [ + CommonModule + ], + declarations: [], + providers: [ + CustomizationService + ], + exports: [] +}) +export class CustomizationServiceModule { +} diff --git a/services/help-content.service.ts b/services/help-content.service.ts index 27865e6d..701ff4be 100644 --- a/services/help-content.service.ts +++ b/services/help-content.service.ts @@ -280,7 +280,10 @@ export class HelpContentService { return this.http.get(helpContentUrl + properties.adminToolsPortalType + '/' + pid + '/page/'+pageId) .pipe(catchError(this.handleError)); } - + getPageById(pageId:string, helpContentUrl:string) { + return this.http.get(helpContentUrl + 'page/' + pageId) + .pipe(catchError(this.handleError)); + } getCommunityPageByRoute(route:string, helpContentUrl:string, pid: string) { return this.http.get(helpContentUrl + properties.adminToolsPortalType +'/' + pid + '/page/?page_route='+route) .pipe(catchError(this.handleError)); diff --git a/services/plugins.service.ts b/services/plugins.service.ts new file mode 100644 index 00000000..ad6e9bd9 --- /dev/null +++ b/services/plugins.service.ts @@ -0,0 +1,76 @@ +import {Injectable} from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {CustomOptions} from "./servicesUtils/customOptions.class"; +import {PluginTemplate} from "../utils/entities/adminTool/pluginTemplate"; +import {Plugin} from "../utils/entities/adminTool/plugin"; +import {properties} from "../../../environments/environment"; + +@Injectable() +export class PluginsService { + + constructor(private http: HttpClient) { + } + getPluginTemplates(api: string, pageId) { + return this.http.get>(api + 'pluginTemplates' + (pageId ? '/page/' + pageId : '')) + + } + + savePluginTemplate(pluginTemplate: PluginTemplate, api: string) { + return this.http.post(api + 'pluginTemplate/save', pluginTemplate, CustomOptions.getAuthOptionsWithBody()); + } + + updatePluginTemplateOrder(pluginTemplate: PluginTemplate, api: string, position) { + return this.http.post(api + 'pluginTemplate/save/order/' + position, pluginTemplate, CustomOptions.getAuthOptionsWithBody()); + } + + updatePluginOrder(plugin: Plugin, api: string, position, community) { + return this.http.post(api + 'community/'+community+'/plugin/save/order/' + position, plugin, CustomOptions.getAuthOptionsWithBody()); + } + + savePlugin(plugin, api: string, community) { + return this.http.post(api + 'community/' + community + '/plugin/save', JSON.stringify(plugin), CustomOptions.getAuthOptionsWithBody()); + } + + deletePluginTemplate(id, api: string) { + return this.http.delete(api + 'pluginTemplate/' + id, CustomOptions.getAuthOptionsWithBody()); + } + deletePlugin(id, api: string) { + return this.http.delete(api + 'plugin/' + id, CustomOptions.getAuthOptionsWithBody()); + } + + countPluginTemplatePerPage(api: string, pid: string) { + return this.http.get(api + properties.adminToolsPortalType + '/' + pid + '/pluginTemplate/page/count'); + } + + countPluginTemplatePerPageForAllPortals(api: string) { + return this.http.get(api + '/pluginTemplate/page/count'); + } + + getPluginsByPage(api: string, pid: string, pageId: string) { + return this.http.get>(api + properties.adminToolsPortalType + '/' + pid + '/plugins/page/' + pageId); + } + + getPluginTemplatesByPage(api: string, pid: string, pageId: string) { + return this.http.get>(api + properties.adminToolsPortalType + '/' + pid + '/pluginTemplates/page/' + pageId); + } + getPluginsByPageRoute(api:string, pid:string, route:string){ + let url = api + 'community/' +pid+'/plugins/page/route?route=' + route; + return this.http.get>(/*(properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url) + (properties.forceCacheReload?'&forceReload=true':'')) : */url); + } + getPluginTemplatesByPageRoute(api:string, pid:string, route:string){ + let url = api + 'community/' + pid + '/pluginTemplates/page/route?route=' + route; + return this.http.get>(/*(properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url) + (properties.forceCacheReload?'&forceReload=true':'')) :*/ url); + } + + togglePlugin(id: string, status: boolean, api: string, community) { + return this.http.post(api + 'community/' + community + '/plugin/status/' + id, status, CustomOptions.getAuthOptionsWithBody()); + } + getPluginById(api: string, id: string) { + return this.http.get(api + '/plugin/' + id); + } + + getPluginTemplateById(api: string, id: string) { + return this.http.get(api + '/pluginTemplates/' + id); + } + +} diff --git a/utils/configuration/configuration.service.ts b/utils/configuration/configuration.service.ts index 6d50c4dc..43f804bb 100644 --- a/utils/configuration/configuration.service.ts +++ b/utils/configuration/configuration.service.ts @@ -5,6 +5,7 @@ import {EnvProperties} from "../properties/env-properties"; import {Portal} from "../entities/adminTool/portal"; import {Page} from "../entities/adminTool/page"; import {AdvancedAsyncSubject} from "../AdvancedAsyncSubject"; +import {properties} from "../../../../environments/environment"; @Injectable({providedIn: 'root'}) export class ConfigurationService { @@ -36,7 +37,7 @@ export class ConfigurationService { if (pid == null || this.portal?.getValue()?.static) return; let url = properties.adminToolsAPIURL + "/" + properties.adminToolsPortalType + "/" + pid + "/full"; this.promise = new Promise(resolve => { - this.sub = this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url).subscribe( + this.sub = this.http.get(/*(properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url) + (properties.forceCacheReload?'&forceReload=true':'')) :*/ url).subscribe( (portal: Portal) => { this.portal.next(portal); resolve(); diff --git a/utils/entities/adminTool/plugin.ts b/utils/entities/adminTool/plugin.ts new file mode 100644 index 00000000..3ee14ddb --- /dev/null +++ b/utils/entities/adminTool/plugin.ts @@ -0,0 +1,31 @@ +import {PluginTemplate} from "./pluginTemplate"; + +export class Plugin { + _id: string; + templateCode: string; + templateId: string; + page: string; + pid:string; + placement: string; + order: number; + active:boolean; + custom:boolean = false; + object:any; + settingsValues:Map = new Map(); + + constructor(page, pid, template:PluginTemplate) { + this.page = page; + this.pid = pid; + this.templateCode = template.code; + this.templateId = template._id; + this.placement = template.placement; + this.active = template.defaultIsActive; + this.object = template.object && Object.keys(template.object).length > 0 ? Object.assign(template.object) : null; + this.order = template.order; + if (template.settings) { + for (let attr of Object.keys(template.settings)) { + this.settingsValues.set(attr, template.settings[attr].value) + } + } + } +} diff --git a/utils/entities/adminTool/pluginTemplate.ts b/utils/entities/adminTool/pluginTemplate.ts new file mode 100644 index 00000000..c17d1573 --- /dev/null +++ b/utils/entities/adminTool/pluginTemplate.ts @@ -0,0 +1,19 @@ + + +export class PluginTemplate{ + _id: string; + name: string; + code: string; + description: string; + image: string; + page: string; + custom:boolean = false; + plan: "starter" | "extended"; + portalSpecific:string[]; + defaultIsActive:boolean = false; + order:number; + placement: string; + portalType: string; + settings: {}; + object:any; +} diff --git a/utils/entities/contentProvider.ts b/utils/entities/contentProvider.ts index 2e7ea4cb..34c76264 100644 --- a/utils/entities/contentProvider.ts +++ b/utils/entities/contentProvider.ts @@ -5,6 +5,9 @@ export class ContentProvider { name: string; officialname: string; selectioncriteria: SelectionCriteria; + deposit: boolean; + enabled:boolean; + message: string; } export class SelectionCriteria { diff --git a/utils/fetchEntitiesClasses/fetchResearchResults.class.ts b/utils/fetchEntitiesClasses/fetchResearchResults.class.ts index ce05a800..82c9732f 100644 --- a/utils/fetchEntitiesClasses/fetchResearchResults.class.ts +++ b/utils/fetchEntitiesClasses/fetchResearchResults.class.ts @@ -86,7 +86,7 @@ export class FetchResearchResults { public getAllResultsForCommunity(resultType:string, communityId: string, page: number, size: number, properties:EnvProperties, contextId = null) { this.searchUtils.status = this.errorCodes.LOADING; - this.subscriptions.push(this._searchResearchResultsService.advancedSearchResults(resultType, "", page, size, "resultdateofacceptance,descending", properties, "&type=results&fq=communityid=" + communityId +(contextId?'&fq=categoryid=' + encodeURIComponent(contextId):'')).subscribe( + this.subscriptions.push(this._searchResearchResultsService.advancedSearchResults(resultType, null, page, size, null, properties, "&type=results&fq=communityid=" + communityId +(contextId?'&fq=categoryid=' + encodeURIComponent(contextId):'')).subscribe( data => { this.searchUtils.totalResults = data[0]; this.allResults = data[1]; diff --git a/utils/helper/helper.service.ts b/utils/helper/helper.service.ts index f263aed1..65eb8159 100644 --- a/utils/helper/helper.service.ts +++ b/utils/helper/helper.service.ts @@ -4,6 +4,7 @@ import {HttpClient} from "@angular/common/http"; import {EnvProperties} from '../properties/env-properties'; import {of} from "rxjs"; +import {properties} from "../../../../environments/environment"; @Injectable() export class HelperService { @@ -25,7 +26,7 @@ export class HelperService { } } - return this.http.get((properties.useLongCache)? (properties.cacheUrl+encodeURIComponent(url)): url); + return this.http.get(/*(properties.useLongCache)? (properties.cacheUrl+encodeURIComponent(url)+ (properties.forceCacheReload?'&forceReload=true':'')):*/ url); //.map(res => res.json()); } @@ -42,7 +43,7 @@ export class HelperService { let url = properties.adminToolsAPIURL; url += '/' + portalType + '/' + portal + '/pagehelpcontent/grouped?active=true&page=' + ((page_route.indexOf("/"+portal+"/")!=-1 ) ? ("/" + page_route.split("/"+portal+"/")[1]) : page_route); - return this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url); + return this.http.get(/*(properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)+ (properties.forceCacheReload?'&forceReload=true':'')) :*/ url); }else { return of(null); } @@ -60,7 +61,7 @@ export class HelperService { let url = properties.adminToolsAPIURL; url += '/'+properties.adminToolsPortalType+'/' + communityId + '/divhelpcontent/grouped?active=true&page='+ ((page_route.indexOf("/"+communityId+"/")!=-1 ) ? ("/" + page_route.split("/"+communityId+"/")[1]) : page_route); - return this.http.get((properties.useLongCache)? (properties.cacheUrl+encodeURIComponent(url)): url); + return this.http.get((properties.useLongCache)? (properties.cacheUrl+encodeURIComponent(url)+ (properties.forceCacheReload?'&forceReload=true':'')): url); }else { return of(null); } diff --git a/utils/isPageEnabled/isPageEnabled.component.ts b/utils/isPageEnabled/isPageEnabled.component.ts new file mode 100644 index 00000000..6c9c083a --- /dev/null +++ b/utils/isPageEnabled/isPageEnabled.component.ts @@ -0,0 +1,60 @@ +import {properties} from "src/environments/environment"; +import {Component, Input, OnDestroy, OnInit} from "@angular/core"; +import {EnvProperties} from "../properties/env-properties"; +import {CommunityInfo} from "../../connect/community/communityInfo"; +import {ActivatedRoute, Router} from "@angular/router"; +import {CommunityService} from "../../connect/community/community.service"; +import {ConfigurationService} from "../configuration/configuration.service"; +import {Subscription} from "rxjs"; + +@Component({ + selector: '[page-enabled]', + template: ` + + + + + ` +}) +export class IsPageEnabledComponent implements OnInit, OnDestroy { + @Input() pageRoute:string; + public properties: EnvProperties = properties; + pageEnabled = false; + + public community: CommunityInfo; + loading; + private subs: any[] = []; + + constructor(private route: ActivatedRoute, + private router: Router, + private communityService: CommunityService, + private configurationService: ConfigurationService) { + } + + + ngOnInit() { + this.subs.push(this.communityService.getCommunityAsObservable().subscribe( community => { + this.community = community; + this.getPageStatus(); + })); + } + + ngOnDestroy() { + this.subs.forEach(sub => { + if (sub instanceof Subscription) { + sub.unsubscribe(); + } + }) + } + + + + + private getPageStatus() { + this.configurationService.isPageEnabled(this.properties, this.community.communityId, '/' + this.pageRoute).subscribe((page) => { + this.pageEnabled = page; + }) + } + + +} diff --git a/utils/isPageEnabled/isPageEnabled.module.ts b/utils/isPageEnabled/isPageEnabled.module.ts new file mode 100644 index 00000000..574c7b9d --- /dev/null +++ b/utils/isPageEnabled/isPageEnabled.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {RouterModule} from "@angular/router"; +import {IsPageEnabledComponent} from "./isPageEnabled.component"; + +@NgModule({ + declarations: [IsPageEnabledComponent], + imports: [ + CommonModule, RouterModule + ], + exports:[IsPageEnabledComponent], + providers:[] +}) +export class IsPageEnabledModule { +} diff --git a/utils/pagingFormatterNoLoad.component.ts b/utils/pagingFormatterNoLoad.component.ts index 77cd5793..4cc6d8d4 100644 --- a/utils/pagingFormatterNoLoad.component.ts +++ b/utils/pagingFormatterNoLoad.component.ts @@ -1,3 +1,4 @@ + import {Component, Input, Output, EventEmitter} from '@angular/core'; import{EnvProperties} from './properties/env-properties'; import {properties} from "../../../environments/environment"; diff --git a/utils/properties/env-properties.ts b/utils/properties/env-properties.ts index f740381d..6f3e2864 100644 --- a/utils/properties/env-properties.ts +++ b/utils/properties/env-properties.ts @@ -156,6 +156,9 @@ export interface EnvProperties { zenodoDumpUrl?:string; openOrgsUrl?:string; orcidDiscoverLinksPage?:string; + + //connect dashboards + forceCacheReload?:boolean; } export function checkPropertyValues(properties:EnvProperties){ diff --git a/utils/properties/searchFields.base.ts b/utils/properties/searchFields.base.ts index a029a42e..4d25b6ec 100644 --- a/utils/properties/searchFields.base.ts +++ b/utils/properties/searchFields.base.ts @@ -32,7 +32,7 @@ export class SearchFieldsBase { ]; public RESULT_ADVANCED_FIELDS: string[] = ["q", "resulttitle", "resultauthor", "authorid", "resultdescription", "resultsubject", "eoscifguidelines", "resultpublisher", - "resultbestaccessright", "community", "collectedfromdatasourceid", "resulthostingdatasourceid", "resultdateofacceptance", + "resultbestaccessright", "community","conceptname", "collectedfromdatasourceid", "resulthostingdatasourceid", "resultdateofacceptance", "relfunder", "relfundinglevel0_id", "relfundinglevel1_id", "relfundinglevel2_id", "resultlanguagename", "relorganizationid", "pid", "relprojectid", "instancetypename", "fos", "sdg"]; @@ -142,6 +142,14 @@ export class SearchFieldsBase { equalityOperator: " exact ", filterType: "checkbox" }, + ["conceptname"]: { + name: "Subcommunity", + type: "keyword", + param: "conceptname", + operator: "sc", + equalityOperator: " exact ", + filterType: "checkbox" + }, ["relproject"]: { name: "Project", type: "refine",