diff --git a/resources/i18n/en.json b/resources/i18n/en.json
index e24ece36ee..a8a45c5dd2 100644
--- a/resources/i18n/en.json
+++ b/resources/i18n/en.json
@@ -153,7 +153,13 @@
"recent-submissions": "Error fetching recent submissions",
"item": "Error fetching item",
"objects": "Error fetching objects",
- "search-results": "Error fetching search results"
+ "search-results": "Error fetching search results",
+ "validation": {
+ "pattern": "This input is restricted by the current pattern: {{ pattern }}.",
+ "license": {
+ "notgranted": "You must grant this license to complete your submission. If you are unable to grant this license at this time you may save your work and return later or remove the submission."
+ }
+ }
},
"form": {
"submit": "Submit",
@@ -168,11 +174,6 @@
"group-collapse": "Collapse",
"group-expand": "Expand",
"group-collapse-help": "Click here to collapse",
- "group-expand-help": "Click here to expand and add more element",
- "error": {
- "validation": {
- "pattern": "This input is restricted by the current pattern: {{ pattern }}."
- }
- }
+ "group-expand-help": "Click here to expand and add more element"
}
}
diff --git a/src/app/shared/chips/chips.component.html b/src/app/shared/chips/chips.component.html
index 870f7db396..9bbe44903e 100644
--- a/src/app/shared/chips/chips.component.html
+++ b/src/app/shared/chips/chips.component.html
@@ -2,25 +2,27 @@
{{tipText}}
- -
+
-
+ (click)="chipsSelected($event, i);">
-
+ [class.text-muted]="!(icon.hasAuthority)"
+ aria-hidden="true"
+ (dragstart)="tooltip.close();"
+ (mouseover)="showTooltip(t, i, icon.metadata)"
+ (mouseout)="t.close()">
{{c.display}}
diff --git a/src/app/shared/chips/chips.component.spec.ts b/src/app/shared/chips/chips.component.spec.ts
index 256c29ed86..74e9c827b9 100644
--- a/src/app/shared/chips/chips.component.spec.ts
+++ b/src/app/shared/chips/chips.component.spec.ts
@@ -9,16 +9,8 @@ import { ChipsComponent } from './chips.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { SortablejsModule } from 'angular-sortablejs';
import { By } from '@angular/platform-browser';
-
-function createTestComponent(html: string, type: { new(...args: any[]): T }): ComponentFixture {
- TestBed.overrideComponent(type, {
- set: {template: html}
- });
- const fixture = TestBed.createComponent(type);
-
- fixture.detectChanges();
- return fixture as ComponentFixture;
-}
+import { FormFieldMetadataValueObject } from '../form/builder/models/form-field-metadata-value.model';
+import { createTestComponent, hasClass } from '../testing/utils';
describe('ChipsComponent test suite', () => {
@@ -35,7 +27,7 @@ describe('ChipsComponent test suite', () => {
TestBed.configureTestingModule({
imports: [
NgbModule.forRoot(),
- SortablejsModule.forRoot({ animation: 150 }),
+ SortablejsModule.forRoot({animation: 150}),
],
declarations: [
ChipsComponent,
@@ -51,103 +43,145 @@ describe('ChipsComponent test suite', () => {
}));
- // synchronous beforeEach
- beforeEach(() => {
- html = `
+ describe('', () => {
+ // synchronous beforeEach
+ beforeEach(() => {
+ html = `
`;
- testFixture = createTestComponent(html, TestComponent) as ComponentFixture;
- testComp = testFixture.componentInstance;
+ testFixture = createTestComponent(html, TestComponent) as ComponentFixture;
+ testComp = testFixture.componentInstance;
+ });
+
+ it('should create Chips Component', inject([ChipsComponent], (app: ChipsComponent) => {
+ expect(app).toBeDefined();
+ }));
});
- it('should create Chips Component', inject([ChipsComponent], (app: ChipsComponent) => {
- expect(app).toBeDefined();
- }));
+ describe('when has items as string', () => {
+ beforeEach(() => {
+ chips = new Chips(['a', 'b', 'c']);
+ chipsFixture = TestBed.createComponent(ChipsComponent);
+ chipsComp = chipsFixture.componentInstance; // TruncatableComponent test instance
+ chipsComp.editable = true;
+ chipsComp.chips = chips;
+ chipsFixture.detectChanges();
+ });
- beforeEach(() => {
- chips = new Chips(['a', 'b', 'c']);
- chipsFixture = TestBed.createComponent(ChipsComponent);
- chipsComp = chipsFixture.componentInstance; // TruncatableComponent test instance
- chipsComp.editable = true;
- chipsComp.chips = chips;
- chipsFixture.detectChanges();
+ afterEach(() => {
+ chipsFixture.destroy();
+ chipsComp = null;
+ });
+
+ it('should set edit mode when a chip item is selected', fakeAsync(() => {
+
+ spyOn(chipsComp.selected, 'emit');
+
+ chipsComp.chipsSelected(new Event('click'), 1);
+ chipsFixture.detectChanges();
+ tick();
+
+ const item = chipsComp.chips.getChipByIndex(1);
+
+ expect(item.editMode).toBe(true);
+ expect(chipsComp.selected.emit).toHaveBeenCalledWith(1);
+ }));
+
+ it('should not set edit mode when a chip item is selected and editable is false', fakeAsync(() => {
+ chipsComp.editable = false;
+ spyOn(chipsComp.selected, 'emit');
+
+ chipsComp.chipsSelected(new Event('click'), 1);
+ chipsFixture.detectChanges();
+ tick();
+
+ const item = chipsComp.chips.getChipByIndex(1);
+
+ expect(item.editMode).toBe(false);
+ expect(chipsComp.selected.emit).not.toHaveBeenCalledWith(1);
+ }));
+
+ it('should emit when a chip item is removed and editable is true', fakeAsync(() => {
+
+ spyOn(chipsComp.chips, 'remove');
+
+ const item = chipsComp.chips.getChipByIndex(1);
+
+ chipsComp.removeChips(new Event('click'), 1);
+ chipsFixture.detectChanges();
+ tick();
+
+ expect(chipsComp.chips.remove).toHaveBeenCalledWith(item);
+ }));
+
+ it('should save chips item index when drag and drop start', fakeAsync(() => {
+ const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
+
+ de.triggerEventHandler('dragstart', null);
+
+ expect(chipsComp.dragged).toBe(0);
+ }));
+
+ it('should update chips item order when drag and drop end', fakeAsync(() => {
+ spyOn(chipsComp.chips, 'updateOrder');
+ const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
+
+ de.triggerEventHandler('dragend', null);
+
+ expect(chipsComp.dragged).toBe(-1);
+ expect(chipsComp.chips.updateOrder).toHaveBeenCalled();
+ }));
});
- afterEach(() => {
- chipsFixture.destroy();
- chipsComp = null;
+ describe('when has items as object', () => {
+ beforeEach(() => {
+ const item = {
+ mainField: new FormFieldMetadataValueObject('main test', null, 'test001'),
+ relatedField: new FormFieldMetadataValueObject('related test', null, 'test002'),
+ otherRelatedField: new FormFieldMetadataValueObject('other related test')
+ };
+
+ const iconsConfig = {
+ mainField: 'fa-user',
+ relatedField: 'fa-user-alt',
+ otherRelatedField: 'fa-user-alt'
+ };
+ chips = new Chips([item], 'display', 'mainField', iconsConfig);
+ chipsFixture = TestBed.createComponent(ChipsComponent);
+ chipsComp = chipsFixture.componentInstance; // TruncatableComponent test instance
+ chipsComp.editable = true;
+ chipsComp.chips = chips;
+ chipsFixture.detectChanges();
+ });
+
+ it('should show icon for every field that has a configured icon', () => {
+ const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
+ const icons = de.queryAll(By.css('i.fa'));
+
+ expect(icons.length).toBe(4);
+
+ });
+
+ it('should has text-muted on icon style when field value had not authority', () => {
+ const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
+ const icons = de.queryAll(By.css('i.fa'));
+
+ expect(hasClass(icons[2].nativeElement, 'text-muted')).toBeTruthy();
+ });
+
+ it('should show tooltip on mouse over an icon', () => {
+ const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
+ const icons = de.queryAll(By.css('i.fa'));
+
+ icons[0].triggerEventHandler('mouseover', null);
+
+ expect(chipsComp.tipText).toBe('main test')
+ });
});
-
- it('should set edit mode when a chip item is selected', fakeAsync(() => {
-
- spyOn(chipsComp.selected, 'emit');
-
- chipsComp.chipsSelected(new Event('click'), 1);
- chipsFixture.detectChanges();
- tick();
-
- const item = chipsComp.chips.getChipByIndex(1);
-
- expect(item.editMode).toBe(true);
- expect(chipsComp.selected.emit).toHaveBeenCalledWith(1);
- }));
-
- it('should not set edit mode when a chip item is selected and editable is false', fakeAsync(() => {
- chipsComp.editable = false;
- spyOn(chipsComp.selected, 'emit');
-
- chipsComp.chipsSelected(new Event('click'), 1);
- chipsFixture.detectChanges();
- tick();
-
- const item = chipsComp.chips.getChipByIndex(1);
-
- expect(item.editMode).toBe(false);
- expect(chipsComp.selected.emit).not.toHaveBeenCalledWith(1);
- }));
-
- it('should emit when a chip item is removed and editable is true', fakeAsync(() => {
-
- spyOn(chipsComp.chips, 'remove');
-
- const item = chipsComp.chips.getChipByIndex(1);
-
- chipsComp.removeChips(new Event('click'), 1);
- chipsFixture.detectChanges();
- tick();
-
- expect(chipsComp.chips.remove).toHaveBeenCalledWith(item);
- }));
-
- it('should save chips item index when drag and drop start', fakeAsync(() => {
- const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
-
- de.triggerEventHandler('dragstart', null);
-
- expect(chipsComp.dragged).toBe(0)
- }));
-
- it('should update chips item order when drag and drop end', fakeAsync(() => {
- spyOn(chipsComp.chips, 'updateOrder');
- const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
-
- de.triggerEventHandler('dragend', null);
-
- expect(chipsComp.dragged).toBe(-1)
- expect(chipsComp.chips.updateOrder).toHaveBeenCalled();
- }));
-
- it('should show item tooltip on mouse over', fakeAsync(() => {
- const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
-
- de.triggerEventHandler('mouseover', null);
-
- expect(chipsComp.tipText).toBe('a')
- }));
});
// declare a test component
diff --git a/src/app/shared/chips/chips.component.ts b/src/app/shared/chips/chips.component.ts
index e8167ec5a1..cd4ae3a3e8 100644
--- a/src/app/shared/chips/chips.component.ts
+++ b/src/app/shared/chips/chips.component.ts
@@ -65,8 +65,7 @@ export class ChipsComponent implements OnChanges {
}
}
- onDragStart(tooltip: NgbTooltip, index) {
- tooltip.close();
+ onDragStart(index) {
this.uploaderService.overrideDragOverPage();
this.dragged = index;
}
@@ -77,10 +76,16 @@ export class ChipsComponent implements OnChanges {
this.chips.updateOrder();
}
- showTooltip(tooltip: NgbTooltip, index, content) {
+ showTooltip(tooltip: NgbTooltip, index, field?) {
tooltip.close();
- if (!this.chips.getChipByIndex(index).editMode && this.dragged === -1) {
- this.tipText = content;
+ const item = this.chips.getChipByIndex(index);
+ if (!item.editMode && this.dragged === -1) {
+ if (field) {
+ this.tipText = item.item[field].display;
+ } else {
+ this.tipText = item.display;
+ }
+
this.cdr.detectChanges();
tooltip.open();
}
diff --git a/src/app/shared/chips/models/chips-item.model.ts b/src/app/shared/chips/models/chips-item.model.ts
index ed082a51eb..b0798ce453 100644
--- a/src/app/shared/chips/models/chips-item.model.ts
+++ b/src/app/shared/chips/models/chips-item.model.ts
@@ -1,7 +1,9 @@
-import { uniqueId } from 'lodash';
+import { uniqueId, isObject } from 'lodash';
import { isNotEmpty } from '../../empty.util';
export interface ChipsItemIcon {
+ metadata: string;
+ hasAuthority: boolean;
style: string;
tooltip?: any;
}
@@ -54,15 +56,12 @@ export class ChipsItem {
private setDisplayText(): void {
let value = this.item;
- if ( typeof this.item === 'object') {
+ if (isObject(this.item)) {
// Check If displayField is in an internal object
const obj = this.objToDisplay ? this.item[this.objToDisplay] : this.item;
- const displayFieldBkp = 'value';
- if (obj instanceof Object && obj && obj[this.fieldToDisplay]) {
- value = obj[this.fieldToDisplay];
- } else if (obj instanceof Object && obj && obj[displayFieldBkp]) {
- value = obj[displayFieldBkp];
+ if (isObject(obj) && obj) {
+ value = obj[this.fieldToDisplay] || obj.value;
} else {
value = obj;
}
diff --git a/src/app/shared/chips/models/chips.model.ts b/src/app/shared/chips/models/chips.model.ts
index 4476c1cd77..2866eb61b3 100644
--- a/src/app/shared/chips/models/chips.model.ts
+++ b/src/app/shared/chips/models/chips.model.ts
@@ -1,9 +1,7 @@
-import { findIndex, isEqual } from 'lodash';
+import { findIndex, isEqual, isObject } from 'lodash';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { ChipsItem, ChipsItemIcon } from './chips-item.model';
import { hasValue } from '../../empty.util';
-import { FormFieldMetadataValueObject } from '../../form/builder/models/form-field-metadata-value.model';
-import { AuthorityValueModel } from '../../../core/integration/models/authority-value.model';
export interface ChipsIconsConfig {
[metadata: string]: string;
@@ -99,15 +97,25 @@ export class Chips {
Object.keys(item)
.forEach((metadata) => {
const value = item[metadata];
- if (hasValue(value)
- && (value instanceof FormFieldMetadataValueObject || value instanceof AuthorityValueModel)
- && ((value as FormFieldMetadataValueObject).authority || (value as AuthorityValueModel).id)
- && this.iconsConfig.hasOwnProperty(metadata)) {
+ if (hasValue(value) && isObject(value) && this.iconsConfig.hasOwnProperty(metadata)) {
- const icon: ChipsItemIcon = {
- style: this.iconsConfig[metadata]
- };
- icons.push(icon);
+ let icon: ChipsItemIcon;
+ const hasAuthority: boolean = ((value.hasOwnProperty('authority') && value.authority)
+ || (value.hasOwnProperty('id') && value.id)) ? true : false;
+
+ // Set icons
+ if ((this.displayObj && this.displayObj === metadata && hasAuthority)
+ || (this.displayObj && this.displayObj !== metadata)) {
+
+ icon = {
+ metadata,
+ hasAuthority: hasAuthority,
+ style: this.iconsConfig[metadata]
+ };
+ }
+ if (icon) {
+ icons.push(icon);
+ }
}
});
diff --git a/src/app/shared/chips/models/chpis-item.model.spec.ts b/src/app/shared/chips/models/chpis-item.model.spec.ts
index 6e1e2dcc3b..72e4e37cab 100644
--- a/src/app/shared/chips/models/chpis-item.model.spec.ts
+++ b/src/app/shared/chips/models/chpis-item.model.spec.ts
@@ -34,14 +34,14 @@ describe('ChipsItem model test suite', () => {
});
it('should update icons', () => {
- const icons: ChipsItemIcon[] = [{style: 'fa fa-plus'}];
+ const icons: ChipsItemIcon[] = [{metadata: 'test', hasAuthority: false, style: 'fa fa-plus'}];
item.updateIcons(icons);
expect(item.icons).toEqual(icons);
});
it('should return true if has icons', () => {
- const icons: ChipsItemIcon[] = [{style: 'fa fa-plus'}];
+ const icons: ChipsItemIcon[] = [{metadata: 'test', hasAuthority: false, style: 'fa fa-plus'}];
item.updateIcons(icons);
const hasIcons = item.hasIcons();
diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts
index 855ef8109b..f37b3868f3 100644
--- a/src/app/shared/form/builder/parsers/field-parser.ts
+++ b/src/app/shared/form/builder/parsers/field-parser.ts
@@ -216,7 +216,7 @@ export abstract class FieldParser {
controlModel.errorMessages = Object.assign(
{},
controlModel.errorMessages,
- {pattern: 'form.error.validation.pattern'});
+ {pattern: 'error.validation.pattern'});
}
diff --git a/src/app/shared/form/builder/parsers/group-field-parser.ts b/src/app/shared/form/builder/parsers/group-field-parser.ts
index 82f2668420..9a7b2bc42d 100644
--- a/src/app/shared/form/builder/parsers/group-field-parser.ts
+++ b/src/app/shared/form/builder/parsers/group-field-parser.ts
@@ -40,7 +40,7 @@ export class GroupFieldParser extends FieldParser {
const mandatoryFieldEntries: FormFieldMetadataValueObject[] = this.getInitFieldValues(modelConfiguration.mandatoryField);
mandatoryFieldEntries.forEach((entry, index) => {
const item = Object.create(null);
- const listFields = modelConfiguration.relationFields.concat(modelConfiguration.mandatoryField);
+ const listFields = [modelConfiguration.mandatoryField].concat(modelConfiguration.relationFields);
listFields.forEach((fieldId) => {
const value = this.getInitFieldValue(0, index, [fieldId]);
item[fieldId] = isNotEmpty(value) ? value : PLACEHOLDER_PARENT_METADATA;