diff --git a/src/app/+item-page/edit-item-page/edit-item-page.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.module.ts
index 0a7b363d6a..adbcf6b0df 100644
--- a/src/app/+item-page/edit-item-page/edit-item-page.module.ts
+++ b/src/app/+item-page/edit-item-page/edit-item-page.module.ts
@@ -12,6 +12,8 @@ import {AbstractSimpleItemActionComponent} from './simple-item-action/abstract-s
import {ItemPrivateComponent} from './item-private/item-private.component';
import {ItemPublicComponent} from './item-public/item-public.component';
import {ItemDeleteComponent} from './item-delete/item-delete.component';
+import { ItemMetadataComponent } from './item-metadata/item-metadata.component';
+import { EditInPlaceComponent } from './item-metadata/edit-in-place-field/edit-in-place-field.component';
/**
* Module that contains all components related to the Edit Item page administrator functionality
@@ -32,7 +34,9 @@ import {ItemDeleteComponent} from './item-delete/item-delete.component';
ItemPrivateComponent,
ItemPublicComponent,
ItemDeleteComponent,
- ItemStatusComponent
+ ItemStatusComponent,
+ ItemMetadataComponent,
+ EditInPlaceComponent
]
})
export class EditItemPageModule {
diff --git a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html
new file mode 100644
index 0000000000..5a5e16383a
--- /dev/null
+++ b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html
@@ -0,0 +1,42 @@
+
+
+ {{metadata.key}}
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+ {{metadata.value}}
+
+
+
+
+ |
+
+
+ {{metadata.language}}
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+ |
diff --git a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.scss b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.scss
new file mode 100644
index 0000000000..58c24635e6
--- /dev/null
+++ b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.scss
@@ -0,0 +1,3 @@
+textarea, input, select {
+ width: 100%;
+}
\ No newline at end of file
diff --git a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts
new file mode 100644
index 0000000000..1139415ecc
--- /dev/null
+++ b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts
@@ -0,0 +1,41 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { isNotEmpty } from '../../../../shared/empty.util';
+import { Metadatum } from '../../../../core/shared/metadatum.model';
+import { RegistryService } from '../../../../core/registry/registry.service';
+
+@Component({
+ selector: 'ds-edit-in-place-field.',
+ styleUrls: ['./edit-in-place-field.component.scss'],
+ templateUrl: './edit-in-place-field.component.html',
+})
+/**
+ * Component for displaying an item's status
+ */
+export class EditInPlaceComponent {
+
+ /**
+ * The value to display
+ */
+ @Input() metadata: Metadatum;
+ @Output() mdUpdate: EventEmitter = new EventEmitter();
+ @Output() mdRemove: EventEmitter = new EventEmitter();
+ editable = false;
+
+ constructor(
+ private metadataFieldService: RegistryService,
+ ) {
+
+ }
+
+ isNotEmpty(value) {
+ return isNotEmpty(value);
+ }
+
+ update() {
+ this.mdUpdate.emit();
+ }
+
+ remove() {
+ this.mdRemove.emit()
+ }
+}
diff --git a/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.html b/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.html
new file mode 100644
index 0000000000..bf32358d37
--- /dev/null
+++ b/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.html
@@ -0,0 +1,12 @@
+
diff --git a/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.ts b/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.ts
new file mode 100644
index 0000000000..cf9420658d
--- /dev/null
+++ b/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.ts
@@ -0,0 +1,37 @@
+import { Component, Input } from '@angular/core';
+import { Item } from '../../../core/shared/item.model';
+import { ItemDataService } from '../../../core/data/item-data.service';
+import { Metadatum } from '../../../core/shared/metadatum.model';
+
+@Component({
+ selector: 'ds-item-metadata',
+ templateUrl: './item-metadata.component.html',
+})
+/**
+ * Component for displaying an item's status
+ */
+export class ItemMetadataComponent {
+
+ /**
+ * The item to display the metadata for
+ */
+ @Input() item: Item;
+
+ constructor(private itemService: ItemDataService) {
+
+ }
+
+ update() {
+ this.itemService.update(this.item);
+ }
+
+ removeMetadata(i: number) {
+ this.item.metadata = this.item.metadata.filter((metadatum: Metadatum, index: number) => index !== i);
+ this.update();
+ }
+
+ addMetadata() {
+ this.item.metadata = [new Metadatum(), ...this.item.metadata];
+ this.update();
+ }
+}
diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts
index 62a4992787..96945cea81 100644
--- a/src/app/core/cache/builders/remote-data-build.service.ts
+++ b/src/app/core/cache/builders/remote-data-build.service.ts
@@ -5,15 +5,7 @@ import {
race as observableRace
} from 'rxjs';
import { Injectable } from '@angular/core';
-import {
- distinctUntilChanged,
- first,
- flatMap,
- map,
- startWith,
- switchMap,
- take
-} from 'rxjs/operators';
+import { distinctUntilChanged, flatMap, map, startWith, switchMap } from 'rxjs/operators';
import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../../shared/empty.util';
import { PaginatedList } from '../../data/paginated-list';
import { RemoteData } from '../../data/remote-data';
@@ -29,7 +21,8 @@ import { getMapsTo, getRelationMetadata, getRelationships } from './build-decora
import { PageInfo } from '../../shared/page-info.model';
import {
filterSuccessfulResponses,
- getRequestFromRequestHref, getRequestFromRequestUUID,
+ getRequestFromRequestHref,
+ getRequestFromRequestUUID,
getResourceLinksFromResponse
} from '../../shared/operators';
@@ -51,8 +44,6 @@ export class RemoteDataBuildService {
const requestEntry$ = observableRace(
href$.pipe(getRequestFromRequestHref(this.requestService)),
requestUUID$.pipe(getRequestFromRequestUUID(this.requestService)),
- ).pipe(
- take(1)
);
// always use self link if that is cached, only if it isn't, get it via the response.
@@ -94,8 +85,8 @@ export class RemoteDataBuildService {
toRemoteDataObservable(requestEntry$: Observable, payload$: Observable) {
return observableCombineLatest(requestEntry$, payload$).pipe(
map(([reqEntry, payload]) => {
- const requestPending = hasValue(reqEntry) && hasValue(reqEntry.requestPending) ? reqEntry.requestPending : true;
- const responsePending = hasValue(reqEntry) && hasValue(reqEntry.responsePending) ? reqEntry.responsePending : false;
+ const requestPending = hasValue(reqEntry.requestPending) ? reqEntry.requestPending : true;
+ const responsePending = hasValue(reqEntry.responsePending) ? reqEntry.responsePending : false;
let isSuccessful: boolean;
let error: RemoteDataError;
if (hasValue(reqEntry) && hasValue(reqEntry.response)) {
diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts
index 6cd3a7fa28..4bd0dabb70 100644
--- a/src/app/core/registry/registry.service.ts
+++ b/src/app/core/registry/registry.service.ts
@@ -28,7 +28,7 @@ import {
import { HALEndpointService } from '../shared/hal-endpoint.service';
import { RegistryMetadatafieldsResponseParsingService } from '../data/registry-metadatafields-response-parsing.service';
import { RegistryMetadatafieldsResponse } from './registry-metadatafields-response.model';
-import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util';
+import { hasValue, hasNoValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util';
import { URLCombiner } from '../url-combiner/url-combiner';
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
import { RegistryBitstreamformatsResponseParsingService } from '../data/registry-bitstreamformats-response-parsing.service';
@@ -166,6 +166,41 @@ export class RegistryService {
return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs);
}
+ public getAllMetadataFields(pagination?: PaginationComponentOptions): Observable>> {
+ if (hasNoValue(pagination)) {
+ pagination = { currentPage: 1, pageSize: Number.MAX_VALUE } as any;
+ }
+ const requestObs = this.getMetadataFieldsRequestObs(pagination);
+
+ const requestEntryObs = requestObs.pipe(
+ flatMap((request: RestRequest) => this.requestService.getByHref(request.href))
+ );
+
+ const rmrObs: Observable = requestEntryObs.pipe(
+ getResponseFromEntry(),
+ map((response: RegistryMetadatafieldsSuccessResponse) => response.metadatafieldsResponse)
+ );
+
+ const metadatafieldsObs: Observable = rmrObs.pipe(
+ map((rmr: RegistryMetadatafieldsResponse) => rmr.metadatafields),
+ map((metadataFields: MetadataField[]) => metadataFields)
+ );
+
+ const pageInfoObs: Observable = requestEntryObs.pipe(
+ getResponseFromEntry(),
+
+ map((response: RegistryMetadatafieldsSuccessResponse) => response.pageInfo)
+ );
+
+ const payloadObs = observableCombineLatest(metadatafieldsObs, pageInfoObs).pipe(
+ map(([metadatafields, pageInfo]) => {
+ return new PaginatedList(pageInfo, metadatafields);
+ })
+ );
+
+ return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs);
+ }
+
public getBitstreamFormats(pagination: PaginationComponentOptions): Observable>> {
const requestObs = this.getBitstreamFormatsRequestObs(pagination);
@@ -238,6 +273,26 @@ export class RegistryService {
);
}
+ private getMetadataFieldsRequestObs(pagination: PaginationComponentOptions): Observable {
+ return this.halService.getEndpoint(this.metadataFieldsPath).pipe(
+ map((url: string) => {
+ const args: string[] = [];
+ args.push(`size=${pagination.pageSize}`);
+ args.push(`page=${pagination.currentPage - 1}`);
+ if (isNotEmpty(args)) {
+ url = new URLCombiner(url, `?${args.join('&')}`).toString();
+ }
+ const request = new GetRequest(this.requestService.generateRequestId(), url);
+ return Object.assign(request, {
+ getResponseParser(): GenericConstructor {
+ return RegistryMetadatafieldsResponseParsingService;
+ }
+ });
+ }),
+ tap((request: RestRequest) => this.requestService.configure(request)),
+ );
+ }
+
private getBitstreamFormatsRequestObs(pagination: PaginationComponentOptions): Observable {
return this.halService.getEndpoint(this.bitstreamFormatsPath).pipe(
map((url: string) => {
diff --git a/src/app/core/shared/metadatum.model.ts b/src/app/core/shared/metadatum.model.ts
index a3c5830608..ca1f3d8591 100644
--- a/src/app/core/shared/metadatum.model.ts
+++ b/src/app/core/shared/metadatum.model.ts
@@ -19,5 +19,4 @@ export class Metadatum {
*/
@autoserialize
value: string;
-
}
diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts
index 6fe510c1aa..4540bed0c4 100644
--- a/src/app/core/shared/operators.ts
+++ b/src/app/core/shared/operators.ts
@@ -60,7 +60,7 @@ export const getRemoteDataPayload = () =>
export const getSucceededRemoteData = () =>
(source: Observable>): Observable> =>
- source.pipe(find((rd: RemoteData) => rd.hasSucceeded), hasValueOperator());
+ source.pipe(find((rd: RemoteData) => rd.hasSucceeded));
export const getAllSucceededRemoteData = () =>
(source: Observable>): Observable> =>