mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
71894: confirm edit metadata button disabled if invalid &
removed unneeded service
This commit is contained in:
@@ -6,6 +6,8 @@
|
|||||||
<div *ngIf="(editable | async)" class="field-container">
|
<div *ngIf="(editable | async)" class="field-container">
|
||||||
<ds-filter-input-suggestions [suggestions]="(metadataFieldSuggestions | async)"
|
<ds-filter-input-suggestions [suggestions]="(metadataFieldSuggestions | async)"
|
||||||
[(ngModel)]="metadata.key"
|
[(ngModel)]="metadata.key"
|
||||||
|
[url]="this.url"
|
||||||
|
[metadata]="this.metadata"
|
||||||
(submitSuggestion)="update(suggestionControl)"
|
(submitSuggestion)="update(suggestionControl)"
|
||||||
(clickSuggestion)="update(suggestionControl)"
|
(clickSuggestion)="update(suggestionControl)"
|
||||||
(typeSuggestion)="update(suggestionControl)"
|
(typeSuggestion)="update(suggestionControl)"
|
||||||
@@ -50,7 +52,7 @@
|
|||||||
title="{{'item.edit.metadata.edit.buttons.edit' | translate}}">
|
title="{{'item.edit.metadata.edit.buttons.edit' | translate}}">
|
||||||
<i class="fas fa-edit fa-fw"></i>
|
<i class="fas fa-edit fa-fw"></i>
|
||||||
</button>
|
</button>
|
||||||
<button [disabled]="!(canSetUneditable() | async)" *ngIf="(editable | async)"
|
<button [disabled]="!(canSetUneditable() | async) || (valid | async) === false" *ngIf="(editable | async)"
|
||||||
(click)="setEditable(false)" class="btn btn-outline-success btn-sm"
|
(click)="setEditable(false)" class="btn btn-outline-success btn-sm"
|
||||||
title="{{'item.edit.metadata.edit.buttons.unedit' | translate}}">
|
title="{{'item.edit.metadata.edit.buttons.unedit' | translate}}">
|
||||||
<i class="fas fa-check fa-fw"></i>
|
<i class="fas fa-check fa-fw"></i>
|
||||||
|
@@ -36,7 +36,7 @@ export class EditInPlaceFieldComponent implements OnInit, OnChanges {
|
|||||||
/**
|
/**
|
||||||
* The metadatum of this field
|
* The metadatum of this field
|
||||||
*/
|
*/
|
||||||
metadata: MetadatumViewModel;
|
@Input() metadata: MetadatumViewModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits whether or not this field is currently editable
|
* Emits whether or not this field is currently editable
|
||||||
|
@@ -68,7 +68,6 @@ import { ItemDataService } from './data/item-data.service';
|
|||||||
import { LicenseDataService } from './data/license-data.service';
|
import { LicenseDataService } from './data/license-data.service';
|
||||||
import { LookupRelationService } from './data/lookup-relation.service';
|
import { LookupRelationService } from './data/lookup-relation.service';
|
||||||
import { MappedCollectionsReponseParsingService } from './data/mapped-collections-reponse-parsing.service';
|
import { MappedCollectionsReponseParsingService } from './data/mapped-collections-reponse-parsing.service';
|
||||||
import { MetadatafieldParsingService } from './data/metadatafield-response-parsing.service';
|
|
||||||
import { MyDSpaceResponseParsingService } from './data/mydspace-response-parsing.service';
|
import { MyDSpaceResponseParsingService } from './data/mydspace-response-parsing.service';
|
||||||
import { ObjectUpdatesService } from './data/object-updates/object-updates.service';
|
import { ObjectUpdatesService } from './data/object-updates/object-updates.service';
|
||||||
import { RelationshipTypeService } from './data/relationship-type.service';
|
import { RelationshipTypeService } from './data/relationship-type.service';
|
||||||
@@ -196,7 +195,7 @@ const PROVIDERS = [
|
|||||||
SiteDataService,
|
SiteDataService,
|
||||||
DSOResponseParsingService,
|
DSOResponseParsingService,
|
||||||
{ provide: MOCK_RESPONSE_MAP, useValue: mockResponseMap },
|
{ provide: MOCK_RESPONSE_MAP, useValue: mockResponseMap },
|
||||||
{ provide: DSpaceRESTv2Service, useFactory: restServiceFactory, deps: [MOCK_RESPONSE_MAP, HttpClient]},
|
{ provide: DSpaceRESTv2Service, useFactory: restServiceFactory, deps: [MOCK_RESPONSE_MAP, HttpClient] },
|
||||||
DynamicFormLayoutService,
|
DynamicFormLayoutService,
|
||||||
DynamicFormService,
|
DynamicFormService,
|
||||||
DynamicFormValidationService,
|
DynamicFormValidationService,
|
||||||
@@ -290,7 +289,6 @@ const PROVIDERS = [
|
|||||||
MetadataSchemaDataService,
|
MetadataSchemaDataService,
|
||||||
MetadataFieldDataService,
|
MetadataFieldDataService,
|
||||||
TokenResponseParsingService,
|
TokenResponseParsingService,
|
||||||
MetadatafieldParsingService,
|
|
||||||
// register AuthInterceptor as HttpInterceptor
|
// register AuthInterceptor as HttpInterceptor
|
||||||
{
|
{
|
||||||
provide: HTTP_INTERCEPTORS,
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
@@ -1,19 +0,0 @@
|
|||||||
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
|
|
||||||
import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer';
|
|
||||||
import { MetadataField } from '../metadata/metadata-field.model';
|
|
||||||
import { RestRequest } from './request.models';
|
|
||||||
import { ResponseParsingService } from './parsing.service';
|
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { MetadatafieldSuccessResponse, RestResponse } from '../cache/response.models';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MetadatafieldParsingService implements ResponseParsingService {
|
|
||||||
|
|
||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
|
||||||
const payload = data.payload;
|
|
||||||
|
|
||||||
const deserialized = new DSpaceSerializer(MetadataField).deserialize(payload);
|
|
||||||
return new MetadatafieldSuccessResponse(deserialized, data.statusCode, data.statusText);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -2,7 +2,6 @@ import { SortOptions } from '../cache/models/sort-options.model';
|
|||||||
import { GenericConstructor } from '../shared/generic-constructor';
|
import { GenericConstructor } from '../shared/generic-constructor';
|
||||||
import { BrowseEntriesResponseParsingService } from './browse-entries-response-parsing.service';
|
import { BrowseEntriesResponseParsingService } from './browse-entries-response-parsing.service';
|
||||||
import { DSOResponseParsingService } from './dso-response-parsing.service';
|
import { DSOResponseParsingService } from './dso-response-parsing.service';
|
||||||
import { MetadatafieldParsingService } from './metadatafield-response-parsing.service';
|
|
||||||
import { ResponseParsingService } from './parsing.service';
|
import { ResponseParsingService } from './parsing.service';
|
||||||
import { EndpointMapResponseParsingService } from './endpoint-map-response-parsing.service';
|
import { EndpointMapResponseParsingService } from './endpoint-map-response-parsing.service';
|
||||||
import { BrowseResponseParsingService } from './browse-response-parsing.service';
|
import { BrowseResponseParsingService } from './browse-response-parsing.service';
|
||||||
@@ -430,14 +429,4 @@ export class RequestError extends Error {
|
|||||||
statusCode: number;
|
statusCode: number;
|
||||||
statusText: string;
|
statusText: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GetMetadataFieldRequest extends GetRequest {
|
|
||||||
constructor(uuid: string, href: string, public options?: HttpOptions) {
|
|
||||||
super(uuid, href, null, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
getResponseParser(): GenericConstructor<ResponseParsingService> {
|
|
||||||
return MetadatafieldParsingService;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* tslint:enable:max-classes-per-file */
|
/* tslint:enable:max-classes-per-file */
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
[action]="action" (keydown)="onKeydown($event)"
|
[action]="action" (keydown)="onKeydown($event)"
|
||||||
(keydown.arrowdown)="shiftFocusDown($event)"
|
(keydown.arrowdown)="shiftFocusDown($event)"
|
||||||
(keydown.arrowup)="shiftFocusUp($event)" (keydown.esc)="close()"
|
(keydown.arrowup)="shiftFocusUp($event)" (keydown.esc)="close()"
|
||||||
(dsClickOutside)="close();">
|
(dsClickOutside)="checkIfValidInput(form);close();">
|
||||||
<input #inputField type="text" formControlName="metadataNameField" [(ngModel)]="value" id="name" [name]="name"
|
<input #inputField type="text" formControlName="metadataNameField" [(ngModel)]="value" id="name" [name]="name"
|
||||||
class="form-control suggestion_input"
|
class="form-control suggestion_input"
|
||||||
[ngClass]="{'is-invalid': !valid}"
|
[ngClass]="{'is-invalid': !valid}"
|
||||||
@@ -11,10 +11,6 @@
|
|||||||
ng-model-options="{standalone: true}"
|
ng-model-options="{standalone: true}"
|
||||||
autocomplete="off">
|
autocomplete="off">
|
||||||
<input type="submit" class="d-none"/>
|
<input type="submit" class="d-none"/>
|
||||||
<small class="text-danger"
|
|
||||||
*ngIf="form.get('metadataNameField').status === 'INVALID' && (form.get('metadataNameField').dirty || form.get('metadataNameField').touched)">
|
|
||||||
{{"item.edit.metadata.metadatafield.invalid" | translate}}
|
|
||||||
</small>
|
|
||||||
<div class="autocomplete dropdown-menu" [ngClass]="{'show': (show | async) && isNotEmpty(suggestions)}">
|
<div class="autocomplete dropdown-menu" [ngClass]="{'show': (show | async) && isNotEmpty(suggestions)}">
|
||||||
<div class="dropdown-list">
|
<div class="dropdown-list">
|
||||||
<div *ngFor="let suggestionOption of suggestions">
|
<div *ngFor="let suggestionOption of suggestions">
|
||||||
|
@@ -7,6 +7,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { MetadataFieldDataService } from '../../../core/data/metadata-field-data.service';
|
import { MetadataFieldDataService } from '../../../core/data/metadata-field-data.service';
|
||||||
|
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
|
||||||
import { FilterInputSuggestionsComponent } from './filter-input-suggestions.component';
|
import { FilterInputSuggestionsComponent } from './filter-input-suggestions.component';
|
||||||
|
|
||||||
describe('FilterInputSuggestionsComponent', () => {
|
describe('FilterInputSuggestionsComponent', () => {
|
||||||
@@ -26,7 +27,9 @@ describe('FilterInputSuggestionsComponent', () => {
|
|||||||
declarations: [FilterInputSuggestionsComponent],
|
declarations: [FilterInputSuggestionsComponent],
|
||||||
providers: [FormsModule,
|
providers: [FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
{ provide: MetadataFieldDataService, useValue: {} }],
|
{ provide: MetadataFieldDataService, useValue: {} },
|
||||||
|
{ provide: ObjectUpdatesService, useValue: {} },
|
||||||
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).overrideComponent(FilterInputSuggestionsComponent, {
|
}).overrideComponent(FilterInputSuggestionsComponent, {
|
||||||
set: { changeDetection: ChangeDetectionStrategy.Default }
|
set: { changeDetection: ChangeDetectionStrategy.Default }
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
import { Component, forwardRef, Input, OnInit } from '@angular/core';
|
import { Component, forwardRef, Input, OnInit } from '@angular/core';
|
||||||
import { FormControl, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
|
||||||
|
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
|
||||||
|
import { MetadatumViewModel } from '../../../core/shared/metadata.models';
|
||||||
import { MetadataFieldValidator } from '../../utils/metadatafield-validator.directive';
|
import { MetadataFieldValidator } from '../../utils/metadatafield-validator.directive';
|
||||||
import { InputSuggestionsComponent } from '../input-suggestions.component';
|
import { InputSuggestionsComponent } from '../input-suggestions.component';
|
||||||
import { InputSuggestion } from '../input-suggestions.model';
|
import { InputSuggestion } from '../input-suggestions.model';
|
||||||
@@ -26,12 +28,23 @@ export class FilterInputSuggestionsComponent extends InputSuggestionsComponent i
|
|||||||
|
|
||||||
form: FormGroup;
|
form: FormGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current url of this page
|
||||||
|
*/
|
||||||
|
@Input() url: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The metadatum of this field
|
||||||
|
*/
|
||||||
|
@Input() metadata: MetadatumViewModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The suggestions that should be shown
|
* The suggestions that should be shown
|
||||||
*/
|
*/
|
||||||
@Input() suggestions: InputSuggestion[] = [];
|
@Input() suggestions: InputSuggestion[] = [];
|
||||||
|
|
||||||
constructor(private metadataFieldValidator: MetadataFieldValidator) {
|
constructor(private metadataFieldValidator: MetadataFieldValidator,
|
||||||
|
private objectUpdatesService: ObjectUpdatesService) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,4 +71,14 @@ export class FilterInputSuggestionsComponent extends InputSuggestionsComponent i
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the input is valid according to validator and send (in)valid state to store
|
||||||
|
* @param form Form with input
|
||||||
|
*/
|
||||||
|
checkIfValidInput(form) {
|
||||||
|
this.valid = !(form.get('metadataNameField').status === 'INVALID' && (form.get('metadataNameField').dirty || form.get('metadataNameField').touched));
|
||||||
|
this.objectUpdatesService.setValidFieldUpdate(this.url, this.metadata.uuid, this.valid);
|
||||||
|
return this.valid;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user