From dbbcf4052e6a2eb7130aa21c015df8e920f848c8 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 2 Sep 2021 11:38:41 +0100 Subject: [PATCH] Hide state action in old apps and add working basic implementation of theming --- .../src/builderStore/store/frontend.js | 20 ++++ .../design/AppPreview/AppThemeSelect.svelte | 1 + .../AppPreview/CurrentItemPreview.svelte | 1 + .../design/AppPreview/ThemeEditor.svelte | 76 +++++++++++++ .../design/AppPreview/iframeTemplate.js | 4 +- .../EventsEditor/EventEditor.svelte | 3 +- .../EventsEditor/actions/index.js | 102 ++++++++++-------- .../design/[assetType]/_layout.svelte | 17 ++- packages/client/manifest.json | 4 +- .../client/src/components/ClientApp.svelte | 27 +++-- packages/client/src/index.js | 1 + packages/client/src/stores/index.js | 1 + packages/client/src/stores/theme.js | 30 ++++++ 13 files changed, 230 insertions(+), 57 deletions(-) create mode 100644 packages/builder/src/components/design/AppPreview/ThemeEditor.svelte create mode 100644 packages/client/src/stores/theme.js 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/design/AppPreview/AppThemeSelect.svelte b/packages/builder/src/components/design/AppPreview/AppThemeSelect.svelte index 21dae25708..09041dbf5a 100644 --- a/packages/builder/src/components/design/AppPreview/AppThemeSelect.svelte +++ b/packages/builder/src/components/design/AppPreview/AppThemeSelect.svelte @@ -33,6 +33,7 @@ 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..6ea82e2713 --- /dev/null +++ b/packages/builder/src/components/design/AppPreview/ThemeEditor.svelte @@ -0,0 +1,76 @@ + + +
+ Edit +
+ + + +
+ + +
+
+ + +
+
+
+
+ + diff --git a/packages/builder/src/components/design/AppPreview/iframeTemplate.js b/packages/builder/src/components/design/AppPreview/iframeTemplate.js index 1e3ff7c856..85f008df08 100644 --- a/packages/builder/src/components/design/AppPreview/iframeTemplate.js +++ b/packages/builder/src/components/design/AppPreview/iframeTemplate.js @@ -66,7 +66,8 @@ export default ` screen, previewType, appId, - theme + theme, + customTheme } = parsed // Set some flags so the app knows we're in the builder @@ -78,6 +79,7 @@ export default ` window["##BUDIBASE_PREVIEW_ID##"] = Math.random() window["##BUDIBASE_PREVIEW_TYPE##"] = previewType window["##BUDIBASE_PREVIEW_THEME##"] = theme + window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"] = customTheme // Initialise app try { diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventEditor.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventEditor.svelte index 4ff746a034..d0c561546f 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventEditor.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventEditor.svelte @@ -9,11 +9,12 @@ ActionMenu, MenuItem, } from "@budibase/bbui" - import actionTypes from "./actions" + import { getAvailableActions } from "./actions" import { generate } from "shortid" const flipDurationMs = 150 const EVENT_TYPE_KEY = "##eventHandlerType" + const actionTypes = getAvailableActions() export let actions export let bindings = [] 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 6c285939ac..eaab22d89d 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 @@ -1,3 +1,6 @@ +import { store } from "builderStore" +import { get } from "svelte/store" + import NavigateTo from "./NavigateTo.svelte" import SaveRow from "./SaveRow.svelte" import DeleteRow from "./DeleteRow.svelte" @@ -17,49 +20,56 @@ import UpdateStateStep from "./UpdateState.svelte" // be considered as camel case too. // There is technical debt here to sanitize all these and standardise them // across the packages but it's a breaking change to existing apps. -export default [ - { - name: "Save Row", - component: SaveRow, - }, - { - name: "Delete Row", - component: DeleteRow, - }, - { - name: "Navigate To", - component: NavigateTo, - }, - { - name: "Execute Query", - component: ExecuteQuery, - }, - { - name: "Trigger Automation", - component: TriggerAutomation, - }, - { - name: "Validate Form", - component: ValidateForm, - }, - { - name: "Log Out", - component: LogOut, - }, - { - name: "Clear Form", - component: ClearForm, - }, - { - name: "Close Screen Modal", - component: CloseScreenModal, - }, - { - name: "Change Form Step", - component: ChangeFormStep, - }, - { - name: "Update State", - component: UpdateStateStep, - }, -] +export const getAvailableActions = () => { + let actions = [ + { + name: "Save Row", + component: SaveRow, + }, + { + name: "Delete Row", + component: DeleteRow, + }, + { + name: "Navigate To", + component: NavigateTo, + }, + { + name: "Execute Query", + component: ExecuteQuery, + }, + { + name: "Trigger Automation", + component: TriggerAutomation, + }, + { + name: "Validate Form", + component: ValidateForm, + }, + { + name: "Log Out", + component: LogOut, + }, + { + name: "Clear Form", + component: ClearForm, + }, + { + name: "Close Screen Modal", + component: CloseScreenModal, + }, + { + name: "Change Form Step", + component: ChangeFormStep, + }, + ] + + if (get(store).clientFeatures?.state) { + actions.push({ + name: "Update State", + component: UpdateStateStep, + }) + } + + return actions +} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte index 207daae84a..b5d1a8df11 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte @@ -14,6 +14,7 @@ import { findComponent, findComponentPath } from "builderStore/storeUtils" import { get } from "svelte/store" import AppThemeSelect from "components/design/AppPreview/AppThemeSelect.svelte" + import ThemeEditor from "components/design/AppPreview/ThemeEditor.svelte" // Cache previous values so we don't update the URL more than necessary let previousType @@ -153,6 +154,9 @@ {#if $store.clientFeatures.spectrumThemes} {/if} + {#if $store.clientFeatures.customThemes} + + {/if}
{#key $store.version} @@ -202,9 +206,18 @@ padding: var(--spacing-xl) 40px; } .preview-header { - display: grid; - grid-template-columns: 1fr 100px; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; } + .preview-header > :global(*) { + flex: 0 0 auto; + } + .preview-header > :global(*:first-child) { + flex: 1 1 auto; + } + .preview-content { flex: 1 1 auto; } diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 194706744d..51ae1cf30d 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -2,7 +2,9 @@ "features": { "spectrumThemes": true, "intelligentLoading": true, - "deviceAwareness": true + "deviceAwareness": true, + "state": true, + "customThemes": true }, "layout": { "name": "Layout", diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index cdc39ac225..4c494f9104 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -11,7 +11,7 @@ authStore, routeStore, builderStore, - appStore, + themeStore, } from "stores" import NotificationDisplay from "components/overlay/NotificationDisplay.svelte" import ConfirmationDisplay from "components/overlay/ConfirmationDisplay.svelte" @@ -63,9 +63,6 @@ } } } - - $: themeClass = - $builderStore.theme || $appStore.application?.theme || "spectrum--light" {#if dataLoaded} @@ -73,7 +70,7 @@ id="spectrum-root" lang="en" dir="ltr" - class="spectrum spectrum--medium {themeClass}" + class="spectrum spectrum--medium {$themeStore.theme}" > {#if permissionError}
@@ -87,7 +84,11 @@ -
+
{#key $screenStore.activeLayout._id} {/key} @@ -132,6 +133,20 @@ border: 1px solid var(--spectrum-global-color-gray-300); } + #app-root { + /* Primary */ + --spectrum-global-color-blue-600: var(--primaryColor); + --spectrum-global-color-blue-700: var(--primaryColor); + --spectrum-global-color-static-blue-600: var(--primaryColor); + --spectrum-global-color-static-blue-700: var(--primaryColor); + + /* Primary hover */ + --spectrum-global-color-blue-400: var(--primaryColorHover); + --spectrum-global-color-blue-500: var(--primaryColorHover); + --spectrum-global-color-static-blue-400: var(--primaryColorHover); + --spectrum-global-color-static-blue-500: var(--primaryColorHover); + } + /* Custom scrollbars */ :global(::-webkit-scrollbar) { width: 8px; diff --git a/packages/client/src/index.js b/packages/client/src/index.js index ceae36c9f3..2d1c9fd1c0 100644 --- a/packages/client/src/index.js +++ b/packages/client/src/index.js @@ -17,6 +17,7 @@ const loadBudibase = () => { previewId: window["##BUDIBASE_PREVIEW_ID##"], previewType: window["##BUDIBASE_PREVIEW_TYPE##"], theme: window["##BUDIBASE_PREVIEW_THEME##"], + customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"], }) // Set app ID - this window flag is set by both the preview and the real diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index 6c99e3f453..02c848120c 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -8,6 +8,7 @@ export { dataSourceStore } from "./dataSource" export { confirmationStore } from "./confirmation" export { peekStore } from "./peek" export { stateStore } from "./state" +export { themeStore } from "./theme" // Context stores are layered and duplicated, so it is not a singleton export { createContextStore } from "./context" diff --git a/packages/client/src/stores/theme.js b/packages/client/src/stores/theme.js new file mode 100644 index 0000000000..821c41ccc7 --- /dev/null +++ b/packages/client/src/stores/theme.js @@ -0,0 +1,30 @@ +import { derived } from "svelte/store" +import { appStore } from "./app" +import { builderStore } from "./builder" + +const createThemeStore = () => { + const store = derived( + [builderStore, appStore], + ([$builderStore, $appStore]) => { + const theme = + $builderStore.theme || $appStore.application?.theme || "spectrum--light" + const customTheme = + $builderStore.customTheme || $appStore.application?.customTheme || {} + let customThemeCss = "" + Object.entries(customTheme).forEach(([key, value]) => { + customThemeCss += `--${key}:${value};` + }) + return { + theme, + customTheme, + customThemeCss, + } + } + ) + + return { + subscribe: store.subscribe, + } +} + +export const themeStore = createThemeStore()