Renamed form.reducers.ts to form.reducer.ts

Created custom sass variable
Removed use of instanceof operator
This commit is contained in:
Giuseppe Digilio
2018-07-03 17:51:26 +02:00
parent b74993413d
commit ff41b80a33
29 changed files with 220 additions and 137 deletions

View File

@@ -3,7 +3,7 @@ import * as fromRouter from '@ngrx/router-store';
import { headerReducer, HeaderState } from './header/header.reducer'; import { headerReducer, HeaderState } from './header/header.reducer';
import { hostWindowReducer, HostWindowState } from './shared/host-window.reducer'; import { hostWindowReducer, HostWindowState } from './shared/host-window.reducer';
import { formReducer, FormState } from './shared/form/form.reducers'; import { formReducer, FormState } from './shared/form/form.reducer';
import { import {
SearchSidebarState, SearchSidebarState,
sidebarReducer sidebarReducer

View File

@@ -33,7 +33,7 @@ import {
import { DYNAMIC_FORM_CONTROL_TYPE_TYPEAHEAD } from './models/typeahead/dynamic-typeahead.model'; import { DYNAMIC_FORM_CONTROL_TYPE_TYPEAHEAD } from './models/typeahead/dynamic-typeahead.model';
import { DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; import { DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.model';
import { DYNAMIC_FORM_CONTROL_TYPE_TAG } from './models/tag/dynamic-tag.model'; import { DYNAMIC_FORM_CONTROL_TYPE_TAG } from './models/tag/dynamic-tag.model';
import { DYNAMIC_FORM_CONTROL_TYPE_RELATION } from './models/dynamic-group/dynamic-group.model'; import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './models/dynamic-group/dynamic-group.model';
import { DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER } from './models/date-picker/date-picker.model'; import { DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER } from './models/date-picker/date-picker.model';
import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP } from './models/lookup/dynamic-lookup.model'; import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP } from './models/lookup/dynamic-lookup.model';
import { DynamicListCheckboxGroupModel } from './models/list/dynamic-list-checkbox-group.model'; import { DynamicListCheckboxGroupModel } from './models/list/dynamic-list-checkbox-group.model';
@@ -137,7 +137,7 @@ export class DsDynamicFormControlComponent extends DynamicFormControlComponent i
case DYNAMIC_FORM_CONTROL_TYPE_TAG: case DYNAMIC_FORM_CONTROL_TYPE_TAG:
return NGBootstrapFormControlType.Tag; return NGBootstrapFormControlType.Tag;
case DYNAMIC_FORM_CONTROL_TYPE_RELATION: case DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP:
return NGBootstrapFormControlType.Relation; return NGBootstrapFormControlType.Relation;
case DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER: case DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER:

View File

@@ -16,6 +16,7 @@ export class DynamicConcatModel extends DynamicFormGroupModel {
@serializable() separator: string; @serializable() separator: string;
@serializable() hasLanguages = false; @serializable() hasLanguages = false;
isCustomGroup = true;
constructor(config: DynamicConcatModelConfig, layout?: DynamicFormControlLayout) { constructor(config: DynamicConcatModelConfig, layout?: DynamicFormControlLayout) {

View File

@@ -20,6 +20,7 @@ export class DynamicQualdropModel extends DynamicFormGroupModel {
@serializable() languageUpdates: Subject<string>; @serializable() languageUpdates: Subject<string>;
@serializable() hasLanguages = false; @serializable() hasLanguages = false;
@serializable() readOnly: boolean; @serializable() readOnly: boolean;
isCustomGroup = true;
constructor(config: DsDynamicQualdropModelConfig, layout?: DynamicFormControlLayout) { constructor(config: DsDynamicQualdropModelConfig, layout?: DynamicFormControlLayout) {
super(config, layout); super(config, layout);

View File

@@ -1,7 +1,9 @@
import { import {
DYNAMIC_FORM_CONTROL_TYPE_ARRAY,
DynamicFormArrayModel, DynamicFormArrayModelConfig, DynamicFormControlLayout, DynamicFormArrayModel, DynamicFormArrayModelConfig, DynamicFormControlLayout,
serializable serializable
} from '@ng-dynamic-forms/core'; } from '@ng-dynamic-forms/core';
import { DYNAMIC_FORM_CONTROL_TYPE_TAG } from './tag/dynamic-tag.model';
export interface DynamicRowArrayModelConfig extends DynamicFormArrayModelConfig { export interface DynamicRowArrayModelConfig extends DynamicFormArrayModelConfig {
notRepeteable: boolean; notRepeteable: boolean;
@@ -9,6 +11,7 @@ export interface DynamicRowArrayModelConfig extends DynamicFormArrayModelConfig
export class DynamicRowArrayModel extends DynamicFormArrayModel { export class DynamicRowArrayModel extends DynamicFormArrayModel {
@serializable() notRepeteable = false; @serializable() notRepeteable = false;
isRowArray = true;
constructor(config: DynamicRowArrayModelConfig, layout?: DynamicFormControlLayout) { constructor(config: DynamicRowArrayModelConfig, layout?: DynamicFormControlLayout) {
super(config, layout); super(config, layout);

View File

@@ -1,5 +1,5 @@
import { DynamicFormGroupModel } from '@ng-dynamic-forms/core'; import { DynamicFormGroupModel } from '@ng-dynamic-forms/core';
export class DynamicRowGroupModel extends DynamicFormGroupModel { export class DynamicRowGroupModel extends DynamicFormGroupModel {
isRowGroup = true;
} }

View File

@@ -27,7 +27,7 @@ import { GlobalConfig } from '../../../../../../../config/global-config.interfac
import { GLOBAL_CONFIG } from '../../../../../../../config'; import { GLOBAL_CONFIG } from '../../../../../../../config';
import { FormGroup } from '@angular/forms'; import { FormGroup } from '@angular/forms';
import { Subscription } from 'rxjs/Subscription'; import { Subscription } from 'rxjs/Subscription';
import { isObjectEmpty } from '../../../../../object.util'; import { hasOnlyEmptyProperties } from '../../../../../object.util';
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model'; import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model';
@@ -70,7 +70,7 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit {
this.formCollapsed = Observable.of(true); this.formCollapsed = Observable.of(true);
} }
this.model.valueUpdates.subscribe((value: any[]) => { this.model.valueUpdates.subscribe((value: any[]) => {
this.formCollapsed = (isNotEmpty(value) && !(value.length === 1 && isObjectEmpty(value[0]))) ? Observable.of(true) : Observable.of(false); this.formCollapsed = (isNotEmpty(value) && !(value.length === 1 && hasOnlyEmptyProperties(value[0]))) ? Observable.of(true) : Observable.of(false);
}); });
this.formId = this.formService.getUniqueId(this.model.id); this.formId = this.formService.getUniqueId(this.model.id);

View File

@@ -4,7 +4,7 @@ import { DsDynamicInputModel, DsDynamicInputModelConfig } from '../ds-dynamic-in
import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model'; import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model';
import { isEmpty, isNull } from '../../../../../empty.util'; import { isEmpty, isNull } from '../../../../../empty.util';
export const DYNAMIC_FORM_CONTROL_TYPE_RELATION = 'RELATION'; export const DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP = 'RELATION';
export const PLACEHOLDER_PARENT_METADATA = '#PLACEHOLDER_PARENT_METADATA_VALUE#'; export const PLACEHOLDER_PARENT_METADATA = '#PLACEHOLDER_PARENT_METADATA_VALUE#';
/** /**
@@ -28,7 +28,7 @@ export class DynamicGroupModel extends DsDynamicInputModel {
@serializable() scopeUUID: string; @serializable() scopeUUID: string;
@serializable() submissionScope: string; @serializable() submissionScope: string;
@serializable() _value: any[]; @serializable() _value: any[];
@serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_RELATION; @serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP;
constructor(config: DynamicGroupModelConfig, layout?: DynamicFormControlLayout) { constructor(config: DynamicGroupModelConfig, layout?: DynamicFormControlLayout) {
super(config, layout); super(config, layout);

View File

@@ -22,6 +22,7 @@ export class DynamicListCheckboxGroupModel extends DynamicCheckboxGroupModel {
@serializable() repeatable: boolean; @serializable() repeatable: boolean;
@serializable() groupLength: number; @serializable() groupLength: number;
@serializable() _value: AuthorityValueModel[]; @serializable() _value: AuthorityValueModel[];
isListGroup = true;
valueUpdates: Subject<any>; valueUpdates: Subject<any>;
constructor(config: DynamicListCheckboxGroupModelConfig, layout?: DynamicFormControlLayout) { constructor(config: DynamicListCheckboxGroupModelConfig, layout?: DynamicFormControlLayout) {

View File

@@ -19,6 +19,7 @@ export class DynamicListRadioGroupModel extends DynamicRadioGroupModel<any> {
@serializable() authorityOptions: AuthorityOptions; @serializable() authorityOptions: AuthorityOptions;
@serializable() repeatable: boolean; @serializable() repeatable: boolean;
@serializable() groupLength: number; @serializable() groupLength: number;
isListGroup = true;
constructor(config: DynamicListModelConfig, layout?: DynamicFormControlLayout) { constructor(config: DynamicListModelConfig, layout?: DynamicFormControlLayout) {
super(config, layout); super(config, layout);

View File

@@ -29,16 +29,16 @@
/* add padding */ /* add padding */
.left-addon input { .left-addon input {
padding-left: 30px; padding-left: $spacer * 2;
} }
.right-addon input { .right-addon input {
padding-right: 30px; padding-right: $spacer * 2;
} }
:host /deep/ .dropdown-menu { :host /deep/ .dropdown-menu {
width: 100% !important; width: 100% !important;
max-height: 200px; max-height: $dropdown-menu-max-height;
overflow-y: auto !important; overflow-y: auto !important;
overflow-x: hidden; overflow-x: hidden;
} }
@@ -50,23 +50,16 @@
color: $dropdown-link-hover-color !important; color: $dropdown-link-hover-color !important;
background-color: $dropdown-link-hover-bg !important; background-color: $dropdown-link-hover-bg !important;
} }
//
.dropdown-menu { //.dropdown-menu {
margin-top: -10px; // margin-top: -($spacer * 0.625);
} //}
div { div {
overflow: visible; overflow: visible;
//padding-right: 0 !important; //padding-right: 0 !important;
} }
//
button { //button {
margin-right: 10px; // margin-right: $spacer * 0.625;
}
//@media (min-width: $screen-sm-min) {
// .firstName {
// padding-left: 0 !important;
// margin-left: -5px !important;
// }
//} //}

View File

@@ -2,7 +2,7 @@
.scrollable-menu { .scrollable-menu {
height: auto; height: auto;
max-height: 200px; max-height: $dropdown-menu-max-height;
overflow-x: hidden; overflow-x: hidden;
} }
@@ -13,14 +13,14 @@
.scrollable-dropdown-loading { .scrollable-dropdown-loading {
background-color: map-get($theme-colors, primary); background-color: map-get($theme-colors, primary);
color: white; color: white;
height: 2rem !important; height: $spacer * 2 !important;
line-height: 2rem; line-height: $spacer * 2;
position: sticky; position: sticky;
bottom: 0; bottom: 0;
} }
.scrollable-dropdown-menu { .scrollable-dropdown-menu {
left: 0 !important; left: 0 !important;
margin-bottom: 1rem; margin-bottom: $spacer;
z-index: 1000; z-index: 1000;
} }

View File

@@ -6,7 +6,7 @@
<ds-chips [chips]="chips" [wrapperClass]="'border-bottom border-light'"> <ds-chips [chips]="chips" [wrapperClass]="'border-bottom border-light'">
<input *ngIf="!searchOptions" <input *ngIf="!searchOptions"
class="border-0 form-control-plaintext tag-input mt-1 mb-1 chips-sort-ignore" class="border-0 form-control-plaintext tag-input flex-grow-1 mt-1 mb-1 chips-sort-ignore"
type="text" type="text"
[class.pl-3]="chips.hasItems()" [class.pl-3]="chips.hasItems()"
[placeholder]="model.label" [placeholder]="model.label"
@@ -19,7 +19,7 @@
<input *ngIf="searchOptions" <input *ngIf="searchOptions"
class="border-0 form-control-plaintext tag-input mt-1 mb-1 chips-sort-ignore" class="border-0 form-control-plaintext tag-input flex-grow-1 mt-1 mb-1 chips-sort-ignore"
type="text" type="text"
[(ngModel)]="currentValue" [(ngModel)]="currentValue"
[attr.autoComplete]="model.autoComplete" [attr.autoComplete]="model.autoComplete"

View File

@@ -12,11 +12,11 @@
:host /deep/ .dropdown-menu { :host /deep/ .dropdown-menu {
width: 100% !important; width: 100% !important;
max-height: 200px; max-height: $dropdown-menu-max-height;
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
left: 0 !important; left: 0 !important;
margin-top: 15px !important; margin-top: $spacer !important;
} }
:host /deep/ .dropdown-item.active, :host /deep/ .dropdown-item.active,
@@ -28,7 +28,6 @@
} }
.tag-input { .tag-input {
flex-grow: 1;
outline: none; outline: none;
width: auto !important; width: auto !important;
} }

View File

@@ -11,7 +11,7 @@
:host /deep/ .dropdown-menu { :host /deep/ .dropdown-menu {
width: 100% !important; width: 100% !important;
max-height: 200px; max-height: $dropdown-menu-max-height;
overflow-y: auto !important; overflow-y: auto !important;
overflow-x: hidden; overflow-x: hidden;
} }

View File

@@ -13,7 +13,7 @@ import {
DynamicColorPickerModel, DynamicColorPickerModel,
DynamicDatePickerModel, DynamicDatePickerModel,
DynamicEditorModel, DynamicEditorModel,
DynamicFileUploadModel, DynamicFileUploadModel, DynamicFormArrayGroupModel,
DynamicFormArrayModel, DynamicFormArrayModel,
DynamicFormControlModel, DynamicFormControlModel,
DynamicFormControlValue, DynamicFormControlValue,
@@ -48,6 +48,7 @@ import { DsDynamicInputModel } from './ds-dynamic-form-ui/models/ds-dynamic-inpu
import { FormFieldMetadataValueObject } from './models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from './models/form-field-metadata-value.model';
import { DynamicConcatModel } from './ds-dynamic-form-ui/models/ds-dynamic-concat.model'; import { DynamicConcatModel } from './ds-dynamic-form-ui/models/ds-dynamic-concat.model';
import { DynamicLookupNameModel } from './ds-dynamic-form-ui/models/lookup/dynamic-lookup-name.model'; import { DynamicLookupNameModel } from './ds-dynamic-form-ui/models/lookup/dynamic-lookup-name.model';
import { DynamicRowArrayModel } from './ds-dynamic-form-ui/models/ds-dynamic-row-array-model';
describe('FormBuilderService test suite', () => { describe('FormBuilderService test suite', () => {
@@ -248,7 +249,20 @@ describe('FormBuilderService test suite', () => {
new DynamicLookupNameModel({id: 'testLookupName'}), new DynamicLookupNameModel({id: 'testLookupName'}),
new DynamicQualdropModel({id: 'testCombobox', readOnly: false}) new DynamicQualdropModel({id: 'testCombobox', readOnly: false}),
new DynamicRowArrayModel(
{
id: 'testFormRowArray',
initialCount: 5,
notRepeteable: false,
groupFactory: () => {
return [
new DynamicInputModel({id: 'testFormRowArrayGroupInput'})
];
},
}
),
]; ];
testFormConfiguration = { testFormConfiguration = {
@@ -388,6 +402,8 @@ describe('FormBuilderService test suite', () => {
expect(service.findById('testCheckboxGroup1', testModel) instanceof DynamicFormControlModel).toBe(true); expect(service.findById('testCheckboxGroup1', testModel) instanceof DynamicFormControlModel).toBe(true);
expect(service.findById('testCheckboxGroup2', testModel) instanceof DynamicFormControlModel).toBe(true); expect(service.findById('testCheckboxGroup2', testModel) instanceof DynamicFormControlModel).toBe(true);
expect(service.findById('nestedTestInput', testModel) instanceof DynamicFormControlModel).toBe(true); expect(service.findById('nestedTestInput', testModel) instanceof DynamicFormControlModel).toBe(true);
expect(service.findById('testFormRowArrayGroupInput', testModel) instanceof DynamicFormControlModel).toBe(true);
expect(service.findById('testFormRowArrayGroupInput', testModel, 2) instanceof DynamicFormControlModel).toBe(true);
}); });
it('should create an array of form models', () => { it('should create an array of form models', () => {
@@ -484,9 +500,32 @@ describe('FormBuilderService test suite', () => {
it('should return true when model is a Qualdrop Group', () => { it('should return true when model is a Qualdrop Group', () => {
const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID'); const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID');
const model = service.findById('dc_identifier_QUALDROP_GROUP', formModel); let model = service.findById('dc_identifier_QUALDROP_GROUP', formModel);
expect(service.isQualdropGroup(model)).toBe(true); expect(service.isQualdropGroup(model)).toBe(true);
model = service.findById('name_CONCAT_GROUP', formModel);
expect(service.isQualdropGroup(model)).toBe(false);
});
it('should return true when model is a Custom or List Group', () => {
const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID');
let model = service.findById('dc_identifier_QUALDROP_GROUP', formModel);
expect(service.isCustomOrListGroup(model)).toBe(true);
model = service.findById('name_CONCAT_GROUP', formModel);
expect(service.isCustomOrListGroup(model)).toBe(true);
model = service.findById('testCheckboxList', testModel);
expect(service.isCustomOrListGroup(model)).toBe(true);
model = service.findById('testRadioList', testModel);
expect(service.isCustomOrListGroup(model)).toBe(true);
}); });
it('should return true when model is a Custom Group', () => { it('should return true when model is a Custom Group', () => {
@@ -498,6 +537,14 @@ describe('FormBuilderService test suite', () => {
model = service.findById('name_CONCAT_GROUP', formModel); model = service.findById('name_CONCAT_GROUP', formModel);
expect(service.isCustomGroup(model)).toBe(true); expect(service.isCustomGroup(model)).toBe(true);
model = service.findById('testCheckboxList', testModel);
expect(service.isCustomGroup(model)).toBe(false);
model = service.findById('testRadioList', testModel);
expect(service.isCustomGroup(model)).toBe(false);
}); });
it('should return true when model is a List Group', () => { it('should return true when model is a List Group', () => {
@@ -516,6 +563,26 @@ describe('FormBuilderService test suite', () => {
expect(service.isRelationGroup(model)).toBe(true); expect(service.isRelationGroup(model)).toBe(true);
}); });
it('should return true when model is a Array Row Group', () => {
let model = service.findById('testFormRowArray', testModel, null);
expect(service.isRowArrayGroup(model)).toBe(true);
model = service.findById('testFormArray', testModel);
expect(service.isRowArrayGroup(model)).toBe(false);
});
it('should return true when model is a Array Group', () => {
let model = service.findById('testFormRowArray', testModel) as DynamicFormArrayModel;
expect(service.isArrayGroup(model)).toBe(true);
model = service.findById('testFormArray', testModel) as DynamicFormArrayModel;
expect(service.isArrayGroup(model)).toBe(true);
});
it('should return properly form control by field id', () => { it('should return properly form control by field id', () => {
const group = service.createFormGroup(testModel); const group = service.createFormGroup(testModel);
const control = group.controls.testLookup; const control = group.controls.testLookup;

View File

@@ -1,8 +1,11 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { FormGroup } from '@angular/forms'; import { AbstractControl, FormGroup } from '@angular/forms';
import { import {
DynamicFormArrayGroupModel, DYNAMIC_FORM_CONTROL_TYPE_ARRAY,
DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP,
DYNAMIC_FORM_CONTROL_TYPE_GROUP,
DYNAMIC_FORM_CONTROL_TYPE_RADIO_GROUP,
DynamicFormArrayModel, DynamicFormArrayModel,
DynamicFormControlModel, DynamicFormControlModel,
DynamicFormGroupModel, DynamicFormGroupModel,
@@ -10,26 +13,18 @@ import {
DynamicPathable, DynamicPathable,
JSONUtils, JSONUtils,
} from '@ng-dynamic-forms/core'; } from '@ng-dynamic-forms/core';
import { mergeWith, isObject } from 'lodash'; import { isObject, isString, mergeWith } from 'lodash';
import { isEmpty, isNotEmpty, isNotNull, isNotUndefined, isNull } from '../../empty.util'; import { hasValue, isEmpty, isNotEmpty, isNotNull, isNotUndefined, isNull } from '../../empty.util';
import { DynamicQualdropModel } from './ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model'; import { DynamicQualdropModel } from './ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model';
import { SubmissionFormsModel } from '../../../core/shared/config/config-submission-forms.model'; import { SubmissionFormsModel } from '../../../core/shared/config/config-submission-forms.model';
import { DynamicConcatModel } from './ds-dynamic-form-ui/models/ds-dynamic-concat.model'; import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './ds-dynamic-form-ui/models/dynamic-group/dynamic-group.model';
import { DynamicListCheckboxGroupModel } from './ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model'; import { DYNAMIC_FORM_CONTROL_TYPE_TAG } from './ds-dynamic-form-ui/models/tag/dynamic-tag.model';
import {
DYNAMIC_FORM_CONTROL_TYPE_RELATION,
DynamicGroupModel
} from './ds-dynamic-form-ui/models/dynamic-group/dynamic-group.model';
import { DYNAMIC_FORM_CONTROL_TYPE_TAG, DynamicTagModel } from './ds-dynamic-form-ui/models/tag/dynamic-tag.model';
import { DynamicListRadioGroupModel } from './ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model';
import { RowParser } from './parsers/row-parser'; import { RowParser } from './parsers/row-parser';
import { DynamicRowArrayModel } from './ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; import { DynamicRowArrayModel } from './ds-dynamic-form-ui/models/ds-dynamic-row-array-model';
import { DynamicRowGroupModel } from './ds-dynamic-form-ui/models/ds-dynamic-row-group-model';
import { DsDynamicInputModel } from './ds-dynamic-form-ui/models/ds-dynamic-input.model'; import { DsDynamicInputModel } from './ds-dynamic-form-ui/models/ds-dynamic-input.model';
import { FormFieldMetadataValueObject } from './models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from './models/form-field-metadata-value.model';
import { AuthorityValueModel } from '../../../core/integration/models/authority-value.model';
@Injectable() @Injectable()
export class FormBuilderService extends DynamicFormService { export class FormBuilderService extends DynamicFormService {
@@ -37,31 +32,33 @@ export class FormBuilderService extends DynamicFormService {
findById(id: string, groupModel: DynamicFormControlModel[], arrayIndex = null): DynamicFormControlModel | null { findById(id: string, groupModel: DynamicFormControlModel[], arrayIndex = null): DynamicFormControlModel | null {
let result = null; let result = null;
const findByIdFn = (findId: string, findGroupModel: DynamicFormControlModel[]): void => { const findByIdFn = (findId: string, findGroupModel: DynamicFormControlModel[], findArrayIndex): void => {
for (const controlModel of findGroupModel) { for (const controlModel of findGroupModel) {
if (controlModel.id === findId) { if (controlModel.id === findId) {
if (controlModel instanceof DynamicFormArrayModel && isNotNull(arrayIndex)) {
result = controlModel.get(arrayIndex); if (this.isArrayGroup(controlModel) && isNotNull(findArrayIndex)) {
result = (controlModel as DynamicFormArrayModel).get(findArrayIndex);
} else { } else {
result = controlModel; result = controlModel;
} }
break; break;
} }
if (controlModel instanceof DynamicFormGroupModel) { if (this.isGroup(controlModel)) {
findByIdFn(findId, (controlModel as DynamicFormGroupModel).group); findByIdFn(findId, (controlModel as DynamicFormGroupModel).group, findArrayIndex);
} }
if (controlModel instanceof DynamicFormArrayModel && (isNull(arrayIndex) || controlModel.size > (arrayIndex))) { if (this.isArrayGroup(controlModel)
arrayIndex = (isNull(arrayIndex)) ? 0 : arrayIndex; && (isNull(findArrayIndex) || (controlModel as DynamicFormArrayModel).size > (findArrayIndex))) {
findByIdFn(findId, controlModel.get(arrayIndex).group); const index = (isNull(findArrayIndex)) ? 0 : findArrayIndex;
findByIdFn(findId, (controlModel as DynamicFormArrayModel).get(index).group, index);
} }
} }
}; };
findByIdFn(id, groupModel); findByIdFn(id, groupModel, arrayIndex);
return result; return result;
} }
@@ -72,13 +69,13 @@ export class FormBuilderService extends DynamicFormService {
for (const controlModel of findGroupModel) { for (const controlModel of findGroupModel) {
if (controlModel instanceof DynamicFormGroupModel) { if (this.isGroup(controlModel)) {
iterateControlModels((controlModel as DynamicFormGroupModel).group); iterateControlModels((controlModel as DynamicFormGroupModel).group);
continue; continue;
} }
if (controlModel instanceof DynamicFormArrayModel) { if (this.isArrayGroup(controlModel)) {
iterateControlModels(controlModel.groupFactory()); iterateControlModels((controlModel as DynamicFormArrayModel).groupFactory());
continue; continue;
} }
@@ -103,13 +100,12 @@ export class FormBuilderService extends DynamicFormService {
const normalizeValue = (controlModel, controlValue, controlModelIndex) => { const normalizeValue = (controlModel, controlValue, controlModelIndex) => {
const controlLanguage = (controlModel as DsDynamicInputModel).hasLanguages ? (controlModel as DsDynamicInputModel).language : null; const controlLanguage = (controlModel as DsDynamicInputModel).hasLanguages ? (controlModel as DsDynamicInputModel).language : null;
if (((isObject(controlValue) && controlValue.id) || controlValue instanceof AuthorityValueModel)) { if (isString(controlValue)) {
return new FormFieldMetadataValueObject(controlValue.value, controlLanguage, controlValue.id, controlValue.display, controlModelIndex);
} else if (!(controlValue instanceof FormFieldMetadataValueObject)) {
return new FormFieldMetadataValueObject(controlValue, controlLanguage, null, null, controlModelIndex); return new FormFieldMetadataValueObject(controlValue, controlLanguage, null, null, controlModelIndex);
} else { } else if (isObject(controlValue)) {
const authority = controlValue.authority || controlValue.id || null;
const place = controlModelIndex || controlValue.place; const place = controlModelIndex || controlValue.place;
return Object.assign(new FormFieldMetadataValueObject(), controlValue, {place}); return new FormFieldMetadataValueObject(controlValue.value, controlLanguage, authority, controlValue.display, place);
} }
}; };
@@ -118,29 +114,27 @@ export class FormBuilderService extends DynamicFormService {
// Iterate over all group's controls // Iterate over all group's controls
for (const controlModel of findGroupModel) { for (const controlModel of findGroupModel) {
/* tslint:disable-next-line:no-shadowed-variable */
// for (const {controlModel, controlModelIndex} of findGroupModel.map((controlModel, controlModelIndex) => ({ controlModel, controlModelIndex }))) {
if (controlModel instanceof DynamicRowGroupModel && !this.isCustomGroup(controlModel)) { if (this.isRowGroup(controlModel) && !this.isCustomOrListGroup(controlModel)) {
iterateResult = mergeWith(iterateResult, iterateControlModels((controlModel as DynamicFormGroupModel).group), customizer); iterateResult = mergeWith(iterateResult, iterateControlModels((controlModel as DynamicFormGroupModel).group), customizer);
continue; continue;
} }
if (controlModel instanceof DynamicFormGroupModel && !this.isCustomGroup(controlModel)) { if (this.isGroup(controlModel) && !this.isCustomOrListGroup(controlModel)) {
iterateResult[controlModel.name] = iterateControlModels((controlModel as DynamicFormGroupModel).group); iterateResult[controlModel.name] = iterateControlModels((controlModel as DynamicFormGroupModel).group);
continue; continue;
} }
if (controlModel instanceof DynamicRowArrayModel) { if (this.isRowArrayGroup(controlModel)) {
for (const arrayItemModel of controlModel.groups) { for (const arrayItemModel of (controlModel as DynamicRowArrayModel).groups) {
iterateResult = mergeWith(iterateResult, iterateControlModels(arrayItemModel.group, arrayItemModel.index), customizer); iterateResult = mergeWith(iterateResult, iterateControlModels(arrayItemModel.group, arrayItemModel.index), customizer);
} }
continue; continue;
} }
if (controlModel instanceof DynamicFormArrayModel) { if (this.isArrayGroup(controlModel)) {
iterateResult[controlModel.name] = []; iterateResult[controlModel.name] = [];
for (const arrayItemModel of controlModel.groups) { for (const arrayItemModel of (controlModel as DynamicFormArrayModel).groups) {
iterateResult[controlModel.name].push(iterateControlModels(arrayItemModel.group, arrayItemModel.index)); iterateResult[controlModel.name].push(iterateControlModels(arrayItemModel.group, arrayItemModel.index));
} }
continue; continue;
@@ -148,14 +142,14 @@ export class FormBuilderService extends DynamicFormService {
let controlId; let controlId;
// Get the field's name // Get the field's name
if (controlModel instanceof DynamicQualdropModel) { if (this.isQualdropGroup(controlModel)) {
// If is instance of DynamicQualdropModel take the qualdrop id as field's name // If is instance of DynamicQualdropModel take the qualdrop id as field's name
controlId = controlModel.qualdropId; controlId = (controlModel as DynamicQualdropModel).qualdropId;
} else { } else {
controlId = controlModel.name; controlId = controlModel.name;
} }
if (controlModel instanceof DynamicGroupModel) { if (this.isRelationGroup(controlModel)) {
const values = (controlModel as any).value; const values = (controlModel as any).value;
values.forEach((groupValue, groupIndex) => { values.forEach((groupValue, groupIndex) => {
const newGroupValue = Object.create({}); const newGroupValue = Object.create({});
@@ -170,7 +164,6 @@ export class FormBuilderService extends DynamicFormService {
} }
} }
}); });
// controlArrayValue.push(newGroupValue);
}) })
} else if (isNotUndefined((controlModel as any).value) && isNotEmpty((controlModel as any).value)) { } else if (isNotUndefined((controlModel as any).value) && isNotEmpty((controlModel as any).value)) {
const controlArrayValue = []; const controlArrayValue = [];
@@ -217,49 +210,66 @@ export class FormBuilderService extends DynamicFormService {
return rows; return rows;
} }
isModelInCustomGroup(model: DynamicFormControlModel) { isModelInCustomGroup(model: DynamicFormControlModel): boolean {
return model.parent && return this.isCustomGroup((model as any).parent);
(model.parent instanceof DynamicConcatModel
|| model.parent instanceof DynamicQualdropModel);
} }
hasArrayGroupValue(model: DynamicFormControlModel) { hasArrayGroupValue(model: DynamicFormControlModel): boolean {
return model && (this.isListGroup(model) || model.type === DYNAMIC_FORM_CONTROL_TYPE_TAG); return model && (this.isListGroup(model) || model.type === DYNAMIC_FORM_CONTROL_TYPE_TAG);
} }
hasMappedGroupValue(model: DynamicFormControlModel) { hasMappedGroupValue(model: DynamicFormControlModel): boolean {
return ((model.parent && model.parent instanceof DynamicQualdropModel) return (this.isQualdropGroup((model as any).parent)
|| model.parent instanceof DynamicGroupModel); || this.isRelationGroup((model as any).parent));
} }
isQualdropGroup(model: DynamicFormControlModel) { isGroup(model: DynamicFormControlModel): boolean {
return model && model instanceof DynamicQualdropModel; return model && (model.type === DYNAMIC_FORM_CONTROL_TYPE_GROUP || model.type === DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP);
} }
isCustomGroup(model: DynamicFormControlModel) { isQualdropGroup(model: DynamicFormControlModel): boolean {
return (model && model.type === DYNAMIC_FORM_CONTROL_TYPE_GROUP && hasValue((model as any).qualdropId));
}
isCustomGroup(model: DynamicFormControlModel): boolean {
return model && ((model as any).type === DYNAMIC_FORM_CONTROL_TYPE_GROUP && (model as any).isCustomGroup === true);
}
isRowGroup(model: DynamicFormControlModel): boolean {
return model && ((model as any).type === DYNAMIC_FORM_CONTROL_TYPE_GROUP && (model as any).isRowGroup === true);
}
isCustomOrListGroup(model: DynamicFormControlModel): boolean {
return model && return model &&
(model instanceof DynamicConcatModel (this.isCustomGroup(model)
|| this.isQualdropGroup(model)
|| this.isListGroup(model)); || this.isListGroup(model));
} }
isListGroup(model: DynamicFormControlModel) { isListGroup(model: DynamicFormControlModel): boolean {
return model && return model &&
(model instanceof DynamicListCheckboxGroupModel ((model.type === DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP && (model as any).isListGroup === true)
|| model instanceof DynamicListRadioGroupModel); || (model.type === DYNAMIC_FORM_CONTROL_TYPE_RADIO_GROUP && (model as any).isListGroup === true));
} }
isRelationGroup(model: DynamicFormControlModel) { isRelationGroup(model: DynamicFormControlModel): boolean {
return model && model.type === DYNAMIC_FORM_CONTROL_TYPE_RELATION; return model && model.type === DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP;
} }
getFormControlById(id: string, formGroup: FormGroup, groupModel: DynamicFormControlModel[], index = 0) { isRowArrayGroup(model: DynamicFormControlModel): boolean {
return model.type === DYNAMIC_FORM_CONTROL_TYPE_ARRAY && (model as any).isRowArray === true;
}
isArrayGroup(model: DynamicFormControlModel): boolean {
return model.type === DYNAMIC_FORM_CONTROL_TYPE_ARRAY;
}
getFormControlById(id: string, formGroup: FormGroup, groupModel: DynamicFormControlModel[], index = 0): AbstractControl {
const fieldModel = this.findById(id, groupModel, index); const fieldModel = this.findById(id, groupModel, index);
return isNotEmpty(fieldModel) ? formGroup.get(this.getPath(fieldModel)) : null; return isNotEmpty(fieldModel) ? formGroup.get(this.getPath(fieldModel)) : null;
} }
getId(model: DynamicPathable) { getId(model: DynamicPathable): string {
if (model instanceof DynamicFormArrayGroupModel) { if (this.isArrayGroup(model as DynamicFormControlModel)) {
return model.index.toString(); return model.index.toString();
} else { } else {
return ((model as DynamicFormControlModel).id !== (model as DynamicFormControlModel).name) ? return ((model as DynamicFormControlModel).id !== (model as DynamicFormControlModel).name) ?

View File

@@ -1,4 +1,9 @@
import { DynamicFormArrayModel, DynamicFormControlModel, DynamicFormGroupModelConfig } from '@ng-dynamic-forms/core'; import {
DYNAMIC_FORM_CONTROL_TYPE_ARRAY,
DynamicFormArrayModel,
DynamicFormControlModel,
DynamicFormGroupModelConfig
} from '@ng-dynamic-forms/core';
import { uniqueId } from 'lodash'; import { uniqueId } from 'lodash';
import { DateFieldParser } from './date-field-parser'; import { DateFieldParser } from './date-field-parser';
@@ -11,7 +16,10 @@ import { TagFieldParser } from './tag-field-parser';
import { TextareaFieldParser } from './textarea-field-parser'; import { TextareaFieldParser } from './textarea-field-parser';
import { GroupFieldParser } from './group-field-parser'; import { GroupFieldParser } from './group-field-parser';
import { IntegrationSearchOptions } from '../../../../core/integration/models/integration-options.model'; import { IntegrationSearchOptions } from '../../../../core/integration/models/integration-options.model';
import { DynamicGroupModel } from '../ds-dynamic-form-ui/models/dynamic-group/dynamic-group.model'; import {
DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP,
DynamicGroupModel
} from '../ds-dynamic-form-ui/models/dynamic-group/dynamic-group.model';
import { DynamicRowGroupModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-group-model'; import { DynamicRowGroupModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-group-model';
import { isEmpty } from '../../../empty.util'; import { isEmpty } from '../../../empty.util';
import { LookupFieldParser } from './lookup-field-parser'; import { LookupFieldParser } from './lookup-field-parser';
@@ -98,7 +106,7 @@ export class RowParser {
} }
if (fieldModel) { if (fieldModel) {
if (fieldModel instanceof DynamicFormArrayModel || fieldModel instanceof DynamicGroupModel) { if (fieldModel.type === DYNAMIC_FORM_CONTROL_TYPE_ARRAY || fieldModel.type === DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP) {
if (this.rowData.fields.length > 1) { if (this.rowData.fields.length > 1) {
setLayout(fieldModel, 'grid', 'host', layoutGridClass); setLayout(fieldModel, 'grid', 'host', layoutGridClass);
config.group.push(fieldModel); config.group.push(fieldModel);
@@ -111,7 +119,7 @@ export class RowParser {
} }
return; return;
} else { } else {
if (fieldModel instanceof Array) { if (Array.isArray(fieldModel)) {
fieldModel.forEach((model) => { fieldModel.forEach((model) => {
parsedResult = model; parsedResult = model;
return; return;

View File

@@ -18,7 +18,7 @@ import { TranslateModule } from '@ngx-translate/core';
import { FormComponent } from './form.component'; import { FormComponent } from './form.component';
import { FormService } from './form.service'; import { FormService } from './form.service';
import { FormBuilderService } from './builder/form-builder.service'; import { FormBuilderService } from './builder/form-builder.service';
import { FormState } from './form.reducers'; import { FormState } from './form.reducer';
import { FormChangeAction, FormStatusChangeAction } from './form.actions'; import { FormChangeAction, FormStatusChangeAction } from './form.actions';
import { MockStore } from '../testing/mock-store'; import { MockStore } from '../testing/mock-store';
import { FormFieldMetadataValueObject } from './builder/models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from './builder/models/form-field-metadata-value.model';

View File

@@ -24,7 +24,7 @@ import { Subscription } from 'rxjs/Subscription';
import { hasValue, isNotEmpty, isNotNull, isNull } from '../empty.util'; import { hasValue, isNotEmpty, isNotNull, isNull } from '../empty.util';
import { FormService } from './form.service'; import { FormService } from './form.service';
import { formObjectFromIdSelector } from './selectors'; import { formObjectFromIdSelector } from './selectors';
import { FormEntry, FormError } from './form.reducers'; import { FormEntry, FormError } from './form.reducer';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
/** /**

View File

@@ -1,4 +1,4 @@
import { FormEntry, formReducer } from './form.reducers'; import { FormEntry, formReducer } from './form.reducer';
import { import {
FormAddError, FormAddError,
FormChangeAction, FormClearErrorsAction, FormChangeAction, FormClearErrorsAction,

View File

@@ -12,7 +12,7 @@ import {
import { FormService } from './form.service'; import { FormService } from './form.service';
import { FormBuilderService } from './builder/form-builder.service'; import { FormBuilderService } from './builder/form-builder.service';
import { AppState } from '../../app.reducer'; import { AppState } from '../../app.reducer';
import { formReducer } from './form.reducers'; import { formReducer } from './form.reducer';
describe('FormService test suite', () => { describe('FormService test suite', () => {
const formId = 'testForm'; const formId = 'testForm';

View File

@@ -1,7 +1,7 @@
import { createSelector, MemoizedSelector, Selector } from '@ngrx/store'; import { createSelector, MemoizedSelector } from '@ngrx/store';
import { AppState } from '../../app.reducer'; import { AppState } from '../../app.reducer';
import { FormEntry, FormState } from './form.reducers'; import { FormEntry, FormState } from './form.reducer';
export const formStateSelector = (state: AppState) => state.forms; export const formStateSelector = (state: AppState) => state.forms;

View File

@@ -12,15 +12,11 @@
position: relative; position: relative;
top: 0.15em; top: 0.15em;
transform: rotate(-45deg); transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
vertical-align: middle; vertical-align: middle;
width: 0.71em; width: 0.71em;
} }
.chevron.bottom:before { .chevron.bottom:before {
top: -.3em; top: -.3em;
-webkit-transform: rotate(135deg);
-ms-transform: rotate(135deg);
transform: rotate(135deg); transform: rotate(135deg);
} }

View File

@@ -1,4 +1,4 @@
import { deleteProperty, difference, isObjectEmpty } from './object.util'; import { deleteProperty, difference, hasOnlyEmptyProperties } from './object.util';
describe('Object Utils', () => { describe('Object Utils', () => {
let object: any = {}; let object: any = {};
@@ -19,36 +19,36 @@ describe('Object Utils', () => {
}); });
describe('isObjectEmpty', () => { describe('hasOnlyEmptyProperties', () => {
it('should return true when object is empty', () => { it('should return true when object is empty', () => {
object = {}; object = {};
expect(isObjectEmpty(object)).toBe(true); expect(hasOnlyEmptyProperties(object)).toBe(true);
}); });
it('should return true when object has a null property', () => { it('should return true when object has a null property', () => {
object = {a: null}; object = {a: null};
expect(isObjectEmpty(object)).toBe(true); expect(hasOnlyEmptyProperties(object)).toBe(true);
}); });
it('should return true when object property has an empty array as value', () => { it('should return true when object property has an empty array as value', () => {
object = {a: []}; object = {a: []};
expect(isObjectEmpty(object)).toBe(true); expect(hasOnlyEmptyProperties(object)).toBe(true);
}); });
it('should return true when object property has an empty object as value', () => { it('should return true when object property has an empty object as value', () => {
object = {a: {}}; object = {a: {}};
expect(isObjectEmpty(object)).toBe(true); expect(hasOnlyEmptyProperties(object)).toBe(true);
}); });
it('should return false when object is not empty', () => { it('should return false when object is not empty', () => {
object = {a: 'a', b: 'b'}; object = {a: 'a', b: 'b'};
expect(isObjectEmpty(object)).toBe(false); expect(hasOnlyEmptyProperties(object)).toBe(false);
}); });
it('should return false when object has at least a valued property', () => { it('should return false when object has at least a valued property', () => {
object = {a: [], b: 'b'}; object = {a: [], b: 'b'};
expect(isObjectEmpty(object)).toBe(false); expect(hasOnlyEmptyProperties(object)).toBe(false);
}); });
}); });

View File

@@ -4,21 +4,21 @@ import { isEqual, isObject, transform } from 'lodash';
/** /**
* Returns passed object without specified property * Returns passed object without specified property
*/ */
export function deleteProperty(object, key): object { export function deleteProperty(object: object, key: string): object {
const {[key]: deletedKey, ...otherKeys} = object; const {[key]: deletedKey, ...otherKeys} = object;
return otherKeys; return otherKeys;
} }
/** /**
* Returns true if the passed object is empty or has only empty property. * Returns true if the passed object is empty or has only empty property.
* isObjectEmpty({}); // true * hasOnlyEmptyProperties({}); // true
* isObjectEmpty({a: null}); // true * hasOnlyEmptyProperties({a: null}); // true
* isObjectEmpty({a: []}); // true * hasOnlyEmptyProperties({a: []}); // true
* isObjectEmpty({a: [], b: {}); // true * hasOnlyEmptyProperties({a: [], b: {}); // true
* isObjectEmpty({a: 'a', b: 'b'}); // false * hasOnlyEmptyProperties({a: 'a', b: 'b'}); // false
* isObjectEmpty({a: [], b: 'b'}); // false * hasOnlyEmptyProperties({a: [], b: 'b'}); // false
*/ */
export function isObjectEmpty(obj: any): boolean { export function hasOnlyEmptyProperties(obj: object): boolean {
const objectType = typeof obj; const objectType = typeof obj;
if (objectType === 'object') { if (objectType === 'object') {
if (Object.keys(obj).length === 0) { if (Object.keys(obj).length === 0) {
@@ -43,12 +43,12 @@ export function isObjectEmpty(obj: any): boolean {
* difference({a: 'a', b: {}}, {a: 'a'}); // {} * difference({a: 'a', b: {}}, {a: 'a'}); // {}
* difference({a: 'a'}, {a: 'a', b: 'b'}); // {} * difference({a: 'a'}, {a: 'a', b: 'b'}); // {}
*/ */
export function difference(object, base) { export function difference(object: object, base: object) {
const changes = (o, b) => { const changes = (o, b) => {
return transform(o, (result, value, key) => { return transform(o, (result, value, key) => {
if (!isEqual(value, b[key]) && isNotEmpty(value)) { if (!isEqual(value, b[key]) && isNotEmpty(value)) {
const resultValue = (isObject(value) && isObject(b[key])) ? changes(value, b[key]) : value; const resultValue = (isObject(value) && isObject(b[key])) ? changes(value, b[key]) : value;
if (!isObjectEmpty(resultValue)) { if (!hasOnlyEmptyProperties(resultValue)) {
result[key] = resultValue; result[key] = resultValue;
} }
} }

View File

@@ -20,19 +20,19 @@
} }
.ds-document-drop-zone-active { .ds-document-drop-zone-active {
z-index: 1025 !important; z-index: $drop-zone-area-z-index !important;
} }
.ds-document-drop-zone-inner { .ds-document-drop-zone-inner {
background-color: rgba($white, 0.7); background-color: rgba($white, 0.7);
z-index: 1021; z-index: $drop-zone-area-inner-z-index;
top: 0; top: 0;
left: 0; left: 0;
} }
.ds-document-drop-zone-inner-content { .ds-document-drop-zone-inner-content {
border: 4px dashed map-get($theme-colors, primary); border: 4px dashed map-get($theme-colors, primary);
z-index: 1021; z-index: $drop-zone-area-inner-z-index;
} }
.ds-document-drop-zone-inner-content p { .ds-document-drop-zone-inner-content p {

View File

@@ -3,4 +3,7 @@ $content-spacing: $spacer * 1.5;
$button-height: $input-btn-padding-y * 2 + $input-btn-line-height + calculateRem($input-btn-border-width*2); $button-height: $input-btn-padding-y * 2 + $input-btn-line-height + calculateRem($input-btn-border-width*2);
$card-height-percentage:98%; $card-height-percentage:98%;
$card-thumbnail-height:240px; $card-thumbnail-height:240px;
$dropdown-menu-max-height: 200px;
$drop-zone-area-z-index: 1025;
$drop-zone-area-inner-z-index: 1021;