diff --git a/package.json b/package.json index 6c25054..38e13c9 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,13 @@ "ng": "ng", "start": "ng serve --port 4600 --disable-host-check --host 0.0.0.0", "build": "ng build", - "build-dev": "ng build --configuration=development --source-map --base-href /dashboard/", + "build-dev": "ng build --configuration=development --source-map", "build-beta": "ng build --configuration=beta --base-href /dashboard/ --source-map", "build-prod": "ng build --configuration production --base-href /dashboard/ --source-map", "webpack-bundle-analyzer": "ng build --stats-json && webpack-bundle-analyzer dist/monitor-dashboard/browser/stats.json --host 0.0.0.0", "test": "ng test", "e2e": "ng e2e", - "dev:ssr": "ng run monitor-dashboard:serve-ssr", + "dev:ssr": "ng run monitor-dashboard:serve-ssr --port 4600", "serve:ssr": "node dist/monitor-dashboard/server/main.js", "build:ssr-dev": "npm run build-dev && ng run monitor-dashboard:server:development", "build:ssr-beta": "npm run build-beta && ng run monitor-dashboard:server:beta", @@ -34,6 +34,7 @@ "@angular/platform-server": "^14.2.3", "@angular/router": "^14.2.3", "@nguniversal/express-engine": "^14.2.0", + "axios": "^1.4.0", "clipboard": "^1.5.16", "core-js": "^2.5.4", "express": "^4.15.2", @@ -52,12 +53,12 @@ "@angular/compiler-cli": "^14.2.3", "@angular/language-service": "^14.2.3", "@nguniversal/builders": "^14.2.0", + "@types/ckeditor": "^4.9.10", "@types/compression": "^1.7.0", "@types/express": "^4.17.0", "@types/jasmine": "~3.6.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", - "@types/ckeditor": "^4.9.10", "codelyzer": "^6.0.0", "jasmine-core": "~3.8.0", "jasmine-spec-reporter": "~5.0.0", diff --git a/server.ts b/server.ts index 65e200f..f4ec9c1 100644 --- a/server.ts +++ b/server.ts @@ -1,14 +1,22 @@ import 'zone.js/node'; -import { ngExpressEngine } from '@nguniversal/express-engine'; +import {ngExpressEngine} from '@nguniversal/express-engine'; import * as express from 'express'; import * as compression from 'compression'; -import { join } from 'path'; +import {join} from 'path'; -import { AppServerModule } from './src/main.server'; -import { APP_BASE_HREF } from '@angular/common'; -import { existsSync } from 'fs'; +import {AppServerModule} from './src/main.server'; +import {APP_BASE_HREF} from '@angular/common'; +import {existsSync} from 'fs'; import {REQUEST, RESPONSE} from "./src/app/openaireLibrary/utils/tokens"; +import {properties} from "./src/environments/environment"; +import axios, {AxiosHeaders} from "axios"; +import {Stakeholder} from "./src/app/openaireLibrary/monitor/entities/stakeholder"; +import {CacheIndicators} from "./src/cache-indicators"; +import {Session, User} from "./src/app/openaireLibrary/login/utils/helper.class"; + +var bodyParser = require('body-parser'); +var jsonParser = bodyParser.json(); // The Express app is exported so that it can be used by serverless Functions. export function app() { @@ -16,23 +24,90 @@ export function app() { server.use(compression()); const distFolder = join(process.cwd(), 'dist/monitor-dashboard/browser'); const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index'; - + let cacheIndicators: CacheIndicators = new CacheIndicators(); + // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine) server.engine('html', ngExpressEngine({ bootstrap: AppServerModule, inlineCriticalCss: false })); - + server.set('view engine', 'html'); server.set('views', distFolder); - + + server.use('/cache', function (req, res, next) { + res.header('Access-Control-Allow-Origin', req.headers.origin); + res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); + res.header('Access-Control-Allow-Methods', 'GET, OPTIONS, POST, DELETE'); + res.header('Access-Control-Max-Age', "1800"); + next(); + }); + + server.post('/cache/:alias', jsonParser, async (req, res) => { + await checkPermissions(req, res, (stakeholder, user) => { + if (cacheIndicators.completed(stakeholder._id)) { + res.send({ + id: stakeholder._id, + report: cacheIndicators.createReport(stakeholder._id, cacheIndicators.stakeholderToCacheItems(stakeholder), stakeholder.name, user.email) + }); + } else { + res.status(409).send('There is another active caching process for this stakeholder'); + } + }); + }); + + server.get('/cache/:alias', async (req, res) => { + await checkPermissions(req, res, stakeholder => { + if (cacheIndicators.exists(stakeholder._id)) { + res.send({ + id: stakeholder._id, + report: cacheIndicators.getReport(stakeholder._id) + }); + } else { + res.status(404).send('There is not an active caching process for this stakeholder'); + } + }); + }); + + async function checkPermissions(req, res, access: (stakeholder, user) => void) { + let headers: AxiosHeaders = new AxiosHeaders(); + headers.set('Cookie', req.headers.cookie); + let userinfoRes = (await axios.get(properties.userInfoUrl, { + withCredentials: true, + headers: headers + }).catch(error => { + return error.response; + })); + if (userinfoRes.status === 200) { + let user = new User(userinfoRes.data); + let stakeholderRes = (await axios.get(properties.monitorServiceAPIURL + '/stakeholder/' + encodeURIComponent(req.params.alias), { + withCredentials: true, + headers: headers + }).catch(error => { + return error.response; + })); + if (stakeholderRes.status === 200) { + let stakeholder = stakeholderRes.data; + if (Session.isPortalAdministrator(user) || Session.isCurator(stakeholder.type, user)) { + access(stakeholder, user); + } else { + res.status(403).send('You are forbidden to access this resource'); + } + } else { + res.status(stakeholderRes.status).send(stakeholderRes.statusText); + } + } else { + res.status(userinfoRes.status).send(userinfoRes.data.message); + } + } + // Example Express Rest API endpoints // server.get('/api/**', (req, res) => { }); // Serve static files from /browser server.get('*.*', express.static(distFolder, { maxAge: '1y' })); - + // All regular routes use the Universal engine server.get('*', (req, res) => { res.render(indexHtml, { @@ -51,13 +126,13 @@ export function app() { } ); }); - + return server; } function run() { const port = process.env.PORT || 4000; - + // Start up the Node server const server = app(); server.listen(port, () => { diff --git a/src/app/app.component.html b/src/app/app.component.html index 8b1bf09..848c146 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -17,6 +17,7 @@ +
You are currently in a "Preview" mode. The current view of this dashboard may differ. diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 1399f52..a8b6013 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,4 @@ -import {ChangeDetectorRef, Component, HostListener, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core'; import {ActivatedRoute, Data, NavigationEnd, Params, Router} from '@angular/router'; import {EnvProperties} from './openaireLibrary/utils/properties/env-properties'; import {Role, Session, User} from './openaireLibrary/login/utils/helper.class'; @@ -18,7 +18,6 @@ import {LinksResolver} from "./search/links-resolver"; import {Header} from "./openaireLibrary/sharedComponents/navigationBar.component"; import {properties} from "../environments/environment"; import {ConfigurationService} from "./openaireLibrary/utils/configuration/configuration.service"; -import {Option} from "./openaireLibrary/sharedComponents/input/input.component"; import {StakeholderUtils} from "./utils/indicator-utils"; import {SmoothScroll} from "./openaireLibrary/utils/smooth-scroll"; import {ConnectHelper} from "./openaireLibrary/connect/connectHelper"; @@ -343,7 +342,8 @@ export class AppComponent implements OnInit, OnDestroy { false, [], null, {resultbestaccessright: '"' + encodeURIComponent("Open Access") + '"'}, null, null, null, null) ); - this.resourcesService.setResources(this.menuItems, "/" + this.stakeholder.alias); + this.resourcesService.setResources(this.menuItems, '', this.monitorLink, '_blank'); + this.menuItems.push(new MenuItem("support", "Support", this.monitorLink + '/support/', "", false, [], null, {})); if (this.stakeholder.type === "funder") { this.menuItems.push( new MenuItem("develop", "Develop", @@ -402,12 +402,8 @@ export class AppComponent implements OnInit, OnDestroy { this.monitorLink + '/browse', "", false, [], null, {}, null, null, null, null, "_self") ); this.resourcesService.setResources(this.menuItems, '', this.monitorLink); - let about = new MenuItem("about", "About", "", "", false, [], null, {}); - about.items = [ - new MenuItem("how-it-works", "How it works", this.monitorLink + '/about/how-it-works', "", false, [], null, {}, null, null, null, null, "_self"), - new MenuItem("faqs", "FAQs", this.monitorLink + '/about/faqs',"", false, [], null, {}, null, null, null, null, "_self") - ] - this.menuItems.push(about); + this.menuItems.push(new MenuItem("support", "Support", this.monitorLink + '/support/', "", false, [], null, {}, null, null, null, null, "_self")); + this.menuItems.push(new MenuItem("about", "About", this.monitorLink + '/about/', "", false, [], null, {}, null, null, null, null, "_self")); if (this.hasAdminMenu) { this.adminMenuItems = []; this.backItem = null; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index d83acd9..7a3c945 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -29,9 +29,10 @@ import {LoginGuard} from "./openaireLibrary/login/loginGuard.guard"; import {IconsModule} from "./openaireLibrary/utils/icons/icons.module"; import {IconsService} from "./openaireLibrary/utils/icons/icons.service"; import {incognito} from "./openaireLibrary/utils/icons/icons"; +import {CacheIndicatorsModule} from "./cache-indicators/cache-indicators.module"; @NgModule({ - + imports: [ SharedModule, BrowserAnimationsModule, @@ -44,7 +45,7 @@ import {incognito} from "./openaireLibrary/utils/icons/icons"; CookieLawModule, BrowserModule.withServerTransition({appId: 'serverApp'}), AppRoutingModule, - SideBarModule, Schema2jsonldModule, RoleVerificationModule, LoadingModule, NotificationsSidebarModule, IconsModule + SideBarModule, Schema2jsonldModule, RoleVerificationModule, LoadingModule, NotificationsSidebarModule, IconsModule, CacheIndicatorsModule ], declarations: [AppComponent, OpenaireErrorPageComponent], exports: [AppComponent], diff --git a/src/app/cache-indicators/cache-indicators.component.less b/src/app/cache-indicators/cache-indicators.component.less new file mode 100644 index 0000000..08d5c2a --- /dev/null +++ b/src/app/cache-indicators/cache-indicators.component.less @@ -0,0 +1,9 @@ +@import (reference) "~src/assets/openaire-theme/less/_import-variables.less"; + +.cache-progress { + position: fixed; + bottom: 0; + right: 0; + transform: translate(-50%, -50%); + z-index: @global-z-index; +} diff --git a/src/app/cache-indicators/cache-indicators.component.ts b/src/app/cache-indicators/cache-indicators.component.ts new file mode 100644 index 0000000..9a485ba --- /dev/null +++ b/src/app/cache-indicators/cache-indicators.component.ts @@ -0,0 +1,78 @@ +import {Component, Inject, Input, OnChanges, OnDestroy, OnInit, PLATFORM_ID, SimpleChanges} from "@angular/core"; +import {Report} from "../../cache-indicators"; +import {CacheIndicatorsService} from "../utils/services/cache-indicators.service"; +import {interval, Subject, Subscription} from "rxjs"; +import {map, switchMap, takeUntil} from "rxjs/operators"; + +@Component({ + selector: 'cache-indicators', + template: ` +
+
+
+ +
+
+ `, + styleUrls: ['cache-indicators.component.less'] +}) +export class CacheIndicatorsComponent implements OnInit, OnChanges, OnDestroy { + report: Report; + subscriptions: Subscription[] = []; + interval: number = 10000; + readonly destroy$ = new Subject(); + @Input() alias: string; + + constructor(private cacheIndicatorsService: CacheIndicatorsService, + @Inject(PLATFORM_ID) private platformId) { + } + + ngOnInit() { + this.getReport(); + } + + ngOnChanges(changes: SimpleChanges) { + if(changes.alias) { + this.getReport(); + } + } + + getReport() { + this.clear(); + this.subscriptions.push(this.cacheIndicatorsService.getReport(this.alias).subscribe(report => { + this.getReportInterval(report); + })); + } + + getReportInterval(report: Report) { + if(this.isBrowser && (this.report || !report?.completed)) { + this.report = report; + this.subscriptions.push(interval(this.interval).pipe( + map(() => this.cacheIndicatorsService.getReport(this.alias)), + switchMap(report => report), + takeUntil(this.destroy$)).subscribe(report => { + console.log(this.alias); + this.report = report; + if(this.report.completed) { + this.destroy$.next(); + } + })); + } + } + + clear() { + this.subscriptions.forEach(subscription => { + subscription.unsubscribe(); + }) + this.report = null; + } + + + get isBrowser() { + return this.platformId === 'browser'; + } + + ngOnDestroy() { + this.clear(); + } +} diff --git a/src/app/cache-indicators/cache-indicators.module.ts b/src/app/cache-indicators/cache-indicators.module.ts new file mode 100644 index 0000000..aa9cd99 --- /dev/null +++ b/src/app/cache-indicators/cache-indicators.module.ts @@ -0,0 +1,11 @@ +import {NgModule} from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {CacheIndicatorsComponent} from "./cache-indicators.component"; +import {IconsModule} from "../openaireLibrary/utils/icons/icons.module"; + +@NgModule({ + imports: [CommonModule, IconsModule], + declarations: [CacheIndicatorsComponent], + exports: [CacheIndicatorsComponent] +}) +export class CacheIndicatorsModule {} diff --git a/src/app/general/edit-stakeholder/edit-stakeholder.component.ts b/src/app/general/edit-stakeholder/edit-stakeholder.component.ts index 3df8c5e..2454fa7 100644 --- a/src/app/general/edit-stakeholder/edit-stakeholder.component.ts +++ b/src/app/general/edit-stakeholder/edit-stakeholder.component.ts @@ -15,93 +15,106 @@ import {NotifyFormComponent} from "../../openaireLibrary/notifications/notify-fo import {NotificationUtils} from "../../openaireLibrary/notifications/notification-utils"; import {Notification} from "../../openaireLibrary/notifications/notifications"; import {NotificationHandler} from "../../openaireLibrary/utils/notification-handler"; +import {StatsProfilesService} from "../../utils/services/stats-profiles.service"; @Component({ selector: 'edit-stakeholder', template: ` -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
- -
-
- OR -
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+ OR
-
-
-
- -
-
- -
-
- -
-
- -
{{uploadError}}
-
-
-
-
-
-
-
- -
-
-
-
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
{{uploadError}}
- -
+
+
+
+
+
+
+ +
+
+
+
+
+ +
`, styleUrls: ['edit-stakeholder.component.less'] }) @@ -117,8 +130,9 @@ export class EditStakeholderComponent implements OnDestroy { public stakeholder: Stakeholder; public isDefault: boolean; public isNew: boolean; - public loading: boolean = false; + public loading: boolean = false; public types: Option[]; + public statsProfiles: string[]; public properties: EnvProperties = properties; private subscriptions: any[] = []; /** @@ -130,11 +144,12 @@ export class EditStakeholderComponent implements OnDestroy { public deleteCurrentPhoto: boolean = false; private maxsize: number = 200 * 1024; user: User; - @ViewChild('notify', { static: true }) notify: NotifyFormComponent; + @ViewChild('notify', {static: true}) notify: NotifyFormComponent; private notification: Notification; constructor(private fb: UntypedFormBuilder, private stakeholderService: StakeholderService, + private statsProfileService: StatsProfilesService, private utilsService: UtilitiesService, private userManagementService: UserManagementService,) { } @@ -151,92 +166,110 @@ export class EditStakeholderComponent implements OnDestroy { this.isDefault = isDefault; this.isNew = isNew; this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { - this.user = user; - this.types = this.stakeholderUtils.getTypesByUserRoles(this.user, this.stakeholder.alias); - this.stakeholderFb = this.fb.group({ - _id: this.fb.control(this.stakeholder._id), - defaultId: this.fb.control(this.stakeholder.defaultId), - name: this.fb.control(this.stakeholder.name, Validators.required), - description: this.fb.control(this.stakeholder.description), - index_name: this.fb.control(this.stakeholder.index_name, Validators.required), - index_id: this.fb.control(this.stakeholder.index_id, Validators.required), - index_shortName: this.fb.control(this.stakeholder.index_shortName, Validators.required), - creationDate: this.fb.control(this.stakeholder.creationDate), - alias: this.fb.control(this.stakeholder.alias, - [ - Validators.required, - this.stakeholderUtils.aliasValidatorString( - this.alias.filter(alias => alias !== this.stakeholder.alias) - )] - ), - isDefault: this.fb.control((this.isDefault)), - visibility: this.fb.control(this.stakeholder.visibility, Validators.required), - type: this.fb.control(this.stakeholder.type, Validators.required), - topics: this.fb.control(this.stakeholder.topics), - isUpload: this.fb.control(this.stakeholder.isUpload), - logoUrl: this.fb.control(this.stakeholder.logoUrl), - }); - if (this.stakeholder.isUpload) { + this.user = user; + if (this.isCurator) { + this.subscriptions.push(this.statsProfileService.getStatsProfiles().subscribe(statsProfiles => { + this.statsProfiles = statsProfiles; + }, error => { + this.statsProfiles = []; + })); + } else { + this.statsProfiles = []; + } + this.types = this.stakeholderUtils.getTypesByUserRoles(this.user, this.stakeholder.alias); + this.stakeholderFb = this.fb.group({ + _id: this.fb.control(this.stakeholder._id), + defaultId: this.fb.control(this.stakeholder.defaultId), + name: this.fb.control(this.stakeholder.name, Validators.required), + description: this.fb.control(this.stakeholder.description), + index_name: this.fb.control(this.stakeholder.index_name, Validators.required), + index_id: this.fb.control(this.stakeholder.index_id, Validators.required), + index_shortName: this.fb.control(this.stakeholder.index_shortName, Validators.required), + statsProfile: this.fb.control(this.stakeholder.statsProfile, Validators.required), + locale: this.fb.control(this.stakeholder.locale, Validators.required), + creationDate: this.fb.control(this.stakeholder.creationDate), + alias: this.fb.control(this.stakeholder.alias, + [ + Validators.required, + this.stakeholderUtils.aliasValidatorString( + this.alias.filter(alias => alias !== this.stakeholder.alias) + )] + ), + isDefault: this.fb.control((this.isDefault)), + visibility: this.fb.control(this.stakeholder.visibility, Validators.required), + type: this.fb.control(this.stakeholder.type, Validators.required), + topics: this.fb.control(this.stakeholder.topics), + isUpload: this.fb.control(this.stakeholder.isUpload), + logoUrl: this.fb.control(this.stakeholder.logoUrl), + }); + if (this.stakeholder.isUpload) { + this.stakeholderFb.get('logoUrl').clearValidators(); + this.stakeholderFb.get('logoUrl').updateValueAndValidity(); + } else { + this.stakeholderFb.get('logoUrl').setValidators([StringUtils.urlValidator()]); + this.stakeholderFb.get('logoUrl').updateValueAndValidity(); + } + this.subscriptions.push(this.stakeholderFb.get('isUpload').valueChanges.subscribe(value => { + if (value == true) { this.stakeholderFb.get('logoUrl').clearValidators(); - this.stakeholderFb.get('logoUrl').updateValueAndValidity(); + this.stakeholderFb.updateValueAndValidity(); } else { this.stakeholderFb.get('logoUrl').setValidators([StringUtils.urlValidator()]); - this.stakeholderFb.get('logoUrl').updateValueAndValidity(); + this.stakeholderFb.updateValueAndValidity(); } - this.subscriptions.push(this.stakeholderFb.get('isUpload').valueChanges.subscribe(value => { - if (value == true) { - this.stakeholderFb.get('logoUrl').clearValidators(); - this.stakeholderFb.updateValueAndValidity(); - } else { - this.stakeholderFb.get('logoUrl').setValidators([StringUtils.urlValidator()]); - this.stakeholderFb.updateValueAndValidity(); - } - })); - this.secure = (!this.stakeholderFb.get('logoUrl').value || this.stakeholderFb.get('logoUrl').value.includes('https://')); - this.subscriptions.push(this.stakeholderFb.get('logoUrl').valueChanges.subscribe(value => { - this.secure = (!value || value.includes('https://')); - })); - this.initPhoto(); - if (!isDefault) { - this.subscriptions.push(this.stakeholderFb.get('type').valueChanges.subscribe(value => { - this.onTypeChange(value, defaultStakeholders); - })); - this.stakeholderFb.setControl('defaultId', this.fb.control(stakeholder.defaultId, Validators.required)); - } - if (!isNew) { - this.notification = NotificationUtils.editStakeholder(this.user.firstname + ' ' + this.user.lastname, this.stakeholder.name); - this.notify.reset(this.notification.message); - if (this.isAdmin) { - if (this.disableAlias) { - setTimeout(() => { - this.stakeholderFb.get('alias').disable(); - }, 0); - } - } else { + })); + this.secure = (!this.stakeholderFb.get('logoUrl').value || this.stakeholderFb.get('logoUrl').value.includes('https://')); + this.subscriptions.push(this.stakeholderFb.get('logoUrl').valueChanges.subscribe(value => { + this.secure = (!value || value.includes('https://')); + })); + this.initPhoto(); + this.subscriptions.push(this.stakeholderFb.get('type').valueChanges.subscribe(value => { + this.onTypeChange(value, defaultStakeholders); + })); + this.stakeholderFb.setControl('defaultId', this.fb.control(stakeholder.defaultId, (this.isDefault && !this.isNew)?[]:Validators.required)); + if (!this.isNew) { + this.notification = NotificationUtils.editStakeholder(this.user.firstname + ' ' + this.user.lastname, this.stakeholder.name); + this.notify.reset(this.notification.message); + if (this.isAdmin) { + if (this.disableAlias) { setTimeout(() => { this.stakeholderFb.get('alias').disable(); - this.stakeholderFb.get('index_id').disable(); - this.stakeholderFb.get('index_name').disable(); - this.stakeholderFb.get('index_shortName').disable(); + }, 0); + } + } else { + if (!this.isCurator) { + setTimeout(() => { + this.stakeholderFb.get('statsProfile').disable(); }, 0); } setTimeout(() => { - this.stakeholderFb.get('type').disable(); - }, 0); - } else { - this.notification = NotificationUtils.createStakeholder(this.user.firstname + ' ' + this.user.lastname); - this.notify.reset(this.notification.message); - setTimeout(() => { - this.stakeholderFb.get('type').enable(); + this.stakeholderFb.get('alias').disable(); + this.stakeholderFb.get('index_id').disable(); + this.stakeholderFb.get('index_name').disable(); + this.stakeholderFb.get('index_shortName').disable(); }, 0); } - })); + setTimeout(() => { + this.stakeholderFb.get('type').disable(); + }, 0); + } else { + this.notification = NotificationUtils.createStakeholder(this.user.firstname + ' ' + this.user.lastname); + this.notify.reset(this.notification.message); + setTimeout(() => { + this.stakeholderFb.get('type').enable(); + }, 0); + } + })); } public get isAdmin() { return Session.isPortalAdministrator(this.user); } + public get isCurator() { + return this.stakeholder && (this.isAdmin || Session.isCurator(this.stakeholder.type, this.user)); + } + public get disabled(): boolean { return (this.stakeholderFb && this.stakeholderFb.invalid) || (this.stakeholderFb && this.stakeholderFb.pristine && !this.isNew && !this.file) || @@ -247,8 +280,8 @@ export class EditStakeholderComponent implements OnDestroy { return this.stakeholderFb && this.stakeholderFb.dirty; } - public get canChooseType(): boolean { - return !this.stakeholderFb.get('isDefault').value && this.isNew && this.stakeholderFb.get('type').valid && !!this.defaultStakeholdersOptions; + public get canChooseTemplate(): boolean { + return this.isNew && this.stakeholderFb.get('type').valid && !!this.defaultStakeholdersOptions; } reset() { @@ -262,7 +295,7 @@ export class EditStakeholderComponent implements OnDestroy { } onTypeChange(value, defaultStakeholders: Stakeholder[]) { - this.stakeholderFb.setControl('defaultId', this.fb.control(this.stakeholder.defaultId, Validators.required)); + this.stakeholderFb.setControl('defaultId', this.fb.control(this.stakeholder.defaultId, (this.isDefault && !this.isNew)?[]:Validators.required)); this.defaultStakeholdersOptions = [{ label: 'New blank profile', value: '-1' @@ -276,7 +309,7 @@ export class EditStakeholderComponent implements OnDestroy { } public save(callback: Function, errorCallback: Function = null) { - this.loading = true; + this.loading = true; if (this.file) { this.subscriptions.push(this.utilsService.uploadPhoto(this.properties.utilsService + "/upload/" + encodeURIComponent(this.stakeholderFb.getRawValue().type) + "/" + encodeURIComponent(this.stakeholderFb.getRawValue().alias), this.file).subscribe(res => { this.deletePhoto(); @@ -297,12 +330,13 @@ export class EditStakeholderComponent implements OnDestroy { public saveStakeholder(callback: Function, errorCallback: Function = null) { if (this.isNew) { - if (!this.stakeholderFb.getRawValue().isDefault) { - let stakeholder = this.defaultStakeholders.find(value => value._id === this.stakeholderFb.getRawValue().defaultId); - this.stakeholderFb.setValue(this.stakeholderUtils.createFunderFromDefaultProfile(this.stakeholderFb.getRawValue(), - (stakeholder ? stakeholder.topics : []))); - } + let defaultStakeholder = this.defaultStakeholders.find(value => value._id === this.stakeholderFb.getRawValue().defaultId); + this.stakeholderFb.setValue(this.stakeholderUtils.createFunderFromDefaultProfile(this.stakeholderFb.getRawValue(), + (defaultStakeholder ? defaultStakeholder.topics : []), this.stakeholderFb.getRawValue().isDefault)); this.removePhoto(); + if(this.stakeholderFb.getRawValue().isDefault) { + this.stakeholderFb.get('defaultId').setValue(null); + } this.subscriptions.push(this.stakeholderService.buildStakeholder(this.properties.monitorServiceAPIURL, this.stakeholderFb.getRawValue()).subscribe(stakeholder => { this.notification.entity = stakeholder._id; @@ -312,13 +346,13 @@ export class EditStakeholderComponent implements OnDestroy { this.notify.sendNotification(this.notification); NotificationHandler.rise(stakeholder.name + ' has been successfully created'); callback(stakeholder); - this.loading = false; + this.loading = false; }, error => { NotificationHandler.rise('An error has occurred. Please try again later', 'danger'); if (errorCallback) { errorCallback(error) } - this.loading = false; + this.loading = false; })); } else { this.subscriptions.push(this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, this.stakeholderFb.getRawValue()).subscribe(stakeholder => { @@ -328,14 +362,14 @@ export class EditStakeholderComponent implements OnDestroy { this.notification.groups = [Role.curator(stakeholder.type), Role.manager(stakeholder.type, stakeholder.alias)]; this.notify.sendNotification(this.notification); NotificationHandler.rise(stakeholder.name + ' has been successfully saved'); - callback(stakeholder); - this.loading = false; + callback(stakeholder); + this.loading = false; }, error => { NotificationHandler.rise('An error has occurred. Please try again later', 'danger'); if (errorCallback) { errorCallback(error) } - this.loading = false; + this.loading = false; })); } } diff --git a/src/app/manageStakeholders/manageStakeholders.component.html b/src/app/manageStakeholders/manageStakeholders.component.html index edc45e0..696e680 100644 --- a/src/app/manageStakeholders/manageStakeholders.component.html +++ b/src/app/manageStakeholders/manageStakeholders.component.html @@ -69,6 +69,9 @@
  • Edit
  • +
  • + Cache Indicators +
  • diff --git a/src/app/manageStakeholders/manageStakeholders.component.ts b/src/app/manageStakeholders/manageStakeholders.component.ts index 47a3848..90cccdc 100644 --- a/src/app/manageStakeholders/manageStakeholders.component.ts +++ b/src/app/manageStakeholders/manageStakeholders.component.ts @@ -13,6 +13,8 @@ import {Session} from "../openaireLibrary/login/utils/helper.class"; import {EditStakeholderComponent} from "../general/edit-stakeholder/edit-stakeholder.component"; import {properties} from "../../environments/environment"; import {ActivatedRoute} from "@angular/router"; +import {CacheIndicatorsService} from "../utils/services/cache-indicators.service"; +import {NotificationHandler} from "../openaireLibrary/utils/notification-handler"; type Tab = 'all' | 'templates'| 'profiles'; @@ -62,6 +64,7 @@ export class ManageStakeholdersComponent implements OnInit, OnDestroy { @ViewChild('editStakeholderComponent', { static: true }) editStakeholderComponent: EditStakeholderComponent; constructor(private stakeholderService: StakeholderService, + private cacheIndicatorsService: CacheIndicatorsService, private userManagementService: UserManagementService, private route: ActivatedRoute, private title: Title, @@ -202,6 +205,15 @@ export class ManageStakeholdersComponent implements OnInit, OnDestroy { this.editStakeholderModal.open(); } + public createReport(stakeholder: Stakeholder) { + this.cacheIndicatorsService.createReport(stakeholder.alias).subscribe(report => { + NotificationHandler.rise('A caching process for ' + stakeholder.name + ' has been started.' ) + }, error => { + console.log(error); + NotificationHandler.rise(error.message(), 'danger'); + }); + } + public deleteStakeholderOpen(stakeholder: Stakeholder) { this.stakeholder = stakeholder; this.deleteStakeholderModal.alertTitle = 'Delete ' + this.stakeholder.index_name; diff --git a/src/app/monitor/monitor.component.html b/src/app/monitor/monitor.component.html index 5a8de46..84ff408 100644 --- a/src/app/monitor/monitor.component.html +++ b/src/app/monitor/monitor.component.html @@ -108,7 +108,7 @@ class="uk-text-small uk-text-truncate uk-margin-xsmall-bottom uk-margin-right">{{indicator.name}}
  • + [innerHTML]="(indicator.indicatorPaths[0].format == 'NUMBER'?(numberResults.get(i + '-' + j) | numberRound: 2:1:stakeholder.locale):(numberResults.get(i + '-' + j) | numberPercentage: stakeholder.locale))"> --
    {{indicator.name}}
    + [innerHTML]="(indicator.indicatorPaths[0].format == 'NUMBER'?(numberResults.get(i + '-' + j) | numberRound: 2:1:stakeholder.locale):(numberResults.get(i + '-' + j) | numberPercentage: stakeholder.locale))"> --
    diff --git a/src/app/monitor/monitor.component.ts b/src/app/monitor/monitor.component.ts index 4bf9845..e46ff8c 100644 --- a/src/app/monitor/monitor.component.ts +++ b/src/app/monitor/monitor.component.ts @@ -485,7 +485,7 @@ export class MonitorComponent implements OnInit, OnDestroy { urls.forEach((indexes, pair) => { pair = JSON.parse(pair); let activeSubcategory = this.activeSubCategory._id; - this.subscriptions.push(this.statisticsService.getNumbers(this.statisticsService.getSourceType(pair[0]), pair[1]).subscribe(response => { + this.subscriptions.push(this.statisticsService.getNumbers(this.indicatorUtils.getSourceType(pair[0]), pair[1]).subscribe(response => { if(activeSubcategory === this.activeSubCategory._id) { indexes.forEach(([i, j]) => { if( this.activeSubCategory?.numbers[i]?.indicators[j]) { @@ -524,7 +524,7 @@ export class MonitorComponent implements OnInit, OnDestroy { public getUrlByStakeHolder(indicatorPath: IndicatorPath) { return this.sanitizer.bypassSecurityTrustResourceUrl( - this.statisticsService.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, indicatorPath, this.getfl0(), this.periodFilter.selectedFromValue, this.periodFilter.selectedToValue, this.getCoFunded()))); + this.indicatorUtils.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, indicatorPath, this.getfl0(), this.periodFilter.selectedFromValue, this.periodFilter.selectedToValue, this.getCoFunded()))); } public setActiveChart(i: number, j: number, type: string) { diff --git a/src/app/search/search.module.ts b/src/app/search/search.module.ts index 739c81e..c14997d 100644 --- a/src/app/search/search.module.ts +++ b/src/app/search/search.module.ts @@ -15,14 +15,14 @@ import {RouterModule} from "@angular/router"; { path: 'advanced/dataproviders', loadChildren: () => import('./searchPages/advanced/searchDataProviders.module').then(m => m.MonitorAdvancedSearchDataProvidersModule)}, { path: 'advanced/organizations', loadChildren: () => import('./searchPages/advanced/searchOrganizations.module').then(m => m.MonitorAdvancedSearchOrganizationsModule)}, // Landing Pages - { path: 'result', loadChildren: () => import('./landingPages/result/libResult.module').then(m => m.LibResultModule)}, - { path: 'publication', loadChildren: () => import('./landingPages/publication/libPublication.module').then(m => m.LibPublicationModule)}, - { path: 'dataset', loadChildren: () => import('./landingPages/dataset/libDataset.module').then(m => m.LibDatasetModule)}, - { path: 'software', loadChildren: () => import('./landingPages/software/libSoftware.module').then(m => m.LibSoftwareModule)}, - { path: 'other', loadChildren: () => import('./landingPages/orp/libOrp.module').then(m => m.LibOrpModule)}, - { path: 'project', loadChildren: () => import('./landingPages/project/libProject.module').then(m => m.LibProjectModule)}, - { path: 'dataprovider', loadChildren: () => import('./landingPages/dataProvider/libDataProvider.module').then(m => m.LibDataProviderModule)}, - { path: 'organization', loadChildren: () => import('./landingPages/organization/libOrganization.module').then(m => m.LibOrganizationModule)}, + { path: 'result', loadChildren: () => import('./landingPages/result/libResult.module').then(m => m.LibResultModule), data: {hasMenuSearchBar: true}}, + { path: 'publication', loadChildren: () => import('./landingPages/publication/libPublication.module').then(m => m.LibPublicationModule), data: {hasMenuSearchBar: true}}, + { path: 'dataset', loadChildren: () => import('./landingPages/dataset/libDataset.module').then(m => m.LibDatasetModule), data: {hasMenuSearchBar: true}}, + { path: 'software', loadChildren: () => import('./landingPages/software/libSoftware.module').then(m => m.LibSoftwareModule), data: {hasMenuSearchBar: true}}, + { path: 'other', loadChildren: () => import('./landingPages/orp/libOrp.module').then(m => m.LibOrpModule), data: {hasMenuSearchBar: true}}, + { path: 'project', loadChildren: () => import('./landingPages/project/libProject.module').then(m => m.LibProjectModule), data: {hasMenuSearchBar: true}}, + { path: 'dataprovider', loadChildren: () => import('./landingPages/dataProvider/libDataProvider.module').then(m => m.LibDataProviderModule), data: {hasMenuSearchBar: true}}, + { path: 'organization', loadChildren: () => import('./landingPages/organization/libOrganization.module').then(m => m.LibOrganizationModule), data: {hasMenuSearchBar: true}}, ])] }) export class SearchModule {} diff --git a/src/app/topic/indicators.component.html b/src/app/topic/indicators.component.html index d9d25bf..ecdc0cd 100644 --- a/src/app/topic/indicators.component.html +++ b/src/app/topic/indicators.component.html @@ -68,7 +68,7 @@
    {{indicator.name}}
    - + --
    @@ -257,11 +257,16 @@ now
    -
    +
    +
    +
    +
    +
    @@ -297,8 +302,8 @@
    - - {{numberIndicatorPaths.at(i).get('result').value | number}} + -- diff --git a/src/app/topic/indicators.component.ts b/src/app/topic/indicators.component.ts index 521f648..8a0435d 100644 --- a/src/app/topic/indicators.component.ts +++ b/src/app/topic/indicators.component.ts @@ -11,6 +11,7 @@ import { ViewChild } from "@angular/core"; import { + Format, Indicator, IndicatorPath, IndicatorSize, @@ -20,7 +21,14 @@ import { Visibility } from "../openaireLibrary/monitor/entities/stakeholder"; import {IndicatorUtils, StakeholderUtils} from "../utils/indicator-utils"; -import {AbstractControl, UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators} from "@angular/forms"; +import { + AbstractControl, + UntypedFormArray, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, + Validators +} from "@angular/forms"; import {AlertModal} from "../openaireLibrary/utils/modal/alert"; import {StatisticsService} from "../utils/services/statistics.service"; import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class"; @@ -96,9 +104,9 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV @ViewChild('editNumberNotify', {static: true}) editNumberNotify: NotifyFormComponent; @ViewChild('editChartNotify', {static: true}) editChartNotify: NotifyFormComponent; @ViewChild('deleteNotify', {static: true}) deleteNotify: NotifyFormComponent; - + public isFullscreen: boolean = false; - + @HostListener('fullscreenchange', ['$event']) @HostListener('webkitfullscreenchange', ['$event']) @HostListener('mozfullscreenchange', ['$event']) @@ -106,14 +114,14 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV screenChange(event) { this.isFullscreen = !this.isFullscreen; } - + /** * Subscriptions **/ private subscriptions: any[] = []; private urlSubscriptions: any[] = []; private numberSubscription: any[] = []; - + constructor(private layoutService: LayoutService, private stakeholderService: StakeholderService, private statisticsService: StatisticsService, @@ -124,7 +132,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV private sanitizer: DomSanitizer) { this.filesToUpload = []; } - + ngOnInit(): void { if (this.stakeholder) { this.setCharts(); @@ -136,7 +144,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.initReorder(); }) } - + ngOnDestroy(): void { this.subscriptions.forEach(value => { if (value instanceof Subscriber) { @@ -156,11 +164,11 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } }); } - + ngAfterViewInit(): void { this.initReorder(); } - + ngOnChanges(changes: SimpleChanges): void { if (this.canEdit) { if (changes.topicIndex || changes.categoryIndex || changes.subcategoryIndex) { @@ -170,7 +178,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } } } - + initReorder() { this.subscriptions.forEach(value => { if (value instanceof Function) { @@ -223,11 +231,11 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV }); } } - + hide(element: any) { UIkit.dropdown(element).hide(); } - + setCharts() { this.chartSections = this.fb.array([]); this.charts.forEach(section => { @@ -251,7 +259,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV }) }); } - + setNumbers() { this.numberSections = this.fb.array([]); this.numberResults.clear(); @@ -267,7 +275,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV indicators: this.fb.control(section.indicators) })); section.indicators.forEach((number, j) => { - let url = this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, number.indicatorPaths[0]); + let url = this.indicatorUtils.getFullUrl(this.stakeholder, number.indicatorPaths[0]); const pair = JSON.stringify([number.indicatorPaths[0].source, url]); const indexes = urls.get(pair) ? urls.get(pair) : []; indexes.push([i, j]); @@ -285,14 +293,14 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV if (response) { this.calculateResults(response, indexes); } else { - this.numberSubscription.push(this.statisticsService.getNumbers(this.statisticsService.getSourceType(parsed[0]), parsed[1]).subscribe(response => { + this.numberSubscription.push(this.statisticsService.getNumbers(this.indicatorUtils.getSourceType(parsed[0]), parsed[1]).subscribe(response => { this.calculateResults(response, indexes); this.numberResponses.set(pair, response); })); } }); } - + private calculateResults(response: any, indexes: [number, number][]) { indexes.forEach(([i, j]) => { let result = JSON.parse(JSON.stringify(response)); @@ -312,7 +320,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.numberResults.set(i + '-' + j, result); }); } - + get charts(): Section[] { if (this.stakeholder.topics[this.topicIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] && @@ -322,7 +330,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV return []; } } - + get numbers(): Section[] { if (this.stakeholder.topics[this.topicIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] && @@ -332,30 +340,30 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV return []; } } - + set numbers(sections: Section[]) { this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].numbers = sections; } - + get open(): boolean { return this.layoutService.open; } - + get canEdit() { return this.stakeholder && this.stakeholder.topics[this.topicIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]; } - + public get numberIndicatorPaths(): UntypedFormArray { return this.numberIndicatorFb.get('indicatorPaths') as UntypedFormArray; } - + public get chartIndicatorPaths(): UntypedFormArray { return this.chartIndicatorFb.get('indicatorPaths') as UntypedFormArray; } - + public getNumberClassBySize(size: IndicatorSize) { if (size === 'small') { return 'uk-width-medium@m uk-width-1-1'; @@ -365,7 +373,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV return 'uk-width-1-2@l uk-width-1-1@m uk-width-1-1'; } } - + public getChartClassBySize(size: IndicatorSize) { if (size === 'small') { return 'uk-width-1-3@xl uk-width-1-2@m uk-width-1-1'; @@ -375,7 +383,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV return 'uk-width-1-1'; } } - + public addJsonPath(index: number) { if (index == 0 && this.getJsonPath(index).getRawValue()[index].indexOf(",") != -1) { //if in the first path there are more than one paths comma separated, split them and autogenerate the forms @@ -390,13 +398,13 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.getJsonPath(index).push(this.fb.control('', Validators.required)); } } - + public removeJsonPath(i: number, j: number) { if (this.getJsonPath(i).enabled) { this.getJsonPath(i).removeAt(j); } } - + public validateJsonPath(index: number, dirty: boolean = false) { let indicatorPath: UntypedFormGroup = this.numberIndicatorPaths.at(index); if (this.indicator.defaultId === null) { @@ -442,33 +450,33 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV }, 500); })); } - + public getJsonPath(index: number): UntypedFormArray { return this.numberIndicatorPaths.at(index).get('jsonPath') as UntypedFormArray; } - + public getCurrentJsonPath(index: number): string[] { return this.section.indicators[this.index].indicatorPaths[index].jsonPath; } - + public getParameters(index: number): UntypedFormArray { return this.chartIndicatorPaths.at(index).get('parameters') as UntypedFormArray; } - + public getParameter(index: number, key: string): UntypedFormControl { return this.getParameters(index).controls.filter(control => control.value.key === key)[0] as UntypedFormControl; } - + private getSecureUrlByStakeHolder(indicatorPath: IndicatorPath) { return this.sanitizer.bypassSecurityTrustResourceUrl( - this.statisticsService.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath))); + this.indicatorUtils.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath))); } - + private getUrlByStakeHolder(indicatorPath: IndicatorPath) { - return this.statisticsService.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)); + return this.indicatorUtils.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)); } - - public addNumberIndicatorPath(url: string = '', parameters: UntypedFormArray = new UntypedFormArray([]), source: string = 'stats-tool', jsonPath: UntypedFormArray = new UntypedFormArray([])) { + + public addNumberIndicatorPath(url: string = '', parameters: UntypedFormArray = new UntypedFormArray([]), source: string = 'stats-tool', jsonPath: UntypedFormArray = new UntypedFormArray([]), format: Format = "NUMBER") { if (jsonPath.length === 0) { jsonPath.push(this.fb.control('', Validators.required)); } @@ -476,8 +484,8 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV url: this.fb.control(url, [Validators.required, StringUtils.urlValidator()]), jsonPath: jsonPath, result: this.fb.control(0, Validators.required), - // parameters: parameters, - source: this.fb.control(source, Validators.required) + source: this.fb.control(source, Validators.required), + format: this.fb.control(format, Validators.required) } )); let index = this.numberIndicatorPaths.length - 1; @@ -489,7 +497,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.subscriptions.push(this.numberIndicatorPaths.at(index).get('url').valueChanges.subscribe(value => { this.numberIndicatorPaths.at(index).get('result').setValue(null); if (this.numberIndicatorPaths.at(index).get('url').valid) { - let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByNumberUrl(this.statisticsService.getNumberSource(value), value, this.stakeholder, this.numberIndicatorPaths.at(index).get('jsonPath').value, this.statisticsService.numberSources.get(this.statisticsService.getNumberSource(value))); + let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByNumberUrl(this.indicatorUtils.getNumberSource(value), value, this.stakeholder, this.numberIndicatorPaths.at(index).get('jsonPath').value, this.indicatorUtils.numberSources.get(this.indicatorUtils.getNumberSource(value))); if (!this.isStakeholderParametersValid(indicatorPath)) { // default profile if (this.stakeholder.defaultId == null) { @@ -523,7 +531,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } }) ); - + this.subscriptions.push(this.numberIndicatorPaths.at(index).get('jsonPath').valueChanges.subscribe(value => { if (this.indicator.indicatorPaths[index]) { this.indicator.indicatorPaths[index].jsonPath = value; @@ -543,7 +551,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.numberIndicatorPaths.at(index).get('source').disable(); } } - + public addChartIndicatorPath(value: string = '', parameters: UntypedFormArray = new UntypedFormArray([]), disableUrl: boolean = false, type: string = null) { this.chartIndicatorPaths.push(this.fb.group({ url: this.fb.control(value, [Validators.required, StringUtils.urlValidator()]), @@ -558,7 +566,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.checkForSchemaEnhancements(this.chartIndicatorPaths.at(index).get('url').value); this.urlSubscriptions.push(this.chartIndicatorPaths.at(index).get('url').valueChanges.subscribe(value => { if (this.chartIndicatorPaths.at(index).get('url').valid) { - let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.statisticsService.getChartSource(value), value, this.chartIndicatorPaths.at(index).get('type').value, this.stakeholder); + let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.indicatorUtils.getChartSource(value), value, this.chartIndicatorPaths.at(index).get('type').value, this.stakeholder); if (!this.isStakeholderParametersValid(indicatorPath)) { // default profile if (this.stakeholder.defaultId == null) { @@ -586,13 +594,13 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV })); } } - + private isStakeholderParametersValid(indicatorPath: IndicatorPath) { return !((indicatorPath.chartObject && Object.keys(indicatorPath.parameters).indexOf("index_id") == -1 && Object.keys(indicatorPath.parameters).indexOf("index_name") == -1 && Object.keys(indicatorPath.parameters).indexOf("index_shortName") == -1) || (!indicatorPath.chartObject && indicatorPath.url.indexOf("index_id") == -1 && indicatorPath.url.indexOf("index_name") == -1 && (indicatorPath.url).indexOf("index_shortName") == -1)); - + } - + private getJsonPathAsFormArray(indicatorPath: IndicatorPath): UntypedFormArray { let jsonPath = this.fb.array([]); if (indicatorPath.jsonPath) { @@ -602,7 +610,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } return jsonPath; } - + private getParametersAsFormArray(indicatorPath: IndicatorPath): UntypedFormArray { let parameters = this.fb.array([]); if (indicatorPath.parameters) { @@ -624,7 +632,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } return parameters; } - + public editNumberIndicatorOpen(section: Section, id = null) { this.urlParameterizedMessage = null; this.section = section; @@ -645,7 +653,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV defaultId: this.fb.control(this.indicator.defaultId) }); this.indicator.indicatorPaths.forEach(indicatorPath => { - this.addNumberIndicatorPath(this.statisticsService.getNumberUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)), indicatorPath.parameters, indicatorPath.source, this.getJsonPathAsFormArray(indicatorPath)); + this.addNumberIndicatorPath(this.indicatorUtils.getNumberUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)), indicatorPath.parameters, indicatorPath.source, this.getJsonPathAsFormArray(indicatorPath), indicatorPath.format); }); } else { this.indicator = new Indicator('', '', '', 'number', 'small', 'small', "PUBLIC", []); @@ -685,7 +693,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.editNumberModal.stayOpen = true; this.editNumberModal.open(); } - + public editChartIndicatorOpen(section: Section, id = null) { this.urlParameterizedMessage = null; this.urlSubscriptions.forEach(value => { @@ -752,7 +760,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.editChartModal.stayOpen = true; this.editChartModal.open(); } - + saveIndicator() { this.editing = true; if (this.indicator.type === 'chart') { @@ -834,7 +842,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } })); } - + saveIndicators(sections) { this.editing = true; let path = [ @@ -892,10 +900,10 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.editing = false; this.importLoading = false; })); - - + + } - + reorderIndicators(sectionId: string, type: IndicatorType, reorder: Reorder) { this.editing = true; let path = [ @@ -916,7 +924,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.editing = false; })); } - + hasDifference(index: number): boolean { let hasDifference = false; this.chartIndicatorPaths.at(index).value.parameters.forEach((parameter) => { @@ -928,22 +936,22 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV return hasDifference || this.indicator.indicatorPaths[index].safeResourceUrl.toString() !== this.getSecureUrlByStakeHolder(this.indicator.indicatorPaths[index]).toString(); } - + public get isAdministrator(): boolean { return Session.isPortalAdministrator(this.user); } - + public get isCurator(): boolean { return this.isAdministrator || Session.isCurator(this.stakeholder.type, this.user); } - + refreshIndicator() { this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths, 'chart', true); this.indicator.indicatorPaths.forEach(indicatorPath => { indicatorPath.safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath); }); } - + deleteIndicatorOpen(section: Section, indicatorId: string, type: string, childrenAction: string = null) { this.indicatorChildrenActionOnDelete = null; if (childrenAction == "delete") { @@ -951,7 +959,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } else if (childrenAction == "disconnect") { this.indicatorChildrenActionOnDelete = childrenAction; } - + this.section = section; if (type === 'chart') { this.index = this.charts.find(value => value._id == section._id).indicators.findIndex(value => value._id == indicatorId); @@ -967,7 +975,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.deleteModal.stayOpen = true; this.deleteModal.open(); } - + deleteIndicator() { this.editing = true; let path = [ @@ -1018,7 +1026,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.deleteModal.cancel(); })); } - + changeIndicatorStatus(sectionId: string, indicator: Indicator, visibility: Visibility) { this.editing = true; let path = [ @@ -1046,7 +1054,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.editing = false; })); } - + saveSection(focused: boolean, sectionControl: AbstractControl, index: number, type: IndicatorType = "chart") { if (!focused && sectionControl.dirty) { this.editing = true; @@ -1081,7 +1089,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV })); } } - + createSection(index = -1, type: IndicatorType = 'chart') { this.editing = true; this.section = new Section(type, null, null, this.stakeholder.alias); @@ -1123,7 +1131,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.editing = false; })); } - + // deleteNumberSectionOpen(section: Section, index: number) { // this.section = section; // this.index = index; @@ -1141,7 +1149,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV // this.deleteChartSectionModal.okButtonText = 'Yes'; // this.deleteChartSectionModal.open(); // } - + deleteSectionOpen(section: Section, index: number, type: IndicatorType, childrenAction: string = null) { if (!this.editing && !section.defaultId) { this.sectionTypeToDelete = type; @@ -1151,7 +1159,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } else if (childrenAction == "disconnect") { this.sectionChildrenActionOnDelete = childrenAction; } - + this.section = section; this.index = index; this.deleteSectionModal.alertTitle = 'Delete Section'; @@ -1161,7 +1169,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.deleteSectionModal.open(); } } - + deleteSection() { this.editing = true; let path = [ @@ -1197,21 +1205,22 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.deleteSectionModal.cancel(); })); } - + private checkForSchemaEnhancements(url: string) { this.showCheckForSchemaEnhancements = this.isAdministrator && url && !this.properties.useOldStatisticsSchema && this.indicatorUtils.checkForSchemaEnhancements(url); } - migrateFromOldImportJsonFile(charts){ + + migrateFromOldImportJsonFile(charts) { // first section contains numbers // second contains charts let hasNumbers = false; - for (let chart of charts) { + for (let chart of charts) { if (chart['type'] == 'number') { hasNumbers = true; break; } } - let chartsSection = (hasNumbers?1:0); // no numbers: first sections contains charts + let chartsSection = (hasNumbers ? 1 : 0); // no numbers: first sections contains charts for (let chart of charts) { if (chart['sectionIndex'] == null) { chart['sectionIndex'] = chart['type'] == 'chart' ? chartsSection : 0; @@ -1219,7 +1228,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } return charts; } - + importIndicatorsAndSave(charts: any[]) { let sectionsToSave: Section[] = []; let countIndicators = 0; @@ -1246,7 +1255,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } else if (!chart.url) { invalid_file_message = "No indicator url is specified."; } - + if (invalid_file_message) { UIkit.notification(invalid_file_message, { status: 'danger', @@ -1257,9 +1266,9 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.importLoading = false; break; } - + if (chart.type == "chart") { - indicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.statisticsService.getChartSource(chart.url), chart.url, chart.type, this.stakeholder); + indicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.indicatorUtils.getChartSource(chart.url), chart.url, chart.type, this.stakeholder); for (let section of this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index].charts) { for (let chart of section.indicators) { if (JSON.stringify(chart.indicatorPaths[0].chartObject) == JSON.stringify(indicatorPath.chartObject)) { @@ -1267,11 +1276,11 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV exists = true; } } - + } } else if (chart.type == "number") { - indicatorPath = this.indicatorUtils.generateIndicatorByNumberUrl(this.statisticsService.getNumberSource(chart.url), chart.url, this.stakeholder, - chart.jsonPath, this.statisticsService.numberSources.get(this.statisticsService.getNumberSource(chart.url))); + indicatorPath = this.indicatorUtils.generateIndicatorByNumberUrl(this.indicatorUtils.getNumberSource(chart.url), chart.url, this.stakeholder, + chart.jsonPath, this.indicatorUtils.numberSources.get(this.indicatorUtils.getNumberSource(chart.url))); for (let section of this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index].numbers) { for (let chart of section.indicators) { if (JSON.stringify(chart.indicatorPaths[0].chartObject) == JSON.stringify(indicatorPath.chartObject)) { @@ -1279,7 +1288,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV exists = true; } } - + } } if (!this.isStakeholderParametersValid(indicatorPath)) { @@ -1290,9 +1299,9 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV sectionsToSave[chart['sectionIndex']].indicators.push(i); countIndicators++; } - + } - + if (duplicates > 0) { UIkit.notification(duplicates + " urls already exist and will not be imported!", { status: 'warning', @@ -1313,7 +1322,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.editing = false; this.importLoading = false; } else if (sectionsToSave.length > 0 && countIndicators > 0) { - this.saveIndicators(sectionsToSave) + this.saveIndicators(sectionsToSave.filter(section => !!section)); } if (sectionsToSave.length == 0 || countIndicators == 0) { UIkit.notification(" No urls imported!", { @@ -1325,7 +1334,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.importLoading = false; } } - + public exportIndicators(subcategoryIndex) { this.editing = true; let indicators = []; @@ -1338,7 +1347,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV "type": indicator.type, "name": indicator.name, "jsonPath": indicatorPath.jsonPath, "description": indicator.description, "additionalDescription": indicator.additionalDescription, "visibility": indicator.visibility, "width": indicator.width, "height": indicator.height, - "url": this.statisticsService.getNumberUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)), + "url": this.indicatorUtils.getNumberUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)), "sectionTitle": section.title, "sectionType": section.type, "sectionIndex": index @@ -1348,7 +1357,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV }); index++; }); - + this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[subcategoryIndex].charts.forEach(section => { section.indicators.forEach(indicator => { indicator.indicatorPaths.forEach(indicatorPath => { @@ -1365,13 +1374,13 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV }); }); index++; - + }); - + let topic = this.stakeholder ? this.stakeholder.topics[this.topicIndex] : null; let category = topic ? topic.categories[this.categoryIndex] : null; let subCategory = category ? category.subCategories[this.subcategoryIndex] : null; - + var jsonFileUrl = window.URL.createObjectURL(new Blob([JSON.stringify(indicators)], {type: 'application/json'})); var a = window.document.createElement('a'); window.document.body.appendChild(a); @@ -1381,10 +1390,10 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV a.click(); window.URL.revokeObjectURL(jsonFileUrl); a.remove(); // remove the element - + this.editing = false; } - + fileChangeEvent(fileInput: any, index) { this.index = index; this.editing = true; @@ -1392,7 +1401,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.filesToUpload = >fileInput.target.files; this.upload(); } - + upload() { if (this.filesToUpload.length == 0) { console.error("There is no selected file to upload."); @@ -1417,11 +1426,11 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV return; } } - + this.makeFileRequest(this.properties.utilsService + '/upload?type=json', [], this.filesToUpload).then(async (result: string) => { - + let json_result = JSON.parse(result); - + // validate file if (!json_result || json_result.length == 0) { UIkit.notification("Importing file is empty", { @@ -1445,7 +1454,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.importLoading = false; }); } - + makeFileRequest(url: string, params: Array, files: Array) { return new Promise((resolve, reject) => { const formData: any = new FormData(); @@ -1466,7 +1475,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV xhr.send(formData); }); } - + copyToClipboard(value) { const tempBox = document.createElement('textarea'); tempBox.style.position = 'fixed'; diff --git a/src/app/utils/adminDashboard.guard.ts b/src/app/utils/adminDashboard.guard.ts index 213717a..cf34e2e 100644 --- a/src/app/utils/adminDashboard.guard.ts +++ b/src/app/utils/adminDashboard.guard.ts @@ -27,7 +27,7 @@ export class AdminDashboardGuard implements CanActivate, CanActivateChild { check(path: string, alias: string): Observable | boolean { let errorCode = LoginErrorCodes.NOT_LOGIN; return zip( - this.userManagementService.getUserInfo() ,this.stakeholderService.getStakeholder(alias) + this.userManagementService.getUserInfo(), this.stakeholderService.getStakeholder(alias) ).pipe(take(1),map(res => { if(res[0]) { errorCode = LoginErrorCodes.NOT_ADMIN; diff --git a/src/app/utils/indicator-utils.ts b/src/app/utils/indicator-utils.ts index 114155c..b186f4b 100644 --- a/src/app/utils/indicator-utils.ts +++ b/src/app/utils/indicator-utils.ts @@ -1,12 +1,17 @@ import { - ChartHelper, FilterType, - Indicator, IndicatorFilterUtils, - IndicatorPath, IndicatorPathType, IndicatorType, + ChartHelper, + FilterType, + Indicator, + IndicatorFilterUtils, + IndicatorPath, + IndicatorPathType, + IndicatorType, SourceType, Stakeholder, + StakeholderEntities, SubCategory, - Topic, Visibility, - StakeholderEntities + Topic, + Visibility } from "../openaireLibrary/monitor/entities/stakeholder"; import {AbstractControl, ValidatorFn, Validators} from "@angular/forms"; import {Option} from "../openaireLibrary/sharedComponents/input/input.component"; @@ -15,6 +20,7 @@ import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class"; import {properties} from "../../environments/environment"; export class StakeholderUtils { + statuses: Option[] = [ {value: 'PUBLIC', label: 'Public'}, {value: 'RESTRICTED', label: 'Restricted'}, @@ -34,64 +40,58 @@ export class StakeholderUtils { {icon: 'incognito', value: "PRIVATE", label: 'Private'}, ]; - - visibilityIcon: Map = new Map ([ + locales: Option[] = [ + {value: "en", label: 'English'}, + {value: "eu", label: 'Europe'} + ]; + + visibilityIcon: Map = new Map([ ["PUBLIC", 'earth'], ["PRIVATE", 'incognito'], ["RESTRICTED", 'restricted'] ]); - getTypesByUserRoles(user, id:string = null):Option[]{ + getTypesByUserRoles(user, id: string = null): Option[] { let types = []; - for(let type of this.types){ - if(Session.isCurator(type.value, user)|| Session.isPortalAdministrator(user)|| (id && Session.isManager(type.value, id, user))){ + for (let type of this.types) { + if (Session.isCurator(type.value, user) || Session.isPortalAdministrator(user) || (id && Session.isManager(type.value, id, user))) { types.push(type); } } return types; } - public createFunderFromDefaultProfile(funder: Stakeholder, defaultTopics: Topic[]): Stakeholder { + public createFunderFromDefaultProfile(funder: Stakeholder, defaultTopics: Topic[], isDefault: boolean = false): Stakeholder { funder.topics = HelperFunctions.copy(defaultTopics); for (let topic of funder.topics) { - // console.log('id:' + topic._id); - topic.defaultId = topic._id; + topic.defaultId = !isDefault ? topic._id : null; topic._id = null; - // console.log('defaultId:' + topic.defaultId); for (let category of topic.categories) { - category.defaultId = category._id; + category.defaultId = !isDefault ? category._id : null; category._id = null; let subTokeep: SubCategory[] = []; for (let subCategory of category.subCategories) { - subCategory.defaultId = subCategory._id; + subCategory.defaultId = !isDefault ? subCategory._id : null; subCategory._id = null; subTokeep.push(subCategory); for (let section of subCategory.charts) { let chartsTokeep: Indicator[] = []; - section.defaultId = section._id; + section.defaultId = !isDefault ? section._id : null; section.stakeholderAlias = funder.alias; section._id = null; for (let indicator of section.indicators) { - indicator.defaultId = indicator._id; + indicator.defaultId = !isDefault ? indicator._id : null; indicator._id = null; chartsTokeep.push(indicator); for (let indicatorPath of indicator.indicatorPaths) { if (indicatorPath.parameters) { Object.keys(indicatorPath.parameters).forEach(key => { - //TODO check before delete - /*if (indicatorPath.parameters[key].indexOf("_funder_name_") != -1) { - indicatorPath.parameters[key] = indicatorPath.parameters[key].replace("_funder_name_", funder.index_name); - } else if (indicatorPath.parameters[key].indexOf("_funder_id_") != -1) { - indicatorPath.parameters[key] = indicatorPath.parameters[key].replace("_funder_id_", funder.index_id); - } else if (indicatorPath.parameters[key].indexOf("_fsn_") != -1) { - indicatorPath.parameters[key] = indicatorPath.parameters[key].toString().replace("_fsn_", funder.index_shortName.toLowerCase()); - }*/ if (key == "index_name") { indicatorPath.parameters[key] = funder.index_name; - } else if (key == "index_id" ) { + } else if (key == "index_id") { indicatorPath.parameters[key] = funder.index_id; - } else if (key == "index_shortName" ) { - indicatorPath.parameters[key] = funder.index_shortName.toLowerCase(); + } else if (key == "index_shortName") { + indicatorPath.parameters[key] = funder.index_shortName.toLowerCase(); } }); } @@ -100,34 +100,19 @@ export class StakeholderUtils { section.indicators = chartsTokeep; } for (let section of subCategory.numbers) { - section.defaultId = section._id; + section.defaultId = !isDefault ? section._id : null; section.stakeholderAlias = funder.alias; section._id = null; - for(let indicator of section.indicators) { - indicator.defaultId = indicator._id; + for (let indicator of section.indicators) { + indicator.defaultId = !isDefault ? indicator._id : null; indicator._id = null; - for (let indicatorPath of indicator.indicatorPaths) { - /* indicatorPath.url = indicatorPath.url.replace("index_id", encodeURIComponent(funder.index_id)); - indicatorPath.url = indicatorPath.url.replace("index_name", encodeURIComponent(funder.index_name)); - indicatorPath.url = indicatorPath.url.replace("index_shortName", encodeURIComponent(funder.index_shortName));*/ - // if(indicatorPath.parameters) { - // indicatorPath.parameters.forEach((value: string, key: string) => { - // if (value.indexOf("_funder_name_")!=-1) { - // indicatorPath.parameters.set(key,value.toString().replace("_funder_name_", funder.index_name)); - // }else if (value.indexOf("_fsn_")!=-1) { - // indicatorPath.parameters.set(key,value.toString().replace("_fsn_", funder.index_shortName.toLowerCase())); - // } - // }); - // } - } } } - + } category.subCategories = subTokeep; } } - //console.log (funder); return funder; } @@ -141,7 +126,7 @@ export class StakeholderUtils { return null; } } - + aliasValidator(elements: any[]): ValidatorFn { return (control: AbstractControl): { [key: string]: string } | null => { if (control.value && elements.find(element => @@ -165,7 +150,7 @@ export class StakeholderUtils { } export class IndicatorUtils { - + allChartTypes: Option[] = [ {value: 'pie', label: 'Pie'}, {value: 'table', label: 'Table'}, @@ -174,76 +159,121 @@ export class IndicatorUtils { {value: 'bar', label: 'Bar'}, {value: 'other', label: 'Other'} ]; - basicChartTypes:IndicatorPathType[] =["pie", "line", "column", "bar"]; - defaultChartType:IndicatorPathType = "other"; + basicChartTypes: IndicatorPathType[] = ["pie", "line", "column", "bar"]; + defaultChartType: IndicatorPathType = "other"; indicatorSizes: Option[] = [ {value: 'small', label: 'Small (Enabled only for large screens)'}, {value: 'medium', label: 'Medium'}, {value: 'large', label: 'Large'} ]; - - allSourceTypes: Option[] = [ + + allSourceTypes: Option[] = [ {value: 'search', label: 'Search'}, {value: 'statistics', label: 'Statistics'}, {value: 'stats-tool', label: 'Statistics tool'} ]; - sourceTypes: Option[] = [ + + formats: Option[] = [ + {value: "NUMBER", label: "Number"}, + {value: "PERCENTAGE", label: "Percentage"} + ]; + + sourceTypes: Option[] = [ {value: 'stats-tool', label: 'Statistics tool'} ]; - isPublic: Option[] = [ - {icon: 'public', value: true, label: 'Public'}, - {icon: 'lock', value: false, label: 'Private'}, - ]; - + isActive: Option[] = [ {icon: 'brightness_1', iconClass: '', value: true, label: 'Active'}, {icon: 'brightness_1', value: false, label: 'Inactive'}, ]; - - chartTypesIcons: Map = new Map([ - ['pie', 'pie_chart'], - ['table', 'table_chart'], - ['line', 'show_chart'], - ['column', 'bar_chart'], - ['bar', 'notes'], - ['other', 'perm_media'] + + parametersValidators: Map = new Map([ + ['start_year', [Validators.required, Validators.pattern('^\\d+$')]], + ['end_year', [Validators.required, Validators.pattern('^\\d+$')]] ]); - getChartTypes(initialType){ - let types: Option[]= []; - if(this.basicChartTypes.indexOf(initialType) != -1){ + ignoredParameters = ['index_name', 'index_id', 'index_shortName']; + statsProfileParameter = 'profile'; + + numberSources: Map = new Map(); + chartSources: Map = new Map(); + + constructor() { + this.numberSources.set('statistics', [properties.statisticsAPIURL]); + this.numberSources.set('search', [properties.searchAPIURLLAst]); + this.numberSources.set('stats-tool', [properties.monitorStatsFrameUrl, "http://marilyn.athenarc.gr:8080/stats-api/", "http://88.197.53.71:8080/stats-api/", "https://stats.madgik.di.uoa.gr/stats-api/","https://beta.services.openaire.eu/stats-tool/","https://services.openaire.eu/stats-tool/","https://services.openaire.eu/monitor-stats-tool/"]); + this.chartSources.set('stats-tool', [properties.monitorStatsFrameUrl, "http://marilyn.athenarc.gr:8080/stats-api/", "http://88.197.53.71:8080/stats-api/", "https://stats.madgik.di.uoa.gr/stats-api/","https://beta.services.openaire.eu/stats-tool/","https://services.openaire.eu/stats-tool/","https://services.openaire.eu/monitor-stats-tool/"]); + this.chartSources.set('old', [properties.statisticsFrameAPIURL]); + this.chartSources.set('image', [""]); + } + + getSourceType(source:string): SourceType{ + let sourceType: SourceType = 'search'; + this.numberSources.forEach((values, key) => { + if(key == source) { + sourceType = key; + } + }); + return sourceType; + } + + getChartUrl(source: SourceType, url: string): string { + return this.chartSources.get(source)[0] + url; + } + + getNumberUrl(source: SourceType, url: string): string { + return this.numberSources.get(this.getSourceType(source))[0] + url; + } + + getNumberSource(url: string): SourceType { + let source: SourceType = 'search'; + this.numberSources.forEach((values, key) => { + values.forEach((value) => { + if (value !== '' && url.indexOf(value) !== -1) { + source = key; + } + }); + }); + return source; + } + + getChartSource(url: string): SourceType { + let source: SourceType = 'image'; + this.chartSources.forEach((values, key) => { + values.forEach((value) => { + if (value !== '' && url.indexOf(value) !== -1) { + source = key; + } + }); + }); + return source; + } + + getChartTypes(initialType) { + let types: Option[] = []; + if (this.basicChartTypes.indexOf(initialType) != -1) { (this.allChartTypes).forEach(option => { - if(this.basicChartTypes.indexOf(option.value)!=-1){ + if (this.basicChartTypes.indexOf(option.value) != -1) { types.push(option); } }); return types; - }else if(initialType == "table") { + } else if (initialType == "table") { (this.allChartTypes).forEach(option => { if (initialType == option.value) { types.push(option); } }); return types; - }else { + } else { return this.allChartTypes; } } - isPublicIcon: Map = new Map([ - [true, 'public'], - [false, 'lock'] - ]); - - isActiveIcon: string = 'brightness_1'; - - ignoredParameters = ['index_name','index_id','index_shortName']; - - parametersValidators: Map = new Map([ - ['start_year', [Validators.required, Validators.pattern('^\\d+$')]], - ['end_year', [Validators.required, Validators.pattern('^\\d+$')]] - ]); - - public getFullUrl(stakeholder:Stakeholder, indicatorPath: IndicatorPath, fundingL0: string = null, startYear: string = null, endYear: string = null): string { - let replacedUrl =indicatorPath.chartObject?indicatorPath.chartObject:indicatorPath.url; + + public getFullUrl(stakeholder: Stakeholder, indicatorPath: IndicatorPath, fundingL0: string = null, startYear: string = null, endYear: string = null): string { + let replacedUrl = indicatorPath.chartObject ? indicatorPath.chartObject : indicatorPath.url; + if (stakeholder.statsProfile) { + replacedUrl = replacedUrl.split(ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix).join(stakeholder.statsProfile) + } if (indicatorPath.parameters) { Object.keys(indicatorPath.parameters).forEach(key => { let replacedValue = indicatorPath.parameters[key]; @@ -262,14 +292,14 @@ export class IndicatorUtils { if (key == "index_shortName") { replacedValue = stakeholder.index_shortName.toLowerCase(); } - + replacedUrl = replacedUrl.split(ChartHelper.prefix + key + ChartHelper.suffix).join(replacedValue) }); } if (indicatorPath.chartObject) { if (fundingL0 && indicatorPath.filters["fundingL0"]) { let newJsonObject = JSON.parse(replacedUrl); - for (let queries of this.getQueryObjectName(newJsonObject)?newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)]:newJsonObject[this.getDescriptionObjectName(newJsonObject)]) { + for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) { if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) { queries["query"]["filters"] = []; } @@ -280,8 +310,8 @@ export class IndicatorUtils { } if (startYear && indicatorPath.filters["start_year"]) { let newJsonObject = JSON.parse(replacedUrl); - - for (let queries of this.getQueryObjectName(newJsonObject)?newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)]:newJsonObject[this.getDescriptionObjectName(newJsonObject)]) { + + for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) { if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) { queries["query"]["filters"] = []; } @@ -292,7 +322,7 @@ export class IndicatorUtils { } if (endYear && indicatorPath.filters["end_year"]) { let newJsonObject = JSON.parse(replacedUrl); - for (let queries of this.getQueryObjectName(newJsonObject)?newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)]:newJsonObject[this.getDescriptionObjectName(newJsonObject)]) { + for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) { if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) { queries["query"]["filters"] = []; } @@ -301,23 +331,27 @@ export class IndicatorUtils { } replacedUrl = JSON.stringify(newJsonObject); } - + } - //For numbers (e.g from stats-api , search service, etc) - if(indicatorPath.url.indexOf(ChartHelper.prefix + 'index_id' + ChartHelper.suffix) !=- 1){ - replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_id' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_id)) + //For numbers (e.g. from stats-api , search service, etc) + if (replacedUrl.indexOf(ChartHelper.prefix + 'index_id' + ChartHelper.suffix) != -1) { + replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_id' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_id)); } - if(indicatorPath.url.indexOf(ChartHelper.prefix + 'index_name' + ChartHelper.suffix) !=- 1){ - replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_name' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_name)) + if (replacedUrl.indexOf(ChartHelper.prefix + 'index_name' + ChartHelper.suffix) != -1) { + replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_name' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_name)); } - if(indicatorPath.url.indexOf(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix) !=- 1){ - replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_shortName)) + if (replacedUrl.indexOf(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix) != -1) { + replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_shortName)); } - return (indicatorPath.chartObject?indicatorPath.url + encodeURIComponent(replacedUrl):replacedUrl); + return (indicatorPath.chartObject ? indicatorPath.url + encodeURIComponent(replacedUrl) : replacedUrl); } - public getFullUrlWithFilters(stakeholder:Stakeholder, indicatorPath: IndicatorPath, fundingL0: string = null, startYear: string = null, endYear: string = null, coFunded:boolean=false): string { + + public getFullUrlWithFilters(stakeholder: Stakeholder, indicatorPath: IndicatorPath, fundingL0: string = null, startYear: string = null, endYear: string = null, coFunded: boolean = false): string { indicatorPath.filtersApplied = 0; - let replacedUrl = indicatorPath.chartObject?indicatorPath.chartObject:indicatorPath.url; + let replacedUrl = indicatorPath.chartObject ? indicatorPath.chartObject : indicatorPath.url; + if (stakeholder.statsProfile) { + replacedUrl = replacedUrl.split(ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix).join(stakeholder.statsProfile); + } if (indicatorPath.parameters) { Object.keys(indicatorPath.parameters).forEach(key => { let replacedValue = indicatorPath.parameters[key]; @@ -340,123 +374,119 @@ export class IndicatorUtils { if (key == "index_shortName") { replacedValue = stakeholder.index_shortName.toLowerCase(); } - + replacedUrl = replacedUrl.split(ChartHelper.prefix + key + ChartHelper.suffix).join(replacedValue) }); } if (fundingL0) { - if(indicatorPath.source == "stats-tool" && indicatorPath.chartObject) { + if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) { let filterResults = this.addFilter(replacedUrl, 'fundingL0', fundingL0); replacedUrl = filterResults.url; indicatorPath.filtersApplied += filterResults.filtersApplied; } } if (startYear) { - if(indicatorPath.source == "stats-tool" && indicatorPath.chartObject) { - let filterResults = this.addFilter(replacedUrl, 'start_year', startYear); + if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) { + let filterResults = this.addFilter(replacedUrl, 'start_year', startYear); replacedUrl = filterResults.url; indicatorPath.filtersApplied += filterResults.filtersApplied; } } - if (endYear ) { - if(indicatorPath.source == "stats-tool" && indicatorPath.chartObject) { + if (endYear) { + if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) { let filterResults = this.addFilter(replacedUrl, 'end_year', endYear); replacedUrl = filterResults.url; indicatorPath.filtersApplied += filterResults.filtersApplied; } } - if (coFunded ) { - if(indicatorPath.source == "stats-tool" && indicatorPath.chartObject) { + if (coFunded) { + if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) { let filterResults = this.addFilter(replacedUrl, 'co-funded', endYear); replacedUrl = filterResults.url; indicatorPath.filtersApplied += filterResults.filtersApplied; } } - + //For numbers if (replacedUrl.indexOf(ChartHelper.prefix + 'index_id' + ChartHelper.suffix) != -1) { - replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_id' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_id)) + replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_id' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_id)); } if (replacedUrl.indexOf(ChartHelper.prefix + 'index_name' + ChartHelper.suffix) != -1) { - replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_name' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_name)) + replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_name' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_name)); } if (replacedUrl.indexOf(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix) != -1) { - replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_shortName)) + replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_shortName)); } - //Check apply enhancements return this.applySchemaEnhancements( ..); - return (indicatorPath.chartObject?indicatorPath.url + encodeURIComponent(replacedUrl):replacedUrl); - + //Check apply enhancements return this.applySchemaEnhancements( ..); + return (indicatorPath.chartObject ? indicatorPath.url + encodeURIComponent(replacedUrl) : replacedUrl); + } - private addFilter(replacedUrl, filterType:FilterType, filterValue){ + + private addFilter(replacedUrl, filterType: FilterType, filterValue) { let newJsonObject = JSON.parse(replacedUrl); - let filterApplied:boolean = false; + let filterApplied: boolean = false; let queryIndex = 0; - for (let queries of this.getQueryObjectName(newJsonObject)?newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)]:newJsonObject[this.getDescriptionObjectName(newJsonObject)]) { + for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) { /*Chart with Named Queries*/ - if(queries["query"]["name"] && !queries["query"]["select"]){ - - if(queries["query"]["name"].indexOf("monitor.")==-1 || !queries["query"]["parameters"]){ + if (queries["query"]["name"] && !queries["query"]["select"]) { + + if (queries["query"]["name"].indexOf("monitor.") == -1 || !queries["query"]["parameters"]) { continue; } - if(filterType == 'fundingL0') { + if (filterType == 'fundingL0') { let paramFields = queries["query"]["name"].split(".").slice(3); - let filterPosition = queries["query"]["name"].split(".").indexOf(filterType == "fundingL0" ? 'fl0' : filterType) ; + let filterPosition = queries["query"]["name"].split(".").indexOf(filterType == "fundingL0" ? 'fl0' : filterType); if (filterPosition != -1) { //already filtered //TODO double check if we need to override if the fl0 is already filtered - filterPosition -=3; - /* //update the value - if(paramFields.length == queries["query"]["parameters"].length ){ - //ok - queries["query"]["parameters"][filterPosition] = filterValue; - }else if((paramFields.length + 2) == queries["query"]["parameters"].length || (paramFields.length*2 + 4) == queries["query"]["parameters"].length){ - queries["query"]["parameters"][filterPosition + 2]=filterValue; + filterPosition -= 3; + /* //update the value + if(paramFields.length == queries["query"]["parameters"].length ){ + //ok + queries["query"]["parameters"][filterPosition] = filterValue; + }else if((paramFields.length + 2) == queries["query"]["parameters"].length || (paramFields.length*2 + 4) == queries["query"]["parameters"].length){ + queries["query"]["parameters"][filterPosition + 2]=filterValue; + filterApplied = true; + } + if((paramFields.length*2 + 4) == queries["query"]["parameters"].length){ + queries["query"]["parameters"][(2* filterPosition) + 5]=filterValue; + }*/ + //if applied with the same value mark as filtered + if (paramFields.length == queries["query"]["parameters"].length && queries["query"]["parameters"][filterPosition] == filterValue) { filterApplied = true; - } - if((paramFields.length*2 + 4) == queries["query"]["parameters"].length){ - queries["query"]["parameters"][(2* filterPosition) + 5]=filterValue; - }*/ - //if applied with the same value mark as filtered - if(paramFields.length == queries["query"]["parameters"].length && queries["query"]["parameters"][filterPosition] == filterValue){ - filterApplied = true; - }else if((paramFields.length + 2) == queries["query"]["parameters"].length || (paramFields.length*2 + 4) == queries["query"]["parameters"].length && queries["query"]["parameters"][filterPosition + 2]==filterValue){ + } else if ((paramFields.length + 2) == queries["query"]["parameters"].length || (paramFields.length * 2 + 4) == queries["query"]["parameters"].length && queries["query"]["parameters"][filterPosition + 2] == filterValue) { filterApplied = true; } } else { // if((paramFields.length*2) == queries["query"]["parameters"].length){ // queries["query"]["parameters"].splice(paramFields.length, 0, filterValue); // } - if((paramFields.length*2 + 4) == queries["query"]["parameters"].length){ + if ((paramFields.length * 2 + 4) == queries["query"]["parameters"].length) { queries["query"]["parameters"].splice(paramFields.length + 1, 0, filterValue); } queries["query"]["name"] = queries["query"]["name"] + ".fl0"; queries["query"]["parameters"].push(filterValue); filterApplied = true; } - }else{ + } else { let paramFields = queries["query"]["name"].split(".").slice(3); - // console.debug("Field Params length:" + paramFields.length) - // console.debug(paramFields) - // console.debug("Parameters length:" + queries["query"]["parameters"].length) - - if((paramFields.length + 2) == queries["query"]["parameters"].length || (paramFields.length*2 + 4) == queries["query"]["parameters"].length){ + if ((paramFields.length + 2) == queries["query"]["parameters"].length || (paramFields.length * 2 + 4) == queries["query"]["parameters"].length) { filterApplied = true; - if(filterType == "start_year"){ - queries["query"]["parameters"][0] = parseInt(filterValue); - }else if(filterType == "end_year"){ - queries["query"]["parameters"][1] = parseInt(filterValue); - } + if (filterType == "start_year") { + queries["query"]["parameters"][0] = parseInt(filterValue); + } else if (filterType == "end_year") { + queries["query"]["parameters"][1] = parseInt(filterValue); + } } - if((paramFields.length*2 + 4) == queries["query"]["parameters"].length){ + if ((paramFields.length * 2 + 4) == queries["query"]["parameters"].length) { filterApplied = true; - if(filterType == "start_year"){ + if (filterType == "start_year") { queries["query"]["parameters"][paramFields.length + 2] = parseInt(filterValue); - }else if(filterType == "end_year"){ + } else if (filterType == "end_year") { queries["query"]["parameters"][paramFields.length + 3] = parseInt(filterValue); } } } - // console.debug(queries["query"]) // it is a name query continue; } @@ -466,7 +496,7 @@ export class IndicatorUtils { /*Chart with proper json object*/ //apply the filter in any select fields for (let select of queries["query"]["select"]) { - let filterString = IndicatorFilterUtils.getFilter(select["field"],filterType); + let filterString = IndicatorFilterUtils.getFilter(select["field"], filterType); if (filterString) { let filter = JSON.parse(filterString); //check if filter already exists @@ -508,16 +538,16 @@ export class IndicatorUtils { } queryIndex++; } - return { "url":JSON.stringify(newJsonObject), "filtersApplied":(filterApplied)?1:0}; + return {"url": JSON.stringify(newJsonObject), "filtersApplied": (filterApplied) ? 1 : 0}; } - - isComparingChart(newJsonObject, filter,){ - let queriesCount = this.getQueryObjectName(newJsonObject)?newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)].length:newJsonObject[this.getDescriptionObjectName(newJsonObject)].length; + + isComparingChart(newJsonObject, filter,) { + let queriesCount = this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)].length : newJsonObject[this.getDescriptionObjectName(newJsonObject)].length; let values = []; - if(queriesCount < 2){ + if (queriesCount < 2) { return false; } - for (let queries of this.getQueryObjectName(newJsonObject)?newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)]:newJsonObject[this.getDescriptionObjectName(newJsonObject)]) { + for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) { let filterposition = IndicatorFilterUtils.filterIndexOf(filter, queries["query"]["filters"]); if (filterposition) { if (values.indexOf(queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0]) == -1) { @@ -525,16 +555,17 @@ export class IndicatorUtils { } } } - // console.debug(values); return values.length > 1; } - generateIndicatorByForm(form: any, indicatorPaths: IndicatorPath[], type:IndicatorType, addParameters:boolean = true ): Indicator { + + generateIndicatorByForm(form: any, indicatorPaths: IndicatorPath[], type: IndicatorType, addParameters: boolean = true): Indicator { let indicator: Indicator = new Indicator(form.name, form.description, form.additionalDescription, type, form.width, form.height, form.visibility, indicatorPaths, form.defaultId); indicator._id = form._id; form.indicatorPaths.forEach((indicatorPath, index) => { indicator.indicatorPaths[index].type = indicatorPath.type; - if(addParameters) { + indicator.indicatorPaths[index].format = indicatorPath.format; + if (addParameters) { indicatorPath.parameters.forEach(parameter => { indicator.indicatorPaths[index].parameters[parameter.key] = parameter.value; if (parameter.key === 'type') { @@ -545,24 +576,25 @@ export class IndicatorUtils { }); return indicator; } - generateIndicatorByNumberUrl(source: SourceType, url: string, stakeholder:Stakeholder, jsonPath = [], sourceServices:string[] =[] ): IndicatorPath { + + generateIndicatorByNumberUrl(source: SourceType, url: string, stakeholder: Stakeholder, jsonPath = [], sourceServices: string[] = []): IndicatorPath { let indicatorPath = new IndicatorPath(null, source, url, null, jsonPath); if (source === 'stats-tool') { indicatorPath.url = url.split("json=")[0] + "json="; indicatorPath.url = indicatorPath.url.split("/")[indicatorPath.url.split("/").length - 1]; - indicatorPath.chartObject = decodeURIComponent(url.indexOf("json=")!=-1?url.split("json=")[1]:""); + indicatorPath.chartObject = decodeURIComponent(url.indexOf("json=") != -1 ? url.split("json=")[1] : ""); let chart = JSON.parse(indicatorPath.chartObject); this.parameterizeDefaultQuery(chart, indicatorPath, stakeholder); this.extractStakeHolders(chart, indicatorPath, stakeholder); indicatorPath.chartObject = JSON.stringify(chart); - if(!jsonPath || jsonPath.length == 0 || (jsonPath.length == 1 && jsonPath[0]=="")) { + if (!jsonPath || jsonPath.length == 0 || (jsonPath.length == 1 && jsonPath[0] == "")) { indicatorPath.jsonPath = ["data", "0", "0", "0"]; } // this.addResultFilters(chart, indicatorPath); - }else { - for( let service of sourceServices){ - if(url.indexOf(service)!=-1){ - url = url.split(service)[1] ; + } else { + for (let service of sourceServices) { + if (url.indexOf(service) != -1) { + url = url.split(service)[1]; } } try { @@ -582,7 +614,8 @@ export class IndicatorUtils { } return indicatorPath; } - generateIndicatorByChartUrl(source: SourceType, url: string, type: IndicatorPathType = null, stakeholder:Stakeholder): IndicatorPath { + + generateIndicatorByChartUrl(source: SourceType, url: string, type: IndicatorPathType = null, stakeholder: Stakeholder): IndicatorPath { let indicatorPath = new IndicatorPath(type, source, null, null, []); try { if (source === 'stats-tool') { @@ -590,20 +623,19 @@ export class IndicatorUtils { indicatorPath.url = indicatorPath.url.split("/")[indicatorPath.url.split("/").length - 1]; indicatorPath.chartObject = decodeURIComponent(url.split("json=")[1]); let chart = JSON.parse(indicatorPath.chartObject); - // console.debug(indicatorPath); if (indicatorPath.url == "chart?json=") { - - if (chart["library"] && (chart["library"] == "HighCharts" || chart["library"] == "eCharts" || chart["library"] == "HighMaps" )) { + + if (chart["library"] && (chart["library"] == "HighCharts" || chart["library"] == "eCharts" || chart["library"] == "HighMaps")) { indicatorPath.type = this.extractType(chart, indicatorPath); } else { indicatorPath.type = this.defaultChartType; } - + this.extractTitle(chart, indicatorPath); this.extractSubTitle(chart, indicatorPath); this.extractXTitle(chart, indicatorPath); this.extractYTitle(chart, indicatorPath); - }else if(indicatorPath.url == "table?json="){ + } else if (indicatorPath.url == "table?json=") { indicatorPath.type = "table"; } if (indicatorPath.url == "chart?json=" || indicatorPath.url == "table?json=") { @@ -628,38 +660,39 @@ export class IndicatorUtils { indicatorPath.url = url; indicatorPath.type = type; } - }catch(e){ + } catch (e) { console.error(e); indicatorPath.url = url; indicatorPath.type = type; } - // console.debug(indicatorPath.parameters); - // console.debug(indicatorPath.chartObject); - if(indicatorPath.type == null){ + if (indicatorPath.type == null) { indicatorPath.type = this.defaultChartType; } return indicatorPath; } - private getQueryObjectName(obj){ - if((obj[this.getDescriptionObjectName(obj)]).hasOwnProperty("queriesInfo")){ - return "queriesInfo"; - }else if((obj[this.getDescriptionObjectName(obj)]).hasOwnProperty("queries")) { + + private getQueryObjectName(obj) { + if ((obj[this.getDescriptionObjectName(obj)]).hasOwnProperty("queriesInfo")) { + return "queriesInfo"; + } else if ((obj[this.getDescriptionObjectName(obj)]).hasOwnProperty("queries")) { return "queries"; } } - private getDescriptionObjectName(obj){ - if(obj.hasOwnProperty("mapDescription")){ + + private getDescriptionObjectName(obj) { + if (obj.hasOwnProperty("mapDescription")) { return "mapDescription"; - }else if(obj.hasOwnProperty("chartDescription")) { + } else if (obj.hasOwnProperty("chartDescription")) { return "chartDescription"; - }else if(obj.hasOwnProperty("tableDescription") ){ + } else if (obj.hasOwnProperty("tableDescription")) { return "tableDescription"; - }else if(obj.hasOwnProperty("series") ){ + } else if (obj.hasOwnProperty("series")) { return "series"; } - } + } + private extractType(obj, indicatorPath: IndicatorPath): IndicatorPathType { - let type = (obj[this.getDescriptionObjectName(obj)] && obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)][0]["type"])?obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)][0]["type"]:""; + let type = (obj[this.getDescriptionObjectName(obj)] && obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)][0]["type"]) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)][0]["type"] : ""; if (this.basicChartTypes.indexOf(type) == -1) { type = this.defaultChartType; } else { @@ -668,16 +701,21 @@ export class IndicatorUtils { } return type; } - private extractStakeHolders(obj, indicatorPath: IndicatorPath, stakeholder:Stakeholder) { + + private extractStakeHolders(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) { this.extractFunder(obj, indicatorPath, stakeholder); this.extractRI(obj, indicatorPath, stakeholder); this.extractOrganization(obj, indicatorPath, stakeholder); } - private extractFunder(obj, indicatorPath: IndicatorPath, stakeholder:Stakeholder) { - if(stakeholder.type != "funder"){ + + private extractFunder(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) { + if (stakeholder.type != "funder") { return; } - for (let query of this.getQueryObjectName(obj)?obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]:obj[this.getDescriptionObjectName(obj)]) { + for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) { + if (query["query"]["profile"]) { + query["query"]["profile"] = ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix; + } if (!query["query"]["filters"]) { return; } @@ -698,12 +736,15 @@ export class IndicatorUtils { } } } - - private extractRI(obj, indicatorPath: IndicatorPath, stakeholder:Stakeholder) { - if(stakeholder.type != "ri"){ + + private extractRI(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) { + if (stakeholder.type != "ri") { return; } - for (let query of this.getQueryObjectName(obj)?obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]:obj[this.getDescriptionObjectName(obj)]) { + for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) { + if (query["query"]["profile"]) { + query["query"]["profile"] = ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix; + } if (!query["query"]["filters"]) { return; } @@ -720,14 +761,17 @@ export class IndicatorUtils { } } } - - private extractOrganization(obj, indicatorPath: IndicatorPath, stakeholder:Stakeholder) { + + private extractOrganization(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) { // works for publication.project.organization.name // and publication.organization.name - if(stakeholder.type != "organization"){ + if (stakeholder.type != "organization") { return; } - for (let query of this.getQueryObjectName(obj)?obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]:obj[this.getDescriptionObjectName(obj)]) { + for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) { + if (query["query"]["profile"]) { + query["query"]["profile"] = ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix; + } if (!query["query"]["filters"]) { return; } @@ -744,6 +788,7 @@ export class IndicatorUtils { } } } + private extractStartYear(obj, indicatorPath: IndicatorPath) { let start_year; for (let query of obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) { @@ -761,7 +806,7 @@ export class IndicatorUtils { } } } - + private extractEndYear(obj, indicatorPath: IndicatorPath) { let end_year; for (let query of obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) { @@ -779,31 +824,31 @@ export class IndicatorUtils { } } } - - private parameterizeDefaultQuery(obj, indicatorPath: IndicatorPath, stakeholder:Stakeholder) { + + private parameterizeDefaultQuery(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) { let name = ""; - for (let query of this.getQueryObjectName(obj)?obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]:obj[this.getDescriptionObjectName(obj)]) { + for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) { //monitor.{{stakeholderType}}.{{queryname}} //parameters: stakeholderId*, type if (query["query"]["name"]) { name = query["query"]["name"]; - let parameters = (query["query"]["parameters"])?query["query"]["parameters"]:[]; - if(name.split('.')[0] == "rcd" && parameters.length > 0 && stakeholder.type=="ri") { + let parameters = (query["query"]["parameters"]) ? query["query"]["parameters"] : []; + if (name.split('.')[0] == "rcd" && parameters.length > 0 && stakeholder.type == "ri") { //rcd.{{queryname}} parameters[0] = ChartHelper.prefix + "index_id" + ChartHelper.suffix; indicatorPath.parameters["index_id"] = stakeholder.index_id; - }else if(name.split('.')[0] == "monitor" && parameters.length == 0 && stakeholder.type=="funder"){ + } else if (name.split('.')[0] == "monitor" && parameters.length == 0 && stakeholder.type == "funder") { // old saved queries without params //monitor.{{funder_shortName}}.{{type}}.{{queryname}} let stakeholderSN = name.split('.')[1]; - query["query"]["name"] = name.split('.' + stakeholderSN + ".")[0] + "." + ChartHelper.prefix + "index_shortName" + ChartHelper.suffix +"." + name.split('.' + stakeholderSN + ".")[1]; + query["query"]["name"] = name.split('.' + stakeholderSN + ".")[0] + "." + ChartHelper.prefix + "index_shortName" + ChartHelper.suffix + "." + name.split('.' + stakeholderSN + ".")[1]; indicatorPath.parameters["index_shortName"] = stakeholder.index_shortName.toLowerCase(); - }else if(name.split('.')[0] == "monitor" && parameters.length > 0 && name.split('.')[1] == stakeholder.type) { + } else if (name.split('.')[0] == "monitor" && parameters.length > 0 && name.split('.')[1] == stakeholder.type) { // new parameterized queries //monitor.{{type}}.{{queryname}}.{{param1 - id }}.{{param2 result-type}}.{{fl0}} --> params [start year, end year, id, result type, fl0] - - let index = (name.split('.').slice(3).length +2 == parameters.length)?[2]:((name.split('.').slice(3).length * 2 + 4 == parameters.length)?[2,name.split('.').slice(3).length+4]:[0]); - for(let i of index) { + + let index = (name.split('.').slice(3).length + 2 == parameters.length) ? [2] : ((name.split('.').slice(3).length * 2 + 4 == parameters.length) ? [2, name.split('.').slice(3).length + 4] : [0]); + for (let i of index) { if (name.split('.').length > 3 && name.split('.')[3] == "id") { parameters[i] = ChartHelper.prefix + "index_id" + ChartHelper.suffix; indicatorPath.parameters["index_id"] = stakeholder.index_id; @@ -819,85 +864,87 @@ export class IndicatorUtils { } } } + private extractDataTitle(obj, indicatorPath: IndicatorPath) { let index = 0; - if(!obj[this.getDescriptionObjectName(obj)] || !obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]){ + if (!obj[this.getDescriptionObjectName(obj)] || !obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) { return; } for (let query of obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) { if (query["name"]) { let name = query["name"]; - query["name"] = ChartHelper.prefix + "data_title_"+index + ChartHelper.suffix; - indicatorPath.parameters["data_title_"+index] = name; + query["name"] = ChartHelper.prefix + "data_title_" + index + ChartHelper.suffix; + indicatorPath.parameters["data_title_" + index] = name; } index++; } } + private extractTitle(obj, indicatorPath: IndicatorPath) { let title = ""; if (obj[this.getDescriptionObjectName(obj)]["title"]) { title = obj[this.getDescriptionObjectName(obj)]["title"]["text"]; obj[this.getDescriptionObjectName(obj)]["title"]["text"] = ChartHelper.prefix + "title" + ChartHelper.suffix; - }else if (obj[this.getDescriptionObjectName(obj)]["options"] && obj[this.getDescriptionObjectName(obj)]["options"]["title"]) { + } else if (obj[this.getDescriptionObjectName(obj)]["options"] && obj[this.getDescriptionObjectName(obj)]["options"]["title"]) { title = obj[this.getDescriptionObjectName(obj)]["options"]["title"]; obj[this.getDescriptionObjectName(obj)]["options"]["title"] = ChartHelper.prefix + "title" + ChartHelper.suffix; } indicatorPath.parameters["title"] = title ? title : ""; } - + private extractSubTitle(obj, indicatorPath: IndicatorPath) { let subtitle = ""; if (obj[this.getDescriptionObjectName(obj)]["subtitle"]) { subtitle = obj[this.getDescriptionObjectName(obj)]["subtitle"]["text"]; obj[this.getDescriptionObjectName(obj)]["subtitle"]["text"] = ChartHelper.prefix + "subtitle" + ChartHelper.suffix; indicatorPath.parameters["subtitle"] = subtitle ? subtitle : ""; - }else if (obj[this.getDescriptionObjectName(obj)]["title"] && obj[this.getDescriptionObjectName(obj)]["title"] && obj[this.getDescriptionObjectName(obj)]["title"]["subtext"]) { + } else if (obj[this.getDescriptionObjectName(obj)]["title"] && obj[this.getDescriptionObjectName(obj)]["title"] && obj[this.getDescriptionObjectName(obj)]["title"]["subtext"]) { subtitle = obj[this.getDescriptionObjectName(obj)]["title"]["subtext"]; obj[this.getDescriptionObjectName(obj)]["title"]["subtext"] = ChartHelper.prefix + "subtitle" + ChartHelper.suffix; indicatorPath.parameters["subtitle"] = subtitle ? subtitle : ""; } } - + private extractXTitle(obj, indicatorPath: IndicatorPath) { let title = ""; if (obj[this.getDescriptionObjectName(obj)]["xAxis"] && obj[this.getDescriptionObjectName(obj)]["xAxis"]["title"]) { title = obj[this.getDescriptionObjectName(obj)]["xAxis"]["title"]["text"]; obj[this.getDescriptionObjectName(obj)]["xAxis"]["title"]["text"] = ChartHelper.prefix + "xAxisTitle" + ChartHelper.suffix; - }else if (obj[this.getDescriptionObjectName(obj)]["options"] && obj[this.getDescriptionObjectName(obj)]["options"]["hAxis"] && obj[this.getDescriptionObjectName(obj)]["options"]["hAxis"]["title"]) { + } else if (obj[this.getDescriptionObjectName(obj)]["options"] && obj[this.getDescriptionObjectName(obj)]["options"]["hAxis"] && obj[this.getDescriptionObjectName(obj)]["options"]["hAxis"]["title"]) { title = obj[this.getDescriptionObjectName(obj)]["options"]["hAxis"]["title"]; obj[this.getDescriptionObjectName(obj)]["options"]["hAxis"]["title"] = ChartHelper.prefix + "xAxisTitle" + ChartHelper.suffix; - }else if (obj[this.getDescriptionObjectName(obj)]["xAxis"] && obj[this.getDescriptionObjectName(obj)]["xAxis"]["name"]) { + } else if (obj[this.getDescriptionObjectName(obj)]["xAxis"] && obj[this.getDescriptionObjectName(obj)]["xAxis"]["name"]) { title = obj[this.getDescriptionObjectName(obj)]["xAxis"]["name"]; obj[this.getDescriptionObjectName(obj)]["xAxis"]["name"] = ChartHelper.prefix + "xAxisTitle" + ChartHelper.suffix; } indicatorPath.parameters["xAxisTitle"] = title ? title : ""; } - + private extractYTitle(obj, indicatorPath: IndicatorPath) { let title = ""; - if (obj[this.getDescriptionObjectName(obj)]["yAxis"] && obj[this.getDescriptionObjectName(obj)]["yAxis"]["title"] ) { + if (obj[this.getDescriptionObjectName(obj)]["yAxis"] && obj[this.getDescriptionObjectName(obj)]["yAxis"]["title"]) { title = obj[this.getDescriptionObjectName(obj)]["yAxis"]["title"]["text"]; obj[this.getDescriptionObjectName(obj)]["yAxis"]["title"]["text"] = ChartHelper.prefix + "yAxisTitle" + ChartHelper.suffix; - }else if (obj[this.getDescriptionObjectName(obj)]["options"]&& obj[this.getDescriptionObjectName(obj)]["options"]["vAxis"] && obj[this.getDescriptionObjectName(obj)]["options"]["vAxis"]["title"]) { + } else if (obj[this.getDescriptionObjectName(obj)]["options"] && obj[this.getDescriptionObjectName(obj)]["options"]["vAxis"] && obj[this.getDescriptionObjectName(obj)]["options"]["vAxis"]["title"]) { title = obj[this.getDescriptionObjectName(obj)]["options"]["vAxis"]["title"]; obj[this.getDescriptionObjectName(obj)]["options"]["vAxis"]["title"] = ChartHelper.prefix + "yAxisTitle" + ChartHelper.suffix; - }else if (obj[this.getDescriptionObjectName(obj)]["yAxis"] && obj[this.getDescriptionObjectName(obj)]["yAxis"]["name"]) { + } else if (obj[this.getDescriptionObjectName(obj)]["yAxis"] && obj[this.getDescriptionObjectName(obj)]["yAxis"]["name"]) { title = obj[this.getDescriptionObjectName(obj)]["yAxis"]["name"]; obj[this.getDescriptionObjectName(obj)]["yAxis"]["name"] = ChartHelper.prefix + "xAxisTitle" + ChartHelper.suffix; } indicatorPath.parameters["yAxisTitle"] = title ? title : ""; } - + private extractOldToolTitle(obj, indicatorPath: IndicatorPath) { let title = ""; if (obj["title"]) { title = obj["title"]; obj["title"] = ChartHelper.prefix + "title" + ChartHelper.suffix; indicatorPath.parameters["title"] = title; - + } } - + private extractOldToolXTitle(obj, indicatorPath: IndicatorPath) { let title = ""; if (obj["xaxistitle"]) { @@ -906,7 +953,7 @@ export class IndicatorUtils { indicatorPath.parameters["xAxisTitle"] = title; } } - + private extractOldToolYTitle(obj, indicatorPath: IndicatorPath) { let title = ""; if (obj["fieldsheaders"]) { @@ -919,18 +966,19 @@ export class IndicatorUtils { indicatorPath.parameters["yAxisTitle"] = title; } } - - public checkForSchemaEnhancements(url:string):boolean{ - return url !=this.applySchemaEnhancements(url); + + public checkForSchemaEnhancements(url: string): boolean { + return url != this.applySchemaEnhancements(url); } - public applySchemaEnhancements(url:string):string{ + + public applySchemaEnhancements(url: string): string { let resultEnhancements = [ - [".project.acronym",".project acronym"], - [".project.title",".project title"], - [".project.funder",".project funder"], - [".project.funding level 0",".project funding level 0"], - [".datasource.name",".HostedBy datasource"], - [".datasource.type",".HostedBy datasource type"] + [".project.acronym", ".project acronym"], + [".project.title", ".project title"], + [".project.funder", ".project funder"], + [".project.funding level 0", ".project funding level 0"], + [".datasource.name", ".HostedBy datasource"], + [".datasource.type", ".HostedBy datasource type"] ]; let changes = ""; for (let field of resultEnhancements) { @@ -941,19 +989,17 @@ export class IndicatorUtils { } } } - - if(url.split('json=').length > 1) { + + if (url.split('json=').length > 1) { let obj = JSON.parse(decodeURIComponent(url.split('json=')[1])); - for (let query of this.getQueryObjectName(obj)?obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]:obj[this.getDescriptionObjectName(obj)]) { - if (!query["query"]["profile"] || query["query"]["profile"] == 'OpenAIRE All-inclusive' || query["query"]["profile"] == 'OpenAIRE original') { - changes += (query["query"]["profile"] ? ( "Changed profile \"" + query["query"]["profile"] + "\" to " ):"Added profile ") + " \"monitor\""; + for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) { + if (!query["query"]["profile"] || query["query"]["profile"] == 'OpenAIRE All-inclusive' || query["query"]["profile"] == 'OpenAIRE original') { + changes += (query["query"]["profile"] ? ("Changed profile \"" + query["query"]["profile"] + "\" to ") : "Added profile ") + " \"monitor\""; query["query"]["profile"] = 'monitor'; } } url = url.split('json=')[0] + "json=" + encodeURIComponent(JSON.stringify(obj)); } - console.debug(changes); - console.debug(url); return url; } } diff --git a/src/app/utils/services/cache-indicators.service.ts b/src/app/utils/services/cache-indicators.service.ts new file mode 100644 index 0000000..64320cb --- /dev/null +++ b/src/app/utils/services/cache-indicators.service.ts @@ -0,0 +1,26 @@ +import {Injectable} from "@angular/core"; +import {HttpClient} from "@angular/common/http"; +import {properties} from "../../../environments/environment"; +import {BehaviorSubject, Observable} from "rxjs"; +import {CustomOptions} from "../../openaireLibrary/services/servicesUtils/customOptions.class"; +import {map, tap} from "rxjs/operators"; +import {Report} from "../../../cache-indicators"; + +@Injectable({ + providedIn: 'root' +}) +export class CacheIndicatorsService { + + constructor(private http: HttpClient) { + } + + createReport(alias: string) { + return this.http.post(properties.domain + properties.baseLink + '/cache/' + alias, {}, CustomOptions.registryOptions()) + .pipe(map(res => res.report)); + } + + getReport(alias: string) { + return this.http.get(properties.domain + properties.baseLink + '/cache/' + alias, CustomOptions.registryOptions()) + .pipe(map(res => res.report)); + } +} diff --git a/src/app/utils/services/statistics.service.ts b/src/app/utils/services/statistics.service.ts index 2a85eda..49defe2 100644 --- a/src/app/utils/services/statistics.service.ts +++ b/src/app/utils/services/statistics.service.ts @@ -3,69 +3,23 @@ import {HttpClient} from "@angular/common/http"; import {Observable} from "rxjs"; import {SourceType} from "../../openaireLibrary/monitor/entities/stakeholder"; import {properties} from "../../../environments/environment"; +import {IndicatorUtils} from "../indicator-utils"; @Injectable({ - providedIn: 'root' + providedIn: 'root' }) export class StatisticsService { - - numberSources: Map = new Map(); - chartSources: Map = new Map(); - - constructor(private http:HttpClient) { - this.numberSources.set('statistics', [properties.statisticsAPIURL]); - this.numberSources.set('search', [properties.searchAPIURLLAst]); - this.numberSources.set('stats-tool', [properties.monitorStatsFrameUrl, "http://marilyn.athenarc.gr:8080/stats-api/", "http://88.197.53.71:8080/stats-api/", "https://stats.madgik.di.uoa.gr/stats-api/","https://beta.services.openaire.eu/stats-tool/","https://services.openaire.eu/stats-tool/","https://services.openaire.eu/monitor-stats-tool/"]); - this.chartSources.set('stats-tool', [properties.monitorStatsFrameUrl, "http://marilyn.athenarc.gr:8080/stats-api/", "http://88.197.53.71:8080/stats-api/", "https://stats.madgik.di.uoa.gr/stats-api/","https://beta.services.openaire.eu/stats-tool/","https://services.openaire.eu/stats-tool/","https://services.openaire.eu/monitor-stats-tool/"]); - this.chartSources.set('old', [properties.statisticsFrameAPIURL]); - this.chartSources.set('image', [""]); + + indicatorsUtils = new IndicatorUtils(); + + constructor(private http: HttpClient) {} + + getNumbers(source: SourceType, url: string): Observable { + if (source !== null) { + return this.http.get(this.indicatorsUtils.getNumberUrl(source, url)); + } else { + return this.http.get(url); + } } - getSourceType(source:string):SourceType{ - let sourceType: SourceType = 'search'; - this.numberSources.forEach((values, key) => { - if(key == source) { - sourceType = key; - - } - }); - return sourceType; - } - - getNumbers(source: SourceType, url: string): Observable { - if(source !== null) { - return this.http.get(this.numberSources.get(source)[0] + url); - } else { - return this.http.get(url); - } - } - - getChartUrl(source: SourceType, url: string): string { - return this.chartSources.get(source)[0] + url; - } - getNumberUrl(source: string, url: string): string { - return this.numberSources.get(this.getSourceType(source))[0] + url; - } - getNumberSource(url: string): SourceType { - let source: SourceType = 'search'; - this.numberSources.forEach((values, key) => { - values.forEach((value) => { - if(value !== '' && url.indexOf(value) !== -1) { - source = key; - } - }); - }); - return source; - } - getChartSource(url: string): SourceType { - let source: SourceType = 'image'; - this.chartSources.forEach((values, key) => { - values.forEach((value) => { - if(value !== '' && url.indexOf(value) !== -1) { - source = key; - } - }); - }); - return source; - } } diff --git a/src/app/utils/services/stats-profiles.service.ts b/src/app/utils/services/stats-profiles.service.ts new file mode 100644 index 0000000..0698ea6 --- /dev/null +++ b/src/app/utils/services/stats-profiles.service.ts @@ -0,0 +1,20 @@ +import {Injectable} from "@angular/core"; +import {HttpClient} from "@angular/common/http"; +import {properties} from "../../../environments/environment"; +import {Observable} from "rxjs"; +import {CustomOptions} from "../../openaireLibrary/services/servicesUtils/customOptions.class"; +import {map} from "rxjs/operators"; + +@Injectable({ + providedIn: 'root' +}) +export class StatsProfilesService { + + constructor(private http: HttpClient) { + } + + getStatsProfiles(): Observable { + return this.http.get(properties.monitorStatsFrameUrl + 'schema/profiles') + .pipe(map(profiles => profiles.map(profile => profile.name))); + } +} diff --git a/src/cache-indicators.ts b/src/cache-indicators.ts new file mode 100644 index 0000000..8817488 --- /dev/null +++ b/src/cache-indicators.ts @@ -0,0 +1,262 @@ +import {IndicatorType, Stakeholder} from "./app/openaireLibrary/monitor/entities/stakeholder"; +import axios from "axios"; +import {IndicatorUtils} from "./app/utils/indicator-utils"; +import {Composer} from "./app/openaireLibrary/utils/email/composer"; +import {properties} from "./environments/environment"; +import {error} from "protractor"; + + +export interface CacheItem { + reportId: string, + type: IndicatorType, + url: string +} + +export class Report { + creator: string; + name: string; + success: number; + errors: { + url: string, + status: number + }[]; + total: number; + completed: boolean; + percentage: number + + constructor(total: number, name: string, creator: string) { + this.creator = creator; + this.name = name; + this.success = 0; + this.errors = []; + this.total = total; + this.completed = false; + } + + setPercentage() { + this.percentage = Math.floor((this.success + this.errors.length) / this.total * 100); + } +} + +export class CacheIndicators { + + private static BATCH_SIZE = 10; + + private reports: Map = new Map(); + private queue: CacheItem[] = []; + private process: Promise; + private isFinished: boolean = true; + + stakeholderToCacheItems(stakeholder: Stakeholder) { + let cacheItems: CacheItem[] = []; + let indicatorUtils = new IndicatorUtils(); + stakeholder.topics.forEach(topic => { + topic.categories.forEach(category => { + category.subCategories.forEach(subCategory => { + subCategory.numbers.forEach(section => { + section.indicators.forEach(indicator => { + indicator.indicatorPaths.forEach(indicatorPath => { + let url = indicatorUtils.getNumberUrl(indicatorPath.source, indicatorUtils.getFullUrl(stakeholder, indicatorPath)); + cacheItems.push({ + reportId: stakeholder._id, + type: 'number', + url: url + }); + }); + }); + }); + subCategory.charts.forEach(section => { + section.indicators.forEach(indicator => { + indicator.indicatorPaths.forEach(indicatorPath => { + let url = indicatorUtils.getChartUrl(indicatorPath.source, indicatorUtils.getFullUrl(stakeholder, indicatorPath)); + cacheItems.push({ + reportId: stakeholder._id, + type: 'chart', + url: url + }); + }); + }); + }); + }); + }); + }); + return cacheItems; + } + + public exists(id: string) { + return this.reports.has(id); + } + + public completed(id: string) { + return !this.exists(id) || this.reports.get(id).completed; + } + + public createReport(id: string, cacheItems: CacheItem[], name: string, creator: string) { + let report = new Report(cacheItems.length, name, creator); + this.reports.set(id, report); + this.addItemsToQueue(cacheItems); + return report; + } + + public getReport(id: string) { + return this.reports.get(id); + } + + private async processQueue() { + this.isFinished = false; + while (this.queue.length > 0) { + let batch = this.queue.splice(0, CacheIndicators.BATCH_SIZE); + await this.processBatch(batch); + } + } + + private async processBatch(batch: CacheItem[]) { + let promises: Promise[] = []; + let ids = new Set(); + batch.forEach(item => { + let promise; + ids.add(item.reportId); + if (item.type === 'chart') { + let [url, json] = item.url.split('?json='); + json = decodeURIComponent(json); + json = statsToolParser(JSON.parse(json)); + promise = axios.post(url, json); + } else { + promise = axios.get(item.url); + } + promises.push(promise.then(response => { + let report = this.reports.get(item.reportId); + if (report) { + report.success++; + report.setPercentage(); + } + return response; + }).catch(error => { + let report = this.reports.get(item.reportId); + if (report) { + report.errors.push({url: item.url, status: error.response.status}); + report.setPercentage(); + } + return error.response; + })); + }); + await Promise.all(promises); + ids.forEach(id => { + let report = this.reports.get(id); + if (report?.percentage === 100) { + report.completed = true; + this.sendEmail(report); + } + }); + } + + private addItemsToQueue(cacheItems: CacheItem[]) { + cacheItems.forEach(item => { + this.queue.push(item); + }); + if (this.isFinished) { + this.processQueue().then(() => { + this.isFinished = true; + }); + } + } + + sendEmail(report: Report) { + let email = Composer.composeEmailToReportCachingProcess(report); + axios.post(properties.adminToolsAPIURL + "sendMail/", email).catch(error => { + console.error(error); + }); + } +} + +export function statsToolParser(dataJSONobj: any): any { + let RequestInfoObj = Object.assign({}); + switch (dataJSONobj.library) { + case "GoogleCharts": + //Pass the Chart library to ChartDataFormatter + RequestInfoObj.library = dataJSONobj.library; + RequestInfoObj.orderBy = dataJSONobj.orderBy; + + //Create ChartInfo Object Array + RequestInfoObj.chartsInfo = []; + //Create ChartInfo and pass the Chart data queries to ChartDataFormatter + //along with the requested Chart type + RequestInfoObj.chartsInfo = dataJSONobj.chartDescription.queriesInfo; + break; + case "eCharts": + //Pass the Chart library to ChartDataFormatter + RequestInfoObj.library = dataJSONobj.library; + RequestInfoObj.orderBy = dataJSONobj.orderBy; + + //Create ChartInfo Object Array + RequestInfoObj.chartsInfo = []; + + //Create ChartInfo and pass the Chart data queries to ChartDataFormatter + //along with the requested Chart type + for (let index = 0; index < dataJSONobj.chartDescription.queries.length; index++) { + let element = dataJSONobj.chartDescription.queries[index]; + var ChartInfoObj = Object.assign({}); + + if (element.type === undefined) + ChartInfoObj.type = dataJSONobj.chartDescription.series[index].type; + else + ChartInfoObj.type = element.type; + + if (element.name === undefined) + ChartInfoObj.name = null; + else + ChartInfoObj.name = element.name; + + ChartInfoObj.query = element.query; + RequestInfoObj.chartsInfo.push(ChartInfoObj); + } + break; + case "HighCharts": + RequestInfoObj.library = dataJSONobj.library; + RequestInfoObj.orderBy = dataJSONobj.orderBy; + //Pass the Chart type to ChartDataFormatter + var defaultType = dataJSONobj.chartDescription.chart.type; + //Create ChartInfo Object Array + RequestInfoObj.chartsInfo = []; + //Create ChartInfo and pass the Chart data queries to ChartDataFormatter + //along with the requested Chart type + dataJSONobj.chartDescription.queries.forEach(element => { + var ChartInfoObj = Object.assign({}); + + if (element.type === undefined) + ChartInfoObj.type = defaultType; + else + ChartInfoObj.type = element.type; + + if (element.name === undefined) + ChartInfoObj.name = null; + else + ChartInfoObj.name = element.name; + + ChartInfoObj.query = element.query; + RequestInfoObj.chartsInfo.push(ChartInfoObj); + }); + break; + case "HighMaps": + RequestInfoObj.library = dataJSONobj.library; + //Create ChartInfo Object Array + RequestInfoObj.chartsInfo = []; + + //Create ChartInfo and pass the Chart data queries to ChartDataFormatter + dataJSONobj.mapDescription.queries.forEach(element => { + var ChartInfoObj = Object.assign({}); + + if (element.name === undefined) + ChartInfoObj.name = null; + else + ChartInfoObj.name = element.name; + + ChartInfoObj.query = element.query; + RequestInfoObj.chartsInfo.push(ChartInfoObj); + }); + break; + default: + console.log("Unsupported Library: " + dataJSONobj.library); + } + return RequestInfoObj; +} diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 259c6f5..77ef2c4 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -62,7 +62,6 @@ export let properties: EnvProperties = { cookieDomain: ".di.uoa.gr", feedbackmail: "openaire.test@gmail.com", cacheUrl: "http://scoobydoo.di.uoa.gr:3000/get?url=", - // monitorServiceAPIURL: "https://services.openaire.eu/uoa-monitor-service", monitorServiceAPIURL: "http://duffy.di.uoa.gr:19380/uoa-monitor-service", adminToolsAPIURL: "http://duffy.di.uoa.gr:19380/uoa-monitor-service/", notificationsAPIURL: "http://duffy.di.uoa.gr:19380/uoa-monitor-service/notification/", @@ -75,7 +74,7 @@ export let properties: EnvProperties = { csvLimit: 2000, pagingLimit: 20, resultsPerPage: 10, - baseLink: "/dashboard", + baseLink: "/", domain: "http://mpagasas.di.uoa.gr:4600", searchLinkToResult: "/search/result?id=", searchLinkToPublication: "/search/publication?articleId=", diff --git a/src/index.html b/src/index.html index 456b6f1..797d990 100644 --- a/src/index.html +++ b/src/index.html @@ -4,7 +4,7 @@ - +