Compare commits

..

No commits in common. "master" and "production-release-november-2021" have entirely different histories.

618 changed files with 165187 additions and 1505 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
.angular/
node_modules/
dist/
.idea/

6
.gitmodules vendored
View File

@ -4,6 +4,6 @@
[submodule "src/assets/common-assets"]
path = src/assets/common-assets
url = gitea@code-repo.d4science.org:MaDgIK/openaire-assets.git
[submodule "src/assets/openaire-theme"]
path = src/assets/openaire-theme
url = gitea@code-repo.d4science.org:MaDgIK/openaire-theme.git
[submodule "src/assets/dashboard-theme"]
path = src/assets/dashboard-theme
url = gitea@code-repo.d4science.org:MaDgIK/dashboard-theme.git

View File

@ -22,6 +22,7 @@
"skipTests": true
},
"@schematics/angular:module": {
"skipTests": true
},
"@schematics/angular:pipe": {
"skipTests": true
@ -34,6 +35,7 @@
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"aot": true,
"outputPath": "dist/monitor-dashboard/browser",
"index": "src/index.html",
"main": "src/main.ts",
@ -44,35 +46,23 @@
"src/robots.txt"
],
"styles": [
"src/styles.less",
"src/assets/common-assets/library-css/material.scss"
"src/styles.css",
"src/material.scss"
],
"scripts": [
"src/assets/common-assets/js/copy.js",
"node_modules/uikit/dist/js/uikit.min.js",
"node_modules/uikit/dist/js/uikit-icons.min.js",
"src/assets/common-assets/common/jquery.js",
"src/assets/common-assets/common/uikit.min.js",
"src/assets/common-assets/common/uikit-icons.min.js",
"node_modules/jquery/dist/jquery.js"
],
"vendorChunk": true,
"extractLicenses": false,
"buildOptimizer": false,
"sourceMap": true,
"optimization": false,
"namedChunks": true
]
},
"configurations": {
"development": {
"optimization": {
"scripts": true,
"styles": {
"minify": true,
"inlineCritical": false
},
"fonts": true
},
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
@ -95,17 +85,11 @@
"with": "src/environments/environment.beta.ts"
}
],
"optimization": {
"scripts": true,
"styles": {
"minify": true,
"inlineCritical": false
},
"fonts": true
},
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
@ -140,17 +124,11 @@
"with": "src/environments/environment.prod.ts"
}
],
"optimization": {
"scripts": true,
"styles": {
"minify": true,
"inlineCritical": false
},
"fonts": true
},
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
@ -166,8 +144,7 @@
}
]
}
},
"defaultConfiguration": ""
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
@ -194,7 +171,7 @@
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"src/styles.less"
"src/styles.css"
],
"scripts": [],
"assets": [
@ -202,23 +179,30 @@
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/monitor-dashboard/server",
"main": "server.ts",
"tsConfig": "src/tsconfig.server.json",
"sourceMap": true,
"optimization": false,
"buildOptimizer": false
"tsConfig": "src/tsconfig.server.json"
},
"configurations": {
"development": {
"outputHashing": "media",
"sourceMap": false,
"optimization": true,
"vendorChunk": true,
"buildOptimizer": true
"optimization": true
},
"beta": {
"outputHashing": "media",
@ -229,8 +213,7 @@
}
],
"sourceMap": false,
"optimization": true,
"buildOptimizer": true
"optimization": true
},
"production": {
"outputHashing": "media",
@ -241,11 +224,9 @@
}
],
"sourceMap": false,
"optimization": true,
"buildOptimizer": true
"optimization": true
}
},
"defaultConfiguration": ""
}
},
"serve-ssr": {
"builder": "@nguniversal/builders:ssr-dev-server",
@ -291,8 +272,18 @@
"devServerTarget": "monitor-dashboard:serve:production"
}
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**"
]
}
}
}
}
}
},
"defaultProject": "monitor-dashboard"
}

View File

@ -1,64 +1,61 @@
{
"name": "monitor-dashboard",
"version": "1.0.1",
"version": "1.0.0",
"scripts": {
"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",
"build-dev": "ng build --configuration=development --source-map --base-href /dashboard/",
"build-beta": "ng build --configuration=beta --base-href /dashboard/ --source-map",
"build-prod": "ng build --configuration production --base-href /dashboard/ --source-map",
"build-prod": "ng build --prod --base-href /dashboard/ --sourceMap ",
"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 --port 4600",
"dev:ssr": "ng run monitor-dashboard:serve-ssr",
"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",
"build:ssr-prod": "npm run build-prod && ng run monitor-dashboard:server:production",
"prerender": "ng run monitor-dashboard:prerender",
"after-build-clean": "rm -rf dist/monitor-dashboard/browser/assets/common-assets/.git src/app/openaireLibrary/.git node_modules .angular src/assets/common-assets/.git .git"
"after-build-clean": "rm -rf dist/monitor-dashboard/browser/assets/common-assets/.git src/app/openaireLibrary/.git node_modules src/assets/common-assets/.git .git"
},
"private": true,
"dependencies": {
"@angular/animations": "^16.1.7",
"@angular/cdk": "^16.1.6",
"@angular/common": "^16.1.7",
"@angular/compiler": "^16.1.7",
"@angular/core": "^16.1.7",
"@angular/forms": "^16.1.7",
"@angular/localize": "^16.1.7",
"@angular/material": "^16.1.6",
"@angular/platform-browser": "^16.1.7",
"@angular/platform-browser-dynamic": "^16.1.7",
"@angular/platform-server": "^16.1.7",
"@angular/router": "^16.1.7",
"@nguniversal/express-engine": "^16.1.1",
"axios": "^1.4.0",
"@angular/animations": "~11.2.14",
"@angular/cdk": "^11.2.13",
"@angular/common": "~11.2.14",
"@angular/compiler": "~11.2.14",
"@angular/core": "~11.2.14",
"@angular/forms": "~11.2.14",
"@angular/localize": "^11.2.14",
"@angular/material": "^11.2.13",
"@angular/platform-browser": "~11.2.14",
"@angular/platform-browser-dynamic": "~11.2.14",
"@angular/platform-server": "~11.2.14",
"@angular/router": "~11.2.14",
"@nguniversal/express-engine": "^11.2.1",
"clipboard": "^1.5.16",
"core-js": "^2.5.4",
"express": "^4.15.2",
"jquery": "^3.4.1",
"ng-recaptcha": "^12.0.2",
"ng2-ckeditor": "1.3.7",
"ng-recaptcha": "^7.0.1",
"ng2-ckeditor": "1.3.1",
"rxjs": "^6.5.1",
"ts-md5": "^1.2.0",
"tslib": "^2.0.0",
"uikit": "3.16.24",
"zone.js": "~0.13.1"
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "^16.1.6",
"@angular/cli": "^16.1.6",
"@angular/compiler-cli": "^16.1.7",
"@angular/language-service": "^16.1.7",
"@nguniversal/builders": "^16.1.1",
"@types/ckeditor": "^4.9.10",
"@types/compression": "^1.7.0",
"@angular-devkit/build-angular": "~0.1102.14",
"@angular/cli": "~11.2.14",
"@angular/compiler-cli": "~11.2.14",
"@angular/language-service": "~11.2.14",
"@nguniversal/builders": "^11.2.1",
"@types/express": "^4.17.0",
"@types/compression": "^1.7.0",
"@types/node": "^12.11.1",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^16.18.50",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.8.0",
"jasmine-spec-reporter": "~5.0.0",
@ -69,6 +66,6 @@
"karma-jasmine-html-reporter": "^1.6.0",
"protractor": "~7.0.0",
"ts-node": "~7.0.0",
"typescript": "~4.9.5"
"typescript": "~4.0.7"
}
}

101
server.ts
View File

@ -1,23 +1,14 @@
import 'zone.js/node';
import 'zone.js/dist/zone-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/app/openaireLibrary/monitor-admin/utils/cache-indicators/cache-indicators";
import {Session, User} from "./src/app/openaireLibrary/login/utils/helper.class";
import {UserManagementService} from "./src/app/openaireLibrary/services/user-management.service";
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() {
@ -25,90 +16,22 @@ 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<any>(UserManagementService.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<Stakeholder>(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, {
@ -127,13 +50,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, () => {

View File

@ -1,34 +1,37 @@
import {NgModule} from "@angular/core";
import {RouterModule} from "@angular/router";
import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class";
@NgModule({
imports: [RouterModule.forChild([
{
path: '',
loadChildren: () => import('../openaireLibrary/monitor-admin/general/general.module').then(m => m.GeneralModule),
loadChildren: () => import('../general/general.module').then(m => m.GeneralModule),
data: {hasAdminMenu: true},
pathMatch: 'full'
},
{
path: 'users',
redirectTo: 'users/manager',
pathMatch: 'full'
},
{
path: 'users/:user_type',
loadChildren: () => import('../users/users.module').then(m => m.UsersModule),
data: {hasAdminMenu: true},
pathMatch: 'full'
},
{
matcher: HelperFunctions.routingMatcher(['indicators', 'indicators/:topic']),
loadChildren: () => import('../openaireLibrary/monitor-admin/topic/topic.module').then(m => m.TopicModule),
data: {hasInternalSidebar: true},
path: 'indicators',
loadChildren: () => import('../topic/topic.module').then(m => m.TopicModule),
pathMatch: 'full'
},
{
path: 'indicators/:topic',
loadChildren: () => import('../topic/topic.module').then(m => m.TopicModule),
pathMatch: 'full'
},
{
path: 'admin-tools',
loadChildren: () => import('../admin-tools/admin-tools-routing.module').then(m => m.AdminToolsRoutingModule),
data: {param: 'stakeholder', parentClass: 'monitor'}
data: {
hasAdminMenu: true,
param: 'stakeholder'
}
}
])]
})

View File

@ -1,61 +1,50 @@
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {PreloadAllModules, RouterModule, Routes} from '@angular/router';
import {OpenaireErrorPageComponent} from './error/errorPage.component';
import {AdminLoginGuard} from "./openaireLibrary/login/adminLoginGuard.guard";
import {AdminDashboardGuard} from "./utils/adminDashboard.guard";
import {LoginGuard} from "./openaireLibrary/login/loginGuard.guard";
import {AdminDashboardGuard} from "./openaireLibrary/monitor-admin/utils/adminDashboard.guard";
const routes: Routes = [
{
path: 'reload',
loadChildren: () => import('./reload/libReload.module').then(m => m.LibReloadModule),
data: {hasSidebar: false}
data: {hasSidebar: false, hasHeader: false}
},
{
path: 'user-info',
loadChildren: () => import('./login/libUser.module').then(m => m.LibUserModule),
data: {hasSidebar: false}
data: {hasSidebar: false, isFrontPage: true}
},
{
path: 'error',
component: OpenaireErrorPageComponent,
data: {hasSidebar: false}
data: {hasSidebar: false, isFrontPage: true}
},
{
path: 'admin',
loadChildren: () => import('./openaireLibrary/monitor-admin/manageStakeholders/manageStakeholders.module').then(m => m.ManageStakeholdersModule),
canActivateChild: [LoginGuard],
data: {hasAdminMenu: true, hasSidebar: false}
},
{
path: 'admin/user-info',
loadChildren: () => import('./login/libUser.module').then(m => m.LibUserModule),
data: {hasAdminMenu: true, hasSidebar: false}
loadChildren: () => import('./manageStakeholders/manageStakeholders.module').then(m => m.ManageStakeholdersModule),
data: {hasAdminMenu: true},
canActivateChild: [LoginGuard]
},
{
path: 'admin/admin-tools',
loadChildren: () => import('./admin-tools/portal-admin-tools-routing.module').then(m => m.PortalAdminToolsRoutingModule),
canActivateChild: [AdminLoginGuard],
data: {hasAdminMenu: true, hasSidebar: false}
data: {hasAdminMenu: true}
},
{
path: 'admin/monitor/admin-tools',
loadChildren: () => import('./admin-tools/admin-tools-routing.module').then(m => m.AdminToolsRoutingModule),
canActivateChild: [AdminLoginGuard],
data: {hasAdminMenu: true, hasSidebar: false, portal: 'monitor', monitorCurator: true, parentClass: 'monitor'}
data: {hasAdminMenu: true, portal: 'monitor'}
},
{
path: 'admin/:stakeholder',
loadChildren: () => import('./admin-stakeholder/admin-stakeholder-routing.module').then(m => m.AdminStakeholderRoutingModule),
canActivateChild: [AdminDashboardGuard],
data: {hasAdminMenu: true, hasSidebar: false, activeMenuItem: "manage"}
},
{
path: 'theme',
loadChildren: () => import('./openaireLibrary/utils/theme/theme.module').then(m => m.ThemeModule),
canActivateChild: [AdminLoginGuard],
data: {hasSidebar: false, hasHeader: false, monitorCurator: true, monitorManager: true}
canActivateChild: [AdminDashboardGuard]
},
{path: 'theme', loadChildren: () => import('./openaireLibrary/utils/theme/theme.module').then(m => m.ThemeModule)},
{
path: '',
loadChildren: () => import('./monitor/monitor.module').then(m => m.MonitorModule),
@ -65,12 +54,15 @@ const routes: Routes = [
path: '**',
pathMatch: 'full',
component: OpenaireErrorPageComponent,
data: {hasSidebar: false}
data: {hasSidebar: false, hasAdminMenu: false, isFrontPage: true}
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
imports: [RouterModule.forRoot(routes, {
preloadingStrategy: PreloadAllModules,
onSameUrlNavigation: "reload"
})],
exports: [RouterModule]
})
export class AppRoutingModule {

View File

@ -1,70 +1,31 @@
<div *ngIf="loading">
<div *ngIf="loading == true">
<loading [full]="true"></loading>
</div>
<div *ngIf="!loading" [class.monitor]="isFrontPage">
<div id="modal-container"></div>
<ng-container *ngIf="!isHidden">
<navbar *ngIf="hasHeader" portal="monitor_dashboard" [header]="menuHeader" [userMenuItems]=userMenuItems [menuItems]="menuItems" [user]="user"
[notificationConfiguration]="isMobile && user && notificationGroupsInitialized?notificationConfiguration:null"></navbar>
<div>
<div class="sidebar_main_swipe uk-flex uk-background-default" [class.sidebar_main_active]="open && (hasSidebar || hasAdminMenu || hasInternalSidebar)"
[class.sidebar_mini]="!open && (hasSidebar || hasAdminMenu || hasInternalSidebar)" [class.sidebar_hover]="hover">
<dashboard-sidebar *ngIf="stakeholder && isFrontPage && hasSidebar && !hasInternalSidebar" queryParamsHandling="merge" [items]="sideBarItems"
[activeItem]="activeTopic?activeTopic.alias:null" [activeSubItem]="activeCategory?activeCategory.alias:null"></dashboard-sidebar>
<dashboard-sidebar *ngIf="hasAdminMenu && !hasInternalSidebar" [items]="adminMenuItems" [backItem]="backItem"></dashboard-sidebar>
<main class="uk-width-1-1">
<router-outlet></router-outlet>
</main>
</div>
<bottom id="bottom" *ngIf="isFrontPage" [centered]="true" [properties]="properties" [showMenuItems]="true"></bottom>
<notification-sidebar *ngIf="!isMobile && user && notificationGroupsInitialized" [configuration]="notificationConfiguration" [user]="user"></notification-sidebar>
<cache-indicators *ngIf="stakeholder && !isFrontPage && isCurator()" [alias]="stakeholder.alias"></cache-indicators>
<div *ngIf="view" class="preview uk-text-small uk-flex uk-flex-middle">
<span>You are currently in a <span class="uk-text-bold">"Preview"</span> mode. <span class="uk-visible@m"><a (click)="removeView()">The current view</a> of this dashboard may differ.</span></span>
</div>
</div>
</ng-container>
<div *ngIf="projectUpdate && !isFrontPage" class="project-update">
<div *ngIf="projectUpdate === 'danger'" class="uk-alert uk-alert-danger" uk-alert>
<a class="uk-alert-close" uk-close></a>
<div class="uk-text-bold uk-text-small">Projects Status: Urgent Update Needed</div>
<div class="uk-margin-xsmall-top uk-text-xsmall">
Your project list was last updated more than a year ago. Please send an updated project list to
<a href="mailto:mining@openaire.eu">mining@openaire.eu</a> or contact <a [href]="monitorLink + '/contact-us'">support</a>.
</div>
</div>
<div *ngIf="projectUpdate === 'warning'" class="uk-alert uk-alert-warning" uk-alert>
<a class="uk-alert-close" uk-close></a>
<div class="uk-text-bold uk-text-small">Projects Status: Update Needed</div>
<div class="uk-margin-xsmall-top uk-text-xsmall">
Your project list was last updated between 6 to 12 months ago. Please send an updated project list to
<a href="mailto:mining@openaire.eu">mining@openaire.eu</a> or contact <a [href]="monitorLink + '/contact-us'" target="_blank" class="custom-external">support</a>.
</div>
<div *ngIf="loading == false">
<div class="sidebar_main_swipe" [class.sidebar_main_active]="open && hasSidebar"
[class.sidebar_mini]="!open && hasSidebar" [class.stakeholderPage]="isFrontPage">
<div *ngIf="hasHeader" style="right: 0; top: 0; position: fixed; width: 100%; z-index:981;">
<navbar *ngIf="properties" [properties]="properties" portal="monitor_dashboard" [header]="menuHeader"
[userMenuItems]=userMenuItems [menuItems]="menuItems" [user]="user" [offCanvasFlip]="true"></navbar>
</div>
<dashboard-sidebar *ngIf="stakeholder && isFrontPage && hasSidebar" [items]="sideBarItems"
[activeItem]="activeTopic?activeTopic.alias:null" [showHeader]=true
[specialMenuItem]="specialSideBarMenuItem"
[searchParams]="{}"
[headerUrl]="'https://' + (properties.environment == 'beta' ? 'beta.' : '') +
'monitor.openaire.eu'" queryParamsHandling="merge"
></dashboard-sidebar>
<dashboard-sidebar *ngIf="hasAdminMenu" [items]="adminMenuItems" logoLabel="Admin"
[headerUrl]="'https://' + (properties.environment == 'beta' ? 'beta.' : '') +
'monitor.openaire.eu'" headerPosition="right"
[specialMenuItem]="specialSideBarMenuItem"
></dashboard-sidebar>
<router-outlet></router-outlet>
<bottom *ngIf="isFrontPage" [darkBackground]="false"
[centered]="true" [properties]="properties" [showMenuItems]="true"></bottom>
<role-verification *ngIf="stakeholder"
[id]="stakeholder.alias" [name]="stakeholder.name" [type]="stakeholder.type"></role-verification>
<notification-sidebar *ngIf="user && notificationGroupsInitialized"
[user]="user" [availableGroups]="notificationGroups" service="monitor"></notification-sidebar>
</div>
<div *ngIf="isHidden" class="private-data uk-light dark">
<div class="uk-section uk-section-small uk-container uk-container-small uk-text-center">
<img src="assets/common-assets/logo-services/monitor/inverted.svg" style="height: 80px;">
<h1 class="uk-h4 uk-margin-large-top">Private Content</h1>
<div class="uk-text-large">
The contents of this dashboard are only visible to invited members.
</div>
<div class="uk-margin-large-top uk-margin-large-bottom">
<icon name="incognito" ratio="7"></icon>
</div>
<div class="uk-margin-medium-bottom">
<div *ngIf="!user">
If you are a member of this dashboard, please sign in.
</div>
<div>
If you want to be a member of this dashboard - Contact us.
</div>
</div>
<div class="uk-flex uk-flex-center uk-flex-middle">
<a *ngIf="!user" class="uk-button uk-button-primary uk-margin-right" (click)="login()">Sign in</a>
<a class="uk-button uk-button-secondary" [href]="monitorLink + '/contact-us'">Contact us</a>
</div>
</div>
</div>
<role-verification *ngIf="stakeholder" [id]="stakeholder.alias" [name]="stakeholder.name" [type]="stakeholder.type" [userInfoLink]="monitorLink + '/user-info'"></role-verification>
</div>

View File

@ -1,12 +0,0 @@
@import (reference) "~src/assets/openaire-theme/less/_import-variables";
.project-update {
z-index: @global-z-index;
position: fixed;
bottom: 0;
left: 50%;
right: 50%;
transform: translate(-50%, 0);
width: 500px;
max-width: 60%;
}

View File

@ -1,53 +1,44 @@
import {ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core';
import {ChangeDetectorRef, Component, HostListener, 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';
import {UserManagementService} from "./openaireLibrary/services/user-management.service";
import {StakeholderService} from "./openaireLibrary/monitor/services/stakeholder.service";
import {BehaviorSubject, Subscriber, Subscription} from "rxjs";
import {BehaviorSubject, Subscriber} from "rxjs";
import {LayoutService} from "./openaireLibrary/dashboard/sharedComponents/sidebar/layout.service";
import {MenuItem} from "./openaireLibrary/sharedComponents/menu";
import {
Category,
Stakeholder,
StakeholderEntities,
Topic,
Visibility
} from "./openaireLibrary/monitor/entities/stakeholder";
import {MenuItem, RootMenuItem} from "./openaireLibrary/sharedComponents/menu";
import {Stakeholder, Topic, Visibility} from "./openaireLibrary/monitor/entities/stakeholder";
import {LinksResolver} from "./search/links-resolver";
import {Header} from "./openaireLibrary/sharedComponents/navigationBar.component";
import {arrow_left} from "./openaireLibrary/utils/icons/icons";
import {properties} from "../environments/environment";
import {ConfigurationService} from "./openaireLibrary/utils/configuration/configuration.service";
import {StakeholderConfiguration, StakeholderUtils} from "./openaireLibrary/monitor-admin/utils/indicator-utils";
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";
import {ResourcesService} from "./openaireLibrary/monitor/services/resources.service";
import {StringUtils} from "./openaireLibrary/utils/string-utils.class";
import {
NotificationConfiguration
} from "./openaireLibrary/notifications/notifications-sidebar/notifications-sidebar.component";
import {StakeholderBaseComponent} from "./openaireLibrary/monitor-admin/utils/stakeholder-base.component";
import {SidebarBaseComponent} from "./openaireLibrary/dashboard/sharedComponents/sidebar/sidebar-base.component";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['app.component.less']
templateUrl: './app.component.html'
})
export class AppComponent extends SidebarBaseComponent implements OnInit {
export class AppComponent implements OnInit, OnDestroy {
properties: EnvProperties = properties;
user: User;
updateStakeholder: boolean = true;
params: BehaviorSubject<Params> = new BehaviorSubject<Params>(null);
data: BehaviorSubject<Data> = new BehaviorSubject<Data>(null);
hasSidebar: boolean = false;
hasHeader: boolean = false;
hasAdminMenu: boolean = false;
hasInternalSidebar: boolean = false;
isFrontPage: boolean = false;
isMobile: boolean = false;
view: Visibility;
menuItems: MenuItem[] = [];
isDashboard: boolean = false;
isViewPublic: boolean = false;
sideBarItems: MenuItem[] = [];
specialSideBarMenuItem: MenuItem = null;
menuItems: RootMenuItem[] = [];
notificationGroups: Option[] = [];
notificationGroupsInitialized: boolean = false;
notificationConfiguration: NotificationConfiguration = new NotificationConfiguration();
stakeholderUtils: StakeholderUtils = new StakeholderUtils();
menuHeader: Header = {
route: "/",
@ -55,39 +46,58 @@ export class AppComponent extends SidebarBaseComponent implements OnInit {
title: "Default menu header",
logoUrl: null,
logoSmallUrl: null,
position: 'left',
badge: true,
menuPosition: "center"
position: 'center',
badge: false,
stickyAnimation: false
};
userMenuItems: MenuItem[] = [];
adminMenuItems: MenuItem[] = [];
stakeholder: Stakeholder = null;
activeTopic: Topic = null;
activeCategory: Category = null;
loading: boolean = true;
paramsResolved: boolean = false;
innerWidth;
projectUpdate: 'danger' | 'warning';
paramsSubscription: Subscription;
constructor(protected _route: ActivatedRoute,
protected _router: Router,
protected layoutService: LayoutService,
protected cdr: ChangeDetectorRef,
private subscriptions: any[] = [];
constructor(private route: ActivatedRoute,
private router: Router,
private userManagementService: UserManagementService,
private layoutService: LayoutService,
private smoothScroll: SmoothScroll,
private stakeholderService: StakeholderService,
private configurationService: ConfigurationService,
private resourcesService: ResourcesService) {
super();
this.initRouterParams(_route);
private cdr: ChangeDetectorRef, private configurationService: ConfigurationService) {
this.subscriptions.push(this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
let r = this.route;
while (r.firstChild) {
r = r.firstChild;
}
this.paramsResolved = true;
this.params.next(r.snapshot.params);
this.data.next(r.snapshot.data);
}
}));
}
@HostListener('window:resize', ['$event'])
onResize(event) {
if (this.layoutService.isSmallScreen && event.target.innerWidth > 1219) {
this.layoutService.setSmallScreen(false);
} else if (!this.layoutService.isSmallScreen && event.target.innerWidth < 1219) {
this.layoutService.setSmallScreen(true);
this.layoutService.setOpen(false);
}
}
ngOnInit() {
super.ngOnInit();
if (typeof document !== 'undefined' && window) {
this.innerWidth = window.innerWidth;
}
this.subscriptions.push(this.layoutService.hasSidebar.subscribe(hasSidebar => {
this.hasSidebar = hasSidebar;
this.cdr.detectChanges();
}));
this.subscriptions.push(this.layoutService.hasHeader.subscribe(hasHeader => {
this.hasHeader = hasHeader;
this.cdr.detectChanges();
@ -100,146 +110,108 @@ export class AppComponent extends SidebarBaseComponent implements OnInit {
this.isFrontPage = isFrontPage;
this.cdr.detectChanges();
}));
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
this.subscriptions.push(this.layoutService.isDashboard.subscribe(isDashboard => {
this.isDashboard = isDashboard;
this.cdr.detectChanges();
}));
this._route.queryParams.subscribe(params => {
this.view = params['view'];
if(this.stakeholder) {
this.setSideBar();
}
this.route.queryParams.subscribe(params => {
this.isViewPublic = (params['view'] == 'public');
});
this.layoutService.setSmallScreen((this.innerWidth && this.innerWidth < 1219));
this.layoutService.setOpen(!(this.innerWidth && this.innerWidth < 1219));
this.subscriptions.push(this.params.subscribe(params => {
if (this.paramsResolved) {
this.loading = true;
let isSearch = this.router.url.includes('/search/');
if (params && params['stakeholder']) {
// this.stakeholder = this.stakeholderService.stakeholder;
if (!this.stakeholder || this.stakeholder.alias !== params['stakeholder']) {
this.subscriptions.push(this.stakeholderService.getStakeholder(params['stakeholder']).subscribe(stakeholder => {
if (stakeholder) {
this.stakeholder = stakeholder;
LinksResolver.setProperties(this.stakeholder.alias);
this.setProperties(this.stakeholder.alias, this.stakeholder.type);
if (isSearch) {
this.activeTopic = null;
} else if (params && params['topic'] && !this.activeTopic) {
this.activeTopic = this.stakeholder.topics.find(topic => topic.alias === decodeURIComponent(params['topic']) && this.isPublicOrIsMember(topic.visibility));
} else {
this.activeTopic = this.stakeholder.topics.find(topic => this.isPublicOrIsMember(topic.visibility));
}
this.setSideBar();
this.buildMenu();
this.loading = false;
} else {
this.stakeholder = null;
LinksResolver.resetProperties();
this.navigateToError();
this.buildMenu();
this.loading = false;
}
}));
} else {
this.buildMenu();
if (isSearch) {
this.activeTopic = null;
} else if (params && params['topic']) {
this.activeTopic = this.stakeholder.topics.find(topic => topic.alias === decodeURIComponent(params['topic']) && this.isPublicOrIsMember(topic.visibility));
} else {
this.activeTopic = this.stakeholder.topics.find(topic => this.isPublicOrIsMember(topic.visibility));
}
this.loading = false;
}
} else {
LinksResolver.resetProperties();
this.stakeholderService.setStakeholder(null);
this.layoutService.setOpen(!(this.innerWidth && this.innerWidth < 1219));
this.stakeholder = null;
this.buildMenu();
this.loading = false;
}
}
}));
this.subscriptions.push(this.data.subscribe(data => {
if (data && data.portal) {
if(data && data.portal) {
this.setProperties(data.portal);
this.configurationService.initPortal(this.properties, this.properties.adminToolsCommunity);
this.configurationService.initCommunityInformation(this.properties, this.properties.adminToolsCommunity);
}
}));
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
this.updateStakeholder = !this._router.url.includes('user-info');
this.user = user;
if (user) {
this.user = user;
if (!this.notificationGroupsInitialized) {
this.setNotificationConfiguration();
this.buildMenu();
if(!this.notificationGroupsInitialized) {
this.setNotificationGroups();
}
} else if(this.user) {
this.user = user;
this.notificationGroupsInitialized = false;
this.notificationConfiguration.availableGroups = [];
}
if(this.paramsSubscription) {
this.paramsSubscription.unsubscribe();
}
this.paramsSubscription = this.params.subscribe(params => {
if (this.paramsResolved) {
this.loading = true;
if (params && params['stakeholder']) {
if (!this.stakeholder || this.stakeholder.alias !== params['stakeholder'] || this.updateStakeholder) {
this.subscriptions.push(this.stakeholderService.getStakeholder(params['stakeholder'], this.updateStakeholder).subscribe(stakeholder => {
if (stakeholder) {
this.stakeholder = stakeholder;
this.updateStakeholder = false;
LinksResolver.setProperties(this.stakeholder.alias);
this.setProperties(this.stakeholder.alias, this.stakeholder.type);
this.buildMenu();
this.setActives(params);
this.setSideBar();
this.loading = false;
} else {
this.stakeholder = null;
LinksResolver.resetProperties();
this.navigateToError();
this.buildMenu();
this.loading = false;
}
}));
} else {
this.buildMenu();
this.setActives(params);
this.loading = false;
}
} else {
LinksResolver.resetProperties();
this.stakeholderService.setStakeholder(null);
this.stakeholder = null;
this.buildMenu();
this.loading = false;
}
}
});
this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
this.setProjectUpdate(stakeholder);
}))
}));
}
setActives(params: Params) {
if (params && params['topic']) {
this.activeTopic = this.stakeholder.topics.find(topic => topic.alias === decodeURIComponent(params['topic']) && this.hasPermission(topic.visibility));
} else {
this.activeTopic = this.stakeholder.topics.find(topic => this.hasPermission(topic.visibility));
public setNotificationGroups() {
this.notificationGroups = [];
if(Session.isPortalAdministrator(this.user)) {
this.notificationGroups.push({value: Role.PORTAL_ADMIN, label: 'Portal Administrators'});
}
if(this.activeTopic) {
if (params && params['category']) {
this.activeCategory = this.activeTopic.categories.find(category => category.alias === decodeURIComponent(params['category']) && this.hasPermission(category.visibility));
} else {
this.activeCategory = this.activeTopic.categories.find(category => this.hasPermission(category.visibility));
}
}
}
public setNotificationConfiguration() {
this.notificationConfiguration.entities = this.stakeholderUtils.types.map(option => option.value);
this.notificationConfiguration.service = 'monitor';
this.notificationConfiguration.availableGroups = [];
if (Session.isPortalAdministrator(this.user)) {
this.notificationConfiguration.availableGroups.push({value: Role.PORTAL_ADMIN, label: 'Portal Administrators'});
}
for (let type of this.stakeholderUtils.types) {
if (Session.isCurator(type.value, this.user) || Session.isPortalAdministrator(this.user)) {
this.notificationConfiguration.availableGroups.push({value: Role.curator(type.value), label: type.label + ' Curators'});
this.notificationConfiguration.availableGroups.push({value: Role.typeManager(type.value), label: type.label + ' Managers'});
this.notificationConfiguration.availableGroups.push({value: Role.typeMember(type.value), label: type.label + ' Members'});
for(let type of this.stakeholderUtils.types) {
if(Session.isCurator(type.value, this.user) || Session.isPortalAdministrator(this.user)) {
this.notificationGroups.push({value: Role.curator(type.value), label: type.label + ' Curators'});
}
}
this.subscriptions.push(this.stakeholderService.getMyStakeholders(this.properties.monitorServiceAPIURL).subscribe(stakeholders => {
stakeholders.forEach(stakeholder => {
this.notificationConfiguration.availableGroups.push({
value: Role.manager(stakeholder.type, stakeholder.alias),
label: stakeholder.name + ' Managers'
});
this.notificationConfiguration.availableGroups.push({
value: Role.member(stakeholder.type, stakeholder.alias),
label: stakeholder.name + ' Members'
});
this.notificationGroups.push({value: Role.manager(stakeholder.type, stakeholder.alias), label: stakeholder.name + ' Managers'});
this.notificationGroups.push({value: Role.member(stakeholder.type, stakeholder.alias), label: stakeholder.name + ' Members'});
});
this.notificationGroupsInitialized = true;
}));
}
public setProjectUpdate(stakeholder: Stakeholder) {
if(stakeholder?.projectUpdateDate && this.user) {
let today = new Date();
let date = new Date(stakeholder.projectUpdateDate);
let months = (today.getFullYear() - date.getFullYear())*12 + (today.getMonth() - date.getMonth());
if(months >= 12) {
this.projectUpdate = 'danger';
} else if (months >= 6 && months < 12) {
this.projectUpdate = 'warning';
} else {
this.projectUpdate = null;
}
} else {
this.projectUpdate = null;
}
}
public ngOnDestroy() {
super.ngOnDestroy();
if(this.paramsSubscription) {
this.paramsSubscription.unsubscribe();
}
this.subscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();
}
});
this.userManagementService.clearSubscriptions();
this.layoutService.clearSubscriptions();
this.stakeholderService.clearSubscriptions();
@ -248,198 +220,219 @@ export class AppComponent extends SidebarBaseComponent implements OnInit {
}
private navigateToError() {
this._router.navigate([this.properties.errorLink], {queryParams: {'page': this.properties.baseLink + this._router.url}});
this.router.navigate(['/error'], {queryParams: {'page': this.properties.baseLink + this.router.url}});
}
public removeView() {
this._router.navigate([], {relativeTo: this._route});
}
public login() {
this.userManagementService.login();
}
get isHidden() {
return this.stakeholder && !this.hasPermission(this.view?this.view:this.stakeholder.visibility);
}
get monitorLink() {
return "https://" + (this.properties.environment == 'beta' ? 'beta.' : '') + 'monitor.openaire.eu';
public get open() {
return this.layoutService.open;
}
private setSideBar() {
let items: MenuItem[] = [];
if (this.hasPermission(this.view?this.view:this.stakeholder.visibility)) {
this.stakeholder.topics.forEach((topic: Topic) => {
if (this.hasPermission(topic.visibility)) {
let topicItem: MenuItem = new MenuItem(topic.alias, topic.name, "", '/' + this.stakeholder.alias + '/' + topic.alias,
null, [], [], {}, {svg: topic.icon}, null, null, (
'/' + this.stakeholder.alias + '/' + topic.alias));
topicItem.items = topic.categories.filter(category => this.hasPermission(category.visibility)).map(category => {
return new MenuItem(category.alias, category.name, "", ('/' + this.stakeholder.alias + '/' + topic.alias + '/' + category.alias),
null, [], [], {}, {svg: topic.icon}, null, null,
('/' + this.stakeholder.alias + '/' + topic.alias + '/' + category.alias));
});
if (this.isPublicOrIsMember(this.stakeholder.visibility)) {
this.stakeholder.topics.forEach((topic) => {
if (this.isPublicOrIsMember(topic.visibility)) {
let topicItem: MenuItem = new MenuItem(topic.alias, topic.name, "", (
'/' + this.stakeholder.alias + '/' + topic.alias),
null, [], [], {});
topicItem.icon = topic.icon;
items.push(topicItem);
}
});
if (items.length === 0) {
items.push(new MenuItem('noTopics', 'No topics available yet', "", "", false, [], [], {}));
}
} else {
let topicItem: MenuItem = new MenuItem("private", "Private Data", "", "", null, [], [], {});
items.push(topicItem);
}
this.adminMenuItems = [];
this.adminMenuItems.push(new MenuItem("general", "General", "", "/admin/" + this.stakeholder.alias, false, [], [], {}, {name: 'badge'}));
this.adminMenuItems.push(new MenuItem("indicators", "Indicators", "", "/admin/" + this.stakeholder.alias + '/indicators', false, [], [], {}, {name: 'bar_chart'}, null, "uk-visible@m"));
if (this.stakeholder.defaultId) {
this.adminMenuItems.push(new MenuItem("users", "Users", "", "/admin/" + this.stakeholder.alias + "/users", false, [], [], {}, {name: 'group'}, null, "uk-visible@m", "/admin/" + this.stakeholder.alias + "/users"));
if (this.isCurator()) {
this.adminMenuItems.push(new MenuItem("admin-tools", "Pages & Entities", "", "/admin/" + this.stakeholder.alias + "/admin-tools/pages", false, [], [], {}, {name: 'description'}, null, "uk-visible@m", "/admin/" + this.stakeholder.alias + "/admin-tools"));
}
}
this.backItem = new MenuItem("back", "Manage profiles", "", "/admin", false, [], null, {}, {name: 'west'});
this.sideBarItems = items;
this.hasSidebar = this.hasSidebar && this.sideBarItems.length > 0;
}
buildMenu() {
this.menuItems = [];
this.adminMenuItems = [];
this.userMenuItems = [];
if (this.user) {
if (this.isKindOfMonitorManager()) {
if (this.isCurator()) {
this.userMenuItems.push(new MenuItem("", "Manage profiles",
"", "/admin", false, [], [], {}));
}
if (Session.isPortalAdministrator(this.user)) {
this.userMenuItems.push(new MenuItem("adminOptions", "Super Admin options", "", "/admin/admin-tools/portals", false, [], [], {},null, null, "uk-visible@m"));
}
if (this.isCurator()) {
this.userMenuItems.push(new MenuItem("monitorOptions", "Monitor options", "", "/admin/monitor/admin-tools/pages", false, [], [], {},null, null, "uk-visible@m"));
if(Session.isPortalAdministrator(this.user) ) {
this.userMenuItems.push( new MenuItem("adminOptions", "Super Admin options","", "/admin/admin-tools/portals", false, [], [], {}));
this.userMenuItems.push(new MenuItem("monitorOptions", "Monitor portal options","", "/admin/monitor/admin-tools/pages", false, [], [], {}));
}
this.userMenuItems.push(new MenuItem("", "User information", "", "/user-info", false, [], [], {}));
}
if (this.stakeholder) {
this.userMenuItems.push(new MenuItem("", "User information", "", "/" + this.stakeholder.alias + "/user-info", false, [], [], {}));
if (this.hasPermission((this.view && this.isManager(this.stakeholder))?this.view:this.stakeholder.visibility)) {
this.menuItems.push(
new MenuItem("dashboard", "Dashboard",
"", "/" + this.stakeholder.alias, false, [], null, {}
, null, null, null, null)
);
this.menuItems.push(
new MenuItem("search", "Browse Data", "", this.properties.searchLinkToResults,
false, [], null, {resultbestaccessright: '"' + encodeURIComponent("Open Access") + '"'},
null, null, null, null)
);
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",
"", "/" + this.stakeholder.alias + "/develop", false, [], null, {})
);
}
}
if (this.isManager(this.stakeholder)) {
this.menuItems.push(
new MenuItem("manage", "Manage",
"", "/admin/" + this.stakeholder.alias, false, [], null, {}
, null, null, "uk-visible@m", null)
);
}
if (!this.hasAdminMenu && this.isFrontPage) {
if (!this.isDashboard) {
this.menuHeader = {
route: './' + this.stakeholder.alias,
url: null,
title: this.stakeholder.name,
logoUrl: StringUtils.getLogoUrl(this.stakeholder),
logoSmallUrl: StringUtils.getLogoUrl(this.stakeholder),
logoInfo: '<div class="uk-margin-left uk-width-medium"><div class="uk-margin-remove uk-text-background uk-text-bold uk-text-small">Monitor Dashboard</div>' +
'<div class="uk-h6 uk-text-truncate uk-margin-remove">' + this.stakeholder.name + '</div></div>',
route: null,
url: "https://" + (this.properties.environment == 'beta' ? 'beta.' : '') + 'monitor.openaire.eu',
title: "Monitor",
logoUrl: 'assets/common-assets/logo-large-monitor.png',
logoSmallUrl: "assets/common-assets/logo-small-monitor.png",
position: 'left',
badge: true,
menuPosition: "center"
stickyAnimation: false
};
this.menuItems.push({
rootItem: new MenuItem("dashboard", "Dashboard",
"", "/" + this.stakeholder.alias, false, [], null, {}), items: []
});
this.menuItems.push({
rootItem: new MenuItem("methodology", "Methodology",
"", "/" + this.stakeholder.alias + "/methodology", false, [], null, {}), items: [
new MenuItem("methodology", "Terminology and construction",
"", "/" + this.stakeholder.alias + "/methodology", false, [], null, {}),
new MenuItem("methodology", "See how it works",
"", "/" + this.stakeholder.alias + "/methodology", false, [], null, {}, null, "how"),
]
});
if(this.stakeholder.type === "funder") {
this.menuItems.push({
rootItem: new MenuItem("develop", "Develop",
"", "/" + this.stakeholder.alias + "/develop", false, [], null, {}), items: []
});
}
if (this.isCurator()) {
this.menuItems.push({
rootItem: new MenuItem("manage", "Manage",
"", "/admin", false, [], null, {}), items: []
});
}
}
else if (this.isFrontPage) {
this.menuHeader = {
route: "/" + this.stakeholder.alias,
url: null,
title: this.stakeholder.name,
logoUrl: null,
logoSmallUrl: null,
position: 'center',
badge: false,
stickyAnimation: false
};
this.menuItems.push({
rootItem: new MenuItem("methodology", "Methodology",
"", "/" + this.stakeholder.alias + "/methodology", false, [], null, {}), items: [
new MenuItem("methodology", "Terminology and construction",
"", "/" + this.stakeholder.alias + "/methodology", false, [], null, {}),
new MenuItem("methodology", "See how it works",
"", "/" + this.stakeholder.alias + "/methodology", false, [], null, {}, null, "how"),
]
});
if(this.stakeholder.type === "funder") {
this.menuItems.push({
rootItem: new MenuItem("develop", "Develop",
"", "/" + this.stakeholder.alias + "/develop", false, [], null, {}), items: []
});
}
if (this.isCurator()) {
this.menuItems.push({
rootItem: new MenuItem("manage", "Manage",
"", "/admin", false, [], null, {}), items: []
});
}
if (this.isPublicOrIsMember(this.stakeholder.visibility)) {
this.specialSideBarMenuItem = new MenuItem("search", "Search research outcomes", "", this.properties.searchLinkToResults, false, [], null, {resultbestaccessright: '"' + encodeURIComponent("Open Access") + '"'});
this.specialSideBarMenuItem.icon = '<span uk-icon="search"></span>';
} else {
this.specialSideBarMenuItem = null;
}
} else {
this.menuHeader = {
route: './' + this.stakeholder.alias,
route: "/admin/" + this.stakeholder.alias,
url: null,
title: this.stakeholder.name,
logoUrl: StringUtils.getLogoUrl(this.stakeholder),
logoSmallUrl: StringUtils.getLogoUrl(this.stakeholder),
logoInfo: '<div class="uk-margin-left uk-width-medium"><div class="uk-margin-remove uk-text-background uk-text-bold uk-text-small">Monitor Admin Dashboard</div>' +
'<div class="uk-h6 uk-text-truncate uk-margin-remove">' + this.stakeholder.name + '</div></div>',
position: 'left',
badge: true,
menuPosition: "center"
title: 'Admin - ' + this.stakeholder.name,
logoUrl: null,
logoSmallUrl: null,
position: 'center',
badge: false,
stickyAnimation: false
};
this.menuItems.push({
rootItem: new MenuItem("", "Dashboard",
"", '/' + this.stakeholder.alias + '/', false, [], null, {}), items: []
});
this.adminMenuItems.push(new MenuItem("general", "General", "", "/admin/" + this.stakeholder.alias, false, [], [], {}, "<i uk-icon=\"image\"></i>"));
this.adminMenuItems.push(new MenuItem("indicators", "Indicators", "", "/admin/" + this.stakeholder.alias + '/indicators', false, [], [], {}, "<i uk-icon=\"image\"></i>"));
if(this.stakeholder.defaultId) {
this.adminMenuItems.push(new MenuItem("users", "Users", "", "/admin/" + this.stakeholder.alias + "/users", false, [], [], {}, "<i uk-icon=\"users\"></i>"));
if (Session.isPortalAdministrator(this.user)) {
this.adminMenuItems.push(new MenuItem("admin-tools", "Pages & Entities", "", "/admin/" + this.stakeholder.alias + "/admin-tools/pages", false, [], [], {}, null, null, null, "/admin/" + this.stakeholder.alias + "/admin-tools"));
}
}
this.specialSideBarMenuItem = new MenuItem("back", "Manage profiles", "", "/admin", false, [], null, {});
this.specialSideBarMenuItem.icon = '<span class="uk-icon-button small uk-icon uk-button-secondary">' + arrow_left.data + '</span>'; // '<span class="uk-icon-button uk-icon portal-button " uk-icon="chevron-left"></span>';
this.specialSideBarMenuItem.customClass = 'uk-text-uppercase uk-text-bold uk-text-secondary';
}
} else {
this.userMenuItems.push(new MenuItem("", "User information", this.monitorLink + '/user-info', '', false, [], [], {}, null, null, null, null, "_self"));
this.menuHeader = {
route: null,
url: "https://" + (this.properties.environment == 'beta' ? 'beta.' : '') + 'monitor.openaire.eu',
title: "Monitor",
logoUrl: 'assets/common-assets/logo-services/monitor/main.svg',
logoSmallUrl: "assets/common-assets/logo-services/monitor/small.svg",
position: 'left',
badge: true,
menuPosition: "center"
};
this.menuItems.push(
new MenuItem("stakeholders", "Browse " + this.stakeholderUtils.entities.stakeholders,
this.monitorLink + '/browse', "", false, [], null, {}, null, null, null, null, "_self")
);
this.resourcesService.setResources(this.menuItems, '', this.monitorLink);
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) {
if (this.isFrontPage || !this.hasAdminMenu) {
this.menuHeader = {
route: null,
url: "https://" + (this.properties.environment == 'beta' ? 'beta.' : '') + 'monitor.openaire.eu',
title: "Monitor",
logoUrl: 'assets/common-assets/logo-large-monitor.png',
logoSmallUrl: "assets/common-assets/logo-small-monitor.png",
position: 'left',
badge: true,
stickyAnimation: false
};
this.menuItems.push({
rootItem: new MenuItem("about", "About",
"https://" + (this.properties.environment == 'beta' ? 'beta.' : '') + 'monitor.openaire.eu/about/learn-how', "", false, [], null, {}),
items: []
});
this.menuItems.push({
rootItem: new MenuItem("browse", "Browse",
"https://" + (this.properties.environment == 'beta' ? 'beta.' : '') + 'monitor.openaire.eu/browse', "", false, [], null, {}),
items: []
});
this.menuItems.push({
rootItem: new MenuItem("contact", "Contact us",
"https://" + (this.properties.environment == 'beta' ? 'beta.' : '') + 'monitor.openaire.eu/contact-us', "", false, [], null, {}),
items: []
});
} else {
this.menuHeader = {
route: "/",
url: null,
title: "Monitor Dashboard",
logoUrl: null,
logoSmallUrl: null,
position: 'center',
badge: false,
stickyAnimation: false
};
this.adminMenuItems = [];
this.backItem = null;
this.adminMenuItems.push(new MenuItem("stakeholders", "Manage profiles", "", "/admin", false, [], [], {}, {name: 'settings'}));
if (Session.isPortalAdministrator(this.user)) {
this.adminMenuItems.push(new MenuItem("adminOptions", "Super Admin options", "", "/admin/admin-tools/portals", false, [], [], {}, {name: 'settings'}, null, "uk-visible@m", '/admin/admin-tools'));
}
if (Session.isPortalAdministrator(this.user) || Session.isMonitorCurator(this.user)) {
this.adminMenuItems.push(new MenuItem("monitorOptions", "Monitor options", "", "/admin/monitor/admin-tools/pages", false, [], [], {}, {name: 'settings'}, null, "uk-visible@m", '/admin/monitor/admin-tools'));
}
this.hasAdminMenu = this.hasAdminMenu && this.adminMenuItems.length > 1;
this.specialSideBarMenuItem = null;
this.adminMenuItems.push(new MenuItem("stakeholders", "Manage profiles", "", "/admin", false, [], [], {}, "<i uk-icon=\"cog\"></i>"));
}
}
}
public isCurator() {
return this.user && (Session.isPortalAdministrator(this.user) || Session.isMonitorCurator(this.user));
}
public isKindOfMonitorManager() {
return this.user && (Session.isPortalAdministrator(this.user) || Session.isMonitorCurator(this.user) || Session.isKindOfMonitorManager(this.user));
}
public isMember(stakeholder: Stakeholder) {
return this.user && (Session.isPortalAdministrator(this.user) || Session.isCurator(stakeholder.type, this.user)
|| Session.isManager(stakeholder.type, stakeholder.alias, this.user) || Session.isMember(stakeholder.type, stakeholder.alias, this.user));
}
public isManager(stakeholder: Stakeholder) {
return this.user && (Session.isPortalAdministrator(this.user) || Session.isCurator(stakeholder.type, this.user) || Session.isManager(stakeholder.type, stakeholder.alias, this.user));
}
public hasPermission(visibility: Visibility): boolean {
if(visibility === 'PUBLIC') {
return true;
} else if(visibility === 'RESTRICTED') {
return (!this.view || this.view === 'RESTRICTED') && this.isMember(this.stakeholder);
} else {
return !this.view && this.isManager(this.stakeholder);
}
public isPublicOrIsMember(visibility: Visibility): boolean {
return !(visibility == "PRIVATE" || (this.isViewPublic && visibility != "PUBLIC"));
}
setProperties(id, type = null) {
setProperties(id, type = null){
this.properties.adminToolsCommunity = id;
if (type) {
if(type) {
this.properties.adminToolsPortalType = type;
} else {
ConnectHelper.setPortalTypeFromPid(id);
}
this.configurationService.initPortal(this.properties, this.properties.adminToolsCommunity);
this.configurationService.initCommunityInformation(this.properties, this.properties.adminToolsCommunity);
}
}

View File

@ -1,8 +1,8 @@
import {APP_ID, NgModule} from '@angular/core';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {CommonModule} from '@angular/common';
import {HTTP_INTERCEPTORS, HttpClientModule} from "@angular/common/http";
import {BrowserModule} from '@angular/platform-browser';
import {BrowserModule, BrowserTransferStateModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {AppComponent} from './app.component';
import {OpenaireErrorPageComponent} from './error/errorPage.component';
@ -21,18 +21,12 @@ import {HttpInterceptorService} from "./openaireLibrary/http-interceptor.service
import {DEFAULT_TIMEOUT, TimeoutInterceptor} from "./openaireLibrary/timeout-interceptor.service";
import {ErrorInterceptorService} from "./openaireLibrary/error-interceptor.service";
import {AdminLoginGuard} from "./openaireLibrary/login/adminLoginGuard.guard";
import {
NotificationsSidebarModule
} from "./openaireLibrary/notifications/notifications-sidebar/notifications-sidebar.module";
import {AdminDashboardGuard} from "./utils/adminDashboard.guard";
import {NotificationsSidebarModule} from "./openaireLibrary/notifications/notifications-sidebar/notifications-sidebar.module";
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 {AdminDashboardGuard} from "./openaireLibrary/monitor-admin/utils/adminDashboard.guard";
import {CacheIndicatorsModule} from "./openaireLibrary/monitor-admin/utils/cache-indicators/cache-indicators.module";
@NgModule({
imports: [
SharedModule,
BrowserAnimationsModule,
@ -43,14 +37,14 @@ import {CacheIndicatorsModule} from "./openaireLibrary/monitor-admin/utils/cache
NavigationBarModule,
BottomModule,
CookieLawModule,
BrowserModule,
BrowserModule.withServerTransition({ appId: 'serverApp' }),
AppRoutingModule,
SideBarModule, Schema2jsonldModule, RoleVerificationModule, LoadingModule, NotificationsSidebarModule, IconsModule, CacheIndicatorsModule
BrowserTransferStateModule,
SideBarModule, Schema2jsonldModule, RoleVerificationModule, LoadingModule, NotificationsSidebarModule
],
declarations: [AppComponent, OpenaireErrorPageComponent],
exports: [AppComponent],
providers: [
{provide: APP_ID, useValue: 'monitor-dashboard'},
AdminLoginGuard, AdminDashboardGuard, LoginGuard,
{
provide: HTTP_INTERCEPTORS,
@ -69,7 +63,4 @@ import {CacheIndicatorsModule} from "./openaireLibrary/monitor-admin/utils/cache
})
//
export class AppModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([incognito])
}
}

View File

@ -0,0 +1,60 @@
.uk-card {
box-shadow: 0 6px 15px #0000001A;
border-radius: 36px;
padding: 65px;
font-family: "Roboto", sans-serif;
font-size: var(--large-font-size);
}
ul.portal-circle {
list-style: none;
padding-left: 40px;
font-family: "Open Sans", sans-serif;
font-size: var(--font-size);
}
ul.portal-circle li {
margin: 0 0 20px 0;
position: relative;
}
ul.portal-circle li:before {
content: "";
border: 5px var(--portal-main-color) solid !important;
border-radius: 50px;
line-height: 21px;
margin-left: -20px;
position: absolute;
top: 7px;
}
.documentation {
max-width: 500px;
background: #EEF7E6;
border-radius: 15px;
padding: 30px;
font-family: "Open Sans", sans-serif;
font-size: var(--small-font-size);
}
@media only screen and (max-width: 959px) {
.uk-card {
padding: 30px;
}
ul.portal-circle {
padding-left: 20px;
}
ul.light-blue-triangle li {
margin: 0 0 20px 0;
}
ul.light-blue-circle.large li {
margin: 0 0 20px 0;
}
.documentation {
padding: 10px;
}
}

View File

@ -6,120 +6,101 @@ import {Meta, Title} from "@angular/platform-browser";
import {SEOService} from "../openaireLibrary/sharedComponents/SEO/SEO.service";
import {properties} from "../../environments/environment";
import {Router} from "@angular/router";
import {StakeholderUtils} from "../openaireLibrary/monitor-admin/utils/indicator-utils";
import {OpenaireEntities} from "../openaireLibrary/utils/properties/searchFields";
import {EnvProperties} from "../openaireLibrary/utils/properties/env-properties";
import {PiwikService} from "../openaireLibrary/utils/piwik/piwik.service";
import {StakeholderUtils} from "../utils/indicator-utils";
@Component({
selector: 'develop',
template: `
<div class="uk-section">
<div class="uk-container uk-container-large">
<h1>Help developers <br> with OpenAIRE APIs<span class="uk-text-primary">.</span></h1>
</div>
<div class="uk-section uk-container uk-container-large">
<div class="uk-grid uk-grid-large uk-child-width-1-3@m uk-child-width-1-1" uk-grid>
<div class="uk-text-center uk-margin-large-top">
<div class="uk-icon-bg-shadow uk-icon-bg-shadow-large uk-margin-auto">
<icon name="description" customClass="uk-text-background" [flex]="true" ratio="2.5" type="outlined" visuallyHidden="For {{openaireEntities.RESULTS}}"></icon>
</div>
<h3>For {{openaireEntities.RESULTS | lowercase}}</h3>
<div class="uk-margin-bottom">
For {{openaireEntities.RESULTS | lowercase}} ({{openaireEntities.PUBLICATIONS | lowercase}}, {{openaireEntities.DATASETS | lowercase}}, {{openaireEntities.SOFTWARE | lowercase}} and {{openaireEntities.OTHER | lowercase}}) you can use the Selective Access APIs by adding the funder parameter.
</div>
<a class="uk-display-inline-block uk-button uk-button-text"
href="https://graph.openaire.eu/develop/api.html" target="_blank">
<span class="uk-flex uk-flex-middle">
<span>Selective Access APIs</span>
</span>
</a>
</div>
<div>
<img src="assets/apis.svg" alt="">
</div>
<div class="uk-text-center uk-margin-large-top">
<div class="uk-icon-bg-shadow uk-icon-bg-shadow-large uk-margin-auto">
<icon name="content_paste" customClass="uk-text-background" [flex]="true" ratio="2.5" type="outlined" visuallyHidden="For {{openaireEntities.PROJECTS}}"></icon>
</div>
<h3>For {{openaireEntities.PROJECTS | lowercase}}</h3>
<div class="uk-margin-bottom">
For {{openaireEntities.PROJECTS | lowercase}} you can use the Selective Access APIs and the Bulk Access APIs.
</div>
<div class="uk-flex uk-flex-column uk-flex-center uk-flex-middle">
<a class="uk-display-inline-block uk-button uk-button-text uk-margin-bottom"
href="https://graph.openaire.eu/develop/api.html" target="_blank">
<span class="uk-flex uk-flex-middle">
<span>Selective Access APIs</span>
</span>
</a>
<a class="uk-display-inline-block uk-button uk-button-text"
href="https://graph.openaire.eu/develop/bulk-projects.html" target="_blank">
<span class="uk-flex uk-flex-middle">
<span>Bulk Access APIs</span>
</span>
</a>
</div>
</div>
</div>
</div>
<div class="uk-section uk-container uk-container-large">
<div class="uk-grid uk-grid-large uk-child-width-1-2@m uk-child-width-1-1" uk-grid>
<div>
<div>Request examples for {{openaireEntities.RESULTS | lowercase}}:</div>
<ul class="uk-list uk-list-large uk-list-bullet uk-list-primary">
<li>
<span>Access all </span><span class="uk-text-bolder">{{openaireEntities.RESULTS}}</span> ({{openaireEntities.PUBLICATIONS}}, {{openaireEntities.DATASETS}}, {{openaireEntities.SOFTWARE}}, {{openaireEntities.OTHER}})<br>
<span class="uk-text-bold uk-margin-small-right">GET</span>
<span class="">https://api.openaire.eu/search/researchProducts?funder={{stakeholder.index_shortName}}</span>
</li>
<li>
<span>Access </span><span class="uk-text-bolder">{{openaireEntities.PUBLICATIONS}}</span><br>
<span class="uk-text-bold uk-margin-small-right">GET</span>
<span class="">https://api.openaire.eu/search/publications?funder={{stakeholder.index_shortName}}</span>
</li>
<li>
<span>Access </span><span class="uk-text-bolder">Open Access {{openaireEntities.PUBLICATIONS}}</span><br>
<span class="uk-text-bold uk-margin-small-right">GET</span>
<span class="uk-text-break">http://api.openaire.eu/search/publications?funder={{stakeholder.index_shortName}}&OA=true</span>
</li>
<li>
<span>Access </span><span class="uk-text-bolder">{{openaireEntities.DATASETS}}</span><br>
<span class="uk-text-bold uk-margin-small-right">GET</span>
<span class="uk-text-break">https://api.openaire.eu/search/datasets?funder={{stakeholder.index_shortName}}</span>
</li>
<li>
<span>Access </span><span class="uk-text-bolder">{{openaireEntities.SOFTWARE}}</span><br>
<span class="uk-text-bold uk-margin-small-right">GET</span>
<span class="uk-text-break">https://api.openaire.eu/search/software?funder={{stakeholder.index_shortName}}</span>
</li>
<li>
<span>Access </span><span class="uk-text-bolder">{{openaireEntities.OTHER}}</span><br>
<span class="uk-text-bold uk-margin-small-right">GET</span>
<span class="uk-text-break">https://api.openaire.eu/search/other?funder={{stakeholder.index_shortName}}</span>
</li>
</ul>
</div>
<div>
<div>Request examples for {{openaireEntities.PROJECTS | lowercase}}:</div>
<ul class="uk-list uk-list-large uk-list-bullet uk-list-primary">
<li>
<span>For the </span><span class="uk-text-bolder">Selective Access</span><br>
<span class="uk-text-break">https://api.openaire.eu/search/projects?funder={{stakeholder.index_shortName}}</span>
</li>
<li>
<span>For the </span><span class="uk-text-bolder">Bulk Access</span><br>
<span class="uk-text-bold uk-text-nowrap">DSpace endpoint:</span>
<span class="uk-text-break uk-margin-small-left">https://api.openaire.eu/projects/dspace/{{stakeholder.index_shortName}}/ALL/ ALL</span><br>
<span class="uk-text-bold uk-text-nowrap">ePrints endpoint:</span>
<span class="uk-text-break uk-margin-small-left">https://api.openaire.eu/projects/eprints/{{stakeholder.index_shortName}}/ALL/ ALL</span>
</li>
</ul>
</div>
</div>
</div>
</div>
`
<div page-content>
<div inner>
<div *ngIf="stakeholder" class="uk-container uk-container-large uk-section-small">
<h1 class="uk-text-center uk-h2">
Develop
</h1>
<div class="uk-margin-medium-top uk-card uk-card-body uk-card-default">
<h3 class="uk-text-center">Help developers with <span
class="portal-color uk-text-bold">OpenAIRE APIs</span>
</h3>
<div class="uk-margin-large-top uk-margin-medium-bottom">
Not sure where to start? Let us give you some guides and request examples.
</div>
<div class="uk-grid uk-child-width-1-2@l uk-child-width-1-1" uk-grid>
<div>
<p>
<span class="uk-text-bold">For research outcomes </span>
(publications, datasets, software and other research data) you can use the
<a href="http://api.openaire.eu/api.html" target="_blank">Selective Access APIs</a>
by adding the <span class="uk-text-lowercase">{{type}}</span> parameter.
</p>
<p>
Request examples:
</p>
<ul class="portal-circle">
<li>
<span class="uk-text-bold">Access Publications</span><br>
<span class="uk-text-bold">GET</span>
<span class="uk-text-break space">https://api.openaire.eu/search/publications?funder={{stakeholder.index_shortName}}</span>
</li>
<li>
<span class="uk-text-bold">Access Open Access Publications</span><br>
<span class="uk-text-bold">GET</span>
<span class="uk-text-break space">http://api.openaire.eu/search/publications?funder={{stakeholder.index_shortName}}&OA=true</span>
</li>
<li>
<span class="uk-text-bold">Access Datasets</span><br>
<span class="uk-text-bold">GET</span>
<span class="uk-text-break space">https://api.openaire.eu/search/datasets?funder={{stakeholder.index_shortName}}</span>
</li>
<li>
<span class="uk-text-bold">Access Software</span><br>
<span class="uk-text-bold">GET</span>
<span class="uk-text-break space">https://api.openaire.eu/search/software?funder={{stakeholder.index_shortName}}</span>
</li>
<li>
<span class="uk-text-bold">Access Other Research</span><br>
<span class="uk-text-bold">GET</span>
<span class="uk-text-break space">https://api.openaire.eu/search/other?funder={{stakeholder.index_shortName}}</span>
</li>
</ul>
</div>
<div>
<p>
<span class="uk-text-bold">For projects</span> you can use the <a href="http://api.openaire.eu/api.html" target="_blank">Selective Access APIs</a>
and the <a href="http://api.openaire.eu/bulk-projects.html" target="_blank">Bulk Access APIs</a>.
</p>
<p>
Request examples:
</p>
<ul class="portal-circle">
<li>
<span class="uk-text-bold">For the Selective Access</span><br>
<span class="uk-text-break space">https://api.openaire.eu/search/projects?funder={{stakeholder.index_shortName}}</span>
</li>
<li>
<span class="uk-text-bold">For the Bulk Access</span><br>
<span class="uk-text-bold uk-text-nowrap">DSpace endpoint:</span>
<span class="uk-text-break space">https://api.openaire.eu/projects/dspace/{{stakeholder.index_shortName}}/ALL/ ALL</span><br>
<span class="uk-text-bold uk-text-nowrap">ePrints endpoint:</span>
<span class="uk-text-break space">https://api.openaire.eu/projects/eprints/{{stakeholder.index_shortName}}/ALL/ ALL</span>
</li>
</ul>
<div class="uk-flex uk-flex-center uk-width-1-1 uk-margin-medium-top">
<img width="350" src="assets/develop.png">
</div>
</div>
</div>
<div class="uk-margin-large-top uk-flex uk-flex-center uk-padding">
<div class="documentation">
For <span class="uk-text-bold">more information</span> on the full potential of the OpenAIRE APIs please check
the <a href="http://develop.openaire.eu/" target="_blank">OpenAIRE API Documentation</a>.
</div>
</div>
</div>
</div>
</div>
</div>
`,
styleUrls: ['develop.component.css']
})
export class DevelopComponent implements OnInit, OnDestroy {
@ -127,13 +108,10 @@ export class DevelopComponent implements OnInit, OnDestroy {
private subscriptions: any[] = [];
private stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public type: string;
public openaireEntities = OpenaireEntities;
public properties: EnvProperties = properties;
constructor(private stakeholderService: StakeholderService,
private seoService: SEOService,
private _meta: Meta,
private piwikService: PiwikService,
private _router: Router,
private _title: Title) {
}
@ -155,7 +133,7 @@ export class DevelopComponent implements OnInit, OnDestroy {
this._meta.updateTag({content: description}, "property='og:description'");
this._meta.updateTag({content: title}, "property='og:title'");
this._title.setTitle(title);
this.subscriptions.push(this.piwikService.trackView(properties, title).subscribe());
/* Initializations */
this.stakeholderUtils.types.forEach(type => {
if (type.value === stakeholder.type) {
@ -167,7 +145,7 @@ export class DevelopComponent implements OnInit, OnDestroy {
}
private navigateToError() {
this._router.navigate([this.properties.errorLink], {queryParams: {'page': this._router.url}});
this._router.navigate(['/error'], {queryParams: {'page': this._router.url}});
}
ngOnDestroy() {

View File

@ -4,7 +4,6 @@ import {DevelopComponent} from "./develop.component";
import {RouterModule} from "@angular/router";
import {PreviousRouteRecorder} from "../openaireLibrary/utils/piwik/previousRouteRecorder.guard";
import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
import {IconsModule} from "../openaireLibrary/utils/icons/icons.module";
@NgModule({
declarations: [DevelopComponent],
@ -14,7 +13,7 @@ import {IconsModule} from "../openaireLibrary/utils/icons/icons.module";
component: DevelopComponent,
canDeactivate: [PreviousRouteRecorder]
},
]), PageContentModule, IconsModule],
]), PageContentModule],
exports: [DevelopComponent]
})
export class DevelopModule {

View File

@ -3,9 +3,12 @@ import {Component} from '@angular/core';
@Component({
selector: 'openaire-error',
template: `
<div class="uk-section">
<div class="uk-margin-large-top">
<error></error>
</div>
`
})
export class OpenaireErrorPageComponent {}
export class OpenaireErrorPageComponent {
constructor() {}
}

View File

@ -0,0 +1,10 @@
.uk-border-circle {
width: 100px;
height: 100px;
position: relative;
}
.uk-border-circle > img {
max-width: 64px;
max-height: 64px;
}

View File

@ -0,0 +1,416 @@
import {Component, Input, OnDestroy, ViewChild} from "@angular/core";
import {Stakeholder} from "../../openaireLibrary/monitor/entities/stakeholder";
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import {StakeholderUtils} from "../../utils/indicator-utils";
import {Option} from "../../openaireLibrary/sharedComponents/input/input.component";
import {Subscriber, Subscription} from "rxjs";
import {EnvProperties} from "../../openaireLibrary/utils/properties/env-properties";
import {properties} from "../../../environments/environment";
import {StakeholderService} from "../../openaireLibrary/monitor/services/stakeholder.service";
import {UtilitiesService} from "../../openaireLibrary/services/utilities.service";
import {Role, Session, User} from "../../openaireLibrary/login/utils/helper.class";
import {UserManagementService} from "../../openaireLibrary/services/user-management.service";
import {StringUtils} from "../../openaireLibrary/utils/string-utils.class";
import {NotifyFormComponent} from "../../openaireLibrary/notifications/notify-form/notify-form.component";
import {NotificationUtils} from "../../openaireLibrary/notifications/notification-utils";
import {Notification} from "../../openaireLibrary/notifications/notifications";
declare var UIkit;
@Component({
selector: 'edit-stakeholder',
template: `
<div [ngStyle]="{'max-height': maxHeight}"
[class.uk-padding-small]="!paddingLarge" [class.uk-padding-large]="paddingLarge"
class="uk-overflow-auto uk-padding-remove-bottom">
<form *ngIf="stakeholderFb" [formGroup]="stakeholderFb">
<div class="uk-grid" [class.uk-margin-small-bottom]="!paddingLarge"
[class.uk-margin-large-bottom]="paddingLarge" uk-grid uk-height-match=".uk-form-hint">
<div dashboard-input id="name" class="uk-width-1-2@m" [formInput]="stakeholderFb.get('name')" label="Name"
placeholder="Write a name..."
hint="Set a name for your profile."></div>
<div dashboard-input class="uk-width-1-2@m" [formInput]="stakeholderFb.get('alias')"
hint="Set an URL alias for your profile."
label="URL Alias" placeholder="Write an alias..."></div>
<div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('index_id')"
label="Index ID" placeholder="Write index ID.">
</div>
<div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('index_name')"
label="Index Name" placeholder="Write index name.">
</div>
<div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('index_shortName')"
label="Index Short Name" placeholder="Write index short name.">
</div>
<div dashboard-input class="uk-width-1-1" [type]="'textarea'" placeholder="Write a description..."
hint="Write a description for your profile"
[rows]="4" [formInput]="stakeholderFb.get('description')" label="Description"></div>
<input #file id="photo" type="file" class="uk-hidden" (change)="fileChangeEvent($event)"/>
<div dashboard-input class="uk-width-1-1" type="logoURL" flex="top" [hideControl]="stakeholderFb.get('isUpload').value"
hint="Upload or link the logo of your profile" [placeholder]="'Write link to the logo'"
[formInput]="stakeholderFb.get('logoUrl')" label="Logo">
<div *ngIf="!stakeholderFb.get('isUpload').value" style="margin-top: 7px;" class="uk-width-2-5@l uk-width-1-1">
<div class="uk-grid uk-flex uk-flex-middle" uk-grid>
<div class="uk-width-3-4@l uk-width-1-1 uk-flex uk-flex-center">
<button class="uk-button uk-button-secondary uk-flex uk-flex-middle uk-flex-wrap"
(click)="file.click()">
<icon name="cloud_upload" [flex]="true"></icon>
<span class="uk-margin-small-left">Upload a file</span>
</button>
</div>
<div class="uk-text-center uk-text-bold uk-width-expand">
OR
</div>
</div>
</div>
<div *ngIf="stakeholderFb.get('isUpload').value" class="uk-width-1-1 uk-flex uk-flex-middle">
<div class="uk-card uk-card-default uk-text-center uk-border-circle">
<img class="uk-position-center" [src]="photo">
</div>
<div class="uk-margin-left">
<button (click)="remove()" class="uk-button-secondary outlined uk-icon-button">
<icon name="remove"></icon>
</button>
</div>
<div class="uk-margin-small-left">
<button class="uk-button-secondary uk-icon-button" (click)="file.click()">
<icon name="edit"></icon>
</button>
</div>
</div>
</div>
<div *ngIf="uploadError" class="uk-text-danger uk-width-1-1">{{uploadError}}</div>
<div class="uk-width-1-1 uk-grid uk-child-width-1-1" [class.uk-child-width-1-2@m]="!canChooseType"
[class.uk-child-width-1-3@m]="canChooseType" uk-grid>
<div dashboard-input [formInput]="stakeholderFb.get('visibility')"
[placeholder]="'Select a status'"
label="Status" hint="Select the visibility status of your profile"
[options]="stakeholderUtils.statuses" type="select">
</div>
<div dashboard-input [formInput]="stakeholderFb.get('type')"
[placeholder]="'Select a type'" hint="Select the type of your profile"
label="Type" [options]="types" type="select">
</div>
<ng-container *ngIf="canChooseType">
<div [placeholder]="'Select a template'"
hint="Select a template for your profile"
dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('defaultId')"
label="Template" [options]="defaultStakeholdersOptions" type="select"></div>
</ng-container>
</div>
</div>
</form>
<div #notify notify-form class="uk-width-1-1 uk-margin-medium-top uk-margin-medium-bottom"></div>
</div>`,
styleUrls: ['edit-stakeholder.component.css']
})
export class EditStakeholderComponent implements OnDestroy {
@Input()
public maxHeight = 'none';
@Input()
public paddingLarge: boolean = false;
@Input()
public disableAlias: boolean = false;
public stakeholderFb: FormGroup;
public secure: boolean = false;
public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public defaultStakeholdersOptions: Option[];
public defaultStakeholders: Stakeholder[];
public alias: string[];
public stakeholder: Stakeholder;
public isDefault: boolean;
public isNew: boolean;
public types: Option[];
public properties: EnvProperties = properties;
private subscriptions: any[] = [];
/**
* Photo upload
* */
public file: File;
public photo: string | ArrayBuffer;
public uploadError: string;
public deleteCurrentPhoto: boolean = false;
private maxsize: number = 200 * 1024;
user: User;
@ViewChild('notify', { static: true }) notify: NotifyFormComponent;
private notification: Notification;
constructor(private fb: FormBuilder,
private stakeholderService: StakeholderService,
private utilsService: UtilitiesService, private userManagementService: UserManagementService,) {
}
ngOnDestroy() {
this.reset();
}
public init(stakeholder: Stakeholder, alias: string[], defaultStakeholders: Stakeholder[], isDefault: boolean, isNew: boolean) {
this.reset();
this.deleteCurrentPhoto = false;
this.stakeholder = stakeholder;
this.alias = alias;
this.defaultStakeholders = defaultStakeholders;
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.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.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 {
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);
}
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 disabled(): boolean {
return (this.stakeholderFb && this.stakeholderFb.invalid) ||
(this.stakeholderFb && this.stakeholderFb.pristine && !this.isNew && !this.file) ||
(this.uploadError && this.uploadError.length > 0);
}
public get dirty(): boolean {
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;
}
reset() {
this.uploadError = null;
this.stakeholderFb = null;
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) {
subscription.unsubscribe();
}
});
}
onTypeChange(value, defaultStakeholders: Stakeholder[]) {
this.stakeholderFb.setControl('defaultId', this.fb.control(this.stakeholder.defaultId, Validators.required));
this.defaultStakeholdersOptions = [{
label: 'New blank profile',
value: '-1'
}];
defaultStakeholders.filter(stakeholder => stakeholder.type === value).forEach(stakeholder => {
this.defaultStakeholdersOptions.push({
label: 'Use ' + stakeholder.name + ' profile',
value: stakeholder._id
})
});
}
public save(callback: Function, errorCallback: Function = null) {
if (this.file) {
this.stakeholderFb.get('alias').enable();
this.subscriptions.push(this.utilsService.uploadPhoto(this.properties.utilsService + "/upload/stakeholder/" + encodeURIComponent(this.stakeholderFb.value.alias), this.file).subscribe(res => {
this.deletePhoto();
this.removePhoto();
this.stakeholderFb.get('logoUrl').setValue(res.filename);
this.saveStakeholder(callback, errorCallback);
}, error => {
this.uploadError = "An error has been occurred during upload your image. Try again later";
this.saveStakeholder(callback, errorCallback);
}));
} else if (this.deleteCurrentPhoto) {
this.deletePhoto();
this.saveStakeholder(callback, errorCallback);
} else {
this.saveStakeholder(callback, errorCallback);
}
}
public saveStakeholder(callback: Function, errorCallback: Function = null) {
if (this.isNew) {
if (!this.stakeholderFb.value.isDefault) {
let stakeholder = this.defaultStakeholders.find(value => value._id === this.stakeholderFb.value.defaultId);
this.stakeholderFb.setValue(this.stakeholderUtils.createFunderFromDefaultProfile(this.stakeholderFb.value,
(stakeholder ? stakeholder.topics : [])));
}
this.removePhoto();
this.subscriptions.push(this.stakeholderService.buildStakeholder(this.properties.monitorServiceAPIURL,
this.stakeholderFb.value).subscribe(stakeholder => {
this.notification.entity = stakeholder._id;
this.notification.stakeholder = stakeholder.alias;
this.notification.stakeholderType = stakeholder.type;
this.notification.groups = [Role.curator(stakeholder.type)];
this.notify.sendNotification(this.notification);
UIkit.notification(stakeholder.name + ' has been <b>successfully created</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
callback(stakeholder);
}, error => {
UIkit.notification('An error has occurred. Please try again later', {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
if (errorCallback) {
errorCallback(error)
}
}));
} else {
this.stakeholderFb.get('alias').enable();
this.stakeholderFb.get('type').enable();
this.stakeholderFb.get('index_id').enable();
this.stakeholderFb.get('index_name').enable();
this.stakeholderFb.get('index_shortName').enable();
this.subscriptions.push(this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, this.stakeholderFb.value).subscribe(stakeholder => {
this.notification.entity = stakeholder._id;
this.notification.stakeholder = stakeholder.alias;
this.notification.stakeholderType = stakeholder.type;
this.notification.groups = [Role.curator(stakeholder.type), Role.manager(stakeholder.type, stakeholder.alias)];
this.notify.sendNotification(this.notification);
UIkit.notification(stakeholder.name + ' has been <b>successfully saved</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
callback(stakeholder);
}, error => {
UIkit.notification('An error has occurred. Please try again later', {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
}));
}
}
fileChangeEvent(event) {
if (event.target.files && event.target.files[0]) {
this.file = event.target.files[0];
if (this.file.type !== 'image/png' && this.file.type !== 'image/jpeg') {
this.uploadError = 'You must choose a file with type: image/png or image/jpeg!';
this.stakeholderFb.get('isUpload').setValue(false);
this.stakeholderFb.get('isUpload').markAsDirty();
this.removePhoto();
} else if (this.file.size > this.maxsize) {
this.uploadError = 'File exceeds size\'s limit! Maximum resolution is 256x256 pixels.';
this.stakeholderFb.get('isUpload').setValue(false);
this.stakeholderFb.get('isUpload').markAsDirty();
this.removePhoto();
} else {
this.uploadError = null;
const reader = new FileReader();
reader.readAsDataURL(this.file);
reader.onload = () => {
this.photo = reader.result;
this.stakeholderFb.get('isUpload').setValue(true);
this.stakeholderFb.get('isUpload').markAsDirty();
};
}
}
}
initPhoto() {
if (this.stakeholderFb.value.isUpload) {
this.photo = this.properties.utilsService + "/download/" + this.stakeholderFb.get('logoUrl').value;
}
}
removePhoto() {
if (this.file) {
if (typeof document != 'undefined') {
(<HTMLInputElement>document.getElementById("photo")).value = "";
}
this.initPhoto();
this.file = null;
}
}
remove() {
this.stakeholderFb.get('isUpload').setValue(false);
this.stakeholderFb.get('isUpload').markAsDirty();
this.removePhoto();
this.stakeholderFb.get('logoUrl').setValue(null);
if (this.stakeholder.isUpload) {
this.deleteCurrentPhoto = true;
}
}
public deletePhoto() {
if (this.stakeholder.logoUrl) {
this.subscriptions.push(this.utilsService.deletePhoto(this.properties.utilsService + '/delete/stakeholder/' + this.stakeholder.logoUrl).subscribe());
}
}
}

View File

@ -0,0 +1,20 @@
import {NgModule} from "@angular/core";
import {EditStakeholderComponent} from "./edit-stakeholder.component";
import {CommonModule} from "@angular/common";
import {InputModule} from "../../openaireLibrary/sharedComponents/input/input.module";
import {ReactiveFormsModule} from "@angular/forms";
import {IconsModule} from "../../openaireLibrary/utils/icons/icons.module";
import {IconsService} from "../../openaireLibrary/utils/icons/icons.service";
import {cloud_upload, edit, remove} from "../../openaireLibrary/utils/icons/icons";
import {NotifyFormModule} from "../../openaireLibrary/notifications/notify-form/notify-form.module";
@NgModule({
imports: [CommonModule, InputModule, ReactiveFormsModule, IconsModule, NotifyFormModule],
declarations: [EditStakeholderComponent],
exports: [EditStakeholderComponent]
})
export class EditStakeholderModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([remove, edit, cloud_upload]);
}
}

View File

@ -0,0 +1,19 @@
import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import {PreviousRouteRecorder} from '../openaireLibrary/utils/piwik/previousRouteRecorder.guard';
import {GeneralComponent} from "./general.component";
@NgModule({
imports: [
RouterModule.forChild([
{
path: '',
component: GeneralComponent,
canDeactivate: [PreviousRouteRecorder],
data: {hasSidebar: true}
}
])
]
})
export class GeneralRoutingModule {
}

View File

@ -0,0 +1,38 @@
<div page-content>
<div inner>
<div *ngIf="stakeholder">
<div class="uk-card-header">
<div class="uk-flex uk-child-width-1-1 uk-child-width-1-2@m uk-grid" uk-grid>
<div>
<div class="uk-text-small title">
Manage Profile
</div>
<div>
<span class="uk-text-bold">{{stakeholder.name}}</span>
<span *ngIf="editStakeholderComponent.dirty && !loading"> (unsaved changes)</span>
</div>
</div>
<div class="uk-text-right@m uk-text-center">
<button class="uk-button uk-button-secondary outlined uk-margin-right"
(click)="reset()"
[disabled]="loading || !editStakeholderComponent.dirty">Reset
</button>
<button class="uk-button uk-button-secondary"
(click)="save()"
[disabled]="loading || editStakeholderComponent.disabled">Save
</button>
</div>
</div>
</div>
<div class="uk-card uk-card-default uk-position-relative" style="min-height: 60vh">
<div [class.hidden]="loading">
<edit-stakeholder #editStakeholderComponent [disableAlias]="true"
[maxHeight]="'60vh'" [paddingLarge]="true" ></edit-stakeholder>
</div>
<div *ngIf="loading" class="uk-position-center">
<loading *ngIf="loading"></loading>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,72 @@
import {Component, OnDestroy, OnInit, ViewChild} from "@angular/core";
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
import {EnvProperties} from "../openaireLibrary/utils/properties/env-properties";
import {Stakeholder} from "../openaireLibrary/monitor/entities/stakeholder";
import { Subscription, zip} from "rxjs";
import {EditStakeholderComponent} from "./edit-stakeholder/edit-stakeholder.component";
import {properties} from "../../environments/environment";
import {Title} from "@angular/platform-browser";
@Component({
selector: 'general',
templateUrl: "./general.component.html"
})
export class GeneralComponent implements OnInit, OnDestroy {
public stakeholder: Stakeholder;
public alias: string[];
public properties: EnvProperties = properties;
public defaultStakeholders: Stakeholder[];
public loading: boolean = false;
private subscriptions: any[] = [];
@ViewChild('editStakeholderComponent') editStakeholderComponent: EditStakeholderComponent;
constructor(private stakeholderService: StakeholderService,
private title: Title) {
}
ngOnInit() {
this.loading = true;
this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
this.stakeholder = stakeholder;
if(this.stakeholder) {
this.title.setTitle(this.stakeholder.name + " | General");
let data = zip(
this.stakeholderService.getDefaultStakeholders(this.properties.monitorServiceAPIURL),
this.stakeholderService.getAlias(this.properties.monitorServiceAPIURL)
);
this.subscriptions.push(data.subscribe(res => {
this.defaultStakeholders = res[0];
this.alias = res[1];
this.reset();
this.loading = false;
}));
}
}));
}
public reset() {
this.editStakeholderComponent.init(this.stakeholder, this.alias, this.defaultStakeholders, this.stakeholder.defaultId == null, false)
}
public save() {
this.loading = true;
this.editStakeholderComponent.save((stakeholder) => {
this.stakeholder = stakeholder;
this.stakeholderService.setStakeholder(this.stakeholder);
this.reset();
this.loading = false;
}, (error) => {
this.loading = false;
});
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if(subscription instanceof Subscription) {
subscription.unsubscribe();
}
});
}
}

View File

@ -0,0 +1,34 @@
import {NgModule} from "@angular/core";
import {GeneralComponent} from "./general.component";
import {GeneralRoutingModule} from "./general-routing.module";
import {PreviousRouteRecorder} from "../openaireLibrary/utils/piwik/previousRouteRecorder.guard";
import {CommonModule} from "@angular/common";
import {RouterModule} from "@angular/router";
import {InputModule} from "../openaireLibrary/sharedComponents/input/input.module";
import {LoadingModule} from "../openaireLibrary/utils/loading/loading.module";
import {AlertModalModule} from "../openaireLibrary/utils/modal/alertModal.module";
import {ReactiveFormsModule} from "@angular/forms";
import {EditStakeholderModule} from "./edit-stakeholder/edit-stakeholder.module";
import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
@NgModule({
declarations: [GeneralComponent],
imports: [
GeneralRoutingModule,
CommonModule,
RouterModule,
InputModule,
LoadingModule,
AlertModalModule,
ReactiveFormsModule,
EditStakeholderModule,
PageContentModule
],
providers: [
PreviousRouteRecorder,
],
exports: [GeneralComponent]
})
export class GeneralModule {
}

View File

@ -0,0 +1,19 @@
import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import {PreviousRouteRecorder} from '../openaireLibrary/utils/piwik/previousRouteRecorder.guard';
import {ManageStakeholdersComponent} from "./manageStakeholders.component";
@NgModule({
imports: [
RouterModule.forChild([
{
path: '',
component: ManageStakeholdersComponent,
canDeactivate: [PreviousRouteRecorder],
data: {hasSidebar: true}
}
])
]
})
export class ManageStakeholdersRoutingModule {
}

View File

@ -0,0 +1,21 @@
.uk-card {
min-height: 230px;
}
.uk-card-body {
padding-top: 75px;
}
.uk-card-default .name {
margin-left: auto;
margin-right: auto;
}
.uk-card-default .uk-card-title .logo {
display: inline-block;
max-width: 80%;
}
.uk-card-default .uk-card-title .logo > img {
max-height: 60px;
}

View File

@ -0,0 +1,144 @@
<div page-content>
<div header>
<ul *ngIf="isCurator()" class="uk-tab customTabs admin uk-flex uk-flex-center uk-flex-left@m" uk-tab>
<li [class.uk-active]="tab === 'all'"><a routerLink="./"><span class="title">All</span></a></li>
<li [class.uk-active]="tab === 'templates'"><a routerLink="./" fragment="templates"><span class="title">Profile templates</span></a>
</li>
<li [class.uk-active]="tab === 'profiles'"><a routerLink="./" fragment="profiles"><span
class="title">Profiles</span></a></li>
</ul>
<!--<div class="uk-grid uk-margin-medium" uk-grid>
<div *ngIf="filters" class="uk-width-2-3@m uk-width-1-1 uk-child-width-1-3@m uk-child-width-1-1" uk-grid>
<div>
<div dashboard-input [formInput]="filters.get('status')"
type="select" [options]="[all].concat(stakeholderUtils.visibility)"
label="Visibility"></div>
</div>
</div>
<div class="uk-width-expand@m uk-width-1-1 uk-flex uk-flex-middle uk-flex-right">
<div class="uk-inline uk-width-medium">
<div dashboard-input [formInput]="filters.get('keyword')" label="Locate profile" icon="search"></div>
</div>
</div>
</div>-->
</div>
<div inner>
<div *ngIf="loading" class="uk-margin-medium-top uk-padding-large">
<loading></loading>
</div>
<div *ngIf="!loading">
<div *ngIf="tab != 'profiles' && isCurator()" class="uk-margin-medium-top">
<h6 class="uk-text-bold">Profile Templates</h6>
<div class="uk-grid uk-child-width-1-4@xl uk-child-width-1-3@l uk-child-width-1-2@m uk-grid-match" uk-grid
uk-height-match="target: .name;">
<ng-template ngFor [ngForOf]="displayDefaultStakeholders" let-stakeholder let-i="index">
<ng-container *ngTemplateOutlet="stakeholderBox; context: {stakeholder:stakeholder}"></ng-container>
</ng-template>
<div *ngIf="!loading && isCurator()">
<ng-container *ngTemplateOutlet="newBox; context: {text:'Create a new default profile.', isDefault:true}"></ng-container>
</div>
</div>
</div>
<div *ngIf="!isManager()" class="message">
<h4 class="uk-text-center">
No profiles to manage yet
</h4>
</div>
<div *ngIf="tab != 'templates' && isManager()" class="uk-margin-large-top">
<h6 class="uk-text-bold">Profiles</h6>
<div class="uk-grid uk-grid-match uk-child-width-1-4@xl uk-child-width-1-3@l uk-child-width-1-2@m" uk-grid
uk-height-match="target: .name;">
<ng-template ngFor [ngForOf]="displayStakeholders" let-stakeholder let-i="index">
<ng-container *ngTemplateOutlet="stakeholderBox; context: {stakeholder:stakeholder}"></ng-container>
</ng-template>
<div *ngIf="!loading && isCurator()">
<ng-container *ngTemplateOutlet="newBox; context: {text:'Create a new profile by selecting the type (Funder, Organization, Research Initiative or Project) and ' +
'select indicators based on a default or a blank profile.', isDefault:false}"></ng-container>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #stakeholderBox let-stakeholder="stakeholder">
<div *ngIf="stakeholder">
<div class="uk-card uk-card-default uk-card-body uk-position-relative">
<div class="uk-position-top-right uk-margin-small-right uk-margin-small-top clickable">
<i uk-icon="more-vertical"
(click)="$event.stopPropagation();$event.preventDefault()"></i>
<div #element uk-dropdown="mode: click; pos: bottom-right; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li><a
(click)="$event.stopPropagation();editStakeholder(stakeholder, !stakeholder.defaultId);hide(element);$event.preventDefault()">Edit</a>
</li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<li *ngIf="stakeholder.visibility != v.value"><a (click)="changeStakeholderStatus(stakeholder, v.value);
hide(element)">
{{'Make ' + v.label.toLowerCase()}}</a>
</li>
</ng-template>
<hr *ngIf="isProfileManager(stakeholder)" class="uk-nav-divider">
<li *ngIf="isProfileManager(stakeholder)"><a
(click)="$event.stopPropagation();deleteStakeholderOpen(stakeholder);hide(element);$event.preventDefault()">Delete</a>
</li>
</ul>
</div>
</div>
<div class="uk-position-top-left uk-margin-small-left uk-margin-small-top clickable visibility">
<span class="clickable color">
<icon [name]="stakeholderUtils.visibilityIcon.get(stakeholder.visibility)"></icon>
</span>
<div #element uk-dropdown="mode: click; pos: bottom-left; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li *ngFor="let v of stakeholderUtils.visibility" class="uk-position-relative">
<a *ngIf="stakeholder.visibility != v.value"
(click)="$event.stopPropagation();changeStakeholderStatus(stakeholder,v.value);hide(element);$event.preventDefault()">
<icon [name]="stakeholderUtils.visibilityIcon.get(v.value)" ratio="0.8"></icon>
<span> {{v.label}}</span>
</a>
<a *ngIf="stakeholder.visibility == v.value">
<icon [name]="stakeholderUtils.visibilityIcon.get(v.value)" [ratio]="0.8"></icon>
<span> {{v.label}}</span>
<span class="uk-position-center-right">
<icon customClass="uk-text-secondary" [ratio]="0.5" name="bullet"></icon>
</span>
</a>
</li>
</ul>
</div>
</div>
<a class="uk-display-block uk-text-center uk-card-title" [routerLink]="stakeholder.alias">
<div class="name uk-width-2-3@l">
{{stakeholder.name}}
</div>
<div *ngIf="stakeholder.logoUrl" class="logo uk-margin-top uk-margin-bottom">
<img *ngIf="stakeholder.isUpload" [src]="properties.utilsService + '/download/' + stakeholder.logoUrl">
<img *ngIf="!stakeholder.isUpload" [src]="stakeholder.logoUrl">
</div>
</a>
</div>
</div>
</ng-template>
<ng-template #newBox let-text="text" let-isDefault="isDefault">
<div *ngIf="!loading">
<div class="uk-card uk-card-default uk-text-center uk-card-body clickable" (click)="editStakeholder(null, isDefault)">
<div class="uk-text-small uk-text-muted">
{{text}}
</div>
<div class="uk-margin-medium-top uk-margin-small-bottom">
<span class="uk-text-secondary">
<icon name="add" [ratio]="3"></icon>
</span>
</div>
</div>
</div>
</ng-template>
<modal-alert #editStakeholderModal
id="edit_modal" [large]="true"
(alertOutput)="editStakeholderComponent.save(callback)"
[okDisabled]="editStakeholderComponent.disabled">
<edit-stakeholder #editStakeholderComponent></edit-stakeholder>
</modal-alert>
<modal-alert #deleteStakeholderModal (alertOutput)="deleteStakeholder()"></modal-alert>

View File

@ -0,0 +1,284 @@
import {Component, OnDestroy, OnInit, ViewChild} from "@angular/core";
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
import {EnvProperties} from "../openaireLibrary/utils/properties/env-properties";
import {Stakeholder, Visibility} from "../openaireLibrary/monitor/entities/stakeholder";
import {Subscriber, zip} from "rxjs";
import {StakeholderUtils} from "../utils/indicator-utils";
import {FormBuilder, FormGroup} from "@angular/forms";
import {AlertModal} from "../openaireLibrary/utils/modal/alert";
import {Option} from "../openaireLibrary/sharedComponents/input/input.component";
import {Title} from "@angular/platform-browser";
import {UserManagementService} from "../openaireLibrary/services/user-management.service";
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";
type Tab = 'all' | 'templates'| 'profiles';
declare var UIkit;
@Component({
selector: 'home',
templateUrl: "./manageStakeholders.component.html",
styleUrls: ['manageStakeholders.component.css']
})
export class ManageStakeholdersComponent implements OnInit, OnDestroy {
public properties: EnvProperties;
public loading: boolean = true;
public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public defaultStakeholders: Stakeholder[];
public stakeholders: Stakeholder[];
public alias: string[];
public stakeholder: Stakeholder;
public index: number;
public user = null;
/**
* Filtered Stakeholders
*/
public displayDefaultStakeholders: Stakeholder[];
public displayStakeholders: Stakeholder[];
/**
* Top filters
*/
public filters: FormGroup;
public all: Option = {
value: 'all',
label: 'All'
};
public callback: Function;
/**
* Grid or List View
*/
private subscriptions: any[] = [];
@ViewChild('editStakeholderModal', { static: true }) editStakeholderModal: AlertModal;
@ViewChild('deleteStakeholderModal', { static: true }) deleteStakeholderModal: AlertModal;
@ViewChild('editStakeholderComponent', { static: true }) editStakeholderComponent: EditStakeholderComponent;
tab: Tab = 'all';
constructor(private stakeholderService: StakeholderService,
private userManagementService: UserManagementService,
private route: ActivatedRoute,
private title: Title,
private fb: FormBuilder) {
}
ngOnInit(): void {
this.subscriptions.push(this.route.fragment.subscribe((fragment: Tab) => {
if (this.isTab(fragment)) {
this.tab = fragment;
} else {
this.tab = 'all';
}
}));
this.buildFilters();
this.properties = properties;
this.title.setTitle('Manage profiles');
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
this.user = user;
}));
let data = zip(
this.stakeholderService.getDefaultStakeholders(this.properties.monitorServiceAPIURL),
this.stakeholderService.getMyStakeholders(this.properties.monitorServiceAPIURL),
this.stakeholderService.getAlias(this.properties.monitorServiceAPIURL)
);
this.subscriptions.push(data.subscribe(res => {
this.defaultStakeholders = res[0];
this.stakeholders = res[1];
this.displayDefaultStakeholders = res[0];
this.displayStakeholders = res[1];
this.alias = res[2];
this.loading = false;
}));
this.subscriptions.push(UIkit.util.on(document, 'hidden', '#edit_modal', (): void => {
this.editStakeholderComponent.removePhoto();
}));
}
ngOnDestroy(): void {
this.subscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();
} else if (value instanceof Function) {
value();
}
});
}
hide(element: any) {
UIkit.dropdown(element).hide();
}
private buildFilters() {
this.filters = this.fb.group({
status: this.fb.control('all'),
keyword: this.fb.control('')
});
this.subscriptions.push(this.filters.get('status').valueChanges.subscribe(value => {
this.onStatusChange(value);
}));
this.subscriptions.push(this.filters.get('keyword').valueChanges.subscribe(value => {
this.onKeywordChange(value);
}));
}
onStatusChange(value) {
this.displayDefaultStakeholders = this.filterStatus(this.defaultStakeholders, value);
this.displayStakeholders = this.filterStatus(this.stakeholders, value);
}
onKeywordChange(value) {
this.displayDefaultStakeholders = this.filterByKeyword(this.defaultStakeholders, value);
this.displayStakeholders = this.filterByKeyword(this.stakeholders, value);
}
private filterStatus(stakeholders: Stakeholder[], value): Stakeholder[] {
if (value === 'all') {
return stakeholders;
} else {
return stakeholders.filter(stakeholder => stakeholder.visibility == value);
}
}
private filterByKeyword(stakeholders: Stakeholder[], value): Stakeholder[] {
if (value === null || value === '') {
return stakeholders;
} else {
return stakeholders.filter(stakeholder =>
stakeholder.name && stakeholder.name.toLowerCase().includes(value.toLowerCase()) ||
stakeholder.type && stakeholder.type.toLowerCase().includes(value.toLowerCase()) ||
stakeholder.index_id && stakeholder.index_id.toLowerCase().includes(value.toLowerCase()) ||
stakeholder.index_shortName && stakeholder.index_shortName.toLowerCase().includes(value.toLowerCase()) ||
stakeholder.index_name && stakeholder.index_name.toLowerCase().includes(value.toLowerCase())
);
}
}
public editStakeholder(stakeholder: Stakeholder = null, isDefault: boolean = false) {
if (isDefault) {
this.index = (stakeholder) ? this.defaultStakeholders.findIndex(value => value._id === stakeholder._id) : -1;
} else {
this.index = (stakeholder) ? this.stakeholders.findIndex(value => value._id === stakeholder._id) : -1;
}
if (!stakeholder) {
this.stakeholder = new Stakeholder(null, null, null,
null, null, null, null, null);
} else {
this.stakeholder = stakeholder;
}
this.editStakeholderComponent.init(this.stakeholder, this.alias, this.defaultStakeholders, isDefault, this.index === -1);
if (this.index !== -1) {
this.callback = (stakeholder: Stakeholder) => {
if (stakeholder.defaultId == null) {
this.defaultStakeholders[this.index] = stakeholder;
} else {
this.stakeholders[this.index] = stakeholder;
}
};
this.editStakeholderModal.okButtonText = 'Save Changes';
} else {
this.callback = (stakeholder: Stakeholder) => {
if (stakeholder.defaultId === null) {
this.defaultStakeholders.push(stakeholder);
} else {
this.stakeholders.push(stakeholder);
}
};
this.editStakeholderModal.okButtonText = 'Create';
}
this.editStakeholderModal.cancelButtonText = 'Cancel';
this.editStakeholderModal.okButtonLeft = false;
this.editStakeholderModal.alertMessage = false;
this.editStakeholderModal.open();
}
public deleteStakeholderOpen(stakeholder: Stakeholder) {
this.stakeholder = stakeholder;
this.deleteStakeholderModal.alertTitle = 'Delete ' + this.stakeholder.index_name;
this.deleteStakeholderModal.cancelButtonText = 'No';
this.deleteStakeholderModal.okButtonText = 'Yes';
this.deleteStakeholderModal.message = 'This stakeholder will permanently be deleted. Are you sure you want to proceed?';
this.deleteStakeholderModal.open();
}
public deleteStakeholder() {
if (!this.stakeholder.defaultId) {
this.index = (this.stakeholder) ? this.defaultStakeholders.findIndex(value => value._id === this.stakeholder._id) : -1;
} else {
this.index = (this.stakeholder) ? this.stakeholders.findIndex(value => value._id === this.stakeholder._id) : -1;
}
this.subscriptions.push(this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, [this.stakeholder._id]).subscribe(() => {
UIkit.notification(this.stakeholder.name+ ' has been <b>successfully deleted</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
if (!this.stakeholder.defaultId) {
this.defaultStakeholders.splice(this.index, 1);
} else {
this.stakeholders.splice(this.index, 1);
}
}, error => {
UIkit.notification('An error has occurred. Please try again later', {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
}));
}
changeStakeholderStatus(stakeholder: Stakeholder, visibility: Visibility) {
let path = [
stakeholder._id
];
this.subscriptions.push(this.stakeholderService.changeVisibility(this.properties.monitorServiceAPIURL, path, visibility).subscribe(visibility => {
stakeholder.visibility = visibility;
UIkit.notification(stakeholder.name+ '\'s status has been <b>successfully changed</b> to ' + stakeholder.visibility.toLowerCase(), {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
}, error => {
UIkit.notification('An error has occurred. Please try again later', {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
}));
}
public isManager(): boolean {
return this.isCurator() || (Session.isKindOfMonitorManager(this.user));
}
public isProfileManager(stakeholder: Stakeholder): boolean {
return this.isCurator() || (Session.isManager(stakeholder.type, stakeholder.alias, this.user));
}
public isCurator(): boolean {
return this.isAdmin() || Session.isMonitorCurator(this.user);
}
public isAdmin(): boolean {
return Session.isPortalAdministrator(this.user);
}
private isTab(tab: Tab): boolean {
switch (tab) {
case "all":
return true;
case "profiles":
return true;
case "templates":
return true;
default:
return false;
}
}
}

View File

@ -0,0 +1,40 @@
import {NgModule} from "@angular/core";
import {ManageStakeholdersComponent} from "./manageStakeholders.component";
import {ManageStakeholdersRoutingModule} from "./manageStakeholders-routing.module";
import {PreviousRouteRecorder} from "../openaireLibrary/utils/piwik/previousRouteRecorder.guard";
import {CommonModule} from "@angular/common";
import {RouterModule} from "@angular/router";
import {InputModule} from "../openaireLibrary/sharedComponents/input/input.module";
import {LoadingModule} from "../openaireLibrary/utils/loading/loading.module";
import {AlertModalModule} from "../openaireLibrary/utils/modal/alertModal.module";
import {ReactiveFormsModule} from "@angular/forms";
import {EditStakeholderModule} from "../general/edit-stakeholder/edit-stakeholder.module";
import {IconsModule} from "../openaireLibrary/utils/icons/icons.module";
import {IconsService} from "../openaireLibrary/utils/icons/icons.service";
import {add, bullet, earth, group, lock, search} from "../openaireLibrary/utils/icons/icons";
import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
@NgModule({
declarations: [ManageStakeholdersComponent],
imports: [
ManageStakeholdersRoutingModule,
CommonModule,
RouterModule,
InputModule,
LoadingModule,
AlertModalModule,
ReactiveFormsModule,
EditStakeholderModule,
IconsModule,
PageContentModule
],
providers: [
PreviousRouteRecorder,
],
exports: [ManageStakeholdersComponent]
})
export class ManageStakeholdersModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([bullet, search, earth, group, lock, add]);
}
}

View File

@ -0,0 +1,53 @@
table {
font-size: 14px;
background-color: #FFFFFF;
width:100%;
table-layout: fixed;
overflow-wrap: break-word;
}
table th {
width: 25%;
}
table th, table td {
border: 1px solid #DEDEDE;
padding: 25px 40px;
vertical-align: top;
text-align: start;
}
table th.important {
background-color: #eff6e6;
}
ul.portal-circle {
list-style: none;
padding-left: 40px;
font-family: "Open Sans", sans-serif;
}
ul.portal-circle li {
margin: 0 0 2px 0;
position: relative;
}
ul.portal-circle li:before {
content: "";
border: 5px var(--portal-main-color) solid !important;
border-radius: 50px;
line-height: 21px;
margin-left: -20px;
position: absolute;
top: 7px;
}
@media only screen and (max-width: 959px) {
table th {
width: 50%;
}
ul.portal-circle {
padding-left: 20px;
}
}

View File

@ -0,0 +1,236 @@
import {Component, OnDestroy, OnInit} from "@angular/core";
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
import {Stakeholder} from "../openaireLibrary/monitor/entities/stakeholder";
import {Subscription} from "rxjs";
import {Meta, Title} from "@angular/platform-browser";
import {SEOService} from "../openaireLibrary/sharedComponents/SEO/SEO.service";
import {properties} from "../../environments/environment";
import {ActivatedRoute, Router} from "@angular/router";
@Component({
selector: 'methodology',
template: `
<div page-content>
<div inner>
<div class="uk-container uk-container-large uk-section-small">
<h2 class="uk-text-center">
Terminology and construction
</h2>
<div class="uk-margin-large-top">
<ul class="uk-tab admin customTabs uk-margin-medium-bottom" uk-tab>
<li [class.uk-active]="tab === 'entities'"><a (click)="tab = 'entities'"><span
class="title">Entities</span></a></li>
<li [class.uk-active]="tab === 'attributes'"><a (click)="tab = 'attributes'"><span class="title">Attributes of Entities</span></a>
</li>
</ul>
<table *ngIf="tab === 'entities'">
<tr>
<th class="important">Research Outcomes</th>
<td>
<div>There are currently four different types of research outcomes in the OpenAIRE Research
Graph:
</div>
<ul class="portal-circle">
<li>Publication</li>
<li>Dataset</li>
<li>Software</li>
<li>Other Research Product</li>
</ul>
<div class="uk-margin-small-top">
OpenAIRE deduplicates (merges) different records of research outcomes and keeps the metadata of all
instances.
</div>
</td>
</tr>
<tr>
<th>Publication</th>
<td>Research outcomes intended for human reading (published articles, pre-prints, conference papers,
presentations, technical reports, etc.)
</td>
</tr>
<tr>
<th>Dataset</th>
<td>
<p>Research data</p>
<p>Granularity is not defined by OpenAIRE, it reflects the granularity supported by
the sources from which the description of the dataset has been collected.</p>
</td>
</tr>
<tr>
<th>Software</th>
<td>Source code or software package developed and/or used in a research context</td>
</tr>
<tr>
<th>Other Research Product</th>
<td>Anything that does not fall in the previous categories (e.g. workflow, methods, protocols)</td>
</tr>
</table>
<table *ngIf="tab === 'attributes'">
<tr>
<th>Organization & Country</th>
<td>
<p><span class="uk-text-bold">For research outcomes:</span> the affiliated organizations of its
authors (and their country)</p>
<p><span class="uk-text-bold">For projects:</span> the organizations participating in the project
(i.e. beneficiaries of the grant) and
their countries
</p>
<p>
<span class="uk-text-bold">Country code mapping: </span>
<a href="https://api.openaire.eu/vocabularies/dnet:countries" target="_blank">
https://api.openaire.eu/vocabularies/dnet:countries</a>
</p>
</td>
</tr>
<tr>
<th>Type</th>
<td>
<p>The sub-type of a research outcome (e.g., a publication can be a pre-print, conference proceeding,
article,
etc.)</p>
<p><span class="uk-text-bold">Resource type mapping: </span>
<a href="https://api.openaire.eu/vocabularies/dnet:result_typologies" target="_blank">https://api.openaire.eu/vocabularies/dnet:result_typologies</a>
(click on the code to see the specific types for each result type)
</p>
</td>
</tr>
<tr>
<th>Access mode</th>
<td>
<p>The best available (across all instances) access rights of a research outcome</p>
<p>Types: open, restricted, closed, embargo (= closed for a specific period of time, then open)</p>
<p><span class="uk-text-bold">Note:</span> definition of <span class="uk-text-bold">restricted</span>
may vary by data source.</p>
</td>
</tr>
<tr>
<th>PID (persistent identifier)</th>
<td>
<p>A long-lasting reference to a resource</p>
<p><span class="uk-text-bold">Types: </span> <a
href="http://api.openaire.eu/vocabularies/dnet:pid_types" target="_blank">http://api.openaire.eu/vocabularies/dnet:pid_types</a>
</p>
</td>
</tr>
<tr>
<th>Context</th>
<td>Related research community, initiative or infrastructure</td>
</tr>
<tr>
<th>Journal</th>
<td>The scientific journal an article is published in.</td>
</tr>
<tr>
<th>Publisher</th>
<td>The publisher of the venue (journal, book, etc.) of a research outcome</td>
</tr>
<tr>
<th class="important">Content Providers (Datasources)</th>
<td>
<p>The different data sources ingested in the OpenAIRE Research Graph.</p>
<div class="uk-text-bold">Content Provider Types:</div>
<ul class="portal-circle">
<li>Repositories</li>
<li>Open Access Publishers & Journals</li>
<li>Aggregators</li>
<li>Entity Registries</li>
<li>Journal Aggregators</li>
<li>CRIS (Current Research Information System)</li>
</ul>
</td>
</tr>
<tr>
<th>Repositories</th>
<td>Information systems where scientists upload the bibliographic metadata and payloads of their
research outcomes (e.g. PDFs of their scientific articles, CSVs of their data, archive with their
software), due to obligations from their organizations, their funders, or due to community practices
(e.g. ArXiv, Europe PMC, Zenodo).
</td>
</tr>
<tr>
<th>Open Access Publishers & Journals</th>
<td>Information systems of open access publishers or relative journals, which offer bibliographic
metadata and PDFs of their published articles.
</td>
</tr>
<tr>
<th>Aggregators</th>
<td>Information systems that collect descriptive metadata about research products from multiple sources
in order to enable cross-data source discovery of given research products (e,g, DataCite,
BASE, DOAJ).
</td>
</tr>
<tr>
<th>Entity Registries</th>
<td>Information systems created with the intent of maintaining authoritative registries of given
entities in the scholarly communication, such as OpenDOAR for the institutional repositories, re3data
for the data repositories, CORDA and other funder databases for projects and funding information.
</td>
</tr>
<tr>
<th>CRIS (Current Research Information System)</th>
<td>Information systems adopted by research and academic organizations to keep track of their research
administration records and relative results; examples of CRIS content are articles or datasets funded
by projects, their principal investigators, facilities acquired thanks to funding, etc.
</td>
</tr>
</table>
<div class="uk-text-small uk-margin-small-top">
<img src="assets/common-assets/graph.svg" style="opacity: 0.4">
<span class="uk-margin-small-left uk-text-baseline uk-text-muted">More information for <a
href="https://graph.openaire.eu" class="graph-color">OpenAIRE Research Graph</a>.</span>
</div>
</div>
</div>
<div id="how" class="uk-container uk-container-large uk-section-small">
<h2 class="uk-text-center">
See how it works
</h2>
<div class="uk-margin-large-top">
<how></how>
</div>
</div>
</div>
</div>
`,
styleUrls: ['methodology.component.css']
})
export class MethodologyComponent implements OnInit, OnDestroy {
public stakeholder: Stakeholder;
public tab: 'entities' | 'attributes' = 'entities';
private subscriptions: any[] = [];
constructor(private stakeholderService: StakeholderService,
private seoService: SEOService,
private _meta: Meta,
private _router: Router,
private route: ActivatedRoute,
private _title: Title) {
}
ngOnInit() {
this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
this.stakeholder = stakeholder;
if (this.stakeholder) {
/* Metadata */
const url = properties.domain + properties.baseLink + this._router.url;
this.seoService.createLinkForCanonicalURL(url, false);
this._meta.updateTag({content: url}, "property='og:url'");
const description = "Methodology | " + this.stakeholder.name;
const title = "Methodology | " + this.stakeholder.name;
this._meta.updateTag({content: description}, "name='description'");
this._meta.updateTag({content: description}, "property='og:description'");
this._meta.updateTag({content: title}, "property='og:title'");
this._title.setTitle(title);
}
}));
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) {
subscription.unsubscribe();
}
});
}
}

View File

@ -0,0 +1,22 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {MethodologyComponent} from "./methodology.component";
import {RouterModule} from "@angular/router";
import {PreviousRouteRecorder} from "../openaireLibrary/utils/piwik/previousRouteRecorder.guard";
import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
import {HowModule} from "../openaireLibrary/monitor/how/how.module";
@NgModule({
declarations: [MethodologyComponent],
imports: [CommonModule, RouterModule.forChild([
{
path: '',
component: MethodologyComponent,
canDeactivate: [PreviousRouteRecorder]
},
]), PageContentModule, HowModule],
exports: [MethodologyComponent]
})
export class MethodologyModule {
}

View File

@ -2,7 +2,6 @@ import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import {PreviousRouteRecorder} from '../openaireLibrary/utils/piwik/previousRouteRecorder.guard';
import {MonitorComponent} from "./monitor.component";
import {OpenaireErrorPageComponent} from "../error/errorPage.component";
@NgModule({
imports: [
@ -11,77 +10,45 @@ import {OpenaireErrorPageComponent} from "../error/errorPage.component";
{
path: ':stakeholder',
component: MonitorComponent,
canDeactivate: [PreviousRouteRecorder],
data: {
activeMenuItem: "dashboard"
}
},
{
path: ':stakeholder/indicators',
loadChildren: () => import('../openaireLibrary/monitor/indicators/indicators.module').then(m => m.IndicatorsModule),
canDeactivate: [PreviousRouteRecorder],
data: {
hasSidebar: false
}
canDeactivate: [PreviousRouteRecorder]
},
{
path: ':stakeholder/develop',
loadChildren: () => import('../develop/develop.module').then(m => m.DevelopModule),
canDeactivate: [PreviousRouteRecorder],
data: {
hasSidebar: false
hasSidebar: false,
isDashboard: false
}
},
{
path: ':stakeholder/methodology',
loadChildren: () => import('../openaireLibrary/monitor/methodology/methodology.module').then(m => m.MethodologyModule),
loadChildren: () => import('../methodology/methodology.module').then(m => m.MethodologyModule),
canDeactivate: [PreviousRouteRecorder],
data: {
hasSidebar: false
hasSidebar: false,
isDashboard: false
}
},
{
path: ':stakeholder/search',
loadChildren: () => import('../search/search.module').then(m => m.SearchModule),
canDeactivate: [PreviousRouteRecorder],
data: {
hasSidebar: false,
activeMenuItem: "search"
}
},
{
path: ':stakeholder/error',
component: OpenaireErrorPageComponent,
data: {hasSidebar: false}
},
{
path: ':stakeholder/user-info',
loadChildren: () => import('../login/libUser.module').then(m => m.LibUserModule),
data: {hasSidebar: false}
canDeactivate: [PreviousRouteRecorder]
},
{
path: ':stakeholder/:topic',
component: MonitorComponent,
canDeactivate: [PreviousRouteRecorder],
data: {
activeMenuItem: "dashboard"
}
canDeactivate: [PreviousRouteRecorder]
},
{
path: ':stakeholder/:topic/:category',
component: MonitorComponent,
canDeactivate: [PreviousRouteRecorder],
data: {
activeMenuItem: "dashboard"
}
canDeactivate: [PreviousRouteRecorder]
},
{
path: ':stakeholder/:topic/:category/:subCategory',
component: MonitorComponent,
canDeactivate: [PreviousRouteRecorder],
data: {
activeMenuItem: "dashboard"
}
canDeactivate: [PreviousRouteRecorder]
}
])
]

View File

@ -0,0 +1,3 @@
.uk-card {
min-height: 270px;
}

View File

@ -1,308 +1,292 @@
<ng-template #selected_filters_pills>
<div class="uk-slider filters-slider" uk-slider="finite: true">
<div [class.uk-invisible]="list.children.length === 0" class="uk-position-relative">
<div class="uk-slider-container" style="height: 40px">
<ul #list class="uk-slider-items uk-grid uk-grid-small uk-margin-small-right uk-flex-nowrap">
<li *ngIf="periodFilter.selectedFromAndToValues.length > 0">
<span class="uk-label uk-label-primary uk-flex uk-flex-middle">
<span
class="uk-margin-small-right uk-width-expand uk-text-truncate">{{periodFilter.selectedFromAndToValues}}</span>
<button [class.uk-disabled]="loading" (click)="clearPeriodFilter()" class="uk-close uk-icon"
[disabled]="loading">
<icon name="close" flex="true" ratio="0.7"></icon>
</button>
</span>
</li>
<ng-container *ngFor="let filter of filters">
<ng-container *ngIf="filter.countSelectedValues > 0">
<ng-container *ngFor="let value of filter.values; let i = index;">
<ng-container *ngIf="value.selected">
<li>
<span class="uk-label uk-label-primary uk-flex uk-flex-middle">
<span class="uk-margin-small-right uk-width-expand uk-text-truncate">{{value.name}}</span>
<button [class.uk-disabled]="loading" (click)="clearFilterValue(filter, value)"
class="uk-close uk-icon" [disabled]="loading">
<icon name="close" flex="true" ratio="0.7"></icon>
</button>
<ng-template #selected_filters_pills let-margin="margin">
<!-- <div class="uk-grid uk-grid-small uk-text-small" uk-grid>-->
<span *ngIf="periodFilter.selectedFromAndToValues.length > 0" class="uk-grid-margin">
<a (click)="clearPeriodFilter()" [class]="((loading)?' uk-disabled':' ')+' uk-link-text '"> <span
class="selectedFilterLabel" [class.uk-margin-small-left]="margin"
title="Remove {{periodFilter.selectedFromAndToValues}}">
<i uk-icon="close"></i>
<span class="uk-margin-small-left">{{periodFilter.selectedFromAndToValues}}</span>
</span></a>
</span>
<ng-container *ngFor="let filter of filters ">
<ng-container *ngIf="filter.countSelectedValues > 0">
<ng-container *ngFor="let value of filter.values; let i = index; let end = last; ">
<ng-container *ngIf="value.selected">
<span class="uk-grid-margin">
<!-- if no grid on the div above, remove it and move class 'selectedFilterLabel' on top span -->
<span class="selectedFilterLabel " [class.uk-margin-small-left]="margin" [title]="'Remove '+value.name"
(click)="value.selected = false; filter.radioValue=''; filter.countSelectedValues=
filter.countSelectedValues -1;
filterChanged({value:filter}) ">
<a [class]="((loading)?' uk-disabled':' ')+' uk-link-text '">
<span class=" clickable" aria-hidden="true">
<span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="close" ratio="0.8"><path fill="none" stroke="#000" stroke-width="1.6"
d="M16,16 L4,4"></path><path fill="none"
stroke="#000"
stroke-width="1.6"
d="M16,4 L4,16"></path></svg>
</span>
</li>
</ng-container>
</ng-container>
</ng-container>
</ng-container>
</ul>
</div>
<slider-arrow type="previous"></slider-arrow>
<slider-arrow type="next"></slider-arrow>
</div>
</div>
</span>
<span class="uk-margin-small-left"
[innerHtml]="(value.name.length > 34)?value.name.substring(0,34)+'...':value.name"></span>
</a>
</span>
</span>
</ng-container>
</ng-container>
</ng-container>
</ng-container>
<!-- </div>-->
</ng-template>
<div page-content [border]="isMobile">
<div header>
<div *ngIf="stakeholder" class="uk-hidden">
<h1 class="uk-h6 uk-margin-remove">{{stakeholder.name}}</h1>
</div>
</div>
<div actions>
<sidebar-mobile-toggle *ngIf="isMobile" [class.uk-margin-bottom]="!activeCategory || countSubCategoriesToShow(activeCategory) <= 1" class="uk-margin-top uk-display-block"></sidebar-mobile-toggle>
<div *ngIf="activeCategory && countSubCategoriesToShow(activeCategory) > 1"
[class.uk-margin-bottom]="isMobile" class="uk-margin-medium-top">
<slider-tabs *ngIf="stakeholder && !loading && activeTopic" [border]="!isMobile"
[tabsClass]="isMobile?'uk-subnav uk-subnav-pill-alt uk-text-small':'uk-tab'" [type]="'dynamic'">
<ng-template ngFor [ngForOf]="activeCategory.subCategories" let-subCategory>
<slider-tab *ngIf="hasPermission(subCategory.visibility)" [tabTitle]="subCategory.name"
[queryParams]="queryParams" customClass="uk-text-uppercase"
[routerLink]="['/', stakeholder.alias, activeTopic.alias, activeCategory.alias, subCategory.alias]"
[active]="subCategory.alias === activeSubCategory.alias"></slider-tab>
</ng-template>
</slider-tabs>
<div page-content [class.greyOut]="filterToggle" (click)=" (filterToggle)?filterToggle = false:filterToggle">
<div *ngIf="activeTopic && activeTopic.categories.length > 0" header>
<nav class=" ">
<div *ngIf="stakeholder && status === errorCodes.DONE && activeTopic"
class="uk-grid uk-flex uk-flex-middle" uk-grid>
<div class="uk-width-expand">
<ul class="customTabs uk-tab">
<ng-template ngFor [ngForOf]="activeTopic.categories" let-category let-i="index">
<li *ngIf="isPublicOrIsMember(category.visibility)"
[class.uk-active]="category.alias ===
activeCategory.alias">
<a (click)="navigateTo(stakeholder.alias,activeTopic.alias, category.alias)">
<span class="title">{{category.name}}</span>
</a>
</li>
</ng-template>
</ul>
</div>
<div class="uk-width-auto@m uk-width-1-1 uk-flex uk-flex-center">
<a class="uk-text-uppercase uk-flex uk-flex-middle uk-flex-center">
<button class="uk-icon-button large uk-button-secondary" (click)="printReport()">
<icon name="print"></icon>
</button>
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary" (click)="printReport()">
Print Report
</button>
</a>
</div>
</div>
</nav>
<ul *ngIf="activeCategory && countSubCategoriesToShow(activeCategory) > 1"
class="uk-subnav uk-subnav-pill subCategoriesTabs ">
<ng-template ngFor [ngForOf]="activeCategory.subCategories" let-subCategory let-i="index">
<li *ngIf="isPublicOrIsMember(subCategory.visibility)"
[ngClass]="(subCategory.alias === activeSubCategory.alias)?'uk-active':''">
<a (click)="navigateTo(stakeholder.alias,activeTopic.alias,activeCategory.alias, subCategory.alias)"
class="uk-margin-remove-bottom"
><span>{{subCategory.name}}</span></a>
</li>
</ng-template>
</ul>
<div *ngIf="countSelectedFilters() > 0" class="uk-grid uk-grid-small uk-margin-bottom uk-text-small">
<span class="uk-grid-margin">Filters: </span>
<ng-container *ngTemplateOutlet="selected_filters_pills; context: {margin:true}"></ng-container>
</div>
</div>
<div inner>
<div *ngIf="privateStakeholder" class="message">
<div class="uk-text-center">
<h3 class="uk-flex uk-flex-middle">
<icon name="incognito" ratio="2" visuallyHidden="private"></icon>
<span class="uk-margin-left">Private data</span>
</h3>
</div>
</div>
<div *ngIf="!privateStakeholder && stakeholder" class="uk-section">
<div *ngIf="activeSubCategory?.description" class="uk-margin-medium-bottom">
{{activeSubCategory.description}}
</div>
<div *ngIf="(activeSubCategory && (activeSubCategory.charts.length == 0 || countSectionsWithIndicatorsToShow(activeSubCategory.charts) == 0))
&& ((activeSubCategory && activeSubCategory.description && activeSubCategory.description.length > 0) ||
(activeCategory && activeCategory.description && activeCategory.description.length > 0) ||
(activeTopic && activeTopic.description && activeTopic.description.length > 0))" class="uk-text-center">
<div class="uk-height-small uk-margin-large-top uk-margin-xlarge-right uk-margin-xlarge-left">
{{activeSubCategory && activeSubCategory.description && activeSubCategory.description.length > 0 ? activeSubCategory.description
: (activeCategory && activeCategory.description && activeCategory.description.length > 0 ? activeCategory.description :
(activeTopic.description && activeTopic.description.length > 0 ? activeTopic.description : ""))}}
</div>
</div>
<ng-template [ngIf]="!loading && !privateStakeholder &&
(!activeSubCategory ||
((activeSubCategory.numbers.length == 0 || countSectionsWithIndicatorsToShow(activeSubCategory.numbers) == 0) &&
(activeSubCategory.charts.length == 0 || countSectionsWithIndicatorsToShow(activeSubCategory.charts) == 0))
|| !activeTopic || !activeCategory || !activeSubCategory)" [ngIfElse]="content">
<div class="message uk-text-center">
<h3>
Nothing to see here!
<div [class.uk-padding]="!isSmallScreen" class="uk-padding-remove-vertical">
<div *ngIf="privateStakeholder" class="message">
<div class="uk-text-center">
<h3><i>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="black" width="24px" height="24px">
<path d="M0 0h24v24H0z" fill="none"/>
<path
d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/>
</svg>
</i>
Private data
</h3>
<div class="uk-text-large "></div>
</div>
</ng-template>
<ng-template #content>
<div *ngIf="countSectionsWithIndicatorsToShow(activeSubCategory.numbers) > 0" class="uk-margin-medium-bottom">
<ng-container *ngFor="let number of activeSubCategory.numbers; let i = index;">
<ng-container *ngIf="!isMobile && countIndicatorsToShow(number.indicators) > 0">
<div class="uk-grid uk-grid-small uk-grid-match uk-margin-medium-bottom" uk-grid
uk-height-match="target: .uk-card">
<h5 *ngIf="number.title" class="uk-width-1-1 uk-margin-bottom">{{number.title}}</h5>
<ng-template ngFor [ngForOf]="number.indicators" let-indicator let-j="index">
<div *ngIf="hasPermission(indicator.visibility)" [ngClass]="getNumberClassBySize(indicator.width)">
<div class="uk-card uk-card-default uk-padding-small number-card uk-position-relative"
[class.semiFiltered]="indicator.indicatorPaths[0].filtersApplied < countSelectedFilters()">
<div *ngIf="!indicator.overlay">
<div
class="uk-text-small uk-text-truncate uk-margin-xsmall-bottom uk-margin-right">{{indicator.name}}</div>
<div class="number uk-text-small uk-text-bold">
<span *ngIf="numberResults.get(i + '-' + j)"
[innerHTML]="(indicator.indicatorPaths[0].format == 'NUMBER'?(numberResults.get(i + '-' + j) | numberRound: 2:1:stakeholder.locale):(numberResults.get(i + '-' + j) | numberPercentage: stakeholder.locale))"></span>
<span *ngIf="!numberResults.get(i + '-' + j)">--</span>
</div>
<div *ngIf="indicator.description || indicator.additionalDescription"
class="uk-position-top-right uk-text-center uk-margin-small-top uk-margin-small-right uk-visible@m">
<a class="uk-display-inline-block uk-button uk-button-link" uk-tooltip="Note"
(click)="changeOverlay($event, indicator, 'description')">
<span class="uk-flex uk-flex-middle">
<icon name="analytics" type="outlined" [flex]="true"></icon>
</span>
</a>
</div>
</div>
<div
*ngIf="indicator.overlay && (indicator.description || indicator.additionalDescription)"
click-outside-or-esc class="uk-overflow-auto"
(clickOutside)="closeOverlay($event, indicator)">
<div class="uk-position-top-right uk-text-center uk-margin-small-top uk-margin-small-right">
<a class="uk-display-inline-block uk-button uk-button-link"
(click)="changeOverlay($event, indicator, false)">
<span class="uk-flex uk-flex-middle">
<icon name="close" type="outlined" [flex]="true"></icon>
</span>
</a>
</div>
<div class="uk-margin-small-top uk-margin-right">
<p *ngIf="indicator.description">
{{indicator.description}}
</p>
<p *ngIf="indicator.additionalDescription">
{{indicator.additionalDescription}}
</p>
</div>
</div>
</div>
</div>
</ng-template>
</div>
</ng-container>
<ng-container *ngIf="isMobile && countIndicatorsToShow(number.indicators) > 0">
<h6 *ngIf="number.title" class="uk-width-1-1 uk-margin-bottom">{{number.title}}</h6>
<div class="uk-card uk-card-default uk-padding-small number-card">
<div class="uk-grid uk-grid-small uk-child-width-1-1" uk-grid>
<ng-template ngFor [ngForOf]="number.indicators" let-indicator let-j="index">
<div *ngIf="hasPermission(indicator.visibility)" [ngClass]="getNumberClassBySize(indicator.width)">
<div [class.semiFiltered]="indicator.indicatorPaths[0].filtersApplied < countSelectedFilters()">
<div *ngIf="!indicator.overlay">
<div
class="uk-text-xsmall uk-text-truncate uk-margin-xsmall-bottom uk-margin-right">{{indicator.name}}</div>
<div class="number uk-text-small uk-text-bold">
<span *ngIf="numberResults.get(i + '-' + j)"
[innerHTML]="(indicator.indicatorPaths[0].format == 'NUMBER'?(numberResults.get(i + '-' + j) | numberRound: 2:1:stakeholder.locale):(numberResults.get(i + '-' + j) | numberPercentage: stakeholder.locale))"></span>
<span *ngIf="!numberResults.get(i + '-' + j)">--</span>
</div>
</div>
</div>
</div>
</ng-template>
</div>
</div>
</ng-container>
</ng-container>
</div>
<div *ngIf="!privateStakeholder && stakeholder">
<div *ngIf="(activeSubCategory && (activeSubCategory.charts.length == 0 || countSectionsWithIndicatorsToShow(activeSubCategory.charts) == 0))
&& ((activeSubCategory && activeSubCategory.description && activeSubCategory.description.length > 0) ||
(activeCategory && activeCategory.description && activeCategory.description.length > 0) ||
(activeTopic && activeTopic.description && activeTopic.description.length > 0))"
class="uk-text-center">
<div class="uk-height-small uk-margin-large-top uk-margin-xlarge-right uk-margin-xlarge-left">
{{activeSubCategory && activeSubCategory.description && activeSubCategory.description.length > 0 ? activeSubCategory.description
: (activeCategory && activeCategory.description && activeCategory.description.length > 0 ? activeCategory.description :
(activeTopic.description && activeTopic.description.length > 0 ? activeTopic.description : ""))}}
</div>
</div>
<ng-container *ngFor="let chart of activeSubCategory.charts; let i = index;">
<div *ngIf="countIndicatorsToShow(chart.indicators) > 0"
class="uk-grid uk-grid-small uk-grid-match uk-margin-medium-bottom uk-flex uk-flex-middle" uk-grid
<ng-template [ngIf]="!loading && !privateStakeholder &&
(!activeSubCategory ||
((activeSubCategory.numbers.length == 0 || countSectionsWithIndicatorsToShow(activeSubCategory.numbers) == 0) &&
(activeSubCategory.charts.length == 0 || countSectionsWithIndicatorsToShow(activeSubCategory.charts) == 0))
|| !activeTopic || !activeCategory || !activeSubCategory)" [ngIfElse]="content">
<div class="message uk-text-center">
<h3>
No indicators available yet. Stay tuned!
</h3>
</div>
</ng-template>
<ng-template #content>
<div *ngFor="let number of activeSubCategory.numbers; let i = index;"
class="uk-grid uk-grid-small uk-margin-bottom uk-margin-top"
uk-height-match="target: .uk-card">
<h5 *ngIf="chart.title && !isMobile" class="uk-width-1-1 uk-margin-bottom">{{chart.title}}</h5>
<h6 *ngIf="chart.title && isMobile" class="uk-width-1-1">{{chart.title}}</h6>
<ng-template ngFor [ngForOf]="chart.indicators" let-indicator let-j="index">
<div *ngIf="hasPermission(indicator.visibility) && chartsActiveType.get(i + '-' + j)"
[ngClass]="getChartClassBySize(indicator.width)">
<div class="uk-card uk-card-default uk-position-relative"
[class.semiFiltered]="chartsActiveType.get(i + '-' + j).filtersApplied < countSelectedFilters()">
<div class="uk-card-body uk-text-center uk-margin-small-bottom">
<h6 class="uk-margin-bottom chartTitle uk-flex uk-flex-bottom">
{{indicator.name + " "}}
</h6>
<div *ngIf="indicator.indicatorPaths.length > 1" class="uk-button-group">
<button *ngFor="let indicatorPath of indicator.indicatorPaths;"
class="uk-button"
(click)="setActiveChart(i, j, indicatorPath.type)"
[class.uk-button-secondary]="chartsActiveType.get(i + '-' + j).url === indicatorPath.url">
{{indicatorPath.type}}
</button>
</div>
<!--<div *ngIf="properties.environment === 'development'">
Filtered: {{chartsActiveType.get(i + '-' + j).filtersApplied}} out of
{{countSelectedFilters()}}</div>-->
<iframe [class.uk-blend-multiply]="!isFullscreen"
*ngIf=" !properties.disableFrameLoad && chartsActiveType.get(i + '-' + j).source !== 'image'"
[src]="chartsActiveType.get(i + '-' + j).safeResourceUrl"
class="uk-width-1-1" allowfullscreen="true" mozallowfullscreen="true"
[ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')"></iframe>
<div *ngIf="properties.disableFrameLoad && chartsActiveType.get(i + '-' + j).source !== 'image'">
<img class="uk-width-1-1 uk-blend-multiply"
[ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')"
src="assets/chart-placeholder.png">
</div>
<img *ngIf="chartsActiveType.get(i + '-' + j).source === 'image'"
[src]="chartsActiveType.get(i + '-' + j).safeResourceUrl"
class="uk-width-1-1 uk-blend-multiply"
[ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')">
<h5 *ngIf="countIndicatorsToShow(number.indicators)> 0 "
class="uk-width-1-1 uk-margin-bottom">{{number.title}}</h5>
<ng-template ngFor [ngForOf]="number.indicators" let-indicator let-j="index">
<div *ngIf="isPublicOrIsMember(indicator.visibility)" [ngClass]="getNumberClassBySize(indicator.width)" class="uk-margin-bottom">
<div class="uk-card uk-card-default uk-flex uk-flex-column uk-flex-center"
[class.uk-disabled]="indicator.indicatorPaths[0].filtersApplied < countSelectedFilters()"
[class.semiFiltered]="indicator.indicatorPaths[0].filtersApplied < countSelectedFilters()">
<div class="uk-card-body uk-text-center">
<div *ngIf="properties.environment === 'development'">Filtered:
{{indicator.indicatorPaths[0].filtersApplied}}
out of
{{countSelectedFilters()}}</div>
<div class="uk-text-bold ">{{indicator.name}}</div>
<h3 class="uk-margin-medium-top uk-text-bold">
<span *ngIf="numberResults.get(i + '-' + j)">{{numberResults.get(i + '-' + j) | number}}</span>
<span *ngIf="!numberResults.get(i + '-' + j)">--</span>
</h3>
<!--<ng-container *ngTemplateOutlet="description; context: {indicator:indicator}"></ng-container>-->
</div>
<div class="uk-position-bottom-left uk-margin-left uk-margin-small-bottom uk-visible@m">
<a *ngIf="indicator.description || indicator.additionalDescription"
class="uk-display-inline-block uk-button uk-button-text"
(click)="changeOverlay($event, indicator, 'description')">
<span class="uk-flex uk-flex-middle">
<icon name="analytics" type="outlined" [flex]="true"></icon>
<span class="uk-margin-small-left">Note</span>
</span>
</a>
</div>
<div *ngIf="indicator.overlay" class="indicator-overlay uk-card uk-card-default uk-flex uk-flex-middle uk-flex-center">
<div *ngIf="indicator.overlay == 'description'" class="inner" click-outside-or-esc
(clickOutside)="closeOverlay($event, indicator)">
<div class="uk-padding-small">
<div class="uk-flex uk-flex-right">
<button class="uk-close uk-icon" (click)="changeOverlay($event, indicator, false)">
<icon name="close" ratio="1"></icon>
</button>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<p *ngIf="indicator.description">
{{indicator.description}}
</p>
<p *ngIf="indicator.additionalDescription">
{{indicator.additionalDescription}}
</p>
</div>
<div *ngIf="indicator.description || indicator.additionalDescription" class="uk-overlay uk-position-bottom">
<div class="uk-padding-small">
<div *ngIf="indicator.description">
{{indicator.description}}
</div>
<div *ngIf="indicator.additionalDescription">
{{indicator.additionalDescription}}
</div>
</div>
</div>
</div>
</div>
<div class="printGap uk-hidden"></div>
</ng-template>
</div>
</ng-container>
</ng-template>
</div>
</div>
<div sticky_footer class="uk-visible@m">
<ng-container *ngTemplateOutlet="graph_and_feedback_template"></ng-container>
</div>
<ng-template #graph_and_feedback_template>
<div *ngIf="!view" class="uk-margin-small-top uk-margin-small-bottom uk-grid uk-grid-small uk-text-small hideInfo"
uk-grid>
<!-- Last Stats Date-->
<div class="uk-width-expand@m uk-width-1-1">
<a href="https://graph.openaire.eu" target="_blank" class="uk-width-1-1 uk-width-auto@m">
<img src="assets/common-assets/openaire-badge-1.png" alt="Powered by OpenAIRE graph" style="height: 16px;">
</a>
<span *ngIf="statsUpdateDate" class="uk-text-baseline uk-text-meta">
<span class="uk-margin-xsmall-left uk-margin-xsmall-right">-</span>
<span>Last update of statistics in OpenAIRE: {{statsUpdateDate | date: 'MMM dd, yyyy'}}</span>
</span>
</div>
<!--Feedback-->
<div class="uk-width-auto@m uk-width-1-1">
<span class="uk-text-meta">Send us your </span>
<a class="uk-link" [href]="feedback" target="_self">feedback</a>
<span class="uk-text-meta">.</span>
<div [class.uk-margin-large-top]="activeSubCategory.numbers.length > 0">
<div *ngFor="let chart of activeSubCategory.charts; let i = index;"
class="uk-grid uk-grid-small uk-margin-bottom uk-flex uk-flex-middle "
uk-height-match="target: .uk-card">
<h5 *ngIf="chart.title && chart.title.length > 0 && countIndicatorsToShow(chart.indicators) > 0 "
class="uk-width-1-1 uk-margin-bottom">{{chart.title}}</h5>
<ng-template ngFor [ngForOf]="chart.indicators" let-indicator let-j="index">
<div
*ngIf="isPublicOrIsMember(indicator.visibility) && chartsActiveType.get(i + '-' + j)"
[ngClass]="getChartClassBySize(indicator.width)" class="uk-margin-bottom">
<div class="uk-card uk-card-default"
[class.uk-disabled]="chartsActiveType.get(i + '-' + j).filtersApplied < countSelectedFilters()"
[class.semiFiltered]="chartsActiveType.get(i + '-' + j).filtersApplied < countSelectedFilters()">
<div class="uk-card-body uk-text-center">
<h4 class="uk-margin-bottom chartTitle uk-flex uk-flex-bottom ">
<div>{{indicator.name + " "}}</div>
</h4>
<div *ngIf="indicator.indicatorPaths.length > 1" class="uk-button-group">
<button *ngFor="let indicatorPath of indicator.indicatorPaths;"
class="uk-button"
(click)="setActiveChart(i, j, indicatorPath.type)"
[class.uk-button-secondary]="chartsActiveType.get(i + '-' + j).url === indicatorPath.url">
{{indicatorPath.type}}
</button>
</div>
<div *ngIf="properties.environment === 'development'">
Filtered: {{chartsActiveType.get(i + '-' + j).filtersApplied}} out of
{{countSelectedFilters()}}</div>
<iframe *ngIf=" !properties.disableFrameLoad && chartsActiveType.get(i + '-' + j).source !==
'image'"
[src]="chartsActiveType.get(i + '-' + j).safeResourceUrl"
[class]="' uk-width-1-1 uk-height-' +
(indicator.height?indicator.height.toLowerCase():'medium')"></iframe>
<div *ngIf="properties.disableFrameLoad && chartsActiveType.get(i + '-' + j).source !==
'image'" class="uk-alert uk-alert-danger uk-text-center">I frames preview is disabled</div>
<!-- {{chartsActiveType.get(i).safeResourceUrl}}-->
<!-- <a [href]="chartsActiveType.get(i).safeResourceUrl" target="_blank" > ChartuURL</a>-->
<img *ngIf="chartsActiveType.get(i + '-' + j).source === 'image'"
[src]="chartsActiveType.get(i + '-' + j).safeResourceUrl"
[class]="' uk-width-1-1 uk-height-' +
(indicator.height?indicator.height.toLowerCase():'medium')">
<!--<ng-container *ngTemplateOutlet="description; context: {indicator:indicator}"></ng-container>-->
</div>
<div *ngIf="indicator.description || indicator.additionalDescription"
class="uk-overlay uk-position-bottom">
<div class="uk-padding multi-line-ellipsis lines-3">
<p class="uk-margin-remove">
<span *ngIf="indicator.description">
{{indicator.description}}
</span>
<br>
<span *ngIf="indicator.additionalDescription">
{{indicator.additionalDescription}}
</span>
</p>
</div>
</div>
</div>
</div>
</ng-template>
</div>
</div>
<div class="uk-margin-medium-top uk-flex hideInfo">
<!-- Last Stats Date-->
<div class="uk-width-2-3@m uk-width-1-2">
<img src="assets/common-assets/graph.svg" style="opacity: 0.4">
<span class="uk-margin-small-left uk-text-baseline uk-text-muted">Powered by <a
href="https://graph.openaire.eu" class="graph-color">OpenAIRE Research Graph</a></span>
<span *ngIf="statsUpdateDate" class="uk-text-baseline uk-text-muted">
. Last update of statistics in OpenAIRE: {{statsUpdateDate | date: 'MMM dd, yyyy'}}
</span>
</div>
<!--Feedback-->
<div class="uk-width-expand uk-text-right">
<span class="uk-text-muted">Send us your <a [href]="feedback" target="_self">feedback</a>.</span>
</div>
</div>
</ng-template>
</div>
</div>
</ng-template>
</div>
</div>
<a *ngIf="stakeholder && !privateStakeholder " href="#style_switcher" uk-toggle="" id="filters_switcher_toggle"
class="uk-offcanvas-switcher uk-flex uk-flex-center uk-flex-middle uk-link-reset">
<icon name="filters" ratio="1.5" visuallyHidden="Filters" gradient="filters_icon"></icon>
<span [class.uk-hidden]="countSelectedFilters() === 0"
class="uk-offcanvas-count uk-flex uk-flex-middle uk-flex-center">
{{countSelectedFilters()}}
</span>
</a>
<div *ngIf="stakeholder && !privateStakeholder" id="style_switcher" class="uk-offcanvas"
uk-offcanvas="flip:true; overlay: true">
<div class="uk-offcanvas-bar">
<!--(click)="filterToggle= !filterToggle"
[style.display]="(filterToggle?'none':'inherit')"-->
<div *ngIf="stakeholder && !privateStakeholder " href="#style_switcher" uk-toggle="" id="filters_switcher_toggle">
<i class=" uk-text-muted">
<svg style="margin-top: 8px;" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24"
viewBox="0 0 20 20"
fill="white" width="24px" height="16px">
<g>
<path d="M0,0h24 M24,24H0" fill="none"/>
<path
d="M4.25,5.61C6.57,8.59,10,13,10,13v5c0,1.1,0.9,2,2,2h0c1.1,0,2-0.9,2-2v-5c0,0,3.43-4.41,5.75-7.39 C20.26,4.95,19.79,4,18.95,4H5.04C4.21,4,3.74,4.95,4.25,5.61z"/>
<path d="M0,0h24v24H0V0z" fill="none"/>
</g>
</svg>
</i>
</div>
<div *ngIf="stakeholder && !privateStakeholder" id="style_switcher" class=" uk-offcanvas filters_switcher"
uk-offcanvas="flip:true" mode="slide" overlay="" style="z-index:982;">
<div class="uk-offcanvas-bar offcanvas-white">
<div class="uk-float-right">
<button class="uk-offcanvas-close uk-close uk-icon" type="button">
<icon name="close" ratio="1.5" visuallyHidden="close"></icon>
</button>
<button class="uk-offcanvas-close uk-close uk-icon" type="button" uk-close=""></button>
</div>
<div>
<div class="uk-flex uk-flex-middle uk-margin-bottom">
<h4 class="uk-margin-remove-bottom">Filters</h4>
<a *ngIf="countSelectedFilters() > 1" class="uk-text-small uk-margin-left" (click)="clearAll()"> Clear All </a>
<div class="uk-padding">
<div class="uk-grid uk-flex uk-flex-middle">
<h5>Filters</h5>
<a *ngIf="countSelectedFilters() > 1"
class=" portal-link uk-width-1-2" (click)="clearAll()"> Clear All </a>
</div>
<ng-container *ngTemplateOutlet="selected_filters_pills"></ng-container>
<div *ngIf="!user" class="uk-margin-top"><a class="uk-link" (click)="logIn()"> Sign in</a> to apply filters.</div>
<ul *ngIf="user" class="uk-list uk-list-xlarge uk-list-divider uk-margin-top">
<div class="uk-grid uk-grid-small uk-text-small" uk-grid>
<ng-container *ngTemplateOutlet="selected_filters_pills; context: {margin:false}"></ng-container>
</div>
<div *ngIf="user || countSelectedFilters() > 0 " class="uk-margin-small-top"><i
class="uk-text-muted uk-text-small"> If your filter
selection cannot be
applied to a chart, that chart will appear grayed-out.</i></div>
<div
*ngIf="!user" class="uk-margin-top uk-alert uk-alert-warning"> Sign in to apply filters</div>
<ul *ngIf="user" class="uk-list uk-list-divider uk-margin-medium">
<li>
<range-filter #rangeFilter [filter]="periodFilter"[yearMin]="minYear" [yearMax]="maxYear"
[mandatoryRange]="true" (onFilterChange)="filter()"></range-filter>
<range-filter [filter]="periodFilter" yearMin="2000" [yearMax]="currentYear" [mandatoryRange]="true"
(onFilterChange)="filter()"></range-filter>
</li>
<ng-container *ngFor="let filter of filters ">
<li *ngIf="filter.values.length >0">
@ -311,14 +295,19 @@
</li>
</ng-container>
</ul>
<i *ngIf="user || countSelectedFilters() > 0 " class="uk-margin-medium-top uk-text-small uk-display-block">
<sup>*</sup> If your filter selection cannot be applied to a chart, that chart will appear grayed-out.
</i>
</div>
</div>
</div>
<!-- <div *ngIf="stakeholder && !loading && activeTopic" id="print_toggle"
class="uk-offcanvas-switcher uk-flex uk-flex-center uk-flex-middle" (click)="printReport()">
<icon name="print" ratio="1.5" customClass="uk-text-background" visuallyHidden="Print"></icon>
</div> -->
<ng-template #description let-indicator="indicator">
<span class="descriptionIcon"
*ngIf="(indicator.description && indicator.description.length > 0)
|| (indicator.additionalDescription && indicator.additionalDescription.length > 0)"
uk-icon="info"
[attr.uk-tooltip]="'title:<div class=\'uk-padding-small\'>'+
(indicator.description&& indicator.description.length > 0?indicator.description:'') +'<br>'+
(indicator.additionalDescription && indicator.additionalDescription.length?indicator.additionalDescription:'')
+'</div>'">
</span>
</ng-template>

View File

@ -1,7 +0,0 @@
@import (reference) "~src/assets/openaire-theme/less/_import-variables";
&.semiFiltered {
&, & > * > .highcharts-series-group {
opacity: 0.5;
}
}

View File

@ -1,47 +1,102 @@
import {ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {ChangeDetectorRef, Component, OnDestroy, OnInit, ViewRef} from '@angular/core';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {DomSanitizer, Meta, Title} from '@angular/platform-browser';
import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties';
import {PiwikService} from '../openaireLibrary/utils/piwik/piwik.service';
import {StringUtils} from '../openaireLibrary/utils/string-utils.class';
import {Dates, StringUtils} from '../openaireLibrary/utils/string-utils.class';
import {ErrorCodes} from '../openaireLibrary/utils/properties/errorCodes';
import {ErrorMessagesComponent} from '../openaireLibrary/utils/errorMessages.component';
import {HelperService} from "../openaireLibrary/utils/helper/helper.service";
import {SEOService} from "../openaireLibrary/sharedComponents/SEO/SEO.service";
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
import {IndicatorPath} from "../openaireLibrary/monitor/entities/stakeholder";
import {StatisticsService} from "../openaireLibrary/monitor-admin/utils/services/statistics.service";
import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service";
import {Subscription} from "rxjs";
import {UserManagementService} from "../openaireLibrary/services/user-management.service";
import {IndexInfoService} from "../openaireLibrary/utils/indexInfo.service";
import {RangeFilterComponent} from "../openaireLibrary/utils/rangeFilter/rangeFilter.component";
import {
MonitorIndicatorStakeholderBaseComponent
} from "../openaireLibrary/monitor/monitor-indicator-stakeholder-base.component";
Category, Indicator,
IndicatorPath, IndicatorSize, Section,
Stakeholder,
SubCategory,
Topic,
Visibility
} from "../openaireLibrary/monitor/entities/stakeholder";
import {StatisticsService} from "../utils/services/statistics.service";
import {IndicatorUtils, StakeholderUtils} from "../utils/indicator-utils";
import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service";
import {FormBuilder, FormControl} from "@angular/forms";
import {Subscriber, Subscription} from "rxjs";
import {User} from "../openaireLibrary/login/utils/helper.class";
import {UserManagementService} from "../openaireLibrary/services/user-management.service";
import {RangeFilter} from "../openaireLibrary/utils/rangeFilter/rangeFilterHelperClasses.class";
import {Filter} from "../openaireLibrary/searchPages/searchUtils/searchHelperClasses.class";
import {Location} from "@angular/common";
import {RouterHelper} from "../openaireLibrary/utils/routerHelper.class";
import {properties} from "../../environments/environment";
import {IndexInfoService} from "../openaireLibrary/utils/indexInfo.service";
import {ConfigurationService} from "../openaireLibrary/utils/configuration/configuration.service";
@Component({
selector: 'monitor',
templateUrl: 'monitor.component.html',
styleUrls: ['monitor.component.less']
styleUrls: ['monitor.component.css']
})
export class MonitorComponent extends MonitorIndicatorStakeholderBaseComponent implements OnInit {
@ViewChild('rangeFilter') rangeFilter: RangeFilterComponent;
export class MonitorComponent implements OnInit, OnDestroy {
public user: User;
public subscriptions: any[] = [];
piwikSiteId;
title;
description;
public pageContents = null;
public divContents = null;
public status: number;
public loading: boolean = true;
public isViewPublic: boolean = false;
public indicatorUtils: IndicatorUtils = new IndicatorUtils();
public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public activeTopic: Topic = null;
public activeCategory: Category = null;
public activeSubCategory: SubCategory = null;
public errorCodes: ErrorCodes;
public stakeholder: Stakeholder;
public numberResults: Map<string, number> = new Map<string, number>();
public chartsActiveType: Map<string, IndicatorPath> = new Map<string, IndicatorPath>();
private errorMessages: ErrorMessagesComponent;
properties: EnvProperties = properties;
filterToggle = false;
public routerHelper: RouterHelper = new RouterHelper();
filters: Filter[] = [];
queryParams = {};
public currentYear = new Date().getFullYear();
periodFilter: RangeFilter = {
title: "Time range",
filterId: "year",
originalFilterIdFrom: null,
originalFilterIdTo: null,
selectedFromValue: null,
selectedToValue: null,
selectedFromAndToValues: ""
};
privateStakeholder = false;
public keyword: FormControl;
public statsUpdateDate: Date;
constructor(
protected _route: ActivatedRoute,
protected _router: Router,
protected _meta: Meta,
protected _title: Title,
protected _piwikService: PiwikService,
protected seoService: SEOService,
protected sanitizer: DomSanitizer,
protected cdr: ChangeDetectorRef,
protected layoutService: LayoutService,
protected statisticsService: StatisticsService,
private route: ActivatedRoute,
private _router: Router,
private _meta: Meta,
private _title: Title,
private _piwikService: PiwikService,
private helper: HelperService,
private stakeholderService: StakeholderService,
private userManagementService: UserManagementService,
private indexInfoService: IndexInfoService) {
super();
private statisticsService: StatisticsService,
private layoutService: LayoutService,
private seoService: SEOService,
private cdr: ChangeDetectorRef,
private indexInfoService: IndexInfoService,
private sanitizer: DomSanitizer, private _fb: FormBuilder, private router: Router,
private configurationService: ConfigurationService) {
this.errorCodes = new ErrorCodes();
this.errorMessages = new ErrorMessagesComponent();
this.status = this.errorCodes.LOADING;
}
public ngOnInit() {
@ -52,19 +107,31 @@ export class MonitorComponent extends MonitorIndicatorStakeholderBaseComponent i
}
}));
}
this.keyword = this._fb.control('');
this.subscriptions.push(this.keyword.valueChanges.subscribe(value => {
console.log("Keyword Changed!");
//TODO do a real action
}));
let subscription: Subscription;
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
this.user = user;
this.subscriptions.push(this._route.params.subscribe(params => {
this.subscriptions.push(this.route.params.subscribe(params => {
this.loading = true;
this.activeTopic = null;
this.activeCategory = null;
this.activeSubCategory = null;
this.filterToggle = false;
if (subscription) {
subscription.unsubscribe();
}
var url = properties.domain + properties.baseLink + this._router.url;
this.subscriptions.push(this.route.queryParams.subscribe(params => {
this.queryParams = Object.assign({}, params);
this.isViewPublic = (params['view'] == 'public');
}));
if (!this.stakeholder || this.stakeholder.alias !== params['stakeholder']) {
this.status = this.errorCodes.LOADING;
this.numberResults = new Map<string, number>();
this.chartsActiveType = new Map<string, IndicatorPath>();
subscription = this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
@ -92,7 +159,7 @@ export class MonitorComponent extends MonitorIndicatorStakeholderBaseComponent i
}
if (this.stakeholder.type == "funder") {
// this.filters.push({title: "Co-funded research outcomes",filterId: "co-funded",originalFilterId: "co-funded", countSelectedValues: 0,
// values:[{fname: "true", id: "co-funded", selected: false, number: 0}, {name: "false", id: "no-co-funded", selected: false, number: 0}]
// values:[{name: "true", id: "co-funded", selected: false, number: 0}, {name: "false", id: "no-co-funded", selected: false, number: 0}]
// ,filterOperator: "or", valueIsExact: true, filterType: "radio", radioValue:""});
this.filters.push({
title: "Co-funded", filterId: "co-funded", originalFilterId: "co-funded", countSelectedValues: 0,
@ -100,20 +167,38 @@ export class MonitorComponent extends MonitorIndicatorStakeholderBaseComponent i
, filterOperator: "or", valueIsExact: true, filterType: "checkbox", radioValue: ""
});
}
this.subscriptions.push(this._route.queryParams.subscribe(queryParams => {
this.handleQueryParams(queryParams, params);
this.title = "Monitor Dashboard | " + this.stakeholder.name;
this.description = "Monitor Dashboard | " + this.stakeholder.name;
this.setMetadata();
if (this.hasPermission((this.view && this.isManager(this.stakeholder))?this.view:this.stakeholder.visibility)) {
this.setView(params);
} else {
this.privateStakeholder = true;
if (subscription) {
subscription.unsubscribe();
this.initializeFilters();
this.seoService.createLinkForCanonicalURL(url, false);
this._meta.updateTag({content: url}, "property='og:url'");
this.description = "Monitor Dashboard | " + this.stakeholder.name;
this.title = "Monitor Dashboard | " + this.stakeholder.name;
this._meta.updateTag({content: this.description}, "name='description'");
this._meta.updateTag({content: this.description}, "property='og:description'");
this._meta.updateTag({content: this.title}, "property='og:title'");
this._title.setTitle(this.title);
if (this.properties.enablePiwikTrack && (typeof document !== 'undefined')) {
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal && portal.piwik) {
console.debug(portal)
this.piwikSiteId = portal.piwik;
console.debug(this.piwikSiteId)
this.subscriptions.push(this._piwikService.trackView(this.properties, this.title, this.piwikSiteId).subscribe());
}
}));
}
if (this.isPublicOrIsMember(stakeholder.visibility)) {
//this.getDivContents();
// this.getPageContents();
this.status = this.errorCodes.DONE;
this.setView(params);
} else {
this.privateStakeholder = true;
// this.navigateToError();
if (subscription) {
subscription.unsubscribe();
}
}));
}
} else {
this.navigateToError();
if (subscription) {
@ -123,15 +208,207 @@ export class MonitorComponent extends MonitorIndicatorStakeholderBaseComponent i
});
this.subscriptions.push(subscription);
} else {
this.trackView();
this.subscriptions.push(this._route.queryParams.subscribe(queryParams => {
this.handleQueryParams(queryParams, params);
}));
if (this.properties.enablePiwikTrack && (typeof document !== 'undefined')) {
if (this.piwikSiteId) {
console.debug(this.piwikSiteId)
this.subscriptions.push(this._piwikService.trackView(this.properties, this.title, this.piwikSiteId).subscribe());
}
}
this.initializeFilters();
this.setView(params);
}
}));
}));
}
private initializeFilters() {
this.periodFilter.selectedFromValue = (this.queryParams['year'] && this.queryParams['year'].indexOf("range") == 0) ? this.queryParams['year'].split("range")[1].split(":")[0] : "";
this.periodFilter.selectedToValue = (this.queryParams['year'] && this.queryParams['year'].indexOf("range") == 0) ? this.queryParams['year'].split("range")[1].split(":")[1] : "";
this.validateYearRange(false);
for (let filter of this.filters) {
if (this.queryParams[filter.filterId]) {
for (let value of filter.values) {
if (value.id == StringUtils.URIDecode(StringUtils.unquote(this.queryParams[filter.filterId]))) {
value.selected = true;
filter.countSelectedValues = 1;
break;
}
}
} else {
this.clearfFilter(filter);
}
}
}
private validateYearRange(navigateTo: boolean = false) {
let validYears = true;
if (this.periodFilter.selectedToValue && (this.periodFilter.selectedToValue.length == 0 || !Dates.isValidYear(this.periodFilter.selectedToValue, Dates.currentYear - 20, Dates.currentYear))) {
this.periodFilter.selectedToValue = Dates.currentYear + "";
validYears = false;
}
if (this.periodFilter.selectedFromValue && (this.periodFilter.selectedFromValue.length == 0 || !Dates.isValidYear(this.periodFilter.selectedFromValue, Dates.currentYear - 20, Dates.currentYear))) {
this.periodFilter.selectedFromValue = Dates.currentYear - 20 + "";
validYears = false;
}
if (this.periodFilter.selectedFromValue && this.periodFilter.selectedFromValue.length && this.periodFilter.selectedToValue && this.periodFilter.selectedToValue.length > 0 && parseInt(this.periodFilter.selectedFromValue, 10) > parseInt(this.periodFilter.selectedToValue, 10)) {
this.periodFilter.selectedFromValue = this.periodFilter.selectedToValue;
validYears = false;
}
if (!validYears || navigateTo) {
if (this.periodFilter.selectedFromValue || this.periodFilter.selectedToValue) {
this.queryParams["year"] = 'range' + (this.periodFilter.selectedFromValue ? this.periodFilter.selectedFromValue : '') + ":" + (this.periodFilter.selectedToValue ? this.periodFilter.selectedToValue : "");
} else {
delete this.queryParams["year"];
}
// this.location.go(location.pathname, this.routerHelper.createQueryParamsString( Object.keys(this.queryParams), Object.values(this.queryParams)));
this.router.navigate([], {queryParams: this.queryParams});
this.setIndicators();
}
}
clearAll() {
for (let filter of this.filters) {
this.clearfFilter(filter);
}
this.periodFilter.selectedFromValue = "";
this.periodFilter.selectedToValue = "";
this.validateYearRange(true)
}
clearfFilter(filter: Filter) {
filter.countSelectedValues = 0;
filter.radioValue = "";
for (let value of filter.values) {
if (value.selected) {
value.selected = false;
}
}
if (this.queryParams[filter.filterId]) {
delete this.queryParams[filter.filterId];
}
}
countSelectedFilters(): number {
let count = 0;
if (this.periodFilter.selectedFromAndToValues.length > 0) {
count += 2;
}
for (let filter of this.filters) {
count += filter.countSelectedValues;
}
return count;
}
public get isSmallScreen() {
return this.layoutService.isSmallScreen;
}
public get open() {
return this.layoutService.open;
}
private getPageContents() {
this.subscriptions.push(this.helper.getPageHelpContents(this.properties, this.properties.adminToolsCommunity, this._router.url).subscribe(contents => {
this.pageContents = contents;
}));
}
private getDivContents() {
this.subscriptions.push(this.helper.getDivHelpContents(this.properties, this.properties.adminToolsCommunity, this._router.url).subscribe(contents => {
this.divContents = contents;
}));
}
private setView(params: Params) {
this.loading = false;
if (params['topic']) {
this.activeTopic = this.stakeholder.topics.find(topic => topic.alias === decodeURIComponent(params['topic']) && this.isPublicOrIsMember(topic.visibility));
if (this.activeTopic) {
if (params['category']) {
this.activeCategory = this.activeTopic.categories.find(category =>
(category.alias === params['category']) && this.isPublicOrIsMember(category.visibility));
if (!this.activeCategory) {
this.navigateToError();
return;
}
} else {
this.activeCategory = this.activeTopic.categories.find(category => this.isPublicOrIsMember(category.visibility));
if (this.activeCategory) {
this.activeSubCategory = this.activeCategory.subCategories.find(subCategory =>
this.isPublicOrIsMember(subCategory.visibility));
if (this.activeSubCategory) {
this.setIndicators();
}
}
return;
}
if (this.activeCategory) {
if (params['subCategory']) {
this.activeSubCategory = this.activeCategory.subCategories.find(subCategory =>
(subCategory.alias === params['subCategory'] && this.isPublicOrIsMember(subCategory.visibility)));
if (!this.activeSubCategory) {
this.navigateToError();
return;
}
} else {
this.activeSubCategory = this.activeCategory.subCategories.find(subCategory =>
this.isPublicOrIsMember(subCategory.visibility));
}
if (this.activeSubCategory) {
this.setIndicators();
} else {
this.navigateToError();
}
return;
} else {
this.activeSubCategory = null;
}
} else {
this.navigateToError();
return;
}
} else {
this.activeTopic = this.stakeholder.topics.find(topic => this.isPublicOrIsMember(topic.visibility));
if (this.activeTopic) {
this.activeCategory = this.activeTopic.categories.find(category => this.isPublicOrIsMember(category.visibility));
if (this.activeCategory) {
this.activeSubCategory = this.activeCategory.subCategories.find(subCategory => this.isPublicOrIsMember(subCategory.visibility));
if (this.activeSubCategory) {
this.setIndicators();
}
}
}
}
}
filter() {
this.validateYearRange(true);
}
filterChanged($event, navigate: boolean = true) {
let selected = "";
for (let value of $event.value.values) {
if (value.selected) {
selected = value.id;
break;
}
}
if (selected) {
this.queryParams[$event.value.filterId] = StringUtils.quote(StringUtils.URIEncode(selected));
} else {
delete this.queryParams[$event.value.filterId];
}
if (navigate) {
this.router.navigate([], {queryParams: this.queryParams});
this.setIndicators();
}
}
private getfl0() {
if (this.queryParams["relfundinglevel0_id"] && this.filters.length > 0) {
let value = StringUtils.URIDecode(StringUtils.unquote(this.queryParams["relfundinglevel0_id"]));
@ -139,23 +416,172 @@ export class MonitorComponent extends MonitorIndicatorStakeholderBaseComponent i
}
return null;
}
private getCoFunded() {
if (this.queryParams["co-funded"] && this.filters.length > 0) {
return this.queryParams["co-funded"] && StringUtils.URIDecode(StringUtils.unquote(this.queryParams["co-funded"])) == "co-funded-results";
}
return false;
}
public getFullUrl(indicatorPath: IndicatorPath) {
return this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, indicatorPath, this.getfl0(), this.periodFilter.selectedFromValue, this.periodFilter.selectedToValue, this.getCoFunded());
clearPeriodFilter() {
if (this.periodFilter.selectedFromValue || this.periodFilter.selectedToValue) {
this.periodFilter.selectedFromValue = "";
this.periodFilter.selectedToValue = "";
this.filter();
}
}
private setIndicators() {
this.periodFilter.selectedFromAndToValues = (this.periodFilter.selectedFromValue || this.periodFilter.selectedToValue ? ((this.periodFilter.selectedFromValue && !this.periodFilter.selectedToValue ? "From " : "") + (!this.periodFilter.selectedFromValue && this.periodFilter.selectedToValue ? "Until " : "") + (this.periodFilter.selectedFromValue ? this.periodFilter.selectedFromValue : "") +
(this.periodFilter.selectedFromValue && this.periodFilter.selectedToValue ? " - " : "") + (this.periodFilter.selectedToValue ? this.periodFilter.selectedToValue : "")) : "");
//clear numbers when filters change
this.numberResults.clear();
let urls: Map<string, [number, number][]> = new Map<string, [number, number][]>();
this.activeSubCategory.numbers.forEach((section, i) => {
section.indicators.forEach((number, j) => {
if (this.isPublicOrIsMember(number.visibility)) {
let url = this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, number.indicatorPaths[0], this.getfl0(), this.periodFilter.selectedFromValue, this.periodFilter.selectedToValue, this.getCoFunded());
const pair = JSON.stringify([number.indicatorPaths[0].source, url]);
const indexes = urls.get(pair) ? urls.get(pair) : [];
indexes.push([i, j]);
urls.set(pair, indexes);
}
});
});
urls.forEach((indexes, pair) => {
pair = JSON.parse(pair);
this.subscriptions.push(this.statisticsService.getNumbers(this.statisticsService.getSourceType(pair[0]), pair[1]).subscribe(response => {
indexes.forEach(([i, j]) => {
let result = JSON.parse(JSON.stringify(response));
this.activeSubCategory.numbers[i].indicators[j].indicatorPaths[0].jsonPath.forEach(jsonPath => {
if (result) {
result = result[jsonPath];
}
});
if (typeof result === 'string' || typeof result === 'number') {
result = Number(result);
if (result === Number.NaN) {
result = 0;
}
} else {
result = 0;
}
this.numberResults.set(i + '-' + j, result);
});
}));
});
this.activeSubCategory.charts.forEach((section, i) => {
section.indicators.forEach((indicator, j) => {
if (indicator.indicatorPaths.length > 0) {
indicator.indicatorPaths[0].safeResourceUrl = this.getUrlByStakeHolder(indicator.indicatorPaths[0]);
this.chartsActiveType.set(i + '-' + j, indicator.indicatorPaths[0]);
}
});
});
if (this.cdr && !(this.cdr as ViewRef).destroyed) {
this.cdr.detectChanges();
}
}
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())));
}
public setActiveChart(i: number, j: number, type: string) {
let activeChart = this.activeSubCategory.charts[i].indicators[j].indicatorPaths.filter(indicatorPath => indicatorPath.type === type)[0];
activeChart.safeResourceUrl = this.getUrlByStakeHolder(activeChart);
this.chartsActiveType.set(i + '-' + j, activeChart);
}
private navigateToError() {
this._router.navigate(['/error'], {queryParams: {'page': this._router.url}});
}
public navigateTo(stakeholder: string, topic: string, category: string = null, subcategory: string = null) {
let url = stakeholder + '/' + topic + ((category) ? ('/'
+ category) : '') + ((subcategory) ? ('/' + subcategory) : '');
return this._router.navigate([url], {queryParams: this.queryParams});
}
public quote(param: string): string {
return StringUtils.quote(param);
}
public ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
public isPublicOrIsMember(visibility: Visibility): boolean {
if (visibility == "PRIVATE" || (this.isViewPublic && visibility != "PUBLIC")) {
return false;
}
return true;
}
public countSubCategoriesToShow(category: Category): number {
let counter = 0;
for (let sub of category.subCategories) {
if (this.isPublicOrIsMember(sub.visibility)) {
counter++;
}
}
return counter;
}
public countSectionsWithIndicatorsToShow(sections: Section[]):number {
let counter = 0;
sections.forEach(section => {
section.indicators.forEach(indicator => {
if (this.isPublicOrIsMember(indicator.visibility)) {
counter++;
}
});
});
return counter;
}
public countIndicatorsToShow(indicators: Indicator[]): number {
let counter = 0;
indicators.forEach(indicator => {
if (this.isPublicOrIsMember(indicator.visibility)) {
counter++;
}
});
return counter;
}
public get feedback() {
return "mailto:" + this.properties.feedbackmail + "?subject=%5BOpenAIRE%20Monitor%5D%20" + (this.stakeholder ? this.stakeholder.name : "") + "%20dashboard%20feedback"
}
public getNumberClassBySize(size: IndicatorSize) {
if (size === 'small') {
return 'uk-width-medium';
} else if (size === 'medium') {
return 'uk-width-1-4@l uk-width-1-2@m uk-width-1-1';
} else {
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';
} else if (size === 'medium') {
return 'uk-width-1-2@l uk-width-1-1';
} else {
return 'uk-width-1-1';
}
}
logIn() {
this.userManagementService.login();
public printReport() {
window.print();
}
}

View File

@ -12,7 +12,7 @@ import {Schema2jsonldModule} from "../openaireLibrary/sharedComponents/schema2js
import {SEOServiceModule} from "../openaireLibrary/sharedComponents/SEO/SEOService.module";
import {MonitorRoutingModule} from "./monitor-routing.module";
import {MonitorComponent} from "./monitor.component";
import {StatisticsService} from "../openaireLibrary/monitor-admin/utils/services/statistics.service";
import {StatisticsService} from "../utils/services/statistics.service";
import {SideBarModule} from "../openaireLibrary/dashboard/sharedComponents/sidebar/sideBar.module";
import {InputModule} from "../openaireLibrary/sharedComponents/input/input.module";
import {UserMiniModule} from "../openaireLibrary/login/userMiniModule.module";
@ -23,21 +23,13 @@ import {SearchFilterModule} from "../openaireLibrary/searchPages/searchUtils/sea
import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
import {IconsService} from '../openaireLibrary/utils/icons/icons.service';
import {IconsModule} from '../openaireLibrary/utils/icons/icons.module';
import {filters, incognito} from "../openaireLibrary/utils/icons/icons";
import {LogoUrlPipeModule} from "../openaireLibrary/utils/pipes/logoUrlPipe.module";
import {NumberRoundModule} from "../openaireLibrary/utils/pipes/number-round.module";
import {SliderTabsModule} from "../openaireLibrary/sharedComponents/tabs/slider-tabs.module";
import {SliderUtilsModule} from "../openaireLibrary/sharedComponents/slider-utils/slider-utils.module";
import {
SidebarMobileToggleModule
} from "../openaireLibrary/dashboard/sharedComponents/sidebar/sidebar-mobile-toggle/sidebar-mobile-toggle.module";
import {print} from "../openaireLibrary/utils/icons/icons";
@NgModule({
imports: [
CommonModule, FormsModule, RouterModule, ErrorMessagesModule,
HelperModule, Schema2jsonldModule, SEOServiceModule, MonitorRoutingModule, SideBarModule, InputModule,
UserMiniModule, ClickModule, BottomModule, RangeFilterModule, SearchFilterModule, PageContentModule, IconsModule,
LogoUrlPipeModule, NumberRoundModule, SliderTabsModule, SliderUtilsModule, SidebarMobileToggleModule
UserMiniModule, ClickModule, BottomModule, RangeFilterModule, SearchFilterModule, PageContentModule, IconsModule
],
declarations: [
MonitorComponent
@ -53,6 +45,6 @@ import {
})
export class MonitorModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([incognito, filters]);
this.iconsService.registerIcons([print]);
}
}

@ -1 +1 @@
Subproject commit 44e821b1f16f2edbdf58510d18fbe47a1083edd3
Subproject commit 3632510e387b3a83f8d8e0f27cd796912a19c741

View File

@ -2,20 +2,22 @@ import {Component} from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router";
import {StakeholderService} from "../../../openaireLibrary/monitor/services/stakeholder.service";
import {Subscriber} from "rxjs";
import {ConfigurationService} from "../../../openaireLibrary/utils/configuration/configuration.service";
@Component({
selector: 'monitor-dataprovider',
template: `
<div id="page_content">
<dataprovider *ngIf="initialized" [communityId]="communityId"></dataprovider>
<dataprovider *ngIf="initialized" [communityId]="communityId" [piwikSiteId]="piwikSiteId"></dataprovider>
</div>`,
})
export class MonitorDataProviderComponent {
initialized: boolean = false;
communityId;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -32,6 +34,11 @@ export class MonitorDataProviderComponent {
if (stakeholder) {
this.initialized = true;
this.communityId = stakeholder.alias;
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
}
}));
}

View File

@ -7,15 +7,18 @@ import {ConfigurationService} from "../../../openaireLibrary/utils/configuration
@Component({
selector: 'monitor-dataset',
template: `
<result-landing *ngIf="initialized" type="dataset" [communityId]="communityId"></result-landing>
<div id="page_content">
<result-landing *ngIf="initialized" type="dataset" [communityId]="communityId" [piwikSiteId]="piwikSiteId"></result-landing>
</div>
`,
})
export class MonitorDatasetComponent {
initialized: boolean = false;
communityId;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -32,6 +35,11 @@ export class MonitorDatasetComponent {
if (stakeholder) {
this.initialized = true;
this.communityId = stakeholder.alias;
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
}
}));
}

View File

@ -7,20 +7,19 @@ import {ConfigurationService} from "../../../openaireLibrary/utils/configuration
@Component({
selector: 'monitor-organization',
template: `
<organization *ngIf="initialized" [communityId]="communityId"></organization>
`,
<div id="page_content">
<organization *ngIf="initialized" [communityId]="communityId" [piwikSiteId]="piwikSiteId"></organization>
</div>`,
})
export class MonitorOrganizationComponent {
initialized: boolean = false;
communityId;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
@ -28,7 +27,6 @@ export class MonitorOrganizationComponent {
}
});
}
ngOnInit() {
this.subscriptions.push(this.route.params.subscribe(params => {
if (params['stakeholder']) {
@ -36,6 +34,11 @@ export class MonitorOrganizationComponent {
if (stakeholder) {
this.initialized = true;
this.communityId = stakeholder.alias;
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
}
}));
}

View File

@ -7,17 +7,19 @@ import {ConfigurationService} from "../../../openaireLibrary/utils/configuration
@Component({
selector: 'monitor-orp',
template: `
<result-landing *ngIf="initialized" type="orp" [communityId]="communityId"></result-landing>
<div id="page_content">
<result-landing *ngIf="initialized" type="orp" [communityId]="communityId" [piwikSiteId]="piwikSiteId"></result-landing>
</div>
`,
})
export class MonitorOrpComponent {
initialized: boolean = false;
communityId;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -34,6 +36,11 @@ export class MonitorOrpComponent {
if (stakeholder) {
this.initialized = true;
this.communityId = stakeholder.alias;
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
}
}));
}

View File

@ -7,16 +7,17 @@ import {ConfigurationService} from "../../../openaireLibrary/utils/configuration
@Component({
selector: 'monitor-project',
template: `
<project *ngIf="initialized" [communityId]="communityId"></project>
`,
<div id="page_content">
<project *ngIf="initialized" [communityId]="communityId" [piwikSiteId]="piwikSiteId"></project>
</div>`,
})
export class MonitorProjectComponent {
initialized: boolean = false;
communityId;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -33,6 +34,11 @@ export class MonitorProjectComponent {
if (stakeholder) {
this.initialized = true;
this.communityId = stakeholder.alias;
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
}
}));
}

View File

@ -7,16 +7,18 @@ import {ConfigurationService} from "../../../openaireLibrary/utils/configuration
@Component({
selector: 'monitor-publication',
template: `
<result-landing *ngIf="initialized" type="publication" [communityId]="communityId"></result-landing>
<div id="page_content">
<result-landing *ngIf="initialized" type="publication" [communityId]="communityId" [piwikSiteId]="piwikSiteId"></result-landing>
</div>
`,
})
export class MonitorPublicationComponent {
initialized: boolean = false;
communityId;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -33,6 +35,12 @@ export class MonitorPublicationComponent {
if (stakeholder) {
this.initialized = true;
this.communityId = stakeholder.alias;
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
console.debug(portal)
this.piwikSiteId = portal.piwik;
}
}));
}
}));
}

View File

@ -7,16 +7,17 @@ import {ConfigurationService} from "../../../openaireLibrary/utils/configuration
@Component({
selector: 'monitor-result',
template: `
<result-landing *ngIf="initialized" type="result" [communityId]="communityId"></result-landing>
`,
<div id="page_content">
<result-landing *ngIf="initialized" type="result" [communityId]="communityId" [piwikSiteId]="piwikSiteId"></result-landing>
</div>`,
})
export class MonitorResultComponent {
initialized: boolean = false;
communityId;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -33,6 +34,11 @@ export class MonitorResultComponent {
if (stakeholder) {
this.initialized = true;
this.communityId = stakeholder.alias;
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
}
}));
}

View File

@ -7,16 +7,18 @@ import {ConfigurationService} from "../../../openaireLibrary/utils/configuration
@Component({
selector: 'monitor-software',
template: `
<result-landing *ngIf="initialized" type="software"></result-landing>
<div id="page_content">
<result-landing *ngIf="initialized" type="software" [piwikSiteId]="piwikSiteId"></result-landing>
</div>
`,
})
export class MonitorSoftwareComponent {
initialized: boolean = false;
communityId;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -33,6 +35,11 @@ export class MonitorSoftwareComponent {
if (stakeholder) {
this.initialized = true;
this.communityId = stakeholder.alias;
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
}
}));
}

View File

@ -10,22 +10,13 @@ interface Links {
searchLinkToOrp;
searchLinkToOrganization;
searchLinkToResults,
searchLinkToPublications,
searchLinkToDatasets,
searchLinkToSoftware,
searchLinkToOrps,
searchLinkToProjects,
searchLinkToDataProviders,
searchLinkToOrganizations,
searchLinkToAdvancedResults,
searchLinkToAdvancedPublications,
searchLinkToAdvancedDatasets
searchLinkToAdvancedSoftware,
searchLinkToAdvancedOrps,
searchLinkToAdvancedProjects,
searchLinkToAdvancedDataProviders,
searchLinkToAdvancedOrganizations,
errorLink
}
export class LinksResolver {
@ -40,25 +31,16 @@ export class LinksResolver {
searchLinkToOrp: properties.searchLinkToOrp,
searchLinkToOrganization: properties.searchLinkToOrganization,
searchLinkToResults: properties.searchLinkToResults,
searchLinkToPublications: properties.searchLinkToPublications,
searchLinkToDatasets: properties.searchLinkToDatasets,
searchLinkToSoftware: properties.searchLinkToSoftware,
searchLinkToOrps: properties.searchLinkToOrps,
searchLinkToDataProviders: properties.searchLinkToDataProviders,
searchLinkToProjects: properties.searchLinkToProjects,
searchLinkToOrganizations: properties.searchLinkToOrganizations,
searchLinkToAdvancedResults: properties.searchLinkToAdvancedResults,
searchLinkToAdvancedPublications: properties.searchLinkToAdvancedPublications,
searchLinkToAdvancedDatasets: properties.searchLinkToAdvancedDatasets,
searchLinkToAdvancedSoftware: properties.searchLinkToAdvancedSoftware,
searchLinkToAdvancedOrps: properties.searchLinkToAdvancedOrps,
searchLinkToAdvancedProjects: properties.searchLinkToAdvancedProjects,
searchLinkToAdvancedDataProviders: properties.searchLinkToAdvancedDataProviders,
searchLinkToAdvancedOrganizations: properties.searchLinkToAdvancedOrganizations,
errorLink: properties.errorLink
};
public static setProperties(alias: string) {
public static setProperties( alias: string) {
Object.keys(this.default).forEach(field => {
properties[field] = "/" + alias + (<string>this.default[field]);
});

View File

@ -4,7 +4,7 @@ import {RouterModule} from "@angular/router";
@NgModule({
imports: [CommonModule, RouterModule.forChild([
// Search Pages
{ path: '', redirectTo: 'find/research-outcomes', pathMatch: 'full'},
{ path: '', redirectTo: 'find/research-outcomes'},
{ path: 'find/research-outcomes', loadChildren: () => import('./searchPages/simple/searchResearchResults.module').then(m => m.MonitorSearchResearchResultsModule)},
{ path: 'find/projects', loadChildren: () => import('./searchPages/simple/searchProjects.module').then(m => m.MonitorSearchProjectsModule)},
{ path: 'find/dataproviders', loadChildren: () => import('./searchPages/simple/searchDataProviders.module').then(m => m.MonitorSearchDataProvidersModule)},
@ -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), 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}},
{ 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)},
])]
})
export class SearchModule {}

View File

@ -1,32 +1,31 @@
import {Component, Input} from '@angular/core';
import {Component} from '@angular/core';
import {SearchCustomFilter} from "../../../openaireLibrary/searchPages/searchUtils/searchUtils.class";
import {ActivatedRoute, Router} from "@angular/router";
import {StakeholderService} from "../../../openaireLibrary/monitor/services/stakeholder.service";
import {Subscriber} from "rxjs";
import {SearchForm} from "../../../openaireLibrary/searchPages/searchUtils/newSearchPage.component";
import {ConfigurationService} from "../../../openaireLibrary/utils/configuration/configuration.service";
@Component({
selector: 'monitor-advanced-search-dataproviders',
template: `
<div id="page_content">
<search-dataproviders *ngIf="initialized" [simpleView]="false"
[customFilter]=customFilter [hasPrefix]="false" [searchForm]="searchForm"
[includeOnlyResultsAndFilter]="false" [showSwitchSearchLink]="showSwitchSearchLink">
[customFilter]=customFilter [hasPrefix]="false"
[includeOnlyResultsAndFilter]="false" [showSwitchSearchLink]="showSwitchSearchLink" [piwikSiteId]="piwikSiteId">
</search-dataproviders>
</div>
`
})
export class MonitorAdvancedSearchDataprovidersComponent {
@Input() searchForm: SearchForm = {class: 'search-form', dark: false};
customFilter: SearchCustomFilter = null;
initialized: boolean = false;
showSwitchSearchLink: boolean = false;
showSwitchSearchLink:boolean = false;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
@ -41,19 +40,24 @@ export class MonitorAdvancedSearchDataprovidersComponent {
this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
if (stakeholder) {
if (stakeholder.type === "organization") {
let value = stakeholder.index_id;
this.customFilter = new SearchCustomFilter("Organization", "relorganizationid", value, "");
this.showSwitchSearchLink = true;
let value = stakeholder.index_id;
this.customFilter = new SearchCustomFilter("Organization", "relorganizationid", value, "");
this.showSwitchSearchLink = true;
} else if (stakeholder.type === "funder") {
let value = stakeholder.index_id + "||" + stakeholder.index_name + "||" + stakeholder.index_shortName;
this.customFilter = new SearchCustomFilter("Funder", "relfunder", value, stakeholder.name);
let value = stakeholder.index_id+"||"+stakeholder.index_name+"||"+stakeholder.index_shortName;
this.customFilter = new SearchCustomFilter("Funder", "relfunder", value, stakeholder.name);
} else if (stakeholder.type === "ri") {
let value = stakeholder.index_id + "||" + stakeholder.index_name;
this.customFilter = new SearchCustomFilter("Community", "community", value, stakeholder.name);
let value = stakeholder.index_id+"||"+stakeholder.index_name;
this.customFilter = new SearchCustomFilter("Community", "community", value, stakeholder.name);
}
this.initialized = true;
}
}));
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
this.initialized = true;
}
}));
}
}));
}

View File

@ -1,25 +1,27 @@
import {Component, Input} from '@angular/core';
import {Component} from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router";
import {StakeholderService} from "../../../openaireLibrary/monitor/services/stakeholder.service";
import {SearchCustomFilter} from "../../../openaireLibrary/searchPages/searchUtils/searchUtils.class";
import {Subscriber} from "rxjs";
import {SearchForm} from "../../../openaireLibrary/searchPages/searchUtils/newSearchPage.component";
import {ConfigurationService} from "../../../openaireLibrary/utils/configuration/configuration.service";
@Component({
selector: 'monitor-advanced-search-organizations',
template: `
<search-organizations *ngIf="initialized" [simpleView]="false" [showSwitchSearchLink]="false" [customFilter]="customFilter" [searchForm]="searchForm">
<div id="page_content">
<search-organizations *ngIf="initialized" [simpleView]="false" [showSwitchSearchLink]="false" [customFilter]="customFilter"
[piwikSiteId]="piwikSiteId">
</search-organizations>
</div>
`
})
export class MonitorAdvancedSearchOrganizationsComponent {
@Input() searchForm: SearchForm = {class: 'search-form', dark: false};
initialized: boolean = false;
customFilter: SearchCustomFilter = null;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -48,6 +50,11 @@ export class MonitorAdvancedSearchOrganizationsComponent {
this.customFilter = new SearchCustomFilter("Community", "community", value, stakeholder.name);
this.customFilter.isHiddenFilter = false;
}
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
this.initialized = true;
}
}));

View File

@ -1,34 +1,35 @@
import {Component, Input} from '@angular/core';
import {Component} from '@angular/core';
import {SearchCustomFilter} from "../../../openaireLibrary/searchPages/searchUtils/searchUtils.class";
import {ActivatedRoute, Router} from "@angular/router";
import {StakeholderService} from "../../../openaireLibrary/monitor/services/stakeholder.service";
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {SearchForm} from "../../../openaireLibrary/searchPages/searchUtils/newSearchPage.component";
import {ConfigurationService} from "../../../openaireLibrary/utils/configuration/configuration.service";
@Component({
selector: 'monitor-advanced-search-projects',
template: `
<div id="page_content">
<search-projects *ngIf="initialized" [simpleView]="false"
[customFilter]=customFilter [hasPrefix]="false"
[includeOnlyResultsAndFilter]="false" [showSwitchSearchLink]="showSwitchSearchLink"
[openaireLink]="'https://'+(properties.environment != 'production'?'beta.':'')+'explore.openaire.eu/search/simple/projects'"
[searchForm]="searchForm"
[piwikSiteId]="piwikSiteId"
>
</search-projects>
</div>
`
})
export class MonitorAdvancedSearchProjectsComponent {
@Input() searchForm: SearchForm = {class: 'search-form', dark: false};
customFilter: SearchCustomFilter = null;
initialized: boolean = false;
showSwitchSearchLink:boolean = false;
properties;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -57,6 +58,11 @@ export class MonitorAdvancedSearchProjectsComponent {
let value = stakeholder.index_id+"||"+stakeholder.index_name;
this.customFilter = new SearchCustomFilter("Community", "community", value, stakeholder.name);
}
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
this.initialized = true;
}
}));

View File

@ -1,32 +1,33 @@
import {Component, Input} from '@angular/core';
import {Component} from '@angular/core';
import {SearchCustomFilter} from "../../../openaireLibrary/searchPages/searchUtils/searchUtils.class";
import {ActivatedRoute, Router} from "@angular/router";
import {StakeholderService} from "../../../openaireLibrary/monitor/services/stakeholder.service";
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {ConfigurationService} from "../../../openaireLibrary/utils/configuration/configuration.service";
import {SearchForm} from "../../../openaireLibrary/searchPages/searchUtils/newSearchPage.component";
@Component({
selector: 'monitor-advanced-search-results',
template: `
<div id="page_content">
<search-research-results *ngIf="initialized" resultType="result" [simpleView]="false"
[customFilter]=customFilter [hasPrefix]="false"
[includeOnlyResultsAndFilter]="false"
[showSwitchSearchLink]="true"
[openaireLink]="'https://'+(properties.environment != 'production'?'beta.':'')+'explore.openaire.eu/search/advanced/research-outcomes'"
[searchForm]="searchForm"
[piwikSiteId]="piwikSiteId"
></search-research-results>
</div>
`
})
export class MonitorAdvancedSearchResearchResultsComponent {
customFilter: SearchCustomFilter = null;
initialized: boolean = false;
@Input() searchForm: SearchForm = {class: 'search-form', dark: false};
properties;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -53,6 +54,11 @@ export class MonitorAdvancedSearchResearchResultsComponent {
let value = stakeholder.index_id+"||"+stakeholder.index_name;
this.customFilter = new SearchCustomFilter("Community", "community", value, stakeholder.name);
}
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
this.initialized = true;
}
}));

View File

@ -1,36 +1,31 @@
import {Component, Input} from '@angular/core';
import {Component} from '@angular/core';
import {SearchCustomFilter} from "../../../openaireLibrary/searchPages/searchUtils/searchUtils.class";
import {ActivatedRoute, Router} from "@angular/router";
import {StakeholderService} from "../../../openaireLibrary/monitor/services/stakeholder.service";
import {Subscriber} from "rxjs";
import {ConfigurationService} from "../../../openaireLibrary/utils/configuration/configuration.service";
import {SearchForm} from "../../../openaireLibrary/searchPages/searchUtils/newSearchPage.component";
import {EnvProperties} from "../../../openaireLibrary/utils/properties/env-properties";
import {properties} from "../../../../environments/environment";
@Component({
selector: 'monitor-search-dataproviders',
template: `
<search-dataproviders *ngIf="initialized"
[customFilter]=customFilter [hasPrefix]="false" [searchForm]="searchForm"
[includeOnlyResultsAndFilter]="false" [showSwitchSearchLink]="showSwitchSearchLink">
</search-dataproviders>
<div id="page_content">
<search-dataproviders *ngIf="initialized"
[customFilter]=customFilter [hasPrefix]="false"
[includeOnlyResultsAndFilter]="false" [showSwitchSearchLink]="showSwitchSearchLink" [piwikSiteId]="piwikSiteId">
</search-dataproviders>
</div>
`
})
export class MonitorSearchDataprovidersComponent {
@Input() searchForm: SearchForm = {class: 'search-form', dark: false};
customFilter: SearchCustomFilter = null;
initialized: boolean = false;
showSwitchSearchLink: boolean = false;
public properties: EnvProperties = properties;
showSwitchSearchLink:boolean = false;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
@ -38,7 +33,7 @@ export class MonitorSearchDataprovidersComponent {
}
});
}
ngOnInit() {
this.subscriptions.push(this.route.params.subscribe(params => {
if (params['stakeholder']) {
@ -52,6 +47,11 @@ export class MonitorSearchDataprovidersComponent {
} else if (stakeholder.type === "ri") {
this.navigateToError();
}
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
this.initialized = true;
}
}));
@ -60,6 +60,6 @@ export class MonitorSearchDataprovidersComponent {
}
navigateToError() {
this.router.navigate([this.properties.errorLink], {queryParams: {'page': this.router.url}});
this.router.navigate(['/error'], {queryParams: {'page': this.router.url}});
}
}

View File

@ -1,20 +1,21 @@
import {Component, Input} from '@angular/core';
import {Component} from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router";
import {StakeholderService} from "../../../openaireLibrary/monitor/services/stakeholder.service";
import {Subscriber} from "rxjs";
import {ConfigurationService} from "../../../openaireLibrary/utils/configuration/configuration.service";
import {SearchForm} from "../../../openaireLibrary/searchPages/searchUtils/newSearchPage.component";
@Component({
selector: 'monitor-search-organizations',
template: `
<search-organizations *ngIf="initialized" [searchForm]="searchForm">
<div id="page_content">
<search-organizations *ngIf="initialized" [piwikSiteId]="piwikSiteId">
</search-organizations>
</div>
`
})
export class MonitorSearchOrganizationsComponent {
@Input() searchForm: SearchForm = {class: 'search-form', dark: false};
initialized: boolean = false;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
@ -33,6 +34,11 @@ export class MonitorSearchOrganizationsComponent {
if (params['stakeholder']) {
this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
if (stakeholder) {
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
this.initialized = true;
}
}));

View File

@ -1,31 +1,33 @@
import {Component, Input} from '@angular/core';
import {Component} from '@angular/core';
import {SearchCustomFilter} from "../../../openaireLibrary/searchPages/searchUtils/searchUtils.class";
import {ActivatedRoute, Router} from "@angular/router";
import {StakeholderService} from "../../../openaireLibrary/monitor/services/stakeholder.service";
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {SearchForm} from "../../../openaireLibrary/searchPages/searchUtils/newSearchPage.component";
import {ConfigurationService} from "../../../openaireLibrary/utils/configuration/configuration.service";
@Component({
selector: 'monitor-search-projects',
template: `
<div id="page_content">
<search-projects *ngIf="initialized"
[customFilter]=customFilter [hasPrefix]="false"
[includeOnlyResultsAndFilter]="false"
[openaireLink]="'https://'+(properties.environment != 'production'?'beta.':'')+'explore.openaire.eu/search/simple/projects'"
[searchForm]="searchForm">
[openaireLink]="'https://'+(properties.environment != 'production'?'beta.':'')+'explore.openaire.eu/search/simple/projects'"
[piwikSiteId]="piwikSiteId">
</search-projects>
</div>
`
})
export class MonitorSearchProjectsComponent {
@Input() searchForm: SearchForm = {class: 'search-form', dark: false};
customFilter: SearchCustomFilter = null;
initialized: boolean = false;
properties;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -51,6 +53,11 @@ export class MonitorSearchProjectsComponent {
} else if (stakeholder.type === "ri") {
this.navigateToError();
}
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
this.initialized = true;
}
@ -60,6 +67,6 @@ export class MonitorSearchProjectsComponent {
}
navigateToError() {
this.router.navigate([this.properties.errorLink], {queryParams: {'page': this.router.url}});
this.router.navigate(['/error'], {queryParams: {'page': this.router.url}});
}
}

View File

@ -1,32 +1,33 @@
import {Component, Input} from '@angular/core';
import {Component} from '@angular/core';
import {SearchCustomFilter} from "../../../openaireLibrary/searchPages/searchUtils/searchUtils.class";
import {ActivatedRoute, Router} from "@angular/router";
import {StakeholderService} from "../../../openaireLibrary/monitor/services/stakeholder.service";
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {ConfigurationService} from "../../../openaireLibrary/utils/configuration/configuration.service";
import {SearchForm} from "../../../openaireLibrary/searchPages/searchUtils/newSearchPage.component";
@Component({
selector: 'monitor-search-results',
template: `
<div id="page_content">
<search-research-results *ngIf="initialized" resultType="result"
[customFilter]=customFilter [hasPrefix]="false"
[includeOnlyResultsAndFilter]="false"
[showSwitchSearchLink]="true"
[searchForm]="searchForm"
[openaireLink]="'https://'+(properties.environment != 'production'?'beta.':'')+'explore.openaire.eu/search/find/research-outcomes'"
[piwikSiteId]="piwikSiteId"
></search-research-results>
</div>
`,
})
export class MonitorSearchResearchResultsComponent {
@Input() searchForm: SearchForm = {class: 'search-form', dark: false};
customFilter: SearchCustomFilter = null;
initialized: boolean = false;
properties;
piwikSiteId;
constructor(private route: ActivatedRoute,
private router: Router,
private stakeholderService: StakeholderService) {
private stakeholderService: StakeholderService, private configurationService: ConfigurationService) {
}
subscriptions = [];
ngOnDestroy() {
@ -53,6 +54,11 @@ export class MonitorSearchResearchResultsComponent {
let value = stakeholder.index_id+"||"+stakeholder.index_name;
this.customFilter = new SearchCustomFilter("Community", "community", value, stakeholder.name);
}
this.subscriptions.push(this.configurationService.communityInformationState.subscribe(portal => {
if (portal) {
this.piwikSiteId = portal.piwik;
}
}));
this.initialized = true;
}
}));

View File

@ -0,0 +1,18 @@
.uk-card {
min-height: 270px;
}
div[id*="number-"] .uk-card-body {
padding-top: 60px;
}
div[id*="chart-"] .uk-card-body {
padding-top: 75px;
}
.number-preview {
border: 1px solid #D1D1D1;
border-radius: 4px;
min-width: 100px;
min-height: 70px;
}

View File

@ -0,0 +1,614 @@
<div *ngIf="stakeholder && canEdit">
<div *ngIf="numberSections">
<h6 class="uk-text-bold">Number Indicators</h6>
<ng-template ngFor [ngForOf]="displayNumbers" let-number let-i="index">
<div [id]="'number-' + number._id"
class="uk-grid-match uk-grid-small uk-grid uk-margin-top section"
uk-sortable="group: number" uk-grid>
<div class="tools disable-sortable uk-sortable-nodrag">
<div class="actions">
<a [class.uk-disabled]="editing" class="" (click)="createSection(i, 'number')"
title="Create a new section">
<icon name="add"></icon>
</a>
<!--<button class="md-btn md-btn-mini"><i class="material-icons rotate-90">drag_indicator</i></button>-->
<a [title]="(number.defaultId?'Default sections cannot be deleted':'Delete section')"
(click)="deleteSectionOpen(number, i, 'number', 'delete')">
<icon name="close"></icon>
</a>
<!-- <ng-container *ngIf="!stakeholder.defaultId">-->
<!-- <button [disabled]="editing || number.defaultId " class="md-btn md-btn-mini"-->
<!-- [title]="(number.defaultId?'Default sections cannot be deleted':'Delete all related sections')"-->
<!-- (click)="deleteSectionOpen(number, i, 'number', 'delete')"><i class="material-icons">highlight_off</i>-->
<!-- </button>-->
<!-- <button [disabled]="editing || number.defaultId " class="md-btn md-btn-mini"-->
<!-- [title]="(number.defaultId?'Default sections cannot be deleted':'Delete section and disconnect related')"-->
<!-- (click)="deleteSectionOpen(number, i, 'number', 'disconnect')"><i class="material-icons">link_off</i>-->
<!-- </button>-->
<!-- </ng-container>-->
</div>
</div>
<div *ngIf="numberSections.at(i)"
class="uk-width-1-1 uk-margin-medium-bottom disable-sortable uk-sortable-nodrag">
<div dashboard-input [formInput]="numberSections.at(i).get('title')"
[extraLeft]="false" class="uk-width-1-3@m uk-width-1-1" placeholder="Title"
inputClass="input-borderless uk-h5 uk-margin-remove">
<div [class.uk-invisible]="numberSections.at(i).get('title').pristine">
<button class="uk-button uk-button-secondary" [disabled]="editing"
(click)="saveSection(numberSections.at(i).value, i, 'number')">
Save
</button>
</div>
</div>
</div>
<ng-template ngFor [ngForOf]="number.indicators" let-indicator let-j="index">
<div *ngIf="indicator" [id]="indicator._id"
[ngClass]="getNumberClassBySize(indicator.width)"
[class.disable-sortable]="!canReorder"
[class.uk-sortable-nodrag]="!canReorder">
<div class="uk-card uk-card-default uk-flex uk-flex-column uk-flex-center uk-position-relative" [class.uk-card-hover]="canReorder">
<div class="uk-card-body">
<ng-container
*ngTemplateOutlet="visibilityOptions; context:{indicator: indicator, sectionId: number._id}"></ng-container>
<div
[attr.uk-tooltip]="exportLoading ? 'title:Edit is disabled, while exporting indicators; cls:uk-active' : 'cls: uk-invisible'"
class="uk-position-top-right uk-margin-small-right uk-margin-small-top clickable">
<i [class]="exportLoading ? 'uk-disabled ' : ' '" uk-icon="more-vertical"
(click)="$event.stopPropagation();$event.preventDefault()"></i>
<div #element uk-dropdown="mode: click; pos: bottom-right; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li *ngIf="!editing"><a
(click)="editNumberIndicatorOpen(number, indicator._id)">Edit</a></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<li *ngIf="indicator.visibility != v.value"><a (click)="changeIndicatorStatus(number._id,
indicator, v.value); hide(element)">
{{'Make ' + v.label.toLowerCase()}}</a>
</li>
</ng-template>
<hr *ngIf="!indicator.defaultId" class="uk-nav-divider">
<li *ngIf="!indicator.defaultId && !editing"><a
(click)="deleteIndicatorOpen(number, indicator._id, 'number', 'delete');hide(element)">Delete</a>
<!-- <ng-container *ngIf="!stakeholder.defaultId">-->
<!-- <a (click)="deleteIndicatorOpen(number, indicator._id, 'number', 'delete');hide(element)">Delete from all profiles</a>-->
<!-- <a (click)="deleteIndicatorOpen(number, indicator._id, 'number', 'disconnect');hide(element)">Delete and disconnect from all profiles</a>-->
<!-- </ng-container>-->
</li>
</ul>
</div>
</div>
<div>
<div class="uk-text-center uk-text-bold">
{{indicator.name ? indicator.name : 'No title available'}}
</div>
<h3 class="uk-margin-medium-top uk-text-center uk-text-bold">
<span *ngIf="numberResults.get(i + '-' + j)">{{numberResults.get(i + '-' + j) | number}}</span>
<span *ngIf="!numberResults.get(i + '-' + j)">--</span>
</h3>
<!--<ng-container *ngTemplateOutlet="description; context: {indicator:indicator}"></ng-container>-->
</div>
<div *ngIf="indicator.description || indicator.additionalDescription"
class="uk-overlay uk-position-bottom">
<div class="uk-padding multi-line-ellipsis lines-3">
<p class="uk-margin-remove">
<span *ngIf="indicator.description">
{{indicator.description}}
</span>
<br>
<span *ngIf="indicator.additionalDescription">
{{indicator.additionalDescription}}
</span>
</p>
</div>
</div>
</div>
</div>
</div>
</ng-template>
<div class="disable-sortable uk-sortable-nodrag uk-width-1-1">
<div class="uk-grid uk-grid-small" uk-grid>
<div [ngClass]="getNumberClassBySize('small')">
<div class="uk-card uk-card-default uk-card-body clickable" (click)="editNumberIndicatorOpen(number)">
<h6 class="uk-text-bold uk-text-center">
Create a new number Indicator
</h6>
<div class="uk-flex uk-flex-center uk-text-secondary uk-margin-large-top">
<icon name="add" ratio="4"></icon>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-template>
<ng-container *ngTemplateOutlet="new_section; context:{type: 'number'}"></ng-container>
</div>
<div *ngIf="chartSections" class="uk-margin-large-top">
<h6 class="uk-text-bold">Chart Indicators</h6>
<ng-template ngFor [ngForOf]="displayCharts" let-chart let-i="index">
<div [id]="'chart-' + chart._id"
class="uk-grid-match section uk-grid-small uk-grid uk-margin-top"
uk-sortable="group: chart" uk-grid>
<div class="tools disable-sortable uk-sortable-nodrag">
<div class="actions">
<a [class.uk-disabled]="editing" class="" (click)="createSection(i)"
title="Create a new section">
<icon name="add"></icon>
</a>
<!--<button class="md-btn md-btn-mini"><i class="material-icons rotate-90">drag_indicator</i></button>-->
<a [title]="(chart.defaultId?'Default sections cannot be deleted':'Delete section')"
(click)="deleteSectionOpen(chart, i, 'chart', 'delete')">
<icon name="close"></icon>
</a>
<!-- <ng-container *ngIf="!stakeholder.defaultId">-->
<!-- <button [disabled]="editing || chart.defaultId " class="md-btn md-btn-mini"-->
<!-- [title]="(chart.defaultId?'Default sections cannot be deleted':'Delete all related sections')"-->
<!-- (click)="deleteSectionOpen(chart, i, 'chart', 'delete')"><i class="material-icons">highlight_off</i>-->
<!-- </button>-->
<!-- <button [disabled]="editing || chart.defaultId " class="md-btn md-btn-mini"-->
<!-- [title]="(chart.defaultId?'Default sections cannot be deleted':'Delete section and disconnect related')"-->
<!-- (click)="deleteSectionOpen(chart, i, 'chart', 'disconnect')"><i class="material-icons">link_off</i>-->
<!-- </button>-->
<!-- </ng-container>-->
</div>
</div>
<div *ngIf="chartSections.at(i)"
class="uk-width-1-1 uk-margin-medium-bottom disable-sortable uk-sortable-nodrag">
<div dashboard-input [formInput]="chartSections.at(i).get('title')"
[extraLeft]="false" class="uk-width-1-3@m uk-width-1-1" placeholder="Title"
inputClass="input-borderless uk-h5 uk-margin-remove">
<div [class.uk-invisible]="chartSections.at(i).get('title').pristine">
<button class="uk-button uk-button-secondary" [disabled]="editing"
(click)="saveSection(chartSections.at(i).value, i)">
Save
</button>
</div>
</div>
</div>
<ng-template ngFor [ngForOf]="chart.indicators" let-indicator let-j="index">
<div *ngIf="indicator" [id]="indicator._id"
[ngClass]="getChartClassBySize(indicator.width)"
[class.disable-sortable]="!canReorder"
[class.uk-sortable-nodrag]="!canReorder">
<div class="uk-card uk-card-default uk-card-body uk-position-relative" [class.uk-card-hover]="canReorder">
<ng-container
*ngTemplateOutlet="visibilityOptions; context:{indicator: indicator, sectionId: chart._id}"></ng-container>
<div
[attr.uk-tooltip]="exportLoading ? 'title:Edit is disabled, while exporting indicators; cls:uk-active' : 'cls: uk-invisible'"
class="uk-position-top-right uk-margin-small-right uk-margin-small-top clickable">
<i [class]="exportLoading ? 'uk-disabled ' : ' '" uk-icon="more-vertical"
(click)="$event.stopPropagation();$event.preventDefault()"></i>
<div #element uk-dropdown="mode: click; pos: bottom-right; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li *ngIf="!editing"><a
(click)="editChartIndicatorOpen(chart, indicator._id);hide(element)">Edit</a>
</li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<li *ngIf="indicator.visibility != v.value"><a (click)="changeIndicatorStatus(chart._id,
indicator, v.value); hide(element)">
{{'Make ' + v.label.toLowerCase()}}</a>
</li>
</ng-template>
<hr *ngIf="!indicator.defaultId " class="uk-nav-divider">
<li *ngIf="!editing && !indicator.defaultId "><a
(click)="deleteIndicatorOpen(chart, indicator._id, 'chart', 'delete');hide(element)">
Delete</a>
<!-- <a (click)="deleteIndicatorOpen(chart, indicator._id, 'chart', 'delete');hide(element)">Delete from all profiles</a>-->
<!-- <a (click)="deleteIndicatorOpen(chart, indicator._id, 'chart', 'disconnect');hide(element)">Delete and disconnect from all profiles</a>-->
</li>
</ul>
</div>
</div>
<div>
<div *ngIf="indicator.name" class="uk-text-center uk-text-bold uk-margin-small-bottom">
{{indicator.name}}
</div>
<iframe *ngIf="!properties.disableFrameLoad && indicator.indicatorPaths[0] &&
indicator.indicatorPaths[0].source !==
'image' &&
safeUrls.get(indicatorUtils.getFullUrl(stakeholder, indicator.indicatorPaths[0]))"
[src]="safeUrls.get(indicatorUtils.getFullUrl(stakeholder, indicator.indicatorPaths[0]))"
[class]="' uk-width-1-1 uk-height-' +
(indicator.height?indicator.height.toLowerCase():'medium')"></iframe>
<div *ngIf="properties.disableFrameLoad &&
indicator.indicatorPaths[0].source !==
'image'" class="uk-alert uk-alert-danger uk-text-center">I frames
preview is disabled
</div>
<div *ngIf="indicator.indicatorPaths[0] && indicator.indicatorPaths[0].source === 'image'">
<img [class]="' uk-width-1-1 uk-height-' +
(indicator.height?indicator.height.toLowerCase():'medium')"
[src]="indicator.indicatorPaths[0].url">
</div>
<!--<ng-container *ngTemplateOutlet="description; context: {indicator:indicator}"></ng-container>-->
</div>
<div *ngIf="indicator.description || indicator.additionalDescription"
class="uk-overlay uk-position-bottom">
<div class="uk-padding multi-line-ellipsis lines-3">
<p class="uk-margin-remove">
<span *ngIf="indicator.description">
{{indicator.description}}
</span>
<br>
<span *ngIf="indicator.additionalDescription">
{{indicator.additionalDescription}}
</span>
</p>
</div>
</div>
</div>
</div>
</ng-template>
<div class="disable-sortable uk-sortable-nodrag uk-width-1-1">
<div class="uk-grid uk-grid-small" uk-grid>
<div [ngClass]="getChartClassBySize('small')">
<div class=" uk-card uk-card-default uk-card-body clickable" (click)="editChartIndicatorOpen(chart)">
<h5 class="uk-text-bold">
Create a custom indicator
</h5>
<div class="uk-text-muted uk-text-small">
Use our advance tool to create a custom Indicator that suit the needs of your funding
KPI's.
</div>
<div class="uk-flex uk-flex-center uk-text-secondary uk-margin-medium-top">
<icon name="add" ratio="5"></icon>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-template>
<ng-container *ngTemplateOutlet="new_section; context:{type: 'chart'}"></ng-container>
</div>
</div>
<modal-alert #editNumberModal
[large]="true"
(alertOutput)="saveIndicator()"
[okDisabled]="numberIndicatorFb && (numberIndicatorFb.invalid || numberIndicatorFb.pristine)">
<div class="uk-padding-small">
<div *ngIf="numberIndicatorFb" class="uk-grid" [formGroup]="numberIndicatorFb" uk-grid>
<div dashboard-input class="uk-width-1-1" [formInput]="numberIndicatorFb.get('name')" placeholder="Write a title"
label="Title"></div>
<div dashboard-input class="uk-width-1-1" *ngIf="stakeholder.defaultId !=-1 && ( (indicator.description &&
indicator.description.length > 0) || !stakeholder.defaultId)"
[formInput]="numberIndicatorFb.get('description')"
placeholder="Write a description"
label="Profile description" type="textarea">
</div>
<div dashboard-input class="uk-width-1-1" *ngIf="stakeholder.defaultId"
[formInput]="numberIndicatorFb.get('additionalDescription')"
placeholder="Write a description"
label="Description" type="textarea">
</div>
<div dashboard-input class="uk-width-1-2@m" [formInput]="numberIndicatorFb.get('visibility')"
placeholder="Select a status"
label="Visibility" [options]="stakeholderUtils.visibility" type="select">
</div>
<div dashboard-input class="uk-width-1-2@m" [formInput]="numberIndicatorFb.get('width')"
type="select" [options]="indicatorUtils.indicatorSizes"
placeholder="Select a size" label="Number Size">
</div>
<div *ngIf="numberIndicatorPaths" formArrayName="indicatorPaths">
<div *ngFor="let indicatorPath of numberIndicatorPaths.controls; let i=index"
[formGroup]="indicatorPath">
<div class="uk-grid" uk-grid>
<div class="uk-width-1-1">
<div class="uk-grid" uk-grid>
<div class="uk-width-1-1">
<div dashboard-input [formInput]="indicatorPath.get('url')" label="Number URL"
placeholder="Write a URL">
<div *ngIf="urlParameterizedMessage" warning>{{urlParameterizedMessage}}</div>
</div>
</div>
<div *ngIf="showCheckForSchemaEnhancements" class=" uk-width-1-1 ">
<div class="uk-alert uk-alert-warning">
There are schema enhancements that can be applied in this query. <a
(click)="indicatorPath.get('url').setValue(indicatorUtils.applySchemaEnhancements(indicatorPath.get('url').value)); indicatorPath.get('url').markAsDirty()">Apply
now</a>
</div>
</div>
<div class="uk-width-1-1">
<div dashboard-input [formInput]="indicatorPath.get('source')" label="Source"
type="select" placeholder="Select a source"
[options]="isAdministrator?indicatorUtils.allSourceTypes:indicatorUtils.sourceTypes">
</div>
</div>
</div>
</div>
<div formArrayName="jsonPath" class="uk-width-1-1">
<h6 class="uk-text-bold uk-flex uk-flex-middle uk-margin-remove-bottom">
<span>JSON Path</span>
</h6>
<div
*ngIf="numberIndicatorPaths.at(i).get('result').invalid && numberIndicatorPaths.at(i).get('result').errors.required">
<div class="uk-text-danger uk-text-small">
This JSON path is not valid or the result has not been calculated yet.
Please press calculate on box below to see the result.
</div>
</div>
<div class="uk-grid uk-child-width-1-3@m uk-child-width-1-1 uk-margin-top" uk-grid>
<div *ngFor="let jsonPath of getJsonPath(i).controls; let j=index" class="uk-flex uk-flex-middle">
<div dashboard-input class="uk-width-1-1"
[extraLeft]="false"
[formInput]="jsonPath"
placeholder="Write a field"
[label]="'Level ' + +(j + 1)">
<div class="uk-flex uk-flex-middle">
<span *ngIf="getJsonPath(i).length !== 1"
[class.uk-hidden]="numberIndicatorFb.get('defaultId').value"
class="uk-margin-small-left uk-text-danger clickable"
[class.uk-disabled]="getJsonPath(i).disabled"
(click)="removeJsonPath(i, j)">
<icon name="close"></icon>
</span>
<span class="uk-text-center uk-margin-left">
<icon *ngIf="indicator.defaultId === null || j < (getJsonPath(i).controls.length - 1)"
name="arrow_right"></icon>
</span>
</div>
</div>
</div>
<div *ngIf="indicator.defaultId === null" class="uk-flex uk-flex-middle">
<button class="uk-icon-button uk-button-secondary uk-margin-medium-top"
(click)="addJsonPath(i)">
<icon name="add"></icon>
</button>
</div>
</div>
</div>
<div class="uk-width-1-1 uk-flex uk-flex-center">
<div class="uk-flex uk-position-relative">
<span class="uk-padding number number-preview uk-text-center">
<span
*ngIf="numberIndicatorPaths.at(i).get('result').valid && numberIndicatorPaths.at(i).get('result').value !== 0">
{{numberIndicatorPaths.at(i).get('result').value | number}}
</span>
<span
*ngIf="numberIndicatorPaths.at(i).get('result').valid && numberIndicatorPaths.at(i).get('result').value === 0">
--
</span>
</span>
<div *ngIf="numberIndicatorPaths.at(i).get('result').invalid"
class="uk-width-1-1 uk-height-1-1 refresh-indicator">
<div class="uk-position-relative uk-height-1-1">
<div class="uk-position-center uk-text-center clickable uk-text-small"
[class.uk-disabled]="numberIndicatorPaths.at(i).get('url').invalid"
(click)="validateJsonPath(i, true)">
<div>
<icon name="refresh"></icon>
</div>
<span *ngIf="numberIndicatorPaths.at(i).get('result').errors.required">Calculate</span>
<span *ngIf="numberIndicatorPaths.at(i).get('result').errors.validating">Calculating...</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div #editNumberNotify notify-form class="uk-width-1-1 uk-margin-medium-top"></div>
</div>
</modal-alert>
<modal-alert #editChartModal
[large]="true"
(alertOutput)="saveIndicator()"
[okDisabled]="chartIndicatorFb && (chartIndicatorFb.invalid || chartIndicatorFb.pristine)">
<div class="uk-padding-small">
<div *ngIf="chartIndicatorFb" [formGroup]="chartIndicatorFb" class="uk-grid" uk-grid>
<div dashboard-input class="uk-width-1-1" [formInput]="chartIndicatorFb.get('name')" placeholder="Write a title"
label="Title"></div>
<div dashboard-input class="uk-width-1-1" *ngIf="stakeholder.defaultId !=-1 &&
((indicator.description && indicator.description.length > 0) || !stakeholder.defaultId)"
[formInput]="chartIndicatorFb.get('description')" placeholder="Write a description"
label="Default Description" type="textarea">
</div>
<div dashboard-input *ngIf="stakeholder.defaultId" class="uk-width-1-1"
[formInput]="chartIndicatorFb.get('additionalDescription')" placeholder="Write a default description"
label="Description" type="textarea">
</div>
<div dashboard-input class="uk-width-1-2@m" [formInput]="chartIndicatorFb.get('visibility')"
placeholder="Select a status"
label="Status" [options]="stakeholderUtils.visibility" type="select">
</div>
<div dashboard-input class="uk-width-1-2@m" [formInput]="chartIndicatorFb.get('width')"
type="select" [options]="indicatorUtils.indicatorSizes" placeholder="Select a size"
label="Chart width">
</div>
<div dashboard-input class="uk-width-1-2@m" [formInput]="chartIndicatorFb.get('height')"
type="select" [options]="indicatorUtils.indicatorSizes" placeholder="Select a size"
label="Chart height">
</div>
<div *ngIf="chartIndicatorPaths" formArrayName="indicatorPaths" class="uk-width-1-1">
<div *ngFor="let indicatorPath of chartIndicatorPaths.controls; let i=index;"
[formGroup]="indicatorPath" class="uk-grid" uk-grid>
<div dashboard-input class="uk-width-1-1"
[title]="indicatorPath.get('url').disabled?'Default chart URLs cannot change':''"
[formInput]="indicatorPath.get('url')" placeholder="Write a URL" label="Chart URL">
<div *ngIf="urlParameterizedMessage" warning>{{urlParameterizedMessage}}</div>
</div>
<div *ngIf="showCheckForSchemaEnhancements" class=" uk-width-1-1 ">
<div class="uk-alert uk-alert-warning">
There are schema enchancements that can be applied in this query. <a
(click)="indicatorPath.get('url').setValue(indicatorUtils.applySchemaEnhancements(indicatorPath.get('url').value)); indicatorPath.get('url').markAsDirty()">Apply
now</a>
</div>
</div>
<div class="uk-width-1-1" formArrayName="parameters">
<div class="uk-grid" uk-grid>
<div *ngIf="getParameter(i, 'title')" class="uk-width-1-1">
<div dashboard-input
[formInput]="getParameter(i, 'title').get('value')"
placeholder="Write a title"
label="Chart Title"></div>
</div>
<div *ngIf="getParameter(i, 'subtitle')" class="uk-width-1-1">
<div dashboard-input placeholder="Write a subtitle"
[formInput]="getParameter(i, 'subtitle').get('value')"
label="Chart Subtitle"></div>
</div>
<div *ngIf="!getParameter(i, 'type')" class="uk-width-1-3@s">
<div dashboard-input [formInput]="indicatorPath.get('type')"
type="select" placeholder="Select a type"
[options]="(indicatorPath.get('type').value == 'table' && getParameter(i, 'data_title_0'))?indicatorUtils.getChartTypes(indicatorPath.get('type').value):indicatorUtils.allChartTypes"
label="Chart Type"></div>
</div>
<div *ngIf="getParameter(i, 'type')" class="uk-width-1-3@s">
<div dashboard-input [formInput]="getParameter(i, 'type').get('value')"
placeholder="Select a type"
type="select" [options]="indicatorUtils.getChartTypes(getParameter(i, 'type').get('value').value)"
label="Chart Type"></div>
</div>
<div *ngIf="getParameter(i, 'xAxisTitle')" class="uk-width-1-3@s">
<div dashboard-input [formInput]="getParameter(i, 'xAxisTitle').get('value')"
placeholder="Write a title for X-Axis"
label="X-Axis Title"></div>
</div>
<div *ngIf="getParameter(i, 'yAxisTitle')" class="uk-width-1-3@s">
<div dashboard-input [formInput]="getParameter(i, 'yAxisTitle').get('value')"
placeholder="Write a title"
label="Y-Axis Title"></div>
</div>
<div *ngIf="getParameter(i, 'data_title_0')" class="uk-width-1-3@s">
<div dashboard-input [formInput]="getParameter(i, 'data_title_0').get('value')"
placeholder="Write a title"
label="Data title"></div>
</div>
<div *ngIf="getParameter(i, 'data_title_1')" class="uk-width-1-3@s">
<div dashboard-input [formInput]="getParameter(i, 'data_title_1').get('value')"
placeholder="Write a title"
label="Data title"></div>
</div>
<div *ngIf="getParameter(i, 'start_year')" class="uk-width-1-3@s">
<div dashboard-input [formInput]="getParameter(i, 'start_year').get('value')"
placeholder="Write a year"
label="Year (From)"></div>
</div>
<div *ngIf="getParameter(i, 'end_year')" class="uk-width-1-3@s">
<div dashboard-input [formInput]="getParameter(i, 'end_year').get('value')"
placeholder="Write a year"
label="Year (To)"></div>
</div>
</div>
</div>
<div *ngIf="indicator && indicator.indicatorPaths[i] && indicator.indicatorPaths[i].safeResourceUrl"
class="uk-margin-medium-top uk-position-relative uk-width-1-1 uk-flex uk-flex-center">
<div *ngIf="(hasDifference(i)) && !indicatorPath.invalid"
class="uk-width-1-1 uk-height-large refresh-indicator">
<div class="uk-position-relative uk-height-1-1">
<div class="uk-position-center uk-text-center clickable"
(click)="refreshIndicator()">
<div>
<icon name="refresh"></icon>
</div>
<span>Click to refresh the graph view</span>
</div>
</div>
</div>
<iframe *ngIf="indicator.indicatorPaths[i].source !== 'image'"
[src]="indicator.indicatorPaths[i].safeResourceUrl"
class="uk-width-1-1 uk-height-large"></iframe>
<!-- <div *ngIf="properties.disableFrameLoad && indicator.indicatorPaths[i].source !== 'image'" class="uk-alert uk-alert-danger uk-text-center">I frames-->
<!-- preview is disabled</div>-->
<div *ngIf="indicator.indicatorPaths[i].source === 'image'">
<img class="uk-width-1-1 uk-height-large" [src]="indicator.indicatorPaths[i].url">
</div>
</div>
</div>
</div>
</div>
<div #editChartNotify notify-form class="uk-width-1-1 uk-margin-medium-top"></div>
</div>
</modal-alert>
<modal-alert #deleteModal (alertOutput)="deleteIndicator()">
You are about to delete <span class="uk-text-bold" *ngIf="indicator && index !== -1">
"{{indicator.name ? indicator.name : indicator.indicatorPaths[0].parameters.title}}"</span> indicator permanently.
<div *ngIf="indicatorChildrenActionOnDelete == 'delete'" class="uk-text-bold">
Indicators of all profiles based on this default indicator, will be deleted as well.
</div>
<!-- <span *ngIf="indicatorChildrenActionOnDelete == 'disconnect'" class="uk-text-bold">-->
<!-- Indicators of all profiles based on this default indicator, will not be marked as copied from default anymore.-->
<!-- </span>-->
Are you sure you want to proceed?
<div #deleteNotify notify-form class="uk-width-1-1 uk-margin-medium-top"></div>
</modal-alert>
<!--<modal-alert #deleteAllModal (alertOutput)="deleteIndicator('delete')">
You are about to delete <span class="uk-text-bold" *ngIf="indicator && index !== -1">
"{{indicator.name ? indicator.name : indicator.indicatorPaths[0].parameters.title}}"</span> indicator permanently.
<span class="uk-text-bold">Indicators of all profiles based on this default indicator, will be deleted as well.</span>
Are you sure you want to proceed?
</modal-alert>
<modal-alert #deleteAndDisconnectModal (alertOutput)="deleteIndicator('disconnect')">
You are about to delete <span class="uk-text-bold" *ngIf="indicator && index !== -1">
"{{indicator.name ? indicator.name : indicator.indicatorPaths[0].parameters.title}}"</span> indicator permanently.
<span class="uk-text-bold">Indicators of all profiles based on this default indicator, will not be marked as copied from default anymore.</span>
Are you sure you want to proceed?
</modal-alert>-->
<modal-alert #deleteSectionModal (alertOutput)="deleteSection()">
You are about to delete this section and its indicators permanently.
<div *ngIf="sectionChildrenActionOnDelete == 'delete' && !stakeholder.defaultId" class="uk-text-bold">
Sections of all profiles based on this default section and their contents, will be deleted as well.
</div>
<!-- <span *ngIf="sectionChildrenActionOnDelete == 'disconnect'" class="uk-text-bold">-->
<!-- Sections of all profiles based on this default section and their contents, will not be marked as copied from default anymore.-->
<!-- </span>-->
Are you sure you want to proceed?
</modal-alert>
<!--<modal-alert #deleteNumberSectionModal (alertOutput)="deleteSection('number')">
You are about to delete this section and its indicators permanently.
Are you sure you want to proceed?
</modal-alert>
<modal-alert #deleteChartSectionModal (alertOutput)="deleteSection()">
You are about to delete this section and its indicators permanently.
Are you sure you want to proceed?
</modal-alert>-->
<ng-template #visibilityOptions let-indicator="indicator" let-sectionId="sectionId">
<span
[attr.uk-tooltip]="exportLoading ? 'title:Edit is disabled, while exporting indicators; cls:uk-active' : 'cls: uk-invisible'"
class="uk-position-top-left uk-margin-small-left uk-margin-small-top visibility"
[class]="exportLoading ? '' : ' clickable '">
<span [class]="exportLoading ? 'uk-disabled ' : ' '" class="clickable color">
<icon [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)"></icon>
</span>
<div #element uk-dropdown="mode: click; pos: bottom-left; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li *ngFor="let v of stakeholderUtils.visibility" class="uk-position-relative">
<a *ngIf="indicator.visibility != v.value"
(click)="$event.stopPropagation();changeIndicatorStatus(sectionId, indicator,v.value);hide(element);$event.preventDefault()">
<icon [name]="stakeholderUtils.visibilityIcon.get(v.value)" ratio="0.8"></icon>
<span> {{v.label}}</span>
</a>
<a *ngIf="indicator.visibility == v.value">
<icon [name]="stakeholderUtils.visibilityIcon.get(v.value)" [ratio]="0.8"></icon>
<span> {{v.label}}</span>
<span class="uk-position-center-right">
<icon customClass="uk-text-secondary" [ratio]="0.5" name="bullet"></icon>
</span>
</a>
</li>
</ul>
</div>
</span>
</ng-template>
<ng-template #new_section let-type="type">
<div class="new-section uk-margin-large-top">
<div class="tools uk-flex uk-flex-middle clickable" (click)="createSection(-1, type)">
<button class="uk-margin-small-right uk-icon-button uk-button-secondary">
<icon name="add" [ratio]="1.5"></icon>
</button>
<span>Create a new section</span>
</div>
</div>
</ng-template>
<ng-template #description let-indicator="indicator">
<span class="descriptionIcon"
*ngIf="(indicator.description && indicator.description.length > 0)
|| (indicator.additionalDescription && indicator.additionalDescription.length > 0)"
uk-icon="info"
[attr.uk-tooltip]="'title:<div class=\'uk-padding-small\'>'+
(indicator.description&& indicator.description.length > 0?indicator.description:'') +'<br>'+
(indicator.additionalDescription && indicator.additionalDescription.length?indicator.additionalDescription:'')
+'</div>'">
</span>
</ng-template>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import {PreviousRouteRecorder} from '../openaireLibrary/utils/piwik/previousRouteRecorder.guard';
import {TopicComponent} from "./topic.component";
import {CanExitGuard} from "../openaireLibrary/utils/can-exit.guard";
@NgModule({
imports: [
RouterModule.forChild([
{
path: '',
component: TopicComponent,
canDeactivate: [PreviousRouteRecorder, CanExitGuard]
}
])
]
})
export class TopicRoutingModule {
}

View File

@ -0,0 +1,286 @@
<aside id="sidebar_main">
<div id="sidebar_content">
<div class="menu_section uk-margin-top">
<div class="uk-text-center">
<a [routerLink]="'/admin/' + stakeholder.alias"
class="uk-link-heading uk-text-uppercase uk-flex uk-flex-middle uk-flex-center">
<icon name="close" ratio="2"></icon>
<span *ngIf="open" class="uk-margin-left">Indicators</span>
</a>
</div>
<div class="menu_section uk-margin-xlarge-top">
<ul class="uk-list">
<ng-template ngFor [ngForOf]="stakeholder.topics" let-topic let-i="index">
<li class="uk-visible-toggle"
[class.uk-active]="topicIndex == i">
<a [routerLink]="'/admin/'+stakeholder.alias + '/indicators/' + topic.alias"
class="uk-flex uk-flex-middle" [title]="topic.name">
<span *ngIf="topic.icon"></span>
<div class="uk-width-expand uk-position-relative uk-flex uk-flex-middle"
[class.uk-flex-center]="open">
<span class="uk-flex-none">
<ng-container *ngTemplateOutlet="visibilityOptions; context:
{i:i, type: 'topic', visibility: stakeholder.topics[i].visibility}">
</ng-container>
</span>
<span [class.uk-text-center]="open"
[class.uk-text-truncate]="!open" [class.uk-width-3-5]="!open">{{topic.name}}</span>
<span class="uk-invisible-hover color"
(click)="$event.stopPropagation();$event.preventDefault()">
<span class="uk-icon more" uk-icon="more-vertical"></span>
<div #element uk-dropdown="mode: click; pos: bottom-right; offset: 5; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav uk-list">
<li><a (click)="editTopicOpen(i); hide(element)">Edit</a></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<li *ngIf="topic.visibility != v.value"><a (click)="changeTopicStatus(i, v.value);
hide(element)">
{{'Make ' + v.label.toLowerCase()}}</a>
</li>
</ng-template>
<hr *ngIf="!topic.defaultId" class="uk-nav-divider">
<li *ngIf="!topic.defaultId"><a (click)="deleteTopicOpen(i, 'delete'); hide(element)">Delete</a>
<!-- <ng-container *ngIf="!stakeholder.defaultId">-->
<!-- <a (click)="deleteTopicOpen(i, 'delete'); hide(element)">Delete from all profiles</a>-->
<!-- <a (click)="deleteTopicOpen(i, 'disconnect'); hide(element)">Delete and disconnect from all profiles</a>-->
<!-- </ng-container>-->
</li>
</ul>
</div>
</span>
</div>
</a>
</li>
</ng-template>
<li class="uk-margin-top" [class.uk-visible-toggle]="open">
<span (click)="editTopicOpen(-1); $event.preventDefault()"
class="clickable uk-flex uk-flex-middle uk-flex-center">
<span class="uk-icon-button small portal-icon-button">
<icon name="add"></icon>
</span>
<span [class.uk-hidden-hover]="stakeholder.topics.length > 0" class="space" [class.uk-hidden]="!open"> Create new topic</span>
</span>
</li>
</ul>
</div>
<div *ngIf="stakeholder && stakeholder.topics.length > 0" class="uk-position-bottom uk-margin-bottom">
<div class="uk-flex uk-flex-center">
<!--<a class="portal-icon-button uk-icon-button icon-button-small uk-margin-right" uk-tooltip="Help">
<i uk-icon="icon:question;ratio:0.7" class="uk-icon"></i>
</a>-->
<a class="portal-icon-button uk-icon-button small" uk-tooltip="Preview">
<icon name="preview" [ratio]="0.7"></icon>
</a>
<div #element uk-dropdown="mode: click; pos: top-left; offset: 5; delay-hide: 0; flip: false"
class="uk-padding-remove-horizontal">
<ul class="uk-nav uk-dropdown-nav">
<li><a target="_blank" [routerLink]="'/' + stakeholder.alias + '/' + stakeholder.topics[topicIndex].alias"
[queryParams]="{view: 'public'}"
(click)="hide(element)">Public view</a>
</li>
<li><a target="_blank" [routerLink]="'/' + stakeholder.alias + '/' +
stakeholder.topics[topicIndex].alias"
[queryParams]="{view: 'restricted'}"
(click)="hide(element)">Restricted view</a>
</li>
<!--<li class="disabled"><a class="uk-disabled uk-text-muted"
uk-tooltip="Note: available only in administration dashboard"
(click)="hide(element)">Private view</a>
</li>-->
</ul>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="!isSmallScreen" id="sidebar_switcher_toggle" class="clickable "
(click)="toggleOpen($event)">
<span class="uk-position-center" *ngIf="!open" uk-icon="icon:chevron-right; ratio: 1.5"></span>
<span class="uk-position-center" *ngIf="open" uk-icon="icon: chevron-left; ratio:1.5"></span>
</div>
</aside>
<div *ngIf="stakeholder && filters" page-content>
<div header>
<nav>
<div *ngIf="stakeholder.topics.length > 0 && stakeholder.topics[topicIndex]">
<ul *ngIf="stakeholder.topics[topicIndex]"
class="customTabs uk-tab admin uk-flex uk-flex-middle" visibility="true">
<ng-template ngFor [ngForOf]="stakeholder.topics[topicIndex].categories" let-category let-i="index">
<li class="uk-visible-toggle uk-flex uk-flex-middle"
[class.uk-active]="category.alias === stakeholder.topics[topicIndex].categories[categoryIndex].alias">
<span class="uk-flex-none">
<ng-container *ngTemplateOutlet="visibilityOptions; context:
{i:i, type: 'cat',
visibility: stakeholder.topics[topicIndex].categories[i].visibility}">
</ng-container>
</span>
<a (click)="toggleCategory(i)">
<span class="title"> {{category.name}}</span>
</a>
<span class="uk-invisible-hover" (click)="$event.stopPropagation();$event.preventDefault()">
<span class="uk-icon clickable" uk-icon="more-vertical"></span>
<div #element uk-dropdown="mode: click; pos: bottom-right; offset: 5; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li><a (click)="editCategoryOpen(i); hide(element)">Edit</a></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<li *ngIf="category.visibility != v.value"><a (click)="changeCategoryStatus(i, v.value);
hide(element)">
{{'Make ' + v.label.toLowerCase()}}</a>
</li>
</ng-template>
<hr *ngIf="!stakeholder.topics[topicIndex].categories[i].defaultId" class="uk-nav-divider">
<li *ngIf="!stakeholder.topics[topicIndex].categories[i].defaultId"><a
(click)="deleteCategoryOpen(i, 'delete'); hide(element)">Delete</a>
</li>
</ul>
</div>
</span>
</li>
</ng-template>
<li class="uk-visible-toggle">
<span (click)="editCategoryOpen(); $event.preventDefault()" class="clickable">
<span class="uk-icon-button small portal-icon-button">
<icon name="add"></icon>
</span>
<span [class.uk-hidden-hover]="stakeholder.topics[topicIndex].categories.length > 0" class="space">Create new category</span>
</span>
</li>
</ul>
</div>
</nav>
<ul *ngIf="stakeholder.topics.length > 0 && stakeholder.topics[topicIndex].categories.length > 0 && stakeholder.topics[topicIndex].categories[categoryIndex]"
visibility="true" class="uk-subnav uk-subnav-pill subCategoriesTabs admin uk-flex uk-flex-middle">
<ng-template ngFor [ngForOf]="stakeholder.topics[topicIndex].categories[categoryIndex].subCategories"
let-subCategory let-i="index">
<li [class.uk-active]="(subCategory.alias ===
stakeholder.topics[topicIndex].categories[categoryIndex].subCategories[subCategoryIndex].alias)"
class="uk-visible-toggle uk-position-relative uk-padding-remove-horizontal">
<span>
<span class="uk-flex-none">
<ng-container *ngTemplateOutlet="visibilityOptions; context:
{i:i, type: 'sub',
visibility: stakeholder.topics[topicIndex].categories[categoryIndex].subCategories[i].visibility}">
</ng-container>
</span>
<a (click)="chooseSubcategory(categoryIndex, i);$event.preventDefault()"
class="space">
<span>{{subCategory.name}}</span>
</a>
<span class="uk-invisible-hover uk-position-center-right color"
(click)="$event.stopPropagation();$event.preventDefault()">
<span class="clickable" uk-icon="more-vertical"></span>
<div #element uk-dropdown="mode: click; pos: bottom-right; offset: 10; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li><a (click)="editSubCategoryOpen(i); hide(element)">Edit</a></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibility" let-v>
<li *ngIf="subCategory.visibility != v.value"><a (click)="changeSubcategoryStatus(i, v.value);
hide(element)">
{{'Make ' + v.label.toLowerCase()}}</a>
</li>
</ng-template>
<li *ngIf="indicators && indicators.isCurator"><a (click)=" indicators.exportIndicators();
hide(element)">Export
indicators</a></li>
<li *ngIf="indicators && indicators.isCurator"><a (click)="file.value = ''; file.click(); hide(element)">Import indicators</a></li>
<hr *ngIf="!stakeholder.topics[topicIndex].categories[categoryIndex].subCategories[i].defaultId"
class="uk-nav-divider">
<li *ngIf="!stakeholder.topics[topicIndex].categories[categoryIndex].subCategories[i].defaultId"><a
(click)="deleteSubcategoryOpen(i, 'delete'); hide(element)">Delete</a>
</li>
</ul>
</div>
</span>
</span>
</li>
</ng-template>
<li class="uk-visible-toggle">
<span (click)="editSubCategoryOpen(); $event.preventDefault()" class="clickable">
<span class="uk-icon-button small portal-icon-button">
<icon name="add"></icon>
</span>
<span [class.uk-hidden-hover]="stakeholder.topics[topicIndex].categories[selectedCategoryIndex].subCategories.length > 0" class="space">Create new subcategory</span>
</span>
</li>
</ul>
<!--<div class="uk-grid uk-margin-medium" uk-grid>
<div *ngIf="filters" class="uk-width-2-3@m uk-width-1-1 uk-child-width-1-3@m uk-child-width-1-1" uk-grid>
<div>
<div dashboard-input [formInput]="filters.get('chartType')"
type="select" [options]="[all].concat(indicatorUtils.allChartTypes)"
label="Chart Type"></div>
</div>
<div>
<div dashboard-input [formInput]="filters.get('status')"
type="select" [options]="[all].concat(stakeholderUtils.visibility)"
label="Status"></div>
</div>
</div>
<div class="uk-width-expand@m uk-width-1-1 uk-flex uk-flex-middle uk-flex-right">
<div class="uk-inline uk-width-medium">
<span class="uk-position-center-right"><i uk-icon="search" class="uk-icon"></i></span>
<div dashboard-input [formInput]="filters.get('keyword')" label="Locate indicator"></div>
</div>
</div>
</div>-->
</div>
<div inner>
<input #file id="import-file" type="file" class="uk-hidden" (change)="indicators.fileChangeEvent($event)"/>
<indicators #indicators [properties]="properties"
[topicIndex]="topicIndex"
[categoryIndex]="categoryIndex"
[filters]="filters"
[subcategoryIndex]="subCategoryIndex"></indicators>
</div>
</div>
<modal-alert #deleteModal (alertOutput)="deleteElement()">
You are about to delete <span class="uk-text-bold" *ngIf="element">"{{element.name}}"</span> {{type}} permanently.
<div *ngIf="elementChildrenActionOnDelete == 'delete'" class="uk-text-bold">
{{getPluralTypeName()}} of all profiles based on this default {{type}}, will be deleted as well.
</div>
Are you sure you want to proceed?
</modal-alert>
<modal-alert #editModal (alertOutput)="saveElement()" [okDisabled]="form && (form.invalid || form.pristine)">
<div *ngIf="form" class="uk-grid uk-padding uk-padding-remove-horizontal uk-child-width-1-1" [formGroup]="form"
uk-grid>
<div dashboard-input [formInput]="form.get('name')" label="Title"></div>
<div dashboard-input [formInput]="form.get('description')"
label="Description" type="textarea">
</div>
<div *ngIf="form.get('icon')" dashboard-input [formInput]="form.get('icon')"
label="Icon(SVG)" type="textarea">
</div>
<div dashboard-input [formInput]="form.get('visibility')"
label="Status" [options]="stakeholderUtils.visibility" type="select">
</div>
</div>
</modal-alert>
<ng-template #visibilityOptions let-type="type" let-i="i" let-visibility="visibility">
<span class="uk-invisible-hover" (click)="$event.stopPropagation();$event.preventDefault()">
<span class="clickable visibility small">
<icon [name]="stakeholderUtils.visibilityIcon.get(visibility)" [ratio]="0.5"></icon>
</span>
<div #element uk-dropdown="mode: click; pos: bottom-left; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li *ngFor="let v of stakeholderUtils.visibility">
<a *ngIf="visibility != v.value"
(click)="$event.stopPropagation();toggleStatusByIndex(i, v.value, type);hide(element);$event.preventDefault()">
<icon [name]="stakeholderUtils.visibilityIcon.get(v.value)" ratio="0.8"></icon>
<span> {{v.label}}</span>
</a>
<a *ngIf="visibility == v.value" class="uk-position-relative">
<icon [name]="stakeholderUtils.visibilityIcon.get(v.value)" [ratio]="0.8"></icon>
<span> {{v.label}}</span>
<span class="uk-position-center-right">
<icon customClass="uk-text-secondary" [ratio]="0.5" name="bullet"></icon>
</span>
</a>
</li>
</ul>
</div>
</span>
</ng-template>

View File

@ -0,0 +1,580 @@
import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Title} from '@angular/platform-browser';
import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties';
import {
Category,
Stakeholder,
SubCategory,
Topic,
Visibility
} from "../openaireLibrary/monitor/entities/stakeholder";
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class";
import {AlertModal} from "../openaireLibrary/utils/modal/alert";
import {Subscriber, Subscription} from "rxjs";
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import {IndicatorUtils, StakeholderUtils} from "../utils/indicator-utils";
import {StringUtils} from "../openaireLibrary/utils/string-utils.class";
import {IDeactivateComponent} from "../openaireLibrary/utils/can-exit.guard";
import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service";
import {Option} from "../openaireLibrary/sharedComponents/input/input.component";
import {properties} from "../../environments/environment";
import {IndicatorsComponent} from "./indicators.component";
import {Session} from "../openaireLibrary/login/utils/helper.class";
declare var UIkit;
@Component({
selector: 'topic',
templateUrl: './topic.component.html',
})
export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
private subscriptions: any[] = [];
private paramsSub: any;
public properties: EnvProperties;
public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public loading: boolean = true;
public stakeholder: Stakeholder;
/**
* Current topic
**/
public topicIndex: number = 0;
/**
* categoryIndex: Current category to be edited, selectedCategoryIndex: selected on menu(opened)
*/
public categoryIndex: number = 0;
public selectedCategoryIndex: number = 0;
/**
* Current Subcategory to be edited
*/
public subCategoryIndex: number = 0;
/**
* Current element and index of topic, category or subcategory to be deleted.
*/
public form: FormGroup;
public element: Topic | Category | SubCategory;
public type: 'topic' | 'category' | 'subcategory' = "topic";
public index: number = -1;
/**
* Check form validity
*/
public toggle: boolean = false;
@ViewChild('deleteModal', { static: true }) deleteModal: AlertModal;
@ViewChild('editModal', { static: true }) editModal: AlertModal;
public elementChildrenActionOnDelete: string;
public filters: FormGroup;
public all: Option = {
value: 'all',
label: 'All'
};
constructor(
private route: ActivatedRoute,
private router: Router,
private title: Title,
private fb: FormBuilder,
private stakeholderService: StakeholderService,
private layoutService: LayoutService) {
}
public ngOnInit() {
this.properties = properties;
let subscription: Subscription;
this.paramsSub = this.route.params.subscribe(params => {
if (subscription) {
subscription.unsubscribe();
}
subscription = this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
if (stakeholder) {
this.stakeholder = stakeholder;
if(params['topic']) {
this.topicIndex = this.stakeholder.topics.findIndex(topic => topic.alias === params['topic']);
}else{
this.topicIndex = 0;
}
this.categoryIndex = 0;
this.subCategoryIndex = 0;
this.filters = this.fb.group({
chartType: this.fb.control('all'),
status: this.fb.control('all'),
keyword: this.fb.control('')
});
if (this.topicIndex === -1) {
this.navigateToError();
} else {
this.title.setTitle(stakeholder.name + " | Indicators");
this.toggle = true;
}
}
});
this.subscriptions.push(subscription);
});
}
public ngOnDestroy() {
this.subscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();
}
});
if(this.paramsSub instanceof Subscriber) {
this.paramsSub.unsubscribe();
}
}
canExit(): boolean {
this.subscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();
}
});
this.stakeholderService.setStakeholder(this.stakeholder);
return true;
}
hide(element: any) {
UIkit.dropdown(element).hide();
}
public saveElement() {
if (this.type === "topic") {
this.saveTopic();
} else if (this.type === "category") {
this.saveCategory();
} else {
this.saveSubCategory();
}
}
// public closeDeleteModal() {
// this.deleteModal.cancel();
// }
public deleteElement() {
if (this.type === "topic") {
this.deleteTopic();
} else if (this.type === "category") {
this.deleteCategory();
} else {
this.deleteSubcategory();
}
}
private buildTopic(topic: Topic) {
let topics = this.stakeholder.topics.filter(element => element._id !== topic._id);
this.form = this.fb.group({
_id: this.fb.control(topic._id),
name: this.fb.control(topic.name, Validators.required),
description: this.fb.control(topic.description),
creationDate: this.fb.control(topic.creationDate),
alias: this.fb.control(topic.alias, [
Validators.required,
this.stakeholderUtils.aliasValidator(topics)
]
),
visibility: this.fb.control(topic.visibility),
defaultId: this.fb.control(topic.defaultId),
categories: this.fb.control(topic.categories),
icon: this.fb.control(topic.icon)
});
this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
let i = 1;
value = this.stakeholderUtils.generateAlias(value);
this.form.controls['alias'].setValue(value);
while (this.form.get('alias').invalid) {
this.form.controls['alias'].setValue(value + i);
i++;
}
}));
}
public editTopicOpen(index = -1) {
this.index = index;
this.type = 'topic';
if (index === -1) {
this.buildTopic(new Topic(null, null, null, "PUBLIC"));
} else {
this.buildTopic(this.stakeholder.topics[index]);
}
this.editOpen();
}
public saveTopic() {
if (!this.form.invalid) {
let path = [this.stakeholder._id];
let callback = (topic: Topic): void => {
if (this.index === -1) {
this.stakeholder.topics.push(topic);
} else {
this.stakeholder.topics[this.index] = HelperFunctions.copy(topic);
}
};
if (this.index === -1) {
this.save('Topic has been successfully created', path, this.form.value, callback);
} else {
this.save('Topic has been successfully saved', path, this.form.value, callback);
}
}
}
public changeTopicStatus(index: number, visibility: Visibility) {
this.type = 'topic';
let path = [
this.stakeholder._id,
this.stakeholder.topics[index]._id
];
this.changeStatus(this.stakeholder.topics[index], path, visibility);
}
public deleteTopicOpen(index = this.topicIndex, childrenAction: string = null) {
this.type = 'topic';
this.index = index;
this.element = this.stakeholder.topics[this.index];
this.deleteOpen(childrenAction);
}
public deleteTopic() {
let path: string[] = [
this.stakeholder._id,
this.stakeholder.topics[this.index]._id
];
let callback = (): void => {
this.stakeholder.topics.splice(this.index, 1);
};
this.delete('Topic has been successfully be deleted', path, callback, (this.topicIndex === this.index));
}
public toggleCategory(index: number) {
if (this.categoryIndex !== index) {
this.categoryIndex = index;
this.toggle = true;
} else {
this.toggle = !this.toggle;
}
}
private buildCategory(category: Category) {
let categories = this.stakeholder.topics[this.topicIndex].categories.filter(element => element._id !== category._id);
this.form = this.fb.group({
_id: this.fb.control(category._id),
name: this.fb.control(category.name, Validators.required),
description: this.fb.control(category.description),
creationDate: this.fb.control(category.creationDate),
alias: this.fb.control(category.alias, [
Validators.required,
this.stakeholderUtils.aliasValidator(categories)
]
),
visibility: this.fb.control(category.visibility),
defaultId: this.fb.control(category.defaultId),
subCategories: this.fb.control(category.subCategories)
});
this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
let i = 1;
value = this.stakeholderUtils.generateAlias(value);
this.form.controls['alias'].setValue(value);
while (this.form.get('alias').invalid) {
this.form.controls['alias'].setValue(value + i);
i++;
}
}));
}
public editCategoryOpen(index: number = -1) {
this.index = index;
this.type = 'category';
if (index === -1) {
this.buildCategory(new Category(null, null, null, "PUBLIC"));
} else {
this.buildCategory(this.stakeholder.topics[this.topicIndex].categories[index]);
}
this.editOpen();
}
public saveCategory() {
if (!this.form.invalid) {
let path = [this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id];
let callback = (category: Category): void => {
if (this.index === -1) {
this.stakeholder.topics[this.topicIndex].categories.push(category);
} else {
this.stakeholder.topics[this.topicIndex].categories[this.index] = HelperFunctions.copy(category);
}
};
if (this.index === -1) {
this.save('Category has been successfully created', path, this.form.value, callback);
} else {
this.save('Category has been successfully saved', path, this.form.value, callback);
}
}
}
public changeCategoryStatus(index: number, visibility: Visibility) {
this.index = index;
this.type = 'category';
let path = [
this.stakeholder._id,
this.stakeholder.topics[this.topicIndex]._id,
this.stakeholder.topics[this.topicIndex].categories[this.index]._id
];
this.changeStatus(this.stakeholder.topics[this.topicIndex].categories[this.index], path, visibility);
}
public deleteCategoryOpen(index: number, childrenAction: string = null) {
this.type = 'category';
this.index = index;
this.element = this.stakeholder.topics[this.topicIndex].categories[this.index];
this.deleteOpen(childrenAction);
}
public deleteCategory() {
let path: string[] = [
this.stakeholder._id,
this.stakeholder.topics[this.topicIndex]._id,
this.stakeholder.topics[this.topicIndex].categories[this.index]._id
];
let callback = (): void => {
this.stakeholder.topics[this.topicIndex].categories.splice(this.index, 1);
};
this.delete('Category has been successfully be deleted', path, callback);
}
private buildSubcategory(subCategory: SubCategory) {
let subCategories = this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.filter(element => element._id !== subCategory._id);
this.form = this.fb.group({
_id: this.fb.control(subCategory._id),
name: this.fb.control(subCategory.name, Validators.required),
description: this.fb.control(subCategory.description),
creationDate: this.fb.control(subCategory.creationDate),
alias: this.fb.control(subCategory.alias, [
Validators.required,
this.stakeholderUtils.aliasValidator(subCategories)
]
),
visibility: this.fb.control(subCategory.visibility),
defaultId: this.fb.control(subCategory.defaultId),
charts: this.fb.control(subCategory.charts),
numbers: this.fb.control(subCategory.numbers)
});
this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
let i = 1;
value = this.stakeholderUtils.generateAlias(value);
this.form.controls['alias'].setValue(value);
while (this.form.get('alias').invalid) {
this.form.controls['alias'].setValue(value + i);
i++;
}
}));
}
public editSubCategoryOpen(index: number = -1) {
this.index = index;
this.type = 'subcategory';
if (index === -1) {
this.buildSubcategory(new SubCategory(null, null, null, "PUBLIC"));
} else {
this.buildSubcategory(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[index]);
}
this.editOpen();
}
public saveSubCategory() {
if (!this.form.invalid) {
let path: string[] = [
this.stakeholder._id,
this.stakeholder.topics[this.topicIndex]._id,
this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id
];
let callback = (subCategory: SubCategory): void => {
if (this.index === -1) {
this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.push(subCategory);
} else {
this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index] = HelperFunctions.copy(subCategory);
}
};
if (this.index === -1) {
this.save('Subcategory has been successfully created', path, this.form.value, callback);
} else {
this.save('Subcategory has been successfully saved', path, this.form.value, callback);
}
}
}
public changeSubcategoryStatus(index: number, visibility: Visibility) {
this.index = index;
this.type = 'subcategory';
let path = [
this.stakeholder._id,
this.stakeholder.topics[this.topicIndex]._id,
this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
];
this.changeStatus(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index], path, visibility);
}
public deleteSubcategoryOpen(index, childrenAction: string = null) {
this.type = 'subcategory';
this.index = index;
this.element = this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index];
this.deleteOpen(childrenAction);
}
public deleteSubcategory() {
let path: string[] = [
this.stakeholder._id,
this.stakeholder.topics[this.topicIndex]._id,
this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
];
let callback = (): void => {
this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.splice(this.index, 1);
};
this.delete('Subcategory has been successfully be deleted', path, callback);
}
private navigateToError() {
this.router.navigate(['/error'], {queryParams: {'page': this.router.url}});
}
private editOpen() {
this.editModal.cancelButtonText = 'Cancel';
this.editModal.okButtonLeft = false;
this.editModal.alertMessage = false;
if (this.index === -1) {
this.editModal.alertTitle = 'Create a new ' + this.type;
this.editModal.okButtonText = 'Create';
} else {
this.editModal.alertTitle = 'Edit ' + this.type + '\'s information ';
this.editModal.okButtonText = 'Save';
}
this.editModal.open();
}
private deleteOpen(childrenAction: string = null) {
this.elementChildrenActionOnDelete = null;
if (childrenAction == "delete") {
this.elementChildrenActionOnDelete = childrenAction;
} else if (childrenAction == "disconnect") {
this.elementChildrenActionOnDelete = childrenAction;
}
this.deleteModal.alertTitle = 'Delete ' + this.type;
this.deleteModal.cancelButtonText = 'No';
this.deleteModal.okButtonText = 'Yes';
// this.deleteModal.cancelButton = false;
// this.deleteModal.okButton = false;
this.deleteModal.open();
}
private save(message: string, path: string[], saveElement: any, callback: Function, redirect = false) {
this.subscriptions.push(this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, saveElement, path).subscribe(saveElement => {
callback(saveElement);
UIkit.notification(message, {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
if (redirect) {
this.router.navigate(['../' + saveElement.alias], {
relativeTo: this.route
});
}
}, error => {
UIkit.notification(error.error.message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
}));
}
private delete(message: string, path: string[], callback: Function, redirect = false) {
this.subscriptions.push(this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path, this.elementChildrenActionOnDelete).subscribe(() => {
callback();
UIkit.notification(message, {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
if (redirect) {
this.back();
}
}, error => {
UIkit.notification(error.error.message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
}));
}
public toggleStatusByIndex(index: number, visibility: Visibility, type) {
if (type == "sub") {
this.changeSubcategoryStatus(index, visibility);
} else if (type == "cat") {
this.changeCategoryStatus(index, visibility);
} else if (type == "topic") {
this.changeTopicStatus(index, visibility);
}
}
private changeStatus(element: Topic | Category | SubCategory, path: string[], visibility: Visibility) {
this.subscriptions.push(this.stakeholderService.changeVisibility(this.properties.monitorServiceAPIURL, path, visibility).subscribe(visibility => {
element.visibility = visibility;
UIkit.notification(StringUtils.capitalize(this.type) + ' has been <b>successfully changed</b> to ' + element.visibility.toLowerCase(), {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
}, error => {
UIkit.notification(error.error.message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
}));
}
back() {
this.router.navigate(['../'], {
relativeTo: this.route
});
}
chooseSubcategory(categoryIndex: number, subcategoryIndex: number) {
this.categoryIndex = categoryIndex;
this.subCategoryIndex = subcategoryIndex;
}
public getPluralTypeName(): string {
if (this.type == "topic") {
return "Topics";
} else if (this.type == "category") {
return "Categories";
} else if (this.type == "subcategory") {
return "Subcategories";
} else {
return this.type;
}
}
public get isSmallScreen() {
return this.layoutService.isSmallScreen;
}
public get open() {
return this.layoutService.open;
}
public toggleOpen(event: MouseEvent) {
event.preventDefault();
this.layoutService.setOpen(!this.open);
}
}

View File

@ -0,0 +1,52 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {PreviousRouteRecorder} from '../openaireLibrary/utils/piwik/previousRouteRecorder.guard';
import {PiwikService} from '../openaireLibrary/utils/piwik/piwik.service';
import {TopicComponent} from "./topic.component";
import {TopicRoutingModule} from "./topic-routing.module";
import {RouterModule} from "@angular/router";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {IndicatorsComponent} from "./indicators.component";
import {AlertModalModule} from "../openaireLibrary/utils/modal/alertModal.module";
import {InputModule} from "../openaireLibrary/sharedComponents/input/input.module";
import {ClickModule} from "../openaireLibrary/utils/click/click.module";
import {IconsService} from "../openaireLibrary/utils/icons/icons.service";
import {
preview,
bullet,
add,
earth,
lock,
group,
refresh,
close,
arrow_right, done, cloud_upload
} from "../openaireLibrary/utils/icons/icons";
import {IconsModule} from "../openaireLibrary/utils/icons/icons.module";
import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
import {LoadingModule} from "../openaireLibrary/utils/loading/loading.module";
import {NotifyFormModule} from "../openaireLibrary/notifications/notify-form/notify-form.module";
@NgModule({
imports: [
CommonModule, TopicRoutingModule, ClickModule, RouterModule, FormsModule, AlertModalModule,
ReactiveFormsModule, InputModule, IconsModule, PageContentModule, LoadingModule, NotifyFormModule
],
declarations: [
TopicComponent, IndicatorsComponent
],
providers: [
PreviousRouteRecorder,
PiwikService
],
exports: [
TopicComponent
]
})
export class TopicModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([preview, bullet, add, earth, lock, group, refresh, close, arrow_right, done, cloud_upload]);
}
}

View File

@ -3,11 +3,14 @@
<loading></loading>
</div>
</div>
<role-users *ngIf="!loading && stakeholder" [id]="stakeholder.alias" [type]="stakeholder.type" [name]="stakeholder.name" [link]="link" [role]="tab" [message]="messages.get(tab)"
<ng-template #tabs>
<ul class="uk-tab customTabs admin uk-flex uk-flex-center uk-flex-left@m" uk-tab>
<li [class.uk-active]="tab === 'manager'"><a routerLink="./"><span class="title">Managers</span></a></li>
<li [class.uk-active]="tab === 'member'"><a routerLink="./" fragment="member"><span class="title">Members</span></a></li>
</ul>
</ng-template>
<role-users *ngIf="!loading && alias" [id]="alias" [type]="type" [name]="name" [link]="link" [role]="tab" [message]="messages.get(tab)"
[emailComposer]="emailComposer" [notificationFn]="notificationFn">
<ul class="uk-tab uk-margin-remove-bottom uk-margin-medium-top">
<li [class.uk-active]="tab === 'manager'"><a routerLink="../manager">Managers</a></li>
<li [class.uk-active]="tab === 'member'"><a routerLink="../member">Members</a></li>
</ul>
<ng-container [ngTemplateOutlet]="tabs"></ng-container>
</role-users>

View File

@ -11,8 +11,6 @@ import {Notification} from "../openaireLibrary/notifications/notifications";
import {User} from "../openaireLibrary/login/utils/helper.class";
import {UserManagementService} from "../openaireLibrary/services/user-management.service";
import {EnvProperties} from "../openaireLibrary/utils/properties/env-properties";
import {Stakeholder} from "../openaireLibrary/monitor/entities/stakeholder";
import {StringUtils} from "../openaireLibrary/utils/string-utils.class";
type Tab = 'member' | 'manager';
@ -21,8 +19,10 @@ type Tab = 'member' | 'manager';
templateUrl: 'users.component.html'
})
export class UsersComponent implements OnInit {
public stakeholder: Stakeholder;
public alias: string;
public name: string;
public type: string;
public link: string;
public loading: boolean;
public messages: Map<Tab, string> = new Map<Tab, string>();
@ -37,10 +37,10 @@ export class UsersComponent implements OnInit {
if(invitation) {
invitation.link = this.link + invitation.link;
}
let notification: Notification = NotificationUtils.invite(this.stakeholder.name, role, 'user', invitation);
let notification: Notification = NotificationUtils.invite(this.name, role, 'user', invitation);
notification.entity = recipient;
notification.stakeholderType = this.stakeholder.type;
notification.stakeholder = this.stakeholder.alias;
notification.stakeholderType = this.type;
notification.stakeholder = this.alias;
notification.name = this.user.firstname;
notification.surname = this.user.lastname;
notification.groups = [recipient];
@ -55,21 +55,20 @@ export class UsersComponent implements OnInit {
ngOnInit() {
this.loading = true;
this.subscriptions.push(this.route.params.subscribe(params => {
if (this.isTab(params['user_type'])) {
this.tab = params['user_type'];
this.subscriptions.push(this.route.fragment.subscribe((fragment: Tab) => {
if (this.isTab(fragment)) {
this.tab = fragment;
} else {
this.tab = 'manager';
}
if(this.stakeholder) {
this.title.setTitle(this.stakeholder.name + " | " + this.users);
}
}));
this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
if (stakeholder) {
this.stakeholder = stakeholder;
this.title.setTitle(this.stakeholder.name + " | " + this.users);
this.link = this.getURL(this.stakeholder.alias);
this.alias = stakeholder.alias;
this.name = stakeholder.name;
this.title.setTitle(this.name + " | Users");
this.type = stakeholder.type;
this.link = this.getURL(this.alias);
this.messages.set("member", 'A member has the right to view the <b>restricted access</b> areas of this indicator\'s profile. ' +
'A member has <b>no access</b> to the administration part of the profile.');
this.messages.set("manager", 'A manager has the right to access the administration part of this indicator\'s profile, ' +
@ -90,10 +89,6 @@ export class UsersComponent implements OnInit {
});
}
get users(): string {
return StringUtils.capitalize(this.tab) + 's';
}
private isTab(tab: Tab): boolean {
switch (tab) {
case "manager":

View File

@ -6,10 +6,9 @@ import {LoadingModule} from "../openaireLibrary/utils/loading/loading.module";
import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
import {RoleUsersModule} from "../openaireLibrary/dashboard/users/role-users/role-users.module";
import {RouterModule} from "@angular/router";
import {LogoUrlPipeModule} from "../openaireLibrary/utils/pipes/logoUrlPipe.module";
@NgModule({
imports: [CommonModule, UsersRoutingModule, LoadingModule, PageContentModule, RoleUsersModule, RouterModule, LogoUrlPipeModule],
imports: [CommonModule, UsersRoutingModule, LoadingModule, PageContentModule, RoleUsersModule, RouterModule],
declarations: [UsersComponent],
exports: [UsersComponent]
})

View File

@ -0,0 +1,53 @@
import {Injectable} from '@angular/core';
import {
ActivatedRouteSnapshot,
CanActivate,
CanActivateChild,
Router,
RouterStateSnapshot,
UrlTree
} from '@angular/router';
import {map, take, tap} from "rxjs/operators";
import {UserManagementService} from "../openaireLibrary/services/user-management.service";
import {LoginErrorCodes} from "../openaireLibrary/login/utils/guardHelper.class";
import {Session} from "../openaireLibrary/login/utils/helper.class";
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
import {Observable, zip} from "rxjs";
@Injectable()
export class AdminDashboardGuard implements CanActivate, CanActivateChild {
constructor(private router: Router,
private stakeholderService: StakeholderService,
private userManagementService: UserManagementService) {
}
check(path: string, alias: string): Observable<boolean> | boolean {
if (Session.isLoggedIn()) {
return zip(
this.userManagementService.getUserInfo(false)
,this.stakeholderService.getStakeholder(alias)
).pipe(take(1),map(res =>{
return res[0] && res[1] && (Session.isPortalAdministrator(res[0]) ||
Session.isCurator(res[1].type, res[0]) || Session.isManager(res[1].type, res[1].alias, res[0]));
}),tap(authorized => {
if(!authorized){
this.router.navigate(['/user-info'], {queryParams: {'errorCode': LoginErrorCodes.NOT_ADMIN, 'redirectUrl':path}});
}
}));
} else {
this.router.navigate(['/user-info'], {queryParams: {'errorCode': LoginErrorCodes.NOT_LOGIN, 'redirectUrl':path}});
return false;
}
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.check(state.url, route.params.stakeholder);
}
canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.check(state.url, childRoute.params.stakeholder);
}
}

View File

@ -0,0 +1,944 @@
import {
ChartHelper, FilterType,
Indicator, IndicatorFilterUtils,
IndicatorPath, IndicatorPathType, IndicatorType,
SourceType,
Stakeholder,
SubCategory,
Topic, Visibility
} from "../openaireLibrary/monitor/entities/stakeholder";
import {AbstractControl, ValidatorFn, Validators} from "@angular/forms";
import {Option} from "../openaireLibrary/sharedComponents/input/input.component";
import {Session} from "../openaireLibrary/login/utils/helper.class";
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'},
{value: 'PRIVATE', label: 'Private'}
];
types: Option[] = [
{value: 'funder', label: 'Funder'},
{value: 'ri', label: 'Research Initiative'},
{value: 'project', label: 'Project'},
{value: 'organization', label: 'Organization'}
];
visibility: Option[] = [
{icon: 'world', value: "PUBLIC", label: 'Public'},
{icon: 'lock', value: "RESTRICTED", label: 'Restricted'},
{icon: 'users', value: "PRIVATE", label: 'Private'},
];
visibilityIcon: Map<Visibility, string> = new Map<Visibility, string> ([
["PUBLIC", 'earth'],
["PRIVATE", 'lock'],
["RESTRICTED", 'group']
]);
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))){
types.push(type);
}
}
return types;
}
public createFunderFromDefaultProfile(funder: Stakeholder, defaultTopics: Topic[]): Stakeholder {
funder.topics = HelperFunctions.copy(defaultTopics);
for (let topic of funder.topics) {
// console.log('id:' + topic._id);
topic.defaultId = topic._id;
topic._id = null;
// console.log('defaultId:' + topic.defaultId);
for (let category of topic.categories) {
category.defaultId = category._id;
category._id = null;
let subTokeep: SubCategory[] = [];
for (let subCategory of category.subCategories) {
subCategory.defaultId = subCategory._id;
subCategory._id = null;
subTokeep.push(subCategory);
for (let section of subCategory.charts) {
let chartsTokeep: Indicator[] = [];
section.defaultId = section._id;
section.stakeholderAlias = funder.alias;
section._id = null;
for (let indicator of section.indicators) {
indicator.defaultId = indicator._id;
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" ) {
indicatorPath.parameters[key] = funder.index_id;
} else if (key == "index_shortName" ) {
indicatorPath.parameters[key] = funder.index_shortName.toLowerCase();
}
});
}
}
}
section.indicators = chartsTokeep;
}
for (let section of subCategory.numbers) {
section.defaultId = section._id;
section.stakeholderAlias = funder.alias;
section._id = null;
for(let indicator of section.indicators) {
indicator.defaultId = indicator._id;
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;
}
aliasValidatorString(elements: string[]): ValidatorFn {
return (control: AbstractControl): { [key: string]: string } | null => {
if (control.value && elements.find(element =>
element === control.value
)) {
return {'error': 'Alias already in use'};
}
return null;
}
}
aliasValidator(elements: any[]): ValidatorFn {
return (control: AbstractControl): { [key: string]: string } | null => {
if (control.value && elements.find(element =>
element.alias === control.value
)) {
return {'error': 'Alias already in use'};
}
return null;
}
}
generateAlias(name: string): string {
let alias = name.toLowerCase();
while (alias.includes('/') || alias.includes(' ')) {
alias = alias.replace(' / ', '-');
alias = alias.replace('/', '-');
alias = alias.replace(' ', '-');
}
return alias;
}
}
export class IndicatorUtils {
allChartTypes: Option[] = [
{value: 'pie', label: 'Pie'},
{value: 'table', label: 'Table'},
{value: 'line', label: 'Line'},
{value: 'column', label: 'Column'},
{value: 'bar', label: 'Bar'},
{value: 'other', label: '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[] = [
{value: 'search', label: 'Search'},
{value: 'statistics', label: 'Statistics'},
{value: 'metrics', label: 'Metrics'},
{value: 'stats-tool', label: 'Statistics tool'}
];
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<string, string> = new Map([
['pie', 'pie_chart'],
['table', 'table_chart'],
['line', 'show_chart'],
['column', 'bar_chart'],
['bar', 'notes'],
['other', 'perm_media']
]);
getChartTypes(initialType){
let types: Option[]= [];
if(this.basicChartTypes.indexOf(initialType) != -1){
(this.allChartTypes).forEach(option => {
if(this.basicChartTypes.indexOf(option.value)!=-1){
types.push(option);
}
});
return types;
}else if(initialType == "table") {
(this.allChartTypes).forEach(option => {
if (initialType == option.value) {
types.push(option);
}
});
return types;
}else {
return this.allChartTypes;
}
}
isPublicIcon: Map<boolean, string> = new Map([
[true, 'public'],
[false, 'lock']
]);
isActiveIcon: string = 'brightness_1';
ignoredParameters = ['index_name','index_id','index_shortName'];
parametersValidators: Map<string, any> = new Map<string, any>([
['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;
if (indicatorPath.parameters) {
Object.keys(indicatorPath.parameters).forEach(key => {
let replacedValue = indicatorPath.parameters[key];
if (startYear && key == "start_year" && indicatorPath.filters["start_year"]) {
replacedValue = (replacedValue < startYear) ? startYear : replacedValue;
}
if (endYear && key == "end_year" && indicatorPath.filters["end_year"]) {
replacedValue = (replacedValue > endYear) ? endYear : replacedValue;
}
if (key == "index_id") {
replacedValue = stakeholder.index_id;
}
if (key == "index_name") {
replacedValue = stakeholder.index_name;
}
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)]) {
if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) {
queries["query"]["filters"] = [];
}
//TODO check how it works if the query already has a filter
queries["query"]["filters"].push(JSON.parse(indicatorPath.filters["fundingL0"].replace(ChartHelper.prefix + "fundingL0" + ChartHelper.suffix, fundingL0)));
}
replacedUrl = JSON.stringify(newJsonObject);
}
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)]) {
if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) {
queries["query"]["filters"] = [];
}
//TODO check how it works if the query already has a filter
queries["query"]["filters"].push(JSON.parse(indicatorPath.filters["start_year"].replace(ChartHelper.prefix + "start_year" + ChartHelper.suffix, startYear)));
}
replacedUrl = JSON.stringify(newJsonObject);
}
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)]) {
if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) {
queries["query"]["filters"] = [];
}
//TODO check how it works if the query already has a filter
queries["query"]["filters"].push(JSON.parse(indicatorPath.filters["end_year"].replace(ChartHelper.prefix + "end_year" + ChartHelper.suffix, endYear)));
}
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))
}
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(indicatorPath.url.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);
}
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;
if (indicatorPath.parameters) {
Object.keys(indicatorPath.parameters).forEach(key => {
let replacedValue = indicatorPath.parameters[key];
if (startYear && key == "start_year") {
replacedValue = (replacedValue < startYear) ? startYear : replacedValue;
}
if (endYear && key == "end_year") {
replacedValue = (replacedValue > endYear) ? endYear : replacedValue;
}
if (key == "index_id") {
replacedValue = stakeholder.index_id;
}
if (key == "index_name") {
replacedValue = stakeholder.index_name;
}
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) {
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);
replacedUrl = filterResults.url;
indicatorPath.filtersApplied += filterResults.filtersApplied;
}
}
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) {
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))
}
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 (replacedUrl.indexOf(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix) != -1) {
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);
}
private addFilter(replacedUrl, filterType:FilterType, filterValue){
let newJsonObject = JSON.parse(replacedUrl);
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)]) {
if(queries["query"]["name"] && !queries["query"]["select"]){
if(queries["query"]["name"].indexOf("monitor.")==-1 || !queries["query"]["parameters"]){
continue;
}
if(filterType == 'fundingL0') {
let paramFields = queries["query"]["name"].split(".").slice(3);
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;
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){
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){
queries["query"]["parameters"].splice(paramFields.length + 1, 0, filterValue);
}
queries["query"]["name"] = queries["query"]["name"] + ".fl0";
queries["query"]["parameters"].push(filterValue);
filterApplied = true;
}
}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){
filterApplied = true;
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){
filterApplied = true;
if(filterType == "start_year"){
queries["query"]["parameters"][paramFields.length + 2] = parseInt(filterValue);
}else if(filterType == "end_year"){
queries["query"]["parameters"][paramFields.length + 3] = parseInt(filterValue);
}
}
}
// console.debug(queries["query"])
// it is a name query
continue;
}
if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) {
queries["query"]["filters"] = [];
}
let field = queries["query"]["select"][0]["field"];
let filterString = IndicatorFilterUtils.getFilter(field&&field.length > 0? field.split(".")[0]:"",filterType);
if(filterString){
let filter = JSON.parse(filterString);
let filterposition = IndicatorFilterUtils.filterIndexOf(filter,queries["query"]["filters"])
if(filterposition){
if(queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0] != filter['groupFilters'][0]["values"][0].replace(ChartHelper.prefix + filterType + ChartHelper.suffix, filterValue)){
//change filter value
// queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0] = filter['groupFilters'][0]["values"][0].replace(ChartHelper.prefix + filterType + ChartHelper.suffix, filterValue);
//add user filter value
// queries["query"]["filters"].push(JSON.parse(filterString.replace(ChartHelper.prefix + filterType + ChartHelper.suffix, filterValue)));
// update colors
//if noit a pie, map and chart has more than one query
//
if(!newJsonObject.hasOwnProperty("mapDescription") && queries["type"]!="pie" && this.isComparingChart(newJsonObject, filter)) {
let activeColors = ["#7CB5EC", "#434348", "#8bbc21", "#910000", "#1aadce", "#492970", "#f28f43", "#77a1e5", "#c42525", "#a6c96a"];
let inActiveColors = ["#E4EFFB", "#D8D8D9", "#8bbc21", "#910000", "#1aadce", "#492970", "#f28f43", "#77a1e5", "#c42525", "#a6c96a"];
if (!newJsonObject[this.getDescriptionObjectName(newJsonObject)]["colors"]) {
newJsonObject[this.getDescriptionObjectName(newJsonObject)]["colors"] = activeColors;
}
newJsonObject[this.getDescriptionObjectName(newJsonObject)]["colors"][queryIndex] = inActiveColors[queryIndex];
filterApplied = true;
}else if (filterType == "start_year" || filterType == "end_year") {
//if has date filter already
if(filterType == "start_year" && parseInt(filterValue) > parseInt(queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0])){
queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0] = filterValue;
}else if(filterType == "end_year" && parseInt(filterValue) < parseInt(queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0])) {
queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0] = filterValue;
}
filterApplied = true;
}
}else{
filterApplied = true;
}
}else {
queries["query"]["filters"].push(JSON.parse(filterString.replace(ChartHelper.prefix + filterType + ChartHelper.suffix, filterValue)));
filterApplied = true;
}
}
queryIndex++;
}
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;
let values = [];
if(queriesCount < 2){
return false;
}
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) {
values.push(queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0]);
}
}
}
// console.debug(values);
return values.length > 1;
}
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) {
indicatorPath.parameters.forEach(parameter => {
indicator.indicatorPaths[index].parameters[parameter.key] = parameter.value;
if (parameter.key === 'type') {
indicator.indicatorPaths[index].type = parameter.value;
}
});
}
});
return indicator;
}
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]:"");
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]=="")) {
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] ;
}
}
try {
if (url.indexOf(encodeURIComponent(stakeholder.index_id)) !== -1) {
url = url.split(encodeURIComponent(stakeholder.index_id)).join(ChartHelper.prefix + "index_id" + ChartHelper.suffix);
}
if (url.indexOf(encodeURIComponent(stakeholder.index_name)) !== -1) {
url = url.split(encodeURIComponent(stakeholder.index_name)).join(ChartHelper.prefix + "index_name" + ChartHelper.suffix);
}
if (url.indexOf(encodeURIComponent(stakeholder.index_shortName)) !== -1) {
url = url.split(encodeURIComponent(stakeholder.index_shortName)).join(ChartHelper.prefix + "index_shortName" + ChartHelper.suffix);
}
indicatorPath.url = url;
} catch (e) {
console.error(e);
}
}
return 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') {
indicatorPath.url = url.split("json=")[0] + "json=";
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" )) {
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="){
indicatorPath.type = "table";
}
if (indicatorPath.url == "chart?json=" || indicatorPath.url == "table?json=") {
// common for tables and other chart types
this.extractDataTitle(chart, indicatorPath);
this.parameterizeDefaultQuery(chart, indicatorPath, stakeholder);
this.extractStakeHolders(chart, indicatorPath, stakeholder);
this.extractStartYear(chart, indicatorPath);
this.extractEndYear(chart, indicatorPath);
indicatorPath.chartObject = JSON.stringify(chart);
}
} else if (source === 'old') {
indicatorPath.url = url.split("data=")[0].split("/stats/")[1] + "data=";
indicatorPath.chartObject = decodeURIComponent(url.split("data=")[1].split("&")[0]);
indicatorPath.type = type;
let chart = JSON.parse(indicatorPath.chartObject);
this.extractOldToolTitle(chart, indicatorPath);
this.extractOldToolXTitle(chart, indicatorPath);
this.extractOldToolYTitle(chart, indicatorPath);
indicatorPath.chartObject = JSON.stringify(chart);
} else {
indicatorPath.url = url;
indicatorPath.type = type;
}
}catch(e){
console.error(e);
indicatorPath.url = url;
indicatorPath.type = type;
}
// console.debug(indicatorPath.parameters);
// console.debug(indicatorPath.chartObject);
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")) {
return "queries";
}
}
private getDescriptionObjectName(obj){
if(obj.hasOwnProperty("mapDescription")){
return "mapDescription";
}else if(obj.hasOwnProperty("chartDescription")) {
return "chartDescription";
}else if(obj.hasOwnProperty("tableDescription") ){
return "tableDescription";
}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"]:"";
if (this.basicChartTypes.indexOf(type) == -1) {
type = this.defaultChartType;
} else {
obj[this.getDescriptionObjectName(obj)]["queries"][0]["type"] = ChartHelper.prefix + "type" + ChartHelper.suffix;
indicatorPath.parameters['type'] = type;
}
return type;
}
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"){
return;
}
for (let query of this.getQueryObjectName(obj)?obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]:obj[this.getDescriptionObjectName(obj)]) {
if (!query["query"]["filters"]) {
return;
}
for (let filter of query["query"]["filters"]) {
if (filter["groupFilters"][0]["field"].indexOf(" funder") != -1) {//new statistcs schema
filter["groupFilters"][0]["values"][0] = ChartHelper.prefix + "index_name" + ChartHelper.suffix;
indicatorPath.parameters["index_name"] = stakeholder.index_name;
}else if (filter["groupFilters"][0]["field"].indexOf(".funder") != -1) {
filter["groupFilters"][0]["values"][0] = ChartHelper.prefix + "index_name" + ChartHelper.suffix;
indicatorPath.parameters["index_name"] = stakeholder.index_name;
}else if (filter["groupFilters"][0]["field"].indexOf(".funder.id") != -1) {
filter["groupFilters"][0]["values"][0] = ChartHelper.prefix + "index_shortName" + ChartHelper.suffix;
indicatorPath.parameters["index_shortName"] = stakeholder.index_shortName;
}
}
}
}
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)]) {
if (!query["query"]["filters"]) {
return;
}
for (let filter of query["query"]["filters"]) {
if (filter["groupFilters"][0]["field"].indexOf(".context.name") != -1) {
filter["groupFilters"][0]["values"][0] = ChartHelper.prefix + "index_name" + ChartHelper.suffix;
indicatorPath.parameters["index_name"] = stakeholder.index_name;
}else if (filter["groupFilters"][0]["field"].indexOf(".context.id") != -1) {
filter["groupFilters"][0]["values"][0] = ChartHelper.prefix + "index_shortName" + ChartHelper.suffix;
indicatorPath.parameters["index_shortName"] = stakeholder.index_shortName;
}
}
}
}
private extractOrganization(obj, indicatorPath: IndicatorPath, stakeholder:Stakeholder) {
// works for publication.project.organization.name
// and publication.organization.name
if(stakeholder.type != "organization"){
return;
}
for (let query of this.getQueryObjectName(obj)?obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]:obj[this.getDescriptionObjectName(obj)]) {
if (!query["query"]["filters"]) {
return;
}
for (let filter of query["query"]["filters"]) {
if (filter["groupFilters"][0]["field"].indexOf(".organization.name") != -1) {
filter["groupFilters"][0]["values"][0] = ChartHelper.prefix + "index_name" + ChartHelper.suffix;
indicatorPath.parameters["index_name"] = stakeholder.index_name;
}else if (filter["groupFilters"][0]["field"].indexOf(".organization.id") != -1) {
filter["groupFilters"][0]["values"][0] = ChartHelper.prefix + "index_shortName" + ChartHelper.suffix;
indicatorPath.parameters["index_shortName"] = stakeholder.index_shortName;
}
}
}
}
private extractStartYear(obj, indicatorPath: IndicatorPath) {
let start_year;
for (let query of obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) {
if (!query["query"]["filters"]) {
return;
}
for (let filter of query["query"]["filters"]) {
for (let gfilter of filter["groupFilters"]) {
if ((gfilter["field"].indexOf(".year") != -1 || gfilter["field"].indexOf(".start year") != -1) && gfilter["type"].indexOf(">") != -1) {
start_year = gfilter["values"][0];
gfilter["values"][0] = ChartHelper.prefix + "start_year" + ChartHelper.suffix;
indicatorPath.parameters["start_year"] = start_year;
}
}
}
}
}
private extractEndYear(obj, indicatorPath: IndicatorPath) {
let end_year;
for (let query of obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) {
if (!query["query"]["filters"]) {
return;
}
for (let filter of query["query"]["filters"]) {
for (let gfilter of filter["groupFilters"]) {
if ((gfilter["field"].indexOf(".year") != -1 || gfilter["field"].indexOf(".start year") != -1) && gfilter["type"].indexOf("<") != -1) {
end_year = gfilter["values"][0];
gfilter["values"][0] = ChartHelper.prefix + "end_year" + ChartHelper.suffix;
indicatorPath.parameters["end_year"] = end_year;
}
}
}
}
}
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)]) {
//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") {
//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"){
// 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];
indicatorPath.parameters["index_shortName"] = stakeholder.index_shortName.toLowerCase();
}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) {
if (name.split('.').length > 3 && name.split('.')[3] == "id") {
parameters[i] = ChartHelper.prefix + "index_id" + ChartHelper.suffix;
indicatorPath.parameters["index_id"] = stakeholder.index_id;
} else if (name.split('.').length > 3 && name.split('.')[3] == "shortname") {
parameters[i] = ChartHelper.prefix + "index_shortName" + ChartHelper.suffix;
indicatorPath.parameters["index_shortName"] = stakeholder.index_shortName.toLowerCase();
} else if (name.split('.').length > 3 && name.split('.')[3] == "name") {
parameters[i] = ChartHelper.prefix + "index_name" + ChartHelper.suffix;
indicatorPath.parameters["index_name"] = stakeholder.index_name;
}
}
}
}
}
}
private extractDataTitle(obj, indicatorPath: IndicatorPath) {
let index = 0;
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;
}
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"]) {
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"]) {
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"]) {
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"]) {
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"] ) {
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"]) {
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"]) {
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"]) {
title = obj["xaxistitle"];
obj["xaxistitle"] = ChartHelper.prefix + "xAxisTitle" + ChartHelper.suffix;
indicatorPath.parameters["xAxisTitle"] = title;
}
}
private extractOldToolYTitle(obj, indicatorPath: IndicatorPath) {
let title = "";
if (obj["fieldsheaders"]) {
title = Array.isArray(obj["fieldsheaders"]) ? obj["fieldsheaders"][0] : obj["fieldsheaders"];
if (Array.isArray(obj["fieldsheaders"])) {
obj["fieldsheaders"][0] = ChartHelper.prefix + "yAxisTitle" + ChartHelper.suffix;
} else {
obj["fieldsheaders"] = ChartHelper.prefix + "yAxisTitle" + ChartHelper.suffix;
}
indicatorPath.parameters["yAxisTitle"] = title;
}
}
public checkForSchemaEnhancements(url:string):boolean{
return url !=this.applySchemaEnhancements(url);
}
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"]
];
let changes = "";
for (let field of resultEnhancements) {
for (let type of ["publication", "software", "dataset", "other", "result"]) {
if (url.indexOf(encodeURIComponent(type + field[0])) != -1) {
changes += "Changed " + type + field[0] + " to " + type + field[1] + "\n";
url = url.split(encodeURIComponent(type + field[0])).join(encodeURIComponent(type + field[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\"";
query["query"]["profile"] = 'monitor';
}
}
url = url.split('json=')[0] + "json=" + encodeURIComponent(JSON.stringify(obj));
}
console.debug(changes);
console.debug(url);
return url;
}
}

View File

@ -0,0 +1,73 @@
import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {Observable} from "rxjs";
import {SourceType} from "../../openaireLibrary/monitor/entities/stakeholder";
import {properties} from "../../../environments/environment";
@Injectable({
providedIn: 'root'
})
export class StatisticsService {
numberSources: Map<SourceType, string[]> = new Map<SourceType, string[]>();
chartSources: Map<SourceType, string[]> = new Map<SourceType, string[]>();
constructor(private http:HttpClient) {
this.numberSources.set('statistics', [properties.statisticsAPIURL]);
this.numberSources.set('search', [properties.searchAPIURLLAst]);
this.numberSources.set('metrics', [properties.metricsAPIURL]);
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('metrics', [properties.metricsAPIURL]);
this.chartSources.set('image', [""]);
}
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<any> {
if(source !== null) {
return this.http.get<any>(this.numberSources.get(source)[0] + url);
} else {
return this.http.get<any>(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;
}
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

@ -1 +1 @@
Subproject commit 186e4bf732f96459a1e22b44ba172f08f0c11d48
Subproject commit 318c6560565a7a0da818385de27ebb430b22aea3

@ -0,0 +1 @@
Subproject commit 8f656664973f82d9f6f0228968a77643964da805

BIN
src/assets/develop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 KiB

View File

@ -0,0 +1,226 @@
.refresh-indicator {
background-color: rgba(0, 0, 0, 0.50);
position: absolute;
}
.rotate-90 {
transform: rotate(90deg);
}
.stakeholderPage #sidebar_main .sidebar_main_header .logo{
margin-top: 15px;
}
.stakeholderPage .uk-navbar-center .uk-logo{
max-height: var(--header-height);
}
.stakeholderPage .uk-navbar ul li.uk-active a{
color:var(--monitor-portal-color);
font-weight: bold;
}
.stakeholderPage #header_main{
padding-left: 6px;
}
/*#header_main.light_header {
background: #F9FBFC !important;
color: #000000B3;
}*/
.dashboard #header_main.light_header .uk-navbar-nav > li > user-mini > a, .dashboard #header_main.light_header .uk-navbar-nav > li > a {
color: #000000B3;
text-transform: uppercase;
}
.dashboard #header_main.light_header .uk-navbar-nav > li > user-mini > a:not(.login) svg > * {
fill: white;
stroke: #000000B3;
}
.sidebar_mini #sidebar_main .menu_section > ul > li {
margin-bottom: 15px !important;
}
.stakeholderPage #sidebar_main .menu_section > ul > li.current_section .menu_title,.stakeholderPage #sidebar_main .menu_section > ul > li.current_section .menu_mini_title, .stakeholderPage #sidebar_main .menu_section > ul > li.current_section:hover .menu_title, .stakeholderPage #sidebar_main .menu_section > ul > li.current_section:hover .menu_mini_title, .stakeholderPage #sidebar_main .menu_section > ul > li.current_section > a > .menu_icon .material-icons,
.stakeholderPage #sidebar_main .menu_section > ul > li.current_section > a > .menu_icon svg *
{
color: var(--portal-main-color) !important;
font-weight: 700;
}
.dashboard #header_main .uk-logo img{
max-height: calc(var(--header-height) - 30px);
}
.stakeholderPage .uk-tab > li.uk-active > a,.stakeholderPage .uk-tab > li > a:focus, .stakeholderPage .uk-tab > li > a:hover {
border: 0 transparent !important;
color: var(--portal-main-color) !important
}
.stakeholderPage .customTabs >li a{
font-size: 14px;
text-transform: capitalize;
}
.stakeholderPage .subCategoriesTabs >li a{
font-size: 13px;
text-transform: capitalize;
}
.stakeholderPage .customTabs > li.uk-active a, .stakeholderPage .subCategoriesTabs > li.uk-active a{
font-weight:bold;
}
#style_switcher_toggle{
background-color: var(--portal-main-color) !important;
}
bottom a, bottom a:hover, bottom a:active {
color: black !important;
}
bottom a:not(.license), bottom a > :not(svg) {
text-decoration: underline;
}
#style_switcher .uk-offcanvas-bar{
width:450px !important;
}
.ng5-slider .ng5-slider-pointer, .ng5-slider .ng5-slider-selection {
background-color: var(--portal-main-color) !important;
}
.ng5-slider .ng5-slider-pointer.ng5-slider-active::after {
background-color:#55637d !important;
}
#style_switcher_toggle{
top:200px !important;
}
.uk-subnav.recentyears > :first-child {
padding-left: 0 !important;
}
.uk-subnav.uk-subnav-divider.recentyears {
padding-left: 0 !important;
}
#sidebar_main .menu_section > ul > li > a {
height:inherit !important;
}
.stakeholderPage #sidebar_main .menu_section > ul > li .menu_mini_title {
font-size: 9px !important;
line-height: 12px;
padding-bottom: 5px;
padding-left: 5px;
padding-right: 5px;
text-overflow: ellipsis;
overflow: hidden;
}
.stakeholderPage:not(.sidebar_mini) #sidebar_main .menu_section > ul > li .menu_mini_title, .stakeholderPage:not(.sidebar_mini) #sidebar_main .menu_section > ul:not(.searchLink) > li .menu_icon, .dashboard .sidebar_main_swipe:not(.stakeholderPage):not(.sidebar_mini) #sidebar_main .menu_section > ul > li .menu_mini_title{
display: none;
}
.stakeholderPage #sidebar_main .menu_section > ul > li {
transition: 0.70s;
-webkit-transition: 0.70s;
-moz-transition: 0.70s;
-ms-transition: 0.70s;
-o-transition: 0.70s;
display: block;
text-align: center;
margin-right: auto;
margin-left: auto;
}
.stakeholderPage #sidebar_main .menu_section > ul > li.current_section {
width: 150px;
height: 100%;
transition: 0.70s;
-webkit-transition: 0.70s;
-moz-transition: 0.70s;
-ms-transition: 0.70s;
-o-transition: 0.70s;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
transform: rotate(-90deg);
margin: 63px auto 63px auto;
}
.sidebar_mini #sidebar_main .menu_section > ul > li.current_section{
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
width: inherit;
height: inherit;
margin: 0px 0px;
}
.stakeholderPage:not(.sidebar_mini) #sidebar_main .menu_section > ul > li.current_section > a .menu_title {
display: inline !important;
}
.uk-subnav-pill.subCategoriesTabs > li.uk-active > a{
color: white;
border: 1px solid var(--portal-main-color);
background-color: var(--portal-main-color);
opacity: 1 ;
}
.uk-tab.customTabs::before {
border-bottom: none !important;
}
.stakeholderPage #style_switcher .uk-offcanvas-bar {
box-shadow: none;
border: 1px solid var(--monitor-portal-color);
}
.stakeholderPage #sidebar_main {
border-right: 1px solid var(--monitor-portal-color);
}
.stakeholderPage .uk-card.uk-disabled, .stakeholderPage .uk-card.semiFiltered{
opacity: 0.5;
}
.stakeholderPage .uk-card.semiFiltered > * > .highcharts-series-group{
opacity: 0.5;
}
.stakeholderPage:not(.sidebar_mini) #sidebar_main .menu_section > ul.searchLink {
margin-top: 80px !important;
}
.stakeholderPage #page_content.greyOut:before {
opacity: 1;
z-index: 1104;
}
.stakeholderPage #page_content > div, .stakeholderPage #page_content .uk-navbar-container{
background-color: #F9FBFC !important;
box-shadow: none;
}
.stakeholderPage #page_content_inner {
background-image: url(/assets/monitor-shapes-bg.svg);
background-size: cover;
background-repeat: no-repeat;
background-position: top;
background-attachment: fixed;
}
@media only screen and (max-width: 1219px) {
.sidebar_main_active #page_content:before {
opacity: 0 !important;
z-index: -1 !important;
}
}
.dashboard .selectedFilterLabel .uk-icon {
opacity: 0.8;
}
.uk-navbar-container:not(.uk-navbar-transparent){
background-color: #F9FBFC !important;
}

View File

@ -1,109 +0,0 @@
.monitor {
/* Import OpenAIRE theme*/
@import (multiple) "~src/assets/openaire-theme/less/_import";
@import (multiple) "~src/assets/common-assets/less/general";
@import (multiple) "~src/assets/common-assets/less/user";
@import (multiple) "~src/assets/common-assets/less/dashboard";
@import (multiple) "~src/assets/common-assets/less/indicators";
@import (multiple) "~src/assets/common-assets/less/landing";
@monitor-dashboard-background: #F3F3F3;
/** Global */
@global-primary-gradient: linear-gradient(110deg, @monitor-light-color 0%, @monitor-dark-color 100%);
/** Background */
@background-primary-background: @monitor-color;
@background-primary-background-gradient: none;
/** Button */
@button-primary-background: @monitor-color;
@button-secondary-border: @monitor-color;
@button-secondary-color: @monitor-color;
@button-secondary-hover-background: @global-secondary-background;
@button-secondary-hover-background-gradient: none;
@button-secondary-active-background: @global-secondary-background;
@button-secondary-active-background-gradient: none;
/** Label */
@label-secondary-color: @monitor-color;
@label-secondary-border: @monitor-color;
/** List */
@list-primary-color: @monitor-color;
/* Navbar */
@inverse-navbar-background: @monitor-color;
@inverse-navbar-background-image: url("banner.jpg");
/** Text */
@text-primary-color: @monitor-color;
@text-background-color: @monitor-color;
@inverse-text-primary-color: @monitor-color;
/* Slider */
@dotnav-item-background: fade(@monitor-color, 50%);
@dotnav-item-hover-background: @monitor-color;
@dotnav-item-onclick-background: @monitor-color;
@dotnav-item-active-background: @monitor-color;
/* General */
@general-search-form-background: @monitor-dashboard-background;
@general-tab-featured-tab: @monitor-color;
/* Landing */
@landing-portal-color: @monitor-color;
/* Dashboard */
@dashboard-page-content-background: @monitor-dashboard-background;
@dashboard-primary-background: @monitor-color;
@dashboard-menu-section-sublist-border: fade(@monitor-color, 30%);
& #filters_icon .start {
stop-color: @monitor-light-color;
}
& #filters_icon .end {
stop-color: @monitor-dark-color;
}
.private-data {
background-image: url("private-overlay.png");
background-repeat: no-repeat;
background-size: cover;
min-height: 100vh;
}
.preview {
position: fixed;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
background: @global-inverse-color;
border: 2px solid @background-primary-background;
border-radius: @global-border-radius;
box-shadow: @global-large-box-shadow;
padding: 20px 25px;
z-index: @global-z-index;
}
}
#print_toggle {
top: 320px !important;
}
#filters_switcher_toggle {
top: 400px !important;
}
@media (max-width: @breakpoint-small-max) {
#filters_switcher_toggle {
top: unset !important;
bottom: 10vh;
}
}
/* Quick fix for svgs with a class that makes their opacity: 0.5*/
svg .a {
opacity: 1 !important;
}

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 606 KiB

249
src/assets/new.css Normal file
View File

@ -0,0 +1,249 @@
:root {
--portal-main-color: #8DCA26;
--portal-main-contrast: white;
--portal-dark-color: #7c9144;
}
.stakeholderPage {
--primary-color: var(--theme-secondary-color);
--secondary-color: var(--theme-secondary-color);
--primary-color-rgb: var(--theme-secondary-color-rgb);
--secondary-color-rgb: var(--theme-secondary-color-rgb);
}
/*Stakeholder Specific*/
.publicationsSearchForm {
background-image: none;
}
.stakeholderPage #page_content {
background-image: url("~src/assets/monitor-shapes-bg.svg");
background-size: contain;
background-repeat: no-repeat;
background-position: bottom;
background-attachment: fixed;
min-height: calc(70vh - var(--header-height));
}
/*General*/
.stakeholderPage {
background: #F9FBFC !important;
}
#style_switcher .uk-offcanvas-bar {
box-sizing: border-box;
padding: 16px;
}
#style_switcher_toggle {
top: 320px !important;
position: fixed;
height: 36px;
/*background: #fff;*/
background-color: rgb(255, 255, 255);
border-radius: 4px 0 0 4px;
cursor: pointer;
padding: 0 8px;
box-shadow: -2px 2px 5px rgba(0, 0, 0, .26);
box-sizing: border-box;
/*z-index: 981;*/
}
#filters_switcher_toggle {
top: 320px !important;
position: fixed;
height: 36px;
background-color: var(--secondary-color);
border-radius: 4px 0 0 4px;
cursor: pointer;
padding: 0 2px;
box-shadow: -2px 2px 5px rgba(0, 0, 0, .26);
box-sizing: border-box;
/*z-index: 981;*/
right: 0;
}
/*Sidebar*/
/*Style*/
/*#sidebar_main .menu_section > ul li.uk-active > a {*/
/* font-size: var(--sidebar-font-size);*/
/* color: rgba(0,0,0,.7);*/
/*}*/
/*Sidebar Header logo */
#sidebar_main .sidebar_main_header .portal-logo {
background: url("~src/assets/common-assets/logo-large-monitor.png") no-repeat;
background-size: contain;
}
.sidebar_mini #sidebar_main .sidebar_main_header .portal-logo {
background: url("~src/assets/common-assets/logo-small-monitor.png") no-repeat;
background-size: contain;
}
/*Sidebar Rotation*/
.stakeholderPage #sidebar_main .menu_section > ul > li.uk-active {
width: 150px;
height: 100%;
transition: 0.70s;
-webkit-transition: 0.70s;
-moz-transition: 0.70s;
-ms-transition: 0.70s;
-o-transition: 0.70s;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
transform: rotate(-90deg);
margin: 63px auto 63px auto;
}
.stakeholderPage #sidebar_main .menu_section > ul > li {
transition: 0.70s;
-webkit-transition: 0.70s;
-moz-transition: 0.70s;
-ms-transition: 0.70s;
-o-transition: 0.70s;
/*display: block;*/
/*text-align: center;*/
/*margin-right: auto;*/
/*margin-left: auto;*/
}
.stakeholderPage.sidebar_mini #sidebar_main .menu_section > ul > li.uk-active {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
width: inherit;
height: inherit;
margin: 4px 0 0;
}
.stakeholderPage #sidebar_main #sidebar_content, .stakeholderPage #sidebar_switcher_toggle {
border-color: var(--monitor-portal-color);
}
/* Section Tools*/
.dashboard .section {
padding-top: 10px;
padding-bottom: 10px;
padding-right: 10px;
border: rgba(0, 0, 0, 0) solid 1px;
position: relative;
}
.dashboard .section .tools {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -100%);
width: 50px;
max-width: 50px;
background: var(--secondary-color);
color: var(--contrast-color);
-webkit-clip-path: polygon(20% 5%, 80% 5%, 100% 100%, 0% 100%);
clip-path: polygon(20% 5%, 80% 5%, 100% 100%, 0% 100%);
display: none;
padding-left: 10px;
}
.dashboard .section {
border: transparent solid 1px;
}
.dashboard .section:hover {
border: var(--secondary-color) solid 1px;
}
.dashboard .section:hover .tools {
display: block;
}
.dashboard .section:hover .tools a {
color: currentColor;
}
/* New section*/
.dashboard .new-section {
border: #707070 dashed 1px;
border-radius: 2px;
background-color: white;
min-height: 200px;
position: relative;
box-shadow: 0 2px 6px #00000038;
}
.dashboard .new-section .tools {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.dashboard .new-section .tools .md-btn .material-icons {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
margin: 0;
}
/*Search */
#searchFormPanel {
margin-top: 30px;
height: 250px;
}
.visibility {
border-right: 1px solid rgba(var(--secondary-color-rgb), 0.5);
border-bottom: 1px solid rgba(var(--secondary-color-rgb), 0.5);
padding: 10px 8px;
margin-right: 4px;
color: rgba(var(--text-color-rgb), 0.5);
}
.visibility.small {
padding: 3px 2px;
}
.more {
position: absolute;
transform: translate(-50%, -50%);
right: -30px;
top: 50%;
}
.descriptionIcon {
position: absolute;
bottom: 3px;
left: 3px;
}
.refresh-indicator {
background-color: rgba(0, 0, 0, 0.50);
border-radius: 4px;
position: absolute;
color: white;
}
.uk-modal-container .uk-modal-dialog {
width: 900px;
}
.stakeholderPage .uk-card.uk-disabled, .stakeholderPage .uk-card.semiFiltered{
opacity: 0.5;
}
.stakeholderPage .uk-card.semiFiltered > * > .highcharts-series-group{
opacity: 0.5;
}
.stakeholderPage .selectedFilterLabel {
background-color: #E6EEF2;
border-color: #E6EEF2;
}
.landing .uk-dropdown, new-search-page .uk-dropdown, search-all .uk-dropdown {
padding: 25px;
}

@ -1 +0,0 @@
Subproject commit e721fef20399f15c9dc9bee28b3d7e9b92db2021

View File

@ -6,50 +6,21 @@
#notifications-switcher,
.getDataButton,
.hideInfo,
.footer-light-background,
#filters_switcher_toggle,
#print_toggle,
.monitor_dashboard-menu,
#main-menu,
.uk-sticky-placeholder,
.uk-subnav-pill-alt,
.uk-text-background {
.footer-light-background {
display: none !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
padding: 0 !important;
margin: 0 !important;
position: relative !important;
height: 0 !important;
}
#page_content,
.uk-navbar-center {
padding-left: 0 !important;
padding-top: 0 !important;
}
#page_content .message, .uk-section {
padding: 0 !important;
}
#page_content_inner {
padding: 0 !important;
margin: 0 !important;
}
.uk-hidden {
display: unset !important;
}
.uk-card .uk-button-text {
display: none !important;
}
.printGap {
padding: 20px;
}
@page {
size: 210mm × 297mm;
margin: 20mm 20mm 20mm 20mm;
}
.chartTitle, iframe {
page-break-after: avoid;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

66
src/assets/search.scss Normal file
View File

@ -0,0 +1,66 @@
/* Search */
.dashboard {
@import "common-assets/library-css/library";
/* Animation*/
[class*=uk-animation-] {
animation-fill-mode: none !important;
}
/* Link */
.uk-link:hover {
color: var(--portal-main-color);
text-decoration: none;
}
/* Paging */
.uk-pagination > * > * {
display: block;
color: #666;
box-sizing: border-box;
min-width: 0;
padding: 0;
background: 0 0;
line-height: 16px;
text-align: center;
transition: .1s ease-in-out;
transition-property: color, background-color, border-color, box-shadow;
font-size: 16px;
letter-spacing: 0;
border: 8px solid transparent;
border-radius: 5px;
height: auto;
}
.uk-pagination > * > :focus, .uk-pagination > * > :hover {
color: #4687e6;
text-decoration: none;
background-color: transparent !important;
border-color: transparent;
}
/* Input */
.uk-checkbox:checked, .uk-checkbox:indeterminate, .uk-radio:checked {
background-color: var(--portal-main-color);
}
/* Alerts */
.uk-alert {
position: relative;
margin-bottom: 20px;
padding: 15px 29px 15px 15px;
background: #fff;
color: #666;
border: 1px solid #ededed;
}
.uk-alert.uk-grid {
display: flex;
}
.uk-alert-primary {
background: #fff;
color: #222080;
border-color: #222080;
}
}

View File

@ -0,0 +1,717 @@
{
"stakeholders": [
{
"id": "1",
"type": "funder",
"index_id": "EC",
"index_name": "European Comission",
"index_shortName": "EC",
"alias": "EC",
"isDefaultProfile": false,
"isActive": true,
"isPublic": true,
"creationDate": "08-10-2019",
"updateDate": "08-10-2019",
"managers": null,
"topics": [
{
"name": "OpenScience",
"alias": "openScience",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do...",
"isActive": true,
"isPublic": true,
"categories": [
{
"name": "Overview",
"alias": "overview",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do...",
"isOverview": true,
"isActive": true,
"isPublic": true,
"subCategories": [
{
"name": null,
"description": null,
"alias": null,
"isActive": true,
"isPublic": true,
"numbers": [
{
"id": "1",
"type": "number",
"name": "Total",
"description": "Total number of publications",
"tags": [
"publications"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/{index_shortName}",
"jsonPath": [
"statistics",
"publications"
]
}
]
},
{
"id": "2",
"type": "number",
"name": "Open",
"description": "Total number of open access publications",
"tags": [
"publication",
"open access"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/{index_shortName}",
"jsonPath": [
"statistics",
"open_access"
]
}
]
},
{
"id": "3",
"type": "number",
"name": "Embargo",
"description": "Total number of embargoed publications",
"tags": [
"publication",
"embargo"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/{index_shortName}",
"jsonPath": [
"statistics",
"embargo"
]
}
]
}
],
"charts": [
{
"id": "4",
"type": "charts",
"name": "Number of publications by project",
"description": "Number of publications by project",
"tags": [
"publication",
"project"
],
"width": "large",
"indicatorPaths": [
{
"type": "bar graph",
"url": "https://www.openaire.eu/stats/chart.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22column%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22EC%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
},
{
"type": "table",
"url": "https://www.openaire.eu/stats/gtable.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22pie%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22European%20Commission%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
}
]
}
]
},
{
"name": "Open",
"description": "open",
"alias": "open",
"isActive": true,
"isPublic": true,
"numbers": [
{
"id": "1",
"type": "number",
"name": "Total",
"description": "Total number of publications",
"tags": [
"publications"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/ec",
"jsonPath": [
"statistics",
"publications"
]
}
]
},
{
"id": "2",
"type": "number",
"name": "Open",
"description": "Total number of open access publications",
"tags": [
"publication",
"open access"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/ec",
"jsonPath": [
"statistics",
"open_access"
]
}
]
},
{
"id": "3",
"type": "number",
"name": "Embargo",
"description": "Total number of embargoed publications",
"tags": [
"publication",
"embargo"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/ec",
"jsonPath": [
"statistics",
"embargo"
]
}
]
}
],
"charts": [
{
"id": "4",
"type": "charts",
"name": "Number of publications by project",
"description": "Number of publications by project",
"tags": [
"publication",
"project"
],
"width": "large",
"indicatorPaths": [
{
"type": "bar graph",
"url": "https://www.openaire.eu/stats/chart.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22column%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22EC%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
},
{
"type": "table",
"url": "https://www.openaire.eu/stats/gtable.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22pie%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22European%20Commission%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
}
]
}
]
}
]
},
{
"name": "Publications",
"alias": "publications",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do...",
"isOverview": false,
"isActive": true,
"isPublic": true,
"subCategories": [
{
"name": null,
"description": null,
"alias": null,
"isActive": true,
"isPublic": true,
"numbers": [
{
"id": "1",
"type": "number",
"name": "Total",
"description": "Total number of publications",
"tags": [
"publications"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/ec",
"jsonPath": [
"statistics",
"publications"
]
}
]
},
{
"id": "2",
"type": "number",
"name": "Open",
"description": "Total number of open access publications",
"tags": [
"publication",
"open access"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/ec",
"jsonPath": [
"statistics",
"open_access"
]
}
]
},
{
"id": "3",
"type": "number",
"name": "Embargo",
"description": "Total number of embargoed publications",
"tags": [
"publication",
"embargo"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/ec",
"jsonPath": [
"statistics",
"embargo"
]
}
]
}
],
"charts": [
{
"id": "4",
"type": "charts",
"name": "Number of publications by project",
"description": "Number of publications by project",
"tags": [
"publication",
"project"
],
"width": "large",
"indicatorPaths": [
{
"type": "bar graph",
"url": "https://www.openaire.eu/stats/chart.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22column%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22EC%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
},
{
"type": "table",
"url": "https://www.openaire.eu/stats/gtable.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22pie%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22European%20Commission%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
}
]
}
]
}
]
},
{
"name": "Research data",
"alias": "researchData",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do...",
"isOverview": false,
"isActive": true,
"isPublic": true,
"subCategories": [
{
"name": null,
"description": null,
"alias": null,
"isActive": true,
"isPublic": true,
"numbers": [
],
"charts": [
]
}
]
},
{
"name": "Software",
"alias": "software",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do...",
"isOverview": false,
"isActive": true,
"isPublic": true,
"subCategories": [
{
"name": null,
"description": null,
"alias": null,
"isActive": true,
"isPublic": true,
"numbers": [
],
"charts": [
]
}
]
},
{
"name": "Other",
"alias": "other",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do...",
"isOverview": false,
"isActive": true,
"isPublic": true,
"subCategories": [
{
"name": null,
"description": null,
"alias": null,
"isActive": true,
"isPublic": true,
"numbers": [
],
"charts": [
]
}
]
}
]
},
{
"name": "Collaboration",
"alias": "collaboration",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do...",
"isActive": true,
"isPublic": true,
"categories": [
{
"name": "Overview",
"alias": "overview",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do...",
"isOverview": true,
"isActive": true,
"isPublic": true,
"subCategories": [
{
"name": null,
"description": null,
"alias": null,
"isActive": true,
"isPublic": true,
"numbers": [
{
"id": "1",
"type": "number",
"name": "Total",
"description": "Total number of publications",
"tags": [
"publications"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/{index_shortName}",
"jsonPath": [
"statistics",
"publications"
]
}
]
},
{
"id": "2",
"type": "number",
"name": "Open",
"description": "Total number of open access publications",
"tags": [
"publication",
"open access"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/{index_shortName}",
"jsonPath": [
"statistics",
"open_access"
]
}
]
},
{
"id": "3",
"type": "number",
"name": "Embargo",
"description": "Total number of embargoed publications",
"tags": [
"publication",
"embargo"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/{index_shortName}",
"jsonPath": [
"statistics",
"embargo"
]
}
]
}
],
"charts": [
{
"id": "4",
"type": "charts",
"name": "Number of publications by project",
"description": "Number of publications by project",
"tags": [
"publication",
"project"
],
"width": "large",
"indicatorPaths": [
{
"type": "bar graph",
"url": "https://www.openaire.eu/stats/chart.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22column%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22EC%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
},
{
"type": "table",
"url": "https://www.openaire.eu/stats/gtable.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22pie%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22European%20Commission%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
}
]
}
]
}
]
}
]
},
{
"name": "Impact/Correlation",
"alias": "impact-correlation",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do...",
"isActive": true,
"isPublic": true,
"categories": [
{
"name": "Overview",
"alias": "overview",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do...",
"isOverview": true,
"isActive": true,
"isPublic": true,
"subCategories": [
{
"name": null,
"description": null,
"alias": null,
"isActive": true,
"isPublic": true,
"numbers": [
{
"id": "1",
"type": "number",
"name": "Total",
"description": "Total number of publications",
"tags": [
"publications"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/{index_shortName}",
"jsonPath": [
"statistics",
"publications"
]
}
]
},
{
"id": "2",
"type": "number",
"name": "Open",
"description": "Total number of open access publications",
"tags": [
"publication",
"open access"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/{index_shortName}",
"jsonPath": [
"statistics",
"open_access"
]
}
]
},
{
"id": "3",
"type": "number",
"name": "Embargo",
"description": "Total number of embargoed publications",
"tags": [
"publication",
"embargo"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/{index_shortName}",
"jsonPath": [
"statistics",
"embargo"
]
}
]
}
],
"charts": [
{
"id": "4",
"type": "charts",
"name": "Number of publications by project",
"description": "Number of publications by project",
"tags": [
"publication",
"project"
],
"width": "large",
"indicatorPaths": [
{
"type": "bar graph",
"url": "https://www.openaire.eu/stats/chart.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22column%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22EC%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
},
{
"type": "table",
"url": "https://www.openaire.eu/stats/gtable.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22pie%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22European%20Commission%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
}
]
}
]
}
]
}
]
}
]
}
],
"indicators": [
{
"id": "1",
"type": "number",
"name": "Total",
"description": "Total number of publications",
"tags": [
"publications"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/ec",
"jsonPath": [
"statistics",
"publications"
]
}
]
},
{
"id": "2",
"type": "number",
"name": "Open",
"description": "Total number of open access publications",
"tags": [
"publication",
"open access"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/ec",
"jsonPath": [
"statistics",
"open_access"
]
}
]
},
{
"id": "3",
"type": "number",
"name": "Embargo",
"description": "Total number of embargoed publications",
"tags": [
"publication",
"embargo"
],
"width": "small",
"indicatorPaths": [
{
"type": "",
"url": "/funders/ec",
"jsonPath": [
"statistics",
"embargo"
]
}
]
},
{
"id": "4",
"type": "charts",
"name": "Number of publications by project",
"description": "Number of publications by project",
"tags": [
"publication",
"project"
],
"width": "large",
"indicatorPaths": [
{
"type": "bar graph",
"url": "https://www.openaire.eu/stats/chart.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22column%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22EC%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
},
{
"type": "table",
"url": "https://www.openaire.eu/stats/gtable.php?com=query&data={%22table%22:%22result%22,%22fields%22:[{%22fld%22:%22number%22,%22agg%22:%22count%22,%22type%22:%22pie%22,%22yaxis%22:1,%22c%22:false}],%22xaxis%22:{%22name%22:%22result_projects-project-title%22,%22agg%22:%22avg%22},%22group%22:%22%22,%22color%22:%22%22,%22type%22:%22chart%22,%22size%22:%2230%22,%22sort%22:%22count-number%22,%22yaxisheaders%22:[%22%22],%22fieldsheaders%22:[%22publications%22],%22in%22:[],%22filters%22:[{%22name%22:%22result_projects-project-funder%22,%22values%22:[%22European%20Commission%22],%22to%22:%22-1%22},{%22name%22:%22type%22,%22values%22:[%22publication%22],%22to%22:%22-1%22}],%22having%22:[],%22xStyle%22:{%22r%22:-90,%22s%22:%22-%22,%22l%22:%22-%22,%22ft%22:10,%22wt%22:%22-%22},%22title%22:%22European%20Commission%20Publications%20by%20project%20(top%2030)%22,%22subtitle%22:%22%22,%22xaxistitle%22:%22project%22,%22order%22:%22d%22}",
"jsonPath": []
}
]
}
]
}

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 118 118" style="enable-background:new 0 0 118 118;" xml:space="preserve">
<style type="text/css">
.st0{clip-path:url(#SVGID_2_);}
.st1{fill:#FFE250;}
.st2{fill:none;stroke:#EFC82A;stroke-width:3;stroke-dasharray:8;}
.st3{enable-background:new ;}
</style>
<g>
<defs>
<rect id="SVGID_1_" y="0" width="118" height="118"/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<g class="st0">
<g transform="translate(27 32)">
<g transform="translate(-161.906 166.693) rotate(-45)">
<rect x="0" y="0" transform="matrix(-1 2.535182e-06 -2.535182e-06 -1 523.3979 37.2033)" class="st1" width="523.4" height="37.2"/>
<rect x="1.5" y="1.5" transform="matrix(-1 2.535182e-06 -2.535182e-06 -1 523.3979 37.2033)" class="st2" width="520.4" height="34.2"/>
</g>
<g class="st3">
<path d="M3.9,21.3l2.2-2.2c1-1,1.9-1.6,2.6-1.8c0.7-0.2,1.4,0.1,2,0.7c0.4,0.4,0.7,0.9,0.7,1.3s0,0.9-0.3,1.3l0,0
c0.5-0.3,1.1-0.5,1.5-0.4c0.5,0.1,0.9,0.3,1.4,0.8c0.6,0.6,0.9,1.4,0.8,2.2c-0.1,0.8-0.6,1.6-1.4,2.4L11,28.4L3.9,21.3z
M8.2,22.6l0.9-0.9c0.4-0.4,0.6-0.8,0.7-1.1s-0.1-0.6-0.3-0.9c-0.3-0.3-0.6-0.4-0.9-0.3c-0.3,0.1-0.7,0.3-1.1,0.8l-0.8,0.8
L8.2,22.6z M9.4,23.8l1.8,1.8l1-1c0.4-0.4,0.6-0.8,0.7-1.2c0-0.4-0.1-0.7-0.4-1c-0.6-0.6-1.3-0.5-2.1,0.4L9.4,23.8z"/>
<path d="M21.7,17.7l-4.1,4.1l-7.1-7.1l4.1-4.1l1.2,1.2l-2.6,2.6l1.6,1.6l2.4-2.4l1.2,1.2l-2.4,2.4l1.8,1.8l2.6-2.6L21.7,17.7z"
/>
<path d="M25.9,13.5L24.4,15l-5.8-5.8l-1.9,1.9l-1.2-1.2l5.3-5.3L22,5.7l-1.9,1.9L25.9,13.5z"/>
<path d="M33.3,6.1L31.1,5l-2.6,2.6l1.2,2.2L28,11.4l-4.6-9.6l1.8-1.8l9.6,4.6L33.3,6.1z M29.4,4.1c-2-1.1-3.1-1.6-3.4-1.8
c-0.3-0.1-0.5-0.3-0.6-0.3c0.3,0.5,1,1.8,2.1,4L29.4,4.1z"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,25 @@
/* IE lte9 fixes */
/* main sidebar */
#sidebar_main {
-ms-transform: translateX(-240px);
}
@media only screen and (max-width: 767px) {
#sidebar_main {
-ms-transform: translateY(-280px);
}
}
.sidebar_main_active #sidebar_main,
.sidebar_main_open #sidebar_main {
-ms-transform: translateY(0);
}
/* secondary sidebar */
#sidebar_secondary {
-ms-transform: translateX(288px);
}
.sidebar_secondary_active #sidebar_secondary {
-ms-transform: translateX(0);
}

14957
src/assets/theme-assets/css/main.css Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1
src/assets/theme-assets/css/main.min.css vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,159 @@
/* style switcher */
#style_switcher {
position: fixed;
right: 0;
top: 140px;
background: #fff;
width: 240px;
z-index: 1094;
-webkit-box-sizing: border-box;
box-sizing: border-box;
padding: 16px;
margin-right: -246px;
-webkit-transition: margin 280ms cubic-bezier(0.4, 0, 0.2, 1);
transition: margin 280ms cubic-bezier(0.4, 0, 0.2, 1);
-webkit-box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.26);
box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.26);
}
#style_switcher.switcher_active {
margin-right: 0;
}
#style_switcher .switcher_app_themes {
margin: 0;
padding: 0;
list-style: none;
overflow: hidden;
}
#style_switcher .switcher_app_themes > li {
padding: 0;
margin: 0;
list-style: none;
}
#style_switcher .switcher_app_themes li {
float: left;
cursor: pointer;
width: 36px;
margin: 0 16px 16px 0;
opacity: 0.5;
-webkit-transition: opacity 280ms cubic-bezier(0.4, 0, 0.2, 1);
transition: opacity 280ms cubic-bezier(0.4, 0, 0.2, 1);
}
#style_switcher .switcher_app_themes li span {
display: block;
padding: 0 4px;
height: 24px;
line-height: 24px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 50%;
float: left;
}
#style_switcher .switcher_app_themes li.active_theme {
opacity: 1;
position: relative;
}
#style_switcher .switcher_app_themes li.active_theme:after {
position: absolute;
top: 0;
left: 50%;
content: '\e5ca';
font-family: "Material Icons";
font-size: 18px;
display: block;
color: #fff;
margin-left: -8px;
}
#style_switcher .switcher_app_themes li.app_style_default .app_color_main {
background: #2196f3;
}
#style_switcher .switcher_app_themes li.app_style_default .app_color_accent {
background: #7cb342;
}
#style_switcher .switcher_app_themes li.switcher_theme_a .app_color_main {
background: #3f51b5;
}
#style_switcher .switcher_app_themes li.switcher_theme_a .app_color_accent {
background: #ff4081;
}
#style_switcher .switcher_app_themes li.switcher_theme_b .app_color_main {
background: #673ab7;
}
#style_switcher .switcher_app_themes li.switcher_theme_b .app_color_accent {
background: #00bcd4;
}
#style_switcher .switcher_app_themes li.switcher_theme_c .app_color_main {
background: #5d4037;
}
#style_switcher .switcher_app_themes li.switcher_theme_c .app_color_accent {
background: #1e88e5;
}
#style_switcher .switcher_app_themes li.switcher_theme_d .app_color_main {
background: #00acc1;
}
#style_switcher .switcher_app_themes li.switcher_theme_d .app_color_accent {
background: #673ab7;
}
#style_switcher .switcher_app_themes li.switcher_theme_e .app_color_main {
background: #607d8b;
}
#style_switcher .switcher_app_themes li.switcher_theme_e .app_color_accent {
background: #e53935;
}
#style_switcher .switcher_app_themes li.switcher_theme_f .app_color_main {
background: #424242;
}
#style_switcher .switcher_app_themes li.switcher_theme_f .app_color_accent {
background: #7cb342;
}
#style_switcher .switcher_app_themes li.switcher_theme_g .app_color_main {
background: #8e24aa;
}
#style_switcher .switcher_app_themes li.switcher_theme_g .app_color_accent {
background: #4caf50;
}
#style_switcher .switcher_app_themes li.switcher_theme_h .app_color_main {
background: #d32f2f;
}
#style_switcher .switcher_app_themes li.switcher_theme_h .app_color_accent {
background: #0277bd;
}
#style_switcher .switcher_app_themes li.switcher_theme_i .app_color_main {
background: #fbc02d;
}
#style_switcher .switcher_app_themes li.switcher_theme_i .app_color_accent {
background: #00acc1;
}
#style_switcher .switcher_app_themes li.switcher_theme_dark .app_color_main {
background: #546e7a;
}
#style_switcher .switcher_app_themes li.switcher_theme_dark .app_color_accent {
background: #009688;
}
#style_switcher_toggle {
position: absolute;
top: 8px;
left: -44px;
width: 44px;
height: 36px;
background: #fff;
border-radius: 4px 0 0 4px;
cursor: pointer;
padding: 0 8px;
-webkit-box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.26);
box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.26);
-webkit-box-sizing: border-box;
box-sizing: border-box;
z-index: 1096;
}
#style_switcher_toggle .material-icons {
font-size: 24px;
line-height: 36px;
color: #212121;
}
.app_theme_dark #style_switcher,
.app_theme_dark #style_switcher_toggle {
background: #424242;
}
.app_theme_dark #style_switcher_toggle .material-icons {
color: #cbcbcb;
}

View File

@ -0,0 +1 @@
#style_switcher{position:fixed;right:0;top:140px;background:#fff;width:240px;z-index:1094;-webkit-box-sizing:border-box;box-sizing:border-box;padding:16px;margin-right:-246px;-webkit-transition:margin 280ms cubic-bezier(.4,0,.2,1);transition:margin 280ms cubic-bezier(.4,0,.2,1);-webkit-box-shadow:-2px 2px 5px rgba(0,0,0,.26);box-shadow:-2px 2px 5px rgba(0,0,0,.26)}#style_switcher.switcher_active{margin-right:0}#style_switcher .switcher_app_themes{margin:0;padding:0;list-style:none;overflow:hidden}#style_switcher .switcher_app_themes>li{padding:0;margin:0;list-style:none}#style_switcher .switcher_app_themes li{float:left;cursor:pointer;width:36px;margin:0 16px 16px 0;opacity:.5;-webkit-transition:opacity 280ms cubic-bezier(.4,0,.2,1);transition:opacity 280ms cubic-bezier(.4,0,.2,1)}#style_switcher .switcher_app_themes li span{display:block;padding:0 4px;height:24px;line-height:24px;-webkit-box-sizing:border-box;box-sizing:border-box;width:50%;float:left}#style_switcher .switcher_app_themes li.active_theme{opacity:1;position:relative}#style_switcher .switcher_app_themes li.active_theme:after{position:absolute;top:0;left:50%;content:'\e5ca';font-family:"Material Icons";font-size:18px;display:block;color:#fff;margin-left:-8px}#style_switcher .switcher_app_themes li.app_style_default .app_color_main{background:#2196f3}#style_switcher .switcher_app_themes li.app_style_default .app_color_accent{background:#7cb342}#style_switcher .switcher_app_themes li.switcher_theme_a .app_color_main{background:#3f51b5}#style_switcher .switcher_app_themes li.switcher_theme_a .app_color_accent{background:#ff4081}#style_switcher .switcher_app_themes li.switcher_theme_b .app_color_main{background:#673ab7}#style_switcher .switcher_app_themes li.switcher_theme_b .app_color_accent{background:#00bcd4}#style_switcher .switcher_app_themes li.switcher_theme_c .app_color_main{background:#5d4037}#style_switcher .switcher_app_themes li.switcher_theme_c .app_color_accent{background:#1e88e5}#style_switcher .switcher_app_themes li.switcher_theme_d .app_color_main{background:#00acc1}#style_switcher .switcher_app_themes li.switcher_theme_d .app_color_accent{background:#673ab7}#style_switcher .switcher_app_themes li.switcher_theme_e .app_color_main{background:#607d8b}#style_switcher .switcher_app_themes li.switcher_theme_e .app_color_accent{background:#e53935}#style_switcher .switcher_app_themes li.switcher_theme_f .app_color_main{background:#424242}#style_switcher .switcher_app_themes li.switcher_theme_f .app_color_accent{background:#7cb342}#style_switcher .switcher_app_themes li.switcher_theme_g .app_color_main{background:#8e24aa}#style_switcher .switcher_app_themes li.switcher_theme_g .app_color_accent{background:#4caf50}#style_switcher .switcher_app_themes li.switcher_theme_h .app_color_main{background:#d32f2f}#style_switcher .switcher_app_themes li.switcher_theme_h .app_color_accent{background:#0277bd}#style_switcher .switcher_app_themes li.switcher_theme_i .app_color_main{background:#fbc02d}#style_switcher .switcher_app_themes li.switcher_theme_i .app_color_accent{background:#00acc1}#style_switcher .switcher_app_themes li.switcher_theme_dark .app_color_main{background:#546e7a}#style_switcher .switcher_app_themes li.switcher_theme_dark .app_color_accent{background:#009688}#style_switcher_toggle{position:absolute;top:8px;left:-44px;width:44px;height:36px;background:#fff;border-radius:4px 0 0 4px;cursor:pointer;padding:0 8px;-webkit-box-shadow:-2px 2px 5px rgba(0,0,0,.26);box-shadow:-2px 2px 5px rgba(0,0,0,.26);-webkit-box-sizing:border-box;box-sizing:border-box;z-index:1096}#style_switcher_toggle .material-icons{font-size:24px;line-height:36px;color:#212121}.app_theme_dark #style_switcher,.app_theme_dark #style_switcher_toggle{background:#424242}.app_theme_dark #style_switcher_toggle .material-icons{color:#cbcbcb}

View File

@ -0,0 +1,194 @@
.app_theme_a .uk-alert {
background: #3f51b5;
}
.app_theme_a .md-btn-primary,
.app_theme_a .md-btn-primary:hover,
.app_theme_a .md-btn-primary:focus,
.app_theme_a .md-btn-primary:active {
background: #3f51b5;
color: #fff;
}
.app_theme_a .md-btn-flat-primary,
.app_theme_a .md-btn-flat-primary:hover,
.app_theme_a .md-btn-flat-primary:focus,
.app_theme_a .md-btn-flat-primary:active {
color: #303f9f;
}
.app_theme_a .md-btn-flat-primary:hover,
.app_theme_a .md-btn-flat-primary:focus,
.app_theme_a .md-btn-flat-primary:active {
background: #d1d6ef;
}
.app_theme_a .uk-badge-primary {
background: #3f51b5;
}
.app_theme_a .md-card-list-wrapper .md-card-list > ul > li.item-shown.md-card-list-item-selected:before {
background: #e8eaf6;
}
.app_theme_a .md-card-list-wrapper .md-card-list .md-card-list-item-selected {
background: #e8eaf6;
}
.app_theme_a .md-card-list-wrapper .md-card-list .md-card-list-item-selected.item-shown {
background: #fff;
}
.app_theme_a .md-card-list-wrapper .md-card-list .md-card-list-item-selected.item-shown:before {
background: #e8eaf6;
}
.app_theme_a .md-fab.md-fab-accent {
background: #ff4081;
}
.app_theme_a .md-list .uk-nestable-list > li.md-list-item-active,
.app_theme_a .md-list > li.md-list-item-active {
color: #ff4081;
}
.app_theme_a .md-list-addon > li.md-list-item-active .md-list-addon-element,
.app_theme_a .md-list-addon > li.md-list-item-active .md-list-addon-element .material-icons {
color: #ff4081;
}
.app_theme_a .uk-pagination > li > a:hover {
background: #ffd9e6;
}
.app_theme_a .uk-pagination > li.uk-active > a,
.app_theme_a .uk-pagination > li.uk-active > span {
background: #ff4081;
color: #fff;
}
.app_theme_a .uk-subnav-pill > .uk-active > * {
background: #ff4081;
}
.app_theme_a .uk-tab > li > a:hover,
.app_theme_a .uk-tab > li > a:focus {
border-bottom-color: #abb4e2;
}
.app_theme_a .uk-tab > li.uk-active > a {
border-bottom-color: #3f51b5;
}
.app_theme_a .uk-tab-bottom li > a:hover,
.app_theme_a .uk-tab-bottom li > a:focus {
border-top-color: #abb4e2;
}
.app_theme_a .uk-tab-bottom li.uk-active > a {
border-top-color: #3f51b5;
}
.app_theme_a .uk-tab-left li > a:hover,
.app_theme_a .uk-tab-left li > a:focus {
border-right-color: #abb4e2;
}
.app_theme_a .uk-tab-left li.uk-active > a {
border-right-color: #3f51b5;
}
.app_theme_a .uk-tab-right li > a:hover,
.app_theme_a .uk-tab-right li > a:focus {
border-left-color: #abb4e2;
}
.app_theme_a .uk-tab-right li.uk-active > a {
border-left-color: #3f51b5;
}
.app_theme_a .uk-tab-double-header li a:hover,
.app_theme_a .uk-tab-double-header li a:focus {
border-bottom-color: #606fc7;
}
.app_theme_a .uk-tab-double-header li.uk-active > a {
border-bottom-color: #ff4081;
}
.app_theme_a #header_main {
background: #3f51b5;
}
.app_theme_a .header_double_height:after {
background: #3f51b5;
}
.app_theme_a #top_bar .top_bar_nav > li > a:hover {
-webkit-box-shadow: inset 0 -3px 0 #3f51b5;
box-shadow: inset 0 -3px 0 #3f51b5;
}
.app_theme_a #top_bar .top_bar_nav > li.uk-active a {
-webkit-box-shadow: inset 0 -3px 0 #3f51b5;
box-shadow: inset 0 -3px 0 #3f51b5;
}
.app_theme_a .user_heading {
background: #303f9f;
}
.app_theme_a #sidebar_main .menu_section > ul > li ul li.act_item a {
color: #ff4081;
}
.app_theme_a #sidebar_main .menu_section > ul > li.current_section > a > .menu_icon .material-icons {
color: #ff4081;
}
.app_theme_a #sidebar_main .menu_section > ul > li.current_section > a .menu_title {
color: #ff4081;
}
.app_theme_a .sidebar_mini #sidebar_main .menu_section > ul > li > a > .menu_title {
background: #ff4081;
color: #fff;
}
.app_theme_a .sidebar_mini #sidebar_main .menu_section > ul > li:hover.sidebar_submenu {
background: #ff4081;
}
.app_theme_a .sidebar_mini #sidebar_main .menu_section > ul > li:hover.sidebar_submenu > a .menu_icon .material-icons {
color: #fff;
}
.app_theme_a .sidebar_mini #sidebar_main .menu_section > ul > li:hover.sidebar_submenu ul {
border-left-color: #ff4081;
}
.app_theme_a .sidebar_mini #sidebar_main .menu_section > ul > li.current_section > a > .menu_icon .material-icons {
color: #ff4081;
}
.app_theme_a .clndr .clndr_days .clndr_days_grid .day.today > span {
background: #ff4081;
}
.app_theme_a .DTTT_print_info h6 {
color: #ff4081;
}
.app_theme_a .fc-unthemed .fc-button.fc-state-active:after {
color: #ff4081;
}
.app_theme_a .fc-unthemed .fc-highlight {
-webkit-box-shadow: inset 0 0 0 2px #3f51b5, inset 0 -1px 0 2px #3f51b5;
box-shadow: inset 0 0 0 2px #3f51b5, inset 0 -1px 0 2px #3f51b5;
}
.app_theme_a .tablesorter-altair tbody > tr.row_highlighted > td {
background: #e8eaf6;
}
.app_theme_a .tablesorter-altair .headerSortUp,
.app_theme_a .tablesorter-altair .tablesorter-headerSortUp,
.app_theme_a .tablesorter-altair .tablesorter-headerAsc,
.app_theme_a .tablesorter-altair .headerSortDown,
.app_theme_a .tablesorter-altair .tablesorter-headerSortDown,
.app_theme_a .tablesorter-altair .tablesorter-headerDesc {
color: #ff4081;
}
.app_theme_a .wizard > .steps {
background: #3f51b5;
}
.app_theme_a .wizard > .steps > ul > li.current a,
.app_theme_a .wizard > .steps > ul > li.current a:hover,
.app_theme_a .wizard > .steps > ul > li.current a:active {
background: #606fc7;
}
.app_theme_a .wizard > .steps > ul > li.done a,
.app_theme_a .wizard > .steps > ul > li.done a:hover,
.app_theme_a .wizard > .steps > ul > li.done a:active {
background: #303f9f;
}
.app_theme_a .md-card-primary {
border-left-color: #3f51b5;
}
.app_theme_a .waves-effect.md-btn-flat-primary {
background: none;
}
.app_theme_a .waves-effect.md-btn-flat-primary .waves-ripple {
background: rgba(63, 81, 181, 0.4);
}
.app_theme_a .search_list_link {
color: #ff4081;
}
.app_theme_a .chatbox.cb_active .chatbox_header {
background: #303f9f;
}
.app_theme_a .chatbox_content .chatbox_message.own .chatbox_message_content li > span {
background: #3f51b5;
}
.app_theme_a .uk-table tr.row_checked td,
.app_theme_a .uk-table-hover tbody tr:hover {
background: #e8eaf6;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,194 @@
.app_theme_b .uk-alert {
background: #673ab7;
}
.app_theme_b .md-btn-primary,
.app_theme_b .md-btn-primary:hover,
.app_theme_b .md-btn-primary:focus,
.app_theme_b .md-btn-primary:active {
background: #673ab7;
color: #fff;
}
.app_theme_b .md-btn-flat-primary,
.app_theme_b .md-btn-flat-primary:hover,
.app_theme_b .md-btn-flat-primary:focus,
.app_theme_b .md-btn-flat-primary:active {
color: #512da8;
}
.app_theme_b .md-btn-flat-primary:hover,
.app_theme_b .md-btn-flat-primary:focus,
.app_theme_b .md-btn-flat-primary:active {
background: #daceef;
}
.app_theme_b .uk-badge-primary {
background: #673ab7;
}
.app_theme_b .md-card-list-wrapper .md-card-list > ul > li.item-shown.md-card-list-item-selected:before {
background: #ede7f6;
}
.app_theme_b .md-card-list-wrapper .md-card-list .md-card-list-item-selected {
background: #ede7f6;
}
.app_theme_b .md-card-list-wrapper .md-card-list .md-card-list-item-selected.item-shown {
background: #fff;
}
.app_theme_b .md-card-list-wrapper .md-card-list .md-card-list-item-selected.item-shown:before {
background: #ede7f6;
}
.app_theme_b .md-fab.md-fab-accent {
background: #00bcd4;
}
.app_theme_b .md-list .uk-nestable-list > li.md-list-item-active,
.app_theme_b .md-list > li.md-list-item-active {
color: #00bcd4;
}
.app_theme_b .md-list-addon > li.md-list-item-active .md-list-addon-element,
.app_theme_b .md-list-addon > li.md-list-item-active .md-list-addon-element .material-icons {
color: #00bcd4;
}
.app_theme_b .uk-pagination > li > a:hover {
background: #d4faff;
}
.app_theme_b .uk-pagination > li.uk-active > a,
.app_theme_b .uk-pagination > li.uk-active > span {
background: #00bcd4;
color: #fff;
}
.app_theme_b .uk-subnav-pill > .uk-active > * {
background: #00bcd4;
}
.app_theme_b .uk-tab > li > a:hover,
.app_theme_b .uk-tab > li > a:focus {
border-bottom-color: #bda7e3;
}
.app_theme_b .uk-tab > li.uk-active > a {
border-bottom-color: #673ab7;
}
.app_theme_b .uk-tab-bottom li > a:hover,
.app_theme_b .uk-tab-bottom li > a:focus {
border-top-color: #bda7e3;
}
.app_theme_b .uk-tab-bottom li.uk-active > a {
border-top-color: #673ab7;
}
.app_theme_b .uk-tab-left li > a:hover,
.app_theme_b .uk-tab-left li > a:focus {
border-right-color: #bda7e3;
}
.app_theme_b .uk-tab-left li.uk-active > a {
border-right-color: #673ab7;
}
.app_theme_b .uk-tab-right li > a:hover,
.app_theme_b .uk-tab-right li > a:focus {
border-left-color: #bda7e3;
}
.app_theme_b .uk-tab-right li.uk-active > a {
border-left-color: #673ab7;
}
.app_theme_b .uk-tab-double-header li a:hover,
.app_theme_b .uk-tab-double-header li a:focus {
border-bottom-color: #8259cb;
}
.app_theme_b .uk-tab-double-header li.uk-active > a {
border-bottom-color: #00bcd4;
}
.app_theme_b #header_main {
background: #673ab7;
}
.app_theme_b .header_double_height:after {
background: #673ab7;
}
.app_theme_b #top_bar .top_bar_nav > li > a:hover {
-webkit-box-shadow: inset 0 -3px 0 #673ab7;
box-shadow: inset 0 -3px 0 #673ab7;
}
.app_theme_b #top_bar .top_bar_nav > li.uk-active a {
-webkit-box-shadow: inset 0 -3px 0 #673ab7;
box-shadow: inset 0 -3px 0 #673ab7;
}
.app_theme_b .user_heading {
background: #512da8;
}
.app_theme_b #sidebar_main .menu_section > ul > li ul li.act_item a {
color: #00bcd4;
}
.app_theme_b #sidebar_main .menu_section > ul > li.current_section > a > .menu_icon .material-icons {
color: #00bcd4;
}
.app_theme_b #sidebar_main .menu_section > ul > li.current_section > a .menu_title {
color: #00bcd4;
}
.app_theme_b .sidebar_mini #sidebar_main .menu_section > ul > li > a > .menu_title {
background: #00bcd4;
color: #fff;
}
.app_theme_b .sidebar_mini #sidebar_main .menu_section > ul > li:hover.sidebar_submenu {
background: #00bcd4;
}
.app_theme_b .sidebar_mini #sidebar_main .menu_section > ul > li:hover.sidebar_submenu > a .menu_icon .material-icons {
color: #fff;
}
.app_theme_b .sidebar_mini #sidebar_main .menu_section > ul > li:hover.sidebar_submenu ul {
border-left-color: #00bcd4;
}
.app_theme_b .sidebar_mini #sidebar_main .menu_section > ul > li.current_section > a > .menu_icon .material-icons {
color: #00bcd4;
}
.app_theme_b .clndr .clndr_days .clndr_days_grid .day.today > span {
background: #00bcd4;
}
.app_theme_b .DTTT_print_info h6 {
color: #00bcd4;
}
.app_theme_b .fc-unthemed .fc-button.fc-state-active:after {
color: #00bcd4;
}
.app_theme_b .fc-unthemed .fc-highlight {
-webkit-box-shadow: inset 0 0 0 2px #673ab7, inset 0 -1px 0 2px #673ab7;
box-shadow: inset 0 0 0 2px #673ab7, inset 0 -1px 0 2px #673ab7;
}
.app_theme_b .tablesorter-altair tbody > tr.row_highlighted > td {
background: #ede7f6;
}
.app_theme_b .tablesorter-altair .headerSortUp,
.app_theme_b .tablesorter-altair .tablesorter-headerSortUp,
.app_theme_b .tablesorter-altair .tablesorter-headerAsc,
.app_theme_b .tablesorter-altair .headerSortDown,
.app_theme_b .tablesorter-altair .tablesorter-headerSortDown,
.app_theme_b .tablesorter-altair .tablesorter-headerDesc {
color: #00bcd4;
}
.app_theme_b .wizard > .steps {
background: #673ab7;
}
.app_theme_b .wizard > .steps > ul > li.current a,
.app_theme_b .wizard > .steps > ul > li.current a:hover,
.app_theme_b .wizard > .steps > ul > li.current a:active {
background: #8259cb;
}
.app_theme_b .wizard > .steps > ul > li.done a,
.app_theme_b .wizard > .steps > ul > li.done a:hover,
.app_theme_b .wizard > .steps > ul > li.done a:active {
background: #512da8;
}
.app_theme_b .md-card-primary {
border-left-color: #673ab7;
}
.app_theme_b .waves-effect.md-btn-flat-primary {
background: none;
}
.app_theme_b .waves-effect.md-btn-flat-primary .waves-ripple {
background: rgba(103, 58, 183, 0.4);
}
.app_theme_b .search_list_link {
color: #00bcd4;
}
.app_theme_b .chatbox.cb_active .chatbox_header {
background: #512da8;
}
.app_theme_b .chatbox_content .chatbox_message.own .chatbox_message_content li > span {
background: #673ab7;
}
.app_theme_b .uk-table tr.row_checked td,
.app_theme_b .uk-table-hover tbody tr:hover {
background: #ede7f6;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,194 @@
.app_theme_c .uk-alert {
background: #5d4037;
}
.app_theme_c .md-btn-primary,
.app_theme_c .md-btn-primary:hover,
.app_theme_c .md-btn-primary:focus,
.app_theme_c .md-btn-primary:active {
background: #5d4037;
color: #fff;
}
.app_theme_c .md-btn-flat-primary,
.app_theme_c .md-btn-flat-primary:hover,
.app_theme_c .md-btn-flat-primary:focus,
.app_theme_c .md-btn-flat-primary:active {
color: #3e2723;
}
.app_theme_c .md-btn-flat-primary:hover,
.app_theme_c .md-btn-flat-primary:focus,
.app_theme_c .md-btn-flat-primary:active {
background: #c4a59c;
}
.app_theme_c .uk-badge-primary {
background: #5d4037;
}
.app_theme_c .md-card-list-wrapper .md-card-list > ul > li.item-shown.md-card-list-item-selected:before {
background: #efebe9;
}
.app_theme_c .md-card-list-wrapper .md-card-list .md-card-list-item-selected {
background: #efebe9;
}
.app_theme_c .md-card-list-wrapper .md-card-list .md-card-list-item-selected.item-shown {
background: #fff;
}
.app_theme_c .md-card-list-wrapper .md-card-list .md-card-list-item-selected.item-shown:before {
background: #efebe9;
}
.app_theme_c .md-fab.md-fab-accent {
background: #1e88e5;
}
.app_theme_c .md-list .uk-nestable-list > li.md-list-item-active,
.app_theme_c .md-list > li.md-list-item-active {
color: #1e88e5;
}
.app_theme_c .md-list-addon > li.md-list-item-active .md-list-addon-element,
.app_theme_c .md-list-addon > li.md-list-item-active .md-list-addon-element .material-icons {
color: #1e88e5;
}
.app_theme_c .uk-pagination > li > a:hover {
background: #d5e9fa;
}
.app_theme_c .uk-pagination > li.uk-active > a,
.app_theme_c .uk-pagination > li.uk-active > span {
background: #1e88e5;
color: #fff;
}
.app_theme_c .uk-subnav-pill > .uk-active > * {
background: #1e88e5;
}
.app_theme_c .uk-tab > li > a:hover,
.app_theme_c .uk-tab > li > a:focus {
border-bottom-color: #b1887c;
}
.app_theme_c .uk-tab > li.uk-active > a {
border-bottom-color: #5d4037;
}
.app_theme_c .uk-tab-bottom li > a:hover,
.app_theme_c .uk-tab-bottom li > a:focus {
border-top-color: #b1887c;
}
.app_theme_c .uk-tab-bottom li.uk-active > a {
border-top-color: #5d4037;
}
.app_theme_c .uk-tab-left li > a:hover,
.app_theme_c .uk-tab-left li > a:focus {
border-right-color: #b1887c;
}
.app_theme_c .uk-tab-left li.uk-active > a {
border-right-color: #5d4037;
}
.app_theme_c .uk-tab-right li > a:hover,
.app_theme_c .uk-tab-right li > a:focus {
border-left-color: #b1887c;
}
.app_theme_c .uk-tab-right li.uk-active > a {
border-left-color: #5d4037;
}
.app_theme_c .uk-tab-double-header li a:hover,
.app_theme_c .uk-tab-double-header li a:focus {
border-bottom-color: #7d564a;
}
.app_theme_c .uk-tab-double-header li.uk-active > a {
border-bottom-color: #1e88e5;
}
.app_theme_c #header_main {
background: #5d4037;
}
.app_theme_c .header_double_height:after {
background: #5d4037;
}
.app_theme_c #top_bar .top_bar_nav > li > a:hover {
-webkit-box-shadow: inset 0 -3px 0 #5d4037;
box-shadow: inset 0 -3px 0 #5d4037;
}
.app_theme_c #top_bar .top_bar_nav > li.uk-active a {
-webkit-box-shadow: inset 0 -3px 0 #5d4037;
box-shadow: inset 0 -3px 0 #5d4037;
}
.app_theme_c .user_heading {
background: #3e2723;
}
.app_theme_c #sidebar_main .menu_section > ul > li ul li.act_item a {
color: #1e88e5;
}
.app_theme_c #sidebar_main .menu_section > ul > li.current_section > a > .menu_icon .material-icons {
color: #1e88e5;
}
.app_theme_c #sidebar_main .menu_section > ul > li.current_section > a .menu_title {
color: #1e88e5;
}
.app_theme_c .sidebar_mini #sidebar_main .menu_section > ul > li > a > .menu_title {
background: #1e88e5;
color: #fff;
}
.app_theme_c .sidebar_mini #sidebar_main .menu_section > ul > li:hover.sidebar_submenu {
background: #1e88e5;
}
.app_theme_c .sidebar_mini #sidebar_main .menu_section > ul > li:hover.sidebar_submenu > a .menu_icon .material-icons {
color: #fff;
}
.app_theme_c .sidebar_mini #sidebar_main .menu_section > ul > li:hover.sidebar_submenu ul {
border-left-color: #1e88e5;
}
.app_theme_c .sidebar_mini #sidebar_main .menu_section > ul > li.current_section > a > .menu_icon .material-icons {
color: #1e88e5;
}
.app_theme_c .clndr .clndr_days .clndr_days_grid .day.today > span {
background: #1e88e5;
}
.app_theme_c .DTTT_print_info h6 {
color: #1e88e5;
}
.app_theme_c .fc-unthemed .fc-button.fc-state-active:after {
color: #1e88e5;
}
.app_theme_c .fc-unthemed .fc-highlight {
-webkit-box-shadow: inset 0 0 0 2px #5d4037, inset 0 -1px 0 2px #5d4037;
box-shadow: inset 0 0 0 2px #5d4037, inset 0 -1px 0 2px #5d4037;
}
.app_theme_c .tablesorter-altair tbody > tr.row_highlighted > td {
background: #efebe9;
}
.app_theme_c .tablesorter-altair .headerSortUp,
.app_theme_c .tablesorter-altair .tablesorter-headerSortUp,
.app_theme_c .tablesorter-altair .tablesorter-headerAsc,
.app_theme_c .tablesorter-altair .headerSortDown,
.app_theme_c .tablesorter-altair .tablesorter-headerSortDown,
.app_theme_c .tablesorter-altair .tablesorter-headerDesc {
color: #1e88e5;
}
.app_theme_c .wizard > .steps {
background: #5d4037;
}
.app_theme_c .wizard > .steps > ul > li.current a,
.app_theme_c .wizard > .steps > ul > li.current a:hover,
.app_theme_c .wizard > .steps > ul > li.current a:active {
background: #7d564a;
}
.app_theme_c .wizard > .steps > ul > li.done a,
.app_theme_c .wizard > .steps > ul > li.done a:hover,
.app_theme_c .wizard > .steps > ul > li.done a:active {
background: #3e2723;
}
.app_theme_c .md-card-primary {
border-left-color: #5d4037;
}
.app_theme_c .waves-effect.md-btn-flat-primary {
background: none;
}
.app_theme_c .waves-effect.md-btn-flat-primary .waves-ripple {
background: rgba(93, 64, 55, 0.4);
}
.app_theme_c .search_list_link {
color: #1e88e5;
}
.app_theme_c .chatbox.cb_active .chatbox_header {
background: #3e2723;
}
.app_theme_c .chatbox_content .chatbox_message.own .chatbox_message_content li > span {
background: #5d4037;
}
.app_theme_c .uk-table tr.row_checked td,
.app_theme_c .uk-table-hover tbody tr:hover {
background: #efebe9;
}

Some files were not shown because too many files have changed in this diff Show More