Adds preview of dataset template, adds delete with spacebar on multiple autocomplete
This commit is contained in:
parent
b8f3c5af70
commit
32caed9f6f
|
@ -31,7 +31,9 @@ export interface MultipleAutoCompleteConfiguration {
|
|||
optionTemplate?: TemplateRef<any>;
|
||||
// Selected value formating template
|
||||
selectedValueTemplate?: TemplateRef<any>;
|
||||
|
||||
// Display icon that opens popup
|
||||
popupItemActionIcon?: string;
|
||||
|
||||
autoSelectFirstOptionOnBlur?: boolean;
|
||||
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
</mat-chip>
|
||||
</ng-container>
|
||||
</mat-chip-list>
|
||||
<input matInput #autocompleteInput class="col" [name]="id" autocomplete="off" #autocompleteTrigger="matAutocompleteTrigger" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($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="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)">
|
||||
<!-- 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)" [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-autocomplete #autocomplete="matAutocomplete" [displayWith]="_displayFn.bind(this)" (optionSelected)="_optionSelected($event)">
|
||||
<span *ngIf="_groupedItems">
|
||||
|
@ -22,10 +22,13 @@
|
|||
<ng-template #cellTemplate *ngIf="_optionTemplate(item)" [ngTemplateOutlet]="_optionTemplate(item)" [ngTemplateOutletContext]="{
|
||||
item: item
|
||||
}"></ng-template>
|
||||
<div *ngIf="!_optionTemplate(item)">
|
||||
<span>{{_titleFn(item)}}</span>
|
||||
<br *ngIf="_subtitleFn(item)">
|
||||
<small *ngIf="_subtitleFn(item)">{{_subtitleFn(item)}}</small>
|
||||
<div *ngIf="!_optionTemplate(item)" class="d-flex">
|
||||
<div class="title-fn">
|
||||
<span>{{_titleFn(item)}}</span>
|
||||
<br *ngIf="_subtitleFn(item)">
|
||||
<small *ngIf="_subtitleFn(item)">{{_subtitleFn(item)}}</small>
|
||||
</div>
|
||||
<span *ngIf="popupItemActionIcon" class="option-icon" (click)="_optionActionClick(item, $event)"><mat-icon>{{popupItemActionIcon}}</mat-icon></span>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-optgroup>
|
||||
|
@ -38,10 +41,13 @@
|
|||
<ng-template #cellTemplate *ngIf="_optionTemplate(item)" [ngTemplateOutlet]="_optionTemplate(item)" [ngTemplateOutletContext]="{
|
||||
item: item
|
||||
}"></ng-template>
|
||||
<div *ngIf="!_optionTemplate(item)">
|
||||
<span *ngIf="!_optionTemplate(item)">{{_titleFn(item)}}</span>
|
||||
<br *ngIf="_subtitleFn(item)">
|
||||
<small *ngIf="_subtitleFn(item)">{{_subtitleFn(item)}}</small>
|
||||
<div *ngIf="!_optionTemplate(item)" class="d-flex">
|
||||
<div class="title-fn">
|
||||
<span *ngIf="!_optionTemplate(item)">{{_titleFn(item)}}</span>
|
||||
<br *ngIf="_subtitleFn(item)">
|
||||
<small *ngIf="_subtitleFn(item)">{{_subtitleFn(item)}}</small>
|
||||
</div>
|
||||
<span *ngIf="popupItemActionIcon" class="option-icon" (click)="_optionActionClick(item, $event)"><mat-icon>{{popupItemActionIcon}}</mat-icon></span>
|
||||
</div>
|
||||
</mat-option>
|
||||
</ng-container>
|
||||
|
|
|
@ -19,6 +19,23 @@
|
|||
|
||||
}
|
||||
|
||||
.title-fn {
|
||||
flex-grow: 1;
|
||||
white-space: nowrap;
|
||||
width: calc(100% - 16px);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.option-icon {
|
||||
mat-icon {
|
||||
margin: 0px 5px 0px 10px;
|
||||
}
|
||||
mat-icon:hover {
|
||||
color: #129d99;
|
||||
}
|
||||
}
|
||||
|
||||
.two-line-mat-option {
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { FocusMonitor } from '@angular/cdk/a11y';
|
||||
import { COMMA, ENTER } from '@angular/cdk/keycodes';
|
||||
import { BACKSPACE, COMMA, ENTER } from '@angular/cdk/keycodes';
|
||||
import { Component, DoCheck, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Optional, Output, Self, SimpleChanges, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { ControlValueAccessor, FormGroupDirective, NgControl, NgForm } from '@angular/forms';
|
||||
import { ErrorStateMatcher, MatChipInputEvent, mixinErrorState } from '@angular/material';
|
||||
|
@ -45,6 +45,9 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
|
|||
@Output() optionSelected: EventEmitter<any> = new EventEmitter();
|
||||
@Output() optionRemoved: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@Output() optionActionClicked: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
|
||||
id = `multiple-autocomplete-${MultipleAutoCompleteComponent.nextId++}`;
|
||||
stateChanges = new Subject<void>();
|
||||
focused = false;
|
||||
|
@ -200,6 +203,12 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
|
|||
}
|
||||
}
|
||||
|
||||
public onKeyDown(event) {
|
||||
if (event.keyCode === BACKSPACE && event.target.value.length === 0 && this._selectedItems.size > 0) {
|
||||
this._removeSelectedItem(Array.from(this._selectedItems.values()).pop(), event);
|
||||
}
|
||||
}
|
||||
|
||||
private _setValue(value: any) {
|
||||
this.value = value;
|
||||
this.pushChanges(this.value);
|
||||
|
@ -301,6 +310,10 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
|
|||
return this.configuration.autoSelectFirstOptionOnBlur != null ? this.configuration.autoSelectFirstOptionOnBlur : false;
|
||||
}
|
||||
|
||||
get popupItemActionIcon(): string {
|
||||
return this.configuration.popupItemActionIcon != null ? this.configuration.popupItemActionIcon : '';
|
||||
}
|
||||
|
||||
//Chip Functions
|
||||
_addItem(event: MatChipInputEvent): void {
|
||||
|
||||
|
@ -329,4 +342,9 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
|
|||
this.autocompleteInput.nativeElement.focus();
|
||||
this.pushChanges(this.value);
|
||||
}
|
||||
|
||||
_optionActionClick(item: any, event: MouseEvent): void {
|
||||
if (event != null) { event.stopPropagation(); }
|
||||
this.optionActionClicked.emit(item);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<div class="template-container">
|
||||
<div mat-dialog-title class="row d-flex m-0 header" (click)="closeDialog()">
|
||||
<span class="template-title align-self-center">{{'DMP-LISTING.COLUMNS.PROFILE' | translate}} - {{data.template.label}}</span>
|
||||
<span class="ml-auto align-self-center"><mat-icon class="close-icon">close</mat-icon></span>
|
||||
</div>
|
||||
<div *ngIf="progressIndication" class="progress-bar">
|
||||
<mat-progress-bar color="primary" mode="indeterminate"></mat-progress-bar>
|
||||
</div>
|
||||
<div mat-dialog-content class="definition-content">
|
||||
<app-dataset-description *ngIf="datasetProfileDefinitionFormGroup && datasetProfileDefinitionModel" [form]="datasetProfileDefinitionFormGroup" [visibilityRules]="datasetProfileDefinitionModel.rules" [datasetProfileId]="data.template.id"></app-dataset-description>
|
||||
</div>
|
||||
<div mat-mat-dialog-actions *ngIf="datasetProfileDefinitionFormGroup">
|
||||
<div class="col-auto d-flex pb-4 pt-2">
|
||||
<button mat-raised-button type="button" class="start-btn ml-auto" (click)="select()">{{'TYPES.EXTERNAL-DATASET-TYPE.SELECT' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,42 @@
|
|||
.template-container {
|
||||
.header {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 89px;
|
||||
background-color: #129D99;
|
||||
color: #FFFFFF;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.template-title {
|
||||
margin-left: 37px;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
cursor: pointer;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.close-icon:hover {
|
||||
background-color: #fefefe6e !important;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.definition-content {
|
||||
display: block;
|
||||
margin: 0px;
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.start-btn {
|
||||
background: #129d99 0% 0% no-repeat padding-box;
|
||||
border: 1px solid #129d99;
|
||||
border-radius: 30px;
|
||||
opacity: 1;
|
||||
width: 101px;
|
||||
height: 43px;
|
||||
color: #ffffff;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { DatasetWizardService } from '@app/core/services/dataset-wizard/dataset-wizard.service';
|
||||
import { ProgressIndicationService } from '@app/core/services/progress-indication/progress-indication-service';
|
||||
import { DatasetDescriptionFormEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model';
|
||||
import { BaseComponent } from '@common/base/base.component';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dataset-preview-dialog-component',
|
||||
templateUrl: 'dataset-preview-dialog.component.html',
|
||||
styleUrls: ['./dataset-preview-dialog.component.scss'],
|
||||
})
|
||||
export class DatasetPreviewDialogComponent extends BaseComponent implements OnInit {
|
||||
|
||||
datasetProfileDefinitionModel: DatasetDescriptionFormEditorModel;
|
||||
datasetProfileDefinitionFormGroup: FormGroup;
|
||||
progressIndication = false;
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<DatasetPreviewDialogComponent>,
|
||||
private datasetWizardService: DatasetWizardService,
|
||||
private progressIndicationService: ProgressIndicationService,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.progressIndicationService.getProgressIndicationObservable().pipe(takeUntil(this._destroyed)).subscribe(x => {
|
||||
setTimeout(() => { this.progressIndication = x; });
|
||||
});
|
||||
|
||||
if (this.data && this.data.template) {
|
||||
this.datasetWizardService.getDefinition(this.data.template.id)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(item => {
|
||||
this.datasetProfileDefinitionModel = new DatasetDescriptionFormEditorModel().fromModel(item);
|
||||
this.datasetProfileDefinitionFormGroup = this.datasetProfileDefinitionModel.buildForm();
|
||||
this.datasetProfileDefinitionFormGroup.disable();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
select(): void {
|
||||
this.dialogRef.close(true);
|
||||
}
|
||||
|
||||
closeDialog(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -48,6 +48,7 @@ import { NgxDropzoneModule } from 'ngx-dropzone';
|
|||
import { DmpToDatasetDialogComponent } from './dmp-to-dataset/dmp-to-dataset-dialog.component';
|
||||
import { FormProgressIndicationComponent } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component';
|
||||
import { FormProgressIndicationModule } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module';
|
||||
import { DatasetPreviewDialogComponent } from './dataset-preview/dataset-preview-dialog.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -99,7 +100,8 @@ import { FormProgressIndicationModule } from '../misc/dataset-description-form/c
|
|||
MainInfoComponent,
|
||||
FundingInfoComponent,
|
||||
DatasetInfoComponent,
|
||||
LicenseInfoComponent
|
||||
LicenseInfoComponent,
|
||||
DatasetPreviewDialogComponent
|
||||
],
|
||||
entryComponents: [
|
||||
DmpInvitationDialogComponent,
|
||||
|
@ -114,7 +116,8 @@ import { FormProgressIndicationModule } from '../misc/dataset-description-form/c
|
|||
AddCostComponent,
|
||||
StartNewDmpDialogComponent,
|
||||
StartNewDatasetDialogComponent,
|
||||
DatasetEditorDetailsComponent
|
||||
DatasetEditorDetailsComponent,
|
||||
DatasetPreviewDialogComponent
|
||||
]
|
||||
})
|
||||
export class DmpModule { }
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</div>
|
||||
<div class="profile-form">
|
||||
<mat-form-field>
|
||||
<app-multiple-auto-complete required='true' [formControl]="formGroup.get('profiles')" placeholder="{{'DMP-EDITOR.FIELDS.SELECT-TEMPLATE' | translate}}" [configuration]="profilesAutoCompleteConfiguration" (optionRemoved)="onRemoveTemplate($event)">
|
||||
<app-multiple-auto-complete required='true' [formControl]="formGroup.get('profiles')" placeholder="{{'DMP-EDITOR.FIELDS.SELECT-TEMPLATE' | translate}}" [configuration]="profilesAutoCompleteConfiguration" (optionRemoved)="onRemoveTemplate($event)" (optionActionClicked)="onPreviewTemplate($event)">
|
||||
</app-multiple-auto-complete>
|
||||
<mat-error *ngIf="formGroup.get('profiles').hasError('backendError')">
|
||||
{{formGroup.get('profiles').getError('backendError').message}}</mat-error>
|
||||
|
|
|
@ -24,6 +24,7 @@ import { DatasetDescriptionFormEditorModel } from '@app/ui/misc/dataset-descript
|
|||
import { DatasetWizardEditorModel } from '@app/ui/dataset/dataset-wizard/dataset-wizard-editor.model';
|
||||
import { DmpListingModel } from '@app/core/model/dmp/dmp-listing';
|
||||
import { UiNotificationService, SnackBarNotificationLevel } from '@app/core/services/notification/ui-notification-service';
|
||||
import { DatasetPreviewDialogComponent } from '../../dataset-preview/dataset-preview-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'dataset-info',
|
||||
|
@ -49,6 +50,7 @@ export class DatasetInfoComponent extends BaseComponent implements OnInit {
|
|||
profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration;
|
||||
|
||||
datasetProfileDefinitionModel: DatasetDescriptionFormEditorModel;
|
||||
datasetProfileDefinitionFormGroup: FormGroup;
|
||||
|
||||
constructor(
|
||||
private language: TranslateService,
|
||||
|
@ -71,7 +73,8 @@ export class DatasetInfoComponent extends BaseComponent implements OnInit {
|
|||
initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
|
||||
displayFn: (item) => item['label'],
|
||||
titleFn: (item) => item['label'],
|
||||
subtitleFn: (item) => item['description']
|
||||
subtitleFn: (item) => item['description'],
|
||||
popupItemActionIcon: 'visibility'
|
||||
};
|
||||
|
||||
if (this.formGroup.get('definition')) { this.selectedDmpProfileDefinition = this.formGroup.get('definition').value; }
|
||||
|
@ -84,7 +87,8 @@ export class DatasetInfoComponent extends BaseComponent implements OnInit {
|
|||
initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
|
||||
displayFn: (item) => item['label'],
|
||||
titleFn: (item) => item['label'],
|
||||
subtitleFn: (item) => item['description']
|
||||
subtitleFn: (item) => item['description'],
|
||||
popupItemActionIcon: 'visibility'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -205,4 +209,30 @@ export class DatasetInfoComponent extends BaseComponent implements OnInit {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
onPreviewTemplate(event) {
|
||||
const dialogRef = this.dialog.open(DatasetPreviewDialogComponent, {
|
||||
width: '590px',
|
||||
minHeight: '200px',
|
||||
restoreFocus: false,
|
||||
data: {
|
||||
template: event
|
||||
},
|
||||
panelClass: 'custom-modalbox'
|
||||
});
|
||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||
if (result) {
|
||||
let profiles = this.formGroup.get('profiles').value;
|
||||
profiles.push(event);
|
||||
this.formGroup.get('profiles').setValue(profiles);
|
||||
this.profilesAutoCompleteConfiguration = {
|
||||
filterFn: this.filterProfiles.bind(this),
|
||||
initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
|
||||
displayFn: (item) => item['label'],
|
||||
titleFn: (item) => item['label'],
|
||||
subtitleFn: (item) => item['description']
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
.expansion-panel {
|
||||
// background-color: #eeeeee54;
|
||||
background-color: white;
|
||||
margin-bottom: 1em;
|
||||
// margin-bottom: 1em;
|
||||
}
|
||||
.addOneFieldButton {
|
||||
margin-top: -15px;
|
||||
|
|
|
@ -667,6 +667,10 @@ hr {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.custom-modalbox > mat-dialog-container {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
@media (min-width: 576px) {
|
||||
.container {
|
||||
max-width: 540px;
|
||||
|
|
Loading…
Reference in New Issue