Skip to content

Commit

Permalink
Standardised field definition validation for ContentEditor and Struct…
Browse files Browse the repository at this point in the history
…Editor
  • Loading branch information
mrzapp committed Mar 8, 2019
1 parent 0afd259 commit d7ea584
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 122 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "hashbrown-cms",
"repository": "https://github.com/HashBrownCMS/hashbrown-cms.git",
"version": "1.1.1",
"version": "1.1.2",
"description": "A free and open-source headless CMS",
"main": "hashbrown.js",
"scripts": {
Expand Down
52 changes: 44 additions & 8 deletions public/js/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -22750,33 +22750,69 @@ function (_ContentHelperCommon) {
return Promise.resolve(content);
});
}
/**
* A check for field definitions
*
* @param {Object} definition
*
* @return {Boolean} Whether or not the definition is empty
*/

}, {
key: "isFieldDefinitionEmpty",
value: function isFieldDefinitionEmpty(definition) {
if (!definition) {
return true;
}

var isEmpty = true;

var checkRecursive = function checkRecursive(object) {
if (!object) {
return;
} // We consider a definition not empty, if it has a value that is not an object
// Remember, null is of type 'object' too


if (_typeof(object) !== 'object') {
return isEmpty = false;
}

for (var k in object) {
checkRecursive(object[k]);
}
};

checkRecursive(definition);
return isEmpty;
}
/**
* A sanity check for fields
*
* @param {Object} value
* @param {Schema} schema
* @param {Object} definition
*/

}, {
key: "fieldSanityCheck",
value: function fieldSanityCheck(value, schema) {
// If the schema value is set to multilingual, but the value isn't an object, convert it
if (schema.multilingual && (!value || _typeof(value) !== 'object')) {
value: function fieldSanityCheck(value, definition) {
// If the definition value is set to multilingual, but the value isn't an object, convert it
if (definition.multilingual && (!value || _typeof(value) !== 'object')) {
var oldValue = value;
value = {};
value[window.language] = oldValue;
} // If the schema value is not set to multilingual, but the value is an object
} // If the definition value is not set to multilingual, but the value is an object
// containing the _multilingual flag, convert it


if (!schema.multilingual && value && _typeof(value) === 'object' && value._multilingual) {
if (!definition.multilingual && value && _typeof(value) === 'object' && value._multilingual) {
value = value[window.language];
} // Update the _multilingual flag


if (schema.multilingual && value && !value._multilingual) {
if (definition.multilingual && value && !value._multilingual) {
value._multilingual = true;
} else if (!schema.multilingual && value && value._multilingual) {
} else if (!definition.multilingual && value && value._multilingual) {
delete value._multilingual;
}

Expand Down
2 changes: 1 addition & 1 deletion public/js/helpers.js.map

Large diffs are not rendered by default.

86 changes: 34 additions & 52 deletions public/js/views.js
Original file line number Diff line number Diff line change
Expand Up @@ -2900,42 +2900,13 @@ function (_Crisp$View) {
} // Get the config


var config; // If the field has a config, check recursively if it's empty
// If it isn't, use this config
var config;

if (fieldDefinition.config) {
var isEmpty = true;

var checkRecursive = function checkRecursive(object) {
if (!object) {
return;
} // We consider a config not empty, if it has a value that is not an object
// Remember, null is of type 'object' too


if (_typeof(object) !== 'object') {
return isEmpty = false;
}

for (var k in object) {
checkRecursive(object[k]);
}
};

checkRecursive(fieldDefinition.config);

if (!isEmpty) {
config = fieldDefinition.config;
}
} // If no config was found, and the Schema has one, use it


if (!config && compiledSchema.config) {
if (!HashBrown.Helpers.ContentHelper.isFieldDefinitionEmpty(fieldDefinition.config)) {
config = fieldDefinition.config;
} else if (!HashBrown.Helpers.ContentHelper.isFieldDefinitionEmpty(compiledSchema.config)) {
config = compiledSchema.config;
} // If still no config was found, assign a placeholder


if (!config) {
} else {
config = {};
} // Instantiate the field editor

Expand Down Expand Up @@ -15766,15 +15737,15 @@ function (_HashBrown$Views$Edit) {
*
* @param {Object} newValue
* @param {String} key
* @param {Object} keyConfig
* @param {Object} fieldDefinition
* @param {Boolean} isSilent
*/


_createClass(StructEditor, [{
key: "onChange",
value: function onChange(newValue, key, keyConfig, isSilent) {
if (keyConfig.multilingual) {
value: function onChange(newValue, key, fieldDefinition, isSilent) {
if (fieldDefinition.multilingual) {
// Sanity check to make sure multilingual fields are accomodated for
if (!this.value[key] || _typeof(this.value[key]) !== 'object') {
this.value[key] = {};
Expand Down Expand Up @@ -15810,17 +15781,17 @@ function (_HashBrown$Views$Edit) {
return _.div({
class: 'field-editor field-editor--struct'
}, // Loop through each key in the struct
_.each(this.config.struct || compiledSchema.config.struct, function (keyName, keyConfig) {
var value = _this2.value[keyName];
_.each(this.config.struct || compiledSchema.config.struct, function (fieldName, fieldDefinition) {
var value = _this2.value[fieldName];

if (!keyConfig || !keyConfig.schemaId) {
throw new Error('Schema id not set for key "' + keyName + '"');
if (!fieldDefinition || !fieldDefinition.schemaId) {
throw new Error('Schema id not set for key "' + fieldName + '"');
}

var fieldSchema = HashBrown.Helpers.SchemaHelper.getFieldSchemaWithParentConfigs(keyConfig.schemaId);
var fieldSchema = HashBrown.Helpers.SchemaHelper.getFieldSchemaWithParentConfigs(fieldDefinition.schemaId);

if (!fieldSchema) {
throw new Error('FieldSchema "' + keyConfig.schemaId + '" could not be found for key "' + keyName + '"');
throw new Error('FieldSchema "' + fieldDefinition.schemaId + '" could not be found for key "' + fieldName + '"');
}

var fieldEditor = HashBrown.Views.Editors.ContentEditor.getFieldEditor(fieldSchema.editorId);
Expand All @@ -15830,22 +15801,33 @@ function (_HashBrown$Views$Edit) {
} // Sanity check


value = HashBrown.Helpers.ContentHelper.fieldSanityCheck(value, keyConfig);
_this2.value[keyName] = value; // Init the field editor
value = HashBrown.Helpers.ContentHelper.fieldSanityCheck(value, fieldDefinition);
_this2.value[fieldName] = value; // Get the config

var config;

if (!HashBrown.Helpers.ContentHelper.isFieldDefinitionEmpty(fieldDefinition.config)) {
config = fieldDefinition.config;
} else if (!HashBrown.Helpers.ContentHelper.isFieldDefinitionEmpty(fieldSchema.config)) {
config = fieldSchema.config;
} else {
config = {};
} // Init the field editor


var fieldEditorInstance = new fieldEditor({
value: keyConfig.multilingual ? value[window.language] : value,
disabled: keyConfig.disabled || false,
config: keyConfig.config || fieldSchema.config || {},
value: fieldDefinition.multilingual ? value[window.language] : value,
disabled: fieldDefinition.disabled || false,
config: config,
schema: fieldSchema,
className: 'editor__field__value'
}); // Hook up the change event

fieldEditorInstance.on('change', function (newValue) {
_this2.onChange(newValue, keyName, keyConfig);
_this2.onChange(newValue, fieldName, fieldDefinition);
});
fieldEditorInstance.on('silentchange', function (newValue) {
_this2.onChange(newValue, keyName, keyConfig, true);
_this2.onChange(newValue, fieldName, fieldDefinition, true);
}); // Return the DOM element

return _.div({
Expand All @@ -15854,9 +15836,9 @@ function (_HashBrown$Views$Edit) {
class: 'editor__field__key'
}, _.div({
class: 'editor__field__key__label'
}, keyConfig.label), _.if(keyConfig.description, _.div({
}, fieldDefinition.label), _.if(fieldDefinition.description, _.div({
class: 'editor__field__key__description'
}, keyConfig.description)), fieldEditorInstance.renderKeyActions()), fieldEditorInstance.$element);
}, fieldDefinition.description)), fieldEditorInstance.renderKeyActions()), fieldEditorInstance.$element);
}));
}
}], [{
Expand Down
2 changes: 1 addition & 1 deletion public/js/views.js.map

Large diffs are not rendered by default.

44 changes: 36 additions & 8 deletions src/Client/Helpers/ContentHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,32 +59,60 @@ class ContentHelper extends ContentHelperCommon {
});
}

/**
* A check for field definitions
*
* @param {Object} definition
*
* @return {Boolean} Whether or not the definition is empty
*/
static isFieldDefinitionEmpty(definition) {
if(!definition) { return true; }

let isEmpty = true;
let checkRecursive = (object) => {
if(!object) { return; }

// We consider a definition not empty, if it has a value that is not an object
// Remember, null is of type 'object' too
if(typeof object !== 'object') { return isEmpty = false; }

for(let k in object) {
checkRecursive(object[k]);
}
};

checkRecursive(definition);

return isEmpty;
}

/**
* A sanity check for fields
*
* @param {Object} value
* @param {Schema} schema
* @param {Object} definition
*/
static fieldSanityCheck(value, schema) {
// If the schema value is set to multilingual, but the value isn't an object, convert it
if(schema.multilingual && (!value || typeof value !== 'object')) {
static fieldSanityCheck(value, definition) {
// If the definition value is set to multilingual, but the value isn't an object, convert it
if(definition.multilingual && (!value || typeof value !== 'object')) {
let oldValue = value;

value = {};
value[window.language] = oldValue;
}

// If the schema value is not set to multilingual, but the value is an object
// If the definition value is not set to multilingual, but the value is an object
// containing the _multilingual flag, convert it
if(!schema.multilingual && value && typeof value === 'object' && value._multilingual) {
if(!definition.multilingual && value && typeof value === 'object' && value._multilingual) {
value = value[window.language];
}

// Update the _multilingual flag
if(schema.multilingual && value && !value._multilingual) {
if(definition.multilingual && value && !value._multilingual) {
value._multilingual = true;

} else if(!schema.multilingual && value && value._multilingual) {
} else if(!definition.multilingual && value && value._multilingual) {
delete value._multilingual;

}
Expand Down
35 changes: 5 additions & 30 deletions src/Client/Views/Editors/ContentEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,39 +222,14 @@ class ContentEditor extends Crisp.View {
// Get the config
let config;

// If the field has a config, check recursively if it's empty
// If it isn't, use this config
if(fieldDefinition.config) {
let isEmpty = true;
let checkRecursive = (object) => {
if(!object) { return; }

// We consider a config not empty, if it has a value that is not an object
// Remember, null is of type 'object' too
if(typeof object !== 'object') { return isEmpty = false; }

for(let k in object) {
checkRecursive(object[k]);
}
};

checkRecursive(fieldDefinition.config);

if(!isEmpty) {
config = fieldDefinition.config;
}
}

// If no config was found, and the Schema has one, use it
if(!config && compiledSchema.config) {
if(!HashBrown.Helpers.ContentHelper.isFieldDefinitionEmpty(fieldDefinition.config)) {
config = fieldDefinition.config;
} else if(!HashBrown.Helpers.ContentHelper.isFieldDefinitionEmpty(compiledSchema.config)) {
config = compiledSchema.config;
}

// If still no config was found, assign a placeholder
if(!config) {
} else {
config = {};
}

// Instantiate the field editor
let fieldEditorInstance = new fieldEditor({
value: fieldValue,
Expand Down
Loading

0 comments on commit d7ea584

Please sign in to comment.