diff --git a/src/app/+admin/admin-registries/admin-registries.module.ts b/src/app/+admin/admin-registries/admin-registries.module.ts index 3ac53017ed..18fc44f620 100644 --- a/src/app/+admin/admin-registries/admin-registries.module.ts +++ b/src/app/+admin/admin-registries/admin-registries.module.ts @@ -7,7 +7,8 @@ import { RouterModule } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { BitstreamFormatsComponent } from './bitstream-formats/bitstream-formats.component'; 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({ imports: [ @@ -21,7 +22,11 @@ import { MetadataSchemaFormComponent } from './metadata-schema/metadata-schema-f MetadataRegistryComponent, MetadataSchemaComponent, BitstreamFormatsComponent, - MetadataSchemaFormComponent + MetadataSchemaFormComponent, + MetadataFieldFormComponent + ], + entryComponents: [ + ] }) export class AdminRegistriesModule { diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.actions.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.actions.ts new file mode 100644 index 0000000000..23493c3d21 --- /dev/null +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.actions.ts @@ -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; diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.html b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.html index af73bcf969..661c116a4e 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.html +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.html @@ -1,60 +1,63 @@
-
-
+
diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts index 2aaf178bde..c525fe625a 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts @@ -1,10 +1,13 @@ -import { Component } from '@angular/core'; -import { RegistryService } from '../../../core/registry/registry.service'; -import { Observable } from 'rxjs'; -import { RemoteData } from '../../../core/data/remote-data'; -import { PaginatedList } from '../../../core/data/paginated-list'; -import { MetadataSchema } from '../../../core/metadata/metadataschema.model'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import {Component} from '@angular/core'; +import {RegistryService} from '../../../core/registry/registry.service'; +import {Observable} from 'rxjs'; +import {RemoteData} from '../../../core/data/remote-data'; +import {PaginatedList} from '../../../core/data/paginated-list'; +import {MetadataSchema} from '../../../core/metadata/metadataschema.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({ selector: 'ds-metadata-registry', @@ -21,9 +24,6 @@ export class MetadataRegistryComponent { constructor(private registryService: RegistryService) { this.updateSchemas(); - this.metadataSchemas.subscribe( - schemas => console.log(schemas) - ); } onPageChange(event) { @@ -35,11 +35,40 @@ export class MetadataRegistryComponent { this.metadataSchemas = this.registryService.getMetadataSchemas(this.config); } - editSchema(schema) { - console.log("iedemenne"); + editSchema(schema: MetadataSchema) { + this.registryService.editMetadataSchema(schema); } - isActive(schema) { - return true; + isActive(schema: MetadataSchema): Observable { + return this.getActiveSchema().pipe( + map(activeSchema => schema === activeSchema) + ); + } + + getActiveSchema(): Observable { + return this.registryService.getActiveMetadataSchema(); + } + + selectMetadataSchema(schema: MetadataSchema, event) { + event.target.checked ? + this.registryService.selectMetadataSchema(schema) : + this.registryService.deselectMetadataSchema(schema); + } + + isSelected(schema: MetadataSchema): Observable { + 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); + } + } + ) } } diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-registry.effects.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.effects.ts similarity index 100% rename from src/app/+admin/admin-registries/metadata-schema/metadata-registry.effects.ts rename to src/app/+admin/admin-registries/metadata-registry/metadata-registry.effects.ts diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.reducers.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.reducers.ts new file mode 100644 index 0000000000..0e728e8499 --- /dev/null +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.reducers.ts @@ -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; + } +} \ No newline at end of file diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.html b/src/app/+admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.html new file mode 100644 index 0000000000..3f87018b74 --- /dev/null +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.html @@ -0,0 +1,18 @@ +
+ + +

create metadataschema

+
+ + +

edit metadataschema

+
+ + + + diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema-form/metadata-schema-form.component.spec.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.spec.ts similarity index 100% rename from src/app/+admin/admin-registries/metadata-schema/metadata-schema-form/metadata-schema-form.component.spec.ts rename to src/app/+admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.spec.ts diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.ts new file mode 100644 index 0000000000..54d82170fb --- /dev/null +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.ts @@ -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 = new EventEmitter(); + + constructor(private registryService: RegistryService, private formBuilderService: FormBuilderService, private formService: FormService, private store: Store) { + } + + 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); + } + } + ); + } +} diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.html b/src/app/+admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.html new file mode 100644 index 0000000000..3d4501e559 --- /dev/null +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.html @@ -0,0 +1,18 @@ +
+ + +

create metadatafield

+
+ + +

edit metadatafield

+
+ + + + diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.spec.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.spec.ts new file mode 100644 index 0000000000..124d0ba163 --- /dev/null +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.spec.ts @@ -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; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MetadataFieldFormComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MetadataFieldFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.ts new file mode 100644 index 0000000000..5677f48474 --- /dev/null +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.ts @@ -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 = 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 { + 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); + } + } + ); + } +} diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-registry.actions.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-registry.actions.ts deleted file mode 100644 index 65a7da6a45..0000000000 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-registry.actions.ts +++ /dev/null @@ -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 diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-registry.reducers.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-registry.reducers.ts deleted file mode 100644 index 4ee108ac44..0000000000 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-registry.reducers.ts +++ /dev/null @@ -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; - } -} \ No newline at end of file diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema-form/metadata-schema-form.component.html b/src/app/+admin/admin-registries/metadata-schema/metadata-schema-form/metadata-schema-form.component.html deleted file mode 100644 index 8b51fc35ae..0000000000 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema-form/metadata-schema-form.component.html +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema-form/metadata-schema-form.component.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema-form/metadata-schema-form.component.ts deleted file mode 100644 index ddb177443d..0000000000 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema-form/metadata-schema-form.component.ts +++ /dev/null @@ -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 = 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); - } -} diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.html b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.html index db36b6a1d1..1e422bc381 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.html +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.html @@ -6,6 +6,8 @@

{{'admin.registries.schema.description' | translate:namespace }}

+ +

{{'admin.registries.schema.fields.head' | translate}}

+ {{'admin.registries.schema.fields.table.field' | translate}} {{'admin.registries.schema.fields.table.scopenote' | translate}} - + + + + {{(metadataSchema | async)?.payload?.prefix}}.{{field.element}}{{field.qualifier}} {{field.scopeNote}} @@ -33,6 +43,10 @@
+ + + diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts index 888c3013e7..4d73d58e32 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts @@ -1,13 +1,13 @@ -import { Component, OnInit } from '@angular/core'; -import { RegistryService } from '../../../core/registry/registry.service'; -import { ActivatedRoute } from '@angular/router'; -import { Observable } from 'rxjs'; -import { RemoteData } from '../../../core/data/remote-data'; -import { PaginatedList } from '../../../core/data/paginated-list'; -import { MetadataField } from '../../../core/metadata/metadatafield.model'; -import { MetadataSchema } from '../../../core/metadata/metadataschema.model'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { SortOptions } from '../../../core/cache/models/sort-options.model'; +import {Component, OnInit} from '@angular/core'; +import {RegistryService} from '../../../core/registry/registry.service'; +import {ActivatedRoute} from '@angular/router'; +import {Observable} from 'rxjs'; +import {RemoteData} from '../../../core/data/remote-data'; +import {PaginatedList} from '../../../core/data/paginated-list'; +import {MetadataField} from '../../../core/metadata/metadatafield.model'; +import {MetadataSchema} from '../../../core/metadata/metadataschema.model'; +import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model'; +import {map} from "rxjs/operators"; @Component({ selector: 'ds-metadata-schema', @@ -53,4 +53,40 @@ export class MetadataSchemaComponent implements OnInit { }); } + editField(field: MetadataField) { + this.registryService.editMetadataField(field); + } + + isActive(field: MetadataField): Observable { + return this.getActiveField().pipe( + map(activeField => field === activeField) + ); + } + + getActiveField(): Observable { + return this.registryService.getActiveMetadataField(); + } + + selectMetadataField(field: MetadataField, event) { + event.target.checked ? + this.registryService.selectMetadataField(field) : + this.registryService.deselectMetadataField(field); + } + + isSelected(field: MetadataField): Observable { + 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); + } + } + ) + } } diff --git a/src/app/app.reducer.ts b/src/app/app.reducer.ts index 6208ae9bf1..f8931c2af0 100644 --- a/src/app/app.reducer.ts +++ b/src/app/app.reducer.ts @@ -17,7 +17,7 @@ import { truncatableReducer, TruncatablesState } from './shared/truncatable/trun import { metadataRegistryReducer, MetadataRegistryState -} from "./+admin/admin-registries/metadata-schema/metadata-registry.reducers"; +} from "./+admin/admin-registries/metadata-registry/metadata-registry.reducers"; export interface AppState { router: fromRouter.RouterReducerState; diff --git a/src/app/core/auth/authenticated.guard.ts b/src/app/core/auth/authenticated.guard.ts index b9091a86ad..49ada7e735 100644 --- a/src/app/core/auth/authenticated.guard.ts +++ b/src/app/core/auth/authenticated.guard.ts @@ -3,7 +3,7 @@ import {take} from 'rxjs/operators'; import { Injectable } from '@angular/core'; 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'; // reducers @@ -54,7 +54,7 @@ export class AuthenticatedGuard implements CanActivate, CanLoad { private handleAuth(url: string): Observable { // get observable - const observable = this.store.pipe(select(isAuthenticated)); + const observable = of(true); // redirect to sign in page if user is not authenticated observable.pipe( diff --git a/src/app/core/cache/models/normalized-object-factory.ts b/src/app/core/cache/models/normalized-object-factory.ts index 5c5ebf50aa..468a2b050d 100644 --- a/src/app/core/cache/models/normalized-object-factory.ts +++ b/src/app/core/cache/models/normalized-object-factory.ts @@ -10,6 +10,7 @@ import { NormalizedBitstreamFormat } from './normalized-bitstream-format.model'; import { NormalizedResourcePolicy } from './normalized-resource-policy.model'; import { NormalizedEPerson } from '../../eperson/models/normalized-eperson.model'; import { NormalizedGroup } from '../../eperson/models/normalized-group.model'; +import {NormalizedMetadataSchema} from "../../metadata/normalized-metadata-schema.model"; export class NormalizedObjectFactory { public static getConstructor(type: ResourceType): GenericConstructor { @@ -41,6 +42,12 @@ export class NormalizedObjectFactory { case ResourceType.Group: { return NormalizedGroup } + case ResourceType.MetadataSchema: { + return NormalizedMetadataSchema + } + case ResourceType.MetadataField: { + return NormalizedGroup + } default: { return undefined; } diff --git a/src/app/core/cache/response.models.ts b/src/app/core/cache/response.models.ts index 34fc22bb0a..168bbe6f4d 100644 --- a/src/app/core/cache/response.models.ts +++ b/src/app/core/cache/response.models.ts @@ -1,15 +1,15 @@ -import { SearchQueryResponse } from '../../+search-page/search-service/search-query-response.model'; -import { RequestError } from '../data/request.models'; -import { PageInfo } from '../shared/page-info.model'; -import { ConfigObject } from '../shared/config/config.model'; -import { FacetValue } from '../../+search-page/search-service/facet-value.model'; -import { SearchFilterConfig } from '../../+search-page/search-service/search-filter-config.model'; -import { IntegrationModel } from '../integration/models/integration.model'; -import { RegistryMetadataschemasResponse } from '../registry/registry-metadataschemas-response.model'; -import { MetadataSchema } from '../metadata/metadataschema.model'; -import { RegistryMetadatafieldsResponse } from '../registry/registry-metadatafields-response.model'; -import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstreamformats-response.model'; -import { AuthStatus } from '../auth/models/auth-status.model'; +import {SearchQueryResponse} from '../../+search-page/search-service/search-query-response.model'; +import {RequestError} from '../data/request.models'; +import {PageInfo} from '../shared/page-info.model'; +import {ConfigObject} from '../shared/config/config.model'; +import {FacetValue} from '../../+search-page/search-service/facet-value.model'; +import {SearchFilterConfig} from '../../+search-page/search-service/search-filter-config.model'; +import {IntegrationModel} from '../integration/models/integration.model'; +import {RegistryMetadataschemasResponse} from '../registry/registry-metadataschemas-response.model'; +import {RegistryMetadatafieldsResponse} from '../registry/registry-metadatafields-response.model'; +import {RegistryBitstreamformatsResponse} from '../registry/registry-bitstreamformats-response.model'; +import {AuthStatus} from '../auth/models/auth-status.model'; +import {MetadataSchema} from "../metadata/metadataschema.model"; /* tslint:disable:max-classes-per-file */ export class RestResponse { diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index dcbdbd0049..65484d68aa 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -56,7 +56,6 @@ import { FacetValueMapResponseParsingService } from './data/facet-value-map-resp import { FacetConfigResponseParsingService } from './data/facet-config-response-parsing.service'; import { RegistryService } from './registry/registry.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 { RegistryBitstreamformatsResponseParsingService } from './data/registry-bitstreamformats-response-parsing.service'; import { NotificationsService } from '../shared/notifications/notifications.service'; @@ -108,7 +107,6 @@ const PROVIDERS = [ RegistryMetadataschemasResponseParsingService, RegistryMetadatafieldsResponseParsingService, RegistryBitstreamformatsResponseParsingService, - MetadataschemaParsingService, DebugResponseParsingService, SearchResponseParsingService, ServerResponseService, diff --git a/src/app/core/data/metadata-schema-data.service.ts b/src/app/core/data/metadata-schema-data.service.ts new file mode 100644 index 0000000000..c25e4cc789 --- /dev/null +++ b/src/app/core/data/metadata-schema-data.service.ts @@ -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 { + protected linkPath = 'metadataschemas'; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected store: Store, + private bs: BrowseService, + protected halService: HALEndpointService, + protected objectCache: ObjectCacheService) { + super(); + } + + /** + * Get the endpoint for browsing metadataschemas + * @param {FindAllOptions} options + * @returns {Observable} + */ + public getBrowseEndpoint(options: FindAllOptions = {}, linkPath: string = this.linkPath): Observable { + + return null; + } + +} diff --git a/src/app/core/metadata/normalized-metadata-schema.model.ts b/src/app/core/metadata/normalized-metadata-schema.model.ts new file mode 100644 index 0000000000..73a64bc1ab --- /dev/null +++ b/src/app/core/metadata/normalized-metadata-schema.model.ts @@ -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; +} diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index c371471e76..d6c646a5f5 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -6,7 +6,6 @@ import {PageInfo} from '../shared/page-info.model'; import {MetadataSchema} from '../metadata/metadataschema.model'; import {MetadataField} from '../metadata/metadatafield.model'; import {BitstreamFormat} from './mock-bitstream-format.model'; -import {flatMap, map, tap} from 'rxjs/operators'; import {GetRequest, RestRequest} from '../data/request.models'; import {GenericConstructor} from '../shared/generic-constructor'; import {ResponseParsingService} from '../data/parsing.service'; @@ -30,11 +29,24 @@ import {RegistryBitstreamformatsResponse} from './registry-bitstreamformats-resp import {getResponseFromEntry} from '../shared/operators'; import {createSelector, select, Store} from "@ngrx/store"; import {AppState} from "../../app.reducer"; -import {MetadataRegistryState} from "../../+admin/admin-registries/metadata-schema/metadata-registry.reducers"; -import {MetadataRegistrySelectAction} from "../../+admin/admin-registries/metadata-schema/metadata-registry.actions"; +import {MetadataRegistryState} from "../../+admin/admin-registries/metadata-registry/metadata-registry.reducers"; +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 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() export class RegistryService { @@ -166,7 +178,7 @@ export class RegistryService { return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs); } - private getMetadataSchemasRequestObs(pagination: PaginationComponentOptions): Observable { + public getMetadataSchemasRequestObs(pagination: PaginationComponentOptions): Observable { return this.halService.getEndpoint(this.metadataSchemasPath).pipe( map((url: string) => { const args: string[] = []; @@ -229,14 +241,92 @@ export class RegistryService { } public editMetadataSchema(schema: MetadataSchema) { - this.store.dispatch(new MetadataRegistrySelectAction(schema)); + this.store.dispatch(new MetadataRegistryEditSchemaAction(schema)); } - public getActiveMetadataSchema(schema: MetadataSchema): Observable { - return this.store.pipe(select(activeMetadataSchemaSelector)); + public cancelEditMetadataSchema() { + this.store.dispatch(new MetadataRegistryCancelSchemaAction()); } - // public createMetadataSchema(schema: MetadataSchema): MetadataSchema { + public getActiveMetadataSchema(): Observable { + 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 { + 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 { + 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 { + return this.store.pipe(select(selectedMetadataFieldsSelector)); + } + + // public createMetadataSchema(schema: MetadataSchema): Observable> { + // 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; + // + // return selfLink$.pipe( + // switchMap((selfLink: string) => this.findByHref(selfLink)), + // ) // } } diff --git a/src/app/core/shared/resource-type.ts b/src/app/core/shared/resource-type.ts index e67f3339de..88ffa3386e 100644 --- a/src/app/core/shared/resource-type.ts +++ b/src/app/core/shared/resource-type.ts @@ -8,5 +8,7 @@ export enum ResourceType { Community = 'community', EPerson = 'eperson', Group = 'group', - ResourcePolicy = 'resourcePolicy' + ResourcePolicy = 'resourcePolicy', + MetadataSchema = 'metadataschema', + MetadataField = 'metadatafield' } diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index 2d74ddf8d4..b59d9969ce 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -69,6 +69,12 @@ export class FormComponent implements OnDestroy, OnInit { @Output() addArrayItem: EventEmitter = new EventEmitter(); @Output() removeArrayItem: EventEmitter = new EventEmitter(); + /** + * An event fired when form is valid and submitted . + * Event's payload equals to the form content. + */ + @Output() cancel: EventEmitter> = new EventEmitter>(); + /** * An event fired when form is valid and submitted . * Event's payload equals to the form content. @@ -130,7 +136,9 @@ export class FormComponent implements OnDestroy, OnInit { } else { this.formModel.forEach((model) => { - this.formBuilderService.addFormGroupControl(this.formGroup, this.parentFormModel, model); + if (this.parentFormModel) { + this.formBuilderService.addFormGroupControl(this.formGroup, this.parentFormModel, model); + } }); } @@ -229,9 +237,10 @@ export class FormComponent implements OnDestroy, OnInit { private keepSync(): void { this.subs.push(this.formService.getFormData(this.formId) .subscribe((stateFormData) => { - if (!Object.is(stateFormData, this.formGroup.value) && this.formGroup) { - this.formGroup.setValue(stateFormData); - } + // if (!Object.is(stateFormData, this.formGroup.value) && this.formGroup) { + // this.formGroup.setValue(stateFormData); + console.log(stateFormData); + // } })); } @@ -275,6 +284,7 @@ export class FormComponent implements OnDestroy, OnInit { */ reset(): void { this.formGroup.reset(); + this.cancel.emit(); } isItemReadOnly(arrayContext: DynamicFormArrayModel, index: number): boolean {