Merge pull request #1234 from Budibase/lab-day-cheeks
Useful features and fixes from lab day
This commit is contained in:
commit
f20e5e28fd
|
@ -120,7 +120,7 @@ const getContextBindings = (asset, componentId) => {
|
||||||
tableName = info.table?.name
|
tableName = info.table?.name
|
||||||
|
|
||||||
// Add _id and _rev fields for certain types
|
// Add _id and _rev fields for certain types
|
||||||
if (datasource.type === "table" || datasource.type === "link") {
|
if (schema && ["table", "link"].includes(datasource.type)) {
|
||||||
schema["_id"] = { type: "string" }
|
schema["_id"] = { type: "string" }
|
||||||
schema["_rev"] = { type: "string" }
|
schema["_rev"] = { type: "string" }
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"fieldgroup",
|
"fieldgroup",
|
||||||
"stringfield",
|
"stringfield",
|
||||||
"numberfield",
|
"numberfield",
|
||||||
|
"passwordfield",
|
||||||
"optionsfield",
|
"optionsfield",
|
||||||
"booleanfield",
|
"booleanfield",
|
||||||
"longformfield",
|
"longformfield",
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
"heading",
|
"heading",
|
||||||
"text",
|
"text",
|
||||||
"image",
|
"image",
|
||||||
|
"backgroundimage",
|
||||||
"link",
|
"link",
|
||||||
"icon",
|
"icon",
|
||||||
"embed"
|
"embed"
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
<script>
|
||||||
|
import { Label } from "@budibase/bbui"
|
||||||
|
import { getBindableProperties } from "builderStore/dataBinding"
|
||||||
|
import { currentAsset, store } from "builderStore"
|
||||||
|
import DrawerBindableInput from "components/common/DrawerBindableInput.svelte"
|
||||||
|
|
||||||
|
export let parameters
|
||||||
|
|
||||||
|
let bindingDrawer
|
||||||
|
$: bindings = getBindableProperties($currentAsset, $store.selectedComponentId)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="root">
|
||||||
|
<Label small>Email</Label>
|
||||||
|
<DrawerBindableInput
|
||||||
|
title="Email"
|
||||||
|
value={parameters.email}
|
||||||
|
on:change={value => (parameters.email = value.detail)}
|
||||||
|
{bindings} />
|
||||||
|
<Label small>Password</Label>
|
||||||
|
<DrawerBindableInput
|
||||||
|
title="Password"
|
||||||
|
value={parameters.password}
|
||||||
|
on:change={value => (parameters.password = value.detail)}
|
||||||
|
{bindings} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.root {
|
||||||
|
display: grid;
|
||||||
|
column-gap: var(--spacing-l);
|
||||||
|
row-gap: var(--spacing-s);
|
||||||
|
grid-template-columns: auto 1fr auto 1fr;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<div class="root">This action doesn't require any additional settings.</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.root {
|
||||||
|
font-size: var(--font-size-s);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -4,6 +4,8 @@ import DeleteRow from "./DeleteRow.svelte"
|
||||||
import ExecuteQuery from "./ExecuteQuery.svelte"
|
import ExecuteQuery from "./ExecuteQuery.svelte"
|
||||||
import TriggerAutomation from "./TriggerAutomation.svelte"
|
import TriggerAutomation from "./TriggerAutomation.svelte"
|
||||||
import ValidateForm from "./ValidateForm.svelte"
|
import ValidateForm from "./ValidateForm.svelte"
|
||||||
|
import LogIn from "./LogIn.svelte"
|
||||||
|
import LogOut from "./LogOut.svelte"
|
||||||
|
|
||||||
// defines what actions are available, when adding a new one
|
// defines what actions are available, when adding a new one
|
||||||
// the component is the setup panel for the action
|
// the component is the setup panel for the action
|
||||||
|
@ -35,4 +37,12 @@ export default [
|
||||||
name: "Validate Form",
|
name: "Validate Form",
|
||||||
component: ValidateForm,
|
component: ValidateForm,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Log In",
|
||||||
|
component: LogIn,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Log Out",
|
||||||
|
component: LogOut,
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
screenStore,
|
screenStore,
|
||||||
authStore,
|
authStore,
|
||||||
} from "../store"
|
} from "../store"
|
||||||
|
import { TableNames, ActionTypes } from "../constants"
|
||||||
|
|
||||||
// Provide contexts
|
// Provide contexts
|
||||||
setContext("sdk", SDK)
|
setContext("sdk", SDK)
|
||||||
|
@ -25,10 +26,20 @@
|
||||||
await authStore.actions.fetchUser()
|
await authStore.actions.fetchUser()
|
||||||
loaded = true
|
loaded = true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Register this as a refreshable datasource so that user changes cause
|
||||||
|
// the user object to be refreshed
|
||||||
|
$: actions = [
|
||||||
|
{
|
||||||
|
type: ActionTypes.RefreshDatasource,
|
||||||
|
callback: () => authStore.actions.fetchUser(),
|
||||||
|
metadata: { datasource: { type: "table", tableId: TableNames.USERS } },
|
||||||
|
},
|
||||||
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if loaded && $screenStore.activeLayout}
|
{#if loaded && $screenStore.activeLayout}
|
||||||
<Provider key="user" data={$authStore}>
|
<Provider key="user" data={$authStore} {actions}>
|
||||||
<Component definition={$screenStore.activeLayout.props} />
|
<Component definition={$screenStore.activeLayout.props} />
|
||||||
<NotificationDisplay />
|
<NotificationDisplay />
|
||||||
</Provider>
|
</Provider>
|
||||||
|
|
|
@ -21,7 +21,7 @@ const createAuthStore = () => {
|
||||||
const logIn = async ({ email, password }) => {
|
const logIn = async ({ email, password }) => {
|
||||||
const user = await API.logIn({ email, password })
|
const user = await API.logIn({ email, password })
|
||||||
if (!user.error) {
|
if (!user.error) {
|
||||||
store.set(user)
|
await fetchUser()
|
||||||
await initialise()
|
await initialise()
|
||||||
goToDefaultRoute()
|
goToDefaultRoute()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
import { routeStore, builderStore } from "../store"
|
import { routeStore, builderStore, authStore } from "../store"
|
||||||
import { saveRow, deleteRow, executeQuery, triggerAutomation } from "../api"
|
import { saveRow, deleteRow, executeQuery, triggerAutomation } from "../api"
|
||||||
import { ActionTypes } from "../constants"
|
import { ActionTypes } from "../constants"
|
||||||
|
|
||||||
|
@ -68,6 +68,15 @@ const refreshDatasourceHandler = async (action, context) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loginHandler = async action => {
|
||||||
|
const { email, password } = action.parameters
|
||||||
|
await authStore.actions.logIn({ email, password })
|
||||||
|
}
|
||||||
|
|
||||||
|
const logoutHandler = async () => {
|
||||||
|
await authStore.actions.logOut()
|
||||||
|
}
|
||||||
|
|
||||||
const handlerMap = {
|
const handlerMap = {
|
||||||
["Save Row"]: saveRowHandler,
|
["Save Row"]: saveRowHandler,
|
||||||
["Delete Row"]: deleteRowHandler,
|
["Delete Row"]: deleteRowHandler,
|
||||||
|
@ -76,6 +85,8 @@ const handlerMap = {
|
||||||
["Trigger Automation"]: triggerAutomationHandler,
|
["Trigger Automation"]: triggerAutomationHandler,
|
||||||
["Validate Form"]: validateFormHandler,
|
["Validate Form"]: validateFormHandler,
|
||||||
["Refresh Datasource"]: refreshDatasourceHandler,
|
["Refresh Datasource"]: refreshDatasourceHandler,
|
||||||
|
["Log In"]: loginHandler,
|
||||||
|
["Log Out"]: logoutHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -294,6 +294,63 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"backgroundimage": {
|
||||||
|
"name": "Background Image",
|
||||||
|
"description": "A background image",
|
||||||
|
"icon": "ri-image-line",
|
||||||
|
"styleable": true,
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"label": "URL",
|
||||||
|
"key": "url"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "select",
|
||||||
|
"label": "Position",
|
||||||
|
"key": "position",
|
||||||
|
"defaultValue": "center center",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "Center Top",
|
||||||
|
"value": "center top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Center",
|
||||||
|
"value": "center center"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Center Bottom",
|
||||||
|
"value": "center bottom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Left Top",
|
||||||
|
"value": "left top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Left Center",
|
||||||
|
"value": "left center"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Left Bottom",
|
||||||
|
"value": "left bottom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Right Top",
|
||||||
|
"value": "right top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Right Center",
|
||||||
|
"value": "right center"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Right Bottom",
|
||||||
|
"value": "right bottom"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"icon": {
|
"icon": {
|
||||||
"name": "Icon",
|
"name": "Icon",
|
||||||
"description": "A basic component for displaying icons",
|
"description": "A basic component for displaying icons",
|
||||||
|
@ -394,6 +451,11 @@
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"label": "New Tab",
|
"label": "New Tab",
|
||||||
"key": "openInNewTab"
|
"key": "openInNewTab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "External",
|
||||||
|
"key": "external"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1233,6 +1295,34 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"passwordfield": {
|
||||||
|
"name": "Password Field",
|
||||||
|
"icon": "ri-lock-password-line",
|
||||||
|
"styleable": true,
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"type": "field/string",
|
||||||
|
"label": "Field",
|
||||||
|
"key": "field"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"label": "Label",
|
||||||
|
"key": "label"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"label": "Placeholder",
|
||||||
|
"key": "placeholder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Disabled",
|
||||||
|
"key": "disabled",
|
||||||
|
"defaultValue": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"optionsfield": {
|
"optionsfield": {
|
||||||
"name": "Options Picker",
|
"name": "Options Picker",
|
||||||
"icon": "ri-file-list-line",
|
"icon": "ri-file-list-line",
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<script>
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
|
||||||
|
const { styleable } = getContext("sdk")
|
||||||
|
const component = getContext("component")
|
||||||
|
|
||||||
|
export let url
|
||||||
|
export let position
|
||||||
|
|
||||||
|
let style = ""
|
||||||
|
$: {
|
||||||
|
if (url) {
|
||||||
|
style += `background-image: url("${url}");`
|
||||||
|
}
|
||||||
|
if (position) {
|
||||||
|
style += `background-position: ${position};`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="outer" use:styleable={$component.styles}>
|
||||||
|
<div class="inner" {style} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.outer {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inner {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -7,11 +7,19 @@
|
||||||
export let url = ""
|
export let url = ""
|
||||||
export let text = ""
|
export let text = ""
|
||||||
export let openInNewTab = false
|
export let openInNewTab = false
|
||||||
|
export let external = false
|
||||||
|
|
||||||
$: target = openInNewTab ? "_blank" : "_self"
|
$: target = openInNewTab ? "_blank" : "_self"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if external}
|
||||||
|
<a href={url || '/'} {target} use:styleable={$component.styles}>
|
||||||
|
{text}
|
||||||
|
<slot />
|
||||||
|
</a>
|
||||||
|
{:else}
|
||||||
<a href={url || '/'} use:linkable {target} use:styleable={$component.styles}>
|
<a href={url || '/'} use:linkable {target} use:styleable={$component.styles}>
|
||||||
{text}
|
{text}
|
||||||
<slot />
|
<slot />
|
||||||
</a>
|
</a>
|
||||||
|
{/if}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<script>
|
||||||
|
import StringField from "./StringField.svelte"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<StringField {...$$props} type="password" />
|
|
@ -8,3 +8,4 @@ export { default as longformfield } from "./LongFormField.svelte"
|
||||||
export { default as datetimefield } from "./DateTimeField.svelte"
|
export { default as datetimefield } from "./DateTimeField.svelte"
|
||||||
export { default as attachmentfield } from "./AttachmentField.svelte"
|
export { default as attachmentfield } from "./AttachmentField.svelte"
|
||||||
export { default as relationshipfield } from "./RelationshipField.svelte"
|
export { default as relationshipfield } from "./RelationshipField.svelte"
|
||||||
|
export { default as passwordfield } from "./PasswordField.svelte"
|
||||||
|
|
|
@ -31,5 +31,6 @@ export { default as cardhorizontal } from "./CardHorizontal.svelte"
|
||||||
export { default as cardstat } from "./CardStat.svelte"
|
export { default as cardstat } from "./CardStat.svelte"
|
||||||
export { default as icon } from "./Icon.svelte"
|
export { default as icon } from "./Icon.svelte"
|
||||||
export { default as search } from "./Search.svelte"
|
export { default as search } from "./Search.svelte"
|
||||||
|
export { default as backgroundimage } from "./BackgroundImage.svelte"
|
||||||
export * from "./charts"
|
export * from "./charts"
|
||||||
export * from "./forms"
|
export * from "./forms"
|
||||||
|
|
Loading…
Reference in New Issue