Major re-work, client library stills needs some work but it appears layouts and screens are no longer inter-dependent.

This commit is contained in:
mike12345567 2020-11-25 17:56:09 +00:00
parent f2fc4f1a4c
commit d3759a4c10
43 changed files with 180 additions and 410 deletions

View File

@ -19,14 +19,16 @@ export default function(component, state) {
}) })
} }
// check page first // check layouts first
findMatches(state.pages[state.currentPageName].props) for (let layout of state.layouts) {
findMatches(layout.props)
}
// if viewing screen, check current screen for duplicate // if viewing screen, check current screen for duplicate
if (state.currentFrontEndType === "screen") { if (state.currentFrontEndType === "screen") {
findMatches(state.currentPreviewItem.props) findMatches(state.currentPreviewItem.props)
} else { } else {
// viewing master page - need to find against all screens // viewing a layout - need to find against all screens
for (let screen of get(allScreens)) { for (let screen of get(allScreens)) {
findMatches(screen.props) findMatches(screen.props)
} }

View File

@ -31,14 +31,8 @@ export const allScreens = derived(store, $store => {
return $store.screens return $store.screens
}) })
export const currentScreens = derived(store, $store => { export const mainLayout = derived(store, $store => {
const currentScreens = $store.layouts[currentAssetName]?._screens return $store.layouts?.find(layout => layout.props?._id === "private-master-layout")
if (currentScreens == null) {
return []
}
return Array.isArray(currentScreens)
? currentScreens
: Object.values(currentScreens)
}) })
export const initialise = async () => { export const initialise = async () => {

View File

@ -4,11 +4,11 @@ import {
createProps, createProps,
getBuiltin, getBuiltin,
makePropsSafe, makePropsSafe,
} from "components/userInterface/pagesParsing/createProps" } from "components/userInterface/assetParsing/createProps"
import { allScreens, backendUiStore, currentAsset } from "builderStore" import { allScreens, backendUiStore, currentAsset, mainLayout } from "builderStore"
import { fetchComponentLibDefinitions } from "../loadComponentLibraries" import { fetchComponentLibDefinitions } from "../loadComponentLibraries"
import api from "../api" import api from "../api"
import { DEFAULT_PAGES_OBJECT } from "../../constants" import { DEFAULT_LAYOUTS } from "../../constants"
import getNewComponentName from "../getNewComponentName" import getNewComponentName from "../getNewComponentName"
import analytics from "analytics" import analytics from "analytics"
import { import {
@ -22,7 +22,7 @@ const INITIAL_FRONTEND_STATE = {
apps: [], apps: [],
name: "", name: "",
description: "", description: "",
layouts: DEFAULT_PAGES_OBJECT, layouts: DEFAULT_LAYOUTS,
screens: [], screens: [],
mainUi: {}, mainUi: {},
unauthenticatedUi: {}, unauthenticatedUi: {},
@ -68,16 +68,14 @@ export const getFrontendStore = () => {
await backendUiStore.actions.database.select(pkg.application.instance) await backendUiStore.actions.database.select(pkg.application.instance)
}, },
selectPageOrScreen: type => { selectAssetType: type => {
store.update(state => { store.update(state => {
state.currentFrontEndType = type state.currentFrontEndType = type
const page = get(currentAsset) const asset = get(currentAsset)
const pageOrScreen = type === "page" ? page : page._screens[0] state.currentComponentInfo = asset && asset.props ? asset.props : null
state.currentPreviewItem = asset
state.currentComponentInfo = pageOrScreen ? pageOrScreen.props : null
state.currentPreviewItem = pageOrScreen
state.currentView = "detail" state.currentView = "detail"
return state return state
}) })
@ -94,14 +92,16 @@ export const getFrontendStore = () => {
}, },
}, },
screens: { screens: {
select: screenId => { select: async screenId => {
let promise
store.update(state => { store.update(state => {
const screen = get(allScreens).find(screen => screen._id === screenId) const screen = get(allScreens).find(screen => screen._id === screenId)
state.currentPreviewItem = screen state.currentPreviewItem = screen
state.currentFrontEndType = "screen" state.currentFrontEndType = "screen"
state.currentAssetId = screenId
state.currentView = "detail" state.currentView = "detail"
store.actions.screens.regenerateCssForCurrentScreen() promise = store.actions.screens.regenerateCssForCurrentScreen()
const safeProps = makePropsSafe( const safeProps = makePropsSafe(
state.components[screen.props._component], state.components[screen.props._component],
screen.props screen.props
@ -110,44 +110,38 @@ export const getFrontendStore = () => {
state.currentComponentInfo = safeProps state.currentComponentInfo = safeProps
return state return state
}) })
await promise
}, },
create: async screen => { create: async screen => {
let savePromise let promises = []
store.update(state => { store.update(state => {
state.currentPreviewItem = screen state.currentPreviewItem = screen
state.currentComponentInfo = screen.props state.currentComponentInfo = screen.props
state.currentFrontEndType = "screen" state.currentFrontEndType = "screen"
if (state.currentPreviewItem) { if (state.currentPreviewItem) {
store.actions.screens.regenerateCss(state.currentPreviewItem) promises.push(store.actions.screens.regenerateCss(state.currentPreviewItem))
} }
savePromise = store.actions.screens.save(screen) promises.push(store.actions.screens.save(screen))
return state return state
}) })
await savePromise await Promise.all(promises)
}, },
save: async screen => { save: async screen => {
const page = get(currentAsset)
const currentPageScreens = page._screens
const creatingNewScreen = screen._id === undefined const creatingNewScreen = screen._id === undefined
const response = await api.post(`/api/screens`, screen)
let savePromise
const response = await api.post(`/api/screens/${page._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 = page._screens.findIndex(el => el._id === screen._id)
if (foundScreen !== -1) {
page._screens.splice(foundScreen, 1)
}
page._screens.push(screen)
// TODO: should carry out all server updates to screen in a single call
store.update(state => { store.update(state => {
page._screens = currentPageScreens const foundScreen = state.screens.findIndex(el => el._id === screen._id)
if (foundScreen !== -1) {
state.screens.splice(foundScreen, 1)
}
state.screens.push(screen)
if (creatingNewScreen) { if (creatingNewScreen) {
state.currentPreviewItem = screen state.currentPreviewItem = screen
@ -158,107 +152,99 @@ export const getFrontendStore = () => {
state.currentComponentInfo = safeProps state.currentComponentInfo = safeProps
screen.props = safeProps screen.props = safeProps
} }
savePromise = store.actions.layouts.save()
return state return state
}) })
if (savePromise) await savePromise
}, },
regenerateCss: async asset => { regenerateCss: async asset => {
const response = await api.post("/api/css/generate", asset) const response = await api.post("/api/css/generate", asset)
asset._css = await response.json() asset._css = (await response.json())?.css
}, },
regenerateCssForCurrentScreen: () => { regenerateCssForCurrentScreen: async () => {
const { currentPreviewItem } = get(store) const { currentPreviewItem } = get(store)
if (currentPreviewItem) { if (currentPreviewItem) {
store.actions.screens.regenerateCss(currentPreviewItem) await store.actions.screens.regenerateCss(currentPreviewItem)
} }
}, },
delete: async screens => { delete: async screens => {
let deletePromise
const screensToDelete = Array.isArray(screens) ? screens : [screens] const screensToDelete = Array.isArray(screens) ? screens : [screens]
const screenDeletePromises = []
store.update(state => { store.update(state => {
const currentPage = get(currentAsset)
for (let screenToDelete of screensToDelete) { for (let screenToDelete of screensToDelete) {
// Remove screen from current page as well state.screens = state.screens.filter(screen => screen._id !== screenToDelete._id)
// TODO: Should be done server side screenDeletePromises.push(api.delete(
currentPage._screens = currentPage._screens.filter(
scr => scr._id !== screenToDelete._id
)
deletePromise = api.delete(
`/api/screens/${screenToDelete._id}/${screenToDelete._rev}` `/api/screens/${screenToDelete._id}/${screenToDelete._rev}`
) ))
} }
return state return state
}) })
await deletePromise await Promise.all(screenDeletePromises)
}, },
}, },
preview: { preview: {
saveSelected: async () => { saveSelected: async () => {
const state = get(store) const state = get(store)
if (state.currentFrontEndType !== "page") { if (state.currentFrontEndType !== "layout") {
await store.actions.screens.save(state.currentPreviewItem) await store.actions.screens.save(currentAsset)
} }
await store.actions.layouts.save() await store.actions.layouts.save(currentAsset)
}, },
}, },
layouts: { layouts: {
select: pageName => { select: async layoutName => {
store.update(state => { store.update(state => {
const currentPage = state.layouts[pageName] const layout = store.actions.layouts.find(layoutName)
state.currentFrontEndType = "page" state.currentFrontEndType = "layout"
state.currentView = "detail" state.currentView = "detail"
state.currentAssetId = pageName state.currentAssetId = layout._id
// This is the root of many problems. // This is the root of many problems.
// Uncaught (in promise) TypeError: Cannot read property '_component' of undefined // Uncaught (in promise) TypeError: Cannot read property '_component' of undefined
// it appears that the currentPage sometimes has _props instead of props // it appears that the currentLayout sometimes has _props instead of props
// why // why
const safeProps = makePropsSafe( const safeProps = makePropsSafe(
state.components[currentPage.props._component], state.components[layout.props._component],
currentPage.props layout.props
) )
state.currentComponentInfo = safeProps state.currentComponentInfo = safeProps
currentPage.props = safeProps layout.props = safeProps
state.currentPreviewItem = state.layouts[pageName] state.currentPreviewItem = store.actions.layouts.find(layoutName)
store.actions.screens.regenerateCssForCurrentScreen()
for (let screen of get(allScreens)) {
screen._css = store.actions.screens.regenerateCss(screen)
}
return state return state
}) })
}, let cssPromises = []
save: async page => { cssPromises.push(store.actions.screens.regenerateCssForCurrentScreen())
const storeContents = get(store)
const pageName = storeContents.currentAssetId || "main"
const pageToSave = page || storeContents.pages[pageName]
// TODO: revisit. This sends down a very weird payload for (let screen of get(allScreens)) {
const response = await api.post(`/api/pages/${pageToSave._id}`, { cssPromises.push(store.actions.screens.regenerateCss(screen))
page: { }
componentLibraries: storeContents.pages.componentLibraries, await Promise.all(cssPromises)
...pageToSave,
}, },
screens: pageToSave._screens, save: async layout => {
const response = await api.post(`/api/layouts`, {
...layout,
}) })
const json = await response.json() const json = await response.json()
if (!json.ok) throw new Error("Error updating page") if (!json.ok) throw new Error("Error updating layout")
store.update(state => { store.update(state => {
state.layouts[pageName]._rev = json.rev const layoutToUpdate = state.layouts.find(stateLayouts => stateLayouts._id === layout._id)
if (layoutToUpdate) {
layoutToUpdate._rev = json.rev
}
return state return state
}) })
}, },
find: layoutName => {
if (!layoutName) {
return get(mainLayout)
}
const storeContents = get(store)
return storeContents.layouts.find(layout => layout.name.toLowerCase() === layoutName.toLowerCase())
},
}, },
components: { components: {
select: component => { select: component => {
@ -274,6 +260,9 @@ export const getFrontendStore = () => {
create: (componentToAdd, presetProps) => { create: (componentToAdd, presetProps) => {
store.update(state => { store.update(state => {
function findSlot(component_array) { function findSlot(component_array) {
if (!component_array) {
return false
}
for (let component of component_array) { for (let component of component_array) {
if (component._component === "##builtin/screenslot") { if (component._component === "##builtin/screenslot") {
return true return true
@ -286,7 +275,7 @@ export const getFrontendStore = () => {
if ( if (
componentToAdd.startsWith("##") && componentToAdd.startsWith("##") &&
findSlot(state.layouts[state.currentAssetId].props._children) findSlot(get(currentAsset)?.props._children)
) { ) {
return state return state
} }
@ -349,7 +338,8 @@ export const getFrontendStore = () => {
return state return state
}) })
}, },
paste: (targetComponent, mode) => { paste: async (targetComponent, mode) => {
let promises = []
store.update(state => { store.update(state => {
if (!state.componentToPaste) return state if (!state.componentToPaste) return state
@ -377,26 +367,29 @@ export const getFrontendStore = () => {
const index = mode === "above" ? targetIndex : targetIndex + 1 const index = mode === "above" ? targetIndex : targetIndex + 1
parent._children.splice(index, 0, cloneDeep(componentToPaste)) parent._children.splice(index, 0, cloneDeep(componentToPaste))
store.actions.screens.regenerateCssForCurrentScreen() promises.push(store.actions.screens.regenerateCssForCurrentScreen())
store.actions.preview.saveSelected() promises.push(store.actions.preview.saveSelected())
store.actions.components.select(componentToPaste) store.actions.components.select(componentToPaste)
return state return state
}) })
await Promise.all(promises)
}, },
updateStyle: (type, name, value) => { updateStyle: async (type, name, value) => {
let promises = []
store.update(state => { store.update(state => {
if (!state.currentComponentInfo._styles) { if (!state.currentComponentInfo._styles) {
state.currentComponentInfo._styles = {} state.currentComponentInfo._styles = {}
} }
state.currentComponentInfo._styles[type][name] = value state.currentComponentInfo._styles[type][name] = value
store.actions.screens.regenerateCssForCurrentScreen() promises.push(store.actions.screens.regenerateCssForCurrentScreen())
// save without messing with the store // save without messing with the store
store.actions.preview.saveSelected() promises.push(store.actions.preview.saveSelected())
return state return state
}) })
await Promise.all(promises)
}, },
updateProp: (name, value) => { updateProp: (name, value) => {
store.update(state => { store.update(state => {
@ -423,7 +416,7 @@ export const getFrontendStore = () => {
} }
} }
// Remove root entry since it's the screen or page layout. // Remove root entry since it's the screen or layout.
// Reverse array since we need the correct order of the IDs // Reverse array since we need the correct order of the IDs
const reversedComponents = pathComponents.reverse().slice(1) const reversedComponents = pathComponents.reverse().slice(1)
@ -438,11 +431,12 @@ export const getFrontendStore = () => {
}, },
links: { links: {
save: async (url, title) => { save: async (url, title) => {
let savePromise let promises = []
const layout = get(mainLayout)
store.update(state => { store.update(state => {
// Try to extract a nav component from the master screen // Try to extract a nav component from the master layout
const nav = findChildComponentType( const nav = findChildComponentType(
state.layouts.main, layout,
"@budibase/standard-components/Navigation" "@budibase/standard-components/Navigation"
) )
if (nav) { if (nav) {
@ -475,18 +469,18 @@ export const getFrontendStore = () => {
}).props }).props
} }
// Save page and regenerate all CSS because otherwise weird things happen // Save layout and regenerate all CSS because otherwise weird things happen
nav._children = [...nav._children, newLink] nav._children = [...nav._children, newLink]
state.currentAssetId = "main" state.currentAssetId = layout._id
store.actions.screens.regenerateCss(state.layouts.main) promises.push(store.actions.screens.regenerateCss(layout))
for (let screen of state.layouts.main._screens) { for (let screen of get(allScreens)) {
store.actions.screens.regenerateCss(screen) promises.push(store.actions.screens.regenerateCss(screen))
} }
savePromise = store.actions.layouts.save() promises.push(store.actions.layouts.save(layout))
} }
return state return state
}) })
await savePromise await Promise.all(promises)
}, },
}, },
}, },

View File

@ -1,4 +1,4 @@
import { getBuiltin } from "components/userInterface/pagesParsing/createProps" import { getBuiltin } from "components/userInterface/assetParsing/createProps"
import { uuid } from "./uuid" import { uuid } from "./uuid"
import getNewComponentName from "./getNewComponentName" import getNewComponentName from "./getNewComponentName"

View File

@ -58,7 +58,7 @@
await store.actions.screens.create(screen) await store.actions.screens.create(screen)
} }
// Create autolink to newly created list page // Create autolink to newly created list screen
const listScreen = screens.find(screen => const listScreen = screens.find(screen =>
screen.props._instanceName.endsWith("List") screen.props._instanceName.endsWith("List")
) )

View File

@ -1,6 +1,6 @@
<script> <script>
import { onMount } from "svelte" import { onMount } from "svelte"
import { store } from "builderStore" import { store, currentAsset } from "builderStore"
import iframeTemplate from "./iframeTemplate" import iframeTemplate from "./iframeTemplate"
import { Screen } from "builderStore/store/screenTemplates/utils/Screen" import { Screen } from "builderStore/store/screenTemplates/utils/Screen"
@ -16,14 +16,14 @@
.json() .json()
// Extract data to pass to the iframe // Extract data to pass to the iframe
$: page = $store.layouts[$store.currentPageName] $: layout = currentAsset
$: screen = $: screen =
$store.currentFrontEndType === "page" $store.currentFrontEndType === "layout"
? screenPlaceholder ? screenPlaceholder
: $store.currentPreviewItem : $store.currentPreviewItem
$: selectedComponentId = $store.currentComponentInfo?._id ?? "" $: selectedComponentId = $store.currentComponentInfo?._id ?? ""
$: previewData = { $: previewData = {
page, layout,
screen, screen,
selectedComponentId, selectedComponentId,
} }

View File

@ -20,7 +20,7 @@ export default `<html>
} }
// Extract data from message // Extract data from message
const { selectedComponentId, page, screen } = JSON.parse(event.data) const { selectedComponentId, layout, screen } = JSON.parse(event.data)
// Update selected component style // Update selected component style
if (selectedComponentStyle) { if (selectedComponentStyle) {
@ -33,7 +33,8 @@ export default `<html>
// Set some flags so the app knows we're in the builder // Set some flags so the app knows we're in the builder
window["##BUDIBASE_IN_BUILDER##"] = true; window["##BUDIBASE_IN_BUILDER##"] = true;
window["##BUDIBASE_PREVIEW_PAGE##"] = page; // TODO: need to update this
window["##BUDIBASE_PREVIEW_PAGE##"] = layout;
window["##BUDIBASE_PREVIEW_SCREEN##"] = screen; window["##BUDIBASE_PREVIEW_SCREEN##"] = screen;
// Initialise app // Initialise app

View File

@ -27,7 +27,7 @@
const selectComponent = component => { const selectComponent = component => {
store.actions.components.select(component) store.actions.components.select(component)
const path = store.actions.components.findRoute(component) const path = store.actions.components.findRoute(component)
$goto(`./:page/:screen/${path}`) $goto(`./:screen/${path}`)
} }
const moveUpComponent = () => { const moveUpComponent = () => {

View File

@ -23,7 +23,7 @@
const path = store.actions.components.findRoute(component) const path = store.actions.components.findRoute(component)
// Go to correct URL // Go to correct URL
$goto(`./:page/:screen/${path}`) $goto(`./:screen/${path}`)
} }
const dragstart = component => e => { const dragstart = component => e => {

View File

@ -19,7 +19,7 @@
const changeScreen = screenId => { const changeScreen = screenId => {
// select the route // select the route
store.actions.screens.select(screenId) store.actions.screens.select(screenId)
$goto(`./:page/${screenId}`) $goto(`./${screenId}`)
} }
</script> </script>

View File

@ -16,15 +16,6 @@
const screenToDelete = $allScreens.find(scr => scr._id === screen) const screenToDelete = $allScreens.find(scr => scr._id === screen)
store.actions.screens.delete(screenToDelete) store.actions.screens.delete(screenToDelete)
store.actions.routing.fetch() store.actions.routing.fetch()
// update the page if required
store.update(state => {
if (state.currentPreviewItem._id === screen) {
store.actions.layouts.select($store.currentPageName)
notifier.success(`Screen ${screenToDelete.name} deleted successfully.`)
$goto(`./:page/page-layout`)
}
return state
})
} }
</script> </script>

View File

@ -58,7 +58,7 @@
return components return components
} }
function setPageOrScreenProp(name, value) { function setAssetProps(name, value) {
store.update(state => { store.update(state => {
if (name === "_instanceName" && state.currentFrontEndType === "screen") { if (name === "_instanceName" && state.currentFrontEndType === "screen") {
state.currentPreviewItem.props[name] = value state.currentPreviewItem.props[name] = value
@ -94,8 +94,8 @@
{panelDefinition} {panelDefinition}
displayNameField={displayName} displayNameField={displayName}
onChange={store.actions.components.updateProp} onChange={store.actions.components.updateProp}
onScreenPropChange={setPageOrScreenProp} onScreenPropChange={setAssetProps}
screenOrPageInstance={$store.currentView !== 'component' && $store.currentPreviewItem} /> assetInstance={$store.currentView !== 'component' && $store.currentPreviewItem} />
{/if} {/if}
</div> </div>

View File

@ -27,7 +27,7 @@
const onComponentChosen = component => { const onComponentChosen = component => {
store.actions.components.create(component._component, component.presetProps) store.actions.components.create(component._component, component.presetProps)
const path = store.actions.components.findRoute($store.currentComponentInfo) const path = store.actions.components.findRoute($store.currentComponentInfo)
$goto(`./:page/:screen/${path}`) $goto(`./:screen/${path}`)
close() close()
} }
</script> </script>

View File

@ -18,7 +18,7 @@
</script> </script>
<div class="root"> <div class="root">
{#if $store.currentFrontEndType === 'page' || $allScreens.length} {#if $store.currentFrontEndType === "layout" || $allScreens.length}
<div class="switcher"> <div class="switcher">
<button <button
class:selected={selected === COMPONENT_SELECTION_TAB} class:selected={selected === COMPONENT_SELECTION_TAB}

View File

@ -1,10 +1,10 @@
<script> <script>
import { onMount } from "svelte" import { onMount } from "svelte"
import { store, currentScreens } from "builderStore" import { store, currentAsset } from "builderStore"
import api from "builderStore/api" import api from "builderStore/api"
import ComponentNavigationTree from "components/userInterface/ComponentNavigationTree/index.svelte" import ComponentNavigationTree from "components/userInterface/ComponentNavigationTree/index.svelte"
import PageLayout from "components/userInterface/PageLayout.svelte" import Layout from "components/userInterface/Layout.svelte"
import PagesList from "components/userInterface/LayoutsList.svelte" import LayoutsList from "components/userInterface/LayoutsList.svelte"
import NewScreenModal from "components/userInterface/NewScreenModal.svelte" import NewScreenModal from "components/userInterface/NewScreenModal.svelte"
import { Modal } from "@budibase/bbui" import { Modal } from "@budibase/bbui"
@ -21,14 +21,17 @@
<h1>Screens</h1> <h1>Screens</h1>
<i on:click={modal.show} data-cy="new-screen" class="ri-add-circle-fill" /> <i on:click={modal.show} data-cy="new-screen" class="ri-add-circle-fill" />
</div> </div>
<PagesList /> <LayoutsList />
{#if $store.currentFrontEndType === "layout" && $currentAsset}
<div class="nav-items-container"> <div class="nav-items-container">
<PageLayout layout={$store.layouts[$store.currentPageName]} /> <Layout layout={$currentAsset} />
<ComponentNavigationTree /> <ComponentNavigationTree />
</div> </div>
<Modal bind:this={modal}> <Modal bind:this={modal}>
<NewScreenModal /> <NewScreenModal />
</Modal> </Modal>
{/if}
<style> <style>
.title { .title {

View File

@ -22,8 +22,8 @@
} }
const setCurrentScreenToLayout = () => { const setCurrentScreenToLayout = () => {
store.actions.selectPageOrScreen("page") store.actions.selectAssetType("layout")
$goto("./:page/page-layout") $goto("./layout")
} }
</script> </script>

View File

@ -2,11 +2,6 @@
import { params, goto } from "@sveltech/routify" import { params, goto } from "@sveltech/routify"
import { store } from "builderStore" import { store } from "builderStore"
const getPage = (state, name) => {
const props = state.pages[name]
return { name, props }
}
const layouts = [ const layouts = [
{ {
title: "Private", title: "Private",
@ -23,7 +18,7 @@
const changeLayout = id => { const changeLayout = id => {
store.actions.layouts.select(id) store.actions.layouts.select(id)
$goto(`./${id}/page-layout`) $goto(`./${id}/layout`)
} }
</script> </script>

View File

@ -85,7 +85,7 @@
}) })
} }
$goto(`./:page/${name}`) $goto(`./${name}`)
} }
const routeNameExists = route => { const routeNameExists = route => {

View File

@ -2,9 +2,8 @@
import { isEmpty } from "lodash/fp" import { isEmpty } from "lodash/fp"
import PropertyControl from "./PropertyControl.svelte" import PropertyControl from "./PropertyControl.svelte"
import Input from "./PropertyPanelControls/Input.svelte" import Input from "./PropertyPanelControls/Input.svelte"
import { goto } from "@sveltech/routify"
import { excludeProps } from "./propertyCategories.js" import { excludeProps } from "./propertyCategories.js"
import { store, allScreens, currentAsset } from "builderStore" import { store, allScreens } from "builderStore"
import { walkProps } from "builderStore/storeUtils" import { walkProps } from "builderStore/storeUtils"
export let panelDefinition = [] export let panelDefinition = []
@ -13,13 +12,13 @@
export let onChange = () => {} export let onChange = () => {}
export let onScreenPropChange = () => {} export let onScreenPropChange = () => {}
export let displayNameField = false export let displayNameField = false
export let screenOrPageInstance export let assetInstance
let pageScreenProps = ["title", "favicon", "description", "route"] let assetProps = ["title", "favicon", "description", "route"]
let duplicateName = false let duplicateName = false
const propExistsOnComponentDef = prop => const propExistsOnComponentDef = prop =>
pageScreenProps.includes(prop) || prop in componentDefinition.props assetProps.includes(prop) || prop in componentDefinition.props
function handleChange(key, data) { function handleChange(key, data) {
data.target ? onChange(key, data.target.value) : onChange(key, data) data.target ? onChange(key, data.target.value) : onChange(key, data)
@ -30,7 +29,7 @@
{ key: "route", label: "Route", control: Input }, { key: "route", label: "Route", control: Input },
] ]
const pageDefinition = [ const layoutDefinition = [
{ key: "title", label: "Title", control: Input }, { key: "title", label: "Title", control: Input },
{ key: "favicon", label: "Favicon", control: Input }, { key: "favicon", label: "Favicon", control: Input },
] ]
@ -44,8 +43,8 @@
) )
} }
$: isPage = screenOrPageInstance && screenOrPageInstance.favicon $: isLayout = assetInstance && assetInstance.favicon
$: screenOrPageDefinition = isPage ? pageDefinition : screenDefinition $: assetDefinition = isLayout ? layoutDefinition : screenDefinition
const isDuplicateName = name => { const isDuplicateName = name => {
let duplicate = false let duplicate = false
@ -86,14 +85,14 @@
</script> </script>
<div class="settings-view-container"> <div class="settings-view-container">
{#if screenOrPageInstance} {#if assetInstance}
{#each screenOrPageDefinition as def} {#each assetDefinition as def}
<PropertyControl <PropertyControl
bindable={false} bindable={false}
control={def.control} control={def.control}
label={def.label} label={def.label}
key={def.key} key={def.key}
value={screenOrPageInstance[def.key]} value={assetInstance[def.key]}
onChange={onScreenPropChange} onChange={onScreenPropChange}
props={{ ...excludeProps(def, ['control', 'label']) }} /> props={{ ...excludeProps(def, ['control', 'label']) }} />
{/each} {/each}

View File

@ -1,60 +0,0 @@
import { isPlainObject, isArray, cloneDeep } from "lodash/fp"
import { getExactComponent } from "./searchComponents"
export const rename = (pages, screens, oldname, newname) => {
pages = cloneDeep(pages)
screens = cloneDeep(screens)
const changedScreens = []
const existingWithNewName = getExactComponent(screens, newname, true)
if (existingWithNewName)
return {
components: screens,
pages,
error: "Component by that name already exists",
}
const traverseProps = props => {
let hasEdited = false
if (props._component && props._component === oldname) {
props._component = newname
hasEdited = true
}
for (let propName in props) {
const prop = props[propName]
if (isPlainObject(prop) && prop._component) {
hasEdited = traverseProps(prop) || hasEdited
}
if (isArray(prop)) {
for (let element of prop) {
hasEdited = traverseProps(element) || hasEdited
}
}
}
return hasEdited
}
for (let screen of screens) {
let hasEdited = false
if (screen.props.instanceName === oldname) {
screen.props.instanceName = newname
hasEdited = true
}
hasEdited = traverseProps(screen.props) || hasEdited
if (hasEdited && screen.props.instanceName !== newname)
changedScreens.push(screen.props.instanceName)
}
for (let pageName in pages) {
const page = pages[pageName]
if (page.appBody === oldname) {
page.appBody = newname
}
}
return { screens, pages, changedScreens }
}

View File

@ -1167,7 +1167,7 @@ export default {
_component: "##builtin/screenslot", _component: "##builtin/screenslot",
name: "Screen Slot", name: "Screen Slot",
description: description:
"This component is a placeholder for the rendering of a screen within a page.", "This component is a placeholder for the rendering of a screen within a layout.",
icon: "ri-crop-2-line", icon: "ri-crop-2-line",
properties: { design: { ...all } }, properties: { design: { ...all } },
commonProps: {}, commonProps: {},

View File

@ -1,15 +1,13 @@
export const DEFAULT_PAGES_OBJECT = { export const DEFAULT_LAYOUTS = {
main: { main: {
props: { props: {
_component: "@budibase/standard-components/container", _component: "@budibase/standard-components/container",
}, },
_screens: {},
}, },
unauthenticated: { unauthenticated: {
props: { props: {
_component: "@budibase/standard-components/container", _component: "@budibase/standard-components/container",
}, },
_screens: {},
}, },
componentLibraries: [], componentLibraries: [],
stylesheets: [], stylesheets: [],

View File

@ -1,4 +1,6 @@
<script> <script>
import { store } from "builderStore"
import { params } from "@sveltech/routify" import { params } from "@sveltech/routify"
store.actions.layouts.select($params.page)
store.actions.layouts.select($params.layout)
</script> </script>

View File

@ -1,5 +1,4 @@
<script> <script>
import { onMount } from "svelte"
import { params, leftover, goto } from "@sveltech/routify" import { params, leftover, goto } from "@sveltech/routify"
import { store, allScreens } from "builderStore" import { store, allScreens } from "builderStore"
@ -7,7 +6,7 @@
const componentIds = $leftover.split("/").filter(id => id !== "") const componentIds = $leftover.split("/").filter(id => id !== "")
// It's a screen, set it to that screen // It's a screen, set it to that screen
if ($params.screen !== "page-layout") { if ($params.screen !== "layout") {
const currentScreenName = decodeURI($params.screen) const currentScreenName = decodeURI($params.screen)
const validScreen = const validScreen =
$allScreens.findIndex(screen => screen._id === currentScreenName) !== -1 $allScreens.findIndex(screen => screen._id === currentScreenName) !== -1
@ -23,7 +22,7 @@
// There are leftover stuff, like IDs, so navigate the components and find the ID and select it. // There are leftover stuff, like IDs, so navigate the components and find the ID and select it.
if ($leftover) { if ($leftover) {
// Get the correct screen children. // Get the correct screen children.
const screenChildren = $store.layouts[$params.page]._screens.find( const screenChildren = allScreens.find(
screen => screen =>
screen._id === $params.screen || screen._id === $params.screen ||
screen._id === decodeURIComponent($params.screen) screen._id === decodeURIComponent($params.screen)
@ -32,12 +31,13 @@
} }
} }
} else { } else {
// It's a page, so set the screentype to page. // It's a layout, so set the screen type to layout
store.actions.selectPageOrScreen("page") store.actions.selectAssetType("layout")
// There are leftover stuff, like IDs, so navigate the components and find the ID and select it. // There are leftover stuff, like IDs, so navigate the components and find the ID and select it.
const layout = store.actions.layouts.find($params.layout)
if ($leftover) { if ($leftover) {
findComponent(componentIds, $store.layouts[$params.page].props._children) findComponent(componentIds, layout.props._children)
} }
} }

View File

@ -2,7 +2,7 @@
import { params } from "@sveltech/routify" import { params } from "@sveltech/routify"
import { store } from "builderStore" import { store } from "builderStore"
store.actions.layouts.select($params.page) store.actions.layouts.select($params.layout)
</script> </script>
<slot /> <slot />

View File

@ -1,4 +1,4 @@
<script> <script>
import { goto } from "@sveltech/routify" import { goto } from "@sveltech/routify"
$goto("../page-layout") $goto("../layout")
</script> </script>

View File

@ -37,7 +37,7 @@
</div> </div>
<div class="preview-pane"> <div class="preview-pane">
{#if $store.currentPageName && $store.currentPageName.length > 0} {#if $store.currentAssetId && $store.currentAssetId.length > 0}
<ComponentSelectionList /> <ComponentSelectionList />
<div class="preview-content"> <div class="preview-content">
<CurrentItemPreview /> <CurrentItemPreview />

View File

@ -1,4 +1,4 @@
import { createProps } from "../src/components/userInterface/pagesParsing/createProps" import { createProps } from "../src/components/userInterface/assetParsing/createProps"
import { keys, some } from "lodash/fp" import { keys, some } from "lodash/fp"
import { stripStandardProps } from "./testData" import { stripStandardProps } from "./testData"

View File

@ -2,7 +2,7 @@ import {
searchAllComponents, searchAllComponents,
getExactComponent, getExactComponent,
getAncestorProps, getAncestorProps,
} from "../src/components/userInterface/pagesParsing/searchComponents" } from "../src/components/userInterface/assetParsing/searchComponents"
import { componentsAndScreens } from "./testData" import { componentsAndScreens } from "./testData"

View File

@ -852,15 +852,6 @@
svelte-flatpickr "^2.4.0" svelte-flatpickr "^2.4.0"
svelte-portal "^1.0.0" svelte-portal "^1.0.0"
"@budibase/client@^0.3.8":
version "0.3.8"
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.3.8.tgz#75df7e97e8f0d9b58c00e2bb0d3b4a55f8d04735"
integrity sha512-tnFdmCdXKS+uZGoipr69Wa0oVoFHmyoV0ydihI6q0gKQH0KutypVHAaul2qPB8t5a/mTZopC//2WdmCeX1GKVg==
dependencies:
deep-equal "^2.0.1"
mustache "^4.0.1"
regexparam "^1.3.0"
"@budibase/colorpicker@^1.0.1": "@budibase/colorpicker@^1.0.1":
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/@budibase/colorpicker/-/colorpicker-1.0.1.tgz#940c180e7ebba0cb0756c4c8ef13f5dfab58e810" resolved "https://registry.yarnpkg.com/@budibase/colorpicker/-/colorpicker-1.0.1.tgz#940c180e7ebba0cb0756c4c8ef13f5dfab58e810"
@ -1648,11 +1639,6 @@ array-equal@^1.0.0:
resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
array-filter@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83"
integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=
array-union@^2.1.0: array-union@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
@ -1720,13 +1706,6 @@ atob@^2.1.2:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5"
integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==
dependencies:
array-filter "^1.0.0"
aws-sign2@~0.7.0: aws-sign2@~0.7.0:
version "0.7.0" version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
@ -2865,26 +2844,6 @@ deep-equal@^1.0.1:
object-keys "^1.1.1" object-keys "^1.1.1"
regexp.prototype.flags "^1.2.0" regexp.prototype.flags "^1.2.0"
deep-equal@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.4.tgz#6b0b407a074666033169df3acaf128e1c6f3eab6"
integrity sha512-BUfaXrVoCfgkOQY/b09QdO9L3XNoF2XH0A3aY9IQwQL/ZjLOe8FQgCNVl1wiolhsFo8kFdO9zdPViCPbmaJA5w==
dependencies:
es-abstract "^1.18.0-next.1"
es-get-iterator "^1.1.0"
is-arguments "^1.0.4"
is-date-object "^1.0.2"
is-regex "^1.1.1"
isarray "^2.0.5"
object-is "^1.1.3"
object-keys "^1.1.1"
object.assign "^4.1.1"
regexp.prototype.flags "^1.3.0"
side-channel "^1.0.3"
which-boxed-primitive "^1.0.1"
which-collection "^1.0.1"
which-typed-array "^1.1.2"
deep-is@~0.1.3: deep-is@~0.1.3:
version "0.1.3" version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
@ -3066,7 +3025,7 @@ error-ex@^1.3.1:
dependencies: dependencies:
is-arrayish "^0.2.1" is-arrayish "^0.2.1"
es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5: es-abstract@^1.17.0-next.1, es-abstract@^1.17.2:
version "1.17.7" version "1.17.7"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c"
integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==
@ -3083,7 +3042,7 @@ es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstrac
string.prototype.trimend "^1.0.1" string.prototype.trimend "^1.0.1"
string.prototype.trimstart "^1.0.1" string.prototype.trimstart "^1.0.1"
es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: es-abstract@^1.18.0-next.1:
version "1.18.0-next.1" version "1.18.0-next.1"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68"
integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==
@ -3101,20 +3060,6 @@ es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1:
string.prototype.trimend "^1.0.1" string.prototype.trimend "^1.0.1"
string.prototype.trimstart "^1.0.1" string.prototype.trimstart "^1.0.1"
es-get-iterator@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.1.tgz#b93ddd867af16d5118e00881396533c1c6647ad9"
integrity sha512-qorBw8Y7B15DVLaJWy6WdEV/ZkieBcu6QCq/xzWzGOKJqgG1j754vXRfZ3NY7HSShneqU43mPB4OkQBTkvHhFw==
dependencies:
call-bind "^1.0.0"
get-intrinsic "^1.0.1"
has-symbols "^1.0.1"
is-arguments "^1.0.4"
is-map "^2.0.1"
is-set "^2.0.1"
is-string "^1.0.5"
isarray "^2.0.5"
es-to-primitive@^1.2.1: es-to-primitive@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
@ -3493,7 +3438,7 @@ for-in@^1.0.2:
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
foreach@^2.0.5, foreach@~2.0.1: foreach@~2.0.1:
version "2.0.5" version "2.0.5"
resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k=
@ -3583,7 +3528,7 @@ get-caller-file@^2.0.1:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-intrinsic@^1.0.0, get-intrinsic@^1.0.1: get-intrinsic@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be"
integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==
@ -3941,11 +3886,6 @@ is-arrayish@^0.2.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-bigint@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.0.tgz#73da8c33208d00f130e9b5e15d23eac9215601c4"
integrity sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g==
is-binary-path@~2.1.0: is-binary-path@~2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
@ -3953,11 +3893,6 @@ is-binary-path@~2.1.0:
dependencies: dependencies:
binary-extensions "^2.0.0" binary-extensions "^2.0.0"
is-boolean-object@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e"
integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==
is-buffer@^1.1.5: is-buffer@^1.1.5:
version "1.1.6" version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
@ -3996,7 +3931,7 @@ is-data-descriptor@^1.0.0:
dependencies: dependencies:
kind-of "^6.0.0" kind-of "^6.0.0"
is-date-object@^1.0.1, is-date-object@^1.0.2: is-date-object@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
@ -4073,11 +4008,6 @@ is-installed-globally@^0.3.2:
global-dirs "^2.0.1" global-dirs "^2.0.1"
is-path-inside "^3.0.1" is-path-inside "^3.0.1"
is-map@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1"
integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==
is-module@^1.0.0: is-module@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
@ -4088,11 +4018,6 @@ is-negative-zero@^2.0.0:
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461"
integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=
is-number-object@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197"
integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==
is-number@^3.0.0: is-number@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@ -4158,11 +4083,6 @@ is-regex@^1.0.4, is-regex@^1.1.1:
dependencies: dependencies:
has-symbols "^1.0.1" has-symbols "^1.0.1"
is-set@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.1.tgz#d1604afdab1724986d30091575f54945da7e5f43"
integrity sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==
is-stream@^1.1.0: is-stream@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
@ -4173,11 +4093,6 @@ is-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
is-string@^1.0.4, is-string@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==
is-symbol@^1.0.2: is-symbol@^1.0.2:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
@ -4185,31 +4100,11 @@ is-symbol@^1.0.2:
dependencies: dependencies:
has-symbols "^1.0.1" has-symbols "^1.0.1"
is-typed-array@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.3.tgz#a4ff5a5e672e1a55f99c7f54e59597af5c1df04d"
integrity sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==
dependencies:
available-typed-arrays "^1.0.0"
es-abstract "^1.17.4"
foreach "^2.0.5"
has-symbols "^1.0.1"
is-typedarray@~1.0.0: is-typedarray@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
is-weakmap@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2"
integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==
is-weakset@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.1.tgz#e9a0af88dbd751589f5e50d80f4c98b780884f83"
integrity sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==
is-windows@^1.0.2: is-windows@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
@ -4235,11 +4130,6 @@ isarray@1.0.0, isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isarray@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
isbuffer@~0.0.0: isbuffer@~0.0.0:
version "0.0.0" version "0.0.0"
resolved "https://registry.yarnpkg.com/isbuffer/-/isbuffer-0.0.0.tgz#38c146d9df528b8bf9b0701c3d43cf12df3fc39b" resolved "https://registry.yarnpkg.com/isbuffer/-/isbuffer-0.0.0.tgz#38c146d9df528b8bf9b0701c3d43cf12df3fc39b"
@ -5494,7 +5384,7 @@ object-inspect@^1.8.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==
object-is@^1.0.1, object-is@^1.1.3: object-is@^1.0.1:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.3.tgz#2e3b9e65560137455ee3bd62aec4d90a2ea1cc81" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.3.tgz#2e3b9e65560137455ee3bd62aec4d90a2ea1cc81"
integrity sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg== integrity sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==
@ -6101,7 +5991,7 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2" extend-shallow "^3.0.2"
safe-regex "^1.1.0" safe-regex "^1.1.0"
regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0: regexp.prototype.flags@^1.2.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75"
integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==
@ -6109,11 +5999,6 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0:
define-properties "^1.1.3" define-properties "^1.1.3"
es-abstract "^1.17.0-next.1" es-abstract "^1.17.0-next.1"
regexparam@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-1.3.0.tgz#2fe42c93e32a40eff6235d635e0ffa344b92965f"
integrity sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g==
regexpu-core@^4.7.1: regexpu-core@^4.7.1:
version "4.7.1" version "4.7.1"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6"
@ -6577,14 +6462,6 @@ shortid@^2.2.15:
dependencies: dependencies:
nanoid "^2.1.0" nanoid "^2.1.0"
side-channel@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.3.tgz#cdc46b057550bbab63706210838df5d4c19519c3"
integrity sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==
dependencies:
es-abstract "^1.18.0-next.0"
object-inspect "^1.8.0"
signal-exit@^3.0.0, signal-exit@^3.0.2: signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.3" version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
@ -7405,44 +7282,11 @@ whatwg-url@^8.0.0:
tr46 "^2.0.2" tr46 "^2.0.2"
webidl-conversions "^6.1.0" webidl-conversions "^6.1.0"
which-boxed-primitive@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz#cbe8f838ebe91ba2471bb69e9edbda67ab5a5ec1"
integrity sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==
dependencies:
is-bigint "^1.0.0"
is-boolean-object "^1.0.0"
is-number-object "^1.0.3"
is-string "^1.0.4"
is-symbol "^1.0.2"
which-collection@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==
dependencies:
is-map "^2.0.1"
is-set "^2.0.1"
is-weakmap "^2.0.1"
is-weakset "^2.0.1"
which-module@^2.0.0: which-module@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
which-typed-array@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.2.tgz#e5f98e56bda93e3dac196b01d47c1156679c00b2"
integrity sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==
dependencies:
available-typed-arrays "^1.0.2"
es-abstract "^1.17.5"
foreach "^2.0.5"
function-bind "^1.1.1"
has-symbols "^1.0.1"
is-typed-array "^1.1.3"
which@^1.2.9, which@^1.3.0: which@^1.2.9, which@^1.3.0:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"

View File

@ -217,7 +217,11 @@ const createEmptyAppPackage = async (ctx, app) => {
homeScreen._id = generateScreenID() homeScreen._id = generateScreenID()
screensAndLayouts.push(homeScreen) screensAndLayouts.push(homeScreen)
screensAndLayouts = await compileStaticAssets(app._id, screensAndLayouts)
await db.bulkDocs(screensAndLayouts) await db.bulkDocs(screensAndLayouts)
// at the end add CSS to all the structures
for (let asset of screensAndLayouts) {
asset._css = generateAssetCss([asset.props])
}
await compileStaticAssets(app._id, screensAndLayouts)
return newAppFolder return newAppFolder
} }

View File

@ -1,13 +1,11 @@
const CouchDB = require("../../db/client") const CouchDB = require("../../db/client")
const { generateLayoutID } = require("../../db/utils") const { generateLayoutID } = require("../../db/utils")
const compileStaticAssets = require("../../utilities/builder/compileStaticAssets")
exports.save = async function(ctx) { exports.save = async function(ctx) {
const db = new CouchDB(ctx.user.appId) const db = new CouchDB(ctx.user.appId)
let layout = ctx.request.body let layout = ctx.request.body
layout._id = layout._id || generateLayoutID() layout._id = layout._id || generateLayoutID()
layout = await compileStaticAssets(ctx.user.appId, layout)
ctx.body = await db.put(layout) ctx.body = await db.put(layout)
ctx.status = 200 ctx.status = 200
} }

View File

@ -1,6 +1,5 @@
const CouchDB = require("../../db") const CouchDB = require("../../db")
const { getScreenParams, generateScreenID } = require("../../db/utils") const { getScreenParams, generateScreenID } = require("../../db/utils")
const compileStaticAssets = require("../../utilities/builder/compileStaticAssets")
const { AccessController } = require("../../utilities/security/accessLevels") const { AccessController } = require("../../utilities/security/accessLevels")
exports.fetch = async ctx => { exports.fetch = async ctx => {
@ -29,7 +28,6 @@ exports.save = async ctx => {
if (!screen._id) { if (!screen._id) {
screen._id = generateScreenID() screen._id = generateScreenID()
} }
screen = await compileStaticAssets(ctx.user.appId, screen)
const response = await db.put(screen) const response = await db.put(screen)
ctx.message = `Screen ${screen.name} saved.` ctx.message = `Screen ${screen.name} saved.`

View File

@ -18,13 +18,16 @@ const fileProcessor = require("../../../utilities/fileProcessor")
const { AuthTypes } = require("../../../constants") const { AuthTypes } = require("../../../constants")
const env = require("../../../environment") const env = require("../../../environment")
const { generateAssetCss } = require("../../../utilities/builder/generateCss") const { generateAssetCss } = require("../../../utilities/builder/generateCss")
const compileStaticAssets = require("../../../utilities/builder/compileStaticAssets")
// this was the version before we started versioning the component library // this was the version before we started versioning the component library
const COMP_LIB_BASE_APP_VERSION = "0.2.5" const COMP_LIB_BASE_APP_VERSION = "0.2.5"
exports.generateCss = async function(ctx) { exports.generateCss = async function(ctx) {
const structure = ctx.request.body const structure = ctx.request.body
ctx.body = generateAssetCss(structure) structure._css = generateAssetCss([structure.props])
await compileStaticAssets(ctx.appId, structure)
ctx.body = { css: structure._css }
} }
exports.serveBuilder = async function(ctx) { exports.serveBuilder = async function(ctx) {

View File

@ -5,6 +5,6 @@ const controller = require("../controllers/layout")
const router = Router() const router = Router()
router.post("/api/layouts/:layoutId", authorized(BUILDER), controller.save) router.post("/api/layouts", authorized(BUILDER), controller.save)
module.exports = router module.exports = router

View File

@ -6,7 +6,7 @@ const BASE_LAYOUTS = [
stylesheets: [], stylesheets: [],
name: "Main", name: "Main",
props: { props: {
_id: "private-master-root", _id: "private-master-layout",
_component: "@budibase/standard-components/container", _component: "@budibase/standard-components/container",
_children: [ _children: [
{ {
@ -143,6 +143,7 @@ const BASE_LAYOUTS = [
onLoad: [], onLoad: [],
}, },
}, },
// TODO: needs removed
{ {
componentLibraries: ["@budibase/standard-components"], componentLibraries: ["@budibase/standard-components"],
title: "{{ name }}", title: "{{ name }}",
@ -150,7 +151,7 @@ const BASE_LAYOUTS = [
stylesheets: [], stylesheets: [],
name: "Unauthenticated", name: "Unauthenticated",
props: { props: {
_id: "public-master-root", _id: "public-master-layout",
_component: "@budibase/standard-components/container", _component: "@budibase/standard-components/container",
_children: [ _children: [
{ {

View File

@ -5,6 +5,7 @@ const {
writeFile, writeFile,
readdir, readdir,
readFile, readFile,
existsSync,
} = require("fs-extra") } = require("fs-extra")
const { join } = require("../centralPath") const { join } = require("../centralPath")
const { budibaseAppsDir } = require("../budibaseDir") const { budibaseAppsDir } = require("../budibaseDir")
@ -51,11 +52,13 @@ const buildCssBundle = async (publicPath, asset) => {
} }
// bundle up all the CSS in the directory into one top level CSS file // bundle up all the CSS in the directory into one top level CSS file
if (existsSync(cssPath)) {
const cssFiles = await readdir(cssPath) const cssFiles = await readdir(cssPath)
for (let filename of cssFiles) { for (let filename of cssFiles) {
const css = await readFile(filename) const css = await readFile(join(cssPath, filename))
cssString += css cssString += css
} }
}
await writeFile(join(publicPath, "bundle.css"), cssString) await writeFile(join(publicPath, "bundle.css"), cssString)
} }