diff --git a/web/src/app/administration/components/workbasket-access-items/workbasket-access-items.component.html b/web/src/app/administration/components/workbasket-access-items/workbasket-access-items.component.html index 1c204ebd2..d525e9d9d 100644 --- a/web/src/app/administration/components/workbasket-access-items/workbasket-access-items.component.html +++ b/web/src/app/administration/components/workbasket-access-items/workbasket-access-items.component.html @@ -42,7 +42,7 @@ 'has-warning': (accessItemsClone[index].accessId !== accessItem.value.accessId), 'has-error': !accessItem.value.accessId }"> + [displayError]="!isFieldValid('accessItem.value.accessId', index)" (selectedItem)="accessItemSelected($event, index)" (inputField)="focusNewInput($event)"> @@ -50,7 +50,7 @@ !accessItem.value.accessId && formSubmitAttempt}"> + [@validation]="toogleValidationAccessIdMap.get(index)" #htmlInputElement> @@ -94,4 +94,4 @@ - \ No newline at end of file + diff --git a/web/src/app/administration/components/workbasket-access-items/workbasket-access-items.component.ts b/web/src/app/administration/components/workbasket-access-items/workbasket-access-items.component.ts index fd1ccee29..51dd3a767 100644 --- a/web/src/app/administration/components/workbasket-access-items/workbasket-access-items.component.ts +++ b/web/src/app/administration/components/workbasket-access-items/workbasket-access-items.component.ts @@ -1,14 +1,21 @@ -import { Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; +import { Component, + ElementRef, + Input, + OnChanges, + OnDestroy, QueryList, + SimpleChanges, + ViewChildren } from '@angular/core'; import { Observable, Subscription } from 'rxjs'; import { Select } from '@ngxs/store'; -import { FormArray, FormBuilder, Validators } from '@angular/forms'; +import { FormArray, FormBuilder, FormControlDirective, Validators } from '@angular/forms'; import { Workbasket } from 'app/shared/models/workbasket'; import { customFieldCount, WorkbasketAccessItems } from 'app/shared/models/workbasket-access-items'; import { WorkbasketAccessItemsResource } from 'app/shared/models/workbasket-access-items-resource'; import { ACTION } from 'app/shared/models/action'; -import { SavingInformation, SavingWorkbasketService } from 'app/administration/services/saving-workbaskets.service'; +import { SavingInformation, + SavingWorkbasketService } from 'app/administration/services/saving-workbaskets.service'; import { WorkbasketService } from 'app/shared/services/workbasket/workbasket.service'; import { RequestInProgressService } from 'app/shared/services/request-in-progress/request-in-progress.service'; import { highlight } from 'theme/animations/validation.animation'; @@ -17,7 +24,9 @@ import { AccessIdDefinition } from 'app/shared/models/access-id'; import { EngineConfigurationSelectors } from 'app/shared/store/engine-configuration-store/engine-configuration.selectors'; import { NOTIFICATION_TYPES } from '../../../shared/models/notifications'; import { NotificationService } from '../../../shared/services/notifications/notification.service'; -import { AccessItemsCustomisation, CustomField, getCustomFields } from '../../../shared/models/customisation'; +import { AccessItemsCustomisation, + CustomField, + getCustomFields } from '../../../shared/models/customisation'; @Component({ selector: 'taskana-workbasket-access-items', @@ -35,6 +44,9 @@ export class WorkbasketAccessItemsComponent implements OnChanges, OnDestroy { @Input() active: string; + @ViewChildren('htmlInputElement') inputs: QueryList; + + badgeMessage = ''; @Select(EngineConfigurationSelectors.accessItemsCustomisation) accessItemsCustomization$: Observable; @@ -52,6 +64,7 @@ export class WorkbasketAccessItemsComponent implements OnChanges, OnDestroy { toogleValidationAccessIdMap = new Map(); private initialized = false; + private added = false; constructor( private workbasketService: WorkbasketService, @@ -71,13 +84,10 @@ export class WorkbasketAccessItemsComponent implements OnChanges, OnDestroy { this.customFields$ = this.accessItemsCustomization$.pipe(getCustomFields(customFieldCount)); } - setAccessItemsGroups(accessItems: Array) { - const AccessItemsFormGroups = accessItems.map(accessItem => this.formBuilder.group(accessItem)); - AccessItemsFormGroups.forEach(accessItemGroup => { - accessItemGroup.controls.accessId.setValidators(Validators.required); + ngAfterViewInit() { + this.inputs.changes.subscribe(next => { + if (this.added) next.last.nativeElement.focus(); }); - const AccessItemsFormArray = this.formBuilder.array(AccessItemsFormGroups); - this.AccessItemsForm.setControl('accessItemsGroups', AccessItemsFormArray); } ngOnChanges(changes: SimpleChanges): void { @@ -89,6 +99,39 @@ export class WorkbasketAccessItemsComponent implements OnChanges, OnDestroy { } } + private init() { + if (!this.workbasket._links.accessItems) { + return; + } + this.requestInProgress = true; + this.accessItemsubscription = this.workbasketService.getWorkBasketAccessItems(this.workbasket._links.accessItems.href) + .subscribe((accessItemsResource: WorkbasketAccessItemsResource) => { + this.accessItemsResource = accessItemsResource; + this.setAccessItemsGroups(accessItemsResource.accessItems); + this.accessItemsClone = this.cloneAccessItems(accessItemsResource.accessItems); + this.accessItemsResetClone = this.cloneAccessItems(accessItemsResource.accessItems); + this.requestInProgress = false; + }); + this.savingAccessItemsSubscription = this.savingWorkbaskets.triggeredAccessItemsSaving() + .subscribe((savingInformation: SavingInformation) => { + if (this.action === ACTION.COPY) { + this.accessItemsResource._links.self.href = savingInformation.url; + this.setWorkbasketIdForCopy(savingInformation.workbasketId); + this.onSave(); + } + }); + this.initialized = true; + } + + setAccessItemsGroups(accessItems: Array) { + const AccessItemsFormGroups = accessItems.map(accessItem => this.formBuilder.group(accessItem)); + AccessItemsFormGroups.forEach(accessItemGroup => { + accessItemGroup.controls.accessId.setValidators(Validators.required); + }); + const AccessItemsFormArray = this.formBuilder.array(AccessItemsFormGroups); + this.AccessItemsForm.setControl('accessItemsGroups', AccessItemsFormArray); + } + addAccessItem() { const workbasketAccessItems = new WorkbasketAccessItems(); workbasketAccessItems.workbasketId = this.workbasket.workbasketId; @@ -97,6 +140,7 @@ export class WorkbasketAccessItemsComponent implements OnChanges, OnDestroy { newForm.controls.accessId.setValidators(Validators.required); this.accessItemsGroups.push(newForm); this.accessItemsClone.push(workbasketAccessItems); + this.added = true; } clear() { @@ -140,39 +184,6 @@ export class WorkbasketAccessItemsComponent implements OnChanges, OnDestroy { this.accessItemsGroups.controls[row].get('accessName').setValue(accessItem.name); } - ngOnDestroy(): void { - if (this.accessItemsubscription) { - this.accessItemsubscription.unsubscribe(); - } - if (this.savingAccessItemsSubscription) { - this.savingAccessItemsSubscription.unsubscribe(); - } - } - - private init() { - this.initialized = true; - if (!this.workbasket._links.accessItems) { - return; - } - this.requestInProgress = true; - this.accessItemsubscription = this.workbasketService.getWorkBasketAccessItems(this.workbasket._links.accessItems.href) - .subscribe((accessItemsResource: WorkbasketAccessItemsResource) => { - this.accessItemsResource = accessItemsResource; - this.setAccessItemsGroups(accessItemsResource.accessItems); - this.accessItemsClone = this.cloneAccessItems(accessItemsResource.accessItems); - this.accessItemsResetClone = this.cloneAccessItems(accessItemsResource.accessItems); - this.requestInProgress = false; - }); - this.savingAccessItemsSubscription = this.savingWorkbaskets.triggeredAccessItemsSaving() - .subscribe((savingInformation: SavingInformation) => { - if (this.action === ACTION.COPY) { - this.accessItemsResource._links.self.href = savingInformation.url; - this.setWorkbasketIdForCopy(savingInformation.workbasketId); - this.onSave(); - } - }); - } - private onSave() { this.requestInProgressService.setRequestInProgress(true); this.workbasketService.updateWorkBasketAccessItem( @@ -212,4 +223,20 @@ export class WorkbasketAccessItemsComponent implements OnChanges, OnDestroy { getAccessItemCustomProperty(customNumber: number): string { return `permCustom${customNumber}`; } + + focusNewInput(input: ElementRef) { + if (this.added) { + input.nativeElement.focus(); + } + } + + + ngOnDestroy(): void { + if (this.accessItemsubscription) { + this.accessItemsubscription.unsubscribe(); + } + if (this.savingAccessItemsSubscription) { + this.savingAccessItemsSubscription.unsubscribe(); + } + } } diff --git a/web/src/app/shared/components/type-ahead/type-ahead.component.ts b/web/src/app/shared/components/type-ahead/type-ahead.component.ts index 99fe48cf8..95e977ff1 100644 --- a/web/src/app/shared/components/type-ahead/type-ahead.component.ts +++ b/web/src/app/shared/components/type-ahead/type-ahead.component.ts @@ -1,4 +1,11 @@ -import { Component, OnInit, Input, ViewChild, forwardRef, Output, EventEmitter } from '@angular/core'; +import { Component, + OnInit, + Input, + ViewChild, + forwardRef, + Output, + EventEmitter, + OnChanges, ElementRef, AfterViewInit } from '@angular/core'; import { Observable } from 'rxjs'; import { TypeaheadMatch } from 'ngx-bootstrap/typeahead'; @@ -21,7 +28,7 @@ import { AccessIdDefinition } from 'app/shared/models/access-id'; } ] }) -export class TypeAheadComponent implements OnInit, ControlValueAccessor { +export class TypeAheadComponent implements AfterViewInit, ControlValueAccessor { dataSource: any; typing = false; @@ -46,6 +53,9 @@ export class TypeAheadComponent implements OnInit, ControlValueAccessor { @Output() selectedItem = new EventEmitter(); + @Output() + inputField = new EventEmitter(); + @ViewChild('inputTypeAhead', { static: false }) private inputTypeAhead; @@ -96,7 +106,8 @@ export class TypeAheadComponent implements OnInit, ControlValueAccessor { constructor(private accessIdsService: AccessIdsService) { } - ngOnInit() { + ngAfterViewInit() { + this.inputField.emit(this.inputTypeAhead); } initializeDataSource() {