diff --git a/packages/builder/src/builderStore/store/index.js b/packages/builder/src/builderStore/store/index.js index fbb7fdfebf..3c1ef7ad05 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 getNewComponentName from "../getNewComponentName" 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 } @@ -291,9 +293,14 @@ const addChildComponent = store => (componentToAdd, presetProps = {}) => { state ) - state.currentComponentInfo._children = state.currentComponentInfo._children.concat( - newComponent.props - ) + const currentComponent = + state.components[state.currentComponentInfo._component] + + const targetParent = currentComponent.children + ? state.currentComponentInfo + : getParent(state.currentPreviewItem.props, state.currentComponentInfo) + + targetParent._children = targetParent._children.concat(newComponent.props) state.currentFrontEndType === "page" ? _savePage(state) @@ -454,3 +461,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, s) + } + 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..b88bda17b2 100644 --- a/packages/builder/src/builderStore/storeUtils.js +++ b/packages/builder/src/builderStore/storeUtils.js @@ -1,6 +1,8 @@ import { makePropsSafe } from "components/userInterface/pagesParsing/createProps" import api from "./api" import { generate_screen_css } from "./generate_css" +import { uuid } from "./uuid" +import getNewComponentName from "./getNewComponentName" export const selectComponent = (state, component) => { const componentDef = component._component.startsWith("##") @@ -79,3 +81,9 @@ export const regenerateCssForCurrentScreen = state => { ]) return state } + +export const generateNewIdsForComponent = (c, state) => + walkProps(c, p => { + p._id = uuid() + p._instanceName = getNewComponentName(p._component, state) + }) diff --git a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte index c7efd29253..180ce154a3 100644 --- a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte +++ b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte @@ -99,7 +99,7 @@ {#each headers as header} - + {#if schema[header].type === 'link'} {:else}{row[header] || ''}{/if} @@ -168,6 +168,9 @@ max-width: 200px; text-overflow: ellipsis; border: 1px solid var(--grey-4); + overflow: hidden; + white-space: pre; + box-sizing: border-box; } tbody tr { @@ -187,6 +190,7 @@ .popovers { display: flex; + gap: var(--spacing-m); } .no-data { diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditColumn.svelte index 77a6db9d39..3c125260ea 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditColumn.svelte @@ -124,8 +124,14 @@ } .field { - margin-top: var(--spacing-xl); - margin-bottom: var(--spacing-xl); + display: grid; + grid-template-columns: auto 20px 1fr; + align-items: center; + grid-gap: 5px; + font-size: 14px; + font-weight: 500; + margin-bottom: var(--spacing-l); + font-family: var(--font-normal); } .button-margin-3 { diff --git a/packages/builder/src/components/database/ModelDataTable/modals/RecordFieldControl.svelte b/packages/builder/src/components/database/ModelDataTable/modals/RecordFieldControl.svelte index 02d6616f87..ecc79b2ba0 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/RecordFieldControl.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/RecordFieldControl.svelte @@ -31,6 +31,9 @@ {/each} {:else} + {#if type === 'checkbox'} + + {/if} {/if} + + diff --git a/packages/builder/src/components/nav/ModelNavigator/CreateTable.svelte b/packages/builder/src/components/nav/ModelNavigator/CreateTable.svelte index 6125b0851b..9763ade62e 100644 --- a/packages/builder/src/components/nav/ModelNavigator/CreateTable.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/CreateTable.svelte @@ -45,8 +45,7 @@ diff --git a/packages/standard-components/src/CardHorizontal.svelte b/packages/standard-components/src/CardHorizontal.svelte new file mode 100644 index 0000000000..86dc6437ec --- /dev/null +++ b/packages/standard-components/src/CardHorizontal.svelte @@ -0,0 +1,104 @@ + + +
+ {#if showImage} + + {/if} +
+
+

{heading}

+

{description}

+
+ +
+
+ + diff --git a/packages/standard-components/src/index.js b/packages/standard-components/src/index.js index 071ffa1bcf..598f372988 100644 --- a/packages/standard-components/src/index.js +++ b/packages/standard-components/src/index.js @@ -23,5 +23,7 @@ export { default as list } from "./List.svelte" export { default as datasearch } from "./DataSearch.svelte" export { default as embed } from "./Embed.svelte" export { default as stackedlist } from "./StackedList.svelte" +export { default as card } from "./Card.svelte" +export { default as cardhorizontal } from "./CardHorizontal.svelte" export { default as recorddetail } from "./RecordDetail.svelte" export * from "./Chart"