mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-14 21:43:04 +00:00
Finished refactoring, guards, docs, tests
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
<ds-form *ngIf="formModel"
|
||||
[formId]="'comcol-form-id'"
|
||||
[formModel]="formModel" (submitForm)="onSubmit()"></ds-form>
|
@@ -0,0 +1,115 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { DynamicFormService, DynamicInputModel } from '@ng-dynamic-forms/core';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model';
|
||||
import { Community } from '../../../core/shared/community.model';
|
||||
import { ResourceType } from '../../../core/shared/resource-type';
|
||||
import { ComColFormComponent } from './comcol-form.component';
|
||||
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
||||
import { hasValue } from '../../empty.util';
|
||||
import { Metadatum } from '../../../core/shared/metadatum.model';
|
||||
|
||||
describe('ComColFormComponent', () => {
|
||||
let comp: ComColFormComponent<DSpaceObject>;
|
||||
let fixture: ComponentFixture<ComColFormComponent<DSpaceObject>>;
|
||||
let location: Location;
|
||||
const formServiceStub: any = {
|
||||
createFormGroup: (fModel: DynamicFormControlModel[]) => {
|
||||
const controls = {};
|
||||
if (hasValue(fModel)) {
|
||||
fModel.forEach((controlModel) => {
|
||||
controls[controlModel.id] = new FormControl((controlModel as any).value);
|
||||
});
|
||||
return new FormGroup(controls);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
const titleMD = { key: 'dc.title', value: 'Community Title' } as Metadatum;
|
||||
const randomMD = { key: 'dc.random', value: 'Random metadata excluded from form' } as Metadatum;
|
||||
const abstractMD = {
|
||||
key: 'dc.description.abstract',
|
||||
value: 'Community description'
|
||||
} as Metadatum;
|
||||
const newTitleMD = { key: 'dc.title', value: 'New Community Title' } as Metadatum;
|
||||
const formModel = [
|
||||
new DynamicInputModel({
|
||||
id: 'title',
|
||||
name: newTitleMD.key,
|
||||
value: 'New Community Title'
|
||||
}),
|
||||
new DynamicInputModel({
|
||||
id: 'abstract',
|
||||
name: abstractMD.key,
|
||||
value: abstractMD.value
|
||||
})
|
||||
];
|
||||
|
||||
/* tslint:disable:no-empty */
|
||||
const locationStub = {
|
||||
back: () => {
|
||||
}
|
||||
};
|
||||
/* tslint:enable:no-empty */
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot(), RouterTestingModule],
|
||||
declarations: [ComColFormComponent],
|
||||
providers: [
|
||||
{ provide: Location, useValue: locationStub },
|
||||
{ provide: DynamicFormService, useValue: formServiceStub }
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ComColFormComponent);
|
||||
comp = fixture.componentInstance;
|
||||
comp.formModel = [];
|
||||
comp.dso = new Community();
|
||||
fixture.detectChanges();
|
||||
location = (comp as any).location;
|
||||
});
|
||||
|
||||
describe('onSubmit', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(comp.submitForm, 'emit');
|
||||
comp.formModel = formModel;
|
||||
});
|
||||
|
||||
it('should emit the new version of the community', () => {
|
||||
comp.dso = Object.assign(
|
||||
new Community(),
|
||||
{
|
||||
metadata: [
|
||||
titleMD,
|
||||
randomMD
|
||||
]
|
||||
}
|
||||
);
|
||||
|
||||
comp.onSubmit();
|
||||
|
||||
expect(comp.submitForm.emit).toHaveBeenCalledWith(
|
||||
Object.assign(
|
||||
{},
|
||||
new Community(),
|
||||
{
|
||||
metadata: [
|
||||
randomMD,
|
||||
newTitleMD,
|
||||
abstractMD
|
||||
],
|
||||
type: ResourceType.Community
|
||||
},
|
||||
)
|
||||
);
|
||||
})
|
||||
});
|
||||
});
|
112
src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts
Normal file
112
src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import {
|
||||
DynamicFormService,
|
||||
DynamicInputModel
|
||||
} from '@ng-dynamic-forms/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
||||
import { isNotEmpty } from '../../empty.util';
|
||||
import { ResourceType } from '../../../core/shared/resource-type';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-comcol-form',
|
||||
styleUrls: ['./comcol-form.component.scss'],
|
||||
templateUrl: './comcol-form.component.html'
|
||||
})
|
||||
export class ComColFormComponent<T extends DSpaceObject> implements OnInit {
|
||||
/**
|
||||
* DSpaceObject that the form represents
|
||||
*/
|
||||
@Input() dso: T;
|
||||
|
||||
/**
|
||||
* Type of DSpaceObject that the form represents
|
||||
*/
|
||||
protected type;
|
||||
|
||||
/**
|
||||
* @type {string} Key prefix used to generate form labels
|
||||
*/
|
||||
LABEL_KEY_PREFIX = '.form.';
|
||||
|
||||
/**
|
||||
* @type {string} Key prefix used to generate form error messages
|
||||
*/
|
||||
ERROR_KEY_PREFIX = '.form.errors.';
|
||||
|
||||
/**
|
||||
* The form model that represents the fields in the form
|
||||
*/
|
||||
formModel: DynamicFormControlModel[];
|
||||
|
||||
/**
|
||||
* The form group of this form
|
||||
*/
|
||||
formGroup: FormGroup;
|
||||
|
||||
/**
|
||||
* Emits DSO when the form is submitted
|
||||
* @type {EventEmitter<any>}
|
||||
*/
|
||||
@Output() submitForm: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
public constructor(private location: Location,
|
||||
private formService: DynamicFormService,
|
||||
private translate: TranslateService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.formModel.forEach(
|
||||
(fieldModel: DynamicInputModel) => {
|
||||
fieldModel.value = this.dso.findMetadata(fieldModel.name);
|
||||
}
|
||||
);
|
||||
this.formGroup = this.formService.createFormGroup(this.formModel);
|
||||
|
||||
this.updateFieldTranslations();
|
||||
this.translate.onLangChange
|
||||
.subscribe(() => {
|
||||
this.updateFieldTranslations();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks which new fields where added and sends the updated version of the DSO to the parent component
|
||||
*/
|
||||
onSubmit() {
|
||||
const metadata = this.formModel.map(
|
||||
(fieldModel: DynamicInputModel) => {
|
||||
return { key: fieldModel.name, value: fieldModel.value }
|
||||
}
|
||||
);
|
||||
const filteredOldMetadata = this.dso.metadata.filter((filter) => !metadata.map((md) => md.key).includes(filter.key));
|
||||
const filteredNewMetadata = metadata.filter((md) => isNotEmpty(md.value));
|
||||
|
||||
const newMetadata = [...filteredOldMetadata, ...filteredNewMetadata];
|
||||
const updatedDSO = Object.assign({}, this.dso, {
|
||||
metadata: newMetadata,
|
||||
type: ResourceType.Community
|
||||
});
|
||||
this.submitForm.emit(updatedDSO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used the update translations of errors and labels on init and on language change
|
||||
*/
|
||||
private updateFieldTranslations() {
|
||||
this.formModel.forEach(
|
||||
(fieldModel: DynamicInputModel) => {
|
||||
fieldModel.label = this.translate.instant(this.type + this.LABEL_KEY_PREFIX + fieldModel.id);
|
||||
if (isNotEmpty(fieldModel.validators)) {
|
||||
fieldModel.errorMessages = {};
|
||||
Object.keys(fieldModel.validators).forEach((key) => {
|
||||
fieldModel.errorMessages[key] = this.translate.instant(this.type + this.ERROR_KEY_PREFIX + fieldModel.id + '.' + key);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user