diff --git a/packages/client/package.json b/packages/client/package.json
index d7fea8dd64..71fb4b6e87 100644
--- a/packages/client/package.json
+++ b/packages/client/package.json
@@ -15,17 +15,17 @@
"svelte-spa-router": "^3.0.5"
},
"devDependencies": {
+ "@budibase/standard-components": "^0.3.8",
+ "@rollup/plugin-alias": "^3.1.1",
+ "@rollup/plugin-commonjs": "^16.0.0",
+ "@rollup/plugin-node-resolve": "^10.0.0",
"fs-extra": "^8.1.0",
"jsdom": "^16.0.1",
- "rollup": "^2.11.2",
- "rollup-plugin-alias": "^2.2.0",
- "rollup-plugin-commonjs": "^10.0.0",
+ "rollup": "^2.33.2",
"rollup-plugin-node-builtins": "^2.1.2",
"rollup-plugin-node-globals": "^1.4.0",
- "rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-svelte": "^6.1.1",
- "svelte": "3.29.0",
- "svelte-jester": "^1.0.6"
+ "svelte": "^3.29.0"
},
"gitHead": "e4e053cb6ff9a0ddc7115b44ccaa24b8ec41fb9a"
}
diff --git a/packages/client/rollup.config.js b/packages/client/rollup.config.js
index c4b2e51a8f..413372416b 100644
--- a/packages/client/rollup.config.js
+++ b/packages/client/rollup.config.js
@@ -1,9 +1,8 @@
-import resolve from "rollup-plugin-node-resolve"
-import commonjs from "rollup-plugin-commonjs"
+import alias from "@rollup/plugin-alias"
+import commonjs from "@rollup/plugin-commonjs"
+import resolve from "@rollup/plugin-node-resolve"
import builtins from "rollup-plugin-node-builtins"
-import nodeglobals from "rollup-plugin-node-globals"
import svelte from "rollup-plugin-svelte"
-import alias from "rollup-plugin-alias"
import path from "path"
const production = !process.env.ROLLUP_WATCH
@@ -13,13 +12,7 @@ export default {
input: "src/index.js",
output: [
{
- sourcemap: true,
- format: "iife",
- name: "app",
- file: `./dist/budibase-client.js`,
- },
- {
- file: "dist/budibase-client.esm.mjs",
+ file: "dist/budibase-client.js",
format: "esm",
sourcemap: "inline",
},
@@ -45,7 +38,6 @@ export default {
}),
commonjs(),
builtins(),
- nodeglobals(),
],
watch: {
clearScreen: false,
diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte
index dbf19e0865..a3adef6e34 100644
--- a/packages/client/src/components/ClientApp.svelte
+++ b/packages/client/src/components/ClientApp.svelte
@@ -2,11 +2,10 @@
import { onMount } from "svelte"
import { componentStore } from "../store"
import Component from "./Component.svelte"
- import { getValidProps } from "../utils"
let frontendDefinition
let loaded = false
- $: pageProps = frontendDefinition?.page?.props
+ $: pageDefinition = frontendDefinition?.page?.props
onMount(async () => {
frontendDefinition = window["##BUDIBASE_FRONTEND_DEFINITION##"]
@@ -17,9 +16,5 @@
{#if loaded}
-
+
{/if}
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte
index 5b0565eb94..4e4df7664c 100644
--- a/packages/client/src/components/Component.svelte
+++ b/packages/client/src/components/Component.svelte
@@ -1,31 +1,35 @@
-{#if componentConstructor}
-
-
- {#if children && children.length}
- {#each children as child}
-
- {/each}
- {/if}
-
-
+{#if constructor}
+
+ {#if children && children.length}
+ {#each children as child}
+
+ {/each}
+ {/if}
+
{/if}
diff --git a/packages/client/src/components/Router.svelte b/packages/client/src/components/Router.svelte
index b08dc4d5a4..3b5cd675c6 100644
--- a/packages/client/src/components/Router.svelte
+++ b/packages/client/src/components/Router.svelte
@@ -1,9 +1,10 @@
{#if routes}
-
+
+
+
{/if}
diff --git a/packages/client/src/components/Screen.svelte b/packages/client/src/components/Screen.svelte
index 35c4fbfc14..894e1b0ea2 100644
--- a/packages/client/src/components/Screen.svelte
+++ b/packages/client/src/components/Screen.svelte
@@ -1,20 +1,24 @@
{#if screenDefinition}
-
+
{/if}
diff --git a/packages/client/src/index.js b/packages/client/src/index.js
index 68f5d2d701..cb00d4b708 100644
--- a/packages/client/src/index.js
+++ b/packages/client/src/index.js
@@ -2,6 +2,7 @@ import ClientApp from "./components/ClientApp.svelte"
// Initialise client app
const loadBudibase = () => {
+ window.document.body.innerHTML = ""
new ClientApp({
target: window.document.body,
})
diff --git a/packages/client/src/store/components.js b/packages/client/src/store/components.js
index eed1c87325..4ab0a85b3f 100644
--- a/packages/client/src/store/components.js
+++ b/packages/client/src/store/components.js
@@ -2,10 +2,8 @@ import { writable, get } from "svelte/store"
import { getAppId } from "@budibase/component-sdk"
import Router from "../components/Router.svelte"
-const initialState = {}
-
-export const createComponentStore = () => {
- const store = writable(initialState)
+const createComponentStore = () => {
+ const store = writable({})
/**
* Loads the component library from the server
@@ -25,14 +23,13 @@ export const createComponentStore = () => {
if (!componentName) {
return null
}
- const split = componentName.split("/")
- const strippedName = split[split.length - 1]
// Edge case for screen slot
- if (strippedName === "screenslot") {
+ if (componentName === "screenslot") {
return Router
}
- return get(store)[strippedName]
+
+ return get(store)[componentName]
}
// Attach actions to the store
@@ -40,3 +37,5 @@ export const createComponentStore = () => {
return store
}
+
+export const componentStore = createComponentStore()
diff --git a/packages/client/src/store/index.js b/packages/client/src/store/index.js
index ea0a3b5709..08a4ea7e95 100644
--- a/packages/client/src/store/index.js
+++ b/packages/client/src/store/index.js
@@ -1,3 +1 @@
-import { createComponentStore } from "./components"
-
-export const componentStore = createComponentStore()
+export { componentStore } from "./components"
diff --git a/packages/client/src/utils.js b/packages/client/src/utils.js
index 6df8fd6d40..0a08ce8386 100644
--- a/packages/client/src/utils.js
+++ b/packages/client/src/utils.js
@@ -1,16 +1,3 @@
-/**
- * Builds a style string from a style object.
- */
-export const buildStyle = styles => {
- let str = ""
- Object.entries(styles).forEach(([style, value]) => {
- if (style && value) {
- str += `${style}: ${value}; `
- }
- })
- return str
-}
-
/**
* Extracts all valid props from a component definition that should be passed to
* its actual component instance.
diff --git a/packages/component-sdk/package.json b/packages/component-sdk/package.json
index 2087d6e52d..9681576e11 100644
--- a/packages/component-sdk/package.json
+++ b/packages/component-sdk/package.json
@@ -21,6 +21,7 @@
"rollup-plugin-svelte": "^6.1.1"
},
"dependencies": {
+ "svelte": "^3.29.0",
"svelte-spa-router": "^3.0.5"
}
}
diff --git a/packages/component-sdk/src/api/rows.js b/packages/component-sdk/src/api/rows.js
index 5875300546..a8b16a1c06 100644
--- a/packages/component-sdk/src/api/rows.js
+++ b/packages/component-sdk/src/api/rows.js
@@ -14,21 +14,19 @@ export const fetchRow = async ({ tableId, rowId }) => {
/**
* Creates a row in a table.
*/
-export const saveRow = async (params, state) => {
+export const saveRow = async row => {
return await api.post({
- url: `/api/${params.tableId}/rows`,
- body: makeRowRequestBody(params, state),
+ url: `/api/${row.tableId}/rows`,
+ body: row,
})
}
/**
* Updates a row in a table.
*/
-export const updateRow = async (params, state) => {
- const row = makeRowRequestBody(params, state)
- row._id = params._id
+export const updateRow = async row => {
return await api.patch({
- url: `/api/${params.tableId}/rows/${params._id}`,
+ url: `/api/${row.tableId}/rows/${row._id}`,
body: row,
})
}
@@ -55,44 +53,6 @@ export const deleteRows = async ({ tableId, rows }) => {
})
}
-/**
- * Sanitises and parses column types when saving and updating rows.
- */
-const makeRowRequestBody = (parameters, state) => {
- // start with the row thats currently in context
- const body = { ...(state.data || {}) }
-
- // dont send the table
- if (body._table) delete body._table
-
- // then override with supplied parameters
- if (parameters.fields) {
- for (let fieldName of Object.keys(parameters.fields)) {
- const field = parameters.fields[fieldName]
-
- // ensure fields sent are of the correct type
- if (field.type === "boolean") {
- if (field.value === "true") body[fieldName] = true
- if (field.value === "false") body[fieldName] = false
- } else if (field.type === "number") {
- const val = parseFloat(field.value)
- if (!isNaN(val)) {
- body[fieldName] = val
- }
- } else if (field.type === "datetime") {
- const date = new Date(field.value)
- if (!isNaN(date.getTime())) {
- body[fieldName] = date.toISOString()
- }
- } else {
- body[fieldName] = field.value
- }
- }
- }
-
- return body
-}
-
/**
* Enriches rows which contain certain field types so that they can
* be properly displayed.
diff --git a/packages/component-sdk/src/context/contextTypes.js b/packages/component-sdk/src/context/contextTypes.js
new file mode 100644
index 0000000000..3092147d30
--- /dev/null
+++ b/packages/component-sdk/src/context/contextTypes.js
@@ -0,0 +1 @@
+export const DataProvider = "bb-data-provider"
diff --git a/packages/component-sdk/src/context/dataProvider.js b/packages/component-sdk/src/context/dataProvider.js
new file mode 100644
index 0000000000..10d1b88cfb
--- /dev/null
+++ b/packages/component-sdk/src/context/dataProvider.js
@@ -0,0 +1,24 @@
+import { writable } from "svelte/store"
+
+export const createDataProviderContext = () => {
+ const store = writable({
+ rows: [],
+ table: null,
+ })
+ const setRows = rows => {
+ store.update(state => {
+ state.rows = rows
+ return state
+ })
+ }
+ const setTable = table => {
+ store.update(state => {
+ state.table = table
+ return state
+ })
+ }
+ return {
+ subscribe: store.subscribe,
+ actions: { setRows, setTable },
+ }
+}
diff --git a/packages/component-sdk/src/context/index.js b/packages/component-sdk/src/context/index.js
index ba5c1047ce..45c7f54d88 100644
--- a/packages/component-sdk/src/context/index.js
+++ b/packages/component-sdk/src/context/index.js
@@ -1 +1,2 @@
-export const RouterContext = "bb-router"
+export * from "./dataProvider"
+export * as ContextTypes from "./contextTypes"
diff --git a/packages/component-sdk/src/index.js b/packages/component-sdk/src/index.js
index 64af7c9cb5..81228a5503 100644
--- a/packages/component-sdk/src/index.js
+++ b/packages/component-sdk/src/index.js
@@ -1,5 +1,5 @@
export * from "./api"
export * from "./store"
-export * as ContextTypes from "./context"
-export { getAppId } from "./utils"
-export { link } from "svelte-spa-router"
+export * from "./context"
+export * from "./utils"
+export { link as linkable } from "svelte-spa-router"
diff --git a/packages/component-sdk/src/store/auth.js b/packages/component-sdk/src/store/auth.js
index 287dab767d..bca9e4935e 100644
--- a/packages/component-sdk/src/store/auth.js
+++ b/packages/component-sdk/src/store/auth.js
@@ -1,11 +1,9 @@
-import { localStorageStore } from "../../../builder/src/builderStore/store/localStorage"
import * as api from "../api"
import { getAppId } from "../utils"
-
-const initialState = ""
+import { writable } from "svelte/store"
export const createAuthStore = () => {
- const store = localStorageStore("budibase:token", initialState)
+ const store = writable("")
/**
* Logs a user in.
@@ -22,7 +20,7 @@ export const createAuthStore = () => {
* Logs a user out.
*/
const logOut = () => {
- store.set(initialState)
+ store.set("")
// Expire any cookies
const appId = getAppId()
@@ -33,10 +31,14 @@ export const createAuthStore = () => {
}
}
- store.actions = {
- logIn,
- logOut,
+ return {
+ subscribe: store.subscribe,
+ actions: { logIn, logOut },
}
-
- return store
}
+
+if (!window.bbSDKAuthStore) {
+ window.bbSDKAuthStore = createAuthStore()
+}
+
+export const authStore = window.bbSDKAuthStore
diff --git a/packages/component-sdk/src/store/config.js b/packages/component-sdk/src/store/config.js
index b6978d6f77..934a62d939 100644
--- a/packages/component-sdk/src/store/config.js
+++ b/packages/component-sdk/src/store/config.js
@@ -37,11 +37,14 @@ export const createConfigStore = () => {
handler && handler(error)
}
- store.actions = {
- initialise,
- reset,
- handleError,
+ return {
+ subscribe: store.subscribe,
+ actions: { initialise, reset, handleError },
}
-
- return store
}
+
+if (!window.bbSDKConfigStore) {
+ window.bbSDKConfigStore = createConfigStore()
+}
+
+export const configStore = window.bbSDKConfigStore
diff --git a/packages/component-sdk/src/store/index.js b/packages/component-sdk/src/store/index.js
index 91baa595b3..75777e10ed 100644
--- a/packages/component-sdk/src/store/index.js
+++ b/packages/component-sdk/src/store/index.js
@@ -1,9 +1,4 @@
-import { createConfigStore } from "./config"
-import { createAuthStore } from "./auth"
-import { createRouteStore } from "./routes"
-import { createScreenStore } from "./screens"
-
-export const configStore = createConfigStore()
-export const authStore = createAuthStore()
-export const routeStore = createRouteStore()
-export const screenStore = createScreenStore()
+export { configStore } from "./config"
+export { authStore } from "./auth"
+export { routeStore } from "./routes"
+export { screenStore } from "./screens"
diff --git a/packages/component-sdk/src/store/routes.js b/packages/component-sdk/src/store/routes.js
index 50eb072938..7520a4345b 100644
--- a/packages/component-sdk/src/store/routes.js
+++ b/packages/component-sdk/src/store/routes.js
@@ -1,9 +1,12 @@
import { writable } from "svelte/store"
import { push } from "svelte-spa-router"
-const initialState = []
-
export const createRouteStore = () => {
+ const initialState = {
+ routes: [],
+ routeParams: {},
+ activeRoute: null,
+ }
const store = writable(initialState)
const fetchRoutes = () => {
@@ -12,10 +15,35 @@ export const createRouteStore = () => {
path: screen.route,
screenId: screen._id,
}))
- store.set(routes)
+ store.update(state => {
+ state.routes = routes
+ return state
+ })
+ }
+ const setRouteParams = routeParams => {
+ console.log("new route params: ")
+ console.log(routeParams)
+ store.update(state => {
+ state.routeParams = routeParams
+ return state
+ })
+ }
+ const setActiveRoute = route => {
+ store.update(state => {
+ state.activeRoute = route
+ return state
+ })
}
const navigate = push
- store.actions = { fetchRoutes, navigate }
- return store
+ return {
+ subscribe: store.subscribe,
+ actions: { fetchRoutes, navigate, setRouteParams, setActiveRoute },
+ }
}
+
+if (!window.bbSDKRouteStore) {
+ window.bbSDKRouteStore = createRouteStore()
+}
+
+export const routeStore = window.bbSDKRouteStore
diff --git a/packages/component-sdk/src/store/screens.js b/packages/component-sdk/src/store/screens.js
index c29535d34e..f59e8aa9a7 100644
--- a/packages/component-sdk/src/store/screens.js
+++ b/packages/component-sdk/src/store/screens.js
@@ -1,25 +1,33 @@
-import { writable, derived, get } from "svelte/store"
-
-const initialState = []
+import { writable, derived } from "svelte/store"
+import { routeStore } from "./routes"
export const createScreenStore = () => {
- const store = writable(initialState)
- const routeLookupMap = derived(store, $screens => {
- let map = {}
- $screens.forEach(screen => {
- map[screen.route] = screen
- })
- return map
+ console.log("CREATE SCREEN STORE")
+
+ const screens = writable([])
+ const store = derived([screens, routeStore], ([$screens, $routeStore]) => {
+ const activeScreen = $screens.find(
+ screen => screen.route === $routeStore.activeRoute
+ )
+ return {
+ screens: $screens,
+ activeScreen,
+ }
})
const fetchScreens = () => {
const frontendDefinition = window["##BUDIBASE_FRONTEND_DEFINITION##"]
- store.set(frontendDefinition.screens)
+ screens.set(frontendDefinition.screens)
}
- const getScreenByRoute = path => {
- return get(routeLookupMap)[path]
- }
- store.actions = { fetchScreens, getScreenByRoute }
- return store
+ return {
+ subscribe: store.subscribe,
+ actions: { fetchScreens },
+ }
}
+
+if (!window.bbSDKScreenStore) {
+ window.bbSDKScreenStore = createScreenStore()
+}
+
+export const screenStore = window.bbSDKScreenStore
diff --git a/packages/component-sdk/src/utils/index.js b/packages/component-sdk/src/utils/index.js
index 1eb0ca2cfe..63da748cf6 100644
--- a/packages/component-sdk/src/utils/index.js
+++ b/packages/component-sdk/src/utils/index.js
@@ -1 +1,2 @@
export { getAppId } from "./getAppId"
+export { styleable } from "./styleable"
diff --git a/packages/component-sdk/src/utils/styleable.js b/packages/component-sdk/src/utils/styleable.js
new file mode 100644
index 0000000000..8f1d7ac3e1
--- /dev/null
+++ b/packages/component-sdk/src/utils/styleable.js
@@ -0,0 +1,46 @@
+const buildStyleString = styles => {
+ let str = ""
+ Object.entries(styles).forEach(([style, value]) => {
+ if (style && value) {
+ str += `${style}: ${value}; `
+ }
+ })
+ return str
+}
+
+/**
+ * Svelte action to apply correct component styles.
+ */
+export const styleable = (node, styles = {}) => {
+ const normalStyles = styles.normal || {}
+ const hoverStyles = {
+ ...normalStyles,
+ ...styles.hover,
+ }
+
+ function applyNormalStyles() {
+ node.style = buildStyleString(normalStyles)
+ }
+
+ function applyHoverStyles() {
+ node.style = buildStyleString(hoverStyles)
+ }
+
+ // Add listeners to toggle hover styles
+ node.addEventListener("mouseover", applyHoverStyles)
+ node.addEventListener("mouseout", applyNormalStyles)
+
+ // Apply normal styles initially
+ applyNormalStyles()
+
+ // Also apply data tags so we know how to reference each component
+ node.setAttribute("data-bb-id", styles.id)
+
+ return {
+ // Clean up event listeners when component is destroyed
+ destroy: () => {
+ node.removeEventListener("mouseover", applyHoverStyles)
+ node.removeEventListener("mouseout", applyNormalStyles)
+ },
+ }
+}
diff --git a/packages/component-sdk/yarn.lock b/packages/component-sdk/yarn.lock
index 5266d3e283..821ffe191f 100644
--- a/packages/component-sdk/yarn.lock
+++ b/packages/component-sdk/yarn.lock
@@ -828,6 +828,11 @@ svelte-spa-router@^3.0.5:
dependencies:
regexparam "1.3.0"
+svelte@^3.29.0:
+ version "3.29.7"
+ resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.29.7.tgz#e254eb2d0d609ce0fd60f052d444ac4a66d90f7d"
+ integrity sha512-rx0g311kBODvEWUU01DFBUl3MJuJven04bvTVFUG/w0On/wuj0PajQY/QlXcJndFxG+W1s8iXKaB418tdHWc3A==
+
typedarray-to-buffer@~1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-1.0.4.tgz#9bb8ba0e841fb3f4cf1fe7c245e9f3fa8a5fe99c"
diff --git a/packages/standard-components/package.json b/packages/standard-components/package.json
index 64d41ae5f8..71ca8815a8 100644
--- a/packages/standard-components/package.json
+++ b/packages/standard-components/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/standard-components",
- "svelte": "src/index.svelte",
+ "svelte": "src/index.js",
"main": "dist/index.js",
"module": "dist/index.js",
"scripts": {
@@ -15,13 +15,13 @@
"devDependencies": {
"@budibase/client": "^0.3.6",
"@rollup/plugin-alias": "^3.1.1",
- "@rollup/plugin-commonjs": "^11.1.0",
+ "@rollup/plugin-commonjs": "^16.0.0",
+ "@rollup/plugin-json": "^4.1.0",
+ "@rollup/plugin-node-resolve": "^10.0.0",
+ "@rollup/plugin-replace": "^2.3.4",
"lodash": "^4.17.15",
"rollup": "^2.11.2",
- "rollup-plugin-commonjs": "^10.0.2",
- "rollup-plugin-json": "^4.0.0",
"rollup-plugin-livereload": "^1.0.1",
- "rollup-plugin-node-resolve": "^5.0.0",
"rollup-plugin-postcss": "^3.1.5",
"rollup-plugin-svelte": "^6.1.1",
"rollup-plugin-terser": "^7.0.2",
diff --git a/packages/standard-components/rollup.config.js b/packages/standard-components/rollup.config.js
index ae191bfc16..7e49654b66 100644
--- a/packages/standard-components/rollup.config.js
+++ b/packages/standard-components/rollup.config.js
@@ -1,13 +1,13 @@
-import svelte from "rollup-plugin-svelte"
-import resolve from "rollup-plugin-node-resolve"
-import commonjs from "@rollup/plugin-commonjs"
-import postcss from "rollup-plugin-postcss"
import alias from "@rollup/plugin-alias"
+import commonjs from "@rollup/plugin-commonjs"
+import resolve from "@rollup/plugin-node-resolve"
+import replace from "@rollup/plugin-replace"
+import svelte from "rollup-plugin-svelte"
+import postcss from "rollup-plugin-postcss"
import { terser } from "rollup-plugin-terser"
import path from "path"
const production = !process.env.ROLLUP_WATCH
-const lodash_fp_exports = ["isEmpty"]
const projectRootDir = path.resolve(__dirname)
export default {
@@ -17,7 +17,7 @@ export default {
file: "dist/index.js",
format: "esm",
name: "budibaseStandardComponents",
- sourcemap: true,
+ sourcemap: false,
},
],
plugins: [
@@ -33,19 +33,18 @@ export default {
],
}),
production && terser(),
- postcss({
- plugins: [],
- }),
+ postcss(),
svelte({
- hydratable: true,
+ dev: !production,
}),
resolve({
browser: true,
}),
- commonjs({
- namedExports: {
- "lodash/fp": lodash_fp_exports,
- },
+ commonjs(),
+ // Fix for https://github.com/sveltejs/svelte/issues/3165
+ replace({
+ "outros.c.push":
+ "if (outros === undefined) { block.o(local); return }\noutros.c.push",
}),
],
}
diff --git a/packages/standard-components/src/Button.svelte b/packages/standard-components/src/Button.svelte
index 54f7812dc2..89fa1ad273 100644
--- a/packages/standard-components/src/Button.svelte
+++ b/packages/standard-components/src/Button.svelte
@@ -1,25 +1,20 @@
diff --git a/packages/standard-components/src/Container.svelte b/packages/standard-components/src/Container.svelte
index c850e44a5c..4259bf9cef 100644
--- a/packages/standard-components/src/Container.svelte
+++ b/packages/standard-components/src/Container.svelte
@@ -1,58 +1,61 @@
{#if type === 'div'}
-
+
{:else if type === 'header'}
-
+
{:else if type === 'main'}
-
+
{:else if type === 'footer'}
-