diff --git a/hosting/docker-compose.yaml b/hosting/docker-compose.yaml index 36b88466fe..a72b36aef1 100644 --- a/hosting/docker-compose.yaml +++ b/hosting/docker-compose.yaml @@ -98,7 +98,6 @@ services: couchdb-service: restart: unless-stopped image: budibase/couchdb - pull_policy: always environment: - COUCHDB_PASSWORD=${COUCH_DB_PASSWORD} - COUCHDB_USER=${COUCH_DB_USER} diff --git a/lerna.json b/lerna.json index 9d0fb72b23..596fb434bc 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.19.1", + "version": "2.19.5", "npmClient": "yarn", "packages": [ "packages/*", diff --git a/package.json b/package.json index 4f81d216ad..4407fd33f3 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "lint": "yarn run lint:eslint && yarn run lint:prettier", "lint:fix:eslint": "eslint --fix --max-warnings=0 packages qa-core", "lint:fix:prettier": "prettier --write \"packages/**/*.{js,ts,svelte}\" && prettier --write \"examples/**/*.{js,ts,svelte}\" && prettier --write \"qa-core/**/*.{js,ts,svelte}\"", - "lint:fix": "yarn run lint:fix:prettier && yarn run lint:fix:eslint", + "lint:fix": "yarn run lint:fix:eslint && yarn run lint:fix:prettier", "build:specs": "lerna run --stream specs", "build:docker:airgap": "node hosting/scripts/airgapped/airgappedDockerBuild", "build:docker:airgap:single": "SINGLE_IMAGE=1 node hosting/scripts/airgapped/airgappedDockerBuild", @@ -106,7 +106,6 @@ "axios": "1.6.3", "xml2js": "0.6.2", "unset-value": "2.0.1", - "got": "13.0.0", "passport": "0.6.0" }, "engines": { diff --git a/packages/account-portal b/packages/account-portal index 8cbe73c9dc..8c446c4ba3 160000 --- a/packages/account-portal +++ b/packages/account-portal @@ -1 +1 @@ -Subproject commit 8cbe73c9dc39d0bda3dbca3dac345a4a1f916f18 +Subproject commit 8c446c4ba385592127fa31755d3b64467b291882 diff --git a/packages/backend-core/src/logging/correlation/correlation.ts b/packages/backend-core/src/logging/correlation/correlation.ts index 0498bd43d5..13cc7aff8f 100644 --- a/packages/backend-core/src/logging/correlation/correlation.ts +++ b/packages/backend-core/src/logging/correlation/correlation.ts @@ -2,11 +2,12 @@ import { Header } from "../../constants" const correlator = require("correlation-id") -export const setHeader = (headers: any) => { +export const setHeader = (headers: Record) => { const correlationId = correlator.getId() - if (correlationId) { - headers[Header.CORRELATION_ID] = correlationId + if (!correlationId) { + return } + headers[Header.CORRELATION_ID] = correlationId } export function getId() { diff --git a/packages/builder/assets/n8n_square.png b/packages/builder/assets/n8n_square.png new file mode 100644 index 0000000000..23b75ee688 Binary files /dev/null and b/packages/builder/assets/n8n_square.png differ diff --git a/packages/builder/package.json b/packages/builder/package.json index 273994ed0e..52db8e11bc 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -23,7 +23,6 @@ "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/internals/mocks/fileMock.js", "\\.(css|less|sass|scss)$": "identity-obj-proxy", "components(.*)$": "/src/components$1", - "builderStore(.*)$": "/src/builderStore$1", "stores(.*)$": "/src/stores$1", "analytics(.*)$": "/src/analytics$1", "constants/backend": "/src/constants/backend/index.js" diff --git a/packages/builder/src/api.js b/packages/builder/src/api.js index ac878bf82f..6441b4ff48 100644 --- a/packages/builder/src/api.js +++ b/packages/builder/src/api.js @@ -3,14 +3,14 @@ import { CookieUtils, Constants, } from "@budibase/frontend-core" -import { store } from "./builderStore" +import { appStore } from "stores/builder" import { get } from "svelte/store" import { auth, navigation } from "./stores/portal" export const API = createAPIClient({ attachHeaders: headers => { // Attach app ID header from store - let appId = get(store).appId + let appId = get(appStore).appId if (appId) { headers["x-budibase-app-id"] = appId } diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js deleted file mode 100644 index b58d196024..0000000000 --- a/packages/builder/src/builderStore/index.js +++ /dev/null @@ -1,158 +0,0 @@ -import { getFrontendStore } from "./store/frontend" -import { getAutomationStore } from "./store/automation" -import { getTemporalStore } from "./store/temporal" -import { getThemeStore } from "./store/theme" -import { getUserStore } from "./store/users" -import { getDeploymentStore } from "./store/deployments" -import { derived, get } from "svelte/store" -import { findComponent, findComponentPath } from "./componentUtils" -import { RoleUtils } from "@budibase/frontend-core" -import { createHistoryStore } from "builderStore/store/history" -import { cloneDeep } from "lodash/fp" -import { getHoverStore } from "./store/hover" - -export const store = getFrontendStore() -export const automationStore = getAutomationStore() -export const themeStore = getThemeStore() -export const temporalStore = getTemporalStore() -export const userStore = getUserStore() -export const deploymentStore = getDeploymentStore() -export const hoverStore = getHoverStore() - -// Setup history for screens -export const screenHistoryStore = createHistoryStore({ - getDoc: id => get(store).screens?.find(screen => screen._id === id), - selectDoc: store.actions.screens.select, - afterAction: () => { - // Ensure a valid component is selected - if (!get(selectedComponent)) { - store.update(state => ({ - ...state, - selectedComponentId: get(selectedScreen)?.props._id, - })) - } - }, -}) -store.actions.screens.save = screenHistoryStore.wrapSaveDoc( - store.actions.screens.save -) -store.actions.screens.delete = screenHistoryStore.wrapDeleteDoc( - store.actions.screens.delete -) - -// Setup history for automations -export const automationHistoryStore = createHistoryStore({ - getDoc: automationStore.actions.getDefinition, - selectDoc: automationStore.actions.select, -}) -automationStore.actions.save = automationHistoryStore.wrapSaveDoc( - automationStore.actions.save -) -automationStore.actions.delete = automationHistoryStore.wrapDeleteDoc( - automationStore.actions.delete -) - -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, selectedScreen], - ([$store, $selectedScreen]) => { - if ( - $selectedScreen && - $store.selectedComponentId?.startsWith(`${$selectedScreen._id}-`) - ) { - return $selectedScreen?.props - } - if (!$selectedScreen || !$store.selectedComponentId) { - return null - } - const selected = findComponent( - $selectedScreen?.props, - $store.selectedComponentId - ) - - const clone = selected ? cloneDeep(selected) : selected - store.actions.components.migrateSettings(clone) - return clone - } -) - -// For legacy compatibility only, but with the new design UI this is just -// the selected screen -export const currentAsset = selectedScreen - -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, selectedScreen], - ([$store, $selectedScreen]) => { - return findComponentPath( - $selectedScreen?.props, - $store.selectedComponentId - ).map(component => component._id) - } -) - -// Derived automation state -export const selectedAutomation = derived(automationStore, $automationStore => { - if (!$automationStore.selectedAutomationId) { - return null - } - return $automationStore.automations?.find( - x => x._id === $automationStore.selectedAutomationId - ) -}) - -// Derive map of resource IDs to other users. -// We only ever care about a single user in each resource, so if multiple users -// share the same datasource we can just overwrite them. -export const userSelectedResourceMap = derived(userStore, $userStore => { - let map = {} - $userStore.forEach(user => { - const resource = user.builderMetadata?.selectedResourceId - if (resource) { - if (!map[resource]) { - map[resource] = [] - } - map[resource].push(user) - } - }) - return map -}) - -export const isOnlyUser = derived(userStore, $userStore => { - return $userStore.length < 2 -}) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js deleted file mode 100644 index 55208bb97e..0000000000 --- a/packages/builder/src/builderStore/store/frontend.js +++ /dev/null @@ -1,1507 +0,0 @@ -import { get, writable } from "svelte/store" -import { cloneDeep } from "lodash/fp" -import { - selectedScreen, - selectedComponent, - screenHistoryStore, - automationHistoryStore, -} from "builderStore" -import { - datasources, - integrations, - queries, - database, - tables, -} from "stores/backend" -import { API } from "api" -import analytics, { Events } from "analytics" -import { - findComponentParent, - findClosestMatchingComponent, - findAllMatchingComponents, - findComponent, - getComponentSettings, - makeComponentUnique, - findComponentPath, -} from "../componentUtils" -import { Helpers } from "@budibase/bbui" -import { Utils } from "@budibase/frontend-core" -import { - BUDIBASE_INTERNAL_DB_ID, - DB_TYPE_INTERNAL, - DB_TYPE_EXTERNAL, -} from "constants/backend" -import { - buildFormSchema, - getSchemaForDatasource, -} from "builderStore/dataBinding" -import { makePropSafe as safe } from "@budibase/string-templates" -import { getComponentFieldOptions } from "helpers/formFields" -import { createBuilderWebsocket } from "builderStore/websocket" -import { BuilderSocketEvent } from "@budibase/shared-core" - -const INITIAL_FRONTEND_STATE = { - initialised: false, - apps: [], - name: "", - url: "", - description: "", - layouts: [], - screens: [], - components: [], - clientFeatures: { - spectrumThemes: false, - intelligentLoading: false, - deviceAwareness: false, - state: false, - rowSelection: false, - customThemes: false, - devicePreview: false, - messagePassing: false, - continueIfAction: false, - showNotificationAction: false, - sidePanel: false, - }, - features: { - componentValidation: false, - disableUserMetadata: false, - }, - errors: [], - hasAppPackage: false, - libraries: null, - appId: "", - routes: {}, - clientLibPath: "", - theme: "", - customTheme: {}, - previewDevice: "desktop", - highlightedSettingKey: null, - propertyFocus: null, - builderSidePanel: false, - hasLock: true, - showPreview: false, - - // URL params - selectedScreenId: null, - selectedComponentId: null, - selectedLayoutId: null, - - // Client state - selectedComponentInstance: null, - - // Onboarding - onboarding: false, - tourNodes: null, -} - -export const getFrontendStore = () => { - const store = writable({ ...INITIAL_FRONTEND_STATE }) - let websocket - - // This is a fake implementation of a "patch" API endpoint to try and prevent - // 409s. All screen doc mutations (aside from creation) use this function, - // which queues up invocations sequentially and ensures pending mutations are - // always applied to the most up-to-date doc revision. - // This is slightly better than just a traditional "patch" endpoint and this - // supports deeply mutating the current doc rather than just appending data. - const sequentialScreenPatch = Utils.sequential(async (patchFn, screenId) => { - const state = get(store) - const screen = state.screens.find(screen => screen._id === screenId) - if (!screen) { - return - } - let clone = cloneDeep(screen) - const result = patchFn(clone) - // An explicit false result means skip this change - if (result === false) { - return - } - return await store.actions.screens.save(clone) - }) - - store.actions = { - reset: () => { - store.set({ ...INITIAL_FRONTEND_STATE }) - websocket?.disconnect() - websocket = null - }, - initialise: async pkg => { - const { layouts, screens, application, clientLibPath, hasLock } = pkg - if (!websocket) { - websocket = createBuilderWebsocket(application.appId) - } - await store.actions.components.refreshDefinitions(application.appId) - - // Reset store state - store.update(state => ({ - ...state, - libraries: application.componentLibraries, - name: application.name, - description: application.description, - appId: application.appId, - url: application.url, - layouts: layouts || [], - screens: screens || [], - theme: application.theme || "spectrum--light", - customTheme: application.customTheme, - hasAppPackage: true, - appInstance: application.instance, - clientLibPath, - previousTopNavPath: {}, - version: application.version, - revertableVersion: application.revertableVersion, - upgradableVersion: application.upgradableVersion, - navigation: application.navigation || {}, - usedPlugins: application.usedPlugins || [], - hasLock, - features: { - ...INITIAL_FRONTEND_STATE.features, - ...application.features, - }, - automations: application.automations || {}, - icon: application.icon || {}, - initialised: true, - })) - screenHistoryStore.reset() - automationHistoryStore.reset() - - // Initialise backend stores - database.set(application.instance) - await datasources.init() - await integrations.init() - await queries.init() - await tables.init() - }, - theme: { - save: async theme => { - const appId = get(store).appId - const app = await API.saveAppMetadata({ - appId, - metadata: { theme }, - }) - store.update(state => { - state.theme = app.theme - return state - }) - }, - }, - customTheme: { - save: async customTheme => { - const appId = get(store).appId - const app = await API.saveAppMetadata({ - appId, - metadata: { customTheme }, - }) - store.update(state => { - state.customTheme = app.customTheme - return state - }) - }, - }, - navigation: { - save: async navigation => { - const appId = get(store).appId - const app = await API.saveAppMetadata({ - appId, - metadata: { navigation }, - }) - store.update(state => { - state.navigation = app.navigation - return state - }) - }, - }, - screens: { - select: screenId => { - // Check this screen exists - const state = get(store) - const screen = state.screens.find(screen => screen._id === screenId) - if (!screen) { - return - } - - // Check screen isn't already selected - if (state.selectedScreenId === screen._id) { - return - } - - // Select new screen - store.update(state => { - state.selectedScreenId = screen._id - return state - }) - }, - validate: screen => { - // Recursive function to find any illegal children in component trees - const findIllegalChild = ( - component, - illegalChildren = [], - legalDirectChildren = [] - ) => { - const type = component._component - - if (illegalChildren.includes(type)) { - return type - } - if ( - legalDirectChildren.length && - !legalDirectChildren.includes(type) - ) { - return type - } - if (!component?._children?.length) { - return - } - - if (type === "@budibase/standard-components/sidepanel") { - illegalChildren = [] - } - - const definition = store.actions.components.getDefinition( - component._component - ) - // Reset whitelist for direct children - legalDirectChildren = [] - if (definition?.legalDirectChildren?.length) { - legalDirectChildren = definition.legalDirectChildren.map(x => { - return `@budibase/standard-components/${x}` - }) - } - - // Append blacklisted components and remove duplicates - if (definition?.illegalChildren?.length) { - const blacklist = definition.illegalChildren.map(x => { - return `@budibase/standard-components/${x}` - }) - illegalChildren = [...new Set([...illegalChildren, ...blacklist])] - } - - // Recurse on all children - for (let child of component._children) { - const illegalChild = findIllegalChild( - child, - illegalChildren, - legalDirectChildren - ) - if (illegalChild) { - return illegalChild - } - } - } - - // Validate the entire tree and throw an error if an illegal child is - // found anywhere - const illegalChild = findIllegalChild(screen.props) - if (illegalChild) { - const def = store.actions.components.getDefinition(illegalChild) - throw `You can't place a ${def.name} here` - } - }, - save: async screen => { - const state = get(store) - - // Validate screen structure if the app supports it - if (state.features?.componentValidation) { - store.actions.screens.validate(screen) - } - - // Check screen definition for any component settings which need updated - store.actions.screens.enrichEmptySettings(screen) - - // Save screen - const creatingNewScreen = screen._id === undefined - const savedScreen = await API.saveScreen(screen) - const routesResponse = await API.fetchAppRoutes() - - // If plugins changed we need to fetch the latest app metadata - let usedPlugins = state.usedPlugins - if (savedScreen.pluginAdded) { - const { application } = await API.fetchAppPackage(state.appId) - usedPlugins = application.usedPlugins || [] - } - - // Update state - store.update(state => { - // Update screen object - const idx = state.screens.findIndex(x => x._id === savedScreen._id) - if (idx !== -1) { - state.screens.splice(idx, 1, savedScreen) - } else { - state.screens.push(savedScreen) - } - - // Select the new screen if creating a new one - if (creatingNewScreen) { - state.selectedScreenId = savedScreen._id - state.selectedComponentId = savedScreen.props._id - } - - // Update routes - state.routes = routesResponse.routes - - // Update used plugins - state.usedPlugins = usedPlugins - return state - }) - return savedScreen - }, - patch: async (patchFn, screenId) => { - // Default to the currently selected screen - if (!screenId) { - const state = get(store) - screenId = state.selectedScreenId - } - if (!screenId || !patchFn) { - return - } - return await sequentialScreenPatch(patchFn, screenId) - }, - replace: async (screenId, screen) => { - if (!screenId) { - return - } - if (!screen) { - // Screen deletion - store.update(state => ({ - ...state, - screens: state.screens.filter(x => x._id !== screenId), - })) - } else { - const index = get(store).screens.findIndex(x => x._id === screen._id) - if (index === -1) { - // Screen addition - store.update(state => ({ - ...state, - screens: [...state.screens, screen], - })) - } else { - // Screen update - store.update(state => { - state.screens[index] = screen - return state - }) - } - } - }, - delete: async screens => { - const screensToDelete = Array.isArray(screens) ? screens : [screens] - - // Build array of promises to speed up bulk deletions - let promises = [] - let deleteUrls = [] - screensToDelete.forEach(screen => { - // Delete the screen - promises.push( - API.deleteScreen({ - screenId: screen._id, - screenRev: screen._rev, - }) - ) - // Remove links to this screen - deleteUrls.push(screen.routing.route) - }) - - await Promise.all(promises) - await store.actions.links.delete(deleteUrls) - const deletedIds = screensToDelete.map(screen => screen._id) - const routesResponse = await API.fetchAppRoutes() - store.update(state => { - // Remove deleted screens from state - state.screens = state.screens.filter(screen => { - return !deletedIds.includes(screen._id) - }) - - // Deselect the current screen if it was deleted - if (deletedIds.includes(state.selectedScreenId)) { - state.selectedScreenId = null - state.selectedComponentId = null - } - - // Update routing - state.routes = routesResponse.routes - - return state - }) - return null - }, - updateSetting: async (screen, name, value) => { - if (!screen || !name) { - return - } - - // Apply setting update - const patch = screen => { - if (!screen) { - return false - } - // Skip update if the value is the same - if (Helpers.deepGet(screen, name) === value) { - return false - } - Helpers.deepSet(screen, name, value) - } - await store.actions.screens.patch(patch, screen._id) - - // Ensure we don't have more than one home screen for this new role. - // This could happen after updating multiple different settings. - const state = get(store) - const updatedScreen = state.screens.find(s => s._id === screen._id) - if (!updatedScreen) { - return - } - const otherHomeScreens = state.screens.filter(s => { - return ( - s.routing.roleId === updatedScreen.routing.roleId && - s.routing.homeScreen && - s._id !== screen._id - ) - }) - if (otherHomeScreens.length && updatedScreen.routing.homeScreen) { - const patch = screen => { - screen.routing.homeScreen = false - } - for (let otherHomeScreen of otherHomeScreens) { - await store.actions.screens.patch(patch, otherHomeScreen._id) - } - } - }, - removeCustomLayout: async screen => { - // Pull relevant settings from old layout, if required - const layout = get(store).layouts.find(x => x._id === screen.layoutId) - const patch = screen => { - screen.layoutId = null - screen.showNavigation = layout?.props.navigation !== "None" - screen.width = layout?.props.width || "Large" - } - await store.actions.screens.patch(patch, screen._id) - }, - enrichEmptySettings: screen => { - // Flatten the recursive component tree - const components = findAllMatchingComponents(screen.props, x => x) - - // Iterate over all components and run checks - components.forEach(component => { - store.actions.components.enrichEmptySettings(component, { - screen, - }) - }) - }, - }, - preview: { - setDevice: device => { - store.update(state => { - state.previewDevice = device - return state - }) - }, - sendEvent: (name, payload) => { - const { previewEventHandler } = get(store) - previewEventHandler?.(name, payload) - }, - registerEventHandler: handler => { - store.update(state => { - state.previewEventHandler = handler - return state - }) - }, - }, - layouts: { - select: layoutId => { - // Check this layout exists - const state = get(store) - const layout = state.layouts.find(layout => layout._id === layoutId) - if (!layout) { - return - } - - // Check layout isn't already selected - if ( - state.selectedLayoutId === layout._id && - state.selectedComponentId === layout.props?._id - ) { - return - } - - // Select new layout - store.update(state => { - state.selectedLayoutId = layout._id - state.selectedComponentId = layout.props?._id - return state - }) - }, - delete: async layout => { - if (!layout?._id) { - return - } - await API.deleteLayout({ - layoutId: layout._id, - layoutRev: layout._rev, - }) - store.update(state => { - state.layouts = state.layouts.filter(x => x._id !== layout._id) - return state - }) - }, - }, - components: { - refreshDefinitions: async appId => { - if (!appId) { - appId = get(store).appId - } - - // Fetch definitions and filter out custom component definitions so we - // can flag them - const components = await API.fetchComponentLibDefinitions(appId) - const customComponents = Object.keys(components).filter(name => - name.startsWith("plugin/") - ) - - // Update store - store.update(state => ({ - ...state, - components, - customComponents, - clientFeatures: { - ...INITIAL_FRONTEND_STATE.clientFeatures, - ...components.features, - }, - })) - }, - getDefinition: componentName => { - if (!componentName) { - return null - } - return get(store).components[componentName] - }, - getDefaultDatasource: () => { - // Ignore users table - const validTables = get(tables).list.filter(x => x._id !== "ta_users") - - // Try to use their own internal table first - let table = validTables.find(table => { - return ( - table.sourceId !== BUDIBASE_INTERNAL_DB_ID && - table.sourceType === DB_TYPE_INTERNAL - ) - }) - if (table) { - return table - } - - // Then try sample data - table = validTables.find(table => { - return ( - table.sourceId === BUDIBASE_INTERNAL_DB_ID && - table.sourceType === DB_TYPE_INTERNAL - ) - }) - if (table) { - return table - } - - // Finally try an external table - return validTables.find(table => table.sourceType === DB_TYPE_EXTERNAL) - }, - migrateSettings: enrichedComponent => { - const componentPrefix = "@budibase/standard-components" - let migrated = false - - if (enrichedComponent?._component == `${componentPrefix}/formblock`) { - // Use default config if the 'buttons' prop has never been initialised - if (!("buttons" in enrichedComponent)) { - enrichedComponent["buttons"] = - Utils.buildFormBlockButtonConfig(enrichedComponent) - migrated = true - } else if (enrichedComponent["buttons"] == null) { - // Ignore legacy config if 'buttons' has been reset by 'resetOn' - const { _id, actionType, dataSource } = enrichedComponent - enrichedComponent["buttons"] = Utils.buildFormBlockButtonConfig({ - _id, - actionType, - dataSource, - }) - migrated = true - } - - // Ensure existing Formblocks position their buttons at the top. - if (!("buttonPosition" in enrichedComponent)) { - enrichedComponent["buttonPosition"] = "top" - migrated = true - } - } - - return migrated - }, - enrichEmptySettings: (component, opts) => { - if (!component?._component) { - return - } - const defaultDS = store.actions.components.getDefaultDatasource() - const settings = getComponentSettings(component._component) - const { parent, screen, useDefaultValues } = opts || {} - const treeId = parent?._id || component._id - if (!screen) { - return - } - settings.forEach(setting => { - const value = component[setting.key] - - // Fill empty settings - if (value == null || value === "") { - if (setting.type === "multifield" && setting.selectAllFields) { - // Select all schema fields where required - component[setting.key] = Object.keys(defaultDS?.schema || {}) - } else if ( - (setting.type === "dataSource" || setting.type === "table") && - defaultDS - ) { - // Select default datasource where required - component[setting.key] = { - label: defaultDS.name, - tableId: defaultDS._id, - resourceId: defaultDS._id, - type: "table", - } - } else if (setting.type === "dataProvider") { - // Pick closest data provider where required - const path = findComponentPath(screen.props, treeId) - const providers = path.filter(component => - component._component?.endsWith("/dataprovider") - ) - if (providers.length) { - const id = providers[providers.length - 1]?._id - component[setting.key] = `{{ literal ${safe(id)} }}` - } - } else if (setting.type.startsWith("field/")) { - // Autofill form field names - // Get all available field names in this form schema - let fieldOptions = getComponentFieldOptions( - screen.props, - treeId, - setting.type, - false - ) - - // Get all currently used fields - const form = findClosestMatchingComponent( - screen.props, - treeId, - x => x._component === "@budibase/standard-components/form" - ) - const usedFields = Object.keys(buildFormSchema(form) || {}) - - // Filter out already used fields - fieldOptions = fieldOptions.filter(x => !usedFields.includes(x)) - - // Set field name and also assume we have a label setting - if (fieldOptions[0]) { - component[setting.key] = fieldOptions[0] - component.label = fieldOptions[0] - } - } else if (useDefaultValues && setting.defaultValue !== undefined) { - // Use default value where required - component[setting.key] = setting.defaultValue - } - } - // Validate non-empty settings - else { - if (setting.type === "dataProvider") { - // Validate data provider exists, or else clear it - const providers = findAllMatchingComponents( - screen?.props, - component => component._component?.endsWith("/dataprovider") - ) - // Validate non-empty values - const valid = providers?.some(dp => value.includes?.(dp._id)) - if (!valid) { - if (providers.length) { - const id = providers[providers.length - 1]?._id - component[setting.key] = `{{ literal ${safe(id)} }}` - } else { - delete component[setting.key] - } - } - } - } - }) - }, - createInstance: (componentName, presetProps, parent) => { - const definition = store.actions.components.getDefinition(componentName) - if (!definition) { - return null - } - - // Find all existing components of this type so that we can give this - // component a unique name - const screen = get(selectedScreen).props - const otherComponents = findAllMatchingComponents( - screen, - x => x._component === definition.component && x._id !== screen._id - ) - let name = definition.friendlyName || definition.name - name = `${name} ${otherComponents.length + 1}` - - // Generate basic component structure - let instance = { - _id: Helpers.uuid(), - _component: definition.component, - _styles: { - normal: {}, - hover: {}, - active: {}, - }, - _instanceName: name, - ...presetProps, - } - - // Enrich empty settings - store.actions.components.enrichEmptySettings(instance, { - parent, - screen: get(selectedScreen), - useDefaultValues: true, - }) - - // Migrate nested component settings - store.actions.components.migrateSettings(instance) - - // Add any extra properties the component needs - let extras = {} - if (definition.hasChildren) { - extras._children = [] - } - if (componentName.endsWith("/formstep")) { - const parentForm = findClosestMatchingComponent( - get(selectedScreen).props, - get(selectedComponent)._id, - component => component._component.endsWith("/form") - ) - const formSteps = findAllMatchingComponents(parentForm, component => - component._component.endsWith("/formstep") - ) - extras.step = formSteps.length + 1 - extras._instanceName = `Step ${formSteps.length + 1}` - } - return { - ...cloneDeep(instance), - ...extras, - } - }, - create: async (componentName, presetProps, parent, index) => { - const state = get(store) - const componentInstance = store.actions.components.createInstance( - componentName, - presetProps, - parent - ) - if (!componentInstance) { - return - } - - // Insert in position if specified - if (parent && index != null) { - await store.actions.screens.patch(screen => { - let parentComponent = findComponent(screen.props, parent) - if (!parentComponent._children?.length) { - parentComponent._children = [componentInstance] - } else { - parentComponent._children.splice(index, 0, componentInstance) - } - }) - } - - // Otherwise we work out where this component should be inserted - else { - await store.actions.screens.patch(screen => { - // Find the selected component - let selectedComponentId = state.selectedComponentId - if (selectedComponentId.startsWith(`${screen._id}-`)) { - selectedComponentId = screen?.props._id - } - const currentComponent = findComponent( - screen.props, - selectedComponentId - ) - if (!currentComponent) { - return false - } - - // Find parent node to attach this component to - let parentComponent - if (currentComponent) { - // Use selected component as parent if one is selected - const definition = store.actions.components.getDefinition( - currentComponent._component - ) - if (definition?.hasChildren) { - // Use selected component if it allows children - parentComponent = currentComponent - } else { - // Otherwise we need to use the parent of this component - parentComponent = findComponentParent( - screen.props, - currentComponent._id - ) - } - } else { - // Use screen or layout if no component is selected - parentComponent = screen.props - } - - // Attach new component - if (!parentComponent) { - return false - } - if (!parentComponent._children) { - parentComponent._children = [] - } - parentComponent._children.push(componentInstance) - }) - } - - // Select new component - store.update(state => { - state.selectedComponentId = componentInstance._id - return state - }) - - // Log event - analytics.captureEvent(Events.COMPONENT_CREATED, { - name: componentInstance._component, - }) - - return componentInstance - }, - patch: async (patchFn, componentId, screenId) => { - // Use selected component by default - if (!componentId || !screenId) { - const state = get(store) - componentId = componentId || state.selectedComponentId - screenId = screenId || state.selectedScreenId - } - if (!componentId || !screenId || !patchFn) { - return - } - const patchScreen = screen => { - // findComponent looks in the tree not comp.settings[0] - let component = findComponent(screen.props, componentId) - if (!component) { - return false - } - - // Mutates the fetched component with updates - const patchResult = patchFn(component, screen) - - // Mutates the component with any required settings updates - const migrated = store.actions.components.migrateSettings(component) - - // Returning an explicit false signifies that we should skip this - // update. If we migrated something, ensure we never skip. - return migrated ? null : patchResult - } - await store.actions.screens.patch(patchScreen, screenId) - }, - delete: async component => { - if (!component) { - return - } - - // Determine the next component to select after deletion - const state = get(store) - let nextSelectedComponentId - if (state.selectedComponentId === component._id) { - nextSelectedComponentId = store.actions.components.getNext() - if (!nextSelectedComponentId) { - nextSelectedComponentId = store.actions.components.getPrevious() - } - } - - // Patch screen - await store.actions.screens.patch(screen => { - // Check component exists - component = findComponent(screen.props, component._id) - if (!component) { - return false - } - - // Check component has a valid parent - const parent = findComponentParent(screen.props, component._id) - if (!parent) { - return false - } - parent._children = parent._children.filter( - child => child._id !== component._id - ) - }) - - // Update selected component if required - if (nextSelectedComponentId) { - store.update(state => { - state.selectedComponentId = nextSelectedComponentId - return state - }) - } - }, - copy: (component, cut = false, selectParent = true) => { - // Update store with copied component - store.update(state => { - state.componentToPaste = cloneDeep(component) - state.componentToPaste.isCut = cut - return state - }) - - // Select the parent if cutting - if (cut && selectParent) { - const screen = get(selectedScreen) - const parent = findComponentParent(screen?.props, component._id) - if (parent) { - store.update(state => { - state.selectedComponentId = parent._id - return state - }) - } - } - }, - paste: async (targetComponent, mode, targetScreen) => { - const state = get(store) - if (!state.componentToPaste) { - return - } - let newComponentId - - // Remove copied component if cutting, regardless if pasting works - let componentToPaste = cloneDeep(state.componentToPaste) - if (componentToPaste.isCut) { - store.update(state => { - delete state.componentToPaste - return state - }) - } - - // Patch screen - const patch = screen => { - // Get up to date ref to target - targetComponent = findComponent(screen.props, targetComponent._id) - if (!targetComponent) { - return false - } - const cut = componentToPaste.isCut - const originalId = componentToPaste._id - delete componentToPaste.isCut - - // Make new component unique if copying - if (!cut) { - componentToPaste = makeComponentUnique(componentToPaste) - } - newComponentId = componentToPaste._id - - // Delete old component if cutting - if (cut) { - const parent = findComponentParent(screen.props, originalId) - if (parent?._children) { - parent._children = parent._children.filter( - component => component._id !== originalId - ) - } - } - - // Check inside is valid - if (mode === "inside") { - const definition = store.actions.components.getDefinition( - targetComponent._component - ) - if (!definition.hasChildren) { - mode = "below" - } - } - - // Paste new component - if (mode === "inside") { - // Paste inside target component if chosen - if (!targetComponent._children) { - targetComponent._children = [] - } - targetComponent._children.push(componentToPaste) - } else { - // Otherwise paste in the correct order in the parent's children - const parent = findComponentParent( - screen.props, - targetComponent._id - ) - if (!parent?._children) { - return false - } - const targetIndex = parent._children.findIndex(component => { - return component._id === targetComponent._id - }) - const index = mode === "above" ? targetIndex : targetIndex + 1 - parent._children.splice(index, 0, componentToPaste) - } - } - const targetScreenId = targetScreen?._id || state.selectedScreenId - await store.actions.screens.patch(patch, targetScreenId) - - // Select the new component - store.update(state => { - state.selectedScreenId = targetScreenId - state.selectedComponentId = newComponentId - return state - }) - }, - getPrevious: () => { - const state = get(store) - const componentId = state.selectedComponentId - const screen = get(selectedScreen) - const parent = findComponentParent(screen.props, componentId) - const index = parent?._children.findIndex(x => x._id === componentId) - - // Check for screen and navigation component edge cases - const screenComponentId = `${screen._id}-screen` - const navComponentId = `${screen._id}-navigation` - if (componentId === screenComponentId) { - return null - } - if (componentId === navComponentId) { - return screenComponentId - } - if (parent._id === screen.props._id && index === 0) { - return navComponentId - } - - // If we have siblings above us, choose the sibling or a descendant - if (index > 0) { - // If sibling before us accepts children, select a descendant - const previousSibling = parent._children[index - 1] - if (previousSibling._children?.length) { - let target = previousSibling - while (target._children?.length) { - target = target._children[target._children.length - 1] - } - return target._id - } - - // Otherwise just select sibling - return previousSibling._id - } - - // If no siblings above us, select the parent - return parent._id - }, - getNext: () => { - const state = get(store) - const component = get(selectedComponent) - const componentId = component?._id - const screen = get(selectedScreen) - const parent = findComponentParent(screen.props, componentId) - const index = parent?._children.findIndex(x => x._id === componentId) - - // Check for screen and navigation component edge cases - const screenComponentId = `${screen._id}-screen` - const navComponentId = `${screen._id}-navigation` - if (state.selectedComponentId === screenComponentId) { - return navComponentId - } - - // If we have children, select first child - if (component._children?.length) { - return component._children[0]._id - } else if (!parent) { - return null - } - - // Otherwise select the next sibling if we have one - if (index < parent._children.length - 1) { - const nextSibling = parent._children[index + 1] - return nextSibling._id - } - - // Last child, select our parents next sibling - let target = parent - let targetParent = findComponentParent(screen.props, target._id) - let targetIndex = targetParent?._children.findIndex( - child => child._id === target._id - ) - while ( - targetParent != null && - targetIndex === targetParent._children?.length - 1 - ) { - target = targetParent - targetParent = findComponentParent(screen.props, target._id) - targetIndex = targetParent?._children.findIndex( - child => child._id === target._id - ) - } - if (targetParent) { - return targetParent._children[targetIndex + 1]._id - } else { - return null - } - }, - selectPrevious: () => { - const previousId = store.actions.components.getPrevious() - if (previousId) { - store.update(state => { - state.selectedComponentId = previousId - return state - }) - } - }, - selectNext: () => { - const nextId = store.actions.components.getNext() - if (nextId) { - store.update(state => { - state.selectedComponentId = nextId - return state - }) - } - }, - moveUp: async component => { - await store.actions.screens.patch(screen => { - const componentId = component?._id - const parent = findComponentParent(screen.props, componentId) - - // Check we aren't right at the top of the tree - const index = parent?._children.findIndex(x => x._id === componentId) - if (!parent || (index === 0 && parent._id === screen.props._id)) { - return - } - - // Copy original component and remove it from the parent - const originalComponent = cloneDeep(parent._children[index]) - parent._children = parent._children.filter( - component => component._id !== componentId - ) - - // If we have siblings above us, move up - if (index > 0) { - // If sibling before us accepts children, move to last child of - // sibling - const previousSibling = parent._children[index - 1] - const definition = store.actions.components.getDefinition( - previousSibling._component - ) - if (definition.hasChildren) { - previousSibling._children.push(originalComponent) - } - - // Otherwise just move component above sibling - else { - parent._children.splice(index - 1, 0, originalComponent) - } - } - - // If no siblings above us, go above the parent as long as it isn't - // the screen - else if (parent._id !== screen.props._id) { - const grandParent = findComponentParent(screen.props, parent._id) - const parentIndex = grandParent._children.findIndex( - child => child._id === parent._id - ) - grandParent._children.splice(parentIndex, 0, originalComponent) - } - }) - }, - moveDown: async component => { - await store.actions.screens.patch(screen => { - const componentId = component?._id - const parent = findComponentParent(screen.props, componentId) - - // Sanity check parent is found - if (!parent?._children?.length) { - return false - } - - // Check we aren't right at the bottom of the tree - const index = parent._children.findIndex(x => x._id === componentId) - if ( - index === parent._children.length - 1 && - parent._id === screen.props._id - ) { - return - } - - // Copy the original component and remove from parent - const originalComponent = cloneDeep(parent._children[index]) - parent._children = parent._children.filter( - component => component._id !== componentId - ) - - // Move below the next sibling if we are not the last sibling - if (index < parent._children.length) { - // If the next sibling has children, become the first child - const nextSibling = parent._children[index] - const definition = store.actions.components.getDefinition( - nextSibling._component - ) - if (definition.hasChildren) { - nextSibling._children.splice(0, 0, originalComponent) - } - - // Otherwise move below next sibling - else { - parent._children.splice(index + 1, 0, originalComponent) - } - } - - // Last child, so move below our parent - else { - const grandParent = findComponentParent(screen.props, parent._id) - const parentIndex = grandParent._children.findIndex( - child => child._id === parent._id - ) - grandParent._children.splice(parentIndex + 1, 0, originalComponent) - } - }) - }, - updateStyle: async (name, value) => { - await store.actions.components.patch(component => { - if (value == null || value === "") { - delete component._styles.normal[name] - } else { - component._styles.normal[name] = value - } - }) - }, - updateStyles: async (styles, id) => { - const patchFn = component => { - component._styles.normal = { - ...component._styles.normal, - ...styles, - } - } - await store.actions.components.patch(patchFn, id) - }, - updateCustomStyle: async style => { - await store.actions.components.patch(component => { - component._styles.custom = style - }) - }, - updateConditions: async conditions => { - await store.actions.components.patch(component => { - component._conditions = conditions - }) - }, - updateSetting: async (name, value) => { - await store.actions.components.patch( - store.actions.components.updateComponentSetting(name, value) - ) - }, - updateComponentSetting: (name, value) => { - return component => { - if (!name || !component) { - return false - } - // Skip update if the value is the same - if (component[name] === value) { - return false - } - - const settings = getComponentSettings(component._component) - const updatedSetting = settings.find(setting => setting.key === name) - - // Reset dependent fields - settings.forEach(setting => { - const needsReset = - name === setting.resetOn || - (Array.isArray(setting.resetOn) && setting.resetOn.includes(name)) - if (needsReset) { - component[setting.key] = setting.defaultValue || null - } - }) - - if ( - updatedSetting?.type === "dataSource" || - updatedSetting?.type === "table" - ) { - const { schema } = getSchemaForDatasource(null, value) - const columnNames = Object.keys(schema || {}) - const multifieldKeysToSelectAll = settings - .filter(setting => { - return setting.type === "multifield" && setting.selectAllFields - }) - .map(setting => setting.key) - - multifieldKeysToSelectAll.forEach(key => { - component[key] = columnNames - }) - } - component[name] = value - return true - } - }, - requestEjectBlock: componentId => { - store.actions.preview.sendEvent("eject-block", componentId) - }, - handleEjectBlock: async (componentId, ejectedDefinition) => { - let nextSelectedComponentId - await store.actions.screens.patch(screen => { - const block = findComponent(screen.props, componentId) - const parent = findComponentParent(screen.props, componentId) - - // Sanity check - if (!block || !parent?._children?.length) { - return false - } - - // Log event - analytics.captureEvent(Events.BLOCK_EJECTED, { - block: block._component, - }) - - // Attach block children back into ejected definition, using the - // _containsSlot flag to know where to insert them - const slotContainer = findAllMatchingComponents( - ejectedDefinition, - x => x._containsSlot - )[0] - if (slotContainer) { - delete slotContainer._containsSlot - slotContainer._children = [ - ...(slotContainer._children || []), - ...(block._children || []), - ] - } - - // Replace block with ejected definition - ejectedDefinition = makeComponentUnique(ejectedDefinition) - const index = parent._children.findIndex(x => x._id === componentId) - parent._children[index] = ejectedDefinition - nextSelectedComponentId = ejectedDefinition._id - }) - - // Select new root component - if (nextSelectedComponentId) { - store.update(state => { - state.selectedComponentId = nextSelectedComponentId - return state - }) - } - }, - addParent: async (componentId, parentType) => { - if (!componentId || !parentType) { - return - } - - // Create new parent instance - const newParentDefinition = store.actions.components.createInstance( - parentType, - null, - parent - ) - if (!newParentDefinition) { - return - } - - // Replace component with a version wrapped in a new parent - await store.actions.screens.patch(screen => { - // Get this component definition and parent definition - let definition = findComponent(screen.props, componentId) - let oldParentDefinition = findComponentParent( - screen.props, - componentId - ) - if (!definition || !oldParentDefinition) { - return false - } - - // Replace component with parent - const index = oldParentDefinition._children.findIndex( - component => component._id === componentId - ) - if (index === -1) { - return false - } - oldParentDefinition._children[index] = { - ...newParentDefinition, - _children: [definition], - } - }) - - // Select the new parent - store.update(state => { - state.selectedComponentId = newParentDefinition._id - return state - }) - }, - }, - links: { - save: async (url, title) => { - 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 - } - - links.push({ - text: title, - url, - }) - await store.actions.navigation.save({ - ...navigation, - links: [...links], - }) - }, - delete: async urls => { - 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] - links = links.filter(link => !urls.includes(link.url)) - - await store.actions.navigation.save({ - ...navigation, - links, - }) - }, - }, - settings: { - highlight: key => { - store.update(state => ({ - ...state, - highlightedSettingKey: key, - })) - }, - propertyFocus: key => { - store.update(state => ({ - ...state, - propertyFocus: key, - })) - }, - }, - dnd: { - start: component => { - store.actions.preview.sendEvent("dragging-new-component", { - dragging: true, - component, - }) - }, - stop: () => { - store.actions.preview.sendEvent("dragging-new-component", { - dragging: false, - }) - }, - }, - websocket: { - selectResource: id => { - websocket.emit(BuilderSocketEvent.SelectResource, { - resourceId: id, - }) - }, - }, - metadata: { - replace: metadata => { - store.update(state => ({ - ...state, - ...metadata, - })) - }, - }, - } - - return store -} diff --git a/packages/builder/src/builderStore/store/hover.js b/packages/builder/src/builderStore/store/hover.js deleted file mode 100644 index 5db9272975..0000000000 --- a/packages/builder/src/builderStore/store/hover.js +++ /dev/null @@ -1,27 +0,0 @@ -import { get, writable } from "svelte/store" -import { store as builder } from "builderStore" - -export const getHoverStore = () => { - const initialValue = { - componentId: null, - } - - const store = writable(initialValue) - - const update = (componentId, notifyClient = true) => { - if (componentId === get(store).componentId) { - return - } - store.update(state => { - state.componentId = componentId - return state - }) - if (notifyClient) { - builder.actions.preview.sendEvent("hover-component", componentId) - } - } - return { - subscribe: store.subscribe, - actions: { update }, - } -} diff --git a/packages/builder/src/builderStore/tests/dataBinding.test.js b/packages/builder/src/builderStore/tests/dataBinding.test.js deleted file mode 100644 index 039e33a94d..0000000000 --- a/packages/builder/src/builderStore/tests/dataBinding.test.js +++ /dev/null @@ -1,545 +0,0 @@ -import { expect, describe, it, vi } from "vitest" -import { - runtimeToReadableBinding, - readableToRuntimeBinding, - updateReferencesInObject, -} from "../dataBinding" - -vi.mock("@budibase/frontend-core") -vi.mock("builderStore/componentUtils") -vi.mock("builderStore/store") -vi.mock("builderStore/store/theme") -vi.mock("builderStore/store/temporal") - -describe("runtimeToReadableBinding", () => { - const bindableProperties = [ - { - category: "Current User", - icon: "User", - providerId: "user", - readableBinding: "Current User.firstName", - runtimeBinding: "[user].[firstName]", - type: "context", - }, - { - category: "Bindings", - icon: "Brackets", - readableBinding: "Binding.count", - runtimeBinding: "count", - type: "context", - }, - ] - it("should convert a runtime binding to a readable one", () => { - const textWithBindings = `Hello {{ [user].[firstName] }}! The count is {{ count }}.` - expect( - runtimeToReadableBinding( - bindableProperties, - textWithBindings, - "readableBinding" - ) - ).toEqual( - `Hello {{ Current User.firstName }}! The count is {{ Binding.count }}.` - ) - }) - - it("should not convert to readable binding if it is already readable", () => { - const textWithBindings = `Hello {{ [user].[firstName] }}! The count is {{ Binding.count }}.` - expect( - runtimeToReadableBinding( - bindableProperties, - textWithBindings, - "readableBinding" - ) - ).toEqual( - `Hello {{ Current User.firstName }}! The count is {{ Binding.count }}.` - ) - }) -}) - -describe("readableToRuntimeBinding", () => { - const bindableProperties = [ - { - category: "Current User", - icon: "User", - providerId: "user", - readableBinding: "Current User.firstName", - runtimeBinding: "[user].[firstName]", - type: "context", - }, - { - category: "Bindings", - icon: "Brackets", - readableBinding: "Binding.count", - runtimeBinding: "count", - type: "context", - }, - ] - it("should convert a readable binding to a runtime one", () => { - const textWithBindings = `Hello {{ Current User.firstName }}! The count is {{ Binding.count }}.` - expect( - readableToRuntimeBinding( - bindableProperties, - textWithBindings, - "runtimeBinding" - ) - ).toEqual(`Hello {{ [user].[firstName] }}! The count is {{ count }}.`) - }) -}) - -describe("updateReferencesInObject", () => { - it("should increment steps in sequence on 'add'", () => { - let obj = [ - { - id: "a0", - parameters: { - text: "Alpha", - }, - }, - { - id: "a1", - parameters: { - text: "Apple", - }, - }, - { - id: "b2", - parameters: { - text: "Banana {{ actions.1.row }}", - }, - }, - { - id: "c3", - parameters: { - text: "Carrot {{ actions.1.row }}", - }, - }, - { - id: "d4", - parameters: { - text: "Dog {{ actions.3.row }}", - }, - }, - { - id: "e5", - parameters: { - text: "Eagle {{ actions.4.row }}", - }, - }, - ] - updateReferencesInObject({ - obj, - modifiedIndex: 0, - action: "add", - label: "actions", - }) - - expect(obj).toEqual([ - { - id: "a0", - parameters: { - text: "Alpha", - }, - }, - { - id: "a1", - parameters: { - text: "Apple", - }, - }, - { - id: "b2", - parameters: { - text: "Banana {{ actions.2.row }}", - }, - }, - { - id: "c3", - parameters: { - text: "Carrot {{ actions.2.row }}", - }, - }, - { - id: "d4", - parameters: { - text: "Dog {{ actions.4.row }}", - }, - }, - { - id: "e5", - parameters: { - text: "Eagle {{ actions.5.row }}", - }, - }, - ]) - }) - - it("should decrement steps in sequence on 'delete'", () => { - let obj = [ - { - id: "a1", - parameters: { - text: "Apple", - }, - }, - { - id: "b2", - parameters: { - text: "Banana {{ actions.1.row }}", - }, - }, - { - id: "d4", - parameters: { - text: "Dog {{ actions.3.row }}", - }, - }, - { - id: "e5", - parameters: { - text: "Eagle {{ actions.4.row }}", - }, - }, - ] - updateReferencesInObject({ - obj, - modifiedIndex: 2, - action: "delete", - label: "actions", - }) - - expect(obj).toEqual([ - { - id: "a1", - parameters: { - text: "Apple", - }, - }, - { - id: "b2", - parameters: { - text: "Banana {{ actions.1.row }}", - }, - }, - { - id: "d4", - parameters: { - text: "Dog {{ actions.2.row }}", - }, - }, - { - id: "e5", - parameters: { - text: "Eagle {{ actions.3.row }}", - }, - }, - ]) - }) - - it("should handle on 'move' to a lower index", () => { - let obj = [ - { - id: "a1", - parameters: { - text: "Apple", - }, - }, - { - id: "b2", - parameters: { - text: "Banana {{ actions.0.row }}", - }, - }, - { - id: "e5", - parameters: { - text: "Eagle {{ actions.3.row }}", - }, - }, - { - id: "c3", - parameters: { - text: "Carrot {{ actions.0.row }}", - }, - }, - { - id: "d4", - parameters: { - text: "Dog {{ actions.2.row }}", - }, - }, - ] - updateReferencesInObject({ - obj, - modifiedIndex: 2, - action: "move", - label: "actions", - originalIndex: 4, - }) - - expect(obj).toEqual([ - { - id: "a1", - parameters: { - text: "Apple", - }, - }, - { - id: "b2", - parameters: { - text: "Banana {{ actions.0.row }}", - }, - }, - { - id: "e5", - parameters: { - text: "Eagle {{ actions.4.row }}", - }, - }, - { - id: "c3", - parameters: { - text: "Carrot {{ actions.0.row }}", - }, - }, - { - id: "d4", - parameters: { - text: "Dog {{ actions.3.row }}", - }, - }, - ]) - }) - - it("should handle on 'move' to a higher index", () => { - let obj = [ - { - id: "b2", - parameters: { - text: "Banana {{ actions.0.row }}", - }, - }, - { - id: "c3", - parameters: { - text: "Carrot {{ actions.0.row }}", - }, - }, - { - id: "a1", - parameters: { - text: "Apple", - }, - }, - { - id: "d4", - parameters: { - text: "Dog {{ actions.2.row }}", - }, - }, - { - id: "e5", - parameters: { - text: "Eagle {{ actions.3.row }}", - }, - }, - ] - updateReferencesInObject({ - obj, - modifiedIndex: 2, - action: "move", - label: "actions", - originalIndex: 0, - }) - - expect(obj).toEqual([ - { - id: "b2", - parameters: { - text: "Banana {{ actions.2.row }}", - }, - }, - { - id: "c3", - parameters: { - text: "Carrot {{ actions.2.row }}", - }, - }, - { - id: "a1", - parameters: { - text: "Apple", - }, - }, - { - id: "d4", - parameters: { - text: "Dog {{ actions.1.row }}", - }, - }, - { - id: "e5", - parameters: { - text: "Eagle {{ actions.3.row }}", - }, - }, - ]) - }) - - it("should handle on 'move' of action being referenced, dragged to a higher index", () => { - let obj = [ - { - "##eventHandlerType": "Validate Form", - id: "cCD0Dwcnq", - }, - { - "##eventHandlerType": "Close Screen Modal", - id: "3fbbIOfN0H", - }, - { - "##eventHandlerType": "Save Row", - parameters: { - tableId: "ta_bb_employee", - }, - id: "aehg5cTmhR", - }, - { - "##eventHandlerType": "Close Side Panel", - id: "mzkpf86cxo", - }, - { - "##eventHandlerType": "Navigate To", - id: "h0uDFeJa8A", - }, - { - parameters: { - autoDismiss: true, - type: "success", - message: "{{ actions.1.row }}", - }, - "##eventHandlerType": "Show Notification", - id: "JEI5lAyJZ", - }, - ] - updateReferencesInObject({ - obj, - modifiedIndex: 2, - action: "move", - label: "actions", - originalIndex: 1, - }) - - expect(obj).toEqual([ - { - "##eventHandlerType": "Validate Form", - id: "cCD0Dwcnq", - }, - { - "##eventHandlerType": "Close Screen Modal", - id: "3fbbIOfN0H", - }, - { - "##eventHandlerType": "Save Row", - parameters: { - tableId: "ta_bb_employee", - }, - id: "aehg5cTmhR", - }, - { - "##eventHandlerType": "Close Side Panel", - id: "mzkpf86cxo", - }, - { - "##eventHandlerType": "Navigate To", - id: "h0uDFeJa8A", - }, - { - parameters: { - autoDismiss: true, - type: "success", - message: "{{ actions.2.row }}", - }, - "##eventHandlerType": "Show Notification", - id: "JEI5lAyJZ", - }, - ]) - }) - - it("should handle on 'move' of action being referenced, dragged to a lower index", () => { - let obj = [ - { - "##eventHandlerType": "Save Row", - parameters: { - tableId: "ta_bb_employee", - }, - id: "aehg5cTmhR", - }, - { - "##eventHandlerType": "Validate Form", - id: "cCD0Dwcnq", - }, - { - "##eventHandlerType": "Close Screen Modal", - id: "3fbbIOfN0H", - }, - { - "##eventHandlerType": "Close Side Panel", - id: "mzkpf86cxo", - }, - { - "##eventHandlerType": "Navigate To", - id: "h0uDFeJa8A", - }, - { - parameters: { - autoDismiss: true, - type: "success", - message: "{{ actions.4.row }}", - }, - "##eventHandlerType": "Show Notification", - id: "JEI5lAyJZ", - }, - ] - updateReferencesInObject({ - obj, - modifiedIndex: 0, - action: "move", - label: "actions", - originalIndex: 4, - }) - - expect(obj).toEqual([ - { - "##eventHandlerType": "Save Row", - parameters: { - tableId: "ta_bb_employee", - }, - id: "aehg5cTmhR", - }, - { - "##eventHandlerType": "Validate Form", - id: "cCD0Dwcnq", - }, - { - "##eventHandlerType": "Close Screen Modal", - id: "3fbbIOfN0H", - }, - { - "##eventHandlerType": "Close Side Panel", - id: "mzkpf86cxo", - }, - { - "##eventHandlerType": "Navigate To", - id: "h0uDFeJa8A", - }, - { - parameters: { - autoDismiss: true, - type: "success", - message: "{{ actions.0.row }}", - }, - "##eventHandlerType": "Show Notification", - id: "JEI5lAyJZ", - }, - ]) - }) -}) diff --git a/packages/builder/src/components/automation/AutomationBuilder/AutomationBuilder.svelte b/packages/builder/src/components/automation/AutomationBuilder/AutomationBuilder.svelte index b80ba45086..caeb33cb14 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/AutomationBuilder.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/AutomationBuilder.svelte @@ -1,5 +1,5 @@ diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte index fbc79b967c..72cedb2b21 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte @@ -9,11 +9,11 @@ Tags, Tag, } from "@budibase/bbui" - import { automationStore, selectedAutomation } from "builderStore" + import { automationStore, selectedAutomation } from "stores/builder" import { admin, licensing } from "stores/portal" import { externalActions } from "./ExternalActions" import { TriggerStepID, ActionStepID } from "constants/backend/automations" - import { checkForCollectStep } from "builderStore/utils" + import { checkForCollectStep } from "helpers/utils" export let blockIdx export let lastStep @@ -128,10 +128,10 @@ >
zapier diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/AutomationBlockTagline.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/AutomationBlockTagline.svelte index c18368b1b1..8732623dcf 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/AutomationBlockTagline.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/AutomationBlockTagline.svelte @@ -1,7 +1,7 @@ diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte index cce0f4eeab..9d946fe55d 100644 --- a/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte +++ b/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte @@ -4,7 +4,7 @@ automationStore, selectedAutomation, userSelectedResourceMap, - } from "builderStore" + } from "stores/builder" import NavItem from "components/common/NavItem.svelte" import EditAutomationPopover from "./EditAutomationPopover.svelte" import { notifications } from "@budibase/bbui" diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte index d8651f238a..582db950fe 100644 --- a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte +++ b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte @@ -7,7 +7,7 @@ automationStore, selectedAutomation, userSelectedResourceMap, - } from "builderStore" + } from "stores/builder" import NavItem from "components/common/NavItem.svelte" import EditAutomationPopover from "./EditAutomationPopover.svelte" diff --git a/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte b/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte index 9f279427d9..41bffba19e 100644 --- a/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte +++ b/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte @@ -1,5 +1,5 @@ diff --git a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte index 23697bf2c7..23081c92c4 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte @@ -3,13 +3,13 @@ import { Layout } from "@budibase/bbui" import { BUDIBASE_INTERNAL_DB_ID } from "constants/backend" import { - database, datasources, queries, tables, views, viewsV2, - } from "stores/backend" + userSelectedResourceMap, + } from "stores/builder" import EditDatasourcePopover from "./popovers/EditDatasourcePopover.svelte" import EditQueryPopover from "./popovers/EditQueryPopover.svelte" import NavItem from "components/common/NavItem.svelte" @@ -21,7 +21,6 @@ } from "helpers/data/utils" import IntegrationIcon from "./IntegrationIcon.svelte" import { TableNames } from "constants" - import { userSelectedResourceMap } from "builderStore" import { enrichDatasources } from "./datasourceUtils" import { onMount } from "svelte" @@ -75,69 +74,67 @@ searchTerm && !showAppUsersTable && !enrichedDataSources.find(ds => ds.show) -{#if $database?._id} -
- {#if showAppUsersTable} - selectTable(TableNames.USERS)} - selectedBy={$userSelectedResourceMap[TableNames.USERS]} - /> - {/if} - {#each enrichedDataSources.filter(ds => ds.show) as datasource} - selectDatasource(datasource)} - on:iconClick={() => toggleNode(datasource)} - selectedBy={$userSelectedResourceMap[datasource._id]} - > -
- -
- {#if datasource._id !== BUDIBASE_INTERNAL_DB_ID} - - {/if} -
- - {#if datasource.open} - - {#each datasource.queries as query} - $goto(`./query/${query._id}`)} - selectedBy={$userSelectedResourceMap[query._id]} - > - - - {/each} +
+ {#if showAppUsersTable} + selectTable(TableNames.USERS)} + selectedBy={$userSelectedResourceMap[TableNames.USERS]} + /> + {/if} + {#each enrichedDataSources.filter(ds => ds.show) as datasource} + selectDatasource(datasource)} + on:iconClick={() => toggleNode(datasource)} + selectedBy={$userSelectedResourceMap[datasource._id]} + > +
+ +
+ {#if datasource._id !== BUDIBASE_INTERNAL_DB_ID} + {/if} - {/each} - {#if showNoResults} - -
- There aren't any datasources matching that name -
-
+
+ + {#if datasource.open} + + {#each datasource.queries as query} + $goto(`./query/${query._id}`)} + selectedBy={$userSelectedResourceMap[query._id]} + > + + + {/each} {/if} -
-{/if} + {/each} + {#if showNoResults} + +
+ There aren't any datasources matching that name +
+
+ {/if} +
diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DeleteRow.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DeleteRow.svelte index 1e79c51051..b8459ac0eb 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DeleteRow.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DeleteRow.svelte @@ -1,6 +1,6 @@ diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveRow.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveRow.svelte index 9f70272d78..a1fe773455 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveRow.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveRow.svelte @@ -1,8 +1,12 @@ - + diff --git a/packages/builder/src/components/design/settings/controls/ColumnEditor/CellDrawer.svelte b/packages/builder/src/components/design/settings/controls/ColumnEditor/CellDrawer.svelte index 9e53f7f1cf..f5167e3657 100644 --- a/packages/builder/src/components/design/settings/controls/ColumnEditor/CellDrawer.svelte +++ b/packages/builder/src/components/design/settings/controls/ColumnEditor/CellDrawer.svelte @@ -7,7 +7,7 @@ Layout, Label, } from "@budibase/bbui" - import { store } from "builderStore" + import { themeStore } from "stores/builder" import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" export let column @@ -46,7 +46,7 @@ (column.background = e.detail)} - spectrumTheme={$store.theme} + spectrumTheme={$themeStore.theme} /> @@ -54,7 +54,7 @@ (column.color = e.detail)} - spectrumTheme={$store.theme} + spectrumTheme={$themeStore.theme} /> diff --git a/packages/builder/src/components/design/settings/controls/ColumnEditor/ColumnEditor.svelte b/packages/builder/src/components/design/settings/controls/ColumnEditor/ColumnEditor.svelte index cebb429ac4..2b9fa573c2 100644 --- a/packages/builder/src/components/design/settings/controls/ColumnEditor/ColumnEditor.svelte +++ b/packages/builder/src/components/design/settings/controls/ColumnEditor/ColumnEditor.svelte @@ -3,11 +3,8 @@ import { createEventDispatcher } from "svelte" import ColumnDrawer from "./ColumnDrawer.svelte" import { cloneDeep } from "lodash/fp" - import { - getDatasourceForProvider, - getSchemaForDatasource, - } from "builderStore/dataBinding" - import { currentAsset } from "builderStore" + import { getDatasourceForProvider, getSchemaForDatasource } from "dataBinding" + import { selectedScreen } from "stores/builder" import { getFields } from "helpers/searchFields" export let componentInstance @@ -21,8 +18,8 @@ let boundValue $: text = getText(value) - $: datasource = getDatasourceForProvider($currentAsset, componentInstance) - $: schema = getSchema($currentAsset, datasource) + $: datasource = getDatasourceForProvider($selectedScreen, componentInstance) + $: schema = getSchema($selectedScreen, datasource) $: options = allowCellEditing ? Object.keys(schema || {}) : enrichedSchemaFields?.map(field => field.name) diff --git a/packages/builder/src/components/design/settings/controls/DataProviderSelect.svelte b/packages/builder/src/components/design/settings/controls/DataProviderSelect.svelte index 9fd220e798..2e74cac0f4 100644 --- a/packages/builder/src/components/design/settings/controls/DataProviderSelect.svelte +++ b/packages/builder/src/components/design/settings/controls/DataProviderSelect.svelte @@ -1,14 +1,14 @@ diff --git a/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceSelect.svelte b/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceSelect.svelte index 3eb69e9a3b..14cbc973a1 100644 --- a/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceSelect.svelte +++ b/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceSelect.svelte @@ -2,7 +2,7 @@ import { readableToRuntimeBinding, runtimeToReadableBinding, - } from "builderStore/dataBinding" + } from "dataBinding" import { Button, Popover, @@ -17,19 +17,20 @@ notifications, } from "@budibase/bbui" import { createEventDispatcher } from "svelte" - import { store, currentAsset } from "builderStore" import { tables as tablesStore, queries as queriesStore, viewsV2 as viewsV2Store, views as viewsStore, + selectedScreen, + componentStore, datasources, integrations, - } from "stores/backend" + } from "stores/builder" import BindingBuilder from "components/integration/QueryBindingBuilder.svelte" import IntegrationQueryEditor from "components/integration/index.svelte" import { makePropSafe as safe } from "@budibase/string-templates" - import { findAllComponents } from "builderStore/componentUtils" + import { findAllComponents } from "helpers/components" import ClientBindingPanel from "components/common/bindings/ClientBindingPanel.svelte" import DataSourceCategory from "components/design/settings/controls/DataSourceSelect/DataSourceCategory.svelte" import { API } from "api" @@ -75,11 +76,11 @@ ...query, type: "query", })) - $: dataProviders = findAllComponents($currentAsset.props) + $: dataProviders = findAllComponents($selectedScreen.props) .filter(component => { return ( component._component?.endsWith("/dataprovider") && - component._id !== $store.selectedComponentId + component._id !== $componentStore.selectedComponentId ) }) .map(provider => ({ diff --git a/packages/builder/src/components/design/settings/controls/EditComponentPopover.svelte b/packages/builder/src/components/design/settings/controls/EditComponentPopover.svelte index 04bb925873..4e645fe343 100644 --- a/packages/builder/src/components/design/settings/controls/EditComponentPopover.svelte +++ b/packages/builder/src/components/design/settings/controls/EditComponentPopover.svelte @@ -1,9 +1,9 @@
diff --git a/packages/builder/src/components/design/settings/controls/FieldSelect.svelte b/packages/builder/src/components/design/settings/controls/FieldSelect.svelte index 7d1741df17..e50a0e8030 100644 --- a/packages/builder/src/components/design/settings/controls/FieldSelect.svelte +++ b/packages/builder/src/components/design/settings/controls/FieldSelect.svelte @@ -1,10 +1,7 @@ diff --git a/packages/builder/src/components/design/settings/controls/GridColumnConfiguration/GridColumnConfiguration.svelte b/packages/builder/src/components/design/settings/controls/GridColumnConfiguration/GridColumnConfiguration.svelte index 4286328367..439bf5e261 100644 --- a/packages/builder/src/components/design/settings/controls/GridColumnConfiguration/GridColumnConfiguration.svelte +++ b/packages/builder/src/components/design/settings/controls/GridColumnConfiguration/GridColumnConfiguration.svelte @@ -1,9 +1,6 @@ diff --git a/packages/builder/src/components/design/settings/controls/GridColumnConfiguration/PrimaryColumnFieldSetting.svelte b/packages/builder/src/components/design/settings/controls/GridColumnConfiguration/PrimaryColumnFieldSetting.svelte index 1cb29ac6e7..57423e8667 100644 --- a/packages/builder/src/components/design/settings/controls/GridColumnConfiguration/PrimaryColumnFieldSetting.svelte +++ b/packages/builder/src/components/design/settings/controls/GridColumnConfiguration/PrimaryColumnFieldSetting.svelte @@ -4,7 +4,7 @@ import { setContext } from "svelte" import { writable } from "svelte/store" import { FieldTypeToComponentMap } from "../FieldConfiguration/utils" - import { store } from "builderStore" + import { componentStore } from "stores/builder" export let item export let anchor @@ -35,7 +35,7 @@ const component = `@budibase/standard-components/${ FieldTypeToComponentMap[item.columnType] }` - return store.actions.components.getDefinition(component)?.icon + return componentStore.getDefinition(component)?.icon } $: icon = getIcon(item) diff --git a/packages/builder/src/components/design/settings/controls/LayoutSelect.svelte b/packages/builder/src/components/design/settings/controls/LayoutSelect.svelte index eed01c0d94..a7966eb671 100644 --- a/packages/builder/src/components/design/settings/controls/LayoutSelect.svelte +++ b/packages/builder/src/components/design/settings/controls/LayoutSelect.svelte @@ -1,5 +1,5 @@ diff --git a/packages/builder/src/components/design/settings/controls/RelationshipFilterEditor.svelte b/packages/builder/src/components/design/settings/controls/RelationshipFilterEditor.svelte index 0eb93732c3..43f158bef3 100644 --- a/packages/builder/src/components/design/settings/controls/RelationshipFilterEditor.svelte +++ b/packages/builder/src/components/design/settings/controls/RelationshipFilterEditor.svelte @@ -1,14 +1,10 @@ diff --git a/packages/builder/src/components/design/settings/controls/ValidationEditor/ValidationDrawer.svelte b/packages/builder/src/components/design/settings/controls/ValidationEditor/ValidationDrawer.svelte index 25c7651d35..3a98de94cd 100644 --- a/packages/builder/src/components/design/settings/controls/ValidationEditor/ValidationDrawer.svelte +++ b/packages/builder/src/components/design/settings/controls/ValidationEditor/ValidationDrawer.svelte @@ -10,12 +10,9 @@ Input, DatePicker, } from "@budibase/bbui" - import { currentAsset, selectedComponent } from "builderStore" - import { findClosestMatchingComponent } from "builderStore/componentUtils" - import { - getSchemaForDatasource, - getDatasourceForProvider, - } from "builderStore/dataBinding" + import { selectedScreen, selectedComponent } from "stores/builder" + import { findClosestMatchingComponent } from "helpers/components" + import { getSchemaForDatasource, getDatasourceForProvider } from "dataBinding" import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" import { generate } from "shortid" @@ -127,13 +124,14 @@ ], } - const resolveDatasource = (currentAsset, componentInstance, parent) => { + const resolveDatasource = (selectedScreen, componentInstance, parent) => { return ( - getDatasourceForProvider(currentAsset, parent || componentInstance) || {} + getDatasourceForProvider(selectedScreen, parent || componentInstance) || + {} ) } - $: dataSourceSchema = getDataSourceSchema($currentAsset, $selectedComponent) + $: dataSourceSchema = getDataSourceSchema($selectedScreen, $selectedComponent) $: field = fieldName || $selectedComponent?.field $: schemaRules = parseRulesFromSchema(field, dataSourceSchema || {}) $: fieldType = type?.split("/")[1] || "string" diff --git a/packages/builder/src/components/integration/AccessLevelSelect.svelte b/packages/builder/src/components/integration/AccessLevelSelect.svelte index 3dc24983d3..05b336c3b3 100644 --- a/packages/builder/src/components/integration/AccessLevelSelect.svelte +++ b/packages/builder/src/components/integration/AccessLevelSelect.svelte @@ -1,6 +1,6 @@ diff --git a/packages/builder/src/components/start/CreateAppModal.svelte b/packages/builder/src/components/start/CreateAppModal.svelte index 9e831f5bd9..b582232207 100644 --- a/packages/builder/src/components/start/CreateAppModal.svelte +++ b/packages/builder/src/components/start/CreateAppModal.svelte @@ -7,7 +7,7 @@ ModalContent, Dropzone, } from "@budibase/bbui" - import { store, automationStore } from "builderStore" + import { initialise } from "stores/builder" import { API } from "api" import { apps, admin, auth } from "stores/portal" import { onMount } from "svelte" @@ -132,8 +132,9 @@ // Select Correct Application/DB in prep for creating user const pkg = await API.fetchAppPackage(createdApp.instance._id) - await store.actions.initialise(pkg) - await automationStore.actions.fetch() + + await initialise(pkg) + // Update checklist - in case first app await admin.init() diff --git a/packages/builder/src/components/start/ImportAppModal.svelte b/packages/builder/src/components/start/ImportAppModal.svelte index 1bc32dc7a4..4c88593514 100644 --- a/packages/builder/src/components/start/ImportAppModal.svelte +++ b/packages/builder/src/components/start/ImportAppModal.svelte @@ -9,7 +9,7 @@ Body, } from "@budibase/bbui" import { API } from "api" - import { automationStore, store } from "../../builderStore" + import { initialise } from "stores/builder" export let app @@ -28,8 +28,8 @@ const appId = app.devId await API.updateAppFromExport(appId, data) const pkg = await API.fetchAppPackage(appId) - await store.actions.initialise(pkg) - await automationStore.actions.fetch() + await initialise(pkg) + notifications.success("App updated successfully") } catch (err) { notifications.error(`Failed to update app - ${err.message || err}`) diff --git a/packages/builder/src/components/usage/Usage.svelte b/packages/builder/src/components/usage/Usage.svelte index 897a7da3dd..da1bb4489a 100644 --- a/packages/builder/src/components/usage/Usage.svelte +++ b/packages/builder/src/components/usage/Usage.svelte @@ -1,6 +1,6 @@ @@ -31,7 +30,7 @@ on:click|self={close} >
diff --git a/packages/builder/src/pages/builder/app/[application]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/_layout.svelte index 1df2a90250..c7f8c98e73 100644 --- a/packages/builder/src/pages/builder/app/[application]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_layout.svelte @@ -1,11 +1,13 @@ -{#if $store.builderSidePanel} +{#if $builderStore.builderSidePanel} {/if} -
+
- {#if $store.initialised} + {#if $appStore.initialised}
- {$store.name} + {$appStore.name}
@@ -190,7 +182,7 @@ {/await}
-{#if $store.showPreview} +{#if $previewStore.showPreview} {/if} diff --git a/packages/builder/src/pages/builder/app/[application]/automation/[automationId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/automation/[automationId]/_layout.svelte index 3be71a1bbe..9d5f716e0e 100644 --- a/packages/builder/src/pages/builder/app/[application]/automation/[automationId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/automation/[automationId]/_layout.svelte @@ -1,5 +1,5 @@ -{#if $database._id && query} +{#if query} {#if isRestQuery} {:else} diff --git a/packages/builder/src/pages/builder/app/[application]/data/query/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/query/index.svelte index 6e53f69bcc..277970defa 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/query/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/query/index.svelte @@ -1,6 +1,6 @@ -{#if $database._id && datasource && query} +{#if datasource && query} {#if isRestQuery} {:else} diff --git a/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_layout.svelte index e166a509c4..8c60dbdd69 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_layout.svelte @@ -1,12 +1,11 @@ -{#if $database?._id && $tables?.selected?.name} +{#if $tables?.selected?.name} {#if duplicates?.length}
diff --git a/packages/builder/src/pages/builder/app/[application]/data/table/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/table/index.svelte index f513d8ceb9..3f21e48672 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/table/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/table/index.svelte @@ -1,6 +1,6 @@ -{#if $database._id && selectedView} +{#if selectedView} {:else}Create your first table to start building{/if} diff --git a/packages/builder/src/pages/builder/app/[application]/data/view/v2/[viewId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/data/view/v2/[viewId]/_layout.svelte index 8ddd6adbd0..3d0cffc387 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/view/v2/[viewId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/view/v2/[viewId]/_layout.svelte @@ -1,12 +1,11 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/index.svelte index f9f994ce67..50e1ad0cf8 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Navigation/index.svelte @@ -17,15 +17,20 @@ Select, Combobox, } from "@budibase/bbui" - import { selectedScreen, store } from "builderStore" + import { + themeStore, + selectedScreen, + screenStore, + navigationStore, + } from "stores/builder" import { DefaultAppTheme } from "constants" - $: screenRouteOptions = $store.screens + $: screenRouteOptions = $screenStore.screens .map(screen => screen.routing?.route) .filter(x => x != null) const updateShowNavigation = async e => { - await store.actions.screens.updateSetting( + await screenStore.updateSetting( get(selectedScreen), "showNavigation", e.detail @@ -34,9 +39,9 @@ const update = async (key, value) => { try { - let navigation = $store.navigation + let navigation = $navigationStore navigation[key] = value - await store.actions.navigation.save(navigation) + await navigationStore.save(navigation) } catch (error) { notifications.error("Error updating navigation settings") } @@ -45,7 +50,7 @@ @@ -56,13 +61,13 @@
Show nav on this screen
- {#if $selectedScreen.showNavigation} + {#if $selectedScreen?.showNavigation}
@@ -81,25 +86,25 @@
update("navigation", "Top")} /> update("navigation", "Left")} /> - {#if $store.navigation.navigation === "Top"} + {#if $navigationStore.navigation === "Top"}
update("sticky", e.detail)} />
@@ -108,7 +113,7 @@ update("title", e.detail)} updateOnChange={false} /> @@ -133,8 +138,8 @@
update("navBackground", e.detail)} /> @@ -142,8 +147,8 @@
update("navTextColor", e.detail)} />
@@ -159,15 +164,15 @@
update("hideLogo", !e.detail)} /> - {#if !$store.navigation.hideLogo} + {#if !$navigationStore.hideLogo}
update("logoUrl", e.detail)} updateOnChange={false} /> @@ -175,7 +180,7 @@
update("logoLinkUrl", e.detail)} options={screenRouteOptions} /> @@ -183,7 +188,7 @@
update("openLogoLinkInNewTab", !!e.detail)} /> {/if} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/AppThemeSelect.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/AppThemeSelect.svelte index 86a897bf60..9c63ef4d13 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/AppThemeSelect.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/AppThemeSelect.svelte @@ -1,11 +1,11 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePanel.svelte index 13a008fae0..8b3128f852 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePanel.svelte @@ -7,21 +7,17 @@ Icon, Body, } from "@budibase/bbui" - import { store } from "builderStore" - import { get } from "svelte/store" + import { themeStore, appStore } from "stores/builder" import { DefaultAppTheme } from "constants" import AppThemeSelect from "./AppThemeSelect.svelte" import ButtonRoundnessSelect from "./ButtonRoundnessSelect.svelte" import PropertyControl from "components/design/settings/controls/PropertyControl.svelte" - $: customTheme = $store.customTheme || {} + $: customTheme = $themeStore.customTheme || {} const update = async (property, value) => { try { - store.actions.customTheme.save({ - ...get(store).customTheme, - [property]: value, - }) + themeStore.saveCustom({ [property]: value }, $appStore.appId) } catch (error) { notifications.error("Error updating custom theme") } @@ -49,7 +45,7 @@ value={customTheme.primaryColor || DefaultAppTheme.primaryColor} onChange={val => update("primaryColor", val)} props={{ - spectrumTheme: $store.theme, + spectrumTheme: $themeStore.theme, }} /> update("primaryColorHover", val)} props={{ - spectrumTheme: $store.theme, + spectrumTheme: $themeStore.theme, }} /> diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte index 778fa303cc..8a544eac86 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte @@ -1,7 +1,7 @@ - -
-
- {#each tabs as tab} - { - activeTab = tab - }} - > - {capitalise(tab)} - - {/each} +{#if $selectedScreen} + +
+
+ {#each tabs as tab} + { + activeTab = tab + }} + > + {capitalise(tab)} + + {/each} +
-
- - {#if activeTab === "theme"} - - {:else} - - {/if} - - + + {#if activeTab === "theme"} + + {:else} + + {/if} + + +{/if}