Deleted shared/utils folder - openaire-library submodule is added instead

This commit is contained in:
Konstantina Galouni 2023-07-25 13:48:19 +03:00
parent e8db9428bf
commit a8937de064
23 changed files with 1 additions and 2352 deletions

@ -1 +1 @@
Subproject commit 27f644aad1f4568a03bafbbd3d1640568a725957
Subproject commit 6ecde003afe2cc7f4917b1d0f616d8c4b6355346

View File

@ -1,24 +0,0 @@
import {Component, Input} from "@angular/core";
export interface Breadcrumb {
name: string;
route?: string;
keepFormat?: boolean
}
@Component({
selector: 'breadcrumbs',
template: `
<ul class="uk-breadcrumb uk-margin-remove-bottom" [ngClass]="addClass" [class.uk-light]="light">
<li *ngFor="let breadcrumb of breadcrumbs">
<a [class.uk-text-capitalize]="!breadcrumb.keepFormat" *ngIf="breadcrumb.route" [routerLink]="breadcrumb.route">{{breadcrumb.name}}</a>
<span [class.uk-text-capitalize]="!breadcrumb.keepFormat" *ngIf="!breadcrumb.route">{{breadcrumb.name}}</span>
</li>
</ul>`
})
export class BreadcrumbsComponent {
@Input() public light: boolean = false;
@Input() public breadcrumbs: Breadcrumb[] = [];
@Input() public addClass = "";
}

View File

@ -1,11 +0,0 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {BreadcrumbsComponent} from "./breadcrumbs.component";
import {RouterModule} from "@angular/router";
@NgModule({
imports: [CommonModule, RouterModule],
declarations: [BreadcrumbsComponent],
exports: [BreadcrumbsComponent]
})
export class BreadcrumbsModule {}

View File

@ -1,33 +0,0 @@
import {Directive, ElementRef, EventEmitter, HostListener, Output} from '@angular/core';
export interface ClickEvent {
event: any,
clicked: boolean;
}
@Directive({
selector: '[click-outside-or-esc]'
})
export class ClickOutsideOrEsc {
@Output('clickOutside') clickOutside: EventEmitter<ClickEvent> = new EventEmitter<ClickEvent>();
constructor(private elementRef: ElementRef) {}
@HostListener('document:click', ['$event'])
click(event) {
if(event.isTrusted) {
this.clickOutside.emit({
event: event,
clicked: !(this.elementRef && this.elementRef.nativeElement.contains(event.target))
});
}
}
@HostListener('window:keydown.escape', ['$event'])
esc(event: KeyboardEvent) {
this.clickOutside.emit({
event: event,
clicked: true
});
}
}

View File

@ -1,14 +0,0 @@
import {NgModule} from "@angular/core";
import {ClickOutsideOrEsc} from "./click-outside-or-esc.directive";
import {LongClick} from "./long-click.directive";
@NgModule({
imports: [],
declarations: [
ClickOutsideOrEsc, LongClick
],
exports: [
ClickOutsideOrEsc, LongClick
]
})
export class ClickModule {}

View File

@ -1,72 +0,0 @@
import {Directive, EventEmitter, HostListener, Input, Output} from '@angular/core';
@Directive({
selector: '[long-click]'
})
export class LongClick {
@Input() duration: number = 500;
@Output() onLongPress: EventEmitter<any> = new EventEmitter();
@Output() onLongPressing: EventEmitter<any> = new EventEmitter();
@Output() onLongPressEnd: EventEmitter<any> = new EventEmitter();
private pressing: boolean;
private longPressing: boolean;
private timeout: any;
private mouseX: number = 0;
private mouseY: number = 0;
@HostListener('mousedown', ['$event'])
onMouseDown(event) {
// don't do right/middle clicks
if (event.which !== 1) return;
this.mouseX = event.clientX;
this.mouseY = event.clientY;
this.pressing = true;
this.longPressing = false;
this.timeout = setTimeout(() => {
this.longPressing = true;
this.onLongPress.emit(event);
this.loop(event);
}, this.duration);
this.loop(event);
}
@HostListener('mousemove', ['$event'])
onMouseMove(event) {
if (this.pressing && !this.longPressing) {
const xThres = (event.clientX - this.mouseX) > 10;
const yThres = (event.clientY - this.mouseY) > 10;
if (xThres || yThres) {
this.endPress();
}
}
}
loop(event) {
if (this.longPressing) {
this.timeout = setTimeout(() => {
this.onLongPressing.emit(event);
this.loop(event);
}, 50);
}
}
endPress() {
clearTimeout(this.timeout);
this.longPressing = false;
this.pressing = false;
this.onLongPressEnd.emit(true);
}
@HostListener('mouseup')
onMouseUp() {
this.endPress();
}
}

View File

@ -1,97 +0,0 @@
import {Component} from "@angular/core";
@Component({
selector: 'icons-preview',
template: `
<div class="uk-section uk-container uk-container-large" style="font-size: 14px;">
<h4 class="uk-text-bold">Icons</h4>
<div class="uk-grid uk-grid-small uk-child-width-1-6" uk-grid>
<div class="uk-text-center">
<icon name="book"></icon>
<div class="uk-text-bold uk-margin-small-top">book</div>
</div>
<div class="uk-text-center">
<icon name="database"></icon>
<div class="uk-text-bold uk-margin-small-top">database</div>
</div>
<div class="uk-text-center">
<icon name="cog"></icon>
<div class="uk-text-bold uk-margin-small-top">cog</div>
</div>
<div class="uk-text-center">
<icon name="earth"></icon>
<div class="uk-text-bold uk-margin-small-top">earth</div>
</div>
<div class="uk-text-center">
<icon name="incognito"></icon>
<div class="uk-text-bold uk-margin-small-top">incognito</div>
</div>
<div class="uk-text-center">
<icon name="restricted"></icon>
<div class="uk-text-bold uk-margin-small-top">restricted</div>
</div>
<div class="uk-text-center">
<icon name="graph"></icon>
<div class="uk-text-bold uk-margin-small-top">graph</div>
</div>
<div class="uk-text-center">
<icon name="orcid_add"></icon>
<div class="uk-text-bold uk-margin-small-top">orcid_add</div>
</div>
<div class="uk-text-center">
<icon name="orcid_bin"></icon>
<div class="uk-text-bold uk-margin-small-top">orcid_bin</div>
</div>
<div class="uk-text-center">
<icon name="link"></icon>
<div class="uk-text-bold uk-margin-small-top">link</div>
</div>
<div class="uk-text-center">
<icon name="quotes"></icon>
<div class="uk-text-bold uk-margin-small-top">quotes</div>
</div>
<div class="uk-text-center">
<icon name="mining"></icon>
<div class="uk-text-bold uk-margin-small-top">mining</div>
</div>
</div>
<div class="uk-margin-medium-top">
<h4 class="uk-text-bold">Usage</h4>
<ul class="uk-list">
<li>1. Import IconsModule</li>
<li>2. Add this to your module with these icons you will need<br>
<div class="uk-margin-top">
<pre><code>constructor(private iconsService: IconsService) {{ "{" }}
this.iconsService.registerIcons([edit]);
{{ "}" }}</code></pre>
</div>
</li>
<li>3. Use an icon with icon tag. Add parameter ratio to scale this icon. Default size 20x20 (ratio: 1)<br>
<div class="uk-margin-top">
<pre><code>{{'<'}}icon name="edit"{{'><'}}/icon{{'>'}}</code></pre>
</div>
</li>
<li>4. Add a color class in parent of icon to give your icon a color.<br>
<div class="uk-margin-top">
<pre><code>{{'<'}}div class="uk-text-secondary"{{'>'}}
{{'<'}}icon name="edit"{{'><'}}/icon{{'>'}}
{{'<'}}/div{{'>'}}</code></pre>
</div>
</li>
</ul>
</div>
<div class="uk-margin-medium-top">
<h4 class="uk-text-bold">Add a new icon</h4>
<ul class="uk-list">
<li>1. Go to <a href="https://material.io/resources/icons/?style=baseline">Material Icons</a></li>
<li>2. Find your icon and download it as svg.</li>
<li>3. Open svg file with an editor and change width and height to 20</li>
<li>4. Create an entry on icons file with your new icon.</li>
</ul>
</div>
</div>
`
})
export class IconsPreviewComponent {
}

View File

@ -1,32 +0,0 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {RouterModule} from "@angular/router";
import {IconsPreviewComponent} from "./icons-preview.component";
import {IconsService} from "../icons.service";
import {IconsModule} from "../icons.module";
import {
book,
cog,
database,
earth,
filters,
graph,
incognito, link, mining,
orcid_add,
orcid_bin,
quotes,
restricted
} from "../icons";
@NgModule({
imports: [CommonModule, RouterModule.forChild([
{path: '', component: IconsPreviewComponent}
]), IconsModule],
declarations: [IconsPreviewComponent],
exports: [IconsPreviewComponent]
})
export class IconsPreviewModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([book, database, cog, earth, incognito, restricted, graph, filters, orcid_add, orcid_bin, link, quotes, mining])
}
}

View File

@ -1,192 +0,0 @@
import {
AfterViewInit,
ChangeDetectorRef,
Component,
ElementRef,
Input,
OnChanges,
SimpleChanges,
ViewChild
} from "@angular/core";
import {IconsService} from "./icons.service";
export interface StopRule {
class: string,
offset: number
}
/**
* By default, this component uses Material Icons Library to render an icon with
* a specific @name. For custom icons you should:
*
* - Add your icon in icons.ts and register it to Icon registry, by adding this to your component Module.
*
* e.g export class ExampleModule {
* constructor(private iconsService: IconsService) {
* this.iconsService.registerIcons([arrow_right])
* }
* }
*
* If the name of your icon is the same with a Material Icon name, yours will be used instead of the default.
*
* - Custom SVG Icon. Define a variable in your component with an SVG and give it as Input @svg.
*
* In case of SVGs, there is an opportunity to add gradient color by define at least a start and end stop-color rules
* and an id to support them. This option is enabled by giving id as input in @gradient (Optional @degrees for gradient direction)
*
* e.g #gradient .start {
* stop-color: red;
* }
*
* e.g #gradient .end {
* stop-color: orange;
* }
*
* */
@Component({
selector: 'icon',
template: `
<span #icon *ngIf="svg" class="uk-icon" [class.uk-preserve]="gradient" [class.uk-flex]="flex" [ngClass]="customClass" [ngStyle]="style" [innerHTML]="svg | safeHtml"></span>
<span *ngIf="!svg && iconName" [class.uk-flex]="flex" [ngClass]="customClass" [class.uk-display-inline-block]="!flex">
<span class="material-icons" [ngClass]="type" [ngStyle]="style">{{iconName}}</span>
</span>
<span *ngIf="visuallyHidden" class="visually-hidden">{{visuallyHidden}}</span>
`
})
export class IconsComponent implements AfterViewInit, OnChanges {
private static DEFAULT_ICON_SIZE = 20;
public iconName: string;
public style;
/**
* Custom icon as SVG
*/
@Input()
public svg;
@Input()
public defaultSize = false;
/**
* True if this icon should have display flex (Optional, Default: false)
*
* */
@Input()
public flex = false;
/**
*
* Add custom class(es)(Optional)
* */
@Input()
public customClass = '';
/**
* Color of svg (Optional)
* */
@Input()
public fill;
/**
* Color of svg stroke (Optional)
* */
@Input()
public stroke;
/**
* Size of icon (Default: 1)
*
* Disabled if defaultSize = true
* */
@Input()
public ratio = 1;
/**
* In case of Material icon only. Type of icon (Optional)
* */
@Input()
public type: "outlined" | "round" | "sharp" | "two-tone" | null = null;
/**
* Name of icon in registry (Required)
* */
@Input()
set name(iconName: string) {
this.iconName = iconName;
this.svg = this.iconsService.getIcon(iconName);
}
/**
* Set visually hidden name for accessibility
* */
@Input()
public visuallyHidden: string = null;
/**
* Gradient rules
* Available only for SVG!
*
* Define your css rules for stop-colors
* */
@Input()
public gradient: string = null;
@Input()
public degrees: number = 0;
@Input()
public stopRules: StopRule[]= [{class: 'start', offset: 0}, {class: 'end', offset: 100}];
@ViewChild("icon")
public icon: ElementRef;
constructor(private iconsService: IconsService,
private cdr: ChangeDetectorRef) {}
ngAfterViewInit() {
this.initIcon();
}
ngOnChanges(changes: SimpleChanges) {
this.initIcon();
}
initIcon() {
if(this.svg && this.icon) {
this.cdr.detectChanges();
let svg: Element = this.icon.nativeElement.getElementsByTagName('svg').item(0);
if(!this.defaultSize && svg) {
svg.setAttribute("width", (this.ratio * IconsComponent.DEFAULT_ICON_SIZE).toString());
svg.setAttribute("height", (this.ratio * IconsComponent.DEFAULT_ICON_SIZE).toString());
}
if(this.gradient && svg) {
this.addGradient(svg);
} else {
this.style = {
fill: this.fill,
stroke: this.stroke
};
}
} else {
this.style = {
"font-size.px": this.ratio*IconsComponent.DEFAULT_ICON_SIZE
};
}
this.cdr.detectChanges();
}
addGradient(svg: Element) {
if(svg.children.length > 0 && typeof document !== "undefined") {
let gradientDefinition = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');
gradientDefinition.setAttribute('id', this.gradient);
if(this.degrees !== 0) {
let angle = (this.degrees) * (Math.PI / 180);
gradientDefinition.setAttribute('x1', Math.round(50 + Math.sin(angle + Math.PI) * 50) + '%');
gradientDefinition.setAttribute('y1', Math.round(50 + Math.cos(angle + Math.PI) * 50) + '%');
gradientDefinition.setAttribute('x2', Math.round(50 + Math.sin(angle) * 50) + '%');
gradientDefinition.setAttribute('y2', Math.round(50 + Math.cos(angle) * 50) + '%');
}
for(let rule of this.stopRules) {
let item = document.createElementNS('http://www.w3.org/2000/svg','stop');
item.setAttribute('class', rule.class);
item.setAttribute('offset', rule.offset + '%');
gradientDefinition.appendChild(item);
}
let defs = document.createElementNS('http://www.w3.org/2000/svg','defs');
defs.appendChild(gradientDefinition);
for(let i = 0; i < svg.children.length; i++) {
let item = svg.children.item(i);
if(!item.hasAttribute('fill')) {
item.setAttribute('fill', "url('#" + this.gradient + "')");
}
}
svg.insertBefore(defs, svg.childNodes[0]);
}
}
}

View File

@ -1,10 +0,0 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {IconsComponent} from "./icons.component";
@NgModule({
imports: [CommonModule],
declarations: [IconsComponent],
exports: [IconsComponent]
})
export class IconsModule {}

View File

@ -1,18 +0,0 @@
import {Injectable} from "@angular/core";
import {Icon} from "./icons";
@Injectable({
providedIn: 'root'
})
export class IconsService {
private registry = new Map<string, string>();
public registerIcons(icons: any[]): void {
icons.forEach((icon: Icon) => this.registry.set(icon.name, icon.data));
}
public getIcon(iconName: string): string | undefined {
return this.registry.get(iconName);
}
}

View File

@ -1,226 +0,0 @@
export interface Icon {
name: string,
data: string
}
/** @deprecated */
export const arrow_left: Icon = {
name: 'arrow_left',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M20 11H6.83l2.88-2.88c.39-.39.39-1.02 0-1.41-.39-.39-1.02-.39-1.41 0L3.71 11.3c-.39.39-.39 1.02 0 1.41L8.3 17.3c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L6.83 13H20c.55 0 1-.45 1-1s-.45-1-1-1z"/></svg>'
}
/** @deprecated */
export const arrow_right: Icon = {
name: 'arrow_right',
data: '<svg height="20" viewBox="0 0 16 16" width="20" xmlns="http://www.w3.org/2000/svg"><path d="M12.578,4.244,5.667,11.155V8.167A.833.833,0,1,0,4,8.167v5A.832.832,0,0,0,4.833,14h5a.833.833,0,0,0,0-1.667H6.845l6.911-6.911a.833.833,0,1,0-1.178-1.178h0Z" transform="translate(7.071 19.799) rotate(-135)"></path></svg>'
};
/** @deprecated */
export const arrow_up: Icon = {
name: 'arrow_up',
data: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 17.155 17.155"><g transform="translate(0)"><path d="M10.405,11.834,2.022,3.451V7.076A1.011,1.011,0,0,1,0,7.076V1.011A1.009,1.009,0,0,1,1.011,0H7.076a1.011,1.011,0,1,1,0,2.022H3.451l8.383,8.383a1.011,1.011,0,1,1-1.429,1.429h0Z" transform="translate(8.578 0) rotate(45)"/></g></svg>'
}
/** @deprecated */
export const arrow_down: Icon = {
name: 'arrow_down',
data: '<svg height="20" viewBox="0 0 17.155 17.155" width="20" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-1221 -675)"><path d="M14.405,4.3,6.022,12.68V9.055A1.011,1.011,0,0,0,4,9.055V15.12a1.009,1.009,0,0,0,1.011,1.01h6.065a1.011,1.011,0,1,0,0-2.022H7.451l8.383-8.383A1.011,1.011,0,0,0,14.405,4.3h0Z" transform="translate(1215.343 683.578) rotate(-45)"></path></g></svg>'
}
export const book: Icon = {
name: 'book',
data: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 22.106 30"><path id="book" d="M26.9,9.405V25.749c0,.824-.713,1.218-1.579,1.832a1.034,1.034,0,0,1-1.579-.927V10.685a.877.877,0,0,0-.5-.845c-.379-.194-12.218-6.418-12.218-6.418A2.239,2.239,0,0,0,8.9,3.4,4.487,4.487,0,0,0,7.119,4.808l12.916,7.077a.917.917,0,0,1,.555.815V29.755a1.057,1.057,0,0,1-.582.924,1.209,1.209,0,0,1-1.136-.042c-.339-.207-12.274-7.526-13.063-8-.379-.227-.823-.693-.832-1.039L4.8,5.355a2.612,2.612,0,0,1,.456-1.629c1.1-1.711,4.94-3.658,6.884-2.65L26.348,8.268A1.151,1.151,0,0,1,26.9,9.405Z" transform="translate(-4.799 -0.8)"/></svg>'
};
export const database: Icon = {
name: 'database',
data: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 23.864 30"><path id="database" d="M28.2,21.443c-1.437,2.324-6.026,4.025-11.465,4.025S6.7,23.767,5.266,21.443c-.3-.494-.466-.23-.466.012v3.412c0,3.307,5.342,6.733,11.932,6.733s11.932-3.426,11.932-6.731V21.457C28.664,21.213,28.5,20.949,28.2,21.443Zm.018-8.721c-1.415,2.054-6.02,3.562-11.483,3.562S6.661,14.776,5.246,12.722c-.292-.423-.446-.193-.446,0v4.017c0,3,5.342,5.435,11.932,5.435s11.932-2.434,11.932-5.435V12.719c0-.19-.157-.42-.449,0ZM16.732,1.6C10.142,1.6,4.8,3.611,4.8,6.088V8.236c0,2.627,5.342,4.758,11.932,4.758s11.932-2.131,11.932-4.758V6.088C28.664,3.611,23.322,1.6,16.732,1.6Z" transform="translate(-4.8 -1.6)"/></svg>'
};
export const cog: Icon = {
name: 'cog',
data: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 30.001 30"><path id="cog" d="M29.67,17.558A5.108,5.108,0,0,1,32.557,13.2a15.981,15.981,0,0,0-1.235-2.985A4.827,4.827,0,0,1,26.48,8.634a4.665,4.665,0,0,1-1.22-4.841,15.611,15.611,0,0,0-2.985-1.234,5.655,5.655,0,0,1-4.717,2.884,5.658,5.658,0,0,1-4.719-2.884A15.571,15.571,0,0,0,9.855,3.793,4.661,4.661,0,0,1,8.634,8.634a4.824,4.824,0,0,1-4.841,1.577A15.756,15.756,0,0,0,2.559,13.2a5.106,5.106,0,0,1,2.884,4.362,5.661,5.661,0,0,1-2.884,4.719,15.89,15.89,0,0,0,1.234,2.985A4.667,4.667,0,0,1,8.634,26.48a4.669,4.669,0,0,1,1.221,4.841,15.779,15.779,0,0,0,2.985,1.238,5.647,5.647,0,0,1,4.719-2.887,5.658,5.658,0,0,1,4.719,2.887,16.052,16.052,0,0,0,2.985-1.238,4.667,4.667,0,0,1,1.22-4.841A4.84,4.84,0,0,1,31.325,24.9a15.741,15.741,0,0,0,1.235-2.985A5.106,5.106,0,0,1,29.67,17.558Zm-12.111,6.52a6.522,6.522,0,1,1,6.52-6.52A6.521,6.521,0,0,1,17.558,24.079Z" transform="translate(-2.559 -2.559)"/></svg>'
};
export const earth: Icon = {
name: 'earth',
data: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 30 30"><path id="earth" d="M15,0A15,15,0,1,0,30,15,15,15,0,0,0,15,0Zm0,28.125a13.086,13.086,0,0,1-5.192-1.068l6.831-7.685a.935.935,0,0,0,.237-.622V15.938A.938.938,0,0,0,15.938,15c-3.31,0-6.8-3.442-6.837-3.475a.937.937,0,0,0-.663-.275H4.688a.938.938,0,0,0-.937.937v5.625a.936.936,0,0,0,.518.838L7.5,20.267v5.5A13.132,13.132,0,0,1,3.14,9.375H6.563A.935.935,0,0,0,7.226,9.1l3.75-3.75a.937.937,0,0,0,.275-.663V2.42a13.164,13.164,0,0,1,9.5.779c-.122.1-.24.21-.353.323a5.626,5.626,0,0,0,3.974,9.6c.093,0,.186,0,.278-.007A22.007,22.007,0,0,1,24.4,24.027a.878.878,0,0,0-.024.153A13.084,13.084,0,0,1,15,28.125Z"/></svg>'
}
/** @deprecated */
export const edit: Icon = {
name: 'edit',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M3 17.46v3.04c0 .28.22.5.5.5h3.04c.13 0 .26-.05.35-.15L17.81 9.94l-3.75-3.75L3.15 17.1c-.1.1-.15.22-.15.36zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg>'
}
/** @deprecated
*
* Use delete
* */
export const remove: Icon = {
name: 'remove',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 9.91 11.01"><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path d="M8.83,1.85V9.41A1.58,1.58,0,0,1,7.26,11H2.62a1.6,1.6,0,0,1-1.57-1.6V1.85H.28A.26.26,0,0,1,0,1.57.27.27,0,0,1,.28,1.3H2.59v-1A.26.26,0,0,1,2.87,0H7a.28.28,0,0,1,.27.28v1H9.63a.28.28,0,0,1,.28.27.3.3,0,0,1-.28.28Zm-7.23,0V9.41a1,1,0,0,0,1,1.05H7.26a1,1,0,0,0,1-1.05V1.85ZM6.76,1.3V.55H3.15V1.3Z"/><path class="cls-1" d="M3.06,3.73a.28.28,0,0,1,.28-.28.29.29,0,0,1,.27.28V8.58a.29.29,0,0,1-.27.28.28.28,0,0,1-.28-.28Z"/><path class="cls-1" d="M6.29,3.73a.28.28,0,0,1,.28-.28.29.29,0,0,1,.27.28V8.58a.29.29,0,0,1-.27.28.28.28,0,0,1-.28-.28Z"/><path class="cls-1" d="M4.66,3.73a.3.3,0,0,1,.28-.28.29.29,0,0,1,.28.28V8.58a.29.29,0,0,1-.28.28.3.3,0,0,1-.28-.28Z"/></g></g></svg>'
}
/** @deprecated
* Use visibility
* */
export const preview: Icon = {
name: 'preview',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>'
}
/** @deprecated */
export const bullet: Icon = {
name: 'bullet',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0z" fill="none"/><circle cx="12" cy="12" r="10"/></svg>'
}
/** @deprecated */
export const remove_circle = {
name: 'remove_circle',
data: '<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="20" viewBox="0 0 24 24" width="20"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><path d="M12,2C6.47,2,2,6.47,2,12c0,5.53,4.47,10,10,10s10-4.47,10-10C22,6.47,17.53,2,12,2z M16.29,14.89 c0.39,0.39,0.39,1.02,0,1.41c-0.39,0.39-1.02,0.39-1.41,0L12,13.41l-2.89,2.89c-0.39,0.39-1.02,0.39-1.41,0 c-0.39-0.39-0.39-1.02,0-1.41L10.59,12L7.71,9.11c-0.39-0.39-0.39-1.02,0-1.41c0.39-0.39,1.02-0.39,1.41,0L12,10.59l2.89-2.89 c0.39-0.39,1.02-0.39,1.41,0c0.39,0.39,0.39,1.02,0,1.41L13.41,12L16.29,14.89z"/></g></svg>'
}
/** @deprecated */
export const remove_circle_outline = {
name: 'remove_circle_outline',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0V0z" fill="none" opacity=".87"/><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3.59-13L12 10.59 8.41 7 7 8.41 10.59 12 7 15.59 8.41 17 12 13.41 15.59 17 17 15.59 13.41 12 17 8.41z"/></svg>'
}
/** @deprecated */
export const person_add = {
name: 'person_add',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0z" fill="none"/><path d="M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm-9-2V7H4v3H1v2h3v3h2v-3h3v-2H6zm9 4c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg>'
}
/** @deprecated */
export const cloud_upload = {
name: 'cloud_upload',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l4.65-4.65c.2-.2.51-.2.71 0L17 13h-3z"/></svg>'
}
/** @deprecated */
export const add = {
name: 'add',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M18 13h-5v5c0 .55-.45 1-1 1s-1-.45-1-1v-5H6c-.55 0-1-.45-1-1s.45-1 1-1h5V6c0-.55.45-1 1-1s1 .45 1 1v5h5c.55 0 1 .45 1 1s-.45 1-1 1z"/></svg>'
}
/** @deprecated */
export const group = {
name: 'group',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5s-3 1.34-3 3 1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V18c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-1.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05.02.01.03.03.04.04 1.14.83 1.93 1.94 1.93 3.41V18c0 .35-.07.69-.18 1H22c.55 0 1-.45 1-1v-1.5c0-2.33-4.67-3.5-7-3.5z"/></svg>'
}
/** @deprecated */
export const lock = {
name: 'lock',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><g fill="none"><path d="M0 0h24v24H0V0z"/><path d="M0 0h24v24H0V0z" opacity=".87"/></g><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM9 8V6c0-1.66 1.34-3 3-3s3 1.34 3 3v2H9z"/></svg>'
}
/** @deprecated */
export const search = {
name: 'search',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M15.5 14h-.79l-.28-.27c1.2-1.4 1.82-3.31 1.48-5.34-.47-2.78-2.79-5-5.59-5.34-4.23-.52-7.79 3.04-7.27 7.27.34 2.8 2.56 5.12 5.34 5.59 2.03.34 3.94-.28 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>'
}
/** @deprecated */
export const refresh = {
name: 'refresh',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0z" fill="none"/><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>'
}
/** @deprecated */
export const close = {
name: 'close',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M18.3 5.71c-.39-.39-1.02-.39-1.41 0L12 10.59 7.11 5.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L10.59 12 5.7 16.89c-.39.39-.39 1.02 0 1.41.39.39 1.02.39 1.41 0L12 13.41l4.89 4.89c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z"/></svg>'
}
/** @deprecated */
export const done = {
name: 'done',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/></svg>'
}
/** @deprecated */
export const mail = {
name: 'mail',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>'
}
/** @deprecated */
export const photo = {
name: 'photo',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0z" fill="none"/><circle cx="12" cy="12" r="3.2"/><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/></svg>'
}
/** @deprecated */
export const check_circle_outlined = {
name: 'check_circle_outlined',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20"><path d="M0 0h24v24H0V0zm0 0h24v24H0V0z" fill="none"/><path d="M16.59 7.58L10 14.17l-3.59-3.58L5 12l5 5 8-8zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></svg>'
}
/** @deprecated */
export const reset = {
name: 'reset',
data: '<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><polyline fill="#000" points="1 2 2 2 2 6 6 6 6 7 1 7 1 2"></polyline><path fill="none" stroke="#000" stroke-width="1.1" d="M2.1,6.548 C3.391,3.29 6.746,1 10.5,1 C15.5,1 19.5,5 19.5,10 C19.5,15 15.5,19 10.5,19 C5.5,19 1.5,15 1.5,10"></path></svg>'
}
/** @deprecated */
export const send = {
name: 'send',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>'
}
/** @deprecated */
export const print = {
name: 'print',
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="240" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/></svg>'
}
export const incognito = {
name: 'incognito',
data: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24.51 19.525"><g id="Group_13376" data-name="Group 13376" transform="translate(-428.81 -3863.018)"><path id="Path_104500" data-name="Path 104500" d="M44.68,105.185H43.024a23.507,23.507,0,0,0-9.194-.158V106a3.909,3.909,0,0,1,1.264,1.668c.455,1.119.2,3.05,4.148,3.289s4-4.041,4.034-4.438.577-.372.577-.372.541-.021.579.372.09,4.673,4.034,4.438,3.693-2.17,4.146-3.289A3.9,3.9,0,0,1,53.879,106v-.969A23.686,23.686,0,0,0,44.68,105.185Z" transform="translate(397.218 3771.582)" fill="#2c2c2c"/><path id="Path_104501" data-name="Path 104501" d="M41.867,35.784H40.326s-1.95-6.217-2.207-6.735a2.8,2.8,0,0,0-2.591-2.061c-1.92-.266-2.138,1.225-3.544,1.268-1.406-.049-1.617-1.546-3.542-1.268a2.817,2.817,0,0,0-2.592,2.061c-.246.518-2.205,6.735-2.205,6.735H22.1a2.31,2.31,0,0,0-2.371,2.245H44.24A2.311,2.311,0,0,0,41.867,35.784Z" transform="translate(409.08 3836.064)" fill="#2c2c2c"/></g></svg>'
}
export const restricted = {
name: 'restricted',
data: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g id="noun-remove-file-3557544" transform="translate(-176.397 -106.4)"><path id="Path_104600" data-name="Path 104600" d="M181.881,274.166A5.485,5.485,0,1,0,178,272.559,5.484,5.484,0,0,0,181.881,274.166Zm-3.548-5.484a3.531,3.531,0,0,1,.452-1.729l4.839,4.839a3.548,3.548,0,0,1-5.29-3.11Zm7.1,0a3.527,3.527,0,0,1-.452,1.729l-4.839-4.839a3.548,3.548,0,0,1,5.29,3.11Z" transform="translate(0 -147.766)"/><path id="Path_104601" data-name="Path 104601" d="M245.859,106.4a2.258,2.258,0,0,0-2.258,2.258v4.516h1.936v-4.516a.323.323,0,0,1,.323-.323h8.064v3.871h3.871v11.935a.323.323,0,0,1-.323.323h-5.484V126.4h5.484a2.259,2.259,0,0,0,2.258-2.258v-13.3l-4.439-4.439Z" transform="translate(-63.333)"/></g></svg>'
}
export const graph = {
name: 'graph',
data: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 21.744"><g transform="translate(0)"><g transform="translate(0 0)"><path d="M18.772,15.578a2.718,2.718,0,0,0-.427-.368,3.629,3.629,0,0,0-3.291-.5,3.445,3.445,0,0,0-.962.5c-.07.051-.139.1-.2.161a2.335,2.335,0,0,0-.23.207.3.3,0,0,0-.047.051c-.011.013-.027.028-.036.042a1.611,1.611,0,0,0-.163.19L7.039,12.133a8.04,8.04,0,0,1,8.352-5.007h0a3.681,3.681,0,0,0,.93.133h.046a3.633,3.633,0,0,0,2.008-.605,3.57,3.57,0,0,0,.926-.9A3.63,3.63,0,1,0,13.368,1.57a3.491,3.491,0,0,0-.38.71,3.589,3.589,0,0,0-.26,1.35c0,.065,0,.125,0,.19a4.146,4.146,0,0,0,.051.459,3.721,3.721,0,0,0,.125.486L6.369,8.542a3.546,3.546,0,0,0-.649-.59,3.629,3.629,0,0,0-4.2,0,3.675,3.675,0,0,0-.894.9,3.483,3.483,0,0,0-.38.71,3.35,3.35,0,0,0-.137.41,3.563,3.563,0,0,0-.123.949v.19a3.57,3.57,0,0,0,.038.38.635.635,0,0,0,.013.08,3.641,3.641,0,0,0,.634,1.469h0a3.7,3.7,0,0,0,.934.894,3.606,3.606,0,0,0,2.008.607,3.732,3.732,0,0,0,.55-.038l-.044.036a8.037,8.037,0,0,1,8.6,4.556v-.021a3.606,3.606,0,0,0,2.836,2.61,3.472,3.472,0,0,0,1.26,0,3.629,3.629,0,0,0,2.879-2.58.228.228,0,0,0,0-.038,3.606,3.606,0,0,0-.6-3.111,2.769,2.769,0,0,0-.344-.393M14.129,3.515a2.19,2.19,0,0,1,.254-.928,2.323,2.323,0,0,1,.885-.907A2.24,2.24,0,0,1,16.359,1.4a2.206,2.206,0,0,1,1.1.285,2.234,2.234,0,0,1,.886.909,2.179,2.179,0,0,1,.252,1.038,2.213,2.213,0,0,1-.306,1.116,2.181,2.181,0,0,1-.949.888,2.255,2.255,0,0,1-.983.23h-.04a2.158,2.158,0,0,1-.949-.228,2.278,2.278,0,0,1-.569-.406,1.912,1.912,0,0,1-.156-.171,2.314,2.314,0,0,1-.224-.313.078.078,0,0,1-.015-.027,2.226,2.226,0,0,1-.287-1.091.76.76,0,0,1,0-.114M2.638,12.921a2.24,2.24,0,0,1-.731-.569,2.327,2.327,0,0,1-.22-.307,2.24,2.24,0,0,1-.3-1.118,1.122,1.122,0,0,1,0-.114,2.183,2.183,0,0,1,.258-.941,2.316,2.316,0,0,1,.885-.909,2.278,2.278,0,0,1,1.09-.283,2.232,2.232,0,0,1,1.5.59,2.19,2.19,0,0,1,.437.55.313.313,0,0,1,.038.059,2.1,2.1,0,0,1,.207.562,2.149,2.149,0,0,1,.053.484,2.056,2.056,0,0,1-.057.488,2.105,2.105,0,0,1-.226.6.277.277,0,0,1-.017.028,2.183,2.183,0,0,1-.435.535,2.158,2.158,0,0,1-.514.349,2.265,2.265,0,0,1-.985.23,2.23,2.23,0,0,1-.983-.23m15.8,5.44a2.219,2.219,0,0,1-.642,1.346,2.169,2.169,0,0,1-.22.19,2.261,2.261,0,0,1-.746.38,2.175,2.175,0,0,1-1.26-.019,2.12,2.12,0,0,1-.917-.549A2.185,2.185,0,0,1,14,18.1h0a.9.9,0,0,1,.015-.2c.015-.066,0-.076.015-.116a1.575,1.575,0,0,1,.055-.241,1.993,1.993,0,0,1,.2-.48c.011-.025.027-.049.04-.074a2.291,2.291,0,0,1,.321-.4h0c.034-.034.066-.063.1-.093a1.627,1.627,0,0,1,.142-.114,1.693,1.693,0,0,1,.2-.139,2.253,2.253,0,0,1,2.245,0,2.446,2.446,0,0,1,.45.345,2.371,2.371,0,0,1,.323.412,2.266,2.266,0,0,1,.319,1.388" transform="translate(0.01 0)"/><path d="M78.35,12.262a.338.338,0,0,0,.319.222h.8v.845a.2.2,0,0,0,.013.085.325.325,0,0,0,.173.216.268.268,0,0,0,.156.046.294.294,0,0,0,.1-.019.34.34,0,0,0,.245-.328v-.845h.9a.345.345,0,0,0,.347-.344.355.355,0,0,0-.156-.287.349.349,0,0,0-.19-.057h-.9v-.848a.325.325,0,0,0-.082-.216.305.305,0,0,0-.044-.042l-.038-.023-.068-.036a.237.237,0,0,0-.112-.023.3.3,0,0,0-.156.038.19.19,0,0,0-.055.036.323.323,0,0,0-.129.268V11.8h-.8a.363.363,0,0,0-.19.057.38.38,0,0,0-.123.167.247.247,0,0,0-.027.12.3.3,0,0,0,.011.084.315.315,0,0,0,.015.038" transform="translate(-63.459 -8.595)"/></g></g></svg>'
}
export const filters = {
name: 'filters',
data: '<svg id="Group_13364" data-name="Group 13364" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20" viewBox="0 0 24.648 21.128"><defs><linearGradient id="linear-gradient" x2="1" y2="0.961" gradientUnits="objectBoundingBox"><stop offset="0" /><stop offset="1" /></linearGradient><linearGradient id="linear-gradient-2" x1="-0.029" y1="0.037" x2="1" y2="0.928" xlink:href="#linear-gradient"/></defs><g id="Group_13361" data-name="Group 13361" transform="translate(0 10.564)"><line id="Line_420" data-name="Line 420" x2="24.648" transform="translate(0 5.774)" fill="none" stroke="#707070" stroke-width="1"/><g id="Ellipse_515" data-name="Ellipse 515" transform="translate(2.078)" stroke="#fafafa" stroke-width="0.6"><ellipse cx="5.282" cy="5.282" rx="5.282" ry="5.282" stroke="none"/><ellipse cx="5.282" cy="5.282" rx="4.982" ry="4.982" fill="none"/></g></g><g id="Group_13362" data-name="Group 13362"><line id="Line_418" data-name="Line 418" x2="24.648" transform="translate(0 5.388)" fill="none" stroke="#707070" stroke-width="1"/><g id="Path_104494" data-name="Path 104494" transform="translate(11.444)"><path d="M 5.281623840332031 10.26361751556396 C 2.534753799438477 10.26361751556396 0.3000038266181946 8.028787612915039 0.3000038266181946 5.281807899475098 C 0.3000038266181946 2.534827947616577 2.534753799438477 0.2999978959560394 5.281623840332031 0.2999978959560394 C 8.028493881225586 0.2999978959560394 10.26324367523193 2.534827947616577 10.26324367523193 5.281807899475098 C 10.26324367523193 8.028787612915039 8.028493881225586 10.26361751556396 5.281623840332031 10.26361751556396 Z" stroke="none"/><path d="M 5.281623840332031 0.5999975204467773 C 2.700173854827881 0.5999975204467773 0.6000041961669922 2.700247764587402 0.6000041961669922 5.281807899475098 C 0.6000041961669922 7.863368034362793 2.700173854827881 9.963618278503418 5.281623840332031 9.963618278503418 C 7.863073825836182 9.963618278503418 9.96324348449707 7.863368034362793 9.96324348449707 5.281807899475098 C 9.96324348449707 2.700247764587402 7.863073825836182 0.5999975204467773 5.281623840332031 0.5999975204467773 M 5.281623840332031 -1.9073486328125e-06 C 8.198583602905273 -1.9073486328125e-06 10.5632438659668 2.364748001098633 10.5632438659668 5.281807899475098 C 10.5632438659668 8.198867797851562 8.198583602905273 10.56361770629883 5.281623840332031 10.56361770629883 C 2.364664077758789 10.56361770629883 3.814697265625e-06 8.198867797851562 3.814697265625e-06 5.281807899475098 C 3.814697265625e-06 2.364748001098633 2.364664077758789 -1.9073486328125e-06 5.281623840332031 -1.9073486328125e-06 Z" stroke="none" fill="#fafafa"/></g></g></svg>'
}
export const orcid_add = {
name: 'orcid_add',
data: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 42.13 40.77"><defs><style>.cls-2{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><circle cx="18.09" cy="18.09" r="18.09"/><rect class="cls-2" x="9.86" y="11.03" width="2.49" height="15.27"/><ellipse class="cls-2" cx="11.07" cy="8.16" rx="1.63" ry="1.6"/><path class="cls-2" d="M23.07,11.17A6.57,6.57,0,0,0,21.81,11H15.28V13.2h0V24.09h0v2.15h6.34a7.75,7.75,0,0,0,1.45-.14,7.61,7.61,0,0,0,0-14.93ZM25,23l-.26.19a4.3,4.3,0,0,1-.45.29,4.41,4.41,0,0,1-1.64.62H17.63V13.2h4.42a5.63,5.63,0,0,1,2.62.81,4.12,4.12,0,0,1,.47.38A5.74,5.74,0,0,1,25,23Z"/><path d="M41.33,34.62H37.57V30.86a.79.79,0,0,0-.79-.79h0a.79.79,0,0,0-.8.78h0v3.76H32.22a.79.79,0,0,0-.79.79h0a.79.79,0,0,0,.79.79H36V40a.8.8,0,1,0,1.59,0h0V36.21h3.76a.79.79,0,0,0,.8-.78h0A.8.8,0,0,0,41.33,34.62Z"/></g></g></svg>'
}
export const orcid_bin = {
name: 'orcid_bin',
data: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 41.58 41.07"><defs><style>.cls-3{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="Layer_2-2" data-name="Layer 2"><g id="Layer_1-2-2" data-name="Layer 1-2"><path d="M40.55,31.91v7.56A1.58,1.58,0,0,1,39,41.07H34.3a1.59,1.59,0,0,1-1.57-1.6V31.91H32a.25.25,0,0,1-.27-.23v0h0a.28.28,0,0,1,.27-.23h2.32v-1a.25.25,0,0,1,.22-.28h4.22a.3.3,0,0,1,.28.28v1h2.32c.15,0,.22.13.22.28h0c0,.14-.08.18-.22.19Zm-7.23,0v7.56a1,1,0,0,0,1,1H39a1,1,0,0,0,1-1V31.91Zm5.12-.5v-.74H34.82v.74Z"/><path d="M34.74,33.79a.29.29,0,0,1,.28-.28.29.29,0,0,1,.27.28v4.85a.29.29,0,0,1-.27.28.29.29,0,0,1-.28-.28Z"/><path d="M38,33.79a.29.29,0,0,1,.28-.28.29.29,0,0,1,.27.28v4.85a.29.29,0,0,1-.27.28.29.29,0,0,1-.28-.28Z"/><path d="M36.34,33.79a.3.3,0,0,1,.28-.28.28.28,0,0,1,.27.28v4.85a.28.28,0,0,1-.27.28.3.3,0,0,1-.28-.28Z"/><circle cx="18.09" cy="18.09" r="18.09"/><rect class="cls-3" x="9.86" y="11.03" width="2.49" height="15.27"/><ellipse class="cls-3" cx="11.07" cy="8.16" rx="1.63" ry="1.6"/><path class="cls-3" d="M23.07,11.17A6.7,6.7,0,0,0,21.81,11H15.28v2.2h0V24.09h0v2.15h6.34a7.83,7.83,0,0,0,1.45-.14,7.61,7.61,0,0,0,0-14.93ZM25,23l-.26.19a3.46,3.46,0,0,1-.45.29,4.42,4.42,0,0,1-1.64.62h-5V13.2h4.42a5.63,5.63,0,0,1,2.62.81,3.4,3.4,0,0,1,.47.38,5.75,5.75,0,0,1,.38,8.11A6.14,6.14,0,0,1,25,23Z"/></g></g></g></g></svg>'
}
export const link = {
name: 'link',
data: '<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" data-svg="link"><path fill="none" stroke="#000" stroke-width="1.1" d="M10.625,12.375 L7.525,15.475 C6.825,16.175 5.925,16.175 5.225,15.475 L4.525,14.775 C3.825,14.074 3.825,13.175 4.525,12.475 L7.625,9.375"></path><path fill="none" stroke="#000" stroke-width="1.1" d="M9.325,7.375 L12.425,4.275 C13.125,3.575 14.025,3.575 14.724,4.275 L15.425,4.975 C16.125,5.675 16.125,6.575 15.425,7.275 L12.325,10.375"></path><path fill="none" stroke="#000" stroke-width="1.1" d="M7.925,11.875 L11.925,7.975"></path></svg>'
}
export const quotes = {
name: 'quotes',
data: '<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" data-svg="quote-right"><path d="M17.27,7.79 C17.27,9.45 16.97,10.43 15.99,12.02 C14.98,13.64 13,15.23 11.56,15.97 L11.1,15.08 C12.34,14.2 13.14,13.51 14.02,11.82 C14.27,11.34 14.41,10.92 14.49,10.54 C14.3,10.58 14.09,10.6 13.88,10.6 C12.06,10.6 10.59,9.12 10.59,7.3 C10.59,5.48 12.06,4 13.88,4 C15.39,4 16.67,5.02 17.05,6.42 C17.19,6.82 17.27,7.27 17.27,7.79 L17.27,7.79 Z"></path><path d="M8.68,7.79 C8.68,9.45 8.38,10.43 7.4,12.02 C6.39,13.64 4.41,15.23 2.97,15.97 L2.51,15.08 C3.75,14.2 4.55,13.51 5.43,11.82 C5.68,11.34 5.82,10.92 5.9,10.54 C5.71,10.58 5.5,10.6 5.29,10.6 C3.47,10.6 2,9.12 2,7.3 C2,5.48 3.47,4 5.29,4 C6.8,4 8.08,5.02 8.46,6.42 C8.6,6.82 8.68,7.27 8.68,7.79 L8.68,7.79 Z"></path></svg>'
}
export const mining = {
name: 'mining',
data: '<svg width="20" height="20" viewBox="0 0 600 500" xmlns="http://www.w3.org/2000/svg"><g><path d="m449.68 334.84-90.93-52.5c-5.4258-3.1133-12.074-3.1133-17.5 0l-90.93 52.5c-5.4258 3.1328-8.75 8.9062-8.75 15.156v105c0 6.2461 3.3242 12.039 8.75 15.156l90.93 52.5c2.7109 1.5547 5.7227 2.3438 8.75 2.3438s6.0391-0.78906 8.75-2.3438l90.93-52.5c5.4258-3.1328 8.75-8.9062 8.75-15.156v-105c0-6.2461-3.3242-12.023-8.75-15.156zm-99.68 120.16c-28.945 0-52.5-23.555-52.5-52.5s23.555-52.5 52.5-52.5 52.5 23.555 52.5 52.5-23.555 52.5-52.5 52.5z"/><path d="m545.93 35h-391.86c-27.055 0-49.07 22.016-49.07 49.07v20.93h490v-20.93c0-27.055-22.016-49.07-49.07-49.07z"/><path d="m105 370.93c0 27.055 22.016 49.07 49.07 49.07h70v-70c0-12.477 6.7031-24.078 17.5-30.309l90.93-52.5c5.3359-3.0625 11.375-4.6914 17.5-4.6914s12.164 1.6289 17.465 4.6719l90.965 52.516c10.797 6.2305 17.5 17.852 17.5 30.309v70h70c27.055 0.003906 49.07-22.012 49.07-49.066v-230.93h-490zm57.629-138.3 52.5-52.5c6.8438-6.8438 17.902-6.8438 24.746 0l42.84 42.84 75.793-45.484c6.8945-4.1289 15.715-3.0469 21.387 2.625l58.922 58.922 75.266-60.219c7.543-6.0391 18.551-4.8125 24.586 2.7305 6.0391 7.543 4.8125 18.566-2.7305 24.605l-87.5 70c-3.2188 2.5898-7.0859 3.8516-10.938 3.8516-4.4961 0-8.9961-1.7344-12.391-5.1289l-60.34-60.34-75.793 45.484c-6.8789 4.1289-15.68 3.0625-21.387-2.625l-40.09-40.145-40.129 40.129c-6.8438 6.8438-17.902 6.8438-24.746 0-6.8398-6.8438-6.8398-17.906 0.003906-24.746z"/></g></svg>'
}
/** Add new icon under this line to be sure that it will be added on preview */

View File

@ -1,626 +0,0 @@
import {
AfterViewInit,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
HostListener,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
ViewChild
} from "@angular/core";
import {AbstractControl, UntypedFormArray, UntypedFormControl, ValidatorFn} from "@angular/forms";
// import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {Subscription} from "rxjs";
import {ClickEvent} from "../click/click-outside-or-esc.directive";
// import {EnvProperties} from "../../utils/properties/env-properties";
// import {properties} from "../../../../environments/environment";
export type InputType = 'text' | 'URL' | 'logoURL' | 'autocomplete' | 'autocomplete_soft' | 'textarea' | 'select' | 'chips';
export interface Option {
icon?: string,
iconClass?: string,
value: any,
label: string,
tooltip?: string,
disabled?: boolean,
hidden?: boolean
}
export interface Placeholder {
label: string,
static?: boolean
}
declare var UIkit;
/**
* WARNING! dashboard-input selector is @deprecated, use input instead
*
* Autocomplete soft allows values that are not listed in options list. In order to work as expected
* avoid providing options with different label and value.
*
* */
@Component({
selector: '[dashboard-input], [input]',
template: `
<div *ngIf="formControl" [id]="id">
<div class="input-wrapper" [class.disabled]="formControl.disabled" [class.opened]="opened"
[class.focused]="focused" [ngClass]="inputClass" [class.hint]="hint"
[class.active]="(formAsControl?.value || selectable || formAsArray?.length > 0 || getLabel(formAsControl?.value)) && !focused"
[class.danger]="(formControl.invalid && (formControl.touched || !!searchControl?.touched)) || (!!searchControl?.invalid && !!searchControl?.touched)">
<div #inputBox class="input-box" [class.select]="selectable" click-outside-or-esc
[class.static]="placeholderInfo?.static" (clickOutside)="click($event)">
<div *ngIf="!placeholderInfo?.static && placeholderInfo.label" class="placeholder">
<label>{{placeholderInfo.label}} <sup *ngIf="required">*</sup></label>
</div>
<div class="uk-flex" [class.uk-flex-middle]="type !== 'textarea'"
[attr.uk-tooltip]="(tooltip && formControl.value && !focused && type !== 'chips' && type !== 'textarea')?('title: ' + getTooltip(formControl.value) + '; 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">
</ng-template>
<ng-template [ngIf]="type === 'textarea'">
<textarea #textArea class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[rows]="rows" [formControl]="formAsControl"></textarea>
</ng-template>
<ng-template [ngIf]="type === 'select'">
<ng-container *ngIf="placeholderInfo?.static">
<div *ngIf="!getLabel(formControl.value)"
class="input placeholder uk-width-expand uk-text-truncate">{{placeholderInfo.label}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-width-expand uk-text-truncate">{{getLabel(formControl.value)}}</div>
</ng-container>
<ng-container *ngIf="!placeholderInfo?.static">
<div *ngIf="!getLabel(formControl.value)" class="input uk-width-expand uk-text-truncate">{{noValueSelected}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-width-expand uk-text-truncate">{{getLabel(formControl.value)}}</div>
</ng-container>
</ng-template>
<ng-template [ngIf]="type === 'autocomplete'">
<input *ngIf="focused" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
#searchInput class="input" [formControl]="searchControl" [class.uk-text-truncate]="!focused">
<div *ngIf="!focused && !selectable" class="input uk-text-truncate">{{getLabel(formAsControl.value)}}</div>
<ng-container *ngIf="!focused && selectable" >
<div *ngIf="!getLabel(formControl.value)" class="input uk-text-truncate">{{noValueSelected}}</div>
<div *ngIf="getLabel(formControl.value)" class="input uk-text-truncate">{{getLabel(formControl.value)}}</div>
</ng-container>
</ng-template>
<ng-template [ngIf]="type === 'autocomplete_soft'">
<input #input class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[formControl]="formAsControl" [class.uk-text-truncate]="!focused">
</ng-template>
<ng-template [ngIf]="type === 'chips'">
<div class="uk-grid uk-grid-small uk-grid-row-collapse uk-width-expand" uk-grid>
<div *ngFor="let chip of formAsArray.controls; let i=index" [class.uk-hidden]="!focused && i > 0"
class="chip">
<div class="uk-label uk-label-small uk-flex uk-flex-middle"
[attr.uk-tooltip]="(tooltip)?('title: ' + getLabel(chip.value) + '; delay: 500; pos: bottom-left'):null">
<span class="uk-text-truncate uk-width-expand">{{getLabel(chip.value)}}</span>
<icon *ngIf="focused" (click)="remove(i, $event)" class="uk-link-text uk-margin-small-left clickable" [flex]="true"
name="close" ratio="0.7"></icon>
</div>
</div>
<div *ngIf="searchControl && (focused || formAsArray.length === 0)"
class="uk-width-small uk-flex uk-flex-column uk-flex-center">
<input #searchInput class="input" [class.search]="searchControl.value"
[attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[formControl]="searchControl" [class.uk-text-truncate]="!focused">
</div>
<div *ngIf="!focused && formAsArray.length > 1"
class="uk-width-expand uk-flex uk-flex-column uk-flex-center more">
+ {{(formAsArray.length - 1)}} more
</div>
</div>
</ng-template>
<div *ngIf="(formControl.disabled && disabledIcon) || icon || (selectable && selectArrow) || type === 'autocomplete' || searchable"
class="uk-margin-small-left icon">
<icon *ngIf="formControl.disabled && disabledIcon" [name]="disabledIcon" [flex]="true"></icon>
<ng-template [ngIf]="formControl.enabled">
<icon *ngIf="!searchControl?.value && icon" [name]="icon" [flex]="true"></icon>
<icon *ngIf="!icon && selectable && selectArrow" [name]="selectArrow" [flex]="true"></icon>
<button *ngIf="!!searchControl?.value && type === 'autocomplete'" class="uk-close uk-icon"
(click)="resetSearch($event)">
<icon [flex]="true" name="close"></icon>
</button>
<button *ngIf="!!formControl?.value && searchable" class="uk-close uk-icon" (click)="resetValue($event)">
<icon [flex]="true" name="close"></icon>
</button>
</ng-template>
</div>
</div>
<div class="tools">
<ng-content select="[tools]"></ng-content>
</div>
</div>
</div>
<div class="options uk-dropdown" *ngIf="filteredOptions && filteredOptions.length > 0 && opened" #optionBox
uk-dropdown="pos: bottom-justify; mode: none; offset: 15; boundary-align: true;" [attr.boundary]="'#' + id">
<ul class="uk-nav uk-dropdown-nav">
<li *ngFor="let option of filteredOptions; let i=index" [class.uk-hidden]="option.hidden" [class.uk-active]="(formControl.value === option.value) || selectedIndex === i">
<a (click)="selectOption(option, $event)"
[class]="option.disabled ? 'uk-disabled uk-text-muted' : ''">
<span [attr.uk-tooltip]="(tooltip)?('title: ' + (option.tooltip ? option.tooltip : option.label) + '; delay: 500; pos:bottom-left'):null">{{option.label}}</span>
</a>
</li>
</ul>
</div>
</div>
<span *ngIf="formControl?.invalid && formControl?.touched" class="uk-text-danger">
<span *ngIf="formControl.errors.error">{{formControl.errors.error}}</span>
<span *ngIf="type === 'URL' || type === 'logoURL'">Please provide a valid URL (e.g. https://example.com)</span>
</span>
<span class="uk-text-danger uk-text-small">
<ng-content select="[error]"></ng-content>
</span>
<span *ngIf="formControl?.valid" class="uk-text-warning uk-text-small">
<ng-content select="[warning]"></ng-content>
<span *ngIf="!secure">
<span class="uk-text-bold">Note:</span> Prefer urls like "<span class="uk-text-bold">https://</span>example.com/my-secure-image.png"
instead of "<span class="uk-text-bold">http://</span>example.com/my-image.png".
<span class="uk-text-bold">Browsers may not load non secure content.</span>
</span>
</span>
<span class="uk-text-small">
<ng-content select="[note]"></ng-content>
</span>
`
})
export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChanges {
private static INPUT_COUNTER: number = 0;
/** Deprecated options*/
/** @deprecated */
@Input('label') label: string;
/** @deprecated */
@Input() extraLeft: boolean = true;
/** @deprecated */
@Input() gridSmall: boolean = false;
/** @deprecated */
@Input() hideControl: boolean = false;
/** @deprecated */
@Input() flex: 'middle' | 'top' | 'bottom' = 'middle';
/** @deprecated */
@Input() iconLeft: boolean = false;
/** @deprecated */
@Input() removable: boolean = true;
/** @deprecated */
@Input() smallChip: boolean = false;
/** @deprecated */
@Input() panelWidth: number = 300;
/** @deprecated */
@Input() panelClass: string = null;
/** Basic information */
@Input('formInput') formControl: AbstractControl;
@Input('type') type: InputType = 'text';
@Input() validators: ValidatorFn[] | ValidatorFn;
@Input() disabled: boolean = false;
@Input() disabledIcon: string = 'lock';
@Input() value: any | any[];
@Output() valueChange = new EventEmitter<any | any[]>();
@Input() hint: string;
@Input() tooltip: boolean = false;
@Input() searchable: boolean = false;
/** Text */
@ViewChild('input') input: ElementRef;
/** Textarea options */
@ViewChild('textArea') textArea: ElementRef;
@Input('rows') rows: number = 3;
/** Select | Autocomplete | chips available options */
@Input() selectArrow: string = 'arrow_drop_down';
@Input() selectedIndex: number = 0;
@Input() selectable: boolean = false;
@Input() noValueSelected: string = 'No option selected';
/** Chips && Autocomplete*/
public filteredOptions: Option[] = [];
public searchControl: UntypedFormControl;
/** Use modifier's class(es) to change view of your Input */
@Input() inputClass: string = 'inner';
/** Icon on the input */
@Input() icon: string = null;
/** Chip options */
@Input() addExtraChips: boolean = false;
@Input() showOptionsOnEmpty: boolean = true;
@Output() focusEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
/** LogoUrl information */
public secure: boolean = true;
/** Internal basic information */
public id: string;
public placeholderInfo: Placeholder = {label: '', static: true};
public required: boolean = false;
public focused: boolean = false;
public opened: boolean = false;
private initValue: any;
private optionsArray: Option[] = [];
private optionsBreakpoint: number = 6;
private subscriptions: any[] = [];
@ViewChild('inputBox') inputBox: ElementRef;
@ViewChild('optionBox') optionBox: ElementRef;
@ViewChild('searchInput') searchInput: ElementRef;
@Input()
set placeholder(placeholder: string | Placeholder) {
if (typeof placeholder === 'string') {
this.placeholderInfo = {label: placeholder, static: false};
} else {
if (placeholder.static && (this.type === 'autocomplete' || this.type === 'chips' || this.hint)) {
placeholder.static = false;
console.debug('Static placeholder is not available in this type of input and if hint is available.');
}
this.placeholderInfo = placeholder;
}
}
@Input()
set options(options: (Option | string | number) []) {
this.optionsArray = options.map(option => {
if (typeof option === 'string' || typeof option === 'number') {
return {
label: option.toString(),
value: option
};
} else {
return option;
}
});
if(!this.tooltip) {
this.tooltip = this.optionsArray.length > 0;
}
if(this.type === "select") {
if (this.optionsArray.length > this.optionsBreakpoint) {
this.type = 'autocomplete';
this.showOptionsOnEmpty = true;
this.icon = this.selectArrow;
}
this.selectable = true;
}
}
constructor(private elementRef: ElementRef, private cdr: ChangeDetectorRef) {}
@HostListener('window:keydown.arrowUp', ['$event'])
arrowUp(event: KeyboardEvent) {
if (this.opened) {
event.preventDefault();
if (this.selectedIndex > 0) {
this.selectedIndex--;
this.optionBox.nativeElement.scrollBy(0, -34);
}
}
}
@HostListener('window:keydown.arrowDown', ['$event'])
arrowDown(event: KeyboardEvent) {
if (this.opened) {
event.preventDefault();
if (this.selectedIndex < (this.filteredOptions.length - 1)) {
this.selectedIndex++;
this.optionBox.nativeElement.scrollBy(0, 34);
}
}
}
@HostListener('window:keydown.enter', ['$event'])
enter(event: KeyboardEvent) {
if (this.opened && this.optionBox) {
event.preventDefault();
if (this.filteredOptions[this.selectedIndex]) {
this.selectOption(this.filteredOptions[this.selectedIndex], event);
}
this.open(false);
event.stopPropagation();
} else {
this.focus(false, event);
}
}
click(event: ClickEvent) {
this.focus(!event.clicked, event);
}
ngOnInit() {
InputComponent.INPUT_COUNTER++;
this.id = 'input-' + InputComponent.INPUT_COUNTER;
if (!this.formControl) {
if (Array.isArray(this.value)) {
this.formControl = new UntypedFormArray([]);
this.value.forEach(value => {
this.formAsArray.push(new UntypedFormControl(value, this.validators));
});
} else {
this.formControl = new UntypedFormControl(this.value);
this.formControl.setValidators(this.validators);
}
if (this.disabled) {
this.formControl.disable();
}
}
}
ngAfterViewInit() {
this.reset();
}
ngOnChanges(changes: SimpleChanges) {
if (this.formControl) {
if (changes.value) {
this.formControl.setValue(this.value);
}
if (changes.formControl || changes.validators || changes.options) {
this.reset();
}
if (changes.disabled) {
if (this.disabled) {
this.formControl.disable();
} else {
this.formControl.enable();
}
}
}
}
ngOnDestroy(): void {
this.unsubscribe();
}
get formAsControl(): UntypedFormControl {
if (this.formControl instanceof UntypedFormControl) {
return this.formControl;
} else {
return null;
}
}
get formAsArray(): UntypedFormArray {
if (this.formControl instanceof UntypedFormArray) {
return this.formControl;
} else {
return null;
}
}
reset() {
this.secure = true;
this.unsubscribe();
this.initValue = this.copy(this.formControl.value);
if (this.type === 'logoURL') {
this.secure = (!this.initValue || this.initValue.includes('https://'));
}
if (this.optionsArray) {
this.filteredOptions = this.filter('');
this.cdr.detectChanges();
}
if (this.type === 'chips' || this.type === 'autocomplete') {
if (!this.searchControl) {
this.searchControl = new UntypedFormControl('', this.validators);
}
this.subscriptions.push(this.searchControl.valueChanges.subscribe(value => {
this.filteredOptions = this.filter(value);
this.cdr.detectChanges();
if (this.focused) {
this.open(true);
setTimeout(() => {
this.searchInput.nativeElement.focus();
this.searchInput.nativeElement.value = value;
}, 0);
}
}));
}
if (this.formControl.validator) {
let validator = this.formControl.validator({} as AbstractControl);
this.required = (validator && validator.required);
}
this.subscriptions.push(this.formControl.valueChanges.subscribe(value => {
if (this.formControl.enabled) {
value = (value === '') ? null : value;
if (this.type === 'logoURL') {
this.secure = (!value || value.includes('https://'));
}
if (this.initValue === value || (this.initValue === '' && value === null)) {
this.formControl.markAsPristine();
} else {
this.formControl.markAsDirty();
}
if (this.type === 'autocomplete_soft') {
this.filteredOptions = this.filter(value);
this.cdr.detectChanges();
if (this.focused) {
this.open(true);
}
}
if ((this.value && value && this.value !== value) || (!this.value && value) || this.value && !value) {
this.valueChange.emit(this.formControl.value);
}
}
}));
if (this.input) {
this.input.nativeElement.disabled = this.formControl.disabled;
}
}
unsubscribe() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) {
subscription.unsubscribe();
}
});
}
remove(index: number, event) {
if (this.focused) {
this.formAsArray.removeAt(index);
this.formAsArray.markAsDirty();
this.focus(true);
this.searchControl.setValue('');
event.stopPropagation();
}
}
private filter(value: string): Option[] {
let options = this.optionsArray.filter(option => !option.hidden);
if (this.type === "chips") {
options = options.filter(option => !this.formAsArray.value.find(value => this.equals(option.value, value)));
}
if ((!value || value.length == 0)) {
this.selectedIndex = 0;
return (this.showOptionsOnEmpty) ? options : [];
}
const filterValue = value.toString().toLowerCase();
options = options.filter(option => option.label.toLowerCase().indexOf(filterValue) != -1);
this.selectedIndex = options.findIndex(option => option.value === this.formControl.value);
if (this.selectedIndex === -1) {
this.selectedIndex = 0;
}
return options;
}
add(event) {
if (this.addExtraChips && this.searchControl.value && this.searchControl.valid) {
if (event && event.stopPropagation) {
event.stopPropagation();
}
this.formAsArray.push(new UntypedFormControl(this.searchControl.value, this.validators));
this.formAsArray.markAsDirty();
}
this.searchControl.setValue('');
}
getLabel(value: any): string {
let option = this.optionsArray.find(option => this.equals(option.value, value));
return (option) ? option.label : (value);
}
getTooltip(value: any): string {
let option = this.optionsArray.find(option => this.equals(option.value, value));
return (option) ? (option.tooltip ? option.tooltip : option.label) : (value);
}
focus(value: boolean, event = null) {
if (this.focused) {
this.formControl.markAsTouched();
}
this.focused = value;
this.cdr.detectChanges();
if (this.focused) {
if (this.input) {
this.input.nativeElement.focus();
} else if (this.textArea) {
this.textArea.nativeElement.focus();
} else if (this.searchInput) {
this.searchInput.nativeElement.focus();
}
if (this.selectArrow) {
this.open(!this.opened);
} else if (this.type !== 'autocomplete' || this.showOptionsOnEmpty || !this.formControl.value) {
this.open(true);
}
} else {
this.open(false);
if (this.input) {
this.input.nativeElement.blur();
} else if (this.textArea) {
this.textArea.nativeElement.blur();
} else if (this.searchInput) {
this.searchInput.nativeElement.blur();
}
if (this.searchControl) {
this.add(event);
}
}
this.focusEmitter.emit(this.focused);
}
open(value: boolean) {
this.opened = value && this.formControl.enabled;
this.cdr.detectChanges();
if (this.optionBox && this.opened) {
this.selectedIndex = this.filteredOptions.findIndex(option => option.value === this.formControl.value);
if (this.selectedIndex === -1 && this.type !== 'autocomplete_soft') {
this.selectedIndex = 0;
}
UIkit.dropdown(this.optionBox.nativeElement).show();
} else {
if (this.optionBox) {
UIkit.dropdown(this.optionBox.nativeElement).hide();
this.focused = false;
}
}
}
resetSearch(event: any) {
event.stopPropagation();
this.searchControl.setValue('');
this.focus(true, event);
}
resetValue(event: any) {
event.stopPropagation();
this.formControl.setValue('');
this.focus(true, event);
}
selectOption(option: Option, event) {
if (this.formControl.enabled) {
if (this.formAsControl) {
this.formAsControl.setValue(option.value);
} else if (this.formAsArray) {
this.formAsArray.push(new UntypedFormControl(option.value));
this.formAsArray.markAsDirty();
event.stopPropagation();
this.focus(true);
this.searchControl.setValue('');
}
}
}
// External Helper Methods
public equals(object1, object2) {
return object1 === object2 || JSON.stringify(object1) === JSON.stringify(object2);
}
public copy(obj: any): any {
let copy;
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
copy = [];
for (let i = 0, len = obj.length; i < len; i++) {
copy[i] = this.copy(obj[i]);
}
return copy;
}
// Handle Map
if (obj instanceof Map) {
return new Map(obj.entries());
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (let attr in obj) {
if (obj.hasOwnProperty(attr)) {
copy[attr] = this.copy(obj[attr]);
}
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
}

View File

@ -1,24 +0,0 @@
import {NgModule} from '@angular/core';
import {InputComponent} from "./input.component";
import {CommonModule} from "@angular/common";
import {RouterModule} from "@angular/router";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {ClickModule} from "../click/click.module";
@NgModule({
imports: [
CommonModule,
RouterModule,
FormsModule,
ReactiveFormsModule,
ClickModule
],
exports: [
InputComponent
],
declarations: [
InputComponent
]
})
export class InputModule {
}

View File

@ -1,191 +0,0 @@
import {Component, ElementRef, EventEmitter, Input, Output, ViewChild, ViewEncapsulation} from '@angular/core';
declare var UIkit: any;
@Component({
selector: 'modal-alert',
template: `
<div #element class="uk-modal" [class.uk-modal-container]="large" [id]="id" uk-modal="container: #modal-container">
<div class="uk-modal-dialog">
<div class="uk-modal-header uk-flex uk-flex-middle uk-flex-between" [ngClass]="classTitle">
<div [class.uk-invisible]="!alertHeader">
<h5 class="uk-margin-remove">{{alertTitle}}</h5>
</div>
<button class="uk-close uk-icon uk-margin-left" (click)="cancel()">
<icon name="close" ratio="1.5"></icon>
</button>
</div>
<div class="uk-modal-body uk-animation-fast uk-text-left"
[ngClass]="classBody" [attr.uk-overflow-auto]="overflowBody?'':null">
<div *ngIf="message" [hidden]=!alertMessage [innerHTML]="message"></div>
<ng-content></ng-content>
</div>
<div *ngIf="(choice || okButton || cancelButton) && alertFooter" class="uk-modal-footer">
<div class="uk-grid uk-flex uk-flex-middle" uk-grid>
<label *ngIf="choice" class="uk-width-expand">
<input type="checkbox" [(ngModel)]="select">
<span class="uk-margin-small-left">Don't show this message again</span>
</label>
<div [ngClass]="(choice)?'uk-width-auto':'uk-width-1-1'">
<div class="uk-flex-right uk-grid uk-grid-small" uk-grid>
<span *ngIf="okButton" [class.uk-flex-last]="!okButtonLeft">
<button class="uk-button uk-button-primary" [disabled]="okDisabled"
[class.uk-disabled]="okDisabled" (click)="ok()">{{okButtonText}}</button>
</span>
<span *ngIf="cancelButton">
<button class="uk-button uk-button-default uk-margin-small-left"
(click)="cancel()">{{cancelButtonText}}</button>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
`,
encapsulation: ViewEncapsulation.None,
})
/**
* API to an open alert window.
*/
export class AlertModal {
private static MODAL_COUNTER: number = 0;
id: string = "modal";
@Input() classTitle: string = "uk-background-primary-opacity";
@Input() classBody: string = "";
@Input() large: boolean = false;
@Input() overflowBody: boolean = true;
/**
* Caption for the title.
*/
public alertTitle: string;
/**
* Describes if the alert contains Ok Button.
* The default Ok button will close the alert and emit the callback.
* Defaults to true.
*/
public okButton: boolean = true;
/**
* Caption for the OK button.
* Default: Ok
*/
public okButtonText: string = 'OK';
/**
* Describes if the alert contains cancel Button.
* The default Cancelbutton will close the alert.
* Defaults to true.
*/
public cancelButton: boolean = true;
/**
* Caption for the Cancel button.
* Default: Cancel
*/
public cancelButtonText: string = 'Cancel';
/**
* if the alertMessage is true it will show the contentString inside alert body.
*/
public alertMessage: boolean = true;
/**
* Some message/content can be set in message which will be shown in alert body.
*/
public message: string;
/**
* if the value is true alert footer will be visible or else it will be hidden.
*/
public alertFooter: boolean = true;
/**
* shows alert header if the value is true.
*/
public alertHeader: boolean = true;
/**
* if the value is true ok button align on the left, else on the right
*/
public okButtonLeft: boolean = true;
/**
* if the value is true ok button is disabled
*/
@Input()
public okDisabled: boolean = false;
/**
* If the value is true, a checkbox option will be appeared on the right side of footer
*/
@Input()
public choice: boolean = false;
/**
* if the value is true then on ok clicked, modal will stay open.
*/
public stayOpen: boolean = false;
/**
* Value will be emitted if @choice is true
*/
public select: boolean = true;
/**
* Emitted when ok button was clicked
* or when Ok method is called.
*/
@Output() public alertOutput: EventEmitter<any> = new EventEmitter();
/**
* Emitted when cancel button was clicked
* or when cancel method is called.
*/
@Output() public cancelOutput: EventEmitter<any> = new EventEmitter();
@ViewChild('element') element: ElementRef;
constructor() {
}
ngOnInit() {
AlertModal.MODAL_COUNTER++;
this.id = 'modal-' + AlertModal.MODAL_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 an alert window creating backdrop.
*/
open() {
UIkit.modal(this.element.nativeElement).show();
}
/**
* ok method closes the modal and emits modalOutput.
*/
ok() {
if (!this.stayOpen) {
UIkit.modal(this.element.nativeElement).hide();
}
if (!this.choice) {
this.alertOutput.emit(true);
} else {
this.alertOutput.emit({
value: true,
choice: this.select
});
}
}
/**
* cancel method closes the modal.
*/
cancel() {
UIkit.modal(this.element.nativeElement).hide();
this.cancelOutput.emit(true);
}
}

View File

@ -1,18 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import {AlertModal} from './alert';
import {ModalModule} from './modal.module';
import {IconsModule} from "../icons/icons.module";
@NgModule({
imports: [CommonModule, FormsModule, ModalModule, IconsModule],
declarations: [
AlertModal
],
exports: [
AlertModal
]
})
export class AlertModalModule { }

View File

@ -1,144 +0,0 @@
import {
AfterViewInit, ChangeDetectorRef,
Component,
ElementRef,
EventEmitter, HostListener,
Input,
OnDestroy,
OnInit,
Output,
ViewChild
} from "@angular/core";
import {fromEvent, Subscription} from 'rxjs';
import {delay} from "rxjs/operators";
import {HelperFunctions} from "../../HelperFunctions.class";
declare var UIkit;
declare var ResizeObserver;
@Component({
selector: 'fs-modal',
template: `
<div #modal class="uk-modal-full" [id]="id" uk-modal="container: #modal-container">
<div class="uk-modal-dialog">
<div #header class="uk-modal-header uk-flex uk-flex-middle" [ngClass]="classTitle">
<div [class.uk-invisible]="!back" class="uk-width-medium@l uk-width-auto uk-flex uk-flex-center">
<button class="uk-button uk-button-link" [disabled]="!back" (click)="cancel()">
<icon name="west" [flex]="true" ratio="3"></icon>
</button>
</div>
<div [class.uk-invisible]="!title"
class="uk-width-expand uk-padding-small uk-padding-remove-vertical uk-flex uk-flex-center">
<h2 class="uk-margin-remove">{{title}}</h2>
</div>
<div class="uk-width-medium@l uk-width-auto uk-flex" [class.uk-flex-center]="okButton" [class.uk-flex-right]="!okButton">
<button *ngIf="okButton" class="uk-button uk-button-default" [disabled]="okButtonDisabled"
[class.uk-disabled]="okButtonDisabled" (click)="ok()">
{{okButtonText}}
</button>
<button *ngIf="!okButton" class="uk-close uk-icon" (click)="cancel()">
<icon name="close" ratio="2"></icon>
</button>
</div>
</div>
<div #body class="uk-modal-body uk-overflow-auto" [ngStyle]="{'height.px': bodyHeight}">
<div class="uk-container uk-height-1-1" [ngClass]="classBody">
<ng-content></ng-content>
</div>
</div>
</div>
</div>
`
})
export class FullScreenModalComponent implements AfterViewInit, OnDestroy {
private static FS_MODAL_COUNTER: number = 0;
id: string = "fs-modal";
@Input() classTitle: string = "uk-background-primary uk-light";
@Input() classBody: string = 'uk-container-large';
back: boolean = false;
title: string;
okButton: boolean = false;
okButtonText = 'OK';
@Input()
okButtonDisabled = false;
@Output()
okEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
@Output()
cancelEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
@ViewChild('modal') modal: ElementRef;
@ViewChild('header') header: ElementRef;
@ViewChild('body') body: ElementRef;
observer: any;
headerHeight: number;
bodyHeight: number;
constructor(private cdr: ChangeDetectorRef) {
}
@HostListener('window:resize', ['$event'])
onResize() {
this.changeHeight();
}
ngOnInit() {
FullScreenModalComponent.FS_MODAL_COUNTER++;
this.id = 'fs-modal-' + FullScreenModalComponent.FS_MODAL_COUNTER;
}
ngAfterViewInit() {
if(typeof window !== "undefined") {
this.observer = new ResizeObserver(entries => {
for (let entry of entries) {
this.changeHeight();
}
});
this.observer.observe(this.header.nativeElement);
}
}
/* Height = Viewport - header - (Body padding) */
changeHeight() {
if(typeof window !== "undefined" && this.header) {
this.bodyHeight = window.innerHeight - this.header.nativeElement.clientHeight - 80;
this.cdr.detectChanges();
}
}
ngOnDestroy() {
if(this.observer && this.observer instanceof ResizeObserver) {
this.observer.disconnect();
}
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();
}
}
}
}
get isOpen() {
return this.modal && UIkit.modal(this.modal.nativeElement).isToggled();
}
open() {
UIkit.modal(this.modal.nativeElement).show();
HelperFunctions.scroll();
}
cancel() {
UIkit.modal(this.modal.nativeElement).hide();
HelperFunctions.scroll();
this.cancelEmitter.emit();
}
ok() {
UIkit.modal(this.modal.nativeElement).hide();
HelperFunctions.scroll();
this.okEmitter.emit(true);
}
}

View File

@ -1,12 +0,0 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {FullScreenModalComponent} from "./full-screen-modal.component";
import {IconsModule} from "../../icons/icons.module";
@NgModule({
imports: [CommonModule, IconsModule],
declarations: [FullScreenModalComponent],
exports: [FullScreenModalComponent]
})
export class FullScreenModalModule {
}

View File

@ -1,61 +0,0 @@
import {Component, ViewEncapsulation, ComponentRef, ElementRef, Input, EventEmitter, Output} from '@angular/core';
@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" >
<div class="uk-modal-dialog" role="">
<!--div class="modal-content"-->
<div class="uk-modal-body">
<div >
<h4 class="text-center" >{{message}}</h4>
<!-- <div class="uk-spinner"></div>-->
<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-->
</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>
</div>
</div-->
`,
encapsulation: ViewEncapsulation.None,
})
/**
* API to an open alert window.
*/
export class ModalLoading{
@Input() public message:string ="Loading";
/**
* if the value is true alert will be visible or else it will be hidden.
*/
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){}
/**
* Opens a alert window creating backdrop.
*/
open(){
this.isOpen= true;
}
close(){
this.isOpen = false;
}
}

View File

@ -1,19 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import {ModalLoading} from './loading.component';
import {ModalModule} from './modal.module';
//helpers
@NgModule({
imports: [ CommonModule, FormsModule,ModalModule ],
declarations: [
ModalLoading
],
exports: [
ModalLoading
]
})
export class LoadingModalModule { }

View File

@ -1,15 +0,0 @@
/* common components of modal components */
import {NgModule} from '@angular/core';
import {Open} from './open.component';
@NgModule({
imports: [],
declarations: [
Open
],
exports: [
Open
]
})
export class ModalModule {
}

View File

@ -1,57 +0,0 @@
import {Directive, Input, HostBinding} from '@angular/core';
// todo: add animate
// todo: add init and on change
@Directive({selector: '[open]'})
export class Open {
@HostBinding('style.display')
public display:string;
@HostBinding('class.in')
@HostBinding('attr.aria-expanded')
public isExpanded:boolean = true;
@Input()
public set open(value:boolean) {
this.isExpanded = value;
this.toggle();
}
public get open():boolean {
return this.isExpanded;
}
constructor() {
}
init() {
this.isExpanded = false;
this.display = 'none';
}
toggle() {
if (this.isExpanded) {
this.hide();
} else {
this.show();
}
}
hide() {
this.isExpanded = false;
this.display = 'none';
if (typeof document !== 'undefined') {
let backDrop = document.getElementsByClassName("modal-backdrop");
if(backDrop.length>0){
document.body.removeChild(backDrop[0]);
}
}
}
show() {
if (typeof document !== 'undefined') {
// let backDrop = document.createElement('div');
// backDrop.className="modal-backdrop fade in";
// document.body.appendChild(backDrop);
}
this.isExpanded = true;
this.display = 'block';
}
}

View File

@ -1,455 +0,0 @@
import {UrlSegment} from '@angular/router';
import {AbstractControl, UntypedFormGroup, ValidationErrors, ValidatorFn, Validators} from "@angular/forms";
export class Dates {
public static yearMin = 1800;
public static yearMax = (new Date().getFullYear()) + 10;
public static currentYear = (new Date().getFullYear());
public static isValidYear(yearString, yearMin = this.yearMin, yearMax = this.yearMax) {
// First check for the pattern
if (!/^\d{4}$/.test(yearString))
return false;
var year = parseInt(yearString, 10);
// Check the ranges of month and year
return !(year < yearMin || year > yearMax);
}
//format YYYY-MM-DD
public static isValidDate(dateString: string) {
// First check for the pattern
if (!/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(dateString))
return false;
// Parse the date parts to integers
var parts = dateString.split("-");
var day = parseInt(parts[2], 10);
var month = parseInt(parts[1], 10);
var year = parseInt(parts[0], 10);
if (!this.isValidYear(parts[0])) {
return false;
}
// Check the ranges of month and year
if (month == 0 || month > 12)
return false;
var monthLength = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// Adjust for leap years
if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
monthLength[1] = 29;
// Check the range of the day
return day > 0 && day <= monthLength[month - 1];
}
public static getDateToday(): Date {
var myDate = new Date();
return myDate;
}
public static getDateToString(myDate: Date): string {
var date: string = myDate.getFullYear() + "-";
date += ((myDate.getMonth() + 1) < 10) ? "0" + (myDate.getMonth() + 1) : (myDate.getMonth() + 1);
date += "-";
date += (myDate.getDate() < 10) ? "0" + myDate.getDate() : myDate.getDate();
return date;
}
public static getDateXMonthsAgo(x: number): Date {
var myDate = new Date();
myDate.setMonth(myDate.getMonth() - x);
return myDate;
}
public static getDateXYearsAgo(x: number): Date {
var myDate = new Date();
myDate.setFullYear(myDate.getFullYear() - x);
return myDate;
}
public static getDateFromString(date: string): Date {
var myDate = new Date();
myDate.setFullYear(+date.substring(0, 4));
myDate.setMonth(((date.length > 5) ? (+date.substring(5, 7) - 1) : (0)));
myDate.setDate(((date.length > 8) ? (+date.substring(8, 11)) : (1)));
return myDate;
}
public static getDate(dateString: string): Date {
let date = new Date(dateString);
if (Object.prototype.toString.call(date) === "[object Date]") {
if (isNaN(date.getTime())) {
return null;
} else {
return date;
}
} else {
return null;
}
}
public static timeSince(date: Date) {
let seconds = Math.floor((new Date().getTime() - new Date(date).getTime()) / 1000);
let interval = seconds / (365*24*60*60);
if (interval > 1) {
let years = Math.floor(interval);
return (years > 1?(years + ' years ago'):'a year ago');
}
interval = seconds / (7*24*60*60);
if (interval > 1) {
let weeks = Math.floor(interval);
return (weeks > 1?(weeks + ' weeks ago'):'a week ago');
}
interval = seconds / (24*60*60);
if (interval > 1) {
let days = Math.floor(interval);
return (days > 1?(days + ' days ago'):'a day ago');
}
interval = seconds / (60*60);
if (interval > 1) {
let hours = Math.floor(interval);
return (hours > 1?(hours + ' hours ago'):'an hour ago');
}
interval = seconds / 60;
if (interval > 1) {
let minutes = Math.floor(interval);
return (minutes > 1?(minutes + ' minutes ago'):'a minute ago');
}
seconds = Math.floor(interval);
return (seconds > 1?(seconds + ' seconds ago'):' just now');
}
}
export class DOI {
public static getDOIsFromString(str: string): string[] {
return Identifier.getDOIsFromString(str);
}
public static isValidDOI(str: string): boolean {
return Identifier.isValidDOI(str);
}
}
export class Identifier {
class: "doi" | "pmc" | "pmid" | "handle" | "ORCID" | "re3data" = null;
id: string;
public static getDOIsFromString(str: string): string[] {
var DOIs: string[] = [];
var words: string[] = str.split(" ");
for (var i = 0; i < words.length; i++) {
let id = words[i];
if (DOI.isValidDOI(id) ) {
id = Identifier.getRawDOIValue(id);
if( DOIs.indexOf(id) == -1){
DOIs.push(id);
}
}
}
return DOIs;
}
public static getRawDOIValue(id: string): string {
if(id.indexOf("doi.org")!=-1 && id.split("doi.org/").length > 1){
id = id.split("doi.org/")[1];
}
return id;
}
public static getIdentifiersFromString(str: string): Identifier[] {
let identifiers: Identifier[] = [];
let words: string[] = str.split(" ");
for (let id of words) {
if (id.length > 0) {
let identifier: Identifier = this.getIdentifierFromString(id);
if (identifier) {
identifiers.push(identifier);
}
}
}
return identifiers;
}
public static getIdentifierFromString(pid: string,strict:boolean = true): Identifier {
if (Identifier.isValidDOI(pid)) {
pid = Identifier.getRawDOIValue(pid);
return {"class": "doi", "id": pid};
} else if (Identifier.isValidORCID(pid)) {
return {"class": "ORCID", "id": pid};
} else if (Identifier.isValidPMCID(pid)) {
return {"class": "pmc", "id": pid};
} else if (Identifier.isValidPMID(pid)) {
return {"class": "pmid", "id": pid};
} else if (Identifier.isValidHANDLE(pid)) {
return {"class": "handle", "id": pid};
} else if (Identifier.isValidRe3Data(pid)) {
return {"class": "re3data", "id": pid};
}
//set it as a doi, to catch the case that doi has not valid format
return (strict?null:{"class": "doi", "id": pid});
}
public static getPIDFromIdentifiers(identifiers: Map<string, string[]>): Identifier {
let classes:string [] = ["doi", "handle", "pmc", "pmid", "re3data"];
if(identifiers) {
for (let cl of classes) {
if (identifiers.get(cl)) {
for (let pid of identifiers.get(cl)) {
let identifier = Identifier.getIdentifierFromString(pid);
if (identifier) {
return identifier;
}
}
}
}
}
return null;
}
public static isValidDOI(str: string): boolean {
//keep only exp3?
let exp1 = /\b(10[.][0-9]{4,}(?:[.][0-9]+)*\/(?:(?!["&\'<>])\S)+)\b/g;
let exp2 = /\b(10[.][0-9]{4,}(?:[.][0-9]+)*\/(?:(?!["&\'<>])[[:graph:]])+)\b/g;
let exp3 = /\b(10[.]*)\b/g;
return (str.match(exp1) != null || str.match(exp2) != null || str.match(exp3) != null);
}
public static isValidORCID(str: string): boolean {
let exp = /\b\d{4}-\d{4}-\d{4}-(\d{3}X|\d{4})\b/g;
return str.match(exp) != null;
}
public static isValidPMID(str: string): boolean {
let exp = /^\d*$/g;
return str.match(exp) != null;
}
public static isValidPMCID(str: string): boolean {
let exp = /^(PMC\d{7})$/g;
return str.match(exp) != null;
}
public static isValidHANDLE(str: string): boolean {
let exp = /^[0-9a-zA-Z-]*\/[0-9a-zA-Z-]*$/g;
return str.match(exp) != null;
}
public static isValidRe3Data(str: string): boolean {
let exp = /(r3d[1-9]\d{0,8})/g;
return str.match(exp) != null;
}
}
export class StringUtils {
public static urlRegex = 'https?:\\/\\/(?:www(2?)\\.|(?!www(2?)))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www(2?)\\.' +
'[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?:\\/\\/(?:www(2?)\\.|(?!www(2?)))[a-zA-Z0-9]+\\.[^\\s]{2,}|www(2?)\\.' +
'[a-zA-Z0-9]+\\.[^\\s]{2,}';
public static routeRegex = '^[a-zA-Z0-9\/][a-zA-Z0-9\/-]*$';
public static jsonRegex = /^[\],:{}\s]*$/;
public static urlPrefix(url: string): string {
if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("//")) {
return "";
} else {
return "//";
}
}
public static quote(params: string): string {
return '"' + params + '"';
}
public static unquote(params: string): string {
if (params.length > 2 && (params[0] == '"' && params[params.length - 1] == '"') || (params[0] == "'" && params[params.length - 1] == "'")) {
params = params.substring(1, params.length - 1);
}
return params;
}
public static URIEncode(params: string): string {
return encodeURIComponent(params);
}
public static URIDecode(params: string): string {
return decodeURIComponent(params);
}
public static validateEmails(emails: string): boolean {
return (emails.split(',')
.map(email => Validators.email(<AbstractControl>{value: email.trim()}))
.find(_ => _ !== null) === undefined);
}
public static b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
private emailValidator(email: any): boolean {
return !!email.match("^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$");
}
public static isValidUrl(url: string): boolean {
return new RegExp(this.urlRegex).test(url);
}
public static urlValidator(): ValidatorFn {
return Validators.pattern(StringUtils.urlRegex);
}
public static jsonValidator(error: string = ''): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if(control.value) {
let test = control.getRawValue().replace(/\\["\\\/bfnrtu]/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, '');
if(!new RegExp(this.jsonRegex).test(test)) {
return {error: 'Please provide a valid JSON.' + error}
}
}
return null;
};
}
public static validatorType(options: string[]): ValidatorFn {
return (control: AbstractControl): { [key: string]: boolean } | null => {
if (options.filter(type => type === control.value).length === 0) {
return {'type': false};
}
return null;
}
}
public static validRoute(pages: any[], field: string, initial: string = null): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if(control.value) {
if(!new RegExp(this.routeRegex).test(control.value)) {
return {error: 'Route should contain only letters or numbers, e.g /route or route'}
}
if(pages && pages.length > 0 && control.value !== initial) {
const forbidden = pages.filter(page => page[field].replace('/', '') === control.value.replace('/', '')).length > 0;
return forbidden ? {error: 'This route is used by an other page'} : null;
}
}
return null;
};
}
public static sliceString(mystr, size: number): string {
const sliced = String(mystr).substr(0, size);
return sliced + (String(mystr).length > size ? '...' : '');
}
/**
* Splits a text to words base on a list of separators. Returns the words of the text including the separators.
* DO NOT TOUCH, IT WORKS
*
* @param text
* @param separators
*/
public static split(text: string, separators: string[]): string[] {
let words: (string | string[])[] = [text];
separators.forEach(separator => {
words.forEach((word, index) => {
if (typeof word === "string" && separators.indexOf(word) === -1) {
let tokens: string[] = word.split(separator).filter(value => value !== '');
if (tokens.length > 1) {
words[index] = [];
tokens.forEach((token, i) => {
(<string[]>(words[index])).push(token);
if (i !== (tokens.length - 1)) {
(<string[]>(words[index])).push(separator);
}
});
}
}
});
words = [].concat.apply([], words);
});
return <string []>words;
}
public static capitalize(value: string): string {
return value.charAt(0).toUpperCase() + value.slice(1);
}
/**
* Checks if a text contains a word
*/
public static containsWord(text: string, word: string): boolean {
return (text && text.toLowerCase().includes(word));
}
public static URLSegmentsToPath(segments: UrlSegment[]): string {
let path = '';
segments.forEach(route => {
path += '/' + route.path;
})
return path;
}
public static isEuropeanCountry(country: string) {
let countries = ["Albania", "Andorra", "Armenia", "Austria", "Azerbaijan", "Belarus", "Belgium", "Bosnia and Herzegovina",
"Bulgaria", "Croatia", "Cyprus", "Czech Republic", "Denmark", "Estonia", "Finland", "France", "Georgia", "Germany", "Greece", "Hungary", "Iceland", "Ireland",
"Italy", "Kosovo", "Latvia", "Liechtenstein", "Lithuania", "Luxembourg", "Macedonia", "Malta", "Moldova", "Monaco", "Montenegro", "The Netherlands", "Norway", "Poland",
"Portugal", "Romania", "Russia", "San Marino", "Serbia", "Slovakia", "Slovenia", "Spain", "Sweden", "Switzerland", "Turkey", "Ukraine", "United Kingdom", "Vatican City",
];
return (country && countries.indexOf(country) != -1);
}
public static isOpenAIREID(id: string) {
if (id && id.length == 46) {
let exp1 = /^.{12}::([0-9a-z]{32})$/g;
return (id.match(exp1) != null);
}
return false;
}
public static HTMLToString( html:string){
try {
html = html.replace(/&nbsp;/g, ' ');
html = html.replace(/(\r\n|\n|\r| +(?= ))|\s\s+/gm, " ");
html = html.replace(/<[^>]*>/g, '');
}catch( e){
}
return html;
}
public static inValidYearValidator(minYear, maxYear): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
return ((control.value && !Dates.isValidYear(control.value, minYear, maxYear)) ?
{error: 'Year must be between ' + minYear + ' and ' + maxYear + '.'} : null);
};
}
public static fromYearAfterToYearValidator: ValidatorFn = (control: UntypedFormGroup): ValidationErrors | null => {
const yearFrom = control.get('yearFrom');
const yearTo = control.get('yearTo');
return ((yearFrom && yearTo && (parseInt(yearFrom.value, 10) > parseInt(yearTo.value, 10))) ?
{error: 'Starting year must be greater than or equal to ending year.' } : null);
}
public static rangeRequired( enabled:boolean): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const yearFrom = control.get('yearFrom');
const yearTo = control.get('yearTo');
return ((yearFrom && yearTo && enabled && (yearFrom.value == "" || yearTo.value == "")) ? { error: 'Both starting and ending year are required' } : null);
};
}
}