diff --git a/packages/builder/rollup.config.js b/packages/builder/rollup.config.js
index 5a607720d8..9986e39fd5 100644
--- a/packages/builder/rollup.config.js
+++ b/packages/builder/rollup.config.js
@@ -103,6 +103,11 @@ const lodash_fp_exports = [
"toNumber",
"takeRight",
"toPairs",
+ "remove",
+ "findIndex",
+ "compose",
+ "get",
+ "tap",
]
const lodash_exports = [
@@ -159,13 +164,15 @@ export default {
}),
replace({
- "process.env.NODE_ENV": JSON.stringify(production ? "production" : "development")
+ "process.env.NODE_ENV": JSON.stringify(
+ production ? "production" : "development"
+ ),
}),
svelte({
// enable run-time checks when not in production
dev: !production,
- include: "src/**/*.svelte",
+ include: ["src/**/*.svelte", "node_modules/**/*.svelte"],
// we'll extract any component CSS out into
// a separate file — better for performance
css: css => {
diff --git a/packages/builder/src/App.svelte b/packages/builder/src/App.svelte
index 81e74e8543..69bddc225c 100644
--- a/packages/builder/src/App.svelte
+++ b/packages/builder/src/App.svelte
@@ -29,16 +29,16 @@
{/await}
+ {#if $store.useAnalytics}
+
+ {/if}
+ -->
diff --git a/packages/builder/src/budibase.css b/packages/builder/src/budibase.css
index 7a82999241..b64bb77e1a 100644
--- a/packages/builder/src/budibase.css
+++ b/packages/builder/src/budibase.css
@@ -91,4 +91,38 @@
.uk-text-right {
display: flex;
justify-content: flex-start;
+}
+
+.preview-pane {
+ grid-column: 2;
+ margin: 80px 60px;
+ background: #fff;
+ border-radius: 5px;
+ box-shadow: 0 0px 6px rgba(0, 0, 0, 0.05);
+}
+
+.budibase__table {
+ border: 1px solid #ccc;
+ background: #fff;
+ border-radius: 2px;
+}
+
+.budibase__table thead {
+ background: #fafafa;
+}
+
+.budibase__table thead > tr > th {
+ color: var(--button-text);
+ text-transform: capitalize;
+ font-weight: 500;
+}
+
+.budibase__table tr {
+ border-bottom: 1px solid #ccc;
+}
+
+.button--toggled {
+ background: #fafafa;
+ color: var(--button-text);
+ padding: 10px;
}
\ No newline at end of file
diff --git a/packages/builder/src/builderStore/generate_css.js b/packages/builder/src/builderStore/generate_css.js
index dbca389aa4..19148ce9b0 100644
--- a/packages/builder/src/builderStore/generate_css.js
+++ b/packages/builder/src/builderStore/generate_css.js
@@ -39,7 +39,7 @@ const css_map = {
},
direction: {
name: "flex-direction",
- generate: self
+ generate: self,
},
gridarea: {
name: "grid-area",
@@ -113,7 +113,7 @@ const object_to_css_string = [
export const generate_css = ({ layout, position }) => {
let _layout = pipe(layout, object_to_css_string)
if (_layout.length) {
- _layout += `\ndisplay: ${_layout.includes("flex") ? "flex" : "grid"};`;
+ _layout += `\ndisplay: ${_layout.includes("flex") ? "flex" : "grid"};`
}
return {
diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js
index e3bc0b089c..801ecb6464 100644
--- a/packages/builder/src/builderStore/index.js
+++ b/packages/builder/src/builderStore/index.js
@@ -1,12 +1,14 @@
-import getStore from "./store"
-import LogRocket from "logrocket";
+import { getStore } from "./store"
+import { getBackendUiStore } from "./store/backend"
+import LogRocket from "logrocket"
export const store = getStore()
+export const backendUiStore = getBackendUiStore()
export const initialise = async () => {
try {
if (process.env.NODE_ENV === "production") {
- LogRocket.init("knlald/budibase");
+ LogRocket.init("knlald/budibase")
}
setupRouter(store)
await store.initialise()
diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js
new file mode 100644
index 0000000000..65f012e34c
--- /dev/null
+++ b/packages/builder/src/builderStore/store/backend.js
@@ -0,0 +1,355 @@
+import { writable } from "svelte/store"
+import api from "../api"
+import { cloneDeep, sortBy, find, remove } from "lodash/fp"
+import { hierarchy as hierarchyFunctions } from "../../../../core/src"
+import {
+ getNode,
+ validate,
+ constructHierarchy,
+ templateApi,
+ isIndex,
+ canDeleteIndex,
+ canDeleteRecord,
+} from "../../common/core"
+
+export const getBackendUiStore = () => {
+ const INITIAL_BACKEND_UI_STATE = {
+ leftNavItem: "DATABASE",
+ selectedView: {
+ records: [],
+ name: "",
+ },
+ breadcrumbs: [],
+ selectedDatabase: {},
+ selectedModel: {},
+ }
+
+ const store = writable(INITIAL_BACKEND_UI_STATE)
+
+ store.actions = {
+ navigate: name => store.update(state => ({ ...state, leftNavItem: name })),
+ database: {
+ select: db =>
+ store.update(state => {
+ state.selectedDatabase = db
+ state.breadcrumbs = [db.name]
+ return state
+ }),
+ },
+ records: {
+ delete: () =>
+ store.update(state => {
+ state.selectedView = state.selectedView
+ return state
+ }),
+ view: record =>
+ store.update(state => {
+ state.breadcrumbs = [state.selectedDatabase.name, record.id]
+ return state
+ }),
+ select: record =>
+ store.update(state => {
+ state.selectedRecord = record
+ return state
+ }),
+ },
+ views: {
+ select: view =>
+ store.update(state => {
+ state.selectedView = view
+ return state
+ }),
+ },
+ modals: {
+ show: modal => store.update(state => ({ ...state, visibleModal: modal })),
+ hide: () => store.update(state => ({ ...state, visibleModal: null })),
+ },
+ users: {
+ create: user =>
+ store.update(state => {
+ state.users.push(user)
+ state.users = state.users
+ return state
+ }),
+ },
+ }
+
+ return store
+}
+
+// Store Actions
+export const createShadowHierarchy = hierarchy =>
+ constructHierarchy(JSON.parse(JSON.stringify(hierarchy)))
+
+export const createDatabaseForApp = store => appInstance => {
+ store.update(state => {
+ state.appInstances.push(appInstance)
+ return state
+ })
+}
+
+export const saveBackend = async state => {
+ await api.post(`/_builder/api/${state.appname}/backend`, {
+ appDefinition: {
+ hierarchy: state.hierarchy,
+ actions: state.actions,
+ triggers: state.triggers,
+ },
+ accessLevels: state.accessLevels,
+ })
+
+ const instances_currentFirst = state.selectedDatabase
+ ? [
+ state.appInstances.find(i => i.id === state.selectedDatabase.id),
+ ...state.appInstances.filter(i => i.id !== state.selectedDatabase.id),
+ ]
+ : state.appInstances
+
+ for (let instance of instances_currentFirst) {
+ await api.post(
+ `/_builder/instance/${state.appname}/${instance.id}/api/upgradeData`,
+ { newHierarchy: state.hierarchy, accessLevels: state.accessLevels }
+ )
+ }
+}
+
+export const newRecord = (store, useRoot) => () => {
+ store.update(state => {
+ state.currentNodeIsNew = true
+ const shadowHierarchy = createShadowHierarchy(state.hierarchy)
+ const parent = useRoot
+ ? shadowHierarchy
+ : getNode(shadowHierarchy, state.currentNode.nodeId)
+ state.errors = []
+ state.currentNode = templateApi(shadowHierarchy).getNewRecordTemplate(
+ parent,
+ "",
+ true
+ )
+ return state
+ })
+}
+
+export const selectExistingNode = store => nodeId => {
+ store.update(state => {
+ state.currentNode = getNode(state.hierarchy, nodeId)
+ state.currentNodeIsNew = false
+ state.errors = []
+ return state
+ })
+}
+
+export const newIndex = (store, useRoot) => () => {
+ store.update(state => {
+ state.shadowHierarchy = createShadowHierarchy(state.hierarchy)
+ state.currentNodeIsNew = true
+ state.errors = []
+ const parent = useRoot
+ ? state.shadowHierarchy
+ : getNode(state.shadowHierarchy, state.currentNode.nodeId)
+
+ state.currentNode = templateApi(state.shadowHierarchy).getNewIndexTemplate(
+ parent
+ )
+ return state
+ })
+}
+
+export const saveCurrentNode = store => () => {
+ store.update(state => {
+ const errors = validate.node(state.currentNode)
+ state.errors = errors
+ if (errors.length > 0) {
+ return state
+ }
+ const parentNode = getNode(
+ state.hierarchy,
+ state.currentNode.parent().nodeId
+ )
+
+ const existingNode = getNode(state.hierarchy, state.currentNode.nodeId)
+
+ let index = parentNode.children.length
+ if (existingNode) {
+ // remove existing
+ index = existingNode.parent().children.indexOf(existingNode)
+ if (isIndex(existingNode)) {
+ parentNode.indexes = parentNode.indexes.filter(
+ node => node.nodeId !== existingNode.nodeId
+ )
+ } else {
+ parentNode.children = parentNode.children.filter(
+ node => node.nodeId !== existingNode.nodeId
+ )
+ }
+ }
+
+ // should add node into existing hierarchy
+ const cloned = cloneDeep(state.currentNode)
+ templateApi(state.hierarchy).constructNode(parentNode, cloned)
+
+ if (isIndex(existingNode)) {
+ parentNode.children = sortBy("name", parentNode.children)
+ } else {
+ parentNode.indexes = sortBy("name", parentNode.indexes)
+ }
+
+ if (!existingNode && state.currentNode.type === "record") {
+ const defaultIndex = templateApi(state.hierarchy).getNewIndexTemplate(
+ cloned.parent()
+ )
+ defaultIndex.name = `all_${cloned.name}s`
+ defaultIndex.allowedRecordNodeIds = [cloned.nodeId]
+ }
+
+ state.currentNodeIsNew = false
+
+ saveBackend(state)
+
+ return state
+ })
+}
+
+export const deleteCurrentNode = store => () => {
+ store.update(state => {
+ const nodeToDelete = getNode(state.hierarchy, state.currentNode.nodeId)
+ state.currentNode = hierarchyFunctions.isRoot(nodeToDelete.parent())
+ ? state.hierarchy.children.find(node => node !== state.currentNode)
+ : nodeToDelete.parent()
+
+ const isRecord = hierarchyFunctions.isRecord(nodeToDelete)
+
+ const check = isRecord
+ ? canDeleteRecord(nodeToDelete)
+ : canDeleteIndex(nodeToDelete)
+
+ if (!check.canDelete) {
+ state.errors = check.errors.map(e => ({ error: e }))
+ return state
+ }
+
+ const recordOrIndexKey = isRecord ? "children" : "indexes"
+
+ // remove the selected record or index
+ const newCollection = remove(
+ node => node.nodeId === nodeToDelete.nodeId,
+ nodeToDelete.parent()[recordOrIndexKey]
+ )
+
+ nodeToDelete.parent()[recordOrIndexKey] = newCollection
+
+ state.errors = []
+ saveBackend(state)
+ return state
+ })
+}
+
+export const saveField = store => field => {
+ store.update(state => {
+ state.currentNode.fields = state.currentNode.fields.filter(
+ f => f.id !== field.id
+ )
+
+ templateApi(state.hierarchy).addField(state.currentNode, field)
+ return state
+ })
+}
+
+export const deleteField = store => field => {
+ store.update(state => {
+ state.currentNode.fields = state.currentNode.fields.filter(
+ f => f.name !== field.name
+ )
+ return state
+ })
+}
+
+const incrementAccessLevelsVersion = state => {
+ state.accessLevels.version = state.accessLevels.version
+ ? state.accessLevels.version + 1
+ : 1
+ return state
+}
+
+export const saveLevel = store => (newLevel, isNew, oldLevel = null) => {
+ store.update(state => {
+ const levels = state.accessLevels.levels
+
+ const existingLevel = isNew
+ ? null
+ : find(a => a.name === oldLevel.name)(levels)
+
+ if (existingLevel) {
+ state.accessLevels.levels = levels.map(level =>
+ level === existingLevel ? newLevel : level
+ )
+ } else {
+ state.accessLevels.levels.push(newLevel)
+ }
+
+ incrementAccessLevelsVersion(state)
+
+ saveBackend(state)
+ return state
+ })
+}
+
+export const deleteLevel = store => level => {
+ store.update(state => {
+ state.accessLevels.levels = state.accessLevels.levels.filter(
+ t => t.name !== level.name
+ )
+ incrementAccessLevelsVersion(s)
+ saveBackend(state)
+ return state
+ })
+}
+
+export const saveAction = store => (newAction, isNew, oldAction = null) => {
+ store.update(s => {
+ const existingAction = isNew
+ ? null
+ : find(a => a.name === oldAction.name)(s.actions)
+
+ if (existingAction) {
+ s.actions = s.actions.map(action =>
+ action === existingAction ? newAction : action
+ )
+ } else {
+ s.actions.push(newAction)
+ }
+ saveBackend(s)
+ return s
+ })
+}
+
+export const deleteAction = store => action => {
+ store.update(state => {
+ state.actions = state.actions.filter(a => a.name !== action.name)
+ saveBackend(state)
+ return state
+ })
+}
+
+export const saveTrigger = store => (newTrigger, isNew, oldTrigger = null) => {
+ store.update(s => {
+ const existingTrigger = isNew
+ ? null
+ : s.triggers.find(a => a.name === oldTrigger.name)
+
+ if (existingTrigger) {
+ s.triggers = s.triggers.map(a => (a === existingTrigger ? newTrigger : a))
+ } else {
+ s.triggers.push(newTrigger)
+ }
+ saveBackend(s)
+ return s
+ })
+}
+
+export const deleteTrigger = store => trigger => {
+ store.update(s => {
+ s.triggers = s.triggers.filter(t => t.name !== trigger.name)
+ return s
+ })
+}
diff --git a/packages/builder/src/builderStore/store.js b/packages/builder/src/builderStore/store/index.js
similarity index 64%
rename from packages/builder/src/builderStore/store.js
rename to packages/builder/src/builderStore/store/index.js
index 7753fa255d..d7be2fe92a 100644
--- a/packages/builder/src/builderStore/store.js
+++ b/packages/builder/src/builderStore/store/index.js
@@ -1,39 +1,23 @@
-import { hierarchy as hierarchyFunctions } from "../../../core/src"
-import {
- filter,
- cloneDeep,
- sortBy,
- map,
- last,
- concat,
- find,
- isEmpty,
- values,
-} from "lodash/fp"
-import {
- pipe,
- getNode,
- validate,
- constructHierarchy,
- templateApi,
-} from "../common/core"
+import { filter, cloneDeep, last, concat, isEmpty, values } from "lodash/fp"
+import { pipe, getNode, constructHierarchy } from "../../common/core"
+import * as backendStoreActions from "./backend"
import { writable } from "svelte/store"
-import { defaultPagesObject } from "../userInterface/pagesParsing/defaultPagesObject"
-import api from "./api"
-import { getExactComponent } from "../userInterface/pagesParsing/searchComponents"
-import { rename } from "../userInterface/pagesParsing/renameScreen"
+import { defaultPagesObject } from "../../userInterface/pagesParsing/defaultPagesObject"
+import api from "../api"
+import { getExactComponent } from "../../userInterface/pagesParsing/searchComponents"
+import { rename } from "../../userInterface/pagesParsing/renameScreen"
import {
getNewScreen,
createProps,
makePropsSafe,
getBuiltin,
-} from "../userInterface/pagesParsing/createProps"
-import { expandComponentDefinition } from "../userInterface/pagesParsing/types"
-import { loadLibs, libUrlsForPreview } from "./loadComponentLibraries"
-import { buildCodeForScreens } from "./buildCodeForScreens"
-import { generate_screen_css } from "./generate_css"
-import { insertCodeMetadata } from "./insertCodeMetadata"
-import { uuid } from "./uuid"
+} from "../../userInterface/pagesParsing/createProps"
+import { expandComponentDefinition } from "../../userInterface/pagesParsing/types"
+import { loadLibs, libUrlsForPreview } from "../loadComponentLibraries"
+import { buildCodeForScreens } from "../buildCodeForScreens"
+import { generate_screen_css } from "../generate_css"
+import { insertCodeMetadata } from "../insertCodeMetadata"
+import { uuid } from "../uuid"
let appname = ""
@@ -55,8 +39,6 @@ export const getStore = () => {
currentComponentProps: null,
currentNodeIsNew: false,
errors: [],
- activeNav: "database",
- isBackend: true,
hasAppPackage: false,
accessLevels: { version: 0, levels: [] },
currentNode: null,
@@ -68,23 +50,25 @@ export const getStore = () => {
const store = writable(initial)
store.initialise = initialise(store, initial)
- store.newChildRecord = newRecord(store, false)
- store.newRootRecord = newRecord(store, true)
- store.selectExistingNode = selectExistingNode(store)
- store.newChildIndex = newIndex(store, false)
- store.newRootIndex = newIndex(store, true)
- store.saveCurrentNode = saveCurrentNode(store)
+
+ store.newChildRecord = backendStoreActions.newRecord(store, false)
+ store.newRootRecord = backendStoreActions.newRecord(store, true)
+ store.selectExistingNode = backendStoreActions.selectExistingNode(store)
+ store.newChildIndex = backendStoreActions.newIndex(store, false)
+ store.newRootIndex = backendStoreActions.newIndex(store, true)
+ store.saveCurrentNode = backendStoreActions.saveCurrentNode(store)
+ store.deleteCurrentNode = backendStoreActions.deleteCurrentNode(store)
+ store.saveField = backendStoreActions.saveField(store)
+ store.deleteField = backendStoreActions.deleteField(store)
+ store.saveLevel = backendStoreActions.saveLevel(store)
+ store.deleteLevel = backendStoreActions.deleteLevel(store)
+ store.createDatabaseForApp = backendStoreActions.createDatabaseForApp(store)
+ store.saveAction = backendStoreActions.saveAction(store)
+ store.deleteAction = backendStoreActions.deleteAction(store)
+ store.saveTrigger = backendStoreActions.saveTrigger(store)
+ store.deleteTrigger = backendStoreActions.deleteTrigger(store)
store.importAppDefinition = importAppDefinition(store)
- store.deleteCurrentNode = deleteCurrentNode(store)
- store.saveField = saveField(store)
- store.deleteField = deleteField(store)
- store.saveAction = saveAction(store)
- store.deleteAction = deleteAction(store)
- store.saveTrigger = saveTrigger(store)
- store.deleteTrigger = deleteTrigger(store)
- store.saveLevel = saveLevel(store)
- store.deleteLevel = deleteLevel(store)
- store.setActiveNav = setActiveNav(store)
+
store.saveScreen = saveScreen(store)
store.addComponentLibrary = addComponentLibrary(store)
store.renameScreen = renameScreen(store)
@@ -96,8 +80,6 @@ export const getStore = () => {
store.addStylesheet = addStylesheet(store)
store.removeStylesheet = removeStylesheet(store)
store.savePage = savePage(store)
- store.showFrontend = showFrontend(store)
- store.showBackend = showBackend(store)
store.showSettings = showSettings(store)
store.useAnalytics = useAnalytics(store)
store.createGeneratedComponents = createGeneratedComponents(store)
@@ -159,10 +141,6 @@ const initialise = (store, initial) => async () => {
}
initial.appname = appname
initial.pages = pkg.pages
- initial.currentInstanceId =
- pkg.application.instances && pkg.application.instances.length > 0
- ? pkg.application.instances[0].id
- : ""
initial.hasAppPackage = true
initial.hierarchy = pkg.appDefinition.hierarchy
initial.accessLevels = pkg.accessLevels
@@ -174,12 +152,15 @@ const initialise = (store, initial) => async () => {
initial.builtins = [getBuiltin("##builtin/screenslot")]
initial.actions = values(pkg.appDefinition.actions)
initial.triggers = pkg.appDefinition.triggers
+ initial.appInstances = pkg.application.instances
+ initial.appId = pkg.application.id
if (!!initial.hierarchy && !isEmpty(initial.hierarchy)) {
initial.hierarchy = constructHierarchy(initial.hierarchy)
const shadowHierarchy = createShadowHierarchy(initial.hierarchy)
- if (initial.currentNode !== null)
+ if (initial.currentNode !== null) {
initial.currentNode = getNode(shadowHierarchy, initial.currentNode.nodeId)
+ }
}
store.set(initial)
@@ -187,121 +168,16 @@ const initialise = (store, initial) => async () => {
}
const showSettings = store => () => {
- store.update(s => {
- s.showSettings = !s.showSettings
- return s
+ store.update(state => {
+ state.showSettings = !state.showSettings
+ return state
})
}
const useAnalytics = store => () => {
- store.update(s => {
- s.useAnalytics = !s.useAnalytics
- return s
- })
-}
-
-const showBackend = store => () => {
- store.update(s => {
- s.isBackend = true
- return s
- })
-}
-
-const showFrontend = store => () => {
- store.update(s => {
- s.isBackend = false
- return s
- })
-}
-
-const newRecord = (store, useRoot) => () => {
- store.update(s => {
- s.currentNodeIsNew = true
- const shadowHierarchy = createShadowHierarchy(s.hierarchy)
- const parent = useRoot
- ? shadowHierarchy
- : getNode(shadowHierarchy, s.currentNode.nodeId)
- s.errors = []
- s.currentNode = templateApi(shadowHierarchy).getNewRecordTemplate(
- parent,
- "",
- true
- )
- return s
- })
-}
-
-const selectExistingNode = store => nodeId => {
- store.update(s => {
- const shadowHierarchy = createShadowHierarchy(s.hierarchy)
- s.currentNode = getNode(shadowHierarchy, nodeId)
- s.currentNodeIsNew = false
- s.errors = []
- s.activeNav = "database"
- return s
- })
-}
-
-const newIndex = (store, useRoot) => () => {
- store.update(s => {
- s.currentNodeIsNew = true
- s.errors = []
- const shadowHierarchy = createShadowHierarchy(s.hierarchy)
- const parent = useRoot
- ? shadowHierarchy
- : getNode(shadowHierarchy, s.currentNode.nodeId)
-
- s.currentNode = templateApi(shadowHierarchy).getNewIndexTemplate(parent)
- return s
- })
-}
-
-const saveCurrentNode = store => () => {
- store.update(s => {
- const errors = validate.node(s.currentNode)
- s.errors = errors
- if (errors.length > 0) {
- return s
- }
-
- const parentNode = getNode(s.hierarchy, s.currentNode.parent().nodeId)
-
- const existingNode = getNode(s.hierarchy, s.currentNode.nodeId)
-
- let index = parentNode.children.length
- if (existingNode) {
- // remove existing
- index = existingNode.parent().children.indexOf(existingNode)
- existingNode.parent().children = pipe(existingNode.parent().children, [
- filter(c => c.nodeId !== existingNode.nodeId),
- ])
- }
-
- // should add node into existing hierarchy
- const cloned = cloneDeep(s.currentNode)
- templateApi(s.hierarchy).constructNode(parentNode, cloned)
-
- const newIndexOfChild = child => {
- if (child === cloned) return index
- const currentIndex = parentNode.children.indexOf(child)
- return currentIndex >= index ? currentIndex + 1 : currentIndex
- }
-
- parentNode.children = pipe(parentNode.children, [sortBy(newIndexOfChild)])
-
- if (!existingNode && s.currentNode.type === "record") {
- const defaultIndex = templateApi(s.hierarchy).getNewIndexTemplate(
- cloned.parent()
- )
- defaultIndex.name = `all_${cloned.collectionName}`
- defaultIndex.allowedRecordNodeIds = [cloned.nodeId]
- }
-
- s.currentNodeIsNew = false
-
- saveBackend(s)
-
- return s
+ store.update(state => {
+ state.useAnalytics = !state.useAnalytics
+ return state
})
}
@@ -319,143 +195,6 @@ const importAppDefinition = store => appDefinition => {
})
}
-const deleteCurrentNode = store => () => {
- store.update(s => {
- const nodeToDelete = getNode(s.hierarchy, s.currentNode.nodeId)
- s.currentNode = hierarchyFunctions.isRoot(nodeToDelete.parent())
- ? find(n => n != s.currentNode)(s.hierarchy.children)
- : nodeToDelete.parent()
- if (hierarchyFunctions.isRecord(nodeToDelete)) {
- nodeToDelete.parent().children = filter(
- c => c.nodeId !== nodeToDelete.nodeId
- )(nodeToDelete.parent().children)
- } else {
- nodeToDelete.parent().indexes = filter(
- c => c.nodeId !== nodeToDelete.nodeId
- )(nodeToDelete.parent().indexes)
- }
- s.errors = []
- saveBackend(s)
- return s
- })
-}
-
-const saveField = databaseStore => field => {
- databaseStore.update(db => {
- db.currentNode.fields = filter(f => f.name !== field.name)(
- db.currentNode.fields
- )
-
- templateApi(db.hierarchy).addField(db.currentNode, field)
- return db
- })
-}
-
-const deleteField = databaseStore => field => {
- databaseStore.update(db => {
- db.currentNode.fields = filter(f => f.name !== field.name)(
- db.currentNode.fields
- )
-
- return db
- })
-}
-
-const saveAction = store => (newAction, isNew, oldAction = null) => {
- store.update(s => {
- const existingAction = isNew
- ? null
- : find(a => a.name === oldAction.name)(s.actions)
-
- if (existingAction) {
- s.actions = pipe(s.actions, [
- map(a => (a === existingAction ? newAction : a)),
- ])
- } else {
- s.actions.push(newAction)
- }
- saveBackend(s)
- return s
- })
-}
-
-const deleteAction = store => action => {
- store.update(s => {
- s.actions = filter(a => a.name !== action.name)(s.actions)
- saveBackend(s)
- return s
- })
-}
-
-const saveTrigger = store => (newTrigger, isNew, oldTrigger = null) => {
- store.update(s => {
- const existingTrigger = isNew
- ? null
- : find(a => a.name === oldTrigger.name)(s.triggers)
-
- if (existingTrigger) {
- s.triggers = pipe(s.triggers, [
- map(a => (a === existingTrigger ? newTrigger : a)),
- ])
- } else {
- s.triggers.push(newTrigger)
- }
- saveBackend(s)
- return s
- })
-}
-
-const deleteTrigger = store => trigger => {
- store.update(s => {
- s.triggers = filter(t => t.name !== trigger.name)(s.triggers)
- return s
- })
-}
-
-const incrementAccessLevelsVersion = s =>
- (s.accessLevels.version = (s.accessLevels.version || 0) + 1)
-
-const saveLevel = store => (newLevel, isNew, oldLevel = null) => {
- store.update(s => {
- const levels = s.accessLevels.levels
-
- const existingLevel = isNew
- ? null
- : find(a => a.name === oldLevel.name)(levels)
-
- if (existingLevel) {
- s.accessLevels.levels = pipe(levels, [
- map(a => (a === existingLevel ? newLevel : a)),
- ])
- } else {
- s.accessLevels.levels.push(newLevel)
- }
-
- incrementAccessLevelsVersion(s)
-
- saveBackend(s)
- return s
- })
-}
-
-const deleteLevel = store => level => {
- store.update(s => {
- s.accessLevels.levels = filter(t => t.name !== level.name)(
- s.accessLevels.levels
- )
- incrementAccessLevelsVersion(s)
- saveBackend(s)
- return s
- })
-}
-
-const setActiveNav = store => navName => {
- store.update(s => {
- s.activeNav = navName
- return s
- })
-}
-
const createShadowHierarchy = hierarchy =>
constructHierarchy(JSON.parse(JSON.stringify(hierarchy)))
@@ -474,55 +213,27 @@ const _saveScreen = async (store, s, screen) => {
screen
)
.then(() => {
+ if (currentPageScreens.includes(screen)) return
- if(currentPageScreens.includes(screen)) return
-
- const screens = [
- ...currentPageScreens,
- screen,
- ]
+ const screens = [...currentPageScreens, screen]
store.update(innerState => {
innerState.pages[s.currentPageName]._screens = screens
innerState.screens = screens
innerState.currentPreviewItem = screen
const safeProps = makePropsSafe(
- getComponentDefinition(innerState.components, screen.props._component),
+ getComponentDefinition(
+ innerState.components,
+ screen.props._component
+ ),
screen.props
)
innerState.currentComponentInfo = safeProps
screen.props = safeProps
-
+
_savePage(innerState)
return innerState
})
-
-
-
- /*const updatedScreen = await savedScreen.json()
- const screens = [
- ...currentPageScreens.filter(
- storeScreen => storeScreen.name !== updatedScreen.name
- ),
- updatedScreen,
- ]
- store.update(innerState => {
- innerState.pages[s.currentPageName]._screens = screens
- innerState.screens = screens
-
- let curentComponentId
- walkProps(screen.props, p => {
- if(p === innerState.currentComponentInfo)
- currentComponentId = p._id
- })
-
- innerState.currentPreviewItem = updatedScreen
- innerState.currentComponentInfo = makePropsSafe(componentDef, component)
-
- _savePage(innerState)
- return innerState
- })
- */
})
return s
@@ -732,17 +443,6 @@ const _savePage = async s => {
})
}
-const saveBackend = async state => {
- await api.post(`/_builder/api/${appname}/backend`, {
- appDefinition: {
- hierarchy: state.hierarchy,
- actions: state.actions,
- triggers: state.triggers,
- },
- accessLevels: state.accessLevels,
- })
-}
-
const setCurrentPage = store => pageName => {
store.update(s => {
const current_screens = s.pages[pageName]._screens
@@ -772,10 +472,7 @@ const setCurrentPage = store => pageName => {
})
}
-const getContainerComponent = components =>
- getComponentDefinition(components, "@budibase/standard-components/container")
-
-const getComponentDefinition = (components, name) =>
+const getComponentDefinition = (components, name) =>
components.find(c => c.name === name)
/**
@@ -834,8 +531,11 @@ const addTemplatedComponent = store => props => {
state.currentComponentInfo._children = state.currentComponentInfo._children.concat(
props
)
- state.currentPreviewItem._css = generate_screen_css([state.currentPreviewItem.props])
+ state.currentPreviewItem._css = generate_screen_css([
+ state.currentPreviewItem.props,
+ ])
+ setCurrentPageFunctions(state)
_saveCurrentPreviewItem(state)
return state
diff --git a/packages/builder/src/common/CodeArea.svelte b/packages/builder/src/common/CodeArea.svelte
index 4ef86a6602..a58fc12240 100644
--- a/packages/builder/src/common/CodeArea.svelte
+++ b/packages/builder/src/common/CodeArea.svelte
@@ -2,36 +2,20 @@
import { JavaScriptIcon } from "../common/Icons"
// todo: use https://ace.c9.io
export let text = ""
- export let label = ""
- export let javascript = false
-
diff --git a/packages/builder/src/common/ConfirmDialog.svelte b/packages/builder/src/common/ConfirmDialog.svelte
index 8b69a120ad..98524caa18 100644
--- a/packages/builder/src/common/ConfirmDialog.svelte
+++ b/packages/builder/src/common/ConfirmDialog.svelte
@@ -53,14 +53,12 @@
diff --git a/packages/builder/src/common/ErrorsBox.svelte b/packages/builder/src/common/ErrorsBox.svelte
index 9ddea77a49..727ef3f2b3 100644
--- a/packages/builder/src/common/ErrorsBox.svelte
+++ b/packages/builder/src/common/ErrorsBox.svelte
@@ -5,25 +5,9 @@
{#if hasErrors}
-
+
{#each errors as error}
-
- {error.field ? `${error.field}: ` : ''}{error.error}
-
+
{error.field ? `${error.field}: ` : ''}{error.error}
{/each}
{/if}
-
-
diff --git a/packages/builder/src/common/Icons/Preview.svelte b/packages/builder/src/common/Icons/Preview.svelte
index d9c7ce73da..b32fce951a 100644
--- a/packages/builder/src/common/Icons/Preview.svelte
+++ b/packages/builder/src/common/Icons/Preview.svelte
@@ -1,9 +1,12 @@
-
\ No newline at end of file
+
+
+
diff --git a/packages/builder/src/common/Icons/Settings.svelte b/packages/builder/src/common/Icons/Settings.svelte
index 38487fba51..d942d22b34 100644
--- a/packages/builder/src/common/Icons/Settings.svelte
+++ b/packages/builder/src/common/Icons/Settings.svelte
@@ -3,6 +3,9 @@
viewBox="0 0 24 24"
width="24"
height="24">
-
-
-
\ No newline at end of file
+
+
+
diff --git a/packages/builder/src/common/Icons/index.js b/packages/builder/src/common/Icons/index.js
index 3a926d378c..f62fb42ca0 100644
--- a/packages/builder/src/common/Icons/index.js
+++ b/packages/builder/src/common/Icons/index.js
@@ -18,4 +18,3 @@ export { default as AddIcon } from "./Add.svelte"
export { default as JavaScriptIcon } from "./JavaScript.svelte"
export { default as PreviewIcon } from "./Preview.svelte"
export { default as SettingsIcon } from "./Settings.svelte"
-
diff --git a/packages/builder/src/common/Modal.svelte b/packages/builder/src/common/Modal.svelte
index 09aac1a8bb..807dcee922 100644
--- a/packages/builder/src/common/Modal.svelte
+++ b/packages/builder/src/common/Modal.svelte
@@ -3,7 +3,7 @@
import ActionButton from "../common/ActionButton.svelte"
export let isOpen = false
- export let onClosed = () => {}
+ export let onClosed
export let id = ""
export let title
@@ -27,19 +27,24 @@
-
- {#if title}
-
- {/if}
-
- {#if onClosed}
-
+ {#if isOpen}
+
+ {#if title}
+
{/if}
-
+
+ {#if onClosed}
+
+ {/if}
+
+
+
-
+ {/if}
diff --git a/packages/builder/src/common/Select.svelte b/packages/builder/src/common/Select.svelte
index de0c57fc41..1fd2c06935 100644
--- a/packages/builder/src/common/Select.svelte
+++ b/packages/builder/src/common/Select.svelte
@@ -1,10 +1,15 @@
-