UNPKG

@davebaol/angular-formio-editor

Version:

Angular component integrating Form.io builder and renderer with a json editor

1,097 lines (1,063 loc) 103 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('ngx-bootstrap/modal'), require('@angular/forms'), require('@angular/platform-browser'), require('angular-formio'), require('ngx-bootstrap/alert'), require('jsoneditor')) : typeof define === 'function' && define.amd ? define('@davebaol/angular-formio-editor', ['exports', '@angular/core', 'ngx-bootstrap/modal', '@angular/forms', '@angular/platform-browser', 'angular-formio', 'ngx-bootstrap/alert', 'jsoneditor'], factory) : (global = global || self, factory((global.davebaol = global.davebaol || {}, global.davebaol['angular-formio-editor'] = {}), global.ng.core, global['ngx-bootstrap/modal'], global.ng.forms, global.ng.platformBrowser, global['angular-formio'], global['ngx-bootstrap/alert'], global.jsoneditor)); }(this, (function (exports, core, modal, forms, platformBrowser, angularFormio, alert, JsonEditor) { 'use strict'; JsonEditor = JsonEditor && Object.prototype.hasOwnProperty.call(JsonEditor, 'default') ? JsonEditor['default'] : JsonEditor; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function __param(paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } } function __metadata(metadataKey, metadataValue) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); } function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } function __createBinding(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; } function __exportStar(m, exports) { for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) exports[p] = m[p]; } function __values(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spread() { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; } function __spreadArrays() { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; function __await(v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } function __asyncGenerator(thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var g = generator.apply(thisArg, _arguments || []), i, q = []; return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } } function __asyncDelegator(o) { var i, p; return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } } function __asyncValues(o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } } function __makeTemplateObject(cooked, raw) { if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } return cooked; }; function __importStar(mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result.default = mod; return result; } function __importDefault(mod) { return (mod && mod.__esModule) ? mod : { default: mod }; } function __classPrivateFieldGet(receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); } function __classPrivateFieldSet(receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; } var _this = this; /* This is heavily inspired by https://github.com/schnittstabil/merge-options */ var _a = Object.prototype, hasOwnProperty = _a.hasOwnProperty, toString = _a.toString; var propertyIsEnumerable = Object.propertyIsEnumerable; var globalThis = this; var defaultMergeOpts = { ignoreUndefined: false }; var isPlainObject = function (value) { if (toString.call(value) !== '[object Object]') { return false; } var prototype = Object.getPrototypeOf(value); return prototype === null || prototype === Object.prototype; }; var ɵ0 = isPlainObject; var defineProperty = function (obj, name, value) { Object.defineProperty(obj, name, { value: value, writable: true, enumerable: true, configurable: true }); }; var ɵ1 = defineProperty; var getEnumerableOwnPropertyKeys = function (value) { var e_1, _a; var keys = []; for (var key in value) { if (hasOwnProperty.call(value, key)) { keys.push(key); } } if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(value); try { for (var symbols_1 = __values(symbols), symbols_1_1 = symbols_1.next(); !symbols_1_1.done; symbols_1_1 = symbols_1.next()) { var symbol = symbols_1_1.value; if (propertyIsEnumerable.call(value, symbol)) { keys.push(symbol); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (symbols_1_1 && !symbols_1_1.done && (_a = symbols_1.return)) _a.call(symbols_1); } finally { if (e_1) throw e_1.error; } } } return keys; }; var ɵ2 = getEnumerableOwnPropertyKeys; var clone = function (value) { if (Array.isArray(value)) { return cloneArray(value); } if (isPlainObject(value)) { return clonePlainObject(value); } return value; }; var cloneArray = function (array) { var result = array.slice(0, 0); getEnumerableOwnPropertyKeys(array).forEach(function (key) { defineProperty(result, key, clone(array[key])); }); return result; }; var ɵ3 = cloneArray; var clonePlainObject = function (obj) { var result = Object.getPrototypeOf(obj) === null ? Object.create(null) : {}; getEnumerableOwnPropertyKeys(obj).forEach(function (key) { defineProperty(result, key, clone(obj[key])); }); return result; }; var ɵ4 = clonePlainObject; var mergeKeys = function (merged, source, keys, config) { keys.forEach(function (key) { if (typeof source[key] === 'undefined' && config.ignoreUndefined) { return; } // Do not recurse into prototype chain of merged if (key in merged && merged[key] !== Object.getPrototypeOf(merged)) { defineProperty(merged, key, _merge(merged[key], source[key], config)); } else { defineProperty(merged, key, clone(source[key])); } }); return merged; }; var ɵ5 = mergeKeys; // tslint:disable-next-line:variable-name var _merge = function (merged, source, config) { if (!isPlainObject(source) || !isPlainObject(merged)) { return clone(source); } return mergeKeys(merged, source, getEnumerableOwnPropertyKeys(source), config); }; var ɵ6 = _merge; var merge = function () { var e_2, _a; var options = []; for (var _i = 0; _i < arguments.length; _i++) { options[_i] = arguments[_i]; } var config = _merge(clone(defaultMergeOpts), (_this !== globalThis && _this) || {}, defaultMergeOpts); var merged = { _: {} }; try { for (var options_1 = __values(options), options_1_1 = options_1.next(); !options_1_1.done; options_1_1 = options_1.next()) { var option = options_1_1.value; if (option === undefined) { continue; } if (!isPlainObject(option)) { throw new TypeError('`' + option + '` is not a plain Object'); } merged = _merge(merged, { _: option }, config); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (options_1_1 && !options_1_1.done && (_a = options_1.return)) _a.call(options_1); } finally { if (e_2) throw e_2.error; } } return merged._; }; var hasOwnProperty$1 = Object.prototype.hasOwnProperty; // ------------------------------- // SCHEMAS // ------------------------------- var Schema = /** @class */ (function () { function Schema(component) { this.component = component; this.conditions = []; this.required = false; this.dataType = {}; if (component && component.formioComponent) { if (component.formioComponent.conditional) { // Add non-empty condition from the component var cnd = component.formioComponent.conditional; if (typeof cnd.show === 'boolean' && cnd.when) { // console.log(component.formioComponent.type, "Pushing condition") var c = { show: cnd.show, when: cnd.when, eq: cnd.eq }; c.key = this.generateSingleConditionKey(c); this.conditions.push(c); } } if (component.formioComponent.validate) { this.required = component.formioComponent.validate.required; } } } /*private*/ Schema.prototype.generateSingleConditionKey = function (condition) { return JSON.stringify(condition); }; /*private*/ Schema.prototype.generateConditionsKey = function () { return JSON.stringify(this.conditions, function (k, v) { return k === 'key' ? undefined : v; }); }; Schema.prototype.prepareConditions = function () { // Ensure the array has unique conditions this.conditions = this.conditions.sort(function (c1, c2) { return c1.key.compare(c2.key); }) .filter(function (x, i, a) { return i === 0 || x.key !== a[i - 1].key; }); this.conditions.key = this.generateConditionsKey(); }; Schema.prototype.shrink = function () { for (var k in this.properties) { if (hasOwnProperty$1.call(this.properties, k)) { var propSchema = this.properties[k]; if (propSchema instanceof MergeableObjectSchema && propSchema.component && propSchema.component.shrinkable()) { // console.log('Shrink', propSchema.component.formioComponent.type); propSchema.shrink(); delete this.properties[k]; // Remove shribkable schema from parent this.merge(propSchema); // merge its properties and conditions with parent } } } return this; }; // Subclasses overriding this method MUST call super.toJsonSchema() Schema.prototype.toJsonSchema = function () { return Object.assign({}, this.dataType); }; return Schema; }()); var ObjectSchema = /** @class */ (function (_super) { __extends(ObjectSchema, _super); function ObjectSchema(component) { var _this = _super.call(this, component) || this; _this.dataType.type = 'object'; _this.properties = {}; return _this; } ObjectSchema.prototype.addProperty = function (name, schema, required) { this.properties[name] = schema; schema.required = required; return this; }; ObjectSchema.prototype.toJsonSchema = function () { var jsonSchema = _super.prototype.toJsonSchema.call(this); jsonSchema.properties = {}; var required = []; var condPropMap = {}; var conditionsMap = {}; for (var pk in this.properties) { if (hasOwnProperty$1.call(this.properties, pk)) { var childSchema = this.properties[pk]; if (childSchema.conditions.length === 0) { if (childSchema.required) { required.push(pk); } jsonSchema.properties[pk] = childSchema.toJsonSchema(); continue; } childSchema.prepareConditions(); var ck = childSchema.conditions.key; conditionsMap[ck] = childSchema.conditions; if (!(ck in condPropMap)) { condPropMap[ck] = {}; } condPropMap[ck][pk] = childSchema; } } // Add required to jsonSchema if not empty if (required.length > 0) { jsonSchema.required = required; } // Generate allOf from conditional properties var allOf = []; for (var ck in condPropMap) { if (hasOwnProperty$1.call(condPropMap, ck)) { var conds = conditionsMap[ck]; var _if = { properties: conds.reduce(function (acc, c) { acc[c.when] = c.show ? { const: c.eq } : { not: { const: c.eq } }; return acc; }, {}) }; var then = { required: [], properties: {} }; for (var pk in condPropMap[ck]) { if (hasOwnProperty$1.call(condPropMap[ck], pk)) { var childSchema = condPropMap[ck][pk]; if (childSchema.required) { then.required.push(pk); } then.properties[pk] = childSchema.toJsonSchema(); } } // Remove empty required if (then.required.length === 0) { delete then.required; } // Add if/then to allOf allOf.push({ if: _if, then: then }); } } // Add allOf to jsonSchema if not empty if (allOf.length > 0) { jsonSchema.allOf = allOf; } return jsonSchema; }; return ObjectSchema; }(Schema)); var MergeableObjectSchema = /** @class */ (function (_super) { __extends(MergeableObjectSchema, _super); function MergeableObjectSchema(component) { return _super.call(this, component) || this; } MergeableObjectSchema.prototype.merge = function () { var sources = []; for (var _i = 0; _i < arguments.length; _i++) { sources[_i] = arguments[_i]; } var targetProps = this.properties; for (var i = 0, len = sources.length; i < len; i++) { var source = sources[i]; if (source instanceof MergeableObjectSchema) { // merge properties var sourceProps = source.properties; for (var key in sourceProps) { if (hasOwnProperty$1.call(sourceProps, key)) { // Append source schema conditions to the conditions of its sub-schemas Array.prototype.push.apply(sourceProps[key].conditions, source.conditions); // Merge properties recursively if (targetProps[key] && sourceProps[key] instanceof MergeableObjectSchema) { targetProps[key].merge(sourceProps[key]); } else { targetProps[key] = sourceProps[key]; } } } } } return this; }; return MergeableObjectSchema; }(ObjectSchema)); var ArraySchema = /** @class */ (function (_super) { __extends(ArraySchema, _super); function ArraySchema(component, items) { var _this = _super.call(this, component) || this; _this.dataType.type = 'array'; _this.dataType.items = items; return _this; } ArraySchema.prototype.toJsonSchema = function () { var jsonSchema = _super.prototype.toJsonSchema.call(this); jsonSchema.items = this.dataType.items.toJsonSchema(); return jsonSchema; }; return ArraySchema; }(Schema)); var PrimitiveSchema = /** @class */ (function (_super) { __extends(PrimitiveSchema, _super); function PrimitiveSchema(component, type) { var _this = _super.call(this, component) || this; _this.dataType.type = type; return _this; } return PrimitiveSchema; }(Schema)); var BooleanSchema = /** @class */ (function (_super) { __extends(BooleanSchema, _super); function BooleanSchema(component) { return _super.call(this, component, 'boolean') || this; } return BooleanSchema; }(PrimitiveSchema)); var NumberSchema = /** @class */ (function (_super) { __extends(NumberSchema, _super); function NumberSchema(component) { var _this = _super.call(this, component, 'number') || this; if (component && component.formioComponent && component.formioComponent.validate) { var validate = component.formioComponent.validate; if (validate.min || typeof validate.min === 'number') _this.dataType.minimum = Number(validate.min); if (validate.max || typeof validate.max === 'number') _this.dataType.maximum = Number(validate.max); if (validate.integer) _this.dataType.type = 'integer'; } return _this; } return NumberSchema; }(PrimitiveSchema)); var StringSchema = /** @class */ (function (_super) { __extends(StringSchema, _super); function StringSchema(component) { var _this = _super.call(this, component, 'string') || this; if (component && component.formioComponent && component.formioComponent.validate) { var validate = component.formioComponent.validate; if (validate.minLength) _this.dataType.minLength = Number(validate.minLength); if (validate.maxLength) _this.dataType.maxLength = Number(validate.maxLength); if (validate.pattern) _this.dataType.pattern = validate.pattern; } return _this; } return StringSchema; }(PrimitiveSchema)); var EnumSchema = /** @class */ (function (_super) { __extends(EnumSchema, _super); function EnumSchema(component, values) { var _this = _super.call(this, component) || this; _this.dataType.enum = values; return _this; } return EnumSchema; }(Schema)); // ------------------------------- // COMPONENT BASE CLASSES // ------------------------------- var Component = /** @class */ (function () { function Component(formioComponent) { this.formioComponent = formioComponent; } Component.prototype.schema = function () { throw new Error('Subclasses of \'Component\' have to implement the method \'schema\'!'); }; // Layout components are view-only components. From resource perspective, they are to be // shrinked, because they don't have any value neither implicit nor expressed by user. // So they don't contribute to the underlying resource because their 'API key' does not // match any field inside the resource itself. // Howewer, shrink process propagates component's condition (show/when/eq) to child components. Component.prototype.shrinkable = function () { return !(this.formioComponent && this.formioComponent.input); }; return Component; }()); var AtomicComponent = /** @class */ (function (_super) { __extends(AtomicComponent, _super); function AtomicComponent() { return _super !== null && _super.apply(this, arguments) || this; } AtomicComponent.prototype.schema = function () { var schema = this.baseSchema(); if (this.formioComponent.multiple) { if (this.formioComponent.validate && !this.formioComponent.validate.required) { // With multiple values enabled the component can generate null items if required is false schema.dataType = { anyOf: [schema.dataType, { type: 'null' }] }; } return new ArraySchema(this, schema); } return schema; }; AtomicComponent.prototype.baseSchema = function () { throw new Error('Subclasses of \'AtomicComponent\' have to implement the method \'baseSchema\'!'); }; AtomicComponent.prototype.isDefaultCastToString = function () { return false; // cast defaults to 'auto' }; AtomicComponent.prototype.cast = function (val, to) { switch (to) { case 'boolean': return val.toLowerCase() === 'true'; case 'number': return Number(val); case 'object': return JSON.parse(val); case 'string': return val; case 'auto': default: // Either autotype or string if (to !== 'auto' && this.isDefaultCastToString()) return val; if (val === "true") return true; if (val === "false") return false; if (val === "") return val; var v = Number(val); return isNaN(v) ? val : v; } }; return AtomicComponent; }(Component)); var CompoundComponent = /** @class */ (function (_super) { __extends(CompoundComponent, _super); function CompoundComponent() { return _super !== null && _super.apply(this, arguments) || this; } CompoundComponent.prototype.schema = function () { var schema = new MergeableObjectSchema(this); this.childrenSchema(schema); return schema.shrink(); }; /*prorected*/ CompoundComponent.prototype.children = function () { return this.formioComponent.components; }; // Subclasses can override this method to provide a default class // for children that don't have a type /*prorected*/ CompoundComponent.prototype.defaultChildClass = function () { return undefined; }; /*prorected*/ CompoundComponent.prototype.childrenSchema = function (parentSchema) { var children = this.children(); for (var i = 0, len = children.length; i < len; i++) { var c = children[i]; // console.log(this.formioComponent.type, 'child', c) var type = MAP[c.type] || this.defaultChildClass(); if (type) { var schema = new (type)(c).schema(); var required = c.validate && c.validate.required; // Dotted key means nested schema var keyParts = c.key.split('.'); for (var j = keyParts.length - 1; j > 0; j--) { schema = new MergeableObjectSchema(undefined).addProperty(keyParts[j], schema, required); } parentSchema.merge(new MergeableObjectSchema(undefined).addProperty(keyParts[0], schema, required)); } else { // console.log(this.formioComponent.type, ": skipping child with unknown type", c.type); } } return parentSchema; }; return CompoundComponent; }(Component)); // ------------------------------- // ABSTRACT COMPONENT CLASSES // ------------------------------- var StringComponent = /** @class */ (function (_super) { __extends(StringComponent, _super); function StringComponent() { return _super !== null && _super.apply(this, arguments) || this; } StringComponent.prototype.baseSchema = function () { return new StringSchema(this); }; return StringComponent; }(AtomicComponent)); var EnumComponent = /** @class */ (function (_super) { __extends(EnumComponent, _super); function EnumComponent(formioComponent) { var additionalValuesIfNotRequired = []; for (var _i = 1; _i < arguments.length; _i++) { additionalValuesIfNotRequired[_i - 1] = arguments[_i]; } var _this = _super.call(this, formioComponent) || this; _this.additionalValuesIfNotRequired = additionalValuesIfNotRequired; return _this; } // This is needed because different components take values from different path EnumComponent.prototype.values = function () { throw new Error('Subclasses of \'EnumComponent\' have to implement the method \'values\'!'); }; EnumComponent.prototype.baseSchema = function () { var _this = this; var values = this.values().map(function (v) { return _this.cast(v.value, _this.formioComponent.dataType); }); if (this.formioComponent && this.formioComponent.validate && !this.formioComponent.validate.required) { Array.prototype.push.apply(values, this.additionalValuesIfNotRequired); } return new EnumSchema(this, values); }; return EnumComponent; }(AtomicComponent)); // ------------------------------- // BASIC COMPONENTS // ------------------------------- var CheckboxComponent = /** @class */ (function (_super) { __extends(CheckboxComponent, _super); function CheckboxComponent() { return _super !== null && _super.apply(this, arguments) || this; } CheckboxComponent.prototype.baseSchema = function () { return new BooleanSchema(this); }; return CheckboxComponent; }(AtomicComponent)); var NumberComponent = /** @class */ (function (_super) { __extends(NumberComponent, _super); function NumberComponent() { return _super !== null && _super.apply(this, arguments) || this; } NumberComponent.prototype.baseSchema = function () { return new NumberSchema(this); }; return NumberComponent; }(AtomicComponent)); var PasswordComponent = /** @class */ (function (_super) { __extends(PasswordComponent, _super); function PasswordComponent() { return _super !== null && _super.apply(this, arguments) || this; } return PasswordComponent; }(StringComponent)); var RadioComponent = /** @class */ (function (_super) { __extends(RadioComponent, _super); function RadioComponent(formioComponent) { // Empty string and null are valid values if the component is not required return _super.call(this, formioComponent, '', null) || this; } RadioComponent.prototype.values = function () { return this.formioComponent.values; }; return RadioComponent; }(EnumComponent)); var SelectComponent = /** @class */ (function (_super) { __extends(SelectComponent, _super); function SelectComponent(formioComponent) { // Empty string and null are valid values if the component is not required return _super.call(this, formioComponent, '', null) || this; } SelectComponent.prototype.values = function () { return this.formioComponent.data.values; }; SelectComponent.prototype.schema = function () { var schema = _super.prototype.schema.call(this); // If multiple values are enabled ensure uniqueness if (schema instanceof ArraySchema) { schema.dataType.uniqueItems = true; } return schema; }; SelectComponent.prototype.isDefaultCastToString = function () { return true; // cast defaults to 'string' }; return SelectComponent; }(EnumComponent)); var SelectBoxesComponent = /** @class */ (function (_super) { __extends(SelectBoxesComponent, _super); function SelectBoxesComponent() { return _super !== null && _super.apply(this, arguments) || this; } SelectBoxesComponent.prototype.baseSchema = function () { var schema = new ObjectSchema(this); schema.dataType.additionalProperties = false; var values = this.formioComponent.values .forEach(function (v) { return schema.addProperty(v.value, new BooleanSchema(undefined), true); }); if (this.formioComponent.validate && !this.formioComponent.validate.required) { // This is needed for compatibility. // Formio adds a boolean property with name "" when the component is not required. // The property itself must not be required schema.addProperty('', new BooleanSchema(undefined), false); } return schema; }; return SelectBoxesComponent; }(AtomicComponent)); var TextAreaComponent = /** @class */ (function (_super) { __extends(TextAreaComponent, _super); function TextAreaComponent() { return _super !== null && _super.apply(this, arguments) || this; } return TextAreaComponent; }(StringComponent)); var TextFieldComponent = /** @class */ (function (_super) { __extends(TextFieldComponent, _super); function TextFieldComponent() { return _super !== null && _super.apply(this, arguments) || this; } return TextFieldComponent; }(StringComponent)); // ------------------------------- // ADVANCED COMPONENTS // ------------------------------- var DateTimeComponent = /** @class */ (function (_super) { __extends(DateTimeComponent, _super); function DateTimeComponent() { return _super !== null && _super.apply(this, arguments) || this; } return DateTimeComponent; }(StringComponent)); var EmailComponent = /** @class */ (function (_super) { __extends(EmailComponent, _super); function EmailComponent() { return _super !== null && _super.apply(this, arguments) || this; } return EmailComponent; }(StringComponent)); var UrlComponent = /** @class */ (function (_super) { __extends(UrlComponent, _super); function UrlComponent() { return _super !== null && _super.apply(this, arguments) || this; } return UrlComponent; }(StringComponent)); var TagsComponent = /** @class */ (function (_super) { __extends(TagsComponent, _super); function TagsComponent() { return _super !== null && _super.apply(this, arguments) || this; } TagsComponent.prototype.schema = function () { return this.formioComponent.storeas === 'array' ? new ArraySchema(this, this.baseSchema()) : this.baseSchema(); }; TagsComponent.prototype.baseSchema = function () { return new StringSchema(this); }; return TagsComponent; }(AtomicComponent)); // ------------------------------- // LAYOUT COMPONENTS // ------------------------------- var ColumnsComponent = /** @class */ (function (_super) { __extends(ColumnsComponent, _super); function ColumnsComponent() { return _super !== null && _super.apply(this, arguments) || this; } // Determines children from columns. // Children are calculated lazily and cached into this instance. ColumnsComponent.prototype.children = function () { var _this = this; if (!this.components) { this.components = []; this.formioComponent.columns.forEach(function (col) { return Array.prototype.push.apply(_this.components, col.components); }); } return this.components; }; return ColumnsComponent; }(CompoundComponent)); var ContentComponent = /** @class */ (function (_super) { __extends(ContentComponent, _super); function ContentComponent() { return _super !== null && _super.apply(this, arguments) || this; } ContentComponent.prototype.children = function () { return []; // This component never has children }; return ContentComponent; }(CompoundComponent)); var FieldSetComponent = /** @class */ (function (_super) { __extends(FieldSetComponent, _super); function FieldSetComponent() { return _super !== null && _super.apply(this, arguments) || this; } return FieldSetComponent; }(CompoundComponent)); var PanelComponent = /** @class */ (function (_super) { __extends(PanelComponent, _super); function PanelComponent() { return _super !== null && _super.apply(this, arguments) || this; } return PanelComponent; }(CompoundComponent)); var TableComponent = /** @class */ (function (_super) { __extends(TableComponent, _super); function TableComponent() { return _super !== null && _super.apply(this, arguments) || this; } // Determines children from table's rows and columns. // Children are calculated lazily and cached into this instance. TableComponent.prototype.children = function () { var _this = this; if (!this.components) { this.components = []; this.formioComponent.rows.forEach(function (row) { row.forEach(function (col) { return Array.prototype.push.apply(_this.components, col.components); }); }); } return this.components; }; return TableComponent; }(CompoundComponent)); var TabsComponent = /** @class */ (function (_super) { __extends(TabsComponent, _super); function TabsComponent() { return _super !== null && _super.apply(this, arguments) || this; } /*prorected*/ TabsComponent.prototype.defaultChildClass = function () { return CompoundComponent; // Needed because children don't have a type :( }; return TabsComponent; }(CompoundComponent)); var WellComponent = /** @class */ (function (_super) { __extends(WellComponent, _super); function WellComponent() { return _super !== null && _super.apply(this, arguments) || this; } return WellComponent; }(CompoundComponent)); // ------------------------------- // DATA COMPONENTS // ------------------------------- var EditGridComponent = /** @class */ (function (_super) { __extends(EditGridComponent, _super); function EditGridComponent() { return _super !== null && _super.apply(this, arguments) || this; } EditGridComponent.prototype.schema = function () { return new ArraySchema(this, _super.prototype.schema.call(this)); }; return EditGridComponent; }(CompoundComponent)); // ------------------------------- // FORM COMPONENT // ------------------------------- var FormComponent = /** @class */ (function (_super) { __extends(FormComponent, _super); function FormComponent() { return _super !== null && _super.apply(this, arguments) || this; } return FormComponent; }(CompoundComponent)); var MAP = { editgrid: EditGridComponent, checkbox: CheckboxComponent, columns: ColumnsComponent, content: ContentComponent, datetime: DateTimeComponent, email: EmailComponent, fieldset: FieldSetComponent, number: NumberComponent, password: PasswordComponent, panel: PanelComponent, radio: RadioComponent, select: SelectComponent, selectboxes: SelectBoxesComponent, table: TableComponent, tabs: TabsComponent, tags: TagsComponent, textarea: TextAreaComponent, textfield: TextFieldComponent, url: UrlComponent, well: WellComponent }; function generateFormJsonSchema(form) { return new FormComponent(form).schema().toJsonSchema(); } // tslint:disable:object-literal-key-quotes quotemark semicolon var schema = { "title": "Form", "description": "Object containing a form.io form", "type": "object", "required": ["components"], "properties": { "display": { "title": "Display mode", "description": "The given name.", "enum": ["form", "wizard"] }, "components": { "$ref": "components" } } }; // tslint:disable:object-literal-key-quotes quotemark semicolon var components = { "title": "Component List", "description": "The list of all components", "type": "array", "items": { "$ref": "component" } }; // tslint:disable:object-literal-key-quotes quotemark semicolon var componentStrict = { "title": "Component", "description": "Object containing a form.io component", "type": "object", "required": ["type", "key", "input"], "properties": { "type": { "title": "Component Type", "description": "The type of this component", "type": "string" }, "key": { "title": "Component Key", "description": "The API key for this component", "type": "string" }, "label": { "title": "Component Label", "description": "The HTML label to give this component", "type": "string" }, "placeholder": { "title": "Component Placeholder", "description": "The text to show in the input before they type", "type": "string" }, "input": { "title": "User Input?", "description": "Determines if this is an input from the user", "type": "boolean" }, "tableView": { "title": "Component TableView", "description": "Determines if this field will show in the data tables output", "type": "boolean" }, "multiple": { "title": "Component Multiple", "description": "If this field should collect multiple values, creating an array of values", "type": "boolean" }, "protected": { "title": "Component Protected", "description": "If the value of this field should be shown to the end user via API once it is saved", "type": "boolean" }, "prefix": { "title": "Component Prefix",