Merge pull request #483 from mjashanks/delete_screen

Can delete screens
Uses new dropdown menu from bbui
This commit is contained in:
Michael Shanks 2020-07-21 21:31:15 +01:00 committed by GitHub
commit b3145df87c
7 changed files with 161 additions and 38 deletions

View File

@ -55,7 +55,7 @@
]
},
"dependencies": {
"@budibase/bbui": "^1.15.8",
"@budibase/bbui": "^1.16.0",
"@budibase/client": "^0.1.1",
"@budibase/colorpicker": "^1.0.1",
"@nx-js/compiler-util": "^2.0.0",

View File

@ -53,7 +53,6 @@ export const getStore = () => {
store.createDatabaseForApp = backendStoreActions.createDatabaseForApp(store)
store.saveScreen = saveScreen(store)
store.deleteScreen = deleteScreen(store)
store.setCurrentScreen = setCurrentScreen(store)
store.setCurrentPage = setCurrentPage(store)
store.createScreen = createScreen(store)
@ -162,6 +161,7 @@ const createScreen = store => (screenName, route, layoutComponentName) => {
props: createProps(rootComponent).props,
}
newScreen.route = route
newScreen.name = newScreen.props._id
newScreen.props._instanceName = screenName || ""
state.currentPreviewItem = newScreen
state.currentComponentInfo = newScreen.props
@ -191,24 +191,6 @@ const setCurrentScreen = store => screenName => {
})
}
const deleteScreen = store => name => {
store.update(s => {
const components = s.components.filter(c => c.name !== name)
const screens = s.screens.filter(c => c.name !== name)
s.components = components
s.screens = screens
if (s.currentPreviewItem.name === name) {
s.currentPreviewItem = null
s.currentFrontEndType = ""
}
api.delete(`/_builder/api/${s.appId}/screen/${name}`)
return s
})
}
const savePage = store => async page => {
store.update(state => {
if (state.currentFrontEndType !== "page" || !state.currentPageName) {

View File

@ -6,6 +6,7 @@
import { pipe } from "components/common/core"
import { store } from "builderStore"
import { ArrowDownIcon, ShapeIcon } from "components/common/Icons/"
import ScreenDropdownMenu from "./ScreenDropdownMenu.svelte"
export let screens = []
@ -15,12 +16,15 @@
const joinPath = join("/")
const normalizedName = name =>
pipe(name, [
pipe(
name,
[
trimCharsStart("./"),
trimCharsStart("~/"),
trimCharsStart("../"),
trimChars(" "),
])
]
)
const changeScreen = screen => {
store.setCurrentScreen(screen.props._instanceName)
@ -31,7 +35,7 @@
<div class="root">
{#each screens as screen}
<div
class="budibase__nav-item component"
class="budibase__nav-item screen-header-row"
class:selected={$store.currentComponentInfo._id === screen.props._id}
on:click|stopPropagation={() => changeScreen(screen)}>
@ -46,6 +50,10 @@
<i class="ri-artboard-2-fill icon" />
<span class="title">{screen.props._instanceName}</span>
<div class="dropdown-menu">
<ScreenDropdownMenu {screen} />
</div>
</div>
{#if $store.currentPreviewItem.props._instanceName && $store.currentPreviewItem.props._instanceName === screen.props._instanceName && screen.props._children}
@ -63,10 +71,16 @@
color: var(--ink);
}
.screen-header-row {
display: flex;
flex-direction: row;
}
.title {
margin-left: 14px;
font-size: 14px;
font-weight: 400;
flex: 1;
}
.icon {
@ -89,4 +103,20 @@
.rotate :global(svg) {
transform: rotate(-90deg);
}
.dropdown-menu {
display: none;
height: 24px;
width: 24px;
color: var(--ink);
padding: 0px 5px;
border-style: none;
background: rgba(0, 0, 0, 0);
cursor: pointer;
position: relative;
}
.budibase__nav-item:hover .dropdown-menu {
display: block;
}
</style>

View File

@ -19,7 +19,11 @@
const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1)
const get_name = s => (!s ? "" : last(s.split("/")))
const get_capitalised_name = name => pipe(name, [get_name, capitalise])
const get_capitalised_name = name =>
pipe(
name,
[get_name, capitalise]
)
const isScreenslot = name => name === "##builtin/screenslot"
const selectComponent = component => {

View File

@ -0,0 +1,112 @@
<script>
import { MoreIcon } from "components/common/Icons"
import { store } from "builderStore"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import UIkit from "uikit"
import api from "builderStore/api"
import Portal from "svelte-portal"
import { DropdownMenu } from "@budibase/bbui"
export let screen
let confirmDeleteDialog
let dropdown
let buttonForDropdown
const hideDropdown = () => {
dropdown.hide()
}
const deleteScreen = () => {
store.update(s => {
const screens = s.screens.filter(c => c.name !== screen.name)
s.screens = screens
if (s.currentPreviewItem.name === screen.name) {
s.currentPreviewItem = s.pages[s.currentPageName]
s.currentFrontEndType = "page"
}
api.delete(
`/_builder/api/pages/${s.currentPageName}/screens/${screen.name}`
)
return s
})
}
</script>
<div class="root boundary" on:click|stopPropagation={() => {}}>
<button on:click={() => dropdown.show()} bind:this={buttonForDropdown}>
<MoreIcon />
</button>
<DropdownMenu bind:this={dropdown} anchor={buttonForDropdown}>
<ul class="menu" on:click={hideDropdown}>
<li class="item" on:click={() => confirmDeleteDialog.show()}>
<i class="icon ri-delete-bin-2-line" />
Delete
</li>
</ul>
</DropdownMenu>
</div>
<ConfirmDialog
bind:this={confirmDeleteDialog}
title="Confirm Delete"
body={`Are you sure you wish to delete the screen '${screen.props._instanceName}' ?`}
okText="Delete Screen"
onOk={deleteScreen} />
<style>
.root {
overflow: hidden;
z-index: 9;
}
.root button {
border-style: none;
border-radius: 2px;
padding: 5px;
background: transparent;
cursor: pointer;
color: var(--ink);
outline: none;
}
.menu {
z-index: 100000;
overflow: visible;
padding: 12px 0px;
border-radius: 5px;
margin: 0;
}
.menu li {
border-style: none;
background-color: transparent;
list-style-type: none;
padding: 4px 16px;
margin: 0;
width: 100%;
box-sizing: border-box;
}
.item {
display: flex;
align-items: center;
font-size: 14px;
}
.icon {
margin-right: 8px;
}
.menu li:not(.disabled) {
cursor: pointer;
color: var(--grey-7);
}
.menu li:not(.disabled):hover {
color: var(--ink);
background-color: var(--grey-1);
}
</style>

View File

@ -69,19 +69,14 @@ router.patch(
)
router.delete(
"/_builder/api/:appname/pages/:pagename/screen/*",
"/_builder/api/pages/:pagename/screens/:id",
authorized(BUILDER),
async ctx => {
const name = ctx.request.path.replace(
`/_builder/api/${ctx.params.appname}/pages/${ctx.params.pagename}/screen/`,
""
)
await deleteScreen(
ctx.config,
ctx.params.appname,
ctx.user.appId,
ctx.params.pagename,
decodeURI(name)
ctx.params.id
)
ctx.response.status = StatusCodes.OK

View File

@ -75,8 +75,8 @@ module.exports.renameScreen = async (
await rename(oldComponentPath, newComponentPath)
}
module.exports.deleteScreen = async (config, appname, pagename, name) => {
const appPath = appPackageFolder(config, appname)
module.exports.deleteScreen = async (config, appId, pagename, name) => {
const appPath = appPackageFolder(config, appId)
const componentFile = screenPath(appPath, pagename, name)
await unlink(componentFile)