1
0
Fork 0
mirror of synced 2024-09-10 14:35:47 +12:00

Use patch for all component methods, add core component patch function, add component move functions to store

This commit is contained in:
Andrew Kingston 2022-07-15 08:22:06 +01:00
parent 5cdd37f6d8
commit 587b385a47
3 changed files with 131 additions and 98 deletions

View file

@ -11,7 +11,6 @@ import {
import { API } from "api" import { API } from "api"
import analytics, { Events } from "analytics" import analytics, { Events } from "analytics"
import { import {
findComponentType,
findComponentParent, findComponentParent,
findClosestMatchingComponent, findClosestMatchingComponent,
findAllMatchingComponents, findAllMatchingComponents,
@ -62,7 +61,21 @@ const INITIAL_FRONTEND_STATE = {
export const getFrontendStore = () => { export const getFrontendStore = () => {
const store = writable({ ...INITIAL_FRONTEND_STATE }) const store = writable({ ...INITIAL_FRONTEND_STATE })
store.subscribe(state => { const sequentialScreenPatch = Utils.sequential(async (patchFn, screenId) => {
const state = get(store)
const screen = state.screens.find(screen => screen._id === screenId)
if (!screen) {
return
}
let clone = cloneDeep(screen)
const result = patchFn(clone)
if (result === false) {
return
}
return await store.actions.screens.save(clone)
})
store.subscribe(() => {
console.log("new state") console.log("new state")
}) })
@ -228,19 +241,17 @@ export const getFrontendStore = () => {
}) })
return savedScreen return savedScreen
}, },
patch: Utils.sequential(async (screenId, patchFn) => { patch: async (patchFn, screenId) => {
const state = get(store) // Default to the currently selected screen
const screen = state.screens.find(screen => screen._id === screenId) if (!screenId) {
if (!screen) { const state = get(store)
screenId = state.selectedScreenId
}
if (!screenId || !patchFn) {
return return
} }
let clone = cloneDeep(screen) return await sequentialScreenPatch(patchFn, screenId)
const result = patchFn(clone) },
if (result === false) {
return
}
return await store.actions.screens.save(clone)
}),
delete: async screens => { delete: async screens => {
const screensToDelete = Array.isArray(screens) ? screens : [screens] const screensToDelete = Array.isArray(screens) ? screens : [screens]
@ -282,7 +293,9 @@ export const getFrontendStore = () => {
}) })
}, },
updateHomeScreen: async (screen, makeHomeScreen = true) => { updateHomeScreen: async (screen, makeHomeScreen = true) => {
let promises = [] if (!screen) {
return
}
// Find any existing home screen for this role so we can remove it, // Find any existing home screen for this role so we can remove it,
// if we are setting this to be the new home screen // if we are setting this to be the new home screen
@ -297,16 +310,13 @@ export const getFrontendStore = () => {
}) })
if (existingHomeScreen) { if (existingHomeScreen) {
const patch = screen => (screen.routing.homeScreen = false) const patch = screen => (screen.routing.homeScreen = false)
promises.push( await store.actions.screens.patch(patch, existingHomeScreen._id)
store.actions.screens.patch(existingHomeScreen._id, patch)
)
} }
} }
// Update the passed in screen // Update the passed in screen
const patch = screen => (screen.routing.homeScreen = makeHomeScreen) const patch = screen => (screen.routing.homeScreen = makeHomeScreen)
promises.push(store.actions.screens.patch(screen._id, patch)) await store.actions.screens.patch(patch, screen._id)
return await Promise.all(promises)
}, },
removeCustomLayout: async screen => { removeCustomLayout: async screen => {
// Pull relevant settings from old layout, if required // Pull relevant settings from old layout, if required
@ -316,14 +326,10 @@ export const getFrontendStore = () => {
screen.showNavigation = layout?.props.navigation !== "None" screen.showNavigation = layout?.props.navigation !== "None"
screen.width = layout?.props.width || "Large" screen.width = layout?.props.width || "Large"
} }
await store.actions.screens.patch(screen._id, patch) await store.actions.screens.patch(patch, screen._id)
}, },
}, },
preview: { preview: {
saveSelected: async () => {
const selectedAsset = get(currentAsset)
return await store.actions.screens.save(selectedAsset)
},
setDevice: device => { setDevice: device => {
store.update(state => { store.update(state => {
state.previewDevice = device state.previewDevice = device
@ -431,8 +437,8 @@ export const getFrontendStore = () => {
return return
} }
// Patch screen // Patch selected screen
const patch = screen => { await store.actions.screens.patch(screen => {
// Find the selected component // Find the selected component
const currentComponent = findComponent( const currentComponent = findComponent(
screen.props, screen.props,
@ -472,8 +478,7 @@ export const getFrontendStore = () => {
parentComponent._children = [] parentComponent._children = []
} }
parentComponent._children.push(componentInstance) parentComponent._children.push(componentInstance)
} })
await store.actions.screens.patch(state.selectedScreenId, patch)
// Select new component // Select new component
store.update(state => { store.update(state => {
@ -488,15 +493,34 @@ export const getFrontendStore = () => {
return componentInstance return componentInstance
}, },
patch: async (patchFn, componentId, screenId) => {
// Use selected component by default
if (!componentId && !screenId) {
const state = get(store)
componentId = state.selectedComponentId
screenId = state.selectedScreenId
}
// Invalid if only a screen or component ID provided
if (!componentId || !screenId || !patchFn) {
return
}
const patchScreen = screen => {
let component = findComponent(screen.props, componentId)
if (!component) {
return false
}
return patchFn(component, screen)
}
await store.actions.screens.patch(patchScreen, screenId)
},
delete: async component => { delete: async component => {
if (!component) { if (!component) {
return return
} }
const state = get(store)
let parentId let parentId
// Patch screen // Patch screen
const patch = screen => { await store.actions.screens.patch(screen => {
// Check component exists // Check component exists
component = findComponent(screen.props, component._id) component = findComponent(screen.props, component._id)
if (!component) { if (!component) {
@ -512,8 +536,7 @@ export const getFrontendStore = () => {
parent._children = parent._children.filter( parent._children = parent._children.filter(
child => child._id !== component._id child => child._id !== component._id
) )
} })
await store.actions.screens.patch(state.selectedScreenId, patch)
// Select the deleted component's parent // Select the deleted component's parent
store.update(state => { store.update(state => {
@ -522,11 +545,6 @@ export const getFrontendStore = () => {
}) })
}, },
copy: (component, cut = false, selectParent = true) => { copy: (component, cut = false, selectParent = true) => {
const selectedAsset = get(currentAsset)
if (!selectedAsset) {
return null
}
// Update store with copied component // Update store with copied component
store.update(state => { store.update(state => {
state.componentToPaste = cloneDeep(component) state.componentToPaste = cloneDeep(component)
@ -536,7 +554,8 @@ export const getFrontendStore = () => {
// Select the parent if cutting // Select the parent if cutting
if (cut) { if (cut) {
const parent = findComponentParent(selectedAsset.props, component._id) const screen = get(selectedScreen)
const parent = findComponentParent(screen?.props, component._id)
if (parent) { if (parent) {
if (selectParent) { if (selectParent) {
store.update(state => { store.update(state => {
@ -555,7 +574,7 @@ export const getFrontendStore = () => {
let newComponentId let newComponentId
// Patch screen // Patch screen
const patch = screen => { await store.actions.screens.patch(screen => {
// Get up to date ref to target // Get up to date ref to target
targetComponent = findComponent(screen.props, targetComponent._id) targetComponent = findComponent(screen.props, targetComponent._id)
if (!targetComponent) { if (!targetComponent) {
@ -604,8 +623,7 @@ export const getFrontendStore = () => {
const index = mode === "above" ? targetIndex : targetIndex + 1 const index = mode === "above" ? targetIndex : targetIndex + 1
parent._children.splice(index, 0, componentToPaste) parent._children.splice(index, 0, componentToPaste)
} }
} })
await store.actions.screens.patch(state.selectedScreenId, patch)
// Update state // Update state
store.update(state => { store.update(state => {
@ -614,39 +632,78 @@ export const getFrontendStore = () => {
return state return state
}) })
}, },
moveUp: async component => {
await store.actions.screens.patch(screen => {
const componentId = component?._id
const parent = findComponentParent(screen.props, componentId)
if (!parent?._children?.length) {
return false
}
const currentIndex = parent._children.findIndex(
child => child._id === componentId
)
if (currentIndex === 0) {
return false
}
const originalComponent = cloneDeep(parent._children[currentIndex])
const newChildren = parent._children.filter(
component => component._id !== componentId
)
newChildren.splice(currentIndex - 1, 0, originalComponent)
parent._children = newChildren
})
},
moveDown: async component => {
await store.actions.screens.patch(screen => {
const componentId = component?._id
const parent = findComponentParent(screen.props, componentId)
if (!parent?._children?.length) {
return false
}
const currentIndex = parent._children.findIndex(
child => child._id === componentId
)
if (currentIndex === parent._children.length - 1) {
return false
}
const originalComponent = cloneDeep(parent._children[currentIndex])
const newChildren = parent._children.filter(
component => component._id !== componentId
)
newChildren.splice(currentIndex + 1, 0, originalComponent)
parent._children = newChildren
})
},
updateStyle: async (name, value) => { updateStyle: async (name, value) => {
const selected = get(selectedComponent) await store.actions.components.patch(component => {
if (value == null || value === "") { if (value == null || value === "") {
delete selected._styles.normal[name] delete component._styles.normal[name]
} else { } else {
selected._styles.normal[name] = value component._styles.normal[name] = value
} }
await store.actions.preview.saveSelected() })
}, },
updateCustomStyle: async style => { updateCustomStyle: async style => {
const selected = get(selectedComponent) await store.actions.components.patch(component => {
selected._styles.custom = style component._styles.custom = style
await store.actions.preview.saveSelected() })
}, },
updateConditions: async conditions => { updateConditions: async conditions => {
const selected = get(selectedComponent) await store.actions.components.patch(component => {
selected._conditions = conditions component._conditions = conditions
await store.actions.preview.saveSelected() })
}, },
updateProp: async (name, value) => { updateProp: async (name, value) => {
let component = get(selectedComponent) await store.actions.components.patch(component => {
if (!name || !component) { if (!name || !component) {
return return false
} }
if (component[name] === value) { // Skip update if the value is the same
return if (component[name] === value) {
} return false
component[name] = value }
store.update(state => { component[name] = value
state.selectedComponentId = component._id
return state
}) })
await store.actions.preview.saveSelected()
}, },
}, },
links: { links: {

View file

@ -19,43 +19,19 @@
// not show a context menu. // not show a context menu.
$: showMenu = definition?.editable !== false && definition?.static !== true $: showMenu = definition?.editable !== false && definition?.static !== true
const moveUpComponent = () => { const moveUpComponent = async () => {
const asset = get(currentAsset)
const parent = findComponentParent(asset?.props, component._id)
if (!parent) {
return
}
const currentIndex = parent._children.indexOf(component)
if (currentIndex === 0) {
return
}
try { try {
const newChildren = parent._children.filter(c => c !== component) await store.actions.components.moveUp(component)
newChildren.splice(currentIndex - 1, 0, component)
parent._children = newChildren
store.actions.preview.saveSelected()
} catch (error) { } catch (error) {
notifications.error("Error saving screen") notifications.error("Error moving component up")
} }
} }
const moveDownComponent = () => { const moveDownComponent = async () => {
const asset = get(currentAsset)
const parent = findComponentParent(asset?.props, component._id)
if (!parent) {
return
}
const currentIndex = parent._children.indexOf(component)
if (currentIndex === parent._children.length - 1) {
return
}
try { try {
const newChildren = parent._children.filter(c => c !== component) await store.actions.components.moveDown(component)
newChildren.splice(currentIndex + 1, 0, component)
parent._children = newChildren
store.actions.preview.saveSelected()
} catch (error) { } catch (error) {
notifications.error("Error saving screen") notifications.error("Error moving component down")
} }
} }

View file

@ -29,13 +29,13 @@
] ]
} }
const updateProp = Utils.sequential(async (key, value) => { const updateProp = async (key, value) => {
try { try {
await store.actions.components.updateProp(key, value) await store.actions.components.updateProp(key, value)
} catch (error) { } catch (error) {
notifications.error("Error updating component prop") notifications.error("Error updating component prop")
} }
}) }
const canRenderControl = setting => { const canRenderControl = setting => {
const control = getComponentForSetting(setting) const control = getComponentForSetting(setting)