diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 88f7c7b542..f1e1642e22 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -66,11 +66,12 @@ "@spectrum-css/radio": "^3.0.2", "@spectrum-css/search": "^3.0.2", "@spectrum-css/sidenav": "^3.0.2", + "@spectrum-css/slider": "3.0.1", "@spectrum-css/statuslight": "^3.0.2", "@spectrum-css/stepper": "^3.0.3", "@spectrum-css/switch": "^1.0.2", "@spectrum-css/table": "^3.0.1", - "@spectrum-css/tabs": "^3.0.1", + "@spectrum-css/tabs": "^3.2.12", "@spectrum-css/tags": "^3.0.2", "@spectrum-css/textfield": "^3.0.1", "@spectrum-css/toast": "^3.0.1", diff --git a/packages/bbui/src/ActionButton/ActionButton.svelte b/packages/bbui/src/ActionButton/ActionButton.svelte index 2d23120046..53ba6c7e51 100644 --- a/packages/bbui/src/ActionButton/ActionButton.svelte +++ b/packages/bbui/src/ActionButton/ActionButton.svelte @@ -82,6 +82,12 @@ .active svg { color: var(--spectrum-global-color-blue-600); } + :global([dir="ltr"] .spectrum-ActionButton .spectrum-Icon) { + margin-left: 0; + } + .is-selected:not(.spectrum-ActionButton--emphasized) { + background: var(--spectrum-global-color-gray-300); + } .noPadding { padding: 0; min-width: 0; diff --git a/packages/bbui/src/Banner/Banner.svelte b/packages/bbui/src/Banner/Banner.svelte index f41fb5f803..3810021a61 100644 --- a/packages/bbui/src/Banner/Banner.svelte +++ b/packages/bbui/src/Banner/Banner.svelte @@ -8,6 +8,7 @@ export let size = "S" export let extraButtonText export let extraButtonAction + export let showCloseButton = true let show = true @@ -39,22 +40,24 @@ {/if} -
- -
+ {#if showCloseButton} +
+ +
+ {/if} {/if} @@ -63,4 +66,7 @@ pointer-events: all; width: 100%; } + .spectrum-Button { + border: 1px solid rgba(255, 255, 255, 0.2); + } diff --git a/packages/bbui/src/Divider/Divider.svelte b/packages/bbui/src/Divider/Divider.svelte index 2b4de9cfb0..e4f0f2fb61 100644 --- a/packages/bbui/src/Divider/Divider.svelte +++ b/packages/bbui/src/Divider/Divider.svelte @@ -16,6 +16,9 @@ /> diff --git a/packages/bbui/src/Form/Core/index.js b/packages/bbui/src/Form/Core/index.js index 96d81855e4..7c81cfd70b 100644 --- a/packages/bbui/src/Form/Core/index.js +++ b/packages/bbui/src/Form/Core/index.js @@ -12,3 +12,4 @@ export { default as CoreDatePicker } from "./DatePicker.svelte" export { default as CoreDropzone } from "./Dropzone.svelte" export { default as CoreStepper } from "./Stepper.svelte" export { default as CoreRichTextField } from "./RichTextField.svelte" +export { default as CoreSlider } from "./Slider.svelte" diff --git a/packages/bbui/src/Form/Search.svelte b/packages/bbui/src/Form/Search.svelte index 25dd98306b..74ffeeb22a 100644 --- a/packages/bbui/src/Form/Search.svelte +++ b/packages/bbui/src/Form/Search.svelte @@ -10,6 +10,7 @@ export let disabled = false export let updateOnChange = true export let quiet = false + export let inputRef const dispatch = createEventDispatcher() const onChange = e => { @@ -25,6 +26,7 @@ {value} {placeholder} {quiet} + bind:inputRef on:change={onChange} on:click on:input diff --git a/packages/bbui/src/Form/Select.svelte b/packages/bbui/src/Form/Select.svelte index 0df27e2ff0..1b68746c5e 100644 --- a/packages/bbui/src/Form/Select.svelte +++ b/packages/bbui/src/Form/Select.svelte @@ -14,6 +14,7 @@ export let getOptionLabel = option => extractProperty(option, "label") export let getOptionValue = option => extractProperty(option, "value") export let getOptionIcon = option => option?.icon + export let getOptionColour = option => option?.colour export let quiet = false export let autoWidth = false export let sort = false @@ -47,6 +48,7 @@ {getOptionLabel} {getOptionValue} {getOptionIcon} + {getOptionColour} on:change={onChange} on:click /> diff --git a/packages/bbui/src/Form/Slider.svelte b/packages/bbui/src/Form/Slider.svelte new file mode 100644 index 0000000000..34b2251b35 --- /dev/null +++ b/packages/bbui/src/Form/Slider.svelte @@ -0,0 +1,24 @@ + + + + + diff --git a/packages/bbui/src/Icon/Icon.svelte b/packages/bbui/src/Icon/Icon.svelte index eee1d7fbae..9c99178fdb 100644 --- a/packages/bbui/src/Icon/Icon.svelte +++ b/packages/bbui/src/Icon/Icon.svelte @@ -47,7 +47,7 @@ {#if tooltip && showTooltip}
- +
{/if} diff --git a/packages/bbui/src/IconSideNav/IconSideNav.svelte b/packages/bbui/src/IconSideNav/IconSideNav.svelte new file mode 100644 index 0000000000..e8144402e4 --- /dev/null +++ b/packages/bbui/src/IconSideNav/IconSideNav.svelte @@ -0,0 +1,14 @@ +
+ +
+ + diff --git a/packages/bbui/src/IconSideNav/IconSideNavItem.svelte b/packages/bbui/src/IconSideNav/IconSideNavItem.svelte new file mode 100644 index 0000000000..46625c9707 --- /dev/null +++ b/packages/bbui/src/IconSideNav/IconSideNavItem.svelte @@ -0,0 +1,56 @@ + + +
(showTooltip = true)} + on:focus={() => (showTooltip = true)} + on:mouseleave={() => (showTooltip = false)} + on:click +> + + {#if tooltip && showTooltip} +
+ +
+ {/if} +
+ + diff --git a/packages/bbui/src/Notification/NotificationDisplay.svelte b/packages/bbui/src/Notification/NotificationDisplay.svelte index 0b846f06ce..0f7e93eb23 100644 --- a/packages/bbui/src/Notification/NotificationDisplay.svelte +++ b/packages/bbui/src/Notification/NotificationDisplay.svelte @@ -9,7 +9,7 @@
{#each $notifications as { type, icon, message, id, dismissable, action, wide } (id)} -
+
.notifications { position: fixed; - top: 20px; + bottom: 40px; left: 0; right: 0; margin: 0 auto; diff --git a/packages/bbui/src/StatusLight/StatusLight.svelte b/packages/bbui/src/StatusLight/StatusLight.svelte index f56fee0c2a..a0c72443a6 100644 --- a/packages/bbui/src/StatusLight/StatusLight.svelte +++ b/packages/bbui/src/StatusLight/StatusLight.svelte @@ -17,10 +17,13 @@ export let negative = false export let disabled = false export let active = false + export let color = null
+ + diff --git a/packages/bbui/src/Tabs/Tab.svelte b/packages/bbui/src/Tabs/Tab.svelte index 04791619dc..c25be7dbc9 100644 --- a/packages/bbui/src/Tabs/Tab.svelte +++ b/packages/bbui/src/Tabs/Tab.svelte @@ -79,4 +79,10 @@ .emphasized { color: var(--spectrum-global-color-blue-600); } + .spectrum-Tabs-item { + color: var(--spectrum-global-color-gray-600); + } + .spectrum-Tabs-item.is-selected { + color: var(--spectrum-global-color-gray-900); + } diff --git a/packages/bbui/src/Tabs/Tabs.svelte b/packages/bbui/src/Tabs/Tabs.svelte index 579c61e28d..74edc9cd02 100644 --- a/packages/bbui/src/Tabs/Tabs.svelte +++ b/packages/bbui/src/Tabs/Tabs.svelte @@ -10,8 +10,7 @@ export let noHorizPadding = false export let quiet = false export let emphasized = false - // overlay content from the tab bar onto tabs e.g. for a dropdown - export let onTop = false + export let size = "M" let thisSelected = undefined @@ -74,20 +73,18 @@
{#if $tab.info}
{/if}
@@ -98,26 +95,26 @@ /> diff --git a/packages/bbui/src/index.js b/packages/bbui/src/index.js index 2b16f32b84..7d5baad474 100644 --- a/packages/bbui/src/index.js +++ b/packages/bbui/src/index.js @@ -64,6 +64,9 @@ export { default as BannerDisplay } from "./Banner/BannerDisplay.svelte" export { default as MarkdownEditor } from "./Markdown/MarkdownEditor.svelte" export { default as MarkdownViewer } from "./Markdown/MarkdownViewer.svelte" export { default as RichTextField } from "./Form/RichTextField.svelte" +export { default as IconSideNav } from "./IconSideNav/IconSideNav.svelte" +export { default as IconSideNavItem } from "./IconSideNav/IconSideNavItem.svelte" +export { default as Slider } from "./Form/Slider.svelte" // Renderers export { default as BoldRenderer } from "./Table/BoldRenderer.svelte" diff --git a/packages/bbui/yarn.lock b/packages/bbui/yarn.lock index 0bff3e86d9..d301afea53 100644 --- a/packages/bbui/yarn.lock +++ b/packages/bbui/yarn.lock @@ -206,6 +206,11 @@ resolved "https://registry.yarnpkg.com/@spectrum-css/sidenav/-/sidenav-3.0.2.tgz#9d70f408d588ee79c69857751010333671f32713" integrity sha512-YpIdH/F0jEICYmoduGrnkTmxwJq1kfKxEp0wOs+ZkQOsvKMv1an7nyhsfOKCQqcGNfYzJ9mJAk7/u5+vsxHa8g== +"@spectrum-css/slider@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@spectrum-css/slider/-/slider-3.0.1.tgz#5281e6f47eb5a4fd3d1816c138bf66d01d7f2e49" + integrity sha512-DI2dtMRnQuDM1miVzl3SGyR1khUEKnwdXfO5EHDFwkC3yav43F5QogkfjmjFmWWobMVovdJlAuiaaJ/IHejD0Q== + "@spectrum-css/statuslight@^3.0.2": version "3.0.2" resolved "https://registry.yarnpkg.com/@spectrum-css/statuslight/-/statuslight-3.0.2.tgz#dc54b6cd113413dcdb909c486b5d7bae60db65c5" @@ -226,10 +231,10 @@ resolved "https://registry.yarnpkg.com/@spectrum-css/table/-/table-3.0.2.tgz#c666743d569fef81ddc8810fac8cda53b315f8d7" integrity sha512-nt/QNC7NmUank0wozd4FySEX1UIYXuvuOKDyN1II3sxfwFSpJfp/Df9KVMhrYs4EsmB4XMGcoxp8ND/CrvH3ow== -"@spectrum-css/tabs@^3.0.1": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@spectrum-css/tabs/-/tabs-3.0.2.tgz#822316672e7b0dfba66faa988e638ddae18c700e" - integrity sha512-4RNcmwf0wxLpB7M54H02owlj0mKE8neL1+lytQpxOOhlwTO5zdsD82zjvx9tIc8tRnRKuhCCCwTuBxHYstnBmw== +"@spectrum-css/tabs@^3.2.12": + version "3.2.12" + resolved "https://registry.yarnpkg.com/@spectrum-css/tabs/-/tabs-3.2.12.tgz#9b08f23d5aa881b3441af7757800c7173e5685ff" + integrity sha512-rPFUW9SSW4+3/UJ3UrtY2/l3sQvlqB1fqxHLPDjgykvbfrnMejcCTNV4ZrFNHXpE/6+kGnk+yVViSPtWGwJzkA== "@spectrum-css/tags@^3.0.2": version "3.0.2" diff --git a/packages/builder/package.json b/packages/builder/package.json index 5b0e934d6c..8d505ff159 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -95,7 +95,7 @@ "@babel/preset-env": "^7.13.12", "@babel/runtime": "^7.13.10", "@rollup/plugin-replace": "^2.4.2", - "@roxi/routify": "2.18.0", + "@roxi/routify": "2.18.5", "@sveltejs/vite-plugin-svelte": "1.0.0-next.19", "@testing-library/jest-dom": "^5.11.10", "@testing-library/svelte": "^3.0.0", @@ -113,7 +113,7 @@ "rollup": "^2.44.0", "rollup-plugin-copy": "^3.4.0", "start-server-and-test": "^1.12.1", - "svelte": "^3.38.2", + "svelte": "^3.48.0", "svelte-jester": "^1.3.2", "ts-node": "^10.4.0", "tsconfig-paths": "4.0.0", diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index 234f83d7cc..bebd06c6d7 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -20,7 +20,7 @@ import { } from "@budibase/string-templates" import { TableNames } from "../constants" import { JSONUtils } from "@budibase/frontend-core" -import ActionDefinitions from "components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/manifest.json" +import ActionDefinitions from "components/design/settings/controls/ButtonActionEditor/manifest.json" // Regex to match all instances of template strings const CAPTURE_VAR_INSIDE_TEMPLATE = /{{([^}]+)}}/g @@ -478,11 +478,17 @@ const getUrlBindings = asset => { } }) const safeURL = makePropSafe("url") - return params.map(param => ({ + const urlParamBindings = params.map(param => ({ type: "context", runtimeBinding: `${safeURL}.${makePropSafe(param)}`, readableBinding: `URL.${param}`, })) + const queryParamsBinding = { + type: "context", + runtimeBinding: makePropSafe("query"), + readableBinding: "Query params", + } + return urlParamBindings.concat([queryParamsBinding]) } const getRoleBindings = () => { @@ -782,6 +788,13 @@ export const getAllStateVariables = () => { }) }) + // Add on load settings from screens + get(store).screens.forEach(screen => { + if (screen.onLoad) { + eventSettings.push(screen.onLoad) + } + }) + // Extract all state keys from any "update state" actions in each setting let bindingSet = new Set() eventSettings.forEach(setting => { diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js index 619bdd94a1..28ef1f4376 100644 --- a/packages/builder/src/builderStore/index.js +++ b/packages/builder/src/builderStore/index.js @@ -1,65 +1,77 @@ import { getFrontendStore } from "./store/frontend" import { getAutomationStore } from "./store/automation" import { getThemeStore } from "./store/theme" -import { derived, writable } from "svelte/store" -import { FrontendTypes, LAYOUT_NAMES } from "../constants" +import { derived } from "svelte/store" +import { LAYOUT_NAMES } from "../constants" import { findComponent, findComponentPath } from "./componentUtils" +import { RoleUtils } from "@budibase/frontend-core" export const store = getFrontendStore() export const automationStore = getAutomationStore() export const themeStore = getThemeStore() -export const currentAsset = derived(store, $store => { - const type = $store.currentFrontEndType - if (type === FrontendTypes.SCREEN) { - return $store.screens.find(screen => screen._id === $store.selectedScreenId) - } else if (type === FrontendTypes.LAYOUT) { - return $store.layouts.find(layout => layout._id === $store.selectedLayoutId) - } - return null +export const selectedScreen = derived(store, $store => { + return $store.screens.find(screen => screen._id === $store.selectedScreenId) +}) + +export const selectedLayout = derived(store, $store => { + return $store.layouts?.find(layout => layout._id === $store.selectedLayoutId) }) export const selectedComponent = derived( - [store, currentAsset], - ([$store, $currentAsset]) => { - if (!$currentAsset || !$store.selectedComponentId) { + [store, selectedScreen], + ([$store, $selectedScreen]) => { + if (!$selectedScreen || !$store.selectedComponentId) { return null } - return findComponent($currentAsset?.props, $store.selectedComponentId) + return findComponent($selectedScreen?.props, $store.selectedComponentId) } ) +export const sortedScreens = derived(store, $store => { + return $store.screens.slice().sort((a, b) => { + // Sort by role first + const roleA = RoleUtils.getRolePriority(a.routing.roleId) + const roleB = RoleUtils.getRolePriority(b.routing.roleId) + if (roleA !== roleB) { + return roleA > roleB ? -1 : 1 + } + // Then put home screens first + const homeA = !!a.routing.homeScreen + const homeB = !!b.routing.homeScreen + if (homeA !== homeB) { + return homeA ? -1 : 1 + } + // Then sort alphabetically by each URL param + const aParams = a.routing.route.split("/") + const bParams = b.routing.route.split("/") + let minParams = Math.min(aParams.length, bParams.length) + for (let i = 0; i < minParams; i++) { + if (aParams[i] === bParams[i]) { + continue + } + return aParams[i] < bParams[i] ? -1 : 1 + } + // Then sort by the fewest amount of URL params + return aParams.length < bParams.length ? -1 : 1 + }) +}) + export const selectedComponentPath = derived( - [store, currentAsset], - ([$store, $currentAsset]) => { + [store, selectedScreen], + ([$store, $selectedScreen]) => { return findComponentPath( - $currentAsset?.props, + $selectedScreen?.props, $store.selectedComponentId ).map(component => component._id) } ) -export const currentAssetId = derived(store, $store => { - return $store.currentFrontEndType === FrontendTypes.SCREEN - ? $store.selectedScreenId - : $store.selectedLayoutId -}) - -export const currentAssetName = derived(currentAsset, $currentAsset => { - return $currentAsset?.name -}) - -// leave this as before for consistency -export const allScreens = derived(store, $store => { - return $store.screens -}) - export const mainLayout = derived(store, $store => { return $store.layouts?.find( layout => layout._id === LAYOUT_NAMES.MASTER.PRIVATE ) }) -export const selectedAccessRole = writable("BASIC") - -export const screenSearchString = writable(null) +// For compatibility +export const currentAsset = selectedScreen diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index ec810e5c31..16ae5ce215 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -1,12 +1,6 @@ import { get, writable } from "svelte/store" import { cloneDeep } from "lodash/fp" -import { - allScreens, - currentAsset, - mainLayout, - selectedComponent, - selectedAccessRole, -} from "builderStore" +import { currentAsset, mainLayout, selectedComponent } from "builderStore" import { datasources, integrations, @@ -15,7 +9,6 @@ import { tables, } from "stores/backend" import { API } from "api" -import { FrontendTypes } from "constants" import analytics, { Events } from "analytics" import { findComponentType, @@ -27,6 +20,7 @@ import { makeComponentUnique, } from "../componentUtils" import { Helpers } from "@budibase/bbui" +import { DefaultAppTheme, LAYOUT_NAMES } from "../../constants" const INITIAL_FRONTEND_STATE = { apps: [], @@ -47,10 +41,6 @@ const INITIAL_FRONTEND_STATE = { messagePassing: false, continueIfAction: false, }, - currentFrontEndType: "none", - selectedScreenId: "", - selectedLayoutId: "", - selectedComponentId: "", errors: [], hasAppPackage: false, libraries: null, @@ -61,6 +51,11 @@ const INITIAL_FRONTEND_STATE = { customTheme: {}, previewDevice: "desktop", highlightedSettingKey: null, + + // URL params + selectedScreenId: null, + selectedComponentId: null, + selectedLayoutId: null, } export const getFrontendStore = () => { @@ -100,6 +95,7 @@ export const getFrontendStore = () => { previousTopNavPath: {}, version: application.version, revertableVersion: application.revertableVersion, + navigation: application.navigation || {}, })) // Initialise backend stores @@ -108,6 +104,35 @@ export const getFrontendStore = () => { await integrations.init() await queries.init() await tables.init() + + // Add navigation settings to old apps + if (!application.navigation) { + const layout = layouts.find(x => x._id === LAYOUT_NAMES.MASTER.PRIVATE) + const customTheme = application.customTheme + let navigationSettings = { + navigation: "Top", + title: application.name, + navWidth: "Large", + navBackground: + customTheme?.navBackground || DefaultAppTheme.navBackground, + navTextColor: + customTheme?.navTextColor || DefaultAppTheme.navTextColor, + } + if (layout) { + navigationSettings.hideLogo = layout.props.hideLogo + navigationSettings.hideTitle = layout.props.hideTitle + navigationSettings.title = layout.props.title || application.name + navigationSettings.logoUrl = layout.props.logoUrl + navigationSettings.links = layout.props.links + navigationSettings.navigation = layout.props.navigation || "Top" + navigationSettings.sticky = layout.props.sticky + navigationSettings.navWidth = layout.props.width || "Large" + if (navigationSettings.navigation === "None") { + navigationSettings.navigation = "Top" + } + } + await store.actions.navigation.save(navigationSettings) + } }, theme: { save: async theme => { @@ -135,6 +160,19 @@ export const getFrontendStore = () => { }) }, }, + navigation: { + save: async navigation => { + const appId = get(store).appId + await API.saveAppMetadata({ + appId, + metadata: { navigation }, + }) + store.update(state => { + state.navigation = navigation + return state + }) + }, + }, routing: { fetch: async () => { const response = await API.fetchAppRoutes() @@ -147,18 +185,12 @@ export const getFrontendStore = () => { screens: { select: screenId => { store.update(state => { - let screens = get(allScreens) + let screens = state.screens let screen = screens.find(screen => screen._id === screenId) || screens[0] if (!screen) return state - // Update role to the screen's role setting so that it will always - // be visible - selectedAccessRole.set(screen.routing.roleId) - - state.currentFrontEndType = FrontendTypes.SCREEN state.selectedScreenId = screen._id - state.currentView = "detail" state.selectedComponentId = screen.props?._id return state }) @@ -221,16 +253,44 @@ export const getFrontendStore = () => { // Refresh routes await store.actions.routing.fetch() }, + updateHomeScreen: async (screen, makeHomeScreen = true) => { + let promises = [] + + // Find any existing home screen for this role so we can remove it, + // if we are setting this to be the new home screen + if (makeHomeScreen) { + const roleId = screen.routing.roleId + let existingHomeScreen = get(store).screens.find(s => { + return ( + s.routing.roleId === roleId && + s.routing.homeScreen && + s._id !== screen._id + ) + }) + if (existingHomeScreen) { + existingHomeScreen.routing.homeScreen = false + promises.push(store.actions.screens.save(existingHomeScreen)) + } + } + + // Update the passed in screen + screen.routing.homeScreen = makeHomeScreen + promises.push(store.actions.screens.save(screen)) + return await Promise.all(promises) + }, + removeCustomLayout: async screen => { + // Pull relevant settings from old layout, if required + const layout = get(store).layouts.find(x => x._id === screen.layoutId) + screen.layoutId = null + screen.showNavigation = layout?.props.navigation !== "None" + screen.width = layout?.props.width || "Large" + await store.actions.screens.save(screen) + }, }, preview: { saveSelected: async () => { - const state = get(store) const selectedAsset = get(currentAsset) - if (state.currentFrontEndType !== FrontendTypes.LAYOUT) { - return await store.actions.screens.save(selectedAsset) - } else { - return await store.actions.layouts.save(selectedAsset) - } + return await store.actions.screens.save(selectedAsset) }, setDevice: device => { store.update(state => { @@ -245,8 +305,6 @@ export const getFrontendStore = () => { const layout = store.actions.layouts.find(layoutId) || get(store).layouts[0] if (!layout) return - state.currentFrontEndType = FrontendTypes.LAYOUT - state.currentView = "detail" state.selectedLayoutId = layout._id state.selectedComponentId = layout.props?._id return state @@ -297,32 +355,6 @@ export const getFrontendStore = () => { }, }, components: { - select: component => { - const asset = get(currentAsset) - if (!asset || !component) { - return - } - - // If this is the root component, select the asset instead - const parent = findComponentParent(asset.props, component._id) - if (parent == null) { - const state = get(store) - const isLayout = state.currentFrontEndType === FrontendTypes.LAYOUT - if (isLayout) { - store.actions.layouts.select(asset._id) - } else { - store.actions.screens.select(asset._id) - } - return - } - - // Otherwise select the component - store.update(state => { - state.selectedComponentId = component._id - state.currentView = "component" - return state - }) - }, getDefinition: componentName => { if (!componentName) { return null @@ -418,7 +450,6 @@ export const getFrontendStore = () => { // Save components and update UI await store.actions.preview.saveSelected() store.update(state => { - state.currentView = "component" state.selectedComponentId = componentInstance._id return state }) @@ -461,11 +492,14 @@ export const getFrontendStore = () => { parent._children = parent._children.filter( child => child._id !== component._id ) - store.actions.components.select(parent) + store.update(state => { + state.selectedComponentId = parent._id + return state + }) } await store.actions.preview.saveSelected() }, - copy: (component, cut = false) => { + copy: (component, cut = false, selectParent = true) => { const selectedAsset = get(currentAsset) if (!selectedAsset) { return null @@ -485,7 +519,12 @@ export const getFrontendStore = () => { parent._children = parent._children.filter( child => child._id !== component._id ) - store.actions.components.select(parent) + if (selectParent) { + store.update(state => { + state.selectedComponentId = parent._id + return state + }) + } } } }, @@ -536,7 +575,7 @@ export const getFrontendStore = () => { // Save and select the new component promises.push(store.actions.preview.saveSelected()) - store.actions.components.select(componentToPaste) + state.selectedComponentId = componentToPaste._id return state }) await Promise.all(promises) @@ -578,35 +617,38 @@ export const getFrontendStore = () => { }, links: { save: async (url, title) => { - const layout = get(mainLayout) - if (!layout) { + const navigation = get(store).navigation + let links = [...navigation?.links] + + // Skip if we have an identical link + if (links.find(link => link.url === url && link.text === title)) { return } - // Add link setting to main layout - if (!layout.props.links) { - layout.props.links = [] - } - layout.props.links.push({ + links.push({ text: title, url, }) - - await store.actions.layouts.save(layout) + await store.actions.navigation.save({ + ...navigation, + links: [...links], + }) }, delete: async urls => { - const layout = get(mainLayout) - if (!layout?.props.links?.length) { + const navigation = get(store).navigation + let links = navigation?.links + if (!links?.length) { return } // Filter out the URLs to delete urls = Array.isArray(urls) ? urls : [urls] - layout.props.links = layout.props.links.filter( - link => !urls.includes(link.url) - ) + links = links.filter(link => !urls.includes(link.url)) - await store.actions.layouts.save(layout) + await store.actions.navigation.save({ + ...navigation, + links, + }) }, }, settings: { diff --git a/packages/builder/src/builderStore/store/screenTemplates/utils/Screen.js b/packages/builder/src/builderStore/store/screenTemplates/utils/Screen.js index 272f627163..6fc79e53b0 100644 --- a/packages/builder/src/builderStore/store/screenTemplates/utils/Screen.js +++ b/packages/builder/src/builderStore/store/screenTemplates/utils/Screen.js @@ -5,7 +5,8 @@ export class Screen extends BaseStructure { constructor() { super(true) this._json = { - layoutId: "layout_private_master", + showNavigation: true, + width: "Large", props: { _id: Helpers.uuid(), _component: "@budibase/standard-components/container", @@ -26,6 +27,7 @@ export class Screen extends BaseStructure { routing: { route: "", roleId: "BASIC", + homeScreen: false, }, name: "screen-id", } diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte index 7b189ad109..c149b6a00e 100644 --- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte +++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte @@ -26,7 +26,7 @@ import CronBuilder from "./CronBuilder.svelte" import Editor from "components/integration/QueryEditor.svelte" import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte" - import FilterDrawer from "components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte" + import FilterDrawer from "components/design/settings/controls/FilterEditor/FilterDrawer.svelte" import { LuceneUtils } from "@budibase/frontend-core" import { getSchemaForTable } from "builderStore/dataBinding" import { Utils } from "@budibase/frontend-core" diff --git a/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte index cf9e4b1358..633c7e1ad1 100644 --- a/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte +++ b/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte @@ -1,7 +1,7 @@ + + + + + Beta Builder + + Your account has been given access to the budibase beta program. We + would love to hear what you think and get your feedback and suggestions + on the new Design UI. + + + + + + + + diff --git a/packages/builder/src/components/common/NavItem.svelte b/packages/builder/src/components/common/NavItem.svelte index 364ae50f64..4cb67dc9c4 100644 --- a/packages/builder/src/components/common/NavItem.svelte +++ b/packages/builder/src/components/common/NavItem.svelte @@ -1,5 +1,5 @@ - + - + - import { notifications, Select } from "@budibase/bbui" - import { store } from "builderStore" - import { get } from "svelte/store" - - const themeOptions = [ - { - label: "Lightest", - value: "spectrum--lightest", - }, - { - label: "Light", - value: "spectrum--light", - }, - { - label: "Dark", - value: "spectrum--dark", - }, - { - label: "Darkest", - value: "spectrum--darkest", - }, - ] - - const onChangeTheme = async theme => { - try { - await store.actions.theme.save(theme) - await store.actions.customTheme.save({ - ...get(store).customTheme, - navBackground: - theme === "spectrum--light" - ? "var(--spectrum-global-color-gray-50)" - : "var(--spectrum-global-color-gray-100)", - }) - } catch (error) { - notifications.error("Error updating theme") - } - } - - -
- -
-
-
- - -
-
- - -
-
- - -
-
- - -
- -
- -
- - - - diff --git a/packages/builder/src/components/design/AppPreview/index.js b/packages/builder/src/components/design/AppPreview/index.js deleted file mode 100644 index 61030700ec..0000000000 --- a/packages/builder/src/components/design/AppPreview/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./CurrentItemPreview.svelte" diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte deleted file mode 100644 index 6b78bc40c1..0000000000 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte +++ /dev/null @@ -1,157 +0,0 @@ - - -
    - {#each components || [] as component, index (component._id)} -
  • selectComponent(component)}> - {#if $dragDropStore?.targetComponent === component && $dragDropStore.dropPosition === DropPosition.ABOVE} -
    - {/if} - - toggleNodeOpen(component._id)} - on:drop={onDrop} - text={getComponentText(component)} - withArrow - indentLevel={level + 1} - selected={$store.selectedComponentId === component._id} - opened={isOpen(component, $selectedComponentPath, closedNodes)} - > - - - - {#if isOpen(component, $selectedComponentPath, closedNodes)} - - {/if} - - {#if $dragDropStore?.targetComponent === component && ($dragDropStore.dropPosition === DropPosition.INSIDE || $dragDropStore.dropPosition === DropPosition.BELOW)} -
    - {/if} -
  • - {/each} -
- - diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/LayoutDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/LayoutDropdownMenu.svelte deleted file mode 100644 index e54beb9e41..0000000000 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/LayoutDropdownMenu.svelte +++ /dev/null @@ -1,74 +0,0 @@ - - - -
- -
- Edit - Delete -
- - - - - - - - - - diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathDropdownMenu.svelte deleted file mode 100644 index 6de656b6b5..0000000000 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathDropdownMenu.svelte +++ /dev/null @@ -1,82 +0,0 @@ - - - -
- -
- - Delete all screens - -
- - - -
- Are you sure you want to delete all screens under the {path} route? -
-
The following screens will be deleted:
-
- {#each screens as screen} -
{screen.route}
- {/each} -
-
-
- - diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte deleted file mode 100644 index 3d6984cf14..0000000000 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte +++ /dev/null @@ -1,106 +0,0 @@ - - -{#if !noSearchMatch} - - - - - {#if routeOpened} - {#each filteredScreens as screen (screen.id)} - changeScreen(screen.id)} - > - - - {#if selectedScreen?._id === screen.id} - - {/if} - {/each} - {/if} -{/if} diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/dragDropStore.js b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/dragDropStore.js deleted file mode 100644 index d965a2456d..0000000000 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/dragDropStore.js +++ /dev/null @@ -1,104 +0,0 @@ -import { writable, get } from "svelte/store" -import { store as frontendStore } from "builderStore" -import { findComponentPath } from "builderStore/componentUtils" - -export const DropEffect = { - MOVE: "move", - COPY: "copy", -} - -export const DropPosition = { - ABOVE: "above", - BELOW: "below", - INSIDE: "inside", -} - -export default function () { - const store = writable({}) - - store.actions = { - dragstart: component => { - store.update(state => { - state.dragged = component - return state - }) - }, - dragover: ({ - component, - index, - canHaveChildrenButIsEmpty, - mousePosition, - }) => { - store.update(state => { - state.targetComponent = component - // only allow dropping inside when container is empty - // if container has children, drag over them - - if (canHaveChildrenButIsEmpty && index === 0) { - // hovered above center of target - if (mousePosition < 0.4) { - state.dropPosition = DropPosition.ABOVE - } - - // hovered around bottom of target - if (mousePosition > 0.8) { - state.dropPosition = DropPosition.BELOW - } - - // hovered in center of target - if (mousePosition > 0.4 && mousePosition < 0.8) { - state.dropPosition = DropPosition.INSIDE - } - return state - } - - // bottom half - if (mousePosition > 0.5) { - state.dropPosition = DropPosition.BELOW - } else { - state.dropPosition = canHaveChildrenButIsEmpty - ? DropPosition.INSIDE - : DropPosition.ABOVE - } - - return state - }) - }, - reset: () => { - store.update(state => { - state.dropPosition = "" - state.targetComponent = null - state.dragged = null - return state - }) - }, - drop: async () => { - const state = get(store) - - // Stop if the target and source are the same - if (state.targetComponent === state.dragged) { - return - } - // Stop if the target or source are null - if (!state.targetComponent || !state.dragged) { - return - } - // Stop if the target is a child of source - const path = findComponentPath(state.dragged, state.targetComponent._id) - const ids = path.map(component => component._id) - if (ids.includes(state.targetComponent._id)) { - return - } - - // Cut and paste the component - frontendStore.actions.components.copy(state.dragged, true) - await frontendStore.actions.components.paste( - state.targetComponent, - state.dropPosition - ) - store.actions.reset() - }, - } - - return store -} diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/index.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/index.svelte deleted file mode 100644 index ed064f8307..0000000000 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/index.svelte +++ /dev/null @@ -1,83 +0,0 @@ - - -
- {#each paths as path, idx (path)} - 0} {path} route={routes[path]} /> - {/each} - {#if !paths.length} -
- There aren't any screens configured with this access role. -
- {/if} -
- - diff --git a/packages/builder/src/components/design/NavigationPanel/FrontendNavigatePane.svelte b/packages/builder/src/components/design/NavigationPanel/FrontendNavigatePane.svelte deleted file mode 100644 index 0611d4fc71..0000000000 --- a/packages/builder/src/components/design/NavigationPanel/FrontendNavigatePane.svelte +++ /dev/null @@ -1,229 +0,0 @@ - - -
- - -
- - - diff --git a/packages/builder/src/components/design/Panel.svelte b/packages/builder/src/components/design/Panel.svelte new file mode 100644 index 0000000000..c1eab881d5 --- /dev/null +++ b/packages/builder/src/components/design/Panel.svelte @@ -0,0 +1,112 @@ + + +
+
+ {#if showBackButton} + + {/if} + {#if icon} + + {/if} +
+ {title || ""} +
+ {#if showExpandIcon} + (wide = !wide)} + /> + {/if} + {#if showAddButton} +
+ +
+ {/if} +
+
+ +
+
+ + diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertiesPanel.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertiesPanel.svelte deleted file mode 100644 index df91a87456..0000000000 --- a/packages/builder/src/components/design/PropertiesPanel/PropertiesPanel.svelte +++ /dev/null @@ -1,63 +0,0 @@ - - - - -
- {#key componentInstance?._id} - - - - - - {/key} -
-
-
- - diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/NavigationEditor/NavigationEditor.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/NavigationEditor/NavigationEditor.svelte deleted file mode 100644 index 33a82d1886..0000000000 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/NavigationEditor/NavigationEditor.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - -Configure links - - - Configure the links in your navigation bar. - - - - diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js deleted file mode 100644 index 23a0a312bc..0000000000 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js +++ /dev/null @@ -1,68 +0,0 @@ -import { Checkbox, Select, Stepper } from "@budibase/bbui" -import DataSourceSelect from "./DataSourceSelect.svelte" -import S3DataSourceSelect from "./S3DataSourceSelect.svelte" -import DataProviderSelect from "./DataProviderSelect.svelte" -import ButtonActionEditor from "./ButtonActionEditor/ButtonActionEditor.svelte" -import TableSelect from "./TableSelect.svelte" -import ColorPicker from "./ColorPicker.svelte" -import { IconSelect } from "./IconSelect" -import FieldSelect from "./FieldSelect.svelte" -import MultiFieldSelect from "./MultiFieldSelect.svelte" -import SearchFieldSelect from "./SearchFieldSelect.svelte" -import SchemaSelect from "./SchemaSelect.svelte" -import SectionSelect from "./SectionSelect.svelte" -import NavigationEditor from "./NavigationEditor/NavigationEditor.svelte" -import FilterEditor from "./FilterEditor/FilterEditor.svelte" -import URLSelect from "./URLSelect.svelte" -import OptionsEditor from "./OptionsEditor/OptionsEditor.svelte" -import FormFieldSelect from "./FormFieldSelect.svelte" -import ValidationEditor from "./ValidationEditor/ValidationEditor.svelte" -import DrawerBindableCombobox from "components/common/bindings/DrawerBindableCombobox.svelte" -import ColumnEditor from "./ColumnEditor/ColumnEditor.svelte" - -const componentMap = { - text: DrawerBindableCombobox, - select: Select, - dataSource: DataSourceSelect, - "dataSource/s3": S3DataSourceSelect, - dataProvider: DataProviderSelect, - boolean: Checkbox, - number: Stepper, - event: ButtonActionEditor, - table: TableSelect, - color: ColorPicker, - icon: IconSelect, - field: FieldSelect, - multifield: MultiFieldSelect, - searchfield: SearchFieldSelect, - options: OptionsEditor, - schema: SchemaSelect, - section: SectionSelect, - navigation: NavigationEditor, - filter: FilterEditor, - url: URLSelect, - columns: ColumnEditor, - "field/string": FormFieldSelect, - "field/number": FormFieldSelect, - "field/options": FormFieldSelect, - "field/boolean": FormFieldSelect, - "field/longform": FormFieldSelect, - "field/datetime": FormFieldSelect, - "field/attachment": FormFieldSelect, - "field/link": FormFieldSelect, - "field/array": FormFieldSelect, - "field/json": FormFieldSelect, - // Some validation types are the same as others, so not all types are - // explicitly listed here. e.g. options uses string validation - "validation/string": ValidationEditor, - "validation/array": ValidationEditor, - "validation/number": ValidationEditor, - "validation/boolean": ValidationEditor, - "validation/datetime": ValidationEditor, - "validation/attachment": ValidationEditor, - "validation/link": ValidationEditor, -} - -export const getComponentForSettingType = type => { - return componentMap[type] -} diff --git a/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte b/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte deleted file mode 100644 index e0b46d8ed7..0000000000 --- a/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte +++ /dev/null @@ -1,125 +0,0 @@ - - -{#if $store.currentView !== "component" && $currentAsset && $store.currentFrontEndType === FrontendTypes.SCREEN} - - {#each screenSettings as def (`${componentInstance._id}-${def.key}`)} - setAssetProps(def.key, val, def.parser, def.validate)} - {bindings} - props={{ error: errors[def.key] }} - /> - {/each} - -{/if} diff --git a/packages/builder/src/components/design/settings/componentSettings.js b/packages/builder/src/components/design/settings/componentSettings.js new file mode 100644 index 0000000000..56ae3de490 --- /dev/null +++ b/packages/builder/src/components/design/settings/componentSettings.js @@ -0,0 +1,77 @@ +import { Checkbox, Select, Stepper } from "@budibase/bbui" +import DataSourceSelect from "./controls/DataSourceSelect.svelte" +import S3DataSourceSelect from "./controls/S3DataSourceSelect.svelte" +import DataProviderSelect from "./controls/DataProviderSelect.svelte" +import ButtonActionEditor from "./controls/ButtonActionEditor/ButtonActionEditor.svelte" +import TableSelect from "./controls/TableSelect.svelte" +import ColorPicker from "./controls/ColorPicker.svelte" +import { IconSelect } from "./controls/IconSelect" +import FieldSelect from "./controls/FieldSelect.svelte" +import MultiFieldSelect from "./controls/MultiFieldSelect.svelte" +import SearchFieldSelect from "./controls/SearchFieldSelect.svelte" +import SchemaSelect from "./controls/SchemaSelect.svelte" +import SectionSelect from "./controls/SectionSelect.svelte" +import FilterEditor from "./controls/FilterEditor/FilterEditor.svelte" +import URLSelect from "./controls/URLSelect.svelte" +import OptionsEditor from "./controls/OptionsEditor/OptionsEditor.svelte" +import FormFieldSelect from "./controls/FormFieldSelect.svelte" +import ValidationEditor from "./controls/ValidationEditor/ValidationEditor.svelte" +import DrawerBindableCombobox from "components/common/bindings/DrawerBindableCombobox.svelte" +import ColumnEditor from "./controls/ColumnEditor/ColumnEditor.svelte" +import BarButtonList from "./controls/BarButtonList.svelte" + +const componentMap = { + text: DrawerBindableCombobox, + select: Select, + dataSource: DataSourceSelect, + "dataSource/s3": S3DataSourceSelect, + dataProvider: DataProviderSelect, + boolean: Checkbox, + number: Stepper, + event: ButtonActionEditor, + table: TableSelect, + color: ColorPicker, + icon: IconSelect, + field: FieldSelect, + multifield: MultiFieldSelect, + searchfield: SearchFieldSelect, + options: OptionsEditor, + schema: SchemaSelect, + section: SectionSelect, + filter: FilterEditor, + url: URLSelect, + columns: ColumnEditor, + "field/string": FormFieldSelect, + "field/number": FormFieldSelect, + "field/options": FormFieldSelect, + "field/boolean": FormFieldSelect, + "field/longform": FormFieldSelect, + "field/datetime": FormFieldSelect, + "field/attachment": FormFieldSelect, + "field/link": FormFieldSelect, + "field/array": FormFieldSelect, + "field/json": FormFieldSelect, + // Some validation types are the same as others, so not all types are + // explicitly listed here. e.g. options uses string validation + "validation/string": ValidationEditor, + "validation/array": ValidationEditor, + "validation/number": ValidationEditor, + "validation/boolean": ValidationEditor, + "validation/datetime": ValidationEditor, + "validation/attachment": ValidationEditor, + "validation/link": ValidationEditor, +} + +export const getComponentForSetting = setting => { + const { type, showInBar, barStyle } = setting || {} + if (!type) { + return null + } + + // We can show a clone of the bar settings for certain select settings + if (showInBar && type === "select" && barStyle === "buttons") { + return BarButtonList + } + + return componentMap[type] +} diff --git a/packages/builder/src/components/design/settings/controls/BarButtonList.svelte b/packages/builder/src/components/design/settings/controls/BarButtonList.svelte new file mode 100644 index 0000000000..339edb1f74 --- /dev/null +++ b/packages/builder/src/components/design/settings/controls/BarButtonList.svelte @@ -0,0 +1,18 @@ + + + + {#each options as option} + onChange(option.value)} + selected={option.value === value} + /> + {/each} + diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionDrawer.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/ButtonActionDrawer.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionDrawer.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/ButtonActionDrawer.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionEditor.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/ButtonActionEditor.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionEditor.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/ButtonActionEditor.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ChangeFormStep.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ChangeFormStep.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ChangeFormStep.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ChangeFormStep.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ClearForm.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ClearForm.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ClearForm.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ClearForm.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/CloseScreenModal.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/CloseScreenModal.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/CloseScreenModal.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/CloseScreenModal.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ContinueIf.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ContinueIf.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ContinueIf.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ContinueIf.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/DeleteRow.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DeleteRow.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/DeleteRow.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DeleteRow.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/DuplicateRow.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DuplicateRow.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/DuplicateRow.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DuplicateRow.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ExecuteQuery.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ExecuteQuery.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ExecuteQuery.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ExecuteQuery.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ExportData.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ExportData.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ExportData.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ExportData.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/LogOut.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/LogOut.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/LogOut.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/LogOut.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/NavigateTo.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/NavigateTo.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/NavigateTo.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/NavigateTo.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/RefreshDataProvider.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/RefreshDataProvider.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/RefreshDataProvider.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/RefreshDataProvider.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/S3Upload.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/S3Upload.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/S3Upload.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/S3Upload.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/SaveFields.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveFields.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/SaveFields.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveFields.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/SaveRow.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveRow.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/SaveRow.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveRow.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/TriggerAutomation.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/TriggerAutomation.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/TriggerAutomation.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/TriggerAutomation.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/UpdateFieldValue.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/UpdateFieldValue.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/UpdateFieldValue.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/UpdateFieldValue.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/UpdateState.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/UpdateState.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/UpdateState.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/UpdateState.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ValidateForm.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ValidateForm.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ValidateForm.svelte rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ValidateForm.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/index.js b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/index.js similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/index.js rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/index.js diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/index.js b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/index.js similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/index.js rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/index.js diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/manifest.json b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/manifest.json rename to packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColorPicker.svelte b/packages/builder/src/components/design/settings/controls/ColorPicker.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColorPicker.svelte rename to packages/builder/src/components/design/settings/controls/ColorPicker.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColumnEditor/CellDrawer.svelte b/packages/builder/src/components/design/settings/controls/ColumnEditor/CellDrawer.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColumnEditor/CellDrawer.svelte rename to packages/builder/src/components/design/settings/controls/ColumnEditor/CellDrawer.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColumnEditor/CellEditor.svelte b/packages/builder/src/components/design/settings/controls/ColumnEditor/CellEditor.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColumnEditor/CellEditor.svelte rename to packages/builder/src/components/design/settings/controls/ColumnEditor/CellEditor.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColumnEditor/ColumnDrawer.svelte b/packages/builder/src/components/design/settings/controls/ColumnEditor/ColumnDrawer.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColumnEditor/ColumnDrawer.svelte rename to packages/builder/src/components/design/settings/controls/ColumnEditor/ColumnDrawer.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColumnEditor/ColumnEditor.svelte b/packages/builder/src/components/design/settings/controls/ColumnEditor/ColumnEditor.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColumnEditor/ColumnEditor.svelte rename to packages/builder/src/components/design/settings/controls/ColumnEditor/ColumnEditor.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte b/packages/builder/src/components/design/settings/controls/DataProviderSelect.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte rename to packages/builder/src/components/design/settings/controls/DataProviderSelect.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataSourceSelect.svelte b/packages/builder/src/components/design/settings/controls/DataSourceSelect.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataSourceSelect.svelte rename to packages/builder/src/components/design/settings/controls/DataSourceSelect.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FieldSelect.svelte b/packages/builder/src/components/design/settings/controls/FieldSelect.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/FieldSelect.svelte rename to packages/builder/src/components/design/settings/controls/FieldSelect.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte rename to packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterEditor.svelte b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterEditor.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterEditor.svelte rename to packages/builder/src/components/design/settings/controls/FilterEditor/FilterEditor.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/FlatButton.svelte b/packages/builder/src/components/design/settings/controls/FlatButtonGroup/FlatButton.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/FlatButton.svelte rename to packages/builder/src/components/design/settings/controls/FlatButtonGroup/FlatButton.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/FlatButtonGroup.svelte b/packages/builder/src/components/design/settings/controls/FlatButtonGroup/FlatButtonGroup.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/FlatButtonGroup.svelte rename to packages/builder/src/components/design/settings/controls/FlatButtonGroup/FlatButtonGroup.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/index.js b/packages/builder/src/components/design/settings/controls/FlatButtonGroup/index.js similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/index.js rename to packages/builder/src/components/design/settings/controls/FlatButtonGroup/index.js diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte b/packages/builder/src/components/design/settings/controls/FormFieldSelect.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte rename to packages/builder/src/components/design/settings/controls/FormFieldSelect.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/IconSelect.svelte b/packages/builder/src/components/design/settings/controls/IconSelect/IconSelect.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/IconSelect.svelte rename to packages/builder/src/components/design/settings/controls/IconSelect/IconSelect.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/icons.js b/packages/builder/src/components/design/settings/controls/IconSelect/icons.js similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/icons.js rename to packages/builder/src/components/design/settings/controls/IconSelect/icons.js diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/index.js b/packages/builder/src/components/design/settings/controls/IconSelect/index.js similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/index.js rename to packages/builder/src/components/design/settings/controls/IconSelect/index.js diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/LayoutSelect.svelte b/packages/builder/src/components/design/settings/controls/LayoutSelect.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/LayoutSelect.svelte rename to packages/builder/src/components/design/settings/controls/LayoutSelect.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/MultiFieldSelect.svelte b/packages/builder/src/components/design/settings/controls/MultiFieldSelect.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/MultiFieldSelect.svelte rename to packages/builder/src/components/design/settings/controls/MultiFieldSelect.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/OptionsEditor/OptionsDrawer.svelte b/packages/builder/src/components/design/settings/controls/OptionsEditor/OptionsDrawer.svelte similarity index 80% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/OptionsEditor/OptionsDrawer.svelte rename to packages/builder/src/components/design/settings/controls/OptionsEditor/OptionsDrawer.svelte index 340c1eb107..ba8e297189 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/OptionsEditor/OptionsDrawer.svelte +++ b/packages/builder/src/components/design/settings/controls/OptionsEditor/OptionsDrawer.svelte @@ -6,6 +6,7 @@ DrawerContent, Layout, Body, + Label, } from "@budibase/bbui" import { generate } from "shortid" @@ -35,19 +36,12 @@ {/if} {#if options?.length}
+ + +
{#each options as option (option.id)} - - + + import { Select } from "@budibase/bbui" import { roles } from "stores/backend" + import { RoleUtils } from "@budibase/frontend-core" export let value export let error + export let placeholder = null x.routing.route} + getOptionValue={x => x._id} + getOptionIcon={x => (x.routing.homeScreen ? "Home" : "WebPage")} + getOptionColour={x => RoleUtils.getRoleColour(x.routing.roleId)} + bind:value={$store.selectedScreenId} + /> +
+
+ {#if $store.clientFeatures.devicePreview} + + {/if} + +
+
+
+ {#key $store.version} + + {/key} +
+
+ + diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte similarity index 87% rename from packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte index 706550cca7..e332f8e896 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte @@ -1,10 +1,13 @@
diff --git a/packages/builder/src/components/design/AppPreview/DevicePreviewSelect.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/DevicePreviewSelect.svelte similarity index 100% rename from packages/builder/src/components/design/AppPreview/DevicePreviewSelect.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/DevicePreviewSelect.svelte diff --git a/packages/builder/src/components/design/AppPreview/iframeTemplate.js b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/iframeTemplate.js similarity index 97% rename from packages/builder/src/components/design/AppPreview/iframeTemplate.js rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/iframeTemplate.js index c265a64d53..def32dd45f 100644 --- a/packages/builder/src/components/design/AppPreview/iframeTemplate.js +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/iframeTemplate.js @@ -61,11 +61,11 @@ export default ` selectedComponentId, layout, screen, - previewType, appId, theme, customTheme, previewDevice, + navigation } = parsed // Set some flags so the app knows we're in the builder @@ -75,10 +75,10 @@ export default ` window["##BUDIBASE_PREVIEW_SCREEN##"] = screen window["##BUDIBASE_SELECTED_COMPONENT_ID##"] = selectedComponentId window["##BUDIBASE_PREVIEW_ID##"] = Math.random() - window["##BUDIBASE_PREVIEW_TYPE##"] = previewType window["##BUDIBASE_PREVIEW_THEME##"] = theme window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"] = customTheme window["##BUDIBASE_PREVIEW_DEVICE##"] = previewDevice + window["##BUDIBASE_PREVIEW_NAVIGATION##"] = navigation // Initialise app try { 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 new file mode 100644 index 0000000000..00165e4ee9 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_fallback.svelte @@ -0,0 +1,5 @@ + 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 new file mode 100644 index 0000000000..d0eb93466d --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte @@ -0,0 +1,102 @@ + + +
+
+ + $goto("./screens")} + /> + $goto("./components")} + /> + $goto("./theme")} + /> + $goto("./navigation")} + /> + {#if $store.layouts?.length} + $goto("./layouts")} + /> + {/if} + +
+ +
+ {#if $selectedScreen} + + + {/if} +
+
+ + diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte similarity index 100% rename from packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.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 new file mode 100644 index 0000000000..5b86d4da29 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte @@ -0,0 +1,129 @@ + + + $goto("../new")} + showExpandIcon + borderRight +> + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte new file mode 100644 index 0000000000..cc7f70f2c5 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte @@ -0,0 +1,148 @@ + + +
    + {#each components || [] as component, index (component._id)} + {@const opened = isOpen(component, $selectedComponentPath, closedNodes)} +
  • { + $store.selectedComponentId = component._id + }} + id={`component-${component._id}`} + > + dndStore.actions.dragstart(component)} + on:dragover={dragover(component, index)} + on:iconClick={() => toggleNodeOpen(component._id)} + on:drop={onDrop} + text={getComponentText(component)} + icon={getComponentIcon(component)} + withArrow={componentHasChildren(component)} + indentLevel={level + 1} + selected={$store.selectedComponentId === component._id} + {opened} + highlighted={isChildOfSelectedComponent(component)} + > + + + {#if opened} + + {/if} +
  • + {/each} +
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/DNDPositionIndicator.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/DNDPositionIndicator.svelte new file mode 100644 index 0000000000..c01bcaf36f --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/DNDPositionIndicator.svelte @@ -0,0 +1,67 @@ + + +{#if component && position} +
+{/if} + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ScreenslotDropdownMenu.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ScreenslotDropdownMenu.svelte new file mode 100644 index 0000000000..7ec7b0821c --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ScreenslotDropdownMenu.svelte @@ -0,0 +1,52 @@ + + +{#if showMenu} + +
+ +
+ storeComponentForCopy(false)}> + Copy + + pasteComponent("inside")} + disabled={noPaste} + > + Paste inside + +
+{/if} + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/dndStore.js b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/dndStore.js new file mode 100644 index 0000000000..8a9e7ed915 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/dndStore.js @@ -0,0 +1,129 @@ +import { writable, get } from "svelte/store" +import { store as frontendStore, selectedScreen } from "builderStore" +import { + findComponentParent, + findComponentPath, +} from "builderStore/componentUtils" + +export const DropPosition = { + ABOVE: "above", + BELOW: "below", + INSIDE: "inside", +} + +const initialState = { + source: null, + target: null, + targetParent: null, + dropPosition: null, + dragging: false, + valid: false, +} + +const createDNDStore = () => { + const store = writable(initialState) + const actions = { + dragstart: component => { + if (!component) { + return + } + store.set({ + source: component, + target: null, + dropPosition: null, + dragging: true, + valid: false, + }) + }, + dragover: ({ component, mousePosition }) => { + const definition = frontendStore.actions.components.getDefinition( + component._component + ) + const canHaveChildren = definition?.hasChildren + const hasChildren = component._children?.length > 0 + + let dropPosition + let target + let targetParent + + // If it can have children then it can be any position + if (canHaveChildren) { + if (mousePosition <= 0.33) { + dropPosition = DropPosition.ABOVE + } else if (mousePosition >= 0.66) { + dropPosition = DropPosition.BELOW + } else { + dropPosition = DropPosition.INSIDE + } + } + + // Otherwise drop either above or below + else { + dropPosition = + mousePosition > 0.5 ? DropPosition.BELOW : DropPosition.ABOVE + } + + // If hovering over a component with children and attempting to drop + // below, we need to change this to be above the first child instead + if (dropPosition === DropPosition.BELOW && hasChildren) { + target = component._children[0] + dropPosition = DropPosition.ABOVE + } else { + target = component + } + + // If drop position and target are the same then we can skip this update + const state = get(store) + if ( + dropPosition === state.dropPosition && + target?._id === state.target?._id + ) { + return + } + + // Find the parent of the target component + if (target) { + targetParent = findComponentParent( + get(selectedScreen).props, + target._id + ) + } + + store.update(state => { + return { + ...state, + dropPosition, + target, + targetParent, + + /// Mark as invalid if the target is a child of the source + valid: findComponentPath(state.source, target._id)?.length === 0, + } + }) + }, + reset: () => { + store.set(initialState) + }, + drop: async () => { + const state = get(store) + if (!state.valid || !state.source || !state.target) { + return + } + actions.reset() + + // Cut and paste the component + frontendStore.actions.components.copy(state.source, true, false) + await frontendStore.actions.components.paste( + state.target, + state.dropPosition + ) + }, + } + + return { + subscribe: store.subscribe, + actions, + } +} + +export const dndStore = createDNDStore() diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsPanel.svelte new file mode 100644 index 0000000000..ff0c53e7ab --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsPanel.svelte @@ -0,0 +1,46 @@ + + +{#if $selectedComponent} + + + + + + +{/if} diff --git a/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsSection.svelte similarity index 86% rename from packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsSection.svelte index 14e4f74bcb..ba16c705f6 100644 --- a/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsSection.svelte @@ -2,15 +2,16 @@ import { isEmpty } from "lodash/fp" import { Input, DetailSummary, notifications } from "@budibase/bbui" import { store } from "builderStore" - import PropertyControl from "./PropertyControls/PropertyControl.svelte" - import ResetFieldsButton from "./PropertyControls/ResetFieldsButton.svelte" - import { getComponentForSettingType } from "./PropertyControls/componentSettings" + import PropertyControl from "components/design/settings/controls/PropertyControl.svelte" + import ResetFieldsButton from "components/design/settings/controls/ResetFieldsButton.svelte" + import { getComponentForSetting } from "components/design/settings/componentSettings" import { Utils } from "@budibase/frontend-core" export let componentDefinition export let componentInstance export let bindings export let componentBindings + export let isScreen = false $: sections = getSections(componentDefinition) @@ -20,7 +21,7 @@ const customSections = settings.filter(setting => setting.section) return [ { - name: componentDefinition?.name || "General", + name: "General", info: componentDefinition?.info, settings: generalSettings, }, @@ -37,7 +38,7 @@ }) const canRenderControl = setting => { - const control = getComponentForSettingType(setting?.type) + const control = getComponentForSetting(setting) if (!control) { return false } @@ -77,7 +78,7 @@ {#each sections as section, idx (section.name)} - {#if idx === 0 && !componentInstance._component.endsWith("/layout")} + {#if idx === 0 && !componentInstance._component.endsWith("/layout") && !isScreen} updateProp(setting.key, val)} highlighted={$store.highlightedSettingKey === setting.key} props={{ - options: setting.options || [], + // Generic settings placeholder: setting.placeholder || null, + + // Select settings + options: setting.options || [], + + // Number fields min: setting.min || null, max: setting.max || null, }} diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ConditionalUIDrawer.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ConditionalUIDrawer.svelte similarity index 91% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/ConditionalUIDrawer.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ConditionalUIDrawer.svelte index 11d19edf7c..b40b33744f 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ConditionalUIDrawer.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ConditionalUIDrawer.svelte @@ -14,8 +14,8 @@ import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" import { LuceneUtils, Constants } from "@budibase/frontend-core" import { selectedComponent } from "builderStore" - import { getComponentForSettingType } from "./componentSettings" - import PropertyControl from "./PropertyControl.svelte" + import { getComponentForSetting } from "components/design/settings/componentSettings" + import PropertyControl from "components/design/settings/controls/PropertyControl.svelte" import { getComponentSettings } from "builderStore/componentUtils" export let conditions = [] @@ -71,11 +71,6 @@ return settings.find(setting => setting.key === key) } - const getComponentForSetting = key => { - const settingDefinition = getSettingDefinition(key) - return getComponentForSettingType(settingDefinition?.type || "text") - } - const addCondition = () => { conditions = [ ...conditions, @@ -154,6 +149,7 @@ on:consider={updateConditions} > {#each conditions as condition (condition.id)} + {@const definition = getSettingDefinition(condition.setting)}
TO
- {#if getSettingDefinition(condition.setting)} + {#if definition} (condition.settingValue = val)} props={{ - options: getSettingDefinition(condition.setting).options, - placeholder: getSettingDefinition(condition.setting) - .placeholder, + options: definition.options, + placeholder: definition.placeholder, }} {bindings} /> diff --git a/packages/builder/src/components/design/PropertiesPanel/ConditionalUISection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ConditionalUISection.svelte similarity index 93% rename from packages/builder/src/components/design/PropertiesPanel/ConditionalUISection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ConditionalUISection.svelte index b0863dce83..ba84b67622 100644 --- a/packages/builder/src/components/design/PropertiesPanel/ConditionalUISection.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ConditionalUISection.svelte @@ -7,7 +7,7 @@ notifications, } from "@budibase/bbui" import { store } from "builderStore" - import ConditionalUIDrawer from "./PropertyControls/ConditionalUIDrawer.svelte" + import ConditionalUIDrawer from "./ConditionalUIDrawer.svelte" export let componentInstance export let bindings diff --git a/packages/builder/src/components/design/PropertiesPanel/CustomStylesSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/CustomStylesSection.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/CustomStylesSection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/CustomStylesSection.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/DesignSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/DesignSection.svelte similarity index 100% rename from packages/builder/src/components/design/PropertiesPanel/DesignSection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/DesignSection.svelte diff --git a/packages/builder/src/components/design/PropertiesPanel/StyleSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/StyleSection.svelte similarity index 94% rename from packages/builder/src/components/design/PropertiesPanel/StyleSection.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/StyleSection.svelte index aa5147fa62..e34ea1019a 100644 --- a/packages/builder/src/components/design/PropertiesPanel/StyleSection.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/StyleSection.svelte @@ -1,5 +1,5 @@ + + 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 new file mode 100644 index 0000000000..a8e1e3e630 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/index.svelte @@ -0,0 +1,7 @@ + + + + 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 new file mode 100644 index 0000000000..f8c4cc0868 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte @@ -0,0 +1,18 @@ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/_components/NewComponentPanel.svelte new file mode 100644 index 0000000000..7f841e09ea --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/_components/NewComponentPanel.svelte @@ -0,0 +1,263 @@ + + + $goto("../slot")} + borderRight +> + + (searchString = e.detail)} + bind:inputRef={searchRef} + /> + {#if !searchString} + + (section = "components")}>Components + (section = "blocks")}>Blocks + + {/if} + +
+ +
+ {#if searchString || section === "components"} + {#each filteredStructure as category} + +
+ {#each category.children as component} +
15} + class:selected={selectedIndex === orderMap[component.component]} + on:click={() => addComponent(component.component)} + on:mouseover={() => (selectedIndex = null)} + > + + {component.name} +
+ {/each} +
+
+ {/each} + {:else} + + Blocks are collections of pre-built components + + {#each blocks as block} +
addComponent(block.component)} + > + + {block.name} +
+ {/each} +
+
+ {/if} +
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/_components/NewComponentTargetPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/_components/NewComponentTargetPanel.svelte new file mode 100644 index 0000000000..af44934526 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/_components/NewComponentTargetPanel.svelte @@ -0,0 +1,21 @@ + + + + + + Components that you add will be placed {position} + {title} + + + diff --git a/packages/builder/src/components/design/AppPreview/componentStructure.json b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/_components/componentStructure.json similarity index 89% rename from packages/builder/src/components/design/AppPreview/componentStructure.json rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/_components/componentStructure.json index 6873ae547d..acd28c6a41 100644 --- a/packages/builder/src/components/design/AppPreview/componentStructure.json +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/_components/componentStructure.json @@ -26,6 +26,26 @@ "dynamicfilter" ] }, + { + "name": "Basic", + "icon": "TextParagraph", + "children": [ + "heading", + "text", + "button", + "tag", + "spectrumcard", + "cardstat", + "divider", + "image", + "link", + "icon", + "embed", + "markdownviewer", + "backgroundimage", + "embeddedmap" + ] + }, { "name": "Form", "icon": "Form", @@ -39,23 +59,15 @@ "optionsfield", "booleanfield", "longformfield", - "datetimefield", "attachmentfield", - "relationshipfield", "daterangepicker", - "multifieldselect", "jsonfield", + "relationshipfield", + "datetimefield", + "multifieldselect", "s3upload" ] }, - { - "name": "Card", - "icon": "Card", - "children": [ - "spectrumcard", - "cardstat" - ] - }, { "name": "Chart", "icon": "GraphBarVertical", @@ -63,27 +75,9 @@ "bar", "line", "area", + "candlestick", "pie", - "donut", - "candlestick" - ] - }, - { - "name": "Elements", - "icon": "TextParagraph", - "children": [ - "heading", - "text", - "button", - "tag", - "divider", - "image", - "backgroundimage", - "link", - "icon", - "embed", - "markdownviewer", - "embeddedmap" + "donut" ] } ] diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/index.svelte new file mode 100644 index 0000000000..8f2042671b --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/new/index.svelte @@ -0,0 +1,26 @@ + + + + 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 new file mode 100644 index 0000000000..f5e3806bd6 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte @@ -0,0 +1,5 @@ + 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 new file mode 100644 index 0000000000..cba68f899d --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutDropdownMenu.svelte @@ -0,0 +1,41 @@ + + + +
+ +
+ 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 new file mode 100644 index 0000000000..fd38f08ceb --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte @@ -0,0 +1,29 @@ + + + +
+ {#each $store.layouts as layout (layout._id)} + ($store.selectedLayoutId = 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 new file mode 100644 index 0000000000..8e6ac603e7 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte @@ -0,0 +1,53 @@ + + + + + + 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 new file mode 100644 index 0000000000..c82fefab3e --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_layout.svelte @@ -0,0 +1,20 @@ + + + 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 new file mode 100644 index 0000000000..4d39403bc3 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/index.svelte @@ -0,0 +1,7 @@ + + + + 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 new file mode 100644 index 0000000000..1333c6afe3 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/_layout.svelte @@ -0,0 +1,12 @@ + + + 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 new file mode 100644 index 0000000000..09d45f8fde --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/index.svelte @@ -0,0 +1,12 @@ + 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 new file mode 100644 index 0000000000..dbd23c462f --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte @@ -0,0 +1,33 @@ + + + + + {#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/components/design/PropertiesPanel/PropertyControls/NavigationEditor/NavigationDrawer.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte similarity index 94% rename from packages/builder/src/components/design/PropertiesPanel/PropertyControls/NavigationEditor/NavigationDrawer.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte index 4d1823108c..5ffccc5800 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/NavigationEditor/NavigationDrawer.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte @@ -11,6 +11,7 @@ import { dndzone } from "svelte-dnd-action" import { generate } from "shortid" import { store } from "builderStore" + import RoleSelect from "components/design/settings/controls/RoleSelect.svelte" export let links = [] @@ -75,6 +76,7 @@ placeholder="URL" options={urlOptions} /> + .container { width: 100%; - max-width: 600px; + max-width: 800px; margin: 0 auto; } .links { 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 new file mode 100644 index 0000000000..895c82495d --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksEditor.svelte @@ -0,0 +1,34 @@ + + + + + + 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 new file mode 100644 index 0000000000..c6d43984b2 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationSettingsPanel.svelte @@ -0,0 +1,110 @@ + + + + + + + + + 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 new file mode 100644 index 0000000000..fc2e03d8e8 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte @@ -0,0 +1,7 @@ + + + + diff --git a/packages/builder/src/components/design/NavigationPanel/DatasourceModal.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/DatasourceModal.svelte similarity index 90% rename from packages/builder/src/components/design/NavigationPanel/DatasourceModal.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/DatasourceModal.svelte index bd9b6a1741..523e3d9da9 100644 --- a/packages/builder/src/components/design/NavigationPanel/DatasourceModal.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/DatasourceModal.svelte @@ -1,9 +1,15 @@
- Duplicate pasteComponent("inside")} - disabled={!$store.componentToPaste} + disabled={noPaste} > Paste inside + Duplicate Delete
@@ -90,8 +90,8 @@ 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 new file mode 100644 index 0000000000..40d9ab273d --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte @@ -0,0 +1,78 @@ + + + + + (searchString = e.detail)} + /> + role.name} + getOptionValue={role => role._id} + getOptionColour={role => RoleUtils.getRoleColour(role._id)} + options={$roles} + placeholder={null} + /> + 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]/screens/_components/ScreenSettingsPanel.svelte new file mode 100644 index 0000000000..0d861d1cd8 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte @@ -0,0 +1,197 @@ + + + + + {#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/components/design/NavigationPanel/ScreenWizard.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenWizard.svelte similarity index 81% rename from packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenWizard.svelte index 5f36034b93..6485e7a13f 100644 --- a/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenWizard.svelte @@ -1,13 +1,16 @@ + + +{#key $selectedScreen?._id} + +{/key} 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]/theme/_components/AppThemeSelect.svelte new file mode 100644 index 0000000000..accd156c29 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/AppThemeSelect.svelte @@ -0,0 +1,47 @@ + + +
+ + + +
+ + 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 new file mode 100644 index 0000000000..9593f0bff5 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeInfoPanel.svelte @@ -0,0 +1,12 @@ + + + + + + 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 new file mode 100644 index 0000000000..4bad3b7bc4 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeSettingsPanel.svelte @@ -0,0 +1,116 @@ + + + + + + + + + + +
+ {#each ButtonBorderRadiusOptions as option} +
+ +
+ {/each} +
+
+ + + 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 new file mode 100644 index 0000000000..013257d8e1 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/index.svelte @@ -0,0 +1,7 @@ + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/_layout.svelte index d41fc0ee34..ec21d909aa 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/_layout.svelte @@ -1,2 +1,2 @@ - + 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 1a454df4db..6490000b35 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/index.svelte @@ -1,8 +1,67 @@ - +{#if loaded} +
+ + logo +
+ LET’S BRING THIS APP TO LIFE +
+ +
+
+{/if} + + diff --git a/packages/builder/src/pages/builder/app/[application]/index.svelte b/packages/builder/src/pages/builder/app/[application]/index.svelte index d3321037d5..0143f38324 100644 --- a/packages/builder/src/pages/builder/app/[application]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/index.svelte @@ -1,6 +1,4 @@ - - diff --git a/packages/builder/src/pages/builder/app/[application]/settings/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/settings/_layout.svelte deleted file mode 100644 index eff7c155d3..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/settings/_layout.svelte +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/packages/builder/src/pages/builder/app/[application]/settings/index.svelte b/packages/builder/src/pages/builder/app/[application]/settings/index.svelte deleted file mode 100644 index 163d304af4..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/settings/index.svelte +++ /dev/null @@ -1 +0,0 @@ -Settings diff --git a/packages/builder/src/pages/builder/app/index.svelte b/packages/builder/src/pages/builder/app/index.svelte index 110b5e83d9..05a71911d2 100644 --- a/packages/builder/src/pages/builder/app/index.svelte +++ b/packages/builder/src/pages/builder/app/index.svelte @@ -1,4 +1,4 @@ diff --git a/packages/builder/src/pages/builder/portal/overview/[application]/index.svelte b/packages/builder/src/pages/builder/portal/overview/[application]/index.svelte index 83d5b35af2..d0176aa5e0 100644 --- a/packages/builder/src/pages/builder/portal/overview/[application]/index.svelte +++ b/packages/builder/src/pages/builder/portal/overview/[application]/index.svelte @@ -27,6 +27,7 @@ import AppLockModal from "components/common/AppLockModal.svelte" import EditableIcon from "components/common/EditableIcon.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte" + import BetaTab from "components/beta/BetaTab.svelte" import HistoryTab from "components/portal/overview/automation/HistoryTab.svelte" import { checkIncomingDeploymentStatus } from "components/deploy/utils" import { onDestroy, onMount } from "svelte" @@ -317,6 +318,9 @@ + + +
{ const roles = await API.getRoles() - set(roles) + set( + roles.sort((a, b) => { + const priorityA = RoleUtils.getRolePriority(a._id) + const priorityB = RoleUtils.getRolePriority(b._id) + return priorityA > priorityB ? -1 : 1 + }) + ) }, delete: async role => { await API.deleteRole({ diff --git a/packages/builder/yarn.lock b/packages/builder/yarn.lock index 929aa29f2a..32f8767c03 100644 --- a/packages/builder/yarn.lock +++ b/packages/builder/yarn.lock @@ -1223,10 +1223,10 @@ estree-walker "^2.0.1" picomatch "^2.2.2" -"@roxi/routify@2.18.0": - version "2.18.0" - resolved "https://registry.yarnpkg.com/@roxi/routify/-/routify-2.18.0.tgz#8f88bedd936312d0dbe44cbc11ab179b1f938ec2" - integrity sha512-MVB50HN+VQWLzfjLplcBjsSBvwOiExKOmht2DuWR3WQ60JxQi9pSejkB06tFVkFKNXz2X5iYtKDqKBTdae/gRg== +"@roxi/routify@2.18.5": + version "2.18.5" + resolved "https://registry.yarnpkg.com/@roxi/routify/-/routify-2.18.5.tgz#abd2b7cadeed008ab20d40a68323719d9c254552" + integrity sha512-xNG84JOSUtCyOV0WeQwPcj+HbA4nxtXCqvt9JXQZm13pdJZqY18WV2C7ayReKGtRAa3ogQyDo8k/C8f1MixA1w== dependencies: "@roxi/ssr" "^0.2.1" "@types/node" ">=4.2.0 < 13" @@ -5732,10 +5732,10 @@ svelte-portal@0.1.0: resolved "https://registry.yarnpkg.com/svelte-portal/-/svelte-portal-0.1.0.tgz#cc2821cc84b05ed5814e0218dcdfcbebc53c1742" integrity sha512-kef+ksXVKun224mRxat+DdO4C+cGHla+fEcZfnBAvoZocwiaceOfhf5azHYOPXSSB1igWVFTEOF3CDENPnuWxg== -svelte@^3.38.2: - version "3.44.1" - resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.44.1.tgz#5cc772a8340f4519a4ecd1ac1a842325466b1a63" - integrity sha512-4DrCEJoBvdR689efHNSxIQn2pnFwB7E7j2yLEJtHE/P8hxwZWIphCtJ8are7bjl/iVMlcEf5uh5pJ68IwR09vQ== +svelte@^3.48.0: + version "3.48.0" + resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.48.0.tgz#f98c866d45e155bad8e1e88f15f9c03cd28753d3" + integrity sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ== symbol-tree@^3.2.4: version "3.2.4" diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 6f0a55e5a9..fdb5700a5c 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -81,7 +81,7 @@ "container": { "name": "Container", "description": "This component contains things within itself", - "icon": "Sandbox", + "icon": "Selection", "hasChildren": true, "showSettingsBar": true, "styles": [ @@ -393,7 +393,7 @@ "repeater": { "name": "Repeater", "description": "A configurable data list that attaches to your backend tables.", - "icon": "ViewList", + "icon": "JourneyData", "illegalChildren": [ "section" ], @@ -894,7 +894,7 @@ }, "tag": { "name": "Tag", - "icon": "TextParagraph", + "icon": "Label", "showSettingsBar": true, "settings": [ { @@ -1028,7 +1028,7 @@ "icon": { "name": "Icon", "description": "A basic component for displaying icons", - "icon": "Bell", + "icon": "Shapes", "illegalChildren": [ "section" ], @@ -2358,7 +2358,7 @@ }, "optionsfield": { "name": "Options Picker", - "icon": "ViewList", + "icon": "Menu", "styles": [ "size" ], @@ -2686,7 +2686,7 @@ }, "booleanfield": { "name": "Checkbox", - "icon": "Checkmark", + "icon": "SelectBox", "editable": true, "illegalChildren": [ "section" @@ -2763,7 +2763,7 @@ }, "longformfield": { "name": "Long Form Field", - "icon": "TextParagraph", + "icon": "AlignLeft", "styles": [ "size" ], @@ -2838,7 +2838,7 @@ }, "datetimefield": { "name": "Date Picker", - "icon": "DateInput", + "icon": "Date", "styles": [ "size" ], @@ -3430,7 +3430,7 @@ }, "daterangepicker": { "name": "Date Range", - "icon": "Date", + "icon": "Calendar", "styles": [ "size" ], @@ -3467,7 +3467,7 @@ }, "spectrumcard": { "name": "Card", - "icon": "Card", + "icon": "PersonalizationField", "styles": [ "size" ], @@ -3526,7 +3526,7 @@ }, "dynamicfilter": { "name": "Dynamic Filter", - "icon": "FilterEdit", + "icon": "Filter", "showSettingsBar": true, "settings": [ { @@ -4122,7 +4122,7 @@ }, "markdownviewer": { "name": "Markdown Viewer", - "icon": "TaskList", + "icon": "Preview", "styles": [ "size" ], diff --git a/packages/client/src/api/api.js b/packages/client/src/api/api.js index c3cc679220..b96ad9c9e7 100644 --- a/packages/client/src/api/api.js +++ b/packages/client/src/api/api.js @@ -23,9 +23,9 @@ export const API = createAPIClient({ } // Add role header - const role = get(devToolsStore).role - if (role) { - headers["x-budibase-role"] = role + const devToolsState = get(devToolsStore) + if (devToolsState.enabled && devToolsState.role) { + headers["x-budibase-role"] = devToolsState.role } }, @@ -34,7 +34,11 @@ export const API = createAPIClient({ // Or we could check error.status and redirect to login on a 403 etc. onError: error => { const { status, method, url, message, handled } = error || {} - const ignoreErrorUrls = ["bbtel", "/api/global/self"] + const ignoreErrorUrls = [ + "bbtel", + "/api/global/self", + "/api/tables/ta_users", + ] // Log any errors that we haven't manually handled if (!handled) { diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index aab1f78a86..dcf4f54557 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -24,6 +24,7 @@ import DeviceBindingsProvider from "components/context/DeviceBindingsProvider.svelte" import StateBindingsProvider from "components/context/StateBindingsProvider.svelte" import RowSelectionProvider from "components/context/RowSelectionProvider.svelte" + import QueryParamsProvider from "components/context/QueryParamsProvider.svelte" import SettingsBar from "components/preview/SettingsBar.svelte" import SelectionIndicator from "components/preview/SelectionIndicator.svelte" import HoverIndicator from "components/preview/HoverIndicator.svelte" @@ -41,6 +42,40 @@ let dataLoaded = false let permissionError = false + // Determine if we should show devtools or not + $: showDevTools = + !$builderStore.inBuilder && + $devToolsStore.enabled && + !$routeStore.queryParams?.peek + + // Handle no matching route + $: { + if (dataLoaded && $routeStore.routerLoaded && !$routeStore.activeRoute) { + if ($screenStore.screens.length) { + // If we have some available screens, use the first screen which + // represents the best route based on rank + const route = $screenStore.screens[0].routing?.route + if (!route) { + permissionError = true + console.error("No route found but screens exist") + } else { + permissionError = false + routeStore.actions.navigate(route) + } + } else if ($authStore) { + // If the user is logged in but has no screens, they don't have + // permission to use the app + permissionError = true + } else { + // If they have no screens and are not logged in, it probably means + // they should log in to gain access + const returnUrl = `${window.location.pathname}${window.location.hash}` + CookieUtils.setCookie(Constants.Cookies.ReturnUrl, returnUrl) + window.location = "/builder/auth/login" + } + } + } + // Load app config onMount(async () => { await initialise() @@ -50,44 +85,6 @@ builderStore.actions.notifyLoaded() } }) - - // Handle no matching route - this is likely a permission error - $: { - if (dataLoaded && $routeStore.routerLoaded && !$routeStore.activeRoute) { - if ($authStore) { - // There is a logged in user, so handle them - if ($screenStore.screens.length) { - let firstRoute - - // If using devtools, find the first screen matching our role - if ($devToolsStore.role) { - const roleRoutes = $screenStore.screens.filter( - screen => screen.routing?.roleId === $devToolsStore.role - ) - firstRoute = roleRoutes[0]?.routing?.route || "/" - } - - // Otherwise just use the first route - else { - firstRoute = $screenStore.screens[0]?.routing?.route ?? "/" - } - - // Screens exist so navigate back to the home screen - routeStore.actions.navigate(firstRoute) - } else { - // No screens likely means the user has no permissions to view this app - permissionError = true - } - } else { - // The user is not logged in, redirect them to login - const returnUrl = `${window.location.pathname}${window.location.hash}` - CookieUtils.setCookie(Constants.Cookies.ReturnUrl, returnUrl) - window.location = "/builder/auth/login" - } - } - } - - $: isDevPreview = $appStore.isDevApp && !$builderStore.inBuilder {#if dataLoaded} @@ -97,19 +94,11 @@ dir="ltr" class="spectrum spectrum--medium {$themeStore.theme}" > - {#if permissionError} -
- - {@html ErrorSVG} - You don't have permission to use this app - Ask your administrator to grant you access - -
- {:else if $screenStore.activeLayout} + - - - + + + {#key $builderStore.selectedComponentId} @@ -127,36 +116,62 @@ >
- {#if isDevPreview} + {#if showDevTools} {/if}
- - {#key `${$screenStore.activeLayout._id}-${$builderStore.previewType}`} - - {/key} + {#if permissionError} +
+ + {@html ErrorSVG} + + You don't have permission to use this app + + + Ask your administrator to grant you access + + +
+ {:else if !$screenStore.activeLayout} +
+ + {@html ErrorSVG} + + Something went wrong rendering your app + + + Get in touch with support if this issue persists + + +
+ {:else} + + {#key $screenStore.activeLayout._id} + + {/key} - -
+ +
- - - - - + + + - {/if} +
{/if} @@ -226,7 +241,6 @@ } .error { - position: absolute; width: 100%; height: 100%; display: grid; @@ -235,23 +249,19 @@ text-align: center; padding: 20px; } - .error :global(svg) { fill: var(--spectrum-global-color-gray-500); width: 80px; height: 80px; } - .error :global(h1), .error :global(p) { color: var(--spectrum-global-color-gray-800); } - .error :global(p) { font-style: italic; margin-top: -0.5em; } - .error :global(h1) { font-weight: 400; } @@ -261,12 +271,10 @@ #clip-root.preview { padding: 2px; } - #clip-root.tablet-preview { width: calc(1024px + 6px); height: calc(768px + 6px); } - #clip-root.mobile-preview { width: calc(390px + 6px); height: calc(844px + 6px); diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index c196e2ff64..808bfdae07 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -20,9 +20,9 @@ } from "utils/componentProps" import { builderStore, devToolsStore, componentStore, appStore } from "stores" import { Helpers } from "@budibase/bbui" - import Manifest from "manifest.json" import { getActiveConditions, reduceConditionActions } from "utils/conditions" import Placeholder from "components/app/Placeholder.svelte" + import ScreenPlaceholder from "components/app/ScreenPlaceholder.svelte" import ComponentPlaceholder from "components/app/ComponentPlaceholder.svelte" export let instance = {} @@ -90,7 +90,8 @@ // Extract component instance info $: children = instance._children || [] $: id = instance._id - $: name = instance._instanceName + $: name = isScreen ? "Screen" : instance._instanceName + $: icon = definition?.icon // Determine if the component is selected or is part of the critical path // leading to the selected component @@ -109,9 +110,7 @@ // Interactive components can be selected, dragged and highlighted inside // the builder preview $: builderInteractive = - $builderStore.inBuilder && - ($builderStore.previewType === "layout" || insideScreenslot) && - !isBlock + $builderStore.inBuilder && insideScreenslot && !isBlock $: devToolsInteractive = $devToolsStore.allowSelection && !isBlock $: interactive = builderInteractive || devToolsInteractive $: editing = editable && selected && $builderStore.editMode @@ -141,6 +140,9 @@ // Determine and apply settings to the component $: applySettings(staticSettings, enrichedSettings, conditionalSettings) + // Scroll the selected element into view + $: selected && scrollIntoView() + // Update component context $: store.set({ id, @@ -175,8 +177,9 @@ } // Pull definition and constructor - constructor = getComponentConstructor(instance._component) - definition = getComponentDefinition(instance._component) + const component = instance._component + constructor = getComponentConstructor(component) + definition = componentStore.actions.getComponentDefinition(component) if (!definition) { return } @@ -236,19 +239,12 @@ const getComponentConstructor = component => { const split = component?.split("/") const name = split?.[split.length - 1] - if (name === "screenslot" && $builderStore.previewType !== "layout") { + if (name === "screenslot" && !insideScreenslot) { return Router } return AppComponents[name] } - // Gets this component's definition from the manifest - const getComponentDefinition = component => { - const prefix = "@budibase/standard-components/" - const type = component?.replace(prefix, "") - return type ? Manifest[type] : null - } - const getSettingsDefinitionMap = settingsDefinition => { let map = {} settingsDefinition?.forEach(setting => { @@ -402,6 +398,19 @@ } } + const scrollIntoView = () => { + const node = document.getElementsByClassName(id)?.[0]?.childNodes[0] + if (!node) { + return + } + node.style.scrollMargin = "100px" + node.scrollIntoView({ + behavior: "smooth", + block: "start", + inline: "start", + }) + } + onMount(() => { if ( $appStore.isDevApp && @@ -438,22 +447,25 @@ class:block={isBlock} data-id={id} data-name={name} + data-icon={icon} > - {#if hasMissingRequiredSettings} - - {:else} - - {#if children.length} - {#each children as child (child._id)} - - {/each} - {:else if emptyState} + + {#if hasMissingRequiredSettings} + + {:else if children.length} + {#each children as child (child._id)} + + {/each} + {:else if emptyState} + {#if isScreen} + + {:else} - {:else if isBlock} - {/if} - - {/if} + {:else if isBlock} + + {/if} +
{/if} diff --git a/packages/client/src/components/CustomThemeWrapper.svelte b/packages/client/src/components/CustomThemeWrapper.svelte index c656b09306..919aa13926 100644 --- a/packages/client/src/components/CustomThemeWrapper.svelte +++ b/packages/client/src/components/CustomThemeWrapper.svelte @@ -16,6 +16,7 @@ /* Buttons */ --spectrum-semantic-cta-color-background-default: var(--primaryColor); --spectrum-semantic-cta-color-background-hover: var(--primaryColorHover); + --spectrum-semantic-cta-color-background-down: var(--primaryColorHover); --spectrum-button-primary-s-border-radius: var(--buttonBorderRadius); --spectrum-button-primary-m-border-radius: var(--buttonBorderRadius); --spectrum-button-primary-l-border-radius: var(--buttonBorderRadius); diff --git a/packages/client/src/components/Screen.svelte b/packages/client/src/components/Screen.svelte index 17f068e04f..3ec8d1ea52 100644 --- a/packages/client/src/components/Screen.svelte +++ b/packages/client/src/components/Screen.svelte @@ -1,21 +1,36 @@ diff --git a/packages/client/src/components/app/Layout.svelte b/packages/client/src/components/app/Layout.svelte index 4df9087904..58b2797162 100644 --- a/packages/client/src/components/app/Layout.svelte +++ b/packages/client/src/components/app/Layout.svelte @@ -2,13 +2,16 @@ import { getContext, setContext } from "svelte" import { writable } from "svelte/store" import { Heading, Icon } from "@budibase/bbui" - import { FieldTypes } from "../../constants" + import { FieldTypes } from "constants" import active from "svelte-spa-router/active" + import { RoleUtils } from "@budibase/frontend-core" - const { routeStore, styleable, linkable, builderStore } = getContext("sdk") + const sdk = getContext("sdk") + const { routeStore, styleable, linkable, builderStore, currentRole } = sdk const component = getContext("component") const context = getContext("context") + // Legacy props which must remain unchanged for backwards compatibility export let title export let hideTitle = false export let logoUrl @@ -18,18 +21,27 @@ export let links export let width = "Large" - const navigationClasses = { + // New props from new design UI + export let navBackground + export let navTextColor + export let navWidth + export let pageWidth + + const NavigationClasses = { Top: "top", Left: "left", None: "none", } - const widthClasses = { + const WidthClasses = { Max: "max", Large: "l", Medium: "m", Small: "s", + "Extra small": "xs", } + let mobileOpen = false + // Set some layout context. This isn't used in bindings but can be used // determine things about the current app layout. $: mobile = $context.device.mobile @@ -40,18 +52,45 @@ }) setContext("layout", store) - // Permanently go into peek mode if we ever get the peek flag - let isPeeking = false + $: validLinks = getValidLinks(links, $currentRole) + $: typeClass = NavigationClasses[navigation] || NavigationClasses.None + $: navWidthClass = WidthClasses[navWidth || width] || WidthClasses.Large + $: pageWidthClass = WidthClasses[pageWidth || width] || WidthClasses.Large + $: navStyle = getNavStyle( + navBackground, + navTextColor, + $context.device.width, + $context.device.height + ) + + // Scroll navigation into view if selected $: { - if ($routeStore.queryParams?.peek) { - isPeeking = true + if ( + $builderStore.inBuilder && + $builderStore.selectedComponentId === "navigation" + ) { + const node = document.getElementsByClassName("nav-wrapper")?.[0] + if (node) { + node.style.scrollMargin = "100px" + node.scrollIntoView({ + behavior: "smooth", + block: "start", + inline: "start", + }) + } } } - $: validLinks = links?.filter(link => link.text && link.url) || [] - $: typeClass = navigationClasses[navigation] || "none" - $: widthClass = widthClasses[width] || "l" - let mobileOpen = false + const getValidLinks = (allLinks, role) => { + // Strip links missing required info + let validLinks = (allLinks || []).filter(link => link.text && link.url) + + // Filter to only links allowed by the current role + const priority = RoleUtils.getRolePriority(role) + return validLinks.filter(link => { + return !link.roleId || RoleUtils.getRolePriority(link.roleId) <= priority + }) + } const isInternal = url => { return url.startsWith("/") @@ -83,6 +122,17 @@ return navigation === "Top" ? "137px" : "0px" } } + + const getNavStyle = (backgroundColor, textColor, width, height) => { + let style = `--width:${width}px; --height:${height}px;` + if (backgroundColor) { + style += `--navBackground:${backgroundColor};` + } + if (textColor) { + style += `--navTextColor:${textColor};` + } + return style + }
{#if typeClass !== "none"}