diff --git a/dashboard/users/role-users/role-users.component.ts b/dashboard/users/role-users/role-users.component.ts
index 6ce7517b..bf02493e 100644
--- a/dashboard/users/role-users/role-users.component.ts
+++ b/dashboard/users/role-users/role-users.component.ts
@@ -256,9 +256,14 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
NotificationHandler.rise('Group has been successfully created');
this.updateLists();
}, error => {
- NotificationHandler.rise('An error has occurred. Please try again later', 'danger');
- this.loadActive = false;
- this.loadPending = false;
+ if(error.status === 409) {
+ NotificationHandler.rise('Group already exists. You can try to invite a ' + this.role + ' instead.', 'warning');
+ this.updateLists();
+ } else {
+ NotificationHandler.rise('An error has occurred. Please try again later', 'danger');
+ this.loadActive = false;
+ this.loadPending = false;
+ }
});
}
diff --git a/login/adminLoginGuard.guard.ts b/login/adminLoginGuard.guard.ts
index 6c01ac49..5c5fb990 100644
--- a/login/adminLoginGuard.guard.ts
+++ b/login/adminLoginGuard.guard.ts
@@ -28,7 +28,9 @@ export class AdminLoginGuard implements CanActivate, CanActivateChild {
}
return Session.isPortalAdministrator(user) ||
(data.monitorCurator && Session.isMonitorCurator(user)) ||
- (data.communityCurator && Session.isCommunityCurator(user))
+ (data.communityCurator && Session.isCommunityCurator(user)) ||
+ (data.monitorManager && Session.isKindOfMonitorManager(user)) ||
+ (data.communityManager && Session.isKindOfCommunityManager(user))
}),tap(isAdmin => {
if(!isAdmin) {
this.router.navigate(['/user-info'], {
diff --git a/monitor/indicators/indicators.component.ts b/monitor/indicators/indicators.component.ts
index b5cd56a2..eb9e0fd5 100644
--- a/monitor/indicators/indicators.component.ts
+++ b/monitor/indicators/indicators.component.ts
@@ -3,8 +3,9 @@ import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {ActivatedRoute, Router} from "@angular/router";
import {HelperService} from "../../utils/helper/helper.service";
-import {StakeholderService} from "../services/stakeholder.service";
-import {ConfigurationService} from "../../utils/configuration/configuration.service";
+import {Meta, Title} from "@angular/platform-browser";
+import {SEOService} from "../../sharedComponents/SEO/SEO.service";
+import {ResourcesService} from "../services/resources.service";
@Component({
selector: 'indicators-page',
@@ -12,28 +13,43 @@ import {ConfigurationService} from "../../utils/configuration/configuration.serv
})
export class IndicatorsComponent implements OnInit, OnDestroy {
private subscriptions: any[] = [];
+ public types = ResourcesService.types;
public properties = properties;
public pageContents;
constructor(private helper: HelperService,
- private configurationService: ConfigurationService,
+ private resourcesService: ResourcesService,
private router: Router,
- private stakeholderService: StakeholderService,
+ private meta: Meta,
+ private title: Title,
+ private seoService: SEOService,
private route: ActivatedRoute) {
}
ngOnInit() {
this.subscriptions.push(this.route.params.subscribe(params => {
- if(params['stakeholder']) {
- this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
- this.getPageContents(stakeholder.type);
- }));
- } else if(params['type']){
- this.getPageContents(params['type']);
+ if(params['type']){
+ let type = this.types.find(type => type.value === params['type']);
+ if(type) {
+ this.getPageContents(type.value);
+ const description = "Monitor | Indicators " + type.label;
+ const title = "Monitor | Indicators " + type.label;
+ this.metaTags(title, description);
+ }
}
}))
}
+ metaTags(title, description) {
+ const url = properties.domain + properties.baseLink + this.router.url;
+ this.seoService.createLinkForCanonicalURL(url, false);
+ this.meta.updateTag({content: url}, "property='og:url'");
+ this.meta.updateTag({content: description}, "name='description'");
+ this.meta.updateTag({content: description}, "property='og:description'");
+ this.meta.updateTag({content: title}, "property='og:title'");
+ this.title.setTitle(title);
+ }
+
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
@@ -43,8 +59,8 @@ export class IndicatorsComponent implements OnInit, OnDestroy {
}
public getPageContents(type: string) {
- this.subscriptions.push(this.configurationService.isPageEnabled('monitor', '/indicators/' + type, 'monitor').subscribe(isEnabled => {
- if(isEnabled) {
+ this.subscriptions.push(this.resourcesService.isPagesEnabled().subscribe(status => {
+ if(status[0]) {
this.subscriptions.push(this.helper.getPageHelpContents(this.properties, 'monitor', '/indicators/' + type, 'monitor').subscribe(contents => {
this.pageContents = contents;
}));
diff --git a/monitor/methodology/methodology.component.ts b/monitor/methodology/methodology.component.ts
new file mode 100644
index 00000000..5a84b1a5
--- /dev/null
+++ b/monitor/methodology/methodology.component.ts
@@ -0,0 +1,465 @@
+import {Component, OnDestroy, OnInit} from "@angular/core";
+import {Subscription} from "rxjs";
+import {Meta, Title} from "@angular/platform-browser";
+import {ActivatedRoute, Router} from "@angular/router";
+import {Stakeholder} from "../entities/stakeholder";
+import {OpenaireEntities} from "../../utils/properties/searchFields";
+import {StakeholderService} from "../services/stakeholder.service";
+import {SEOService} from "../../sharedComponents/SEO/SEO.service";
+import {properties} from "../../../../environments/environment";
+
+@Component({
+ selector: 'methodology',
+ template: `
+
+
+
Terminology and
construction.
+
+
+
+
+ -
+
+
+
- {{openaireEntities.RESULTS}}
+
-
+
There are currently four different types of {{openaireEntities.RESULTS | lowercase}} in the OpenAIRE Research
Graph:
+
+ - {{openaireEntities.PUBLICATIONS}}
+ - {{openaireEntities.DATASETS}}
+ - {{openaireEntities.SOFTWARE}}
+ - {{openaireEntities.OTHER}}.
+
+
+ OpenAIRE deduplicates (merges) different records of {{openaireEntities.RESULTS | lowercase}} and keeps the
metadata of all instances.
+
+
+
+
+
+
- {{openaireEntities.PUBLICATION}}
+ -
+ {{openaireEntities.RESULTS}} intended for human reading (published articles, pre-prints, conference
papers, presentations, technical reports, etc.)
+
+
+
+
+
- {{openaireEntities.DATASET}}
+
-
+
+
Granularity is not defined by OpenAIRE, it reflects the granularity supported by
+ the sources
from which the description of the {{openaireEntities.DATASET | lowercase}} has been collected.
+
+
+
+
+
- {{openaireEntities.SOFTWARE_SINGULAR}}
+ -
+ Source code or software package developed and/or used in a research context
+
+
+
+
+
- {{openaireEntities.OTHER_SINGULAR}}
+ -
+ Anything that does not fall in the previous categories (e.g. workflow, methods, protocols)
+
+
+
+
+ -
+
+ The attributes of entities listed below are either inherited via entries in the harvested metadata records or automatically generated by our inference (text and data mining) algorithms.
+
+
+
+
+
- {{openaireEntities.ORGANIZATION}}
+
-
+
For {{openaireEntities.RESULTS | lowercase}}, this refers to the affiliated organizations of its authors
+ For {{openaireEntities.PROJECTS | lowercase}}: the {{openaireEntities.ORGANIZATIONS | lowercase}} participating in the {{openaireEntities.PROJECT | lowercase}}
+ (i.e. beneficiaries of the grant)
+ The OpenAIRE research graph is in the process of improving the {{openaireEntities.ORGANIZATION | lowercase}} database (disambiguation) with the newly developed OpenOrgs tool.
+
+
+
+
+
+
+
- Funder
+
-
+
Funders that have joined OpenAIRE, i.e. their {{openaireEntities.PROJECT | lowercase}} data have gone through a validation process.
+ You can visit https://explore.openaire.eu/search/find if you would like to explore the {{openaireEntities.RESULTS | lowercase}} and {{openaireEntities.PROJECTS | lowercase}} of all funders in OpenAIRE (the list of funders can be seen under the "Funder" Filter shown on the left side of the page).
+ To join: https://www.openaire.eu/funders-how-to-join-guide
+
+
+
+
+
- Type
+
-
+
The sub-type of a {{openaireEntities.RESULT | lowercase}} (e.g., a {{openaireEntities.PUBLICATION | lowercase}} can be a pre-print, conference proceeding,
+ article,
+ etc.)
+ Resource type mapping:
+ https://api.openaire.eu/vocabularies/dnet:result_typologies
+ (click on the code to see the specific types for each result type)
+
+
+
+
+
+
- Access mode or access rights
+
-
+
The best available (across all instances) access rights of a {{openaireEntities.RESULT | lowercase}}
+ Types: open, restricted, closed, embargo (= closed for a specific period of time, then open)
+ Note: definition of restricted
+ may vary by data source, it may refer to access rights being given to registered users, potentially behind a paywall.
+
+
+
+
+
+
+
+
+
- Context
+ -
+ Related {{openaireEntities.COMMUNITY | lowercase}}, initiative or infrastructure.
+
+
+
+
+
- Journal
+ -
+ The scientific journal an article is published in.
+
+
+
+
+
- Publisher
+ -
+ The publisher of the venue (journal, book, etc.) of a {{openaireEntities.RESULT | lowercase}}.
+
+
+
+
+
- {{openaireEntities.DATASOURCES}}
+
-
+
The different data sources ingested in the OpenAIRE Research Graph.
+ Data Source Types:
+
+ - Repositories
+ - Open Access Publishers & Journals
+ - Aggregators
+ - Entity Registries
+ - Journal Aggregators
+ - CRIS (Current Research Information System)
+
+
+
+
+
+
- Repositories
+ -
+ Information systems where scientists upload the bibliographic metadata and payloads of their
+ {{openaireEntities.RESULTS | lowercase}} (e.g. PDFs of their scientific articles, CSVs of their data, archive with their
+ software), due to obligations from their {{openaireEntities.ORGANIZATIONS | lowercase}}, their funders, or due to community practices
+ (e.g. ArXiv, Europe PMC, Zenodo).
+
+
+
+
+
- Open Access Publishers & Journals
+ -
+ Information systems of open access publishers or relative journals, which offer bibliographic
+ metadata and PDFs of their published articles.
+
+
+
+
+
- Aggregators
+ -
+ Information systems that collect descriptive metadata about {{openaireEntities.RESULTS | lowercase}} from multiple sources
+ in order to enable cross-data source discovery of given {{openaireEntities.RESULTS | lowercase}} (e,g, DataCite,
+ BASE, DOAJ).
+
+
+
+
+
- Entity Registries
+ -
+ Information systems created with the intent of maintaining authoritative registries of given
+ entities in the scholarly communication, such as OpenDOAR for the institutional repositories, re3data
+ for the data repositories, CORDA and other funder databases for {{openaireEntities.PROJECTS | lowercase}} and funding information.
+
+
+
+
+
- CRIS (Current Research Information System)
+ -
+ Information systems adopted by research and academic {{openaireEntities.ORGANIZATIONS | lowercase}} to keep track of their research
+ administration records and relative results; examples of CRIS content are articles or {{openaireEntities.DATASETS | lowercase}} funded
+ by {{openaireEntities.PROJECTS | lowercase}}, their principal investigators, facilities acquired thanks to funding, etc.
+
+
+
+
+ -
+
+ The attributes of entities under this tab are constructed following the methodology described below.
+
+
+
+
+
- Attribute
+ - Definition
+ - Construction
+
+
+
+ Journal Business Models
+
+
+
+
- Fully Open Access (OA)
+
-
+
A journal that publishes only in open access.
+
+
-
+
We construct the list of fully OA journals using Unpaywall data.
+ In brief, a journal is fully OA if
+
+ - It is in the Directory of Open Access Journals (DOAJ)
+ - It has a known (curated list) fully OA Publisher.
+ - It only publishes OA articles.
+
+ More information
+
+
+
+
+
- Subscription
+
-
+
A journal that charges for access to its articles.
+
+
-
+
Journals without any open access articles.
+
+
+
+
+
- Hybrid
+
-
+
A subscription journal where some of its articles are open access.
+
+
-
+
Journals with open access articles that are not fully OA journals are hybrid.
+
+
+
+
+
- Transformative
+
-
+
"A Transformative Journal is a subscription/hybrid journal that is actively committed to transitioning to a fully Open Access journal.
+ In addition, a Transformative Journal must:
+
+ - gradually increase the share of Open Access content; and
+ - offset subscription income from payments for publishing services (to avoid double payments)."
+
+ Source:
+ https://www.coalition-s.org/transformative-journals-faq/
+
+
-
+
Transformative Journals are identified by ISSN matching with the publicly available Transformative Journals data (https://journalcheckertool.org/transformative-journals/)
+
+
+
+
+ Journal APC Business Models
+
+
+
+
- Diamond OA
+
-
+
A fully OA journal that does not charge article processing charges (APCs).
+
+
-
+
APC information is obtained from DOAJ using DOAJ’s exportable version of the journal metadata (https://doaj.org/docs/public-data-dump/). We used it to determine whether a particular fully OA journal charges APCs.
+
+
+
+
+ Routes to Open Access (OA)
+
+
+
+
- Green OA
+
-
+
An open access scientific publication deposited in a repository
+
+
-
+
As in definition
+
+
+
+
+
- Gold OA
+
-
+
A scientific publication published in a fully OA journal.
+
+
-
+
Fully OA journals are defined above.
+
+
+
+
+
- Hybrid OA
+
-
+
An open access scientific publication published in a hybrid journal with an open license.
+
+
-
+
Hybrid journals are defined above.
+ At this point we consider only CC licenses “open”, we are currently working on cleaning non-CC licenses as well to identify other open ones.
+ In principle, this means that we may be underestimating the number of hybrid OA articles and overestimating the number of bronze.
+
+
+
+
+
- Bronze OA
+
-
+
An open access scientific publication published in a hybrid journal without an open license.
+
+
-
+
+
+
+
+
+ Miscellaneous
+
+
+
+
- Downloads
+
-
+
The number of downloads of a publication’s full text in a specific time frame, from a given set of data sources.
+
+
-
+
Data for downloads is taken from OpenAIRE’s Usage Counts service that harvests it from a set of repositories. The time range of available downloads varies for each repository.
+
+ More information
+
+
+
+
+
+
+
+
+
+
+
+ Inclusion, transparency,
quality, state of the art
technology.
+
+
+
Our methodological approach is based on the following operational quality criteria:
+
+ - Openness and transparency: Methodological assumptions are openly and clearly presented.
+ - Coverage and accuracy: As detailed in graph.openaire.eu
+ multiple data sources are ingested in the OpenAIRE research graph for coverage to the fullest extent possible, in order to provide meaningful indicators.
+ - Clarity and replicability: We describe our construction methodology in detail, so that
+ it can be verified and used by the scholarly communication community to create ongoing updates to our proposed statistics and indicators.
+ - Readiness and timeliness: The methodology is built around well-established open databases
+ and already tested knowledge extraction technologies - natural language processing (NLP)/machine-learning (ML) - using operational
+ workflows in OpenAIRE to warrant timely results.
+ - Trust and robustness: Our methodology also strives to be reliable, robust, and aligned
+ to other assessment methods so that it can be operationalized, used and reused, in conjunction with other assessment methods.
+
+
The text above is modified from
this report (DOI: 10.2777/268348).
+
+
+
Step-by-step
+
+
+
+
+ `
+})
+export class MethodologyComponent implements OnInit, OnDestroy {
+ public stakeholder: Stakeholder;
+ public tab: 'entities' | 'attributes' = 'entities';
+ private subscriptions: any[] = [];
+ public openaireEntities = OpenaireEntities;
+
+ constructor(private stakeholderService: StakeholderService,
+ private seoService: SEOService,
+ private _meta: Meta,
+ private _router: Router,
+ private route: ActivatedRoute,
+ private _title: Title) {
+ }
+
+ ngOnInit() {
+ this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
+ this.stakeholder = stakeholder;
+ if (this.stakeholder) {
+ /* Metadata */
+ const url = properties.domain + properties.baseLink + this._router.url;
+ this.seoService.createLinkForCanonicalURL(url, false);
+ this._meta.updateTag({content: url}, "property='og:url'");
+ const description = "Methodology | " + this.stakeholder.name;
+ const title = "Methodology | " + this.stakeholder.name;
+ this._meta.updateTag({content: description}, "name='description'");
+ this._meta.updateTag({content: description}, "property='og:description'");
+ this._meta.updateTag({content: title}, "property='og:title'");
+ this._title.setTitle(title);
+ }
+ }));
+ }
+
+ ngOnDestroy() {
+ this.subscriptions.forEach(subscription => {
+ if (subscription instanceof Subscription) {
+ subscription.unsubscribe();
+ }
+ });
+ }
+}
diff --git a/monitor/methodology/methodology.module.ts b/monitor/methodology/methodology.module.ts
new file mode 100644
index 00000000..f47f116d
--- /dev/null
+++ b/monitor/methodology/methodology.module.ts
@@ -0,0 +1,28 @@
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {MethodologyComponent} from "./methodology.component";
+import {RouterModule} from "@angular/router";
+import {PreviousRouteRecorder} from "../../utils/piwik/previousRouteRecorder.guard";
+import {PageContentModule} from "../../dashboard/sharedComponents/page-content/page-content.module";
+import {HowModule} from "../../monitor/how/how.module";
+import {TabsModule} from "../../utils/tabs/tabs.module";
+import {IconsModule} from "../../utils/icons/icons.module";
+import {IconsService} from "../../utils/icons/icons.service";
+import {graph} from "../../utils/icons/icons";
+
+@NgModule({
+ declarations: [MethodologyComponent],
+ imports: [CommonModule, RouterModule.forChild([
+ {
+ path: '',
+ component: MethodologyComponent,
+ canDeactivate: [PreviousRouteRecorder]
+ },
+ ]), PageContentModule, HowModule, TabsModule, IconsModule],
+ exports: [MethodologyComponent]
+})
+export class MethodologyModule {
+ constructor(private iconsService: IconsService) {
+ this.iconsService.registerIcons([graph]);
+ }
+}
diff --git a/monitor/services/resources.service.ts b/monitor/services/resources.service.ts
new file mode 100644
index 00000000..d51b9997
--- /dev/null
+++ b/monitor/services/resources.service.ts
@@ -0,0 +1,117 @@
+import {Injectable} from "@angular/core";
+import {MenuItem, RootMenuItem} from "../../sharedComponents/menu";
+import {Option} from "../../sharedComponents/input/input.component";
+import {StakeholderEntities} from "../entities/stakeholder";
+import {from, Subscription} from "rxjs";
+import {HttpClient} from "@angular/common/http";
+import {properties} from "../../../../environments/environment";
+import {Page} from "../../utils/entities/adminTool/page";
+import {map} from "rxjs/operators";
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ResourcesService {
+
+ private subscription: Subscription;
+ private routes = ResourcesService.types.map(type => '/indicators/' + type.value);
+
+ public static readonly types: Option[] = [
+ {value: 'funder', label: StakeholderEntities.FUNDERS},
+ {value: 'ri', label: StakeholderEntities.RIS},
+ {value: 'project', label: StakeholderEntities.PROJECTS},
+ {value: 'organization', label: StakeholderEntities.ORGANIZATIONS}
+ ];
+
+ constructor(private http: HttpClient) {
+ }
+
+ private async getResourcesItemsAsync(prefix = '', portal: string = null): Promise