Add lots of new work on client library rewrite
This commit is contained in:
parent
cbeea17db0
commit
94458b3907
|
@ -15,17 +15,17 @@
|
||||||
"svelte-spa-router": "^3.0.5"
|
"svelte-spa-router": "^3.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"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",
|
"fs-extra": "^8.1.0",
|
||||||
"jsdom": "^16.0.1",
|
"jsdom": "^16.0.1",
|
||||||
"rollup": "^2.11.2",
|
"rollup": "^2.33.2",
|
||||||
"rollup-plugin-alias": "^2.2.0",
|
|
||||||
"rollup-plugin-commonjs": "^10.0.0",
|
|
||||||
"rollup-plugin-node-builtins": "^2.1.2",
|
"rollup-plugin-node-builtins": "^2.1.2",
|
||||||
"rollup-plugin-node-globals": "^1.4.0",
|
"rollup-plugin-node-globals": "^1.4.0",
|
||||||
"rollup-plugin-node-resolve": "^5.2.0",
|
|
||||||
"rollup-plugin-svelte": "^6.1.1",
|
"rollup-plugin-svelte": "^6.1.1",
|
||||||
"svelte": "3.29.0",
|
"svelte": "^3.29.0"
|
||||||
"svelte-jester": "^1.0.6"
|
|
||||||
},
|
},
|
||||||
"gitHead": "e4e053cb6ff9a0ddc7115b44ccaa24b8ec41fb9a"
|
"gitHead": "e4e053cb6ff9a0ddc7115b44ccaa24b8ec41fb9a"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import resolve from "rollup-plugin-node-resolve"
|
import alias from "@rollup/plugin-alias"
|
||||||
import commonjs from "rollup-plugin-commonjs"
|
import commonjs from "@rollup/plugin-commonjs"
|
||||||
|
import resolve from "@rollup/plugin-node-resolve"
|
||||||
import builtins from "rollup-plugin-node-builtins"
|
import builtins from "rollup-plugin-node-builtins"
|
||||||
import nodeglobals from "rollup-plugin-node-globals"
|
|
||||||
import svelte from "rollup-plugin-svelte"
|
import svelte from "rollup-plugin-svelte"
|
||||||
import alias from "rollup-plugin-alias"
|
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
|
||||||
const production = !process.env.ROLLUP_WATCH
|
const production = !process.env.ROLLUP_WATCH
|
||||||
|
@ -13,13 +12,7 @@ export default {
|
||||||
input: "src/index.js",
|
input: "src/index.js",
|
||||||
output: [
|
output: [
|
||||||
{
|
{
|
||||||
sourcemap: true,
|
file: "dist/budibase-client.js",
|
||||||
format: "iife",
|
|
||||||
name: "app",
|
|
||||||
file: `./dist/budibase-client.js`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
file: "dist/budibase-client.esm.mjs",
|
|
||||||
format: "esm",
|
format: "esm",
|
||||||
sourcemap: "inline",
|
sourcemap: "inline",
|
||||||
},
|
},
|
||||||
|
@ -45,7 +38,6 @@ export default {
|
||||||
}),
|
}),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
builtins(),
|
builtins(),
|
||||||
nodeglobals(),
|
|
||||||
],
|
],
|
||||||
watch: {
|
watch: {
|
||||||
clearScreen: false,
|
clearScreen: false,
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { componentStore } from "../store"
|
import { componentStore } from "../store"
|
||||||
import Component from "./Component.svelte"
|
import Component from "./Component.svelte"
|
||||||
import { getValidProps } from "../utils"
|
|
||||||
|
|
||||||
let frontendDefinition
|
let frontendDefinition
|
||||||
let loaded = false
|
let loaded = false
|
||||||
$: pageProps = frontendDefinition?.page?.props
|
$: pageDefinition = frontendDefinition?.page?.props
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
frontendDefinition = window["##BUDIBASE_FRONTEND_DEFINITION##"]
|
frontendDefinition = window["##BUDIBASE_FRONTEND_DEFINITION##"]
|
||||||
|
@ -17,9 +16,5 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if loaded}
|
{#if loaded}
|
||||||
<Component
|
<Component definition={pageDefinition} />
|
||||||
component={pageProps._component}
|
|
||||||
props={getValidProps(pageProps)}
|
|
||||||
children={pageProps._children}
|
|
||||||
styles={pageProps._styles.normal} />
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,31 +1,35 @@
|
||||||
<script>
|
<script>
|
||||||
import { componentStore } from "../store"
|
import { componentStore } from "../store"
|
||||||
import { buildStyle, getValidProps } from "../utils"
|
import { getValidProps } from "../utils"
|
||||||
|
|
||||||
export let props
|
export let definition = {}
|
||||||
export let children
|
|
||||||
export let component
|
|
||||||
export let styles
|
|
||||||
|
|
||||||
$: componentConstructor = componentStore.actions.getComponent(component)
|
$: componentProps = getValidProps(definition)
|
||||||
$: console.log("Rendering: " + component)
|
$: children = definition._children
|
||||||
|
$: componentName = extractComponentName(definition._component)
|
||||||
|
$: constructor = componentStore.actions.getComponent(componentName)
|
||||||
|
$: id = `${componentName}-${definition._id}`
|
||||||
|
$: styles = { ...definition._styles, id }
|
||||||
|
|
||||||
|
// Extracts the actual component name from the library name
|
||||||
|
function extractComponentName(name) {
|
||||||
|
console.log(name)
|
||||||
|
if (name == null) {
|
||||||
|
console.log(definition)
|
||||||
|
}
|
||||||
|
const split = name.split("/")
|
||||||
|
return split[split.length - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
$: console.log("Rendering: " + componentName)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if componentConstructor}
|
{#if constructor}
|
||||||
<div
|
<svelte:component this={constructor} {...componentProps} {styles}>
|
||||||
style={buildStyle(styles)}
|
|
||||||
data-bb-component={component}
|
|
||||||
data-bb-name={component._instanceName}>
|
|
||||||
<svelte:component this={componentConstructor} {...props}>
|
|
||||||
{#if children && children.length}
|
{#if children && children.length}
|
||||||
{#each children as child}
|
{#each children as child}
|
||||||
<svelte:self
|
<svelte:self definition={child} />
|
||||||
props={getValidProps(child)}
|
|
||||||
component={child._component}
|
|
||||||
children={child._children}
|
|
||||||
styles={child._styles.normal} />
|
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</svelte:component>
|
</svelte:component>
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
import { onMount, setContext } from "svelte"
|
||||||
import Router from "svelte-spa-router"
|
import Router from "svelte-spa-router"
|
||||||
import { routeStore, screenStore } from "@budibase/component-sdk"
|
import { routeStore, screenStore, styleable } from "@budibase/component-sdk"
|
||||||
import Screen from "./Screen.svelte"
|
import Screen from "./Screen.svelte"
|
||||||
|
|
||||||
|
export let styles
|
||||||
let routes
|
let routes
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
@ -14,17 +15,23 @@
|
||||||
await routeStore.actions.fetchRoutes()
|
await routeStore.actions.fetchRoutes()
|
||||||
await screenStore.actions.fetchScreens()
|
await screenStore.actions.fetchScreens()
|
||||||
routes = {}
|
routes = {}
|
||||||
$routeStore.forEach(route => {
|
$routeStore.routes.forEach(route => {
|
||||||
routes[route.path] = Screen
|
routes[route.path] = Screen
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Add catch-all route so that we serve the Screen component always
|
||||||
|
routes["*"] = Screen
|
||||||
}
|
}
|
||||||
|
|
||||||
function test(a, b) {
|
function onRouteLoading({ detail }) {
|
||||||
console.log(a)
|
routeStore.actions.setActiveRoute(detail.route)
|
||||||
console.log(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setContext("test", 123)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if routes}
|
{#if routes}
|
||||||
<Router {routes} on:routeEvent={test} />
|
<div use:styleable={styles}>
|
||||||
|
<Router on:routeLoading={onRouteLoading} {routes} />
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
<script>
|
<script>
|
||||||
import { screenStore } from "@budibase/component-sdk"
|
import { screenStore, routeStore } from "@budibase/component-sdk"
|
||||||
import { location } from "svelte-spa-router"
|
|
||||||
import Component from "./Component.svelte"
|
import Component from "./Component.svelte"
|
||||||
import { getValidProps } from "../utils"
|
import { getValidProps } from "../utils"
|
||||||
|
|
||||||
export let params
|
export let params
|
||||||
|
|
||||||
// Get the screen definition for the current route
|
// Get the screen definition for the current route
|
||||||
$: screenDefinition = screenStore.actions.getScreenByRoute($location)
|
$: screenDefinition = $screenStore.activeScreen
|
||||||
$: screenStore.actions
|
|
||||||
|
// Update route params
|
||||||
|
$: routeStore.actions.setRouteParams(params)
|
||||||
|
|
||||||
|
// Redirect to home page if no matching route
|
||||||
|
$: {
|
||||||
|
if (screenDefinition == null) {
|
||||||
|
routeStore.actions.navigate("/")
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if screenDefinition}
|
{#if screenDefinition}
|
||||||
<Component
|
<Component definition={screenDefinition.props} />
|
||||||
component={screenDefinition.props._component}
|
|
||||||
props={getValidProps(screenDefinition.props)}
|
|
||||||
children={screenDefinition.props._children}
|
|
||||||
styles={screenDefinition.props._styles.normal} />
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import ClientApp from "./components/ClientApp.svelte"
|
||||||
|
|
||||||
// Initialise client app
|
// Initialise client app
|
||||||
const loadBudibase = () => {
|
const loadBudibase = () => {
|
||||||
|
window.document.body.innerHTML = ""
|
||||||
new ClientApp({
|
new ClientApp({
|
||||||
target: window.document.body,
|
target: window.document.body,
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,10 +2,8 @@ import { writable, get } from "svelte/store"
|
||||||
import { getAppId } from "@budibase/component-sdk"
|
import { getAppId } from "@budibase/component-sdk"
|
||||||
import Router from "../components/Router.svelte"
|
import Router from "../components/Router.svelte"
|
||||||
|
|
||||||
const initialState = {}
|
const createComponentStore = () => {
|
||||||
|
const store = writable({})
|
||||||
export const createComponentStore = () => {
|
|
||||||
const store = writable(initialState)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the component library from the server
|
* Loads the component library from the server
|
||||||
|
@ -25,14 +23,13 @@ export const createComponentStore = () => {
|
||||||
if (!componentName) {
|
if (!componentName) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const split = componentName.split("/")
|
|
||||||
const strippedName = split[split.length - 1]
|
|
||||||
|
|
||||||
// Edge case for screen slot
|
// Edge case for screen slot
|
||||||
if (strippedName === "screenslot") {
|
if (componentName === "screenslot") {
|
||||||
return Router
|
return Router
|
||||||
}
|
}
|
||||||
return get(store)[strippedName]
|
|
||||||
|
return get(store)[componentName]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach actions to the store
|
// Attach actions to the store
|
||||||
|
@ -40,3 +37,5 @@ export const createComponentStore = () => {
|
||||||
|
|
||||||
return store
|
return store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const componentStore = createComponentStore()
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
import { createComponentStore } from "./components"
|
export { componentStore } from "./components"
|
||||||
|
|
||||||
export const componentStore = createComponentStore()
|
|
||||||
|
|
|
@ -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
|
* Extracts all valid props from a component definition that should be passed to
|
||||||
* its actual component instance.
|
* its actual component instance.
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
"rollup-plugin-svelte": "^6.1.1"
|
"rollup-plugin-svelte": "^6.1.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"svelte": "^3.29.0",
|
||||||
"svelte-spa-router": "^3.0.5"
|
"svelte-spa-router": "^3.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,21 +14,19 @@ export const fetchRow = async ({ tableId, rowId }) => {
|
||||||
/**
|
/**
|
||||||
* Creates a row in a table.
|
* Creates a row in a table.
|
||||||
*/
|
*/
|
||||||
export const saveRow = async (params, state) => {
|
export const saveRow = async row => {
|
||||||
return await api.post({
|
return await api.post({
|
||||||
url: `/api/${params.tableId}/rows`,
|
url: `/api/${row.tableId}/rows`,
|
||||||
body: makeRowRequestBody(params, state),
|
body: row,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a row in a table.
|
* Updates a row in a table.
|
||||||
*/
|
*/
|
||||||
export const updateRow = async (params, state) => {
|
export const updateRow = async row => {
|
||||||
const row = makeRowRequestBody(params, state)
|
|
||||||
row._id = params._id
|
|
||||||
return await api.patch({
|
return await api.patch({
|
||||||
url: `/api/${params.tableId}/rows/${params._id}`,
|
url: `/api/${row.tableId}/rows/${row._id}`,
|
||||||
body: row,
|
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
|
* Enriches rows which contain certain field types so that they can
|
||||||
* be properly displayed.
|
* be properly displayed.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export const DataProvider = "bb-data-provider"
|
|
@ -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 },
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,2 @@
|
||||||
export const RouterContext = "bb-router"
|
export * from "./dataProvider"
|
||||||
|
export * as ContextTypes from "./contextTypes"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export * from "./api"
|
export * from "./api"
|
||||||
export * from "./store"
|
export * from "./store"
|
||||||
export * as ContextTypes from "./context"
|
export * from "./context"
|
||||||
export { getAppId } from "./utils"
|
export * from "./utils"
|
||||||
export { link } from "svelte-spa-router"
|
export { link as linkable } from "svelte-spa-router"
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { localStorageStore } from "../../../builder/src/builderStore/store/localStorage"
|
|
||||||
import * as api from "../api"
|
import * as api from "../api"
|
||||||
import { getAppId } from "../utils"
|
import { getAppId } from "../utils"
|
||||||
|
import { writable } from "svelte/store"
|
||||||
const initialState = ""
|
|
||||||
|
|
||||||
export const createAuthStore = () => {
|
export const createAuthStore = () => {
|
||||||
const store = localStorageStore("budibase:token", initialState)
|
const store = writable("")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs a user in.
|
* Logs a user in.
|
||||||
|
@ -22,7 +20,7 @@ export const createAuthStore = () => {
|
||||||
* Logs a user out.
|
* Logs a user out.
|
||||||
*/
|
*/
|
||||||
const logOut = () => {
|
const logOut = () => {
|
||||||
store.set(initialState)
|
store.set("")
|
||||||
|
|
||||||
// Expire any cookies
|
// Expire any cookies
|
||||||
const appId = getAppId()
|
const appId = getAppId()
|
||||||
|
@ -33,10 +31,14 @@ export const createAuthStore = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
store.actions = {
|
return {
|
||||||
logIn,
|
subscribe: store.subscribe,
|
||||||
logOut,
|
actions: { logIn, logOut },
|
||||||
}
|
}
|
||||||
|
|
||||||
return store
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!window.bbSDKAuthStore) {
|
||||||
|
window.bbSDKAuthStore = createAuthStore()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const authStore = window.bbSDKAuthStore
|
||||||
|
|
|
@ -37,11 +37,14 @@ export const createConfigStore = () => {
|
||||||
handler && handler(error)
|
handler && handler(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
store.actions = {
|
return {
|
||||||
initialise,
|
subscribe: store.subscribe,
|
||||||
reset,
|
actions: { initialise, reset, handleError },
|
||||||
handleError,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return store
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!window.bbSDKConfigStore) {
|
||||||
|
window.bbSDKConfigStore = createConfigStore()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const configStore = window.bbSDKConfigStore
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
import { createConfigStore } from "./config"
|
export { configStore } from "./config"
|
||||||
import { createAuthStore } from "./auth"
|
export { authStore } from "./auth"
|
||||||
import { createRouteStore } from "./routes"
|
export { routeStore } from "./routes"
|
||||||
import { createScreenStore } from "./screens"
|
export { screenStore } from "./screens"
|
||||||
|
|
||||||
export const configStore = createConfigStore()
|
|
||||||
export const authStore = createAuthStore()
|
|
||||||
export const routeStore = createRouteStore()
|
|
||||||
export const screenStore = createScreenStore()
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import { push } from "svelte-spa-router"
|
import { push } from "svelte-spa-router"
|
||||||
|
|
||||||
const initialState = []
|
|
||||||
|
|
||||||
export const createRouteStore = () => {
|
export const createRouteStore = () => {
|
||||||
|
const initialState = {
|
||||||
|
routes: [],
|
||||||
|
routeParams: {},
|
||||||
|
activeRoute: null,
|
||||||
|
}
|
||||||
const store = writable(initialState)
|
const store = writable(initialState)
|
||||||
|
|
||||||
const fetchRoutes = () => {
|
const fetchRoutes = () => {
|
||||||
|
@ -12,10 +15,35 @@ export const createRouteStore = () => {
|
||||||
path: screen.route,
|
path: screen.route,
|
||||||
screenId: screen._id,
|
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
|
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
|
||||||
|
|
|
@ -1,25 +1,33 @@
|
||||||
import { writable, derived, get } from "svelte/store"
|
import { writable, derived } from "svelte/store"
|
||||||
|
import { routeStore } from "./routes"
|
||||||
const initialState = []
|
|
||||||
|
|
||||||
export const createScreenStore = () => {
|
export const createScreenStore = () => {
|
||||||
const store = writable(initialState)
|
console.log("CREATE SCREEN STORE")
|
||||||
const routeLookupMap = derived(store, $screens => {
|
|
||||||
let map = {}
|
const screens = writable([])
|
||||||
$screens.forEach(screen => {
|
const store = derived([screens, routeStore], ([$screens, $routeStore]) => {
|
||||||
map[screen.route] = screen
|
const activeScreen = $screens.find(
|
||||||
})
|
screen => screen.route === $routeStore.activeRoute
|
||||||
return map
|
)
|
||||||
|
return {
|
||||||
|
screens: $screens,
|
||||||
|
activeScreen,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchScreens = () => {
|
const fetchScreens = () => {
|
||||||
const frontendDefinition = window["##BUDIBASE_FRONTEND_DEFINITION##"]
|
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
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export { getAppId } from "./getAppId"
|
export { getAppId } from "./getAppId"
|
||||||
|
export { styleable } from "./styleable"
|
||||||
|
|
|
@ -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)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -828,6 +828,11 @@ svelte-spa-router@^3.0.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
regexparam "1.3.0"
|
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:
|
typedarray-to-buffer@~1.0.0:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-1.0.4.tgz#9bb8ba0e841fb3f4cf1fe7c245e9f3fa8a5fe99c"
|
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-1.0.4.tgz#9bb8ba0e841fb3f4cf1fe7c245e9f3fa8a5fe99c"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/standard-components",
|
"name": "@budibase/standard-components",
|
||||||
"svelte": "src/index.svelte",
|
"svelte": "src/index.js",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/index.js",
|
"module": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -15,13 +15,13 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@budibase/client": "^0.3.6",
|
"@budibase/client": "^0.3.6",
|
||||||
"@rollup/plugin-alias": "^3.1.1",
|
"@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",
|
"lodash": "^4.17.15",
|
||||||
"rollup": "^2.11.2",
|
"rollup": "^2.11.2",
|
||||||
"rollup-plugin-commonjs": "^10.0.2",
|
|
||||||
"rollup-plugin-json": "^4.0.0",
|
|
||||||
"rollup-plugin-livereload": "^1.0.1",
|
"rollup-plugin-livereload": "^1.0.1",
|
||||||
"rollup-plugin-node-resolve": "^5.0.0",
|
|
||||||
"rollup-plugin-postcss": "^3.1.5",
|
"rollup-plugin-postcss": "^3.1.5",
|
||||||
"rollup-plugin-svelte": "^6.1.1",
|
"rollup-plugin-svelte": "^6.1.1",
|
||||||
"rollup-plugin-terser": "^7.0.2",
|
"rollup-plugin-terser": "^7.0.2",
|
||||||
|
|
|
@ -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 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 { terser } from "rollup-plugin-terser"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
|
||||||
const production = !process.env.ROLLUP_WATCH
|
const production = !process.env.ROLLUP_WATCH
|
||||||
const lodash_fp_exports = ["isEmpty"]
|
|
||||||
const projectRootDir = path.resolve(__dirname)
|
const projectRootDir = path.resolve(__dirname)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -17,7 +17,7 @@ export default {
|
||||||
file: "dist/index.js",
|
file: "dist/index.js",
|
||||||
format: "esm",
|
format: "esm",
|
||||||
name: "budibaseStandardComponents",
|
name: "budibaseStandardComponents",
|
||||||
sourcemap: true,
|
sourcemap: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
|
@ -33,19 +33,18 @@ export default {
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
production && terser(),
|
production && terser(),
|
||||||
postcss({
|
postcss(),
|
||||||
plugins: [],
|
|
||||||
}),
|
|
||||||
svelte({
|
svelte({
|
||||||
hydratable: true,
|
dev: !production,
|
||||||
}),
|
}),
|
||||||
resolve({
|
resolve({
|
||||||
browser: true,
|
browser: true,
|
||||||
}),
|
}),
|
||||||
commonjs({
|
commonjs(),
|
||||||
namedExports: {
|
// Fix for https://github.com/sveltejs/svelte/issues/3165
|
||||||
"lodash/fp": lodash_fp_exports,
|
replace({
|
||||||
},
|
"outros.c.push":
|
||||||
|
"if (outros === undefined) { block.o(local); return }\noutros.c.push",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,20 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { styleable } from "@budibase/component-sdk"
|
||||||
|
|
||||||
export let className = "default"
|
export let className = "default"
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let text
|
export let text
|
||||||
|
export let styles
|
||||||
|
|
||||||
export let _bb
|
|
||||||
let theButton
|
let theButton
|
||||||
|
|
||||||
$: if (_bb.props._children && _bb.props._children.length > 0)
|
|
||||||
theButton && _bb.attachChildren(theButton)
|
|
||||||
|
|
||||||
const clickHandler = () => {
|
|
||||||
_bb.call("onClick")
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
bind:this={theButton}
|
bind:this={theButton}
|
||||||
class="default"
|
class="default"
|
||||||
disabled={disabled || false}
|
disabled={disabled || false}
|
||||||
on:click|once={clickHandler}>
|
use:styleable={styles}>
|
||||||
{#if !_bb.props._children || _bb.props._children.length === 0}{text}{/if}
|
{text}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -37,28 +32,4 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.border {
|
|
||||||
border: var(--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.color {
|
|
||||||
color: var(--color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.background {
|
|
||||||
background: var(--background);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hoverBorder:hover {
|
|
||||||
border: var(--hoverBorder);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hoverColor:hover {
|
|
||||||
color: var(--hoverColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hoverBack:hover {
|
|
||||||
background: var(--hoverBackground);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,58 +1,61 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { styleable } from "@budibase/component-sdk"
|
||||||
|
|
||||||
export let className = ""
|
export let className = ""
|
||||||
export let type = "div"
|
export let type = "div"
|
||||||
|
export let styles
|
||||||
$: console.log(type)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if type === 'div'}
|
{#if type === 'div'}
|
||||||
<div>
|
<div use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
{:else if type === 'header'}
|
{:else if type === 'header'}
|
||||||
<header>
|
<header use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</header>
|
</header>
|
||||||
{:else if type === 'main'}
|
{:else if type === 'main'}
|
||||||
<main>
|
<main use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
{:else if type === 'footer'}
|
{:else if type === 'footer'}
|
||||||
<footer>
|
<footer use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</footer>
|
</footer>
|
||||||
{:else if type === 'aside'}
|
{:else if type === 'aside'}
|
||||||
<aside>
|
<aside use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</aside>
|
</aside>
|
||||||
{:else if type === 'summary'}
|
{:else if type === 'summary'}
|
||||||
<summary>
|
<summary use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</summary>
|
</summary>
|
||||||
{:else if type === 'details'}
|
{:else if type === 'details'}
|
||||||
<details>
|
<details use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</details>
|
</details>
|
||||||
{:else if type === 'article'}
|
{:else if type === 'article'}
|
||||||
<article>
|
<article use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</article>
|
</article>
|
||||||
{:else if type === 'nav'}
|
{:else if type === 'nav'}
|
||||||
<nav>
|
<nav use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</nav>
|
</nav>
|
||||||
{:else if type === 'mark'}
|
{:else if type === 'mark'}
|
||||||
<mark><slot /></mark>
|
<mark use:styleable={styles}>
|
||||||
|
<slot />
|
||||||
|
</mark>
|
||||||
{:else if type === 'figure'}
|
{:else if type === 'figure'}
|
||||||
<figure>
|
<figure use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</figure>
|
</figure>
|
||||||
{:else if type === 'figcaption'}
|
{:else if type === 'figcaption'}
|
||||||
<figcaption>
|
<figcaption use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</figcaption>
|
</figcaption>
|
||||||
{:else if type === 'paragraph'}
|
{:else if type === 'paragraph'}
|
||||||
<p>
|
<p use:styleable={styles}>
|
||||||
<slot />
|
<slot />
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import Form from "./Form.svelte"
|
import Form from "./Form.svelte"
|
||||||
|
|
||||||
export let _bb
|
|
||||||
export let table
|
export let table
|
||||||
export let title
|
export let title
|
||||||
export let buttonText
|
export let buttonText
|
||||||
|
export let styles
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Form {_bb} {table} {title} {buttonText} wide={true} />
|
<Form {styles} {table} {title} {buttonText} wide />
|
||||||
|
|
|
@ -1,5 +1,23 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { styleable } from "@budibase/component-sdk"
|
||||||
|
|
||||||
export let embed
|
export let embed
|
||||||
|
export let styles
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{@html embed}
|
<div use:styleable={styles}>
|
||||||
|
{@html embed}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
div :global(> *) {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,54 +1,57 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { getContext } from "svelte"
|
||||||
import { Label, DatePicker, Input, Select, Toggle } from "@budibase/bbui"
|
import { Label, DatePicker, Input, Select, Toggle } from "@budibase/bbui"
|
||||||
import Dropzone from "./attachments/Dropzone.svelte"
|
import Dropzone from "./attachments/Dropzone.svelte"
|
||||||
import LinkedRowSelector from "./LinkedRowSelector.svelte"
|
import LinkedRowSelector from "./LinkedRowSelector.svelte"
|
||||||
import ErrorsBox from "./ErrorsBox.svelte"
|
import ErrorsBox from "./ErrorsBox.svelte"
|
||||||
import { capitalise } from "./helpers"
|
import { capitalise } from "./helpers"
|
||||||
|
import { styleable, ContextTypes, screenStore } from "@budibase/component-sdk"
|
||||||
|
|
||||||
export let _bb
|
|
||||||
export let table
|
export let table
|
||||||
export let wide = false
|
export let wide = false
|
||||||
|
export let styles
|
||||||
|
|
||||||
let store = _bb.store
|
|
||||||
let schema = {}
|
let schema = {}
|
||||||
let rowId
|
let rowId
|
||||||
let errors = {}
|
let errors = {}
|
||||||
|
|
||||||
$: schema = $store.data && $store.data._table && $store.data._table.schema
|
const dataProviderStore = getContext(ContextTypes.DataProvider)
|
||||||
|
$: row = $dataProviderStore.rows[0]
|
||||||
|
$: schema = $dataProviderStore.table && $dataProviderStore.table.schema
|
||||||
$: fields = schema ? Object.keys(schema) : []
|
$: fields = schema ? Object.keys(schema) : []
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="form-content">
|
<div class="form-content" use:styleable={styles}>
|
||||||
<ErrorsBox errors={$store.saveRowErrors || {}} />
|
<!-- <ErrorsBox errors={$store.saveRowErrors || {}} />-->
|
||||||
{#each fields as field}
|
{#each fields as field}
|
||||||
<div class="form-field" class:wide>
|
<div class="form-field" class:wide>
|
||||||
{#if !(schema[field].type === 'boolean' && !wide)}
|
{#if !(schema[field].type === 'boolean' && !wide)}
|
||||||
<Label extraSmall={!wide} grey>{capitalise(schema[field].name)}</Label>
|
<Label extraSmall={!wide} grey>{capitalise(schema[field].name)}</Label>
|
||||||
{/if}
|
{/if}
|
||||||
{#if schema[field].type === 'options'}
|
{#if schema[field].type === 'options'}
|
||||||
<Select secondary bind:value={$store.data[field]}>
|
<Select secondary bind:value={row[field]}>
|
||||||
<option value="">Choose an option</option>
|
<option value="">Choose an option</option>
|
||||||
{#each schema[field].constraints.inclusion as opt}
|
{#each schema[field].constraints.inclusion as opt}
|
||||||
<option>{opt}</option>
|
<option>{opt}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
{:else if schema[field].type === 'datetime'}
|
{:else if schema[field].type === 'datetime'}
|
||||||
<DatePicker bind:value={$store.data[field]} />
|
<DatePicker bind:value={row[field]} />
|
||||||
{:else if schema[field].type === 'boolean'}
|
{:else if schema[field].type === 'boolean'}
|
||||||
<Toggle
|
<Toggle
|
||||||
text={wide ? null : capitalise(schema[field].name)}
|
text={wide ? null : capitalise(schema[field].name)}
|
||||||
bind:checked={$store.data[field]} />
|
bind:checked={row[field]} />
|
||||||
{:else if schema[field].type === 'number'}
|
{:else if schema[field].type === 'number'}
|
||||||
<Input type="number" bind:value={$store.data[field]} />
|
<Input type="number" bind:value={row[field]} />
|
||||||
{:else if schema[field].type === 'string'}
|
{:else if schema[field].type === 'string'}
|
||||||
<Input bind:value={$store.data[field]} />
|
<Input bind:value={row[field]} />
|
||||||
{:else if schema[field].type === 'attachment'}
|
{:else if schema[field].type === 'attachment'}
|
||||||
<Dropzone bind:files={$store.data[field]} />
|
<Dropzone bind:files={row[field]} />
|
||||||
{:else if schema[field].type === 'link'}
|
{:else if schema[field].type === 'link'}
|
||||||
<LinkedRowSelector
|
<LinkedRowSelector
|
||||||
secondary
|
secondary
|
||||||
showLabel={false}
|
showLabel={false}
|
||||||
bind:linkedRows={$store.data[field]}
|
bind:linkedRows={row[field]}
|
||||||
schema={schema[field]} />
|
schema={schema[field]} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,29 +1,22 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { styleable } from "@budibase/component-sdk"
|
||||||
|
|
||||||
export let className = ""
|
export let className = ""
|
||||||
export let type
|
export let type
|
||||||
export let text = ""
|
export let text = ""
|
||||||
|
export let styles
|
||||||
export let _bb
|
|
||||||
|
|
||||||
let containerElement
|
|
||||||
|
|
||||||
$: containerElement &&
|
|
||||||
!text &&
|
|
||||||
_bb.props.children &&
|
|
||||||
_bb.props.children.length &&
|
|
||||||
_bb.attachChildren(containerElement)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if type === 'h1'}
|
{#if type === 'h1'}
|
||||||
<h1 class={className} bind:this={containerElement}>{text}</h1>
|
<h1 class={className} use:styleable={styles}>{text}</h1>
|
||||||
{:else if type === 'h2'}
|
{:else if type === 'h2'}
|
||||||
<h2 class={className} bind:this={containerElement}>{text}</h2>
|
<h2 class={className} use:styleable={styles}>{text}</h2>
|
||||||
{:else if type === 'h3'}
|
{:else if type === 'h3'}
|
||||||
<h3 class={className} bind:this={containerElement}>{text}</h3>
|
<h3 class={className} use:styleable={styles}>{text}</h3>
|
||||||
{:else if type === 'h4'}
|
{:else if type === 'h4'}
|
||||||
<h4 class={className} bind:this={containerElement}>{text}</h4>
|
<h4 class={className} use:styleable={styles}>{text}</h4>
|
||||||
{:else if type === 'h5'}
|
{:else if type === 'h5'}
|
||||||
<h5 class={className} bind:this={containerElement}>{text}</h5>
|
<h5 class={className} use:styleable={styles}>{text}</h5>
|
||||||
{:else if type === 'h6'}
|
{:else if type === 'h6'}
|
||||||
<h6 class={className} bind:this={containerElement}>{text}</h6>
|
<h6 class={className} use:styleable={styles}>{text}</h6>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { link } from "@budibase/component-sdk"
|
import { linkable } from "@budibase/component-sdk"
|
||||||
|
|
||||||
export let url = ""
|
export let url = ""
|
||||||
export let text = ""
|
export let text = ""
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
$: target = openInNewTab ? "_blank" : "_self"
|
$: target = openInNewTab ? "_blank" : "_self"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a href={url} use:link {target}>
|
<a href={url} use:linkable {target}>
|
||||||
{text}
|
{text}
|
||||||
<slot />
|
<slot />
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,21 +1,28 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
import { onMount, setContext } from "svelte"
|
||||||
import { fetchDatasource } from "@budibase/component-sdk"
|
import {
|
||||||
|
fetchDatasource,
|
||||||
|
createDataProviderContext,
|
||||||
|
fetchTableDefinition,
|
||||||
|
ContextTypes,
|
||||||
|
} from "@budibase/component-sdk"
|
||||||
import { isEmpty } from "lodash/fp"
|
import { isEmpty } from "lodash/fp"
|
||||||
|
|
||||||
export let _bb
|
|
||||||
export let datasource = []
|
export let datasource = []
|
||||||
|
|
||||||
let target
|
let target
|
||||||
let store = _bb.store
|
|
||||||
|
const dataProviderContext = createDataProviderContext()
|
||||||
|
setContext(ContextTypes.DataProvider, dataProviderContext)
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (!isEmpty(datasource)) {
|
if (!isEmpty(datasource)) {
|
||||||
const data = await fetchDatasource(datasource)
|
const rows = await fetchDatasource(datasource)
|
||||||
_bb.attachChildren(target, {
|
dataProviderContext.actions.setRows(rows)
|
||||||
hydrate: false,
|
if (datasource.tableId) {
|
||||||
context: data,
|
const tableDefinition = await fetchTableDefinition(datasource.tableId)
|
||||||
})
|
dataProviderContext.actions.setTable(tableDefinition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
import { authStore } from "@budibase/component-sdk"
|
import { authStore, styleable } from "@budibase/component-sdk"
|
||||||
|
|
||||||
export let buttonText = "Log In"
|
export let buttonText = "Log In"
|
||||||
export let logo = ""
|
export let logo = ""
|
||||||
export let title = ""
|
export let title = ""
|
||||||
export let buttonClass = ""
|
export let buttonClass = ""
|
||||||
export let inputClass = ""
|
export let inputClass = ""
|
||||||
export let _bb
|
export let styles
|
||||||
|
|
||||||
let username = ""
|
let username = ""
|
||||||
let password = ""
|
let password = ""
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root" use:styleable={styles}>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
{#if logo}
|
{#if logo}
|
||||||
<div class="logo-container"><img src={logo} alt="logo" /></div>
|
<div class="logo-container"><img src={logo} alt="logo" /></div>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import { authStore, link } from "@budibase/component-sdk"
|
import { authStore, linkable, styleable } from "@budibase/component-sdk"
|
||||||
|
|
||||||
export let logoUrl
|
export let logoUrl
|
||||||
export let title
|
export let title
|
||||||
|
export let styles
|
||||||
|
|
||||||
const logOut = () => {
|
const logOut = () => {
|
||||||
authStore.actions.logOut()
|
authStore.actions.logOut()
|
||||||
|
@ -10,9 +11,9 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="nav">
|
<div class="nav" use:styleable={styles}>
|
||||||
<div class="nav__top">
|
<div class="nav__top">
|
||||||
<a href="/" use:link>
|
<a href="/" use:linkable>
|
||||||
{#if logoUrl}
|
{#if logoUrl}
|
||||||
<img class="logo" alt="logo" src={logoUrl} height="48" />
|
<img class="logo" alt="logo" src={logoUrl} height="48" />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
import { onMount, setContext } from "svelte"
|
||||||
import {
|
import {
|
||||||
fetchTableDefinition,
|
fetchTableDefinition,
|
||||||
fetchTableData,
|
fetchTableData,
|
||||||
fetchRow,
|
fetchRow,
|
||||||
|
screenStore,
|
||||||
|
routeStore,
|
||||||
|
createDataProviderContext,
|
||||||
|
ContextTypes,
|
||||||
} from "@budibase/component-sdk"
|
} from "@budibase/component-sdk"
|
||||||
|
|
||||||
export let _bb
|
|
||||||
export let table
|
export let table
|
||||||
|
|
||||||
let headers = []
|
let headers = []
|
||||||
let store = _bb.store
|
|
||||||
let target
|
// Expose data provider context for this row
|
||||||
|
const dataProviderContext = createDataProviderContext()
|
||||||
|
setContext(ContextTypes.DataProvider, dataProviderContext)
|
||||||
|
|
||||||
async function fetchFirstRow() {
|
async function fetchFirstRow() {
|
||||||
const rows = await fetchTableData(table)
|
const rows = await fetchTableData(table)
|
||||||
|
@ -24,8 +29,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const pathParts = window.location.pathname.split("/")
|
const pathParts = window.location.pathname.split("/")
|
||||||
const routeParamId = _bb.routeParams().id
|
const routeParamId = $routeStore.routeParams.id
|
||||||
|
console.log(routeParamId)
|
||||||
let row
|
let row
|
||||||
|
let tableDefinition
|
||||||
|
|
||||||
// if srcdoc, then we assume this is the builder preview
|
// if srcdoc, then we assume this is the builder preview
|
||||||
if ((pathParts.length === 0 || pathParts[0] === "srcdoc") && table) {
|
if ((pathParts.length === 0 || pathParts[0] === "srcdoc") && table) {
|
||||||
|
@ -37,18 +44,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row) {
|
if (row) {
|
||||||
row._table = await fetchTableDefinition(row.tableId)
|
tableDefinition = await fetchTableDefinition(row.tableId)
|
||||||
_bb.attachChildren(target, {
|
|
||||||
context: row,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
_bb.attachChildren(target)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
dataProviderContext.actions.setRows([row])
|
||||||
await fetchData()
|
dataProviderContext.actions.setTable(tableDefinition)
|
||||||
})
|
}
|
||||||
|
|
||||||
|
onMount(fetchData)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section bind:this={target} />
|
<slot />
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
ModalContent,
|
ModalContent,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
|
|
||||||
export let _bb
|
|
||||||
export let datasource = {}
|
export let datasource = {}
|
||||||
export let editable
|
export let editable
|
||||||
export let theme = "alpine"
|
export let theme = "alpine"
|
||||||
|
@ -32,7 +31,6 @@
|
||||||
|
|
||||||
let modal
|
let modal
|
||||||
|
|
||||||
let store = _bb.store
|
|
||||||
let dataLoaded = false
|
let dataLoaded = false
|
||||||
let data
|
let data
|
||||||
let columnDefs
|
let columnDefs
|
||||||
|
@ -52,7 +50,7 @@
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (!isEmpty(datasource)) {
|
if (!isEmpty(datasource)) {
|
||||||
data = await SDK.fetchDatasource(datasource, $store)
|
data = await SDK.fetchDatasource(datasource)
|
||||||
let schema
|
let schema
|
||||||
|
|
||||||
// Get schema for datasource
|
// Get schema for datasource
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
let anchor
|
let anchor
|
||||||
let dropdown
|
let dropdown
|
||||||
|
|
||||||
export let _bb, table
|
export let table
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={anchor}>
|
<div bind:this={anchor}>
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
<DropdownMenu bind:this={dropdown} {anchor} align="left">
|
<DropdownMenu bind:this={dropdown} {anchor} align="left">
|
||||||
<h5>Add New Row</h5>
|
<h5>Add New Row</h5>
|
||||||
<Modal
|
<Modal
|
||||||
{_bb}
|
|
||||||
{table}
|
{table}
|
||||||
onClosed={dropdown.hide}
|
onClosed={dropdown.hide}
|
||||||
on:newRow={() => dispatch('newRow')} />
|
on:newRow={() => dispatch('newRow')} />
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount, createEventDispatcher } from "svelte"
|
import { onMount, createEventDispatcher } from "svelte"
|
||||||
import { fade } from "svelte/transition"
|
import { fetchRow, saveRow, routeStore } from "@budibase/component-sdk"
|
||||||
import { Button, Label, DatePicker } from "@budibase/bbui"
|
import { Button, Label, DatePicker } from "@budibase/bbui"
|
||||||
import Dropzone from "../../attachments/Dropzone.svelte"
|
import Dropzone from "../../attachments/Dropzone.svelte"
|
||||||
import debounce from "lodash.debounce"
|
import debounce from "lodash.debounce"
|
||||||
|
@ -13,12 +13,10 @@
|
||||||
link: [],
|
link: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
export let _bb
|
|
||||||
export let table
|
export let table
|
||||||
export let onClosed
|
export let onClosed
|
||||||
|
|
||||||
let row = { tableId: table._id }
|
let row = { tableId: table._id }
|
||||||
let store = _bb.store
|
|
||||||
let schema = table.schema
|
let schema = table.schema
|
||||||
let saved = false
|
let saved = false
|
||||||
let rowId
|
let rowId
|
||||||
|
@ -39,36 +37,31 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SAVE_ROW_URL = `/api/${table._id}/rows`
|
const response = await saveRow(row)
|
||||||
const response = await _bb.api.post(SAVE_ROW_URL, row)
|
|
||||||
|
|
||||||
const json = await response.json()
|
if (!response.error) {
|
||||||
|
// store.update(state => {
|
||||||
if (response.status === 200) {
|
// state[table._id] = state[table._id]
|
||||||
store.update(state => {
|
// ? [...state[table._id], json]
|
||||||
state[table._id] = state[table._id]
|
// : [json]
|
||||||
? [...state[table._id], json]
|
// return state
|
||||||
: [json]
|
// })
|
||||||
return state
|
|
||||||
})
|
|
||||||
|
|
||||||
errors = {}
|
errors = {}
|
||||||
|
|
||||||
// wipe form, if new row, otherwise update
|
// wipe form, if new row, otherwise update
|
||||||
// table to get new _rev
|
// table to get new _rev
|
||||||
row = isNew ? { tableId: table._id } : json
|
row = isNew ? { tableId: table._id } : response
|
||||||
|
|
||||||
onClosed()
|
onClosed()
|
||||||
dispatch("newRow")
|
dispatch("newRow")
|
||||||
}
|
} else {
|
||||||
|
errors = [response.error]
|
||||||
if (response.status === 400) {
|
|
||||||
errors = json.errors
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const routeParams = _bb.routeParams()
|
const routeParams = $routeStore.routeParams
|
||||||
rowId =
|
rowId =
|
||||||
Object.keys(routeParams).length > 0 && (routeParams.id || routeParams[0])
|
Object.keys(routeParams).length > 0 && (routeParams.id || routeParams[0])
|
||||||
isNew = !rowId || rowId === "new"
|
isNew = !rowId || rowId === "new"
|
||||||
|
@ -78,10 +71,7 @@
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const GET_ROW_URL = `/api/${table._id}/rows/${rowId}`
|
row = await fetchRow({ tableId: table._id, rowId })
|
||||||
const response = await _bb.api.get(GET_ROW_URL)
|
|
||||||
const json = await response.json()
|
|
||||||
row = json
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { linkable } from "@budibase/component-sdk"
|
||||||
import { Button } from "@budibase/bbui"
|
import { Button } from "@budibase/bbui"
|
||||||
|
|
||||||
export let url
|
export let url
|
||||||
let link
|
let link
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a href={url} bind:this={link} />
|
<a href={url} bind:this={link} use:linkable />
|
||||||
<Button small translucent on:click={() => link.click()}>View</Button>
|
<Button small translucent on:click={() => link.click()}>View</Button>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -147,6 +147,9 @@ function viewDetailsRenderer(options, constraints, editable) {
|
||||||
if (options.detailUrl) {
|
if (options.detailUrl) {
|
||||||
url = options.detailUrl.replace(":id", params.data._id)
|
url = options.detailUrl.replace(":id", params.data._id)
|
||||||
}
|
}
|
||||||
|
if (!url.startsWith("/")) {
|
||||||
|
url = `/${url}`
|
||||||
|
}
|
||||||
|
|
||||||
new ViewDetails({
|
new ViewDetails({
|
||||||
target: container,
|
target: container,
|
||||||
|
|
Loading…
Reference in New Issue