Merge remote-tracking branch 'origin/Development' into Development

This commit is contained in:
George Kalampokis 2021-11-09 14:23:30 +02:00
commit 54b142000c
9 changed files with 84 additions and 50 deletions

View File

@ -49,7 +49,7 @@ public class TagController extends BaseController {
if (this.getApiContext().getOperationsContext().getElasticRepository().getDatasetRepository().exists()) { if (this.getApiContext().getOperationsContext().getElasticRepository().getDatasetRepository().exists()) {
DatasetCriteria criteria = new DatasetCriteria(); DatasetCriteria criteria = new DatasetCriteria();
criteria.setHasTags(true); criteria.setHasTags(true);
List<Tag> tags = this.getApiContext().getOperationsContext().getElasticRepository().getDatasetRepository().query(criteria).stream().map(Dataset::getTags).flatMap(Collection::stream).filter(StreamDistinctBy.distinctByKey(Tag::getId)).filter(tag -> tag.getName().startsWith(query)).collect(Collectors.toList()); List<Tag> tags = this.getApiContext().getOperationsContext().getElasticRepository().getDatasetRepository().query(criteria).stream().map(Dataset::getTags).flatMap(Collection::stream).filter(StreamDistinctBy.distinctByKey(Tag::getId)).filter(tag -> tag.getName().toLowerCase().startsWith(query.toLowerCase())).collect(Collectors.toList());
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<List<Tag>>().payload(tags).status(ApiMessageCode.NO_MESSAGE)); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<List<Tag>>().payload(tags).status(ApiMessageCode.NO_MESSAGE));
} else { } else {

View File

@ -42,7 +42,7 @@ public class LicenseManager {
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
licenseModels.addAll(remoteRepos.stream().map(item -> mapper.convertValue(item, LicenseModel.class)).collect(Collectors.toList())); licenseModels.addAll(remoteRepos.stream().map(item -> mapper.convertValue(item, LicenseModel.class)).collect(Collectors.toList()));
licenseModels = licenseModels.stream().filter(licenseModel -> licenseModel.getName().contains(query)).collect(Collectors.toList()); licenseModels = licenseModels.stream().filter(licenseModel -> licenseModel.getName().toLowerCase().contains(query.toLowerCase())).collect(Collectors.toList());
return licenseModels; return licenseModels;
} }
} }

View File

@ -22,7 +22,7 @@ public class LocalFetchManager {
public List<LocalFetchModel> getCurrency(String query) throws Exception { public List<LocalFetchModel> getCurrency(String query) throws Exception {
List<Map<String, String>> data = localFetcher.retrieveCurrency(); List<Map<String, String>> data = localFetcher.retrieveCurrency();
List<LocalFetchModel> result = data.stream().map(entry -> new LocalFetchModel(entry.get("name"), entry.get("value"))).collect(Collectors.toList()); List<LocalFetchModel> result = data.stream().map(entry -> new LocalFetchModel(entry.get("name"), entry.get("value"))).collect(Collectors.toList());
result = result.stream().filter(localFetchModel -> localFetchModel.getValue() != null).filter(StreamDistinctBy.distinctByKey(LocalFetchModel::getValue)).filter(localFetchModel -> localFetchModel.getName().contains(query)).collect(Collectors.toList()); result = result.stream().filter(localFetchModel -> localFetchModel.getValue() != null).filter(StreamDistinctBy.distinctByKey(LocalFetchModel::getValue)).filter(localFetchModel -> localFetchModel.getName().toLowerCase().contains(query.toLowerCase())).collect(Collectors.toList());
return result; return result;
} }
} }

View File

@ -1,7 +1,5 @@
<div class="row multiple-auto-complete" ngForm> <div class="row multiple-auto-complete" ngForm>
<!-- style="width: calc(100% - 28px) !important;"--> <mat-chip-list #chipList ngDefaultControl style="width: 100% !important;">
<mat-chip-list #chipList ngDefaultControl>
<!-- style="width: calc(100%) !important;"-->
<ng-container *ngIf="value as values"> <ng-container *ngIf="value as values">
<mat-chip *ngFor="let value of values" [disabled]="disabled" [selectable]="selectable" [removable]="removable" [ngClass]="computeClass(value)"> <mat-chip *ngFor="let value of values" [disabled]="disabled" [selectable]="selectable" [removable]="removable" [ngClass]="computeClass(value)">
<ng-container *ngIf="_selectedItems.get(stringify(value)) as selectedItem"> <ng-container *ngIf="_selectedItems.get(stringify(value)) as selectedItem">
@ -11,22 +9,23 @@
</ng-container> </ng-container>
</mat-chip> </mat-chip>
</ng-container> </ng-container>
<!-- <div style="height: 0 !important; width: calc(100% - 28px) !important; visibility: hidden !important;" matAutocompleteOrigin #origin="matAutocompleteOrigin"></div>--> <!-- <input matInput #autocompleteInput class="col" [class.hide-placeholder]="hidePlaceholder" [name]="id" autocomplete="off" #autocompleteTrigger="matAutocompleteTrigger" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($event)" (keydown)="onKeyDown($event)" [disabled]="disabled" (focus)="_onInputFocus()" (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur" (matChipInputTokenEnd)="_addItem($event)">-->
</mat-chip-list> <input matInput #autocompleteInput class="col"
<input matInput #autocompleteInput class="col" [class.hide-placeholder]="hidePlaceholder" [name]="id" autocomplete="off" #autocompleteTrigger="matAutocompleteTrigger" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($event)" (keydown)="onKeyDown($event)" [disabled]="disabled" (focus)="_onInputFocus()" (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur" (matChipInputTokenEnd)="_addItem($event)"> style="width: calc(100% - 8px) !important;"
<!-- <input matInput #autocompleteInput class="col"--> [class.hide-placeholder]="hidePlaceholder" [name]="id"
<!-- style="width: calc(100% - 28px) !important;"--> autocomplete="off" #autocompleteTrigger="matAutocompleteTrigger"
<!-- [class.hide-placeholder]="hidePlaceholder" [name]="id"--> [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue"
<!-- autocomplete="off" #autocompleteTrigger="matAutocompleteTrigger"--> (keyup)="onKeyUp($event)" (keydown)="onKeyDown($event)" [disabled]="disabled" (focus)="_onInputFocus()"
<!-- [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue"--> (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
<!-- (keyup)="onKeyUp($event)" (keydown)="onKeyDown($event)" [disabled]="disabled" (focus)="_onInputFocus()"--> [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur"
<!-- (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes"--> (matChipInputTokenEnd)="_addItem($event)"
<!-- [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur"--> [matAutocompleteConnectedTo]="origin">
<!-- (matChipInputTokenEnd)="_addItem($event)"-->
<!-- [matAutocompleteConnectedTo]="origin">-->
<!-- The attribute autocomplete="nope", set by downshift, is ignored in Chrome 67 and Opera 54 (latest at the time of writing) <!-- The attribute autocomplete="nope", set by downshift, is ignored in Chrome 67 and Opera 54 (latest at the time of writing)
<input matInput #autocompleteInput class="col" [name]="id" autocomplete="nope" #autocompleteTrigger="matAutocompleteTrigger" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($event)" (keydown)="onKeyDown($event)" [disabled]="disabled" (focus)="_onInputFocus()" (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur" (matChipInputTokenEnd)="_addItem($event)"> --> <input matInput #autocompleteInput class="col" [name]="id" autocomplete="nope" #autocompleteTrigger="matAutocompleteTrigger" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($event)" (keydown)="onKeyDown($event)" [disabled]="disabled" (focus)="_onInputFocus()" (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur" (matChipInputTokenEnd)="_addItem($event)"> -->
<mat-icon *ngIf="!disabled" class="align-arrow-right" matSuffix>arrow_drop_down</mat-icon> <mat-icon *ngIf="!disabled" class="align-arrow-right" matSuffix>arrow_drop_down</mat-icon>
<div style="height: 0 !important; width: 100% !important; visibility: hidden !important;" matAutocompleteOrigin #origin="matAutocompleteOrigin"></div>
</mat-chip-list>
<mat-autocomplete #autocomplete="matAutocomplete" [displayWith]="_displayFn.bind(this)" (optionSelected)="_optionSelected($event)"> <mat-autocomplete #autocomplete="matAutocomplete" [displayWith]="_displayFn.bind(this)" (optionSelected)="_optionSelected($event)">
<span *ngIf="_groupedItems"> <span *ngIf="_groupedItems">
<mat-optgroup *ngFor="let group of _groupedItems | async" [label]="group.title"> <mat-optgroup *ngFor="let group of _groupedItems | async" [label]="group.title">
@ -36,12 +35,17 @@
item: item item: item
}"></ng-template> }"></ng-template>
<div *ngIf="!_optionTemplate(item)" class="d-flex"> <div *ngIf="!_optionTemplate(item)" class="d-flex">
<div class="title-subtitle-fn">
<div class="title-fn"> <div class="title-fn">
<!-- <div class="title-fn-inner"> &lt;!&ndash;remove this if you want to see all the description &ndash;&gt;--> <div class="title-fn-inner">
<span>{{_titleFn(item)}}</span> <span *ngIf="!_optionTemplate(item)">{{_titleFn(item)}}</span>
<br *ngIf="_subtitleFn(item)"> </div>
<small *ngIf="_subtitleFn(item)">{{_subtitleFn(item)}}</small> </div>
<!-- </div>--> <div *ngIf="_subtitleFn(item)" class="subtitle-fn">
<div class="subtitle-fn-inner">
<small [innerHTML]="_subtitleFn(item)"></small>
</div>
</div>
</div> </div>
<span *ngIf="popupItemActionIcon" class="option-icon" (click)="_optionActionClick(item, $event)"><mat-icon>{{popupItemActionIcon}}</mat-icon></span> <span *ngIf="popupItemActionIcon" class="option-icon" (click)="_optionActionClick(item, $event)"><mat-icon>{{popupItemActionIcon}}</mat-icon></span>
</div> </div>
@ -49,29 +53,34 @@
</mat-optgroup> </mat-optgroup>
</span> </span>
<span *ngIf="!_groupedItems"> <span *ngIf="!_groupedItems">
<div *ngIf="_items | async as autocompleteItems; else loading"> <ng-container *ngIf="_items | async as autocompleteItems; else loading">
<ng-container *ngIf="autocompleteItems.length; else noItems"> <ng-container *ngIf="autocompleteItems.length">
<mat-option *ngFor="let item of autocompleteItems" [value]="item" [class.two-line-mat-option]="_subtitleFn(item) && !_optionTemplate(item)"> <mat-option *ngFor="let item of autocompleteItems" [value]="item" [class.two-line-mat-option]="_subtitleFn(item) && !_optionTemplate(item)">
<!-- <img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" /> --> <!-- <img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" /> -->
<ng-template #cellTemplate *ngIf="_optionTemplate(item)" [ngTemplateOutlet]="_optionTemplate(item)" [ngTemplateOutletContext]="{ <ng-template #cellTemplate *ngIf="_optionTemplate(item)" [ngTemplateOutlet]="_optionTemplate(item)" [ngTemplateOutletContext]="{
item: item item: item
}"></ng-template> }"></ng-template>
<div *ngIf="!_optionTemplate(item)" class="d-flex"> <div *ngIf="!_optionTemplate(item)" class="d-flex">
<div class="title-subtitle-fn">
<div class="title-fn"> <div class="title-fn">
<div class="title-fn-inner"> <!--remove this if you want to see all the description --> <div class="title-fn-inner">
<span *ngIf="!_optionTemplate(item)">{{_titleFn(item)}}</span> <span *ngIf="!_optionTemplate(item)">{{_titleFn(item)}}</span>
<br *ngIf="_subtitleFn(item)"> </div>
<small *ngIf="_subtitleFn(item)" [innerHTML]="_subtitleFn(item)"></small> </div>
<div *ngIf="_subtitleFn(item)" class="subtitle-fn">
<div class="subtitle-fn-inner">
<small [innerHTML]="_subtitleFn(item)"></small>
</div>
</div> </div>
</div> </div>
<span *ngIf="popupItemActionIcon" class="option-icon" (click)="_optionActionClick(item, $event)"><mat-icon>{{popupItemActionIcon}}</mat-icon></span> <span *ngIf="popupItemActionIcon" class="option-icon" (click)="_optionActionClick(item, $event)"><mat-icon>{{popupItemActionIcon}}</mat-icon></span>
</div> </div>
</mat-option> </mat-option>
</ng-container> </ng-container>
<ng-template #noItems> <ng-container *ngIf="!autocompleteItems.length && showNoResultsLabel && (queryValue == inputValue)">
<mat-option disabled="true">No results found!</mat-option> <mat-option disabled="true">No results found!</mat-option>
</ng-template> </ng-container>
</div> </ng-container>
<ng-template #loading> <ng-template #loading>
<mat-option disabled="true">loading...</mat-option> <mat-option disabled="true">loading...</mat-option>
</ng-template> </ng-template>

View File

@ -19,16 +19,34 @@
} }
.title-subtitle-fn {
height: auto;
width: calc(100% - 46px);
}
.title-fn-inner { .title-fn-inner {
width: inherit;
overflow: unset;
white-space: normal;
}
.title-fn {
width: 100%;
overflow: hidden;
text-overflow: unset !important;
white-space: normal;
}
.subtitle-fn-inner {
width: inherit; width: inherit;
height: inherit; height: inherit;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.title-fn { .subtitle-fn {
height: inherit; width: 100%;
width: calc(100% - 16px);
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
display: -webkit-box; display: -webkit-box;
@ -36,10 +54,10 @@
-moz-box-orient: vertical; -moz-box-orient: vertical;
-ms-box-orient: vertical; -ms-box-orient: vertical;
box-orient: vertical; box-orient: vertical;
-webkit-line-clamp: 2; -webkit-line-clamp: 1;
-moz-line-clamp: 2; -moz-line-clamp: 1;
-ms-line-clamp: 2; -ms-line-clamp: 1;
line-clamp: 2; line-clamp: 1;
} }
.option-icon { .option-icon {

View File

@ -11,7 +11,7 @@ import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/mu
import { BaseComponent } from '@common/base/base.component'; import { BaseComponent } from '@common/base/base.component';
import { isNullOrUndefined } from '@swimlane/ngx-datatable'; import { isNullOrUndefined } from '@swimlane/ngx-datatable';
import { BehaviorSubject, combineLatest, Observable, of as observableOf, Subject, Subscription } from 'rxjs'; import { BehaviorSubject, combineLatest, Observable, of as observableOf, Subject, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, mergeMap, startWith, takeUntil, switchMap } from 'rxjs/operators'; import {debounceTime, distinctUntilChanged, map, mergeMap, startWith, takeUntil, switchMap, tap} from 'rxjs/operators';
export class CustomComponentBase extends BaseComponent { export class CustomComponentBase extends BaseComponent {
constructor( constructor(
@ -57,6 +57,8 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
onSelectAutoCompleteValue = new BehaviorSubject<any>(null); onSelectAutoCompleteValue = new BehaviorSubject<any>(null);
valueAssignSubscription: Subscription; valueAssignSubscription: Subscription;
queryValue: string = "";
focused = false; focused = false;
controlType = 'multiple-autocomplete'; controlType = 'multiple-autocomplete';
describedBy = ''; describedBy = '';
@ -73,6 +75,7 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
get shouldLabelFloat() { return this.focused || !this.empty; } get shouldLabelFloat() { return this.focused || !this.empty; }
@Input() showNoResultsLabel: boolean = true;
@Input() hidePlaceholder: boolean = false; @Input() hidePlaceholder: boolean = false;
@Input() @Input()
get placeholder() { return this._placeholder; } get placeholder() { return this._placeholder; }
@ -264,6 +267,7 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
debounceTime(this.requestDelay), debounceTime(this.requestDelay),
distinctUntilChanged(), distinctUntilChanged(),
distinctUntilChanged(), distinctUntilChanged(),
tap(query => this.queryValue = query),
switchMap(query => this.filter(query))); switchMap(query => this.filter(query)));
if (this.configuration.groupingFn) { this._groupedItems = this._items.pipe(map(items => this.configuration.groupingFn(items))); } if (this.configuration.groupingFn) { this._groupedItems = this._items.pipe(map(items => this.configuration.groupingFn(items))); }
@ -348,7 +352,7 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
} }
get requestDelay(): number { get requestDelay(): number {
return this.configuration.requestDelay != null ? this.configuration.requestDelay : 400; return this.configuration.requestDelay != null ? this.configuration.requestDelay : 600;
} }
get minFilteringChars(): number { get minFilteringChars(): number {

View File

@ -35,7 +35,7 @@
</mat-option> </mat-option>
</ng-container> </ng-container>
<ng-template #noItems> <ng-template #noItems>
<mat-option disabled="true">No results found!</mat-option> <mat-option *ngIf="queryValue == inputValue" disabled="true">No results found!</mat-option>
</ng-template> </ng-template>
</div> </div>
<ng-template #loading> <ng-template #loading>

View File

@ -9,7 +9,7 @@ import { AutoCompleteGroup } from '@app/library/auto-complete/auto-complete-grou
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
import { BaseComponent } from '@common/base/base.component'; import { BaseComponent } from '@common/base/base.component';
import { Observable, of as observableOf, Subject } from 'rxjs'; import { Observable, of as observableOf, Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, mergeMap, startWith, takeUntil, switchMap } from 'rxjs/operators'; import {debounceTime, distinctUntilChanged, map, mergeMap, startWith, takeUntil, switchMap, tap} from 'rxjs/operators';
export class CustomComponentBase extends BaseComponent { export class CustomComponentBase extends BaseComponent {
@ -62,6 +62,7 @@ export class SingleAutoCompleteComponent extends _CustomComponentMixinBase imple
_groupedItems: Observable<AutoCompleteGroup[]>; _groupedItems: Observable<AutoCompleteGroup[]>;
_selectedItems: Map<string, any> = new Map<any, any>(); _selectedItems: Map<string, any> = new Map<any, any>();
queryValue: string = "";
get empty() { return (this.value == null) && (!this.inputValue || this.inputValue.length === 0); } get empty() { return (this.value == null) && (!this.inputValue || this.inputValue.length === 0); }
@ -224,6 +225,7 @@ export class SingleAutoCompleteComponent extends _CustomComponentMixinBase imple
startWith(null), startWith(null),
debounceTime(this.requestDelay), debounceTime(this.requestDelay),
distinctUntilChanged(), distinctUntilChanged(),
tap(query => this.queryValue = query),
switchMap(query => this.filter(query))); switchMap(query => this.filter(query)));
if (this.configuration.groupingFn) { this._groupedItems = this._items.pipe(map(items => this.configuration.groupingFn(items))); } if (this.configuration.groupingFn) { this._groupedItems = this._items.pipe(map(items => this.configuration.groupingFn(items))); }
@ -313,7 +315,7 @@ export class SingleAutoCompleteComponent extends _CustomComponentMixinBase imple
} }
get requestDelay(): number { get requestDelay(): number {
return this.configuration.requestDelay != null ? this.configuration.requestDelay : 400; return this.configuration.requestDelay != null ? this.configuration.requestDelay : 600;
} }
get minFilteringChars(): number { get minFilteringChars(): number {

View File

@ -9,7 +9,8 @@
<div mat-dialog-content class="row content"> <div mat-dialog-content class="row content">
<mat-form-field class="col pt-0 pb-2 mb-4 search"> <mat-form-field class="col pt-0 pb-2 mb-4 search">
<!-- <mat-label>{{'INVITATION-EDITOR.AUTOCOMPLETE-USER-EMAIL' | translate}}</mat-label> --> <!-- <mat-label>{{'INVITATION-EDITOR.AUTOCOMPLETE-USER-EMAIL' | translate}}</mat-label> -->
<app-multiple-auto-complete [formControl]="formGroup.get('users')" placeholder="{{'INVITATION-EDITOR.AUTOCOMPLETE-USER-EMAIL' | translate}}" [configuration]="usersAutoCompleteConfiguration"> <app-multiple-auto-complete [formControl]="formGroup.get('users')" placeholder="{{'INVITATION-EDITOR.AUTOCOMPLETE-USER-EMAIL' | translate}}"
[configuration]="usersAutoCompleteConfiguration" [showNoResultsLabel]="false">
</app-multiple-auto-complete> </app-multiple-auto-complete>
</mat-form-field> </mat-form-field>
<p class="d-flex m-0 hint"> <p class="d-flex m-0 hint">