UNPKG

@gmetrixr/rjson

Version:
245 lines (244 loc) 11.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ElementUtils = exports.ElementFactory = void 0; const elements_1 = require("../definitions/elements"); const ElementDefinition_1 = require("../definitions/elements/ElementDefinition"); const RecordFactory_1 = require("../R/RecordFactory"); const RecordNode_1 = require("../R/RecordNode"); const RecordTypes_1 = require("../R/RecordTypes"); const definitions_1 = require("../definitions"); const gdash_1 = require("@gmetrixr/gdash"); const { generateId } = gdash_1.jsUtils; const deepClone = gdash_1.jsUtils.deepClone; class ElementFactory extends RecordFactory_1.RecordFactory { constructor(json) { super(json); const element_type = json.props.element_type; if (element_type !== undefined && (0, ElementDefinition_1.isElementType)(element_type)) { this.elementType = element_type; } else { throw Error(`The type ${element_type} of this ElementJson isn't a known ElementType`); } } /** * ISSUE : We were facing issue when we copy element from root to group, id for that element was duplicated and that was causing an issue. Below id fix for that * this function will add record with new element id to prevent duplicate issue. */ pasteFromClipboardObject({ obj, position }) { if (obj.parentType !== this._type) { console.error(`Can't paste this object into a RecordNode of type of ${this._type}`); return []; } const addedRecords = []; for (const rn of obj.nodes) { // * if position is passed, then keep incrementing to insert in order, else add at the end of the list rn.id = generateId(); // * generate new ids if required for child elements. ex: group children new ElementFactory(rn).dedupeChildElementIds(); const addedRecord = super.addRecord(rn, position ? position++ : position); if (addedRecord !== undefined) { addedRecords.push(addedRecord); } } return addedRecords; } /** * Regenerate new element_id for all children recursively */ dedupeChildElementIds() { if (this.elementType === definitions_1.en.ElementType.group) { // change ids of all children const children = this.getRecords(RecordTypes_1.RT.element); for (const c of children) { this.changeRecordId(RecordTypes_1.RT.element, c.id); if (c.props.element_type === definitions_1.en.ElementType.group) { new ElementFactory(c).dedupeChildElementIds(); } } } } getElementType() { return this.elementType; } set(property, value) { super.set(property, value); if (property === RecordTypes_1.rtp.element.element_type && (typeof value === "string") && (0, ElementDefinition_1.isElementType)(value)) { this.elementType = value; } return this; } /** * Returns the default value of a property. If no default is found, returns undefined * This is already defined in RecordFactory and is being overridden in ElementFactory */ getDefault(property) { var _a, _b; const elementDefaultValues = (_b = (_a = elements_1.eTypeToDefn[this.elementType]) === null || _a === void 0 ? void 0 : _a.defaultOverrides) !== null && _b !== void 0 ? _b : {}; if (elementDefaultValues[property] !== undefined) return deepClone(elementDefaultValues[property]); const defaultValues = RecordTypes_1.recordTypeDefinitions[RecordTypes_1.RT.element].defaultValues; if (defaultValues[property] !== undefined) return deepClone(defaultValues[property]); } //ELEMENT RELATED FUNCTIONS /** * Used by the right bar to list down properties */ getJsonPropsAndDefaultProps() { const jsonProps = this.getProps(); const elementProps = ElementUtils.getElementDefinition(this.elementType).properties; return Array.from(new Set(jsonProps.concat(elementProps))); } //FILE RELATED FUNCTIONS /** * Gets all file ids from an element structure * file ids are stored in properties of type "source" * Properties of type "source" are generally in properties ending with "source" (Eg: "background_source") * sources */ getFileIdsFromElement() { const fileIds = []; const elementProps = this.getJsonPropsAndDefaultProps(); //Get file ids form element properties for (const sourceProp of definitions_1.en.sourcePropertyNames.elementProperties) { //Iterating over sourceElementProperties instead of elementProps to reduce number of iterations if (elementProps.includes(sourceProp)) { fileIds.push(...ElementUtils.getFileIdsFromValue(this.get(sourceProp))); } } //Get file ids form element array properties for (const sourceProp of definitions_1.en.sourcePropertyNames.elementArrayProperties) { if (elementProps.includes(sourceProp)) { fileIds.push(...ElementUtils.getFileIdsFromElementArrayPropertyValue(this.get(sourceProp))); } } //Get file ids from item properties for (const sourceProp of definitions_1.en.sourcePropertyNames.itemProperties) { for (const item of this.getRecords(RecordTypes_1.RT.item)) { const itemProps = Object.keys(item.props); if (itemProps.includes(sourceProp)) { //Not checking for image_source, as it isn't used in items fileIds.push(...ElementUtils.getFileIdsFromValue(item.props[sourceProp])); } } } //return _.uniq(fileIds); Unique not needed here, done at project level return fileIds; } /** * Inject the given sources into the element */ injectSourceIntoElement(sourceMap) { const elementProps = this.getJsonPropsAndDefaultProps(); //Get file ids form element properties for (const sourceProp of definitions_1.en.sourcePropertyNames.elementProperties) { //Iterating over sourceElementProperties instead of elementProps to reduce number of iterations if (elementProps.includes(sourceProp)) { const currentValue = this.get(sourceProp); const newValue = ElementUtils.getNewSourceValue(currentValue, sourceMap); if (newValue !== undefined) { this.set(sourceProp, deepClone(newValue)); } } } for (const sourceProp of definitions_1.en.sourcePropertyNames.elementArrayProperties) { if (elementProps.includes(sourceProp)) { const currentValue = this.get(sourceProp); const newValue = ElementUtils.getNewSourceValueArray(currentValue, sourceMap); if (newValue !== undefined && newValue.length !== 0) { this.set(sourceProp, deepClone(newValue)); } } } //Get file ids from item properties for (const sourceProp of definitions_1.en.sourcePropertyNames.itemProperties) { for (const item of this.getRecords(RecordTypes_1.RT.item)) { const itemProps = Object.keys(item.props); if (itemProps.includes(sourceProp)) { //Not checking for image_source, as it isn't used in items const currentValue = item.props[sourceProp]; const newValue = ElementUtils.getNewSourceValue(currentValue, sourceMap); if (newValue !== undefined) { item.props[sourceProp] = deepClone(newValue); } } } } } addElementOfType(elementType, position) { const defaultName = ElementUtils.getElementDefinition(elementType).elementDefaultName; const newElement = (0, RecordNode_1.createRecord)(RecordTypes_1.RT.element, undefined, defaultName); newElement.props = ElementUtils.getElementTypeDefaults(elementType); newElement.props.element_type = elementType; this.addRecord(newElement, position); return newElement; } } exports.ElementFactory = ElementFactory; class ElementUtils { } exports.ElementUtils = ElementUtils; /** * Get the element definition of a specific element_type * ElementDefinition can be used to get element_type, properties, propertyDefaults, events, actions * * In case its an unknown element_type, returns BasicElement's Definition */ ElementUtils.getElementDefinition = (elementType) => { const defn = elements_1.eTypeToDefn[elementType]; if (defn !== undefined) { return defn; } else { return ElementDefinition_1.BasicElement; } }; /** Get a list of all defaults for the given elementType */ ElementUtils.getElementTypeDefaults = (elementType) => { var _a, _b, _c, _d; const allElementDefaults = RecordTypes_1.recordTypeDefinitions[RecordTypes_1.RT.element].defaultValues; const elementOverrides = (_b = (_a = elements_1.eTypeToDefn[elementType]) === null || _a === void 0 ? void 0 : _a.defaultOverrides) !== null && _b !== void 0 ? _b : {}; const props = (_d = (_c = elements_1.eTypeToDefn[elementType]) === null || _c === void 0 ? void 0 : _c.properties) !== null && _d !== void 0 ? _d : []; const defaultValues = {}; for (const prop of props) { let value = elementOverrides[prop]; if (value === undefined) value = allElementDefaults[prop]; defaultValues[prop] = value; } return defaultValues; }; /** * Given a property of type Array<Source>, takes file id out of it in an array and returns it */ ElementUtils.getFileIdsFromElementArrayPropertyValue = (value) => { const imageSources = value; return imageSources.map(source => source === null || source === void 0 ? void 0 : source.id).filter(s => s); // filter out undefined and null values }; /** * Given a property value (of type source), takes file id out of it and returns it as an array */ ElementUtils.getFileIdsFromValue = (value) => { const source = value; if ((source === null || source === void 0 ? void 0 : source.id) !== undefined) { //Because we don't want to return default source paths which don't have ids return [source === null || source === void 0 ? void 0 : source.id]; } else { return []; } }; /** * Given a property value and sourceMap, returns a new value with the replaced sources * Can return undefined or a Source or a Source[], depending on the propertyName * The multiple returns type don't matter, because the logic of the calling function doesn't care about return type */ ElementUtils.getNewSourceValueArray = (value, sourceMap) => { const originalSources = value; return originalSources.map(source => sourceMap[source === null || source === void 0 ? void 0 : source.id]); }; ElementUtils.getNewSourceValue = (value, sourceMap) => { const source = value; if ((source === null || source === void 0 ? void 0 : source.id) !== undefined && sourceMap[source === null || source === void 0 ? void 0 : source.id] !== undefined) { //Because we don't want to return default source paths which don't have ids return sourceMap[source === null || source === void 0 ? void 0 : source.id]; } else { return undefined; } };