further store tidy up, derive selected page
This commit is contained in:
parent
a5827a9c53
commit
d473786d7e
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = {}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue