70834: Metadata schema component refactoring and caching issue fix

This commit is contained in:
Kristof De Langhe
2020-05-13 13:56:42 +02:00
parent 7677a673aa
commit cd46f33909
4 changed files with 76 additions and 50 deletions

View File

@@ -177,6 +177,7 @@ export class MetadataFieldFormComponent implements OnInit, OnDestroy {
});
}
this.clearFields();
this.registryService.cancelEditMetadataField();
}
);
}

View File

@@ -1,36 +1,37 @@
<div class="container">
<div class="metadata-schema row">
<div class="col-12">
<div class="col-12" *ngVar="(metadataSchema$ | async) as schema">
<h2 id="header" class="border-bottom pb-2">{{'admin.registries.schema.head' | translate}}: "{{(metadataSchema | async)?.payload?.prefix}}"</h2>
<h2 id="header" class="border-bottom pb-2">{{'admin.registries.schema.head' | translate}}: "{{schema?.prefix}}"</h2>
<p id="description" class="pb-2">{{'admin.registries.schema.description' | translate:namespace }}</p>
<p id="description" class="pb-2">{{'admin.registries.schema.description' | translate:{ namespace: schema?.namespace } }}</p>
<ds-metadata-field-form
[metadataSchema]="(metadataSchema | async)?.payload"
[metadataSchema]="schema"
(submitForm)="forceUpdateFields()"></ds-metadata-field-form>
<h3>{{'admin.registries.schema.fields.head' | translate}}</h3>
<ds-pagination
*ngIf="(metadataFields | async)?.payload?.totalElements > 0"
[paginationOptions]="config"
[pageInfoState]="(metadataFields | async)?.payload"
[collectionSize]="(metadataFields | async)?.payload?.totalElements"
[hideGear]="false"
[hidePagerWhenSinglePage]="true"
(pageChange)="onPageChange($event)">
<div class="table-responsive">
<table id="metadata-fields" class="table table-striped table-hover">
<thead>
<ng-container *ngVar="(metadataFields$ | async)?.payload as fields">
<ds-pagination
*ngIf="fields?.totalElements > 0"
[paginationOptions]="config"
[pageInfoState]="fields"
[collectionSize]="fields?.totalElements"
[hideGear]="false"
[hidePagerWhenSinglePage]="true"
(pageChange)="onPageChange($event)">
<div class="table-responsive">
<table id="metadata-fields" class="table table-striped table-hover">
<thead>
<tr>
<th></th>
<th scope="col">{{'admin.registries.schema.fields.table.field' | translate}}</th>
<th scope="col">{{'admin.registries.schema.fields.table.scopenote' | translate}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let field of (metadataFields | async)?.payload?.page"
</thead>
<tbody>
<tr *ngFor="let field of fields?.page"
[ngClass]="{'table-primary' : isActive(field) | async}">
<td>
<label>
@@ -39,22 +40,23 @@
(change)="selectMetadataField(field, $event)">
</label>
</td>
<td class="selectable-row" (click)="editField(field)">{{(metadataSchema | async)?.payload?.prefix}}.{{field.element}}<label *ngIf="field.qualifier">.</label>{{field.qualifier}}</td>
<td class="selectable-row" (click)="editField(field)">{{schema?.prefix}}.{{field.element}}<label *ngIf="field.qualifier">.</label>{{field.qualifier}}</td>
<td class="selectable-row" (click)="editField(field)">{{field.scopeNote}}</td>
</tr>
</tbody>
</table>
</tbody>
</table>
</div>
</ds-pagination>
<div *ngIf="fields?.totalElements == 0" class="alert alert-info w-100 mb-2" role="alert">
{{'admin.registries.schema.fields.no-items' | translate}}
</div>
</ds-pagination>
<div *ngIf="(metadataFields | async)?.payload?.totalElements == 0" class="alert alert-info w-100 mb-2" role="alert">
{{'admin.registries.schema.fields.no-items' | translate}}
</div>
<div>
<button [routerLink]="['/admin/registries/metadata']" class="btn btn-primary">{{'admin.registries.schema.return' | translate}}</button>
<button *ngIf="(metadataFields | async)?.payload?.page?.length > 0" type="submit" class="btn btn-danger float-right" (click)="deleteFields()">{{'admin.registries.schema.fields.table.delete' | translate}}</button>
</div>
<div>
<button [routerLink]="['/admin/registries/metadata']" class="btn btn-primary">{{'admin.registries.schema.return' | translate}}</button>
<button *ngIf="fields?.page?.length > 0" type="submit" class="btn btn-danger float-right" (click)="deleteFields()">{{'admin.registries.schema.fields.table.delete' | translate}}</button>
</div>
</ng-container>
</div>
</div>

View File

@@ -5,7 +5,7 @@ import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list';
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
import { map, take } from 'rxjs/operators';
import { map, switchMap, take } from 'rxjs/operators';
import { hasValue } from '../../../shared/empty.util';
import { RestResponse } from '../../../core/cache/response.models';
import { zip } from 'rxjs/internal/observable/zip';
@@ -13,8 +13,10 @@ import { NotificationsService } from '../../../shared/notifications/notification
import { TranslateService } from '@ngx-translate/core';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { getSucceededRemoteData } from '../../../core/shared/operators';
import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators';
import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { combineLatest } from 'rxjs/internal/observable/combineLatest';
@Component({
selector: 'ds-metadata-schema',
@@ -26,21 +28,15 @@ import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
* The admin can create, edit or delete metadata fields here.
*/
export class MetadataSchemaComponent implements OnInit {
/**
* The namespace of the metadata schema
*/
namespace;
/**
* The metadata schema
*/
metadataSchema: Observable<RemoteData<MetadataSchema>>;
metadataSchema$: Observable<MetadataSchema>;
/**
* A list of all the fields attached to this metadata schema
*/
metadataFields: Observable<RemoteData<PaginatedList<MetadataField>>>;
metadataFields$: Observable<RemoteData<PaginatedList<MetadataField>>>;
/**
* Pagination config used to display the list of metadata fields
@@ -51,6 +47,11 @@ export class MetadataSchemaComponent implements OnInit {
pageSizeOptions: [25, 50, 100, 200]
});
/**
* Whether or not the list of MetadataFields needs an update
*/
needsUpdate: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
constructor(private registryService: RegistryService,
private route: ActivatedRoute,
private notificationsService: NotificationsService,
@@ -70,7 +71,7 @@ export class MetadataSchemaComponent implements OnInit {
* @param params
*/
initialize(params) {
this.metadataSchema = this.registryService.getMetadataSchemaByName(params.schemaName);
this.metadataSchema$ = this.registryService.getMetadataSchemaByName(params.schemaName).pipe(getFirstSucceededRemoteDataPayload());
this.updateFields();
}
@@ -80,18 +81,21 @@ export class MetadataSchemaComponent implements OnInit {
*/
onPageChange(event) {
this.config.currentPage = event;
this.updateFields();
this.needsUpdate.next(true);
}
/**
* Update the list of fields by fetching it from the rest api or cache
*/
private updateFields() {
this.metadataSchema.pipe(getSucceededRemoteData()).subscribe((schemaData) => {
const schema = schemaData.payload;
this.metadataFields = this.registryService.getMetadataFieldsBySchema(schema, toFindListOptions(this.config));
this.namespace = {namespace: schemaData.payload.namespace};
});
this.metadataFields$ = combineLatest(this.metadataSchema$, this.needsUpdate).pipe(
switchMap(([schema, update]: [MetadataSchema, boolean]) => {
if (update) {
console.log('reloaded list');
return this.registryService.getMetadataFieldsBySchema(schema, toFindListOptions(this.config));
}
})
);
}
/**
@@ -99,8 +103,7 @@ export class MetadataSchemaComponent implements OnInit {
* a new REST call
*/
public forceUpdateFields() {
this.registryService.clearMetadataFieldRequests().subscribe();
this.updateFields();
this.registryService.clearMetadataFieldRequests().subscribe(() => this.needsUpdate.next(true));
}
/**

View File

@@ -45,6 +45,12 @@ export class MetadataFieldDataService extends DataService<MetadataField> {
super();
}
/**
* Find metadata fields belonging to a metadata schema
* @param schema The metadata schema to list fields for
* @param options The options info used to retrieve the fields
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved
*/
findBySchema(schema: MetadataSchema, options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<MetadataField>>) {
const optionsWithSchema = Object.assign(new FindListOptions(), options, {
searchParams: [new SearchParam('schema', schema.prefix)]
@@ -52,6 +58,14 @@ export class MetadataFieldDataService extends DataService<MetadataField> {
return this.searchBy(this.searchBySchemaLinkPath, optionsWithSchema, ...linksToFollow);
}
/**
* Create or Update a MetadataField
* If the MetadataField contains an id, it is assumed the field already exists and is updated instead
* Since creating or updating is nearly identical, the only real difference is the request (and slight difference in endpoint):
* - On creation, a CreateMetadataFieldRequest is used
* - On update, a UpdateMetadataFieldRequest is used
* @param field The MetadataField to create or update
*/
createOrUpdateMetadataField(field: MetadataField): Observable<RestResponse> {
const isUpdate = hasValue(field.id);
const requestId = this.requestService.generateRequestId();
@@ -97,9 +111,15 @@ export class MetadataFieldDataService extends DataService<MetadataField> {
);
}
/**
* Clear all metadata field requests
* Used for refreshing lists after adding/updating/removing a metadata field from a metadata schema
*/
clearRequests(): Observable<string> {
return this.getBrowseEndpoint().pipe(
tap((href: string) => this.requestService.removeByHrefSubstring(href))
tap((href: string) => {
this.requestService.removeByHrefSubstring(href);
})
);
}