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"