diff --git a/packages/builder/src/builderStore/store/index.js b/packages/builder/src/builderStore/store/index.js
index 5b78ea0979..3894725ead 100644
--- a/packages/builder/src/builderStore/store/index.js
+++ b/packages/builder/src/builderStore/store/index.js
@@ -1,4 +1,4 @@
-import { values } from "lodash/fp"
+import { values, cloneDeep } from "lodash/fp"
import { get_capitalised_name } from "../../helpers"
import { backendUiStore } from "builderStore"
import * as backendStoreActions from "./backend"
@@ -24,8 +24,8 @@ import {
saveCurrentPreviewItem as _saveCurrentPreviewItem,
saveScreenApi as _saveScreenApi,
regenerateCssForCurrentScreen,
+ generateNewIdsForComponent,
} from "../storeUtils"
-
export const getStore = () => {
const initial = {
apps: [],
@@ -70,6 +70,8 @@ export const getStore = () => {
store.addTemplatedComponent = addTemplatedComponent(store)
store.setMetadataProp = setMetadataProp(store)
store.editPageOrScreen = editPageOrScreen(store)
+ store.pasteComponent = pasteComponent(store)
+ store.storeComponentForCopy = storeComponentForCopy(store)
return store
}
@@ -454,3 +456,50 @@ const setMetadataProp = store => (name, prop) => {
return s
})
}
+
+const storeComponentForCopy = store => (component, cut = false) => {
+ store.update(s => {
+ const copiedComponent = cloneDeep(component)
+ s.componentToPaste = copiedComponent
+ s.componentToPaste.isCut = cut
+ if (cut) {
+ const parent = getParent(s.currentPreviewItem.props, component._id)
+ parent._children = parent._children.filter(c => c._id !== component._id)
+ selectComponent(s, parent)
+ }
+
+ return s
+ })
+}
+
+const pasteComponent = store => (targetComponent, mode) => {
+ store.update(s => {
+ if (!s.componentToPaste) return s
+
+ const componentToPaste = cloneDeep(s.componentToPaste)
+ // retain the same ids as things may be referencing this component
+ if (componentToPaste.isCut) {
+ // in case we paste a second time
+ s.componentToPaste.isCut = false
+ } else {
+ generateNewIdsForComponent(componentToPaste)
+ }
+ delete componentToPaste.isCut
+
+ if (mode === "inside") {
+ targetComponent._children.push(componentToPaste)
+ return s
+ }
+
+ const parent = getParent(s.currentPreviewItem.props, targetComponent)
+
+ const targetIndex = parent._children.indexOf(targetComponent)
+ const index = mode === "above" ? targetIndex : targetIndex + 1
+ parent._children.splice(index, 0, cloneDeep(componentToPaste))
+ regenerateCssForCurrentScreen(s)
+ _saveCurrentPreviewItem(s)
+ selectComponent(s, componentToPaste)
+
+ return s
+ })
+}
diff --git a/packages/builder/src/builderStore/storeUtils.js b/packages/builder/src/builderStore/storeUtils.js
index 63fd7ecd00..1630d118e0 100644
--- a/packages/builder/src/builderStore/storeUtils.js
+++ b/packages/builder/src/builderStore/storeUtils.js
@@ -1,6 +1,7 @@
import { makePropsSafe } from "components/userInterface/pagesParsing/createProps"
import api from "./api"
import { generate_screen_css } from "./generate_css"
+import { uuid } from "./uuid"
export const selectComponent = (state, component) => {
const componentDef = component._component.startsWith("##")
@@ -79,3 +80,8 @@ export const regenerateCssForCurrentScreen = state => {
])
return state
}
+
+export const generateNewIdsForComponent = c =>
+ walkProps(c, p => {
+ p._id = uuid()
+ })
diff --git a/packages/builder/src/components/userInterface/ComponentDropdownMenu.svelte b/packages/builder/src/components/userInterface/ComponentDropdownMenu.svelte
index 28dd59c16f..23e28a7b48 100644
--- a/packages/builder/src/components/userInterface/ComponentDropdownMenu.svelte
+++ b/packages/builder/src/components/userInterface/ComponentDropdownMenu.svelte
@@ -28,8 +28,7 @@
})
$: dropdown && UIkit.util.on(dropdown, "shown", () => (hidden = false))
$: noChildrenAllowed =
- !component ||
- getComponentDefinition($store, component._component).children === false
+ !component || !getComponentDefinition($store, component._component).children
$: noPaste = !$store.componentToPaste
const lastPartOfName = c => (c ? last(c._component.split("/")) : "")
@@ -105,49 +104,14 @@
})
}
- const generateNewIdsForComponent = c =>
- walkProps(c, p => {
- p._id = uuid()
- })
-
const storeComponentForCopy = (cut = false) => {
- store.update(s => {
- const copiedComponent = cloneDeep(component)
- s.componentToPaste = copiedComponent
- if (cut) {
- const parent = getParent(s.currentPreviewItem.props, component._id)
- parent._children = parent._children.filter(c => c._id !== component._id)
- selectComponent(s, parent)
- }
-
- return s
- })
+ // lives in store - also used by drag drop
+ store.storeComponentForCopy(component, cut)
}
const pasteComponent = mode => {
- store.update(s => {
- if (!s.componentToPaste) return s
-
- const componentToPaste = cloneDeep(s.componentToPaste)
- generateNewIdsForComponent(componentToPaste)
- delete componentToPaste._cutId
-
- if (mode === "inside") {
- component._children.push(componentToPaste)
- return s
- }
-
- const parent = getParent(s.currentPreviewItem.props, component)
-
- const targetIndex = parent._children.indexOf(component)
- const index = mode === "above" ? targetIndex : targetIndex + 1
- parent._children.splice(index, 0, cloneDeep(componentToPaste))
- regenerateCssForCurrentScreen(s)
- saveCurrentPreviewItem(s)
- selectComponent(s, componentToPaste)
-
- return s
- })
+ // lives in store - also used by drag drop
+ store.pasteComponent(component, mode)
}
diff --git a/packages/builder/src/components/userInterface/ComponentsHierarchy.svelte b/packages/builder/src/components/userInterface/ComponentsHierarchy.svelte
index b25d7a4e7b..db4ea2fc27 100644
--- a/packages/builder/src/components/userInterface/ComponentsHierarchy.svelte
+++ b/packages/builder/src/components/userInterface/ComponentsHierarchy.svelte
@@ -7,6 +7,7 @@
import { store } from "builderStore"
import { ArrowDownIcon, ShapeIcon } from "components/common/Icons/"
import ScreenDropdownMenu from "./ScreenDropdownMenu.svelte"
+ import { writable } from "svelte/store"
export let screens = []
@@ -16,12 +17,15 @@
const joinPath = join("/")
const normalizedName = name =>
- pipe(name, [
- trimCharsStart("./"),
- trimCharsStart("~/"),
- trimCharsStart("../"),
- trimChars(" "),
- ])
+ pipe(
+ name,
+ [
+ trimCharsStart("./"),
+ trimCharsStart("~/"),
+ trimCharsStart("../"),
+ trimChars(" "),
+ ]
+ )
const changeScreen = screen => {
store.setCurrentScreen(screen.props._instanceName)
@@ -57,7 +61,8 @@
{#if $store.currentPreviewItem.props._instanceName && $store.currentPreviewItem.props._instanceName === screen.props._instanceName && screen.props._children}