From 7548b48f9e2f1400be692b7675490f195c757bb2 Mon Sep 17 00:00:00 2001 From: Gerard Burns Date: Mon, 22 Jul 2024 09:27:44 +0100 Subject: [PATCH] Allow Opening Certain Context Menus With Right Click (#14169) * Allow Opening NavItem Context Menus With Right Click * dean pr feedback * PR Feedback 1 * Fix pasting into a component issue * Remove animation * Move ContextMenu Into Routify Router Scope --- packages/bbui/src/Icon/Icon.svelte | 1 + .../builder/src/components/ContextMenu.svelte | 62 +++++++++ .../AutomationPanel/AutomationList.svelte | 48 ------- .../AutomationPanel/AutomationNavItem.svelte | 123 +++++++++++++++++ .../AutomationPanel/AutomationPanel.svelte | 27 +--- .../EditAutomationPopover.svelte | 73 ---------- .../DatasourceNavItem.svelte | 82 +++++++++++ .../DeleteConfirmationModal.svelte} | 29 +--- .../DatasourceNavigator.svelte | 53 +------ .../DatasourceNavigator/QueryNavItem.svelte | 103 ++++++++++++++ .../popovers/EditQueryPopover.svelte | 59 -------- .../DeleteConfirmationModal.svelte} | 85 +----------- .../TableNavItem/EditModal.svelte | 58 ++++++++ .../TableNavItem/TableNavItem.svelte | 68 +++++++++ .../TableNavigator/TableNavigator.svelte | 50 ++----- .../DeleteConfirmationModal.svelte | 34 +++++ .../ViewNavItem/EditViewModal.svelte | 45 ++++++ .../ViewNavItem/ViewNavItem.svelte | 71 ++++++++++ .../popovers/EditViewPopover.svelte | 78 ----------- .../src/components/common/NavItem.svelte | 1 + .../start/AppContextMenuModals.svelte | 56 ++++++++ .../src/components/start/AppRow.svelte | 53 ++++--- .../src/components/start/AppRowContext.svelte | 108 --------------- .../start/getAppContextMenuItems.js | 44 ++++++ .../builder/src/pages/builder/_layout.svelte | 2 + .../ComponentDropdownMenu.svelte | 129 ------------------ .../ComponentList/ComponentTree.svelte | 28 +++- .../ScreenslotDropdownMenu.svelte | 57 -------- .../getComponentContextMenuItems.js | 123 +++++++++++++++++ .../getScreenContextMenuItems.js | 40 ++++++ .../_components/ComponentList/index.svelte | 52 ++++++- ...opdownMenu.svelte => ScreenNavItem.svelte} | 119 ++++++++++------ .../_components/ScreenList/index.svelte | 32 +---- .../builder/portal/apps/[appId]/index.svelte | 37 ++++- .../portal/apps/_components/AppNavItem.svelte | 91 ++++++++++++ .../apps/_components/PortalSideBar.svelte | 48 +------ .../builder/src/stores/builder/contextMenu.js | 28 ++++ packages/builder/src/stores/builder/index.js | 2 + 38 files changed, 1287 insertions(+), 912 deletions(-) create mode 100644 packages/builder/src/components/ContextMenu.svelte delete mode 100644 packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte create mode 100644 packages/builder/src/components/automation/AutomationPanel/AutomationNavItem.svelte delete mode 100644 packages/builder/src/components/automation/AutomationPanel/EditAutomationPopover.svelte create mode 100644 packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavItem/DatasourceNavItem.svelte rename packages/builder/src/components/backend/DatasourceNavigator/{popovers/EditDatasourcePopover.svelte => DatasourceNavItem/DeleteConfirmationModal.svelte} (50%) create mode 100644 packages/builder/src/components/backend/DatasourceNavigator/QueryNavItem.svelte delete mode 100644 packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte rename packages/builder/src/components/backend/TableNavigator/{popovers/EditTablePopover.svelte => TableNavItem/DeleteConfirmationModal.svelte} (54%) create mode 100644 packages/builder/src/components/backend/TableNavigator/TableNavItem/EditModal.svelte create mode 100644 packages/builder/src/components/backend/TableNavigator/TableNavItem/TableNavItem.svelte create mode 100644 packages/builder/src/components/backend/TableNavigator/ViewNavItem/DeleteConfirmationModal.svelte create mode 100644 packages/builder/src/components/backend/TableNavigator/ViewNavItem/EditViewModal.svelte create mode 100644 packages/builder/src/components/backend/TableNavigator/ViewNavItem/ViewNavItem.svelte delete mode 100644 packages/builder/src/components/backend/TableNavigator/popovers/EditViewPopover.svelte create mode 100644 packages/builder/src/components/start/AppContextMenuModals.svelte delete mode 100644 packages/builder/src/components/start/AppRowContext.svelte create mode 100644 packages/builder/src/components/start/getAppContextMenuItems.js delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentDropdownMenu.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ScreenslotDropdownMenu.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/getComponentContextMenuItems.js create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/getScreenContextMenuItems.js rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/{DropdownMenu.svelte => ScreenNavItem.svelte} (55%) create mode 100644 packages/builder/src/pages/builder/portal/apps/_components/AppNavItem.svelte create mode 100644 packages/builder/src/stores/builder/contextMenu.js diff --git a/packages/bbui/src/Icon/Icon.svelte b/packages/bbui/src/Icon/Icon.svelte index e293bd408b..6ae1f4ca67 100644 --- a/packages/bbui/src/Icon/Icon.svelte +++ b/packages/bbui/src/Icon/Icon.svelte @@ -29,6 +29,7 @@ >
+ import { contextMenuStore } from "stores/builder" + import { Popover, Menu, MenuItem } from "@budibase/bbui" + + let dropdown + let anchor + + const handleKeyDown = () => { + if ($contextMenuStore.visible) { + contextMenuStore.close() + } + } + + const handleItemClick = async itemCallback => { + await itemCallback() + contextMenuStore.close() + } + + + +{#key $contextMenuStore.position} +
+{/key} + + + + {#each $contextMenuStore.items as item} + {#if item.visible} + handleItemClick(item.callback)} + disabled={item.disabled} + > + {item.name} + + {/if} + {/each} + + + + diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte deleted file mode 100644 index 9d946fe55d..0000000000 --- a/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte +++ /dev/null @@ -1,48 +0,0 @@ - - -
- {#each $automationStore.automations.sort(aut => aut.name) as automation} - selectAutomation(automation._id)} - selectedBy={$userSelectedResourceMap[automation._id]} - > - - - {/each} -
- - diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationNavItem.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationNavItem.svelte new file mode 100644 index 0000000000..31f86f5d78 --- /dev/null +++ b/packages/builder/src/components/automation/AutomationPanel/AutomationNavItem.svelte @@ -0,0 +1,123 @@ + + + automationStore.actions.select(automation._id)} + selectedBy={$userSelectedResourceMap[automation._id]} + disabled={automation.disabled} +> +
+ +
+
+ + + Are you sure you wish to delete the automation + {automation.name}? + This action cannot be undone. + + + + diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte index b5fe6d03fd..c3ef3157bd 100644 --- a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte +++ b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte @@ -3,20 +3,13 @@ import { Modal, notifications, Layout } from "@budibase/bbui" import NavHeader from "components/common/NavHeader.svelte" import { onMount } from "svelte" - import { - automationStore, - selectedAutomation, - userSelectedResourceMap, - } from "stores/builder" - import NavItem from "components/common/NavItem.svelte" - import EditAutomationPopover from "./EditAutomationPopover.svelte" + import { automationStore } from "stores/builder" + import AutomationNavItem from "./AutomationNavItem.svelte" export let modal export let webhookModal let searchString - $: selectedAutomationId = $selectedAutomation?._id - $: filteredAutomations = $automationStore.automations .filter(automation => { return ( @@ -49,10 +42,6 @@ notifications.error("Error getting automations list") } }) - - function selectAutomation(id) { - automationStore.actions.select(id) - } {#each triggerGroup.entries as automation} - selectAutomation(automation._id)} - selectedBy={$userSelectedResourceMap[automation._id]} - disabled={automation.disabled} - > - - + {/each}
{/each} diff --git a/packages/builder/src/components/automation/AutomationPanel/EditAutomationPopover.svelte b/packages/builder/src/components/automation/AutomationPanel/EditAutomationPopover.svelte deleted file mode 100644 index 9465374ae2..0000000000 --- a/packages/builder/src/components/automation/AutomationPanel/EditAutomationPopover.svelte +++ /dev/null @@ -1,73 +0,0 @@ - - - -
- -
- Duplicate - Edit - - {automation.disabled ? "Activate" : "Pause"} - - Delete -
- - - Are you sure you wish to delete the automation - {automation.name}? - This action cannot be undone. - - - - diff --git a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavItem/DatasourceNavItem.svelte b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavItem/DatasourceNavItem.svelte new file mode 100644 index 0000000000..1ba32838ab --- /dev/null +++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavItem/DatasourceNavItem.svelte @@ -0,0 +1,82 @@ + + + +
+ +
+ {#if datasource._id !== BUDIBASE_INTERNAL_DB_ID} + + {/if} +
+ + + + diff --git a/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditDatasourcePopover.svelte b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavItem/DeleteConfirmationModal.svelte similarity index 50% rename from packages/builder/src/components/backend/DatasourceNavigator/popovers/EditDatasourcePopover.svelte rename to packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavItem/DeleteConfirmationModal.svelte index 79efd276f8..13380c2700 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditDatasourcePopover.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavItem/DeleteConfirmationModal.svelte @@ -1,15 +1,16 @@ - -
- -
- {#if datasource.type !== BUDIBASE_DATASOURCE_TYPE} - Edit - {/if} - Delete -
- {datasource.name}? This action cannot be undone. - - - diff --git a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte index 23081c92c4..e0745c15a1 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte @@ -1,7 +1,6 @@ + + goto(`./query/${query._id}`)} + selectedBy={$userSelectedResourceMap[query._id]} +> + + + + + Are you sure you wish to delete this query? This action cannot be undone. + + + diff --git a/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte b/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte deleted file mode 100644 index d77c5cc8c0..0000000000 --- a/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte +++ /dev/null @@ -1,59 +0,0 @@ - - - -
- -
- Delete - Duplicate -
- - - Are you sure you wish to delete this query? This action cannot be undone. - - - diff --git a/packages/builder/src/components/backend/TableNavigator/popovers/EditTablePopover.svelte b/packages/builder/src/components/backend/TableNavigator/TableNavItem/DeleteConfirmationModal.svelte similarity index 54% rename from packages/builder/src/components/backend/TableNavigator/popovers/EditTablePopover.svelte rename to packages/builder/src/components/backend/TableNavigator/TableNavItem/DeleteConfirmationModal.svelte index f2c726c8bf..21a763be08 100644 --- a/packages/builder/src/components/backend/TableNavigator/popovers/EditTablePopover.svelte +++ b/packages/builder/src/components/backend/TableNavigator/TableNavItem/DeleteConfirmationModal.svelte @@ -1,35 +1,15 @@ - -
- -
- {#if !externalTable} - Edit - {/if} - Delete -
- - - -
editTableNameModal.confirm()}> - -
-
-
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentTree.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentTree.svelte index 0219dc304d..997fac6f10 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentTree.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentTree.svelte @@ -1,7 +1,6 @@ @@ -93,6 +106,7 @@ {#each filteredComponents || [] as component, index (component._id)} {@const opened = isOpen(component, openNodes)}
  • openContextMenu(e, component, opened)} on:click|stopPropagation={() => { componentStore.select(component._id) }} @@ -107,7 +121,8 @@ on:dragover={dragover(component, index)} on:iconClick={() => handleIconClick(component._id)} on:drop={onDrop} - hovering={$hoverStore.componentId === component._id} + hovering={$hoverStore.componentId === component._id || + component._id === $contextMenuStore.id} on:mouseenter={() => hover(component._id)} on:mouseleave={() => hover(null)} text={getComponentText(component)} @@ -120,7 +135,12 @@ highlighted={isChildOfSelectedComponent(component)} selectedBy={$userSelectedResourceMap[component._id]} > - + openContextMenu(e, component, opened)} + /> {#if opened} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ScreenslotDropdownMenu.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ScreenslotDropdownMenu.svelte deleted file mode 100644 index ddb1630644..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ScreenslotDropdownMenu.svelte +++ /dev/null @@ -1,57 +0,0 @@ - - -{#if showMenu} - -
    - -
    - storeComponentForCopy(false)} - > - Copy - - pasteComponent("inside")} - disabled={noPaste} - > - Paste - -
    -{/if} - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/getComponentContextMenuItems.js b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/getComponentContextMenuItems.js new file mode 100644 index 0000000000..f2dfb73a68 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/getComponentContextMenuItems.js @@ -0,0 +1,123 @@ +import { get } from "svelte/store" +import { componentStore } from "stores/builder" + +const getContextMenuItems = (component, componentCollapsed) => { + const definition = componentStore.getDefinition(component?._component) + const noPaste = !get(componentStore).componentToPaste + const isBlock = definition?.block === true + const canEject = !(definition?.ejectable === false) + const hasChildren = component?._children?.length + + const keyboardEvent = (key, ctrlKey = false) => { + document.dispatchEvent( + new CustomEvent("component-menu", { + detail: { + key, + ctrlKey, + id: component?._id, + }, + }) + ) + } + + return [ + { + icon: "Delete", + name: "Delete", + keyBind: "!BackAndroid", + visible: true, + disabled: false, + callback: () => keyboardEvent("Delete"), + }, + { + icon: "ChevronUp", + name: "Move up", + keyBind: "Ctrl+!ArrowUp", + visible: true, + disabled: false, + callback: () => keyboardEvent("ArrowUp", true), + }, + { + icon: "ChevronDown", + name: "Move down", + keyBind: "Ctrl+!ArrowDown", + visible: true, + disabled: false, + callback: () => keyboardEvent("ArrowDown", true), + }, + { + icon: "Duplicate", + name: "Duplicate", + keyBind: "Ctrl+D", + visible: true, + disabled: false, + callback: () => keyboardEvent("d", true), + }, + { + icon: "Cut", + name: "Cut", + keyBind: "Ctrl+X", + visible: true, + disabled: false, + callback: () => keyboardEvent("x", true), + }, + { + icon: "Copy", + name: "Copy", + keyBind: "Ctrl+C", + visible: true, + disabled: false, + callback: () => keyboardEvent("c", true), + }, + { + icon: "LayersSendToBack", + name: "Paste", + keyBind: "Ctrl+V", + visible: true, + disabled: noPaste, + callback: () => keyboardEvent("v", true), + }, + { + icon: "Export", + name: "Eject block", + keyBind: "Ctrl+E", + visible: isBlock && canEject, + disabled: false, + callback: () => keyboardEvent("e", true), + }, + { + icon: "TreeExpand", + name: "Expand", + keyBind: "!ArrowRight", + visible: hasChildren, + disabled: !componentCollapsed, + callback: () => keyboardEvent("ArrowRight", false), + }, + { + icon: "TreeExpandAll", + name: "Expand All", + keyBind: "Ctrl+!ArrowRight", + visible: hasChildren, + disabled: !componentCollapsed, + callback: () => keyboardEvent("ArrowRight", true), + }, + { + icon: "TreeCollapse", + name: "Collapse", + keyBind: "!ArrowLeft", + visible: hasChildren, + disabled: componentCollapsed, + callback: () => keyboardEvent("ArrowLeft", false), + }, + { + icon: "TreeCollapseAll", + name: "Collapse All", + keyBind: "Ctrl+!ArrowLeft", + visible: hasChildren, + disabled: componentCollapsed, + callback: () => keyboardEvent("ArrowLeft", true), + }, + ] +} + +export default getContextMenuItems diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/getScreenContextMenuItems.js b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/getScreenContextMenuItems.js new file mode 100644 index 0000000000..25f2e908e6 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/getScreenContextMenuItems.js @@ -0,0 +1,40 @@ +import { get } from "svelte/store" +import { componentStore } from "stores/builder" +import { notifications } from "@budibase/bbui" + +const getContextMenuItems = (component, showCopy) => { + const noPaste = !get(componentStore).componentToPaste + + const storeComponentForCopy = (cut = false) => { + componentStore.copy(component, cut) + } + + const pasteComponent = mode => { + try { + componentStore.paste(component, mode) + } catch (error) { + notifications.error("Error saving component") + } + } + + return [ + { + icon: "Copy", + name: "Copy", + keyBind: "Ctrl+C", + visible: showCopy, + disabled: false, + callback: () => storeComponentForCopy(false), + }, + { + icon: "LayersSendToBack", + name: "Paste", + keyBind: "Ctrl+V", + visible: true, + disabled: noPaste, + callback: () => pasteComponent("inside"), + }, + ] +} + +export default getContextMenuItems diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/index.svelte index 4a6716ebc5..fce8c12800 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/index.svelte @@ -7,14 +7,15 @@ componentStore, userSelectedResourceMap, hoverStore, + contextMenuStore, } from "stores/builder" import NavItem from "components/common/NavItem.svelte" import ComponentTree from "./ComponentTree.svelte" import { dndStore, DropPosition } from "./dndStore.js" - import ScreenslotDropdownMenu from "./ScreenslotDropdownMenu.svelte" import DNDPositionIndicator from "./DNDPositionIndicator.svelte" import ComponentKeyHandler from "./ComponentKeyHandler.svelte" import ComponentScrollWrapper from "./ComponentScrollWrapper.svelte" + import getScreenContextMenuItems from "./getScreenContextMenuItems" let scrolling = false @@ -43,6 +44,32 @@ } const hover = hoverStore.hover + + // showCopy is used to hide the copy button when the user right-clicks the empty + // background of their component tree. Pasting in the empty space makes sense, + // but copying it doesn't + const openScreenContextMenu = (e, showCopy) => { + const screenComponent = $selectedScreen?.props + const definition = componentStore.getDefinition(screenComponent?._component) + // "editable" has been repurposed for inline text editing. + // It remains here for legacy compatibility. + // Future components should define "static": true for indicate they should + // not show a context menu. + if (definition?.editable !== false && definition?.static !== true) { + e.preventDefault() + e.stopPropagation() + + const items = getScreenContextMenuItems(screenComponent, showCopy) + contextMenuStore.open( + `${showCopy ? "background-" : ""}screenComponent._id`, + items, + { + x: e.clientX, + y: e.clientY, + } + ) + } + } @@ -56,8 +83,11 @@
  • -
      -
    • +
        openScreenContextMenu(e, false)} + > +
      • openScreenContextMenu(e, true)}> { componentStore.select(`${$screenStore.selectedScreenId}-screen`) }} - hovering={$hoverStore.componentId === screenComponentId} + hovering={$hoverStore.componentId === screenComponentId || + $selectedScreen?.props._id === $contextMenuStore.id} on:mouseenter={() => hover(screenComponentId)} on:mouseleave={() => hover(null)} id="component-screen" selectedBy={$userSelectedResourceMap[screenComponentId]} > - + openScreenContextMenu(e, $selectedScreen?.props)} + /> +
      • +
      • - import { screenStore, componentStore, navigationStore } from "stores/builder" - import ConfirmDialog from "components/common/ConfirmDialog.svelte" + import { Modal, Helpers, notifications, Icon } from "@budibase/bbui" import { - ActionMenu, - MenuItem, - Icon, - Modal, - Helpers, - notifications, - } from "@budibase/bbui" + navigationStore, + screenStore, + userSelectedResourceMap, + contextMenuStore, + componentStore, + } from "stores/builder" + import NavItem from "components/common/NavItem.svelte" + import RoleIndicator from "./RoleIndicator.svelte" import ScreenDetailsModal from "components/design/ScreenDetailsModal.svelte" import sanitizeUrl from "helpers/sanitizeUrl" import { makeComponentUnique } from "helpers/components" import { capitalise } from "helpers" + import ConfirmDialog from "components/common/ConfirmDialog.svelte" - export let screenId + export let screen let confirmDeleteDialog let screenDetailsModal - $: screen = $screenStore.screens.find(screen => screen._id === screenId) - $: noPaste = !$componentStore.componentToPaste - - const pasteComponent = mode => { - try { - componentStore.paste(screen.props, mode, screen) - } catch (error) { - notifications.error("Error saving component") - } - } - - const duplicateScreen = () => { - screenDetailsModal.show() - } - const createDuplicateScreen = async ({ screenName, screenUrl }) => { // Create a dupe and ensure it is unique let duplicateScreen = Helpers.cloneDeep(screen) @@ -69,22 +55,75 @@ notifications.error("Error deleting screen") } } + + $: noPaste = !$componentStore.componentToPaste + + const pasteComponent = mode => { + try { + componentStore.paste(screen.props, mode, screen) + } catch (error) { + notifications.error("Error saving component") + } + } + + const openContextMenu = (e, screen) => { + e.preventDefault() + e.stopPropagation() + + const items = [ + { + icon: "ShowOneLayer", + name: "Paste inside", + keyBind: null, + visible: true, + disabled: noPaste, + callback: () => pasteComponent("inside"), + }, + { + icon: "Duplicate", + name: "Duplicate", + keyBind: null, + visible: true, + disabled: false, + callback: screenDetailsModal.show, + }, + { + icon: "Delete", + name: "Delete", + keyBind: null, + visible: true, + disabled: false, + callback: confirmDeleteDialog.show, + }, + ] + + contextMenuStore.open(screen._id, items, { x: e.clientX, y: e.clientY }) + } - -
        - + openContextMenu(e, screen)} + scrollable + icon={screen.routing.homeScreen ? "Home" : null} + indentLevel={0} + selected={$screenStore.selectedScreenId === screen._id} + hovering={screen._id === $contextMenuStore.id} + text={screen.routing.route} + on:click={() => screenStore.select(screen._id)} + rightAlignIcon + showTooltip + selectedBy={$userSelectedResourceMap[screen._id]} +> + openContextMenu(e, screen)} + size="S" + hoverable + name="MoreSmallList" + /> +
        +
        - pasteComponent("inside")} - disabled={noPaste} - > - Paste inside - - Duplicate - Delete - +
        .icon { - display: grid; - place-items: center; + margin-left: 4px; + margin-right: 4px; } diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte index 27df661281..5c9da100e4 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte @@ -1,13 +1,7 @@ @@ -116,10 +137,15 @@ size="S" />
        -
    {#if noScreens} @@ -155,6 +181,7 @@ /> {/if} + diff --git a/packages/builder/src/pages/builder/portal/apps/_components/PortalSideBar.svelte b/packages/builder/src/pages/builder/portal/apps/_components/PortalSideBar.svelte index e9cd170c0b..0f72accf9f 100644 --- a/packages/builder/src/pages/builder/portal/apps/_components/PortalSideBar.svelte +++ b/packages/builder/src/pages/builder/portal/apps/_components/PortalSideBar.svelte @@ -1,11 +1,9 @@