diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js
index 429ba1c683..dee0b86fb3 100644
--- a/packages/builder/src/builderStore/dataBinding.js
+++ b/packages/builder/src/builderStore/dataBinding.js
@@ -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" }
}
diff --git a/packages/builder/src/components/design/AppPreview/componentStructure.json b/packages/builder/src/components/design/AppPreview/componentStructure.json
index 87bef3d3a1..16109b5a96 100644
--- a/packages/builder/src/components/design/AppPreview/componentStructure.json
+++ b/packages/builder/src/components/design/AppPreview/componentStructure.json
@@ -12,6 +12,7 @@
"fieldgroup",
"stringfield",
"numberfield",
+ "passwordfield",
"optionsfield",
"booleanfield",
"longformfield",
@@ -49,6 +50,7 @@
"heading",
"text",
"image",
+ "backgroundimage",
"link",
"icon",
"embed"
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/LogIn.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/LogIn.svelte
new file mode 100644
index 0000000000..c49369bf29
--- /dev/null
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/LogIn.svelte
@@ -0,0 +1,36 @@
+
+
+
+
+ (parameters.email = value.detail)}
+ {bindings} />
+
+ (parameters.password = value.detail)}
+ {bindings} />
+
+
+
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/LogOut.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/LogOut.svelte
new file mode 100644
index 0000000000..2b0aad8342
--- /dev/null
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/LogOut.svelte
@@ -0,0 +1,7 @@
+This action doesn't require any additional settings.
+
+
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/index.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/index.js
index e851bdb4be..4700ea5c8f 100644
--- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/index.js
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/index.js
@@ -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,
+ },
]
diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte
index e204209526..e8ab668ef2 100644
--- a/packages/client/src/components/ClientApp.svelte
+++ b/packages/client/src/components/ClientApp.svelte
@@ -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 } },
+ },
+ ]
{#if loaded && $screenStore.activeLayout}
-
+
diff --git a/packages/client/src/store/auth.js b/packages/client/src/store/auth.js
index 29ded50ac7..8158e343c4 100644
--- a/packages/client/src/store/auth.js
+++ b/packages/client/src/store/auth.js
@@ -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()
}
diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js
index cadb046514..4d2865d586 100644
--- a/packages/client/src/utils/buttonActions.js
+++ b/packages/client/src/utils/buttonActions.js
@@ -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,
}
/**
diff --git a/packages/standard-components/manifest.json b/packages/standard-components/manifest.json
index cb321f1bb9..14b20dd9ad 100644
--- a/packages/standard-components/manifest.json
+++ b/packages/standard-components/manifest.json
@@ -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",
diff --git a/packages/standard-components/src/BackgroundImage.svelte b/packages/standard-components/src/BackgroundImage.svelte
new file mode 100644
index 0000000000..c78cdc87b6
--- /dev/null
+++ b/packages/standard-components/src/BackgroundImage.svelte
@@ -0,0 +1,38 @@
+
+
+
+
+
diff --git a/packages/standard-components/src/Link.svelte b/packages/standard-components/src/Link.svelte
index 5ae1ae75c4..0ada211eb7 100644
--- a/packages/standard-components/src/Link.svelte
+++ b/packages/standard-components/src/Link.svelte
@@ -7,11 +7,19 @@
export let url = ""
export let text = ""
export let openInNewTab = false
+ export let external = false
$: target = openInNewTab ? "_blank" : "_self"
-
- {text}
-
-
+{#if external}
+
+ {text}
+
+
+{:else}
+
+ {text}
+
+
+{/if}
diff --git a/packages/standard-components/src/forms/PasswordField.svelte b/packages/standard-components/src/forms/PasswordField.svelte
new file mode 100644
index 0000000000..71edd4f97f
--- /dev/null
+++ b/packages/standard-components/src/forms/PasswordField.svelte
@@ -0,0 +1,5 @@
+
+
+
diff --git a/packages/standard-components/src/forms/index.js b/packages/standard-components/src/forms/index.js
index 3998424db3..fed371278b 100644
--- a/packages/standard-components/src/forms/index.js
+++ b/packages/standard-components/src/forms/index.js
@@ -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"
diff --git a/packages/standard-components/src/index.js b/packages/standard-components/src/index.js
index 14886e2a17..a9d8920895 100644
--- a/packages/standard-components/src/index.js
+++ b/packages/standard-components/src/index.js
@@ -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"