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
|
||||
|
||||
// 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["_rev"] = { type: "string" }
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"fieldgroup",
|
||||
"stringfield",
|
||||
"numberfield",
|
||||
"passwordfield",
|
||||
"optionsfield",
|
||||
"booleanfield",
|
||||
"longformfield",
|
||||
|
@ -49,6 +50,7 @@
|
|||
"heading",
|
||||
"text",
|
||||
"image",
|
||||
"backgroundimage",
|
||||
"link",
|
||||
"icon",
|
||||
"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 TriggerAutomation from "./TriggerAutomation.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
|
||||
// the component is the setup panel for the action
|
||||
|
@ -35,4 +37,12 @@ export default [
|
|||
name: "Validate Form",
|
||||
component: ValidateForm,
|
||||
},
|
||||
{
|
||||
name: "Log In",
|
||||
component: LogIn,
|
||||
},
|
||||
{
|
||||
name: "Log Out",
|
||||
component: LogOut,
|
||||
},
|
||||
]
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
screenStore,
|
||||
authStore,
|
||||
} from "../store"
|
||||
import { TableNames, ActionTypes } from "../constants"
|
||||
|
||||
// Provide contexts
|
||||
setContext("sdk", SDK)
|
||||
|
@ -25,10 +26,20 @@
|
|||
await authStore.actions.fetchUser()
|
||||
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>
|
||||
|
||||
{#if loaded && $screenStore.activeLayout}
|
||||
<Provider key="user" data={$authStore}>
|
||||
<Provider key="user" data={$authStore} {actions}>
|
||||
<Component definition={$screenStore.activeLayout.props} />
|
||||
<NotificationDisplay />
|
||||
</Provider>
|
||||
|
|
|
@ -21,7 +21,7 @@ const createAuthStore = () => {
|
|||
const logIn = async ({ email, password }) => {
|
||||
const user = await API.logIn({ email, password })
|
||||
if (!user.error) {
|
||||
store.set(user)
|
||||
await fetchUser()
|
||||
await initialise()
|
||||
goToDefaultRoute()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { get } from "svelte/store"
|
||||
import { routeStore, builderStore } from "../store"
|
||||
import { routeStore, builderStore, authStore } from "../store"
|
||||
import { saveRow, deleteRow, executeQuery, triggerAutomation } from "../api"
|
||||
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 = {
|
||||
["Save Row"]: saveRowHandler,
|
||||
["Delete Row"]: deleteRowHandler,
|
||||
|
@ -76,6 +85,8 @@ const handlerMap = {
|
|||
["Trigger Automation"]: triggerAutomationHandler,
|
||||
["Validate Form"]: validateFormHandler,
|
||||
["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": {
|
||||
"name": "Icon",
|
||||
"description": "A basic component for displaying icons",
|
||||
|
@ -394,6 +451,11 @@
|
|||
"type": "boolean",
|
||||
"label": "New Tab",
|
||||
"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": {
|
||||
"name": "Options Picker",
|
||||
"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 text = ""
|
||||
export let openInNewTab = false
|
||||
export let external = false
|
||||
|
||||
$: target = openInNewTab ? "_blank" : "_self"
|
||||
</script>
|
||||
|
||||
<a href={url || '/'} use:linkable {target} use:styleable={$component.styles}>
|
||||
{text}
|
||||
<slot />
|
||||
</a>
|
||||
{#if external}
|
||||
<a href={url || '/'} {target} use:styleable={$component.styles}>
|
||||
{text}
|
||||
<slot />
|
||||
</a>
|
||||
{:else}
|
||||
<a href={url || '/'} use:linkable {target} use:styleable={$component.styles}>
|
||||
{text}
|
||||
<slot />
|
||||
</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 attachmentfield } from "./AttachmentField.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 icon } from "./Icon.svelte"
|
||||
export { default as search } from "./Search.svelte"
|
||||
export { default as backgroundimage } from "./BackgroundImage.svelte"
|
||||
export * from "./charts"
|
||||
export * from "./forms"
|
||||
|
|
Loading…
Reference in New Issue