From 1d0ab398cd22de9b5f26531d523078d728e2ea21 Mon Sep 17 00:00:00 2001 From: Gerard Burns Date: Tue, 18 Jul 2023 15:55:06 +0100 Subject: [PATCH 001/183] New Design Section Nav Component --- .../builder/src/components/design/Pane.svelte | 21 +++ .../src/components/design/RightPanel.svelte | 112 +++++++++++ .../_components/NavigationInfoPanel.svelte | 33 ---- .../NavigationInfoPanel/CustomizePane.svelte | 176 ++++++++++++++++++ .../NavigationInfoPanel/SettingsPane.svelte | 31 +++ .../NavigationInfoPanel/index.svelte | 10 + .../design/[screenId]/navigation/index.svelte | 2 +- 7 files changed, 351 insertions(+), 34 deletions(-) create mode 100644 packages/builder/src/components/design/Pane.svelte create mode 100644 packages/builder/src/components/design/RightPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte diff --git a/packages/builder/src/components/design/Pane.svelte b/packages/builder/src/components/design/Pane.svelte new file mode 100644 index 0000000000..88b6ea1c05 --- /dev/null +++ b/packages/builder/src/components/design/Pane.svelte @@ -0,0 +1,21 @@ + + +{#if $paneStore} +
+ +
+{/if} + + diff --git a/packages/builder/src/components/design/RightPanel.svelte b/packages/builder/src/components/design/RightPanel.svelte new file mode 100644 index 0000000000..f9075600f9 --- /dev/null +++ b/packages/builder/src/components/design/RightPanel.svelte @@ -0,0 +1,112 @@ + + +
+
+
+ +
+ {title} +
+
+ {#each Object.entries(panes) as [id, pane]} +
+ +
+ {/each} +
+
+ + +
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte deleted file mode 100644 index 614e1eed80..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {#if $selectedScreen.layoutId} - - You can't preview your navigation settings using this screen as it uses - a custom layout, which is deprecated - - {/if} - - Your navigation is configured for all the screens within your app. - - - You can hide and show your navigation for each screen in the screen - settings. - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte new file mode 100644 index 0000000000..05108b1736 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte @@ -0,0 +1,176 @@ + + + +
+
+ + CHANGES WILL APPLY TO ALL SCREENS +
+ + Your navigation is configured for all the screens within your app. + +
+ +
+
+ +
+ + update("navigation", "Top")} + /> + update("navigation", "Left")} + /> + + + {#if $store.navigation.navigation === "Top"} +
+ +
+ update("sticky", e.detail)} + /> +
+ +
+ update("logoUrl", e.detail)} + updateOnChange={false} + /> + {/if} +
+ +
+ update("hideTitle", !e.detail)} + /> + {#if !$store.navigation.hideTitle} +
+ +
+ update("title", e.detail)} + updateOnChange={false} + /> + {/if} +
+ +
+ update("navBackground", e.detail)} + /> +
+ +
+ update("navTextColor", e.detail)} + /> +
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte new file mode 100644 index 0000000000..d3ce720994 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte @@ -0,0 +1,31 @@ + + + +
+ + Show nav on this screen +
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte new file mode 100644 index 0000000000..6ce5405f93 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte @@ -0,0 +1,10 @@ + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte index fc2e03d8e8..2331d8b285 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte @@ -1,6 +1,6 @@ From 00c04ec9acb5c4657402c05b57910af18242f0e8 Mon Sep 17 00:00:00 2001 From: Gerard Burns Date: Thu, 20 Jul 2023 10:05:50 +0100 Subject: [PATCH 002/183] New Design Section Nav Component --- .../builder/src/components/design/Pane.svelte | 21 +++ .../src/components/design/RightPanel.svelte | 112 +++++++++++ .../_components/NavigationInfoPanel.svelte | 33 ---- .../NavigationInfoPanel/CustomizePane.svelte | 176 ++++++++++++++++++ .../NavigationInfoPanel/SettingsPane.svelte | 31 +++ .../NavigationInfoPanel/index.svelte | 10 + .../design/[screenId]/navigation/index.svelte | 2 +- 7 files changed, 351 insertions(+), 34 deletions(-) create mode 100644 packages/builder/src/components/design/Pane.svelte create mode 100644 packages/builder/src/components/design/RightPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte diff --git a/packages/builder/src/components/design/Pane.svelte b/packages/builder/src/components/design/Pane.svelte new file mode 100644 index 0000000000..88b6ea1c05 --- /dev/null +++ b/packages/builder/src/components/design/Pane.svelte @@ -0,0 +1,21 @@ + + +{#if $paneStore} +
+ +
+{/if} + + diff --git a/packages/builder/src/components/design/RightPanel.svelte b/packages/builder/src/components/design/RightPanel.svelte new file mode 100644 index 0000000000..f9075600f9 --- /dev/null +++ b/packages/builder/src/components/design/RightPanel.svelte @@ -0,0 +1,112 @@ + + +
+
+
+ +
+ {title} +
+
+ {#each Object.entries(panes) as [id, pane]} +
+ +
+ {/each} +
+
+ + +
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte deleted file mode 100644 index 614e1eed80..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {#if $selectedScreen.layoutId} - - You can't preview your navigation settings using this screen as it uses - a custom layout, which is deprecated - - {/if} - - Your navigation is configured for all the screens within your app. - - - You can hide and show your navigation for each screen in the screen - settings. - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte new file mode 100644 index 0000000000..05108b1736 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte @@ -0,0 +1,176 @@ + + + +
+
+ + CHANGES WILL APPLY TO ALL SCREENS +
+ + Your navigation is configured for all the screens within your app. + +
+ +
+
+ +
+ + update("navigation", "Top")} + /> + update("navigation", "Left")} + /> + + + {#if $store.navigation.navigation === "Top"} +
+ +
+ update("sticky", e.detail)} + /> +
+ +
+ update("logoUrl", e.detail)} + updateOnChange={false} + /> + {/if} +
+ +
+ update("hideTitle", !e.detail)} + /> + {#if !$store.navigation.hideTitle} +
+ +
+ update("title", e.detail)} + updateOnChange={false} + /> + {/if} +
+ +
+ update("navBackground", e.detail)} + /> +
+ +
+ update("navTextColor", e.detail)} + /> +
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte new file mode 100644 index 0000000000..d3ce720994 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte @@ -0,0 +1,31 @@ + + + +
+ + Show nav on this screen +
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte new file mode 100644 index 0000000000..6ce5405f93 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte @@ -0,0 +1,10 @@ + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte index fc2e03d8e8..2331d8b285 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte @@ -1,6 +1,6 @@ From d94fe7c2eb880c53cdd57d64020790f73ca46d75 Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 20 Jul 2023 11:32:48 +0100 Subject: [PATCH 003/183] Moved screen settings/theme into the new rightpanel structure. Refactord the color picker to help with positioning. Removed dead home link --- .../bbui/src/Actions/position_dropdown.js | 3 +- .../bbui/src/ColorPicker/ColorPicker.svelte | 75 +++---- packages/bbui/src/Popover/Popover.svelte | 8 + .../builder/src/components/design/Pane.svelte | 2 +- .../controls/ColumnEditor/CellDrawer.svelte | 2 - .../design/[screenId]/_layout.svelte | 6 - .../ScreenSettingsPanel/GeneralPane.svelte | 198 ++++++++++++++++++ .../ScreenSettingsPanel/ThemePane.svelte | 98 +++++++++ .../ScreenSettingsPanel/index.svelte | 15 ++ .../theme}/AppThemeSelect.svelte | 0 .../theme}/ButtonRoundnessSelect.svelte | 0 .../design/[screenId]/screens/index.svelte | 2 +- .../theme/_components/ThemeInfoPanel.svelte | 12 -- .../_components/ThemeSettingsPanel.svelte | 55 ----- .../design/[screenId]/theme/index.svelte | 7 - .../server/src/api/controllers/application.ts | 7 +- 16 files changed, 354 insertions(+), 136 deletions(-) create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/GeneralPane.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/ThemePane.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/index.svelte rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{theme/_components => screens/_components/ScreenSettingsPanel/theme}/AppThemeSelect.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{theme/_components => screens/_components/ScreenSettingsPanel/theme}/ButtonRoundnessSelect.svelte (100%) delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeInfoPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeSettingsPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/index.svelte diff --git a/packages/bbui/src/Actions/position_dropdown.js b/packages/bbui/src/Actions/position_dropdown.js index 01555446d9..d73b3b4d6a 100644 --- a/packages/bbui/src/Actions/position_dropdown.js +++ b/packages/bbui/src/Actions/position_dropdown.js @@ -32,11 +32,10 @@ export default function positionDropdown(element, opts) { left: null, top: null, } - // Determine vertical styles if (align === "right-outside") { styles.top = anchorBounds.top - } else if (window.innerHeight - anchorBounds.bottom < 100) { + } else if (window.innerHeight - anchorBounds.bottom < (maxHeight || 100)) { styles.top = anchorBounds.top - elementBounds.height - offset styles.maxHeight = maxHeight || 240 } else { diff --git a/packages/bbui/src/ColorPicker/ColorPicker.svelte b/packages/bbui/src/ColorPicker/ColorPicker.svelte index 9a70134fb6..2ba5309860 100644 --- a/packages/bbui/src/ColorPicker/ColorPicker.svelte +++ b/packages/bbui/src/ColorPicker/ColorPicker.svelte @@ -1,8 +1,8 @@ -
-
(open = true)}> -
-
- {#if open} -
+
{ + dropdown.toggle() + }} +> +
+
+ + + +
{#each categories as category}
{category.label}
@@ -187,8 +184,8 @@
- {/if} -
+ + diff --git a/packages/builder/src/components/design/settings/controls/ColumnEditor/CellDrawer.svelte b/packages/builder/src/components/design/settings/controls/ColumnEditor/CellDrawer.svelte index a03d22386d..8e3079101a 100644 --- a/packages/builder/src/components/design/settings/controls/ColumnEditor/CellDrawer.svelte +++ b/packages/builder/src/components/design/settings/controls/ColumnEditor/CellDrawer.svelte @@ -42,7 +42,6 @@ (column.background = e.detail)} - alignRight spectrumTheme={$store.theme} /> @@ -51,7 +50,6 @@ (column.color = e.detail)} - alignRight spectrumTheme={$store.theme} /> diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte index 8bc0dcc3e5..72d959c18b 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte @@ -38,12 +38,6 @@ active={$isActive("./components")} on:click={() => $goto("./components")} /> - $goto("./theme")} - /> + + + + + {#if $selectedScreen.layoutId} + + This screen uses a custom layout, which is deprecated + + {/if} + + {#each screenSettings as setting (setting.key)} + setScreenSetting(setting, val)} + props={{ ...setting.props, error: errors[setting.key] }} + {bindings} + /> + {/each} + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/ThemePane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/ThemePane.svelte new file mode 100644 index 0000000000..2e59ad5f7d --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/ThemePane.svelte @@ -0,0 +1,98 @@ + + + +
+
+ + CHANGES WILL APPLY TO ALL SCREENS +
+ + Your navigation is configured for all the screens within your app. + +
+ + + + + + + update("buttonBorderRadius", e.detail)} + /> + + update("primaryColor", val)} + props={{ + spectrumTheme: $store.theme, + }} + /> + update("primaryColorHover", val)} + props={{ + spectrumTheme: $store.theme, + }} + /> + +
+ + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/index.svelte new file mode 100644 index 0000000000..554527ca4a --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/index.svelte @@ -0,0 +1,15 @@ + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/AppThemeSelect.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/theme/AppThemeSelect.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/AppThemeSelect.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/theme/AppThemeSelect.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ButtonRoundnessSelect.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/theme/ButtonRoundnessSelect.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ButtonRoundnessSelect.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/theme/ButtonRoundnessSelect.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/index.svelte index 6236721e1a..77019abebf 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/index.svelte @@ -1,7 +1,7 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeInfoPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeInfoPanel.svelte deleted file mode 100644 index c3325852c8..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeInfoPanel.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Your theme is set across all the screens within your app. - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeSettingsPanel.svelte deleted file mode 100644 index 1c86a51f67..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeSettingsPanel.svelte +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - update("buttonBorderRadius", e.detail)} - /> - - - - update("primaryColor", e.detail)} - /> - - - - update("primaryColorHover", e.detail)} - /> - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/index.svelte deleted file mode 100644 index 013257d8e1..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/index.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index c068a422b0..6f9acb3efe 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -298,12 +298,7 @@ async function performAppCreate(ctx: UserCtx) { title: name, navWidth: "Large", navBackground: "var(--spectrum-global-color-gray-100)", - links: [ - { - url: "/home", - text: "Home", - }, - ], + links: [], }, theme: "spectrum--light", customTheme: { From a2e12a693c046e9ba9c89198e8c2f85dd4c9f5a1 Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 20 Jul 2023 12:16:59 +0100 Subject: [PATCH 004/183] Corrected theme info copy --- .../screens/_components/ScreenSettingsPanel/ThemePane.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/ThemePane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/ThemePane.svelte index 2e59ad5f7d..20d5054648 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/ThemePane.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel/ThemePane.svelte @@ -38,7 +38,7 @@ CHANGES WILL APPLY TO ALL SCREENS
- Your navigation is configured for all the screens within your app. + Your theme is configured for all the screens within your app.
From 8c61359b9d940b6f4eaa6d4840d7f53c2e199066 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Thu, 3 Aug 2023 17:23:15 +0100 Subject: [PATCH 005/183] Allow user specified type casting in MySQL queries --- .vscode/launch.json | 72 ++++++++----------- packages/server/package.json | 2 +- .../server/src/api/controllers/query/index.ts | 4 +- .../tests/{filter.spec.js => filter.spec.ts} | 23 +++--- packages/server/src/integrations/mysql.ts | 11 ++- packages/server/src/threads/definitions.ts | 6 ++ packages/server/src/threads/query.ts | 31 +++++++- 7 files changed, 94 insertions(+), 55 deletions(-) rename packages/server/src/automations/tests/{filter.spec.js => filter.spec.ts} (76%) diff --git a/.vscode/launch.json b/.vscode/launch.json index 8cb49d5825..6c0089bb6b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,42 +1,32 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Budibase Server", - "type": "node", - "request": "launch", - "runtimeArgs": [ - "--nolazy", - "-r", - "ts-node/register/transpile-only" - ], - "args": [ - "${workspaceFolder}/packages/server/src/index.ts" - ], - "cwd": "${workspaceFolder}/packages/server" - }, - { - "name": "Budibase Worker", - "type": "node", - "request": "launch", - "runtimeArgs": [ - "--nolazy", - "-r", - "ts-node/register/transpile-only" - ], - "args": [ - "${workspaceFolder}/packages/worker/src/index.ts" - ], - "cwd": "${workspaceFolder}/packages/worker" - }, - ], - "compounds": [ - { - "name": "Start Budibase", - "configurations": ["Budibase Server", "Budibase Worker"] - } - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Budibase Server", + "type": "node", + "request": "launch", + "runtimeVersion": "14.20.1", + "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"], + "args": ["${workspaceFolder}/packages/server/src/index.ts"], + "cwd": "${workspaceFolder}/packages/server" + }, + { + "name": "Budibase Worker", + "type": "node", + "request": "launch", + "runtimeVersion": "14.20.1", + "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"], + "args": ["${workspaceFolder}/packages/worker/src/index.ts"], + "cwd": "${workspaceFolder}/packages/worker" + } + ], + "compounds": [ + { + "name": "Start Budibase", + "configurations": ["Budibase Server", "Budibase Worker"] + } + ] +} diff --git a/packages/server/package.json b/packages/server/package.json index e112c1f572..aedab54a81 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -100,7 +100,7 @@ "memorystream": "0.3.1", "mongodb": "5.7", "mssql": "9.1.1", - "mysql2": "2.3.3", + "mysql2": "3.5.2", "node-fetch": "2.6.7", "object-sizeof": "2.6.1", "open": "8.4.0", diff --git a/packages/server/src/api/controllers/query/index.ts b/packages/server/src/api/controllers/query/index.ts index c32e17bd92..8e13041bf4 100644 --- a/packages/server/src/api/controllers/query/index.ts +++ b/packages/server/src/api/controllers/query/index.ts @@ -120,7 +120,7 @@ export async function preview(ctx: any) { const query = ctx.request.body // preview may not have a queryId as it hasn't been saved, but if it does // this stops dynamic variables from calling the same query - const { fields, parameters, queryVerb, transformer, queryId } = query + const { fields, parameters, queryVerb, transformer, queryId, schema } = query const authConfigCtx: any = getAuthConfig(ctx) @@ -133,6 +133,7 @@ export async function preview(ctx: any) { parameters, transformer, queryId, + schema, // have to pass down to the thread runner - can't put into context now environmentVariables: envVars, ctx: { @@ -228,6 +229,7 @@ async function execute( user: ctx.user, auth: { ...authConfigCtx }, }, + schema: query.schema, } const runFn = () => Runner.run(inputs) diff --git a/packages/server/src/automations/tests/filter.spec.js b/packages/server/src/automations/tests/filter.spec.ts similarity index 76% rename from packages/server/src/automations/tests/filter.spec.js rename to packages/server/src/automations/tests/filter.spec.ts index 5fa5e0e202..c2c5d13e2d 100644 --- a/packages/server/src/automations/tests/filter.spec.js +++ b/packages/server/src/automations/tests/filter.spec.ts @@ -1,11 +1,18 @@ -const setup = require("./utilities") -const { FilterConditions } = require("../steps/filter") +import * as setup from "./utilities" +import { FilterConditions } from "../steps/filter" describe("test the filter logic", () => { - async function checkFilter(field, condition, value, pass = true) { - let res = await setup.runStep(setup.actions.FILTER.stepId, - { field, condition, value } - ) + async function checkFilter( + field: any, + condition: string, + value: any, + pass = true + ) { + let res = await setup.runStep(setup.actions.FILTER.stepId, { + field, + condition, + value, + }) expect(res.result).toEqual(pass) expect(res.success).toEqual(true) } @@ -36,9 +43,9 @@ describe("test the filter logic", () => { it("check date coercion", async () => { await checkFilter( - (new Date()).toISOString(), + new Date().toISOString(), FilterConditions.GREATER_THAN, - (new Date(-10000)).toISOString(), + new Date(-10000).toISOString(), true ) }) diff --git a/packages/server/src/integrations/mysql.ts b/packages/server/src/integrations/mysql.ts index a01f6b71f9..cb71a78013 100644 --- a/packages/server/src/integrations/mysql.ts +++ b/packages/server/src/integrations/mysql.ts @@ -148,7 +148,9 @@ class MySQLIntegration extends Sql implements DatasourcePlus { this.config = { ...config, multipleStatements: true, - typeCast: function (field: any, next: any) { + } + if (!this.config.typeCast) { + this.config.typeCast = function (field: any, next: any) { if ( field.type == "DATETIME" || field.type === "DATE" || @@ -161,7 +163,7 @@ class MySQLIntegration extends Sql implements DatasourcePlus { return field.buffer()?.[0] } return next() - }, + } } } @@ -204,7 +206,10 @@ class MySQLIntegration extends Sql implements DatasourcePlus { async internalQuery( query: SqlQuery, - opts: { connect?: boolean; disableCoercion?: boolean } = { + opts: { + connect?: boolean + disableCoercion?: boolean + } = { connect: true, disableCoercion: false, } diff --git a/packages/server/src/threads/definitions.ts b/packages/server/src/threads/definitions.ts index 21e7ce0b69..dd0891d34a 100644 --- a/packages/server/src/threads/definitions.ts +++ b/packages/server/src/threads/definitions.ts @@ -11,6 +11,12 @@ export interface QueryEvent { queryId: string environmentVariables?: Record ctx?: any + schema?: { + [key: string]: { + name: string + type: string + } + } } export interface QueryVariable { diff --git a/packages/server/src/threads/query.ts b/packages/server/src/threads/query.ts index 9901ddffa6..d3949f7e25 100644 --- a/packages/server/src/threads/query.ts +++ b/packages/server/src/threads/query.ts @@ -8,6 +8,7 @@ import { context, cache, auth } from "@budibase/backend-core" import { getGlobalIDFromUserMetadataID } from "../db/utils" import sdk from "../sdk" import { cloneDeep } from "lodash/fp" +import { SourceName } from "@budibase/types" import { isSQL } from "../integrations/utils" import { interpolateSQL } from "../integrations/queries/sql" @@ -27,6 +28,7 @@ class QueryRunner { hasRerun: boolean hasRefreshedOAuth: boolean hasDynamicVariables: boolean + schema: any constructor(input: QueryEvent, flags = { noRecursiveQuery: false }) { this.datasource = input.datasource @@ -36,6 +38,7 @@ class QueryRunner { this.pagination = input.pagination this.transformer = input.transformer this.queryId = input.queryId + this.schema = input.schema this.noRecursiveQuery = flags.noRecursiveQuery this.cachedVariables = [] // Additional context items for enrichment @@ -50,7 +53,7 @@ class QueryRunner { } async execute(): Promise { - let { datasource, fields, queryVerb, transformer } = this + let { datasource, fields, queryVerb, transformer, schema } = this let datasourceClone = cloneDeep(datasource) let fieldsClone = cloneDeep(fields) @@ -67,6 +70,32 @@ class QueryRunner { datasourceClone.config.authConfigs = updatedConfigs } + if (datasource.source === SourceName.MYSQL && schema) { + datasourceClone.config.typeCast = function (field: any, next: any) { + if (schema[field.name]?.name === field.name) { + if (["LONGLONG", "NEWDECIMAL", "DECIMAL"].includes(field.type)) { + if (schema[field.name]?.type === "number") { + const value = field.string() + return value ? Number(value) : null + } else { + return field.string() + } + } + } + if ( + field.type == "DATETIME" || + field.type === "DATE" || + field.type === "TIMESTAMP" + ) { + return field.string() + } + if (field.type === "BIT" && field.length === 1) { + return field.buffer()?.[0] + } + return next() + } + } + const integration = new Integration(datasourceClone.config) // pre-query, make sure datasource variables are added to parameters From 057761fdd902c8455e15b99316be39e0f973b358 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Thu, 3 Aug 2023 18:13:51 +0100 Subject: [PATCH 006/183] Update filters types with schemaFields --- .../controls/FilterEditor/FilterDrawer.svelte | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte index e8bbb8a354..25a03a93de 100644 --- a/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte +++ b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte @@ -17,7 +17,7 @@ import { generate } from "shortid" import { LuceneUtils, Constants } from "@budibase/frontend-core" import { getFields } from "helpers/searchFields" - import { createEventDispatcher } from "svelte" + import { createEventDispatcher, onMount } from "svelte" export let schemaFields export let filters = [] @@ -64,6 +64,15 @@ }) } + onMount(() => { + parseFilters(filters) + rawFilters.forEach(filter => { + filter.type = + schemaFields.find(field => field.name === filter.field)?.type || + filter.type + }) + }) + // Add field key prefixes and a special metadata filter object to indicate // whether to use the "match all" or "match any" behaviour const enrichFilters = (rawFilters, matchAny) => { From 20f71fadd32fb7f92e8e6ae972ccbf79707e509a Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Thu, 3 Aug 2023 18:52:55 +0100 Subject: [PATCH 007/183] Refactor --- packages/server/src/integrations/mysql.ts | 63 +++++++++++++++++------ packages/server/src/threads/query.ts | 29 ++--------- packages/types/src/sdk/datasources.ts | 6 +++ 3 files changed, 56 insertions(+), 42 deletions(-) diff --git a/packages/server/src/integrations/mysql.ts b/packages/server/src/integrations/mysql.ts index cb71a78013..b88162c59a 100644 --- a/packages/server/src/integrations/mysql.ts +++ b/packages/server/src/integrations/mysql.ts @@ -93,6 +93,21 @@ const SCHEMA: Integration = { }, } +const defaultTypeCasting = function (field: any, next: any) { + if ( + field.type == "DATETIME" || + field.type === "DATE" || + field.type === "TIMESTAMP" || + field.type === "LONGLONG" + ) { + return field.string() + } + if (field.type === "BIT" && field.length === 1) { + return field.buffer()?.[0] + } + return next() +} + export function bindingTypeCoerce(bindings: any[]) { for (let i = 0; i < bindings.length; i++) { const binding = bindings[i] @@ -147,24 +162,9 @@ class MySQLIntegration extends Sql implements DatasourcePlus { delete config.rejectUnauthorized this.config = { ...config, + typeCast: defaultTypeCasting, multipleStatements: true, } - if (!this.config.typeCast) { - this.config.typeCast = function (field: any, next: any) { - if ( - field.type == "DATETIME" || - field.type === "DATE" || - field.type === "TIMESTAMP" || - field.type === "LONGLONG" - ) { - return field.string() - } - if (field.type === "BIT" && field.length === 1) { - return field.buffer()?.[0] - } - return next() - } - } } async testConnection() { @@ -196,6 +196,37 @@ class MySQLIntegration extends Sql implements DatasourcePlus { return `concat(${parts.join(", ")})` } + defineTypeCastingFromSchema(schema: { + [key: string]: { name: string; type: string } + }): void { + if (!schema) { + return + } + this.config.typeCast = function (field: any, next: any) { + if (schema[field.name]?.name === field.name) { + if (["LONGLONG", "NEWDECIMAL", "DECIMAL"].includes(field.type)) { + if (schema[field.name]?.type === "number") { + const value = field.string() + return value ? Number(value) : null + } else { + return field.string() + } + } + } + if ( + field.type == "DATETIME" || + field.type === "DATE" || + field.type === "TIMESTAMP" + ) { + return field.string() + } + if (field.type === "BIT" && field.length === 1) { + return field.buffer()?.[0] + } + return next() + } + } + async connect() { this.client = await mysql.createConnection(this.config) } diff --git a/packages/server/src/threads/query.ts b/packages/server/src/threads/query.ts index d3949f7e25..37720c66ba 100644 --- a/packages/server/src/threads/query.ts +++ b/packages/server/src/threads/query.ts @@ -70,34 +70,11 @@ class QueryRunner { datasourceClone.config.authConfigs = updatedConfigs } - if (datasource.source === SourceName.MYSQL && schema) { - datasourceClone.config.typeCast = function (field: any, next: any) { - if (schema[field.name]?.name === field.name) { - if (["LONGLONG", "NEWDECIMAL", "DECIMAL"].includes(field.type)) { - if (schema[field.name]?.type === "number") { - const value = field.string() - return value ? Number(value) : null - } else { - return field.string() - } - } - } - if ( - field.type == "DATETIME" || - field.type === "DATE" || - field.type === "TIMESTAMP" - ) { - return field.string() - } - if (field.type === "BIT" && field.length === 1) { - return field.buffer()?.[0] - } - return next() - } - } - const integration = new Integration(datasourceClone.config) + // define the type casting from the schema + integration.defineTypeCastingFromSchema?.(schema) + // pre-query, make sure datasource variables are added to parameters const parameters = await this.addDatasourceVariables() diff --git a/packages/types/src/sdk/datasources.ts b/packages/types/src/sdk/datasources.ts index 2391f6e878..d6a0d4a7c8 100644 --- a/packages/types/src/sdk/datasources.ts +++ b/packages/types/src/sdk/datasources.ts @@ -166,6 +166,12 @@ export interface IntegrationBase { delete?(query: any): Promise testConnection?(): Promise getExternalSchema?(): Promise + defineTypeCastingFromSchema?(schema: { + [key: string]: { + name: string + type: string + } + }): void } export interface DatasourcePlus extends IntegrationBase { From a2667c6d72fdd6b2a6774d6cafc77926ea394a68 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 4 Aug 2023 15:43:02 +0100 Subject: [PATCH 008/183] Removing the ability to set roles, builder and admin structure through basic public API. --- .../api/controllers/public/applications.ts | 18 ++++---- .../src/api/controllers/public/queries.ts | 6 ++- .../server/src/api/controllers/public/rows.ts | 13 +++--- .../src/api/controllers/public/tables.ts | 13 +++--- .../src/api/controllers/public/users.ts | 44 ++++++++++++------- packages/server/src/utilities/users.ts | 17 ++----- 6 files changed, 60 insertions(+), 51 deletions(-) diff --git a/packages/server/src/api/controllers/public/applications.ts b/packages/server/src/api/controllers/public/applications.ts index c4041bedcf..fd72db95d3 100644 --- a/packages/server/src/api/controllers/public/applications.ts +++ b/packages/server/src/api/controllers/public/applications.ts @@ -3,6 +3,8 @@ import { search as stringSearch, addRev } from "./utils" import * as controller from "../application" import * as deployController from "../deploy" import { Application } from "../../../definitions/common" +import { UserCtx } from "@budibase/types" +import { Next } from "koa" function fixAppID(app: Application, params: any) { if (!params) { @@ -14,7 +16,7 @@ function fixAppID(app: Application, params: any) { return app } -async function setResponseApp(ctx: any) { +async function setResponseApp(ctx: UserCtx) { const appId = ctx.body?.appId if (appId && (!ctx.params || !ctx.params.appId)) { ctx.params = { appId } @@ -28,14 +30,14 @@ async function setResponseApp(ctx: any) { } } -export async function search(ctx: any, next: any) { +export async function search(ctx: UserCtx, next: Next) { const { name } = ctx.request.body const apps = await dbCore.getAllApps({ all: true }) ctx.body = stringSearch(apps, name) await next() } -export async function create(ctx: any, next: any) { +export async function create(ctx: UserCtx, next: Next) { if (!ctx.request.body || !ctx.request.body.useTemplate) { ctx.request.body = { useTemplate: false, @@ -47,14 +49,14 @@ export async function create(ctx: any, next: any) { await next() } -export async function read(ctx: any, next: any) { +export async function read(ctx: UserCtx, next: Next) { await context.doInAppContext(ctx.params.appId, async () => { await setResponseApp(ctx) await next() }) } -export async function update(ctx: any, next: any) { +export async function update(ctx: UserCtx, next: Next) { ctx.request.body = await addRev(fixAppID(ctx.request.body, ctx.params)) await context.doInAppContext(ctx.params.appId, async () => { await controller.update(ctx) @@ -63,7 +65,7 @@ export async function update(ctx: any, next: any) { }) } -export async function destroy(ctx: any, next: any) { +export async function destroy(ctx: UserCtx, next: Next) { await context.doInAppContext(ctx.params.appId, async () => { // get the app before deleting it await setResponseApp(ctx) @@ -75,14 +77,14 @@ export async function destroy(ctx: any, next: any) { }) } -export async function unpublish(ctx: any, next: any) { +export async function unpublish(ctx: UserCtx, next: Next) { await context.doInAppContext(ctx.params.appId, async () => { await controller.unpublish(ctx) await next() }) } -export async function publish(ctx: any, next: any) { +export async function publish(ctx: UserCtx, next: Next) { await context.doInAppContext(ctx.params.appId, async () => { await deployController.publishApp(ctx) await next() diff --git a/packages/server/src/api/controllers/public/queries.ts b/packages/server/src/api/controllers/public/queries.ts index 57ec608379..3cb1ab3812 100644 --- a/packages/server/src/api/controllers/public/queries.ts +++ b/packages/server/src/api/controllers/public/queries.ts @@ -1,14 +1,16 @@ import { search as stringSearch } from "./utils" import * as queryController from "../query" +import { UserCtx } from "@budibase/types" +import { Next } from "koa" -export async function search(ctx: any, next: any) { +export async function search(ctx: UserCtx, next: Next) { await queryController.fetch(ctx) const { name } = ctx.request.body ctx.body = stringSearch(ctx.body, name) await next() } -export async function execute(ctx: any, next: any) { +export async function execute(ctx: UserCtx, next: Next) { // don't wrap this, already returns "data" await queryController.executeV2(ctx) await next() diff --git a/packages/server/src/api/controllers/public/rows.ts b/packages/server/src/api/controllers/public/rows.ts index 39cf85a2a3..16403b06c9 100644 --- a/packages/server/src/api/controllers/public/rows.ts +++ b/packages/server/src/api/controllers/public/rows.ts @@ -1,7 +1,8 @@ import * as rowController from "../row" import { addRev } from "./utils" -import { Row } from "@budibase/types" +import { Row, UserCtx } from "@budibase/types" import { convertBookmark } from "../../../utilities" +import { Next } from "koa" // makes sure that the user doesn't need to pass in the type, tableId or _id params for // the call to be correct @@ -21,7 +22,7 @@ export function fixRow(row: Row, params: any) { return row } -export async function search(ctx: any, next: any) { +export async function search(ctx: UserCtx, next: Next) { let { sort, paginate, bookmark, limit, query } = ctx.request.body // update the body to the correct format of the internal search if (!sort) { @@ -40,25 +41,25 @@ export async function search(ctx: any, next: any) { await next() } -export async function create(ctx: any, next: any) { +export async function create(ctx: UserCtx, next: Next) { ctx.request.body = fixRow(ctx.request.body, ctx.params) await rowController.save(ctx) await next() } -export async function read(ctx: any, next: any) { +export async function read(ctx: UserCtx, next: Next) { await rowController.fetchEnrichedRow(ctx) await next() } -export async function update(ctx: any, next: any) { +export async function update(ctx: UserCtx, next: Next) { const { tableId } = ctx.params ctx.request.body = await addRev(fixRow(ctx.request.body, ctx.params), tableId) await rowController.save(ctx) await next() } -export async function destroy(ctx: any, next: any) { +export async function destroy(ctx: UserCtx, next: Next) { const { tableId } = ctx.params // set the body as expected, with the _id and _rev fields ctx.request.body = await addRev( diff --git a/packages/server/src/api/controllers/public/tables.ts b/packages/server/src/api/controllers/public/tables.ts index a346a750da..7486172fa3 100644 --- a/packages/server/src/api/controllers/public/tables.ts +++ b/packages/server/src/api/controllers/public/tables.ts @@ -1,6 +1,7 @@ import { search as stringSearch, addRev } from "./utils" import * as controller from "../table" -import { Table } from "@budibase/types" +import { Table, UserCtx } from "@budibase/types" +import { Next } from "koa" function fixTable(table: Table, params: any) { if (!params || !table) { @@ -15,24 +16,24 @@ function fixTable(table: Table, params: any) { return table } -export async function search(ctx: any, next: any) { +export async function search(ctx: UserCtx, next: Next) { const { name } = ctx.request.body await controller.fetch(ctx) ctx.body = stringSearch(ctx.body, name) await next() } -export async function create(ctx: any, next: any) { +export async function create(ctx: UserCtx, next: Next) { await controller.save(ctx) await next() } -export async function read(ctx: any, next: any) { +export async function read(ctx: UserCtx, next: Next) { await controller.find(ctx) await next() } -export async function update(ctx: any, next: any) { +export async function update(ctx: UserCtx, next: Next) { ctx.request.body = await addRev( fixTable(ctx.request.body, ctx.params), ctx.params.tableId @@ -41,7 +42,7 @@ export async function update(ctx: any, next: any) { await next() } -export async function destroy(ctx: any, next: any) { +export async function destroy(ctx: UserCtx, next: Next) { await controller.destroy(ctx) ctx.body = ctx.table await next() diff --git a/packages/server/src/api/controllers/public/users.ts b/packages/server/src/api/controllers/public/users.ts index 7192077d04..7aaf520dc4 100644 --- a/packages/server/src/api/controllers/public/users.ts +++ b/packages/server/src/api/controllers/public/users.ts @@ -7,16 +7,32 @@ import { import { publicApiUserFix } from "../../../utilities/users" import { db as dbCore } from "@budibase/backend-core" import { search as stringSearch } from "./utils" -import { BBContext, User } from "@budibase/types" +import { UserCtx, User } from "@budibase/types" +import { Next } from "koa" -function isLoggedInUser(ctx: BBContext, user: User) { +function removeRoles(ctx: UserCtx, oldUser?: User) { + const user = ctx.request.body + if (user.builder) { + user.builder = oldUser?.builder || undefined + } + if (user.admin) { + user.admin = oldUser?.admin || undefined + } + if (user.roles) { + user.roles = oldUser?.roles || {} + } + ctx.request.body = user + return ctx +} + +function isLoggedInUser(ctx: UserCtx, user: User) { const loggedInId = ctx.user?._id const globalUserId = dbCore.getGlobalIDFromUserMetadataID(loggedInId!) // check both just incase return globalUserId === user._id || loggedInId === user._id } -function getUser(ctx: BBContext, userId?: string) { +function getUser(ctx: UserCtx, userId?: string) { if (userId) { ctx.params = { userId } } else if (!ctx.params?.userId) { @@ -25,42 +41,38 @@ function getUser(ctx: BBContext, userId?: string) { return readGlobalUser(ctx) } -export async function search(ctx: BBContext, next: any) { +export async function search(ctx: UserCtx, next: Next) { const { name } = ctx.request.body const users = await allGlobalUsers(ctx) ctx.body = stringSearch(users, name, "email") await next() } -export async function create(ctx: BBContext, next: any) { - const response = await saveGlobalUser(publicApiUserFix(ctx)) +export async function create(ctx: UserCtx, next: Next) { + ctx = publicApiUserFix(removeRoles(ctx)) + const response = await saveGlobalUser(ctx) ctx.body = await getUser(ctx, response._id) await next() } -export async function read(ctx: BBContext, next: any) { +export async function read(ctx: UserCtx, next: Next) { ctx.body = await readGlobalUser(ctx) await next() } -export async function update(ctx: BBContext, next: any) { +export async function update(ctx: UserCtx, next: Next) { const user = await readGlobalUser(ctx) ctx.request.body = { ...ctx.request.body, _rev: user._rev, } - // disallow updating your own role - always overwrite with DB roles - if (isLoggedInUser(ctx, user)) { - ctx.request.body.builder = user.builder - ctx.request.body.admin = user.admin - ctx.request.body.roles = user.roles - } - const response = await saveGlobalUser(publicApiUserFix(ctx)) + ctx = publicApiUserFix(removeRoles(ctx, user)) + const response = await saveGlobalUser(ctx) ctx.body = await getUser(ctx, response._id) await next() } -export async function destroy(ctx: BBContext, next: any) { +export async function destroy(ctx: UserCtx, next: Next) { const user = await getUser(ctx) // disallow deleting yourself if (isLoggedInUser(ctx, user)) { diff --git a/packages/server/src/utilities/users.ts b/packages/server/src/utilities/users.ts index 1498a79719..f841ec3646 100644 --- a/packages/server/src/utilities/users.ts +++ b/packages/server/src/utilities/users.ts @@ -1,9 +1,9 @@ import { InternalTables } from "../db/utils" import { getGlobalUser } from "./global" -import { context, db as dbCore, roles } from "@budibase/backend-core" -import { BBContext } from "@budibase/types" +import { context, roles } from "@budibase/backend-core" +import { UserCtx } from "@budibase/types" -export async function getFullUser(ctx: BBContext, userId: string) { +export async function getFullUser(ctx: UserCtx, userId: string) { const global = await getGlobalUser(userId) let metadata: any = {} @@ -29,21 +29,12 @@ export async function getFullUser(ctx: BBContext, userId: string) { } } -export function publicApiUserFix(ctx: BBContext) { +export function publicApiUserFix(ctx: UserCtx) { if (!ctx.request.body) { return ctx } if (!ctx.request.body._id && ctx.params.userId) { ctx.request.body._id = ctx.params.userId } - if (!ctx.request.body.roles) { - ctx.request.body.roles = {} - } else { - const newRoles: { [key: string]: any } = {} - for (let [appId, role] of Object.entries(ctx.request.body.roles)) { - newRoles[dbCore.getProdAppID(appId)] = role - } - ctx.request.body.roles = newRoles - } return ctx } From ec761c238712d4ac04cebbc0763caad596a74ad9 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 4 Aug 2023 18:01:45 +0100 Subject: [PATCH 009/183] Building out public API for role assignment and un-assignment - need to flesh out pro component. --- packages/server/specs/openapi.json | 275 ++++++++++++------ packages/server/specs/openapi.yaml | 195 ++++++++----- packages/server/specs/resources/index.ts | 2 + packages/server/specs/resources/roles.ts | 65 +++++ packages/server/specs/resources/user.ts | 32 -- .../src/api/controllers/public/roles.ts | 15 + .../server/src/api/routes/public/roles.ts | 54 ++++ packages/server/src/definitions/openapi.ts | 133 ++++++--- 8 files changed, 545 insertions(+), 226 deletions(-) create mode 100644 packages/server/specs/resources/roles.ts create mode 100644 packages/server/src/api/controllers/public/roles.ts create mode 100644 packages/server/src/api/routes/public/roles.ts diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index d97b09568c..1071a39c29 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -1519,34 +1519,6 @@ "forceResetPassword": { "description": "If set to true forces the user to reset their password on first login.", "type": "boolean" - }, - "builder": { - "description": "Describes if the user is a builder user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to build any app in the system.", - "type": "boolean" - } - } - }, - "admin": { - "description": "Describes if the user is an admin user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to administrate the system.", - "type": "boolean" - } - } - }, - "roles": { - "description": "Contains the roles of the user per app (assuming they are not a builder user).", - "type": "object", - "additionalProperties": { - "type": "string", - "description": "A map of app ID (production app ID, minus the _dev component) to a role ID, e.g. ADMIN." - } } }, "required": [ @@ -1587,34 +1559,6 @@ "description": "If set to true forces the user to reset their password on first login.", "type": "boolean" }, - "builder": { - "description": "Describes if the user is a builder user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to build any app in the system.", - "type": "boolean" - } - } - }, - "admin": { - "description": "Describes if the user is an admin user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to administrate the system.", - "type": "boolean" - } - } - }, - "roles": { - "description": "Contains the roles of the user per app (assuming they are not a builder user).", - "type": "object", - "additionalProperties": { - "type": "string", - "description": "A map of app ID (production app ID, minus the _dev component) to a role ID, e.g. ADMIN." - } - }, "_id": { "description": "The ID of the user.", "type": "string" @@ -1666,34 +1610,6 @@ "description": "If set to true forces the user to reset their password on first login.", "type": "boolean" }, - "builder": { - "description": "Describes if the user is a builder user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to build any app in the system.", - "type": "boolean" - } - } - }, - "admin": { - "description": "Describes if the user is an admin user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to administrate the system.", - "type": "boolean" - } - } - }, - "roles": { - "description": "Contains the roles of the user per app (assuming they are not a builder user).", - "type": "object", - "additionalProperties": { - "type": "string", - "description": "A map of app ID (production app ID, minus the _dev component) to a role ID, e.g. ADMIN." - } - }, "_id": { "description": "The ID of the user.", "type": "string" @@ -1833,6 +1749,135 @@ "required": [ "name" ] + }, + "rolesAssign": { + "type": "object", + "properties": { + "builder": { + "type": "object", + "properties": { + "global": { + "type": "boolean" + } + }, + "description": "Add/remove global builder permissions from the list of users.", + "required": [ + "global" + ] + }, + "admin": { + "type": "object", + "properties": { + "global": { + "type": "boolean" + } + }, + "description": "Add/remove global admin permissions from the list of users.", + "required": [ + "global" + ] + }, + "role": { + "type": "object", + "properties": { + "roleId": { + "description": "The role ID, such as BASIC, ADMIN or a custom role ID.", + "type": "string" + }, + "appId": { + "description": "The app that the role relates to.", + "type": "string" + } + }, + "description": "Add/remove a per-app role, such as BASIC, ADMIN etc.", + "required": [ + "roleId", + "appId" + ] + }, + "userIds": { + "description": "The user IDs to be updated to add/remove the specified roles.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "userIds" + ] + }, + "rolesUnAssign": { + "type": "object", + "properties": { + "builder": { + "type": "object", + "properties": { + "global": { + "type": "boolean" + } + }, + "description": "Add/remove global builder permissions from the list of users.", + "required": [ + "global" + ] + }, + "admin": { + "type": "object", + "properties": { + "global": { + "type": "boolean" + } + }, + "description": "Add/remove global admin permissions from the list of users.", + "required": [ + "global" + ] + }, + "role": { + "type": "object", + "properties": { + "roleId": { + "description": "The role ID, such as BASIC, ADMIN or a custom role ID.", + "type": "string" + }, + "appId": { + "description": "The app that the role relates to.", + "type": "string" + } + }, + "description": "Add/remove a per-app role, such as BASIC, ADMIN etc.", + "required": [ + "roleId", + "appId" + ] + }, + "userIds": { + "description": "The user IDs to be updated to add/remove the specified roles.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "userIds" + ] + }, + "rolesOutput": { + "type": "object", + "properties": { + "userIds": { + "description": "The updated users' IDs", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "userIds" + ] } } }, @@ -2186,6 +2231,68 @@ } } }, + "/roles/assign": { + "post": { + "operationId": "roleAssign", + "summary": "Assign a role to a list of users", + "tags": [ + "roles" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesAssign" + } + } + } + }, + "responses": { + "200": { + "description": "Returns a list of updated user IDs", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesOutput" + } + } + } + } + } + } + }, + "/roles/unassign": { + "post": { + "operationId": "roleUnAssign", + "summary": "Un-assign a role from a list of users", + "tags": [ + "roles" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesUnAssign" + } + } + } + }, + "responses": { + "200": { + "description": "Returns a list of updated user IDs", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesOutput" + } + } + } + } + } + } + }, "/tables/{tableId}/rows": { "post": { "operationId": "rowCreate", diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index 86807c9981..aa7b3ddb51 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -1296,29 +1296,6 @@ components: description: If set to true forces the user to reset their password on first login. type: boolean - builder: - description: Describes if the user is a builder user or not. - type: object - properties: - global: - description: If set to true the user will be able to build any app in the - system. - type: boolean - admin: - description: Describes if the user is an admin user or not. - type: object - properties: - global: - description: If set to true the user will be able to administrate the system. - type: boolean - roles: - description: Contains the roles of the user per app (assuming they are not a - builder user). - type: object - additionalProperties: - type: string - description: A map of app ID (production app ID, minus the _dev component) to a - role ID, e.g. ADMIN. required: - email - roles @@ -1351,29 +1328,6 @@ components: description: If set to true forces the user to reset their password on first login. type: boolean - builder: - description: Describes if the user is a builder user or not. - type: object - properties: - global: - description: If set to true the user will be able to build any app in the - system. - type: boolean - admin: - description: Describes if the user is an admin user or not. - type: object - properties: - global: - description: If set to true the user will be able to administrate the system. - type: boolean - roles: - description: Contains the roles of the user per app (assuming they are not a - builder user). - type: object - additionalProperties: - type: string - description: A map of app ID (production app ID, minus the _dev component) to a - role ID, e.g. ADMIN. _id: description: The ID of the user. type: string @@ -1414,29 +1368,6 @@ components: description: If set to true forces the user to reset their password on first login. type: boolean - builder: - description: Describes if the user is a builder user or not. - type: object - properties: - global: - description: If set to true the user will be able to build any app in the - system. - type: boolean - admin: - description: Describes if the user is an admin user or not. - type: object - properties: - global: - description: If set to true the user will be able to administrate the system. - type: boolean - roles: - description: Contains the roles of the user per app (assuming they are not a - builder user). - type: object - additionalProperties: - type: string - description: A map of app ID (production app ID, minus the _dev component) to a - role ID, e.g. ADMIN. _id: description: The ID of the user. type: string @@ -1547,6 +1478,94 @@ components: insensitive starts with match. required: - name + rolesAssign: + type: object + properties: + builder: + type: object + properties: + global: + type: boolean + description: Add/remove global builder permissions from the list of users. + required: + - global + admin: + type: object + properties: + global: + type: boolean + description: Add/remove global admin permissions from the list of users. + required: + - global + role: + type: object + properties: + roleId: + description: The role ID, such as BASIC, ADMIN or a custom role ID. + type: string + appId: + description: The app that the role relates to. + type: string + description: Add/remove a per-app role, such as BASIC, ADMIN etc. + required: + - roleId + - appId + userIds: + description: The user IDs to be updated to add/remove the specified roles. + type: array + items: + type: string + required: + - userIds + rolesUnAssign: + type: object + properties: + builder: + type: object + properties: + global: + type: boolean + description: Add/remove global builder permissions from the list of users. + required: + - global + admin: + type: object + properties: + global: + type: boolean + description: Add/remove global admin permissions from the list of users. + required: + - global + role: + type: object + properties: + roleId: + description: The role ID, such as BASIC, ADMIN or a custom role ID. + type: string + appId: + description: The app that the role relates to. + type: string + description: Add/remove a per-app role, such as BASIC, ADMIN etc. + required: + - roleId + - appId + userIds: + description: The user IDs to be updated to add/remove the specified roles. + type: array + items: + type: string + required: + - userIds + rolesOutput: + type: object + properties: + userIds: + description: The updated users' IDs + type: array + items: + type: string + required: + - userIds security: - ApiKeyAuth: [] paths: @@ -1757,6 +1776,44 @@ paths: examples: queries: $ref: "#/components/examples/queries" + /roles/assign: + post: + operationId: roleAssign + summary: Assign a role to a list of users + tags: + - roles + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/rolesAssign" + responses: + "200": + description: Returns a list of updated user IDs + content: + application/json: + schema: + $ref: "#/components/schemas/rolesOutput" + /roles/unassign: + post: + operationId: roleUnAssign + summary: Un-assign a role from a list of users + tags: + - roles + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/rolesUnAssign" + responses: + "200": + description: Returns a list of updated user IDs + content: + application/json: + schema: + $ref: "#/components/schemas/rolesOutput" "/tables/{tableId}/rows": post: operationId: rowCreate diff --git a/packages/server/specs/resources/index.ts b/packages/server/specs/resources/index.ts index 6b8a1aa437..c06148b7de 100644 --- a/packages/server/specs/resources/index.ts +++ b/packages/server/specs/resources/index.ts @@ -5,6 +5,7 @@ import query from "./query" import user from "./user" import metrics from "./metrics" import misc from "./misc" +import roles from "./roles" export const examples = { ...application.getExamples(), @@ -23,4 +24,5 @@ export const schemas = { ...query.getSchemas(), ...user.getSchemas(), ...misc.getSchemas(), + ...roles.getSchemas(), } diff --git a/packages/server/specs/resources/roles.ts b/packages/server/specs/resources/roles.ts new file mode 100644 index 0000000000..02254261be --- /dev/null +++ b/packages/server/specs/resources/roles.ts @@ -0,0 +1,65 @@ +import { object } from "./utils" +import Resource from "./utils/Resource" + +const roleSchema = object( + { + builder: object( + { + global: { + type: "boolean", + }, + }, + { + description: + "Add/remove global builder permissions from the list of users.", + } + ), + admin: object( + { + global: { + type: "boolean", + }, + }, + { + description: + "Add/remove global admin permissions from the list of users.", + } + ), + role: object( + { + roleId: { + description: "The role ID, such as BASIC, ADMIN or a custom role ID.", + type: "string", + }, + appId: { + description: "The app that the role relates to.", + type: "string", + }, + }, + { description: "Add/remove a per-app role, such as BASIC, ADMIN etc." } + ), + userIds: { + description: + "The user IDs to be updated to add/remove the specified roles.", + type: "array", + items: { + type: "string", + }, + }, + }, + { required: ["userIds"] } +) + +export default new Resource().setSchemas({ + rolesAssign: roleSchema, + rolesUnAssign: roleSchema, + rolesOutput: object({ + userIds: { + description: "The updated users' IDs", + type: "array", + items: { + type: "string", + }, + }, + }), +}) diff --git a/packages/server/specs/resources/user.ts b/packages/server/specs/resources/user.ts index a7b9f1ddb9..9ec5388672 100644 --- a/packages/server/specs/resources/user.ts +++ b/packages/server/specs/resources/user.ts @@ -57,38 +57,6 @@ const userSchema = object( "If set to true forces the user to reset their password on first login.", type: "boolean", }, - builder: { - description: "Describes if the user is a builder user or not.", - type: "object", - properties: { - global: { - description: - "If set to true the user will be able to build any app in the system.", - type: "boolean", - }, - }, - }, - admin: { - description: "Describes if the user is an admin user or not.", - type: "object", - properties: { - global: { - description: - "If set to true the user will be able to administrate the system.", - type: "boolean", - }, - }, - }, - roles: { - description: - "Contains the roles of the user per app (assuming they are not a builder user).", - type: "object", - additionalProperties: { - type: "string", - description: - "A map of app ID (production app ID, minus the _dev component) to a role ID, e.g. ADMIN.", - }, - }, }, { required: ["email", "roles"] } ) diff --git a/packages/server/src/api/controllers/public/roles.ts b/packages/server/src/api/controllers/public/roles.ts new file mode 100644 index 0000000000..3b70094ae1 --- /dev/null +++ b/packages/server/src/api/controllers/public/roles.ts @@ -0,0 +1,15 @@ +import { UserCtx } from "@budibase/types" +import { Next } from "koa" + +async function assign(ctx: UserCtx, next: Next) { + ctx.body = { message: "roles assigned" } +} + +async function unAssign(ctx: UserCtx, next: Next) { + ctx.body = { message: "roles un-assigned" } +} + +export default { + assign, + unAssign, +} diff --git a/packages/server/src/api/routes/public/roles.ts b/packages/server/src/api/routes/public/roles.ts new file mode 100644 index 0000000000..2332a0ffd0 --- /dev/null +++ b/packages/server/src/api/routes/public/roles.ts @@ -0,0 +1,54 @@ +import controller from "../../controllers/public/roles" +import Endpoint from "./utils/Endpoint" + +const write = [] + +/** + * @openapi + * /roles/assign: + * post: + * operationId: roleAssign + * summary: Assign a role to a list of users + * tags: + * - roles + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/rolesAssign' + * responses: + * 200: + * description: Returns a list of updated user IDs + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/rolesOutput' + */ +write.push(new Endpoint("post", "/roles/assign", controller.assign)) + +/** + * @openapi + * /roles/unassign: + * post: + * operationId: roleUnAssign + * summary: Un-assign a role from a list of users + * tags: + * - roles + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/rolesUnAssign' + * responses: + * 200: + * description: Returns a list of updated user IDs + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/rolesOutput' + */ +write.push(new Endpoint("post", "/roles/unassign", controller.unAssign)) + +export default { write, read: [] } diff --git a/packages/server/src/definitions/openapi.ts b/packages/server/src/definitions/openapi.ts index 5ca4990647..ee078d0821 100644 --- a/packages/server/src/definitions/openapi.ts +++ b/packages/server/src/definitions/openapi.ts @@ -34,6 +34,12 @@ export interface paths { /** Based on query properties (currently only name) search for queries. */ post: operations["querySearch"]; }; + "/roles/assign": { + post: operations["roleAssign"]; + }; + "/roles/unassign": { + post: operations["roleUnAssign"]; + }; "/tables/{tableId}/rows": { /** Creates a row within the specified table. */ post: operations["rowCreate"]; @@ -256,7 +262,8 @@ export interface components { | "auto" | "json" | "internal" - | "barcodeqr"; + | "barcodeqr" + | "bigint"; /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ constraints?: { /** @enum {string} */ @@ -362,7 +369,8 @@ export interface components { | "auto" | "json" | "internal" - | "barcodeqr"; + | "barcodeqr" + | "bigint"; /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ constraints?: { /** @enum {string} */ @@ -470,7 +478,8 @@ export interface components { | "auto" | "json" | "internal" - | "barcodeqr"; + | "barcodeqr" + | "bigint"; /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ constraints?: { /** @enum {string} */ @@ -577,18 +586,8 @@ export interface components { lastName?: string; /** @description If set to true forces the user to reset their password on first login. */ forceResetPassword?: boolean; - /** @description Describes if the user is a builder user or not. */ - builder?: { - /** @description If set to true the user will be able to build any app in the system. */ - global?: boolean; - }; - /** @description Describes if the user is an admin user or not. */ - admin?: { - /** @description If set to true the user will be able to administrate the system. */ - global?: boolean; - }; - /** @description Contains the roles of the user per app (assuming they are not a builder user). */ - roles: { [key: string]: string }; + } & { + roles: unknown; }; userOutput: { data: { @@ -607,24 +606,14 @@ export interface components { lastName?: string; /** @description If set to true forces the user to reset their password on first login. */ forceResetPassword?: boolean; - /** @description Describes if the user is a builder user or not. */ - builder?: { - /** @description If set to true the user will be able to build any app in the system. */ - global?: boolean; - }; - /** @description Describes if the user is an admin user or not. */ - admin?: { - /** @description If set to true the user will be able to administrate the system. */ - global?: boolean; - }; - /** @description Contains the roles of the user per app (assuming they are not a builder user). */ - roles: { [key: string]: string }; /** @description The ID of the user. */ _id: string; + } & { + roles: unknown; }; }; userSearch: { - data: { + data: ({ /** @description The email address of the user, this must be unique. */ email: string; /** @description The password of the user if using password based login - this will never be returned. This can be left out of subsequent requests (updates) and will be enriched back into the user structure. */ @@ -640,21 +629,11 @@ export interface components { lastName?: string; /** @description If set to true forces the user to reset their password on first login. */ forceResetPassword?: boolean; - /** @description Describes if the user is a builder user or not. */ - builder?: { - /** @description If set to true the user will be able to build any app in the system. */ - global?: boolean; - }; - /** @description Describes if the user is an admin user or not. */ - admin?: { - /** @description If set to true the user will be able to administrate the system. */ - global?: boolean; - }; - /** @description Contains the roles of the user per app (assuming they are not a builder user). */ - roles: { [key: string]: string }; /** @description The ID of the user. */ _id: string; - }[]; + } & { + roles: unknown; + })[]; }; rowSearch: { query: { @@ -712,6 +691,48 @@ export interface components { /** @description The name to be used when searching - this will be used in a case insensitive starts with match. */ name: string; }; + rolesAssign: { + /** @description Add/remove global builder permissions from the list of users. */ + builder?: { + global: boolean; + }; + /** @description Add/remove global admin permissions from the list of users. */ + admin?: { + global: boolean; + }; + /** @description Add/remove a per-app role, such as BASIC, ADMIN etc. */ + role?: { + /** @description The role ID, such as BASIC, ADMIN or a custom role ID. */ + roleId: string; + /** @description The app that the role relates to. */ + appId: string; + }; + /** @description The user IDs to be updated to add/remove the specified roles. */ + userIds: string[]; + }; + rolesUnAssign: { + /** @description Add/remove global builder permissions from the list of users. */ + builder?: { + global: boolean; + }; + /** @description Add/remove global admin permissions from the list of users. */ + admin?: { + global: boolean; + }; + /** @description Add/remove a per-app role, such as BASIC, ADMIN etc. */ + role?: { + /** @description The role ID, such as BASIC, ADMIN or a custom role ID. */ + roleId: string; + /** @description The app that the role relates to. */ + appId: string; + }; + /** @description The user IDs to be updated to add/remove the specified roles. */ + userIds: string[]; + }; + rolesOutput: { + /** @description The updated users' IDs */ + userIds: string[]; + }; }; parameters: { /** @description The ID of the table which this request is targeting. */ @@ -907,6 +928,36 @@ export interface operations { }; }; }; + roleAssign: { + responses: { + /** Returns a list of updated user IDs */ + 200: { + content: { + "application/json": components["schemas"]["rolesOutput"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["rolesAssign"]; + }; + }; + }; + roleUnAssign: { + responses: { + /** Returns a list of updated user IDs */ + 200: { + content: { + "application/json": components["schemas"]["rolesOutput"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["rolesUnAssign"]; + }; + }; + }; /** Creates a row within the specified table. */ rowCreate: { parameters: { From 00e6a43e3ec2c4968af3fc531ad5aeb465b1d52a Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Tue, 8 Aug 2023 16:39:05 +0100 Subject: [PATCH 010/183] Form step and field group require form --- packages/client/manifest.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/client/manifest.json b/packages/client/manifest.json index b6a231917c..925c87e61d 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -2445,6 +2445,7 @@ "name": "Form Step", "icon": "AssetsAdded", "hasChildren": true, + "requiredAncestors": ["form"], "illegalChildren": ["section", "form", "formstep", "formblock"], "styles": ["size"], "size": { @@ -2464,6 +2465,7 @@ "fieldgroup": { "name": "Field Group", "icon": "Group", + "requiredAncestors": ["form"], "illegalChildren": ["section"], "styles": ["size"], "hasChildren": true, From 22b456da5e2562c4efd2c6148e93aa3746132cb8 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Tue, 8 Aug 2023 17:13:40 +0100 Subject: [PATCH 011/183] Allow form step to be bindable --- .../ButtonActionEditor/actions/ChangeFormStep.svelte | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ChangeFormStep.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ChangeFormStep.svelte index ca2df71c6d..81a2119474 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ChangeFormStep.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ChangeFormStep.svelte @@ -1,10 +1,12 @@ - - + {/if} - {/if} + autofocus + bind:value={editableColumn.name} + disabled={uneditable || + (linkEditDisabled && editableColumn.type === LINK_TYPE)} + error={errors?.name} + /> + {/if} update("navWidth", e.detail)} + /> + {/if} +
+ +
+ update("hideLogo", !e.detail)} + /> + {#if !$store.navigation.hideLogo} +
+ +
+ update("logoUrl", e.detail)} + updateOnChange={false} + /> + {/if} +
+ +
+ update("hideTitle", !e.detail)} + /> + {#if !$store.navigation.hideTitle} +
+ +
+ update("title", e.detail)} + updateOnChange={false} + /> + {/if} +
+ +
+ update("navBackground", e.detail)} + /> +
+ +
+ update("navTextColor", e.detail)} + /> +
+ + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte new file mode 100644 index 0000000000..d3ce720994 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte @@ -0,0 +1,31 @@ + + + +
+ + Show nav on this screen +
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte new file mode 100644 index 0000000000..6ce5405f93 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte @@ -0,0 +1,10 @@ + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte index fc2e03d8e8..2331d8b285 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte @@ -1,6 +1,6 @@ From 6886a312c5dbfa07905ca3124d0a23d610dcfe10 Mon Sep 17 00:00:00 2001 From: Gerard Burns Date: Mon, 14 Aug 2023 13:31:12 +0100 Subject: [PATCH 074/183] New Left Panel for Design --- packages/builder/src/builderStore/index.js | 6 + .../src/builderStore/store/frontend.js | 6 +- .../NewScreen}/CreateScreenModal.svelte | 0 .../design/NewScreen}/DatasourceModal.svelte | 0 .../design/NewScreen}/ScreenRoleModal.svelte | 0 .../design/NewScreen}/blank.png | Bin .../components/design/NewScreen/index.svelte | 105 +++++++ .../design/NewScreen}/table.png | Bin .../design/[screenId]/_fallback.svelte | 5 - .../design/[screenId]/_layout.svelte | 86 +----- .../_components/AppPanel.svelte | 46 +--- .../_components/AppPreview.svelte | 55 +--- .../ComponentInfoSection.svelte | 0 .../ComponentSettingsPanel.svelte | 0 .../ComponentSettingsSection.svelte | 0 .../ConditionalUIDrawer.svelte | 0 .../ConditionalUISection.svelte | 0 .../CustomStylesSection.svelte | 0 .../DesignSection.svelte | 0 .../StyleSection.svelte | 0 .../componentStyles.js | 0 .../_components/DevicePreviewSelect.svelte | 0 .../Components}/ComponentDropdownMenu.svelte | 0 .../Components}/ComponentKeyHandler.svelte | 17 +- .../Components}/ComponentScrollWrapper.svelte | 19 +- .../Components}/ComponentTree.svelte | 0 .../Components}/DNDPositionIndicator.svelte | 0 .../Components}/ScreenslotDropdownMenu.svelte | 0 .../Components}/dndStore.js | 0 .../LeftPanel/Components/index.svelte | 156 +++++++++++ .../LeftPanel/Screens/DropdownMenu.svelte} | 0 .../LeftPanel/Screens}/RoleIndicator.svelte | 8 +- .../LeftPanel/Screens/index.svelte | 233 ++++++++++++++++ .../_components/LeftPanel/index.svelte | 24 ++ .../_components/Navigation/index.svelte | 260 ++++++++++++++++++ .../_components/Screen/SettingsPanel.svelte} | 0 .../navigation/ComponentListPanel.svelte | 90 ------ .../components/[componentId]/_layout.svelte | 56 +++- .../design/[screenId]/components/index.svelte | 12 +- .../design/[screenId]/index.svelte | 5 +- .../_components/LayoutDropdownMenu.svelte | 41 --- .../_components/LayoutListPanel.svelte | 29 -- .../_components/LayoutSettingsPanel.svelte | 53 ---- .../layouts/[layoutId]/_layout.svelte | 20 -- .../layouts/[layoutId]/index.svelte | 7 - .../design/[screenId]/layouts/_layout.svelte | 12 - .../design/[screenId]/layouts/index.svelte | 12 - .../NavigationInfoPanel/CustomizePane.svelte | 176 ------------ .../NavigationInfoPanel/SettingsPane.svelte | 31 --- .../NavigationInfoPanel/index.svelte | 10 - .../_components/NavigationLinksDrawer.svelte | 130 --------- .../_components/NavigationLinksEditor.svelte | 34 --- .../NavigationSettingsPanel.svelte | 110 -------- .../design/[screenId]/navigation/index.svelte | 7 - .../_components/ScreenListPanel.svelte | 75 ----- .../design/[screenId]/screens/index.svelte | 12 - .../theme/_components/AppThemeSelect.svelte | 64 ----- .../_components/ButtonRoundnessSelect.svelte | 38 --- .../theme/_components/ThemeInfoPanel.svelte | 12 - .../_components/ThemeSettingsPanel.svelte | 55 ---- .../design/[screenId]/theme/index.svelte | 7 - .../app/[application]/design/index.svelte | 2 +- .../app/[application]/design/new.svelte | 103 +------ .../client/src/components/Component.svelte | 10 +- packages/client/src/components/Screen.svelte | 2 +- .../client/src/components/app/Layout.svelte | 11 +- .../src/components/preview/SettingsBar.svelte | 6 +- 67 files changed, 916 insertions(+), 1342 deletions(-) rename packages/builder/src/{pages/builder/app/[application]/design/_components => components/design/NewScreen}/CreateScreenModal.svelte (100%) rename packages/builder/src/{pages/builder/app/[application]/design/_components => components/design/NewScreen}/DatasourceModal.svelte (100%) rename packages/builder/src/{pages/builder/app/[application]/design/_components => components/design/NewScreen}/ScreenRoleModal.svelte (100%) rename packages/builder/src/{pages/builder/app/[application]/design => components/design/NewScreen}/blank.png (100%) create mode 100644 packages/builder/src/components/design/NewScreen/index.svelte rename packages/builder/src/{pages/builder/app/[application]/design => components/design/NewScreen}/table.png (100%) delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/_fallback.svelte rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{ => components/[componentId]}/_components/AppPanel.svelte (52%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{ => components/[componentId]}/_components/AppPreview.svelte (86%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{settings => Component}/ComponentInfoSection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{settings => Component}/ComponentSettingsPanel.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{settings => Component}/ComponentSettingsSection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{settings => Component}/ConditionalUIDrawer.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{settings => Component}/ConditionalUISection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{settings => Component}/CustomStylesSection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{settings => Component}/DesignSection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{settings => Component}/StyleSection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{settings => Component}/componentStyles.js (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{ => components/[componentId]}/_components/DevicePreviewSelect.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{navigation => LeftPanel/Components}/ComponentDropdownMenu.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{navigation => LeftPanel/Components}/ComponentKeyHandler.svelte (91%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{navigation => LeftPanel/Components}/ComponentScrollWrapper.svelte (84%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{navigation => LeftPanel/Components}/ComponentTree.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{navigation => LeftPanel/Components}/DNDPositionIndicator.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{navigation => LeftPanel/Components}/ScreenslotDropdownMenu.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/{navigation => LeftPanel/Components}/dndStore.js (100%) create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Components/index.svelte rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{screens/_components/ScreenDropdownMenu.svelte => components/[componentId]/_components/LeftPanel/Screens/DropdownMenu.svelte} (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{screens/_components => components/[componentId]/_components/LeftPanel/Screens}/RoleIndicator.svelte (87%) create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/index.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/index.svelte rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{screens/_components/ScreenSettingsPanel.svelte => components/[componentId]/_components/Screen/SettingsPanel.svelte} (100%) delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutDropdownMenu.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_layout.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/_layout.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksEditor.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationSettingsPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/AppThemeSelect.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ButtonRoundnessSelect.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeInfoPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeSettingsPanel.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/index.svelte diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js index 2ca8057b48..3cd387fe95 100644 --- a/packages/builder/src/builderStore/index.js +++ b/packages/builder/src/builderStore/index.js @@ -61,6 +61,12 @@ export const selectedLayout = derived(store, $store => { export const selectedComponent = derived( [store, selectedScreen], ([$store, $selectedScreen]) => { + if ( + $selectedScreen && + ["navigation", "screen"].includes($store.selectedComponentId) + ) { + return findComponent($selectedScreen?.props, $selectedScreen?.props._id) + } if (!$selectedScreen || !$store.selectedComponentId) { return null } diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index f312a58e97..038fb661b9 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -769,9 +769,13 @@ export const getFrontendStore = () => { else { await store.actions.screens.patch(screen => { // Find the selected component + let selectedComponentId = state.selectedComponentId + if (["navigation", "screen"].includes(selectedComponentId)) { + selectedComponentId = screen?.props._id + } const currentComponent = findComponent( screen.props, - state.selectedComponentId + selectedComponentId ) if (!currentComponent) { return false diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/CreateScreenModal.svelte b/packages/builder/src/components/design/NewScreen/CreateScreenModal.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/_components/CreateScreenModal.svelte rename to packages/builder/src/components/design/NewScreen/CreateScreenModal.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/DatasourceModal.svelte b/packages/builder/src/components/design/NewScreen/DatasourceModal.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/_components/DatasourceModal.svelte rename to packages/builder/src/components/design/NewScreen/DatasourceModal.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/ScreenRoleModal.svelte b/packages/builder/src/components/design/NewScreen/ScreenRoleModal.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/_components/ScreenRoleModal.svelte rename to packages/builder/src/components/design/NewScreen/ScreenRoleModal.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/blank.png b/packages/builder/src/components/design/NewScreen/blank.png similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/blank.png rename to packages/builder/src/components/design/NewScreen/blank.png diff --git a/packages/builder/src/components/design/NewScreen/index.svelte b/packages/builder/src/components/design/NewScreen/index.svelte new file mode 100644 index 0000000000..b504940ca7 --- /dev/null +++ b/packages/builder/src/components/design/NewScreen/index.svelte @@ -0,0 +1,105 @@ + + +
+ +
+ Start from scratch or create screens from your data +
+ +
+
createScreenModal.show("blank")}> +
+ +
+
+ Blank screen + Add an empty blank screen +
+
+ +
createScreenModal.show("table")}> +
+ +
+
+ Table + View, edit and delete rows on a table +
+
+
+
+
+ + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/table.png b/packages/builder/src/components/design/NewScreen/table.png similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/table.png rename to packages/builder/src/components/design/NewScreen/table.png diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_fallback.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_fallback.svelte deleted file mode 100644 index 00165e4ee9..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_fallback.svelte +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte index 8bc0dcc3e5..77510951b1 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte @@ -1,11 +1,8 @@ -
-
- - $goto("./screens")} - /> - $goto("./components")} - /> - $goto("./theme")} - /> - $goto("./navigation")} - /> - {#if $store.layouts?.length} - $goto("./layouts")} - /> - {/if} - -
- -
- {#if $selectedScreen} - - - {/if} -
-
- - + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/AppPanel.svelte similarity index 52% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/AppPanel.svelte index 785b221239..379cebca37 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/AppPanel.svelte @@ -1,9 +1,7 @@ @@ -11,22 +9,11 @@
- +
+ Screens +
+
+ +
+
+ +
+
+
+ {#each filteredScreens as screen (screen._id)} + store.actions.screens.select(screen._id)} + rightAlignIcon + showTooltip + selectedBy={$userSelectedResourceMap[screen._id]} + > + + + + {/each} +
+ {#if !filteredScreens?.length} + + + There aren't any screens matching the current filters + + + {/if} +
+ +
+ (newScreen = false)} /> +
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte new file mode 100644 index 0000000000..3f521b23c7 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte @@ -0,0 +1,24 @@ + + +
+ +
+ +
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/index.svelte new file mode 100644 index 0000000000..f442e3a275 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/index.svelte @@ -0,0 +1,260 @@ + + +
+
+
+ +
+ Navigation +
+
+
+
+ General +
+
+ + Show nav on this screen +
+
+
+
+
+ Customize +
+
+
+ + These settings apply to all screens +
+
+ +
+
+ +
+ + update("navigation", "Top")} + /> + update("navigation", "Left")} + /> + + + {#if $store.navigation.navigation === "Top"} +
+ +
+ update("sticky", e.detail)} + /> +
+ +
+ update("logoUrl", e.detail)} + updateOnChange={false} + /> + {/if} +
+ +
+ update("hideTitle", !e.detail)} + /> + {#if !$store.navigation.hideTitle} +
+ +
+ update("title", e.detail)} + updateOnChange={false} + /> + {/if} +
+ +
+ update("navBackground", e.detail)} + /> +
+ +
+ update("navTextColor", e.detail)} + /> +
+
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Screen/SettingsPanel.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Screen/SettingsPanel.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte deleted file mode 100644 index 9513753d76..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte +++ /dev/null @@ -1,90 +0,0 @@ - - - -
- -
- -
    -
  • - { - $store.selectedComponentId = $selectedScreen?.props._id - }} - id={`component-${$selectedScreen?.props._id}`} - selectedBy={$userSelectedResourceMap[$selectedScreen?.props._id]} - > - - - - - - {#if $dndStore.dragging && $dndStore.valid} - - {#if $dndStore.dropPosition !== DropPosition.INSIDE} - - {/if} - {/if} -
  • -
-
-
- - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte index 860258c940..1dcf40a3c5 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte @@ -1,14 +1,19 @@ - - - +
+
+ {#if $selectedScreen} + + + {#if routeComponentId === "screen"} + + {:else if routeComponentId === "navigation"} + + {:else} + + {/if} + + {/if} +
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte index f8c4cc0868..9361415cb7 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte @@ -1,18 +1,8 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte index f5e3806bd6..496467c546 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte @@ -1,5 +1,8 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutDropdownMenu.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutDropdownMenu.svelte deleted file mode 100644 index cba68f899d..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutDropdownMenu.svelte +++ /dev/null @@ -1,41 +0,0 @@ - - - -
- -
- Delete -
- - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte deleted file mode 100644 index cc895317fd..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - -
- {#each $store.layouts as layout (layout._id)} - store.actions.layouts.select(layout._id)} - > - - - {/each} -
-
- - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte deleted file mode 100644 index bfc2f94f43..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - Custom layouts are being deprecated. They will be removed in a future - release. - - - You can save the content of this layout by pressing the button below. - - - This will copy all components inside your layout, which you can then paste - into a screen. - - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_layout.svelte deleted file mode 100644 index c82fefab3e..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_layout.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/index.svelte deleted file mode 100644 index 4d39403bc3..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/index.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/_layout.svelte deleted file mode 100644 index 1333c6afe3..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/_layout.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/index.svelte deleted file mode 100644 index 09d45f8fde..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/index.svelte +++ /dev/null @@ -1,12 +0,0 @@ - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte deleted file mode 100644 index 05108b1736..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/CustomizePane.svelte +++ /dev/null @@ -1,176 +0,0 @@ - - - -
-
- - CHANGES WILL APPLY TO ALL SCREENS -
- - Your navigation is configured for all the screens within your app. - -
- -
-
- -
- - update("navigation", "Top")} - /> - update("navigation", "Left")} - /> - - - {#if $store.navigation.navigation === "Top"} -
- -
- update("sticky", e.detail)} - /> -
- -
- update("logoUrl", e.detail)} - updateOnChange={false} - /> - {/if} -
- -
- update("hideTitle", !e.detail)} - /> - {#if !$store.navigation.hideTitle} -
- -
- update("title", e.detail)} - updateOnChange={false} - /> - {/if} -
- -
- update("navBackground", e.detail)} - /> -
- -
- update("navTextColor", e.detail)} - /> -
-
- - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte deleted file mode 100644 index d3ce720994..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/SettingsPane.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - - -
- - Show nav on this screen -
-
- - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte deleted file mode 100644 index 6ce5405f93..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel/index.svelte +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte deleted file mode 100644 index 5ffccc5800..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte +++ /dev/null @@ -1,130 +0,0 @@ - - - -
- - {#if links?.length} - - {/if} -
- -
-
-
-
- - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksEditor.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksEditor.svelte deleted file mode 100644 index 895c82495d..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksEditor.svelte +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - Configure the links in your navigation bar. - - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationSettingsPanel.svelte deleted file mode 100644 index c6d43984b2..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationSettingsPanel.svelte +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - update("navigation", "Top")} - /> - update("navigation", "Left")} - /> - - - {#if $store.navigation.navigation === "Top"} - update("sticky", e.detail)} - /> - update("logoUrl", e.detail)} - placeholder="Add logo URL" - updateOnChange={false} - /> - {/if} - - - update("hideTitle", !e.detail)} - /> - {#if !$store.navigation.hideTitle} - update("title", e.detail)} - placeholder="Add title" - updateOnChange={false} - /> - {/if} - - - - update("navBackground", e.detail)} - /> - - - - update("navTextColor", e.detail)} - /> - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte deleted file mode 100644 index 2331d8b285..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte deleted file mode 100644 index 6362af3073..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - (searchString = e.detail)} - /> - + + + removeLink(link.id)} + /> +
+ {/each} +
+ {/if} +
+ +
+ +
+ + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/LinksEditor.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/LinksEditor.svelte new file mode 100644 index 0000000000..9ab6681273 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/LinksEditor.svelte @@ -0,0 +1,34 @@ + + + + + + Configure the links in your navigation bar. + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/index.svelte index 6da744a44a..16baa3bfff 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/index.svelte @@ -1,4 +1,5 @@ - + Configure the links in your navigation bar. From 0ea81f98d6fd317367b60e76d9ac14f8f602a9bc Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 22 Aug 2023 16:29:40 +0100 Subject: [PATCH 133/183] Update panel headings to match new designs --- packages/builder/src/components/design/Panel.svelte | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/builder/src/components/design/Panel.svelte b/packages/builder/src/components/design/Panel.svelte index 3968292ba9..db8d9b9096 100644 --- a/packages/builder/src/components/design/Panel.svelte +++ b/packages/builder/src/components/design/Panel.svelte @@ -1,5 +1,5 @@
-
+
Components
@@ -116,15 +116,16 @@ } .header { - padding: 15px 12px; + height: 50px; + box-sizing: border-box; + padding: var(--spacing-l); display: flex; align-items: center; border-bottom: 2px solid transparent; - transition: border-bottom 300ms; + transition: border-bottom 130ms ease-out; } - - .headerScrolling { - border-bottom: 2px solid var(--grey-2); + .header.scrolling { + border-bottom: var(--border-light); } .components :global(.nav-item) { From a07f343f839323f9149ebc01cc5ec6388f86bdb0 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 22 Aug 2023 16:45:37 +0100 Subject: [PATCH 136/183] Fix component scroll offsets not working --- .../Components/ComponentScrollWrapper.svelte | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Components/ComponentScrollWrapper.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Components/ComponentScrollWrapper.svelte index 226aff88ab..484b56f21c 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Components/ComponentScrollWrapper.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Components/ComponentScrollWrapper.svelte @@ -16,7 +16,7 @@ let newOffsets = {} // Calculate left offset - const offsetX = bounds.left + bounds.width + scrollLeft - 36 + const offsetX = bounds.left + bounds.width + scrollLeft + 16 if (offsetX > sidebarWidth) { newOffsets.left = offsetX - sidebarWidth } else { @@ -79,19 +79,4 @@ overflow: auto; height: 0; } - - div::-webkit-scrollbar-track { - background: var(--background-alt); - } - - div::-webkit-scrollbar { - width: 18px; - } - - div::-webkit-scrollbar-thumb { - background-color: var(--grey-3); - border-radius: 20px; - border: 1px solid var(--background-alt); - border-width: 5px 5px; - } From a4a639c2ba98e088a8cc4a0e1fba496ac440f155 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 22 Aug 2023 16:49:04 +0100 Subject: [PATCH 137/183] Update screen list size slightly --- .../[componentId]/_components/LeftPanel/Screens/index.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/index.svelte index a3762b81ed..c11e933624 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/index.svelte @@ -135,7 +135,7 @@ } .screens { - height: 212px; + height: 210px; display: flex; flex-direction: column; transition: height 300ms ease-out; From d0414812cf6f90e6be635b2d7feeff972f28015b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 22 Aug 2023 17:51:47 +0100 Subject: [PATCH 138/183] Adjust design section page layouts to stop remounting left nav on screen change --- .../app/[application]/design/[screenId]/_layout.svelte | 2 ++ .../[componentId]/_components/LeftPanel/index.svelte | 9 ++++++--- .../[screenId]/components/[componentId]/_layout.svelte | 10 ---------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte index 9bc1806349..8471cc03ed 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte @@ -4,6 +4,7 @@ import { syncURLToState } from "helpers/urlStateSync" import { store } from "builderStore" import { onDestroy } from "svelte" + import LeftPanel from "./components/[componentId]/_components/LeftPanel/index.svelte" $: screenId = $store.selectedScreenId $: store.actions.websocket.selectResource(screenId) @@ -23,6 +24,7 @@
+
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte index 86c0df8cac..c1fe15f625 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte @@ -1,25 +1,28 @@
- + {#if $selectedScreen} + + {/if}
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte index 807109326a..51c3c64321 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte @@ -1,5 +1,4 @@ -
- -
{#if routeComponentId === "screen"} {:else if routeComponentId === "navigation"} @@ -58,9 +54,3 @@ {/if} - - From 656870db8b9ec5314f7e62329d71b6f225b2016c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 22 Aug 2023 18:14:08 +0100 Subject: [PATCH 139/183] Adding last of support for per app group builder support, enriching the user on self return, as well as adding the functionality required to server middlewares. --- packages/pro | 2 +- packages/server/src/api/controllers/auth.ts | 9 +- packages/server/src/utilities/global.ts | 85 ++++++++----------- .../server/src/utilities/workerRequests.ts | 31 ++----- .../worker/src/api/controllers/global/self.ts | 4 +- .../src/api/controllers/global/users.ts | 8 +- 6 files changed, 55 insertions(+), 84 deletions(-) diff --git a/packages/pro b/packages/pro index a054a51726..39d76da212 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit a054a51726fa3f17879a469a04675778185b7ed7 +Subproject commit 39d76da2124d96b1bcec0f2352ca5ef9b0c84318 diff --git a/packages/server/src/api/controllers/auth.ts b/packages/server/src/api/controllers/auth.ts index bca6c4e64e..ae98d92332 100644 --- a/packages/server/src/api/controllers/auth.ts +++ b/packages/server/src/api/controllers/auth.ts @@ -2,9 +2,9 @@ import { outputProcessing } from "../../utilities/rowProcessor" import { InternalTables } from "../../db/utils" import { getFullUser } from "../../utilities/users" import { roles, context } from "@budibase/backend-core" -import { groups } from "@budibase/pro" -import { ContextUser, User, Row, UserCtx } from "@budibase/types" +import { ContextUser, Row, UserCtx } from "@budibase/types" import sdk from "../../sdk" +import { processUser } from "src/utilities/global" const PUBLIC_ROLE = roles.BUILTIN_ROLE_IDS.PUBLIC @@ -26,7 +26,7 @@ export async function fetchSelf(ctx: UserCtx) { } const appId = context.getAppId() - const user: ContextUser = await getFullUser(ctx, userId) + let user: ContextUser = await getFullUser(ctx, userId) // this shouldn't be returned by the app self delete user.roles // forward the csrf token from the session @@ -36,8 +36,7 @@ export async function fetchSelf(ctx: UserCtx) { const db = context.getAppDB() // check for group permissions if (!user.roleId || user.roleId === PUBLIC_ROLE) { - const groupRoleId = await groups.getGroupRoleId(user as User, appId) - user.roleId = groupRoleId || user.roleId + user = await processUser(user, { appId }) } // remove the full roles structure delete user.roles diff --git a/packages/server/src/utilities/global.ts b/packages/server/src/utilities/global.ts index 5561b59233..1cb7956d5e 100644 --- a/packages/server/src/utilities/global.ts +++ b/packages/server/src/utilities/global.ts @@ -12,75 +12,64 @@ import { groups } from "@budibase/pro" import { UserCtx, ContextUser, User, UserGroup } from "@budibase/types" import cloneDeep from "lodash/cloneDeep" -export function updateAppRole( +export async function processUser( user: ContextUser, - { appId }: { appId?: string } = {} + opts: { appId?: string; groups?: UserGroup[] } = {} ) { - appId = appId || context.getAppId() - if (!user || (!user.roles && !user.userGroups)) { return user } - // if in an multi-tenancy environment make sure roles are never updated + user = cloneDeep(user) + delete user.password + const appId = opts.appId || context.getAppId() + if (!appId) { + throw new Error("Unable to process user without app ID") + } + // if in a multi-tenancy environment and in wrong tenant make sure roles are never updated if (env.MULTI_TENANCY && appId && !tenancy.isUserInAppTenant(appId, user)) { user = users.removePortalUserPermissions(user) user.roleId = roles.BUILTIN_ROLE_IDS.PUBLIC return user } - // always use the deployed app - if (appId && user.roles) { + let groupList: UserGroup[] = [] + if (appId && user?.userGroups?.length) { + groupList = opts.groups + ? opts.groups + : await groups.getBulk(user.userGroups) + } + // check if a group provides builder access + const builderAppIds = await groups.getGroupBuilderAppIds(user, appId, { + groups: groupList, + }) + if (builderAppIds.length && !users.isBuilder(user, appId)) { + const existingApps = user.builder?.apps || [] + user.builder = { + apps: [...new Set(existingApps.concat(builderAppIds))], + } + } + // builders are always admins within the app + if (users.isBuilder(user, appId)) { + user.roleId = roles.BUILTIN_ROLE_IDS.ADMIN + } + // try to get the role from the user list + if (!user.roleId && appId && user.roles) { user.roleId = user.roles[dbCore.getProdAppID(appId)] } - // if a role wasn't found then either set as admin (builder) or public (everyone else) - if (!user.roleId && users.isBuilder(user, appId)) { - user.roleId = roles.BUILTIN_ROLE_IDS.ADMIN - } else if (!user.roleId && !user?.userGroups?.length) { - user.roleId = roles.BUILTIN_ROLE_IDS.PUBLIC - } - - delete user.roles - return user -} - -async function checkGroupRoles( - user: ContextUser, - opts: { appId?: string; groups?: UserGroup[] } = {} -) { - if (user.roleId && user.roleId !== roles.BUILTIN_ROLE_IDS.PUBLIC) { - return user - } - if (opts.appId) { - user.roleId = await groups.getGroupRoleId(user as User, opts.appId, { - groups: opts.groups, + // try to get the role from the group list + if (!user.roleId && groupList) { + user.roleId = await groups.getGroupRoleId(user, appId, { + groups: groupList, }) } // final fallback, simply couldn't find a role - user must be public if (!user.roleId) { user.roleId = roles.BUILTIN_ROLE_IDS.PUBLIC } + // remove the roles as it is now set + delete user.roles return user } -export async function processUser( - user: ContextUser, - opts: { appId?: string; groups?: UserGroup[] } = {} -) { - let clonedUser = cloneDeep(user) - if (clonedUser) { - delete clonedUser.password - } - const appId = opts.appId || context.getAppId() - clonedUser = updateAppRole(clonedUser, { appId }) - if (!clonedUser.roleId && clonedUser?.userGroups?.length) { - clonedUser = await checkGroupRoles(clonedUser, { - appId, - groups: opts?.groups, - }) - } - - return clonedUser -} - export async function getCachedSelf(ctx: UserCtx, appId: string) { // this has to be tenant aware, can't depend on the context to find it out // running some middlewares before the tenancy causes context to break diff --git a/packages/server/src/utilities/workerRequests.ts b/packages/server/src/utilities/workerRequests.ts index 5230e25bf7..fa9fde7297 100644 --- a/packages/server/src/utilities/workerRequests.ts +++ b/packages/server/src/utilities/workerRequests.ts @@ -8,10 +8,9 @@ import { logging, env as coreEnv, } from "@budibase/backend-core" -import { updateAppRole } from "./global" -import { BBContext, User, EmailInvite } from "@budibase/types" +import { Ctx, User, EmailInvite } from "@budibase/types" -export function request(ctx?: BBContext, request?: any) { +export function request(ctx?: Ctx, request?: any) { if (!request.headers) { request.headers = {} } @@ -43,7 +42,7 @@ export function request(ctx?: BBContext, request?: any) { async function checkResponse( response: any, errorMsg: string, - { ctx }: { ctx?: BBContext } = {} + { ctx }: { ctx?: Ctx } = {} ) { if (response.status !== 200) { let error @@ -105,21 +104,7 @@ export async function sendSmtpEmail({ return checkResponse(response, "send email") } -export async function getGlobalSelf(ctx: BBContext, appId?: string) { - const endpoint = `/api/global/self` - const response = await fetch( - checkSlashesInUrl(env.WORKER_URL + endpoint), - // we don't want to use API key when getting self - request(ctx, { method: "GET" }) - ) - let json = await checkResponse(response, "get self globally", { ctx }) - if (appId) { - json = updateAppRole(json) - } - return json -} - -export async function removeAppFromUserRoles(ctx: BBContext, appId: string) { +export async function removeAppFromUserRoles(ctx: Ctx, appId: string) { const prodAppId = dbCore.getProdAppID(appId) const response = await fetch( checkSlashesInUrl(env.WORKER_URL + `/api/global/roles/${prodAppId}`), @@ -130,7 +115,7 @@ export async function removeAppFromUserRoles(ctx: BBContext, appId: string) { return checkResponse(response, "remove app role") } -export async function allGlobalUsers(ctx: BBContext) { +export async function allGlobalUsers(ctx: Ctx) { const response = await fetch( checkSlashesInUrl(env.WORKER_URL + "/api/global/users"), // we don't want to use API key when getting self @@ -139,7 +124,7 @@ export async function allGlobalUsers(ctx: BBContext) { return checkResponse(response, "get users", { ctx }) } -export async function saveGlobalUser(ctx: BBContext) { +export async function saveGlobalUser(ctx: Ctx) { const response = await fetch( checkSlashesInUrl(env.WORKER_URL + "/api/global/users"), // we don't want to use API key when getting self @@ -148,7 +133,7 @@ export async function saveGlobalUser(ctx: BBContext) { return checkResponse(response, "save user", { ctx }) } -export async function deleteGlobalUser(ctx: BBContext) { +export async function deleteGlobalUser(ctx: Ctx) { const response = await fetch( checkSlashesInUrl( env.WORKER_URL + `/api/global/users/${ctx.params.userId}` @@ -159,7 +144,7 @@ export async function deleteGlobalUser(ctx: BBContext) { return checkResponse(response, "delete user", { ctx }) } -export async function readGlobalUser(ctx: BBContext): Promise { +export async function readGlobalUser(ctx: Ctx): Promise { const response = await fetch( checkSlashesInUrl( env.WORKER_URL + `/api/global/users/${ctx.params.userId}` diff --git a/packages/worker/src/api/controllers/global/self.ts b/packages/worker/src/api/controllers/global/self.ts index 7167d91b23..47dbef964e 100644 --- a/packages/worker/src/api/controllers/global/self.ts +++ b/packages/worker/src/api/controllers/global/self.ts @@ -48,7 +48,7 @@ export async function generateAPIKey(ctx: any) { } catch (err) { devInfo = { _id: id, userId } } - devInfo.apiKey = await apiKey + devInfo.apiKey = apiKey await db.put(devInfo) ctx.body = cleanupDevInfo(devInfo) } @@ -63,7 +63,7 @@ export async function fetchAPIKey(ctx: any) { devInfo = { _id: id, userId: ctx.user._id, - apiKey: await newApiKey(), + apiKey: newApiKey(), } await db.put(devInfo) } diff --git a/packages/worker/src/api/controllers/global/users.ts b/packages/worker/src/api/controllers/global/users.ts index a8207ea89e..ad906c8688 100644 --- a/packages/worker/src/api/controllers/global/users.ts +++ b/packages/worker/src/api/controllers/global/users.ts @@ -25,11 +25,11 @@ import { import { accounts, cache, + ErrorCode, events, migrations, - tenancy, platform, - ErrorCode, + tenancy, } from "@budibase/backend-core" import { checkAnyUserExists } from "../../../utilities/users" import { isEmailConfigured } from "../../../utilities/email" @@ -280,7 +280,7 @@ export const onboardUsers = async (ctx: Ctx) => { let bulkCreateReponse = await userSdk.db.bulkCreate(users, []) // Apply temporary credentials - let createWithCredentials = { + ctx.body = { ...bulkCreateReponse, successful: bulkCreateReponse?.successful.map(user => { return { @@ -290,8 +290,6 @@ export const onboardUsers = async (ctx: Ctx) => { }), created: true, } - - ctx.body = createWithCredentials } else { ctx.throw(400, "User onboarding failed") } From a83e987dcdeeb81d968fb93dcb6d38d665782f3b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 22 Aug 2023 18:55:36 +0100 Subject: [PATCH 140/183] Stop preview jumping when scrolling to components, and improve scrolling behaviour --- packages/client/src/components/Component.svelte | 2 +- packages/client/src/components/app/Layout.svelte | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 31f3cc3db6..94e7587010 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -475,7 +475,7 @@ node.style.scrollMargin = "100px" node.scrollIntoView({ behavior: "smooth", - block: "start", + block: "nearest", inline: "start", }) } diff --git a/packages/client/src/components/app/Layout.svelte b/packages/client/src/components/app/Layout.svelte index b7aff4047a..5207892e42 100644 --- a/packages/client/src/components/app/Layout.svelte +++ b/packages/client/src/components/app/Layout.svelte @@ -73,18 +73,20 @@ ) $: autoCloseSidePanel = !$builderStore.inBuilder && $sidePanelStore.open - // Scroll navigation into view if selected + // Scroll navigation into view if selected. + // Memoize into a primitive to avoid spamming this whenever builder store + // changes. + $: selected = + $builderStore.inBuilder && + $builderStore.selectedComponentId === "navigation" $: { - if ( - $builderStore.inBuilder && - $builderStore.selectedComponentId === "navigation" - ) { + if (selected) { const node = document.getElementsByClassName("nav-wrapper")?.[0] if (node) { node.style.scrollMargin = "100px" node.scrollIntoView({ behavior: "smooth", - block: "start", + block: "nearest", inline: "start", }) } From 3395a5b96b0b9cccf971b63d294a45b7e41127b6 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 22 Aug 2023 19:15:47 +0100 Subject: [PATCH 141/183] Some other minor changes to fully support the per app builder from groups, making sure middlewares are properly aware. --- packages/backend-core/src/cache/user.ts | 14 ++++++++++++++ .../backend-core/src/middleware/builderOnly.ts | 11 ++++++----- .../src/middleware/builderOrAdmin.ts | 11 ++++++----- packages/backend-core/src/users/db.ts | 18 +++++++++++++++++- packages/server/src/utilities/global.ts | 3 ++- 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/packages/backend-core/src/cache/user.ts b/packages/backend-core/src/cache/user.ts index 8281bfca62..e2af78adfd 100644 --- a/packages/backend-core/src/cache/user.ts +++ b/packages/backend-core/src/cache/user.ts @@ -4,6 +4,8 @@ import * as context from "../context" import * as platform from "../platform" import env from "../environment" import * as accounts from "../accounts" +import { UserDB } from "../users" +import { sdk } from "@budibase/shared-core" const EXPIRY_SECONDS = 3600 @@ -60,6 +62,18 @@ export async function getUser( // make sure the tenant ID is always correct/set user.tenantId = tenantId } + // if has groups, could have builder permissions granted by a group + if (user.userGroups && !sdk.users.isGlobalBuilder(user)) { + await context.doInTenant(tenantId, async () => { + const appIds = await UserDB.getGroupBuilderAppIds(user) + if (appIds.length) { + const existing = user.builder?.apps || [] + user.builder = { + apps: [...new Set(existing.concat(appIds))], + } + } + }) + } return user } diff --git a/packages/backend-core/src/middleware/builderOnly.ts b/packages/backend-core/src/middleware/builderOnly.ts index 8c1c54a44c..fafcc524cc 100644 --- a/packages/backend-core/src/middleware/builderOnly.ts +++ b/packages/backend-core/src/middleware/builderOnly.ts @@ -5,11 +5,12 @@ import env from "../environment" export default async (ctx: UserCtx, next: any) => { const appId = getAppId() - const builderFn = env.isWorker() - ? hasBuilderPermissions - : env.isApps() - ? isBuilder - : undefined + const builderFn = + env.isWorker() || !appId + ? hasBuilderPermissions + : env.isApps() + ? isBuilder + : undefined if (!builderFn) { throw new Error("Service name unknown - middleware inactive.") } diff --git a/packages/backend-core/src/middleware/builderOrAdmin.ts b/packages/backend-core/src/middleware/builderOrAdmin.ts index c03e856233..4b8badec15 100644 --- a/packages/backend-core/src/middleware/builderOrAdmin.ts +++ b/packages/backend-core/src/middleware/builderOrAdmin.ts @@ -5,11 +5,12 @@ import env from "../environment" export default async (ctx: UserCtx, next: any) => { const appId = getAppId() - const builderFn = env.isWorker() - ? hasBuilderPermissions - : env.isApps() - ? isBuilder - : undefined + const builderFn = + env.isWorker() || !appId + ? hasBuilderPermissions + : env.isApps() + ? isBuilder + : undefined if (!builderFn) { throw new Error("Service name unknown - middleware inactive.") } diff --git a/packages/backend-core/src/users/db.ts b/packages/backend-core/src/users/db.ts index 14140cba81..c288540f35 100644 --- a/packages/backend-core/src/users/db.ts +++ b/packages/backend-core/src/users/db.ts @@ -20,6 +20,8 @@ import { SaveUserOpts, User, UserStatus, + UserGroup, + ContextUser, } from "@budibase/types" import { getAccountHolderFromUserIds, @@ -32,8 +34,14 @@ import { hash } from "../utils" type QuotaUpdateFn = (change: number, cb?: () => Promise) => Promise type GroupUpdateFn = (groupId: string, userIds: string[]) => Promise type FeatureFn = () => Promise +type GroupGetFn = (ids: string[]) => Promise +type GroupBuildersFn = (user: User) => Promise type QuotaFns = { addUsers: QuotaUpdateFn; removeUsers: QuotaUpdateFn } -type GroupFns = { addUsers: GroupUpdateFn } +type GroupFns = { + addUsers: GroupUpdateFn + getBulk: GroupGetFn + getGroupBuilderAppIds: GroupBuildersFn +} type FeatureFns = { isSSOEnforced: FeatureFn; isAppBuildersEnabled: FeatureFn } const bulkDeleteProcessing = async (dbUser: User) => { @@ -465,4 +473,12 @@ export class UserDB { await cache.user.invalidateUser(userId) await sessions.invalidateSessions(userId, { reason: "deletion" }) } + + static async getGroups(groupIds: string[]) { + return await this.groups.getBulk(groupIds) + } + + static async getGroupBuilderAppIds(user: User) { + return await this.groups.getGroupBuilderAppIds(user) + } } diff --git a/packages/server/src/utilities/global.ts b/packages/server/src/utilities/global.ts index 1cb7956d5e..5aa201990c 100644 --- a/packages/server/src/utilities/global.ts +++ b/packages/server/src/utilities/global.ts @@ -38,7 +38,8 @@ export async function processUser( : await groups.getBulk(user.userGroups) } // check if a group provides builder access - const builderAppIds = await groups.getGroupBuilderAppIds(user, appId, { + const builderAppIds = await groups.getGroupBuilderAppIds(user, { + appId, groups: groupList, }) if (builderAppIds.length && !users.isBuilder(user, appId)) { From a54c5b7222edc4b5cc75f6ec901f2eacd99ddcb6 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 23 Aug 2023 10:27:56 +0100 Subject: [PATCH 142/183] Add resizable screen/component sections and remove redundant /components route --- .../src/builderStore/store/frontend.js | 2 +- .../Component/ComponentInfoSection.svelte | 0 .../Component/ComponentSettingsPanel.svelte | 0 .../Component/ComponentSettingsSection.svelte | 0 .../Component/ConditionalUIDrawer.svelte | 0 .../Component/ConditionalUISection.svelte | 0 .../Component/CustomStylesSection.svelte | 0 .../Component/DesignSection.svelte | 0 .../_components/Component/StyleSection.svelte | 0 .../_components/Component/componentStyles.js | 0 .../_components/Navigation/LinksDrawer.svelte | 0 .../_components/Navigation/LinksEditor.svelte | 0 .../_components/Navigation/index.svelte | 0 .../_components/Screen/SettingsPanel.svelte | 0 .../[componentId]/_layout.svelte | 0 .../[screenId]/[componentId]/index.svelte | 1 + .../new/_components/NewComponentPanel.svelte | 2 +- .../new/_components/componentStructure.json | 0 .../[componentId]/new/index.svelte | 0 .../[screenId]/_components/AppPanel.svelte | 4 +- .../[screenId]/_components/AppPreview.svelte | 8 +- .../ComponentDropdownMenu.svelte | 0 .../ComponentList}/ComponentKeyHandler.svelte | 0 .../ComponentScrollWrapper.svelte | 0 .../ComponentList}/ComponentTree.svelte | 0 .../DNDPositionIndicator.svelte | 0 .../ScreenslotDropdownMenu.svelte | 0 .../ComponentList}/dndStore.js | 0 .../ComponentList}/index.svelte | 10 +- .../[screenId]/_components/LeftPanel.svelte | 24 ++++ .../ScreenList}/DropdownMenu.svelte | 0 .../ScreenList}/RoleIndicator.svelte | 0 .../ScreenList}/index.svelte | 106 +++++++++++++----- .../design/[screenId]/_layout.svelte | 2 +- .../_components/LeftPanel/index.svelte | 28 ----- .../components/[componentId]/index.svelte | 4 - .../design/[screenId]/components/index.svelte | 8 -- .../design/[screenId]/index.svelte | 5 +- .../app/[application]/design/index.svelte | 2 +- 39 files changed, 117 insertions(+), 89 deletions(-) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Component/ComponentInfoSection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Component/ComponentSettingsPanel.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Component/ComponentSettingsSection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Component/ConditionalUIDrawer.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Component/ConditionalUISection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Component/CustomStylesSection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Component/DesignSection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Component/StyleSection.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Component/componentStyles.js (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Navigation/LinksDrawer.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Navigation/LinksEditor.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Navigation/index.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_components/Screen/SettingsPanel.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/_layout.svelte (100%) create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/index.svelte rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/new/_components/NewComponentPanel.svelte (99%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/new/_components/componentStructure.json (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components => }/[componentId]/new/index.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Components => _components/ComponentList}/ComponentDropdownMenu.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Components => _components/ComponentList}/ComponentKeyHandler.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Components => _components/ComponentList}/ComponentScrollWrapper.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Components => _components/ComponentList}/ComponentTree.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Components => _components/ComponentList}/DNDPositionIndicator.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Components => _components/ComponentList}/ScreenslotDropdownMenu.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Components => _components/ComponentList}/dndStore.js (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Components => _components/ComponentList}/index.svelte (96%) create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/LeftPanel.svelte rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Screens => _components/ScreenList}/DropdownMenu.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Screens => _components/ScreenList}/RoleIndicator.svelte (100%) rename packages/builder/src/pages/builder/app/[application]/design/[screenId]/{components/[componentId]/_components/LeftPanel/Screens => _components/ScreenList}/index.svelte (70%) delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/index.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 164fda4440..46b4bab6c0 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -225,7 +225,7 @@ export const getFrontendStore = () => { // Select new screen store.update(state => { state.selectedScreenId = screen._id - state.selectedComponentId = screen.props?._id + state.selectedComponentId = "screen" return state }) }, diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/ComponentInfoSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentInfoSection.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/ComponentInfoSection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentInfoSection.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/ComponentSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsPanel.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/ComponentSettingsPanel.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsPanel.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/ComponentSettingsSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/ComponentSettingsSection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/ConditionalUIDrawer.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUIDrawer.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/ConditionalUIDrawer.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUIDrawer.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/ConditionalUISection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUISection.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/ConditionalUISection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUISection.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/CustomStylesSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/CustomStylesSection.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/CustomStylesSection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/CustomStylesSection.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/DesignSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/DesignSection.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/DesignSection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/DesignSection.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/StyleSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/StyleSection.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/StyleSection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/StyleSection.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/componentStyles.js b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/componentStyles.js similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Component/componentStyles.js rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/componentStyles.js diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/LinksDrawer.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/LinksDrawer.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/LinksDrawer.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/LinksDrawer.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/LinksEditor.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/LinksEditor.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/LinksEditor.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/LinksEditor.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/index.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Navigation/index.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/index.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Screen/SettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/SettingsPanel.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/Screen/SettingsPanel.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/SettingsPanel.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_layout.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_layout.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/index.svelte new file mode 100644 index 0000000000..0ff63d1ead --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/index.svelte @@ -0,0 +1 @@ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte similarity index 99% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/NewComponentPanel.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte index 7dca5b792b..4500723027 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte @@ -1,6 +1,6 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/LeftPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/LeftPanel.svelte new file mode 100644 index 0000000000..32150ef921 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/LeftPanel.svelte @@ -0,0 +1,24 @@ + + +
+ + {#if $isActive("./:componentId")} + + {/if} +
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/DropdownMenu.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/DropdownMenu.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/DropdownMenu.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/DropdownMenu.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/RoleIndicator.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/RoleIndicator.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/RoleIndicator.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/RoleIndicator.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte similarity index 70% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/index.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte index c11e933624..9324b2073d 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/Screens/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte @@ -9,29 +9,42 @@ let newScreen = false let search = false + let resizing = false let searchValue = "" let searchInput let screensContainer let scrolling = false + let height = "210px" + let previousHeight = null + let dragOffset $: filteredScreens = getFilteredScreens($sortedScreens, searchValue) + const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)) + const openSearch = async () => { search = true await tick() searchInput.focus() screensContainer.scroll({ top: 0, behavior: "smooth" }) + previousHeight = height + height = "calc(100% + 1px)" } - const closeSearch = () => { + const closeSearch = async () => { + if (previousHeight) { + // Restore previous height and wait for animation + height = previousHeight + previousHeight = null + await sleep(300) + } search = false searchValue = "" } const getFilteredScreens = (screens, search) => { return screens.filter(screen => { - const searchMatch = !search || screen.routing.route.includes(search) - return searchMatch + return !search || screen.routing.route.includes(search) }) } @@ -54,17 +67,33 @@ } const handleScroll = e => { - if (e.target.scrollTop === 0) { - scrolling = false - } else { - scrolling = true + scrolling = e.target.scrollTop !== 0 + } + + const startResizing = e => { + resizing = true + dragOffset = parseInt(height) - e.clientY + document.addEventListener("mousemove", resize) + document.addEventListener("mouseup", stopResizing) + } + + const resize = e => { + const newHeight = Math.max(0, e.clientY + dragOffset) + if (newHeight == null || isNaN(newHeight)) { + return } + height = `${newHeight}px` + } + + const stopResizing = () => { + resizing = false + document.removeEventListener("mousemove", resize) } -
-
+
+
{/if}
+ +
@@ -129,20 +160,24 @@ z-index: 2; background-color: var(--background); } - .newScreenVisible { display: initial; } .screens { - height: 210px; display: flex; flex-direction: column; - transition: height 300ms ease-out; + min-height: 147px; + max-height: calc(100% - 147px); + position: relative; } - - .screenSearch { - height: 100%; + .screens.search { + transition: height 300ms ease-out; + max-height: none; + } + .screens.resizing { + user-select: none; + cursor: row-resize; } .header { @@ -154,11 +189,10 @@ display: flex; align-items: center; border-bottom: 2px solid transparent; - transition: border-bottom 300ms ease-out; + transition: border-bottom 130ms ease-out; } - - .headerScrolling { - border-bottom: 2px solid var(--grey-2); + .header.scrolling { + border-bottom: var(--border-light); } .input { @@ -178,8 +212,7 @@ .input::placeholder { color: var(--spectrum-global-color-gray-600); } - - .screenSearch input { + .screens.search input { display: block; } @@ -197,6 +230,9 @@ overflow: auto; flex-grow: 1; } + .screens.resizing .content { + pointer-events: none; + } .screens :global(.nav-item) { padding-right: 8px !important; @@ -208,7 +244,6 @@ margin-right: 10px; opacity: 1; } - .searchButton:hover { color: var(--ink); } @@ -223,15 +258,14 @@ cursor: pointer; transition: transform 300ms ease-out; } + .addButton:hover { + color: var(--ink); + } .closeButton { transform: rotate(45deg); } - .addButton:hover { - color: var(--ink); - } - .icon { margin-left: 4px; margin-right: 4px; @@ -240,4 +274,24 @@ .no-results { color: var(--spectrum-global-color-gray-600); } + + .divider { + position: absolute; + bottom: 0; + transform: translateY(50%); + height: 16px; + width: 100%; + } + .divider:after { + content: ""; + position: absolute; + background: var(--spectrum-global-color-gray-200); + height: 2px; + width: 100%; + top: 50%; + transform: translateY(-50%); + } + .divider:hover { + cursor: row-resize; + } diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte index 8471cc03ed..61514270e6 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte @@ -4,7 +4,7 @@ import { syncURLToState } from "helpers/urlStateSync" import { store } from "builderStore" import { onDestroy } from "svelte" - import LeftPanel from "./components/[componentId]/_components/LeftPanel/index.svelte" + import LeftPanel from "./_components/LeftPanel.svelte" $: screenId = $store.selectedScreenId $: store.actions.websocket.selectResource(screenId) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte deleted file mode 100644 index c1fe15f625..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/LeftPanel/index.svelte +++ /dev/null @@ -1,28 +0,0 @@ - - -
- -
- {#if $selectedScreen} - - {/if} -
- - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/index.svelte deleted file mode 100644 index 9b5d05fe57..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/index.svelte +++ /dev/null @@ -1,4 +0,0 @@ - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte deleted file mode 100644 index 9361415cb7..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte index 496467c546..c3951eab5d 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte @@ -1,8 +1,5 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/design/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/index.svelte index 470c81b88c..79d264d120 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/index.svelte @@ -4,7 +4,7 @@ $: { if ($frontendStore.screens.length > 0) { - $redirect(`./${$frontendStore.screens[0]._id}/components/screen`) + $redirect(`./${$frontendStore.screens[0]._id}/screen`) } else { $redirect("./new") } From d486a89ee786b0312de5e5031b8401f1c90632a1 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 23 Aug 2023 10:32:24 +0100 Subject: [PATCH 143/183] Clean all URLs by default in URL state sync --- packages/builder/src/helpers/urlStateSync.js | 4 ++++ .../design/[screenId]/[componentId]/_layout.svelte | 10 +++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/builder/src/helpers/urlStateSync.js b/packages/builder/src/helpers/urlStateSync.js index c4c48fb3fb..04c639b3ec 100644 --- a/packages/builder/src/helpers/urlStateSync.js +++ b/packages/builder/src/helpers/urlStateSync.js @@ -65,6 +65,10 @@ export const syncURLToState = options => { params = res.params } } + // Clean URL + if (url?.endsWith("/index")) { + url = url.replace("/index", "") + } log("Navigating to", url, "with params", params) cachedGoto(url, params) } diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_layout.svelte index 51c3c64321..932a3d360a 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_layout.svelte @@ -13,12 +13,8 @@ $: params = routify.params $: routeComponentId = $params.componentId - const cleanUrl = url => { - // Strip trailing slashes - if (url?.endsWith("/index")) { - url = url.replace("/index", "") - } - // Hide new component panel whenever component ID changes + // Hide new component panel whenever component ID changes + const closeNewComponentPanel = url => { if (url?.endsWith("/new")) { url = url.replace("/new", "") } @@ -40,7 +36,7 @@ fallbackUrl: "../", store, routify, - beforeNavigate: cleanUrl, + beforeNavigate: closeNewComponentPanel, }) onDestroy(stopSyncing) From f72f3f88f7a8dff5749d4e2156c900af7114b02e Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 23 Aug 2023 10:49:48 +0100 Subject: [PATCH 144/183] Improve UX when resizing screen/component lists --- packages/builder/src/builderStore/index.js | 4 +- .../_components/ScreenList/index.svelte | 49 +++++++++++++++---- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js index 3cd387fe95..dfb8609e65 100644 --- a/packages/builder/src/builderStore/index.js +++ b/packages/builder/src/builderStore/index.js @@ -4,7 +4,7 @@ import { getTemporalStore } from "./store/temporal" import { getThemeStore } from "./store/theme" import { getUserStore } from "./store/users" import { getDeploymentStore } from "./store/deployments" -import { derived } from "svelte/store" +import { derived, writable } from "svelte/store" import { findComponent, findComponentPath } from "./componentUtils" import { RoleUtils } from "@budibase/frontend-core" import { createHistoryStore } from "builderStore/store/history" @@ -147,3 +147,5 @@ export const userSelectedResourceMap = derived(userStore, $userStore => { export const isOnlyUser = derived(userStore, $userStore => { return $userStore.length < 2 }) + +export const screensHeight = writable("210px") diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte index 9324b2073d..0ecc9b76bf 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte @@ -1,20 +1,25 @@ -
+
-
+
screensHeight.set("210px")} + />
From 607a36e2e4822bb91f30578d61196a8a1c1a14b6 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 23 Aug 2023 11:03:00 +0100 Subject: [PATCH 145/183] Improve route handling when creating new components and screens --- .../design/NewScreen/CreateScreenModal.svelte | 3 ++- packages/builder/src/helpers/urlStateSync.js | 9 +++++---- .../[screenId]/_components/LeftPanel.svelte | 4 ++-- .../_components/ScreenList/index.svelte | 16 +++++++++++++++- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/builder/src/components/design/NewScreen/CreateScreenModal.svelte b/packages/builder/src/components/design/NewScreen/CreateScreenModal.svelte index 3ca3e6b419..300906eaf6 100644 --- a/packages/builder/src/components/design/NewScreen/CreateScreenModal.svelte +++ b/packages/builder/src/components/design/NewScreen/CreateScreenModal.svelte @@ -67,7 +67,8 @@ } } - $goto(`./${screenId}`) + // Select and go to new screen + store.actions.screens.select(screenId) } catch (error) { console.log(error) notifications.error("Error creating screens") diff --git a/packages/builder/src/helpers/urlStateSync.js b/packages/builder/src/helpers/urlStateSync.js index 04c639b3ec..2408dde2f1 100644 --- a/packages/builder/src/helpers/urlStateSync.js +++ b/packages/builder/src/helpers/urlStateSync.js @@ -56,6 +56,11 @@ export const syncURLToState = options => { // Navigate to a certain URL const gotoUrl = (url, params) => { + // Clean URL + if (url?.endsWith("/index")) { + url = url.replace("/index", "") + } + // Allow custom URL handling if (beforeNavigate) { const res = beforeNavigate(url, params) if (res?.url) { @@ -65,10 +70,6 @@ export const syncURLToState = options => { params = res.params } } - // Clean URL - if (url?.endsWith("/index")) { - url = url.replace("/index", "") - } log("Navigating to", url, "with params", params) cachedGoto(url, params) } diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/LeftPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/LeftPanel.svelte index 32150ef921..977d0ff0a9 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/LeftPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/LeftPanel.svelte @@ -1,12 +1,12 @@
- {#if $isActive("./:componentId")} + {#if $selectedScreen} {/if}
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte index 0ecc9b76bf..b4a97fbf09 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenList/index.svelte @@ -11,6 +11,7 @@ import DropdownMenu from "./DropdownMenu.svelte" import NewScreen from "components/design/NewScreen/index.svelte" import { onMount, tick } from "svelte" + import { beforeUrlChange } from "@roxi/routify" let newScreen = false let search = false @@ -25,6 +26,14 @@ $: filteredScreens = getFilteredScreens($sortedScreens, searchValue) + // Close new screen when URL changes + $beforeUrlChange(() => { + if (newScreen) { + newScreen = false + } + return true + }) + const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)) const openSearch = async () => { @@ -176,7 +185,12 @@
- (newScreen = false)} /> + { + console.log("close") + newScreen = false + }} + />
diff --git a/packages/builder/src/components/design/RightPanel.svelte b/packages/builder/src/components/design/RightPanel.svelte deleted file mode 100644 index f9075600f9..0000000000 --- a/packages/builder/src/components/design/RightPanel.svelte +++ /dev/null @@ -1,112 +0,0 @@ - - -
-
-
- -
- {title} -
-
- {#each Object.entries(panes) as [id, pane]} -
- -
- {/each} -
-
- - -
- - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/theme/AppThemeSelect.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/AppThemeSelect.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/theme/AppThemeSelect.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/AppThemeSelect.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/theme/ButtonRoundnessSelect.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ButtonRoundnessSelect.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/theme/ButtonRoundnessSelect.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ButtonRoundnessSelect.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte similarity index 78% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPane.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte index e6200272be..a08ded8eee 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPane.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte @@ -1,10 +1,8 @@ - - - {#if $selectedScreen.layoutId} - - This screen uses a custom layout, which is deprecated - - {/if} - {#each screenSettings as setting (setting.key)} - setScreenSetting(setting, val)} - props={{ ...setting.props, error: errors[setting.key] }} - {bindings} - /> - {/each} - - +{#if $selectedScreen.layoutId} + + This screen uses a custom layout, which is deprecated + +{/if} +{#each screenSettings as setting (setting.key)} + setScreenSetting(setting, val)} + props={{ ...setting.props, error: errors[setting.key] }} + {bindings} + /> +{/each} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePane.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePane.svelte deleted file mode 100644 index 20d5054648..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePane.svelte +++ /dev/null @@ -1,98 +0,0 @@ - - - -
-
- - CHANGES WILL APPLY TO ALL SCREENS -
- - Your theme is configured for all the screens within your app. - -
- - - - - - - update("buttonBorderRadius", e.detail)} - /> - - update("primaryColor", val)} - props={{ - spectrumTheme: $store.theme, - }} - /> - update("primaryColorHover", val)} - props={{ - spectrumTheme: $store.theme, - }} - /> - -
- - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePanel.svelte new file mode 100644 index 0000000000..f3f2e63cce --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePanel.svelte @@ -0,0 +1,93 @@ + + +
+
+ + CHANGES WILL APPLY TO ALL SCREENS +
+ + Your theme is configured for all the screens within your app. + +
+ + + + + + + update("buttonBorderRadius", e.detail)} + /> + + update("primaryColor", val)} + props={{ + spectrumTheme: $store.theme, + }} + /> + update("primaryColorHover", val)} + props={{ + spectrumTheme: $store.theme, + }} + /> + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte index 554527ca4a..d9c98bda66 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte @@ -1,15 +1,51 @@ - - - - +
+
+ {#each tabs as tab} + { + activeTab = tab + }} + > + {capitalise(tab)} + + {/each} +
+
+ + {#if activeTab === "theme"} + + {:else} + + {/if} + + + + From 07e49f44366ff9e14b6794a58649b0b89b43f582 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 23 Aug 2023 16:46:32 +0100 Subject: [PATCH 172/183] Standardise info boxes between theme and navigation --- .../_components/Navigation/index.svelte | 22 ++++--------- .../_components/Screen/ThemePanel.svelte | 33 +++++-------------- .../_components/Screen/index.svelte | 4 +-- 3 files changed, 17 insertions(+), 42 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/index.svelte index 97622098cd..383026c4f8 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/index.svelte @@ -64,10 +64,8 @@ Customize
-
- - These settings apply to all screens -
+ + These settings apply to all screens