Merge remote-tracking branch 'origin/angular-14' into data-transfer-v2
This commit is contained in:
commit
b34f1cdfbf
|
@ -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">
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,11 +55,11 @@
|
|||
Bulk Actions ({{getSelectedPortals().length}})
|
||||
</button>
|
||||
<div uk-dropdown="mode: click">
|
||||
<ul class="uk-nav uk-dropdown-nav"
|
||||
<ul class="uk-nav uk-dropdown-nav uk-text-capitalize"
|
||||
[attr.uk-tooltip]="getSelectedPortals().length == 0 ? 'pos:left; cls: uk-active' : 'cls: uk-invisible'"
|
||||
title="Select at least one entity">
|
||||
<li>
|
||||
<a (click)="confirmDeleteSelectedPortals()"><i></i>Delete</a>
|
||||
<a (click)="confirmDeleteSelectedPortals()">Delete</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -67,6 +67,7 @@
|
|||
</th>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Piwik</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -81,6 +82,9 @@
|
|||
<td>
|
||||
<div class="type" href="#">{{check.portal.type}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="name" href="#">{{check.portal.piwik}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="uk-flex uk-flex-middle">
|
||||
<icon class="clickable" [flex]="true" name="edit" [customClass]="'uk-text-primary'" (click)="editPortal(i)"></icon>
|
||||
|
|
|
@ -229,11 +229,11 @@ export class PortalsComponent implements OnInit {
|
|||
|
||||
public filterByType(portal: Portal): boolean {
|
||||
let type = this.filterForm.get("type").value;
|
||||
return type == "all" || (type == portal.type);
|
||||
return type == "all" || (type === portal.type);
|
||||
}
|
||||
|
||||
public filterPortals(portal: Portal): boolean {
|
||||
return this.searchText.toString() === '' || (portal.name || portal.type).match(this.searchText) != null;
|
||||
return this.searchText.toString() === '' || (portal.name + portal.type + portal.pid).match(this.searchText) != null;
|
||||
}
|
||||
|
||||
handleUpdateError(message: string, error = null) {
|
||||
|
|
|
@ -2,14 +2,15 @@ import {
|
|||
AfterViewInit,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef, Inject,
|
||||
ElementRef,
|
||||
Inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit, PLATFORM_ID,
|
||||
OnInit,
|
||||
PLATFORM_ID,
|
||||
ViewChild
|
||||
} from "@angular/core";
|
||||
import {LayoutService} from "../sidebar/layout.service";
|
||||
import {Subscription} from "rxjs";
|
||||
|
||||
declare var UIkit;
|
||||
declare var ResizeObserver;
|
||||
|
@ -18,29 +19,27 @@ declare var ResizeObserver;
|
|||
selector: '[page-content]',
|
||||
template: `
|
||||
<div id="page_content">
|
||||
<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-hidden]="!isBrowser" id="page_content_sticky_footer" #sticky_footer
|
||||
class="uk-tile-default uk-blur-background">
|
||||
<div class="uk-container uk-container-large">
|
||||
<div class="uk-padding-small uk-padding-remove-vertical">
|
||||
<div [ngClass]="!isMobile?'uk-padding-small uk-padding-remove-vertical':''">
|
||||
<ng-content select="[sticky_footer]"></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="page_content_header" #header class="uk-blur-background"
|
||||
[attr.uk-sticky]="(headerSticky && shouldSticky)?'media: @m':null" [attr.offset]="offset"
|
||||
<div id="page_content_header" #header class="uk-blur-background" [class.uk-border-bottom]="border && isStickyActive"
|
||||
[attr.style]="'margin-top: '+(footer_height? '-'+footer_height+'px': '0')">
|
||||
<div class="uk-container uk-container-large">
|
||||
<div class="uk-padding-small uk-padding-remove-vertical uk-padding-remove-right">
|
||||
<div [ngClass]="!isMobile?'uk-padding-small uk-padding-remove-vertical uk-padding-remove-right':''">
|
||||
<div class="header">
|
||||
<ng-content select="[header]"></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="page_content_actions" #actions class="uk-blur-background"
|
||||
[attr.uk-sticky]="(!headerSticky && shouldSticky)?'media: @m':null" [attr.offset]="offset">
|
||||
<div id="page_content_actions" #actions class="uk-blur-background" [class.uk-border-bottom]="border && isStickyActive">
|
||||
<div class="uk-container uk-container-large">
|
||||
<div class="uk-padding-small uk-padding-remove-vertical uk-padding-remove-right">
|
||||
<div [ngClass]="!isMobile?'uk-padding-small uk-padding-remove-vertical uk-padding-remove-right':''">
|
||||
<div class="actions">
|
||||
<ng-content select="[actions]"></ng-content>
|
||||
</div>
|
||||
|
@ -48,13 +47,13 @@ declare var ResizeObserver;
|
|||
</div>
|
||||
</div>
|
||||
<div id="page_content_inner" class="uk-container uk-container-large">
|
||||
<div class="uk-padding-small uk-padding-remove-vertical">
|
||||
<div [ngClass]="!isMobile?'uk-padding-small uk-padding-remove-vertical':''">
|
||||
<ng-content select="[inner]"></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
<div id="page_content_footer" #footer>
|
||||
<div class="uk-container uk-container-large">
|
||||
<div class="uk-padding-small uk-padding-remove-vertical">
|
||||
<div [ngClass]="!isMobile?'uk-padding-small uk-padding-remove-vertical':''">
|
||||
<ng-content select="[footer]"></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -65,47 +64,65 @@ declare var ResizeObserver;
|
|||
export class PageContentComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
@Input()
|
||||
public headerSticky: boolean = false;
|
||||
@Input()
|
||||
public border: boolean = true;
|
||||
public offset: number;
|
||||
public shouldSticky: boolean = true;
|
||||
public isMobile: boolean = false;
|
||||
@ViewChild('header') header: ElementRef;
|
||||
@ViewChild('actions') actions: ElementRef;
|
||||
public footer_offset: number = 0;
|
||||
public footer_height: number = 0;
|
||||
@ViewChild("sticky_footer") sticky_footer;
|
||||
@ViewChild("sticky_footer") sticky_footer: ElementRef;
|
||||
private sticky = {
|
||||
header: null,
|
||||
footer: null
|
||||
}
|
||||
public isStickyActive: boolean = false;
|
||||
subscriptions = [];
|
||||
|
||||
|
||||
constructor(private layoutService: LayoutService, private cdr: ChangeDetectorRef,
|
||||
@Inject(PLATFORM_ID) private platformId) {
|
||||
}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
if (typeof document !== "undefined") {
|
||||
this.offset = Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--header-height'));
|
||||
this.stickyBugWorkaround();
|
||||
}
|
||||
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
|
||||
this.isMobile = isMobile;
|
||||
this.cdr.detectChanges();
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
return UIkit.sticky(sticky).isActive;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (typeof document !== "undefined") {
|
||||
// TODO make it smooth
|
||||
// this.observeBottom();
|
||||
this.observeHeader();
|
||||
this.observeStickyFooter();
|
||||
if (this.shouldSticky && typeof document !== 'undefined') {
|
||||
this.sticky.header = UIkit.sticky((this.headerSticky ? this.header.nativeElement : this.actions.nativeElement), {
|
||||
media: '@m',
|
||||
offset: this.offset
|
||||
});
|
||||
this.subscriptions.push(UIkit.util.on(document, 'active', '#' + this.sticky.header.$el.id, () => {
|
||||
this.isStickyActive = true;
|
||||
this.cdr.detectChanges();
|
||||
}));
|
||||
this.subscriptions.push(UIkit.util.on(document, 'inactive', '#' + this.sticky.header.$el.id, () => {
|
||||
this.isStickyActive = false;
|
||||
this.cdr.detectChanges();
|
||||
}));
|
||||
}
|
||||
if (this.sticky_footer) {
|
||||
let footer_offset = this.calcStickyFooterOffset(this.sticky_footer.nativeElement);
|
||||
this.sticky.footer = UIkit.sticky(this.sticky_footer.nativeElement, {bottom: true, offset: footer_offset});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach(subscription => {
|
||||
if (subscription instanceof (ResizeObserver || IntersectionObserver)) {
|
||||
|
@ -113,13 +130,48 @@ export class PageContentComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterContentChecked() {
|
||||
if (this.sticky_footer && typeof document !== 'undefined') {
|
||||
this.footer_offset = this.calcStickyFooterOffset(this.sticky_footer.nativeElement);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Workaround for sticky not update bug when sidebar is toggled.
|
||||
* TODO when UIKit will be updated => remove
|
||||
*
|
||||
* */
|
||||
stickyBugWorkaround() {
|
||||
let sidebarOffset = Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--dashboard-sidebar-width')) -
|
||||
Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--dashboard-sidebar-mini-width'));
|
||||
let transitionDelay = Number.parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--dashboard-transition-delay')) * 1000;
|
||||
this.subscriptions.push(this.layoutService.isOpen.subscribe(isOpen => {
|
||||
if (this.sticky.header) {
|
||||
if (isOpen) {
|
||||
this.sticky.header.$el.style.width = Number.parseInt(this.sticky.header.$el.style.width) - sidebarOffset + 'px';
|
||||
} else {
|
||||
this.sticky.header.$el.style.width = Number.parseInt(this.sticky.header.$el.style.width) + sidebarOffset + 'px';
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.sticky.header.$emit();
|
||||
}, transitionDelay);
|
||||
}
|
||||
if (this.sticky.footer) {
|
||||
if (isOpen) {
|
||||
this.sticky.footer.$el.style.width = Number.parseInt(this.sticky.footer.$el.style.width) - sidebarOffset + 'px';
|
||||
} else {
|
||||
this.sticky.footer.$el.style.width = Number.parseInt(this.sticky.footer.$el.style.width) + sidebarOffset + 'px';
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.sticky.footer.$emit();
|
||||
}, transitionDelay);
|
||||
}
|
||||
this.cdr.detectChanges();
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* Should be smooth
|
||||
*
|
||||
* */
|
||||
private observeBottom() {
|
||||
let bottom = document.getElementById('bottom');
|
||||
if (bottom) {
|
||||
|
@ -132,12 +184,15 @@ export class PageContentComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
bottomObs.observe(bottom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* */
|
||||
private observeHeader() {
|
||||
if (this.header) {
|
||||
let headerObs = new IntersectionObserver(entries => {
|
||||
entries.forEach(entry => {
|
||||
if(entry.boundingClientRect.height > 0) {
|
||||
if (entry.boundingClientRect.height > 0) {
|
||||
this.layoutService.setReplaceHeader(!entry.isIntersecting);
|
||||
}
|
||||
})
|
||||
|
@ -146,13 +201,13 @@ export class PageContentComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
headerObs.observe(this.header.nativeElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private observeStickyFooter() {
|
||||
if (this.sticky_footer) {
|
||||
let resizeObs = new ResizeObserver(entries => {
|
||||
entries.forEach(entry => {
|
||||
setTimeout(() => {
|
||||
this.footer_offset = this.calcStickyFooterOffset(entry.target);
|
||||
this.sticky.footer.offset = this.calcStickyFooterOffset(entry.target);
|
||||
this.cdr.detectChanges();
|
||||
});
|
||||
})
|
||||
|
@ -161,7 +216,7 @@ export class PageContentComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
resizeObs.observe(this.sticky_footer.nativeElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
calcStickyFooterOffset(element) {
|
||||
this.footer_height = element.offsetHeight;
|
||||
return window.innerHeight - this.footer_height;
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
@ -41,6 +46,7 @@ export class LayoutService {
|
|||
private isFrontPageSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
/**
|
||||
* Add isSmallScreen: true on data of route config, if screen is small.
|
||||
* @deprecated
|
||||
*/
|
||||
private isSmallScreenSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
/**
|
||||
|
@ -155,7 +161,11 @@ export class LayoutService {
|
|||
}));
|
||||
this.setObserver();
|
||||
}
|
||||
|
||||
|
||||
get isOpen(): Observable<boolean> {
|
||||
return this.openSubject.asObservable();
|
||||
}
|
||||
|
||||
get open(): boolean {
|
||||
return this.openSubject.getValue();
|
||||
}
|
||||
|
@ -164,6 +174,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();
|
||||
}
|
||||
|
@ -216,10 +234,16 @@ export class LayoutService {
|
|||
this.replaceHeaderSubject.next(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* */
|
||||
get isSmallScreen(): boolean {
|
||||
return this.isSmallScreenSubject.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* */
|
||||
setSmallScreen(value: boolean) {
|
||||
this.isSmallScreenSubject.next(value);
|
||||
}
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
<aside id="sidebar_main">
|
||||
<div id="sidebar_content">
|
||||
<div *ngIf="items.length > 0" class="menu_section uk-margin-large-top" style="min-height: 30vh">
|
||||
<div sidebar-content>
|
||||
<div *ngIf="items.length > 0" class="menu_section mobile 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>
|
||||
<li [class.uk-active]="isTheActiveMenuItem(item)"
|
||||
[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">
|
||||
[queryParams]="item.route?item.params:null" [queryParamsHandling]="item.route?queryParamsHandling:null" 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>
|
||||
</div>
|
||||
<span [class.hide-on-close]="item.icon" class="uk-width-expand@l uk-text-truncate uk-margin-small-left">{{item.title}}</span>
|
||||
</a>
|
||||
<ul *ngIf="item.items?.length > 0 && (isBrowser || isTheActiveMenuItem(item))" class="uk-nav-sub">
|
||||
<li *ngFor="let subItem of item.items"
|
||||
|
@ -37,7 +34,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>
|
||||
|
|
|
@ -85,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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import {Component} 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);
|
||||
}
|
||||
}
|
|
@ -67,9 +67,11 @@
|
|||
<div class="uk-card-body">
|
||||
<span class="uk-text-bold uk-text-large">{{(showCurrent) ? item.email : item}}</span>
|
||||
</div>
|
||||
<div *ngIf="isCurator || !showCurrent" class="uk-card-footer uk-flex uk-flex-right">
|
||||
<button (click)="openDeleteModal(item)" class="uk-button uk-button-link uk-flex uk-flex-middle" [disabled]="role === 'member' && item.isManager"
|
||||
[attr.uk-tooltip]="(role === 'member' && item.isManager)?'This user is a manager and cannot be removed.':null">
|
||||
<div *ngIf="!showCurrent || role === 'member' || canDelete" class="uk-card-footer uk-flex uk-flex-right">
|
||||
<button (click)="openDeleteModal(item)" class="uk-button uk-button-link uk-flex uk-flex-middle"
|
||||
[disabled]="(role === 'member' && item.isManager) || isMe(item.id)"
|
||||
[attr.uk-tooltip]="(role === 'member' && item.isManager)?'This user is a manager and cannot be removed.':
|
||||
(isMe(item.id)?'You cannot remove yourself':null)">
|
||||
<icon name="delete" [flex]="true" type="filled"></icon>
|
||||
<span class="uk-margin-small-left uk-text-bold uk-text-uppercase">{{showCurrent ? 'Delete' : 'Cancel invitation'}}</span>
|
||||
</button>
|
||||
|
|
|
@ -11,6 +11,7 @@ import {StringUtils} from "../../../utils/string-utils.class";
|
|||
import {NotificationService} from "../../../notifications/notification.service";
|
||||
import {Subscription} from "rxjs";
|
||||
import {NotificationHandler} from "../../../utils/notification-handler";
|
||||
import {ClearCacheService} from "../../../services/clear-cache.service";
|
||||
|
||||
@Component({
|
||||
selector: 'role-users',
|
||||
|
@ -29,6 +30,8 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
|
|||
@Input()
|
||||
public role: "member" | "manager" = "manager";
|
||||
@Input()
|
||||
public deleteAuthorizationLevel: 'curator' | 'manager' = 'curator';
|
||||
@Input()
|
||||
public message: string = null;
|
||||
@Input()
|
||||
public emailComposer: Function;
|
||||
|
@ -63,6 +66,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
|
|||
|
||||
constructor(private userRegistryService: UserRegistryService,
|
||||
private userManagementService: UserManagementService,
|
||||
private clearCacheService: ClearCacheService,
|
||||
private notificationService: NotificationService,
|
||||
private router: Router,
|
||||
private fb: UntypedFormBuilder) {
|
||||
|
@ -73,6 +77,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
|
|||
this.updateLists();
|
||||
this.userManagementService.getUserInfo().subscribe(user => {
|
||||
this.user = user;
|
||||
console.log(this.canDelete)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -196,6 +201,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
|
|||
}
|
||||
this.filterActiveBySearch(this.filterForm.value.active);
|
||||
this.userManagementService.updateUserInfo();
|
||||
this.clearCacheService.clearCache(this.role + 's of ' + this.id + ' have been updated');
|
||||
NotificationHandler.rise(this.selectedUser + ' <b>is no longer</b> ' + this.role + ' of ' + this.name + ' Dashboard');
|
||||
this.loadActive = false;
|
||||
}, error => {
|
||||
|
@ -267,6 +273,18 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
|
|||
});
|
||||
}
|
||||
|
||||
public get canDelete() {
|
||||
return (this.deleteAuthorizationLevel === 'curator'?this.isCurator:this.isManager);
|
||||
}
|
||||
|
||||
public isMe(userId: string) {
|
||||
return userId.includes(this.user.id) && !this.isCurator;
|
||||
}
|
||||
|
||||
public get isManager(): boolean {
|
||||
return this.isCurator || !!Session.isManager(this.type, this.id, this.user);
|
||||
}
|
||||
|
||||
public get isCurator(): boolean {
|
||||
return this.isPortalAdmin || !!Session.isCurator(this.type, this.user);
|
||||
}
|
||||
|
|
|
@ -142,9 +142,6 @@ export class UserMiniComponent implements OnInit, OnChanges {
|
|||
if (this.user) {
|
||||
this.userManagementService.logout();
|
||||
}
|
||||
this.loggedIn = false;
|
||||
this.isAuthorized = false;
|
||||
this.user = new User();
|
||||
}
|
||||
|
||||
logIn() {
|
||||
|
|
|
@ -94,7 +94,7 @@ declare var ResizeObserver;
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="uk-sticky uk-background-default uk-padding uk-padding-remove-horizontal" uk-sticky>
|
||||
<div class="uk-sticky uk-background-default uk-padding-small uk-padding-remove-right" uk-sticky>
|
||||
<slider-tabs type="scrollable" position="horizontal">
|
||||
<slider-tab tabId="entities_m" tabTitle="1. Entities"></slider-tab>
|
||||
<slider-tab tabId="inherited-and-inferred-attributes_m"
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -10,6 +10,7 @@ import {AlertModal} from "../utils/modal/alert";
|
|||
import {properties} from "../../../environments/environment";
|
||||
import {EmailService} from "../utils/email/email.service";
|
||||
import {Composer} from "../utils/email/composer";
|
||||
import {ClearCacheService} from "../services/clear-cache.service";
|
||||
|
||||
@Component({
|
||||
selector: 'role-verification',
|
||||
|
@ -65,7 +66,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 +88,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;
|
||||
|
@ -101,7 +107,8 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
|
|||
private fb: UntypedFormBuilder,
|
||||
private emailService: EmailService,
|
||||
private userManagementService: UserManagementService,
|
||||
private userRegistryService: UserRegistryService) {
|
||||
private userRegistryService: UserRegistryService,
|
||||
private clearCacheService: ClearCacheService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@ -190,6 +197,7 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
|
|||
public verifyManager() {
|
||||
this.loading = true;
|
||||
this.subscriptions.push(this.userRegistryService.verify(this.verification.id, this.code.value).subscribe(() => {
|
||||
this.clearCacheService.clearCache('Managers updated');
|
||||
this.managerModal.cancel();
|
||||
this.error = null;
|
||||
this.userManagementService.updateUserInfo(() => {
|
||||
|
@ -227,6 +235,7 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
|
|||
this.loading = true;
|
||||
if (!this.isMember) {
|
||||
this.subscriptions.push(this.userRegistryService.verify(this.verification.id, this.code.value, "member").subscribe(() => {
|
||||
this.clearCacheService.clearCache('Members updated');
|
||||
this.loading = false;
|
||||
this.error = null;
|
||||
this.userManagementService.updateUserInfo(() => {
|
||||
|
|
|
@ -124,7 +124,6 @@ export class UserManagementService {
|
|||
public logout() {
|
||||
this.setRedirectUrl();
|
||||
Session.removeUser();
|
||||
this.getUserInfoSubject.next(null);
|
||||
window.location.href = properties.logoutUrl + "?redirect=" + this.redirectUrl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,50 +14,52 @@ export class UserRegistryService {
|
|||
}
|
||||
|
||||
public createRole(type: string, id: string): Observable<any[]> {
|
||||
return this.http.post<any>(properties.registryUrl + 'create/' + encodeURIComponent(type) + '/' + encodeURIComponent(id), null,
|
||||
return this.http.post<any>(properties.registryUrl + 'create/' + type + '/' + id, null,
|
||||
CustomOptions.registryOptions()).pipe(map((response: any) => response.response));
|
||||
}
|
||||
|
||||
public getMembersCount(type: string, id: string): Observable<any> {
|
||||
return this.http.get(properties.registryUrl + encodeURIComponent(type) + '/' + encodeURIComponent(id) + '/members/count');
|
||||
let url = properties.registryUrl + type + '/' + id + '/members/count';
|
||||
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url);
|
||||
}
|
||||
|
||||
public subscribeTo(type: string, id: string): Observable<any> {
|
||||
return this.http.post(properties.registryUrl + 'subscribe/' + encodeURIComponent(type) + '/' + encodeURIComponent(id),
|
||||
return this.http.post(properties.registryUrl + 'subscribe/' + type + '/' + id,
|
||||
null, CustomOptions.registryOptions());
|
||||
}
|
||||
|
||||
public unsubscribeFrom(type: string, id: string): Observable<any> {
|
||||
return this.http.post(properties.registryUrl + 'unsubscribe/' + encodeURIComponent(type) + '/' + encodeURIComponent(id),
|
||||
return this.http.post(properties.registryUrl + 'unsubscribe/' + type + '/' + id,
|
||||
null, CustomOptions.registryOptions());
|
||||
}
|
||||
|
||||
public remove(type: string, id: string, email: string, role: "member" | "manager" = "manager"): Observable<any> {
|
||||
return this.http.delete<any>(properties.registryUrl +
|
||||
encodeURIComponent(type) + '/' + encodeURIComponent(id) + '/' + role + '/' + encodeURIComponent(email), CustomOptions.registryOptions());
|
||||
type + '/' + id + '/' + role + '/' + encodeURIComponent(email), CustomOptions.registryOptions());
|
||||
}
|
||||
|
||||
public invite(type: string, id: string, details: any, role: "member" | "manager" = "manager"): Observable<any[]> {
|
||||
return this.http.post<any>(properties.registryUrl + 'invite/' +
|
||||
encodeURIComponent(type) + '/' + encodeURIComponent(id) + '/' + role, details,
|
||||
type + '/' + id + '/' + role, details,
|
||||
CustomOptions.registryOptions()).pipe(map((response: any) => response.response));
|
||||
}
|
||||
|
||||
public verify(id: string, code: string, role: "member" | "manager" = "manager"): Observable<any> {
|
||||
return this.http.post<any>(properties.registryUrl + 'verification/' + role + '/' + encodeURIComponent(id), code, CustomOptions.registryOptions());
|
||||
return this.http.post<any>(properties.registryUrl + 'verification/' + role + '/' + id, code, CustomOptions.registryOptions());
|
||||
}
|
||||
|
||||
public getInvitation(id: string): Observable<any> {
|
||||
return this.http.get<any>(properties.registryUrl + 'verification/' + encodeURIComponent(id), CustomOptions.registryOptions())
|
||||
return this.http.get<any>(properties.registryUrl + 'verification/' + id, CustomOptions.registryOptions())
|
||||
.pipe(map((response: any) => response.response));
|
||||
}
|
||||
|
||||
public deleteVerification(id: string): Observable<any> {
|
||||
return this.http.delete<any>(properties.registryUrl + 'verification/' + encodeURIComponent(id), CustomOptions.registryOptions());
|
||||
return this.http.delete<any>(properties.registryUrl + 'verification/' + id, CustomOptions.registryOptions());
|
||||
}
|
||||
|
||||
public getActive(type: string, id: string, role: "member" | "manager" = "manager"): Observable<any[]> {
|
||||
return this.http.get<any>(properties.registryUrl + encodeURIComponent(type) + '/' + encodeURIComponent(id) + "/" + role + 's',
|
||||
let url = properties.registryUrl + type + '/' + id + "/" + role + 's';
|
||||
return this.http.get<any>((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url,
|
||||
CustomOptions.registryOptions()).pipe(map((response:any) => response.response), map(users => {
|
||||
if(users.length > 0 && !users[0].email) {
|
||||
return [];
|
||||
|
@ -68,13 +70,14 @@ export class UserRegistryService {
|
|||
}
|
||||
|
||||
public getPending(type: string, id: string, role: "member" | "manager" = "manager"): Observable<any[]> {
|
||||
return this.http.get<any>(properties.registryUrl + 'invite/' + encodeURIComponent(type) + '/' + encodeURIComponent(id) + "/" + role + 's/',
|
||||
let url = properties.registryUrl + 'invite/' +type + '/' +id + "/" + role + 's/';
|
||||
return this.http.get<any>((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url,
|
||||
CustomOptions.registryOptions()).pipe(map((response: any) => response.response));
|
||||
}
|
||||
|
||||
public cancelInvitation(type: string, id: string, email: string, role: "member" | "manager" = "manager"): Observable<any> {
|
||||
return this.http.delete<any>(properties.registryUrl + 'invite/' +
|
||||
encodeURIComponent(type) + '/' + encodeURIComponent(id) + '/' + role + '/' + encodeURIComponent(email),
|
||||
type + '/' + id + '/' + role + '/' + encodeURIComponent(email),
|
||||
CustomOptions.registryOptions());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
<div *ngIf="showMenu && activeHeader">
|
||||
<div id="main-menu-small" class="uk-hidden@m">
|
||||
<nav class="uk-navbar-container uk-navbar" uk-navbar="delay-hide: 400">
|
||||
<div
|
||||
*ngIf="(properties.environment =='beta' || properties.environment =='development') && showLogo && activeHeader.badge">
|
||||
<img class="uk-position-top-left"
|
||||
[src]="'assets/common-assets/'+(properties.environment =='beta'?'beta_flag.svg':'prototype_flag.svg')"
|
||||
alt="BETA" style="height: 60px; width: 60px;">
|
||||
</div>
|
||||
<div *ngIf="!onlyTop || userMenu" class="uk-navbar-left" [class.uk-light]='activeHeader.darkBg'>
|
||||
<a class="uk-navbar-toggle" href="#tm-mobile" uk-toggle>
|
||||
<div uk-navbar-toggle-icon="" class="uk-navbar-toggle-icon uk-icon custom-navbar-toggle-icon"></div>
|
||||
|
@ -177,7 +171,7 @@
|
|||
<user-mini *ngIf="userMenu" [user]="user"
|
||||
[userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl [logOutUrl]=properties.logoutUrl
|
||||
[cookieDomain]=properties.cookieDomain></user-mini>
|
||||
<div class="uk-visible@l">
|
||||
<div class="uk-visible@m">
|
||||
<ng-content select="[extra-m]"></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -320,7 +314,7 @@
|
|||
<img *ngIf="(mobile && activeHeader.logoSmallUrl) || (!mobile && activeHeader.logoUrl)"
|
||||
[src]="!mobile?activeHeader.logoUrl:activeHeader.logoSmallUrl"
|
||||
[alt]="activeHeader.title">
|
||||
<div *ngIf="activeHeader.logoInfo" [innerHTML]="activeHeader.logoInfo"></div>
|
||||
<div *ngIf="activeHeader.logoInfo && !mobile" [innerHTML]="activeHeader.logoInfo"></div>
|
||||
<ng-container *ngIf="(mobile && !activeHeader.logoSmallUrl) || (!mobile && !activeHeader.logoUrl)">
|
||||
<div class="multi-line-ellipsis lines-2" [style.max-width]="(!mobile)?'25vw':null" [title]="activeHeader.title">
|
||||
<p class="uk-margin-remove">{{activeHeader.title}}</p>
|
||||
|
@ -332,7 +326,7 @@
|
|||
<img *ngIf="(mobile && activeHeader.logoSmallUrl) || (!mobile && activeHeader.logoUrl)"
|
||||
[src]="!mobile?activeHeader.logoUrl:activeHeader.logoSmallUrl"
|
||||
[alt]="activeHeader.title">
|
||||
<div *ngIf="activeHeader.logoInfo" [innerHTML]="activeHeader.logoInfo"></div>
|
||||
<div *ngIf="activeHeader.logoInfo && !mobile" [innerHTML]="activeHeader.logoInfo"></div>
|
||||
<ng-container *ngIf="(mobile && !activeHeader.logoSmallUrl) || (!mobile && !activeHeader.logoUrl)">
|
||||
<div class="multi-line-ellipsis lines-2" [style.max-width]="(!mobile)?'25vw':null" [title]="activeHeader.title">
|
||||
<p class="uk-margin-remove">{{activeHeader.title}}</p>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import {Component, Input} from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: 'slider-arrow',
|
||||
template: `
|
||||
<div *ngIf="type" class="uk-slider-arrow" [ngClass]="positionClasses" [attr.uk-slider-item]="type">
|
||||
<button class="uk-icon-button uk-icon-button-small uk-box-no-shadow uk-box-no-shadow-hover uk-border">
|
||||
<icon [name]="icon" [flex]="true" visuallyHidden="download"></icon>
|
||||
</button>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class SliderArrowComponent {
|
||||
@Input()
|
||||
public type: 'previous' | 'next';
|
||||
|
||||
|
||||
get positionClasses() {
|
||||
return (this.type == 'previous')?'uk-position-center-left uk-slider-left':'uk-position-center-right uk-slider-right'
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return (this.type == 'previous')?'chevron_left':'chevron_right'
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {SliderArrowComponent} from "./slider-arrow.component";
|
||||
import {IconsModule} from "../../utils/icons/icons.module";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, IconsModule],
|
||||
declarations: [SliderArrowComponent],
|
||||
exports: [SliderArrowComponent]
|
||||
})
|
||||
export class SliderUtilsModule {}
|
|
@ -13,4 +13,12 @@ export class SliderTabComponent {
|
|||
public active: boolean = false;
|
||||
@Input()
|
||||
public disabled: boolean = false;
|
||||
@Input()
|
||||
public align: 'left' | 'right' = 'left';
|
||||
@Input()
|
||||
public routerLink: any[] | string | null | undefined = null;
|
||||
@Input()
|
||||
public queryParams: any = null;
|
||||
@Input()
|
||||
public customClass: string = '';
|
||||
}
|
||||
|
|
|
@ -20,35 +20,54 @@ declare var UIkit;
|
|||
template: `
|
||||
<div #sliderElement class="uk-position-relative" [class.uk-slider]="position === 'horizontal'"
|
||||
[ngClass]="customClass">
|
||||
<div [class.uk-slider-container-tabs]="position === 'horizontal'">
|
||||
<ul #tabsElement class="uk-tab" [class.uk-flex-nowrap]="position === 'horizontal'"
|
||||
<div [class.uk-slider-container-tabs]="position === 'horizontal'" [class.uk-border-bottom]="border && position === 'horizontal'">
|
||||
<ul #tabsElement [class.uk-flex-nowrap]="position === 'horizontal'"
|
||||
[class.uk-slider-items]="position === 'horizontal'"
|
||||
[class.uk-tab-left]="position === 'left'" [class.uk-tab-right]="position === 'right'"
|
||||
[attr.uk-tab]="type === 'static'?('connect:' + connect):null"
|
||||
[ngClass]="'uk-flex-' + flexPosition">
|
||||
[attr.uk-switcher]="type === 'static'?('connect:' + connect):null"
|
||||
[ngClass]="'uk-flex-' + flexPosition + ' ' + tabsClass">
|
||||
<ng-container *ngIf="type === 'static'">
|
||||
<li *ngFor="let tab of tabs.toArray()" class="uk-text-capitalize">
|
||||
<li *ngFor="let tab of leftTabs" class="uk-text-capitalize">
|
||||
<a>{{tab.title}}</a>
|
||||
</li>
|
||||
<li *ngFor="let tab of rightTabs; let i=index;"
|
||||
[ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''"
|
||||
class="uk-text-capitalize">
|
||||
<a [ngClass]="tab.customClass">{{tab.title}}</a>
|
||||
</li>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="type === 'dynamic'">
|
||||
<li *ngFor="let tab of leftTabs" [class.uk-active]="tab.active" class="uk-text-capitalize">
|
||||
<a [routerLink]="tab.routerLink" [queryParams]="tab.queryParams" [ngClass]="tab.customClass">{{tab.title}}</a>
|
||||
</li>
|
||||
<li *ngFor="let tab of rightTabs; let i=index;" [class.uk-active]="tab.active"
|
||||
[ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''"
|
||||
class="uk-text-capitalize">
|
||||
<a [routerLink]="tab.routerLink" [queryParams]="tab.queryParams" [ngClass]="tab.customClass">{{tab.title}}</a>
|
||||
</li>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="type === 'scrollable'">
|
||||
<li *ngFor="let tab of tabs.toArray()" class="uk-text-capitalize" [class.uk-active]="tab.active">
|
||||
<a routerLink="./" [fragment]="tab.id">{{tab.title}}</a>
|
||||
<li *ngFor="let tab of leftTabs" class="uk-text-capitalize" [class.uk-active]="tab.active">
|
||||
<a routerLink="./" [fragment]="tab.id" queryParamsHandling="merge" [ngClass]="tab.customClass">{{tab.title}}</a>
|
||||
</li>
|
||||
<li *ngFor="let tab of rightTabs; let i=index;" class="uk-text-capitalize"
|
||||
[ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''"
|
||||
[class.uk-active]="tab.active">
|
||||
<a routerLink="./" [fragment]="tab.id" queryParamsHandling="merge" [ngClass]="tab.customClass">{{tab.title}}</a>
|
||||
</li>
|
||||
</ng-container>
|
||||
</ul>
|
||||
</div>
|
||||
<a *ngIf="position === 'horizontal'" class="uk-position-center-left uk-blur-background" uk-slider-item="previous"><span
|
||||
uk-icon="chevron-left"></span></a>
|
||||
<a *ngIf="position === 'horizontal'" class="uk-position-center-right uk-blur-background" uk-slider-item="next"><span
|
||||
uk-icon="chevron-right"></span></a>
|
||||
<slider-arrow *ngIf="position === 'horizontal' && arrows" type="previous"></slider-arrow>
|
||||
<slider-arrow *ngIf="position === 'horizontal' && arrows" type="next"></slider-arrow>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class SliderTabsComponent implements AfterViewInit, OnDestroy {
|
||||
//TODO now it works only for scrollable and static, to be extended for dynamic
|
||||
/**
|
||||
* Type of tabs: Static = Uikit tabs with @connect class or selector, Dynamic = Active is defined by tabComponent.active input,
|
||||
* Type of tabs:
|
||||
* Static = Uikit tabs with @connect class or selector
|
||||
* Dynamic = Active is defined by tabComponent's active Input
|
||||
* Scrollable = Active is defined by the active fragment of URL and position of scroll
|
||||
* */
|
||||
@Input()
|
||||
|
@ -74,10 +93,19 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
|
|||
@Input()
|
||||
public flexPosition: 'center' | 'left' | 'right' = 'left';
|
||||
/**
|
||||
* Tabs custom class
|
||||
* Set a class above tabs
|
||||
* */
|
||||
@Input()
|
||||
public customClass: string;
|
||||
/**
|
||||
* Tabs class
|
||||
* */
|
||||
@Input()
|
||||
public tabsClass: string = 'uk-tab';
|
||||
@Input()
|
||||
public border: boolean = true;
|
||||
@Input()
|
||||
public arrows: boolean = true;
|
||||
@ContentChildren(SliderTabComponent) tabs: QueryList<SliderTabComponent>;
|
||||
@ViewChild('sliderElement') sliderElement: ElementRef;
|
||||
@ViewChild('tabsElement') tabsElement: ElementRef;
|
||||
|
@ -102,9 +130,12 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
|
|||
let slider = UIkit.slider(this.sliderElement.nativeElement, {finite: true});
|
||||
slider.clsActive = 'uk-slider-active';
|
||||
slider.updateActiveClasses();
|
||||
slider.slides.forEach(item => {
|
||||
item.classList.remove('uk-active');
|
||||
slider.slides.forEach((item, index) => {
|
||||
if(!this.tabs.get(index).active) {
|
||||
item.classList.remove('uk-active');
|
||||
}
|
||||
});
|
||||
console.log(slider);
|
||||
if (this.type === 'static') {
|
||||
let tabs = UIkit.tab(this.tabsElement.nativeElement, {connect: this.connect});
|
||||
tabs.show(this.activeIndex);
|
||||
|
@ -126,7 +157,7 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
|
|||
let index = event.detail[0].index();
|
||||
if (index !== this.activeIndex) {
|
||||
this.activeIndex = index;
|
||||
this.router.navigate(['./'], {relativeTo: this.route, fragment: this.connect.replace('#', '')});
|
||||
this.router.navigate(['./'], {relativeTo: this.route, fragment: this.connect.replace('#', ''), queryParamsHandling: "merge"});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -153,7 +184,8 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
|
|||
this.router.navigate(['./'], {
|
||||
fragment: entry.target.id,
|
||||
relativeTo: this.route,
|
||||
state: {disableScroll: true}
|
||||
state: {disableScroll: true},
|
||||
queryParamsHandling: 'merge'
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
|
@ -186,6 +218,14 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
|
|||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
get leftTabs(): SliderTabComponent[] {
|
||||
return this.tabs.toArray().filter(tab => tab.align === 'left');
|
||||
}
|
||||
|
||||
get rightTabs(): SliderTabComponent[] {
|
||||
return this.tabs.toArray().filter(tab => tab.align === 'right');
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach(subscription => {
|
||||
if (subscription instanceof Subscription) {
|
||||
|
|
|
@ -3,9 +3,10 @@ import {CommonModule} from "@angular/common";
|
|||
import {SliderTabsComponent} from "./slider-tabs.component";
|
||||
import {SliderTabComponent} from "./slider-tab.component";
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {SliderUtilsModule} from "../slider-utils/slider-utils.module";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, RouterModule],
|
||||
imports: [CommonModule, RouterModule, SliderUtilsModule],
|
||||
declarations: [SliderTabsComponent, SliderTabComponent],
|
||||
exports: [SliderTabsComponent, SliderTabComponent]
|
||||
})
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,38 +1,45 @@
|
|||
export enum Level {
|
||||
NONE,
|
||||
K,
|
||||
M,
|
||||
B
|
||||
}
|
||||
|
||||
|
||||
export interface NumberSize {
|
||||
number: number;
|
||||
size: "B" | "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 >= 1000000000) {
|
||||
num = num / 1000000;
|
||||
num = Math.round(num);
|
||||
roundNum = {number: num, size: "B", count: initialNum};
|
||||
} else 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
import {Pipe, PipeTransform} from "@angular/core";
|
||||
import {NumberSize, NumberUtils} from "../number-utils.class";
|
||||
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() {}
|
||||
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
transform(value: number): any {
|
||||
let size: NumberSize = NumberUtils.roundNumber(value);
|
||||
return this.decimalPipe.transform(size.number) + size.size;
|
||||
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>':'');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,14 +107,14 @@ export class ISVocabulariesService {
|
|||
|
||||
getLocalVocabularyFromService(vocabularyName: string, properties: EnvProperties): Observable<AutoCompleteValue[]> {
|
||||
if(vocabularyName == "sdg"){
|
||||
let url = properties.domain+"/assets/vocabulary/sdg.json";
|
||||
let url = properties.domain+"/assets/common-assets/vocabulary/sdg.json";
|
||||
return this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
|
||||
//.map(res => <any> res.json())
|
||||
.pipe(map(res => res['sdg']))
|
||||
.pipe(map(res => this.parseSDGs(res)))
|
||||
.pipe(catchError(this.handleError));
|
||||
}else if( vocabularyName == "fos"){
|
||||
let url = properties.domain+"/assets/vocabulary/fos.json";
|
||||
let url = properties.domain+"/assets/common-assets/vocabulary/fos.json";
|
||||
return this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
|
||||
//.map(res => <any> res.json())
|
||||
.pipe(map(res => res['fos']))
|
||||
|
|
Loading…
Reference in New Issue