mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-14 05:23:06 +00:00
taskid 58789 Metadata Registry UI Part 2
This commit is contained in:
@@ -7,7 +7,8 @@ import { RouterModule } from '@angular/router';
|
|||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { BitstreamFormatsComponent } from './bitstream-formats/bitstream-formats.component';
|
import { BitstreamFormatsComponent } from './bitstream-formats/bitstream-formats.component';
|
||||||
import { SharedModule } from '../../shared/shared.module';
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
import { MetadataSchemaFormComponent } from './metadata-schema/metadata-schema-form/metadata-schema-form.component';
|
import { MetadataSchemaFormComponent } from './metadata-registry/metadata-schema-form/metadata-schema-form.component';
|
||||||
|
import {MetadataFieldFormComponent} from "./metadata-schema/metadata-field-form/metadata-field-form.component";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -21,7 +22,11 @@ import { MetadataSchemaFormComponent } from './metadata-schema/metadata-schema-f
|
|||||||
MetadataRegistryComponent,
|
MetadataRegistryComponent,
|
||||||
MetadataSchemaComponent,
|
MetadataSchemaComponent,
|
||||||
BitstreamFormatsComponent,
|
BitstreamFormatsComponent,
|
||||||
MetadataSchemaFormComponent
|
MetadataSchemaFormComponent,
|
||||||
|
MetadataFieldFormComponent
|
||||||
|
],
|
||||||
|
entryComponents: [
|
||||||
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AdminRegistriesModule {
|
export class AdminRegistriesModule {
|
||||||
|
@@ -0,0 +1,122 @@
|
|||||||
|
import {Action} from '@ngrx/store';
|
||||||
|
import {type} from "../../../shared/ngrx/type";
|
||||||
|
import {MetadataSchema} from "../../../core/metadata/metadataschema.model";
|
||||||
|
import {MetadataField} from "../../../core/metadata/metadatafield.model";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each action type in an action group, make a simple
|
||||||
|
* enum object for all of this group's action types.
|
||||||
|
*
|
||||||
|
* The 'type' utility function coerces strings into string
|
||||||
|
* literal types and runs a simple check to guarantee all
|
||||||
|
* action types in the application are unique.
|
||||||
|
*/
|
||||||
|
export const MetadataRegistryActionTypes = {
|
||||||
|
|
||||||
|
EDIT_SCHEMA: type('dspace/metadata-registry/EDIT_SCHEMA'),
|
||||||
|
CANCEL_EDIT_SCHEMA: type('dspace/metadata-registry/CANCEL_SCHEMA'),
|
||||||
|
SELECT_SCHEMA: type('dspace/metadata-registry/SELECT_SCHEMA'),
|
||||||
|
DESELECT_SCHEMA: type('dspace/metadata-registry/DESELECT_SCHEMA'),
|
||||||
|
|
||||||
|
EDIT_FIELD : type('dspace/metadata-registry/EDIT_FIELD'),
|
||||||
|
CANCEL_EDIT_FIELD : type('dspace/metadata-registry/CANCEL_FIELD'),
|
||||||
|
SELECT_FIELD : type('dspace/metadata-registry/SELECT_FIELD'),
|
||||||
|
DESELECT_FIELD : type('dspace/metadata-registry/DESELEC_FIELDT')
|
||||||
|
};
|
||||||
|
|
||||||
|
/* tslint:disable:max-classes-per-file */
|
||||||
|
/**
|
||||||
|
* Used to collapse the sidebar
|
||||||
|
*/
|
||||||
|
export class MetadataRegistryEditSchemaAction implements Action {
|
||||||
|
type = MetadataRegistryActionTypes.EDIT_SCHEMA;
|
||||||
|
|
||||||
|
schema: MetadataSchema;
|
||||||
|
|
||||||
|
constructor(registry: MetadataSchema) {
|
||||||
|
this.schema = registry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to expand the sidebar
|
||||||
|
*/
|
||||||
|
export class MetadataRegistryCancelSchemaAction implements Action {
|
||||||
|
type = MetadataRegistryActionTypes.CANCEL_EDIT_SCHEMA;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MetadataRegistrySelectSchemaAction implements Action {
|
||||||
|
type = MetadataRegistryActionTypes.SELECT_SCHEMA;
|
||||||
|
|
||||||
|
schema: MetadataSchema;
|
||||||
|
|
||||||
|
constructor(registry: MetadataSchema) {
|
||||||
|
this.schema = registry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MetadataRegistryDeselectSchemaAction implements Action {
|
||||||
|
type = MetadataRegistryActionTypes.DESELECT_SCHEMA;
|
||||||
|
|
||||||
|
schema: MetadataSchema;
|
||||||
|
|
||||||
|
constructor(registry: MetadataSchema) {
|
||||||
|
this.schema = registry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to collapse the sidebar
|
||||||
|
*/
|
||||||
|
export class MetadataRegistryEditFieldAction implements Action {
|
||||||
|
type = MetadataRegistryActionTypes.EDIT_FIELD;
|
||||||
|
|
||||||
|
field: MetadataField;
|
||||||
|
|
||||||
|
constructor(registry: MetadataField) {
|
||||||
|
this.field = registry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to expand the sidebar
|
||||||
|
*/
|
||||||
|
export class MetadataRegistryCancelFieldAction implements Action {
|
||||||
|
type = MetadataRegistryActionTypes.CANCEL_EDIT_FIELD;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MetadataRegistrySelectFieldAction implements Action {
|
||||||
|
type = MetadataRegistryActionTypes.SELECT_FIELD;
|
||||||
|
|
||||||
|
field: MetadataField;
|
||||||
|
|
||||||
|
constructor(registry: MetadataField) {
|
||||||
|
this.field = registry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MetadataRegistryDeselectFieldAction implements Action {
|
||||||
|
type = MetadataRegistryActionTypes.DESELECT_FIELD;
|
||||||
|
|
||||||
|
field: MetadataField;
|
||||||
|
|
||||||
|
constructor(registry: MetadataField) {
|
||||||
|
this.field = registry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tslint:enable:max-classes-per-file */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export a type alias of all actions in this action group
|
||||||
|
* so that reducers can easily compose action types
|
||||||
|
*/
|
||||||
|
export type MetadataRegistryAction
|
||||||
|
= MetadataRegistryEditSchemaAction
|
||||||
|
| MetadataRegistryCancelSchemaAction
|
||||||
|
| MetadataRegistrySelectSchemaAction
|
||||||
|
| MetadataRegistryDeselectSchemaAction
|
||||||
|
| MetadataRegistryEditFieldAction
|
||||||
|
| MetadataRegistryCancelFieldAction
|
||||||
|
| MetadataRegistrySelectFieldAction
|
||||||
|
| MetadataRegistryDeselectFieldAction;
|
@@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
<p id="description" class="pb-2">{{'admin.registries.metadata.description' | translate}}</p>
|
<p id="description" class="pb-2">{{'admin.registries.metadata.description' | translate}}</p>
|
||||||
|
|
||||||
<ds-metadata-schema-form></ds-metadata-schema-form>
|
<ds-metadata-schema-form
|
||||||
|
></ds-metadata-schema-form>
|
||||||
|
|
||||||
<ds-pagination
|
<ds-pagination
|
||||||
*ngIf="(metadataSchemas | async)?.payload?.totalElements > 0"
|
*ngIf="(metadataSchemas | async)?.payload?.totalElements > 0"
|
||||||
@@ -30,17 +31,14 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let schema of (metadataSchemas | async)?.payload?.page"
|
<tr *ngFor="let schema of (metadataSchemas | async)?.payload?.page"
|
||||||
(click)="editSchema(schema)"
|
(click)="editSchema(schema)"
|
||||||
[class.active-row]="isActive(schema)">
|
[class.active-row]="isActive(schema) | async">
|
||||||
<td>
|
<td>
|
||||||
<!--<input type="checkbox" class="custom-control-input"-->
|
<label>
|
||||||
<!--[checked]="item.value"-->
|
<input type="checkbox"
|
||||||
<!--[formControlName]="item.id"-->
|
[checked]="isSelected(schema) | async"
|
||||||
<!--[name]="model.name"-->
|
(change)="selectMetadataSchema(schema, $event)"
|
||||||
<!--[required]="model.required"-->
|
>
|
||||||
<!--[value]="item.value"-->
|
</label>
|
||||||
<!--(blur)="onBlur($event)"-->
|
|
||||||
<!--(change)="onChange($event)"-->
|
|
||||||
<!--(focus)="onFocus($event)"/>-->
|
|
||||||
</td>
|
</td>
|
||||||
<td><a [routerLink]="[schema.prefix]">{{schema.id}}</a></td>
|
<td><a [routerLink]="[schema.prefix]">{{schema.id}}</a></td>
|
||||||
<td><a [routerLink]="[schema.prefix]">{{schema.namespace}}</a></td>
|
<td><a [routerLink]="[schema.prefix]">{{schema.namespace}}</a></td>
|
||||||
@@ -51,7 +49,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</ds-pagination>
|
</ds-pagination>
|
||||||
<div *ngIf="(metadataSchemas | async)?.payload?.totalElements == 0" class="alert alert-info" role="alert">
|
|
||||||
|
<button type="submit" class="btn btn-primary" (click)="deleteSchemas()">{{'form.submit' | translate}}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div *ngIf="(metadataSchemas | async)?.payload?.totalElements == 0" class="alert alert-info"
|
||||||
|
role="alert">
|
||||||
{{'admin.registries.metadata.schemas.no-items' | translate}}
|
{{'admin.registries.metadata.schemas.no-items' | translate}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
import { Component } from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
import { RegistryService } from '../../../core/registry/registry.service';
|
import {RegistryService} from '../../../core/registry/registry.service';
|
||||||
import { Observable } from 'rxjs';
|
import {Observable} from 'rxjs';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import {RemoteData} from '../../../core/data/remote-data';
|
||||||
import { PaginatedList } from '../../../core/data/paginated-list';
|
import {PaginatedList} from '../../../core/data/paginated-list';
|
||||||
import { MetadataSchema } from '../../../core/metadata/metadataschema.model';
|
import {MetadataSchema} from '../../../core/metadata/metadataschema.model';
|
||||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model';
|
||||||
|
import {Store} from "@ngrx/store";
|
||||||
|
import {AppState} from "../../../app.reducer";
|
||||||
|
import {map} from "rxjs/operators";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-metadata-registry',
|
selector: 'ds-metadata-registry',
|
||||||
@@ -21,9 +24,6 @@ export class MetadataRegistryComponent {
|
|||||||
|
|
||||||
constructor(private registryService: RegistryService) {
|
constructor(private registryService: RegistryService) {
|
||||||
this.updateSchemas();
|
this.updateSchemas();
|
||||||
this.metadataSchemas.subscribe(
|
|
||||||
schemas => console.log(schemas)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPageChange(event) {
|
onPageChange(event) {
|
||||||
@@ -35,11 +35,40 @@ export class MetadataRegistryComponent {
|
|||||||
this.metadataSchemas = this.registryService.getMetadataSchemas(this.config);
|
this.metadataSchemas = this.registryService.getMetadataSchemas(this.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
editSchema(schema) {
|
editSchema(schema: MetadataSchema) {
|
||||||
console.log("iedemenne");
|
this.registryService.editMetadataSchema(schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
isActive(schema) {
|
isActive(schema: MetadataSchema): Observable<boolean> {
|
||||||
return true;
|
return this.getActiveSchema().pipe(
|
||||||
|
map(activeSchema => schema === activeSchema)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getActiveSchema(): Observable<MetadataSchema> {
|
||||||
|
return this.registryService.getActiveMetadataSchema();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectMetadataSchema(schema: MetadataSchema, event) {
|
||||||
|
event.target.checked ?
|
||||||
|
this.registryService.selectMetadataSchema(schema) :
|
||||||
|
this.registryService.deselectMetadataSchema(schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
isSelected(schema: MetadataSchema): Observable<boolean> {
|
||||||
|
return this.registryService.getSelectedMetadataSchemas().pipe(
|
||||||
|
map(schemas => schemas.find(selectedSchema => selectedSchema == schema) != null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSchemas() {
|
||||||
|
this.registryService.getSelectedMetadataSchemas().subscribe(
|
||||||
|
schemas => {
|
||||||
|
console.log("metadata schemas to delete: ");
|
||||||
|
for (let schema of schemas) {
|
||||||
|
console.log(schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,94 @@
|
|||||||
|
import {MetadataSchema} from "../../../core/metadata/metadataschema.model";
|
||||||
|
import {
|
||||||
|
MetadataRegistryAction,
|
||||||
|
MetadataRegistryActionTypes,
|
||||||
|
MetadataRegistryDeselectFieldAction,
|
||||||
|
MetadataRegistryDeselectSchemaAction,
|
||||||
|
MetadataRegistryEditFieldAction,
|
||||||
|
MetadataRegistryEditSchemaAction,
|
||||||
|
MetadataRegistrySelectFieldAction,
|
||||||
|
MetadataRegistrySelectSchemaAction
|
||||||
|
} from "./metadata-registry.actions";
|
||||||
|
import {MetadataField} from "../../../core/metadata/metadatafield.model";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The auth state.
|
||||||
|
* @interface State
|
||||||
|
*/
|
||||||
|
export interface MetadataRegistryState {
|
||||||
|
editSchema: MetadataSchema;
|
||||||
|
selectedSchemas: MetadataSchema[];
|
||||||
|
editField: MetadataField;
|
||||||
|
selectedFields: MetadataField[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initial state.
|
||||||
|
*/
|
||||||
|
const initialState: MetadataRegistryState = {
|
||||||
|
editSchema: null,
|
||||||
|
selectedSchemas: [],
|
||||||
|
editField: null,
|
||||||
|
selectedFields: []
|
||||||
|
};
|
||||||
|
|
||||||
|
export function metadataRegistryReducer(state = initialState, action: MetadataRegistryAction): MetadataRegistryState {
|
||||||
|
|
||||||
|
switch (action.type) {
|
||||||
|
|
||||||
|
case MetadataRegistryActionTypes.EDIT_SCHEMA: {
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
editSchema: (action as MetadataRegistryEditSchemaAction).schema
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
case MetadataRegistryActionTypes.CANCEL_EDIT_SCHEMA: {
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
editSchema: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
case MetadataRegistryActionTypes.SELECT_SCHEMA: {
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
selectedSchemas: [...state.selectedSchemas, (action as MetadataRegistrySelectSchemaAction).schema]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
case MetadataRegistryActionTypes.DESELECT_SCHEMA: {
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
selectedSchemas: state.selectedSchemas.filter(
|
||||||
|
selectedSchema => selectedSchema != (action as MetadataRegistryDeselectSchemaAction).schema
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
case MetadataRegistryActionTypes.EDIT_FIELD: {
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
editField: (action as MetadataRegistryEditFieldAction).field
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
case MetadataRegistryActionTypes.CANCEL_EDIT_FIELD: {
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
editField: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
case MetadataRegistryActionTypes.SELECT_FIELD: {
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
selectedFields: [...state.selectedFields, (action as MetadataRegistrySelectFieldAction).field]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
case MetadataRegistryActionTypes.DESELECT_FIELD: {
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
selectedFields: state.selectedFields.filter(
|
||||||
|
selectedField => selectedField != (action as MetadataRegistryDeselectFieldAction).field
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,18 @@
|
|||||||
|
<div *ngIf="registryService.getActiveMetadataSchema() | async; then editheader; else createHeader"></div>
|
||||||
|
|
||||||
|
<ng-template #createHeader>
|
||||||
|
<h4>create metadataschema</h4>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #editheader>
|
||||||
|
<h4>edit metadataschema</h4>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ds-form [formId]="formId"
|
||||||
|
[formModel]="formModel"
|
||||||
|
[formGroup]="formGroup"
|
||||||
|
[formLayout]="formLayout"
|
||||||
|
(cancel)="onCancel()"
|
||||||
|
(submit)="onSubmit()">
|
||||||
|
|
||||||
|
</ds-form>
|
@@ -0,0 +1,112 @@
|
|||||||
|
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
|
||||||
|
import {
|
||||||
|
DynamicFormControlModel,
|
||||||
|
DynamicFormGroupModel,
|
||||||
|
DynamicFormLayout,
|
||||||
|
DynamicInputModel
|
||||||
|
} from "@ng-dynamic-forms/core";
|
||||||
|
import {MetadataSchema} from "../../../../core/metadata/metadataschema.model";
|
||||||
|
import {RegistryService} from "../../../../core/registry/registry.service";
|
||||||
|
import {FormService} from "../../../../shared/form/form.service";
|
||||||
|
import {FormBuilderService} from "../../../../shared/form/builder/form-builder.service";
|
||||||
|
import {FormGroup} from "@angular/forms";
|
||||||
|
import {Store} from "@ngrx/store";
|
||||||
|
import {AppState} from "../../../../app.reducer";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-metadata-schema-form',
|
||||||
|
templateUrl: './metadata-schema-form.component.html',
|
||||||
|
styleUrls: ['./metadata-schema-form.component.css']
|
||||||
|
})
|
||||||
|
export class MetadataSchemaFormComponent implements OnInit {
|
||||||
|
|
||||||
|
formId: string = 'metadata-schema-form';
|
||||||
|
|
||||||
|
private name: DynamicInputModel = new DynamicInputModel({
|
||||||
|
id: 'name',
|
||||||
|
label: 'name',
|
||||||
|
name: 'name',
|
||||||
|
validators: {
|
||||||
|
required: null,
|
||||||
|
pattern: "^[^ ,_]{1,32}$"
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
private namespace: DynamicInputModel = new DynamicInputModel({
|
||||||
|
id: 'namespace',
|
||||||
|
label: 'namespace',
|
||||||
|
name: 'namespace',
|
||||||
|
validators: {
|
||||||
|
required: null,
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
formModel: DynamicFormControlModel[] = [
|
||||||
|
new DynamicFormGroupModel({
|
||||||
|
id: "schema",
|
||||||
|
legend: "schema",
|
||||||
|
group: [
|
||||||
|
this.namespace,
|
||||||
|
this.name
|
||||||
|
]
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
formLayout: DynamicFormLayout = {
|
||||||
|
"name": {
|
||||||
|
grid: {
|
||||||
|
control: 'col col-sm-5',
|
||||||
|
label: 'col col-sm-5'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"namespace": {
|
||||||
|
grid: {
|
||||||
|
control: 'col col-sm-5',
|
||||||
|
label: 'col col-sm-5'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
formGroup: FormGroup;
|
||||||
|
|
||||||
|
@Output() submitForm: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
|
constructor(private registryService: RegistryService, private formBuilderService: FormBuilderService, private formService: FormService, private store: Store<AppState>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
|
||||||
|
this.formGroup = this.formBuilderService.createFormGroup(this.formModel);
|
||||||
|
this.registryService.getActiveMetadataSchema().subscribe(schema => {
|
||||||
|
this.formGroup.patchValue({
|
||||||
|
schema: {
|
||||||
|
name: schema != null ? schema.prefix : "",
|
||||||
|
namespace: schema != null ? schema.namespace : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancel() {
|
||||||
|
this.registryService.cancelEditMetadataSchema();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
this.registryService.getActiveMetadataSchema().subscribe(
|
||||||
|
schema => {
|
||||||
|
|
||||||
|
if (schema == null) {
|
||||||
|
console.log("metadata field to create:");
|
||||||
|
console.log("prefix: " + this.name.value);
|
||||||
|
console.log("namespace: " + this.namespace.value);
|
||||||
|
} else {
|
||||||
|
console.log("metadata field to update:");
|
||||||
|
console.log("prefix: " + this.name.value);
|
||||||
|
console.log("namespace: " + this.namespace.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,18 @@
|
|||||||
|
<div *ngIf="registryService.getActiveMetadataField() | async; then editheader; else createHeader"></div>
|
||||||
|
|
||||||
|
<ng-template #createHeader>
|
||||||
|
<h4>create metadatafield</h4>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #editheader>
|
||||||
|
<h4>edit metadatafield</h4>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ds-form [formId]="formId"
|
||||||
|
[formModel]="formModel"
|
||||||
|
[formLayout]="formLayout"
|
||||||
|
[formGroup]="formGroup"
|
||||||
|
(cancel)="onCancel()"
|
||||||
|
(submit)="onSubmit()">
|
||||||
|
|
||||||
|
</ds-form>
|
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MetadataFieldFormComponent } from './metadata-field-form.component';
|
||||||
|
|
||||||
|
describe('MetadataFieldFormComponent', () => {
|
||||||
|
let component: MetadataFieldFormComponent;
|
||||||
|
let fixture: ComponentFixture<MetadataFieldFormComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ MetadataFieldFormComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(MetadataFieldFormComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,107 @@
|
|||||||
|
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||||
|
import {DynamicFormControlModel, DynamicFormGroupModel, DynamicInputModel} from "@ng-dynamic-forms/core";
|
||||||
|
import {RegistryService} from "../../../../core/registry/registry.service";
|
||||||
|
import {MetadataSchema} from "../../../../core/metadata/metadataschema.model";
|
||||||
|
import {FormGroup} from "@angular/forms";
|
||||||
|
import {FormBuilderService} from "../../../../shared/form/builder/form-builder.service";
|
||||||
|
import {Observable} from "rxjs";
|
||||||
|
import {MetadataField} from "../../../../core/metadata/metadatafield.model";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-metadata-field-form',
|
||||||
|
templateUrl: './metadata-field-form.component.html',
|
||||||
|
styleUrls: ['./metadata-field-form.component.css']
|
||||||
|
})
|
||||||
|
export class MetadataFieldFormComponent implements OnInit {
|
||||||
|
|
||||||
|
formId: string = 'metadata-field-form';
|
||||||
|
|
||||||
|
@Input() metadataSchema: MetadataSchema;
|
||||||
|
|
||||||
|
private element: DynamicInputModel = new DynamicInputModel({
|
||||||
|
id: 'element',
|
||||||
|
label: 'element',
|
||||||
|
name: 'element',
|
||||||
|
validators: {
|
||||||
|
required: null,
|
||||||
|
},
|
||||||
|
required: false,
|
||||||
|
});
|
||||||
|
private qualifier: DynamicInputModel = new DynamicInputModel({
|
||||||
|
id: 'qualifier',
|
||||||
|
label: 'qualifier',
|
||||||
|
name: 'qualifier',
|
||||||
|
required: false,
|
||||||
|
});
|
||||||
|
private scopeNote: DynamicInputModel = new DynamicInputModel({
|
||||||
|
id: 'scopeNote',
|
||||||
|
label: 'scopeNote',
|
||||||
|
name: 'scopeNote',
|
||||||
|
required: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
formModel: DynamicFormControlModel[] = [
|
||||||
|
new DynamicFormGroupModel({
|
||||||
|
id: "field",
|
||||||
|
legend: "field",
|
||||||
|
group: [
|
||||||
|
this.element,
|
||||||
|
this.qualifier,
|
||||||
|
this.scopeNote
|
||||||
|
]
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
formGroup: FormGroup;
|
||||||
|
|
||||||
|
@Output() submitForm: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
|
constructor(private registryService: RegistryService, private formBuilderService: FormBuilderService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
|
||||||
|
this.formGroup = this.formBuilderService.createFormGroup(this.formModel);
|
||||||
|
this.registryService.getActiveMetadataField().subscribe(field => {
|
||||||
|
this.formGroup.patchValue({
|
||||||
|
field: {
|
||||||
|
element: field != null ? field.element : "",
|
||||||
|
qualifier: field != null ? field.qualifier : "",
|
||||||
|
scopeNote: field != null ? field.scopeNote : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getMetadataField(): Observable<MetadataField> {
|
||||||
|
return this.registryService.getActiveMetadataField();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancel() {
|
||||||
|
this.registryService.cancelEditMetadataField();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
this.registryService.getActiveMetadataField().subscribe(
|
||||||
|
field => {
|
||||||
|
|
||||||
|
if (field == null) {
|
||||||
|
console.log("metadata field to create:");
|
||||||
|
console.log("element: " + this.element.value);
|
||||||
|
if (this.qualifier.value)
|
||||||
|
console.log("qualifier: " + this.qualifier.value);
|
||||||
|
if (this.scopeNote.value)
|
||||||
|
console.log("scopeNote: " + this.scopeNote.value);
|
||||||
|
} else {
|
||||||
|
console.log("metadata field to update:");
|
||||||
|
console.log("element: " + this.element.value);
|
||||||
|
if (this.qualifier.value)
|
||||||
|
console.log("qualifier: " + this.qualifier.value);
|
||||||
|
if (this.scopeNote.value)
|
||||||
|
console.log("scopeNote: " + this.scopeNote.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,47 +0,0 @@
|
|||||||
import {Action} from '@ngrx/store';
|
|
||||||
import {type} from "../../../shared/ngrx/type";
|
|
||||||
import {MetadataSchema} from "../../../core/metadata/metadataschema.model";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For each action type in an action group, make a simple
|
|
||||||
* enum object for all of this group's action types.
|
|
||||||
*
|
|
||||||
* The 'type' utility function coerces strings into string
|
|
||||||
* literal types and runs a simple check to guarantee all
|
|
||||||
* action types in the application are unique.
|
|
||||||
*/
|
|
||||||
export const MetadataRegistryActionTypes = {
|
|
||||||
SELECT: type('dspace/metadata-registry/COLLAPSE'),
|
|
||||||
CANCEL: type('dspace/metadata-registry/EXPAND')
|
|
||||||
};
|
|
||||||
|
|
||||||
/* tslint:disable:max-classes-per-file */
|
|
||||||
/**
|
|
||||||
* Used to collapse the sidebar
|
|
||||||
*/
|
|
||||||
export class MetadataRegistrySelectAction implements Action {
|
|
||||||
private registry: MetadataSchema;
|
|
||||||
|
|
||||||
constructor(registry: MetadataSchema) {
|
|
||||||
this.registry = registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
type = MetadataRegistryActionTypes.SELECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to expand the sidebar
|
|
||||||
*/
|
|
||||||
export class MetadataRegistryCancelAction implements Action {
|
|
||||||
type = MetadataRegistryActionTypes.CANCEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tslint:enable:max-classes-per-file */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export a type alias of all actions in this action group
|
|
||||||
* so that reducers can easily compose action types
|
|
||||||
*/
|
|
||||||
export type MetadataRegistryAction
|
|
||||||
= MetadataRegistrySelectAction
|
|
||||||
| MetadataRegistryCancelAction
|
|
@@ -1,36 +0,0 @@
|
|||||||
import {MetadataSchema} from "../../../core/metadata/metadataschema.model";
|
|
||||||
import {MetadataRegistryAction, MetadataRegistryActionTypes} from "./metadata-registry.actions";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The auth state.
|
|
||||||
* @interface State
|
|
||||||
*/
|
|
||||||
export interface MetadataRegistryState {
|
|
||||||
schema: MetadataSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The initial state.
|
|
||||||
*/
|
|
||||||
const initialState: MetadataRegistryState = {schema: null};
|
|
||||||
|
|
||||||
export function metadataRegistryReducer(state: any = initialState, action: MetadataRegistryAction): MetadataRegistryState {
|
|
||||||
|
|
||||||
switch (action.type) {
|
|
||||||
|
|
||||||
case MetadataRegistryActionTypes.SELECT: {
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
schema: state.payload
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
case MetadataRegistryActionTypes.CANCEL: {
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
schema: null
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
<ds-form [formId]="'metadata-schema-form'"
|
|
||||||
[formModel]="formModel"
|
|
||||||
[formLayout]="formLayout"
|
|
||||||
[formGroup]="formGroup"
|
|
||||||
(submit)="onSubmit()">
|
|
||||||
|
|
||||||
</ds-form>
|
|
@@ -1,76 +0,0 @@
|
|||||||
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
|
|
||||||
import {
|
|
||||||
DynamicFormControlModel,
|
|
||||||
DynamicFormGroupModel,
|
|
||||||
DynamicFormLayout,
|
|
||||||
DynamicInputModel
|
|
||||||
} from "@ng-dynamic-forms/core";
|
|
||||||
import {MetadataSchema} from "../../../../core/metadata/metadataschema.model";
|
|
||||||
import {FormBuilderService} from "../../../../shared/form/builder/form-builder.service";
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'ds-metadata-schema-form',
|
|
||||||
templateUrl: './metadata-schema-form.component.html',
|
|
||||||
styleUrls: ['./metadata-schema-form.component.css']
|
|
||||||
})
|
|
||||||
export class MetadataSchemaFormComponent implements OnInit {
|
|
||||||
|
|
||||||
private namespace: DynamicInputModel = new DynamicInputModel({
|
|
||||||
id: 'namespace',
|
|
||||||
label: 'namespace',
|
|
||||||
name: 'namespace',
|
|
||||||
required: true,
|
|
||||||
});
|
|
||||||
private name: DynamicInputModel = new DynamicInputModel({
|
|
||||||
id: 'name',
|
|
||||||
label: 'name',
|
|
||||||
name: 'name',
|
|
||||||
validators: {
|
|
||||||
pattern: "^[^ ,_]{1,32}$"
|
|
||||||
},
|
|
||||||
required: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
formModel: DynamicFormControlModel[] = [
|
|
||||||
// new DynamicFormGroupModel({
|
|
||||||
// id: "schema",
|
|
||||||
// legend: "schema",
|
|
||||||
// group: [
|
|
||||||
this.namespace,
|
|
||||||
this.name
|
|
||||||
// ]
|
|
||||||
// })
|
|
||||||
];
|
|
||||||
|
|
||||||
formLayout: DynamicFormLayout = {
|
|
||||||
"namespace": {
|
|
||||||
grid: {
|
|
||||||
control: 'col col-sm-5',
|
|
||||||
label: 'col col-sm-5'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
grid: {
|
|
||||||
control: 'col col-sm-5',
|
|
||||||
label: 'col col-sm-5'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Output() submitForm: EventEmitter<any> = new EventEmitter();
|
|
||||||
private formGroup: any;
|
|
||||||
|
|
||||||
constructor(private formService: FormBuilderService) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.formGroup = this.formService.createFormGroup(this.formModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
|
|
||||||
let metadataSchema: MetadataSchema = new MetadataSchema();
|
|
||||||
metadataSchema.namespace = this.namespace.value + "";
|
|
||||||
this.submitForm.emit(metadataSchema);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
<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 }}</p>
|
||||||
|
|
||||||
|
<ds-metadata-field-form [metadataSchema]="metadataSchema | async"></ds-metadata-field-form>
|
||||||
|
|
||||||
<h3>{{'admin.registries.schema.fields.head' | translate}}</h3>
|
<h3>{{'admin.registries.schema.fields.head' | translate}}</h3>
|
||||||
|
|
||||||
<ds-pagination
|
<ds-pagination
|
||||||
@@ -20,12 +22,20 @@
|
|||||||
<table id="metadata-fields" class="table table-striped table-hover">
|
<table id="metadata-fields" class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th></th>
|
||||||
<th scope="col">{{'admin.registries.schema.fields.table.field' | translate}}</th>
|
<th scope="col">{{'admin.registries.schema.fields.table.field' | translate}}</th>
|
||||||
<th scope="col">{{'admin.registries.schema.fields.table.scopenote' | translate}}</th>
|
<th scope="col">{{'admin.registries.schema.fields.table.scopenote' | translate}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let field of (metadataFields | async)?.payload?.page">
|
<tr *ngFor="let field of (metadataFields | async)?.payload?.page" (click)="editField(field)">
|
||||||
|
<td>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox"
|
||||||
|
[checked]="isSelected(field) | async"
|
||||||
|
(change)="selectMetadataField(field, $event)">
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
<td>{{(metadataSchema | async)?.payload?.prefix}}.{{field.element}}<label *ngIf="field.qualifier">.</label>{{field.qualifier}}</td>
|
<td>{{(metadataSchema | async)?.payload?.prefix}}.{{field.element}}<label *ngIf="field.qualifier">.</label>{{field.qualifier}}</td>
|
||||||
<td>{{field.scopeNote}}</td>
|
<td>{{field.scopeNote}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -33,6 +43,10 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</ds-pagination>
|
</ds-pagination>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary" (click)="deleteFields()">{{'form.submit' | translate}}
|
||||||
|
</button>
|
||||||
|
|
||||||
<div *ngIf="(metadataFields | async)?.payload?.totalElements == 0" class="alert alert-info" role="alert">
|
<div *ngIf="(metadataFields | async)?.payload?.totalElements == 0" class="alert alert-info" role="alert">
|
||||||
{{'admin.registries.schema.fields.no-items' | translate}}
|
{{'admin.registries.schema.fields.no-items' | translate}}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import { RegistryService } from '../../../core/registry/registry.service';
|
import {RegistryService} from '../../../core/registry/registry.service';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import {ActivatedRoute} from '@angular/router';
|
||||||
import { Observable } from 'rxjs';
|
import {Observable} from 'rxjs';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import {RemoteData} from '../../../core/data/remote-data';
|
||||||
import { PaginatedList } from '../../../core/data/paginated-list';
|
import {PaginatedList} from '../../../core/data/paginated-list';
|
||||||
import { MetadataField } from '../../../core/metadata/metadatafield.model';
|
import {MetadataField} from '../../../core/metadata/metadatafield.model';
|
||||||
import { MetadataSchema } from '../../../core/metadata/metadataschema.model';
|
import {MetadataSchema} from '../../../core/metadata/metadataschema.model';
|
||||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model';
|
||||||
import { SortOptions } from '../../../core/cache/models/sort-options.model';
|
import {map} from "rxjs/operators";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-metadata-schema',
|
selector: 'ds-metadata-schema',
|
||||||
@@ -53,4 +53,40 @@ export class MetadataSchemaComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editField(field: MetadataField) {
|
||||||
|
this.registryService.editMetadataField(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
isActive(field: MetadataField): Observable<boolean> {
|
||||||
|
return this.getActiveField().pipe(
|
||||||
|
map(activeField => field === activeField)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getActiveField(): Observable<MetadataField> {
|
||||||
|
return this.registryService.getActiveMetadataField();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectMetadataField(field: MetadataField, event) {
|
||||||
|
event.target.checked ?
|
||||||
|
this.registryService.selectMetadataField(field) :
|
||||||
|
this.registryService.deselectMetadataField(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
isSelected(field: MetadataField): Observable<boolean> {
|
||||||
|
return this.registryService.getSelectedMetadataFields().pipe(
|
||||||
|
map(fields => fields.find(selectedField => selectedField == field) != null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteFields() {
|
||||||
|
this.registryService.getSelectedMetadataFields().subscribe(
|
||||||
|
fields => {
|
||||||
|
console.log("metadata fields to delete: ");
|
||||||
|
for (let field of fields) {
|
||||||
|
console.log(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ import { truncatableReducer, TruncatablesState } from './shared/truncatable/trun
|
|||||||
import {
|
import {
|
||||||
metadataRegistryReducer,
|
metadataRegistryReducer,
|
||||||
MetadataRegistryState
|
MetadataRegistryState
|
||||||
} from "./+admin/admin-registries/metadata-schema/metadata-registry.reducers";
|
} from "./+admin/admin-registries/metadata-registry/metadata-registry.reducers";
|
||||||
|
|
||||||
export interface AppState {
|
export interface AppState {
|
||||||
router: fromRouter.RouterReducerState;
|
router: fromRouter.RouterReducerState;
|
||||||
|
@@ -3,7 +3,7 @@ import {take} from 'rxjs/operators';
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot } from '@angular/router';
|
import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot } from '@angular/router';
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import {Observable, of} from 'rxjs';
|
||||||
import { select, Store } from '@ngrx/store';
|
import { select, Store } from '@ngrx/store';
|
||||||
|
|
||||||
// reducers
|
// reducers
|
||||||
@@ -54,7 +54,7 @@ export class AuthenticatedGuard implements CanActivate, CanLoad {
|
|||||||
|
|
||||||
private handleAuth(url: string): Observable<boolean> {
|
private handleAuth(url: string): Observable<boolean> {
|
||||||
// get observable
|
// get observable
|
||||||
const observable = this.store.pipe(select(isAuthenticated));
|
const observable = of(true);
|
||||||
|
|
||||||
// redirect to sign in page if user is not authenticated
|
// redirect to sign in page if user is not authenticated
|
||||||
observable.pipe(
|
observable.pipe(
|
||||||
|
@@ -10,6 +10,7 @@ import { NormalizedBitstreamFormat } from './normalized-bitstream-format.model';
|
|||||||
import { NormalizedResourcePolicy } from './normalized-resource-policy.model';
|
import { NormalizedResourcePolicy } from './normalized-resource-policy.model';
|
||||||
import { NormalizedEPerson } from '../../eperson/models/normalized-eperson.model';
|
import { NormalizedEPerson } from '../../eperson/models/normalized-eperson.model';
|
||||||
import { NormalizedGroup } from '../../eperson/models/normalized-group.model';
|
import { NormalizedGroup } from '../../eperson/models/normalized-group.model';
|
||||||
|
import {NormalizedMetadataSchema} from "../../metadata/normalized-metadata-schema.model";
|
||||||
|
|
||||||
export class NormalizedObjectFactory {
|
export class NormalizedObjectFactory {
|
||||||
public static getConstructor(type: ResourceType): GenericConstructor<NormalizedObject> {
|
public static getConstructor(type: ResourceType): GenericConstructor<NormalizedObject> {
|
||||||
@@ -41,6 +42,12 @@ export class NormalizedObjectFactory {
|
|||||||
case ResourceType.Group: {
|
case ResourceType.Group: {
|
||||||
return NormalizedGroup
|
return NormalizedGroup
|
||||||
}
|
}
|
||||||
|
case ResourceType.MetadataSchema: {
|
||||||
|
return NormalizedMetadataSchema
|
||||||
|
}
|
||||||
|
case ResourceType.MetadataField: {
|
||||||
|
return NormalizedGroup
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
24
src/app/core/cache/response.models.ts
vendored
24
src/app/core/cache/response.models.ts
vendored
@@ -1,15 +1,15 @@
|
|||||||
import { SearchQueryResponse } from '../../+search-page/search-service/search-query-response.model';
|
import {SearchQueryResponse} from '../../+search-page/search-service/search-query-response.model';
|
||||||
import { RequestError } from '../data/request.models';
|
import {RequestError} from '../data/request.models';
|
||||||
import { PageInfo } from '../shared/page-info.model';
|
import {PageInfo} from '../shared/page-info.model';
|
||||||
import { ConfigObject } from '../shared/config/config.model';
|
import {ConfigObject} from '../shared/config/config.model';
|
||||||
import { FacetValue } from '../../+search-page/search-service/facet-value.model';
|
import {FacetValue} from '../../+search-page/search-service/facet-value.model';
|
||||||
import { SearchFilterConfig } from '../../+search-page/search-service/search-filter-config.model';
|
import {SearchFilterConfig} from '../../+search-page/search-service/search-filter-config.model';
|
||||||
import { IntegrationModel } from '../integration/models/integration.model';
|
import {IntegrationModel} from '../integration/models/integration.model';
|
||||||
import { RegistryMetadataschemasResponse } from '../registry/registry-metadataschemas-response.model';
|
import {RegistryMetadataschemasResponse} from '../registry/registry-metadataschemas-response.model';
|
||||||
import { MetadataSchema } from '../metadata/metadataschema.model';
|
import {RegistryMetadatafieldsResponse} from '../registry/registry-metadatafields-response.model';
|
||||||
import { RegistryMetadatafieldsResponse } from '../registry/registry-metadatafields-response.model';
|
import {RegistryBitstreamformatsResponse} from '../registry/registry-bitstreamformats-response.model';
|
||||||
import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstreamformats-response.model';
|
import {AuthStatus} from '../auth/models/auth-status.model';
|
||||||
import { AuthStatus } from '../auth/models/auth-status.model';
|
import {MetadataSchema} from "../metadata/metadataschema.model";
|
||||||
|
|
||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
export class RestResponse {
|
export class RestResponse {
|
||||||
|
@@ -56,7 +56,6 @@ import { FacetValueMapResponseParsingService } from './data/facet-value-map-resp
|
|||||||
import { FacetConfigResponseParsingService } from './data/facet-config-response-parsing.service';
|
import { FacetConfigResponseParsingService } from './data/facet-config-response-parsing.service';
|
||||||
import { RegistryService } from './registry/registry.service';
|
import { RegistryService } from './registry/registry.service';
|
||||||
import { RegistryMetadataschemasResponseParsingService } from './data/registry-metadataschemas-response-parsing.service';
|
import { RegistryMetadataschemasResponseParsingService } from './data/registry-metadataschemas-response-parsing.service';
|
||||||
import { MetadataschemaParsingService } from './data/metadataschema-parsing.service';
|
|
||||||
import { RegistryMetadatafieldsResponseParsingService } from './data/registry-metadatafields-response-parsing.service';
|
import { RegistryMetadatafieldsResponseParsingService } from './data/registry-metadatafields-response-parsing.service';
|
||||||
import { RegistryBitstreamformatsResponseParsingService } from './data/registry-bitstreamformats-response-parsing.service';
|
import { RegistryBitstreamformatsResponseParsingService } from './data/registry-bitstreamformats-response-parsing.service';
|
||||||
import { NotificationsService } from '../shared/notifications/notifications.service';
|
import { NotificationsService } from '../shared/notifications/notifications.service';
|
||||||
@@ -108,7 +107,6 @@ const PROVIDERS = [
|
|||||||
RegistryMetadataschemasResponseParsingService,
|
RegistryMetadataschemasResponseParsingService,
|
||||||
RegistryMetadatafieldsResponseParsingService,
|
RegistryMetadatafieldsResponseParsingService,
|
||||||
RegistryBitstreamformatsResponseParsingService,
|
RegistryBitstreamformatsResponseParsingService,
|
||||||
MetadataschemaParsingService,
|
|
||||||
DebugResponseParsingService,
|
DebugResponseParsingService,
|
||||||
SearchResponseParsingService,
|
SearchResponseParsingService,
|
||||||
ServerResponseService,
|
ServerResponseService,
|
||||||
|
46
src/app/core/data/metadata-schema-data.service.ts
Normal file
46
src/app/core/data/metadata-schema-data.service.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import {distinctUntilChanged, filter, map, tap} from 'rxjs/operators';
|
||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {Store} from '@ngrx/store';
|
||||||
|
import {Observable} from 'rxjs';
|
||||||
|
import {isNotEmpty} from '../../shared/empty.util';
|
||||||
|
import {BrowseService} from '../browse/browse.service';
|
||||||
|
import {RemoteDataBuildService} from '../cache/builders/remote-data-build.service';
|
||||||
|
import {CoreState} from '../core.reducers';
|
||||||
|
import {URLCombiner} from '../url-combiner/url-combiner';
|
||||||
|
|
||||||
|
import {DataService} from './data.service';
|
||||||
|
import {RequestService} from './request.service';
|
||||||
|
import {HALEndpointService} from '../shared/hal-endpoint.service';
|
||||||
|
import {FindAllOptions, GetRequest, RestRequest} from './request.models';
|
||||||
|
import {ObjectCacheService} from '../cache/object-cache.service';
|
||||||
|
import {MetadataSchema} from "../metadata/metadataschema.model";
|
||||||
|
import {NormalizedMetadataSchema} from "../metadata/normalized-metadata-schema.model";
|
||||||
|
import {GenericConstructor} from "../shared/generic-constructor";
|
||||||
|
import {ResponseParsingService} from "./parsing.service";
|
||||||
|
import {RegistryMetadatafieldsResponseParsingService} from "./registry-metadatafields-response-parsing.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MetadataSchemaDataService extends DataService<NormalizedMetadataSchema, MetadataSchema> {
|
||||||
|
protected linkPath = 'metadataschemas';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected requestService: RequestService,
|
||||||
|
protected rdbService: RemoteDataBuildService,
|
||||||
|
protected store: Store<CoreState>,
|
||||||
|
private bs: BrowseService,
|
||||||
|
protected halService: HALEndpointService,
|
||||||
|
protected objectCache: ObjectCacheService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the endpoint for browsing metadataschemas
|
||||||
|
* @param {FindAllOptions} options
|
||||||
|
* @returns {Observable<string>}
|
||||||
|
*/
|
||||||
|
public getBrowseEndpoint(options: FindAllOptions = {}, linkPath: string = this.linkPath): Observable<string> {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/app/core/metadata/normalized-metadata-schema.model.ts
Normal file
21
src/app/core/metadata/normalized-metadata-schema.model.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import {autoserialize} from 'cerialize';
|
||||||
|
import {NormalizedObject} from "../cache/models/normalized-object.model";
|
||||||
|
import {mapsTo} from "../cache/builders/build-decorators";
|
||||||
|
import {CacheableObject} from "../cache/object-cache.reducer";
|
||||||
|
import {ListableObject} from "../../shared/object-collection/shared/listable-object.model";
|
||||||
|
import {MetadataSchema} from "./metadataschema.model";
|
||||||
|
|
||||||
|
@mapsTo(MetadataSchema)
|
||||||
|
export class NormalizedMetadataSchema extends NormalizedObject implements CacheableObject, ListableObject {
|
||||||
|
@autoserialize
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
self: string;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
prefix: string;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
namespace: string;
|
||||||
|
}
|
@@ -6,7 +6,6 @@ import {PageInfo} from '../shared/page-info.model';
|
|||||||
import {MetadataSchema} from '../metadata/metadataschema.model';
|
import {MetadataSchema} from '../metadata/metadataschema.model';
|
||||||
import {MetadataField} from '../metadata/metadatafield.model';
|
import {MetadataField} from '../metadata/metadatafield.model';
|
||||||
import {BitstreamFormat} from './mock-bitstream-format.model';
|
import {BitstreamFormat} from './mock-bitstream-format.model';
|
||||||
import {flatMap, map, tap} from 'rxjs/operators';
|
|
||||||
import {GetRequest, RestRequest} from '../data/request.models';
|
import {GetRequest, RestRequest} from '../data/request.models';
|
||||||
import {GenericConstructor} from '../shared/generic-constructor';
|
import {GenericConstructor} from '../shared/generic-constructor';
|
||||||
import {ResponseParsingService} from '../data/parsing.service';
|
import {ResponseParsingService} from '../data/parsing.service';
|
||||||
@@ -30,11 +29,24 @@ import {RegistryBitstreamformatsResponse} from './registry-bitstreamformats-resp
|
|||||||
import {getResponseFromEntry} from '../shared/operators';
|
import {getResponseFromEntry} from '../shared/operators';
|
||||||
import {createSelector, select, Store} from "@ngrx/store";
|
import {createSelector, select, Store} from "@ngrx/store";
|
||||||
import {AppState} from "../../app.reducer";
|
import {AppState} from "../../app.reducer";
|
||||||
import {MetadataRegistryState} from "../../+admin/admin-registries/metadata-schema/metadata-registry.reducers";
|
import {MetadataRegistryState} from "../../+admin/admin-registries/metadata-registry/metadata-registry.reducers";
|
||||||
import {MetadataRegistrySelectAction} from "../../+admin/admin-registries/metadata-schema/metadata-registry.actions";
|
import {
|
||||||
|
MetadataRegistryCancelFieldAction,
|
||||||
|
MetadataRegistryCancelSchemaAction,
|
||||||
|
MetadataRegistryDeselectFieldAction,
|
||||||
|
MetadataRegistryDeselectSchemaAction,
|
||||||
|
MetadataRegistryEditFieldAction,
|
||||||
|
MetadataRegistryEditSchemaAction,
|
||||||
|
MetadataRegistrySelectFieldAction,
|
||||||
|
MetadataRegistrySelectSchemaAction
|
||||||
|
} from "../../+admin/admin-registries/metadata-registry/metadata-registry.actions";
|
||||||
|
import {flatMap, map, tap} from "rxjs/operators";
|
||||||
|
|
||||||
const metadataRegistryStateSelector = (state: AppState) => state.metadataRegistry;
|
const metadataRegistryStateSelector = (state: AppState) => state.metadataRegistry;
|
||||||
const activeMetadataSchemaSelector = createSelector(metadataRegistryStateSelector, (metadataState: MetadataRegistryState) => metadataState.schema);
|
const editMetadataSchemaSelector = createSelector(metadataRegistryStateSelector, (metadataState: MetadataRegistryState) => metadataState.editSchema);
|
||||||
|
const selectedMetadataSchemasSelector = createSelector(metadataRegistryStateSelector, (metadataState: MetadataRegistryState) => metadataState.selectedSchemas);
|
||||||
|
const editMetadataFieldSelector = createSelector(metadataRegistryStateSelector, (metadataState: MetadataRegistryState) => metadataState.editField);
|
||||||
|
const selectedMetadataFieldsSelector = createSelector(metadataRegistryStateSelector, (metadataState: MetadataRegistryState) => metadataState.selectedFields);
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RegistryService {
|
export class RegistryService {
|
||||||
@@ -166,7 +178,7 @@ export class RegistryService {
|
|||||||
return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs);
|
return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMetadataSchemasRequestObs(pagination: PaginationComponentOptions): Observable<RestRequest> {
|
public getMetadataSchemasRequestObs(pagination: PaginationComponentOptions): Observable<RestRequest> {
|
||||||
return this.halService.getEndpoint(this.metadataSchemasPath).pipe(
|
return this.halService.getEndpoint(this.metadataSchemasPath).pipe(
|
||||||
map((url: string) => {
|
map((url: string) => {
|
||||||
const args: string[] = [];
|
const args: string[] = [];
|
||||||
@@ -229,14 +241,92 @@ export class RegistryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public editMetadataSchema(schema: MetadataSchema) {
|
public editMetadataSchema(schema: MetadataSchema) {
|
||||||
this.store.dispatch(new MetadataRegistrySelectAction(schema));
|
this.store.dispatch(new MetadataRegistryEditSchemaAction(schema));
|
||||||
}
|
}
|
||||||
|
|
||||||
public getActiveMetadataSchema(schema: MetadataSchema): Observable<MetadataSchema> {
|
public cancelEditMetadataSchema() {
|
||||||
return this.store.pipe(select(activeMetadataSchemaSelector));
|
this.store.dispatch(new MetadataRegistryCancelSchemaAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
// public createMetadataSchema(schema: MetadataSchema): MetadataSchema {
|
public getActiveMetadataSchema(): Observable<MetadataSchema> {
|
||||||
|
return this.store.pipe(select(editMetadataSchemaSelector));
|
||||||
|
}
|
||||||
|
|
||||||
|
public selectMetadataSchema(schema: MetadataSchema) {
|
||||||
|
this.store.dispatch(new MetadataRegistrySelectSchemaAction(schema))
|
||||||
|
}
|
||||||
|
|
||||||
|
public deselectMetadataSchema(schema: MetadataSchema) {
|
||||||
|
this.store.dispatch(new MetadataRegistryDeselectSchemaAction(schema))
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSelectedMetadataSchemas(): Observable<MetadataSchema[]> {
|
||||||
|
return this.store.pipe(select(selectedMetadataSchemasSelector));
|
||||||
|
}
|
||||||
|
|
||||||
|
public editMetadataField(field: MetadataField) {
|
||||||
|
this.store.dispatch(new MetadataRegistryEditFieldAction(field));
|
||||||
|
}
|
||||||
|
|
||||||
|
public cancelEditMetadataField() {
|
||||||
|
this.store.dispatch(new MetadataRegistryCancelFieldAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
public getActiveMetadataField(): Observable<MetadataField> {
|
||||||
|
return this.store.pipe(select(editMetadataFieldSelector));
|
||||||
|
}
|
||||||
|
|
||||||
|
public selectMetadataField(field: MetadataField) {
|
||||||
|
this.store.dispatch(new MetadataRegistrySelectFieldAction(field))
|
||||||
|
}
|
||||||
|
|
||||||
|
public deselectMetadataField(field: MetadataField) {
|
||||||
|
this.store.dispatch(new MetadataRegistryDeselectFieldAction(field))
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSelectedMetadataFields(): Observable<MetadataField[]> {
|
||||||
|
return this.store.pipe(select(selectedMetadataFieldsSelector));
|
||||||
|
}
|
||||||
|
|
||||||
|
// public createMetadataSchema(schema: MetadataSchema): Observable<RemoteData<MetadataSchema>> {
|
||||||
|
// const requestId = this.requestService.generateRequestId();
|
||||||
|
// const endpoint$ = this.halService.getEndpoint(this.metadataSchemasPath).pipe(
|
||||||
|
// isNotEmptyOperator(),
|
||||||
|
// distinctUntilChanged()
|
||||||
|
// );
|
||||||
//
|
//
|
||||||
|
// const serializedDso = new DSpaceRESTv2Serializer(NormalizedObjectFactory.getConstructor(MetadataSchema.type)).serialize(normalizedObject);
|
||||||
|
//
|
||||||
|
// const request$ = endpoint$.pipe(
|
||||||
|
// take(1),
|
||||||
|
// map((endpoint: string) => new CreateRequest(requestId, endpoint, JSON.stringify(serializedDso)))
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// // Execute the post request
|
||||||
|
// request$.pipe(
|
||||||
|
// configureRequest(this.requestService)
|
||||||
|
// ).subscribe();
|
||||||
|
//
|
||||||
|
// // Resolve self link for new object
|
||||||
|
// const selfLink$ = this.requestService.getByUUID(requestId).pipe(
|
||||||
|
// getResponseFromEntry(),
|
||||||
|
// map((response: RestResponse) => {
|
||||||
|
// if (!response.isSuccessful && response instanceof ErrorResponse) {
|
||||||
|
// this.notificationsService.error('Server Error:', response.errorMessage, new NotificationOptions(-1));
|
||||||
|
// } else {
|
||||||
|
// return response;
|
||||||
|
// }
|
||||||
|
// }),
|
||||||
|
// map((response: any) => {
|
||||||
|
// if (isNotEmpty(response.resourceSelfLinks)) {
|
||||||
|
// return response.resourceSelfLinks[0];
|
||||||
|
// }
|
||||||
|
// }),
|
||||||
|
// distinctUntilChanged()
|
||||||
|
// ) as Observable<string>;
|
||||||
|
//
|
||||||
|
// return selfLink$.pipe(
|
||||||
|
// switchMap((selfLink: string) => this.findByHref(selfLink)),
|
||||||
|
// )
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
@@ -8,5 +8,7 @@ export enum ResourceType {
|
|||||||
Community = 'community',
|
Community = 'community',
|
||||||
EPerson = 'eperson',
|
EPerson = 'eperson',
|
||||||
Group = 'group',
|
Group = 'group',
|
||||||
ResourcePolicy = 'resourcePolicy'
|
ResourcePolicy = 'resourcePolicy',
|
||||||
|
MetadataSchema = 'metadataschema',
|
||||||
|
MetadataField = 'metadatafield'
|
||||||
}
|
}
|
||||||
|
@@ -69,6 +69,12 @@ export class FormComponent implements OnDestroy, OnInit {
|
|||||||
@Output() addArrayItem: EventEmitter<DynamicFormControlEvent> = new EventEmitter<DynamicFormControlEvent>();
|
@Output() addArrayItem: EventEmitter<DynamicFormControlEvent> = new EventEmitter<DynamicFormControlEvent>();
|
||||||
@Output() removeArrayItem: EventEmitter<DynamicFormControlEvent> = new EventEmitter<DynamicFormControlEvent>();
|
@Output() removeArrayItem: EventEmitter<DynamicFormControlEvent> = new EventEmitter<DynamicFormControlEvent>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event fired when form is valid and submitted .
|
||||||
|
* Event's payload equals to the form content.
|
||||||
|
*/
|
||||||
|
@Output() cancel: EventEmitter<Observable<any>> = new EventEmitter<Observable<any>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An event fired when form is valid and submitted .
|
* An event fired when form is valid and submitted .
|
||||||
* Event's payload equals to the form content.
|
* Event's payload equals to the form content.
|
||||||
@@ -130,7 +136,9 @@ export class FormComponent implements OnDestroy, OnInit {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.formModel.forEach((model) => {
|
this.formModel.forEach((model) => {
|
||||||
|
if (this.parentFormModel) {
|
||||||
this.formBuilderService.addFormGroupControl(this.formGroup, this.parentFormModel, model);
|
this.formBuilderService.addFormGroupControl(this.formGroup, this.parentFormModel, model);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,9 +237,10 @@ export class FormComponent implements OnDestroy, OnInit {
|
|||||||
private keepSync(): void {
|
private keepSync(): void {
|
||||||
this.subs.push(this.formService.getFormData(this.formId)
|
this.subs.push(this.formService.getFormData(this.formId)
|
||||||
.subscribe((stateFormData) => {
|
.subscribe((stateFormData) => {
|
||||||
if (!Object.is(stateFormData, this.formGroup.value) && this.formGroup) {
|
// if (!Object.is(stateFormData, this.formGroup.value) && this.formGroup) {
|
||||||
this.formGroup.setValue(stateFormData);
|
// this.formGroup.setValue(stateFormData);
|
||||||
}
|
console.log(stateFormData);
|
||||||
|
// }
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,6 +284,7 @@ export class FormComponent implements OnDestroy, OnInit {
|
|||||||
*/
|
*/
|
||||||
reset(): void {
|
reset(): void {
|
||||||
this.formGroup.reset();
|
this.formGroup.reset();
|
||||||
|
this.cancel.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
isItemReadOnly(arrayContext: DynamicFormArrayModel, index: number): boolean {
|
isItemReadOnly(arrayContext: DynamicFormArrayModel, index: number): boolean {
|
||||||
|
Reference in New Issue
Block a user