@formql/core
Version:
FormQL - A framework for building dynamic forms
1,064 lines (1,053 loc) • 117 kB
JavaScript
import { __decorate, __metadata, __assign, __spread, __param } from 'tslib';
import { Input, Output, Component, EventEmitter, Injectable, ComponentFactoryResolver, ɵɵdefineInjectable, ɵɵinject, Inject, Directive, ViewChild, ViewContainerRef, ChangeDetectionStrategy, ElementRef, Renderer2, TemplateRef, HostListener, forwardRef, NgModule } from '@angular/core';
import { FormGroup, FormControl, FormBuilder, NG_VALUE_ACCESSOR, NG_VALIDATORS, Validators, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { UUID } from 'angular2-uuid';
import { Subject } from 'rxjs';
import { map, concatMap, takeUntil } from 'rxjs/operators';
import { TextMaskModule } from 'angular2-text-mask';
import { createAutoCorrectedDatePipe, createNumberMask } from 'text-mask-addons';
var ContainerType;
(function (ContainerType) {
ContainerType[ContainerType["Section"] = 1] = "Section";
ContainerType[ContainerType["Component"] = 2] = "Component";
ContainerType[ContainerType["Page"] = 3] = "Page";
})(ContainerType || (ContainerType = {}));
var FormQLMode;
(function (FormQLMode) {
FormQLMode[FormQLMode["View"] = 0] = "View";
FormQLMode[FormQLMode["Edit"] = 1] = "Edit";
})(FormQLMode || (FormQLMode = {}));
var PlainLayoutComponent = /** @class */ (function () {
function PlainLayoutComponent() {
this.submit = new EventEmitter();
}
PlainLayoutComponent.prototype.onSubmitTriggered = function () {
this.submit.emit(null);
};
PlainLayoutComponent.componentName = 'PlainLayoutComponent';
__decorate([
Input(),
__metadata("design:type", Object)
], PlainLayoutComponent.prototype, "form", void 0);
__decorate([
Input(),
__metadata("design:type", FormGroup)
], PlainLayoutComponent.prototype, "reactiveForm", void 0);
__decorate([
Input(),
__metadata("design:type", Number)
], PlainLayoutComponent.prototype, "mode", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], PlainLayoutComponent.prototype, "submit", void 0);
PlainLayoutComponent = __decorate([
Component({
selector: 'formql-plain-layout',
template: "<ng-container *ngIf=\"form && form.pages && form.pages.length > 0\">\n <form [formGroup]=\"reactiveForm\" (ngSubmit)=\"onSubmitTriggered()\">\n <div formql-page-wrapper *ngIf=\"form.pages\"\n [(page)]=\"form.pages[0]\"\n [reactivePage]=\"reactiveForm.controls[form.pages[0].pageId]\"\n [formGroupName]=\"form.pages[0].pageId\"\n [mode]=\"mode\"></div>\n </form>\n </ng-container>"
})
], PlainLayoutComponent);
return PlainLayoutComponent;
}());
var DndService = /** @class */ (function () {
function DndService() {
}
DndService.prototype.synchroniseSectionModel = function (page, event) {
var sourceSection = page.sections.find(function (s) { return s.sectionId === event.sourceWrapperId; });
var sourceComponent = null;
if (event.sourceObjectId === 'new') {
sourceComponent = this.newComponent();
event.sourceObjectId = sourceComponent.componentId;
sourceSection = page.sections.find(function (s) { return s.sectionId === event.targetWrapperId; });
if (sourceSection)
sourceSection.components.push(sourceComponent);
else
return page; // this should never happen
}
else
sourceComponent = sourceSection.components.find(function (c) { return c.componentId === event.sourceObjectId; });
if (!sourceComponent)
return;
// has the component been moved across position type (header/body)?
if (sourceComponent.position.type !== event.positionType)
sourceComponent.position.type = event.positionType;
// has the component been placed in a differnet CSS grid area?
if (sourceComponent.position.id !== event.targetPositionId)
sourceComponent.position.id = event.targetPositionId;
if (event.sourceWrapperId !== event.targetWrapperId) {
var targetSection = this.transferComponent(page, sourceSection, event);
targetSection.template.reRender = true;
targetSection = this.reorderComponents(targetSection, sourceComponent, event);
}
else
sourceSection = this.reorderComponents(sourceSection, sourceComponent, event);
sourceSection.template.reRender = true;
return page;
};
DndService.prototype.synchronisePageModel = function (page, event) {
var sourceSection = null;
if (event.sourceObjectId === 'new') {
sourceSection = this.newSection();
page.sections.push(sourceSection);
}
else
sourceSection = page.sections.find(function (s) { return s.sectionId === event.sourceObjectId; });
// can't find the source section, model must be in different page
if (sourceSection != null) {
if (sourceSection.position.id !== event.targetPositionId)
sourceSection.position.id = event.targetPositionId;
page.template.reRender = true;
page = this.reorderSections(page, sourceSection, event);
}
return page;
};
DndService.prototype.reorderComponents = function (section, sourceCompoment, event) {
var components = section.components.filter(function (c) { return c.position.id === sourceCompoment.position.id; });
var targetComponent = components.find(function (c) { return c.componentId === event.targetIndexId; });
if (targetComponent) {
sourceCompoment.position.index = targetComponent.position.index;
targetComponent.position.index = targetComponent.position.index + 0.5;
}
components = components.sort(function (left, right) {
return left.position.index - right.position.index;
});
for (var i = 0; i < components.length; i++) {
components[i].position.index = i;
}
return section;
};
DndService.prototype.reorderSections = function (page, sourceSection, event) {
var sections = page.sections.filter(function (c) { return c.position.id === sourceSection.position.id; });
var targetSection = sections.find(function (c) { return c.sectionId === event.targetIndexId; });
if (targetSection) {
sourceSection.position.index = targetSection.position.index;
targetSection.position.index = targetSection.position.index + 0.5;
}
sections = sections.sort(function (left, right) {
return left.position.index - right.position.index;
});
for (var i = 0; i < sections.length; i++)
sections[i].position.index = i;
return page;
};
DndService.prototype.transferComponent = function (page, sourceSection, event) {
var targetSection = page.sections.find(function (s) { return s.sectionId === event.targetWrapperId; });
if (!targetSection)
return null;
var component = sourceSection.components.find(function (c) { return c.componentId === event.sourceObjectId; });
if (!component)
return null;
var index = sourceSection.components.findIndex(function (s) { return s.componentId === event.sourceObjectId; });
targetSection.components.push(component);
sourceSection.components.splice(index, 1);
return targetSection;
};
DndService.prototype.newSection = function () {
return {
sectionId: UUID.UUID(),
sectionName: 'New section',
components: [],
template: {
header: {
gridTemplateColumns: '1fr',
gridTemplateRows: '1fr',
gridTemplateAreas: '"ID1_1"'
},
body: {
gridTemplateColumns: '1fr',
gridTemplateRows: '1fr',
gridTemplateAreas: '"ID1_1"'
}
},
position: {
id: '-1',
index: 0
}
};
};
DndService.prototype.newComponent = function () {
return {
componentId: UUID.UUID(),
label: 'New Component',
componentName: 'FormQLLabelComponent',
position: {
id: '-1',
index: 0
}
};
};
DndService = __decorate([
Injectable()
], DndService);
return DndService;
}());
var GridPositionType;
(function (GridPositionType) {
GridPositionType[GridPositionType["Header"] = 1] = "Header";
GridPositionType[GridPositionType["Body"] = 2] = "Body";
GridPositionType[GridPositionType["Footer"] = 3] = "Footer";
})(GridPositionType || (GridPositionType = {}));
var InternalEventType;
(function (InternalEventType) {
// Editing events
InternalEventType[InternalEventType["EditingComponent"] = 1] = "EditingComponent";
InternalEventType[InternalEventType["EditingSection"] = 2] = "EditingSection";
InternalEventType[InternalEventType["EditingPage"] = 3] = "EditingPage";
InternalEventType[InternalEventType["EditingForm"] = 4] = "EditingForm";
InternalEventType[InternalEventType["RemoveComponent"] = 5] = "RemoveComponent";
InternalEventType[InternalEventType["RemoveSection"] = 6] = "RemoveSection";
InternalEventType[InternalEventType["RemovePage"] = 7] = "RemovePage";
// Form changes
InternalEventType[InternalEventType["DndFormChanged"] = 8] = "DndFormChanged";
})(InternalEventType || (InternalEventType = {}));
var ComponentResolverService = /** @class */ (function () {
function ComponentResolverService(componentFactoryResolver) {
this.componentFactoryResolver = componentFactoryResolver;
this.componentRegister = {};
}
ComponentResolverService.prototype.resolveComponent = function (componentName) {
if (!this.componentRegister) {
return null;
}
var component = this.componentRegister[componentName];
if (!component) {
console.log("Component " + componentName + " not found.");
return null;
}
var resolvedComponent = this.componentFactoryResolver.resolveComponentFactory(component);
return resolvedComponent;
};
ComponentResolverService.prototype.addComponents = function () {
var _this = this;
var components = [];
for (var _i = 0; _i < arguments.length; _i++) {
components[_i] = arguments[_i];
}
if (Array.isArray(components)) {
components.forEach(function (c) { return _this.componentRegister[c.componentName] = c; });
}
};
ComponentResolverService.prototype.addComponent = function (component) {
this.componentRegister[component.componentName] = component;
};
ComponentResolverService.prototype.getComponentArray = function () {
var _this = this;
return Array.from(Object.keys(this.componentRegister), function (x) { return _this.componentRegister[x]; });
};
ComponentResolverService = __decorate([
Injectable(),
__metadata("design:paramtypes", [ComponentFactoryResolver])
], ComponentResolverService);
return ComponentResolverService;
}());
var HelperService = /** @class */ (function () {
function HelperService() {
}
HelperService_1 = HelperService;
HelperService.evaluateCondition = function (condition, data) {
var response = { value: false, error: null };
if (condition && condition.trim() !== '' && condition !== 'false') {
if (condition === 'true') {
response.value = true;
return response;
}
if (!data)
return response;
response = __assign({}, this.evaluate(condition, data));
if (response.value !== true)
response.value = false;
}
return response;
};
HelperService.evaluateValue = function (path, data) {
var response = { value: null, error: null };
if (!data)
return response;
response = __assign({}, this.evaluate(path, data));
if (Number.isNaN(response.value) || response.value === Infinity)
response.value = null;
else
response.value = this.deepCopy(response.value);
return response;
};
HelperService.evaluate = function (path, data) {
var response = { value: null, error: null };
var props = Object.keys(data);
var params = [];
for (var i = 0; i < props.length; i++)
params.push(data[props[i]]);
params.push(path);
props.push('path');
var expression = "\n 'use strict'\n let window = undefined;\n let document = undefined;\n let alert = undefined;\n let a = undefined;\n return " + path + ";\n ";
props.push(expression);
try {
var evalFunc = new (Function.bind.apply(Function, __spread([void 0], props)))();
response.value = evalFunc.apply(void 0, __spread(params));
}
catch (err) {
response.error = err;
}
return response;
};
HelperService.setValue = function (schema, value, data) {
if (value === undefined)
value = null;
if (schema) {
if (!data)
data = {};
var key = schema;
if (schema.indexOf('.') !== -1) {
var arr = schema.split('.');
var item = data;
for (var i = 0; i <= arr.length - 1; i++) {
key = arr[i];
if (!item[key])
item[key] = {};
if (i !== arr.length - 1)
item = item[key];
}
item[key] = value;
}
else
data[key] = value;
}
return data;
};
HelperService.getValue = function (schema, data, type) {
if (!schema || !data || (data && Object.keys(data).length === 0 && data.constructor === Object))
return;
try {
var evalFunc = new Function('data', "return data." + schema + ";");
return HelperService_1.resolveType(evalFunc(data), type);
}
catch (err) {
return null;
}
};
HelperService.setValidators = function (componentResolverService, component, control) {
var componentRef = componentResolverService.resolveComponent(component.componentName);
if (!componentRef)
return control;
var type = componentRef.componentType;
if (type && (!type['validators'] || (type['validators'] && type['validators'].length === 0)))
return control;
var validators = [];
var rules = component.rules;
if (rules != null) {
var FormValidators_1 = type['validators'];
Object.keys(rules).forEach(function (key) {
var item = rules[key];
if (item.value && item.key !== 'readonly' && item.key !== 'hidden' && item.key !== 'value') {
var validator = FormValidators_1.find(function (x) { return x.key === item.key; });
if (validator && validator.validator)
validators.push(validator.validator);
}
else if (item.value && item.key === 'readonly' && control.enabled)
control.disable();
});
if (control.disabled &&
(!rules || (rules && !rules.readonly) || (rules && rules.readonly && !rules.readonly.value)))
control.enable();
}
if (validators.length > 0)
control.setValidators(validators);
return control;
};
HelperService.createReactiveFormStructure = function (form, initialiseData, data) {
var _this = this;
if (initialiseData === void 0) { initialiseData = true; }
if (data === void 0) { data = null; }
var formControls = {};
var components = {};
var pageGroup = new FormGroup({});
form.pages.forEach(function (page) {
var sectionGroup = {};
if (page.sections != null)
page.sections.forEach(function (section) {
var componentGroup = {};
if (section.components != null)
section.components.forEach(function (component) {
components[component.componentId] = component;
var singleComponentGroup = new FormControl();
formControls[component.componentId] = singleComponentGroup;
componentGroup[component.componentId] = singleComponentGroup;
if (initialiseData) {
if (!data)
data = {};
data = HelperService_1.instantiateData(data, component.schema);
try {
var value = _this.getValue(component.schema, data, component.type);
if (value) {
formControls[component.componentId].setValue(value);
component.value = value;
}
}
catch (err) {
throw err;
}
}
});
sectionGroup[section.sectionId] = new FormGroup(componentGroup);
});
pageGroup[page.pageId] = new FormGroup(sectionGroup);
});
return { pageGroup: pageGroup, formControls: formControls, components: components, data: data };
};
HelperService.instantiateData = function (data, schema) {
if (schema && schema.indexOf('.') !== -1) {
var arr = schema.split('.');
var item = data;
var key = '';
for (var i = 0; i <= arr.length - 2; i++) {
key = arr[i];
if (!item[key])
item[key] = {};
if (i !== arr.length - 2)
item = item[key];
}
}
return data;
};
HelperService.deepCopy = function (oldObj, ignoreProperty) {
if (ignoreProperty === void 0) { ignoreProperty = null; }
var newObj = oldObj;
if (oldObj && typeof oldObj === 'object') {
newObj = Object.prototype.toString.call(oldObj) === '[object Array]' ? [] : {};
var _loop_1 = function (i) {
if (!ignoreProperty || (ignoreProperty && !ignoreProperty.find(function (p) { return p === i; })))
newObj[i] = this_1.deepCopy(oldObj[i]);
};
var this_1 = this;
for (var i in oldObj) {
_loop_1(i);
}
}
return newObj;
};
HelperService.propertyCopy = function (source, target, ignoreProperties) {
if (ignoreProperties === void 0) { ignoreProperties = null; }
if (source && typeof source === 'object') {
var _loop_2 = function (i) {
if (!ignoreProperties || (ignoreProperties && !ignoreProperties.find(function (p) { return p === i; })))
if (source[i] && typeof source[i] === 'object') {
if (!target[i])
target[i] = {};
target[i] = this_2.propertyCopy(source[i], target[i]);
}
else
target[i] = source[i];
else
console.log("propertyCopy function doesn't support primitives");
};
var this_2 = this;
for (var i in source) {
_loop_2(i);
}
}
return target;
};
HelperService.formatForGraphQl = function (obj) {
var _this = this;
var updatedData = this.deepCopy(obj);
if (updatedData['__typename'])
delete updatedData['__typename'];
var dataForQuery = '';
Object.keys(updatedData).forEach(function (fieldName) {
if (updatedData[fieldName] == null)
dataForQuery += fieldName + ': null,';
else if (typeof updatedData[fieldName] === 'object')
dataForQuery += _this.formatForGraphQl(updatedData[fieldName]);
else if (typeof updatedData[fieldName] === 'number' || typeof updatedData[fieldName] === 'boolean')
dataForQuery += fieldName + (":" + updatedData[fieldName] + ",");
else
dataForQuery += fieldName + (":\"" + updatedData[fieldName] + ",");
});
dataForQuery = "{" + dataForQuery.slice(0, -1) + "}";
return dataForQuery;
};
HelperService.formatError = function (error) {
if (!error)
return;
if (error.error && error.error.message)
error.message = error.error.message;
return error;
};
HelperService.resolveType = function (value, type) {
if (value === null || value === undefined || value === '')
return null;
else if (Number.isNaN(value))
return 0;
switch (type) {
case 'number':
if (typeof value === 'string')
value = value.replace(/[^\d\.]/g, '');
return Number(value);
default:
return value;
}
};
HelperService.maskToArray = function (mask) {
var result = [];
if (mask) {
var maskTrimmed = mask.trim().substring(1).slice(0, -1).replace('\\\\', '\\');
var arry = maskTrimmed.split(',');
arry.forEach(function (item) {
result.push(item.trim().replace(/\"/g, '').replace(/\'/g, ''));
});
}
return result;
};
HelperService.updateTemplates = function (form) {
form.pages.forEach(function (page) {
page.template.reRender = false;
page.template = HelperService_1.deepCopy(page.template);
page.sections.forEach(function (section) {
section.template.reRender = false;
section.template = HelperService_1.deepCopy(section.template);
});
});
return form;
};
HelperService.resetValidators = function (components, formControls, componentResolverService) {
if (components && Object.keys(components).length > 0)
Object.keys(components).forEach(function (key) {
var component = components[key];
if (component) {
var componentControl = formControls[component.componentId];
if (componentControl)
componentControl = HelperService_1.setValidators(componentResolverService, component, componentControl);
}
});
return formControls;
};
HelperService.validateForm = function (formGroup) {
var _this = this;
Object.keys(formGroup.controls).forEach(function (field) {
var control = formGroup.get(field);
if (control instanceof FormControl)
control.markAsTouched({ onlySelf: true });
else if (control instanceof FormGroup)
_this.validateForm(control);
});
};
var HelperService_1;
HelperService.ɵprov = ɵɵdefineInjectable({ factory: function HelperService_Factory() { return new HelperService(); }, token: HelperService, providedIn: "root" });
HelperService = HelperService_1 = __decorate([
Injectable({
providedIn: 'root'
})
], HelperService);
return HelperService;
}());
var RuleLogic = /** @class */ (function () {
function RuleLogic() {
this.evalFunctions = ['GET', 'SUM'];
}
/*
Perform a condition evaluation
*/
RuleLogic.prototype.doEval = function (condition, conditionFunctions) {
var conditionFunctionsDeclares = Object.keys(conditionFunctions).map(function (x) { return "let " + x + " = conditionFunctions." + x + "; "; }).join('');
if (condition.trim() === '')
return;
if (this.evalFunctions.indexOf(condition.trim()) !== -1)
throw Error("Funcitons need a parameter (e.g. GET('contact.firstName') )");
var props = [];
var params = [];
params.push(condition);
params.push(conditionFunctions);
props.push('condition');
props.push('conditionFunctions');
var expression = "\n 'use strict'\n " + conditionFunctionsDeclares + "\n let window = undefined;\n let document = undefined;\n let alert = undefined;\n let a = undefined;\n return " + condition + ";\n ";
props.push(expression);
try {
var evalFunc = new (Function.bind.apply(Function, __spread([void 0], props)))();
var response = evalFunc.apply(void 0, __spread(params));
return response;
}
catch (err) {
debugger; // intentionally left to help troubleshooting issues
console.log(err);
throw err;
}
};
/*
Reset all dependancies for any given condition in a component
*/
RuleLogic.prototype.resetDependancies = function (formState, condition, component) {
var self = this;
var registerFunctions = {
GET: function (schema) {
formState.components = self.setDependents(formState.components, schema, component.componentId);
},
SUM: function () {
var schemas = [];
for (var _i = 0; _i < arguments.length; _i++) {
schemas[_i] = arguments[_i];
}
schemas.forEach(function (schema) { return formState.components = self.setDependents(formState.components, schema, component.componentId); });
}
};
return this.doEval(condition, registerFunctions);
};
/*
Evaluetes the value of any given condition
*/
RuleLogic.prototype.evaluate = function (data, condition) {
var self = this;
var evalFunctions = {
GET: function (schema) {
var result = self.getSchemaValue(data, schema);
if (result !== undefined && result !== null)
return result;
else
return '';
},
SUM: function () {
var schemas = [];
for (var _i = 0; _i < arguments.length; _i++) {
schemas[_i] = arguments[_i];
}
var total = 0;
schemas.forEach(function (schema) {
var value = self.getSchemaValue(data, schema);
if (value && !isNaN(value))
total += value;
});
return total;
}
};
return this.doEval(condition, evalFunctions);
};
RuleLogic.prototype.evaluateCondition = function (data, condition) {
var response = { value: false, error: null };
if (condition && condition.trim() !== '' && condition !== 'false') {
if (condition === 'true') {
response.value = true;
return response;
}
if (!data)
return response;
try {
response.value = this.evaluate(data, condition);
}
catch (err) {
response.error = err;
}
if (response.value !== true)
response.value = false;
}
return response;
};
RuleLogic.prototype.evaluateValue = function (data, expression) {
var response = { value: null, error: null };
if (!data)
return response;
try {
response.value = this.evaluate(data, expression);
}
catch (err) {
response.error = err;
return response;
}
if (Number.isNaN(response.value) || response.value === Infinity)
response.value = null;
else
response.value = HelperService.deepCopy(response.value);
return response;
};
RuleLogic.prototype.getSchemaValue = function (data, schema) {
var evalFunc = new Function('data', 'schema', "return data." + schema);
return evalFunc(data, schema);
};
RuleLogic.prototype.setDependents = function (components, schema, componentId) {
Object.keys(components).forEach(function (key) {
var component = components[key];
if (component.schema === schema) {
if (!component.dependents)
component.dependents = [componentId];
else if (component.dependents.indexOf(componentId) === -1)
component.dependents.push(componentId);
}
});
return components;
};
return RuleLogic;
}());
var FormService = /** @class */ (function () {
function FormService(srv, componentResolverService, formBuilder) {
this.componentResolverService = componentResolverService;
this.formBuilder = formBuilder;
this.ruleLogic = new RuleLogic();
this.injectedService = srv;
}
FormService.prototype.getFormAndData = function (formName, ids) {
var _this = this;
if (ids)
return this.injectedService.getForm(formName).pipe(map(function (response) { return response; }), concatMap(function (model) {
return _this.injectedService.getData(model.dataSource, ids).pipe(map(function (data) { return _this.initialiseFormState(model, data); }));
}));
else
return this.injectedService.getForm(formName).pipe(map(function (model) { return _this.initialiseFormState(model, null); }));
};
/*
Invokes the form save in the injected service (see constructor for service)
*/
FormService.prototype.saveForm = function (name, form) {
// remove all transactional data
var updateForm = HelperService.deepCopy(form);
updateForm.pages.forEach(function (page) {
page.sections.forEach(function (section) {
section.components.forEach(function (component) {
Object.keys(component)
.filter(function (key) { return component[key] === null; })
.forEach(function (key) { return delete component[key]; });
delete component.value;
if (component.rules)
if (Object.keys(component.rules).length === 0 && component.rules.constructor === Object)
delete component.rules;
else
Object.keys(component.rules).forEach(function (p) {
delete component.rules[p].value;
});
});
});
});
return this.injectedService.saveForm(name, updateForm).pipe(map(function (response) {
return response;
}));
};
/*
Invokes the data save in the injected service (see constructor for service)
*/
FormService.prototype.saveData = function (dataSource, ids, data) {
return this.injectedService.saveData(dataSource, ids, data).pipe(map(function (result) {
return result;
}));
};
/*
Updates a component value and recalculates all dependents
If reset is set to true, it will recalculate all dependents, this is when a rules as been
modified in the FormQL Editor
*/
FormService.prototype.updateComponent = function (component, formState, reset) {
var _this = this;
if (reset === void 0) { reset = false; }
var value = HelperService.resolveType(component.value, component.type);
formState.data = HelperService.setValue(component.schema, value, formState.data);
if (reset)
this.resetComponentDependents(formState);
// refresh any dependent components
if (component.dependents)
component.dependents.forEach(function (key) {
formState.components[key] = _this.resolveComponentRules(formState.components[key], formState);
});
// set the value on any components that have the same schema
Object.keys(formState.components).forEach(function (key) {
var c = formState.components[key];
if (c.schema === component.schema)
try {
c.value = HelperService.getValue(c.schema, formState.data, c.type);
}
catch (err) {
throw err;
}
});
return formState;
};
/*
Initialises Form State
*/
FormService.prototype.initialiseFormState = function (form, data) {
var reactiveFormStructure = HelperService.createReactiveFormStructure(form, true, data);
var formState = {
components: reactiveFormStructure.components,
data: __assign({}, reactiveFormStructure.data),
form: form,
formControls: reactiveFormStructure.formControls,
reactiveForm: this.formBuilder.group(reactiveFormStructure.pageGroup)
};
return this.resolveConditions(formState);
};
/*
Resets all component dependents, it should only be called when a user modified a question in the formql editor
*/
FormService.prototype.resetComponentDependents = function (formState) {
var _this = this;
if (formState.components) {
Object.keys(formState.components).forEach(function (componentKey) { return delete formState.components[componentKey].dependents; });
Object.keys(formState.components).forEach(function (componentKey) {
var component = formState.components[componentKey];
if (component.rules)
Object.keys(component.rules).forEach(function (ruleKey) {
var rule = component.rules[ruleKey];
_this.ruleLogic.resetDependancies(formState, rule.condition, component);
});
});
Object.keys(formState.components).forEach(function (componentKey) {
return (formState.components[componentKey] = _this.resolveComponentRules(formState.components[componentKey], formState));
});
}
};
FormService.prototype.getData = function (query, ids) {
return this.injectedService.getData(query, ids).pipe(map(function (data) {
if (data)
return data;
else
return {};
}));
};
FormService.prototype.getForms = function () {
return this.injectedService.getForms().pipe(map(function (data) {
return data;
}));
};
FormService.prototype.getForm = function (name) {
return this.injectedService.getForm(name).pipe(map(function (data) {
return data;
}));
};
/*
Resolve all rules for any given component
*/
FormService.prototype.resolveComponentRules = function (component, formState) {
var _this = this;
if (component.rules) {
var resetValidator_1 = false;
Object.keys(component.rules).forEach(function (key) {
var property = component.rules[key];
if (property.condition) {
resetValidator_1 = true;
var evaluatedValue = _this.ruleLogic.evaluate(formState.data, property.condition);
if (key === 'value') {
var value = HelperService.resolveType(evaluatedValue, component.type);
if (component.value !== value) {
component.value = value;
formState = _this.updateComponent(component, formState);
}
}
property.value = evaluatedValue;
}
else
delete component.rules[key];
});
if (resetValidator_1)
formState.formControls[component.componentId] = HelperService.setValidators(this.componentResolverService, component, formState.formControls[component.componentId]);
}
return component;
};
/*
Resolves all conditions in each component, used when initialising the form
*/
FormService.prototype.resolveConditions = function (formState) {
var _this = this;
if (formState.components) {
var components_1 = formState.components;
Object.keys(components_1).forEach(function (componentKey) { return (components_1[componentKey] = _this.resolveComponentRules(components_1[componentKey], formState)); });
}
return formState;
};
FormService.ɵprov = ɵɵdefineInjectable({ factory: function FormService_Factory() { return new FormService(ɵɵinject("FormQLService"), ɵɵinject(ComponentResolverService), ɵɵinject(FormBuilder)); }, token: FormService, providedIn: "root" });
FormService = __decorate([
Injectable({
providedIn: 'root'
}),
__param(0, Inject('FormQLService')),
__metadata("design:paramtypes", [Object, ComponentResolverService,
FormBuilder])
], FormService);
return FormService;
}());
var StoreService = /** @class */ (function () {
function StoreService(formService, componentResolverService, formBuilder) {
this.formService = formService;
this.componentResolverService = componentResolverService;
this.formBuilder = formBuilder;
this.data$ = new Subject();
this.formState$ = new Subject();
this.serviceDestroyed = new Subject();
}
// private formControls: FormControls;
StoreService.prototype.ngOnDestroy = function () {
this.data$.complete();
this.data$.unsubscribe();
};
StoreService.prototype.getData = function () {
return this.data$.asObservable();
};
StoreService.prototype.getFormState = function () {
return this.formState$.asObservable();
};
StoreService.prototype.updateComponent = function (component) {
this.formState = this.formService.updateComponent(component, this.formState, false);
this.data$.next(__assign({}, this.formState.data));
this.formState$.next(__assign({}, this.formState));
};
StoreService.prototype.setComponent = function (component) {
this.formState = this.formService.updateComponent(component, this.formState, true);
// this.formControls = HelperService.resetValidators(this.formState.components, this.formControls, this.componentResolverService);
this.data$.next(__assign({}, this.formState.data));
this.formState$.next(__assign({}, this.formState));
};
StoreService.prototype.getAll = function (formName, ids, mode) {
var _this = this;
this.formService.getFormAndData(formName, ids).pipe(takeUntil(this.serviceDestroyed)).subscribe(function (response) {
_this.formState = __assign({}, response);
_this.formState.ids = ids;
_this.formState.mode = mode;
_this.data$.next(__assign({}, response.data));
_this.formState$.next(_this.formState);
}, function (error) {
_this.formState$.next({
form: {
error: HelperService.formatError({
title: 'Error loading form or data',
error: error
})
}
});
});
};
StoreService.prototype.saveForm = function () {
this.formService.saveForm(this.formState.form.formName, this.formState.form);
};
StoreService.prototype.saveData = function () {
return this.formService.saveData(this.formState.form.dataSource, this.formState.ids, this.formState.data);
};
StoreService.prototype.validateForm = function () {
HelperService.validateForm(this.formState.reactiveForm);
};
StoreService.prototype.isFormValid = function () {
return this.formState.reactiveForm.valid;
};
StoreService.prototype.unsubscribeAll = function () {
this.serviceDestroyed.next();
this.serviceDestroyed.complete();
};
StoreService.prototype.reSetForm = function (eventType, event) {
switch (eventType) {
case InternalEventType.EditingForm:
this.populateReactiveForm();
break;
case InternalEventType.DndFormChanged:
var pageId_1 = event.pageId;
var indexDnd = this.formState.form.pages.findIndex(function (p) { return p.pageId === pageId_1; });
if (indexDnd >= 0)
this.formState.form.pages[indexDnd] = event;
this.populateReactiveForm();
break;
case InternalEventType.RemoveComponent:
var componentId_1 = event.componentId;
var updateSectionId_1 = '';
this.formState.form.pages.forEach(function (page) {
page.sections.forEach(function (section) {
var indexComponent = section.components.findIndex(function (c) { return c.componentId === componentId_1; });
if (indexComponent >= 0) {
section.components.splice(indexComponent, 1);
updateSectionId_1 = section.sectionId;
}
});
});
this.populateReactiveForm();
break;
case InternalEventType.RemoveSection:
var sectionId_1 = event.sectionId;
var updatePageId_1 = '';
this.formState.form.pages.forEach(function (page) {
var indexSection = page.sections.findIndex(function (c) { return c.sectionId === sectionId_1; });
if (indexSection >= 0) {
page.sections.splice(indexSection, 1);
updatePageId_1 = page.pageId;
}
});
this.populateReactiveForm();
break;
}
this.formState$.next(__assign({}, this.formState));
};
StoreService.prototype.populateReactiveForm = function () {
var _this = this;
if (this.formState.form.pages != null && this.formState.form.pages.length > 0) {
// get reactive structure -> formControls, pageGroup and components if it's an update
var reactiveFormStructure_1 = HelperService.createReactiveFormStructure(this.formState.form, true, this.formState.data);
this.formState.formControls = reactiveFormStructure_1.formControls;
// if it's an update, refresh reactive form, set all form controls, validators
this.formState.form.pages.forEach(function (page) {
_this.formState.reactiveForm.setControl(page.pageId, reactiveFormStructure_1.pageGroup[page.pageId]);
});
this.formState.form = HelperService.updateTemplates(this.formState.form);
if (reactiveFormStructure_1.components != null && Object.keys(reactiveFormStructure_1.components).length > 0)
this.formState.formControls = HelperService.resetValidators(reactiveFormStructure_1.components, this.formState.formControls, this.componentResolverService);
this.formState = this.formService.resolveConditions(this.formState);
}
};
StoreService.ɵprov = ɵɵdefineInjectable({ factory: function StoreService_Factory() { return new StoreService(ɵɵinject(FormService), ɵɵinject(ComponentResolverService), ɵɵinject(FormBuilder)); }, token: StoreService, providedIn: "root" });
StoreService = __decorate([
Injectable({ providedIn: 'root' }),
__metadata("design:paramtypes", [FormService,
ComponentResolverService,
FormBuilder])
], StoreService);
return StoreService;
}());
var PageWrapperComponent = /** @class */ (function () {
function PageWrapperComponent(dndService, storeService) {
this.dndService = dndService;
this.storeService = storeService;
this.FormQLMode = FormQLMode;
this.ContainerType = ContainerType;
this.ComponentPositionType = GridPositionType;
}
PageWrapperComponent.prototype.ngOnInit = function () {
this.sections = this.createSections(this.page);
};
PageWrapperComponent.prototype.synchroniseModel = function ($event, positionId) {
var dndEvent = {
sourceObjectId: $event.sourceObjectId,
sourceWrapperId: $event.sourceWrapperId,
targetPositionId: positionId,
targetWrapperId: this.page.pageId,
targetIndexId: $event.targetIndexId
};
this.page = this.dndService.synchronisePageModel(this.page, dndEvent);
this.sections = this.createSections(this.page);
this.storeService.reSetForm(InternalEventType.DndFormChanged, this.page);
};
PageWrapperComponent.prototype.createSections = function (page) {
var sections = {};
if (page && page.sections)
page.sections.forEach(function (section) {
if (sections && sections[section.position.id])
sections[section.position.id].push(section);
else
sections[section.position.id] = [section];
});
return sections;
};
PageWrapperComponent.prototype.trackByFn = function (index, item) {
return item.id;
};
PageWrapperComponent.prototype.resetSections = function () {
if (this.sections)
this.sections = this.createSections(this.page);
};
__decorate([
Input(),
__metadata("design:type", Object)
], PageWrapperComponent.prototype, "page", void 0);
__decorate([
Input(),
__metadata("design:type", FormGroup)
], PageWrapperComponent.prototype, "reactivePage", void 0);
__decorate([
Input(),
__metadata("design:type", Number)
], PageWrapperComponent.prototype, "mode", void 0);
PageWrapperComponent = __decorate([
Component({
// tslint:disable-next-line: component-selector
selector: '[formql-page-wrapper]',
template: "\n <div class=\"fql-page-body\">\n <ng-template formqlGdConfig\n [formqlGdConfigOf]=\"page.template.body\" let-bodyitem let-i=\"index\"\n (resetItems)=\"resetSections()\">\n <div\n [ngClass]=\"{'fql-page-container': mode === FormQLMode.Edit}\"\n [ngStyle]=\"bodyitem.style\">\n <div formqlDndDrop\n [type]=\"ContainerType.Section\"\n [mode]=\"mode\"\n [ngClass]=\"{'fql-page-container': (mode === FormQLMode.Edit)}\"\n (synchronise)=\"synchroniseModel($event, bodyitem.id)\">\n <ng-container *ngFor=\"let section of sections[bodyitem.id]; trackBy: trackByFn\">\n <ng-container *ngTemplateOutlet=\"templateRef; context: {section: section}\">\n </ng-container>\n </ng-container>\n </div>\n </div>\n </ng-template>\n </div>\n <ng-template #templateRef let-section=\"section\">\n <div [formGroup]=\"reactivePage\">\n <div formql-section-wrapper\n [page]=\"page\"\n [section]=\"section\"\n [formGroupName]=\"section.sectionId\"\n [reactiveSection]=\"reactivePage.controls[section.sectionId]\"\n [mode]=\"mode\">\n </div>\n </div>\n </ng-template>",
providers: [DndService],
styles: [".fql-bundle-field-input{width:100%;box-sizing:border-box;-webk