Merging explore-redesign branch into develop for Explore July release #7

Merged
konstantina.galouni merged 112 commits from explore-redesign into develop 2023-07-05 11:11:53 +02:00
26 changed files with 437 additions and 219 deletions
Showing only changes of commit 03b28d57d5 - Show all commits

View File

@ -2,8 +2,10 @@ import {throwError as observableThrowError} from 'rxjs';
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {ClaimEntity, ClaimResult} from '../claimHelper.class';
import {map} from "rxjs/operators";
import {map, timeout} from "rxjs/operators";
import {EnvProperties} from "../../../utils/properties/env-properties";
import {properties} from "../../../../../environments/environment";
import {StringUtils} from "../../../utils/string-utils.class";
@Injectable()
export class SearchCrossrefService {
@ -20,7 +22,9 @@ export class SearchCrossrefService {
}
searchCrossrefByDOIs(DOIs: string[], properties: EnvProperties, parse: boolean = false): any {
searchCrossrefByDOIs(DOIs: string[], properties: EnvProperties, parse: boolean = false, file: boolean = false): any {
let timeoutTime: number = properties.environment == "production" ? 6000 : 12000;
// let timeoutTimeForFile: number = 60000;
var doisParams = "";
for (var i = 0; i < DOIs.length; i++) {
@ -28,11 +32,21 @@ export class SearchCrossrefService {
}
let url = properties.searchCrossrefAPIURL + '?filter=' + doisParams;
return this.http.get(url)
//.map(request => <any> request.json().message)
.pipe(map(request => request['message']))
.pipe(map(request => [request["total-results"], parse ? this.parse(request['items']) : request]))
//.catch(this.handleError);
// .pipe(timeout(file ? timeoutTimeForFile : (timeoutTime)))
.pipe(timeout(timeoutTime))
.pipe(map(request => request['message']))
.pipe(map(request => [request["total-results"], parse ? this.parse(request['items']) : request]))
}
searchCrossrefByDOI(DOI: string): any {
let timeoutTimeForFile: number = 20000;
let url = properties.searchCrossrefAPIURL + '/' + StringUtils.URIEncode(DOI);
return this.http.get(url)
.pipe(timeout(timeoutTimeForFile))
.pipe(map(request => request['message']))
.pipe(map(request => this.parse(request)))
}
searchCrossrefByMultipleDOIs(dois: string[], properties: EnvProperties, parse: boolean = false): any {
let url = properties.searchCrossrefAPIURL + '?filter=doi:';
for (var i = 0; i < dois.length; i++) {
@ -56,8 +70,11 @@ export class SearchCrossrefService {
parse(response): ClaimEntity[] {
const results: ClaimEntity[] = [];
for (let i = 0; i < response.length; i++) {
const item = response[i];
let length = Array.isArray(response) ? response.length : 1;
for (let i = 0; i < length; i++) {
const item = Array.isArray(response) ? response[i] : response;
const entity: ClaimEntity = new ClaimEntity();
entity.result = new ClaimResult();
entity.result.publisher = null;

View File

@ -3,7 +3,7 @@ import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {EnvProperties} from '../../../utils/properties/env-properties';
import {ClaimEntity, ClaimResult} from '../claimHelper.class';
import {catchError, map} from 'rxjs/operators';
import {catchError, map, timeout} from 'rxjs/operators';
import {properties} from "../../../../../environments/environment";
@ -21,10 +21,14 @@ export class SearchDataciteService {
//.catch(this.handleError);
}
getDataciteResultByDOI(doi: string, properties: EnvProperties, parse: boolean = false): any {
getDataciteResultByDOI(doi: string, properties: EnvProperties, parse: boolean = false, file: boolean = false): any {
let timeoutTime: number = properties.environment == "production" ? 6000 : 12000;
let timeoutTimeForFile: number = 20000;
let url = properties.searchDataciteAPIURL + '/' + doi;
let key = url;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(timeout(file ? timeoutTimeForFile : (timeoutTime)))
.pipe(map(request => (parse ? SearchDataciteService.parse([request["data"]])[0] : request)), catchError(err => of(null)));
}

View File

@ -21,14 +21,16 @@ declare var UIkit: any;
<div>
<!--div class="uk-text-lead">Upload a DOI csv file <helper div="link-result-bulk" tooltip=true ></helper></div>
<label for="exampleInputFile">Select a file: </label-->
<div class="js-upload uk-float-left" uk-form-custom>
<input id="exampleInputFile" class="uk-width-medium" type="file" (change)="fileChangeEvent($event)"/>
<span class="uk-link " style="text-decoration: underline;">Upload a DOI's CSV file </span>
<div class="uk-float-left">
<span class="js-upload" uk-form-custom>
<input id="exampleInputFile" class="uk-width-medium" type="file" (change)="fileChangeEvent($event)"/>
<span class="uk-link " style="text-decoration: underline;">Upload a DOI's CSV file </span>
</span>
<!--button class="uk-button portal-button" type="button" tabindex="-1" [class.disabled]="!enableUpload" ><span class="uk-margin-small-right uk-icon" >
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <polyline fill="none" stroke="#000" points="5 8 9.5 3.5 14 8 "></polyline> <rect x="3" y="17" width="13" height="1"></rect>
<line fill="none" stroke="#000" x1="9.5" y1="15" x2="9.5" y2="4"></line></svg></span> Select</button-->
<!--helper div="link-result-bulk" tooltip=true ></helper-->
<span class=" " title="{{tooltip}}" uk-tooltip><span class="uk-icon" uk-icon="icon: info; ratio: 0.8">&nbsp; </span> </span>
<span class=" " title="{{tooltip}}" uk-tooltip><span class="uk-icon" uk-icon="icon: info; ratio: 0.8">&nbsp; </span> </span>
</div>
<div *ngIf="showReport" uk-alert class="uk-alert-primary">
<a class="uk-alert-close" uk-close></a>
@ -107,17 +109,16 @@ export class BulkClaimComponent {
exceedsLimit = false;
@Input() basketLimit ;
tooltip = `
<div class="uk-padding-small uk-padding-remove-right uk-padding-remove-left">
<div >
<div><span class="uk-text-bold">CSV format:</span> <br>&quot;DOI&quot;,&quot;ACCESS_MODE&quot;,&quot;DATE&quot;</div>
<br>
<div class=" uk-text-small">
<div>- DOI is required</div>
<div>- Access mode: <br> OPEN, CLOSED, EMBARGO</div>
<div>- Embargo end date:<br> YYYY-MM-DD </div>
</div>
</div>
</div>`;
<div>
<div class="uk-margin-bottom">Up to 100 DOIs</div>
<div><span class="uk-text-bold">CSV format:</span> <br>&quot;DOI&quot;,&quot;ACCESS_MODE&quot;,&quot;DATE&quot;</div>
<br>
<div class="uk-text-small">
<div>- DOI is required</div>
<div>- Access mode: <br> OPEN, CLOSED, EMBARGO</div>
<div>- Embargo end date:<br> YYYY-MM-DD </div>
</div>
</div>`;
constructor(private _searchCrossrefService: SearchCrossrefService, private _searchDataciteService: SearchDataciteService) {
this.filesToUpload = [];
}
@ -247,11 +248,12 @@ export class BulkClaimComponent {
}
fetchResult(id: string, accessMode: string, date: string, row: number) {
this.subscriptions.push(this._searchCrossrefService.searchCrossrefByDOIs([id], this.properties, true).subscribe(
// this.subscriptions.push(this._searchCrossrefService.searchCrossrefByDOIs([id], this.properties, true, true).subscribe(
this.subscriptions.push(this._searchCrossrefService.searchCrossrefByDOI(id).subscribe(
data => {
const result:ClaimEntity = data[1][0];
if (data[1].length > 0) {
if (data.length > 0) {
const result:ClaimEntity = data[0];
this.foundIds.push(id);
result.result.accessRights = accessMode;
result.result.embargoEndDate = date;

View File

@ -26,7 +26,7 @@
<div *ngIf="contactForm.get('description')" class="uk-width-1-1" input type="textarea" rows="4" placeholder="Description"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('description')"></div>
<div *ngIf="contactForm.get('recaptcha')" class="uk-flex uk-flex-center" [class.uk-width-1-1]="smallForm" [class.uk-flex-last@s]="!smallForm">
<re-captcha (resolved)="handleRecaptcha($event)" [siteKey]="properties.reCaptchaSiteKey"></re-captcha>
<re-captcha #captchaElem (resolved)="handleRecaptcha($event)" [siteKey]="properties.reCaptchaSiteKey"></re-captcha>
</div>
<div class="uk-flex uk-flex-center" [class.uk-width-1-1]="smallForm" [class.uk-flex-column]="!smallForm">
<div class="uk-flex uk-flex-center" [class.uk-flex-left@s]="!smallForm">

View File

@ -1,7 +1,8 @@
import {Component, EventEmitter, Input, Output} from '@angular/core';
import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {EnvProperties} from "../utils/properties/env-properties";
import {properties} from "../../../environments/environment";
import {RecaptchaComponent} from "ng-recaptcha";
@Component({
selector: 'contact-us',
@ -18,6 +19,8 @@ export class ContactUsComponent {
@Input() public scrollspy: boolean = false;
@Input() public sending: boolean = false;
@Output() sendEmitter: EventEmitter<any> = new EventEmitter<any>();
@ViewChild('captchaElem') captchaElem: RecaptchaComponent;
public properties: EnvProperties = properties;
public send() {
@ -29,4 +32,8 @@ export class ContactUsComponent {
public handleRecaptcha(captchaResponse: string) {
this.contactForm.get('recaptcha').setValue(captchaResponse);
}
public resetRecaptcha() {
this.captchaElem.reset();
}
}

View File

@ -2,10 +2,10 @@ import {
AfterViewInit,
ChangeDetectorRef,
Component,
ElementRef,
ElementRef, Inject,
Input,
OnDestroy,
OnInit,
OnInit, PLATFORM_ID,
ViewChild
} from "@angular/core";
import {LayoutService} from "../sidebar/layout.service";
@ -18,7 +18,7 @@ declare var ResizeObserver;
selector: '[page-content]',
template: `
<div id="page_content">
<div id="page_content_sticky_footer" #sticky_footer class="uk-tile-default uk-blur-background"
<div [class.uk-hidden]="!isBrowser" id="page_content_sticky_footer" #sticky_footer class="uk-tile-default uk-blur-background"
[attr.uk-sticky]="'bottom: true'" [attr.offset]="footer_offset">
<div class="uk-container uk-container-large">
<div class="uk-padding-small uk-padding-remove-vertical">
@ -74,7 +74,8 @@ export class PageContentComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild("sticky_footer") sticky_footer;
subscriptions = [];
constructor(private layoutService: LayoutService, private cdr: ChangeDetectorRef) {
constructor(private layoutService: LayoutService, private cdr: ChangeDetectorRef,
@Inject(PLATFORM_ID) private platformId) {
}
ngOnInit() {
@ -83,6 +84,10 @@ export class PageContentComponent implements OnInit, AfterViewInit, OnDestroy {
}
}
get isBrowser() {
return this.platformId === 'browser';
}
get isStickyActive() {
if (this.header && this.actions && this.shouldSticky) {
let sticky = this.headerSticky ? this.header.nativeElement : this.actions.nativeElement;

View File

@ -17,6 +17,11 @@ export class LayoutService {
*/
private openSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
/**
* Set this to true when sidebar is hovered, otherwise false.
*/
private hoverSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
/**
* Add hasSidebar: false on data of route config, if sidebar is not needed.
*/
@ -164,6 +169,14 @@ export class LayoutService {
this.openSubject.next(value);
}
get hover(): boolean {
return this.hoverSubject.getValue();
}
setHover(value: boolean) {
this.hoverSubject.next(value);
}
get hasSidebar(): Observable<boolean> {
return this.hasSidebarSubject.asObservable();
}

View File

@ -1,5 +1,5 @@
<aside id="sidebar_main">
<div id="sidebar_content">
<div sidebar-content>
<div *ngIf="items.length > 0" class="menu_section uk-margin-large-top" style="min-height: 30vh">
<ul #nav class="uk-list uk-nav uk-nav-default uk-nav-parent-icon" uk-nav="duration: 400">
<ng-template ngFor [ngForOf]="items" let-item>
@ -7,15 +7,14 @@
[class.uk-parent]="item.items.length > 0">
<a [routerLink]="getItemRoute(item)" [title]="item.title"
[queryParams]="item.route?item.params:null" [queryParamsHandling]="item.route?queryParamsHandling:null">
<div class="uk-flex uk-flex-middle uk-flex-center">
<div class="uk-flex uk-flex-middle">
<div *ngIf="item.icon && (item.icon.svg || item.icon.name)" class="uk-width-auto">
<icon class="menu-icon" [customClass]="item.icon.class" [name]="item.icon.name" ratio="0.9" [svg]="item.icon.svg" [flex]="true"></icon>
</div>
<span *ngIf="open || !item.icon" [class.uk-text-small]="!open" class="uk-width-expand uk-text-truncate uk-margin-small-left">{{item.title}}</span>
<span *ngIf="item.items?.length > 0"></span>
<span [class.hide-on-close]="item.icon" class="uk-width-expand uk-text-truncate uk-margin-small-left">{{item.title}}</span>
</div>
</a>
<ul *ngIf="item.items?.length > 0" class="uk-nav-sub">
<ul *ngIf="item.items?.length > 0 && (isBrowser || isTheActiveMenuItem(item))" class="uk-nav-sub">
<li *ngFor="let subItem of item.items"
[class.uk-active]="isTheActiveMenuItem(item, subItem)">
<a [routerLink]="subItem.route?subItem.route:null" [queryParams]="subItem.route?subItem.params:null"
@ -37,7 +36,8 @@
<div *ngIf="specialMenuItem.icon" class="uk-width-auto">
<icon class="menu-icon" [customClass]="specialMenuItem.icon.class" [name]="specialMenuItem.icon.name" ratio="1.2" [svg]="specialMenuItem.icon.svg" [flex]="true"></icon>
</div>
<span *ngIf="open || !specialMenuItem.icon" [class.uk-text-small]="!open" class="uk-width-expand uk-text-truncate uk-margin-small-left">{{specialMenuItem.title}}</span>
<span class="uk-width-expand uk-text-truncate uk-margin-small-left"
[class.hide-on-close]="specialMenuItem.icon">{{specialMenuItem.title}}</span>
</div>
</a>
</li>

View File

@ -1,4 +1,4 @@
import {AfterViewInit, Component, ElementRef, Input, ViewChild} from '@angular/core';
import {AfterViewInit, Component, ElementRef, Inject, Input, PLATFORM_ID, ViewChild} from '@angular/core';
import {MenuItem} from "../../../sharedComponents/menu";
import {ActivatedRoute, Router} from "@angular/router";
import {DomSanitizer} from "@angular/platform-browser";
@ -20,18 +20,24 @@ export class SideBarComponent implements AfterViewInit {
@ViewChild("nav") nav: ElementRef
public properties = properties;
constructor(private route: ActivatedRoute, private router: Router, private sanitizer: DomSanitizer, private layoutService: LayoutService) {}
constructor(private route: ActivatedRoute, private router: Router,
private sanitizer: DomSanitizer, private layoutService: LayoutService,
@Inject(PLATFORM_ID) private platformId) {}
ngAfterViewInit() {
if(this.nav) {
if(this.nav && typeof UIkit !== "undefined") {
setTimeout(() => {
if(this.items[this.activeIndex].items.length > 0) {
if(this.items[this.activeIndex]?.items?.length > 0) {
UIkit.nav(this.nav.nativeElement).toggle(this.activeIndex, true);
}
});
}
}
get isBrowser() {
return this.platformId === 'browser';
}
get currentRoute() {
return {
route: this.router.url.split('?')[0].split('#')[0],
@ -79,9 +85,4 @@ export class SideBarComponent implements AfterViewInit {
public get open() {
return this.layoutService.open;
}
public toggleOpen(event: MouseEvent) {
event.preventDefault();
this.layoutService.setOpen(!this.open);
}
}

View File

@ -6,6 +6,7 @@ import {RouterModule} from "@angular/router";
import {SideBarComponent} from './sideBar.component';
import {UrlPrefixModule} from "../../../utils/pipes/url-prefix.module";
import {IconsModule} from "../../../utils/icons/icons.module";
import {SidebarContentComponent} from "./sidebar-content.component";
@NgModule({
imports: [
@ -15,11 +16,13 @@ import {IconsModule} from "../../../utils/icons/icons.module";
IconsModule
],
declarations: [
SideBarComponent
SideBarComponent,
SidebarContentComponent
],
providers: [],
exports: [
SideBarComponent
SideBarComponent,
SidebarContentComponent
]
})
export class SideBarModule {

View File

@ -0,0 +1,29 @@
import {Component, HostListener} from "@angular/core";
import {LayoutService} from "./layout.service";
@Component({
selector: '[sidebar-content]',
template: `
<div id="sidebar_toggle" (click)="toggleOpen()"></div>
<div id="sidebar_content" (mouseenter)="onMouseEnter()" (mouseleave)="onMouseLeave()">
<ng-content></ng-content>
</div>
`
})
export class SidebarContentComponent {
constructor(private layoutService: LayoutService) {
}
onMouseEnter() {
this.layoutService.setHover(true);
}
onMouseLeave() {
this.layoutService.setHover(false);
}
public toggleOpen() {
this.layoutService.setOpen(!this.layoutService.open);
}
}

View File

@ -1,25 +1,29 @@
import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { tap } from 'rxjs/operators';
import { TransferState, makeStateKey, StateKey } from '@angular/platform-browser';
import { isPlatformServer } from '@angular/common';
import {Injectable, Inject, PLATFORM_ID, Optional} from '@angular/core';
import {HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse, HttpHeaders} from '@angular/common/http';
import {Observable, of} from 'rxjs';
import {tap} from 'rxjs/operators';
import {TransferState, makeStateKey, StateKey} from '@angular/platform-browser';
import {isPlatformServer} from '@angular/common';
import {properties} from "../../environments/environment";
import {REQUEST} from "./utils/tokens";
import * as Xhr2 from 'xhr2';
Xhr2.prototype._restrictedHeaders = {};
@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
private static HTTP_WHITELIST = [ properties.monitorServiceAPIURL + '/stakeholder' ];
constructor(private transferState: TransferState, @Inject(PLATFORM_ID) private platformId: any) {}
private static HTTP_WHITELIST = [];
constructor(private transferState: TransferState, @Inject(PLATFORM_ID) private platformId: any, @Optional() @Inject(REQUEST) protected req: any) {
}
public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (request.method !== 'GET' || this.isService(request, HttpInterceptorService.HTTP_WHITELIST)) {
return next.handle(request);
}
const key: StateKey<string> = makeStateKey<string>(request.url);
const storedResponse = this.transferState.get<any>(key, null);
//console.info(key, storedResponse);
if (storedResponse) {
@ -31,7 +35,14 @@ export class HttpInterceptorService implements HttpInterceptor {
return of(response);
} else {
if (isPlatformServer(this.platformId)) {
return next.handle(request).pipe(tap((event) => {
let headers = new HttpHeaders();
if(request.withCredentials) {
headers = headers.set('Cookie', this.req.get('Cookie'));
}
const authReq = request.clone({
headers: headers
});
return next.handle(authReq).pipe(tap((event) => {
//console.info("server add: ", key);
this.transferState.set(key, (<HttpResponse<any>>event).body);
}));
@ -40,15 +51,15 @@ export class HttpInterceptorService implements HttpInterceptor {
}
}
}
isService(req: HttpRequest<any>, service: string | string[]):boolean {
if(Array.isArray(service)) {
isService(req: HttpRequest<any>, service: string | string[]): boolean {
if (Array.isArray(service)) {
return !!service.find(element => req.url.indexOf(element) !== -1);
} else {
return req.url.indexOf(service) !== -1;
}
}
// public cleanRequest(requestUrl: string) {
// console.log("cleaned");
// const key: StateKey<string> = makeStateKey<string>(requestUrl);

View File

@ -5,41 +5,52 @@ import {AlertModal} from "../../../utils/modal/alert";
import {OpenaireEntities} from "src/app/openaireLibrary/utils/properties/searchFields";
@Component({
selector: 'landing-header',
template: `
<div class="title-section" [class.uk-margin-small-bottom]="!isSticky" [ngClass]="titleClass">
<div class="uk-margin-small-bottom">
<showTitle [titleName]="title" classNames="uk-margin-remove-bottom"></showTitle>
<div *ngIf="subTitle">
<span class="uk-text-meta uk-text-small" [innerHTML]="subTitle"></span>
</div>
</div>
selector: 'landing-header',
template: `
<div class="title-section" [class.uk-margin-small-bottom]="!isSticky" [ngClass]="titleClass">
<div class="uk-margin-small-bottom">
<showTitle [titleName]="title" classNames="uk-margin-remove-bottom"></showTitle>
<div *ngIf="subTitle">
<span class="uk-text-meta uk-text-small" [innerHTML]="subTitle"></span>
</div>
</div>
<div class="uk-margin-bottom uk-text-xsmall uk-text-emphasis uk-flex uk-flex-middle uk-flex-wrap">
<!-- oa -->
<ng-container *ngIf="(openAccessMandatePublications != undefined && openAccessMandatePublications) || (openAccessMandateDatasets != undefined && openAccessMandateDatasets)">
<ng-container
*ngIf="(openAccessMandatePublications != undefined && openAccessMandatePublications) || (openAccessMandateDatasets != undefined && openAccessMandateDatasets)">
<span class="uk-margin-xsmall-right uk-text-success">
<icon name="open_access" flex="true" ratio="0.8"></icon>
</span>
<span class="uk-text-bolder" *ngIf="openAccessMandatePublications != undefined && openAccessMandatePublications && openAccessMandateDatasets != undefined && openAccessMandateDatasets">
<span class="uk-text-bolder"
*ngIf="openAccessMandatePublications != undefined && openAccessMandatePublications && openAccessMandateDatasets != undefined && openAccessMandateDatasets">
Open Access Mandate for {{openaireEntities.PUBLICATIONS}} and {{openaireEntities.DATASETS}}
</span>
<span class="uk-text-bolder" *ngIf="openAccessMandatePublications != undefined && openAccessMandatePublications && (openAccessMandateDatasets == undefined || !openAccessMandateDatasets)">
<span class="uk-text-bolder"
*ngIf="openAccessMandatePublications != undefined && openAccessMandatePublications && (openAccessMandateDatasets == undefined || !openAccessMandateDatasets)">
Open Access Mandate for {{openaireEntities.PUBLICATIONS}}
</span>
<span class="uk-text-bolder" *ngIf="openAccessMandateDatasets != undefined && openAccessMandateDatasets && (openAccessMandatePublications == undefined || !openAccessMandatePublications)">
<span class="uk-text-bolder"
*ngIf="openAccessMandateDatasets != undefined && openAccessMandateDatasets && (openAccessMandatePublications == undefined || !openAccessMandatePublications)">
Open Access Mandate for {{openaireEntities.DATASETS}}
</span>
<span class="uk-margin-xsmall-left uk-margin-xsmall-right">&#x2022;</span>
</ng-container>
<!-- types -->
<span *ngIf="entityType" class="uk-margin-xsmall-right">
<icon *ngIf="entityType.toLowerCase() == 'publication'" name="description" type="outlined" [flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'research data'" name="database" type="outlined" [flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'research software'" name="integration_instructions" type="outlined" [flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'other research product'" name="apps" type="outlined" [flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'project'" name="assignment_turned_in" type="outlined" [flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'data source'" name="note_add" type="outlined" [flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'organization'" name="corporate_fare" type="outlined" [flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'publication'" name="description" type="outlined"
[flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'research data'" name="database" type="outlined"
[flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'research software'" name="integration_instructions"
type="outlined" [flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'other research product'" name="apps" type="outlined"
[flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'project'" name="assignment_turned_in" type="outlined"
[flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'data source'" name="note_add" type="outlined"
[flex]="true" ratio="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'organization'" name="corporate_fare" type="outlined"
[flex]="true" ratio="0.8"></icon>
</span>
<span *ngIf="entityType" class="uk-text-capitalize uk-text-bolder" style="text-decoration: underline;">
{{entityType}}
@ -64,12 +75,12 @@ import {OpenaireEntities} from "src/app/openaireLibrary/utils/properties/searchF
<ng-container *ngIf="startDate && endDate">
<span class="uk-margin-xsmall-left uk-margin-xsmall-right">&#x2022;</span>
<ng-container *ngIf="startDate">
<span>{{startDate | date: 'dd MMM yyyy'}}</span>
<span>{{startDate | date: 'dd MMM yyyy'}}</span>
<span class="uk-margin-xsmall-left">(Started)</span>
</ng-container>
<span *ngIf="startDate && endDate" class="uk-margin-xsmall-left uk-margin-xsmall-right">-</span>
<ng-container *ngIf="endDate">
<span>{{endDate | date: 'dd MMM yyyy'}}</span>
</ng-container>
<span *ngIf="startDate && endDate" class="uk-margin-xsmall-left uk-margin-xsmall-right">-</span>
<ng-container *ngIf="endDate">
<span>{{endDate | date: 'dd MMM yyyy'}}</span>
<span class="uk-margin-xsmall-left">{{currentDate >= endDate ? '(Ended)' : '(Ending)'}}</span>
</ng-container>
</ng-container>
@ -85,10 +96,10 @@ import {OpenaireEntities} from "src/app/openaireLibrary/utils/properties/searchF
<span class="uk-margin-xsmall-left uk-margin-xsmall-right">&#x2022;</span>
<span>Embargo end date: {{embargoEndDate | date: 'dd MMM yyyy'}}</span>
</ng-container>
<span *ngIf="underCuration">
<span *ngIf="underCuration">
. <span title="{{buildCurationTooltip()}}"
uk-tooltip="pos:bottom-right; delay:10;"
class="uk-text-primary">Under curation</span>
uk-tooltip="pos:bottom-right; delay:10;"
class="uk-text-primary">Under curation</span>
</span>
<!-- languages -->
<ng-container *ngIf="languages && removeUnknown(languages).length > 0">
@ -112,13 +123,14 @@ import {OpenaireEntities} from "src/app/openaireLibrary/utils/properties/searchF
<span>
<!-- link not working - dont know why -->
<a *ngIf="compatibility.id"
[queryParams]="{datasourceId: compatibility.id}" routerLinkActive="router-link-active"
[routerLink]="properties.searchLinkToDataProvider.split('?')[0]">
[queryParams]="{datasourceId: compatibility.id}" routerLinkActive="router-link-active"
[routerLink]="properties.searchLinkToDataProvider.split('?')[0]">
{{compatibility.info}}
<ng-container *ngIf="compatibility.name">{{compatibility.name}}</ng-container>
</a>
<span *ngIf="!compatibility.id">
<ng-container *ngIf="compatibility.info.toLowerCase() != 'not yet registered'">{{compatibility.info}}</ng-container>
<ng-container
*ngIf="compatibility.info.toLowerCase() != 'not yet registered'">{{compatibility.info}}</ng-container>
<ng-container *ngIf="compatibility.info.toLowerCase() == 'not yet registered'">
{{compatibility.info}} <span *ngIf="properties.adminToolsPortalType == 'eosc'">in OpenAIRE</span>
</ng-container>
@ -128,7 +140,8 @@ import {OpenaireEntities} from "src/app/openaireLibrary/utils/properties/searchF
</span>
</span>
</ng-container>
<ng-container *ngIf="aggregationStatus && aggregationStatus.fulltexts && aggregationStatus.fulltexts > 0">
<ng-container
*ngIf="aggregationStatus && aggregationStatus.fulltexts && aggregationStatus.fulltexts > 0">
<span class="uk-margin-xsmall-left uk-margin-xsmall-right">&#x2022;</span>
<span>OpenAIRE Text Mining</span>
</ng-container>
@ -137,33 +150,35 @@ import {OpenaireEntities} from "src/app/openaireLibrary/utils/properties/searchF
<span>Thematic</span>
</ng-container>
</div>
<div *ngIf="authors">
<showAuthors [authorsLimit]="authorLimit" [modal]="modal" [showAll]="showAllAuthors" [authors]="authors" [isSticky]="isSticky"></showAuthors>
</div>
</div>`
<div *ngIf="authors">
<showAuthors [authorsLimit]="authorLimit" [modal]="modal" [showAll]="showAllAuthors" [authors]="authors"
[isSticky]="isSticky"></showAuthors>
</div>
</div>
`
})
export class LandingHeaderComponent {
@Input() entityType: string;
@Input() properties: EnvProperties;
@Input() types: string[];
@Input() startDate: number; // project landing
@Input() endDate: number; // project landing
@Input() entityType: string;
@Input() properties: EnvProperties;
@Input() types: string[];
@Input() startDate: number; // project landing
@Input() endDate: number; // project landing
@Input() currentDate: number; // project landing
@Input() status: string; // project landing
@Input() status: string; // project landing
@Input() openAccessMandatePublications: boolean // project landing
@Input() openAccessMandateDatasets: boolean // project landing
@Input() date: Date;
@Input() embargoEndDate: Date;
@Input() title: string;
@Input() subTitle: string;
@Input() authors: Author[];
@Input() authorLimit: number = 7;
@Input() showAllAuthors: boolean = true;
@Input() underCuration: boolean = false;
@Input() modal: AlertModal;
@Input() titleClass: string = null;
@Input() isTitleH1:boolean =true;
@Input() isSticky: boolean = false;
@Input() date: Date;
@Input() embargoEndDate: Date;
@Input() title: string;
@Input() subTitle: string;
@Input() authors: Author[];
@Input() authorLimit: number = 7;
@Input() showAllAuthors: boolean = true;
@Input() underCuration: boolean = false;
@Input() modal: AlertModal;
@Input() titleClass: string = null;
@Input() isTitleH1: boolean = true;
@Input() isSticky: boolean = false;
@Input() publisher; // showPublisher component
@Input() journal; // showPublisher component
@Input() languages;
@ -175,25 +190,25 @@ export class LandingHeaderComponent {
public openaireEntities = OpenaireEntities;
public removeUnknown(array: string[], type: boolean = false): string[] {
if (type) {
return this.removeDuplicates(array).filter(value => value.toLowerCase() !== 'unknown');
} else {
return array.filter(value => value.toLowerCase() !== 'unknown');
}
}
public removeDuplicates(array: string[]): string[] {
return array.filter(value => value.toLowerCase() !== this.entityType);
}
public buildCurationTooltip(): string {
let tooltipContent: string = "<div class='uk-padding-small'>";
tooltipContent += "<h5>Record in preview</h5>";
tooltipContent += "<p>Bibliographic record accepted by the system, but not yet processed by <br> OpenAIRE tools for information quality improvement and de-duplication</p>";
tooltipContent += "</div>";
return tooltipContent;
}
public removeUnknown(array: string[], type: boolean = false): string[] {
if (type) {
return this.removeDuplicates(array).filter(value => value.toLowerCase() !== 'unknown');
} else {
return array.filter(value => value.toLowerCase() !== 'unknown');
}
}
public removeDuplicates(array: string[]): string[] {
return array.filter(value => value.toLowerCase() !== this.entityType);
}
public buildCurationTooltip(): string {
let tooltipContent: string = "<div class='uk-padding-small'>";
tooltipContent += "<h5>Record in preview</h5>";
tooltipContent += "<p>Bibliographic record accepted by the system, but not yet processed by <br> OpenAIRE tools for information quality improvement and de-duplication</p>";
tooltipContent += "</div>";
return tooltipContent;
}
}

View File

@ -1,4 +1,6 @@
@media only screen and (min-width: 640px) {
@import "~src/assets/openaire-theme/less/_import-variables";
@media only screen and (min-width: @breakpoint-small) {
.how .first > div:first-child {
position: relative;
}
@ -157,7 +159,7 @@
}
}
@media only screen and (max-width: 639px) {
@media only screen and (max-width: @breakpoint-xsmall-max) {
.how .first {
position: relative;
padding-bottom: 30%;

View File

@ -26,12 +26,8 @@ export class StakeholderService {
private promise: Promise<void>;
private sub;
constructor(private http: HttpClient, private route: ActivatedRoute) {
constructor(private http: HttpClient) {
this.stakeholderSubject = new BehaviorSubject<Stakeholder>(null);
/* let source = new EventSource(properties.monitorServiceAPIURL + "/stakeholder/events", {withCredentials: true});
source.addEventListener('message', message => {
console.log(message.data);
});*/
}
ngOnDestroy() {
@ -44,8 +40,8 @@ export class StakeholderService {
}
}
getStakeholder(alias: string): Observable<Stakeholder> {
if (!this.stakeholderSubject.value || this.stakeholderSubject.value.alias !== alias) {
getStakeholder(alias: string, shouldUpdate: boolean = false): Observable<Stakeholder> {
if (!this.stakeholderSubject.value || this.stakeholderSubject.value.alias !== alias || shouldUpdate) {
this.promise = new Promise<void>((resolve, reject) => {
this.sub = this.http.get<Stakeholder>(properties.monitorServiceAPIURL + '/stakeholder/' + encodeURIComponent(alias), CustomOptions.registryOptions()).pipe(map(stakeholder => {
return this.formalize(this.checkIsUpload(stakeholder));

View File

@ -65,7 +65,10 @@ import {Composer} from "../utils/email/composer";
We are unable to process the request. What happened?
<ul class="uk-margin-top uk-list uk-list-circle uk-list-primary">
<li>You are logged in with a different email, than the one you have received the invitation.
Check <a [routerLink]="[userInfoLinkPrefix + '/user-info']" (click)="errorModal.cancel()">here</a> the email of your account.</li>
Check
<a *ngIf="!userInfoLink" [routerLink]="[userInfoLinkPrefix + '/user-info']" (click)="errorModal.cancel()">here</a>
<a *ngIf="userInfoLink" [href]="userInfoLink" (click)="errorModal.cancel()">here</a>
the email of your account.</li>
<li>The invitation has been canceled.</li>
<li>The URL is invalid.</li>
</ul>
@ -84,6 +87,8 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
public service: "connect" | "monitor" = "monitor";
@Input()
public userInfoLinkPrefix = '';
@Input()
public userInfoLink = null;
public user: User;
public verification: any;
public code: UntypedFormControl;

View File

@ -18,6 +18,10 @@
</h2>
<div class="uk-width-3-4@m" uk-scrollspy-class>
We have developed a classification scheme for UN Sustainable Development Goals, to view contributions of research towards complex challenges for humanity such as climate change, biodiversity loss, pollution and poverty reduction.
<div class="uk-text-meta uk-margin-top">
For more information please visit <a href="https://www.openaire.eu/openaire-explore-introducing-sdgs-and-fos" target="_blank">https://www.openaire.eu/openaire-explore-introducing-sdgs-and-fos</a>
</div>
</div>
<div>
<!-- TODO: need a page for the description of the algorithm - to get us there from the learn more btn -->

View File

@ -1,9 +1,8 @@
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {BehaviorSubject, from, Observable} from "rxjs";
import {COOKIE, Session, User} from "../login/utils/helper.class";
import {Observable} from "rxjs";
import {Session, User} from "../login/utils/helper.class";
import {map} from "rxjs/operators";
import {NavigationEnd, Router} from "@angular/router";
import {properties} from "../../../environments/environment";
import {StringUtils} from "../utils/string-utils.class";
import {CustomOptions} from "./servicesUtils/customOptions.class";

View File

@ -11,38 +11,40 @@
</div>
</ng-template>
<ng-container *ngIf="shortView;else longView">
<div *ngIf="properties.footerGrantText || (divContents && divContents['footer']?.length > 0)"
class="uk-padding uk-flex uk-flex-middle">
<div *ngIf="showCommision" class="uk-width-1-2 uk-margin-left">
<div class="uk-flex uk-flex-middle@m uk-flex-top">
<div>
<img style="max-width: 42px;"
[src]="assetsPath + 'common/commission.jpg'"
alt="flag black white low" width="50px" loading="lazy">
</div>
<div class="uk-margin-left">
<helper *ngIf="divContents && divContents['footer']?.length > 0"
[texts]="divContents['footer']"></helper>
<div class="uk-visible@m">
<div *ngIf="properties.footerGrantText" class="">
<span style="font-size: 12px; line-height: 0.7!important;"
[innerHtml]="properties.footerGrantText"></span>
</div>
<div [ngClass]="background">
<div *ngIf="properties.footerGrantText || (divContents && divContents['footer']?.length > 0)"
class="uk-padding-small uk-flex uk-flex-middle uk-flex-between">
<div *ngIf="showCommision" class="uk-width-expand">
<div class="uk-flex uk-flex-middle@m uk-flex-top">
<div>
<img style="max-width: 42px;"
[src]="assetsPath + 'common/commission.jpg'"
alt="flag black white low" width="50px" loading="lazy">
</div>
<div class="uk-text-center uk-hidden@m">
<div *ngIf="properties.footerGrantText" class="">
<div class="uk-margin-left">
<helper *ngIf="divContents && divContents['footer']?.length > 0"
[texts]="divContents['footer']"></helper>
<div class="uk-visible@m">
<div *ngIf="properties.footerGrantText" class="">
<span style="font-size: 12px; line-height: 0.7!important;"
[innerHtml]="properties.footerGrantText"></span>
</div>
</div>
<div class="uk-text-center uk-hidden@m">
<div *ngIf="properties.footerGrantText" class="">
<span style="font-size: 12px; line-height: 0.7!important;"
[innerHtml]="properties.footerGrantText"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="showOpenaire" class="uk-text-right uk-width-1-2">
<!-- <img [src]="assetsPath + 'common/Logo_Horizontal_'+(darkBackground?'white':'dark')+'_small.png'" -->
<img [src]="assetsPath + 'common/Logo_Horizontal.png'"
width="140px"
height="50px" class="el-image" alt="OpenAIRE" loading="lazy">
<div *ngIf="showOpenaire" class="uk-width-1-2 uk-margin-left">
<!-- <img [src]="assetsPath + 'common/Logo_Horizontal_'+(darkBackground?'white':'dark')+'_small.png'" -->
<img [src]="assetsPath + 'common/Logo_Horizontal.png'"
width="140px"
height="50px" class="el-image" alt="OpenAIRE" loading="lazy">
</div>
</div>
</div>
</ng-container>

View File

@ -60,10 +60,10 @@ declare var UIkit;
<label>{{placeholderInfo.label}} <sup *ngIf="required">*</sup></label>
</div>
<div class="uk-flex" [class.uk-flex-middle]="type !== 'textarea'"
[attr.uk-tooltip]="(tooltip && !focused && type !== 'chips' && type !== 'textarea')?('title: ' + getTooltip(formControl.value ? (formControl.value) : (placeholderInfo?.static?placeholderInfo.label:hint)) + '; delay: 500; pos: bottom-left'):null">
[attr.uk-tooltip]="(tooltip && !focused && type !== 'chips' && type !== 'textarea' && (formControl.value || hint || placeholderInfo?.label))?('title: ' + (formControl.value ?getTooltip(formControl.value):(hint?hint:placeholderInfo?.label)) + '; delay: 500; pos: bottom-left'):null">
<ng-template [ngIf]="type === 'text' || type === 'URL' || type === 'logoURL'">
<input #input class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[formControl]="formAsControl" [class.uk-text-truncate]="!focused">
[type]="password?'password':'text'" [formControl]="formAsControl" [class.uk-text-truncate]="!focused">
</ng-template>
<ng-template [ngIf]="type === 'textarea'">
<textarea #textArea class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
@ -197,6 +197,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
/** Basic information */
@Input('formInput') formControl: AbstractControl;
@Input('type') type: InputType = 'text';
@Input() password: boolean = false;
@Input() validators: ValidatorFn[] | ValidatorFn;
@Input() disabled: boolean = false;
@Input() disabledIcon: string = 'lock';

View File

@ -9,7 +9,9 @@ export const DEFAULT_TIMEOUT = new InjectionToken<number>('defaultTimeout');
@Injectable()
export class TimeoutInterceptor implements HttpInterceptor {
private static TIMEOUT_WHITELIST = [properties.csvAPIURL, properties.registryUrl, properties.claimsAPIURL];
// timeout inside services for: properties.searchCrossrefAPIURL, properties.searchDataciteAPIURL
private static TIMEOUT_WHITELIST = [properties.csvAPIURL, properties.registryUrl, properties.claimsAPIURL,
properties.searchCrossrefAPIURL, properties.searchDataciteAPIURL];
constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout: number, @Inject(PLATFORM_ID) private platformId: any) {
}

View File

@ -86,7 +86,7 @@ export class Composer {
+ "<span><b>Name</b>: " + contactForm.name + "</span><br>"
+ "<span><b>Surname</b>: " + contactForm.surname + "</span><br>"
+ "<span><b>Email</b>: " + contactForm.email + "</span><br>"
+ "<span><b>Affiliation</b>: " + contactForm.affiliation ? contactForm.affiliation : '-' + "</span><br>"
+ "<span><b>Affiliation</b>: " + (contactForm.affiliation ? contactForm.affiliation : '-') + "</span><br>"
+ "<p>" + contactForm.message + "</p>"
+ "</div>";
email.recipients = admins;

View File

@ -1,10 +1,21 @@
import {Component, ViewEncapsulation, ComponentRef, ElementRef, Input, EventEmitter, Output} from '@angular/core';
import {
Component,
ViewEncapsulation,
ComponentRef,
ElementRef,
Input,
EventEmitter,
Output,
ViewChild
} from '@angular/core';
declare var UIkit: any;
@Component({
selector: 'modal-loading',
template: `
<!--uk-modal="center:true"-->
<div [class]="(!isOpen)?'uk-modal ':'uk-modal uk-open uk-animation-fade'" [open]="!isOpen" tabindex="-1" role="dialog" >
<!-- uk-modal="center:true"-->
<!-- <div [class]="(!isOpen)?'uk-modal ':'uk-modal uk-open uk-animation-fade'" [open]="!isOpen" uk-modal tabindex="-1" role="dialog" >-->
<div #loading_element class="uk-modal" [id]="id" uk-modal="container: #modal-container">
<div class="uk-modal-dialog" role="">
<!--div class="modal-content"-->
@ -23,6 +34,23 @@ import {Component, ViewEncapsulation, ComponentRef, ElementRef, Input, EventEmit
</div>
<!--/div-->
</div>
<!-- <div #element [class]="(!isOpen)?'uk-modal ':'uk-modal uk-animation-fade uk-open'" [open]="!isOpen" uk-modal="container: #modal-container">-->
<!-- <div class="uk-modal-dialog">-->
<!-- <div class="uk-modal-body uk-animation-fast uk-text-left">-->
<!-- <h4 class="text-center" >{{message}}</h4>-->
<!-- <div class="uk-animation-fade uk-margin-top uk-width-1-1" role="alert">-->
<!-- <span class="loading-gif uk-align-center" ></span>-->
<!-- </div>-->
<!-- <ng-content></ng-content>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!--div class="uk-modal uk-open" aria-hidden="false" style="display: block; overflow-y: scroll;">
<div class="uk-modal-dialog" tabindex="">
<div class="uk-modal-spinner"></div>
@ -35,27 +63,54 @@ import {Component, ViewEncapsulation, ComponentRef, ElementRef, Input, EventEmit
* API to an open alert window.
*/
export class ModalLoading{
private static MODAL_LOADING_COUNTER: number = 0;
id: string = "modal-loading";
@Input() public message:string ="Loading";
@ViewChild('loading_element') element: ElementRef;
/**
* if the value is true alert will be visible or else it will be hidden.
*/
public isOpen:boolean=false;
// public isOpen:boolean=false;
/**
* Emitted when a ok button was clicked
* or when Ok method is called.
*/
@Output() public alertOutput:EventEmitter<any> = new EventEmitter();
constructor( public _elementRef: ElementRef){}
constructor( public _elementRef: ElementRef){
}
ngOnInit() {
ModalLoading.MODAL_LOADING_COUNTER++;
this.id = 'modal-loading-' + ModalLoading.MODAL_LOADING_COUNTER;
}
ngOnDestroy() {
if(typeof document !== "undefined") {
const element = document.getElementById("modal-container");
for (let i = element.childNodes.length - 1; i >= 0; --i) {
let child: ChildNode = element.childNodes[i];
if (child['id'] == this.id) {
child.remove();
}
}
}
}
/**
* Opens a alert window creating backdrop.
*/
open(){
this.isOpen= true;
// this.isOpen= true;
UIkit.modal(this.element.nativeElement).show();
}
close(){
this.isOpen = false;
// this.isOpen = false;
UIkit.modal(this.element.nativeElement).hide();
}
}

View File

@ -1,34 +1,45 @@
export enum Level {
NONE,
K,
M,
B
}
export interface NumberSize {
number: number;
size: "M" | "K" | "";
size: "B" | "M" | "K" | ""
count: number;
}
export class NumberUtils{
export class NumberUtils {
public static roundNumber(num: number):any {
//console.log("Trying to round number: "+ num);
var roundNum: NumberSize = null;
var initialNum = num;
if(num >= 1000000){
num=num/1000000;
num= Math.round(num);
roundNum = { number: num, size: "M", count: initialNum};
}else if( num >= 1000){
num=num/1000;
num= Math.round(num);
roundNum = { number: num, size: "K", count: initialNum};
}else if (num >= 100) {
num=num/100;
num= Math.round(num);
num=num*100;
roundNum = { number: num, size: "" , count: initialNum};
}else{
roundNum = { number: num, size: "" , count: initialNum};
}
return roundNum;
public static roundNumber(num: number, level: Level = Level.NONE, decimal = 0): any {
let roundNum: NumberSize;
let initialNum = num;
let variance = Math.pow(10, decimal);
if (num >= 1000000000 && level <= Level.B) {
num = num / 1000000;
num = Math.round(num * variance) / variance;
roundNum = {number: num, size: "B", count: initialNum};
} else if (num >= 1000000 && level <= Level.M) {
num = num / 1000000;
num = Math.round(num * variance) / variance;
roundNum = {number: num, size: "M", count: initialNum};
} else if (num >= 1000 && level <= Level.K) {
num = num / 1000;
num = Math.round(num * variance) / variance;
roundNum = {number: num, size: "K", count: initialNum};
} else if (num >= 100) {
num = num / 100;
num = Math.round(num * variance) / variance;
num = num * 100;
roundNum = {number: num, size: "", count: initialNum};
} else {
roundNum = {number: num, size: "", count: initialNum};
}
return roundNum;
}
}

View File

@ -0,0 +1,11 @@
import {NgModule} from "@angular/core";
import {NumberRoundPipe} from "./number-round.pipe";
@NgModule({
declarations: [NumberRoundPipe],
exports: [NumberRoundPipe]
})
export class NumberRoundModule {
}

View File

@ -0,0 +1,23 @@
import {Pipe, PipeTransform} from "@angular/core";
import {Level, NumberSize, NumberUtils} from "../number-utils.class";
import {DecimalPipe} from "@angular/common";
@Pipe({name: 'numberRound'})
export class NumberRoundPipe implements PipeTransform {
decimalPipe: DecimalPipe = new DecimalPipe("en");
constructor() {}
transform(value: number, ...args: any[]): any {
let level = Level.NONE;
let decimal = 0;
if(args[0]) {
level = args[0];
}
if(args[1]) {
decimal = args[1];
}
let size: NumberSize = NumberUtils.roundNumber(value, level, decimal);
return this.decimalPipe.transform(size.number) + (size.size?'<span class="number-size">' + size.size + '</span>':'');
}
}