From 456b2d5811c7f9cd218ed5f6c22712f03d032f50 Mon Sep 17 00:00:00 2001 From: "k.triantafyllou" Date: Tue, 5 May 2020 10:37:36 +0000 Subject: [PATCH] [Library | Trunk]: Add openaire metrics. git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-services-library/trunk/ng-openaire-library/src/app@58598 d315682c-612b-4755-9ff5-7f18f6832af3 --- .../annotation/annotation.component.ts | 14 +- .../dataProvider/dataProvider.component.html | 14 + .../dataProvider/dataProvider.component.ts | 4 + .../dataProvider/dataProvider.module.ts | 2 +- .../landing-utils/metrics.component.ts | 170 ------------ landingPages/landing-utils/metrics.module.ts | 26 -- .../metrics/metrics.component.css | 91 +++++++ .../metrics/metrics.component.ts | 255 ++++++++++++++++++ .../landing-utils/metrics/metrics.module.ts | 28 ++ landingPages/project/project.component.html | 27 +- landingPages/project/project.component.ts | 4 + landingPages/project/project.module.ts | 5 +- .../result/resultLanding.component.html | 239 +--------------- .../result/resultLanding.component.ts | 4 + landingPages/result/resultLanding.module.ts | 2 +- utils/click/click-outside-or-esc.directive.ts | 24 +- utils/iframe.component.ts | 19 +- 17 files changed, 470 insertions(+), 458 deletions(-) delete mode 100644 landingPages/landing-utils/metrics.component.ts delete mode 100644 landingPages/landing-utils/metrics.module.ts create mode 100644 landingPages/landing-utils/metrics/metrics.component.css create mode 100644 landingPages/landing-utils/metrics/metrics.component.ts create mode 100644 landingPages/landing-utils/metrics/metrics.module.ts diff --git a/landingPages/annotation/annotation.component.ts b/landingPages/annotation/annotation.component.ts index 54984989..5b9685d0 100644 --- a/landingPages/annotation/annotation.component.ts +++ b/landingPages/annotation/annotation.component.ts @@ -93,10 +93,20 @@ export class AnnotationComponent implements OnInit, OnDestroy { id = this.landingInfo.deletedByInferenceIds[0]; this.url = this.url.replace(this.id, id); } - this.pid = this.url; + if (this.landingInfo.identifiers && this.landingInfo.identifiers.size > 0) { + if (this.landingInfo.identifiers.get('doi')) { + this.pid = this.landingInfo.identifiers.get('doi')[0]; + } else { + const key: string = this.landingInfo.identifiers.keys().next().value; + if (key) { + this.pid = this.landingInfo.identifiers.get(key)[0]; + } + } + } else { + this.pid = id; + } this.annotationService.getAllAnnotations(this.properties, this.url).subscribe(annotations => { this.annotations = annotations; - console.log(this.annotations); }); } } diff --git a/landingPages/dataProvider/dataProvider.component.html b/landingPages/dataProvider/dataProvider.component.html index 4fee0e9d..c0582e3a 100644 --- a/landingPages/dataProvider/dataProvider.component.html +++ b/landingPages/dataProvider/dataProvider.component.html @@ -582,6 +582,20 @@
Share - Bookmark
+ +
+
Metrics
+
+
+
+ + +
+
+
diff --git a/landingPages/dataProvider/dataProvider.component.ts b/landingPages/dataProvider/dataProvider.component.ts index 98c8194b..2fdb8766 100644 --- a/landingPages/dataProvider/dataProvider.component.ts +++ b/landingPages/dataProvider/dataProvider.component.ts @@ -600,6 +600,10 @@ export class DataProviderComponent { this.totalDownloads = $event.totalDownloads; this.pageViews = $event.pageViews; } + + public get hasMetrics(): boolean { + return !(this.totalViews && this.totalDownloads && this.pageViews) || this.totalViews > 0 || this.totalDownloads > 0||this.pageViews > 0; + } public openStatistics() { this.statsClicked = true; diff --git a/landingPages/dataProvider/dataProvider.module.ts b/landingPages/dataProvider/dataProvider.module.ts index 7d891051..82fc2e70 100644 --- a/landingPages/dataProvider/dataProvider.module.ts +++ b/landingPages/dataProvider/dataProvider.module.ts @@ -7,7 +7,7 @@ import {IFrameModule} from '../../utils/iframe.module'; import {ErrorMessagesModule} from '../../utils/errorMessages.module'; // import { ResultLandingModule } from '../resultLanding.module'; import {TabResultModule } from '../../searchPages/searchUtils/tabResult.module'; -import {MetricsModule} from '../landing-utils/metrics.module'; +import {MetricsModule} from '../landing-utils/metrics/metrics.module'; import {LandingModule} from '../landing-utils/landing.module'; import {PagingModule} from '../../utils/paging.module'; diff --git a/landingPages/landing-utils/metrics.component.ts b/landingPages/landing-utils/metrics.component.ts deleted file mode 100644 index f554cfbb..00000000 --- a/landingPages/landing-utils/metrics.component.ts +++ /dev/null @@ -1,170 +0,0 @@ -import {Component, Input, Output, EventEmitter} from '@angular/core'; -import {Metrics} from '../../utils/entities/metrics'; -import {MetricsService } from '../../services/metrics.service'; -import {ErrorCodes} from '../../utils/properties/errorCodes'; - -import { Subscription } from 'rxjs'; -import{EnvProperties} from '../../utils/properties/env-properties'; - -@Component({ - selector: 'metrics', - template: ` -
- - -
- No metrics available -
-
-
Project metrics are derived from aggregating individual research results metrics.
-
-
-
{{pageViews | number}}
-
views in OpenAIRE
-
-
-
-
-
{{metrics.totalViews | number}} - - ( {{metrics.totalOpenaireViews | number}} from OpenAIRE ) -
-
views in local repository
-
-
-
-
-
{{metrics.totalDownloads | number}} - - ( {{metrics.totalOpenaireDownloads | number}} from OpenAIRE ) -
-
downloads in local repository
-
-
- -
- -

The information is available from the following content providers:

- - - - - - - - - - - - - - - -
FromNumber Of ViewsNumber Of Downloads
- - {{metrics.infos.get(key).name}} - - - {{metrics.infos.get(key).numOfViews | number}} - - ( {{metrics.infos.get(key).openaireViews | number}} from OpenAIRE ) - - - {{metrics.infos.get(key).numOfDownloads | number}} - - ( {{metrics.infos.get(key).openaireDownloads | number}} from OpenAIRE ) - -
-
-
-
-
Metrics
-
- {{metrics.pageViews | number}} views in OpenAIRE -
-
- {{metrics.totalViews | number}} - - ( {{metrics.totalOpenaireViews | number}} from OpenAIRE ) - - views in local repository -
-
- {{metrics.totalDownloads | number}} - - ( {{metrics.totalOpenaireDownloads | number}} from OpenAIRE ) - downloads in local repository -
-
-
- ` - }) - -export class MetricsComponent { - @Output() metricsResults = new EventEmitter(); - @Input() id: string; - @Input() entityType: string; - @Input() entity: string; - //@Input() name: string = ""; - @Input() pageViews: number = 0; - @Input() properties:EnvProperties; - @Input() shortView:boolean = false; - - public metrics: Metrics; - public errorCodes:ErrorCodes; - private sub: Subscription; - - public status: number; - - constructor (private _metricsService: MetricsService) {} - - ngOnInit() { - this.errorCodes = new ErrorCodes(); - this.status = this.errorCodes.LOADING; - this.getMetrics(); - } - - ngOnDestroy() { - this.sub.unsubscribe(); - } - - private getMetrics() { - //if(this.id == undefined || this.id == "") { - // console.log("supplied id in metrics is not acceptable"); - //} - //if(this.type == undefined || this.type == "") { - // console.log("supplied id in metrics is not acceptable"); - //} - - this.sub = this._metricsService.getMetrics(this.id, this.entityType, this.properties).subscribe( - data => { - this.metrics = data; - this.status = this.errorCodes.DONE; - this.metricsResults.emit({ - totalViews: this.metrics.totalViews, - totalDownloads: this.metrics.totalDownloads, - pageViews: this.metrics.pageViews - }); - }, - err => { - console.log(err); - if(err.status == '404') { - this.status = this.errorCodes.NOT_FOUND; - } else if(err.status == '500') { - this.status = this.errorCodes.ERROR; - } else { - this.status = this.errorCodes.NOT_AVAILABLE; - } - this.metricsResults.emit({ - totalViews: 0, - totalDownloads: 0 - }); - } - ); - } - - public getKeys( map) { - return Array.from(map.keys()); - } -} diff --git a/landingPages/landing-utils/metrics.module.ts b/landingPages/landing-utils/metrics.module.ts deleted file mode 100644 index 3fb241b4..00000000 --- a/landingPages/landing-utils/metrics.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* This module contains all common components for all landing pages */ - -import { NgModule} from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - - import {MetricsComponent} from './metrics.component'; - import { MetricsService } from '../../services/metrics.service'; - - import {ErrorMessagesModule} from '../../utils/errorMessages.module'; - -@NgModule({ - imports: [ - CommonModule, FormsModule, ErrorMessagesModule - ], - declarations: [ - MetricsComponent - ], - providers:[ - MetricsService - ], - exports: [ - MetricsComponent - ] -}) -export class MetricsModule { } diff --git a/landingPages/landing-utils/metrics/metrics.component.css b/landingPages/landing-utils/metrics/metrics.component.css new file mode 100644 index 00000000..a1f466c8 --- /dev/null +++ b/landingPages/landing-utils/metrics/metrics.component.css @@ -0,0 +1,91 @@ +.metrics { + position: relative; + display: inline-block; +} + +.metrics .widget { + position: absolute; + left: 50%; + transform: translateX(-85%); + margin-top: 20px; + margin-left: 20px; + width: 350px; + z-index: 1; +} + +.metrics .widget:after { + position: absolute; + left: 80%; + transform: translateX(-65%); + top: -10px; + width: 0; + height: 0; + content: ''; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-bottom: 10px solid #2E2D7A; +} + +.metrics .m-badge .number { + font-size: 18px; + color: #222080; + font-weight: 700; + text-align: center; +} + +.metrics .widget > .body { + box-shadow: 0 3px 6px #00000029; + border-radius: 4px 4px 0 4px; + padding: 10px 18px; + background: #2E2D7A no-repeat padding-box; + color: white; + font-size: 12px; + height: inherit; +} + +.metrics .widget > .body > div { + opacity: 0; + height: inherit; + overflow: hidden; +} + +.metrics .widget > .body .charts { + margin-top: 10px; + opacity: 0; +} + +.metrics .widget > .body .charts .uk-slidenav { + background-color: #bbbbca; + color: #49494f; + padding: 5px 10px; + border-radius: 50%; +} + +.metrics .widget > .footer { + background: #FFFFFF; + box-shadow: 0 3px 6px #00000029; + border-radius: 0 0 4px 4px; + font-size: 11px; + padding: 5px 10px; + color: rgba(126, 126, 126, 0.80); + display: inline-block; + float: right; + position: relative; + z-index: -1; + transform: translateY(-80px); +} + +.metrics .widget .footer > *:first-child { + margin-right: 10px; + line-height: 33px; + vertical-align: middle; +} + +.metrics .widget .number { + font-weight: 700; + font-size: 18px; +} + +.metrics .uk-grid-divider>:not(.uk-first-column)::before { + border-left: 1px solid #ffffff; +} \ No newline at end of file diff --git a/landingPages/landing-utils/metrics/metrics.component.ts b/landingPages/landing-utils/metrics/metrics.component.ts new file mode 100644 index 00000000..d79ff8fb --- /dev/null +++ b/landingPages/landing-utils/metrics/metrics.component.ts @@ -0,0 +1,255 @@ +import {Component, Input, Output, EventEmitter} from '@angular/core'; +import {Metrics} from '../../../utils/entities/metrics'; +import {MetricsService} from '../../../services/metrics.service'; +import {ErrorCodes} from '../../../utils/properties/errorCodes'; + +import {Subscription} from 'rxjs'; +import {EnvProperties} from '../../../utils/properties/env-properties'; +import {animate, state, style, transition, trigger} from "@angular/animations"; + +@Component({ + selector: 'metrics', + styleUrls: ['metrics.component.css'], + template: ` +
+
+ +
{{total | number}}
+
+
+
+
+
+ Project metrics + are derived from aggregating individual research results metrics. + +
+
+
+
{{metrics.totalDownloads | number}}
+
Downloads
+
+
+
{{pageViews | number}}
+
OpenAIRE views
+
+
+
{{metrics.totalViews | number}}
+
Total views
+
+
+
+
    +
  • + + +
  • +
  • + + +
  • +
+
+ + +
+
+
+
+ +
+
+ `, + animations: [ + trigger('widget', [ + state('-1', style({ + width: '150px', + opacity: 0, + height: '60px', + })), + state('0', style({ + width: '150px', + opacity: 0, + height: '60px', + "margin-top": '-25px' + })), + state('1', style({ + width: '150px', + opacity: 1, + height: '60px', + })), + state('2', style({ + width: '350px', + height: 'auto', + })), + state('3', style({ + width: '350px', + height: 'auto', + })), + state('4', style({ + width: '350px', + height: 'auto', + })), + transition('0 => 1', [ + animate('300ms ease-out') + ]), + transition('1 => 2', [ + animate('400ms cubic-bezier(.18,.89,.56,1)') + ]) + ]), + trigger('body', [ + state('2', style({ + opacity: 1, + height: 'auto', + })), + state('3', style({ + opacity: 1, + height: 'auto' + })), + state('4', style({ + opacity: 1, + height: 'auto' + })), + transition('* => 2', [ + animate('400ms cubic-bezier(.18,.89,.56,1)') + ]) + ]), + trigger('charts', [ + state('3', style({ + opacity: 1 + })), + state('4', style({ + opacity: 1 + })), + transition('* => 3', [ + animate('800ms ease-out') + ]) + ]), + trigger('footer', [ + state('4', style({ + transform: 'translateY(0)' + })), + transition('3 => 4', [ + animate('800ms ease-out') + ]) + ]) + ] +}) + +export class MetricsComponent { + @Output() metricsResults = new EventEmitter(); + @Input() id: string; + @Input() entityType: string; + @Input() entity: string; + //@Input() name: string = ""; + @Input() pageViews: number = 0; + @Input() properties: EnvProperties; + @Input() shortView: boolean = false; + @Input() open = false; + @Input() viewsFrameUrl: string; + @Input() downloadsFrameUrl: string; + + public metrics: Metrics; + public errorCodes: ErrorCodes; + private sub: Subscription; + private timeouts: any[] = []; + + public status: number; + public state: number = -1; + + constructor(private _metricsService: MetricsService) { + } + + ngOnInit() { + this.errorCodes = new ErrorCodes(); + this.status = this.errorCodes.LOADING; + this.getMetrics(); + } + + ngOnDestroy() { + this.sub.unsubscribe(); + } + + public get total(): number { + return +this.pageViews + +this.metrics.totalViews + +this.metrics.totalDownloads; + } + + private getMetrics() { + this.sub = this._metricsService.getMetrics(this.id, this.entityType, this.properties).subscribe( + data => { + this.metrics = data; + this.status = this.errorCodes.DONE; + this.metricsResults.emit({ + totalViews: this.metrics.totalViews, + totalDownloads: this.metrics.totalDownloads, + pageViews: this.metrics.pageViews + }); + }, + err => { + console.log(err); + if (err.status == '404') { + this.status = this.errorCodes.NOT_FOUND; + } else if (err.status == '500') { + this.status = this.errorCodes.ERROR; + } else { + this.status = this.errorCodes.NOT_AVAILABLE; + } + this.metricsResults.emit({ + totalViews: 0, + totalDownloads: 0 + }); + } + ); + } + + public close(event) { + if(event.value && this.state !== -1) { + this.timeouts.forEach(timeout => { + clearTimeout(timeout); + }); + this.state = -1; + this.timeouts = []; + } + } + + + public toggle(event) { + event.stopPropagation(); + if(this.state !== -1) { + this.timeouts.forEach(timeout => { + clearTimeout(timeout); + }); + this.state = -1; + this.timeouts = []; + } else { + this.state++; + this.timeouts.push(setTimeout(() => { + this.state++; + this.timeouts.push(setTimeout(() => { + this.state++; + this.timeouts.push(setTimeout(() => { + this.state++; + this.timeouts.push(setTimeout(() => { + this.state++; + }, 400)); + }, 800)); + }, 300)); + }, 100)); + } + } + + public getKeys(map) { + return Array.from(map.keys()); + } +} diff --git a/landingPages/landing-utils/metrics/metrics.module.ts b/landingPages/landing-utils/metrics/metrics.module.ts new file mode 100644 index 00000000..9d0441c9 --- /dev/null +++ b/landingPages/landing-utils/metrics/metrics.module.ts @@ -0,0 +1,28 @@ +/* This module contains all common components for all landing pages */ + +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; + +import {MetricsComponent} from './metrics.component'; +import {MetricsService} from '../../../services/metrics.service'; + +import {ErrorMessagesModule} from '../../../utils/errorMessages.module'; +import {IFrameModule} from "../../../utils/iframe.module"; +import {ClickModule} from "../../../utils/click/click.module"; + +@NgModule({ + imports: [ + CommonModule, FormsModule, ErrorMessagesModule, IFrameModule, ClickModule + ], + declarations: [ + MetricsComponent + ], + providers:[ + MetricsService + ], + exports: [ + MetricsComponent + ] +}) +export class MetricsModule { } diff --git a/landingPages/project/project.component.html b/landingPages/project/project.component.html index a2000842..e055ff64 100644 --- a/landingPages/project/project.component.html +++ b/landingPages/project/project.component.html @@ -544,6 +544,20 @@
Share - Bookmark
+ +
+
Metrics
+
+
+
+ + +
+
+
Share project's content
@@ -642,19 +656,6 @@
- - - - - - - - - - - - - diff --git a/landingPages/project/project.component.ts b/landingPages/project/project.component.ts index 0d58b199..d7e96bd8 100644 --- a/landingPages/project/project.component.ts +++ b/landingPages/project/project.component.ts @@ -447,6 +447,10 @@ export class ProjectComponent { this.totalDownloads = $event.totalDownloads; this.pageViews = $event.pageViews; } + + public get hasMetrics(): boolean { + return !(this.totalViews && this.totalDownloads && this.pageViews) || this.totalViews > 0 || this.totalDownloads > 0||this.pageViews > 0; + } public openStatistics() { this.statsClicked = true; diff --git a/landingPages/project/project.module.ts b/landingPages/project/project.module.ts index cd6d792a..696cf7cb 100644 --- a/landingPages/project/project.module.ts +++ b/landingPages/project/project.module.ts @@ -11,7 +11,7 @@ import {HtmlProjectReportService} from "../htmlProjectReport/htmlProjectReport.s import {ReportsServiceModule} from '../../services/reportsService.module'; import {SearchResearchResultsServiceModule} from '../../services/searchResearchResultsService.module'; -import {MetricsModule} from '../landing-utils/metrics.module'; +import {MetricsModule} from '../landing-utils/metrics/metrics.module'; import {LandingModule } from '../landing-utils/landing.module'; import {LandingHeaderModule} from "../landing-utils/landing-header/landing-header.module"; @@ -26,6 +26,7 @@ import {IsRouteEnabled} from '../../error/isRouteEnabled.guard'; import {Schema2jsonldModule} from '../../sharedComponents/schema2jsonld/schema2jsonld.module'; import {SEOServiceModule } from '../../sharedComponents/SEO/SEOService.module'; import {FeedbackModule} from "../feedback/feedback.module"; +import {AltMetricsModule} from "../../utils/altmetrics.module"; @NgModule({ imports: [ @@ -34,7 +35,7 @@ import {FeedbackModule} from "../feedback/feedback.module"; IFrameModule, MetricsModule, ReportsServiceModule, SearchResearchResultsServiceModule, ProjectServiceModule, Schema2jsonldModule, SEOServiceModule, HelperModule, - LandingHeaderModule, MatSelectModule, FeedbackModule + LandingHeaderModule, MatSelectModule, FeedbackModule, AltMetricsModule ], declarations: [ diff --git a/landingPages/result/resultLanding.component.html b/landingPages/result/resultLanding.component.html index 6540acfb..69dddba2 100644 --- a/landingPages/result/resultLanding.component.html +++ b/landingPages/result/resultLanding.component.html @@ -195,232 +195,7 @@ - -
+
Metrics
-
+
-
+
+ + +
diff --git a/landingPages/result/resultLanding.component.ts b/landingPages/result/resultLanding.component.ts index 2834bfff..50af7952 100644 --- a/landingPages/result/resultLanding.component.ts +++ b/landingPages/result/resultLanding.component.ts @@ -334,6 +334,10 @@ export class ResultLandingComponent { this.totalDownloads = $event.totalDownloads; this.pageViews = $event.pageViews; } + + public get hasMetrics(): boolean { + return !(this.totalViews && this.totalDownloads && this.pageViews) || this.totalViews > 0 || this.totalDownloads > 0||this.pageViews > 0; + } public buildCurationTooltip(): string { let tooltipContent: string = "
"; diff --git a/landingPages/result/resultLanding.module.ts b/landingPages/result/resultLanding.module.ts index e6bcc4e7..a218c9d7 100644 --- a/landingPages/result/resultLanding.module.ts +++ b/landingPages/result/resultLanding.module.ts @@ -4,7 +4,7 @@ import {FormsModule} from '@angular/forms'; import {RouterModule} from '@angular/router'; import {SharedModule} from '../../shared/shared.module'; -import {MetricsModule} from '../landing-utils/metrics.module'; +import {MetricsModule} from '../landing-utils/metrics/metrics.module'; import {LandingModule} from '../landing-utils/landing.module'; import {CiteThisModule} from '../landing-utils/citeThis/citeThis.module'; import {IFrameModule} from '../../utils/iframe.module'; diff --git a/utils/click/click-outside-or-esc.directive.ts b/utils/click/click-outside-or-esc.directive.ts index 7127def1..f25830e5 100644 --- a/utils/click/click-outside-or-esc.directive.ts +++ b/utils/click/click-outside-or-esc.directive.ts @@ -61,17 +61,21 @@ export class ClickOutsideOrEsc implements OnInit, OnDestroy { onGlobalClick(event: MouseEvent) { if (event instanceof MouseEvent && this.listening === true) { - if (event.target['id'] != this.targetId) { - this.clickOutside.emit({ - target: (event.target || null), - value: false - }); - } else { - this.clickOutside.emit({ - target: (event.target || null), - value: true - }); + let element: HTMLElement = event.target; + while (element) { + if(element.id === this.targetId) { + this.clickOutside.emit({ + target: (event.target || null), + value: false + }); + return; + } + element = element.parentElement; } + this.clickOutside.emit({ + target: (event.target || null), + value: true + }); } } } diff --git a/utils/iframe.component.ts b/utils/iframe.component.ts index da4559a0..568cc7ec 100644 --- a/utils/iframe.component.ts +++ b/utils/iframe.component.ts @@ -4,19 +4,30 @@ import { SafeResourceUrl, DomSanitizer } from '@angular/platform-browser'; @Component({ selector: 'i-frame', template: ` -
- +
+ +
+
+
- ` }) export class IFrameComponent { public safeUrl: SafeResourceUrl; @Input() url ; + @Input() width: number; + @Input() height: number; + public style: any; + constructor(private sanitizer: DomSanitizer) { } ngOnInit() { this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.url); - //console.info("URL:" + this.safeUrl); + if(this.width && this.height) { + this.style = { + "width.px": this.width, + "height.px": this.height + } + } } }