diff --git a/package.json b/package.json index 50ff0a9..8552a0a 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "homepage": "https://github.com/redux-autoform/redux-autoform#readme", "dependencies": { "bootstrap": "^3.3.5", - "clone": "^1.0.2", "font-awesome": "^4.6.3", "react": "^15.1.0", "react-addons-update": "^15.2.1", @@ -39,8 +38,7 @@ "redux": "^3.4.0", "redux-autoform-bootstrap-ui": "^1.0.1", "redux-autoform-utils": "^1.0.3", - "redux-form": "^5.2.5", - "underscore": "^1.8.3" + "redux-form": "^5.2.5" }, "devDependencies": { "babel-cli": "^6.6.5", diff --git a/src/metadata/MetadataProvider.js b/src/metadata/MetadataProvider.js index 60e09aa..bf65c16 100644 --- a/src/metadata/MetadataProvider.js +++ b/src/metadata/MetadataProvider.js @@ -1,6 +1,3 @@ -import _ from 'underscore'; -import clone from 'clone'; - export default class MetadataProvider { /** @@ -38,23 +35,37 @@ export default class MetadataProvider { }); } - schema = clone(schema); - schema.entities = MetadataProvider.canonizeArray(schema.entities); - _.each(schema.entities, entity => { - entity.fields = MetadataProvider.canonizeArray(entity.fields); - entity.layouts = MetadataProvider.canonizeArray(entity.layouts); - _.each(entity.layouts, layout => { - layout.fields = MetadataProvider.canonizeArray(layout.fields); - layout.groups = MetadataProvider.canonizeArray(layout.groups); - _.each(layout.groups, group => { - group.fields = MetadataProvider.canonizeArray(group.fields); - }) - }); - }); + schema = {...schema}; + this._canonizeArrays(schema, ["entities", "layouts", "groups"]) + + //schema.entities = MetadataProvider.canonizeArray(schema.entities); + //_.each(schema.entities, entity => { + // entity.fields = MetadataProvider.canonizeArray(entity.fields); + // entity.layouts = MetadataProvider.canonizeArray(entity.layouts); + // _.each(entity.layouts, layout => { + // layout.fields = MetadataProvider.canonizeArray(layout.fields); + // layout.groups = MetadataProvider.canonizeArray(layout.groups); + // _.each(layout.groups, group => { + // group.fields = MetadataProvider.canonizeArray(group.fields); + // }) + // }); + //}); + return schema; } + static _canonizeArrays(dataArray, keys, id = 0) { + dataArray[keys[id]] = MetadataProvider.canonizeArray(dataArray[keys[id]]); + if(dataArray[keys[id]]) { + dataArray[keys[id]].forEach(elem => { + elem.fields = MetadataProvider.canonizeArray(elem.fields); + if(id + 1 < keys.length) + this._canonizeArrays(elem, keys, id + 1); + }) + } + + } /** * Ensures the object passed in is an array. If it is, it is returned, otherwise, this function * converts the target object into an array. @@ -67,14 +78,15 @@ export default class MetadataProvider { static canonizeArray(obj) { if (!obj) return obj; // this is so the canonizeSchema method doesn't have to check every property for undefined - if (_.isArray(obj)) + if (Array.isArray(obj)) return obj; // let's create an array - return _.map(_.keys(obj), (property) => { - if (!_.isObject(obj[property])) + return Object.keys(obj).map((property) => { + let isObject = obj[property] && typeof obj[property] === "object"; + if (!isObject) throw Error('cannot generate canonical array. Every field should be an object'); - return _.extend({name: property}, obj[property]); + return {name: property, ...obj[property]}; }); } @@ -101,7 +113,7 @@ export default class MetadataProvider { let entity; if(entityName) - entity = _.find(schema.entities, e => e.name === entityName); + entity = schema.entities.find(e => e.name === entityName); else { if(schema.entities.length != 1) throw Error('When an entityName is not specified, there must be one and only one entity'); @@ -123,7 +135,7 @@ export default class MetadataProvider { let layout; if(layoutName) - layout = _.find(entity.layouts, l => l.name === layoutName); + layout = entity.layouts? entity.layouts.find(l => l.name === layoutName) : layout; else { if(entity.layouts.length != 1) throw Error('When the layoutName is not specified, there must be one and only one layout'); @@ -170,8 +182,8 @@ export default class MetadataProvider { let thisGroupFields = []; if (layout.groups) { - _.each(layout.groups, g => { - thisGroupFields = _.union(thisGroupFields, this.getFieldsInternal(schema, entity, g, partialResult, callback)) + layout.groups.forEach(g => { + thisGroupFields = [... new Set(thisGroupFields.concat(this.getFieldsInternal(schema, entity, g, partialResult, callback)))]; }); } @@ -180,9 +192,9 @@ export default class MetadataProvider { for (let i = 0; i < layout.fields.length; i++) { let groupField = layout.fields[i]; - let existingEntityProperty = _.find(entity.fields, field => field.name == groupField.name); + let existingEntityProperty = entity.fields.find(field => field.name == groupField.name); - let field = _.extend({}, existingEntityProperty || {}, groupField); + let field = {...existingEntityProperty || {}, ...groupField}; this.validateFieldMetadata(field); thisGroupFields.push(field); @@ -222,7 +234,7 @@ export default class MetadataProvider { } } - return _.union(partialResult, thisGroupFields); + return [...new Set(partialResult.concat(thisGroupFields))]; } /** @@ -306,7 +318,7 @@ export default class MetadataProvider { if (!fieldMetadata) throw Error('fieldMetadata should be truthy'); let result = []; - _.each(fieldMetadata, f => { + fieldMetadata.forEach(f => { if (f.fields) { // if a field has fields, it's either an array or a complex object let fieldPrefix = f.type == 'array' ? `${f.name}[]` : f.name; diff --git a/src/metadata/evaluator/filter/arrayMetadataFilter.js b/src/metadata/evaluator/filter/arrayMetadataFilter.js index 2c932b2..ddfb771 100644 --- a/src/metadata/evaluator/filter/arrayMetadataFilter.js +++ b/src/metadata/evaluator/filter/arrayMetadataFilter.js @@ -1,5 +1,3 @@ -import _ from 'underscore'; - export default { filter: function(propertyMetadata, model, keyPrefix, metadataEvaluator, reduxProps, onChange) { @@ -11,7 +9,7 @@ export default { throw Error('when metadata is of type \'array\' and arrayType is \'entity\', it must have a fields property'); } - if (!_.has(model, propertyMetadata.name) || model[propertyMetadata.name] === null || model[propertyMetadata.name] === undefined) { + if (!model.hasOwnProperty(propertyMetadata.name) || model[propertyMetadata.name] === null || model[propertyMetadata.name] === undefined) { // if the property does not exist, create it model[propertyMetadata.name] = []; } else { @@ -24,7 +22,7 @@ export default { // returns the reduxProps for a particular array item let getReduxPropsForItem = (index) => { if(!reduxProps) return undefined; - if(!_.has(reduxProps, propertyMetadata.name)) throw Error('reduxProps is defined but it does not have the required property metadata'); + if(reduxProps && !reduxProps.hasOwnProperty(propertyMetadata.name)) throw Error('reduxProps is defined but it does not have the required property metadata'); return reduxProps[propertyMetadata.name][index]; }; diff --git a/src/metadata/evaluator/filter/defaultMetadataFilter.js b/src/metadata/evaluator/filter/defaultMetadataFilter.js index 38fafad..167ce2e 100644 --- a/src/metadata/evaluator/filter/defaultMetadataFilter.js +++ b/src/metadata/evaluator/filter/defaultMetadataFilter.js @@ -1,5 +1,3 @@ -import _ from 'underscore'; - export default { filter: function(propertyMetadata, model, keyPrefix, metadataEvaluator, reduxProps, onChange) { @@ -9,7 +7,7 @@ export default { propertyMetadata.key = keyPrefix; // set redux properties - if(_.has(reduxProps, propertyMetadata.name)) { + if(reduxProps && reduxProps.hasOwnProperty(propertyMetadata.name)) { propertyMetadata.reduxFormProps = reduxProps[propertyMetadata.name]; } diff --git a/src/metadata/evaluator/filter/entityMetadataFilter.js b/src/metadata/evaluator/filter/entityMetadataFilter.js index 7e04536..33fa558 100644 --- a/src/metadata/evaluator/filter/entityMetadataFilter.js +++ b/src/metadata/evaluator/filter/entityMetadataFilter.js @@ -1,5 +1,3 @@ -import _ from 'underscore'; - export default { filter: function(propertyMetadata, model, keyPrefix, metadataEvaluator, reduxProps, onChange) { if(!propertyMetadata) { @@ -13,7 +11,7 @@ export default { throw Error('when metadata is of type entity, it must have a fields property'); } - if(!_.has(model, propertyMetadata.name) || model[propertyMetadata.name] === null || model[propertyMetadata.name] === undefined) { + if(model && !model.hasOwnProperty(propertyMetadata.name) || model[propertyMetadata.name] === null || model[propertyMetadata.name] === undefined) { // if the property does not exist, create it model[propertyMetadata.name] = {}; } else { diff --git a/src/metadata/evaluator/metadataEvaluator.js b/src/metadata/evaluator/metadataEvaluator.js index fcb1633..7cd3ac9 100644 --- a/src/metadata/evaluator/metadataEvaluator.js +++ b/src/metadata/evaluator/metadataEvaluator.js @@ -5,7 +5,6 @@ import arrayMetadataFilter from './filter/arrayMetadataFilter.js'; // property filters import defaultPropertyMetadataFilter from './property-filter/defaultMetadataPropertyFilter.js'; -import _ from 'underscore'; class MetadataEvaluator { @@ -33,7 +32,7 @@ class MetadataEvaluator { if (propertyMetadata.constructor === Array) return propertyMetadata.map(i => this.evaluate(i, model, keyPrefix, reduxFieldProps, onChange)); let result = {}; - _.each(_.keys(propertyMetadata), (fieldName) => { + Object.keys(propertyMetadata).forEach((fieldName) => { result[fieldName] = this.filterPropertyField(fieldName, propertyMetadata[fieldName], model); }); let newPrefix = keyPrefix ? `${keyPrefix}.${propertyMetadata.name}` : propertyMetadata.name; diff --git a/src/metadata/model/modelParser.js b/src/metadata/model/modelParser.js index 21f6f85..043ca4e 100644 --- a/src/metadata/model/modelParser.js +++ b/src/metadata/model/modelParser.js @@ -1,5 +1,3 @@ -import _ from 'underscore'; - import dateTimeParser from './parsers/dateTimeParser'; import numberParser from './parsers/numberParser'; import entityParser from './parsers/entityParser'; @@ -23,7 +21,7 @@ class ModelProcessor { let result = {}; - _.each(propertyMetadata, (eachPropertyMetadata) => { + propertyMetadata.forEach((eachPropertyMetadata) => { result[eachPropertyMetadata.name] = this.processProperty(eachPropertyMetadata, model); }); @@ -38,7 +36,7 @@ class ModelProcessor { if (!types) throw Error('\'type\' should be truthy'); if (!(types instanceof Array)) throw Error('type should be an array'); - _.each(types, type => { + types.forEach(type => { this.parsers[type] = parser; }); } diff --git a/src/metadata/validator/metadataValidator.js b/src/metadata/validator/metadataValidator.js index 6e7d32b..ff1201f 100644 --- a/src/metadata/validator/metadataValidator.js +++ b/src/metadata/validator/metadataValidator.js @@ -1,4 +1,3 @@ -import _ from 'underscore'; import defaultValidator from './validators/defaultMetadataValidator'; import arrayValidator from './validators/arrayValidator'; import entityValidator from './validators/entityValidator'; @@ -21,7 +20,7 @@ var validator = { if (propertyMetadata.constructor !== Array) throw Error('ApropertyMetadata should be an array'); let validationResult = {}; - _.each(propertyMetadata, m => { + propertyMetadata.forEach(m => { let propertyValidation; for(let i = 0; i < this.validators.length; i++) { let validate = this.validators[i];