diff --git a/LICENSE b/LICENSE index a6bd926020..e4721dea64 100644 --- a/LICENSE +++ b/LICENSE @@ -5,7 +5,6 @@ Each Budibase package has its own license: builder: GPLv3 server: GPLv3 client: MPLv2.0 -standard-components: MPLv2.0 You can consider Budibase to be GPLv3 licensed. diff --git a/lerna.json b/lerna.json index 5bbd1fee4e..6eb85a8173 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "0.9.122", + "version": "0.9.123-alpha.3", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/package.json b/package.json index 05c69e54dc..f8d9d1789e 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "setup": "node ./hosting/scripts/setup.js && yarn && yarn bootstrap && yarn build && yarn dev", "bootstrap": "lerna link && lerna bootstrap", "build": "lerna run build", - "initialise": "lerna run initialise", "publishdev": "lerna run publishdev", "publishnpm": "yarn build && lerna publish --force-publish", "release": "yarn build && lerna publish patch --yes --force-publish", diff --git a/packages/auth/package.json b/packages/auth/package.json index 487dfe8061..27f85dc6a4 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/auth", - "version": "0.9.122", + "version": "0.9.123-alpha.3", "description": "Authentication middlewares for budibase builder and apps", "main": "src/index.js", "author": "Budibase", diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 1116c0a605..a5d7c1f100 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -70,6 +70,23 @@ function isDevApp(app) { return exports.isDevAppID(app.appId) } +/** + * Given an app ID this will attempt to retrieve the tenant ID from it. + * @return {null|string} The tenant ID found within the app ID. + */ +exports.getTenantIDFromAppID = appId => { + const split = appId.split(SEPARATOR) + const hasDev = split[1] === DocumentTypes.DEV + if ((hasDev && split.length === 3) || (!hasDev && split.length === 2)) { + return null + } + if (hasDev) { + return split[2] + } else { + return split[1] + } +} + /** * Generates a new workspace ID. * @returns {string} The new workspace ID which the workspace doc can be stored under. diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 5421dea214..569456ea10 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -11,6 +11,7 @@ const { oidc, auditLog, tenancy, + appTenancy, } = require("./middleware") const { setDB } = require("./db") const userCache = require("./cache/user") @@ -57,6 +58,7 @@ module.exports = { oidc, jwt: require("jsonwebtoken"), buildTenancyMiddleware: tenancy, + buildAppTenancyMiddleware: appTenancy, auditLog, }, cache: { diff --git a/packages/auth/src/middleware/appTenancy.js b/packages/auth/src/middleware/appTenancy.js new file mode 100644 index 0000000000..30fc4f7453 --- /dev/null +++ b/packages/auth/src/middleware/appTenancy.js @@ -0,0 +1,25 @@ +const { + isMultiTenant, + updateTenantId, + isTenantIdSet, + DEFAULT_TENANT_ID, +} = require("../tenancy") +const ContextFactory = require("../tenancy/FunctionContext") +const { getTenantIDFromAppID } = require("../db/utils") + +module.exports = () => { + return ContextFactory.getMiddleware(ctx => { + // if not in multi-tenancy mode make sure its default and exit + if (!isMultiTenant()) { + updateTenantId(DEFAULT_TENANT_ID) + return + } + // if tenant ID already set no need to continue + if (isTenantIdSet()) { + return + } + const appId = ctx.appId ? ctx.appId : ctx.user ? ctx.user.appId : null + const tenantId = getTenantIDFromAppID(appId) || DEFAULT_TENANT_ID + updateTenantId(tenantId) + }) +} diff --git a/packages/auth/src/middleware/index.js b/packages/auth/src/middleware/index.js index 689859a139..059f20af8b 100644 --- a/packages/auth/src/middleware/index.js +++ b/packages/auth/src/middleware/index.js @@ -5,6 +5,7 @@ const oidc = require("./passport/oidc") const authenticated = require("./authenticated") const auditLog = require("./auditLog") const tenancy = require("./tenancy") +const appTenancy = require("./appTenancy") module.exports = { google, @@ -14,4 +15,5 @@ module.exports = { authenticated, auditLog, tenancy, + appTenancy, } diff --git a/packages/auth/src/middleware/tenancy.js b/packages/auth/src/middleware/tenancy.js index 19cce82273..adfd36a503 100644 --- a/packages/auth/src/middleware/tenancy.js +++ b/packages/auth/src/middleware/tenancy.js @@ -2,7 +2,11 @@ const { setTenantId } = require("../tenancy") const ContextFactory = require("../tenancy/FunctionContext") const { buildMatcherRegex, matches } = require("./matchers") -module.exports = (allowQueryStringPatterns, noTenancyPatterns, opts = {}) => { +module.exports = ( + allowQueryStringPatterns, + noTenancyPatterns, + opts = { noTenancyRequired: false } +) => { const allowQsOptions = buildMatcherRegex(allowQueryStringPatterns) const noTenancyOptions = buildMatcherRegex(noTenancyPatterns) diff --git a/packages/auth/src/tenancy/context.js b/packages/auth/src/tenancy/context.js index f3f1f541e9..b1ef5a5807 100644 --- a/packages/auth/src/tenancy/context.js +++ b/packages/auth/src/tenancy/context.js @@ -21,9 +21,7 @@ exports.doInTenant = (tenantId, task) => { cls.setOnContext(TENANT_ID, tenantId) // invoke the task - const result = task() - - return result + return task() }) } diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 3a841ba064..6254c17042 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "0.9.122", + "version": "0.9.123-alpha.3", "license": "AGPL-3.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", diff --git a/packages/bbui/src/Form/Core/DatePicker.svelte b/packages/bbui/src/Form/Core/DatePicker.svelte index 44b77e0bbe..18c93b6c5c 100644 --- a/packages/bbui/src/Form/Core/DatePicker.svelte +++ b/packages/bbui/src/Form/Core/DatePicker.svelte @@ -13,6 +13,7 @@ export let enableTime = true export let value = null export let placeholder = null + export let appendTo = null const dispatch = createEventDispatcher() const flatpickrId = `${generateID()}-wrapper` @@ -24,6 +25,7 @@ altInput: true, altFormat: enableTime ? "F j Y, H:i" : "F j, Y", wrap: true, + appendTo, } const handleChange = event => { diff --git a/packages/bbui/src/Form/DatePicker.svelte b/packages/bbui/src/Form/DatePicker.svelte index 9e0c40b11d..aff7ddc1c5 100644 --- a/packages/bbui/src/Form/DatePicker.svelte +++ b/packages/bbui/src/Form/DatePicker.svelte @@ -10,6 +10,7 @@ export let error = null export let enableTime = true export let placeholder = null + export let appendTo = null const dispatch = createEventDispatcher() const onChange = e => { @@ -26,6 +27,7 @@ {value} {placeholder} {enableTime} + {appendTo} on:change={onChange} /> diff --git a/packages/bbui/src/Icon/Icon.svelte b/packages/bbui/src/Icon/Icon.svelte index ffaa99cb79..2f39fde0d9 100644 --- a/packages/bbui/src/Icon/Icon.svelte +++ b/packages/bbui/src/Icon/Icon.svelte @@ -36,7 +36,7 @@ transition: color var(--spectrum-global-animation-duration-100, 130ms); } svg.hoverable:hover { - color: var(--spectrum-alias-icon-color-selected); + color: var(--spectrum-alias-icon-color-selected-hover); cursor: pointer; } diff --git a/packages/builder/package.json b/packages/builder/package.json index dd31322643..461c499898 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "0.9.122", + "version": "0.9.123-alpha.3", "license": "AGPL-3.0", "private": true, "scripts": { @@ -65,10 +65,10 @@ } }, "dependencies": { - "@budibase/bbui": "^0.9.122", - "@budibase/client": "^0.9.122", + "@budibase/bbui": "^0.9.123-alpha.3", + "@budibase/client": "^0.9.123-alpha.3", "@budibase/colorpicker": "1.1.2", - "@budibase/string-templates": "^0.9.122", + "@budibase/string-templates": "^0.9.123-alpha.3", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index 887695d41e..903512d0fb 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -266,12 +266,16 @@ const getDeviceBindings = () => { * Gets all state bindings that are globally available. */ const getStateBindings = () => { - const safeState = makePropSafe("state") - return getAllStateVariables().map(key => ({ - type: "context", - runtimeBinding: `${safeState}.${makePropSafe(key)}`, - readableBinding: `State.${key}`, - })) + let bindings = [] + if (get(store).clientFeatures?.state) { + const safeState = makePropSafe("state") + bindings = getAllStateVariables().map(key => ({ + type: "context", + runtimeBinding: `${safeState}.${makePropSafe(key)}`, + readableBinding: `State.${key}`, + })) + } + return bindings } /** diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 192ade9e5d..7d0b9d0547 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -41,6 +41,8 @@ const INITIAL_FRONTEND_STATE = { spectrumThemes: false, intelligentLoading: false, deviceAwareness: false, + state: false, + customThemes: false, }, currentFrontEndType: "none", selectedScreenId: "", @@ -53,6 +55,7 @@ const INITIAL_FRONTEND_STATE = { routes: {}, clientLibPath: "", theme: "", + customTheme: {}, } export const getFrontendStore = () => { @@ -77,6 +80,7 @@ export const getFrontendStore = () => { layouts, screens, theme: application.theme || "spectrum--light", + customTheme: application.customTheme, hasAppPackage: true, appInstance: application.instance, clientLibPath, @@ -110,6 +114,22 @@ export const getFrontendStore = () => { } }, }, + customTheme: { + save: async customTheme => { + const appId = get(store).appId + const response = await api.put(`/api/applications/${appId}`, { + customTheme, + }) + if (response.status === 200) { + store.update(state => { + state.customTheme = customTheme + return state + }) + } else { + throw new Error("Error updating theme") + } + }, + }, routing: { fetch: async () => { const response = await api.get("/api/routing") diff --git a/packages/builder/src/components/common/ConfigChecklist.svelte b/packages/builder/src/components/common/ConfigChecklist.svelte index 83e6a41063..7914a78b65 100644 --- a/packages/builder/src/components/common/ConfigChecklist.svelte +++ b/packages/builder/src/components/common/ConfigChecklist.svelte @@ -7,13 +7,7 @@ ProgressCircle, } from "@budibase/bbui" import { admin } from "stores/portal" - - const MESSAGES = { - apps: "Create your first app", - smtp: "Set up email", - adminUser: "Create your first user", - sso: "Set up single sign-on", - } + import { goto } from "@roxi/routify" @@ -28,9 +22,12 @@ {#each Object.keys($admin.checklist) as checklistItem, idx} -
- {idx + 1}. {MESSAGES[checklistItem]} - +
$goto($admin.checklist[checklistItem].link)} + > + {idx + 1}. {$admin.checklist[checklistItem].label} +
{/each} diff --git a/packages/builder/src/components/design/AppPreview/AppThemeSelect.svelte b/packages/builder/src/components/design/AppPreview/AppThemeSelect.svelte index 21dae25708..ec51688219 100644 --- a/packages/builder/src/components/design/AppPreview/AppThemeSelect.svelte +++ b/packages/builder/src/components/design/AppPreview/AppThemeSelect.svelte @@ -33,6 +33,6 @@ diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 38441d4323..85fb086b59 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -49,6 +49,7 @@ selectedComponentId, previewType: $store.currentFrontEndType, theme: $store.theme, + customTheme: $store.customTheme, } // Saving pages and screens to the DB causes them to have _revs. diff --git a/packages/builder/src/components/design/AppPreview/ThemeEditor.svelte b/packages/builder/src/components/design/AppPreview/ThemeEditor.svelte new file mode 100644 index 0000000000..c5c85fad46 --- /dev/null +++ b/packages/builder/src/components/design/AppPreview/ThemeEditor.svelte @@ -0,0 +1,140 @@ + + +
+ Theme +
+ + + +
+ + +
+
+ +
+