TSK-1039: Autofocus AccessID field after adding a new AccessID in Workbasket

This commit is contained in:
Tristan Eisermann 2020-06-15 10:52:21 +02:00 committed by Tristan2357
parent 716ad7a7df
commit 015ba38a25
3 changed files with 87 additions and 49 deletions

View File

@ -42,7 +42,7 @@
'has-warning': (accessItemsClone[index].accessId !== accessItem.value.accessId),
'has-error': !accessItem.value.accessId }">
<taskana-type-ahead formControlName="accessId" placeHolderMessage="* Access id is required" [validationValue]="toogleValidationAccessIdMap.get(index)"
[displayError]="!isFieldValid('accessItem.value.accessId', index)" (selectedItem)="accessItemSelected($event, index)"></taskana-type-ahead>
[displayError]="!isFieldValid('accessItem.value.accessId', index)" (selectedItem)="accessItemSelected($event, index)" (inputField)="focusNewInput($event)"></taskana-type-ahead>
</td>
<ng-template #accessIdInput>
<td class="input-group text-align text-width">
@ -50,7 +50,7 @@
!accessItem.value.accessId && formSubmitAttempt}">
<input type="text" class="form-control" formControlName="accessId" placeholder="{{accessItem.invalid?
'* Access id is required': ''}}"
[@validation]="toogleValidationAccessIdMap.get(index)">
[@validation]="toogleValidationAccessIdMap.get(index)" #htmlInputElement>
</div>
</td>
</ng-template>

View File

@ -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<ElementRef>;
badgeMessage = '';
@Select(EngineConfigurationSelectors.accessItemsCustomisation) accessItemsCustomization$: Observable<AccessItemsCustomisation>;
@ -52,6 +64,7 @@ export class WorkbasketAccessItemsComponent implements OnChanges, OnDestroy {
toogleValidationAccessIdMap = new Map<number, boolean>();
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<WorkbasketAccessItems>) {
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<WorkbasketAccessItems>) {
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();
}
}
}

View File

@ -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<AccessIdDefinition>();
@Output()
inputField = new EventEmitter<ElementRef>();
@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() {