bug fixing

This commit is contained in:
lotte
2019-02-25 09:57:46 +01:00
parent 3c104a460b
commit 35be122eea
13 changed files with 93 additions and 80 deletions

View File

@@ -175,7 +175,7 @@
},
"view": {
"head": "View Item",
"title": "Item Edit - Item"
"title": "Item Edit - View"
},
"curate": {
"head": "Curate",

View File

@@ -7,19 +7,20 @@
<div *ngIf="(editable | async)" class="field-container">
<ds-input-suggestions [suggestions]="(metadataFieldSuggestions | async)"
[(ngModel)]="metadata.key"
(submitSuggestion)="update(suggestionControl.control)"
(clickSuggestion)="update(suggestionControl.control)"
(typeSuggestion)="update(suggestionControl.control)"
(blur)="checkValidity(suggestionControl.control)"
(submitSuggestion)="update(suggestionControl)"
(clickSuggestion)="update(suggestionControl)"
(typeSuggestion)="update(suggestionControl)"
(dsClickOutside)="checkValidity(suggestionControl)"
(findSuggestions)="findMetadataFieldSuggestions($event)"
#suggestionControl="ngModel"
[dsInListValidator]="metadataFields | async"
[valid]="(valid | async)"
[dsInListValidator]="metadataFields"
[valid]="(valid | async) !== false"
dsAutoFocus autoFocusSelector=".suggestion_input"
[ngModelOptions]="{standalone: true}"
></ds-input-suggestions>
</div>
<small class="text-danger"
*ngIf="!(valid | async)">{{"item.edit.metadata.metadatafield.invalid" | translate}}</small>
*ngIf="(valid | async) === false">{{"item.edit.metadata.metadatafield.invalid" | translate}}</small>
</div>
</td>
<td class="w-100">

View File

@@ -11,7 +11,7 @@ import { FieldChangeType } from '../../../../core/data/object-updates/object-upd
import { FieldUpdate } from '../../../../core/data/object-updates/object-updates.reducer';
import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service';
import { getSucceededRemoteData } from '../../../../core/shared/operators';
import { FormControl } from '@angular/forms';
import { NgModel } from '@angular/forms';
@Component({
// tslint:disable-next-line:component-selector
@@ -27,14 +27,22 @@ export class EditInPlaceFieldComponent implements OnInit, OnChanges {
* The current field, value and state of the metadatum
*/
@Input() fieldUpdate: FieldUpdate;
/**
* The current url of this page
*/
@Input() url: string;
/**
* List of strings with all metadata field keys available
*/
@Input() metadataFields: string[];
/**
* The metadatum of this field
*/
metadata: Metadatum;
/**
* Emits whether or not this field is currently editable
*/
@@ -50,11 +58,6 @@ export class EditInPlaceFieldComponent implements OnInit, OnChanges {
*/
metadataFieldSuggestions: BehaviorSubject<InputSuggestion[]> = new BehaviorSubject([]);
/**
* List of strings with all metadata field keys available
*/
metadataFields: Observable<string[]>;
constructor(
private metadataFieldService: RegistryService,
private objectUpdatesService: ObjectUpdatesService,
@@ -67,26 +70,26 @@ export class EditInPlaceFieldComponent implements OnInit, OnChanges {
ngOnInit(): void {
this.editable = this.objectUpdatesService.isEditable(this.url, this.metadata.uuid);
this.valid = this.objectUpdatesService.isValid(this.url, this.metadata.uuid);
this.metadataFields = this.findMetadataFields()
}
/**
* Sends a new change update for this field to the object updates service
*/
update(control?: FormControl) {
update(ngModel?: NgModel) {
this.objectUpdatesService.saveChangeFieldUpdate(this.url, this.metadata);
if (hasValue(control)) {
this.checkValidity(control);
if (hasValue(ngModel)) {
this.checkValidity(ngModel);
}
}
/**
* Method to check the validity of a form control
* @param control The form control to check
* @param ngModel
*/
private checkValidity(control: FormControl) {
control.updateValueAndValidity();
this.objectUpdatesService.setValidFieldUpdate(this.url, this.metadata.uuid, control.valid);
private checkValidity(ngModel: NgModel) {
ngModel.control.setValue(ngModel.viewModel);
ngModel.control.updateValueAndValidity();
this.objectUpdatesService.setValidFieldUpdate(this.url, this.metadata.uuid, ngModel.control.valid);
}
/**
@@ -124,6 +127,7 @@ export class EditInPlaceFieldComponent implements OnInit, OnChanges {
* @param query The query to look for
*/
findMetadataFieldSuggestions(query: string): void {
if (isNotEmpty(query)) {
this.metadataFieldService.queryMetadataFields(query).pipe(
// getSucceededRemoteData(),
take(1),
@@ -134,20 +138,13 @@ export class EditInPlaceFieldComponent implements OnInit, OnChanges {
return {
displayValue: field.toString().split('.').join('.&#8203;'),
value: field.toString()
}
};
})
)
);
} else {
this.metadataFieldSuggestions.next([]);
}
/**
* Method to request all metadata fields and convert them to a list of strings
*/
findMetadataFields(): Observable<string[]> {
return this.metadataFieldService.getAllMetadataFields().pipe(
getSucceededRemoteData(),
take(1),
map((remoteData$) => remoteData$.payload.page.map((field: MetadataField) => field.toString())));
}
/**

View File

@@ -33,6 +33,7 @@
<tr *ngFor="let updateValue of ((updates$ | async)| dsObjectValues); trackBy: trackUpdate"
ds-edit-in-place-field
[fieldUpdate]="updateValue || {}"
[metadataFields]="metadataFields$ | async"
[url]="url"
[ngClass]="{
'table-warning': updateValue.changeType === 0,

View File

@@ -11,12 +11,14 @@ import {
Identifiable
} from '../../../core/data/object-updates/object-updates.reducer';
import { Metadatum } from '../../../core/shared/metadatum.model';
import { first, map, switchMap, tap } from 'rxjs/operators';
import { first, map, switchMap, take, tap } from 'rxjs/operators';
import { getSucceededRemoteData } from '../../../core/shared/operators';
import { RemoteData } from '../../../core/data/remote-data';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { GLOBAL_CONFIG, GlobalConfig } from '../../../../config';
import { TranslateService } from '@ngx-translate/core';
import { RegistryService } from '../../../core/registry/registry.service';
import { MetadataField } from '../../../core/metadata/metadatafield.model';
@Component({
selector: 'ds-item-metadata',
@@ -47,6 +49,11 @@ export class ItemMetadataComponent implements OnInit {
private notitifactionPrefix = 'item.edit.metadata.notifications.';
/**
* Observable with a list of strings with all existing metadata field keys
*/
metadataFields$: Observable<string[]>;
constructor(
private itemService: ItemDataService,
private objectUpdatesService: ObjectUpdatesService,
@@ -54,7 +61,8 @@ export class ItemMetadataComponent implements OnInit {
private notificationsService: NotificationsService,
private translateService: TranslateService,
@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig,
private route: ActivatedRoute
private route: ActivatedRoute,
private metadataFieldService: RegistryService,
) {
}
@@ -63,6 +71,7 @@ export class ItemMetadataComponent implements OnInit {
* Set up and initialize all fields
*/
ngOnInit(): void {
this.metadataFields$ = this.findMetadataFields()
this.route.parent.data.pipe(map((data) => data.item))
.pipe(
first(),
@@ -208,4 +217,14 @@ export class ItemMetadataComponent implements OnInit {
return this.translateService.instant(this.notitifactionPrefix + key + '.content');
}
/**
* Method to request all metadata fields and convert them to a list of strings
*/
findMetadataFields(): Observable<string[]> {
return this.metadataFieldService.getAllMetadataFields().pipe(
getSucceededRemoteData(),
take(1),
map((remoteData$) => remoteData$.payload.page.map((field: MetadataField) => field.toString())));
}
}

View File

@@ -78,7 +78,7 @@ const initialFieldState = { editable: false, isNew: false, isValid: true };
/**
* Initial state for a newly added field
*/
const initialNewFieldState = { editable: true, isNew: true, isValid: true };
const initialNewFieldState = { editable: true, isNew: true, isValid: undefined };
// Object.create(null) ensures the object has no default js properties (e.g. `__proto__`)
const initialState = Object.create(null);

View File

@@ -2,13 +2,12 @@
[action]="action" (keydown)="onKeydown($event)"
(keydown.arrowdown)="shiftFocusDown($event)"
(keydown.arrowup)="shiftFocusUp($event)" (keydown.esc)="close()"
(dsClickOutside)="close()">
(dsClickOutside)="close();">
<input #inputField type="text" [(ngModel)]="value" [name]="name"
class="form-control suggestion_input"
[ngClass]="{'is-invalid': !valid}"
[dsDebounce]="debounceTime" (onDebounce)="find($event)"
[placeholder]="placeholder"
(blur)="blur.emit($event);"
[ngModelOptions]="{standalone: true}" autocomplete="off"/>
<input type="submit" class="d-none"/>
<div class="autocomplete dropdown-menu" [ngClass]="{'show': (show | async) && isNotEmpty(suggestions)}">

View File

@@ -85,11 +85,6 @@ export class InputSuggestionsComponent implements ControlValueAccessor, OnChange
*/
@Output() findSuggestions = new EventEmitter();
/**
* Emits event when the input field loses focus
*/
@Output() blur = new EventEmitter();
/**
* Emits true when the list of suggestions should be shown
*/
@@ -119,9 +114,14 @@ export class InputSuggestionsComponent implements ControlValueAccessor, OnChange
*/
_value: string;
/** Fields needed to add ngModel */
@Input() disabled = false;
propagateChange = (_: any) => {
/* Empty implementation */
};
propagateTouch = (_: any) => {
/* Empty implementation */
};
/**
* When any of the inputs change, check if we should still show the suggestions
@@ -214,9 +214,9 @@ export class InputSuggestionsComponent implements ControlValueAccessor, OnChange
find(data) {
if (!this.blockReopen) {
this.findSuggestions.emit(data);
this.typeSuggestion.emit(data);
}
this.blockReopen = false;
this.typeSuggestion.emit(data);
}
onSubmit(data) {
@@ -230,11 +230,11 @@ export class InputSuggestionsComponent implements ControlValueAccessor, OnChange
}
registerOnTouched(fn: any): void {
/* no implementation */
this.propagateTouch = fn;
}
setDisabledState(isDisabled: boolean): void {
/* no implementation */
this.disabled = isDisabled;
}
writeValue(value: any): void {

View File

@@ -14,7 +14,6 @@ export class AutoFocusDirective implements AfterViewInit {
ngAfterViewInit() {
if (isNotEmpty(this.autoFocusSelector)) {
return this.el.nativeElement.querySelector(this.autoFocusSelector).focus();
} else {
return this.el.nativeElement.focus();
}

View File

@@ -16,9 +16,11 @@ export class ClickOutsideDirective {
constructor(private _elementRef: ElementRef) {
}
@HostListener('document:click', ['$event.target'])
public onClick(targetElement) {
const clickedInside = this._elementRef.nativeElement.contains(targetElement);
@HostListener('document:click')
public onClick() {
const hostElement = this._elementRef.nativeElement;
const focusElement = hostElement.ownerDocument.activeElement;
const clickedInside = hostElement.contains(focusElement);
if (!clickedInside) {
this.dsClickOutside.emit(null);
}

View File

@@ -25,12 +25,6 @@ export class DebounceDirective implements OnInit, OnDestroy {
@Input()
public dsDebounce = 500;
/**
* True if no changes have been made to the input field's value
*/
@Input()
private isFirstChange = true;
/**
* Subject to unsubscribe from
*/
@@ -47,11 +41,9 @@ export class DebounceDirective implements OnInit, OnDestroy {
this.model.valueChanges.pipe(
takeUntil(this.subject),
debounceTime(this.dsDebounce),
distinctUntilChanged(),)
distinctUntilChanged())
.subscribe((modelValue) => {
if (this.isFirstChange) {
this.isFirstChange = false;
} else {
if (this.model.dirty) {
this.onDebounce.emit(modelValue);
}
});

View File

@@ -24,9 +24,6 @@ export class InListValidator implements Validator {
* @param c The FormControl
*/
validate(c: FormControl): ValidationErrors | null {
if (this.dsInListValidator !== null) {
return inListValidator(this.dsInListValidator)(c);
}
return null;
}
}

View File

@@ -1,4 +1,5 @@
import { AbstractControl, ValidatorFn } from '@angular/forms';
import { isNotEmpty } from '../empty.util';
/**
* Returns a validator function to check if the control's value is in a given list
@@ -6,6 +7,11 @@ import { AbstractControl, ValidatorFn } from '@angular/forms';
*/
export function inListValidator(list: string[]): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } | null => {
const contains = list.indexOf(control.value) > -1;
return contains ? null : {inList: {value: control.value}} };
const hasValue = isNotEmpty(control.value);
let inList = true;
if (isNotEmpty(list)) {
inList = list.indexOf(control.value) > -1;
}
return (hasValue && inList) ? null : { inList: { value: control.value } }
};
}