Skip to content

Commit

Permalink
fix: migrate meta.id to config.controlId for smaller payloads
Browse files Browse the repository at this point in the history
add descriptions to json schema
  • Loading branch information
kevinchappell committed Nov 19, 2024
1 parent f6ad0a2 commit 47d1bc5
Show file tree
Hide file tree
Showing 12 changed files with 273 additions and 184 deletions.
6 changes: 2 additions & 4 deletions src/demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,8 @@
<span id="formeo-logo-wrap"></span>
</header>
<section id="main_content" class="inner">
<form class="build-form clearfix"></form>
<div class="render-form">
<h2>Rendered Form</h2>
</div>
<form class="build-form"></form>
<div class="render-form"></div>
</section>
<div class="container render-btn-wrap" id="editor-action-buttons">
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/lib/js/components/autocomplete.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ export const labelCount = (arr, label) => {
* @return {String} component label
*/
const getComponentLabel = ({ name, id, ...component }) => {
const labelPaths = ['config.label', 'attrs.id', 'meta.id']
const labelPaths = ['config.label', 'config.controlId', 'meta.id', 'attrs.id']
const label = labelPaths.reduce((acc, cur) => {
if (!acc) {
acc = component.get(cur)
return component.get(cur)
}
return acc
}, null)
Expand Down
31 changes: 25 additions & 6 deletions src/lib/js/components/component-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,30 @@ import { uuid, clone, merge } from '../common/utils/index.mjs'
import { get } from '../common/utils/object.mjs'

export default class ComponentData extends Data {
load = (data = Object.create(null)) => {
load = dataArg => {
const data = this.parseformData(dataArg)
this.empty()
if (typeof data === 'string') {
data = JSON.parse(data)
for (const [key, val] of Object.entries(data)) {
this.add(key, val)
}
Object.entries(data).forEach(([key, val]) => this.add(key, val))
return this.data
}

/**
* Retrieves data from the specified path or adds new data if no path is provided.
*
* @param {string} [path] - The path to retrieve data from. If not provided, new data will be added.
* @returns {*} The data retrieved from the specified path or the result of adding new data.
*/
get = path => (path ? get(this.data, path) : this.add())

/**
* Adds a new component with the given id and data.
*
* @param {string} id - The unique identifier for the component. If not provided, a new UUID will be generated.
* @param {Object} [data=Object.create(null)] - The data to initialize the component with.
* @returns {Object} The newly created component.
*/
add = (id, data = Object.create(null)) => {
const elemId = id || uuid()
const component = this.Component({ ...data, id: elemId })
Expand All @@ -29,16 +42,22 @@ export default class ComponentData extends Data {
*/
remove = componentId => {
if (Array.isArray(componentId)) {
componentId.forEach(id => {
for (const id of componentId) {
this.get(id).remove()
})
}
} else {
this.get(componentId).remove()
}

return this.data
}

/**
* Deletes a component from the data object.
*
* @param {string} componentId - The ID of the component to delete.
* @returns {string} The ID of the deleted component.
*/
delete = componentId => {
delete this.data[componentId]
return componentId
Expand Down
32 changes: 25 additions & 7 deletions src/lib/js/components/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Components from './index.js'
import Data from './data.js'
import animate from '../common/animation.js'
import Controls from './controls/index.js'
import { get } from '../common/utils/object.mjs'
import { get, set } from '../common/utils/object.mjs'
import { toTitleCase } from '../common/utils/string.mjs'

export default class Component extends Data {
Expand Down Expand Up @@ -355,6 +355,7 @@ export default class Component extends Data {

/**
* Method for handling onAdd for all components
* @todo improve readability of this method
* @param {Object} evt
* @return {Object} Component
*/
Expand Down Expand Up @@ -397,10 +398,14 @@ export default class Component extends Data {

const onAddConditions = {
controls: () => {
const { controlData } = Controls.get(item.id)
const {
meta: { id: metaId },
} = controlData
controlData: {
meta: { id: metaId },
...elementData
},
} = Controls.get(item.id)

set(elementData, 'config.controlId', metaId)

const controlType = metaId.startsWith('layout-') ? metaId.replace(/^layout-/, '') : 'field'
const targets = {
Expand All @@ -424,7 +429,7 @@ export default class Component extends Data {
const depth = get(targets, `${this.name}.${controlType}`)
const action = depthMap.get(depth)()
dom.remove(item)
const component = action(controlData, newIndex)
const component = action(elementData, newIndex)

return component
},
Expand Down Expand Up @@ -501,10 +506,23 @@ export default class Component extends Data {
events.onRender && dom.onRender(this.dom, events.onRender)
}

/**
* Sets the configuration for the component. See src/demo/js/options/config.js for example
* @param {Object} config - Configuration object with possible structures:
* @param {Object} [config.all] - Global configuration applied to all components
* @param {Object} [config[controlId]] - Configuration specific to a control type
* @param {Object} [config[id]] - Configuration specific to a component instance
* @description Merges configurations in order of precedence:
* 1. Existing config (this.configVal)
* 2. Global config (all)
* 3. Control type specific config
* 4. Instance specific config
* The merged result is stored in this.configVal
*/
set config(config) {
const metaId = get(this.data, 'meta.id')
const allConfig = get(config, 'all')
const typeConfig = metaId && get(config, metaId)
const controlId = get(this.data, 'config.controlId')
const typeConfig = controlId && get(config, controlId)
const idConfig = get(config, this.id)
const mergedConfig = [allConfig, typeConfig, idConfig].reduce(
(acc, cur) => (cur ? merge(acc, cur) : acc),
Expand Down
31 changes: 18 additions & 13 deletions src/lib/js/components/controls/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import layoutControls from './layout/index.js'
import formControls from './form/index.js'
import htmlControls from './html/index.js'
import defaultOptions from './options.js'
import { get } from '../../common/utils/object.mjs'
import { get, set } from '../../common/utils/object.mjs'

const defaultElements = [...formControls, ...htmlControls, ...layoutControls]

Expand Down Expand Up @@ -126,17 +126,17 @@ export class Controls {
*/
groupConfig.content = elements.filter(control => {
const { controlData: field } = this.get(control.id)
const fieldId = field.meta.id || ''
const controlId = field.meta.id || ''
const filters = [
match(fieldId, this.options.disable.elements),
match(controlId, this.options.disable.elements),
field.meta.group === group.id,
!usedElementIds.includes(field.meta.id),
!usedElementIds.includes(controlId),
]

let shouldFilter = true
shouldFilter = filters.every(val => val === true)
if (shouldFilter) {
usedElementIds.push(fieldId)
usedElementIds.push(controlId)
}

return shouldFilter
Expand Down Expand Up @@ -349,24 +349,29 @@ export class Controls {
return element
}

layoutTypes = {
row: () => Stages.active.addChild(),
column: () => this.layoutTypes.row().addChild(),
field: controlData => this.layoutTypes.column().addChild(controlData),
}

/**
* Append an element to the stage
* @param {String} id of elements
*/
addElement = id => {
const controlData = get(this.get(id), 'controlData')

const {
meta: { group, id: metaId },
} = controlData
...elementData
} = get(this.get(id), 'controlData')

set(elementData, 'config.controlId', metaId)

const layoutTypes = {
row: () => Stages.active.addChild(),
column: () => layoutTypes.row().addChild(),
field: controlData => layoutTypes.column().addChild(controlData),
if (group === 'layout') {
return this.layoutTypes[metaId.replace('layout-', '')]()
}

return group !== 'layout' ? layoutTypes.field(controlData) : layoutTypes[metaId.replace('layout-', '')]()
return this.layoutTypes.field(elementData)
}

applyOptions = async (controlOptions = {}) => {
Expand Down
21 changes: 21 additions & 0 deletions src/lib/js/components/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,25 @@ export default class Data {
}
setCallbacks = {}
configVal = Object.create(null)

/**
* Parses the provided data argument. If the argument is a string, it attempts to parse it as JSON.
* If the parsing fails, it logs an error and returns an empty object.
* If the argument is not a string, it returns the argument as is.
*
* @param {string|Object} dataArg - The data to be parsed. Can be a JSON string or an object.
* @returns {Object} - The parsed object or the original object if the input was not a string.
*/
parseformData = (dataArg = Object.create(null)) => {
if (typeof dataArg === 'string') {
try {
return JSON.parse(dataArg)
} catch (e) {
console.error('Invalid JSON string provided:', e)
return Object.create(null)
}
}

return dataArg
}
}
11 changes: 6 additions & 5 deletions src/lib/js/components/fields/edit-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ export default class EditPanel {
* @param {String} attr
* @param {String|Array} val
*/
addAttribute = (attr, val) => {
addAttribute = (attr, valArg) => {
let val = valArg
const safeAttr = slugify(attr)
const itemKey = `attrs.${safeAttr}`

Expand Down Expand Up @@ -157,16 +158,16 @@ export default class EditPanel {
* Add option to options panel
*/
addOption = () => {
const metaId = this.field.data.meta.id
const controlId = this.field.data.config.controlId
const fieldOptionData = this.field.get('options')
const type = metaId === 'select' ? 'option' : metaId
const type = controlId === 'select' ? 'option' : controlId
const newOptionLabel = i18n.get('newOptionLabel', { type }) || 'New Option'
const itemKey = `options.${this.data.length}`

const lastOptionData = fieldOptionData[fieldOptionData.length - 1]
const optionTemplate = fieldOptionData.length ? lastOptionData : {}
const itemData = { ...optionTemplate, label: newOptionLabel }
if (metaId !== 'button') {
if (controlId !== 'button') {
itemData.value = slugify(newOptionLabel)
}
const newOption = new EditPanelItem({
Expand Down
4 changes: 2 additions & 2 deletions src/lib/js/components/fields/field.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export default class Field extends Component {
const hideLabel = !!this.get('config.hideLabel')

if (hideLabel) {
return
return null
}

const labelVal = this.get('config.editorLabel') || this.get('config.label')
Expand Down Expand Up @@ -308,7 +308,7 @@ export default class Field extends Component {
*/
fieldPreview() {
const prevData = clone(this.data)
const { action = {} } = controls.get(prevData.meta.id)
const { action = {} } = controls.get(prevData.config.controlId)
prevData.id = `prev-${this.id}`
prevData.action = action

Expand Down
19 changes: 18 additions & 1 deletion src/lib/js/components/fields/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ComponentData from '../component-data.js'
import Field from './field.js'
import Controls from '../controls/index.js'
import { get } from '../../common/utils/object.mjs'
import { get, set } from '../../common/utils/object.mjs'

const DEFAULT_CONFIG = {
actionButtons: {
Expand Down Expand Up @@ -60,6 +60,23 @@ export class Fields extends ComponentData {
return acc
}, {})
}

load = (dataArg = Object.create(null)) => {
const allFieldData = this.parseformData(dataArg)
this.empty()

for (const [key, val] of Object.entries(allFieldData)) {
const { meta, ...data } = val
// meta object is only for controls, we want to migrate it out of field data
// we only need the control id to tie actions back to control definitons
if (meta?.id) {
set(data, 'config.controlId', meta?.id)
}
this.add(key, data)
}

return this.data
}
}

const fields = new Fields()
Expand Down
Loading

0 comments on commit 47d1bc5

Please sign in to comment.