backing up current trunk

This commit is contained in:
Antonis Lempesis 2021-07-09 10:10:30 +00:00
commit 615176e113
421 changed files with 72071 additions and 0 deletions

12
.editorconfig Normal file
View File

@ -0,0 +1,12 @@
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

55
.gitignore vendored Normal file
View File

@ -0,0 +1,55 @@
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Users Environment Variables
.lock-wscript
# OS generated files #
.DS_Store
ehthumbs.db
Icon?
Thumbs.db
# Node Files #
/node_modules
/bower_components
# Coverage #
/coverage/
# Typing #
/src/typings/tsd/
/typings/
/tsd_typings/
# Dist #
/dist
/public/__build__/
/src/*/__build__/
__build__/**
.webpack.json
# Doc #
/doc/
# IDE #
.idea/
*.swp

49
README.md Executable file
View File

@ -0,0 +1,49 @@
# UOA Repository Manager UI
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.0.8 (Angular version 6.1.10).
## Minimum requirements for installing and building the project
[Node.js](https://nodejs.org/en/) version 8.x or 10.x.<br>
[npm client](https://docs.npmjs.com/cli/install) command line interface (it is installed with Node.js by default).
## Installing the project
After checking out (or updating) the repository enter the created folder and run `npm ci`.
This will install the exact versions of the dependencies as mentioned in the `package-lock.json` file (inside the root folder).
## Build for production
Run `npm run build` (equivalent of `ng build --prod`) to build the project. The build artifacts will be stored in the `dist/uoa-repository-manager-ui` directory.
## Deploy project to nginx server
Run `tar -czvf dist.tar.gz dist/` to generate a compressed `.gz` file containing the built angular folder<br>
Run `scp dist.tar.gz path/to/server/` to copy the compressed file to the server.<br>
Connect to server (`ssh user@server.ip.address`).<br>
Uncompress `dist.tar.gz` file.<br>
Navigate to the root folder of the server.
Copy the contents of the uncompressed dist/uoa-repository-manager-ui folder
into the `uoa-repository-manager-dashboard` folder (superuser privileges are normally required for this action).<br>
## Other topics
### Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.<br>
Run `npm run start:proxy` (equivalent of `ng serve --proxy-config proxy.conf.json`) instead, to run the project using a development proxy. To configure the proxy modify the `proxy.conf.json` file (inside the root folder).
### Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
### Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
### Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
### Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

133
angular.json Executable file
View File

@ -0,0 +1,133 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"uoa-repository-manager-ui": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/uoa-repository-manager-ui",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/uikit/dist/js/uikit.min.js",
"node_modules/uikit/dist/js/uikit-icons.min.js"
]
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "uoa-repository-manager-ui:build",
"port": 4200,
"host": "localhost"
},
"configurations": {
"production": {
"browserTarget": "uoa-repository-manager-ui:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "uoa-repository-manager-ui:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"src/styles.scss"
],
"scripts": [],
"assets": [
"src/favicon.ico",
"src/assets"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"uoa-repository-manager-ui-e2e": {
"root": "e2e/",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "uoa-repository-manager-ui:serve"
},
"configurations": {
"production": {
"devServerTarget": "uoa-repository-manager-ui:serve:production"
}
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "uoa-repository-manager-ui"
}

28
e2e/protractor.conf.js Executable file
View File

@ -0,0 +1,28 @@
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.e2e.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

14
e2e/src/app.e2e-spec.ts Executable file
View File

@ -0,0 +1,14 @@
import { AppPage } from './app.po';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to uoa-repository-manager-ui!');
});
});

11
e2e/src/app.po.ts Executable file
View File

@ -0,0 +1,11 @@
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}

13
e2e/tsconfig.e2e.json Executable file
View File

@ -0,0 +1,13 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}

10587
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

55
package.json Executable file
View File

@ -0,0 +1,55 @@
{
"name": "uoa-repository-manager-ui",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"start:proxy": "ng serve --proxy-config proxy.conf.json",
"build": "rm -rf dist; ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^6.0.3",
"@angular/common": "^6.0.3",
"@angular/compiler": "^6.0.3",
"@angular/core": "^6.0.3",
"@angular/forms": "^6.0.3",
"@angular/http": "^6.0.3",
"@angular/platform-browser": "^6.0.3",
"@angular/platform-browser-dynamic": "^6.0.3",
"@angular/router": "^6.0.3",
"angular2-cookie-law": "^6.0.4",
"bootstrap": "^4.1.3",
"core-js": "^2.5.4",
"jquery": "^3.3.1",
"ngx-bootstrap": "^3.0.1",
"ngx-matomo": "^0.1.2",
"rxjs": "6.3.3",
"uikit": "^3.0.0-rc.19",
"zone.js": "^0.8.26"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.6.8",
"@angular/cli": "~6.0.8",
"@angular/compiler-cli": "^6.0.3",
"@angular/language-service": "^6.0.3",
"@types/jasmine": "~2.8.6",
"@types/jasminewd2": "~2.0.3",
"@types/node": "~8.9.4",
"codelyzer": "~4.2.1",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.0",
"karma-jasmine": "~1.1.1",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "^5.4.1",
"ts-node": "~5.0.1",
"tslint": "~5.9.1",
"typescript": "~2.7.2"
}
}

8
proxy.conf.json Executable file
View File

@ -0,0 +1,8 @@
{
"/uoa-repository-manager-service/*": {
"target": "http://localhost:8480",
"secure": false,
"logLevel": "debug",
"changeOrigin": true
}
}

63
src/app/app-routing.module.ts Executable file
View File

@ -0,0 +1,63 @@
import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core';
import { LandingComponent } from './pages/landing/landing.component';
import { AuthGuardService } from './services/auth-guard.service';
import { DashboardComponent } from './pages/dashboard/dashboard.component';
import { ForbiddenPageComponent } from './shared/reusablecomponents/403-forbidden-page.component';
const appRoutes: Routes = [
{
path: '',
redirectTo: '/landing',
pathMatch: 'full'
},
{
path: 'landing',
component: LandingComponent
},
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [AuthGuardService]
},
{
path: 'sources',
loadChildren: './pages/sources/sources.module#SourcesModule',
canActivate: [AuthGuardService]
},
{
path: 'compatibility',
loadChildren: './pages/compatibility/compatibility.module#CompatibilityModule'
},
{
path: 'content',
loadChildren: './pages/content/content.module#ContentModule',
canActivate: [AuthGuardService]
},
{
path: 'getImpact',
loadChildren: './pages/metrics/metrics.module#MetricsModule',
canActivate: [AuthGuardService]
},
{
path: 'admin',
loadChildren: './pages/adminPg/adminPg.module#AdminPgModule',
},
{
path: '403-forbidden',
component: ForbiddenPageComponent
},
{
path: '**',
redirectTo: '/landing'
}
];
@NgModule ({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule {}

0
src/app/app.component.css Executable file
View File

26
src/app/app.component.html Executable file
View File

@ -0,0 +1,26 @@
<div class="uk-offcanvas-content">
<top-menu></top-menu>
<router-outlet></router-outlet>
<footer></footer>
<cookie-law position="bottom">
OpenAIRE uses cookies in order to function properly.<br>
Cookies are small pieces of data that websites store in your browser to allow us to give you the best browsing experience possible.
By using the OpenAIRE portal you accept our use of cookies. <a href="http://ec.europa.eu/ipg/basics/legal/cookies/index_en.htm" target="_blank"> Read more <span class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="chevron-right" ratio="1"><polyline fill="none" stroke="#000" stroke-width="1.03" points="7 4 13 10 7 16"></polyline></svg>
</span></a>
</cookie-law>
</div>
<!-- Matomo -->
<!--<script type="text/javascript">
var _paq = _paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//https://analytics.openaire.eu/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', piwikUrl]);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
</script>-->
<!-- End Matomo Code -->

27
src/app/app.component.spec.ts Executable file
View File

@ -0,0 +1,27 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to uoa-repository-manager-ui!');
}));
});

62
src/app/app.component.ts Executable file
View File

@ -0,0 +1,62 @@
import { Component, OnInit } from '@angular/core';
import { NavigationEnd, Router, RoutesRecognized } from '@angular/router';
import { AuthenticationService } from './services/authentication.service';
import { environment } from '../environments/environment';
import { MatomoInjector, MatomoTracker } from 'ngx-matomo';
@Component({
selector: 'oa-repo-manager',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
constructor(private router: Router,
private authService: AuthenticationService,
private matomoInjector: MatomoInjector,
private matomoTracker: MatomoTracker) {
console.log('21-06-2019. Fixed matomo to log userIds?');
let piwikUrl;
if (window.location.origin.includes('beta')) {
// piwikUrl = 'https://analytics.openaire.eu/piwik.php?idsite=92&rec=1';
piwikUrl = '92';
} else if (window.location.origin.includes('localhost:4200') ||
window.location.origin.includes('athenarc')) {
// piwikUrl = 'https://analytics.openaire.eu/piwik.php?idsite=92&rec=1';
piwikUrl = '9222222';
} else {
// piwikUrl = 'https://analytics.openaire.eu/piwik.php?idsite=111&rec=1';
piwikUrl = '111';
}
this.matomoInjector.init('https://analytics.openaire.eu/', piwikUrl);
/*disabling console.log in production*/
if ( environment.production === true ) {
console.log = function () {};
}
// URL of the SPA to redirect the user to after login
// this.authService.redirectUrl = "/dashboard";
if (window.location.pathname.includes('/compatibility/browseHistory/')) {
this.authService.redirectUrl = window.location.pathname;
console.log('redirectUrl', this.authService.redirectUrl);
}
this.authService.tryLogin();
}
ngOnInit() {
this.router.events.subscribe((evt) => {
if (!(evt instanceof NavigationEnd)) {
return;
}
if (this.authService.isLoggedIn) {
this.matomoTracker.setUserId(this.authService.getUserEmail());
}
window.scrollTo(0, 0);
});
}
}

60
src/app/app.module.ts Executable file
View File

@ -0,0 +1,60 @@
import { AppComponent } from './app.component';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { ReusableComponentsModule } from './shared/reusablecomponents/reusable-components.module';
import { CookieLawModule } from './shared/reusablecomponents/cookie-law/cookie-law.module';
import { AppRoutingModule } from './app-routing.module';
import { AuthenticationInterceptor } from './services/authentication-interceptor';
import { BrokerService } from './services/broker.service';
import { MonitorService } from './services/monitor.service';
import { PiwikService } from './services/piwik.service';
import { RepositoryService } from './services/repository.service';
import { ValidatorService } from './services/validator.service';
import { UsagestatsService } from './services/usagestats.service';
import { StatisticsService } from './services/statistics.service';
import { AuthGuardService } from './services/auth-guard.service';
import { AuthenticationService } from './services/authentication.service';
import { LandingComponent } from './pages/landing/landing.component';
import { DashboardComponent } from './pages/dashboard/dashboard.component';
import { MatomoModule } from 'ngx-matomo';
@NgModule({
declarations: [
AppComponent,
LandingComponent,
DashboardComponent
],
imports: [
BrowserModule,
NoopAnimationsModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
ReusableComponentsModule,
CookieLawModule,
MatomoModule,
AppRoutingModule
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthenticationInterceptor,
multi: true
},
BrokerService,
MonitorService,
PiwikService,
RepositoryService,
ValidatorService,
UsagestatsService,
StatisticsService,
AuthGuardService,
AuthenticationService
],
bootstrap: [AppComponent]
})
export class AppModule { }

1
src/app/domain/job-types.ts Executable file
View File

@ -0,0 +1 @@
export const jobTypes = ['Compatibility Test', 'Registration Request', 'Workflow Request'];

186
src/app/domain/oa-description.ts Executable file
View File

@ -0,0 +1,186 @@
/*
* created by myrto 12/2017
*/
/* class copied from omtd-platform git repository */
/* THE DESCRIPTION TEXTS PROBABLY NEED REVIEWING ! */
export class Description {
desc: string;
label: string;
mandatory: boolean;
recommended: boolean;
}
/* Description of the repository interface repeating form */
export const interfaceFormDesc = {
desc : 'Form for updating or creating new interfaces for your repository/journal',
label : 'Interface',
mandatory : true,
recommended : false
};
/* Desription of the Datasource Info Forms Fields */
export const softwarePlatformDesc = {
desc: 'The typology used by your repository/journal.\nIf you use a typology not found in the drop-down list,\nyou can enter a custom name in the field below.',
label: 'Software Platform (*)',
mandatory: true,
recommended: false
};
export const platformNameDesc = {
desc: 'The typology used by your repository/journal.\nIf you use a typology not found in the above drop-down list,\nyou can enter a custom name here.',
label: '',
mandatory: true,
recommended: false
};
export const officialNameDesc = {
desc: 'Your repository\'s/journal\'s official name.',
label: 'Official Name (*)',
mandatory: true,
recommended: false
};
export const issnDesc = {
desc: 'Input your journal\'s issn (www.issn.org)',
label: 'ISSN (*)',
mandatory: true,
recommended: false
};
export const eissnDesc = {
desc: 'Input your journal\'s eissn, if it has one (www.issn.org)',
label: 'EISSN',
mandatory: false,
recommended: false
};
export const lissnDesc = {
desc: 'Input your journal\'s lissn, if it has one (www.issn.org)',
label: 'LISSN',
mandatory: false,
recommended: false
};
export const repoDescriptionDesc = {
desc: 'A description of your repository/journal',
label: 'Description (*)',
mandatory: true,
recommended: false
};
export const countryDesc = {
desc: 'The country where your repository/journal is located',
label: 'Country (*)',
mandatory: true,
recommended: false
};
export const longtitudeDesc = {
desc: 'The (approximate) longtitude of your repository/journal\'s location',
label: 'Longtitude (*)',
mandatory: true,
recommended: false
};
export const latitudeDesc = {
desc: 'The (approximate) latitude of your repository/journal\'s location',
label: 'Latitude (*)',
mandatory: true,
recommended: false
};
export const websiteUrlDesc = {
desc: 'The main page of your repository/journal\'s website',
label: 'Entry URL (*)',
mandatory: true,
recommended: false
};
export const institutionNameDesc = {
desc: 'The institution that your repository belongs to',
label: 'Institution (*)',
mandatory: true,
recommended: false
};
export const englishNameDesc = {
desc: 'Your repository/journal\'s name in english',
label: 'English Name (*)',
mandatory: true,
recommended: false
};
export const logoUrlDesc = {
desc: 'A link to an image file containing your repository/journal\'s logo',
label: 'Logo URL',
mandatory: false,
recommended: false
};
export const timezoneDesc = {
desc: 'The timezone of the area where your repository/ journal is located',
label: 'Timezone (*)',
mandatory: true,
recommended: false
};
export const datasourceTypeDesc = {
desc: 'The type of your repository',
label: 'Repository Type (*)',
mandatory: true,
recommended: false
};
export const journalTypeDesc = {
desc: 'The type of your journal',
label: 'Journal Type (*)',
mandatory: true,
recommended: false
};
export const aggregatorTypeDesc = {
desc: 'The type of your aggregator',
label: 'Aggregator Type (*)',
mandatory: true,
recommended: false
};
export const adminEmailDesc = {
desc: 'The email address of the repository/journal\'s administrator',
label: 'Admin Email (*)',
mandatory: true,
recommended: false
};
export const baseUrlDesc = {
desc: 'The url that handles the external OAI-PMH requests for the repository/journal.\nIf you are not sure about the base URL of the repository/journal you want to register,\nplease contact the repository/journal\s administrator.',
label: 'Base URL',
mandatory: true,
recommended: false
};
export const existingValSetDesc = {
desc: 'The main set that contains EC or other funder records and will be used for validation.\nIf you are using the OJS plugin make sure to specify it correctly.',
label: 'Available validation sets',
mandatory: false,
recommended: false
};
export const customValSetDesc = {
desc: 'If the validation set you want to use is not in the drop list above, enter a custom one here.',
label: 'Custom validation set',
mandatory: false,
recommended: false
};
export const compatibilityLevelDesc = {
desc: 'Choose your desired compatibility level from the list',
label: 'Desired Compatibility Level',
mandatory: true,
recommended: false
};

44
src/app/domain/page-content.ts Executable file
View File

@ -0,0 +1,44 @@
/**
* Created by stefania on 7/17/17.
*/
import {PiwikInfo} from './typeScriptClasses';
export class PageContent {
content: PositionContents;
route: string;
_id: string;
name: string;
}
export interface PositionContents {
top: Content[];
right: Content[];
bottom: Content[];
left: Content[];
}
export interface Content {
_id: string;
page: Page | string;
placement: string;
order: number;
content: string;
isActive: boolean;
}
export interface Page {
_id: string;
route: string;
name: string;
}
export class PiwikInfoPage {
total: number;
from: number;
to: number;
results: PiwikInfo[];
}

View File

@ -0,0 +1,97 @@
/* Service Down Message */
export const noServiceMessage = 'The service is not available at the moment.';
/* Repositories Messages */
export const loadingUserRepoInfoError = 'Failed to load information on your registered repositories';
export const loadingUserRepoInfoEmpty = 'You have not yet registered any repositories';
export const reposRetrievalError = 'The repositories can not be retrieved at the moment';
export const noRepositoriesFound = 'No Datasources were found';
export const loadingReposMessage = 'Retrieving repositories ...';
export const noRepositoryChosenMsg = 'You need to select a repository first.';
export const loadingRepoMessage = 'Retrieving repository information ...';
export const loadingRepoError = 'System error retrieving repository info';
export const loadingInterfacesError = 'System error retrieving interfaces';
export const loadingAggregationHistory = 'Retrieving aggregation history ...';
export const loadingAggregationHistoryError = 'System error retrieving repository aggregation history.';
export const noAggregationHistory = 'There is no aggregation history for this repository at the moment';
/* Interfaces Messages */
export const noInterfacesSaved = 'You have to create at least one interface.';
export const errorsInInterfaces = 'There are still invalid interfaces. Please correct or remove them.';
export const nonRemovableInterface = 'This interface can not be removed!';
/* Rules Messages */
export const loadingRuleSets = 'Retrieving sets of rules ...';
export const loadingRuleSetsError = 'The rule sets can not be retrieved at the moment';
export const noRuleSets = 'No rule sets were found';
export const noContentRulesResults = 'No content rules were tested';
export const noUsageRulesResults = 'No usage rules were tested';
export const didntSelectRules = 'You need to select at least one rule';
export const didntSelectCrisEntities = 'You need to select at least one entity';
/* Loading Validation Sets Messages */
export const loadingValSets = 'Retrieving validation sets ...';
export const loadingValSetsError = 'The validation sets can not be retrieved at the moment';
/* Jobs of User */
export const loadingUserJobs = 'Retrieving job results ...';
export const loadingUserJobsError = 'Your job results can not be retrieved at the moment';
export const noUserJobsFound = 'No stored jobs found';
export const loadingJobSummary = 'Retrieving job summary ...';
export const loadingJobSummaryError = 'The job summary can not be retrieved at the moment';
export const submittingJob = 'Submitting the new job';
export const submittingJobError = 'The job could not be submitted';
/* Loading Topics Messages */
export const loadingTopics = 'Retrieving topics for the datasource...';
export const loadingTopicsError = 'Failed to load the topics for your datasource';
export const noTopicsFound = 'No topics were found for this datasource';
/* Loading Events Messages */
export const loadingEvents = 'Retrieving events for topic ...';
export const loadingEventsError = 'Failed to retrieve events';
export const noEventsForTopic = 'No events were found for this topic';
export const noEventsWithParams = 'No events were found with the given parameters';
/* Loading Subscriptions Messages */
export const loadingSubscriptions = 'Retrieving subscriptions ...';
export const noSubscriptionsFound = 'No subscriptions found for your account';
export const deletingSubscription = 'Deleting subscription ...';
export const deletingSubscriptionError = 'Failed to delete your subscription';
export const deletingSubscriptionSuccess = 'The subscription was deleted successfully';
export const subscribingToEvents = 'Subscribing to events ...';
export const subscribingToEventsError = 'Failed to subscribe you to the chosen events';
export const subscribingToeventsSuccess = 'The subscription was submitted successfully';
export const subscribingChooseFrequency = 'Please choose a frequency for the notifications';
/* Piwik Messages */
export const loadingMetrics = 'Loading diagrams ...';
export const loadingMetricsError = 'Failed to load the metrics for this repository';
export const enablingMetrics = 'Enabling metrics for this repository...';
export const enabledMetricsSuccess = 'The metrics for this repository were enabled';
export const enabledMetricsError = 'System error enabling metrics for this repository.';
export const validatePiwikSiteSuccess = 'The piwik site was approved.';
/* Forms validation Messages */
export const formInfoLoading = 'Loading information';
export const formInterfacesLoading = 'Loading interfaces';
export const formSubmitting = 'Saving changes ...';
export const formErrorRequiredFields = 'All the fields marked with (*) are mandatory';
export const formErrorInvalidFields = 'There are invalid fields';
export const formErrorWasntSaved = 'The form could not be submitted';
let errorRegisterRepo = 'Due to an error, the registration can\'t be finished. ';
errorRegisterRepo = errorRegisterRepo + 'Please contact "helpdesk@openaire.eu" for support. ';
errorRegisterRepo = errorRegisterRepo + 'We\'re sorry for the inconvenience.';
export const formErrorRegisterRepo = errorRegisterRepo;
export const formSuccessUpdatedRepo = 'The datasource was updated successfully.';
export const formSuccessRegisteredDatasource = 'The datasource was registered successfully';
export const formSuccessAddedInterface = 'The interface was added successfully.';
export const formSuccessUpdatedInterface = 'The interface was updated successfully.';
/* BaseUrl validation Messages */
export const didntChooseBaseUrl = 'You need to select a base URL';
export const invalidCustomBaseUrl = 'The url is not responding or is not a valid OAI-PMH url. Please, make sure that you are using the correct protocol ("http" or "https"), as the service is currently unable to follow url redirects.';
export const identifyingUrl = 'Identifying Url ...';

40
src/app/domain/timezones.ts Executable file
View File

@ -0,0 +1,40 @@
export const timezones = [
{ offset: -12.0, name: '[GMT - 12:00] United States Minor Outlying Islands' },
{ offset: -11.0, name: '[GMT - 11:00] United States, New Zealand' },
{ offset: -10.0, name: '[GMT - 10:00] Honolulu, Papeete...' },
{ offset: -9.5, name: '[GMT - 09:30] French Polynesia' },
{ offset: -9.0, name: '[GMT - 09:00] Anchorage...' },
{ offset: -8.0, name: '[GMT - 08:00] Los Angeles, Vancouver, Tijuana...' },
{ offset: -7.0, name: '[GMT - 07:00] Phoenix, Denver, Calgary, Ciudad Juárez...' },
{ offset: -6.0, name: '[GMT - 06:00] Chicago, Mexico City, Guatemala City, Tegucigalpa, Managua, Winnipeg, San José, San Salvador...' },
{ offset: -5.0, name: '[GMT - 05:00] New York, Toronto, Havana, Lima, Bogotá, Kingston...' },
{ offset: -4.0, name: '[GMT - 04:00] Santiago, Santo Domingo, Manaus, Caracas, La Paz, Asunción, Halifax...' },
{ offset: -3.5, name: '[GMT - 03:30] St. Johns...' },
{ offset: -3.0, name: '[GMT - 03:00] São Paulo, Buenos Aires, Montevideo...' },
{ offset: -2.0, name: '[GMT - 02:00] Brazil, United Kingdom...' },
{ offset: -1.0, name: '[GMT - 01:00] Praia, Ponta Delgada...' },
{ offset: 0.0, name: '[GMT] London, Dublin, Lisbon, Accra, Dakar...' },
{ offset: 1.0, name: '[GMT + 01:00] Berlin, Rome, Paris, Madrid, Vienna, Warsaw, Lagos, Kinshasa, Luanda, Algiers, Casablanca...' },
{ offset: 2.0, name: '[GMT + 02:00] Cairo, Khartoum, Johannesburg, Athens, Kiev, Bucharest, Lubumbashi, Jerusalem...' },
{ offset: 3.0, name: '[GMT + 03:00] Moscow, Istanbul, Riyadh, Baghdad, Nairobi, Minsk, Doha...' },
{ offset: 3.5, name: '[GMT + 03:30] Tehran...' },
{ offset: 4.0, name: '[GMT + 04:00] Dubai, Baku, Samara...' },
{ offset: 4.5, name: '[GMT + 04:30] Kabul...' },
{ offset: 5.0, name: '[GMT + 05:00] Karachi, Tashkent, Yekaterinburg...' },
{ offset: 5.5, name: '[GMT + 05:30] Mumbai, Delhi, Colombo...' },
{ offset: 5.75, name: '[GMT + 05:45] Kathmandu...' },
{ offset: 6.0, name: '[GMT + 06:00] Dhaka, Almaty, Omsk...' },
{ offset: 6.5, name: '[GMT + 06:30] Yangon...' },
{ offset: 7.0, name: '[GMT + 07:00] Jakarta, Bangkok, Ho Chi Minh City, Krasnoyarsk...' },
{ offset: 8.0, name: '[GMT + 08:00] Shanghai, Beijing, Hong Kong, Kuala Lumpur, Singapore, Taipei, Perth, Manila, Makassar, Irkutsk...' },
{ offset: 8.75, name: '[GMT + 08:45] Australia' },
{ offset: 9.0, name: '[GMT + 09:00] Tokyo, Seoul, Pyongyang, Ambon, Yakutsk...' },
{ offset: 9.5, name: '[GMT + 09:30] Adelaide, Darwin...' },
{ offset: 10.0, name: '[GMT + 10:00] Sydney, Melbourne, Port Moresby, Vladivostok...' },
{ offset: 10.5, name: '[GMT + 10:30] Australia (New South Wales)...' },
{ offset: 11.0, name: '[GMT + 11:00] Nouméa, Magadan...' },
{ offset: 12.0, name: '[GMT + 12:00] Auckland, Suva, Petropavlovsk-Kamchatsky...' },
{ offset: 12.75, name: '[GMT + 12:45] New Zealand (Chatham Islands)...' },
{ offset: 13.0, name: '[GMT + 13:00] Kiribati (Phoenix Islands), New Zealand (Tokelau), Samoa, Tonga' },
{ offset: 14.0, name: '[GMT + 14:00] Kiribati (Line Islands)' },
];

View File

@ -0,0 +1,670 @@
// Generated using typescript-generator version 1.29.366 on 2018-02-05 16:06:12.
export class BrowseData {
data: { [index: string]: FieldData };
fields: string[];
}
export class DataCollectionAccessProtocol {
value: string;
username: string;
password: string;
}
export class DataCollectionInterface {
protocol: DataCollectionAccessProtocol;
baseUrl: string;
format: string;
filter: string;
}
export class DataCollectionType {
dataCollectionInterface: DataCollectionInterface;
id: string;
label: string;
group: string;
}
export class Document {
map: { [index: string]: string[] };
fieldNames: string[];
}
export class FieldData {
fieldRowList: FieldRow[];
count: number[];
values: string[];
}
export class FieldRow {
value: string;
count: number;
}
export class FormattedSearchResult {
formattedResult: string;
resultsNumber: number;
}
export class Hint {
alternateTerm: string;
autoFollowHint: boolean;
}
export class DriverResource implements Serializable {
resourceId: string;
resourceUri: string;
resourceKind: string;
resourceType: string;
dateOfCreation: Date;
}
export class MDFormatDataStructure extends DriverResource {
resourceName: string;
layouts: { [index: string]: LayoutField[] };
}
export class PiwikInfo implements IsSerializable {
repositoryId: string;
openaireId: string;
repositoryName: string;
country: string;
siteId: string;
authenticationToken: string;
creationDate: Date;
requestorName: string;
requestorEmail: string;
validated: boolean;
validationDate: Date;
comment: string;
}
export class Repository extends DriverResource implements IsSerializable {
id: string;
officialName: string;
englishName: string;
websiteUrl: string;
logoUrl: string;
contactEmail: string;
countryName: string;
countryCode: string;
organization: string;
latitude: number;
longitude: number;
timezone: number;
namespacePrefix: string;
odNumberOfItems: string;
odNumberOfItemsDate: string;
odPolicies: string;
odLanguages: string;
odContentTypes: string;
collectedFrom: string;
inferred: boolean;
deletedByInference: boolean;
trust: number;
inferenceProvenance: string;
dateOfValidation: Date;
datasourceClass: string;
provenanceActionClass: string;
dateOfCollection: Date;
typology: string;
activationId: string;
mergehomonyms: boolean;
description: string;
releaseStartDate: Date;
releaseEndDate: Date;
missionStatementUrl: string;
dataProvider: boolean;
serviceProvider: boolean;
databaseAccessType: string;
dataUploadType: string;
databaseAccessRestriction: string;
dataUploadRestriction: string;
versioning: boolean;
citationGuidelineUrl: string;
qualityManagementKind: string;
pidSystems: string;
certificates: string;
aggregator: string;
issn: string;
eissn: string;
lissn: string;
interfaces: RepositoryInterface[];
availableDiskSpace: string;
securityParameters: string;
protocol: string;
registeredBy: string;
datasourceType: string;
datasourceAggregatorId: string;
datasourceOriginalIdValue: string;
datasourceOriginalIdProvenance: string;
datasourceAggregated: boolean;
datasourceComplianceDegreeValue: string;
datasourceComplianceDegreeEncoding: string;
numberOfObjects: number;
maxSizeOfDatastructure: number;
maxNumberOfDataStructures: number;
registered: boolean;
extraFields: { [index: string]: string };
piwikInfo: PiwikInfo;
environments: string[];
registrationDate: Date;
verified: boolean;
dataCollectionTypes: DataCollectionType[];
}
export class RepositorySnippet {
id: string;
officialname: string;
englishname: string;
websiteurl: string;
typology: string;
registeredby: string;
organizations: Organization[];
registrationdate: Date;
piwikInfo: PiwikInfo;
logoUrl: string;
description: string;
consentTermsOfUse: string;
consentTermsOfUseDate: Date;
fullTextDownload: string;
}
export class Organization {
country: string;
legalname: string;
websiteurl: string;
legalshortname: string;
logourl: string;
}
export class RepositoryAccessProtocol {
value: string;
username: string;
password: string;
filter: string;
}
export class RepositoryBlackboard {
lastrequest: string;
lastresponse: string;
messages: RepositoryBlackboardMessage[];
}
export class RepositoryBlackboardMessage {
id: string;
action: Action;
actionStatus: ActionStatus;
parameters: string[];
}
export class RepositoryComparator implements Comparator<Repository> {
}
export class RepositoryInterface implements Serializable, IsSerializable {
desiredCompatibilityLevel: string;
complianceName: string;
upgradeToV3: string;
deleteApi: boolean;
accessSet: string;
accessFormat: string;
metadataIdentifierPath: string;
lastCollectionDate: string;
nextScheduledExecution: string;
status: string;
collectedFrom: string;
id: string;
typology: string;
compliance: string;
contentDescription: string;
accessProtocol: string;
baseUrl: string;
active: boolean;
removable: boolean;
accessParams: { [index: string]: string };
extraFields: { [index: string]: string };
}
export class SearchCriteriaImpl implements SearchCriteria {
startsWith: string;
endsWith: string;
contains: string;
}
export class RepositorySearchCriteria extends SearchCriteriaImpl implements SearchCriteria {
haveDocuments: boolean;
protocolType: string;
adminInfo: string;
officialName: string;
registeredBy: string;
country: string;
verified: boolean;
}
export class SearchResult {
query: string;
locale: string;
total: number;
page: number;
size: number;
fields: string[];
searchResults: string[];
browseResults: string[];
}
export class SimilarDocument {
id: string;
score: number;
}
export class StoreInfo {
serviceUrl: string;
storeId: string;
}
export class StoreObjectInfo {
storeInfo: StoreInfo;
objectId: string;
}
export class SuggestiveResult {
epr: EPR;
alternativeTerm: string;
autofollow: boolean;
}
export class CustomProperties implements IsSerializable {
properties: { [index: string]: string };
}
export class JobForValidation implements IsSerializable {
officialName: string;
baseUrl: string;
userEmail: string;
validationSet: string;
datasourceId: string;
interfaceId: string;
desiredCompatibilityLevel: string;
activationId: string;
repoType: string;
interfaceIdOld: string;
groupByXpath: string;
metadataPrefix: string;
records: number;
registration: boolean;
updateExisting: boolean;
cris: boolean;
crisReferentialChecks: boolean;
selectedCrisEntities: string[];
selectedContentRules: number[];
selectedUsageRules: number[];
adminEmails: string[];
}
export class JobResultEntry implements IsSerializable {
name: string;
description: string;
successes: string;
weight: number;
errors: string[];
ruleId: number;
hasErrors: boolean;
mandatory: boolean;
type: string;
}
export class Rule implements IsSerializable {
id: number;
name: string;
description: string;
type: string;
mandatory: boolean;
weight: number;
provider_information: string;
job_type: string;
entity_type: string;
for_cris: boolean;
configuration: CustomProperties;
}
export class RuleSet implements Serializable, IsSerializable {
id: number;
name: string;
description: string;
guidelinesAcronym: string;
shortName: string;
visibility: string[];
contentRules: Rule[];
usageRules: Rule[];
contentRulesIds: number[];
usageRulesIds: number[];
}
export class StoredJob extends JobForValidation implements IsSerializable {
contentJobStatus: string;
usageJobStatus: string;
started: string;
ended: string;
duration: string;
error: string;
validationType: string;
jobType: string;
guidelinesShortName: string;
validationStatus: string;
recordsTested: number;
id: number;
contentJobScore: number;
usageJobScore: number;
rules: number[];
resultEntries: JobResultEntry[];
filteredScores: { [index: string]: number };
}
export class AdvQueryObject implements IsSerializable {
datasource: string;
topic: string;
titles: string[];
subjects: string[];
authors: string[];
dates: Range[];
trust: Range;
page: number;
}
export class BrowseEntry implements Comparable<BrowseEntry>, IsSerializable {
value: string;
size: number;
}
export class ConditionParams implements IsSerializable {
value: string;
otherValue: string;
}
export class Dataset implements IsSerializable {
titles: string[];
collectedFrom: string[];
pids: Pid[];
instances: Instance[];
}
export class DatasourcesBroker implements IsSerializable {
datasourcesOfUser: Tuple<BrowseEntry, string>[];
sharedDatasources: Tuple<BrowseEntry, string>[];
datasourcesOfOthers: Tuple<BrowseEntry, string>[];
}
export class EventsPage implements IsSerializable {
datasource: string;
topic: string;
currPage: number;
totalPages: number;
total: number;
values: OpenAireEventPayload[];
}
export class ExternalReference implements IsSerializable {
url: string;
sitename: string;
type: string;
refidentifier: string;
}
export class Instance implements IsSerializable {
url: string;
license: string;
hostedby: string;
instancetype: string;
}
export class Journal implements IsSerializable {
name: string;
issn: string;
eissn: string;
lissn: string;
}
export class MapConditions implements IsSerializable {
field: string;
fieldType: MapValueType;
operator: ConditionOperator;
listParams: ConditionParams[];
}
export class OpenAireEventPayload implements IsSerializable {
publication: Publication;
highlight: Publication;
provenance: Provenance;
trust: number;
}
export class OpenaireSubscription implements IsSerializable {
subscriber: string;
frequency: NotificationFrequency;
mode: NotificationMode;
query: AdvQueryObject;
}
export class Pid implements IsSerializable {
value: string;
type: string;
}
export class Project implements IsSerializable {
code: string;
acronym: string;
title: string;
funder: string;
fundingProgram: string;
jurisdiction: string;
}
export class Provenance implements IsSerializable {
repositoryName: string;
url: string;
id: string;
}
export class Publication implements IsSerializable {
originalId: string;
titles: string[];
abstracts: string[];
language: string;
subjects: string[];
creators: string[];
publicationdate: string;
publisher: string;
embargoenddate: string;
contributor: string[];
journal: Journal;
collectedFrom: string[];
pids: Pid[];
instances: Instance[];
externalReferences: ExternalReference[];
publications: Publication[];
projects: Project[];
datasets: Dataset[];
softwares: Software[];
}
export class Range implements IsSerializable {
min: string;
max: string;
}
export class SimpleSubscriptionDesc implements IsSerializable {
id: string;
datasource: string;
topic: string;
count: number;
creationDate: Date;
lastNotificationDate: Date;
}
export class Software implements IsSerializable {
name: string;
description: string;
landingPage: string;
repository: string;
}
export class Subscription implements IsSerializable {
subscriptionId: string;
subscriber: string;
topic: string;
frequency: NotificationFrequency;
mode: NotificationMode;
creationDate: Date;
lastNotificationDate: Date;
conditions: string;
conditionsAsList: MapConditions[];
}
export class LayoutField {
name: string;
xpath: string;
type: string;
indexable: boolean;
result: boolean;
stat: boolean;
tokenizable: boolean;
}
export interface IsSerializable {
}
export interface Serializable {
}
export interface SearchCriteria {
}
export class EPR {
epr: string;
address: string;
serviceName: string;
endpointName: string;
parameterNames: string[];
}
export class Tuple<K, V> implements IsSerializable {
first: K;
second: V;
}
export interface Comparator<T> {
}
export interface Comparable<T> {
}
export type ConditionOperator = "EXACT" | "MATCH_ANY" | "MATCH_ALL" | "RANGE";
export type MapValueType = "STRING" | "INTEGER" | "FLOAT" | "DATE" | "BOOLEAN" | "LIST_STRING" | "LIST_INTEGER" | "LIST_FLOAT" | "LIST_DATE" | "LIST_BOOLEAN";
export type NotificationFrequency = "never" | "realtime" | "daily" | "weekly" | "monthly";
export type NotificationMode = "MOCK" | "EMAIL";
export type Action = "CREATE" | "DELETE" | "UPDATE" | "MANAGE" | "RELEASE" | "CANCEL";
export type ActionStatus = "DONE" | "ONGOING" | "FAILED" | "WAITING" | "ASSIGNED";
export class Country {
name: string;
code: string;
}
export class Term implements IsSerializable {
englishName: string;
nativeName: string;
encoding: string;
code: string;
}
export class Timezone {
name: string;
offset: number;
}
export class InterfaceInformation implements IsSerializable {
identified: boolean;
sets: string[];
adminEmails: string[];
}
export class JobsOfUser implements IsSerializable {
totalJobs: number;
totalJobsSuccessful: number;
totalJobsFailed: number;
totalJobsOngoing: number;
jobs: StoredJob[];
}
export class MetricsNumbers implements IsSerializable {
downloads: string[];
pageviews: string;
total_downloads: string;
total_openaire_downloads: string;
total_openaire_views: string;
total_views: string;
views: string[];
}
export class MetricsInfo implements IsSerializable {
diagramsBaseURL: string;
metricsNumbers: MetricsNumbers;
}
export class Typology {
value: string;
name: string;
}
export class AggregationDetails implements IsSerializable {
aggregationStage: string;
date: Date;
numberOfRecords: number;
collectionMode: string;
indexedVersion: boolean;
}
export class Aggregations implements IsSerializable {
aggregationHistory: AggregationDetails[];
lastCollection: AggregationDetails[];
lastTransformation: AggregationDetails[];
}
export class UserInfo implements IsSerializable {
sub: string;
role: string[];
name: string;
email: string;
}
export class UsageStatsSummary implements IsSerializable {
literature: string;
aggregators: string;
journal: string;
software: string;
lastYearUsagestats: { number: string; year: number; };
usagestats: string;
dataRepositories: string;
datasets: string;
publications: string;
}
export class RepositorySummaryInfo {
id: string;
repositoryName: string;
logoURL: string;
recordsCollected: number;
lastIndexedVersion: Date;
enrichmentEvents: number;
totalViews: string;
totalDownloads: string;
}

41
src/app/domain/typologies.ts Executable file
View File

@ -0,0 +1,41 @@
export const typologies = [
{ value: '', name: '[Other] (enter name below)' },
{ value: 'CONTENTdm', name: 'CONTENTdm' },
{ value: 'Digibib', name: 'Digibib' },
{ value: 'Digital Commons', name: 'Digital Commons' },
{ value: 'DigiTool', name: 'DigiTool' },
{ value: 'DIVA', name: 'DIVA' },
{ value: 'Diva-Portal', name: 'Diva-Portal' },
{ value: 'dLibra', name: 'dLibra' },
{ value: 'Doks', name: 'Doks' },
{ value: 'Drupal', name: 'Drupal' },
{ value: 'DSpace', name: 'DSpace' },
{ value: 'Earmas', name: 'Earmas' },
{ value: 'EPrints', name: 'EPrints' },
{ value: 'ETD', name: 'ETD' },
{ value: 'ETD - db', name: 'ETD - db' },
{ value: 'Fedora', name: 'Fedora' },
{ value: 'Fez', name: 'Fez' },
{ value: 'Greenstone', name: 'Greenstone' },
{ value: 'HAL', name: 'HAL' },
{ value: 'invenio', name: 'invenio' },
{ value: 'MyCoRe', name: 'MyCoRe' },
{ value: 'Open Repository', name: 'Open Repository' },
{ value: 'OPUS', name: 'OPUS' },
{ value: 'Pica - Verbundkatalog', name: 'Pica - Verbundkatalog' },
{ value: 'Proprietary Software', name: 'Proprietary Software' },
{ value: 'PUMA', name: 'PUMA' },
{ value: 'PURE', name: 'PURE' },
{ value: 'SciELO', name: 'SciELO' },
{ value: 'SFIX', name: 'SFIX' },
{ value: 'VITAL', name: 'VITAL' },
{ value: 'VTOAI', name: 'VTOAI' },
{ value: 'WEKO', name: 'WEKO' },
{ value: 'XooNIps', name: 'XooNIps' },
{ value: 'OJS', name: 'OJS' },
{ value: 'HyperJournal', name: 'HyperJournal' },
{ value: 'ePubTk', name: 'ePubTk' },
{ value: 'GAPworks', name: 'GAPworks' },
{ value: 'DPubS', name: 'DPubS' },
{ value: 'E - Journal', name: 'E - Journal' },
];

View File

@ -0,0 +1,7 @@
/**
* Created by stefania on 9/6/16.
*/
export class URLParameter {
key: string;
value: string[];
}

View File

@ -0,0 +1,110 @@
// Generated using typescript-generator version 1.29.366 on 2018-05-11 15:13:15.
export class Contact {
"E-mail": string;
Contact: string;
}
export class Customer {
ID: string;
ReportItems: ReportItem[];
}
export class Filter {
Name: string;
Value: string;
}
export class Filters {
UsageDateRange: UsageDateRange;
Filter: Filter[];
ReportAttribute: Filter[];
}
export class Instance {
MetricType: string;
Count: string;
}
export class ItemIdentifier {
Type: string;
Value: string;
}
export class ItemPerformance {
Period: Period;
Category: string;
Instance: Instance[];
}
export class Period {
Begin: string;
End: string;
}
export class Report {
"@Created": string;
"@Version": string;
"@Name": string;
Vendor: Vendor;
Customer: Customer;
}
export class ReportDefinition {
"@Name": string;
"@Release": string;
Filters: Filters;
}
export class ReportException {
"@Created": string;
Number: string;
Severity: string;
Message: string;
Data: string;
}
export class ReportItem {
ItemIdentifier: ItemIdentifier[];
ItemPublisher: string;
ItemPlatform: string;
ItemDataType: string;
ItemName: string;
ItemPerformance: ItemPerformance[];
}
export class ReportResponse {
"@Created": string;
Exception: ReportException[];
Requestor: Requestor;
ReportDefinition: ReportDefinition;
Report: ReportWrapper;
}
export class ReportResponseWrapper {
ReportResponse: ReportResponse;
}
export class ReportWrapper {
Report: Report;
}
export class Requestor {
ID: string;
}
export class UsageDateRange {
Begin: string;
End: string;
}
export class BaseRepository {
}
export class UsageReport extends BaseRepository {
}
export class Vendor {
Contact: Contact;
Name: string;
}

12
src/app/domain/utilities.ts Executable file
View File

@ -0,0 +1,12 @@
export function sortAlpgabetically (array: any[]) {
array.sort(function(a,b){
if(a < b ){
return -1;
} else if(a > b ){
return 1;
} else {
return 0;
}
});
}

43
src/app/domain/utils.ts Executable file
View File

@ -0,0 +1,43 @@
/**
* Created by stefanos on 2/3/2017.
*/
export function getCookie(name: string) : string {
let ca: string[] = document.cookie.split(';');
let caLen: number = ca.length;
let cookieName = `${name}=`;
let c: string;
/*console.log(`document.cookie is: ${document.cookie.toString()}`);
console.log(`ca is: ${JSON.stringify(ca)}`);*/
for (let i: number = 0; i < caLen; i += 1) {
c = ca[i].replace(/^\s+/g, '');
if (c.indexOf(cookieName) == 0) {
return c.substring(cookieName.length, c.length);
}
}
return null;
}
export function deleteCookie(name) {
setCookie(name, '', -1);
console.log(`after delete: document.cookie is: ${document.cookie.toString()}`);
}
/* defaulr path used to be '' */
function setCookie(name: string, value: string, expireDays: number, path: string = '/') {
let d:Date = new Date();
d.setTime(d.getTime() + expireDays * 24 * 60 * 60 * 1000);
let expires:string = `expires=${d.toUTCString()}`;
/*let cpath:string = path ? `; path=${path}` : '';*/
/*document.cookie = `${name}=${value}; ${expires}${cpath}`;*/
/* new code from Argyro */
let domain = "";
if (document.domain.indexOf(".di.uoa.gr")!= -1) { // for development
domain = ".athenarc.gr";
} else if(document.domain.indexOf(".openaire.eu") != -1) {
domain = ".openaire.eu";
}
document.cookie = name+'='+value+'; path='+path+'; domain='+domain+';';
}

View File

@ -0,0 +1,169 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Metrics Admin</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class="uk-width-expand@m">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="successMessage" class="uk-alert uk-alert-success">{{ successMessage }}</div>
<div class="uk-grid">
<div class="uk-width-1-1@m uk-padding" style="background-color: #fff; text-align: center">
<form [formGroup]="dataForm" class="uk-search uk-search-default uk-width-1-1@m">
<input class="uk-width-1-2 uk-search-input" type="search" formControlName="searchField" placeholder="Search..." style="background-color: #fff">
<button class="uk-button" (click)="handleChangeAndResetPage()">Search</button>
<div class="uk-position-right">
<button class="uk-button uk-button-primary" (click)="downloadCSV()">Export to CSV</button>
</div>
</form>
</div>
</div>
<div class="uk-grid">
<div class="uk-width-expand@m">
<div class="uk-grid">
<div class="uk-width-1-1@m uk-margin-medium">
<form [formGroup]="dataForm" class="uk-form-horizontal uk-grid">
<div class="uk-width-2-5@m">
<div class="uk-margin">
<label class="uk-form-label uk-text-right" for="quantity">Items per page: </label>
<div class="uk-form-controls">
<select class="uk-select" id="quantity" (change)="handleChangeAndResetPage()" formControlName="quantity">
<option value="10">10</option>
<option value="25" selected>25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
</div>
</div>
<div class="uk-width-expand@m ">
<div class="uk-float-right">
<label class="uk-form-label uk-text-right" for="orderBy">Order by: </label>
<div class="uk-form-controls">
<select class="uk-select" id="orderBy" (change)="handleChangeAndResetPage()" formControlName="order">
<option value="DSC">Descending</option>
<option value="ASC" selected>Ascending</option>
</select>
</div>
</div>
<div class="uk-float-right">
<label class="uk-form-label uk-text-right" for="sortBy">Sort by: </label>
<div class="uk-form-controls">
<select class="uk-select" id="sortBy" (change)="handleChangeAndResetPage()" formControlName="orderField">
<option value="CREATION_DATE" >Date</option>
<option value="REPOSITORY_NAME" selected>Name</option>
</select>
</div>
</div>
</div>
</form>
</div>
<div class="uk-width-1-1@m">
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<!-- TABLE -->
<div *ngIf="piwiks && piwiks.results.length>0">
<table class="uk-table uk-table-striped uk-table-middle" style="font-size: 12px;">
<thead>
<tr>
<th class="uk-text-nowrap">Repository</th>
<th class="uk-text-nowrap">Piwik site</th>
<th class="uk-text-nowrap">Requested on</th>
<th class="uk-text-nowrap">Requestor</th>
<th class="uk-text-nowrap">Validated</th>
<th class="uk-text-nowrap">Actions</th>
</tr>
</thead>
<tbody>
<tr class="el-item" *ngFor="let piwik of piwiks.results">
<td class="uk-table-shrink uk-text-truncate" style="min-width: 400px;">
{{ piwik.repositoryName }}<br>
<a class="viewDetails" [routerLink]="['/getImpact/show_metrics/', piwik.repositoryId]">(ID: {{ piwik.repositoryId }})</a>
</td>
<td class="uk-table-shrink">ID: {{ piwik.siteId }}<br>Authentication Token: {{ piwik.authenticationToken }}</td>
<td class="uk-text-nowrap uk-table-shrink">{{ piwik.creationDate | date : "yyyy-MM-dd" }}</td>
<td class="uk-text-nowrap uk-table-shrink">{{ piwik.requestorName }}<br>{{ piwik.requestorEmail }}</td>
<td class="uk-text-nowrap uk-table-shrink">
<span *ngIf="piwik.validated">YES<br>on {{ piwik.validationDate | date : "yyyy-MM-dd" }}</span>
<span *ngIf="!piwik.validated">NO</span>
</td>
<td class="uk-text-nowrap uk-table-shrink">
<button id="{{ piwik.repositoryId }}"
*ngIf="!piwik.validated"
class="uk-button uk-button-primary validate"
(click)="confirmApproval(piwik.repositoryId)">Validate</button>
</td>
</tr>
</tbody>
</table>
</div>
<ul class="uk-pagination uk-flex-center" uk-margin>
<li><a (click)="previousPage()"><span uk-pagination-previous></span></a></li>
<!-- <li class="uk-active"><span>{{+dataForm.get('page').value + 1}}</span></li>-->
<li [ngClass]="{'uk-active': (this.dataForm.get('page').value == page) }" *ngFor="let page of pages">
<a (click)="selectPage(page)">{{page+1}}</a> </li>
<li><a (click)="nextPage()"><span uk-pagination-next></span></a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>
<confirmation-dialog #confirmApprovalModal [title]="modalTitle" [isModalShown]="isModalShown"
[confirmActionButton]="modalButton" (emitObject)="confirmedApproval($event)">
Are you sure you want to validate the selected piwik site(s)?
</confirmation-dialog>

View File

@ -0,0 +1,213 @@
import {Component, Input, OnInit, ViewChild} from '@angular/core';
import { PiwikService } from '../../services/piwik.service';
import { PiwikInfo } from '../../domain/typeScriptClasses';
import {
enabledMetricsError,
enablingMetrics,
loadingReposMessage,
reposRetrievalError,
validatePiwikSiteSuccess
} from '../../domain/shared-messages';
import { ConfirmationDialogComponent } from '../../shared/reusablecomponents/confirmation-dialog.component';
import {URLParameter} from '../../domain/url-parameter';
import {FormBuilder, FormGroup} from '@angular/forms';
import {RepositoryService} from '../../services/repository.service';
import {ActivatedRoute, Router} from '@angular/router';
import {PiwikInfoPage} from '../../domain/page-content';
import {environment} from '../../../environments/environment';
import {st} from '@angular/core/src/render3';
@Component ({
selector: 'app-admin-metrics',
templateUrl: 'adminPg-metrics.component.html'
})
export class AdminPgMetricsComponent implements OnInit {
piwiks: PiwikInfoPage;
urlParams: URLParameter[] = [];
errorMessage: string;
successMessage: string;
loadingMessage: string;
modalTitle = 'Approval Confirmation';
modalButton = 'Yes, validate';
isModalShown: boolean;
formPrepare = {
searchField: '',
orderField: 'REPOSITORY_NAME',
order: 'ASC',
page: '0',
quantity: '25',
from: '0'
};
dataForm: FormGroup;
@ViewChild('confirmApprovalModal')
public confirmApprovalModal: ConfirmationDialogComponent;
private pageTotal: number;
private piwiksTotal: number;
public pages = [];
private offset = 2;
constructor(private piwikService: PiwikService,
private fb: FormBuilder,
private route: ActivatedRoute,
private router: Router) {}
ngOnInit() {
this.dataForm = this.fb.group(this.formPrepare);
this.urlParams = [];
this.route.queryParams
.subscribe(params => {
for (const i in params) {
this.dataForm.get(i).setValue(params[i]);
}
for (let i in this.dataForm.controls) {
if (this.dataForm.get(i).value) {
this.urlParams.push({key: i, value: [this.dataForm.get(i).value]});
}
}
this.handleChange();
},
error => this.errorMessage = <any>error
);
this.isModalShown = false;
}
downloadCSV() {
const url = environment.API_ENDPOINT;
let csvUrlParams = '/piwik/getPiwikSitesForRepos/csv?';
for (let i in this.dataForm.controls) {
if (this.dataForm.get(i).value !== '') {
csvUrlParams = csvUrlParams.concat(i, '=', this.dataForm.get(i).value, '&');
}
}
csvUrlParams = csvUrlParams.split('&page=')[0];
window.open(url + csvUrlParams, '_blank');
}
getPiwiks() {
this.loadingMessage = loadingReposMessage;
this.piwikService.getPiwikSitesForRepos(this.urlParams)
.subscribe(
piwiks => {
this.piwiks = piwiks;
this.getPages();
},
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = reposRetrievalError;
},
() => {
this.loadingMessage = '';
window.scroll(1, 1);
}
);
}
confirmApproval(repoId: string) {
this.confirmApprovalModal.ids = [repoId];
this.confirmApprovalModal.showModal();
}
confirmedApproval(ids: string[]) {
const id = ids[0];
console.log(`approving validation of piwik for repo with id: ${id}`);
this.approvePiwik(id);
}
approvePiwik(id: string) {
this.loadingMessage = enablingMetrics;
this.errorMessage = '';
this.successMessage = '';
/*this.piwikService.approvePiwikSite(id).subscribe(*/
this.piwikService.markPiwikSiteAsValidated(id).subscribe(
response => console.log(`approvePiwikSite responded: ${JSON.stringify(response)}`),
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = enabledMetricsError;
},
() => {
this.loadingMessage = '';
this.errorMessage = '';
this.successMessage = validatePiwikSiteSuccess;
this.getPiwiks();
}
);
}
handleChange() {
this.urlParams = [];
const map: { [name: string]: string; } = {};
for (let i in this.dataForm.controls) {
if (this.dataForm.get(i).value !== '') {
this.urlParams.push({key: i, value: [this.dataForm.get(i).value]});
map[i] = this.dataForm.get(i).value;
}
}
this.router.navigate([`/admin/metrics`], {queryParams: map});
this.getPiwiks();
}
handleChangeAndResetPage() {
this.dataForm.get('page').setValue(0);
this.dataForm.get('from').setValue(0);
this.handleChange();
}
getPages() {
let addToEndCounter = 0;
let addToStartCounter = 0;
this.pages = [];
this.pageTotal = Math.ceil(this.piwiks.total / (this.dataForm.get('quantity').value));
for ( let i = (+this.dataForm.get('page').value - this.offset); i < (+this.dataForm.get('page').value + 1 + this.offset); ++i ) {
if ( i < 0 ) { addToEndCounter++; }
if ( i >= this.pageTotal ) { addToStartCounter++; }
if ((i >= 0) && (i < this.pageTotal)) {
this.pages.push(i);
}
}
for ( let i = 0; i < addToEndCounter; ++i ) {
if (this.pages.length < this.pageTotal) {
this.pages.push(this.pages.length);
}
}
for ( let i = 0; i < addToStartCounter; ++i ) {
if (this.pages[0] > 0) {
this.pages.unshift(this.pages[0] - 1 );
}
}
}
selectPage(page) {
this.dataForm.get('page').setValue(page);
this.dataForm.get('from').setValue(((+this.dataForm.get('page').value) * (+this.dataForm.get('quantity').value)));
this.handleChange();
}
previousPage() {
if (this.dataForm.get('page').value > 0) {
this.dataForm.get('page').setValue(+this.dataForm.get('page').value - 1);
this.dataForm.get('from').setValue(+this.dataForm.get('from').value - +this.dataForm.get('quantity').value);
this.handleChange();
}
}
nextPage() {
// if ((this.dataForm.get('searchField').value) !== '') { this.piwiksTotal = this.piwiks.to; } else { this.piwiksTotal = this.piwiks.total; }
this.pageTotal = Math.ceil(this.piwiks.total / (this.dataForm.get('quantity').value)) - 1;
if (this.dataForm.get('page').value < this.pageTotal) {
this.dataForm.get('page').setValue(+this.dataForm.get('page').value + 1);
this.dataForm.get('from').setValue(+this.dataForm.get('from').value + +this.dataForm.get('quantity').value);
this.handleChange();
}
}
}

View File

@ -0,0 +1,12 @@
.uk-form-horizontal .uk-form-label {
width: 100px;
}
.uk-form-horizontal .uk-form-controls {
margin-left: 115px;
}
.uk-search-default .uk-search-input {
padding-left: 15px;
padding-right: 15px;
}

View File

@ -0,0 +1,171 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Registrations Admin</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-expand uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class="uk-width-expand@m">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="successMessage" class="uk-alert uk-alert-success">{{ successMessage }}</div>
<div class="uk-grid">
<div class="uk-width-1-1@m uk-padding" style="background-color: #fff; text-align: center">
<form [formGroup]="dataForm" class="uk-search uk-search-default uk-width-1-1@m">
<input class="uk-width-1-2 uk-search-input" type="search" formControlName="officialName" placeholder="Search (official name) ..." style="background-color: #fff">
<button class="uk-button" (click)="handleChangeAndResetPage()">Search</button>
</form>
</div>
</div>
<div class="uk-grid">
<div class="uk-width-1-5@m">
<form [formGroup]="dataForm" class="uk-form-stacked">
<div class="uk-form-label uk-text-large">Filtered By</div>
<div class="uk-margin">
<div class="uk-form-label uk-text-large">Datasource Type</div>
<div class="uk-form-controls">
<label><input class="uk-radio" type="radio" value="" (change)="handleChangeAndResetPage()" formControlName="typology"> Any</label><br>
<label><input class="uk-radio" type="radio" value="Aggregator" (change)="handleChangeAndResetPage()" formControlName="typology"> Aggregator</label><br>
<label><input class="uk-radio" type="radio" value="Journal" (change)="handleChangeAndResetPage()" formControlName="typology"> Journal</label><br>
<label><input class="uk-radio" type="radio" value="datarepository" (change)="handleChangeAndResetPage()" formControlName="typology"> Data Repository</label><br>
<label><input class="uk-radio" type="radio" value="pubsrepository" (change)="handleChangeAndResetPage()" formControlName="typology"> Public Repository</label><br>
<label><input class="uk-radio" type="radio" value="entityregistry" (change)="handleChangeAndResetPage()" formControlName="typology"> Entity Registry</label><br>
<label><input class="uk-radio" type="radio" value="Institutional" (change)="handleChangeAndResetPage()" formControlName="typology"> Institutional</label><br>
<label><input class="uk-radio" type="radio" value="Thematic" (change)="handleChangeAndResetPage()" formControlName="typology"> Thematic</label><br>
<label><input class="uk-radio" type="radio" value="Products" (change)="handleChangeAndResetPage()" formControlName="typology"> Products</label><br>
<label><input class="uk-radio" type="radio" value="Unknown" (change)="handleChangeAndResetPage()" formControlName="typology"> Unknown</label>
</div>
</div>
<div class="uk-margin">
<div class="uk-form-label uk-text-large">Countries</div>
<div class="uk-form-controls">
<ng-container *ngIf="countries && countries.length>0">
<read-more [maxHeight]="238">
<div><input class="uk-radio" type="radio" value="" (change)="handleChangeAndResetPage()" formControlName="country"> Any</div>
<ng-container *ngFor="let country of countries">
<div class="">
<input class="uk-radio" type="radio" value="{{country.code}}"
(change)="handleChangeAndResetPage()" formControlName="country"> {{country.name}}
</div>
</ng-container>
</read-more>
</ng-container>
</div>
</div>
</form>
</div>
<div class="uk-width-expand@m">
<div class="uk-grid">
<div class="uk-width-1-1@m uk-margin-medium">
<form [formGroup]="dataForm" class="uk-form-horizontal uk-grid">
<div class="uk-width-2-5@m">
<div class="uk-margin">
<label class="uk-form-label uk-text-right" for="size">Items per page: </label>
<div class="uk-form-controls">
<select class="uk-select" id="size" (change)="handleChangeAndResetPage()" formControlName="size">
<option value="10">10</option>
<option value="25" selected>25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
</div>
</div>
<div class="uk-width-expand@m ">
<div class="uk-float-right">
<label class="uk-form-label uk-text-right" for="orderBy">Order by: </label>
<div class="uk-form-controls">
<select class="uk-select" id="orderBy" (change)="handleChangeAndResetPage()" formControlName="order">
<option value="DESCENDING" selected>Descending</option>
<option value="ASCENDING">Ascending</option>
</select>
</div>
</div>
<div class="uk-float-right">
<label class="uk-form-label uk-text-right" for="sortBy">Sort by: </label>
<div class="uk-form-controls">
<select class="uk-select" id="sortBy" (change)="handleChangeAndResetPage()" formControlName="requestSortBy">
<option value="registrationdate" selected>Date</option>
<option value="officialname">Name</option>
</select>
</div>
</div>
</div>
</form>
</div>
<div class="uk-width-1-1@m">
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<!-- TABLE -->
<table class="uk-table uk-table-striped">
<thead>
<tr>
<th>Repository</th>
<th>Date</th>
<th>Organization</th>
<th>Type</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let res of repositorySnippet">
<td class="uk-width-1-6@m">{{res.officialname}} <br> ({{res.id}}) <br> {{res.registeredby}}</td>
<td >{{res.registrationdate}}</td>
<td> <div *ngFor="let organization of res.organizations">{{organization.legalname + ' (' + getCountryName(organization.country) + ')'}}<br></div></td>
<td>{{res.typology.split('::')[0]}}<br>{{res.typology.split('::')[1]}}<br>{{res.typology.split('::')[2]}}</td>
<td><a class="viewDetails" [routerLink]="['/sources/update/', res.id ]"><i class="fa fa-pencil-square-o"></i></a></td>
</tr>
</tbody>
</table>
<ul class="uk-pagination uk-flex-center" uk-margin>
<li><a (click)="previousPage()"><span uk-pagination-previous></span></a></li>
<li class="uk-active"><span>{{+dataForm.get('page').value + 1}}</span></li>
<li><a (click)="nextPage()"><span uk-pagination-next></span></a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,157 @@
import {Component, OnInit} from '@angular/core';
import {loadingReposMessage, noServiceMessage} from '../../domain/shared-messages';
import {Country, RepositorySnippet} from '../../domain/typeScriptClasses';
import {RepositoryService} from '../../services/repository.service';
import {FormBuilder, FormGroup} from '@angular/forms';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {URLParameter} from '../../domain/url-parameter';
@Component({
selector: 'app-registration',
templateUrl: 'adminPg-registrations.component.html',
styleUrls: ['./adminPg-registrations.component.css']
})
export class RegistrationComponent implements OnInit {
errorMessage: string;
successMessage: string;
loadingMessage: string;
countries: Country[] = [];
repositorySnippet: RepositorySnippet[] = [];
urlParams: URLParameter[] = [];
thisIsForBadUse: RepositorySnippet[] = []; // remove if page total is fixed!!!
formPrepare = {
country: '',
typology: '',
officialName: '',
requestSortBy: 'registrationdate',
order: 'DESCENDING',
page: '0',
size: '25'
};
dataForm: FormGroup;
constructor(private repoService: RepositoryService,
private fb: FormBuilder,
private route: ActivatedRoute,
private router: Router) { }
ngOnInit() {
this.dataForm = this.fb.group(this.formPrepare);
const tempUrlParams = new Array<URLParameter>();
this.route.queryParams
.subscribe(params => {
for (const i in params) {
this.dataForm.get(i).setValue(params[i]);
}
for (let i in this.dataForm.controls) {
if (this.dataForm.get(i).value) {
tempUrlParams.push({key: i, value: [this.dataForm.get(i).value]});
}
}
this.handleChange();
},
error => this.errorMessage = <any>error
);
this.getCountries();
}
getCountries() {
this.repoService.getCountries()
.subscribe(
countries => this.countries = countries.sort(function (a, b) {
if (a.name < b.name) {
return -1;
} else if (a.name > b.name) {
return 1;
} else {
return 0;
}
}),
error => {
this.loadingMessage = '';
this.errorMessage = noServiceMessage;
console.log(error);
}
);
}
getRegisteredRepositories(urlParams: URLParameter[]) {
this.loadingMessage = loadingReposMessage;
this.repoService.searchRegisteredRepositories(this.dataForm.get('page').value,
this.dataForm.get('size').value, urlParams).subscribe(
suc => this.repositorySnippet = suc,
error => {
console.log(error);
this.loadingMessage = '';
},
() => this.loadingMessage = ''
);
}
handleChange() {
const tempUrlParams = new Array<URLParameter>();
const map: { [name: string]: string; } = {};
for (let i in this.dataForm.controls) {
if (this.dataForm.get(i).value !== '') {
tempUrlParams.push({key: i, value: [this.dataForm.get(i).value]});
map[i] = this.dataForm.get(i).value;
}
}
this.router.navigate([`/admin/registrations`],
{queryParams: map});
this.getRegisteredRepositories(tempUrlParams);
}
handleChangeAndResetPage() {
this.dataForm.get('page').setValue(0);
this.handleChange();
}
getCountryName(countryCode): string {
for (const country of Object.values(this.countries)) {
if (country.code === countryCode) {
return country.name;
}
}
}
previousPage() {
if (this.dataForm.get('page').value > 0) {
this.dataForm.get('page').setValue(+this.dataForm.get('page').value - 1);
this.handleChange();
}
}
nextPage() {
/** remove when page total is fixed!!! **/
const tempUrlParams = new Array<URLParameter>();
for (let i in this.dataForm.controls) {
if (this.dataForm.get(i).value !== '') {
tempUrlParams.push({key: i, value: [this.dataForm.get(i).value]});
}
}
this.repoService.searchRegisteredRepositories(+this.dataForm.get('page').value + 1,
this.dataForm.get('size').value, tempUrlParams).subscribe(
suc => this.thisIsForBadUse = suc,
error => console.log(error),
() => {
if (!(this.thisIsForBadUse.length === 0)) {
this.dataForm.get('page').setValue(+this.dataForm.get('page').value + 1);
this.handleChange();
}
}
);
/** **/
}
}

View File

@ -0,0 +1,17 @@
/*
* updated by myrto on 19/12/2018
*/
import { Component, OnInit } from '@angular/core';
@Component ({
selector: 'app-admin',
templateUrl: '../pageContainer.html'
})
export class AdminPgComponent implements OnInit {
constructor() {}
ngOnInit() {}
}

View File

@ -0,0 +1,27 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TabsModule } from 'ngx-bootstrap';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import { AdminPgRouting } from './adminPg.routing';
import { ReusableComponentsModule } from '../../shared/reusablecomponents/reusable-components.module';
import { AdminPgComponent } from './adminPg.component';
import { AdminPgMetricsComponent } from './adminPg-metrics.component';
import {RegistrationComponent} from './adminPg-registrations.component';
@NgModule ({
imports: [
CommonModule,
TabsModule.forRoot(),
FormsModule,
ReactiveFormsModule,
AdminPgRouting,
ReusableComponentsModule,
],
declarations: [
AdminPgComponent,
AdminPgMetricsComponent,
RegistrationComponent
]
})
export class AdminPgModule {}

View File

@ -0,0 +1,33 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AdminPgComponent } from './adminPg.component';
import { AdminPgMetricsComponent } from './adminPg-metrics.component';
import { AuthGuardService } from '../../services/auth-guard.service';
import {RegistrationComponent} from './adminPg-registrations.component';
const adminRoutes: Routes = [
{
path: '',
component: AdminPgComponent,
canActivate: [AuthGuardService],
canLoad: [AuthGuardService],
children: [
{
path: 'metrics',
component: AdminPgMetricsComponent
},
{
path: 'registrations',
component: RegistrationComponent
}
]
}
];
@NgModule ({
imports: [RouterModule.forChild(adminRoutes)],
exports: [RouterModule]
})
export class AdminPgRouting {}

View File

@ -0,0 +1,76 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Aggregation history for {{ repoName }}</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="noAggregations">{{ noAggregations }}</div>
<div *ngIf="aggregationsMap && years && (years.length > 0) && !noAggregations">
<div *ngFor="let year of years" class="uk-width-1-1@m">
<ul class="uk-list uk-list-striped">
<h4>{{ year }}</h4>
<li *ngFor="let aggr of aggregationsMap[year]">
<div class="uk-grid uk-child-width-1-4">
<div><span *ngIf="aggr.date">{{ aggr.date | date : "yyyy-MM-dd" }}</span></div>
<div><span *ngIf="aggr.aggregationStage">Aggregation stage: {{ aggr.aggregationStage }}</span></div>
<div><span *ngIf="aggr.collectionMode">CollectionMode: {{ aggr.collectionMode }}</span></div>
<div><span *ngIf="aggr.numberOfRecords">Number of records: {{ aggr.numberOfRecords }}</span></div>
<div><span *ngIf="aggr.indexedVersion !== null">Is the indexed version: {{ (aggr.indexedVersion === true) ? 'Yes': 'No' }}</span></div>
</div>
</li>
</ul>
<hr>
</div>
</div>
<div *ngIf="repo" class="uk-inline">
<div class="uk-float-right" style="z-index: 100; bottom: 30px; position: fixed; right: 30px;">
<button [routerLink]="['/compatibility/monitor', repo.id]"
style="box-shadow: 0 1px 10px #444444"
class="uk-button uk-button-primary">
Go back
</button>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>

View File

@ -0,0 +1,86 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import {AggregationDetails, Repository} from '../../domain/typeScriptClasses';
import { RepositoryService } from '../../services/repository.service';
import { loadingAggregationHistory, loadingAggregationHistoryError, loadingRepoError,
loadingRepoMessage, noAggregationHistory } from '../../domain/shared-messages';
import { AuthenticationService } from '../../services/authentication.service';
@Component ({
selector: 'app-compatibility-fullhistory-monitor-repo',
templateUrl: 'compatibility-monitor-fullHistory-repo.component.html'
})
export class CompatibilityMonitorFullHistoryRepoComponent implements OnInit {
loadingMessage: string;
errorMessage: string;
noAggregations: string;
repoId = '';
repoName = '';
repo: Repository;
aggregationsMap: Map<string, AggregationDetails[]> = new Map<string, AggregationDetails[]>();
years: string[] = [];
constructor(private route: ActivatedRoute,
private router: Router,
private repoService: RepositoryService,
private authService: AuthenticationService) {}
ngOnInit() {
this.readRepoId();
this.getRepo();
}
readRepoId() {
this.repoId = this.route.snapshot.paramMap.get('id');
this.repoName = `repository with id \'${this.repoId}\'`;
}
getRepo() {
if (this.repoId) {
this.loadingMessage = loadingRepoMessage;
this.repoService.getRepositoryById(this.repoId).subscribe(
repo => {
this.repo = repo;
},
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = loadingRepoError;
},
() => {
this.loadingMessage = '';
if (this.repo) {
this.repoName = this.repo.officialName;
this.getAllAggregationHistory();
} else {
this.errorMessage = loadingRepoError;
}
}
);
}
}
getAllAggregationHistory() {
this.loadingMessage = loadingAggregationHistory;
this.repoService.getRepositoryAggregationsByYear(this.repo.id).subscribe(
aggr => this.aggregationsMap = aggr,
error => {
this.loadingMessage = '';
this.errorMessage = loadingAggregationHistoryError;
},
() => {
this.loadingMessage = '';
this.years = Object.keys(this.aggregationsMap);
if ( this.years.length === 0 ) {
this.noAggregations = noAggregationHistory;
} else {
this.years.sort( (a, b) => ( a > b ? -1 : 1 ) );
}
}
);
}
}

View File

@ -0,0 +1,80 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Recent aggregation history for {{ repoName }}</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="noAggregations">{{ noAggregations }}</div>
<div *ngIf="latestAggregations &&
(latestAggregations.length > 0) &&
!noAggregations">
<div class="uk-width-1-1@m">
<div class="section md-bg-blue-grey-700">
<div class="uk-container uk-container-center">
<div class="al_timeline">
<div *ngFor="let aggr of latestAggregations" class="al_timeline_block versionChange">
<div class="al_timeline_image uk-scrollspy-init-inview uk-scrollspy-inview uk-animation-scale-up">
<ng-container *ngIf="aggr.indexedVersion">
<img src="https://www.openaire.eu/images/Logos/Favicon-90x90.png" style="width: 80%;margin-top: 9%;">
</ng-container>
</div>
<div class="al_timeline_content uk-scrollspy-init-inview uk-scrollspy-inview uk-animation-slide-left">
<h3 *ngIf="aggr.date" class="uk-inline">{{ aggr.date | date : "yyyy-MM-dd" }}</h3>
<span *ngIf="aggr.indexedVersion" class="ng-star-inserted uk-inline uk-float-right uk-badge"
style="padding-top: 10px;padding-left: 10px;padding-right: 10px;margin-top: 5px;">Indexed version</span>
<p *ngIf="aggr.aggregationStage">Aggregation stage - {{ aggr.aggregationStage }}</p>
<p *ngIf="aggr.collectionMode">CollectionMode - {{ aggr.collectionMode }}</p>
<p *ngIf="aggr.numberOfRecords">Number of records - {{ aggr.numberOfRecords }}</p>
<!--<p *ngIf="aggr.indexedVersion !== null">Is the indexed version - {{ (aggr.indexedVersion === true) ? 'Yes': 'No' }}</p>-->
</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-margin-top uk-text-center">
<a [routerLink]="['/compatibility/monitor/fullHistory', repo.id]" class="uk-h3 uk-link">See more results ...</a>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>

View File

@ -0,0 +1,82 @@
import { Component, OnInit } from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {AggregationDetails, Repository} from '../../domain/typeScriptClasses';
import { RepositoryService } from '../../services/repository.service';
import { loadingAggregationHistory, loadingAggregationHistoryError, loadingRepoError,
loadingRepoMessage, noAggregationHistory } from '../../domain/shared-messages';
import {AuthenticationService} from '../../services/authentication.service';
@Component ({
selector: 'app-compatibility-monitor-repo',
templateUrl: 'compatibility-monitor-repo.component.html'
})
export class CompatibilityMonitorRepoComponent implements OnInit {
loadingMessage: string;
errorMessage: string;
noAggregations: string;
repoId = '';
repoName = '';
repo: Repository;
latestAggregations: AggregationDetails[] = [];
constructor(private route: ActivatedRoute,
private router: Router,
private repoService: RepositoryService,
private authService: AuthenticationService) {}
ngOnInit() {
this.readRepoId();
this.getRepo();
}
readRepoId() {
this.repoId = this.route.snapshot.paramMap.get('id');
this.repoName = `repository with id \'${this.repoId}\'`;
}
getRepo() {
if (this.repoId) {
this.loadingMessage = loadingRepoMessage;
this.repoService.getRepositoryById(this.repoId).subscribe(
repo => {
this.repo = repo;
},
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = loadingRepoError;
},
() => {
this.loadingMessage = '';
if (this.repo) {
this.repoName = this.repo.officialName;
this.getLatestAggregationHistory();
} else {
this.errorMessage = loadingRepoError;
}
}
);
}
}
getLatestAggregationHistory() {
this.loadingMessage = loadingAggregationHistory;
this.repoService.getRepositoryAggregations(this.repo.id).subscribe(
aggr => this.latestAggregations = aggr,
error => {
this.loadingMessage = '';
this.errorMessage = loadingAggregationHistoryError;
},
() => {
this.loadingMessage = '';
if ( !this.latestAggregations || (this.latestAggregations.length === 0) ) {
this.noAggregations = noAggregationHistory;
}
}
);
}
}

View File

@ -0,0 +1,42 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Monitor</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<repository-tiles [parent]="'compatibilityMonitor'"></repository-tiles>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>

View File

@ -0,0 +1,13 @@
import {Component, OnInit} from '@angular/core';
@Component ({
selector: 'app-compatibility-monitor',
templateUrl: 'compatibility-monitor.component.html'
})
export class CompatibilityMonitorComponent implements OnInit {
constructor() {}
ngOnInit() {}
}

View File

@ -0,0 +1,20 @@
<div *ngIf="baseUrlList" [formGroup]="group" class="form-group">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div>
<label class="btn btn-link validationSetRadio" for="selectRadio">
<input id="selectRadio" value="select" name="baseURLRadio" type="radio" (change)="chooseUrl(true)" checked>
<span class="uk-margin-small-left">Select base URL from one of your registered repositories</span>
</label>
</div>
<select id="selectBaseUrl" formControlName="selectBaseUrl" class="form-control" >
<option value="">-- none selected --</option>
<option *ngFor="let url of baseUrlList" value="{{ url }}">{{ url }}</option>
</select>
<div>
<label class="btn btn-link validationSetRadio" for="customRadio">
<input id="customRadio" value="custom" name="baseURLRadio" type="radio" (change)="chooseUrl(false)">
<span class="uk-margin-small-left">or enter new</span>
</label>
</div>
<input id="customBaseUrl" formControlName="customBaseUrl" class="form-control" type="text">
</div>

View File

@ -0,0 +1,62 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { didntChooseBaseUrl, invalidCustomBaseUrl } from '../../../domain/shared-messages';
import { ValidatorService } from '../../../services/validator.service';
@Component({
selector: 'compatibility-validate-step1',
templateUrl: 'compatibility-validate-step1.component.html'
})
export class CompatibilityValidateStep1Component implements OnInit {
group: FormGroup;
errorMessage: string;
@Input() baseUrlList: string[];
@Output() emitObject: EventEmitter<any> = new EventEmitter();
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.group = this.fb.group({
selectBaseUrl : '',
customBaseUrl : ''
});
this.group.get('customBaseUrl').disable();
}
chooseUrl(choice: boolean){
if (choice) {
this.group.get('selectBaseUrl').enable();
this.group.get('customBaseUrl').disable();
} else {
this.group.get('selectBaseUrl').disable();
this.group.get('customBaseUrl').enable();
}
}
submitForm() {
if (this.group.get('selectBaseUrl').enabled){
if ( this.group.get('selectBaseUrl').value) {
this.emitObject.emit(this.group.get('selectBaseUrl').value);
console.log(`selected baseUrl!`);
this.errorMessage = '';
return true;
} else {
this.errorMessage = didntChooseBaseUrl;
return false;
}
} else {
if ( this.group.get('customBaseUrl').value ) {
this.emitObject.emit(this.group.get('customBaseUrl').value);
console.log('added new baseUrl!');
this.errorMessage = '';
return true;
} else {
this.errorMessage = didntChooseBaseUrl;
return false;
}
}
}
}

View File

@ -0,0 +1,69 @@
<div *ngIf="ruleSets" [formGroup]="group" class="form-group">
<div *ngFor="let set of ruleSets; let set_index = index">
<label class="btn btn-link" for="ruleSet_{{ set_index }}">
<input id="ruleSet_{{ set_index }}"
value="{{ set.id }}"
formControlName="ruleSet"
name="ruleSet"
type="radio"
(change)="refreshLists()"
[checked]="set_index == 0">
<span class="uk-margin-small-left">{{ set.name }}</span>
</label>
</div>
<button class="uk-button uk-button-link" (click)="toggleShowRules()">
<span *ngIf="showRules">
<i class="fa fa-angle-up"></i>
Hide Content and Usage Rules</span>
<span *ngIf="!showRules">
<i class="fa fa-angle-down"></i>
Show Content and Usage Rules</span>
</button>
<div *ngIf="showRules" class="uk-grid uk-animation-fade">
<div class="uk-width-expand@m uk-width-1-2@s uk-grid-item-match uk-first-column" formArrayName="contentRules">
<div class="margin10">
<div class="checkbox selectAll">
<label>
<input type="checkbox" [checked]="selectedAllContentRules" (change)="toggleSelectAllContentRules()">
<span>Select / Deselect All Content Rules</span>
</label>
</div>
<div *ngFor="let content of group.controls['contentRules'].controls; let content_index = index" class="checkbox">
<div [formGroupName]="content_index">
<label class="uk-link-muted small" for="contentRules_{{ content_index }}">
<input id="contentRules_{{ content_index }}"
title="{{ currentContentRules[content_index].description }}"
formControlName="rule"
type="checkbox"
(change)="onToggleCheckRule($event,'content')">
<span class="uk-margin-small-left">{{ currentContentRules[content_index].name }}</span>
</label>
</div>
</div>
</div>
</div>
<div class="uk-width-expand@m uk-width-1-2@s uk-grid-item-match uk-first-column" formArrayName="usageRules">
<div class="margin10">
<div class="checkbox selectAll">
<label>
<input type="checkbox" [checked]="selectedAllUsageRules" (change)="toggleSelectAllUsageRules()">
<span>Select / Deselect All Usage Rules</span>
</label>
</div>
<div *ngFor="let usage of group.controls['usageRules'].controls; let usage_index = index" class="checkbox">
<div [formGroupName]="usage_index">
<label class="uk-link-muted small" for="usageRules_{{ usage_index }}">
<input id="usageRules_{{ usage_index }}"
value="{{ currentUsageRules[usage_index].id }}"
title="{{ currentUsageRules[usage_index].description }}"
formControlName="rule"
type="checkbox"
(change)="onToggleCheckRule($event,'usage')">
<span class="uk-margin-small-left">{{ currentUsageRules[usage_index].name }}</span>
</label>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,173 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Rule, RuleSet } from '../../../domain/typeScriptClasses';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
@Component ({
selector: 'compatibility-validate-step2',
templateUrl: 'compatibility-validate-step2.component.html'
})
export class CompatibilityValidateStep2Component implements OnInit {
showRules: boolean;
currentContentRules: Rule[] = [];
currentUsageRules: Rule[] = [];
selectedAllContentRules: boolean;
selectedAllUsageRules: boolean;
group: FormGroup;
@Input() ruleSets: RuleSet[];
@Output() emitObject: EventEmitter<any> = new EventEmitter();
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.showRules = false;
this.selectedAllContentRules = true;
this.selectedAllUsageRules = true;
if ( this.ruleSets.length ) {
this.group = this.fb.group({
ruleSet: ['', Validators.required],
contentRules: this.fb.array([this.initRules()]),
usageRules: this.fb.array([this.initRules()])
});
this.group.get('ruleSet').setValue(this.ruleSets[0].id);
this.getCurrentRuleSets();
this.getRulesLists();
}
}
/* creates a formGroup of the Rules FormArray */
initRules() {
return this.fb.group({
rule : [true]
});
}
/* returns Rules for selected RuleSet */
getCurrentRuleSets () {
console.log(this.group.get('ruleSet').value);
let id = this.group.get('ruleSet').value;
let index: number;
this.currentContentRules = [];
this.currentUsageRules = [];
for (let i=0; i< this.ruleSets.length; i++ ) {
if (this.ruleSets[i].id == id) {
index = i;
break;
}
}
this.currentContentRules = this.ruleSets[index].contentRules;
this.currentUsageRules = this.ruleSets[index].usageRules;
console.log(`contentRules length: ${this.currentContentRules.length}`);
console.log(`usageRules length: ${this.currentUsageRules.length}`);
}
/* inputs the Rule Lists into the FormArrays */
getRulesLists() {
let contentRules = <FormArray>this.group.controls['contentRules'];
for ( let i = 0; i<this.currentContentRules.length-1; i++ ) {
contentRules.push(this.initRules());
}
let usageRules = <FormArray>this.group.controls['usageRules'];
for ( let i = 0; i<this.currentUsageRules.length-1; i++ ) {
usageRules.push(this.initRules());
}
}
/* refreshes the Rule Lists according to the selected RuleSet and reinitializes the form controls */
refreshLists(){
this.removeRulesControls();
this.getCurrentRuleSets();
this.getRulesLists();
}
/* removes form controls in order to reinitialize contentRules formArrays */
removeRulesControls() {
let contentRules = <FormArray>this.group.controls['contentRules'];
// contentRules.reset();
contentRules.controls = [];
contentRules.push(this.initRules());
let usageRules = <FormArray>this.group.controls['usageRules'];
// usageRules.reset();
usageRules.controls = [];
usageRules.push(this.initRules());
}
/* selects/deselects all content rules */
toggleSelectAllContentRules() {
let contentRules = <FormArray>this.group.controls['contentRules'];
if (this.selectedAllContentRules) {
this.selectedAllContentRules = false;
contentRules.controls.map(x => x.get('rule').setValue(false));
} else {
this.selectedAllContentRules = true;
contentRules.controls.map(x => x.get('rule').setValue(true));
}
}
/* selects/deselects all usage rules */
toggleSelectAllUsageRules() {
let usageRules = <FormArray>this.group.controls['usageRules'];
if (this.selectedAllUsageRules) {
this.selectedAllUsageRules = false;
usageRules.controls.map(x => x.get('rule').setValue(false))
} else {
this.selectedAllUsageRules = true;
usageRules.controls.map(x => x.get('rule').setValue(true))
}
}
onToggleCheckRule(event:any, contentOrUsage: string) {
if ( !event.target.checked ) {
if (contentOrUsage == 'content') {
this.selectedAllContentRules = false;
} else if (contentOrUsage == 'usage') {
this.selectedAllUsageRules = false;
}
}
}
toggleShowRules() {
this.showRules = !this.showRules;
return this.showRules;
}
saveChanges() {
let emitted: any[] = [];
let index: number;
for (let i=0; i< this.ruleSets.length; i++ ) {
if (this.ruleSets[i].id == this.group.get('ruleSet').value) {
index = i;
break;
}
}
emitted.push(this.ruleSets[index].guidelinesAcronym);
console.log(`saving the selected rules`);
let contentRules = <FormArray>this.group.controls['contentRules'];
let selectedContent: number[] = [];
for (let i=0; i< this.ruleSets[index].contentRules.length; i++ ) {
if (contentRules.at(i).get('rule').value) {
selectedContent.push(this.ruleSets[index].contentRules[i].id);
}
}
emitted.push(selectedContent);
let selectedUsage: number[] = [];
let usageRules = <FormArray>this.group.controls['usageRules'];
for (let i=0; i< this.ruleSets[index].usageRules.length; i++ ) {
if (usageRules.at(i).get('rule').value) {
selectedUsage.push(this.ruleSets[index].usageRules[i].id);
}
}
emitted.push(selectedUsage);
this.emitObject.emit(emitted);
}
}

View File

@ -0,0 +1,50 @@
<div *ngIf="entitiesList" [formGroup]="group">
<div class="marginBottom20 uk-margin-top">
<div>
<label>Cris Entities</label>
</div>
<div>
<div class="margin10" formArrayName="entities">
<div class="checkbox selectAll">
<label>
<input type="checkbox" [checked]="selectedAllEntities" (change)="toggleSelectAllContentRules()">
<span>Select / Deselect All Entities</span>
</label>
</div>
<div *ngFor="let content of group.controls['entities'].controls; let i = index" class="checkbox">
<div [formGroupName]="i">
<label for="entity_{{ i }}">
<input id="entity_{{ i }}"
formControlName="entity"
type="checkbox"
(change)="onToggleCheckEntity($event)">
<span class="uk-margin-small-left">{{ entitiesList[i] }}</span>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="marginBottom20">
<div>
<label>Check Referential Integrity</label>
</div>
<div class="uk-grid form-inline">
<div class="uk-width-1-1">
<label class="btn btn-link" for="yes">
<input id="yes"
name="referentialIntegrity"
value="yes"
checked
type="radio"> <span class="uk-margin-small-left">Yes</span>
</label>
<label class="btn btn-link" for="no">
<input id="no"
name="referentialIntegrity"
value="no"
type="radio"> <span class="uk-margin-small-left">No</span>
</label>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,87 @@
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
@Component ({
selector: 'compatibility-validate-step3-cris',
templateUrl: 'compatibility-validate-step3-cris.component.html'
})
export class CompatibilityValidateStep3CrisComponent implements OnInit {
entitiesList: string[] = [];
selectedAllEntities: boolean;
group: FormGroup;
@Output() emitObject: EventEmitter<any> = new EventEmitter();
constructor(private fb: FormBuilder) {}
ngOnInit () {
this.selectedAllEntities = true;
this.getEntitiesList();
if (this.entitiesList && this.entitiesList.length) {
this.group = this.fb.group({
entities: this.fb.array([this.initEntities()]),
refIntegrity: ''
});
this.setEntitiesControls();
}
}
getEntitiesList() {
this.entitiesList = ['Funding','Organisation','Person','Project','Publication','Product','Service'];
}
initEntities() {
return this.fb.group({
entity : [true]
});
}
/* inputs the entities List into the FormArray */
setEntitiesControls() {
let entities = <FormArray>this.group.controls['entities'];
for ( let i = 0; i<this.entitiesList.length-1; i++ ) {
entities.push(this.initEntities());
}
}
/* selects/deselects all entities */
toggleSelectAllContentRules() {
let entities = <FormArray>this.group.controls['entities'];
if (this.selectedAllEntities) {
this.selectedAllEntities = false;
entities.controls.map(x => x.get('entity').setValue(false));
} else {
this.selectedAllEntities = true;
entities.controls.map(x => x.get('entity').setValue(true));
}
}
onToggleCheckEntity(event:any) {
if ( !event.target.checked ) {
this.selectedAllEntities = false;
}
}
saveChanges() {
let emitted: any[] = [];
let chosenEntities: string[] = [];
console.log(`saving the selected entities`);
let entities = <FormArray>this.group.controls['entities'];
for (let i=0; i<this.entitiesList.length; i++ ) {
if (entities.at(i).get('entity').value) {
chosenEntities.push(this.entitiesList[i]);
}
}
emitted.push(chosenEntities);
if (this.group.get('refIntegrity').value){
emitted.push(true);
} else {
emitted.push(false);
}
this.emitObject.emit(emitted);
}
}

View File

@ -0,0 +1,62 @@
<div class="uk-margin-top">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{errorMessage}}</div>
<div class="marginBottom20" [formGroup]="group">
<div>
<label>Number of records to validate</label>
</div>
<div class="uk-margin uk-grid">
<div class="uk-width-1-4@s">
<label class="uk-link-muted" for="allRecords">
<input id="allRecords" name="noOfRecords" type="radio" (change)="chooseAll(true)" checked>
<span class="uk-margin-small-left">All</span>
</label>
</div>
<div class="uk-width-1-4@s">
<label class="uk-link-muted" for="someRecords">
<input id="someRecords" name="noOfRecords" type="radio" (change)="chooseAll(false)">
<span class="uk-margin-small-left">Custom</span>
</label>
</div>
<div class="uk-width-1-2@s">
<input class="form-control" formControlName="noOfRecordsInput" type="number">
</div>
</div>
<div class="marginBottom20">
<div>
<label for="selectValSet">Validation Set</label>
</div>
<div>
<select id="selectValSet" class="form-control" formControlName="selectValSet">
<option value="">All sets</option>
<option *ngFor="let set of valSets" value="{{set}}">{{set}}</option>
</select>
</div>
<div class="xPathPanel marginBottom20">
<div>
<label>Would you like to group your results by a specific field?</label>
</div>
<div class="uk-grid">
<div class="uk-width-1-4@s">
<label class="uk-link-muted" for="noXPath">
<input id="noXPath" name="xpath" type="radio" (change)="addXpath(false)" checked>
<span class="uk-margin-small-left">No</span>
</label>
</div>
<div class="uk-width-1-4@s">
<label class="uk-link-muted" for="customXPath">
<input id="customXPath" name="xpath" type="radio" (change)="addXpath(true)">
<span class="uk-margin-small-left">Yes</span>
</label>
</div>
<div class="uk-width-1-2@s">
<input class="form-control" formControlName="xpathInput" placeholder="-XPATH-" type="text">
</div>
</div>
<div class="comment fontItalic marginTop10">
<strong>XPath Examples:</strong>
1. //header/setSpec 2. //record/metadata//*[name()='dc:language']
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,75 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { formErrorRequiredFields } from '../../../domain/shared-messages';
@Component ({
selector: 'compatibility-validate-step3',
templateUrl: 'compatibility-validate-step3.component.html'
})
export class CompatibilityValidateStep3Component implements OnInit {
errorMessage: string;
@Input() valSets: string[];
@Output() emitObject: EventEmitter<any> = new EventEmitter();
group: FormGroup;
constructor (private fb: FormBuilder) {}
ngOnInit () {
this.group = this.fb.group({
noOfRecordsInput : '',
selectValSet : [''],
xpathInput : ''
});
this.group.get('noOfRecordsInput').setValue(10);
this.group.get('noOfRecordsInput').disable();
this.group.get('xpathInput').disable();
}
chooseAll(all: boolean) {
if (all) {
this.group.get('noOfRecordsInput').disable();
} else {
this.group.get('noOfRecordsInput').enable();
}
}
addXpath(xpath: boolean) {
if (xpath) {
this.group.get('xpathInput').enable();
} else {
this.group.get('xpathInput').disable();
}
}
submitChanges() {
if (this.group.valid) {
this.errorMessage = '';
const emitted: string [] = [];
if ( this.group.get('selectValSet').value) {
emitted.push(this.group.get('selectValSet').value);
} else {
emitted.push('none');
}
if ( this.group.get('noOfRecordsInput').enabled ) {
emitted.push(this.group.get('noOfRecordsInput').value);
} else {
emitted.push('-1');
}
if ( this.group.get('xpathInput').enabled ) {
emitted.push(this.group.get('xpathInput').value);
} else {
emitted.push('');
}
this.emitObject.emit(emitted);
} else {
this.errorMessage = formErrorRequiredFields;
}
}
}

View File

@ -0,0 +1,133 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Run compatibility test</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class="uk-width-expand@m">
<div class="wizard">
<div class="wizardBreadcrumbs">
<div class="steps clearfix">
<div class="step active">
<div>
Select datasource
<span></span>
</div>
</div>
<div class="step {{ (currentStep > 0) ? 'active' : '' }}">
<div>
{{ (type === 'cris') ? 'Finish' : 'Select guidelines' }}
<span></span>
</div>
</div>
<div *ngIf="(type !== 'cris')" class="step {{ (currentStep > 1) ? 'active' : '' }}">
<div>
Select parameters
<span></span>
</div>
</div>
<div *ngIf="(type !== 'cris')" class="step {{ (currentStep > 2) ? 'active' : '' }} ">
<div>
Finish
<span></span>
</div>
</div>
</div>
</div>
<div class="content">
<div>
<div class="animated fadeInRight stepContent">
<div *ngIf="errorMessage && (type!=='cris' && errorMessage!=='No rule sets were found')" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="(currentStep === 0) && !loadingMessage">
<compatibility-validate-step1 #step1ChooseBaseUrl
[baseUrlList]="baseUrlList"
(emitObject)="getChosenUrl($event)"></compatibility-validate-step1>
</div>
<div *ngIf="(currentStep === 1) && !loadingMessage">
<compatibility-validate-step2 #step2ChooseGuidelines
[ruleSets]="ruleSets"
(emitObject)="getChosenRules($event)">
</compatibility-validate-step2>
</div>
<div *ngIf="(currentStep === 2) && (type !== 'cris') && !loadingMessage">
<compatibility-validate-step3 #step3ChooseParameters
[valSets]="valSets"
(emitObject)="getChosenParameters($event)">
</compatibility-validate-step3>
</div>
<div *ngIf="(currentStep === 2) && (type === 'cris') && !loadingMessage">
<compatibility-validate-step3-cris #step3ChooseCrisEntities
(emitObject)="getChosenCrisEntities($event)">
</compatibility-validate-step3-cris>
</div>
<div *ngIf="(currentStep === 3) && !loadingMessage">
<div>
<div class="success">
<i class="fa fa-check-circle" style=""></i>
<h3>Validation has begun</h3>
</div>
<div class="uk-alert uk-alert-primary marginTop20 textAlignCenter">
You will be notified by email with the results of the compatibility test.
</div>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="!loadingMessage" class="wizardActions">
<button *ngIf="((currentStep === 1) || (currentStep === 2)) && (type !== 'cris') && !loadingMessage"
class="uk-button uk-button-grey-light uk-margin-small-right" type="button"
(click)="moveBackAStep()">
<i class="fa fa-angle-double-left"></i>
Back
</button>
<button *ngIf="((currentStep < 3) && !loadingMessage)"
class="uk-button uk-button-grey-light uk-margin-small-left" type="button"
(click)="(type !== 'cris') ? moveAStep() : (moveAStep() + submitForValidation())">
<span class="{{((currentStep === 2) || ((type === 'cris') && (currentStep === 1))) ? 'uk-link' : ''}}">
{{ ((currentStep < 2) && (type !== 'cris')) || (currentStep === 0) ? 'Next' : 'Finish' }}
</span>
<i class="fa fa-angle-double-right"></i>
</button>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>

View File

@ -0,0 +1,317 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router} from '@angular/router';
import { CompatibilityValidateStep1Component } from './compatibility-validate-forms/compatibility-validate-step1.component';
import { RepositoryService } from '../../services/repository.service';
import { JobForValidation, RuleSet } from '../../domain/typeScriptClasses';
import { AuthenticationService } from '../../services/authentication.service';
import { didntSelectCrisEntities, didntSelectRules, identifyingUrl, invalidCustomBaseUrl,
loadingReposMessage, loadingRuleSets, loadingRuleSetsError, loadingUserRepoInfoError,
loadingValSets, loadingValSetsError, noRuleSets, noServiceMessage, submittingJobError
} from '../../domain/shared-messages';
import { ValidatorService } from '../../services/validator.service';
import { CompatibilityValidateStep2Component } from './compatibility-validate-forms/compatibility-validate-step2.component';
import { CompatibilityValidateStep3Component } from './compatibility-validate-forms/compatibility-validate-step3.component';
import { CompatibilityValidateStep3CrisComponent } from './compatibility-validate-forms/compatibility-validate-step3-cris.component';
import { AsideHelpContentComponent, HelpContentComponent } from '../../shared/reusablecomponents/help-content.component';
@Component ({
selector: 'compatibility-validate-literature',
templateUrl: 'compatibility-validate-type.component.html'
})
export class CompatibilityValidateTypeComponent implements OnInit {
type = '';
/* queryParams is used to change the queryParams without refreshing the page
* This was needed for Help Service [which sends back info according to the current router.url]
* the param that is used is 'step' and the values are: 'baseUrl','guidelines','crisEntities'/'parameters','finish'
*/
currentStep: number;
@ViewChild('topHelperContent')
public topHelperContent: HelpContentComponent;
@ViewChild('leftHelperContent')
public leftHelperContent: AsideHelpContentComponent;
@ViewChild('rightHelperContent')
public rightHelperContent: AsideHelpContentComponent;
@ViewChild('bottomHelperContent')
public bottomHelperContent: HelpContentComponent;
baseUrlList: string[] = [];
ruleSets: RuleSet[] = [];
valSets: string[] = [];
chosenUrl: string;
identifiedUrl: boolean;
chosenGuidelinesAcronym: string;
chosenContentRules: number[];
chosenUsageRules: number[];
chosenValSet: string;
noOfRecords: number;
xPath: string;
chosenCrisEntities: string[];
crisRefIntegrity: boolean;
errorMessage: string;
loadingMessage: string;
@ViewChild('step1ChooseBaseUrl') step1ChooseBaseUrl: CompatibilityValidateStep1Component;
@ViewChild('step2ChooseGuidelines') step2ChooseGuidelines: CompatibilityValidateStep2Component;
@ViewChild('step3ChooseParameters') step3ChooseParameters: CompatibilityValidateStep3Component;
@ViewChild('step3ChooseCrisEntities') step3ChooseCrisEntities: CompatibilityValidateStep3CrisComponent;
constructor(private route: ActivatedRoute,
private router: Router,
private authService: AuthenticationService,
private repoService: RepositoryService,
private valService: ValidatorService) {}
ngOnInit() {
if (this.route.snapshot.paramMap.has('type')) {
this.type = this.route.snapshot.paramMap.get('type');
this.getBaseUrlList();
this.route.queryParams.subscribe(
() => this.getStep()
);
}
}
getStep() {
this.currentStep = 0;
if (this.route.snapshot.queryParamMap.has('step')) {
const stepName = this.route.snapshot.queryParamMap.get('step');
if (stepName === 'guidelines') {
if (!this.identifiedUrl) {
this.router.navigateByUrl(`/compatibility/validate/${this.type}?step=baseUrl`);
} else {
this.currentStep = 1;
}
} else if ((stepName === 'parameters') || (stepName === 'crisEntities')) {
if (!this.chosenUrl) {
this.router.navigateByUrl(`/compatibility/validate/${this.type}?step=baseUrl`);
} else {
this.currentStep = 2;
}
} else if (stepName === 'finish') {
this.currentStep = 3;
}
}
this.rightHelperContent.ngOnInit();
this.topHelperContent.ngOnInit();
this.leftHelperContent.ngOnInit();
this.bottomHelperContent.ngOnInit();
}
/* retrieves the baseUrl list for the registered repositories of the user */
getBaseUrlList() {
this.loadingMessage = loadingReposMessage;
this.repoService.getUrlsOfUserRepos()
.subscribe(
repos => this.baseUrlList = repos.sort( function(a , b) {
if (a < b ) {
return -1;
} else if (a > b ) {
return 1;
} else {
return 0;
}
}),
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = loadingUserRepoInfoError;
window.scroll(1, 1);
},
() => {
this.loadingMessage = '';
}
);
}
moveAStep() {
this.errorMessage = '';
if (this.currentStep === 0) {
this.step1ChooseBaseUrl.submitForm();
} else if (this.currentStep === 1) {
this.step2ChooseGuidelines.saveChanges();
console.log(this.chosenContentRules);
if (this.chosenContentRules.length || this.chosenUsageRules.length) {
if (this.type === 'cris') {
this.router.navigateByUrl(`/compatibility/validate/${this.type}?step=crisEntities`);
} else {
this.getValidationSets();
this.router.navigateByUrl(`/compatibility/validate/${this.type}?step=parameters`);
}
} else {
this.errorMessage = didntSelectRules;
window.scroll(1, 1);
}
} else if ((this.currentStep === 2) && (this.type !== 'cris')) {
this.step3ChooseParameters.submitChanges();
// save all changes
this.submitForValidation();
} else if ((this.currentStep === 2) && (this.type === 'cris')) {
this.step3ChooseCrisEntities.saveChanges();
if (this.chosenCrisEntities.length) {
// save all changes
this.submitForValidation();
} else {
this.errorMessage = didntSelectCrisEntities;
window.scroll(1, 1);
}
}
}
moveBackAStep () {
this.errorMessage = '';
if (this.currentStep === 1) {
this.router.navigateByUrl(`/compatibility/validate/${this.type}?step=baseUrl`);
} else if ((this.currentStep === 2) && (this.type !== 'cris')) {
this.router.navigateByUrl(`/compatibility/validate/${this.type}?step=guidelines`);
} else if ((this.currentStep === 2) && (this.type === 'cris')) {
this.router.navigateByUrl(`/compatibility/validate/${this.type}?step=guidelines`);
}
}
identifyUrl() {
this.loadingMessage = identifyingUrl;
console.log(`identifying ${this.chosenUrl}`);
this.valService.identifyRepository(this.chosenUrl).subscribe(
res => {
this.identifiedUrl = res;
console.log(`identifyRepository responded: ${this.identifiedUrl}`);
},
error => {
console.log(error);
this.loadingMessage = '';
this.identifiedUrl = false;
this.errorMessage = noServiceMessage;
window.scroll(1, 1);
}, () => {
this.loadingMessage = '';
if (this.identifiedUrl) {
this.getRuleSetsForType();
} else {
this.errorMessage = invalidCustomBaseUrl;
window.scroll(1, 1);
}
}
);
}
getRuleSetsForType() {
this.loadingMessage = loadingRuleSets;
this.valService.getRuleSets(this.type)
.subscribe(
rules => this.ruleSets = rules,
error => {
this.loadingMessage = '';
this.errorMessage = loadingRuleSetsError;
window.scroll(1, 1);
},
() => {
this.loadingMessage = '';
if (this.ruleSets && this.ruleSets.length) {
this.router.navigateByUrl(`/compatibility/validate/${this.type}?step=guidelines`);
} else {
this.errorMessage = noRuleSets;
window.scroll(1, 1);
}
}
);
}
getValidationSets() {
this.loadingMessage = loadingValSets;
this.valService.getSetsOfRepository(this.chosenUrl)
.subscribe(
sets => this.valSets = sets,
error => {
this.errorMessage = loadingValSetsError;
window.scroll(1, 1);
},
() => {
this.loadingMessage = '';
this.currentStep = 2;
}
);
}
getChosenUrl(url: string) {
this.chosenUrl = url;
this.identifyUrl();
}
getChosenRules(rules: any[]) {
this.chosenGuidelinesAcronym = rules[0];
this.chosenContentRules = rules[1];
this.chosenUsageRules = rules[2];
}
getChosenParameters (params: string[]) {
this.chosenValSet = params[0];
this.noOfRecords = +params[1];
this.xPath = params[2];
}
getChosenCrisEntities (crisParams: any[]) {
this.chosenCrisEntities = crisParams[0];
console.log(this.chosenCrisEntities);
this.crisRefIntegrity = crisParams[1];
}
submitForValidation() {
let isCris: boolean;
if (this.type === 'cris') {
isCris = true;
this.chosenValSet = 'none';
this.noOfRecords = -1;
} else {
isCris = false;
this.crisRefIntegrity = null;
this.chosenCrisEntities = null;
}
const newJob: JobForValidation = {
selectedCrisEntities: this.chosenCrisEntities,
selectedContentRules: this.chosenContentRules,
selectedUsageRules: this.chosenUsageRules,
desiredCompatibilityLevel: this.chosenGuidelinesAcronym,
baseUrl: this.chosenUrl,
validationSet: this.chosenValSet,
records: this.noOfRecords,
groupByXpath: this.xPath,
cris: isCris,
crisReferentialChecks: this.crisRefIntegrity,
userEmail: this.authService.getUserEmail(),
adminEmails: [],
officialName: '',
datasourceId: '',
interfaceId: '',
activationId: '',
repoType: '',
interfaceIdOld: '',
metadataPrefix: '',
registration: false,
updateExisting: false
};
console.log(JSON.stringify(newJob));
this.valService.submitJobForValidation(newJob).subscribe(
job => console.log(JSON.stringify(job)),
error => {
this.errorMessage = submittingJobError;
window.scroll(1, 1);
},
() => {
this.router.navigateByUrl(`/compatibility/validate/${this.type}?step=finish`);
}
);
}
}

View File

@ -0,0 +1,84 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Validate your datasource</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div>
<div class="uk-margin uk-grid repositoryTypeSelection">
<div class="uk-width-expand@m uk-width-1-3@s uk-grid-item-match uk-first-column">
<div class="uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium" uk-scrollspy-class="" data-id="" style="">
<a class="uk-position-cover uk-margin-remove-adjacent" [routerLink]="['literature']" [queryParams]="{ step: 'baseUrl' }"></a>
<div class="uk-card-media-top">
<img src="../../../assets/imgs/Literature_repos_wide.png" alt="" style="width:100%;">
</div>
<div class="uk-card-body">
<h3 class="el-title uk-margin uk-card-title uk-margin-remove-adjacent uk-margin-small-bottom">
Run compatibility test against the OpenAIRE literature guidelines.
</h3>
</div>
</div>
</div>
<div class="uk-width-expand@m uk-width-1-3@s uk-grid-item-match uk-first-column">
<div class="uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium" uk-scrollspy-class="" data-id="" style="">
<a class="el-link uk-position-cover uk-margin-remove-adjacent" [routerLink]="['data']" [queryParams]="{ step: 'baseUrl' }"></a>
<div class="uk-card-media-top">
<img class="el-image" src="../../../assets/imgs/Data_repos_wide.png" alt="" style="width:100%;">
</div>
<div class="uk-card-body">
<h3 class="el-title uk-margin uk-card-title uk-margin-remove-adjacent uk-margin-small-bottom">
Run compatibility test against the OpenAIRE Guidelines for Data Archives.
</h3>
</div>
</div>
</div>
<div class="uk-width-expand@m uk-width-1-3@s uk-grid-item-match uk-first-column">
<div class="uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium" uk-scrollspy-class="" data-id="" style="">
<a class="el-link uk-position-cover uk-margin-remove-adjacent" [routerLink]="['cris']" [queryParams]="{ step: 'baseUrl' }"></a>
<div class="uk-card-media-top">
<img class="el-image" src="../../../assets/imgs/CRIS_wide.png" alt="" style="width:100%;">
</div>
<div class="uk-card-body">
<h3 class="el-title uk-margin uk-card-title uk-margin-remove-adjacent uk-margin-small-bottom">
Run compatibility test against the OpenAIRE Guidelines for CRIS Managers based on CERIF-XML.
</h3>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>

View File

@ -0,0 +1,13 @@
import { Component, OnInit } from '@angular/core';
@Component ({
selector: 'app-compatibility-validation',
templateUrl: 'compatibility-validate.component.html'
})
export class CompatibilityValidateComponent implements OnInit {
constructor() {}
ngOnInit() {}
}

View File

@ -0,0 +1,207 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Previous validations</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div *ngIf="successMessage" class="uk-alert uk-alert-success">{{ successMessage }}</div>
<div *ngIf="failureMessage" class="uk-alert uk-alert-danger">{{ failureMessage }}</div>
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big"
style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="jobsOfUser">
<div class="uk-grid page-controls">
<div class="uk-margin-bottom uk-width-1-1 filters">
<div class="links">
<div class="filterLabel">Filter by job type:</div>
<div class="inlineBlock">
<select class="form-control" #selectType (change)="getJobType(selectType.value)">
<option value="">--none selected--</option>
<option *ngFor="let type of jobTypes" value="{{type}}">{{type}}</option>
</select>
</div>
</div>
</div>
<div class="uk-margin-bottom uk-width-1-1 filters">
<div class="links uk-inline">
<div class="filterLabel" style="display: inline;">Filter validation jobs:</div>
<a class="uk-active"
[class.active]="currentFilter==='all'"
(click)="filterJobs('all')">All jobs ({{this.jobsOfUser.totalJobs}})</a>
<a class="uk-active"
[class.active]="currentFilter==='successful'"
(click)="filterJobs('successful')">successful ({{this.jobsOfUser.totalJobsSuccessful}})</a>
<a class="uk-active"
[class.active]="currentFilter==='failed'"
(click)="filterJobs('failed')">failed ({{this.jobsOfUser.totalJobsFailed}})</a>
<a class="uk-active"
[class.active]="currentFilter==='ongoing'"
(click)="filterJobs('ongoing')">ongoing ({{this.jobsOfUser.totalJobsOngoing}})</a>
</div>
<div class="show-options uk-inline" style="float: right;">
<div class="filterLabel" style="display: inline;">Jobs per page:</div>
<div class="inlineBlock">
<select #itemsPerPage class="form-control" (change)="getItemsPerPage(+itemsPerPage.value)">
<option value="10" selected>10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
</div>
</div>
</div>
<div class="contentAndPagerPanel">
<div>
<ul class="uk-pagination">
<li>
<a class="uk-link uk-link-muted" (click)="goToPreviousPage()">
<span class="uk-margin-small-right uk-pagination-previous uk-icon" uk-pagination-previous="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg"
icon="pagination-previous" ratio="1"></svg>
</span>
Previous
</a>
</li>
<li class="uk-margin-auto-left">
<a class="uk-link uk-link-muted" (click)="goToNextPage()">
Next
<span class="uk-margin-small-left uk-pagination-next uk-icon" uk-pagination-next="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg"
icon="pagination-next" ratio="1"></svg>
</span>
</a>
</li>
</ul>
<div class="resultsPageLabel">page {{ (totalPages > 0) ? currentPage+1 : 0 }} of {{ totalPages }}</div>
</div>
<div>
<div>
<div class="uk-overflow-auto uk-scrollspy-inview uk-animation-slide-top-medium uk-margin-top uk-margin-bottom">
<table class="uk-table uk-table-middle uk-table-striped" style="vertical-align: top !important;">
<thead>
<tr>
<th>Repository</th>
<th>Validation Type</th>
<th>Status</th>
<th>Score</th>
<th>Started</th>
<th>Guidelines</th>
<th>Actions</th>
<th></th>
</tr>
</thead>
<tr *ngIf="infoMessage">
<td colspan="7">{{ infoMessage }}</td>
</tr>
<tbody *ngIf="jobsOfUser && jobsOfUser.jobs">
<tr class="el-item" *ngFor="let job of jobsOfUser.jobs">
<td class="uk-table-shrink" style="vertical-align: top !important;">
<div class="el-title">{{ job.baseUrl }}</div>
</td>
<td class="uk-table-shrink" style="vertical-align: top !important;">
<div *ngIf="job.validationType.includes('C')" class="el-title">OAI Content</div>
<div *ngIf="job.validationType.includes('U')" class="el-title">OAI Usage</div>
</td>
<td class="uk-table-shrink" style="vertical-align: top !important;">
<div *ngIf="job.validationType.includes('C')" class="el-title">{{ job.contentJobStatus }}</div>
<div *ngIf="job.validationType.includes('U')" class="el-title">{{ job.usageJobStatus }}</div>
</td>
<td class="uk-table-shrink" style="vertical-align: top !important;">
<div *ngIf="job.validationType.includes('C')" class="el-title">{{ job.contentJobScore }}</div>
<div *ngIf="job.validationType.includes('U')" class="el-title">{{ job.usageJobScore }}</div>
</td>
<td class="uk-table-shrink" style="vertical-align: top !important;">
<div class="el-title">{{ job.started }}</div>
</td>
<td class="uk-table-shrink" style="vertical-align: top !important;">
<div class="el-title">{{ job.guidelinesShortName }}</div>
</td>
<td class="uk-table-shrink" style="vertical-align: top !important;">
<div class="el-link">
<div class="viewDetailsLinkWrapper">
<a class="viewDetails" [routerLink]="[job.id]">
View Results<i class="fa fa-angle-right"></i>
</a>
</div>
<div>
<a class="resubmitJob" (click)="resubmitJob(job.id.toString(), job.userEmail)">Resubmit Job<i class="fa fa-repeat"></i></a>
</div>
</div>
</td>
<td class="uk-table-shrink" style="vertical-align: top !important;">
<img type="image" [src]="getResultImage(job.validationStatus)" title="{{job.validationStatus}}">
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div>
<ul class="uk-pagination">
<li>
<a class="uk-link uk-link-muted" (click)="goToPreviousPage()">
<span class="uk-margin-small-right uk-pagination-previous uk-icon" uk-pagination-previous="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg"
icon="pagination-previous" ratio="1"></svg>
</span>
Previous
</a>
</li>
<li class="uk-margin-auto-left">
<a class="uk-link uk-link-muted" (click)="goToNextPage()">
Next
<span class="uk-margin-small-left uk-pagination-next uk-icon" uk-pagination-next="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg"
icon="pagination-next" ratio="1"></svg>
</span>
</a>
</li>
</ul>
<div class="resultsPageLabel">page {{ (totalPages > 0) ? currentPage+1 : 0 }} of {{ totalPages }}</div>
</div>
</div>
<div class="row"></div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>

View File

@ -0,0 +1,171 @@
import { Component, OnInit } from '@angular/core';
import { jobTypes } from '../../domain/job-types';
import { MonitorService } from '../../services/monitor.service';
import { AuthenticationService } from '../../services/authentication.service';
import { JobsOfUser, StoredJob } from '../../domain/typeScriptClasses';
import { ValidatorService } from '../../services/validator.service';
import { loadingUserJobs, loadingUserJobsError, noUserJobsFound } from '../../domain/shared-messages';
import { URLParameter } from '../../domain/url-parameter';
@Component ({
selector: 'app-compatibility-validation-history',
templateUrl: 'compatibility-validation-history.component.html'
})
export class CompatibilityValidationHistoryComponent implements OnInit {
userEmail: string;
loadingMessage: string;
errorMessage: string;
infoMessage: string;
successMessage: string;
failureMessage: string;
jobTypes: string[];
jobsOfUser: JobsOfUser;
jobs: StoredJob[];
itemsPerPage: number;
currentPage: number;
currentTotalJobs: number;
totalPages: number;
currentFilter: string;
chosenJobType: string;
constructor(private authService: AuthenticationService,
private monitorService: MonitorService,
private valService: ValidatorService) {}
ngOnInit() {
this.loadTable();
}
loadTable() {
// initialize
this.userEmail = this.authService.getUserEmail();
this.jobTypes = jobTypes;
this.itemsPerPage = 10;
this.currentPage = 0;
this.currentFilter = 'all';
this.chosenJobType = '';
// call API and get all jobs:
this.getJobs();
}
getJobType(type: string) {
this.chosenJobType = type;
this.currentPage = 0;
this.getJobs();
}
filterJobs(filter: string) {
this.currentFilter = filter;
this.currentPage = 0;
console.log(`requesting ${this.currentFilter} jobs`);
this.getJobs();
}
getItemsPerPage(num: number) {
this.itemsPerPage = num;
this.currentPage = 0;
this.getJobs();
}
goToNextPage() {
if ( (this.currentPage + 1) < this.totalPages ) {
this.currentPage++;
console.log(`Get me page ${this.currentPage}!`);
this.getJobs();
}
}
goToPreviousPage() {
if (this.currentPage > 0) {
this.currentPage--;
console.log(`Get me page ${this.currentPage}!`);
this.getJobs();
}
}
storedJobs () {
this.valService.getStoredJobsNew().subscribe(
jobs => this.jobs = jobs,
error => console.log(error.status),
() => {
console.log('Also hit getStoredJobsNew and got:');
console.log(this.jobs);
}
);
}
getJobs() {
this.loadingMessage = loadingUserJobs;
this.errorMessage = '';
this.infoMessage = '';
this.successMessage = '';
this.failureMessage = '';
const params: URLParameter[] = [];
// params.push({key: 'user', value: [this.userEmail]});
if ( this.chosenJobType ) {
params.push({key: 'jobType', value: [this.chosenJobType]});
}
params.push({key: 'offset', value: [( (this.currentPage) * this.itemsPerPage).toString()]});
params.push({key: 'limit', value: [this.itemsPerPage.toString()]});
/* can also add dateFrom and dateTo if needed */
params.push({key: 'validationStatus', value: [this.currentFilter]});
params.push({key: 'includeJobsTotal', value: ['true']});
this.monitorService.getJobsOfUser(params).subscribe(
jobs => this.jobsOfUser = jobs,
error => {
console.log(`The API returned ${error.status}`);
this.loadingMessage = '';
this.jobsOfUser = null;
this.errorMessage = loadingUserJobsError;
},
() => {
if (this.currentFilter === 'all') {
this.currentTotalJobs = this.jobsOfUser.totalJobs;
} else if (this.currentFilter === 'successful') {
this.currentTotalJobs = this.jobsOfUser.totalJobsSuccessful;
} else if (this.currentFilter === 'failed') {
this.currentTotalJobs = this.jobsOfUser.totalJobsFailed;
} else {
this.currentTotalJobs = this.jobsOfUser.totalJobsOngoing;
}
this.totalPages = Math.ceil(this.currentTotalJobs / this.itemsPerPage);
this.loadingMessage = '';
if (!this.totalPages || !this.jobsOfUser.jobs) {
this.infoMessage = noUserJobsFound;
this.currentPage = -1;
}
}
);
}
getResultImage(status: string) {
if (status === 'ongoing') {
return `../../../assets/imgs/icon_colours-question.jpg`;
} else if (status === 'successful') {
return `../../../assets/imgs/icon_colours-check.jpg`;
} else {
return `../../../assets/imgs/icon_colours-x.jpg`;
}
}
resubmitJob (id: string) {
this.valService.reSubmitJobForValidation(id).subscribe(
res => this.successMessage = `The job with id ${id} was successfully resubmitted`,
error => {
this.failureMessage = `Could not resubmit the job with id ${id}`;
console.log(error);
}
);
this.getJobs();
}
}

View File

@ -0,0 +1,256 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Validation results for</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div>
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big"
style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="jobSummary">
<div>
<div>
<h4 class="uk-h4 uk-text-primary uk-scrollspy-inview uk-animation-slide-top-medium"
uk-scrollspy-class=""><span>{{jobSummary.baseUrl}}</span></h4>
<div class="uk-margin-small">by {{jobSummary.userEmail}}</div>
</div>
</div>
<div>
<div>
<hr class="uk-scrollspy-inview uk-animation-slide-bottom-small" uk-scrollspy-class="">
<div>
<span>{{ jobSummary.jobType }}</span>
|
<span>{{ jobSummary.guidelinesShortName }}</span>
|
<span>Validation set: {{ jobSummary.validationSet }}</span>
</div>
<div>
<span>Started: {{ jobSummary.started }}</span>
,
<span>Ended: {{ jobSummary.ended ? jobSummary.ended : '--' }}</span>
,
<span>Duration: {{ jobSummary.duration }}</span>
</div>
<div style="font-size: 120%;">
<span>Records tested: {{ jobSummary.recordsTested }}</span>
</div>
<div>
<span class="uk-label uk-margin-right">Score for content: {{ jobSummary.contentJobScore }}</span>
<span class="uk-label">Score for usage: {{ jobSummary.usageJobScore }}</span>
</div>
<hr class="uk-scrollspy-inview uk-animation-slide-bottom-small" uk-scrollspy-class="">
</div>
</div>
<div>
<ul class="uk-margin el-nav uk-tab" uk-switcher="connect: .uk-switcher">
<li routerLinkActive="uk-active">
<a href="#">for Content</a>
</li>
<li routerLinkActive="uk-active">
<a href="#">for Usage</a>
</li>
</ul>
<ul class="uk-switcher">
<li class="el-item">
<div class="uk-grid-margin uk-grid uk-grid-stack">
<div class="uk-width-1-1@m uk-first-column">
<div class="uk-overflow-auto uk-scrollspy-inview uk-animation-slide-top-medium">
<div *ngIf="noContent" class="uk-alert">{{ noContent }}</div>
<div *ngIf="contentResults && contentResults.length > 0">
<table class="uk-table uk-table-striped uk-table-middle rules-table">
<thead>
<tr>
<th>Rule Name</th>
<th class="uk-text-nowrap">Rule Description</th>
<th class="uk-text-nowrap">Rule Weight</th>
<th class="uk-text-nowrap"># of records</th>
<th class="uk-text-nowrap">Status</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let contentRule of contentResults" class="el-item">
<td class="uk-table-shrink">
<div class="el-title">{{ contentRule.name }}</div>
</td>
<td class="uk-table-shrink">
<div class="el-title" [innerHtml]="contentRule.description">
</div>
</td>
<td class="uk-table-shrink">
<div class="el-title">{{ contentRule.weight }}</div>
</td>
<td class="uk-table-shrink">
<div class="el-title">{{ contentRule.successes }}</div>
</td>
<td class="uk-table-shrink">
<div *ngIf="!contentRule.hasErrors" class="el-title">
<span uk-icon="icon: check" style="color: #4b991f" class="uk-icon">
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="check" ratio="1">
<polyline fill="none" stroke="#000" stroke-width="1.1"
points="4,10 8,15 17,4"></polyline>
</svg>-->
</span>
</div>
<div *ngIf="contentRule.hasErrors && contentRule.mandatory">
<span uk-icon="icon: close" style="color: #cd242b" class="uk-icon">
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="close" ratio="1">
<path fill="none" stroke="#000" stroke-width="1.06" d="M16,16 L4,4"></path>
<path fill="none" stroke="#000" stroke-width="1.06" d="M16,4 L4,16"></path>
</svg>-->
</span>
<a class="errorlink viewErrors uk-display-block"
(click)="viewErrors(contentRule)"><span>View Errors</span></a>
</div>
<div *ngIf="contentRule.hasErrors && !contentRule.mandatory">
<span uk-icon="icon: warning" style="color: #e9d60d" class="uk-icon">
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="warning" ratio="1">
<circle cx="10" cy="14" r="1"></circle>
<circle fill="none" stroke="#000" stroke-width="1.1" cx="10" cy="10" r="9"></circle>
<path
d="M10.97,7.72 C10.85,9.54 10.56,11.29 10.56,11.29 C10.51,11.87 10.27,12 9.99,12 C9.69,12 9.49,11.87 9.43,11.29 C9.43,11.29 9.16,9.54 9.03,7.72 C8.96,6.54 9.03,6 9.03,6 C9.03,5.45 9.46,5.02 9.99,5 C10.53,5.01 10.97,5.44 10.97,6 C10.97,6 11.04,6.54 10.97,7.72 L10.97,7.72 Z"></path>
</svg>-->
</span>
<a class="warninglink viewErrors uk-display-block"
(click)="viewErrors(contentRule)"><span>View Warnings</span></a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</li>
<li class="el-item">
<div class="uk-grid-margin uk-grid uk-grid-stack">
<div class="uk-width-1-1@m uk-first-column">
<div class="uk-overflow-auto uk-scrollspy-inview uk-animation-slide-top-medium">
<div *ngIf="noUsage" class="uk-alert">{{ noUsage }}</div>
<div *ngIf="usageResults && usageResults.length > 0">
<table class="uk-table uk-table-striped uk-table-middle rules-table">
<thead>
<tr>
<th>Rule Name</th>
<th class="uk-text-nowrap">Rule Description</th>
<th class="uk-text-nowrap">Rule Weight</th>
<th class="uk-text-nowrap"># of records</th>
<th class="uk-text-nowrap">Status</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let usageRule of usageResults" class="el-item">
<td class="uk-table-shrink">
<div class="el-title">{{ usageRule.name }}</div>
</td>
<td class="uk-table-shrink">
<div class="el-title" [innerHtml]="usageRule.description">
</div>
</td>
<td class="uk-table-shrink">
<div class="el-title">{{ usageRule.weight }}</div>
</td>
<td class="uk-table-shrink">
<div class="el-title">{{ usageRule.successes }}</div>
</td>
<td class="uk-table-shrink">
<div *ngIf="!usageRule.hasErrors" class="el-title">
<span uk-icon="icon: check" style="color: #4b991f" class="uk-icon">
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="check" ratio="1">
<polyline fill="none" stroke="#000" stroke-width="1.1"
points="4,10 8,15 17,4"></polyline>
</svg>-->
</span>
</div>
<div *ngIf="usageRule.hasErrors && usageRule.mandatory">
<span uk-icon="icon: close" style="color: #cd242b" class="uk-icon">
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="close" ratio="1">
<path fill="none" stroke="#000" stroke-width="1.06" d="M16,16 L4,4"></path>
<path fill="none" stroke="#000" stroke-width="1.06" d="M16,4 L4,16"></path>
</svg>-->
</span>
<a class="errorlink viewErrors uk-display-block"
(click)="viewErrors(usageRule)"><span>View Errors</span></a>
</div>
<div *ngIf="usageRule.hasErrors && !usageRule.mandatory">
<span uk-icon="icon: warning" style="color: #e9d60d" class="uk-icon">
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="warning" ratio="1">
<circle cx="10" cy="14" r="1"></circle>
<circle fill="none" stroke="#000" stroke-width="1.1" cx="10" cy="10" r="9"></circle>
<path
d="M10.97,7.72 C10.85,9.54 10.56,11.29 10.56,11.29 C10.51,11.87 10.27,12 9.99,12 C9.69,12 9.49,11.87 9.43,11.29 C9.43,11.29 9.16,9.54 9.03,7.72 C8.96,6.54 9.03,6 9.03,6 C9.03,5.45 9.46,5.02 9.99,5 C10.53,5.01 10.97,5.44 10.97,6 C10.97,6 11.04,6.54 10.97,7.72 L10.97,7.72 Z"></path>
</svg>-->
</span>
<a class="warninglink viewErrors uk-display-block"
(click)="viewErrors(usageRule)"><span>View Warnings</span></a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>
<confirmation-dialog #checkErrors [title]="modalTitle" [isModalShown]="false" [hideModalButton]="'OK'">
<div>
<p>See the list of errors found for this specific rule</p>
<a *ngFor="let er of currentErrors" class="uk-display-block" target="_blank" href="{{ linkToError(er) }}">{{ er }}</a>
</div>
</confirmation-dialog>

View File

@ -0,0 +1,96 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { JobResultEntry, StoredJob } from '../../domain/typeScriptClasses';
import { MonitorService } from '../../services/monitor.service';
import { loadingJobSummary, loadingJobSummaryError, noContentRulesResults,
noUsageRulesResults } from '../../domain/shared-messages';
import { ConfirmationDialogComponent } from '../../shared/reusablecomponents/confirmation-dialog.component';
import { AuthenticationService } from '../../services/authentication.service';
@Component({
selector: 'app-compatibility-validation-results',
templateUrl: 'compatibility-validation-results.component.html'
})
export class CompatibilityValidationResultsComponent implements OnInit {
errorMessage: string;
loadingMessage: string;
noRulesTested: string;
noContent: string;
noUsage: string;
jobSummary: StoredJob;
contentResults: JobResultEntry[] = [];
usageResults: JobResultEntry[] = [];
currentErrors: string[] = [];
modalTitle: string;
isModalShown: boolean;
@ViewChild('checkErrors')
public checkErrors: ConfirmationDialogComponent;
constructor (private route: ActivatedRoute,
private router: Router,
private monitorService: MonitorService,
private authService: AuthenticationService) {}
ngOnInit () {
if (this.authService.getIsUserLoggedIn()) {
this.getJobInfo();
} else {
const id = this.route.snapshot.paramMap.get('id');
this.authService.redirectUrl = '/compatibility/browseHistory/' + id;
this.authService.loginWithState();
}
}
getJobInfo() {
const id = this.route.snapshot.paramMap.get('id');
this.loadingMessage = loadingJobSummary;
this.monitorService.getJobSummary(id, 'all').subscribe(
job => {
this.jobSummary = job;
if (this.jobSummary.resultEntries && this.jobSummary.resultEntries.length) {
this.jobSummary.resultEntries.forEach(
entry => {
if (entry.type === 'content') {
this.contentResults.push(entry);
} else if (entry.type === 'usage') {
this.usageResults.push(entry);
}
}
);
}
},
error => {
console.log(error);
this.errorMessage = loadingJobSummaryError;
this.loadingMessage = '';
},
() => {
this.loadingMessage = '';
if (!this.contentResults.length) {
this.noContent = noContentRulesResults;
}
if (!this.usageResults.length) {
this.noUsage = noUsageRulesResults;
}
/*if ( this.authService.activateFrontAuthorization && (this.authService.getUserEmail() !== this.jobSummary.userEmail.trim()) ) {
this.router.navigateByUrl('/403-forbidden', { skipLocationChange: true });
}*/
}
);
}
viewErrors(rule: JobResultEntry) {
this.modalTitle = `Rule: ${rule.name}`;
this.currentErrors = rule.errors;
this.checkErrors.showModal();
}
linkToError(er: string) {
return encodeURI(`${this.jobSummary.baseUrl}?verb=GetRecord&metadataPrefix=${this.jobSummary.metadataPrefix}&identifier=${er}`);
}
}

View File

@ -0,0 +1,12 @@
import {Component, OnInit} from '@angular/core';
@Component ({
selector: 'app-compatibility',
templateUrl: '../pageContainer.html'
})
export class CompatibilityComponent implements OnInit {
constructor() {}
ngOnInit() {}
}

View File

@ -0,0 +1,44 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TabsModule } from 'ngx-bootstrap';
import { ReactiveFormsModule } from '@angular/forms';
import { CompatibilityRouting } from './compatibility.routing';
import { ReusableComponentsModule } from '../../shared/reusablecomponents/reusable-components.module';
import { CompatibilityComponent } from './compatibility.component';
import { CompatibilityValidateComponent } from './compatibility-validate.component';
import { CompatibilityValidationHistoryComponent } from './compatibility-validation-history.component';
import { CompatibilityValidationResultsComponent } from './compatibility-validation-results.component';
import { CompatibilityMonitorComponent } from './compatibility-monitor.component';
import { CompatibilityMonitorRepoComponent } from './compatibility-monitor-repo.component';
import { CompatibilityMonitorFullHistoryRepoComponent } from './compatibility-monitor-fullHistory-repo.component';
import { CompatibilityValidateTypeComponent } from './compatibility-validate-type.component';
import { CompatibilityValidateStep1Component } from './compatibility-validate-forms/compatibility-validate-step1.component';
import { CompatibilityValidateStep2Component } from './compatibility-validate-forms/compatibility-validate-step2.component';
import { CompatibilityValidateStep3Component } from './compatibility-validate-forms/compatibility-validate-step3.component';
import { CompatibilityValidateStep3CrisComponent } from './compatibility-validate-forms/compatibility-validate-step3-cris.component';
@NgModule ({
imports: [
CommonModule,
TabsModule.forRoot(),
ReactiveFormsModule,
CompatibilityRouting,
ReusableComponentsModule
],
declarations: [
CompatibilityComponent,
CompatibilityValidateComponent,
CompatibilityValidationHistoryComponent,
CompatibilityValidationResultsComponent,
CompatibilityMonitorComponent,
CompatibilityMonitorRepoComponent,
CompatibilityMonitorFullHistoryRepoComponent,
CompatibilityValidateTypeComponent,
CompatibilityValidateStep1Component,
CompatibilityValidateStep2Component,
CompatibilityValidateStep3Component,
CompatibilityValidateStep3CrisComponent
]
})
export class CompatibilityModule {}

View File

@ -0,0 +1,62 @@
import { NgModule} from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CompatibilityComponent } from './compatibility.component';
import { CompatibilityValidateTypeComponent } from './compatibility-validate-type.component';
import { CompatibilityValidationHistoryComponent } from './compatibility-validation-history.component';
import { CompatibilityValidationResultsComponent } from './compatibility-validation-results.component';
import { CompatibilityMonitorComponent } from './compatibility-monitor.component';
import { CompatibilityMonitorRepoComponent } from './compatibility-monitor-repo.component';
import { CompatibilityMonitorFullHistoryRepoComponent } from './compatibility-monitor-fullHistory-repo.component';
import { CompatibilityValidateComponent } from './compatibility-validate.component';
import { AuthGuardService } from '../../services/auth-guard.service';
const compatibilityRoutes: Routes = [
{
path: '',
component: CompatibilityComponent,
children: [
{
path: 'validate',
component: CompatibilityValidateComponent,
canActivate: [AuthGuardService]
},
{
path: 'validate/:type',
component: CompatibilityValidateTypeComponent,
canActivate: [AuthGuardService]
},
{
path: 'browseHistory',
component: CompatibilityValidationHistoryComponent,
canActivate: [AuthGuardService]
},
{
path: 'browseHistory/:id',
component: CompatibilityValidationResultsComponent
},
{
path: 'monitor',
component: CompatibilityMonitorComponent,
canActivate: [AuthGuardService]
},
{
path: 'monitor/:id',
component: CompatibilityMonitorRepoComponent,
canActivate: [AuthGuardService]
},
{
path: 'monitor/fullHistory/:id',
component: CompatibilityMonitorFullHistoryRepoComponent,
canActivate: [AuthGuardService]
}
]
}
];
@NgModule ({
imports: [RouterModule.forChild(compatibilityRoutes)],
exports: [RouterModule]
})
export class CompatibilityRouting {}

View File

@ -0,0 +1,524 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">{{ repoName }}</h1>
<div class="uk-text uk-text-small uk-text-secondary">{{ topic }}</div>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div>
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{errorMessage}}</div>
<div *ngIf="successMessage" class="uk-alert uk-alert-success">{{successMessage}}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">{{ loadingMessage }}</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="noEvents" class="uk-alert">{{ noEvents }}</div>
<div *ngIf="!noEvents && !loadingMessage && !errorMessage && eventsPage && eventsPage.totalPages>0" class="events-results">
<div class="numberOfEventsLabel">
<!-- RESTORE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<!--<span>Showing {{(eventsPage.currPage*10)+1 }}-{{ ( (eventsPage.total < 10) || (eventsPage.total < (eventsPage.currPage+1)*10) ) ? (eventsPage.total) : (eventsPage.currPage+1)*10 }} of {{ eventsPage.total }} results</span>-->
<!-- DELETE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<span>Showing {{(currentPage*10)+1 }}-{{ ( (eventsPage.total < 10) || (eventsPage.total < (currentPage+1)*10) ) ? (eventsPage.total) : (currentPage+1)*10 }} of {{ eventsPage.total }} results</span>
<span class="uk-float-right">
<button id="subscribe" type="button" class="uk-button uk-button-primary uk-button-small" (click)="showSubscriptionModal()">Subscribe to these events</button>
</span>
</div>
<div>
<ul class="uk-pagination">
<li>
<a class="uk-link uk-link-muted" (click)="goToPreviousPage()">
<span class="uk-margin-small-right uk-pagination-previous uk-icon" uk-pagination-previous="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg" icon="pagination-previous" ratio="1"></svg>
</span>
Previous
</a>
</li>
<li class="uk-margin-auto-left">
<a class="uk-link uk-link-muted" (click)="goToNextPage()">
Next
<span class="uk-margin-small-left uk-pagination-next uk-icon" uk-pagination-next="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg" icon="pagination-next" ratio="1"></svg>
</span>
</a>
</li>
</ul>
<!-- RESTORE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<!--<div class="resultsPageLabel">page {{ eventsPage.currPage+1 }} of {{ eventsPage.totalPages }}</div>-->
<!-- DELETE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<div class="resultsPageLabel">page {{ (eventsPage.totalPages > 0) ? currentPage+1 : 0 }} of {{ eventsPage.totalPages }}</div>
</div>
<div *ngFor="let event of eventsPage.values" class="events-list">
<div class="uk-card uk-card-default well uk-scrollspy-inview uk-animation-slide-top-medium">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<p class="text-right"><span class="uk-label">Trust: {{ event.trust }}</span></p>
<div class="uk-overflow-auto uk-scrollspy-inview uk-animation-slide-top-medium">
<table class="uk-table uk-table-striped uk-table-middle">
<tbody>
<tr class="el-item">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">ID</strong></td>
<td class="uk-table-shrink">
<div class="el-title">{{ event.publication.originalId }}</div>
</td>
</tr>
<tr class="el-item">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Title(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let t of event.publication.titles; let ti_index = index">
<br *ngIf="ti_index>0">
<span>{{ t }}</span>
</span>
</div>
</td>
</tr>
<tr class="el-item">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Author(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let auth of event.publication.creators; let au_index = index">
<span *ngIf="au_index>0"> | </span>
<span>{{ auth }}</span>
</span>
</div>
</td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.pids && event.highlight.pids.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">PID(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let pid of event.publication.pids; let a_index = index">
<br *ngIf="a_index > 0">
<span>{{ pid.value }} <b>&nbsp;&nbsp;({{ pid.type }})&nbsp;&nbsp;</b>
<span *ngFor="let hl_pid of event.highlight.pids">
<span *ngIf="hl_pid.value.indexOf(pid.value)>=0 && event.highlight.pids.length>0 && event.provenance">
<span class="uk-label uk-label-success">added</span>
<span class="pull-right">
<b>from: </b>
<ng-container *ngIf="event.provenance.url">
<a href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</ng-container>
<ng-container *ngIf="!event.provenance.url">
<span>{{ event.provenance.repositoryName }}</span>
</ng-container>
</span>
</span>
</span>
</span>
</span>
</div>
</td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.abstracts && event.highlight.abstracts.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Abstract(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let abs of event.publication.abstracts; let a_index = index">
<br *ngIf="a_index > 0 && event.publication.abstracts[a_index-1].length > 0">
<span>{{ abs }}</span>
<span *ngIf="event.highlight.abstracts.indexOf(abs)>=0 && event.highlight.abstracts.length>0 && event.provenance">
<span class="pull-right">
<b>from: </b>
<ng-container *ngIf="event.provenance.url">
<a href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</ng-container>
<ng-container *ngIf="!event.provenance.url">
<span>{{ event.provenance.repositoryName }}</span>
</ng-container>
</span>
</span>
</span>
</div>
</td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.projects && event.highlight.projects.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Project(s)/Relation(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let proj of event.publication.projects; let p_index = index">
<br *ngIf="p_index > 0">
<span *ngIf="proj.acronym && proj.acronym !==''">{{ proj.acronym }}</span>
<span *ngIf="!proj.acronym || proj.acronym ===''">{{ proj.title }}</span>
<span *ngIf="(proj.funder && proj.funder !=='') ||
(proj.fundingProgram && proj.fundingProgram !=='')">
(<span *ngIf="proj.funder && proj.funder !==''">{{ proj.funder }} </span>
<span *ngIf="(proj.funder && proj.funder !=='') &&
(proj.fundingProgram && proj.fundingProgram !=='')">/</span>
<span *ngIf="proj.fundingProgram && proj.fundingProgram !==''">{{ proj.fundingProgram }}</span>)
</span>
<span *ngFor="let hl_proj of event.highlight.projects">
<span *ngIf="hl_proj.code.indexOf(proj.code)>=0 && event.highlight.projects.length>0 && event.provenance">
<span class="pull-right">
<b>from: </b>
<ng-container *ngIf="event.provenance.url">
<a href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</ng-container>
<ng-container *ngIf="!event.provenance.url">
<span>{{ event.provenance.repositoryName }}</span>
</ng-container>
</span>
</span>
</span>
</span>
</div>
</td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.subjects && event.highlight.subjects.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Subject(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let subj of event.publication.subjects; let s_index = index">
<br *ngIf="s_index > 0">
<span>{{ subj }}</span>
<span *ngIf="event.highlight.subjects.indexOf(subj)>=0 && event.highlight.subjects.length>0 && event.provenance">
<span class="pull-right">
<b>from: </b>
<ng-container *ngIf="event.provenance.url">
<a href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</ng-container>
<ng-container *ngIf="!event.provenance.url">
<span>{{ event.provenance.repositoryName }}</span>
</ng-container>
</span>
</span>
</span>
</div>
</td>
</tr>
<!--Publications-->
<tr class="el-item" [ngClass]="{'success': event.highlight.publications && event.highlight.publications.length>0 }">
<td *ngIf="this.topic.includes('PUBLICATION')" class="uk-table-shrink uk-width-1-4">
<strong class="el-title uk-display-block">{{this.lastTopicEntry}}<br>Publication(s)</strong>
</td>
<td *ngIf="!(this.topic.includes('PUBLICATION'))"
class="uk-table-shrink uk-width-1-4">
<strong class="el-title uk-display-block">Publication(s)</strong>
</td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let pub of event.publication.publications; let s_index = index">
<br *ngIf="s_index > 0">
<span>{{ pub.titles[0] }} (ID: {{pub.originalId}})</span>
<span *ngFor="let hl_pub of event.highlight.publications">
<span *ngIf="hl_pub.originalId.indexOf(pub.originalId)>=0 && event.highlight.publications.length>0 && event.provenance">
<span class="pull-right">
<b>from: </b>
<ng-container *ngIf="event.provenance.url">
<a href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</ng-container>
<ng-container *ngIf="!event.provenance.url">
<span>{{ event.provenance.repositoryName }}</span>
</ng-container>
</span>
</span>
</span>
</span>
</div>
</td>
</tr>
<!--Datasets-->
<tr class="el-item" [ngClass]="{'success': event.highlight.datasets && event.highlight.datasets.length>0 }">
<td *ngIf="this.topic.includes('DATASET')" class="uk-table-shrink uk-width-1-4">
<strong class="el-title uk-display-block">{{this.lastTopicEntry}}<br>Dataset(s)</strong>
</td>
<td *ngIf="!(this.topic.includes('DATASET'))" class="uk-table-shrink uk-width-1-4">
<strong class="el-title uk-display-block">Dataset(s)</strong>
</td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let dataset of event.publication.datasets; let s_index = index">
<br *ngIf="s_index > 0">
<span>{{ dataset.titles[0] }} <span *ngIf="dataset.pids && dataset.pids.length>0">({{dataset.pids[0].type}}: {{dataset.pids[0].value}})</span></span>
<span *ngFor="let hl_dataset of event.highlight.datasets">
<span *ngIf="hl_dataset.pids.indexOf(dataset.pids[s_index])>=0 && event.highlight.datasets.length>0 && event.provenance">
<span class="pull-right">
<b>from: </b>
<ng-container *ngIf="event.provenance.url">
<a href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</ng-container>
<ng-container *ngIf="!event.provenance.url">
<span>{{ event.provenance.repositoryName }}</span>
</ng-container>
</span>
</span>
</span>
</span>
</div>
</td>
</tr>
<!--Software-->
<tr class="el-item" [ngClass]="{'success': event.highlight.softwares && event.highlight.softwares.length>0 }">
<td *ngIf="this.topic.includes('SOFTWARE')" class="uk-table-shrink uk-width-1-4">
<strong class="el-title uk-display-block">Software</strong>
</td>
<td *ngIf="!(this.topic.includes('SOFTWARE'))" class="uk-table-shrink uk-width-1-4">
<strong class="el-title uk-display-block">Software</strong>
</td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let software of event.publication.softwares; let s_index = index">
<br *ngIf="s_index > 0">
<span>{{ software.name }}</span>
<span *ngIf="software.description"> <br> {{ software.description }}</span>
<span><br><a href="{{ software.landingPage }}" target="_blank">{{ software.landingPage }}</a></span>
<span *ngIf="software.landingPage !== software.repository"><br><a href="{{ software.repository }}" target="_blank">{{ software.repository }}</a></span>
<span *ngFor="let hl_software of event.highlight.softwares">
<span *ngIf="hl_software.name.indexOf(software.name)>=0 && event.highlight.softwares.length>0 && event.provenance">
<span class="pull-right">
<b>from: </b>
<ng-container *ngIf="event.provenance.url">
<a href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</ng-container>
<ng-container *ngIf="!event.provenance.url">
<span>{{ event.provenance.repositoryName }}</span>
</ng-container>
</span>
</span>
</span>
</span>
</div>
</td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.publicationdate && event.highlight.publicationdate.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Publication date</strong></td>
<td class="uk-table-shrink"><div class="el-title">{{ event.publication.publicationdate }}</div></td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.instances && event.highlight.instances.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Rights</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let l of event.publication.instances; let l_index = index">
<br *ngIf="l_index > 0">
<span>
{{ l.license }}&nbsp;&nbsp;<b>{{ l.hostedby }}</b><br>
<a href="{{ l.url }}" target="_blank">{{ l.url }}</a>
</span>
<span *ngFor="let hl of event.highlight.instances">
<span *ngIf="hl.hostedby.indexOf(l.hostedby)>=0 && event.highlight.instances.length>0 && event.provenance">
&nbsp;&nbsp;<span class="uk-label uk-label-success">added</span>&nbsp;&nbsp;
<b>from: </b>
<ng-container *ngIf="event.provenance.url">
<a href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</ng-container>
<ng-container *ngIf="!event.provenance.url">
<span>{{ event.provenance.repositoryName }}</span>
</ng-container>
</span>
</span>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div>
<ul class="uk-pagination">
<li>
<a class="uk-link uk-link-muted" (click)="goToPreviousPage()">
<span class="uk-margin-small-right uk-pagination-previous uk-icon" uk-pagination-previous="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg" icon="pagination-previous" ratio="1"></svg>
</span>
Previous
</a>
</li>
<li class="uk-margin-auto-left">
<a class="uk-link uk-link-muted" (click)="goToNextPage()">
Next
<span class="uk-margin-small-left uk-pagination-next uk-icon" uk-pagination-next="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg" icon="pagination-next" ratio="1"></svg>
</span>
</a>
</li>
</ul>
<!-- RESTORE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<!--<div class="resultsPageLabel">page {{ eventsPage.currPage+1 }} of {{ eventsPage.totalPages }}</div>-->
<!-- DELETE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<div class="resultsPageLabel">page {{ (eventsPage.totalPages > 0) ? currentPage+1 : 0 }} of {{ eventsPage.totalPages }}</div>
</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT CAN'T BE USED IN THIS PAGE -->
<div [formGroup]="group" class="tm-sidebar uk-width-1-4@m">
<div class="enrichContentAdvancedSearch uk-card uk-card-body uk-card-default sidemenu">
<div>
<h6 class="uk-h6 uk-text-primary uk-scrollspy-inview uk-animation-slide-top-medium" uk-scrollspy-class="">
<span>Tweak and refine events</span>
</h6>
</div>
<div role="form" class="uk-form-horizontal">
<div class="uk-form-horizontal">
<div class="form-group">
<label class="control-label">Trust [{{group.get('trustMin').value}} - {{group.get('trustMax').value}}]</label><br>
<input type="range" min="0" max="1" step="0.05" formControlName="trustMin" class="uk-range"/>
<input type="range" min="0" max="1" step="0.05" formControlName="trustMax" class="uk-range"/>
</div>
</div>
<div class="uk-form-horizontal">
<div class="form-group">
<label class="control-label" style="display: block;">Title</label>
<div formArrayName="eventTitles" *ngFor="let title of eventTitleFormArray; let title_index = index">
<div [formGroupName]="title_index">
<input class="form-control inlineBlock" style="width:88%;" type="text" formControlName="eventTitle">
<a class="inlineBlock deleteIcon" (click)="removeControl('eventTitles',title_index)"><i class="fa fa-remove"></i></a>
</div>
</div>
<a (click)="addControl('eventTitles',titleDefinition)"><i class="fa fa-plus"></i> Add another</a>
</div>
</div>
<div class="uk-form-horizontal">
<div class="form-group">
<label class="control-label" style="display: block;">Author</label>
<div formArrayName="eventAuthors" *ngFor="let author of eventAuthorFormArray; let author_index = index">
<div [formGroupName]="author_index">
<input class="form-control inlineBlock" style="width:88%;" type="text" formControlName="eventAuthor">
<a class="inlineBlock deleteIcon" (click)="removeControl('eventAuthors',author_index)"><i class="fa fa-remove"></i></a>
</div>
</div>
<a (click)="addControl('eventAuthors', authorDefinition)"><i class="fa fa-plus"></i> Add another</a>
</div>
</div>
<div class="uk-form-horizontal">
<div class="form-group">
<label class="control-label" style="display: block;">Subject</label>
<div formArrayName="eventSubjects" *ngFor="let subject of eventSubjectsFormArray; let subject_index = index">
<div [formGroupName]="subject_index">
<input class="form-control inlineBlock" style="width:88%;" type="text" formControlName="eventSubject">
<a class="inlineBlock deleteIcon" (click)="removeControl('eventSubjects', subject_index)"><i class="fa fa-remove"></i></a>
</div>
</div>
<a (click)="addControl('eventSubjects', subjectDefinition)"><i class="fa fa-plus"></i> Add another</a>
</div>
</div>
<div>
<div class="uk-form-horizontal">
<div class="form-group">
<label class="control-label" style="display: block;">Date</label>
<div formArrayName="eventDateRanges" *ngFor="let date of eventDateRangesFormArray; let date_index = index">
<div class="uk-form" style="position: relative;" [formGroupName]=date_index>
<input class="form-control inlineBlock dateFrom" style="width:88%;"
placeholder="From"
type="text"
onfocus="(this.type='date')"
formControlName=dateFrom>
<input class="form-control inlineBlock dateTo" style="width:88%;"
placeholder="To"
type="text"
onfocus="(this.type='date')"
formControlName=dateTo>
<a class="inlineBlock deleteIcon" (click)="removeControl('eventDateRanges',date_index)"><i class="fa fa-remove" style=""></i></a>
</div>
</div>
<a (click)="addControl('eventDateRanges', dateRangeDefinition)"><i class="fa fa-plus"></i> Add another</a>
</div>
</div>
</div>
<div role="form" class="form-horizontal">
<div class="form-group">
<div class="actionButtons">
<button type="button" (click)="updateQuery()" class="uk-button uk-button-primary advancedSearch uk-margin-small-right">Apply</button>
<button type="reset" (click)="clearForm()" class="uk-button uk-button-default clearCriteria">Clear</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>
<confirmation-dialog #subscribeToEventsModal [title]="'Create subscription for'" [isModalShown]="isModalShown"
[confirmActionButton]="'Subscribe'" (emitObject)="subscribeToEvents($event)">
<div *ngIf="eventsPage">
<div *ngIf="modalErrorMessage" class="uk-alert uk-alert-danger">{{ modalErrorMessage }}</div>
<div>
<h4 class="uk-h4">{{ eventsPage.datasource }}</h4>
<div class="uk-text uk-text-small uk-text-secondary">{{ eventsPage.topic }}</div>
</div>
<div>
<div class="form-group">
<label class="control-label">Email</label>
<div>{{ userEmail }}</div>
</div>
<div class="form-group">
<label class="control-label">Frequency (*)</label>
<select class="form-control" #selectFreq (change)="choseFrequency(selectFreq.value)">
<option value="">-- none selected --</option>
<option value="never">never</option>
<option value="realtime">realtime</option>
<option value="daily">daily</option>
<option value="weekly">weekly</option>
<option value="monthly">monthly</option>
</select>
</div>
<div class="form-group">
<label class="control-label">Options</label>
<div>
<table class="table table-bordered">
<tbody>
<tr>
<td>Trust</td>
<td>[{{advanceSearch.trust.min}}, {{advanceSearch.trust.max}}]</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</confirmation-dialog>

View File

@ -0,0 +1,332 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AdvQueryObject, EventsPage, NotificationFrequency, NotificationMode } from '../../domain/typeScriptClasses';
import { BrokerService } from '../../services/broker.service';
import { loadingEvents, noEventsForTopic, noEventsWithParams, noServiceMessage,
subscribingChooseFrequency, subscribingToEvents, subscribingToEventsError,
subscribingToeventsSuccess } from '../../domain/shared-messages';
import { AbstractControl, FormArray, FormBuilder, FormGroup } from '@angular/forms';
import { AuthenticationService } from '../../services/authentication.service';
import { ConfirmationDialogComponent } from '../../shared/reusablecomponents/confirmation-dialog.component';
@Component ({
selector: 'app-content-events-of-repo-eventslist',
templateUrl: 'content-events-of-repo-eventslist.component.html'
})
export class ContentEventsOfRepoEventslistComponent implements OnInit {
errorMessage: string;
loadingMessage: string;
successMessage: string;
noEvents: string;
eventsPageInitialized = false;
topic = '';
lastTopicEntry = '';
correctTopic = '';
repoName = '';
advanceSearch: AdvQueryObject;
eventsPage: EventsPage;
currentPage: number; /* DELETE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
group: FormGroup;
readonly titleDefinition = { eventTitle: [''] };
readonly authorDefinition = { eventAuthor: [''] };
readonly subjectDefinition = { eventSubject: [''] };
readonly dateRangeDefinition = { dateFrom: '', dateTo: '' };
readonly groupDefinition = {
trustMin: [+''],
trustMax: [+''],
eventTitles: this.fb.array([this.initControl(this.titleDefinition)]),
eventAuthors: this.fb.array([this.initControl(this.authorDefinition)]),
eventSubjects: this.fb.array([this.initControl(this.subjectDefinition)]),
eventDateRanges: this.fb.array([this.initControl(this.dateRangeDefinition)])
};
eventTitleFormArray: any;
eventAuthorFormArray: any;
eventSubjectsFormArray: any;
eventDateRangesFormArray: any;
frequencyChoice: string;
userEmail: string;
modalErrorMessage: string;
isModalShown: boolean;
@ViewChild('subscribeToEventsModal')
public subscribeToEventsModal: ConfirmationDialogComponent;
constructor (private route: ActivatedRoute,
private fb: FormBuilder,
private brokerService: BrokerService,
private authService: AuthenticationService) {}
ngOnInit () {
this.userEmail = this.authService.getUserEmail();
this.getParams();
this.initQuery();
this.initForm();
this.currentPage = 0; /* DELETE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
this.getEventsPage(0);
}
getParams() {
this.topic = this.route.snapshot.paramMap.get('topic');
console.log(`my topic is: ${this.topic}`);
this.lastTopicEntry = this.topic.substring(this.topic.lastIndexOf('|') + 1).toLowerCase();
this.lastTopicEntry = this.replaceAll(this.lastTopicEntry, '_', ' ');
this.getCorrectTopic();
this.repoName = this.route.snapshot.paramMap.get('name');
}
replaceAll(str, find, replace) {
return str.replace(new RegExp(find, 'g'), replace);
}
initQuery() {
this.advanceSearch = {
datasource: this.repoName,
topic: this.correctTopic,
titles: [],
subjects: [],
authors: [],
dates: [],
trust: {min: '0', max: '1'},
page: 0
};
}
initForm() {
this.group = this.fb.group( this.groupDefinition, { validator: checkMinMax } );
this.group.get('trustMin').setValue(0);
this.group.get('trustMax').setValue(1);
}
initControl(definition: any) {
return this.fb.group(definition);
}
removeControl(controlName: string, i: number) {
const controlArray = <FormArray>this.group.controls[controlName];
controlArray.removeAt(i);
}
addControl(controlName: string, definition: any) {
const controlArray = <FormArray>this.group.controls[controlName];
controlArray.push(this.initControl(definition));
}
clearForm() {
let controlArray: FormArray;
controlArray = <FormArray>this.group.controls['eventTitles'];
controlArray.controls = [];
controlArray.push(this.initControl(this.titleDefinition));
controlArray = <FormArray>this.group.controls['eventAuthors'];
controlArray.controls = [];
controlArray.push(this.initControl(this.authorDefinition));
controlArray = <FormArray>this.group.controls['eventSubjects'];
controlArray.controls = [];
controlArray.push(this.initControl(this.subjectDefinition));
controlArray = <FormArray>this.group.controls['eventDateRanges'];
controlArray.controls = [];
controlArray.push(this.initControl(this.dateRangeDefinition));
this.group.get('trustMin').setValue(0);
this.group.get('trustMax').setValue(1);
this.initQuery();
this.getEventsPage(0);
}
updateQuery() {
let i: number;
let controlArray: FormArray;
if ( this.group.valid ) {
this.initQuery();
this.advanceSearch.trust.min = this.group.get('trustMin').value;
this.advanceSearch.trust.max = this.group.get('trustMax').value;
controlArray = <FormArray>this.group.controls['eventTitles'];
for (i = 0; i < controlArray.length; i++) {
if (controlArray.at(i).get('eventTitle').value) {
this.advanceSearch.titles.push(controlArray.at(i).get('eventTitle').value);
}
}
controlArray = <FormArray>this.group.controls['eventAuthors'];
for (i = 0; i < controlArray.length; i++) {
if (controlArray.at(i).get('eventAuthor').value) {
this.advanceSearch.authors.push(controlArray.at(i).get('eventAuthor').value);
}
}
controlArray = <FormArray>this.group.controls['eventSubjects'];
for (i = 0; i < controlArray.length; i++) {
if (controlArray.at(i).get('eventSubject').value) {
this.advanceSearch.subjects.push(controlArray.at(i).get('eventSubject').value);
}
}
controlArray = <FormArray>this.group.controls['eventDateRanges'];
for (i = 0; i < controlArray.length; i++) {
if (controlArray.at(i).get('dateFrom').value) {
let toDate;
if (controlArray.at(i).get('dateTo').value ||
(controlArray.at(i).get('dateFrom').value > controlArray.at(i).get('dateTo').value) ) {
toDate = controlArray.at(i).get('dateTo').value;
} else {
toDate = Date.now();
}
this.advanceSearch.dates.push({
min: controlArray.at(i).get('dateFrom').value,
max: toDate
});
}
}
console.log(this.advanceSearch);
this.currentPage = 0; /* DELETE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
this.getEventsPage(0);
}
}
getEventsPage(page: number) {
this.noEvents = '';
this.errorMessage = '';
this.successMessage = '';
this. loadingMessage = loadingEvents;
this.brokerService.advancedShowEvents(page, 10, this.advanceSearch).subscribe(
events => this.eventsPage = events,
error => {
this.loadingMessage = '';
this.errorMessage = noServiceMessage;
console.log(error);
},
() => {
this.loadingMessage = '';
console.log(this.eventsPage);
if (!this.eventsPage.total) {
if (!this.eventsPageInitialized) {
this.noEvents = noEventsForTopic;
} else {
this.noEvents = noEventsWithParams;
}
}
let tempArray = <FormArray>this.group.controls['eventTitles'];
this.eventTitleFormArray = tempArray.controls;
tempArray = <FormArray>this.group.controls['eventAuthors'];
this.eventAuthorFormArray = tempArray.controls;
tempArray = <FormArray>this.group.controls['eventSubjects'];
this.eventSubjectsFormArray = tempArray.controls;
tempArray = <FormArray>this.group.controls['eventDateRanges'];
this.eventDateRangesFormArray = tempArray.controls;
console.log(`total pages is ${this.eventsPage.totalPages}`);
this.eventsPageInitialized = true;
}
);
}
isHighlighted(item: any, itemList: any[]) {
return itemList.some(x => x === item);
}
getCorrectTopic() {
const temp = this.topic.split('|');
this.correctTopic = temp[0];
this.topic = temp[0];
for (let i = 1; i < temp.length; i++) {
this.correctTopic += `/${temp[i]}`;
this.topic += ` | ${temp[i]}`;
}
}
goToNextPage() {
/* RESTORE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
/*if(this.eventsPage.currPage < this.eventsPage.totalPages) {
console.log(`Get me page ${this.eventsPage.currPage+1}!`);
this.getEventsPage(this.eventsPage.currPage+1);
}*/
/* DELETE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
if ( (this.currentPage + 1) < this.eventsPage.totalPages) {
this.currentPage = this.currentPage + 1;
console.log(`Get me page ${this.currentPage}!`);
this.getEventsPage(this.currentPage);
}
}
goToPreviousPage() {
/* RESTORE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
/*if(this.eventsPage.currPage > 0) {
console.log(`Get me page ${this.eventsPage.currPage-1}!`);
this.getEventsPage(this.eventsPage.currPage-1);
}*/
/* DELETE WHEN ADVANCED SHOW EVENTS IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
if (this.currentPage > 0) {
this.currentPage = this.currentPage - 1;
console.log(`Get me page ${this.currentPage}!`);
this.getEventsPage(this.currentPage);
}
}
showSubscriptionModal() {
if (this.advanceSearch && this.eventsPage) {
this.subscribeToEventsModal.confirmed = false;
this.subscribeToEventsModal.showModal();
}
}
choseFrequency(freq: string) {
this.frequencyChoice = freq;
}
subscribeToEvents(event: any) {
this.modalErrorMessage = '';
if (this.frequencyChoice) {
this.subscribeToEventsModal.confirmed = true;
const freq = <NotificationFrequency>this.frequencyChoice;
const mod: NotificationMode = 'EMAIL';
const sub = {
subscriber: this.userEmail,
frequency: freq,
mode: mod,
query: this.advanceSearch
};
this.errorMessage = '';
this.successMessage = '';
console.log(JSON.stringify(sub));
this.loadingMessage = subscribingToEvents;
this.brokerService.subscribeToEvent(sub).subscribe(
response => console.log(`subscribeToEvents responded ${JSON.stringify(response)}`),
error => {
this.errorMessage = subscribingToEventsError;
this.loadingMessage = '';
},
() => {
this.loadingMessage = '';
this.successMessage = subscribingToeventsSuccess;
}
);
} else {
this.modalErrorMessage = subscribingChooseFrequency;
}
}
}
export function checkMinMax(c: AbstractControl) {
if ( c.get('trustMin').value > c.get('trustMax').value ) {
return 'invalid';
}
return null;
}
export function checkDates(c: AbstractControl) {
if ( c.get('dateFrom').value > c.get('dateTo').value ) {
return 'invalid';
}
return null;
}

View File

@ -0,0 +1,123 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Enrichments for {{ correctName }}</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div>
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{errorMessage}}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">{{ loadingMessage }}</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="noTopics" class="uk-alert">{{ noTopics }}</div>
<div *ngIf="repoTopics && repoTopics.length > 0" class="uk-grid-margin uk-grid uk-grid-stack repos-list">
<div class="uk-width-1-2@m uk-first-column">
<div class="uk-overflow-auto uk-scrollspy-inview uk-animation-slide-top-medium">
<div>
<h4 class="uk-h4 uk-text-primary uk-scrollspy-inview uk-animation-slide-top-medium" uk-scrollspy-class="">
<span>More</span>
</h4>
<table class="uk-table uk-table-striped uk-table-middle">
<thead>
<tr>
<th>Events that may enrich {{ repoName }} content</th>
<th class="uk-text-nowrap"># of events</th>
</tr>
</thead>
<tbody>
<tr class="el-item" *ngFor="let moreTopic of moreList">
<td class="uk-table-shrink uk-width-4-5">
<a (click)="goToEventsList(moreTopic.value)" class="el-link">{{ moreTopic.value }}</a>
<div *ngIf="topics[moreTopic.value]" class="uk-text uk-text-meta">{{ topics[moreTopic.value]['englishName'] }}</div>
</td>
<td class="uk-text-nowrap uk-table-shrink uk-width-1-5">
<div class="el-title">{{ moreTopic.size }}</div>
</td>
</tr>
<tr class="el-item footers">
<td class="uk-text-nowrap uk-table-shrink uk-width-4-5">
<div class="el-title">Total</div>
</td>
<td class="uk-text-nowrap uk-table-shrink uk-width-1-5">
<div class="el-title">{{ totalMore }}</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="uk-width-1-2@m uk-first-column">
<div class="uk-overflow-auto uk-scrollspy-inview uk-animation-slide-top-medium">
<div>
<h4 class="uk-h4 uk-text-primary uk-scrollspy-inview uk-animation-slide-top-medium" uk-scrollspy-class="">
<span>Missing</span>
</h4>
<table class="uk-table uk-table-striped uk-table-middle">
<thead>
<tr>
<th>Events that may enrich {{ repoName }} content</th>
<th class="uk-text-nowrap"># of events</th>
</tr>
</thead>
<tbody>
<tr class="el-item" *ngFor="let missingTopic of missingList">
<td class="uk-table-shrink uk-width-4-5">
<a (click)="goToEventsList(missingTopic.value)" class="el-link">{{ missingTopic.value }}</a>
<div *ngIf="topics[missingTopic.value]" class="uk-text uk-text-meta">{{ topics[missingTopic.value]['englishName'] }}</div>
</td>
<td class="uk-text-nowrap uk-table-shrink uk-width-1-5">
<div class="el-title">{{ missingTopic.size }}</div>
</td>
</tr>
<tr class="el-item footers">
<td class="uk-text-nowrap uk-table-shrink uk-width-4-5">
<div class="el-title">Total</div>
</td>
<td class="uk-text-nowrap uk-table-shrink uk-width-1-5">
<div class="el-title">{{ totalMissing }}</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>

View File

@ -0,0 +1,110 @@
import { Component, OnInit } from '@angular/core';
import { BrowseEntry, Term } from '../../domain/typeScriptClasses';
import { ActivatedRoute, Router } from '@angular/router';
import { loadingTopics, loadingTopicsError, noTopicsFound } from '../../domain/shared-messages';
import { BrokerService } from '../../services/broker.service';
@Component ({
selector: 'content-events-of-repository',
templateUrl: 'content-events-of-repository.component.html'
})
export class ContentEventsOfRepositoryComponent implements OnInit {
errorMessage: string;
loadingMessage: string;
noTopics: string;
repoName = '';
correctName = '';
topics: Map<string, Term> = new Map<string, Term>();
repoTopics: BrowseEntry[] = [];
moreList: BrowseEntry[] = [];
missingList: BrowseEntry[] = [];
totalMore = 0;
totalMissing = 0;
constructor(
private route: ActivatedRoute,
private router: Router,
private brokerService: BrokerService
) {}
ngOnInit() {
this.repoName = this.route.snapshot.paramMap.get('name');
this.getCorrectName();
this.getTopics();
}
getRepoTopics(): void {
this.loadingMessage = loadingTopics;
this.brokerService.getTopicsForDataSource(this.correctName)
.subscribe(
topics => {
this.repoTopics = topics;
},
error => {
console.log(error);
this.errorMessage = loadingTopicsError;
this.loadingMessage = '';
},
() => {
this.loadingMessage = '';
if (this.repoTopics.length === 0) {
this.noTopics = noTopicsFound;
} else {
for (const browseEntry of this.repoTopics) {
if (browseEntry.value.startsWith('ENRICH/MORE')) {
this.totalMore += browseEntry.size;
this.moreList.push(browseEntry);
} else if (browseEntry.value.startsWith('ENRICH/MISSING')) {
this.totalMissing += browseEntry.size;
this.missingList.push(browseEntry);
}
}
}
}
);
}
getTopics () {
this.loadingMessage = loadingTopics;
this.brokerService.getDnetTopics().subscribe(
topics => this.topics = topics,
error => {
console.log(error);
this.errorMessage = loadingTopicsError;
this.loadingMessage = '';
},
() => {
this.loadingMessage = '';
console.log(this.topics);
this.getRepoTopics();
}
);
}
goToEventsList(topic: string) {
const temp = topic.replace(/\//g, '|');
let chosenTopic = temp[0];
for (let i = 1; i < temp.length; i++) {
chosenTopic += '|' + temp[i];
}
chosenTopic = encodeURIComponent(chosenTopic);
/*this.router.navigate([`/content/events/${this.repoName}`, chosenTopic]);*/
console.log(temp, this.route.url);
this.router.navigate([temp], {relativeTo: this.route});
}
getCorrectName() {
const temp = this.repoName.split('|');
this.correctName = temp[0];
this.repoName = temp[0];
for (let i = 1; i < temp.length; i++) {
this.correctName += `/${temp[i]}`;
this.repoName += ` | ${temp[i]}`;
}
}
}

View File

@ -0,0 +1,130 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Enrich Your Content - Browse Events</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div>
<div class="uk-width-1-1 uk-grid">
<div class="uk-width-1-1 uk-first-column uk-margin-bottom">
<div class="uk-float-right">
<a class="grid-view" [class.active]="tilesView" (click)="toggleTiles()">
<i class="fa fa-th"></i>
</a>
<a class="grid-view" [class.active]="!tilesView" (click)="toggleTiles()">
<i class="fa fa-th-list"></i>
</a>
</div>
</div>
<div class="uk-width-1-1">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="noDatasourcesMessage" class="uk-alert uk-alert-warning">{{ noDatasourcesMessage }}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<!--TILES VIEW-->
<div *ngIf="tilesView && datasourcesOfUser && datasourcesOfUser.length>0" class="uk-grid-large uk-grid-margin-large uk-grid repos-grid uk-height-1-1">
<div *ngFor="let repo of datasourcesOfUser" class="uk-width-expand@m uk-width-auto\@m uk-first-column uk-margin-bottom" style="min-width: 300px; max-width: 22%;">
<div class="uk-margin uk-grid-match uk-child-width-1-1 uk-grid-small uk-grid-divider uk-grid uk-scrollspy-inview uk-animation-slide-top-medium uk-grid-stack">
<div class="uk-first-column">
<div class="">
<a class="el-link uk-vertical-align-middle uk-height-1-1" (click)="goToRepoEvents(repo['first']['value'])">
<div class="el-item uk-panel uk-scrollspy-inview uk-animation-slide-top-medium" uk-scrollspy-class="">
<div class="uk-child-width-expand uk-grid-medium uk-flex-middle uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-3@m uk-first-column" style="width: 90px;">
<img *ngIf="!repo['second']" class="el-image uk-border-rounded" src="../../../assets/imgs/yourLogoHere.jpg" alt="">
<img *ngIf="repo['second']" class="el-image uk-border-rounded" src="{{ repo['second'] }}" alt="">
</div>
<div class="uk-first-column">
<h3 class="el-title uk-margin uk-h5 uk-margin-remove-adjacent uk-margin-small-bottom">{{ repo['first']['value'] }}</h3>
<div class="el-meta uk-margin uk-text-meta">
<span>({{ repo['first']['size'] }} events)</span>
</div>
</div>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
<!-- LIST VIEW -->
<div *ngIf="!tilesView && datasourcesOfUser && datasourcesOfUser.length>0" class="uk-grid-large uk-grid-margin-large uk-grid repos-list">
<div class="uk-width-1-1@m uk-first-column">
<div class="uk-overflow-auto uk-scrollspy-inview uk-animation-slide-top-medium">
<div>
<table class="uk-table uk-table-striped uk-table-middle">
<thead>
<tr>
<th class="uk-text-nowrap">Logo</th>
<th class="uk-text-nowrap">Name</th>
<th class="uk-text-nowrap"># of Events</th>
</tr>
</thead>
<tbody>
<tr class="el-item" *ngFor="let repo of datasourcesOfUser">
<td class="uk-table-shrink">
<img *ngIf="repo['second']" class="el-image uk-preserve-width" src="{{ repo['second'] }}" style="height: 45px;">
<img *ngIf="!repo['second']" class="el-image uk-preserve-width" src="../../../assets/imgs/yourLogoHere.jpg" alt="[Repo Logo]" style="height: 45px;">
</td>
<td class="uk-text-nowrap uk-table-shrink">
<a (click)="goToRepoEvents(repo['first']['value'])">{{ repo['first']['value'] }}</a>
</td>
<td class="uk-text-nowrap uk-table-shrink">
{{ repo['first']['size'] }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>

View File

@ -0,0 +1,71 @@
import { Component, Input, OnInit } from '@angular/core';
import { AuthenticationService } from '../../services/authentication.service';
import { BrokerService } from '../../services/broker.service';
import { ActivatedRoute, Router } from '@angular/router';
import { loadingRepoMessage, loadingUserRepoInfoEmpty, reposRetrievalError } from '../../domain/shared-messages';
@Component ({
selector: 'app-content-events',
templateUrl: 'content-events.component.html'
})
export class ContentEventsComponent implements OnInit {
datasourcesOfUser = [];
tilesView: boolean;
errorMessage: string;
noDatasourcesMessage: string;
loadingMessage: string;
@Input() parent = '';
constructor(private authService: AuthenticationService,
private brokerService: BrokerService,
private router: Router,
private route: ActivatedRoute) {}
ngOnInit() {
this.tilesView = true;
this.getDatasourcesOfUser();
}
getDatasourcesOfUser() {
this.loadingMessage = loadingRepoMessage;
this.brokerService.getDatasourcesOfUser().subscribe(
res => {
this.datasourcesOfUser = res['datasourcesOfUser'];
},
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = reposRetrievalError;
},
() => {
this.loadingMessage = '';
if (!this.datasourcesOfUser || !this.datasourcesOfUser.length) {
this.noDatasourcesMessage = loadingUserRepoInfoEmpty;
} else {
this.datasourcesOfUser.sort( function(a, b) {
if ( a['first']['value'] < b['first']['value'] ) {
return -1;
} else if (a['first']['value'] > b['first']['value']) {
return 1;
} else {
return 0;
}
});
}
}
);
}
toggleTiles() {
this.tilesView = !this.tilesView;
}
goToRepoEvents(repoName: string) {
const newName = repoName.replace(/\//g, '|');
this.router.navigate([newName], {relativeTo: this.route});
}
}

View File

@ -0,0 +1,264 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 *ngIf="eventsPage" class="uk-h2">{{ eventsPage.datasource }}</h1>
<div *ngIf="eventsPage" class="uk-text uk-text-small uk-text-secondary">{{ topic }}</div>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{errorMessage}}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">{{ loadingMessage }}</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="noEvents" class="uk-alert">{{ noEvents }}</div>
<div *ngIf="!noEvents && !loadingMessage && !errorMessage && eventsPage && eventsPage.totalPages>0" class="events-results">
<div class="numberOfEventsLabel">
<!-- RESTORE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<!--<span>Showing {{(eventsPage.currPage*10)+1 }}-{{ ( (eventsPage.total < 10) || (eventsPage.total < (eventsPage.currPage+1)*10) ) ? (eventsPage.total) : (eventsPage.currPage+1)*10 }} of {{ eventsPage.total }} results</span>-->
<!-- DELETE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<span>Showing {{(currentPage*10)+1 }}-{{ ( (eventsPage.total < 10) || (eventsPage.total < (currentPage+1)*10) ) ? (eventsPage.total) : (currentPage+1)*10 }} of {{ eventsPage.total }} results</span>
</div>
<div>
<ul class="uk-pagination">
<li>
<a class="uk-link uk-link-muted" (click)="goToPreviousPage()">
<span class="uk-margin-small-right uk-pagination-previous uk-icon" uk-pagination-previous="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg" icon="pagination-previous" ratio="1"></svg>
</span>
Previous
</a>
</li>
<li class="uk-margin-auto-left">
<a class="uk-link uk-link-muted" (click)="goToNextPage()">
Next
<span class="uk-margin-small-left uk-pagination-next uk-icon" uk-pagination-next="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg" icon="pagination-next" ratio="1"></svg>
</span>
</a>
</li>
</ul>
<!-- RESTORE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<!--<div class="resultsPageLabel">page {{ eventsPage.currPage+1 }} of {{ eventsPage.totalPages }}</div>-->
<!-- DELETE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<div class="resultsPageLabel">page {{ (eventsPage.totalPages > 0) ? currentPage+1 : 0 }} of {{ eventsPage.totalPages }}</div>
</div>
<div *ngFor="let event of eventsPage.values" class="events-list">
<div class="uk-card uk-card-default well uk-scrollspy-inview uk-animation-slide-top-medium">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<p class="text-right"><span class="uk-label">Trust: {{ event.trust }}</span></p>
<div class="uk-overflow-auto uk-scrollspy-inview uk-animation-slide-top-medium">
<table class="uk-table uk-table-striped uk-table-middle">
<tbody>
<tr class="el-item">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">ID</strong></td>
<td class="uk-table-shrink">
<div class="el-title">{{ event.publication.originalId }}</div>
</td>
</tr>
<tr class="el-item">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Title(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let t of event.publication.titles; let ti_index = index">
<br *ngIf="ti_index>0">
<span>{{ t }}</span>
</span>
</div>
</td>
</tr>
<tr class="el-item">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Author(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let auth of event.publication.creators; let au_index = index">
<span *ngIf="au_index>0"> | </span>
<span>{{ auth }}</span>
</span>
</div>
</td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.pids && event.highlight.pids.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">PID(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let pid of event.publication.pids">
<span>{{ pid.value }} <b>&nbsp;&nbsp;({{ pid.type }})&nbsp;&nbsp;</b>
<span *ngIf="event.highlight.pids && event.highlight.pids.length>0 && isHighlighted(pid,event.highlight.pids)">
<span class="uk-label uk-label-success">added</span>&nbsp;&nbsp;
<span *ngIf="event.provenance" class="pull-right">
<b>from: </b>
<a *ngIf="event.provenance.url" href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</span>
</span>
</span>
</span>
</div>
</td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.abstracts && event.highlight.abstracts.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Abstract(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let abs of event.publication.abstracts; let a_index = index">
<br *ngIf="a_index > 0">
<span>{{ abs }}</span>
<span *ngIf="event.highlight.abstracts && event.highlight.abstracts.length>0 && event.provenance">
<span class="pull-right">
<b>from: </b>
<a *ngIf="event.provenance.url" href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</span>
</span>
</span>
</div>
</td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.projects && event.highlight.projects.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Project(s)/Relation(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let proj of event.publication.projects; let p_index = index">
<br *ngIf="p_index > 0">
<span *ngIf="proj.acronym && proj.acronym !==''">{{ proj.acronym }}</span>
<span *ngIf="!proj.acronym || proj.acronym ===''">{{ proj.title }}</span>
<span *ngIf="(proj.funder && proj.funder !=='') ||
(proj.fundingProgram && proj.fundingProgram !=='')">
(<span *ngIf="proj.funder && proj.funder !==''">{{ proj.funder }} </span>
<span *ngIf="(proj.funder && proj.funder !=='') &&
(proj.fundingProgram && proj.fundingProgram !=='')">/</span>
<span *ngIf="proj.fundingProgram && proj.fundingProgram !==''">{{ proj.fundingProgram }}</span>)
</span>
<span *ngIf="event.highlight.projects && event.highlight.projects.length>0 && event.provenance">
<span class="pull-right">
<b>from: </b>
<a *ngIf="event.provenance.url" href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</span>
</span>
</span>
</div>
</td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.subjects && event.highlight.subjects.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Subject(s)</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let subj of event.publication.subjects; let s_index = index">
<br *ngIf="s_index > 0">
<span>{{ subj }}</span>
<span *ngIf="event.highlight.subjects && event.highlight.subjects.length>0 && event.provenance">
<span class="pull-right">
<b>from: </b>
<a *ngIf="event.provenance.url" href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</span>
</span>
</span>
</div>
</td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.publicationdate && event.highlight.publicationdate.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Publication date</strong></td>
<td class="uk-table-shrink"><div class="el-title">{{ event.publication.publicationdate }}</div></td>
</tr>
<tr class="el-item" [ngClass]="{'success': event.highlight.instances && event.highlight.instances.length>0 }">
<td class="uk-table-shrink uk-width-1-4"><strong class="el-title uk-display-block">Rights</strong></td>
<td class="uk-table-shrink">
<div class="el-title">
<span *ngFor="let l of event.publication.instances; let l_index = index">
<br *ngIf="l_index > 0">
<span>
{{ l.license }}&nbsp;&nbsp;<b>{{ l.hostedby }}</b><br>
<a href="{{ l.url }}" target="_blank">{{ l.url }}</a>
</span>
<span *ngIf="event.highlight.instances && event.highlight.instances.length>0 && isHighlighted(l,event.highlight.instances)">
<span class="uk-label uk-label-success">added</span>&nbsp;&nbsp;
<span *ngIf="event.provenance" class="pull-right">
<b>from: </b>
<a *ngIf="event.provenance.url" href="{{ event.provenance.url }}" target="_blank">{{ event.provenance.repositoryName }}</a>
<span *ngIf="event.provenance.id"> (ID: {{ event.provenance.id }})</span>
</span>
</span>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div>
<ul class="uk-pagination">
<li>
<a class="uk-link uk-link-muted" (click)="goToPreviousPage()">
<span class="uk-margin-small-right uk-pagination-previous uk-icon" uk-pagination-previous="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg" icon="pagination-previous" ratio="1"></svg>
</span>
Previous
</a>
</li>
<li class="uk-margin-auto-left">
<a class="uk-link uk-link-muted" (click)="goToNextPage()">
Next
<span class="uk-margin-small-left uk-pagination-next uk-icon" uk-pagination-next="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg" icon="pagination-next" ratio="1"></svg>
</span>
</a>
</li>
</ul>
<!-- RESTORE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<!--<div class="resultsPageLabel">page {{ eventsPage.currPage+1 }} of {{ eventsPage.totalPages }}</div>-->
<!-- DELETE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE -->
<div class="resultsPageLabel">page {{ (eventsPage.totalPages > 0) ? currentPage+1 : 0 }} of {{ eventsPage.totalPages }}</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>

View File

@ -0,0 +1,96 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { BrokerService } from '../../services/broker.service';
import { loadingEvents, noEventsForTopic, noServiceMessage } from '../../domain/shared-messages';
import { EventsPage } from '../../domain/typeScriptClasses';
@Component ({
selector: 'app-content-notifications-of-subscription',
templateUrl: 'content-notifications-of-subscription.component.html'
})
export class ContentNotificationsOfSubscriptionComponent implements OnInit {
noEvents: string;
errorMessage: string;
loadingMessage: string;
subId: string;
topic: string;
eventsPage: EventsPage;
currentPage: number; /* DELETE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
constructor(private route: ActivatedRoute,
private brokerService: BrokerService) {}
ngOnInit () {
this.subId = this.route.snapshot.paramMap.get('id');
this.currentPage = 0; /* DELETE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
this.getEventsPage(0);
}
getEventsPage(page: number) {
this.noEvents = '';
this.errorMessage = '';
this. loadingMessage = loadingEvents;
this.brokerService.getNotificationsBySubscriptionId(this.subId, page, 10).subscribe(
events => this.eventsPage = events,
error => {
this.loadingMessage = '';
this.errorMessage = noServiceMessage;
console.log(error);
},
() => {
this.loadingMessage = '';
console.log(this.eventsPage);
if (!this.eventsPage.total) {
this.noEvents = noEventsForTopic;
}
this.getCorrectTopic();
}
);
}
goToNextPage() {
/* RESTORE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
/*if(this.eventsPage.currPage < this.eventsPage.totalPages) {
console.log(`Get me page ${this.eventsPage.currPage+1}!`);
this.getEventsPage(this.eventsPage.currPage+1);
}*/
/* DELETE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
if ( (this.currentPage + 1) < this.eventsPage.totalPages) {
this.currentPage = this.currentPage + 1;
console.log(`Get me page ${this.currentPage}!`);
this.getEventsPage(this.currentPage);
}
}
goToPreviousPage() {
/* RESTORE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
/*if(this.eventsPage.currPage > 0) {
console.log(`Get me page ${this.eventsPage.currPage-1}!`);
this.getEventsPage(this.eventsPage.currPage-1);
}*/
/* DELETE WHEN getNotificationsBySubscriptionId IS FIXED AND SENDS CORRECT VALUE FOR CURRENT PAGE */
if (this.currentPage > 0) {
this.currentPage = this.currentPage - 1;
console.log(`Get me page ${this.currentPage}!`);
this.getEventsPage(this.currentPage);
}
}
isHighlighted(item: any, itemList: any[]) {
return itemList.some(x => x === item);
}
getCorrectTopic() {
const temp = this.eventsPage.topic.split('/');
this.topic = temp[0];
for (let i = 1; i < temp.length; i++) {
this.topic += ` | ${temp[i]}`;
}
}
}

View File

@ -0,0 +1,92 @@
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Enrich Your Content - Browse Subscriptions</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div>
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{errorMessage}}</div>
<div *ngIf="successMessage" class="uk-alert uk-alert-success">{{successMessage}}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">{{ loadingMessage }}</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="noSubscriptions" class="uk-alert">{{noSubscriptions}}</div>
</div>
<div *ngIf="subscrOfUser && subKeys">
<div *ngFor="let key of subKeys">
<h4 class="uk-h4 uk-text-primary uk-scrollspy-inview uk-animation-slide-top-medium uk-scrollspy-class=">
<span>{{ key }}</span>
</h4>
<table class="uk-table uk-table-striped uk-table-middle">
<thead>
<tr>
<th>Topic</th>
<th>Creation Date</th>
<th>Last Notification Date</th>
<th class="uk-text-nowrap"># of notifications</th>
<th class="uk-text-nowrap">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let sub of subscrOfUser[key]" class="el-item">
<td class="uk-table-shrink">
<a [routerLink]="sub.id">
<div class="el-title">{{ sub.topic }}</div>
</a>
</td>
<td class="uk-table-shrink">
<div class="el-title">{{ sub.creationDate | date:'yyyy-MM-dd HH:mm:ss' }}</div>
</td>
<td class="uk-table-shrink">
<div class="el-title">{{ sub.lastNotificationDate | date:'yyyy-MM-dd HH:mm:ss' }}</div>
</td>
<td class="uk-text-nowrap uk-table-shrink">
<div class="el-title">{{ sub.count }}</div>
</td>
<td class="uk-text-nowrap uk-table-shrink">
<a class="el-link" (click)="deleteSubscription(sub.id)">
<i class="fa fa-remove" aria-hidden="true"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>

View File

@ -0,0 +1,74 @@
import {Component, OnInit} from '@angular/core';
import { SimpleSubscriptionDesc } from '../../domain/typeScriptClasses';
import { AuthenticationService } from '../../services/authentication.service';
import { BrokerService } from '../../services/broker.service';
import { deletingSubscription, deletingSubscriptionError, deletingSubscriptionSuccess,
loadingSubscriptions, noServiceMessage, noSubscriptionsFound } from '../../domain/shared-messages';
@Component ({
selector: 'app-content-notifications',
templateUrl: 'content-notifications.component.html'
})
export class ContentNotificationsComponent implements OnInit {
errorMessage: string;
successMessage: string;
loadingMessage: string;
noSubscriptions: string;
subscrOfUser: Map<string, SimpleSubscriptionDesc[]> = new Map<string, SimpleSubscriptionDesc[]>();
subKeys: string[];
constructor(private authService: AuthenticationService,
private brokerService: BrokerService) {}
ngOnInit() {
this.getSubscriptions();
}
getSubscriptions() {
this.errorMessage = '';
this.loadingMessage = loadingSubscriptions;
this.subKeys = [];
this.brokerService.getSimpleSubscriptionsOfUser().subscribe(
subscrs => this.subscrOfUser = subscrs,
error => {
console.log(`getSimpleSubscriptions returned error`);
console.log(error);
this.loadingMessage = '';
this.errorMessage = noServiceMessage;
},
() => {
this.loadingMessage = '';
for (const key in this.subscrOfUser) {
this.subKeys.push(key);
console.log(key);
}
if (!this.subKeys.length) {
this.noSubscriptions = noSubscriptionsFound;
}
}
);
}
deleteSubscription(key: string) {
this.loadingMessage = deletingSubscription;
this.successMessage = '';
this.errorMessage = '';
this.brokerService.unsubscribe(key).subscribe(
response => console.log(`unsubscribe responded with ${response}`),
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = deletingSubscriptionError;
},
() => {
this.loadingMessage = '';
this.successMessage = deletingSubscriptionSuccess;
this.getSubscriptions();
}
);
}
}

View File

@ -0,0 +1,13 @@
import { Component, OnInit } from '@angular/core';
@Component ({
selector: 'app-content',
templateUrl: '../pageContainer.html'
})
export class ContentComponent implements OnInit {
constructor() {}
ngOnInit() {}
}

View File

@ -0,0 +1,32 @@
import { ReusableComponentsModule } from '../../shared/reusablecomponents/reusable-components.module';
import { ContentEventsOfRepositoryComponent } from './content-events-of-repository.component';
import { ContentEventsOfRepoEventslistComponent } from './content-events-of-repo-eventslist.component';
import { ReactiveFormsModule } from '@angular/forms';
import { ContentNotificationsOfSubscriptionComponent } from './content-notifications-of-subscription.component';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TabsModule } from 'ngx-bootstrap';
import { ContentRouting } from './content.routing';
import { ContentComponent } from './content.component';
import { ContentEventsComponent } from './content-events.component';
import { ContentNotificationsComponent } from './content-notifications.component';
@NgModule ({
imports: [
CommonModule,
TabsModule.forRoot(),
ContentRouting,
ReactiveFormsModule,
ReusableComponentsModule
],
declarations: [
ContentComponent,
ContentEventsComponent,
ContentEventsOfRepositoryComponent,
ContentEventsOfRepoEventslistComponent,
ContentNotificationsComponent,
ContentNotificationsOfSubscriptionComponent
]
})
export class ContentModule {}

View File

@ -0,0 +1,44 @@
import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core';
import { ContentEventsComponent } from './content-events.component';
import { ContentComponent } from './content.component';
import { ContentNotificationsComponent } from './content-notifications.component';
import { ContentEventsOfRepositoryComponent } from './content-events-of-repository.component';
import { ContentEventsOfRepoEventslistComponent } from './content-events-of-repo-eventslist.component';
import { ContentNotificationsOfSubscriptionComponent } from './content-notifications-of-subscription.component';
const contentRoutes: Routes = [
{
path: '',
component: ContentComponent,
children: [
{
path: 'events',
component: ContentEventsComponent,
},
{
path: 'events/:name',
component: ContentEventsOfRepositoryComponent,
},
{
path: 'events/:name/:topic',
component: ContentEventsOfRepoEventslistComponent,
},
{
path: 'notifications',
component: ContentNotificationsComponent,
},
{
path: 'notifications/:id',
component: ContentNotificationsOfSubscriptionComponent,
}
]
}
];
@NgModule ({
imports: [RouterModule.forChild(contentRoutes)],
exports: [RouterModule]
})
export class ContentRouting {}

View File

@ -0,0 +1,145 @@
<div *ngIf="getIsUserLoggedIn()" id="contentWrapper" class="tm-main uk-section uk-section-default" uk-height-viewport="expand: true" style="box-sizing: border-box;" >
<div class="uk-container uk-container-expand">
<div class="uk-sticky-placeholder" style="height: 84px; margin: 0px;" aria-hidden="aria-hidden"></div>
<div class="uk-grid uk-padding">
<div class="uk-width-3-4@m uk-first-column">
<div class="uk-margin uk-grid-match uk-child-width-1-1 uk-child-width-1-2@m uk-grid-small uk-grid uk-scrollspy-inview uk-animation-fade" uk-scrollspy-class="" uk-grid="" style="">
<div class="uk-first-column">
<div class="el-item uk-card uk-card-hover uk-card-body uk-scrollspy-inview uk-animation-fade" uk-scrollspy-class="" style="">
<a class="el-link uk-position-cover uk-margin-remove-adjacent" [routerLink]="['/sources','register']" uk-scroll=""></a>
<div class="uk-child-width-expand uk-flex-middle uk-grid" uk-grid="">
<div class="uk-width-1-2@m uk-first-column">
<img class="el-image uk-border-rounded" src="../../../assets/imgs/iStock-153949408.jpg" >
</div>
<div>
<div>
<h3 class="el-title uk-margin uk-card-title">Register</h3>
<div class="el-content uk-margin">
Register data sources in the OpenAIRE infrastructure
</div>
</div>
</div>
</div>
</div>
</div>
<div>
<div class="el-item uk-card uk-card-hover uk-card-body uk-scrollspy-inview uk-animation-fade" uk-scrollspy-class="" style="">
<a class="el-link uk-position-cover uk-margin-remove-adjacent" [routerLink]="['/compatibility','validate']" uk-scroll=""></a>
<div class="uk-child-width-expand uk-flex-middle uk-grid" uk-grid="">
<div class="uk-width-1-2@m uk-first-column">
<img class="el-image uk-border-rounded" src="../../../assets/imgs/iStock-516286898.jpg" >
</div>
<div>
<div>
<h3 class="el-title uk-margin uk-card-title">Validate</h3>
<div class="el-content uk-margin">
Validate data sources against OpenAIRE guidelines
</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-grid-margin uk-first-column">
<div class="el-item uk-card uk-card-hover uk-card-body uk-scrollspy-inview uk-animation-fade" uk-scrollspy-class="" style="">
<a class="el-link uk-position-cover uk-margin-remove-adjacent" [routerLink]="['/content','notifications']" uk-scroll=""></a>
<div class="uk-child-width-expand uk-flex-middle uk-grid" uk-grid="">
<div class="uk-width-1-2@m uk-first-column">
<img class="el-image uk-border-rounded" src="../../../assets/imgs/iStock-466267165.jpg" >
</div>
<div>
<div>
<h3 class="el-title uk-margin uk-card-title">Notifications</h3>
<div class="el-content uk-margin">
View notifications to enrich the metadata and the content
</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-grid-margin">
<div class="el-item uk-card uk-card-hover uk-card-body uk-scrollspy-inview uk-animation-fade" uk-scrollspy-class="" style="">
<a class="el-link uk-position-cover uk-margin-remove-adjacent" uk-scroll="" [routerLink]="['/getImpact']"></a>
<div class="uk-child-width-expand uk-flex-middle uk-grid" uk-grid="">
<div class="uk-width-1-2@m uk-first-column">
<img class="el-image uk-border-rounded" src="../../../assets/imgs/iStock-659630328.jpg" >
</div>
<div>
<div>
<h3 class="el-title uk-margin uk-card-title">Metrics</h3>
<div class="el-content uk-margin">
View aggregated, cleaned usage statistics for repository access
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-width-1-4@m">
<div class="uk-card uk-card-body uk-card-grey" style="min-height: 300px;">
<h5 class="">MY DATASOURCES AT A GLANCE</h5>
<div *ngIf="loading">
<div class="loader-big" style="text-align: center; padding-top: 100px; color: rgb(47, 64, 80); font-weight: bold;">
Retrieving your datasources...
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="!loading">
<div *ngIf="repositories && repositories.length>0">
<div *ngFor="let repository of repositories" class="uk-margin-bottom uk-margin-top">
<div class="uk-padding-small" style="background-color: #fff">
<div class="uk-inline uk-width-1-3@m">
<img src="{{repository.logoURL ? repository.logoURL : '../../../assets/imgs/yourLogoHere.jpg'}}" alt="">
</div>
<div class="uk-inline uk-width-2-3@m">
<div class="uk-margin-left">{{repository.repositoryName}}</div>
</div>
</div>
<div class="uk-margin-small-top">
<div>Number of records collected:
<span *ngIf="repository.recordsCollected">{{repository.recordsCollected}}</span>
<span *ngIf="!repository.recordsCollected">not available</span>
</div>
<div>Last indexed version:
<span *ngIf="repository.lastIndexedVersion">{{repository.lastIndexedVersion | date :'short'}}</span>
<span *ngIf="!repository.lastIndexedVersion">not available</span>
</div>
<div>Content enrichment events:
<span *ngIf="repository.enrichmentEvents">{{repository.enrichmentEvents}}</span>
<span *ngIf="!repository.enrichmentEvents">not available</span>
</div>
<div>Views:
<span *ngIf="repository.totalViews">{{repository.totalViews}}</span>
<span *ngIf="!repository.totalViews">not available</span>
</div>
<div>Downloads:
<span *ngIf="repository.totalDownloads">{{repository.totalDownloads}}</span>
<span *ngIf="!repository.totalDownloads">not available</span>
</div>
</div>
</div>
</div>
<div *ngIf="!repositories || repositories.length==0">
No repositories available...
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,49 @@
import { Component, OnInit } from '@angular/core';
import { AuthenticationService } from '../../services/authentication.service';
import { RepositoryService } from '../../services/repository.service';
import {Repository, RepositorySnippet, RepositorySummaryInfo} from '../../domain/typeScriptClasses';
@Component ({
selector: 'app-dashboard',
templateUrl: 'dashboard.component.html'
})
export class DashboardComponent implements OnInit {
constructor(private authService: AuthenticationService,
private repositoryService: RepositoryService) { }
repositories: RepositorySummaryInfo[] = [];
userEmail: string;
loading: boolean = true;
ngOnInit() {
// this.getUserEmail();
this.userEmail = sessionStorage.getItem('email');
if (this.userEmail) {
this.getRepositoriesSummaryInfo();
}
}
getIsUserLoggedIn() {
return this.authService.getIsUserLoggedIn();
}
getUserEmail() {
this.userEmail = this.authService.getUserEmail();
}
getRepos() {
console.log('in getRepos');
this.getRepositoriesSummaryInfo();
}
getRepositoriesSummaryInfo() {
this.repositoryService.getRepositoriesSummaryInfo().subscribe(
repositories => { this.repositories = repositories; this.loading=false },
error => { console.log('Errrrror'); this.loading=false },
() => { console.log(this.repositories); this.loading=false }
);
}
}

View File

@ -0,0 +1,294 @@
<div>
<div class="image-front-topbar uk-section-default"
uk-scrollspy="{&quot;target&quot;:&quot;[uk-scrollspy-class]&quot;,&quot;cls&quot;:&quot;uk-animation-fade&quot;,&quot;delay&quot;:false}" tm-header-transparent="light">
<div style="background-image: url('../../../assets/imgs/KOJu48AA.jpeg'); background-color: rgb(255, 255, 255); box-sizing: border-box; min-height: calc(-101.35px + 100vh);"
class="uk-background-norepeat uk-background-cover uk-background-top-center uk-background-fixed uk-section uk-padding-remove-bottom uk-flex uk-flex-middle" uk-height-viewport="offset-top: true;offset-bottom: 20">
<div class="uk-width-1-1">
<div class="uk-margin-medium uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m">
</div>
</div>
<div class="uk-container uk-container-large uk-margin-large">
<div class="uk-sticky-placeholder" style="height: 84px; margin: 0px;"></div>
<div class="search_box_bg uk-grid-large uk-flex-middle uk-grid uk-grid-stack" uk-grid="">
<div class="el-overlay uk-panel uk-width-xlarge uk-dark">
<h1 class="el-title uk-margin uk-heading-hero provide">Content Provider Dashboard</h1>
<div class="el-content uk-margin"><h2 style="color:#1a1a1a!important">A one-stop-shop for sharing, finding and enriching your content</h2></div>
<p><a (click)="goToPage('/dashboard')" class="el-link uk-button uk-button-primary">Start here</a></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-section-default uk-section uk-section-small">
<div class="uk-container uk-container-large">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<div class="uk-margin uk-text-center uk-child-width-1-1 uk-grid-match uk-child-width-1-1@s uk-child-width-1-4@m uk-child-width-1-4@l uk-grid-large uk-grid" uk-grid="">
<div class="uk-first-column">
<div class="el-item uk-card uk-card-hover uk-card-small uk-card-body">
<a (click)="goToPage('/compatibility/validate')" class="el-link uk-position-cover uk-position-z-index uk-margin-remove-adjacent"></a>
<img src="../../../assets/imgs/Path%20163.svg" class="el-image" alt="" uk-svg="" hidden="true">
<h3 class="el-title uk-margin uk-h3">Validate</h3>
<!--<div class="el-content uk-margin uk-text-lead">-->
<div class="el-content uk-margin">
<p><strong>Interoperable metadata is key for effective content sharing.</strong></p>
<p>Use our validation service and see how you can apply the OpenAIRE Guidelines to expose your content using global standards.</p>
</div>
</div>
</div>
<div class="">
<div class="el-item uk-card uk-card-hover uk-card-small uk-card-body">
<a (click)="goToPage('/sources/register')" class="el-link uk-position-cover uk-position-z-index uk-margin-remove-adjacent"></a>
<img src="../../../assets/imgs/Group%20987.svg" class="el-image" alt="" uk-svg="" hidden="true">
<h3 class="el-title uk-margin uk-h3" style="margin-top: 26px !important;">Register</h3>
<div class="el-content uk-margin">
<p><strong>Reach a wider audience around the world</strong></p>
<p>Register your literature or data repository, OA Journal, CRIS in OpenAIRE and be part of a global interlinked network. Start now!</p>
</div>
</div>
</div>
<div class="">
<div class="el-item uk-card uk-card-hover uk-card-small uk-card-body">
<a (click)="goToPage('/content/events')" class="el-link uk-position-cover uk-position-z-index uk-margin-remove-adjacent"></a>
<img src="../../../assets/imgs/Group%20409.svg" class="el-image" alt="" uk-svg="" hidden="true">
<h3 class="el-title uk-margin uk-h3">Enrich</h3>
<div class="el-content uk-margin">
<p><strong>Improve your metadata. Get more connections</strong></p>
<p>Our newly released OA Broker service offers a wealth of information on scholarly communication data. Find out what interests you and subscribe to enrich your records. Learn more!</p>
</div>
</div>
</div>
<div class="">
<div class="el-item uk-card uk-card-hover uk-card-small uk-card-body">
<a (click)="goToPage('/getImpact')" class="el-link uk-position-cover uk-position-z-index uk-margin-remove-adjacent"></a>
<img src="../../../assets/imgs/Group%20410.svg" class="el-image" alt="" uk-svg="" hidden="true">
<h3 class="el-title uk-margin uk-h3" style="margin-top: 34px !important;">Measure</h3>
<div class="el-content uk-margin">
<p><strong>Open research impact empowers Open Science</strong></p>
<p>Participate in the Open Metrics service by sharing your usage data. Get the benefit of an aggregated environment to broaden the mechanisms for impact assesment. Learn more!</p>
</div>
</div>
</div>
</div>
<div class="uk-margin-medium uk-text-center uk-scrollspy-inview uk-animation-slide-top-medium" uk-scrollspy-class="" style="">
<a (click)="goToPage('/dashboard')" class="el-content uk-button uk-button-primary">
Get Started
</a>
</div>
</div>
</div>
</div>
</div>
<div class="uk-section-muted uk-section uk-section-small">
<div class="uk-container uk-container-large">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<div class="uk-margin uk-child-width-1-1 uk-grid-match uk-child-width-1-1@s uk-child-width-1-2@m
uk-child-width-1-2@l uk-grid-large uk-grid uk-grid-divider provide" uk-grid="">
<div class="uk-first-column uk-text-center">
<div class="el-item uk-card uk-card-small uk-card-body">
<img src="../../../assets/imgs/Group%20599.svg" class="el-image" alt="" uk-svg="" hidden="true">
<h3 class="el-title uk-margin uk-h3">Have more questions?</h3>
</div>
</div>
<div class="questions">
<div class="el-item uk-card uk-card-small uk-card-body">
<ul class="uk-list uk-list-divider">
<!--<li><a href="https://www.openaire.eu/os-primers">Learn about open science policies and how to align</a></li>-->
<!--<li><a href="https://www.openaire.eu/rdm-handbook">Learn more on how to manage your data in the open science era</a></li>-->
<!--<li><a href="https://www.openaire.eu/guides/">Find out how to use OpenAIRE to best serve your needs</a></li>-->
<!--<li><a href="https://www.openaire.eu/webinars/">View our training material on a variety of related topics</a></li>-->
<!--<li><a href="https://www.openaire.eu/contact-us/">Contact us</a></li>-->
<li><a href="https://www.openaire.eu/validator-registration-guide">Learn how to validate and register your repository</a></li>
<li><a href="https://www.openaire.eu/guides">Find out how to use OpenAIRE to best serve your needs</a></li>
<li><a href="https://www.openaire.eu/category/content-providers">View our training material for Content Providers</a></li>
<li><a href="https://guidelines.openaire.eu/en/latest/">Follow the OpenAIRE Guidelines</a></li>
<li><a href="https://www.openaire.eu/contact-us/">Contact us</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-section-default uk-section">
<div class="uk-container">
<div class="uk-grid-medium uk-margin-medium uk-grid" uk-grid="">
<div class="uk-width-2-3@m uk-first-column">
<div class="uk-margin-medium-top uk-panel">
<h3 class="el-title uk-margin uk-h3">
Our community
</h3>
<hr class="uk-divider-small uk-text-left provide">
<div class="uk-grid uk-margin-medium-top">
<div class="uk-width-expand@m">
<p class="uk-margin-medium-bottom">
<span class="emphasis provide">{{ (statisticsNumbers && statisticsNumbers.literature) ? (statisticsNumbers.literature | number) : 'N/A' }}</span><br>
<span class="uk-text-uppercase">literature repositories</span>
</p>
<p>
<span class="emphasis provide">{{ (statisticsNumbers && statisticsNumbers.journal) ? (statisticsNumbers.journal | number) : 'N/A' }}</span><br>
<span class="uk-text-uppercase">OA Journals</span>
</p>
</div>
<div class="uk-width-expand@m">
<p class="uk-margin-medium-bottom">
<span class="emphasis provide">{{ (statisticsNumbers && statisticsNumbers.dataRepositories) ? (statisticsNumbers.dataRepositories | number) : 'N/A' }}</span><br>
<span class="uk-text-uppercase">data repositories</span>
</p>
<p>
<span class="emphasis provide">{{ (statisticsNumbers && statisticsNumbers.aggregators) ? (statisticsNumbers.aggregators | number) : 'N/A' }}</span><br>
<span class="uk-text-uppercase">aggregators</span>
</p>
</div>
</div>
<div class="uk-grid">
<div class="uk-width-expand@m">
<p>
<span class="emphasis">{{ (statisticsNumbers && statisticsNumbers.publications) ? (statisticsNumbers.publications | number) : 'N/A' }}</span>
<span class="uk-text-uppercase"> publications</span>
</p>
<p>
<span class="emphasis">{{ (statisticsNumbers && statisticsNumbers.datasets) ? (statisticsNumbers.datasets | number) : 'N/A' }}</span>
<span class="uk-text-uppercase"> datasets</span>
</p>
<p>
<span class="emphasis">{{ (statisticsNumbers && statisticsNumbers.software) ? (statisticsNumbers.software | number) : 'N/A' }}</span>
<span class="uk-text-uppercase"> software</span>
</p>
</div>
<div class="uk-width-expand@m">
<p>
<span class="emphasis">{{ statisticsNumbers ? (statisticsNumbers.lastYearUsagestats.number | number) : 'N/A' }}</span>
<span class="uk-text-uppercase"> usage events
({{ statisticsNumbers ? statisticsNumbers.lastYearUsagestats.year : 'N/A' }})</span>
</p>
<p>
<span class="emphasis">
{{ (statisticsNumbers && statisticsNumbers.usagestats) ? statisticsNumbers.usagestats : 'N/A' }}
</span>
<span class="uk-text-uppercase"> metadata exchange events</span>
</p>
</div>
</div>
</div>
</div>
<div class="uk-width-expand@m">
<div class="uk-card uk-card-body uk-card-provide">
<h3 class="uk-margin-remove-top uk-h3">
<span class="">Our data policies</span>
</h3>
<hr class="uk-divider-small uk-text-left">
<ul class="uk-margin-small uk-list uk-list-large uk-margin-medium-bottom">
<li class="el-item uk-margin-medium-bottom">
<h5 class="el-title uk-h5">Data acquisition</h5>
<div class="el-content">
<span>How we retrieve data, how often, what processes it goes through (aggregating cleaning, transforming, inferring, de-duplicating), what are the quality checks&nbsp;along all&nbsp; data processing stages.</span>
</div>
</li>
<li class="el-item">
<h5 class="el-title uk-h5">Data usage</h5>
<div class="el-content">
<span>Who is able to retrieve our data, what are the licences, what about specific SLAs.</span>
</div>
</li>
</ul>
<div class="uk-margin uk-margin-remove-bottom uk-text-left">
<h6 class="uk-h6">
<a class="el-content uk-link-text" href="https://www.openaire.eu/data-aquisition-policy" target="_blank">
Learn more
</a>
</h6>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-section-muted" uk-scrollspy="{&quot;target&quot;:&quot;[uk-scrollspy-class]&quot;,&quot;cls&quot;:&quot;uk-animation-fade&quot;,&quot;delay&quot;:false}">
<div class="uk-container uk-container-large">
<div class="uk-grid uk-margin-large-top uk-margin-large-bottom" uk-grid="">
<div class="uk-width-expand@m uk-width-1-2@s uk-dark uk-grid-item-match uk-first-column explore">
<div class="uk-margin uk-panel uk-scrollspy-inview uk-animation-fade" uk-scrollspy-class="" style="">
<h4 class="el-title uk-margin uk-h4">
Researcher?
</h4>
<div class="el-content uk-margin">
Explore all OA research results. Link all your research. Build your profile
</div>
<p>
<a href="https://{{ inBeta ? 'beta.' : '' }}explore.openaire.eu" class="el-link uk-button uk-button-default" target="_blank">
OpenAIRE.EXPLORE
</a>
</p>
</div>
</div>
<div class="uk-width-expand@m uk-width-1-2@s uk-dark uk-grid-item-match connect">
<div class="uk-margin uk-panel uk-scrollspy-inview uk-animation-fade" uk-scrollspy-class="" style="">
<h4 class="el-title uk-margin uk-h4">
Research community?
</h4>
<div class="el-content uk-margin">
Use a trusted partner to share, link, disseminate and monitor your research.
</div>
<p>
<a href="https://{{ inBeta ? 'beta.' : '' }}connect.openaire.eu" class="el-link uk-button uk-button-default" target="_blank">
OpenAIRE.CONNECT
</a>
</p>
</div>
</div>
<div class="uk-width-expand@m uk-width-1-2@s uk-dark uk-grid-item-match monitor">
<div class="uk-margin uk-panel uk-scrollspy-inview uk-animation-fade" uk-scrollspy-class="" style="">
<h4 class="el-title uk-margin uk-h4">
Research manager?
</h4>
<div class="el-content uk-margin">
Use our monitoring services and easily track all relevant research results.
</div>
<p>
<a href="https://monitor.openaire.eu" class="el-link uk-button uk-button-default" target="_blank">
OpenAIRE.MONITOR
</a>
</p>
</div>
</div>
<div class="uk-width-expand@m uk-width-1-2@s uk-dark uk-grid-item-match develop">
<div class="uk-margin uk-panel uk-scrollspy-inview uk-animation-fade" uk-scrollspy-class="" style="">
<h4 class="el-title uk-margin uk-h4">
Developer?
</h4>
<div class="el-content uk-margin">
Get access to OpenAIRE data and capitalize on on Europe's open linked research
</div>
<p>
<a href="https://develop.openaire.eu" class="el-link uk-button uk-button-default" target="_blank">
OpenAIRE.DEVELOP
</a>
</p>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,56 @@
import { Component, OnInit } from '@angular/core';
import { UsageStatsSummary } from '../../domain/typeScriptClasses';
import { AuthenticationService } from '../../services/authentication.service';
import { StatisticsService } from '../../services/statistics.service';
import { Router } from '@angular/router';
@Component ({
selector: 'app-landing',
templateUrl: './landing.component.html'
})
export class LandingComponent implements OnInit {
statisticsNumbers: UsageStatsSummary;
inBeta: boolean;
constructor(private authService: AuthenticationService,
private statsService: StatisticsService,
private router: Router) { }
ngOnInit() {
this.getStatisticsNumbers();
const baseUrl = window.location.origin;
this.inBeta = ( baseUrl.includes('beta') || baseUrl.includes('athenarc') );
}
login() {
this.authService.loginWithState();
}
getStatisticsNumbers() {
this.statsService.getStatisticsNumbers().subscribe(
res => {
this.statisticsNumbers = res;
// this.statisticsNumbers.lastYearUsagestats = JSON.parse(res['lastYearUsagestats'].toString());
},
error => console.log(error),
() => {
console.log('statisticsNumbers is', JSON.stringify(this.statisticsNumbers));
}
);
}
goToPage(pageUrl: string) {
if (this.authService.getIsUserLoggedIn()) {
this.router.navigate([pageUrl]);
} else {
this.authService.redirectUrl = pageUrl;
this.login();
}
}
}

View File

@ -0,0 +1,89 @@
<div class="uk-section-default uk-section uk-section-small uk-padding-remove-bottom" style="min-height: 325px">
<!-- MARGIN-TOP -->
<div class="uk-sticky-placeholder" style="height: 84px; margin: 0px;" aria-hidden="true"></div>
<div class="uk-container uk-container-large">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Metrics</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div>
<div *ngIf="successMessage" class="uk-alert uk-alert-success">{{ successMessage }}</div>
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="repo && !loadingMessage">
<div>
<h4>You don't have metrics enabled for this repository yet. Would you like to enable them?</h4>
<p><img src="../../../assets/imgs/metricsWorkflow-new.svg"
style="display:block; margin: 0 auto;"
width="50%"></p>
<p>Once you select to enable metrics for your repository, the following steps need to be performed:</p>
<p><i>On your side</i><br>
1. Download the tracking code for your repository platform<br>
2. Configure the tracking code according to the instructions<br>
3. Deploy the tracking code in your repository platform
</p>
<p><i>On the OpenAIRE's side</i><br>
4. Validate the installation of the tracking code and inform the repository manager accordingly<br>
</p>
<div class="uk-alert uk-alert-info">
For more details about the workflows and tools please consult the
<a target="_blank" href="https://openaire.github.io/usage-statistics-guidelines/">
“Guidelines for Collecting Usage Events and Provision of Usage Statistics”
</a>
.
</div>
<button class="uk-button uk-button-primary" (click)="confirmEnabling()">Enable Metrics</button>
</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>
</div>
</div>
<confirmation-dialog #confirmEnablingModal [title]="modalTitle" [isModalShown]="isModalShown"
[confirmActionButton]="modalButton" (emitObject)="confirmedEnabling($event)">
Are you sure you want to enable metrics for this repository?
</confirmation-dialog>

View File

@ -0,0 +1,118 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ConfirmationDialogComponent } from '../../shared/reusablecomponents/confirmation-dialog.component';
import { PiwikService } from '../../services/piwik.service';
import { RepositoryService } from '../../services/repository.service';
import { PiwikInfo, Repository } from '../../domain/typeScriptClasses';
import { enabledMetricsError, enabledMetricsSuccess, enablingMetrics,
loadingRepoError, loadingRepoMessage } from '../../domain/shared-messages';
import { AuthenticationService } from '../../services/authentication.service';
@Component ({
selector: 'metrics-enable',
templateUrl: 'metrics-enable.component.html'
})
export class MetricsEnableComponent implements OnInit {
successMessage: string;
errorMessage: string;
loadingMessage: string;
readonly analyticsUrl = 'https://analytics.openaire.eu/addsite.php?';
readonly authenticationToken = '32846584f571be9b57488bf4088f30ea'; /* THE ACTUAL TOKEN WILL BE NEEDED EVENTUALLY!! */
repo: Repository;
oaId: string;
modalTitle = 'Confirmation';
modalButton = 'Yes, enable it';
isModalShown: boolean;
@ViewChild('confirmEnablingModal')
public confirmEnablingModal: ConfirmationDialogComponent;
constructor (
private route: ActivatedRoute,
private router: Router,
private authService: AuthenticationService,
private piwikService: PiwikService,
private repoService: RepositoryService
) {}
ngOnInit() {
this.getRepo();
this.isModalShown = false;
}
getRepo(): void {
const id = this.route.snapshot.paramMap.get('id');
this.loadingMessage = loadingRepoMessage;
this.repoService.getRepositoryById(id).subscribe(
repo => {
this.repo = repo;
},
error => {
console.log(error);
this.errorMessage = loadingRepoError;
this.loadingMessage = '';
}, () => {
if (this.repo) {
this.getOAid();
}
this.loadingMessage = '';
}
);
}
getOAid () {
this.piwikService.getOpenaireId(this.repo.id).subscribe(
id => {
this.oaId = id;
console.log(`getOpenaireId responded: ${this.oaId}`);
},
error => console.log(`ERROR is ${error}`)
);
}
confirmEnabling() {
if (this.repo) {
this.confirmEnablingModal.showModal();
}
}
confirmedEnabling(event: any) {
if (this.repo) {
this.loadingMessage = enablingMetrics;
const piwik: PiwikInfo = {
repositoryId: this.repo.id,
openaireId: this.oaId,
repositoryName: this.repo.officialName,
country: this.repo.countryName,
siteId: '',
authenticationToken: this.authenticationToken,
creationDate: null,
requestorName: this.authService.getUserName(),
requestorEmail: this.authService.getUserEmail(),
validated: false,
validationDate: null,
comment: ''
};
this.piwikService.enableMetricsForRepository(this.repo.officialName, this.repo.websiteUrl, piwik).subscribe(
response => {
console.log(`enableMetrics answered: ${response}`);
this.successMessage = enabledMetricsSuccess;
this.loadingMessage = '';
},
error => {
console.log(error);
this.errorMessage = enabledMetricsError;
this.loadingMessage = '';
},
() => {
this.router.navigate([`/getImpact/instructions/${this.repo.id}`]);
}
);
}
}
}

View File

@ -0,0 +1,91 @@
<div class="uk-section-default uk-section uk-section-small uk-padding-remove-bottom" style="min-height: 325px">
<!-- MARGIN-TOP -->
<div class="uk-sticky-placeholder" style="height: 84px; margin: 0px;" aria-hidden="true"></div>
<div class="uk-container uk-container-large">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Metrics Configuration & Software Details</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="piwik">
<p>
OpenAIREs usage statistic service uses the <i>Matomo Open Source Analytics platform</i> (matomo.org) to track usage activity. When <i>metrics</i>
are enabled for a repository, two unique identifiers are generated - a matomo-ID that associates the repository with its usage events in Matomo
and an authentication-ID that allows to track usage activity on the Matomo platform. Metadata views and item downloads are tracked and automatically sent to Matomo. Statistics are generated using the COUNTER Code of practice directives.
</p>
<p>
OpenAIRE's usage statistics service tracking code exploits Matomos API. In order to make the tracking of usage events from repositories more robust, it was necessary to implement repository platform specific patches and plugins starting with DSpace and EPrints. The code is maintained on Github:
</p>
<ul>
<li>as a patch for various versions of DSpace
(<a target="_blank" href="https://github.com/openaire/OpenAIRE-Piwik-DSpace">https://github.com/openaire/OpenAIRE-Piwik-DSpace</a>)</li>
<li>as an Eprints plugin for version 3
(<a target="_blank" href="https://github.com/openaire/EPrints-OAPiwik">https://github.com/openaire/EPrints-OAPiwik</a>)</li>
<li>as a python script for all other cases
(<a target="_blank" href="https://github.com/openaire/Generic-Matomo-Tracker">https://github.com/openaire/Generic-Matomo-Tracker</a>)</li>
</ul>
<p>
To configure your repository to allow tracking in Matomo platform, please change the configuration files with the following parameters and values, generated for your site:
</p>
<dl class="uk-description-list">
<dt>MatomoID</dt>
<dd>{{ piwik.siteId }}</dd>
<dt>AuthenticationToken</dt>
<dd>{{ piwik.authenticationToken }}</dd>
</dl>
<p>
Details for the configuration files are given in the README of the tracking code.
</p>
<div class="uk-alert uk-alert-info">
<strong>NOTE</strong>
- You will be informed by e-mail that the installation of the tracking code has been validated and when the usage statistics will be available.
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,47 @@
/**
* Created by myrto on 11/24/17.
*/
import { Component, OnInit } from '@angular/core';
import { PiwikInfo } from '../../domain/typeScriptClasses';
import { ActivatedRoute, Router } from '@angular/router';
import { PiwikService } from '../../services/piwik.service';
import { AuthenticationService } from '../../services/authentication.service';
import { loadingUserRepoInfoError } from '../../domain/shared-messages';
@Component ({
selector: 'app-metrics-instructions',
templateUrl: 'metrics-instructions.component.html'
})
export class MetricsInstructionsComponent implements OnInit {
piwik: PiwikInfo;
errorMessage: string;
loadingMessage: string;
constructor(
private route: ActivatedRoute,
private router: Router,
private piwikService: PiwikService,
private authService: AuthenticationService) {}
ngOnInit() {
this.getPiwik();
}
getPiwik(): void {
this.loadingMessage = 'Retrieving instructions ...';
const id = this.route.snapshot.paramMap.get('id');
this.piwikService.getPiwikInfo(id).subscribe(
piwik => this.piwik = piwik,
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = loadingUserRepoInfoError;
},
() => {
this.loadingMessage = '';
}
);
}
}

View File

@ -0,0 +1,100 @@
<div class="uk-section-default uk-section uk-section-small uk-padding-remove-bottom" style="min-height: 325px">
<!-- MARGIN-TOP -->
<div class="uk-sticky-placeholder" style="height: 84px; margin: 0px;" aria-hidden="true"></div>
<div class="uk-container uk-container-large">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">{{ piwik ? piwik.repositoryName : 'Metrics'}}</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="repoMetrics">
<div class="uk-grid">
<div class="uk-width-1-1 uk-margin-bottom">
<div class="uk-float-right">
<a class="uk-button uk-button-primary"
[routerLink]="['/getImpact/usagestats',repoId]" title="">Get statistics report</a>
</div>
</div>
<div class="uk-width-1-1 uk-margin-medium-bottom">
<div>
<div class="uk-child-width-1-3@m uk-grid-small uk-grid-match uk-grid" uk-grid="">
<div class="metrics-openaire uk-first-column">
<div class="uk-tile uk-tile-default uk-padding-small">
<div class="uk-text-center"> {{ pageViews }}</div>
<div class="uk-text-center"> views in OpenAIRE</div>
</div>
</div>
<div class="metrics-views">
<div class="uk-tile uk-tile-muted uk-padding-small">
<div class="uk-text-center"> {{ totalViews }}
<span *ngIf="repoMetrics.metricsNumbers.total_openaire_views">( {{ repoMetrics.metricsNumbers.total_openaire_views }} from OpenAIRE )</span>
</div>
<div class="uk-text-center">views in local repository</div>
</div>
</div>
<div class="metrics-downloads">
<div class="uk-tile uk-tile-primary uk-padding-small">
<div class="uk-text-center"> {{ totalDownloads }}
<span *ngIf="repoMetrics.metricsNumbers.total_openaire_downloads">( {{ repoMetrics.metricsNumbers.total_openaire_downloads }} from OpenAIRE )</span></div>
<div class="uk-text-center">downloads in local repository</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-width-1-1 uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium uk-margin-bottom uk-padding">
<iframe class="statsFrame" [src]="viewsUrl"></iframe>
</div>
<div class="uk-width-1-1 uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium uk-margin-bottom uk-padding">
<iframe class="statsFrame" [src]="downloadsUrl"></iframe>
</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,125 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MetricsInfo, PiwikInfo } from '../../domain/typeScriptClasses';
import { PiwikService } from '../../services/piwik.service';
import { RepositoryService } from '../../services/repository.service';
import { loadingMetrics, loadingMetricsError } from '../../domain/shared-messages';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { AuthenticationService } from '../../services/authentication.service';
@Component ({
selector: 'metrics-show',
templateUrl: 'metrics-show.component.html'
})
export class MetricsShowComponent implements OnInit {
errorMessage: string;
loadingMessage: string;
repoId: string;
piwik: PiwikInfo;
repoMetrics: MetricsInfo;
pageViews = '--';
totalViews = '--';
totalDownloads = '--';
viewsUrl: SafeResourceUrl;
downloadsUrl: SafeResourceUrl;
constructor(
private route: ActivatedRoute,
private router: Router,
private sanitizer: DomSanitizer,
private piwikService: PiwikService,
private repoService: RepositoryService,
private authService: AuthenticationService) {}
ngOnInit() {
this.repoId = this.route.snapshot.paramMap.get('id');
this.getPiwik();
}
getPiwik() {
this.loadingMessage = loadingMetrics;
this.piwikService.getPiwikInfo(this.repoId).subscribe(
piwik => this.piwik = piwik,
error => {
this.loadingMessage = '';
this.errorMessage = loadingMetricsError;
console.log(error);
},
() => {
this.loadingMessage = '';
this.errorMessage = '';
this.getMetrics();
}
);
}
getMetrics() {
this.loadingMessage = loadingMetrics;
this.repoService.getMetricsInfoForRepository(this.repoId).subscribe(
metrics => {
this.repoMetrics = metrics;
if (this.repoMetrics.metricsNumbers.pageviews) {
this.pageViews = this.repoMetrics.metricsNumbers.pageviews;
}
if (this.repoMetrics.metricsNumbers.total_views) {
this.totalViews = this.repoMetrics.metricsNumbers.total_views;
}
if (this.repoMetrics.metricsNumbers.total_downloads) {
this.totalDownloads = this.repoMetrics.metricsNumbers.total_downloads;
}
this.getViewsUrl();
this.getDownloadsUrl();
},
error => {
this.loadingMessage = '';
this.errorMessage = loadingMetricsError;
console.log(error);
},
() => {
this.loadingMessage = '';
this.errorMessage = '';
}
);
}
getViewsUrl () {
this.viewsUrl = this.sanitizer.bypassSecurityTrustResourceUrl(
`${this.repoMetrics.diagramsBaseURL}merge.php?com=query
&data=[{"query":"dtsrcRepoViews","dtsrcName":"${this.piwik.openaireId}",
"table":"","fields":[{"fld":"sum","agg":"sum","type":"chart","yaxis":1,"c":false}],
"xaxis":{"name":"month","agg":"sum"},"group":"","color":"","type":"chart","size":30,
"sort":"xaxis","xStyle":{"r":-30,"s":"0","l":"-","ft":"-","wt":"-"},"title":"","subtitle":"",
"xaxistitle":"","yaxisheaders":["Monthly views"],"generalxaxis":"","theme":0,"in":[]}]
&info_types=["spline"]&stacking=&steps=false&fontFamily=Courier&spacing=[5,0,0,0]
&style=[{"color":"rgba(0, 0, 0, 1)","size":"18"},{"color":"rgba(0, 0, 0, 1)","size":"18"},
{"color":"000000","size":""},{"color":"000000","size":""}]&backgroundColor=rgba(255,255,255,1)
&colors[]=rgba(124,181, 236, 1)&colors[]=rgba(67, 67, 72, 1)&colors[]=rgba(144, 237, 125,1)
&colors[]=rgba(247, 163, 92, 1)&colors[]=rgba(128, 133, 233,1)&colors[]=rgba(241, 92, 128, 1)
&colors[]=rgba(228, 211, 84,1)&colors[]=rgba(43, 144, 143, 1)&colors[]=rgba(244, 91, 91,1)
&colors[]=rgba(145, 232, 225,1)&xlinew=0&ylinew=1&legends=true&tooltips=true&persistent=false`
);
}
getDownloadsUrl () {
this.downloadsUrl = this.sanitizer.bypassSecurityTrustResourceUrl(
`${this.repoMetrics.diagramsBaseURL}merge.php?com=query
&data=[{"query":"dtsrcRepoDownloads","dtsrcName":"${this.piwik.openaireId}",
"table":"","fields":[{"fld":"sum","agg":"sum","type":"chart","yaxis":1,"c":false}],
"xaxis":{"name":"month","agg":"sum"},"group":"","color":"","type":"chart","size":30,
"sort":"xaxis","xStyle":{"r":-30,"s":"0","l":"-","ft":"-","wt":"-"},"title":"","subtitle":"",
"xaxistitle":"","yaxisheaders":["Monthly downloads"],"generalxaxis":"","theme":0,"in":[]}]
&info_types=["spline"]&stacking=&steps=false&fontFamily=Courier&spacing=[5,0,0,0]
&style=[{"color":"rgba(0, 0, 0, 1)","size":"18"},{"color":"rgba(0, 0, 0,1)","size":"18"},
{"color":"000000","size":""},{"color":"000000","size":""}]&backgroundColor=rgba(255,255,255,1)
&colors[]=rgba(124, 181, 236, 1)&colors[]=rgba(67, 67, 72, 1)&colors[]=rgba(144, 237, 125,1)
&colors[]=rgba(247, 163, 92, 1)&colors[]=rgba(128, 133, 233,1)&colors[]=rgba(241, 92, 128, 1)
&colors[]=rgba(228, 211, 84,1)&colors[]=rgba(43, 144, 143, 1)&colors[]=rgba(244, 91, 91,1)
&colors[]=rgba(145, 232, 225,1)&xlinew=0&ylinew=1&legends=true&tooltips=true&persistent=false`
);
}
}

View File

@ -0,0 +1,7 @@
.innerTable {
padding: 50px;
}
.innerTable th, .innerTable td {
padding: 11px 12px;
}

View File

@ -0,0 +1,229 @@
<div class="uk-section-default uk-section uk-section-small uk-padding-remove-bottom" style="min-height: 325px">
<!-- MARGIN-TOP -->
<div class="uk-sticky-placeholder" style="height: 84px; margin: 0px;" aria-hidden="true"></div>
<div class="uk-container uk-container-large">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Get usage statistics report</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m" style="min-height:500px;">
<div *ngIf="errorMessage" class="uk-alert uk-alert-warning">{{errorMessage}}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="repoResponse" class="uk-margin-top">
<h3>{{ repoResponse.ReportDefinition['@Name'] }} Report Results
<span *ngIf="repoResponse.Report &&
repoResponse.Report.Report &&
repoResponse.Report.Report.Customer &&
repoResponse.Report.Report.Customer.ReportItems &&
repoResponse.Report.Report.Customer.ReportItems.length > 0">for {{ repoResponse.Report.Report.Customer.ReportItems[0].ItemPlatform }}</span>
</h3>
<div class="uk-width-1-2">
<table class="uk-table">
<tr>
<th>Period covered</th>
<td>{{ coveredPeriod }}</td>
</tr>
<tr>
<th>Filters</th>
<td>
<span *ngFor="let filter of repoResponse.ReportDefinition.Filters.Filter; let i = index">
<br *ngIf="i>0">
{{ filter.Name }}: {{ filter.Value }}
</span>
</td>
</tr>
<tr>
<th>Date run</th>
<td>{{ repoResponse.Report.Report['@Created'] | date: "yyyy-MM-dd HH:mm:ss" }}</td>
</tr>
<tr>
<th>Number of results</th>
<td>{{ repoResponse.ReportDefinition.Filters.ReportAttribute[1].Value }}</td>
</tr>
</table>
</div>
<div *ngIf="repoResponse.Report.Report.Customer &&
repoResponse.Report.Report.Customer.ReportItems">
<div>
<div class="show-options uk-inline" style="float: right;">
<div class="filterLabel" style="display: inline;">Results per page:</div>
<div [formGroup]="pageSizeSelect" class="inlineBlock">
<select class="form-control" formControlName="selectPageSize" (change)="getPageSize()">
<option value="10" selected>10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
</div>
</div><br>
<div class="contentAndPagerPanel">
<!-- TOP PAGINATION LINKS -->
<div>
<ul class="uk-pagination">
<li>
<a class="uk-link uk-link-muted" (click)="goToPreviousPage()">
<span class="uk-margin-small-right uk-pagination-previous uk-icon" uk-pagination-previous="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg"
icon="pagination-previous" ratio="1"></svg>
</span>
Previous
</a>
</li>
<li class="uk-margin-auto-left">
<a class="uk-link uk-link-muted" (click)="goToNextPage()">
Next
<span class="uk-margin-small-left uk-pagination-next uk-icon" uk-pagination-next="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg"
icon="pagination-next" ratio="1"></svg>
</span>
</a>
</li>
</ul>
<div class="resultsPageLabel">page {{ (totalPages > 0) ? page+1 : 0 }} of {{ totalPages }}</div>
</div>
<!-- RESULTS TABLE -->
<div>
<div>
<div class="uk-overflow-auto uk-scrollspy-inview uk-animation-slide-top-medium uk-margin-top uk-margin-bottom">
<table class="uk-table uk-table-middle uk-table-striped" style="vertical-align: top !important;">
<thead>
<tr>
<th *ngIf="chosenReport !== 'RR1'">Title</th>
<th *ngIf="chosenReport !== 'RR1'">Publisher</th>
<th *ngIf="chosenReport === 'RR1'">Platform name</th>
<th>{{ (chosenReport !== 'RR1') ? 'Item Urls' : 'Url' }}</th>
<th>Type</th>
<th colspan="2">Downloads/Views</th>
</tr>
</thead>
<td colspan="6" *ngIf="infoMessage" class="uk-alert">{{ infoMessage }}</td>
<tbody *ngFor="let item of repoResponse.Report.Report.Customer.ReportItems; let item_i = index"
style="border-bottom: 1px solid whitesmoke;">
<tr>
<td *ngIf="chosenReport !== 'RR1'">{{ item.ItemName }}</td>
<td *ngIf="chosenReport !== 'RR1'">{{ item.ItemPublisher }}</td>
<td *ngIf="chosenReport === 'RR1'">{{ item.ItemPlatform }}</td>
<td style="min-width: 300px;">
<span *ngFor="let url of transformItem(item.ItemIdentifier); let i = index">
<br *ngIf="i>0">{{ url }}
</span>
</td>
<td>{{ item.ItemDataType }}</td>
<td class="uk-text-center"
*ngIf="repoResponse.ReportDefinition.Filters.ReportAttribute[0].Value === 'Monthly'" colspan="2">
<a *ngIf="item.ItemPerformance && (item.ItemPerformance.length > 0)"
(click)="displayItemPerformance(item_i)">{{ (selectedItemIndex === item_i) ? 'Hide' : 'See' }} results</a>
</td>
<td class="uk-text-center"
*ngIf="repoResponse.ReportDefinition.Filters.ReportAttribute[0].Value === 'Totals'">
{{ item.ItemPerformance[0].Instance[0].Count }}
</td>
<td class="uk-text-center"
*ngIf="repoResponse.ReportDefinition.Filters.ReportAttribute[0].Value === 'Totals'">
{{ item.ItemPerformance[0].Instance[1].Count }}
</td>
</tr>
<tr *ngIf="(selectedItemIndex === item_i)">
<td colspan="6">
<div class="uk-animation-slide-top-medium uk-margin-small-top">
<table class="uk-table uk-table-middle uk-table-striped innerTable">
<tr>
<th>Month</th>
<th>Downloads</th>
<th>Views</th>
</tr>
<tr *ngFor="let month of item.ItemPerformance">
<td>{{ month.Period.Begin | date: "MMM yyyy" }}</td>
<td>{{ month.Instance[0].Count }}</td>
<td>{{ month.Instance[1].Count }}</td>
</tr>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- BOTTOM PAGINATION LINKS -->
<div>
<ul class="uk-pagination">
<li>
<a class="uk-link uk-link-muted" (click)="goToPreviousPage()">
<span class="uk-margin-small-right uk-pagination-previous uk-icon" uk-pagination-previous="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg"
icon="pagination-previous" ratio="1"></svg>
</span>
Previous
</a>
</li>
<li class="uk-margin-auto-left">
<a class="uk-link uk-link-muted" (click)="goToNextPage()">
Next
<span class="uk-margin-small-left uk-pagination-next uk-icon" uk-pagination-next="">
<svg width="7" height="12" viewBox="0 0 7 12" xmlns="http://www.w3.org/2000/svg"
icon="pagination-next" ratio="1"></svg>
</span>
</a>
</li>
</ul>
<div class="resultsPageLabel">page {{ (totalPages > 0) ? page+1 : 0 }} of {{ totalPages }}</div>
</div>
</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,159 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AuthenticationService } from '../../services/authentication.service';
import { UsagestatsService } from '../../services/usagestats.service';
import { ReportResponse } from '../../domain/usageStatsClasses';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'metrics-usagestats-report-results',
templateUrl: 'metrics-usagestats-report-results.component.html',
styleUrls: ['metrics-usagestats-report-results.component.css']
})
export class MetricsUsagestatsReportResultsComponent implements OnInit {
loadingMessage: string;
errorMessage: string;
infoMessage: string;
repoResponse: ReportResponse;
coveredPeriod: string;
params: URLSearchParams;
page: number;
pageSize: number;
totalPages: number;
selectedItemIndex: number;
pageSizeSelect: FormGroup;
chosenReport: string;
constructor(private route: ActivatedRoute,
private authService: AuthenticationService,
private usageService: UsagestatsService,
private fb: FormBuilder) {}
ngOnInit() {
this.page = 0;
this.pageSize = 10;
this.readParams();
this.pageSizeSelect = this.fb.group({selectPageSize: ['']});
}
readParams() {
this.params = new URLSearchParams();
this.route.queryParams.subscribe( qparams => {
this.params.append('Report', qparams['report']);
this.params.append('Release', '4');
this.params.append('RequestorID', this.authService.getUserEmail());
this.params.append('BeginDate', qparams['beginDate']);
this.params.append('EndDate', qparams['endDate']);
this.params.append('RepositoryIdentifier', qparams['repoId']);
this.params.append('ItemIdentifier', qparams['itemIdentifier']);
this.params.append('ItemDataType', qparams['itemIdentifier']);
this.params.append('Granularity', qparams['granularity']);
});
this.chosenReport = this.params.get('Report');
this.getReportResponse();
}
getReportResponse() {
this.errorMessage = '';
this.loadingMessage = 'Loading results...';
this.infoMessage = '';
this.selectedItemIndex = null;
this.repoResponse = null;
this.usageService.getReportResponse(this.page.toString(), this.pageSize.toString(), this.params).subscribe(
responseWrapper => {
this.repoResponse = responseWrapper.ReportResponse;
},
error => {
this.errorMessage = 'Failed to load the report results!';
this.loadingMessage = '';
},
() => {
this.errorMessage = '';
this.loadingMessage = '';
this.pageSizeSelect.get('selectPageSize').setValue(this.pageSize);
this.pageSizeSelect.get('selectPageSize').updateValueAndValidity();
this.totalPages = Math.ceil(
+this.repoResponse.ReportDefinition.Filters
.ReportAttribute.filter(x => x['Name'] === 'ReportItemCount')[0].Value / this.pageSize);
if ( this.totalPages === 0 ) {
this.infoMessage = 'No results were found';
}
if (this.repoResponse.ReportDefinition && this.repoResponse.ReportDefinition.Filters &&
this.repoResponse.ReportDefinition.Filters.ReportAttribute) {
if (this.repoResponse.Report && this.repoResponse.ReportDefinition.Filters.UsageDateRange &&
this.repoResponse.ReportDefinition.Filters.UsageDateRange.Begin &&
this.repoResponse.ReportDefinition.Filters.UsageDateRange.End) {
this.coveredPeriod = this.repoResponse.ReportDefinition.Filters.UsageDateRange.Begin + ' to ';
this.coveredPeriod = this.coveredPeriod + this.repoResponse.ReportDefinition.Filters.UsageDateRange.End;
} else {
const defaultDatePeriod = this.repoResponse.Exception.filter(x => x['Message'] === 'Unspecified Date Arguments');
this.coveredPeriod = defaultDatePeriod[0].Data.split(':')[1].trim() + ' to ';
this.coveredPeriod = this.coveredPeriod + defaultDatePeriod[1].Data.split(':')[1].trim() + ' (default)';
}
} else {
this.repoResponse = null;
}
}
);
}
getPageSize() {
this.pageSize = +(this.pageSizeSelect.get('selectPageSize').value);
this.page = 0;
this.getReportResponse();
}
goToNextPage() {
if ( (this.page + 1) < this.totalPages) {
this.page++;
console.log(`Get me page ${this.page}!`);
this.getReportResponse();
}
}
goToPreviousPage() {
if (this.page > 0) {
this.page--;
console.log(`Get me page ${this.page}!`);
this.getReportResponse();
}
}
displayItemPerformance(i: number) {
if (this.selectedItemIndex === i) {
this.selectedItemIndex = null;
} else {
this.selectedItemIndex = i;
}
}
transformItem(itemIdentifiers: any[]) {
let field: string;
if (this.chosenReport === 'RR1') {
field = 'URL';
} else {
field = 'URLs';
}
const i = itemIdentifiers.findIndex(x => x['Type'] === field);
if ( i > -1 ) {
const urls = itemIdentifiers[i]['Value'];
return urls.split(';');
}
return '';
}
}

View File

@ -0,0 +1,210 @@
<div class="uk-section-default uk-section uk-section-small uk-padding-remove-bottom" style="min-height: 325px">
<!-- MARGIN-TOP -->
<div class="uk-sticky-placeholder" style="height: 84px; margin: 0px;" aria-hidden="true"></div>
<div class="uk-container uk-container-large">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">{{ title }}</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m" style="min-height:500px;">
<div *ngIf="errorMessage" class="uk-alert uk-alert-warning">{{errorMessage}}</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="repo && chosen_report" class="uk-margin-top">
<div class="uk-forml uk-width-1-1@s uk-width-2-3@m uk-container uk-container-large">
<h3>Report Request</h3>
<div class="uk-grid">
<div class=" uk-width-1-3 uk-text-right">
Report Name:
</div>
<div class="uk-width-2-3">
{{ chosen_report }}
</div>
</div>
<div class="uk-grid">
<div class=" uk-width-1-3 uk-text-right">
Release:
</div>
<div class="uk-width-2-3">
4
</div>
</div>
<div class="uk-grid">
<div class=" uk-width-1-3 uk-text-right">
Requestor:
</div>
<div class="uk-width-2-3">
{{ userEmail }}
</div>
</div>
<h3>Report Filters</h3>
<h5>Date range</h5>
<p>Valid date formats are yyyy-mm-dd or yyyy-mm. Default range is the last available month.
</p>
<div class="uk-grid">
<div class=" uk-width-1-3 uk-text-right">
Begin Date:
</div>
<div class="uk-width-2-3">
<input name="BeginDate" placeholder="2016-03" type="text" (blur)="updateBeginDate($event)">
</div>
</div>
<div class="uk-grid">
<div class=" uk-width-1-3 uk-text-right">
End Date:
</div>
<div class="uk-width-2-3">
<input name="EndDate" placeholder="2016-06" type="text" (blur)="updateEndDate($event)">
</div>
</div>
<h5><span *ngIf="chosen_report == 'RR1' || chosen_report == 'JR1'">Optional </span>Filters</h5>
<p *ngIf="chosen_report != 'RR1' && chosen_report != 'JR1'">
For more specific results, provide an Item Identifier.<br>
Identifier format: <b>namespace:value</b><br>
Valid namespace for Item Identifier: <b>openaire</b>, <b>doi</b> or <b>oid</b>(for OAI-PMH).
</p>
<p *ngIf="chosen_report =='RR1'">
By default results are returned for all repositories.<br>
To get just the results for the current repository, check the box.</p>
<div *ngIf="chosen_report != 'JR1'" class="uk-grid">
<div class=" uk-width-1-3 uk-text-right">
Repository Identifier:
</div>
<div class="uk-width-2-3">
{{ shownRepoId }}
</div>
<div *ngIf="chosen_report =='RR1'" class=" uk-width-1-3 uk-text-right">
Select current repository
</div>
<div *ngIf="chosen_report =='RR1'" class="uk-width-2-3 checkbox">
<input type="checkbox" value="useCurrentRepo"
(change)="updateUseCurrentRepo($event)">
</div>
</div>
<div *ngIf="repo.issn && chosen_report == 'JR1'" class="uk-grid">
<div class=" uk-width-1-3 uk-text-right">
Journal Identifier:
</div>
<div class="uk-width-2-3">
{{ shownRepoId }}
</div>
</div>
<div *ngIf="chosen_report != 'JR1' && chosen_report != 'RR1'" class="uk-grid">
<div class=" uk-width-1-3 uk-text-right">
Item Identifier:
</div>
<div class="uk-width-2-3">
<input name="ItemIdentifier" placeholder="e.g. openaire:od_________::fb90de6f20d79783d05749d8f60417d5"
type="text" (blur)="updateItemIdentifier($event)">
</div>
</div>
<div *ngIf="chosen_report == 'IR1' || chosen_report == 'RR1' || chosen_report == 'JR1'">
<p>Optional filter to only show results for a single item type, e.g. article, book, etc.</p>
<div class="uk-grid">
<div class=" uk-width-1-3 uk-text-right">
Item Data Type:
</div>
<div class="uk-width-2-3">
<!-- TODO: get the list from api if it becomes available -->
<select name="ItemDataType" (change)="updateItemDataType($event)">
<option value="">--- Select Item Data Type ---</option>
<option value="Annotation">Annotation</option>
<option value="Article">Article</option>
<option value="Bachelor thesis">Bachelor thesis</option>
<option value="Book">Book</option>
<option value="clinical trial">clinical trial</option>
<option value="Collection">Collection</option>
<option value="Conference object">Conference object</option>
<option value="Contribution for newspaper or weekly magazine">Contribution for newspaper or weekly magazine</option>
<option value="Dataset">Dataset</option>
<option value="Doctoral thesis">Doctoral thesis</option>
<option value="Event">Event</option>
<option value="External research report">External research report</option>
<option value="Film">Film</option>
<option value="Image">Image</option>
<option value="InteractiveResource">InteractiveResource</option>
<option value="Internal report">Internal report</option>
<option value="Lecture">Lecture</option>
<option value="Master thesis">Master thesis</option>
<option value="Newsletter">Newsletter</option>
<option value="Other">Other</option>
<option value="Part of book or chapter of book">Part of book or chapter of book</option>
<option value="Patent">Patent</option>
<option value="PhysicalObject">PhysicalObject</option>
<option value="Preprint">Preprint</option>
<option value="Report">Report</option>
<option value="Research">Research</option>
<option value="Review">Review</option>
<option value="Software">Software</option>
<option value="Sound">Sound</option>
<option value="Unknown">Unknown</option>
</select>
</div>
</div>
</div>
<h3>Report Attributes</h3>
<p>Valid Granularity values: Monthly or Totals</p>
<div class="uk-grid">
<div class=" uk-width-1-3 uk-text-right">
Granularity:
</div>
<div class="uk-width-2-3">
<select name="Granularity" (change)="updateGranularity($event)">
<option value="Monthly">Monthly</option>
<option value="Totals">Totals</option>
</select>
</div>
</div>
<!--<p>The Pretty attribute is just for humans playing with the API and looking at results in a browser.</p>
<p><input name="Pretty" value="Pretty" checked="checked" type="checkbox" (change)="updatePretty($event)">Pretty print json(p) for humans</p>-->
<a class="uk-button uk-button-primary uk-margin-top" (click)="goToReport()">Get Report</a>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,147 @@
import { Component, OnInit } from '@angular/core';
import { Repository } from '../../domain/typeScriptClasses';
import { ActivatedRoute, Router } from '@angular/router';
import { RepositoryService } from '../../services/repository.service';
import { AuthenticationService } from '../../services/authentication.service';
import { loadingRepoMessage } from '../../domain/shared-messages';
@Component({
selector: 'metrics-usagestats-report',
templateUrl: './metrics-usagestats-report.component.html'
})
export class MetricsUsagestatsReportComponent implements OnInit {
errorMessage: string;
loadingMessage: string;
title: string;
repo: Repository;
repoId: string;
shownRepoId: string;
shownOpenaireId: string;
useCurrentRepo: boolean;
issnToShow = '';
chosen_report: string;
userEmail: string;
beginDate = '';
endDate = '';
itemIdentifier = '';
itemDataType = '';
granularity = 'Monthly';
constructor(private repoService: RepositoryService,
private route: ActivatedRoute,
private router: Router,
private authService: AuthenticationService) {}
ngOnInit() {
this.getParams();
this.getUserEmail();
this.getRepo();
}
getParams() {
this.repoId = this.route.snapshot.paramMap.get('id');
this.chosen_report = this.route.snapshot.paramMap.get('reportID');
this.shownRepoId = this.convertToDisplayedFormat(this.repoId);
console.log(`shownRepoId is ${this.repoId}`);
this.title = `${this.chosen_report} report`;
if (this.chosen_report !== 'RR1') {
this.useCurrentRepo = true;
}
}
convertToDisplayedFormat(input: string) {
const tempArray = this.repoId.split('____::');
return tempArray[0] + ':' + tempArray[1];
}
getUserEmail() {
this.userEmail = this.authService.getUserEmail();
}
getRepo() {
this.loadingMessage = loadingRepoMessage;
this.repoService.getRepositoryById(this.repoId).subscribe(
repo => this.repo = repo,
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = 'The repository could not be retrieved';
},
() => {
this.loadingMessage = '';
if (this.repo.piwikInfo) {
this.shownOpenaireId = this.convertToDisplayedFormat(this.repo.piwikInfo.openaireId);
}
if (this.repo.issn && this.repo.issn !== 'null') {
this.shownRepoId = this.repo.issn.slice(0, 4) + '-' + this.repo.issn.toString().slice(4);
}
this.title = `${this.chosen_report} report for ${this.repo.officialName}`;
}
);
}
updateBeginDate(event: any) {
this.beginDate = event.target.value;
}
updateEndDate(event: any) {
this.endDate = event.target.value;
}
updateItemDataType(event: any) {
this.itemDataType = event.target.value;
}
updateItemIdentifier(event: any) {
this.itemIdentifier = event.target.value;
}
updateGranularity(event: any) {
this.granularity = event.target.value;
}
updateUseCurrentRepo(event: any) {
this.useCurrentRepo = event.target.value;
}
goToReport() {
if (!this.useCurrentRepo) { this.shownRepoId = ''; }
this.router.navigate(['/getImpact/usagestats-report-results'], {
queryParams: {
report: this.chosen_report,
beginDate: this.beginDate,
endDate: this.endDate,
repoId: this.shownRepoId,
itemDataType: this.itemDataType,
itemIdentifier: this.itemIdentifier,
granularity: this.granularity
}
});
/*const params = new URLSearchParams();
params.append('Report', this.chosen_report);
params.append('Release', '4');
params.append('RequestorID', this.authService.getUserEmail());
params.append('BeginDate', this.beginDate);
params.append('EndDate', this.endDate);
params.append('RepositoryIdentifier', this.shownRepoId);
if (this.itemIdentifier) {
params.append('ItemIdentifier', this.itemIdentifier);
}
if (this.itemDataType) {
params.append('ItemDataType', this.itemDataType);
}
params.append('Pretty', 'Pretty');
let url = `http://beta.services.openaire.eu/usagestats/sushilite/GetReport/?${params}`;
console.log(`going to: ${url}`);
window.location.href = url;*/
}
}

View File

@ -0,0 +1,136 @@
<div class="uk-section-default uk-section uk-section-small uk-padding-remove-bottom" style="min-height: 325px">
<!-- MARGIN-TOP -->
<div class="uk-sticky-placeholder" style="height: 84px; margin: 0px;" aria-hidden="true"></div>
<div class="uk-container uk-container-large">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">{{ title }}</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m" style="min-height:500px;">
<div *ngIf="errorMessage" class="uk-alert uk-alert-warning">{{ errorMessage }}</div>
<div *ngIf="repo">
<h3>Supported Reports</h3>
<div class="uk-margin uk-grid repositoryTypeSelection">
<div class="uk-width-1-3 uk-grid-item-match uk-first-column">
<div class="uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium">
<a [routerLink]="['AR1']" class="uk-position-cover uk-margin-remove-adjacent"></a>
<div class="uk-card-media-top">
<img src="../../../assets/imgs/Icons_Reports_wide_AR1.png" alt="" style="width: 100%;">
</div>
<div class="uk-card-body">
<h3 class="el-title uk-margin uk-card-title uk-margin-remove-adjacent uk-margin-small-bottom">
Article Report 1, number of successful article download requests by month and repository.
</h3>
</div>
</div>
</div>
<div class="uk-width-1-3 uk-grid-item-match uk-first-column">
<div class="uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium">
<a [routerLink]="['IR1']" class="uk-position-cover uk-margin-remove-adjacent"></a>
<div class="uk-card-media-top">
<img class="el-image" src="../../../assets/imgs/Icons_Reports_wide_IR1.png" alt="" style="width:100%;">
</div>
<div class="uk-card-body">
<h3 class="el-title uk-margin uk-card-title uk-margin-remove-adjacent uk-margin-small-bottom">
Item Report 1, number of successful item download requests by month and repository.
</h3>
</div>
</div>
</div>
<div class="uk-width-1-3 uk-grid-item-match uk-first-column">
<div class="uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium">
<a [routerLink]="['RR1']" class="uk-position-cover uk-margin-remove-adjacent"></a>
<div class="uk-card-media-top">
<img class="el-image" src="../../../assets/imgs/Icons_Reports_wide_RR1.png" alt="" style="width:100%;">
</div>
<div class="uk-card-body">
<h3 class="el-title uk-margin uk-card-title uk-margin-remove-adjacent uk-margin-small-bottom">
Repository Report 1, number of successful item downloads for all repositories participating in the usage statistics service.
</h3>
</div>
</div>
</div>
<div *ngIf="repo.datasourceType === 'journal'" class="uk-width-1-3 uk-grid-item-match uk-first-column">
<div class="uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium">
<a [routerLink]="['JR1']" class="uk-position-cover uk-margin-remove-adjacent"></a>
<div class="uk-card-media-top">
<img class="el-image" src="../../../assets/imgs/Icons_Reports_wide_JR1.png" alt="" style="width:100%;">
</div>
<div class="uk-card-body">
<h2 class="el-title uk-margin uk-card-title uk-margin-remove-adjacent uk-margin-small-bottom">
Journal Report 1, number of successful full-text article requests by month and journal.
</h2>
</div>
</div>
</div>
<div class="uk-width-1-3 uk-grid-item-match uk-first-column">
<div class="uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium">
<a [routerLink]="['BR1']" class="uk-position-cover uk-margin-remove-adjacent"></a>
<div class="uk-card-media-top">
<img class="el-image" src="../../../assets/imgs/Icons_Reports_wide_BR1.png" alt="" style="width:100%;">
</div>
<div class="uk-card-body">
<h3 class="el-title uk-margin uk-card-title uk-margin-remove-adjacent uk-margin-small-bottom">
Book Report 1, number of successful title requests by month and title.
</h3>
</div>
</div>
</div>
<div class="uk-width-1-3 uk-grid-item-match uk-first-column">
<div class="uk-text-center uk-card uk-card-default uk-card-hover uk-scrollspy-inview uk-animation-slide-top-medium">
<a [routerLink]="['BR2']" class="uk-position-cover uk-margin-remove-adjacent"></a>
<div class="uk-card-media-top">
<img class="el-image" src="../../../assets/imgs/Icons_Reports_wide_BR2.png" alt="" style="width:100%;">
</div>
<div class="uk-card-body">
<h3 class="el-title uk-margin uk-card-title uk-margin-remove-adjacent uk-margin-small-bottom">
Book Report 2, number of successful section requests by month and title.
</h3>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,47 @@
import { Component, OnInit } from '@angular/core';
import { Repository } from '../../domain/typeScriptClasses';
import { RepositoryService } from '../../services/repository.service';
import { AuthenticationService } from '../../services/authentication.service';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
selector: 'metrics-usagestats',
templateUrl: 'metrics-usagestats.component.html'
})
export class MetricsUsagestatsComponent implements OnInit {
errorMessage: string;
title = 'Get usage statistics report';
repo: Repository;
repoId: string;
constructor(private repoService: RepositoryService,
private authService: AuthenticationService,
private route: ActivatedRoute,
private router: Router) {}
ngOnInit() {
this.getRepo();
}
getRepo() {
this.repoId = this.route.snapshot.paramMap.get('id');
if (this.repoId) {
this.repoService.getRepositoryById(this.repoId).subscribe(
repo => this.repo = repo,
error => {
console.log(error);
this.errorMessage = 'The repository could not be retrieved';
},
() => {
this.title = this.title + ' for ' + this.repo.officialName;
console.log(this.authService.getUserEmail(), this.repo.registeredBy);
}
);
}
}
}

View File

@ -0,0 +1,50 @@
<div class="uk-section-default uk-section uk-section-small uk-padding-remove-bottom" style="min-height: 325px">
<!-- MARGIN-TOP -->
<div class="uk-sticky-placeholder" style="height: 84px; margin: 0px;" aria-hidden="true"></div>
<div class="uk-container uk-container-large">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<h1 class="uk-h2">Metrics</h1>
<!-- TOP HELP CONTENT -->
<help-content #topHelperContent [position]="'top'"
[ngClass]="topHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
<div class="uk-container uk-container-large uk-margin-medium-top uk-margin-medium-bottom" style="min-height: 500px;">
<div class="uk-grid">
<!-- LEFT HELP CONTENT -->
<aside-help-content #leftHelperContent [position]="'left'"
[ngClass]="leftHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<repository-tiles [parent]="'metrics'"></repository-tiles>
</div>
<!-- RIGHT HELP CONTENT -->
<aside-help-content #rightHelperContent [position]="'right'"
[ngClass]="rightHelperContent.isPresent()?'tm-sidebar uk-width-1-4@m uk-first-column':'clear-style'">
</aside-help-content>
</div>
</div>
<!-- BOTTOM HELP CONTENT -->
<help-content #bottomHelperContent [position]="'bottom'"
[ngClass]="bottomHelperContent.isPresent()?'uk-margin-medium-top uk-margin-medium-bottom':'clear-style'">
</help-content>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,17 @@
/**
* Created by myrto on 11/27/17.
*/
import { Component, OnInit } from '@angular/core';
@Component ({
selector: 'app-metrics',
templateUrl: 'metrics.component.html'
})
export class MetricsComponent implements OnInit {
constructor() {}
ngOnInit() { }
}

View File

@ -0,0 +1,37 @@
/**
* Created by myrto on 11/27/17.
*/
import { NgModule } from '@angular/core';
import { TabsModule } from 'ngx-bootstrap';
import { CommonModule } from '@angular/common';
import { MetricsRouting } from './metrics.routing';
import { ReusableComponentsModule } from '../../shared/reusablecomponents/reusable-components.module';
import { ReactiveFormsModule } from '@angular/forms';
import { MetricsComponent } from './metrics.component';
import { MetricsEnableComponent } from './metrics-enable.component';
import { MetricsInstructionsComponent } from './metrics-instructions.component';
import { MetricsShowComponent } from './metrics-show.component';
import { MetricsUsagestatsComponent } from './metrics-usagestats.component';
import { MetricsUsagestatsReportComponent } from './metrics-usagestats-report.component';
import { MetricsUsagestatsReportResultsComponent } from './metrics-usagestats-report-results.component';
@NgModule ({
imports: [
CommonModule,
TabsModule.forRoot(),
MetricsRouting,
ReusableComponentsModule,
ReactiveFormsModule
],
declarations: [
MetricsComponent,
MetricsEnableComponent,
MetricsInstructionsComponent,
MetricsShowComponent,
MetricsUsagestatsComponent,
MetricsUsagestatsReportComponent,
MetricsUsagestatsReportResultsComponent
]
})
export class MetricsModule { }

View File

@ -0,0 +1,52 @@
/**
* Created by myrto on 11/27/17.
*/
import { RouterModule, Routes } from '@angular/router';
import { MetricsComponent } from './metrics.component';
import { MetricsEnableComponent } from './metrics-enable.component';
import { MetricsShowComponent } from './metrics-show.component';
import { MetricsInstructionsComponent } from './metrics-instructions.component';
import { MetricsUsagestatsComponent } from './metrics-usagestats.component';
import { MetricsUsagestatsReportComponent } from './metrics-usagestats-report.component';
import { MetricsUsagestatsReportResultsComponent } from './metrics-usagestats-report-results.component';
import { NgModule } from '@angular/core';
const metricsRoutes: Routes = [
{
path: '',
component: MetricsComponent
},
{
path: 'enable/:id',
component: MetricsEnableComponent
},
{
path: 'show_metrics/:id',
component: MetricsShowComponent
},
{
path: 'instructions/:id',
component: MetricsInstructionsComponent
},
{
path: 'usagestats/:id',
component: MetricsUsagestatsComponent
},
{
path: 'usagestats/:id/:reportID',
component: MetricsUsagestatsReportComponent
},
{
path: 'usagestats-report-results',
component: MetricsUsagestatsReportResultsComponent
}
];
@NgModule ({
imports: [RouterModule.forChild(metricsRoutes)],
exports: [RouterModule]
})
export class MetricsRouting {}

View File

@ -0,0 +1,8 @@
<div class="uk-section-default uk-section uk-section-small uk-padding-remove-bottom" style="min-height: 325px">
<!-- MARGIN-TOP -->
<div class="uk-sticky-placeholder" style="height: 84px; margin: 0px;" aria-hidden="true"></div>
<div class="uk-container uk-container-large" style="min-height: 500px;">
<router-outlet></router-outlet>
</div>
</div>

View File

@ -0,0 +1,118 @@
<form [formGroup]="group">
<div>
<h4 class="uk-h4 uk-text-primary uk-scrollspy-inview uk-animation-slide-top-medium" uk-scrollspy-class="">
Basic information
</h4>
</div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">{{ errorMessage }}</div>
<div *ngIf="successMessage" class="uk-alert uk-alert-success">{{ successMessage }}</div>
<form-inline [description]="softwarePlatformDesc" [valid]="group.get('softwarePlatform').valid">
<select formControlName="softwarePlatform" class="form-control">
<option *ngFor="let platform of typologies" value="{{ platform.value }}">{{ platform.name }}</option>
</select>
</form-inline>
<form-inline [description]="officialNameDesc" [valid]="group.get('officialName').valid">
<input formControlName="officialName" class="form-control" type="text">
</form-inline>
<div *ngIf="mode == 'journal'">
<form-inline [description]="issnDesc" [valid]="group.get('issn').valid">
<span *ngIf="group.get('issn').invalid && group.get('issn').touched && group.get('issn').dirty"
class="help-block inline uk-text-danger"
style="margin-top: 0px; margin-bottom: 0px; padding-left: 10px;">Issn needs to be of the form: "1111-1111" or "1111-111X"</span>
<input formControlName="issn" class="form-control" type="text" (focus)="group.get('issn').markAsUntouched()" (blur)="group.get('issn').updateValueAndValidity()">
</form-inline>
<form-inline [description]="eissnDesc" [valid]="group.get('eissn').valid">
<span *ngIf="group.get('eissn').invalid && group.get('eissn').touched && group.get('eissn').dirty"
class="help-block inline uk-text-danger"
style="margin-top: 0px; margin-bottom: 0px; padding-left: 10px;">Eissn needs to be of the form: "1111-1111" or "1111-111X"</span>
<input formControlName="eissn"class="form-control" type="text" (focus)="group.get('eissn').markAsUntouched()" (blur)="group.get('eissn').updateValueAndValidity()">
</form-inline>
<form-inline [description]="lissnDesc" [valid]="group.get('lissn').valid">
<span *ngIf="group.get('lissn').invalid && group.get('lissn').touched && group.get('lissn').dirty"
class="help-block inline uk-text-danger"
style="margin-top: 0px; margin-bottom: 0px; padding-left: 10px;">Lissn needs to be of the form: "1111-1111" or "1111-111X"</span>
<input formControlName="lissn"class="form-control" type="text" (focus)="group.get('lissn').markAsUntouched()" (blur)="group.get('lissn').updateValueAndValidity()">
</form-inline>
</div>
<form-inline [description]="repoDescriptionDesc" [valid]="group.get('repoDescription').valid">
<textarea formControlName="repoDescription" class="form-control"></textarea>
</form-inline>
<form-inline [description]="countryDesc" [valid]="group.get('country').valid">
<select formControlName="country" class="form-control">
<option value="">-- none selected --</option>
<option *ngFor="let country of countries" value="{{ country.code }}">{{ country.name }}</option>
</select>
</form-inline>
<form-inline [description]="longtitudeDesc" [valid]="group.get('longtitude').valid">
<span *ngIf="group.get('longtitude').invalid && group.get('longtitude').touched && group.get('longtitude').dirty"
class="help-block inline uk-text-danger"
style="margin-top: 0px; margin-bottom: 0px; ">Invalid Longtitude</span>
<input formControlName="longtitude" class="form-control" type="number" step="0.5"
(focus)="group.get('longtitude').markAsUntouched()"
(blur)="group.get('longtitude').updateValueAndValidity()">
</form-inline>
<form-inline [description]="latitudeDesc" [valid]="group.get('latitude').valid">
<span *ngIf="group.get('latitude').invalid && group.get('latitude').touched && group.get('latitude').dirty"
class="help-block inline uk-text-danger"
style="margin-top: 0px; margin-bottom: 0px; ">Invalid Latitude</span>
<input formControlName="latitude" class="form-control" type="number" step="0.5"
(focus)="group.get('latitude').markAsUntouched()"
(blur)="group.get('latitude').updateValueAndValidity()">
</form-inline>
<form-inline [description]="websiteUrlDesc" [valid]="group.get('websiteUrl').valid">
<span *ngIf="group.get('websiteUrl').invalid && group.get('websiteUrl').touched && group.get('websiteUrl').dirty"
class="help-block inline uk-text-danger"
style="margin-top: 0px; margin-bottom: 0px; ">You need to enter a valid url</span>
<input formControlName="websiteUrl" class="form-control" type="text"
(focus)="group.get('websiteUrl').markAsUntouched()"
(blur)="group.get('websiteUrl').updateValueAndValidity()">
</form-inline>
<form-inline [description]="institutionNameDesc" [valid]="group.get('institutionName').valid">
<input formControlName="institutionName" class="form-control" type="text">
</form-inline>
<h4 class="uk-h4 uk-text-primary uk-scrollspy-inview uk-animation-slide-top-medium"
uk-scrollspy-class="">Extra Information</h4>
<form-inline [description]="englishNameDesc" [valid]="group.get('englishName').valid">
<input formControlName="englishName" class="form-control" type="text" >
</form-inline>
<form-inline [description]="logoUrlDesc" [valid]="group.get('logoUrl').valid">
<span *ngIf="group.get('logoUrl').invalid && group.get('logoUrl').touched && group.get('logoUrl').dirty"
class="help-block inline uk-text-danger"
style="margin-top: 0px; margin-bottom: 0px; ">The url you entered is not valid</span>
<input formControlName="logoUrl" class="form-control" type="text"
(focus)="group.get('logoUrl').markAsUntouched()"
(blur)="group.get('logoUrl').updateValueAndValidity()">
<div class="comment fontItalic">
Please make sure that the maximum size of the uploaded image is width=360px, height=240px
</div>
</form-inline>
<form-inline [description]="timezoneDesc" [valid]="group.get('timezone').valid">
<select formControlName="timezone" class="form-control">
<option value="">-- none selected --</option>
<option *ngFor="let timezone of timezones" value="{{ timezone.offset }}">{{ timezone.name }}</option>
</select>
</form-inline>
<form-inline [description]="datasourceTypeDesc" [valid]="group.get('datasourceType').valid">
<select formControlName="datasourceType" class="form-control">
<option value="">-- none selected --</option>
<option *ngFor="let key of classCodes" value="{{key}}">{{ datasourceClasses[key] }}</option>
</select>
</form-inline>
<h4 class="uk-h4 uk-text-primary uk-scrollspy-inview uk-animation-slide-top-medium"
uk-scrollspy-class="">Administrator & contact information</h4>
<form-inline [description]="adminEmailDesc" [valid]="group.get('adminEmail').valid">
<span *ngIf="group.get('adminEmail').invalid && group.get('adminEmail').touched && group.get('adminEmail').dirty"
class="help-block inline"
style="margin-top: 0px; margin-bottom: 0px; ">You need to enter a valid email address</span>
<input formControlName="adminEmail" class="form-control" type="text"
(focus)="group.get('adminEmail').markAsUntouched()"
(blur)="group.get('adminEmail').updateValueAndValidity()">
</form-inline>
</form>

View File

@ -0,0 +1,257 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Country, Repository, Timezone, Typology } from '../../../domain/typeScriptClasses';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { adminEmailDesc, countryDesc, datasourceTypeDesc, Description, eissnDesc, englishNameDesc, institutionNameDesc,
issnDesc, latitudeDesc, lissnDesc, logoUrlDesc, longtitudeDesc, officialNameDesc, repoDescriptionDesc,
softwarePlatformDesc, timezoneDesc, websiteUrlDesc } from '../../../domain/oa-description';
import { ActivatedRoute } from '@angular/router';
import { RepositoryService } from '../../../services/repository.service';
import { AuthenticationService } from '../../../services/authentication.service';
import { formErrorRequiredFields, noServiceMessage } from '../../../domain/shared-messages';
@Component ({
selector: 'datasource-create-form',
templateUrl: './datasource-create-form.component.html'
})
export class DatasourceCreateFormComponent implements OnInit {
errorMessage: string;
successMessage: string;
loadingMessage: string;
typologies: Typology[] = [];
timezones: Timezone[] = [];
countries: Country[] = [];
datasourceClasses: Map<string, string> = new Map<string, string>();
classCodes: string[] = [];
@Input() mode: string;
@Output() emittedInfo: EventEmitter<Repository> = new EventEmitter();
@Input() selectedRepo: Repository;
formSubmitted = false;
group: FormGroup;
// old issn regex
// issn : ['', [Validators.pattern('^\\d\\d\\d\\d[-]\\d\\d\\d\\d$')] ],
readonly groupDefinition = {
softwarePlatform : ['', Validators.required],
officialName : ['', Validators.required],
issn : ['', [Validators.pattern('^\\d{4}-\\d{3}[\\dxX]$')] ],
eissn : ['', Validators.pattern('^\\d{4}-\\d{3}[\\dxX]$') ],
lissn : ['', Validators.pattern('^\\d{4}-\\d{3}[\\dxX]$') ],
repoDescription : ['', Validators.required],
country : ['', Validators.required],
longtitude : ['', [Validators.required, Validators.min(-180), Validators.max(180)] ],
latitude : ['', [Validators.required, Validators.min(-90), Validators.max(90)] ],
websiteUrl : ['', [Validators.required, Validators.pattern('^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$')] ],
institutionName : ['', Validators.required],
englishName: ['', Validators.required],
logoUrl: ['', Validators.pattern('^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$') ],
timezone: ['', Validators.required],
datasourceType: ['', Validators.required],
adminEmail: ['', [Validators.required, Validators.email] ]
};
softwarePlatformDesc: Description = softwarePlatformDesc;
officialNameDesc: Description = officialNameDesc;
issnDesc: Description = issnDesc;
eissnDesc: Description = eissnDesc;
lissnDesc: Description = lissnDesc;
repoDescriptionDesc: Description = repoDescriptionDesc;
countryDesc: Description = countryDesc;
longtitudeDesc: Description = longtitudeDesc;
latitudeDesc: Description = latitudeDesc;
websiteUrlDesc: Description = websiteUrlDesc;
institutionNameDesc: Description = institutionNameDesc;
englishNameDesc: Description = englishNameDesc;
logoUrlDesc: Description = logoUrlDesc;
timezoneDesc: Description = timezoneDesc;
datasourceTypeDesc: Description = datasourceTypeDesc;
adminEmailDesc: Description = adminEmailDesc;
constructor(
private fb: FormBuilder,
private route: ActivatedRoute,
private repoService: RepositoryService,
private authService: AuthenticationService
) {}
ngOnInit() {
this.loadForm();
}
loadForm() {
if (!this.mode) {
this.mode = this.route.snapshot.url[0].path.toString();
console.log(`my mode is ${this.mode}`);
}
this.group = this.fb.group(this.groupDefinition);
if (this.mode === 'journal') {
this.group.get('issn').clearValidators();
this.group.get('issn').setValidators([Validators.required, Validators.pattern('^\\d{4}-\\d{3}[\\dxX]$')]);
}
this.getTypologies();
this.getTimezones();
this.getCountries();
this.getDatasourceClasses();
if (this.selectedRepo) {
this.setupForm();
}
}
setupForm() {
if (this.selectedRepo) {
console.log(`my datasource type is: ${this.selectedRepo.datasourceType}`);
this.group.setValue({
softwarePlatform: this.selectedRepo.typology,
officialName: this.selectedRepo.officialName,
issn: '',
eissn: '',
lissn: '',
repoDescription: this.selectedRepo.description,
country: this.selectedRepo.countryCode,
longtitude: this.selectedRepo.longitude,
latitude: this.selectedRepo.latitude,
websiteUrl: this.selectedRepo.websiteUrl,
institutionName: this.selectedRepo.organization,
englishName: this.selectedRepo.englishName,
logoUrl: this.selectedRepo.logoUrl,
timezone: this.selectedRepo.timezone,
datasourceType: this.selectedRepo.datasourceClass,
adminEmail: this.selectedRepo.contactEmail
});
if (this.selectedRepo.datasourceType === 'journal') {
let ssnToShow = this.selectedRepo.issn.slice(0, 4) + '-' + this.selectedRepo.issn.toString().slice(4);
this.group.get('issn').setValue(ssnToShow);
if (this.selectedRepo.eissn.trim().length) {
ssnToShow = this.selectedRepo.eissn.slice(0, 4) + '-' + this.selectedRepo.eissn.toString().slice(4);
this.group.get('eissn').setValue(ssnToShow);
}
if (this.selectedRepo.lissn.trim().length) {
ssnToShow = this.selectedRepo.lissn.slice(0, 4) + '-' + this.selectedRepo.lissn.toString().slice(4);
this.group.get('lissn').setValue(ssnToShow);
}
}
}
}
getCountries() {
this.repoService.getCountries()
.subscribe(
countries => this.countries = countries.sort( function(a, b) {
if (a.name < b.name) {
return -1;
} else if (a.name > b.name) {
return 1;
} else {
return 0;
}
} ),
error => {
this.errorMessage = noServiceMessage;
console.log(error);
});
}
getDatasourceClasses() {
this.repoService.getDatasourceClasses(this.mode).subscribe(
classes => this.datasourceClasses = classes,
error => {
this.errorMessage = noServiceMessage;
console.log(error);
},
() => {
for (const key of Object.keys(this.datasourceClasses)) {
this.classCodes.push(key);
}
}
);
}
getTypologies() {
this.repoService.getTypologies().subscribe(
types => this.typologies = types,
error => console.log(error)
);
}
getTimezones() {
this.repoService.getTimezones().subscribe(
zones => this.timezones = zones,
error => console.log(error)
);
}
registerDatasource() {
this.formSubmitted = true;
this.errorMessage = '';
this.successMessage = '';
window.scroll(1, 1);
if (this.group.valid) {
this.selectedRepo = this.createNewRepository();
this.emittedInfo.emit(this.selectedRepo);
} else {
this.errorMessage = formErrorRequiredFields;
}
}
createNewRepository(): Repository {
const newRepo: Repository = new Repository();
newRepo.officialName = this.group.get('officialName').value.toString();
newRepo.englishName = this.group.get('englishName').value.toString();
newRepo.websiteUrl = this.group.get('websiteUrl').value;
newRepo.logoUrl = this.group.get('logoUrl').value;
newRepo.contactEmail = this.group.get('adminEmail').value;
newRepo.countryName = this.countries.filter(x => x.code === this.group.get('country').value)[0].name;
newRepo.countryCode = this.group.get('country').value;
newRepo.organization = this.group.get('institutionName').value.toString();
newRepo.latitude = this.group.get('latitude').value;
newRepo.longitude = this.group.get('longtitude').value;
newRepo.timezone = this.group.get('timezone').value;
newRepo.datasourceClass = this.group.get('datasourceType').value;
newRepo.typology = this.group.get('softwarePlatform').value;
newRepo.description = this.group.get('repoDescription').value.toString();
newRepo.issn = '';
newRepo.eissn = '';
newRepo.lissn = '';
if ( this.group.get('issn').value ) {
let ssnParts = this.group.get('issn').value.split('-');
let correctSSN = ssnParts[0] + ssnParts[1];
newRepo.issn = correctSSN;
if ( this.group.get('eissn').value ) {
ssnParts = this.group.get('eissn').value.split('-');
correctSSN = ssnParts[0] + ssnParts[1];
newRepo.eissn = correctSSN;
}
if ( this.group.get('lissn').value ) {
ssnParts = this.group.get('lissn').value.split('-');
correctSSN = ssnParts[0] + ssnParts[1];
newRepo.lissn = correctSSN;
}
}
newRepo.registeredBy = this.authService.getUserEmail();
/* THE BELOW FIELDS ARE NOT SET IN GWT CODE*/
newRepo.datasourceType = this.mode;
newRepo.dateOfCreation = new Date(Date.now()); // NOT NEEDED ??
newRepo.registered = true;
newRepo.registrationDate = new Date(Date.now()); // NOT NEEDED ??
return newRepo;
}
}

View File

@ -0,0 +1,58 @@
<div>
<div *ngIf="loadingMessage" class="loading-big">
<div class="loader-big" style="text-align: center; padding-top: 170px; color: rgb(47, 64, 80); font-weight: bold;">
{{ loadingMessage }}
</div>
<div class="whiteFilm"></div>
</div>
<div *ngIf="repoInterfaceForm && (!loadingMessage || (loadingMessage===''))" [formGroup]="repoInterfaceForm">
<div class="interfaceActionsPanel">
<a *ngIf="!inRegister" (click)="saveInterface()" class="uk-margin-small-right"><i class="far fa-save fa-lg"></i></a>
<a (click)="removeInterface()" class="uk-margin-small-left"><i class="fas fa-times fa-lg"></i></a>
</div>
<div *ngIf="successMessage" class="uk-alert uk-alert-success" style="clear: both">{{ successMessage }}</div>
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger" style="clear: both">{{ errorMessage }}</div>
<div class="form-group has-success">
<label class="control-label" for="baseUrl" title="{{ baseUrlDesc.desc }}">Base OAI-PMH URL (*)</label>
<span *ngIf="identifiedBaseUrl" class="help-block inline" style="margin-top: 0px; margin-bottom: 0px; padding-left: 10px;">
Identified
</span>
<input id="baseUrl" type="text" class="form-control" formControlName="baseUrl" (blur)="getInterfaceInfo()">
</div>
<div class="form-group">
<label class="control-label">Validation Set</label>
<div>
<label class="uk-button validationSetRadio" for="selectRadio{{interfaceID}}" title="{{ existingValSetDesc.desc }}">
<input id="selectRadio{{interfaceID}}" value="select" name="validationSet{{interfaceID}}" type="radio"
(change)="chooseValSet(true)" checked >
<span class="uk-margin-small-left">Choose existing</span>
</label>
</div>
<select id="selectValidationSet{{interfaceID}}" formControlName="selectValidationSet"
class="form-control" (change)="checkIfValid()">
<option value="" selected>-- none selected --</option>
<option *ngFor="let set of valsetList" value="{{set}}">{{set}}</option>
</select>
<div>
<label class="uk-button validationSetRadio" for="customRadio{{interfaceID}}" title="{{ customValSetDesc.desc }}">
<input id="customRadio{{interfaceID}}" value="custom" name="validationSet{{interfaceID}}" type="radio"
(change)="chooseValSet(false)">
<span class="uk-margin-small-left">or a custom one</span>
</label>
</div>
<input id="customValidationSet{{interfaceID}}" formControlName="customValidationSet"
class="form-control" type="text" (keyup)="checkIfValid()">
</div>
<div class="form-group">
<label class="control-label" for="compLvl" title="{{ compatibilityLevelDesc.desc }}">Desired Compatibility Level (*)</label>
<select class="form-control" id="compLvl" formControlName="compatibilityLevel" (change)="checkIfValid()">
<option value="">-- none selected --</option>
<option *ngFor="let key of classCodes" value="{{key}}">{{compClasses[key]}}</option>
</select>
</div>
<div>
<label class="uk-form-controls-text control-label">Current Compatibility Level</label>
<div *ngIf="existingCompLevel">{{ existingCompLevel ? existingCompLevel : 'not available' }}</div>
</div>
</div>
</div>

View File

@ -0,0 +1,352 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { baseUrlDesc, compatibilityLevelDesc, customValSetDesc, Description, existingValSetDesc } from '../../../domain/oa-description';
import { InterfaceInformation, RepositoryInterface } from '../../../domain/typeScriptClasses';
import { ValidatorService } from '../../../services/validator.service';
import { RepositoryService } from '../../../services/repository.service';
import { formErrorWasntSaved, formInfoLoading, formSubmitting, formSuccessAddedInterface, formSuccessUpdatedInterface, invalidCustomBaseUrl,
nonRemovableInterface, noServiceMessage } from '../../../domain/shared-messages';
export class RepoFields {
id: string;
datasourceType: string;
datasourceClass: string;
registeredBy: string;
}
@Component({
selector: 'app-repository-interface-form',
templateUrl: './datasource-new-interface-form.component.html'
})
export class DatasourceNewInterfaceFormComponent implements OnInit {
loadingMessage: string;
successMessage: string;
errorMessage: string;
@Input() data: any[] = []; // expects an array containing at least 3 of the 4 below fields in this order
inRegister: boolean;
interfaceID: number; // holds the interface index in the interfaces array as displayed
currentRepo: RepoFields; // a fraction of the Repository class
currentInterface: RepositoryInterface;
@Output() emitDeleteInterface: EventEmitter<number> = new EventEmitter<number>();
interfaceToExport: RepositoryInterface;
repoInterfaceForm: FormGroup;
readonly repoInterfaceFormDef = {
baseUrl: ['', Validators.required],
selectValidationSet: [''],
customValidationSet: [''],
compatibilityLevel: ['']
};
baseUrlDesc: Description = baseUrlDesc;
existingValSetDesc: Description = existingValSetDesc;
customValSetDesc: Description = customValSetDesc;
compatibilityLevelDesc: Description = compatibilityLevelDesc;
identifiedBaseUrl: boolean;
valsetList: string[] = [];
existingCompLevel: string;
classCodes: string[] = [];
compClasses: Map<string, string> = new Map<string, string>();
existingValSet: boolean;
interfaceInfo: InterfaceInformation;
constructor(private fb: FormBuilder,
private valService: ValidatorService,
private repoService: RepositoryService) {}
ngOnInit() {
if (this.data && (this.data.length >= 3)) {
this.inRegister = this.data[0];
this.interfaceID = this.data[1];
this.currentRepo = this.data[2];
this.repoInterfaceForm = this.fb.group(this.repoInterfaceFormDef);
this.chooseValSet(true);
if (this.data[3]) {
this.currentInterface = this.data[3];
this.repoInterfaceForm.get('baseUrl').setValue(this.currentInterface.baseUrl);
this.repoInterfaceForm.get('compatibilityLevel').setValue(this.currentInterface.desiredCompatibilityLevel);
}
this.getInterfaceInfo();
this.getCompatibilityClasses();
}
}
getInterfaceInfo() {
this.successMessage = '';
this.errorMessage = '';
const baseUrl = this.repoInterfaceForm.get('baseUrl').value;
if (baseUrl) {
this.loadingMessage = formInfoLoading;
this.valService.getInterfaceInformation(baseUrl).subscribe(
info => {
this.interfaceInfo = info;
if (this.interfaceInfo.identified) {
this.identifiedBaseUrl = true;
} else {
this.errorMessage = invalidCustomBaseUrl;
}
if (this.interfaceInfo.sets) {
this.valsetList = this.interfaceInfo.sets;
console.log(this.valsetList);
}
},
error => {
console.log(error);
this.loadingMessage = '';
this.identifiedBaseUrl = false;
this.errorMessage = noServiceMessage;
},
() => {
if ( this.currentInterface && this.currentInterface.accessParams && this.currentInterface.accessParams['set'] ) {
if ( this.valsetList.some( x => x === this.currentInterface.accessParams['set']) ) {
this.repoInterfaceForm.get('selectValidationSet').setValue(this.currentInterface.accessParams['set']);
} else {
this.repoInterfaceForm.get('customValidationSet').setValue(this.currentInterface.accessParams['set']);
}
}
this.loadingMessage = '';
this.repoInterfaceForm.updateValueAndValidity();
this.checkIfValid();
}
);
}
}
getCompatibilityClasses() {
this.repoService.getCompatibilityClasses(this.currentRepo.datasourceType).subscribe(
classes => {
this.compClasses = classes;
this.classCodes = Object.keys(this.compClasses);
},
error => {
this.errorMessage = noServiceMessage;
console.log(error);
},
() => {
this.getExistingCompatibilityLevel();
this.repoInterfaceForm.updateValueAndValidity();
}
);
}
getExistingCompatibilityLevel() {
if (this.currentInterface) {
if (this.currentInterface.desiredCompatibilityLevel &&
this.classCodes.some( x => x === this.currentInterface.desiredCompatibilityLevel ) ) {
this.existingCompLevel = this.compClasses[this.currentInterface.desiredCompatibilityLevel];
} else {
this.repoInterfaceForm.get('compatibilityLevel').setValue('');
this.existingCompLevel = this.currentInterface.desiredCompatibilityLevel;
}
}
}
chooseValSet(fromList: boolean) {
this.existingValSet = fromList;
if (this.existingValSet) {
this.repoInterfaceForm.get('selectValidationSet').enable();
this.repoInterfaceForm.get('customValidationSet').disable();
} else {
this.repoInterfaceForm.get('selectValidationSet').disable();
this.repoInterfaceForm.get('customValidationSet').enable();
}
this.checkIfValid();
}
checkIfCompatibilityLevelWasChosen() {
return ( (this.repoInterfaceForm.get('compatibilityLevel').value !== '') ||
(this.existingCompLevel && (this.existingCompLevel !== '')) );
}
formIsValid() {
return (this.repoInterfaceForm.valid &&
this.identifiedBaseUrl &&
this.checkIfCompatibilityLevelWasChosen());
}
checkIfValid() {
if (this.formIsValid()) {
if (this.inRegister) {
this.successMessage = 'The interface will be stored when the registration procedure is completed.';
this.saveInterface();
}
} else {
this.successMessage = '';
this.interfaceToExport = null;
}
}
saveInterface() {
this.errorMessage = '';
this.successMessage = '';
if (this.formIsValid()) {
const baseUrl = this.repoInterfaceForm.get('baseUrl').value;
let valset = '';
if (this.existingValSet) {
valset = this.repoInterfaceForm.get('selectValidationSet').value;
} else {
valset = this.repoInterfaceForm.get('customValidationSet').value;
}
let compLvl = '';
if (this.repoInterfaceForm.get('compatibilityLevel').value) {
this.existingCompLevel = this.compClasses[this.repoInterfaceForm.get('compatibilityLevel').value];
console.log('this.existingCompLevel is', this.existingCompLevel);
compLvl = this.repoInterfaceForm.get('compatibilityLevel').value;
} else {
compLvl = this.existingCompLevel;
}
if (this.currentInterface) {
this.updateCurrent(baseUrl, valset, compLvl);
} else {
this.addCurrent(baseUrl, valset, compLvl);
}
} else {
this.interfaceToExport = null;
this.errorMessage = 'Please make sure all required fields are filled with acceptable values.';
}
}
getCurrentValues() {
let intrf = this.currentInterface;
if (intrf == null) {
intrf = new RepositoryInterface();
}
intrf.baseUrl = this.repoInterfaceForm.get('baseUrl').value;
if (this.existingValSet) {
intrf.accessSet = this.repoInterfaceForm.get('selectValidationSet').value;
intrf.accessParams = {'set': this.repoInterfaceForm.get('selectValidationSet').value};
} else {
intrf.accessSet = this.repoInterfaceForm.get('customValidationSet').value;
intrf.accessParams = {'set': this.repoInterfaceForm.get('customValidationSet').value};
}
if (this.repoInterfaceForm.get('compatibilityLevel').value) {
intrf.desiredCompatibilityLevel = this.repoInterfaceForm.get('compatibilityLevel').value;
intrf.compliance = this.repoInterfaceForm.get('compatibilityLevel').value;
} else {
intrf.desiredCompatibilityLevel = this.existingCompLevel;
intrf.compliance = this.existingCompLevel;
}
intrf.typology = this.currentRepo.datasourceClass;
return intrf;
}
addCurrent (baseUrl: string, valset: string, compLvl: string) {
const currentInterface = new RepositoryInterface();
currentInterface.baseUrl = baseUrl;
currentInterface.accessSet = valset;
currentInterface.accessParams = {'set': valset};
currentInterface.desiredCompatibilityLevel = compLvl;
currentInterface.compliance = compLvl;
currentInterface.typology = this.currentRepo.datasourceClass;
if (!this.inRegister) {
this.addInterface(currentInterface);
} else {
this.successMessage = 'The interface will be stored when the registration procedure is completed';
console.log('SAVED !');
this.interfaceToExport = currentInterface;
}
}
addInterface(newInterface: RepositoryInterface) {
this.loadingMessage = formSubmitting;
this.repoService.addInterface(this.currentRepo.datasourceType,
this.currentRepo.id,
this.currentRepo.registeredBy,
newInterface).subscribe(
addedInterface => {
console.log(`addInterface responded ${JSON.stringify(addedInterface)}`);
this.currentInterface = addedInterface;
},
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = formErrorWasntSaved;
this.currentInterface = null;
},
() => {
this.loadingMessage = '';
if (this.currentInterface.id) {
this.successMessage = formSuccessAddedInterface;
this.getExistingCompatibilityLevel();
} else {
this.errorMessage = formErrorWasntSaved;
}
}
);
}
updateCurrent (baseUrl: string, valset: string, compLvl: string) {
this.currentInterface.baseUrl = baseUrl;
this.currentInterface.accessSet = valset;
this.currentInterface.accessParams['set'] = valset;
this.currentInterface.desiredCompatibilityLevel = compLvl;
this.currentInterface.compliance = compLvl;
this.currentInterface.typology = this.currentRepo.datasourceClass;
if (!this.inRegister) {
this.updateInterface();
} else {
this.successMessage = 'The interface will be stored when the registration procedure is completed';
console.log('SAVED !');
this.interfaceToExport = this.currentInterface;
}
}
updateInterface() {
this.loadingMessage = formSubmitting;
this.repoService.updateInterface(this.currentRepo.id,
this.currentRepo.registeredBy,
this.currentInterface).subscribe(
response => {
console.log(`updateRepository responded ${JSON.stringify(response)}`);
if (response) {
this.currentInterface = response;
this.successMessage = formSuccessUpdatedInterface;
} else {
this.errorMessage = formErrorWasntSaved;
}
},
error => {
console.log(error);
this.loadingMessage = '';
this.errorMessage = formErrorWasntSaved;
},
() => {
this.loadingMessage = '';
this.getExistingCompatibilityLevel();
}
);
}
removeInterface() {
this.errorMessage = '';
this.successMessage = '';
if (this.interfaceID > 0) {
if (this.currentInterface && (this.currentInterface.id !== null) && !this.inRegister) {
this.repoService.deleteInterface(this.currentInterface.id, this.currentRepo.registeredBy).subscribe(
res => console.log(`deleteInterface responded: ${JSON.stringify(res)}`),
er => console.log(er),
() => this.emitDeleteInterface.emit(this.interfaceID)
);
} else {
this.emitDeleteInterface.emit(this.interfaceID);
}
} else {
this.errorMessage = nonRemovableInterface;
}
}
getInterface() {
return this.interfaceToExport;
}
}

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