Merge remote-tracking branch 'origin/develop' into angular-17

This commit is contained in:
Alex Martzios 2024-07-25 11:27:53 +03:00
commit 8a6f84000b
8 changed files with 286 additions and 326 deletions

View File

@ -6,7 +6,8 @@
<div class="section"> <div class="section">
<div *ngIf="isEditable" class="tools"> <div *ngIf="isEditable" class="tools">
<div class="uk-flex uk-flex-middle"> <div class="uk-flex uk-flex-middle">
<a *ngIf="isCurator" [class.uk-disabled]="editing" class="" (click)="createSection(i, 'number')" <a *ngIf="isCurator" [class.uk-disabled]="editing" class=""
(click)="createSection(i, 'number')"
uk-tooltip="Create a new section"> uk-tooltip="Create a new section">
<icon name="add" [flex]="true"></icon> <icon name="add" [flex]="true"></icon>
</a> </a>
@ -20,66 +21,67 @@
<div *ngIf="isEditable" input [formInput]="numberSections.at(i).get('title')" <div *ngIf="isEditable" input [formInput]="numberSections.at(i).get('title')"
(focusEmitter)="saveSection($event, numberSections.at(i), i, 'number')" (focusEmitter)="saveSection($event, numberSections.at(i), i, 'number')"
class="uk-width-1-3@m uk-width-1-1" placeholder="Title" inputClass="border-bottom"></div> class="uk-width-1-3@m uk-width-1-1" placeholder="Title" inputClass="border-bottom"></div>
<h5 *ngIf="!isEditable" class="uk-margin-remove">{{numberSections.at(i).get('title').value}}</h5> <h5 *ngIf="!isEditable"
class="uk-margin-remove">{{ numberSections.at(i).get('title').value }}</h5>
</div> </div>
<div [id]="'number-' + number._id" class="uk-grid uk-grid-small uk-grid-match" <div [id]="'number-' + number._id" class="uk-grid uk-grid-small uk-grid-match"
[attr.uk-sortable]="isEditable ? 'group: number': null" uk-grid> [attr.uk-sortable]="isEditable ? 'group: number': null" uk-grid>
<ng-template ngFor [ngForOf]="number.indicators" let-indicator let-j="index"> <div *ngFor="let indicator of number.indicators; let j=index" [id]="indicator._id"
<div *ngIf="indicator" [id]="indicator._id" [ngClass]="getNumberClassBySize(indicator.width)">
[ngClass]="getNumberClassBySize(indicator.width)"> <div class="uk-card uk-card-default uk-padding-small number-card uk-position-relative">
<div class="uk-card uk-card-default uk-padding-small number-card uk-position-relative"> <div *ngIf="!dragging"
<div *ngIf="!dragging" class="uk-position-top-right uk-margin-small-right uk-margin-small-top">
class="uk-position-top-right uk-margin-small-right uk-margin-small-top"> <icon *ngIf="!isEditable && showVisibility" [flex]="true"
<icon *ngIf="!isEditable && showVisibility" [flex]="true"
[name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)" [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)"
ratio="0.6"></icon> ratio="0.6"></icon>
<a *ngIf="isEditable && (isCurator || showVisibility)" class="uk-link-reset uk-flex uk-flex-middle" [class.uk-disabled]="editing"> <a *ngIf="isEditable && (isCurator || showVisibility)"
<icon *ngIf="showVisibility" [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)" ratio="0.6"></icon> class="uk-link-reset uk-flex uk-flex-middle" [class.uk-disabled]="editing">
<icon [flex]="true" name="more_vert"></icon> <icon *ngIf="showVisibility" [flex]="true"
</a> [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)"
<div #element *ngIf="isEditable && (isCurator || showVisibility)" class="uk-dropdown" ratio="0.6"></icon>
uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0"> <icon [flex]="true" name="more_vert"></icon>
<ul class="uk-nav uk-dropdown-nav"> </a>
<ng-container *ngIf="isCurator"> <div #element *ngIf="isEditable && (isCurator || showVisibility)"
<li> class="uk-dropdown"
<a (click)="editNumberIndicatorOpen(number, indicator._id); hide(element)">Edit</a> uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0">
</li> <ul class="uk-nav uk-dropdown-nav">
</ng-container> <ng-container *ngIf="isCurator">
<ng-container *ngIf="showVisibility"> <li>
<li *ngIf="isCurator" class="uk-nav-divider"></li> <a (click)="editNumberIndicatorOpen(number, indicator._id); hide(element)">Edit</a>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibilities" let-v> </li>
<li> </ng-container>
<a (click)="changeIndicatorStatus(number._id, indicator, v.value);hide(element)"> <ng-container *ngIf="showVisibility">
<div class="uk-flex uk-flex-middle"> <li *ngIf="isCurator" class="uk-nav-divider"></li>
<icon [flex]="true" [name]="v.icon" <li *ngFor="let v of stakeholderUtils.visibilities">
ratio="0.6"></icon> <a (click)="changeIndicatorStatus(number._id, indicator, v.value);hide(element)">
<span class="uk-margin-small-left uk-width-expand">{{ v.label }}</span> <div class="uk-flex uk-flex-middle">
<icon *ngIf="indicator.visibility === v.value" <icon [flex]="true" [name]="v.icon"
[flex]="true" name="done" ratio="0.6"></icon>
class="uk-text-secondary" ratio="0.8"></icon> <span class="uk-margin-small-left uk-width-expand">{{ v.label }}</span>
</div> <icon *ngIf="indicator.visibility === v.value"
</a> [flex]="true" name="done"
</li> class="uk-text-secondary" ratio="0.8"></icon>
</ng-template> </div>
</ng-container> </a>
<ng-container *ngIf="!indicator.defaultId && !editing && isCurator"> </li>
<li class="uk-nav-divider"> </ng-container>
<li> <ng-container *ngIf="!indicator.defaultId && !editing && isCurator">
<a (click)="deleteIndicatorOpen(number, indicator._id, 'number', 'delete');hide(element)">Delete</a> <li class="uk-nav-divider">
</li> <li>
</ng-container> <a (click)="deleteIndicatorOpen(number, indicator._id, 'number', 'delete');hide(element)">Delete</a>
</ul> </li>
</div> </ng-container>
</div> </ul>
<div class="uk-text-small uk-text-truncate uk-margin-xsmall-bottom uk-margin-right">{{ indicator.name }}</div>
<div class="number uk-text-small uk-text-bold">
<span *ngIf="numberResults.get(i + '-' + j + '-' + 0)"
[innerHTML]="(indicator.indicatorPaths[0].format == 'NUMBER'?(numberResults.get(i + '-' + j + '-' + 0) | numberRound: 2:1:stakeholder.locale):(numberResults.get(i + '-' + j + '-' + 0) | numberPercentage: stakeholder.locale))"></span>
<span *ngIf="!numberResults.get(i + '-' + j + '-' + 0)">--</span>
</div> </div>
</div> </div>
<div class="uk-text-small uk-text-truncate uk-margin-xsmall-bottom uk-margin-right">{{ indicator.name }}</div>
<div class="number uk-text-small uk-text-bold">
<span *ngIf="numberResults.get(i + '-' + j + '-' + 0)"
[innerHTML]="(indicator.indicatorPaths[0].format == 'NUMBER'?(numberResults.get(i + '-' + j + '-' + 0) | numberRound: 2:1:stakeholder.locale):(numberResults.get(i + '-' + j + '-' + 0) | numberPercentage: stakeholder.locale))"></span>
<span *ngIf="!numberResults.get(i + '-' + j + '-' + 0)">--</span>
</div>
</div> </div>
</ng-template> </div>
</div> </div>
<div *ngIf="isCurator && isEditable" class="uk-margin-top"> <div *ngIf="isCurator && isEditable" class="uk-margin-top">
<div class="uk-grid uk-grid-small" uk-grid> <div class="uk-grid uk-grid-small" uk-grid>
@ -99,7 +101,14 @@
</div> </div>
</div> </div>
<div *ngIf="isEditable && isCurator"> <div *ngIf="isEditable && isCurator">
<ng-container *ngTemplateOutlet="new_section; context:{type: 'number'}"></ng-container> <div class="section">
<div class="uk-flex uk-flex-center" (click)="createSection(-1, 'number')">
<button class="uk-button uk-button-primary uk-flex uk-flex-middle">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">New section</span>
</button>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -125,24 +134,30 @@
<div *ngIf="isEditable" input [formInput]="chartSections.at(i).get('title')" <div *ngIf="isEditable" input [formInput]="chartSections.at(i).get('title')"
(focusEmitter)="saveSection($event, chartSections.at(i), i)" (focusEmitter)="saveSection($event, chartSections.at(i), i)"
class="uk-width-1-3@m uk-width-1-1" placeholder="Title" inputClass="border-bottom"></div> class="uk-width-1-3@m uk-width-1-1" placeholder="Title" inputClass="border-bottom"></div>
<h5 *ngIf="!isEditable" class="uk-margin-remove">{{chartSections.at(i).get('title').value}}</h5> <h5 *ngIf="!isEditable"
class="uk-margin-remove">{{ chartSections.at(i).get('title').value }}</h5>
</div> </div>
<div [id]="'chart-' + chart._id" class="uk-grid uk-grid-small uk-grid-match" <div [id]="'chart-' + chart._id" class="uk-grid uk-grid-small uk-grid-match"
[attr.uk-sortable]="isEditable ? 'group: chart': null" uk-grid> [attr.uk-sortable]="isEditable ? 'group: chart': null" uk-grid>
<ng-template ngFor [ngForOf]="chart.indicators" let-indicator let-j="index"> <div *ngFor="let indicator of chart.indicators; let j=index" [id]="indicator._id"
<div *ngIf="indicator" [id]="indicator._id" [ngClass]="getChartClassBySize(indicator.width)">
[ngClass]="getChartClassBySize(indicator.width)"> <div class="uk-card uk-card-default uk-position-relative">
<div class="uk-card uk-card-default uk-card-body uk-position-relative"> <div class="uk-card-body uk-margin-small-bottom">
<!-- Dropdown -->
<div *ngIf="!dragging" <div *ngIf="!dragging"
class="uk-position-top-right uk-margin-small-right uk-margin-small-top"> class="uk-position-top-right uk-margin-small-right uk-margin-small-top">
<icon *ngIf="!isEditable && showVisibility" [flex]="true" <icon *ngIf="!isEditable && showVisibility" [flex]="true"
[name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)" [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)"
ratio="0.6"></icon> ratio="0.6"></icon>
<a *ngIf="isEditable && (isCurator || showVisibility)" class="uk-link-reset uk-flex uk-flex-middle" [class.uk-disabled]="editing"> <a *ngIf="isEditable && (isCurator || showVisibility)"
<icon *ngIf="showVisibility" [flex]="true" [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)" ratio="0.6"></icon> class="uk-link-reset uk-flex uk-flex-middle" [class.uk-disabled]="editing">
<icon *ngIf="showVisibility" [flex]="true"
[name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)"
ratio="0.6"></icon>
<icon [flex]="true" name="more_vert"></icon> <icon [flex]="true" name="more_vert"></icon>
</a> </a>
<div #element *ngIf="isEditable && (isCurator || showVisibility)" class="uk-dropdown" <div #element *ngIf="isEditable && (isCurator || showVisibility)"
class="uk-dropdown"
uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0"> uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0">
<ul class="uk-nav uk-dropdown-nav"> <ul class="uk-nav uk-dropdown-nav">
<ng-container *ngIf="isCurator"> <ng-container *ngIf="isCurator">
@ -152,20 +167,18 @@
</ng-container> </ng-container>
<ng-container *ngIf="showVisibility"> <ng-container *ngIf="showVisibility">
<li *ngIf="isCurator" class="uk-nav-divider"></li> <li *ngIf="isCurator" class="uk-nav-divider"></li>
<ng-template ngFor [ngForOf]="stakeholderUtils.visibilities" let-v> <li *ngFor="let v of stakeholderUtils.visibilities">
<li> <a (click)="changeIndicatorStatus(chart._id, indicator, v.value);">
<a (click)="changeIndicatorStatus(chart._id, indicator, v.value);"> <div class="uk-flex uk-flex-middle">
<div class="uk-flex uk-flex-middle"> <icon [flex]="true" [name]="v.icon"
<icon [flex]="true" [name]="v.icon" ratio="0.6"></icon>
ratio="0.6"></icon> <span class="uk-margin-small-left uk-width-expand">{{ v.label }}</span>
<span class="uk-margin-small-left uk-width-expand">{{ v.label }}</span> <icon *ngIf="indicator.visibility === v.value"
<icon *ngIf="indicator.visibility === v.value" [flex]="true" name="done"
[flex]="true" name="done" class="uk-text-secondary" ratio="0.8"></icon>
class="uk-text-secondary" ratio="0.8"></icon> </div>
</div> </a>
</a> </li>
</li>
</ng-template>
</ng-container> </ng-container>
<ng-container *ngIf="!indicator.defaultId && !editing && isCurator"> <ng-container *ngIf="!indicator.defaultId && !editing && isCurator">
<li class="uk-nav-divider"> <li class="uk-nav-divider">
@ -176,41 +189,44 @@
</ul> </ul>
</div> </div>
</div> </div>
<!-- Main content-->
<div> <div>
<div *ngIf="indicator.name" <h6 class="uk-margin-bottom chartTitle uk-flex uk-flex-bottom">
class="uk-text-center uk-text-bold uk-margin-small-bottom"> {{ indicator.name + " " }}
{{ indicator.name }} </h6>
</div>
<iframe *ngIf="!properties.disableFrameLoad && getActiveIndicatorPath(indicator) && getActiveIndicatorPath(indicator).source !=='image' && <iframe *ngIf="!properties.disableFrameLoad && getActiveIndicatorPath(indicator) && getActiveIndicatorPath(indicator).source !=='image' &&
safeUrls.get(indicatorUtils.getFullUrl(stakeholder, getActiveIndicatorPath(indicator)))" safeUrls.get(indicatorUtils.getFullUrl(stakeholder, getActiveIndicatorPath(indicator)))"
allowfullscreen="true" mozallowfullscreen="true" allowfullscreen="true" mozallowfullscreen="true"
webkitallowfullscreen="true" webkitallowfullscreen="true"
[src]="safeUrls.get(indicatorUtils.getFullUrl(stakeholder, getActiveIndicatorPath(indicator)))" [src]="safeUrls.get(indicatorUtils.getFullUrl(stakeholder, getActiveIndicatorPath(indicator)))"
class="uk-width-1-1" class="uk-width-1-1"
[ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')" [ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')"
[class.uk-blend-multiply]="!isFullscreen"></iframe> [class.uk-blend-multiply]="!isFullscreen"></iframe>
<div *ngIf="properties.disableFrameLoad && indicator.indicatorPaths && <div *ngIf="properties.disableFrameLoad && getActiveIndicatorPath(indicator)?.source !=='image'">
indicator.indicatorPaths.length > 0 && getActiveIndicatorPath(indicator).source !=='image'">
<img class="uk-width-1-1 uk-blend-multiply" <img class="uk-width-1-1 uk-blend-multiply"
[ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')" [ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')"
src="assets/chart-placeholder.png"> src="assets/chart-placeholder.png">
</div> </div>
<div *ngIf="indicator.indicatorPaths && getActiveIndicatorPath(indicator) && getActiveIndicatorPath(indicator).source === 'image'"> <div *ngIf="getActiveIndicatorPath(indicator)?.source === 'image'">
<img class="uk-width-1-1 uk-blend-multiply" <img class="uk-width-1-1 uk-blend-multiply"
[ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')" [ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')"
[src]="getActiveIndicatorPath(indicator).url"> [src]="getActiveIndicatorPath(indicator).url">
</div> </div>
<slider-tabs *ngIf="indicator.indicatorPaths.length > 1" [type]="'dynamic'" [flexPosition]="'right'" (activeEmitter)="indicator.activePath = $event"
tabsClass="uk-subnav uk-subnav-pill uk-subnav-small" containerClass="uk-margin-top uk-margin-bottom" [border]="false">
<slider-tab *ngFor="let indicatorPath of indicator.indicatorPaths; let i=index"
[tabTitle]="indicatorPath.parameters.tab ? indicatorPath.parameters.tab : indicatorPath.parameters.title"
[tabId]="i" [active]="(!indicator.activePath && i == 0) || indicator.activePath == i">
</slider-tab>
</slider-tabs>
</div> </div>
<!-- Tabs -->
<slider-tabs [type]="'dynamic'" [flexPosition]="'right'"
(activeEmitter)="indicator.activePath = $event"
tabsClass="uk-subnav uk-subnav-pill uk-subnav-small"
containerClass="uk-margin-top uk-margin-bottom" [border]="false">
<slider-tab *ngFor="let indicatorPath of indicator.indicatorPaths; let i=index"
[tabTitle]="indicatorPath.parameters.tab ? indicatorPath.parameters.tab : indicatorPath.parameters.title"
[invisible]="indicator.indicatorPaths.length < 2"
[tabId]="i" [active]="getActivePathIndex(indicator) == i">
</slider-tab>
</slider-tabs>
</div> </div>
</div> </div>
</ng-template> </div>
</div> </div>
<div *ngIf="isCurator && isEditable" class="uk-margin-top"> <div *ngIf="isCurator && isEditable" class="uk-margin-top">
<div class="uk-grid uk-grid-small uk-grid-match" uk-grid> <div class="uk-grid uk-grid-small uk-grid-match" uk-grid>
@ -235,7 +251,14 @@
</div> </div>
</div> </div>
<div *ngIf="isEditable && isCurator"> <div *ngIf="isEditable && isCurator">
<ng-container *ngTemplateOutlet="new_section; context:{type: 'chart'}"></ng-container> <div class="section">
<div class="uk-flex uk-flex-center" (click)="createSection(-1)">
<button class="uk-button uk-button-primary uk-flex uk-flex-middle">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">New section</span>
</button>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -269,68 +292,8 @@
</div> </div>
<hr class="uk-width-1-1"> <hr class="uk-width-1-1">
<div *ngIf="numberIndicatorPaths" formArrayName="indicatorPaths"> <div *ngIf="numberIndicatorPaths" formArrayName="indicatorPaths">
<div *ngIf="stakeholderUtils.hasMultiNumberIndicatorPaths" class="uk-margin-medium-bottom">
<ul #numbersTransition class="uk-subnav uk-subnav-pill uk-subnav-small" transition-group>
<li *ngFor="let indicatorPath of numberIndicatorPaths.controls; let i=index"
class="uk-visible-toggle uk-flex uk-margin-small-top" transition-group-item
[class.uk-active]="(!indicator.activePath && i == 0) || indicator.activePath === i">
<a (click)="activeNumberIndicatorPath(i)">
<span *ngIf="indicatorPath.get('result').valid && indicatorPath.get('result').value !== 0"
[innerHTML]="(indicatorPath.get('format').value == 'NUMBER'?(indicatorPath.get('result').value | numberRound: 2:1:stakeholder.locale):(indicatorPath.get('result').value | numberPercentage: stakeholder.locale))">
</span>
<span *ngIf="!indicatorPath.get('result').valid || indicatorPath.get('result').value === 0">
--
</span>
</a>
<span *ngIf="!indicator.defaultId && numberIndicatorPaths.length > 1"
class="uk-flex uk-flex-column uk-flex-center uk-margin-small-left"
[class.uk-invisible-hover]="indicator.activePath !== i"
(click)="$event.stopPropagation();$event.preventDefault()">
<a *ngIf="isCurator" class="uk-link-reset uk-flex uk-flex-middle">
<icon [flex]="true" name="more_vert"></icon>
</a>
<div #element uk-dropdown="mode: click; pos: bottom-left; offset: 5; delay-hide: 0;">
<ul class="uk-nav uk-dropdown-nav">
<li *ngIf="i > 0">
<a (click)="hide(element);moveIndicatorPath(numberIndicatorFb, 'number', i)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="west" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Move Left</span>
</div>
</a>
</li>
<li *ngIf="i < numberIndicatorPaths.length - 1">
<a (click)="hide(element);moveIndicatorPath(numberIndicatorFb, 'number', i, i + 1)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="east" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Move Right</span>
</div>
</a>
</li>
<li>
<a (click)="removeNumberIndicatorPath(i); hide(element)">
<div class="uk-flex uk-flex-middle">
<icon [flex]="true" name="delete" ratio="0.6"></icon>
<span class="uk-margin-small-left uk-width-expand">Delete</span>
</div>
</a>
</li>
</ul>
</div>
</span>
</li>
<li class="uk-margin-small-top">
<a (click)="activeNumberIndicatorPath(numberIndicatorPaths.length); $event.preventDefault()"
class="uk-flex uk-flex-middle">
<icon name="add" [flex]="true"></icon>
<span class="uk-text-uppercase">Add</span>
</a>
</li>
</ul>
</div>
<div *ngFor="let indicatorPath of numberIndicatorPaths.controls; let i=index" [formGroupName]="i"> <div *ngFor="let indicatorPath of numberIndicatorPaths.controls; let i=index" [formGroupName]="i">
<div *ngIf="(!indicator.activePath && i == 0) || indicator.activePath === i" class="uk-grid" <div *ngIf="getActivePathIndex() === i" class="uk-grid" uk-grid>
uk-grid>
<div class="uk-width-1-1"> <div class="uk-width-1-1">
<div class="uk-grid" uk-grid> <div class="uk-grid" uk-grid>
<div class="uk-width-1-1 uk-flex uk-flex-middle"> <div class="uk-width-1-1 uk-flex uk-flex-middle">
@ -388,8 +351,8 @@
</a> </a>
<span [class.uk-invisible]="getJsonPath(i).disabled || j === (getJsonPath(i).controls.length - 1)" <span [class.uk-invisible]="getJsonPath(i).disabled || j === (getJsonPath(i).controls.length - 1)"
class="uk-text-center uk-margin-small-left"> class="uk-text-center uk-margin-small-left">
<icon name="east"></icon> <icon name="east"></icon>
</span> </span>
</div> </div>
<div *ngIf="indicator.defaultId === null"> <div *ngIf="indicator.defaultId === null">
<button class="uk-icon-button uk-button-primary" (click)="addJsonPath(i)"> <button class="uk-icon-button uk-button-primary" (click)="addJsonPath(i)">
@ -471,17 +434,17 @@
[options]="indicatorUtils.indicatorSizes" type="select"> [options]="indicatorUtils.indicatorSizes" type="select">
</div> </div>
<div *ngIf="chartIndicatorPaths" formArrayName="indicatorPaths" class="uk-width-1-1"> <div *ngIf="chartIndicatorPaths" formArrayName="indicatorPaths" class="uk-width-1-1">
<div *ngIf="stakeholderUtils.hasMultiChartIndicatorPaths" class="uk-margin-medium-bottom"> <div class="uk-margin-medium-bottom">
<ul #chartsTransition class="uk-subnav uk-subnav-pill uk-subnav-small" transition-group> <ul #chartsTransition class="uk-subnav uk-subnav-pill uk-subnav-small" transition-group>
<li *ngFor="let indicatorPath of chartIndicatorPaths.controls; let i=index" <li *ngFor="let indicatorPath of chartIndicatorPaths.controls; let i=index"
class="uk-visible-toggle uk-flex uk-margin-small-top" transition-group-item class="uk-visible-toggle uk-flex uk-margin-small-top" transition-group-item
[class.uk-active]="(!indicator.activePath && i == 0) || indicator.activePath === i"> [class.uk-active]="getActivePathIndex() === i">
<a (click)="activeChartIndicatorPath(i)"> <a (click)="setActiveChartIndicatorPath(i)">
<span>{{ getParameter(i, 'tab')?.get('value')?.value ? getParameter(i, 'tab').get('value').value : 'No title yet' }}</span> <span>{{ getParameter(i, 'tab')?.get('value')?.value ? getParameter(i, 'tab').get('value').value : 'No title yet' }}</span>
</a> </a>
<span *ngIf="!indicator.defaultId && chartIndicatorPaths.length > 1" <span *ngIf="!indicator.defaultId && chartIndicatorPaths.length > 1"
class="uk-flex uk-flex-column uk-flex-center uk-margin-small-left" class="uk-flex uk-flex-column uk-flex-center uk-margin-small-left"
[class.uk-invisible-hover]="indicator.activePath !== i" [class.uk-invisible-hover]="getActivePathIndex()!== i"
(click)="$event.stopPropagation();$event.preventDefault()"> (click)="$event.stopPropagation();$event.preventDefault()">
<a *ngIf="isCurator" class="uk-link-reset uk-flex uk-flex-middle"> <a *ngIf="isCurator" class="uk-link-reset uk-flex uk-flex-middle">
<icon [flex]="true" name="more_vert"></icon> <icon [flex]="true" name="more_vert"></icon>
@ -517,7 +480,7 @@
</span> </span>
</li> </li>
<li *ngIf="!indicator.defaultId" class="uk-margin-small-top"> <li *ngIf="!indicator.defaultId" class="uk-margin-small-top">
<a (click)="activeChartIndicatorPath(chartIndicatorPaths.length); $event.preventDefault()" <a (click)="setActiveChartIndicatorPath(chartIndicatorPaths.length); $event.preventDefault()"
class="uk-flex uk-flex-middle"> class="uk-flex uk-flex-middle">
<icon name="add" [flex]="true"></icon> <icon name="add" [flex]="true"></icon>
<span class="uk-text-uppercase">Add</span> <span class="uk-text-uppercase">Add</span>
@ -525,10 +488,8 @@
</li> </li>
</ul> </ul>
</div> </div>
<div *ngFor="let indicatorPath of chartIndicatorPaths.controls; let i=index;" <div *ngFor="let indicatorPath of chartIndicatorPaths.controls; let i=index;" [formGroupName]="i">
[formGroupName]="i"> <div *ngIf="getActivePathIndex() === i" class="uk-grid" uk-grid>
<div *ngIf="(!indicator.activePath && i == 0) || indicator.activePath === i" class="uk-grid"
uk-grid>
<div class="uk-width-1-1 uk-flex uk-flex-middle"> <div class="uk-width-1-1 uk-flex uk-flex-middle">
<div input class="uk-width-expand" <div input class="uk-width-expand"
[title]="indicatorPath.get('url').disabled?'Default chart URLs cannot change':''" [title]="indicatorPath.get('url').disabled?'Default chart URLs cannot change':''"
@ -542,7 +503,7 @@
</div> </div>
<div class="uk-width-1-1" formArrayName="parameters"> <div class="uk-width-1-1" formArrayName="parameters">
<div class="uk-grid" uk-grid> <div class="uk-grid" uk-grid>
<div *ngIf="stakeholderUtils.hasMultiChartIndicatorPaths && getParameter(i, 'tab')" input class="uk-width-1-1" <div *ngIf="getParameter(i, 'tab')" input class="uk-width-1-1"
[formInput]="getParameter(i, 'tab').get('value')" [formInput]="getParameter(i, 'tab').get('value')"
placeholder="Tab Title"></div> placeholder="Tab Title"></div>
<div *ngIf="getParameter(i, 'title')" input class="uk-width-1-1" <div *ngIf="getParameter(i, 'title')" input class="uk-width-1-1"
@ -566,7 +527,8 @@
[formInput]="getParameter(i, 'yAxisTitle').get('value')" [formInput]="getParameter(i, 'yAxisTitle').get('value')"
placeholder="Y-Axis Title"></div> placeholder="Y-Axis Title"></div>
<ng-container *ngIf="isLegendEnabled(indicator, i)"> <ng-container *ngIf="isLegendEnabled(indicator, i)">
<div *ngFor="let dataTitle of dataTitles(i); let j=index" input class="uk-width-1-3@s" <div *ngFor="let dataTitle of dataTitles(i); let j=index" input
class="uk-width-1-3@s"
[formInput]="getParameter(i, dataTitle).get('value')" [formInput]="getParameter(i, dataTitle).get('value')"
[placeholder]="'Data Title ' + (j + 1)"></div> [placeholder]="'Data Title ' + (j + 1)"></div>
</ng-container> </ng-container>
@ -641,13 +603,3 @@
Are you sure you want to proceed? Are you sure you want to proceed?
</div> </div>
</modal-alert> </modal-alert>
<ng-template #new_section let-type="type">
<div class="section">
<div class="uk-flex uk-flex-center" (click)="createSection(-1, type)">
<button class="uk-button uk-button-primary uk-flex uk-flex-middle">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">New section</span>
</button>
</div>
</div>
</ng-template>

View File

@ -10,8 +10,8 @@ import {
ViewChild ViewChild
} from "@angular/core"; } from "@angular/core";
import { import {
Format, Format, ImportIndicators,
Indicator, Indicator, IndicatorImport,
IndicatorPath, IndicatorPath,
IndicatorSize, IndicatorSize,
IndicatorType, IndicatorType,
@ -79,7 +79,6 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
* Editable indicator * Editable indicator
*/ */
public section: Section; public section: Section;
public indicator: Indicator;
public index: number = -1; public index: number = -1;
public editing: boolean = false; public editing: boolean = false;
public dragging: boolean = false; public dragging: boolean = false;
@ -102,7 +101,6 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
@ViewChild('editChartNotify', {static: true}) editChartNotify: NotifyFormComponent; @ViewChild('editChartNotify', {static: true}) editChartNotify: NotifyFormComponent;
@ViewChild('deleteNotify', {static: true}) deleteNotify: NotifyFormComponent; @ViewChild('deleteNotify', {static: true}) deleteNotify: NotifyFormComponent;
/* Transition Groups */ /* Transition Groups */
@ViewChild('numbersTransition') numbersTransition: TransitionGroupComponent;
@ViewChild('chartsTransition') chartsTransition: TransitionGroupComponent; @ViewChild('chartsTransition') chartsTransition: TransitionGroupComponent;
public isFullscreen: boolean = false; public isFullscreen: boolean = false;
@ -581,26 +579,14 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
} }
} }
public removeNumberIndicatorPath(index: number) {
this.numberIndicatorPaths.removeAt(index);
this.indicator.indicatorPaths.splice(index, 1);
this.numbersTransition.init();
if (this.indicator.activePath === index) {
this.activeNumberIndicatorPath(Math.max(0, index - 1));
} else if (this.indicator.activePath > index) {
this.activeNumberIndicatorPath(this.indicator.activePath - 1);
}
this.numberIndicatorFb.markAsDirty();
}
public removeChartIndicatorPath(index: number) { public removeChartIndicatorPath(index: number) {
this.chartIndicatorPaths.removeAt(index); this.chartIndicatorPaths.removeAt(index);
this.indicator.indicatorPaths.splice(index, 1); this.indicator.indicatorPaths.splice(index, 1);
this.chartsTransition.init(); this.chartsTransition.init();
if (this.indicator.activePath === index) { if (this.indicator.activePath === index) {
this.activeChartIndicatorPath(Math.max(0, index - 1)); this.setActiveChartIndicatorPath(Math.max(0, index - 1));
} else if (this.indicator.activePath > index) { } else if (this.indicator.activePath > index) {
this.activeChartIndicatorPath(this.indicator.activePath - 1); this.setActiveChartIndicatorPath(this.indicator.activePath - 1);
} }
this.chartIndicatorFb.markAsDirty(); this.chartIndicatorFb.markAsDirty();
} }
@ -609,9 +595,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
type: 'number' | 'chart', index: number, type: 'number' | 'chart', index: number,
newIndex: number = index - 1) { newIndex: number = index - 1) {
let indicatorPaths = type == 'number'?this.numberIndicatorPaths:this.chartIndicatorPaths; let indicatorPaths = type == 'number'?this.numberIndicatorPaths:this.chartIndicatorPaths;
if(type == 'number') { if(type == 'chart') {
this.numbersTransition.init();
} else {
this.chartsTransition.init(); this.chartsTransition.init();
} }
let a = indicatorPaths.at(index); let a = indicatorPaths.at(index);
@ -627,16 +611,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
form.markAsDirty(); form.markAsDirty();
} }
public activeNumberIndicatorPath(index: number) { public setActiveChartIndicatorPath(index: number) {
let paths = this.numberIndicatorPaths;
if (index == paths.length) {
this.addNumberIndicatorPath();
this.numbersTransition.init();
}
this.indicator.activePath = index;
}
public activeChartIndicatorPath(index: number) {
let paths = this.chartIndicatorPaths; let paths = this.chartIndicatorPaths;
if (index == paths.length) { if (index == paths.length) {
this.addChartIndicatorPath(); this.addChartIndicatorPath();
@ -1008,8 +983,10 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
this.getSecureUrlByStakeHolder(this.indicator.indicatorPaths[index]).toString(); this.getSecureUrlByStakeHolder(this.indicator.indicatorPaths[index]).toString();
} else if (type === 'number') { } else if (type === 'number') {
let indicatorPath = this.numberIndicatorPaths.at(index).value; let indicatorPath = this.numberIndicatorPaths.at(index).value;
indicatorPath.parameters.forEach(parameter => { indicatorPath.parameters.forEach((parameter: { value: any; key: string | number; }) => {
if (parameter.value !== this.indicator.indicatorPaths[index].parameters[parameter.key]) { if (!parameter.value && !this.indicator.indicatorPaths[index].parameters[parameter.key]) {
return;
} else if (parameter.value !== this.indicator.indicatorPaths[index].parameters[parameter.key]) {
hasDifference = true; hasDifference = true;
return; return;
} }
@ -1027,6 +1004,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
} }
refreshIndicator(type: IndicatorType = 'chart') { refreshIndicator(type: IndicatorType = 'chart') {
let activePath = this.indicator.activePath;
if (type === 'chart') { if (type === 'chart') {
this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths, 'chart'); this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths, 'chart');
this.indicator.indicatorPaths.forEach(indicatorPath => { this.indicator.indicatorPaths.forEach(indicatorPath => {
@ -1038,6 +1016,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
this.validateJsonPath(index); this.validateJsonPath(index);
}); });
} }
this.indicator.activePath = activePath;
} }
deleteIndicatorOpen(section: Section, indicatorId: string, type: string, childrenAction: string = null) { deleteIndicatorOpen(section: Section, indicatorId: string, type: string, childrenAction: string = null) {
@ -1276,10 +1255,10 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
})); }));
} }
importIndicatorsAndSave(stakeholder: Stakeholder, charts: any[]) { importIndicatorsAndSave(importIndicators: ImportIndicators) {
let sectionsToSave: Section[] = []; let sectionsToSave: Section[] = [];
let countIndicators = 0; let countIndicators = 0;
if (stakeholder.type !== this.stakeholder.type) { if (importIndicators.stakeholder.type !== this.stakeholder.type) {
UIkit.notification("The type of this profile is not the same with the file's one!", { UIkit.notification("The type of this profile is not the same with the file's one!", {
status: 'warning', status: 'warning',
timeout: 6000, timeout: 6000,
@ -1290,26 +1269,26 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
} }
// name description additionalDescription, height, width, visibility // name description additionalDescription, height, width, visibility
let duplicates = 0; let duplicates = 0;
for (let chart of charts) { for (let indicator of importIndicators.indicators) {
chart.visibility = this.showVisibility ? chart.visibility : this.stakeholderUtils.defaultValue(this.stakeholderUtils.visibilities); indicator.visibility = this.showVisibility ? indicator.visibility : this.stakeholderUtils.defaultValue(this.stakeholderUtils.visibilities);
if (!sectionsToSave[chart['sectionIndex']]) { if (!sectionsToSave[indicator['sectionIndex']]) {
let sectionToSave = new Section(chart['sectionType'] ? chart['sectionType'] : chart['type'], chart['sectionTitle']); let sectionToSave = new Section(indicator['sectionType'] ? indicator['sectionType'] : indicator['type'], indicator['sectionTitle']);
sectionToSave.indicators = []; sectionToSave.indicators = [];
sectionsToSave[chart['sectionIndex']] = sectionToSave; sectionsToSave[indicator['sectionIndex']] = sectionToSave;
} }
let exists = false; let exists = false;
let indicatorPaths: IndicatorPath[] = []; let indicatorPaths: IndicatorPath[] = [];
// validate indicators' schema from file // validate indicators' schema from file
let invalid_file_message; let invalid_file_message;
if (!chart.type) { if (!indicator.type) {
invalid_file_message = "No indicator type is specified. Type should be chart or number."; invalid_file_message = "No indicator type is specified. Type should be chart or number.";
} else if (chart.type != "chart" && chart.type != "number") { } else if (indicator.type != "chart" && indicator.type != "number") {
invalid_file_message = "Invalid indicator type. Type should be chart or number."; invalid_file_message = "Invalid indicator type. Type should be chart or number.";
} else if (chart.indicatorPaths.length === 0) { } else if (indicator.indicatorPaths.length === 0) {
invalid_file_message = "No indicator paths are specified." invalid_file_message = "No indicator paths are specified."
} else if (chart.type == "number" && chart.indicatorPaths.filter(path => !path.jsonPath).length > 0) { } else if (indicator.type == "number" && indicator.indicatorPaths.filter(path => !path.jsonPath).length > 0) {
invalid_file_message = "No jsonPath is specified for number indicator." invalid_file_message = "No jsonPath is specified for number indicator."
} else if (chart.indicatorPaths.filter(path => !path.url).length > 0) { } else if (indicator.indicatorPaths.filter(path => !path.url).length > 0) {
invalid_file_message = "No indicator url is specified."; invalid_file_message = "No indicator url is specified.";
} }
@ -1323,8 +1302,8 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
break; break;
} }
if (chart.type == "chart") { if (indicator.type == "chart") {
indicatorPaths = chart.indicatorPaths.map(path => this.indicatorUtils.generateIndicatorByChartUrl(this.indicatorUtils.getChartSource(path.url), path.url, chart.type, stakeholder, path.tab)); indicatorPaths = indicator.indicatorPaths.map(path => this.indicatorUtils.generateIndicatorByChartUrl(this.indicatorUtils.getChartSource(path.url), path.url, null, importIndicators.stakeholder, path.tab));
this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index].charts.forEach((section: Section) => { this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index].charts.forEach((section: Section) => {
section.indicators.forEach(indicator => { section.indicators.forEach(indicator => {
indicator.indicatorPaths.forEach(path => { indicator.indicatorPaths.forEach(path => {
@ -1337,10 +1316,10 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
}); });
}); });
}); });
} else if (chart.type == "number") { } else if (indicator.type == "number") {
indicatorPaths = chart.indicatorPaths.map(path => indicatorPaths = indicator.indicatorPaths.map(path =>
this.indicatorUtils.generateIndicatorByNumberUrl(this.indicatorUtils.getNumberSource(path.url), path.url, this.indicatorUtils.generateIndicatorByNumberUrl(this.indicatorUtils.getNumberSource(path.url), path.url,
stakeholder, path.jsonPath, this.indicatorUtils.numberSources.get(this.indicatorUtils.getNumberSource(path.url)))); importIndicators.stakeholder, path.jsonPath, this.indicatorUtils.numberSources.get(this.indicatorUtils.getNumberSource(path.url))));
this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index].numbers.forEach((section: Section) => { this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index].numbers.forEach((section: Section) => {
section.indicators.forEach(indicator => { section.indicators.forEach(indicator => {
indicator.indicatorPaths.forEach(path => { indicator.indicatorPaths.forEach(path => {
@ -1355,8 +1334,8 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
}); });
} }
if (indicatorPaths.length > 0) { if (indicatorPaths.length > 0) {
let i: Indicator = new Indicator(chart.name, chart.description, chart.additionalDescription, chart.type, chart.width, chart.height, this.showVisibility ? "RESTRICTED" : this.stakeholderUtils.defaultValue(this.stakeholderUtils.visibilities), indicatorPaths); let i: Indicator = new Indicator(indicator.name, indicator.description, indicator.additionalDescription, indicator.type, indicator.width, indicator.height, this.showVisibility ? "RESTRICTED" : this.stakeholderUtils.defaultValue(this.stakeholderUtils.visibilities), indicatorPaths);
sectionsToSave[chart['sectionIndex']].indicators.push(i); sectionsToSave[indicator['sectionIndex']].indicators.push(i);
countIndicators++; countIndicators++;
} }
} }
@ -1498,7 +1477,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
}); });
this.finish(); this.finish();
} else { } else {
this.importIndicatorsAndSave(json.stakeholder, json.indicators); this.importIndicatorsAndSave(json);
} }
}, (error) => { }, (error) => {
console.error("Error importing files", error); console.error("Error importing files", error);

View File

@ -84,8 +84,6 @@ export class StakeholderConfiguration {
{icon: 'incognito', value: "PRIVATE", label: 'Private'}, {icon: 'incognito', value: "PRIVATE", label: 'Private'},
]; ];
public static CACHE_INDICATORS: boolean = true; public static CACHE_INDICATORS: boolean = true;
public static NUMBER_MULTI_INDICATOR_PATHS = false;
public static CHART_MULTI_INDICATOR_PATHS = true;
public static openAccess: Map<string, OAIndicator> = new Map(); public static openAccess: Map<string, OAIndicator> = new Map();
} }
@ -119,14 +117,6 @@ export class StakeholderUtils {
return StakeholderConfiguration.CACHE_INDICATORS; return StakeholderConfiguration.CACHE_INDICATORS;
} }
get hasMultiNumberIndicatorPaths() {
return StakeholderConfiguration.NUMBER_MULTI_INDICATOR_PATHS;
}
get hasMultiChartIndicatorPaths() {
return StakeholderConfiguration.CHART_MULTI_INDICATOR_PATHS;
}
get openAccess(): Map<string, OAIndicator> { get openAccess(): Map<string, OAIndicator> {
return StakeholderConfiguration.openAccess; return StakeholderConfiguration.openAccess;
} }

View File

@ -2,7 +2,7 @@ import {Directive} from "@angular/core";
import {BaseComponent} from "../../sharedComponents/base/base.component"; import {BaseComponent} from "../../sharedComponents/base/base.component";
import {IndicatorUtils, StakeholderUtils} from "./indicator-utils"; import {IndicatorUtils, StakeholderUtils} from "./indicator-utils";
import {ConnectHelper} from "../../connect/connectHelper"; import {ConnectHelper} from "../../connect/connectHelper";
import {IndicatorSize} from "../../monitor/entities/stakeholder"; import {Indicator, IndicatorSize} from "../../monitor/entities/stakeholder";
import {statsToolParser} from "./cache-indicators/cache-indicators"; import {statsToolParser} from "./cache-indicators/cache-indicators";
@Directive() @Directive()
@ -53,6 +53,7 @@ export abstract class StakeholderBaseComponent extends BaseComponent {
export abstract class IndicatorStakeholderBaseComponent extends StakeholderBaseComponent { export abstract class IndicatorStakeholderBaseComponent extends StakeholderBaseComponent {
indicatorUtils: IndicatorUtils = new IndicatorUtils(); indicatorUtils: IndicatorUtils = new IndicatorUtils();
indicator: Indicator;
public getNumberClassBySize(size: IndicatorSize): string { public getNumberClassBySize(size: IndicatorSize): string {
if (size === 'small') { if (size === 'small') {
@ -73,4 +74,15 @@ export abstract class IndicatorStakeholderBaseComponent extends StakeholderBaseC
return 'uk-width-1-1'; return 'uk-width-1-1';
} }
} }
public getActivePathIndex(indicator: Indicator = this.indicator): number {
return indicator?.activePath ? indicator.activePath : 0;
}
public getActiveIndicatorPath(indicator: Indicator = this.indicator) {
if(indicator?.indicatorPaths.length > this.getActivePathIndex(indicator)) {
return indicator.indicatorPaths[this.getActivePathIndex(indicator)];
}
return null;
}
} }

View File

@ -16,6 +16,31 @@ export type Format = 'NUMBER' | 'PERCENTAGE';
export type Visibility = 'PUBLIC' | 'PRIVATE' | 'RESTRICTED'; export type Visibility = 'PUBLIC' | 'PRIVATE' | 'RESTRICTED';
export type Overlay = 'embed' | 'description' | false; export type Overlay = 'embed' | 'description' | false;
export interface IndicatorImport {
indicatorPaths?: IndicatorPathImport[];
type: IndicatorType,
name: string,
description: string,
additionalDescription: string,
visibility: Visibility,
width: IndicatorSize,
height: IndicatorSize,
sectionTitle: string,
sectionType: IndicatorType,
sectionIndex: number
}
export interface IndicatorPathImport {
jsonPath?: string[],
tab: string,
url: string
}
export interface ImportIndicators {
stakeholder: Stakeholder,
indicators: IndicatorImport[]
}
export class ManageStakeholders { export class ManageStakeholders {
templates: (Stakeholder & StakeholderInfo)[]; templates: (Stakeholder & StakeholderInfo)[];
standalone: (Stakeholder & StakeholderInfo)[]; standalone: (Stakeholder & StakeholderInfo)[];

View File

@ -367,6 +367,14 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Compact results -->
<a *ngIf="hasCompactView && (searchUtils.status !== errorCodes.LOADING || !loadPaging)"
class="uk-link-reset custom-view-button active uk-margin-left">
<icon *ngIf="!compactView" uk-tooltip="Compact results" (click)="toggleView(true)"
name="unfold_less" [flex]="true" visuallyHidden="Compact results"></icon>
<icon *ngIf="compactView" uk-tooltip="Expand results" (click)="toggleView(false)"
name="unfold_more" [flex]="true" visuallyHidden="Expand results"></icon>
</a>
<!-- Download results --> <!-- Download results -->
<div *ngIf="showDownload && (searchUtils.status !== errorCodes.LOADING || !loadPaging)" <div *ngIf="showDownload && (searchUtils.status !== errorCodes.LOADING || !loadPaging)"
class="uk-margin-left uk-flex uk-flex-middle" [class.uk-flex-center]="mobile" [class.uk-margin-medium-top]="mobile"> class="uk-margin-left uk-flex uk-flex-middle" [class.uk-flex-center]="mobile" [class.uk-margin-medium-top]="mobile">
@ -381,14 +389,6 @@
</a> </a>
</ng-container> </ng-container>
</div> </div>
<!-- Compact results -->
<a *ngIf="hasCompactView && (searchUtils.status !== errorCodes.LOADING || !loadPaging)"
class="uk-link-reset custom-view-button active uk-margin-left">
<icon *ngIf="!compactView" uk-tooltip="Compact results" (click)="toggleView(true)"
name="unfold_less" [flex]="true" visuallyHidden="Compact results"></icon>
<icon *ngIf="compactView" uk-tooltip="Expand results" (click)="toggleView(false)"
name="unfold_more" [flex]="true" visuallyHidden="Expand results"></icon>
</a>
</div> </div>
</div> </div>

View File

@ -15,6 +15,8 @@ export class SliderTabComponent {
@Input() @Input()
public disabled: boolean = false; public disabled: boolean = false;
@Input() @Input()
public invisible: boolean = false;
@Input()
public align: 'left' | 'right' = 'left'; public align: 'left' | 'right' = 'left';
@Input() @Input()
public routerLink: any[] | string | null | undefined = null; public routerLink: any[] | string | null | undefined = null;

View File

@ -21,71 +21,71 @@ declare var UIkit;
@Component({ @Component({
selector: 'slider-tabs', selector: 'slider-tabs',
template: ` template: `
<div #sliderElement class="uk-position-relative" [class.uk-slider]="position === 'horizontal'" <div #sliderElement class="uk-position-relative" [class.uk-slider]="position === 'horizontal'"
[ngClass]="customClass"> [ngClass]="customClass">
<div [class.uk-slider-container-tabs]="position === 'horizontal'" [class.uk-border-bottom]="border && position === 'horizontal'" [ngClass]="containerClass"> <div [class.uk-slider-container-tabs]="position === 'horizontal'" [class.uk-border-bottom]="border && position === 'horizontal'" [ngClass]="containerClass">
<ul #tabsElement [class.uk-flex-nowrap]="position === 'horizontal'" <ul #tabsElement [class.uk-flex-nowrap]="position === 'horizontal'"
[class.uk-slider-items]="position === 'horizontal'" [class.uk-slider-items]="position === 'horizontal'"
[class.uk-tab-left]="position === 'left'" [class.uk-tab-right]="position === 'right'" [class.uk-tab-left]="position === 'left'" [class.uk-tab-right]="position === 'right'"
[attr.uk-switcher]="type === 'static'?('connect:' + connect):null" [attr.uk-switcher]="type === 'static'?('connect:' + connect):null"
[ngClass]="'uk-flex-' + flexPosition + ' ' + tabsClass"> [ngClass]="'uk-flex-' + flexPosition + ' ' + tabsClass">
<ng-container *ngIf="type === 'static'"> <ng-container *ngIf="type === 'static'">
<li *ngFor="let tab of leftTabs" [ngStyle]="" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block"> <li *ngFor="let tab of leftTabs" [class.uk-invisible]="tab.invisible" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block">
<a> <a [class.uk-disabled]="tab.invisible || tab.disabled">
<span *ngIf="tab.title">{{tab.title}}</span> <span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container> <ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a> </a>
</li> </li>
<li *ngFor="let tab of rightTabs; let i=index;" [style.max-width]="(position === 'horizontal')?'50%':null" [ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''" <li *ngFor="let tab of rightTabs; let i=index;" [class.uk-invisible]="tab.invisible" [style.max-width]="(position === 'horizontal')?'50%':null" [ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''"
class="uk-text-capitalize uk-text-truncate uk-display-block"> class="uk-text-capitalize uk-text-truncate uk-display-block">
<a [ngClass]="tab.customClass"> <a [class.uk-disabled]="tab.invisible || tab.disabled" [ngClass]="tab.customClass">
<span *ngIf="tab.title">{{tab.title}}</span> <span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container> <ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a> </a>
</li> </li>
</ng-container>
<ng-container *ngIf="type === 'dynamic'">
<li *ngFor="let tab of leftTabs; let i=index;" [class.uk-invisible]="tab.invisible" [class.uk-active]="tab.active" [style.max-width]="(position === 'horizontal')?'50%':null">
<a [class.uk-disabled]="tab.invisible || tab.disabled" [routerLink]="tab.routerLink" [queryParams]="tab.queryParams" [ngClass]="tab.customClass" [relativeTo]="tab.relativeTo"
(click)="showActive(i)"
class="uk-text-capitalize uk-text-truncate uk-display-block">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li>
<li *ngFor="let tab of rightTabs; let i=index;" [class.uk-invisible]="tab.invisible" [style.max-width]="(position === 'horizontal')?'50%':null" [class.uk-active]="tab.active"
[ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''">
<a [class.uk-disabled]="tab.invisible || tab.disabled" [routerLink]="tab.routerLink" [queryParams]="tab.queryParams" [ngClass]="tab.customClass" [relativeTo]="tab.relativeTo"
(click)="showActive(i)"
class="uk-text-capitalize uk-text-truncate uk-display-block">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li>
</ng-container>
<ng-container *ngIf="type === 'scrollable'">
<li *ngFor="let tab of leftTabs" [class.uk-invisible]="tab.invisible" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block" [class.uk-active]="tab.active">
<a [class.uk-disabled]="tab.invisible || tab.disabled" routerLink="./" [fragment]="tab.id" queryParamsHandling="merge" [ngClass]="tab.customClass">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li>
<li *ngFor="let tab of rightTabs; let i=index;" [class.uk-invisible]="tab.invisible" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block"
[ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''"
[class.uk-active]="tab.active">
<a [class.uk-disabled]="tab.invisible || tab.disabled" routerLink="./" [fragment]="tab.id" queryParamsHandling="merge" [ngClass]="tab.customClass">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li>
</ng-container>
</ul>
</div>
<ng-container *ngIf="!isServer">
<slider-arrow *ngIf="position === 'horizontal' && arrows" type="previous"></slider-arrow>
<slider-arrow *ngIf="position === 'horizontal' && arrows" type="next"></slider-arrow>
</ng-container> </ng-container>
<ng-container *ngIf="type === 'dynamic'">
<li *ngFor="let tab of leftTabs; let i=index;" [class.uk-active]="tab.active" [style.max-width]="(position === 'horizontal')?'50%':null">
<a [routerLink]="tab.routerLink" [queryParams]="tab.queryParams" [ngClass]="tab.customClass" [relativeTo]="tab.relativeTo"
(click)="showActive(i)"
class="uk-text-capitalize uk-text-truncate uk-display-block">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li>
<li *ngFor="let tab of rightTabs; let i=index;" [style.max-width]="(position === 'horizontal')?'50%':null" [class.uk-active]="tab.active"
[ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''">
<a [routerLink]="tab.routerLink" [queryParams]="tab.queryParams" [ngClass]="tab.customClass" [relativeTo]="tab.relativeTo"
(click)="showActive(i)"
class="uk-text-capitalize uk-text-truncate uk-display-block">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li>
</ng-container>
<ng-container *ngIf="type === 'scrollable'">
<li *ngFor="let tab of leftTabs" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block" [class.uk-active]="tab.active">
<a routerLink="./" [fragment]="tab.id" queryParamsHandling="merge" [ngClass]="tab.customClass">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li>
<li *ngFor="let tab of rightTabs; let i=index;" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block"
[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">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li>
</ng-container>
</ul>
</div> </div>
<ng-container *ngIf="!isServer">
<slider-arrow *ngIf="position === 'horizontal' && arrows" type="previous"></slider-arrow>
<slider-arrow *ngIf="position === 'horizontal' && arrows" type="next"></slider-arrow>
</ng-container>
</div>
`, `,
}) })
export class SliderTabsComponent implements AfterViewInit, OnDestroy { export class SliderTabsComponent implements AfterViewInit, OnDestroy {
@ -149,18 +149,18 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
private observer: IntersectionObserver; private observer: IntersectionObserver;
private timeout: Timeout; private timeout: Timeout;
isServer: boolean; isServer: boolean;
constructor(private route: ActivatedRoute, constructor(private route: ActivatedRoute,
private router: Router, private router: Router,
private cdr: ChangeDetectorRef, private cdr: ChangeDetectorRef,
@Inject(PLATFORM_ID) private platform: any) { @Inject(PLATFORM_ID) private platform: any) {
this.isServer = isPlatformServer(this.platform); this.isServer = isPlatformServer(this.platform);
} }
ngAfterViewInit() { ngAfterViewInit() {
this.initTabs(); this.initTabs();
this.tabs.changes.subscribe(() => { this.tabs.changes.subscribe(() => {
this.initTabs(); this.initTabs();
}); });
} }
@ -194,7 +194,7 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
}); });
} }
} }
private scrollToStart() { private scrollToStart() {
this.subscriptions.push(UIkit.util.on(this.connect, 'shown', (event): void => { this.subscriptions.push(UIkit.util.on(this.connect, 'shown', (event): void => {
let index = event.detail[0].index(); let index = event.detail[0].index();
@ -204,7 +204,7 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
} }
})); }));
} }
private scrollable(slider = null) { private scrollable(slider = null) {
this.activeFragment(this.route.snapshot.fragment, slider); this.activeFragment(this.route.snapshot.fragment, slider);
this.subscriptions.push(this.route.fragment.subscribe(fragment => { this.subscriptions.push(this.route.fragment.subscribe(fragment => {
@ -212,7 +212,7 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
})); }));
this.setObserver(); this.setObserver();
} }
private setObserver() { private setObserver() {
if (this.observer) { if (this.observer) {
this.observer.disconnect(); this.observer.disconnect();
@ -249,7 +249,7 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
this.slider.show(this.activeIndex); this.slider.show(this.activeIndex);
} }
} }
private activeFragment(fragment, slider) { private activeFragment(fragment, slider) {
let index = 0; let index = 0;
if (fragment) { if (fragment) {
@ -268,15 +268,15 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
}); });
this.cdr.detectChanges(); this.cdr.detectChanges();
} }
get leftTabs(): SliderTabComponent[] { get leftTabs(): SliderTabComponent[] {
return this.tabs.toArray().filter(tab => tab.align === 'left'); return this.tabs.toArray().filter(tab => tab.align === 'left');
} }
get rightTabs(): SliderTabComponent[] { get rightTabs(): SliderTabComponent[] {
return this.tabs.toArray().filter(tab => tab.align === 'right'); return this.tabs.toArray().filter(tab => tab.align === 'right');
} }
ngOnDestroy() { ngOnDestroy() {
this.subscriptions.forEach(subscription => { this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) { if (subscription instanceof Subscription) {