react-planner
Version:
react-planner is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
217 lines (189 loc) • 7.21 kB
JavaScript
import {
PropertyColor,
PropertyEnum,
PropertyString,
PropertyNumber,
PropertyLengthMeasure,
PropertyToggle,
PropertyCheckbox,
PropertyHidden,
PropertyReadOnly
} from './properties/export';
import {UNIT_CENTIMETER} from '../constants';
export default class Catalog {
constructor(unit = UNIT_CENTIMETER) {
this.elements = {};
this.categories = {root: {name: 'root', label: '/', elements: [], categories: []}};
this.propertyTypes = {};
this.unit = unit;
this.registerMultiplePropertyType([
['color', PropertyColor, PropertyColor],
['enum', PropertyEnum, PropertyEnum],
['string', PropertyString, PropertyString],
['number', PropertyNumber, PropertyNumber],
['length-measure', PropertyLengthMeasure, PropertyLengthMeasure],
['toggle', PropertyToggle, PropertyToggle],
['checkbox', PropertyCheckbox, PropertyCheckbox],
['hidden', PropertyHidden, PropertyHidden],
['read-only', PropertyReadOnly, PropertyReadOnly]
]);
}
/** @description Get catalog's element
* @param {string} type Element's type
* @return {?object} Element
*/
getElement(type) {
if (this.hasElement(type)) {
return this.elements[type];
}
throw new Error(`Element ${type} does not exist in catalog`);
}
/** @description Get catalog category
* @param {string} categoryName Name of category
* @return {object} Category
*/
getCategory(categoryName) {
if (this.hasCategory(categoryName)) {
return this.categories[categoryName];
}
throw new Error(`Category ${categoryName} does not exist in catalog`);
}
/** @description Return type of a specfied property
* @param {string} type Property type
* @return {?object} Property
*/
getPropertyType(type) {
if (this.propertyTypes.hasOwnProperty(type)) {
return this.propertyTypes[type];
}
throw new Error(`Element ${type} does not exist in catalog`);
}
/** @description Register a new element
* @param {object} json Element structure
* @return {void}
*/
registerElement(json) {
json.properties = json.properties || {};
if (this.validateElement(json)) {
this.elements[json.name] = json;
this.categories.root.elements.push(this.elements[json.name]);
}
}
/** @description Register multiple elements
* @param {array} [elementArray] Array of elements
* @return {void}
*/
registerMultipleElements(elementArray) {
elementArray.forEach(el => this.registerElement(el));
}
/** @description Register a new property
* @param {string} type Type of property
* @param {object} Viewer Property viewer component
* @param {object} Editor Property editor component
* @return {void}
*/
registerPropertyType(type, Viewer, Editor) {
this.propertyTypes[type] = {type, Viewer, Editor};
}
/** @description Register multiple property
* @param {array} propertyTypeArray Array of properties
* @return {void}
*/
registerMultiplePropertyType(propertyTypeArray) {
propertyTypeArray.forEach(el => this.registerPropertyType(...el));
}
/** @description Validate an element
* @param {object} json Element's structure
* @return {?boolean}
*/
validateElement(json) {
if (!json.hasOwnProperty('name')) throw new Error('Element not valid');
let name = json.name;
if (!json.hasOwnProperty('prototype')) throw new Error(`Element ${name} doesn't have prototype`);
if (!json.hasOwnProperty('info')) throw new Error(`Element ${name} doesn't have info`);
if (!json.info.hasOwnProperty('tag')) throw new Error(`Element ${name} doesn't have tag`);
if (!json.info.hasOwnProperty('description')) throw new Error(`Element ${name} doesn't have description`);
if (!json.info.hasOwnProperty('image')) throw new Error(`Element ${name} doesn't have image`);
if (!json.hasOwnProperty('render2D')) throw new Error(`Element ${name} doesn't have render2D handler`);
if (!json.hasOwnProperty('render3D')) throw new Error(`Element ${name} doesn't have render3D handler`);
if (!json.hasOwnProperty('properties')) throw new Error(`Element ${name} doesn't have properties`);
for (let propertyName in json.properties) {
let propertyConfigs = json.properties[propertyName];
if (!propertyConfigs.hasOwnProperty('type')) throw new Error(`Element ${name}, Property ${propertyName} doesn't have type`);
if (!propertyConfigs.hasOwnProperty('defaultValue')) throw new Error(`Element ${name}, Property ${propertyName} doesn't have defaultValue`);
}
return true;
}
/** @description Check if catalog has element
* @param {string} type Element's type
* @return {boolean}
*/
hasElement(type) {
return this.elements.hasOwnProperty(type);
}
/** @description Register a new category
* @param {string} name Name of category
* @param {string} label Label of category
* @param {array} [childs] Category's childs
* @return {?object} Registered category
*/
registerCategory(name, label, childs) {
if (this.validateCategory(name, label)) {
this.categories[name] = {name, label, categories: [], elements: []};
this.categories.root.categories.push(this.categories[name]);
if(childs && childs.length) {
childs.forEach( el => this.addToCategory( name, el ) );
}
return this.categories[name];
}
return null;
}
/** @description Add an element to the specified category
* @param {string} name Name of category
* @param {object} child Element's structure
* @return {?void}
*/
addToCategory(name, child) {
if (this.hasElement(child.name)) {
this.categories[name].elements.push(child);
this.categories.root.elements.splice(this.categories.root.elements.indexOf(child), 1);
} else if (this.hasCategory(child.name)) {
this.categories[name].categories.push(child);
this.categories.root.categories.splice(this.categories.root.categories.indexOf(child), 1);
} else {
throw new Error(`child ${child} is either category nor element`);
}
}
/** @description Check if category contain element
* @param {string} categoryName Name of category
* @param {string} elementName Name of element
* @return {boolean}
*/
categoryHasElement(categoryName, elementName) {
return this.hasCategory(categoryName) && this.categories[categoryName].elements.some(el => el.name === elementName);
}
/** @description Validate a category
* @param {string} name Name of category
* @param {string} label Label of category
* @return {?boolean}
*/
validateCategory(name, label) {
if (!name) {
throw new Error('Category has undefined name');
}
if (name === '') {
throw new Error('Category has empty name');
}
if (this.hasCategory(name)) {
throw new Error('Category has already been registered');
}
return true;
}
/** @description Verify if catalog already contain a category with specified name
* @param {string} categoryName Name of category
* @return {boolean}
*/
hasCategory(categoryName) {
return this.categories.hasOwnProperty(categoryName);
}
}