further store tidy up, derive selected page

This commit is contained in:
Martin McKeaveney 2020-11-19 11:15:29 +00:00
parent 26cfb54a0f
commit a00bf70d29
10 changed files with 95 additions and 49 deletions

View File

@ -31,6 +31,12 @@ export const currentScreens = derived(store, $store => {
: Object.values(currentScreens) : Object.values(currentScreens)
}) })
export const selectedPage = derived(store, $store => {
if (!$store.pages) return null
return $store.pages[$store.currentPageName || "main"]
})
export const initialise = async () => { export const initialise = async () => {
try { try {
await analytics.activate() await analytics.activate()

View File

@ -5,8 +5,7 @@ import {
getBuiltin, getBuiltin,
makePropsSafe, makePropsSafe,
} from "components/userInterface/pagesParsing/createProps" } from "components/userInterface/pagesParsing/createProps"
import { getExactComponent } from "components/userInterface/pagesParsing/searchComponents" import { allScreens, backendUiStore, selectedPage } from "builderStore"
import { allScreens, backendUiStore } from "builderStore"
import { generate_screen_css } from "../generate_css" import { generate_screen_css } from "../generate_css"
import { fetchComponentLibDefinitions } from "../loadComponentLibraries" import { fetchComponentLibDefinitions } from "../loadComponentLibraries"
import api from "../api" import api from "../api"
@ -112,10 +111,9 @@ export const getFrontendStore = () => {
store.update(state => { store.update(state => {
state.currentFrontEndType = type state.currentFrontEndType = type
const pageOrScreen = const page = get(selectedPage)
type === "page"
? state.pages[state.currentPageName] const pageOrScreen = type === "page" ? page : page._screens[0]
: state.pages[state.currentPageName]._screens[0]
state.currentComponentInfo = pageOrScreen ? pageOrScreen.props : null state.currentComponentInfo = pageOrScreen ? pageOrScreen.props : null
state.currentPreviewItem = pageOrScreen state.currentPreviewItem = pageOrScreen
@ -159,32 +157,25 @@ export const getFrontendStore = () => {
await savePromise await savePromise
}, },
save: async screen => { save: async screen => {
const storeContents = get(store) const page = get(selectedPage)
const pageName = storeContents.currentPageName || "main" const currentPageScreens = page._screens
const currentPage = storeContents.pages[pageName]
const currentPageScreens = currentPage._screens
const creatingNewScreen = screen._id === undefined const creatingNewScreen = screen._id === undefined
let savePromise let savePromise
const response = await api.post( const response = await api.post(`/api/screens/${page._id}`, screen)
`/api/screens/${currentPage._id}`,
screen
)
const json = await response.json() const json = await response.json()
screen._rev = json.rev screen._rev = json.rev
screen._id = json.id screen._id = json.id
const foundScreen = currentPageScreens.findIndex( const foundScreen = page._screens.findIndex(el => el._id === screen._id)
el => el._id === screen._id
)
if (foundScreen !== -1) { if (foundScreen !== -1) {
currentPageScreens.splice(foundScreen, 1) page._screens.splice(foundScreen, 1)
} }
currentPageScreens.push(screen) page._screens.push(screen)
// TODO: should carry out all server updates to screen in a single call // TODO: should carry out all server updates to screen in a single call
store.update(state => { store.update(state => {
state.pages[pageName]._screens = currentPageScreens page._screens = currentPageScreens
if (creatingNewScreen) { if (creatingNewScreen) {
state.currentPreviewItem = screen state.currentPreviewItem = screen
@ -210,21 +201,20 @@ export const getFrontendStore = () => {
store.actions.screens.regenerateCss(currentPreviewItem) store.actions.screens.regenerateCss(currentPreviewItem)
} }
}, },
delete: async (screensToDelete, pageName) => { delete: async screens => {
let deletePromise let deletePromise
const screensToDelete = Array.isArray(screens) ? screens : [screens]
store.update(state => { store.update(state => {
if (pageName == null) { const currentPage = get(selectedPage)
pageName = state.pages.main.name
} for (let screenToDelete of screensToDelete) {
for (let screenToDelete of Array.isArray(screensToDelete)
? screensToDelete
: [screensToDelete]) {
// Remove screen from current page as well // Remove screen from current page as well
// TODO: Should be done server side // TODO: Should be done server side
state.pages[pageName]._screens = state.pages[ currentPage._screens = currentPage._screens.filter(
pageName scr => scr._id !== screenToDelete._id
]._screens.filter(scr => scr._id !== screenToDelete._id) )
deletePromise = api.delete( deletePromise = api.delete(
`/api/screens/${screenToDelete._id}/${screenToDelete._rev}` `/api/screens/${screenToDelete._id}/${screenToDelete._rev}`
) )
@ -310,14 +300,13 @@ export const getFrontendStore = () => {
create: (componentToAdd, presetProps) => { create: (componentToAdd, presetProps) => {
store.update(state => { store.update(state => {
function findSlot(component_array) { function findSlot(component_array) {
for (let i = 0; i < component_array.length; i += 1) { for (let component of component_array) {
if (component_array[i]._component === "##builtin/screenslot") { if (component._component === "##builtin/screenslot") {
return true return true
} }
if (component_array[i]._children) findSlot(component_array[i]) if (component._children) findSlot(component)
} }
return false return false
} }

View File

@ -1,11 +1,10 @@
<script> <script>
import { goto } from "@sveltech/routify" import { goto } from "@sveltech/routify"
import { store } from "builderStore" import { store } from "builderStore"
import { last } from "lodash/fp" import { getComponentDefinition } from "builderStore/storeUtils"
import { DropEffect, DropPosition } from "./dragDropStore" import { DropEffect, DropPosition } from "./dragDropStore"
import ComponentDropdownMenu from "../ComponentDropdownMenu.svelte" import ComponentDropdownMenu from "../ComponentDropdownMenu.svelte"
import NavItem from "components/common/NavItem.svelte" import NavItem from "components/common/NavItem.svelte"
import { getComponentDefinition } from "builderStore/storeUtils"
export let components = [] export let components = []
export let currentComponent export let currentComponent
@ -56,7 +55,7 @@
<ul> <ul>
{#each components as component, index (component._id)} {#each components as component, index (component._id)}
<li on:click|stopPropagation={() => selectComponent(component)}> <li on:click|stopPropagation={() => selectComponent(component)}>
{#if $dragDropStore && $dragDropStore.targetComponent === component && $dragDropStore.dropPosition === DropPosition.ABOVE} {#if $dragDropStore?.targetComponent === component && $dragDropStore.dropPosition === DropPosition.ABOVE}
<div <div
on:drop={dragDropStore.actions.drop} on:drop={dragDropStore.actions.drop}
ondragover="return false" ondragover="return false"
@ -87,7 +86,7 @@
level={level + 1} /> level={level + 1} />
{/if} {/if}
{#if $dragDropStore && $dragDropStore.targetComponent === component && ($dragDropStore.dropPosition === DropPosition.INSIDE || $dragDropStore.dropPosition === DropPosition.BELOW)} {#if $dragDropStore?.targetComponent === component && ($dragDropStore.dropPosition === DropPosition.INSIDE || $dragDropStore.dropPosition === DropPosition.BELOW)}
<div <div
on:drop={dragDropStore.actions.drop} on:drop={dragDropStore.actions.drop}
ondragover="return false" ondragover="return false"

View File

@ -1,12 +1,14 @@
<script> <script>
import { writable } from "svelte/store" import { writable } from "svelte/store"
import { goto } from "@sveltech/routify" import { goto } from "@sveltech/routify"
import { store } from "builderStore"
import instantiateStore from "./dragDropStore" import instantiateStore from "./dragDropStore"
import ComponentsTree from "./ComponentTree.svelte" import ComponentsTree from "./ComponentTree.svelte"
import NavItem from "components/common/NavItem.svelte" import NavItem from "components/common/NavItem.svelte"
import { store } from "builderStore" import ScreenDropdownMenu from "./ScreenDropdownMenu.svelte"
const dragDropStore = instantiateStore() const dragDropStore = instantiateStore()
export let route export let route
export let indent export let indent
@ -27,16 +29,17 @@
text={route.fullpath} text={route.fullpath}
withArrow={route.subpaths} withArrow={route.subpaths}
on:click={() => console.log(route)} /> on:click={() => console.log(route)} />
{#each Object.keys(route.screens) as screen} {#each Object.keys(route.screens) as screen}
<NavItem <NavItem
icon="ri-artboard-2-line" icon="ri-artboard-2-line"
indentLevel={indent || 1} indentLevel={indent || 1}
selected={$store.currentComponentInfo._id === route.screens[screen]} selected={$store.currentPreviewItem._id === route.screens[screen]}
opened={$store.currentPreviewItem._id === route.screens[screen]} opened={$store.currentPreviewItem._id === route.screens[screen]}
text={screen || 'DEFAULT'} text={screen || 'DEFAULT'}
withArrow={route.subpaths} withArrow={route.subpaths}
on:click={() => changeScreen(route.screens[screen])}> on:click={() => changeScreen(route.screens[screen])}>
<!-- <ScreenDropdownMenu screen={route.screens[screen]} /> --> <ScreenDropdownMenu screen={route.screens[screen]} />
</NavItem> </NavItem>
{#if selectedScreen?._id === route.screens[screen]} {#if selectedScreen?._id === route.screens[screen]}
<ComponentsTree <ComponentsTree

View File

@ -0,0 +1,53 @@
<script>
import { goto } from "@sveltech/routify"
import { store } from "builderStore"
import { notifier } from "builderStore/store/notifications"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { DropdownMenu } from "@budibase/bbui"
import { DropdownContainer, DropdownItem } from "components/common/Dropdowns"
export let screen
let confirmDeleteDialog
let dropdown
let anchor
const deleteScreen = () => {
store.actions.screens.delete(screen, $store.currentPageName)
// update the page if required
store.update(state => {
if (state.currentPreviewItem._id === screen._id) {
store.actions.pages.select($store.currentPageName)
notifier.success(`Screen ${screen.name} deleted successfully.`)
$goto(`./:page/page-layout`)
}
return state
})
}
</script>
<div bind:this={anchor} on:click|stopPropagation>
<div class="icon" on:click={() => dropdown.show()}>
<i class="ri-more-line" />
</div>
<DropdownMenu bind:this={dropdown} {anchor} align="left">
<DropdownContainer>
<DropdownItem
icon="ri-delete-bin-line"
title="Delete"
on:click={() => confirmDeleteDialog.show()} />
</DropdownContainer>
</DropdownMenu>
</div>
<ConfirmDialog
bind:this={confirmDeleteDialog}
title="Confirm Deletion"
body={'Are you sure you wish to delete this screen?'}
okText="Delete Screen"
onOk={deleteScreen} />
<style>
.icon i {
font-size: 16px;
}
</style>

View File

@ -46,7 +46,7 @@ export default function() {
// hovered in center of target // hovered in center of target
if (mousePosition > 0.4 && mousePosition < 0.8) { if (mousePosition > 0.4 && mousePosition < 0.8) {
state.dropPosition = DropPosition.BELOW state.dropPosition = DropPosition.INSIDE
} }
return return
} }

View File

@ -1,10 +1,6 @@
<script> <script>
import { goto } from "@sveltech/routify" import { goto } from "@sveltech/routify"
import ComponentTree from "./ComponentTree.svelte"
import { store } from "builderStore" import { store } from "builderStore"
import ScreenDropdownMenu from "../ScreenDropdownMenu.svelte"
import { writable } from "svelte/store"
import NavItem from "components/common/NavItem.svelte"
import PathTree from "./PathTree.svelte" import PathTree from "./PathTree.svelte"
export let routes = {} export let routes = {}

View File

@ -100,7 +100,7 @@
const drop = () => { const drop = () => {
if ($dragDropStore.targetComponent !== $dragDropStore.componentToDrop) { if ($dragDropStore.targetComponent !== $dragDropStore.componentToDrop) {
store.actions.components.cut($dragDropStore.componentToDrop) store.actions.components.copy($dragDropStore.componentToDrop)
store.actions.components.paste( store.actions.components.paste(
$dragDropStore.targetComponent, $dragDropStore.targetComponent,
$dragDropStore.dropPosition $dragDropStore.dropPosition

View File

@ -43,7 +43,7 @@ export const screenRouter = ({ screens, onScreenSelected, window }) => {
return sanitize(url) return sanitize(url)
} }
const routes = screens.map(s => makeRootedPath(s.routing && s.routing.route)) const routes = screens.map(screen => makeRootedPath(screen.routing.route))
let fallback = routes.findIndex(([p]) => p === makeRootedPath("*")) let fallback = routes.findIndex(([p]) => p === makeRootedPath("*"))
if (fallback < 0) fallback = 0 if (fallback < 0) fallback = 0