budibase/packages/builder/src/components/userInterface/ComponentDropdownMenu.svelte

208 lines
5.2 KiB
Svelte
Raw Normal View History

2020-06-01 23:16:55 +02:00
<script>
import { goto } from "@sveltech/routify"
2020-06-01 13:15:44 +02:00
import { store } from "builderStore"
import { getComponentDefinition } from "builderStore/storeUtils"
2020-06-01 13:15:44 +02:00
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { last, cloneDeep } from "lodash/fp"
import { getParent, saveCurrentPreviewItem } from "builderStore/storeUtils"
2020-06-01 13:15:44 +02:00
import { uuid } from "builderStore/uuid"
2020-09-07 00:50:11 +02:00
import { DropdownMenu } from "@budibase/bbui"
2020-06-01 13:15:44 +02:00
export let component
let confirmDeleteDialog
let dropdown
2020-09-07 00:50:11 +02:00
let anchor
2020-06-01 13:15:44 +02:00
$: noChildrenAllowed =
2020-08-12 17:28:19 +02:00
!component || !getComponentDefinition($store, component._component).children
$: noPaste = !$store.componentToPaste
2020-06-01 13:15:44 +02:00
const lastPartOfName = c => (c ? last(c._component.split("/")) : "")
const hideDropdown = () => {
dropdown.hide()
}
const selectComponent = component => {
store.selectComponent(component)
const path = store.getPathToComponent(component)
$goto(`./:page/:screen/${path}`)
}
2020-06-01 13:15:44 +02:00
const moveUpComponent = () => {
store.update(s => {
const parent = getParent(s.currentPreviewItem.props, component)
if (parent) {
const currentIndex = parent._children.indexOf(component)
if (currentIndex === 0) return s
const newChildren = parent._children.filter(c => c !== component)
newChildren.splice(currentIndex - 1, 0, component)
parent._children = newChildren
}
s.currentComponentInfo = component
saveCurrentPreviewItem(s)
2020-06-01 13:15:44 +02:00
return s
})
}
2020-06-01 13:15:44 +02:00
const moveDownComponent = () => {
store.update(s => {
const parent = getParent(s.currentPreviewItem.props, component)
2020-06-01 13:15:44 +02:00
if (parent) {
const currentIndex = parent._children.indexOf(component)
if (currentIndex === parent._children.length - 1) return s
2020-06-01 13:15:44 +02:00
const newChildren = parent._children.filter(c => c !== component)
newChildren.splice(currentIndex + 1, 0, component)
parent._children = newChildren
}
s.currentComponentInfo = component
saveCurrentPreviewItem(s)
2020-06-01 13:15:44 +02:00
return s
})
2020-06-01 13:15:44 +02:00
}
const copyComponent = () => {
2020-10-07 23:30:00 +02:00
storeComponentForCopy(false)
pasteComponent("below")
2020-06-01 13:15:44 +02:00
}
2020-06-01 13:15:44 +02:00
const deleteComponent = () => {
store.update(state => {
const parent = getParent(state.currentPreviewItem.props, component)
2020-06-01 13:15:44 +02:00
if (parent) {
parent._children = parent._children.filter(c => c !== component)
selectComponent(parent)
2020-06-01 13:15:44 +02:00
}
2020-06-01 13:15:44 +02:00
saveCurrentPreviewItem(state)
return state
})
}
2020-06-01 13:15:44 +02:00
const storeComponentForCopy = (cut = false) => {
2020-08-12 17:28:19 +02:00
// lives in store - also used by drag drop
store.storeComponentForCopy(component, cut)
2020-06-01 13:15:44 +02:00
}
2020-06-01 13:15:44 +02:00
const pasteComponent = mode => {
2020-08-12 17:28:19 +02:00
// lives in store - also used by drag drop
store.pasteComponent(component, mode)
2020-06-01 13:15:44 +02:00
}
2020-06-01 11:18:45 +02:00
</script>
2020-09-07 00:50:11 +02:00
<div bind:this={anchor} on:click|stopPropagation={() => {}}>
2020-10-14 14:21:43 +02:00
<div class="icon" on:click={dropdown.show}><i class="ri-more-line" /></div>
2020-09-07 00:50:11 +02:00
</div>
<DropdownMenu
bind:this={dropdown}
on:click={hideDropdown}
width="170px"
{anchor}
align="left">
<ul>
2020-06-01 23:16:55 +02:00
<li class="item" on:click={() => confirmDeleteDialog.show()}>
<i class="ri-delete-bin-2-line" />
2020-06-01 23:16:55 +02:00
Delete
</li>
<li class="item" on:click={moveUpComponent}>
<i class="ri-arrow-up-line" />
2020-06-01 23:16:55 +02:00
Move up
</li>
<li class="item" on:click={moveDownComponent}>
<i class="ri-arrow-down-line" />
2020-06-01 23:16:55 +02:00
Move down
</li>
<li class="item" on:click={copyComponent}>
<i class="ri-repeat-one-line" />
2020-06-01 23:16:55 +02:00
Duplicate
</li>
<li class="item" on:click={() => storeComponentForCopy(true)}>
<i class="ri-scissors-cut-line" />
2020-06-01 23:16:55 +02:00
Cut
</li>
<li class="item" on:click={() => storeComponentForCopy(false)}>
<i class="ri-file-copy-line" />
2020-06-01 23:16:55 +02:00
Copy
</li>
<hr class="hr-style" />
<li
class="item"
class:disabled={noPaste}
on:click={() => pasteComponent('above')}>
<i class="ri-insert-row-top" />
2020-06-01 23:16:55 +02:00
Paste above
</li>
<li
class="item"
class:disabled={noPaste}
on:click={() => pasteComponent('below')}>
<i class="ri-insert-row-bottom" />
2020-06-01 23:16:55 +02:00
Paste below
</li>
<li
class="item"
class:disabled={noPaste || noChildrenAllowed}
on:click={() => pasteComponent('inside')}>
<i class="ri-insert-column-right" />
2020-06-01 23:16:55 +02:00
Paste inside
</li>
2020-09-07 00:50:11 +02:00
</ul>
</DropdownMenu>
2020-06-01 11:18:45 +02:00
<ConfirmDialog
bind:this={confirmDeleteDialog}
title="Confirm Delete"
body={`Are you sure you wish to delete this '${lastPartOfName(component)}' component?`}
okText="Delete Component"
onOk={deleteComponent} />
2020-06-01 11:18:45 +02:00
<style>
2020-09-07 00:50:11 +02:00
ul {
list-style: none;
padding: 0;
margin: var(--spacing-s) 0;
2020-09-07 00:50:11 +02:00
}
li {
display: flex;
font-family: var(--font-sans);
font-size: var(--font-size-xs);
color: var(--ink);
padding: var(--spacing-s) var(--spacing-m);
margin: auto 0;
2020-09-07 00:50:11 +02:00
align-items: center;
cursor: pointer;
}
li:not(.disabled):hover {
2020-09-07 00:50:11 +02:00
background-color: var(--grey-2);
}
li:active {
color: var(--blue);
2020-06-01 13:15:44 +02:00
}
li i {
2020-06-01 16:31:55 +02:00
margin-right: 8px;
font-size: var(--font-size-s);
2020-06-01 16:31:55 +02:00
}
li.disabled {
color: var(--grey-4);
2020-06-01 13:15:44 +02:00
cursor: default;
}
2020-06-01 16:31:55 +02:00
.icon i {
font-size: 16px;
}
2020-06-01 16:31:55 +02:00
.hr-style {
margin: 8px 0;
color: var(--grey-4);
2020-06-01 16:31:55 +02:00
}
2020-06-01 13:15:44 +02:00
</style>