From 79da5956b82105e4b2d3ab6a535e85b94ae33a8f Mon Sep 17 00:00:00 2001 From: Dean Date: Mon, 30 Oct 2023 12:46:44 +0000 Subject: [PATCH 01/83] Patch from original environment --- packages/builder/package.json | 2 +- packages/builder/src/api.js | 4 +- .../{builderStore => builder}/dataBinding.js | 32 +- .../schemaGenerator.js | 0 .../createFromScratchScreen.js | 0 .../store/screenTemplates/index.js | 0 .../store/screenTemplates/rowListScreen.js | 0 .../screenTemplates/utils/BaseStructure.js | 0 .../store/screenTemplates/utils/Component.js | 0 .../store/screenTemplates/utils/Screen.js | 5 + .../screenTemplates/utils/commonComponents.js | 0 .../screenTemplates/utils/sanitizeUrl.js | 0 .../src/{builderStore => builder}/utils.js | 0 packages/builder/src/builderStore/index.js | 151 -- .../src/builderStore/store/frontend.js | 1453 ----------------- .../AutomationBuilder.svelte | 2 +- .../FlowChart/ActionModal.svelte | 4 +- .../FlowChart/FlowChart.svelte | 7 +- .../FlowChart/FlowItem.svelte | 2 +- .../FlowChart/FlowItemHeader.svelte | 2 +- .../FlowChart/TestDataModal.svelte | 2 +- .../AutomationBuilder/TestPanel.svelte | 2 +- .../AutomationPanel/AutomationList.svelte | 2 +- .../CreateAutomationModal.svelte | 2 +- .../EditAutomationPopover.svelte | 2 +- .../UpdateAutomationModal.svelte | 2 +- .../SetupPanel/AutomationBlockSetup.svelte | 4 +- .../Shared/CreateWebhookModal.svelte | 2 +- .../backend/DataTable/TableDataTable.svelte | 8 +- .../DataTable/modals/CreateEditColumn.svelte | 2 +- .../DataTable/modals/JSONSchemaModal.svelte | 2 +- .../modals/grid/GridUsersTableButton.svelte | 7 +- .../DatasourceNavigator.svelte | 11 +- .../TableNavigator/TableNavigator.svelte | 5 +- .../popovers/EditTablePopover.svelte | 6 +- .../commandPalette/CommandPalette.svelte | 19 +- .../common/CodeEditor/CodeEditor.svelte | 2 +- .../components/common/CodeMirrorEditor.svelte | 2 +- .../common/bindings/BindableCombobox.svelte | 2 +- .../common/bindings/BindingPanel.svelte | 2 +- .../bindings/DrawerBindableCombobox.svelte | 2 +- .../bindings/DrawerBindableInput.svelte | 13 +- .../common/bindings/DrawerBindableSlot.svelte | 2 +- .../common/bindings/ModalBindableInput.svelte | 2 +- .../src/components/deploy/AppActions.svelte | 45 +- .../CreateWebhookDeploymentModal.svelte | 2 +- .../src/components/deploy/DeleteModal.svelte | 13 +- .../src/components/deploy/RevertModal.svelte | 8 +- .../src/components/deploy/VersionModal.svelte | 29 +- .../design/ScreenDetailsModal.svelte | 6 +- .../ButtonActionDrawer.svelte | 2 +- .../actions/ChangeFormStep.svelte | 6 +- .../actions/ClearForm.svelte | 6 +- .../actions/DuplicateRow.svelte | 10 +- .../actions/ExportData.svelte | 6 +- .../actions/NavigateTo.svelte | 4 +- .../actions/OpenSidePanel.svelte | 4 +- .../actions/RefreshDataProvider.svelte | 6 +- .../actions/S3Upload.svelte | 4 +- .../ButtonActionEditor/actions/SaveRow.svelte | 12 +- .../actions/ScrollTo.svelte | 8 +- .../actions/TriggerAutomation.svelte | 2 +- .../actions/UpdateFieldValue.svelte | 8 +- .../actions/UpdateState.svelte | 2 +- .../actions/ValidateForm.svelte | 6 +- .../controls/ButtonActionEditor/index.js | 4 +- .../settings/controls/ColorPicker.svelte | 4 +- .../controls/ColumnEditor/CellDrawer.svelte | 6 +- .../controls/ColumnEditor/ColumnEditor.svelte | 4 +- .../controls/DataProviderSelect.svelte | 9 +- .../settings/controls/DataSourceSelect.svelte | 6 +- .../EditFieldPopover.svelte | 9 +- .../FieldConfiguration.svelte | 7 +- .../settings/controls/FieldSelect.svelte | 4 +- .../controls/FilterEditor/FilterEditor.svelte | 4 +- .../settings/controls/FormFieldSelect.svelte | 2 +- .../settings/controls/LayoutSelect.svelte | 4 +- .../settings/controls/MultiFieldSelect.svelte | 4 +- .../settings/controls/PropertyControl.svelte | 6 +- .../controls/RelationshipFilterEditor.svelte | 6 +- .../controls/ResetFieldsButton.svelte | 8 +- .../controls/SearchFieldSelect.svelte | 4 +- .../controls/SortableFieldSelect.svelte | 4 +- .../design/settings/controls/URLSelect.svelte | 4 +- .../ValidationEditor/ValidationDrawer.svelte | 6 +- .../integration/QueryBindingBuilder.svelte | 2 +- .../components/integration/QueryEditor.svelte | 2 +- .../QueryViewerBindingBuilder.svelte | 4 +- .../integration/RestQueryViewer.svelte | 2 +- .../portal/licensing/LicensingOverlays.svelte | 3 +- .../portal/licensing/licensingBanners.js | 3 +- .../portal/onboarding/TourPopover.svelte | 21 +- .../portal/onboarding/TourWrap.svelte | 4 +- .../portal/onboarding/tourHandler.js | 10 +- .../src/components/portal/onboarding/tours.js | 10 +- .../src/components/settings/ThemeModal.svelte | 2 +- .../components/start/CreateAppModal.svelte | 9 +- .../components/start/ImportAppModal.svelte | 6 +- packages/builder/src/helpers/formFields.js | 4 +- .../_components/BuilderSidePanel.svelte | 22 +- .../_components/PreviewOverlay.svelte | 21 +- .../builder/app/[application]/_layout.svelte | 53 +- .../automation/[automationId]/_layout.svelte | 2 +- .../[application]/automation/_layout.svelte | 11 +- .../app/[application]/automation/index.svelte | 2 +- .../GoogleButton.svelte | 4 +- .../RestAuthenticationModal.svelte | 5 +- .../_components/panels/Headers.svelte | 2 +- .../_components/panels/Variables/index.svelte | 2 +- .../datasource/[datasourceId]/_layout.svelte | 4 +- .../data/datasource/bb_internal/index.svelte | 4 +- .../index.svelte | 4 +- .../data/query/[queryId]/_layout.svelte | 4 +- .../data/query/[queryId]/index.svelte | 3 +- .../query/new/[datasourceId]/index.svelte | 3 +- .../data/table/[tableId]/_layout.svelte | 4 +- .../data/table/[tableId]/index.svelte | 3 +- .../data/view/v1/[viewName]/_layout.svelte | 4 +- .../data/view/v1/[viewName]/index.svelte | 3 +- .../data/view/v2/[viewId]/_layout.svelte | 4 +- .../Component/ComponentSettingsPanel.svelte | 14 +- .../Component/ComponentSettingsSection.svelte | 9 +- .../Component/ConditionalUIDrawer.svelte | 4 +- .../Component/ConditionalUISection.svelte | 4 +- .../Component/CustomStylesSection.svelte | 8 +- .../_components/Component/StyleSection.svelte | 4 +- .../_components/Navigation/LinksDrawer.svelte | 4 +- .../_components/Navigation/LinksEditor.svelte | 8 +- .../_components/Navigation/index.svelte | 53 +- .../_components/Screen/AppThemeSelect.svelte | 6 +- .../_components/Screen/GeneralPanel.svelte | 14 +- .../_components/Screen/ThemePanel.svelte | 14 +- .../_components/Screen/index.svelte | 62 +- .../[screenId]/[componentId]/_layout.svelte | 20 +- .../new/_components/NewComponentPanel.svelte | 27 +- .../[screenId]/_components/AppPanel.svelte | 8 +- .../[screenId]/_components/AppPreview.svelte | 72 +- .../ComponentDropdownMenu.svelte | 6 +- .../ComponentList/ComponentKeyHandler.svelte | 32 +- .../ComponentList/ComponentTree.svelte | 23 +- .../ScreenslotDropdownMenu.svelte | 10 +- .../_components/ComponentList/dndStore.js | 15 +- .../_components/ComponentList/index.svelte | 27 +- .../_components/DevicePreviewSelect.svelte | 14 +- .../ScreenList/DropdownMenu.svelte | 16 +- .../_components/ScreenList/index.svelte | 8 +- .../design/[screenId]/_layout.svelte | 7 +- .../design/[screenId]/index.svelte | 4 +- .../NewScreen/CreateScreenModal.svelte | 16 +- .../NewScreen/DatasourceModal.svelte | 2 +- .../NewScreen/ScreenRoleModal.svelte | 4 +- .../design/_components/NewScreen/index.svelte | 4 +- .../app/[application]/design/index.svelte | 6 +- .../app/[application]/design/new.svelte | 4 +- .../app/[application]/settings/_layout.svelte | 2 +- .../_components/HistoryDetailsPanel.svelte | 2 +- .../settings/automation-history/index.svelte | 4 +- .../_components/ActionsRenderer.svelte | 2 +- .../settings/backups/index.svelte | 12 +- .../app/[application]/settings/embed.svelte | 4 +- .../settings/exportImport.svelte | 4 +- .../settings/name-and-url.svelte | 24 +- .../app/[application]/settings/version.svelte | 10 +- .../pages/builder/portal/apps/index.svelte | 7 +- .../portal/apps/onboarding/index.svelte | 7 +- .../builder/portal/users/users/index.svelte | 2 +- .../builder/src/stores/backend/database.js | 3 - packages/builder/src/stores/backend/index.js | 43 +- .../builder/src/stores/frontend/BudiStore.js | 27 + packages/builder/src/stores/frontend/app.js | 100 ++ .../frontend/automations.js} | 35 +- .../builder/src/stores/frontend/builder.js | 102 ++ .../src/stores/frontend/components/index.js | 938 +++++++++++ .../frontend/components/utils.js} | 4 +- .../builder/src/stores/frontend/database.js | 17 + .../store => stores/frontend}/deployments.js | 8 +- .../store => stores/frontend}/history.js | 0 packages/builder/src/stores/frontend/index.js | 88 + .../builder/src/stores/frontend/layouts.js | 82 + .../builder/src/stores/frontend/navigation.js | 86 + .../builder/src/stores/frontend/preview.js | 66 + .../builder/src/stores/frontend/screens.js | 517 ++++++ .../src/stores/frontend/tests/app.test.js | 135 ++ .../src/stores/frontend/tests/builder.test.js | 184 +++ .../src/stores/frontend/tests/fixtures.js | 161 ++ .../frontend/tests}/history.test.js | 2 +- .../stores/frontend/tests/navigation.test.js | 244 +++ .../src/stores/frontend/tests/screens.test.js | 803 +++++++++ packages/builder/src/stores/frontend/theme.js | 64 + .../store => stores/frontend}/users.js | 24 +- .../frontend}/websocket.js | 25 +- packages/builder/src/stores/portal/index.js | 2 + .../store => stores/portal}/temporal.js | 4 +- .../store => stores/portal}/theme.js | 3 + packages/builder/vite.config.js | 4 +- .../client/src/components/app/Layout.svelte | 8 +- packages/client/src/sdk.js | 2 + 197 files changed, 4422 insertions(+), 2277 deletions(-) rename packages/builder/src/{builderStore => builder}/dataBinding.js (97%) rename packages/builder/src/{builderStore => builder}/schemaGenerator.js (100%) rename packages/builder/src/{builderStore => builder}/store/screenTemplates/createFromScratchScreen.js (100%) rename packages/builder/src/{builderStore => builder}/store/screenTemplates/index.js (100%) rename packages/builder/src/{builderStore => builder}/store/screenTemplates/rowListScreen.js (100%) rename packages/builder/src/{builderStore => builder}/store/screenTemplates/utils/BaseStructure.js (100%) rename packages/builder/src/{builderStore => builder}/store/screenTemplates/utils/Component.js (100%) rename packages/builder/src/{builderStore => builder}/store/screenTemplates/utils/Screen.js (94%) rename packages/builder/src/{builderStore => builder}/store/screenTemplates/utils/commonComponents.js (100%) rename packages/builder/src/{builderStore => builder}/store/screenTemplates/utils/sanitizeUrl.js (100%) rename packages/builder/src/{builderStore => builder}/utils.js (100%) delete mode 100644 packages/builder/src/builderStore/index.js delete mode 100644 packages/builder/src/builderStore/store/frontend.js delete mode 100644 packages/builder/src/stores/backend/database.js create mode 100644 packages/builder/src/stores/frontend/BudiStore.js create mode 100644 packages/builder/src/stores/frontend/app.js rename packages/builder/src/{builderStore/store/automation/index.js => stores/frontend/automations.js} (88%) create mode 100644 packages/builder/src/stores/frontend/builder.js create mode 100644 packages/builder/src/stores/frontend/components/index.js rename packages/builder/src/{builderStore/componentUtils.js => stores/frontend/components/utils.js} (98%) create mode 100644 packages/builder/src/stores/frontend/database.js rename packages/builder/src/{builderStore/store => stores/frontend}/deployments.js (76%) rename packages/builder/src/{builderStore/store => stores/frontend}/history.js (100%) create mode 100644 packages/builder/src/stores/frontend/index.js create mode 100644 packages/builder/src/stores/frontend/layouts.js create mode 100644 packages/builder/src/stores/frontend/navigation.js create mode 100644 packages/builder/src/stores/frontend/preview.js create mode 100644 packages/builder/src/stores/frontend/screens.js create mode 100644 packages/builder/src/stores/frontend/tests/app.test.js create mode 100644 packages/builder/src/stores/frontend/tests/builder.test.js create mode 100644 packages/builder/src/stores/frontend/tests/fixtures.js rename packages/builder/src/{builderStore/store => stores/frontend/tests}/history.test.js (99%) create mode 100644 packages/builder/src/stores/frontend/tests/navigation.test.js create mode 100644 packages/builder/src/stores/frontend/tests/screens.test.js create mode 100644 packages/builder/src/stores/frontend/theme.js rename packages/builder/src/{builderStore/store => stores/frontend}/users.js (56%) rename packages/builder/src/{builderStore => stores/frontend}/websocket.js (83%) rename packages/builder/src/{builderStore/store => stores/portal}/temporal.js (90%) rename packages/builder/src/{builderStore/store => stores/portal}/theme.js (94%) diff --git a/packages/builder/package.json b/packages/builder/package.json index 3cc5612652..679bca2891 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -23,7 +23,7 @@ "\\.(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", + "builder(.*)$": "/src/builder$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 37894d9bbc..df18f4c17a 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/frontend" import { get } from "svelte/store" import { auth } 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/dataBinding.js b/packages/builder/src/builder/dataBinding.js similarity index 97% rename from packages/builder/src/builderStore/dataBinding.js rename to packages/builder/src/builder/dataBinding.js index 8445bf9e6d..ca0c51af98 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builder/dataBinding.js @@ -5,8 +5,13 @@ import { findComponent, findComponentPath, getComponentSettings, -} from "./componentUtils" -import { store, currentAsset } from "builderStore" +} from "stores/frontend/components/utils" +import { + currentAsset, + componentStore, + screenStore, + appStore, +} from "stores/frontend" import { queries as queriesStores, tables as tablesStore, @@ -178,7 +183,7 @@ export const getComponentBindableProperties = (asset, componentId) => { // Ensure that the component exists and exposes context const component = findComponent(asset.props, componentId) - const def = store.actions.components.getDefinition(component?._component) + const def = componentStore.getDefinition(component?._component) if (!def?.context) { return [] } @@ -209,7 +214,7 @@ export const getContextProviderComponents = ( // Filter by only data provider components return path.filter(component => { - const def = store.actions.components.getDefinition(component._component) + const def = componentStore.getDefinition(component._component) if (!def?.context) { return false } @@ -240,7 +245,7 @@ export const getActionProviderComponents = (asset, componentId, actionType) => { // Filter by only data provider components return path.filter(component => { - const def = store.actions.components.getDefinition(component._component) + const def = componentStore.getDefinition(component._component) return def?.actions?.includes(actionType) }) } @@ -312,7 +317,7 @@ const getProviderContextBindings = (asset, dataProviders) => { // Create bindings for each data provider let bindings = [] dataProviders.forEach(component => { - const def = store.actions.components.getDefinition(component._component) + const def = componentStore.getDefinition(component._component) const contexts = Array.isArray(def.context) ? def.context : [def.context] // Create bindings for each context block provided by this data provider @@ -502,7 +507,7 @@ export const getUserBindings = () => { */ const getDeviceBindings = () => { let bindings = [] - if (get(store).clientFeatures?.deviceAwareness) { + if (get(appStore).clientFeatures?.deviceAwareness) { const safeDevice = makePropSafe("device") bindings = [ @@ -540,7 +545,7 @@ const getDeviceBindings = () => { */ const getSelectedRowsBindings = asset => { let bindings = [] - if (get(store).clientFeatures?.rowSelection) { + if (get(appStore).clientFeatures?.rowSelection) { // Add bindings for table components let tables = findAllMatchingComponents(asset?.props, component => component._component.endsWith("table") @@ -595,7 +600,7 @@ export const makeStateBinding = key => { */ const getStateBindings = () => { let bindings = [] - if (get(store).clientFeatures?.state) { + if (get(appStore).clientFeatures?.state) { bindings = getAllStateVariables().map(makeStateBinding) } return bindings @@ -671,8 +676,7 @@ export const getEventContextBindings = ({ } const definition = - componentDefinition ?? - store.actions.components.getDefinition(component?._component) + componentDefinition ?? componentStore.getDefinition(component?._component) const settings = getComponentSettings(component?._component) const eventSetting = settings.find(setting => setting.key === settingKey) @@ -1015,7 +1019,7 @@ export const getAllStateVariables = () => { }) // Add on load settings from screens - get(store).screens.forEach(screen => { + get(screenStore).screens.forEach(screen => { if (screen.onLoad) { eventSettings.push(screen.onLoad) } @@ -1044,8 +1048,8 @@ export const getAllStateVariables = () => { export const getAllAssets = () => { // Get all component containing assets let allAssets = [] - allAssets = allAssets.concat(get(store).layouts || []) - allAssets = allAssets.concat(get(store).screens || []) + allAssets = allAssets.concat(get(appStore).layouts || []) + allAssets = allAssets.concat(get(screenStore).screens || []) return allAssets } diff --git a/packages/builder/src/builderStore/schemaGenerator.js b/packages/builder/src/builder/schemaGenerator.js similarity index 100% rename from packages/builder/src/builderStore/schemaGenerator.js rename to packages/builder/src/builder/schemaGenerator.js diff --git a/packages/builder/src/builderStore/store/screenTemplates/createFromScratchScreen.js b/packages/builder/src/builder/store/screenTemplates/createFromScratchScreen.js similarity index 100% rename from packages/builder/src/builderStore/store/screenTemplates/createFromScratchScreen.js rename to packages/builder/src/builder/store/screenTemplates/createFromScratchScreen.js diff --git a/packages/builder/src/builderStore/store/screenTemplates/index.js b/packages/builder/src/builder/store/screenTemplates/index.js similarity index 100% rename from packages/builder/src/builderStore/store/screenTemplates/index.js rename to packages/builder/src/builder/store/screenTemplates/index.js diff --git a/packages/builder/src/builderStore/store/screenTemplates/rowListScreen.js b/packages/builder/src/builder/store/screenTemplates/rowListScreen.js similarity index 100% rename from packages/builder/src/builderStore/store/screenTemplates/rowListScreen.js rename to packages/builder/src/builder/store/screenTemplates/rowListScreen.js diff --git a/packages/builder/src/builderStore/store/screenTemplates/utils/BaseStructure.js b/packages/builder/src/builder/store/screenTemplates/utils/BaseStructure.js similarity index 100% rename from packages/builder/src/builderStore/store/screenTemplates/utils/BaseStructure.js rename to packages/builder/src/builder/store/screenTemplates/utils/BaseStructure.js diff --git a/packages/builder/src/builderStore/store/screenTemplates/utils/Component.js b/packages/builder/src/builder/store/screenTemplates/utils/Component.js similarity index 100% rename from packages/builder/src/builderStore/store/screenTemplates/utils/Component.js rename to packages/builder/src/builder/store/screenTemplates/utils/Component.js diff --git a/packages/builder/src/builderStore/store/screenTemplates/utils/Screen.js b/packages/builder/src/builder/store/screenTemplates/utils/Screen.js similarity index 94% rename from packages/builder/src/builderStore/store/screenTemplates/utils/Screen.js rename to packages/builder/src/builder/store/screenTemplates/utils/Screen.js index 6fc79e53b0..afe9123b6d 100644 --- a/packages/builder/src/builderStore/store/screenTemplates/utils/Screen.js +++ b/packages/builder/src/builder/store/screenTemplates/utils/Screen.js @@ -33,6 +33,11 @@ export class Screen extends BaseStructure { } } + role(role) { + this._json.routing.roleId = role + return this + } + normalStyle(styling) { this._json.props._styles.normal = styling return this diff --git a/packages/builder/src/builderStore/store/screenTemplates/utils/commonComponents.js b/packages/builder/src/builder/store/screenTemplates/utils/commonComponents.js similarity index 100% rename from packages/builder/src/builderStore/store/screenTemplates/utils/commonComponents.js rename to packages/builder/src/builder/store/screenTemplates/utils/commonComponents.js diff --git a/packages/builder/src/builderStore/store/screenTemplates/utils/sanitizeUrl.js b/packages/builder/src/builder/store/screenTemplates/utils/sanitizeUrl.js similarity index 100% rename from packages/builder/src/builderStore/store/screenTemplates/utils/sanitizeUrl.js rename to packages/builder/src/builder/store/screenTemplates/utils/sanitizeUrl.js diff --git a/packages/builder/src/builderStore/utils.js b/packages/builder/src/builder/utils.js similarity index 100% rename from packages/builder/src/builderStore/utils.js rename to packages/builder/src/builder/utils.js diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js deleted file mode 100644 index eecccab7a6..0000000000 --- a/packages/builder/src/builderStore/index.js +++ /dev/null @@ -1,151 +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, writable } from "svelte/store" -import { findComponent, findComponentPath } from "./componentUtils" -import { RoleUtils } from "@budibase/frontend-core" -import { createHistoryStore } from "builderStore/store/history" -import { get } from "svelte/store" - -export const store = getFrontendStore() -export const automationStore = getAutomationStore() -export const themeStore = getThemeStore() -export const temporalStore = getTemporalStore() -export const userStore = getUserStore() -export const deploymentStore = getDeploymentStore() - -// 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 - } - return findComponent($selectedScreen?.props, $store.selectedComponentId) - } -) - -// 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 -}) - -export const screensHeight = writable("210px") diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js deleted file mode 100644 index a567caf87f..0000000000 --- a/packages/builder/src/builderStore/store/frontend.js +++ /dev/null @@ -1,1453 +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) - - 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, - }, - 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.type === DB_TYPE_INTERNAL - ) - }) - if (table) { - return table - } - - // Then try sample data - table = validTables.find(table => { - return ( - table.sourceId === BUDIBASE_INTERNAL_DB_ID && - table.type === DB_TYPE_INTERNAL - ) - }) - if (table) { - return table - } - - // Finally try an external table - return validTables.find(table => table.type === DB_TYPE_EXTERNAL) - }, - 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 treeId = parent?._id || component._id - const path = findComponentPath(screen?.props, treeId) - const providers = path.filter(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 - } - - // Generate basic component structure - let instance = { - _id: Helpers.uuid(), - _component: definition.component, - _styles: { - normal: {}, - hover: {}, - active: {}, - }, - _instanceName: `New ${definition.friendlyName || definition.name}`, - ...presetProps, - } - - // Enrich empty settings - store.actions.components.enrichEmptySettings(instance, { - parent, - screen: get(selectedScreen), - useDefaultValues: true, - }) - - // 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 - } - return patchFn(component, screen) - } - 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) - - const resetFields = settings.filter( - setting => name === setting.resetOn - ) - resetFields?.forEach(setting => { - component[setting.key] = 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 - } - }, - 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/components/automation/AutomationBuilder/AutomationBuilder.svelte b/packages/builder/src/components/automation/AutomationBuilder/AutomationBuilder.svelte index b80ba45086..6ca3e65d5d 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 15dd864168..f950d91746 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/frontend" 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 "builder/utils" export let blockIdx export let lastStep diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte index 63a3478ef3..8811306f05 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte @@ -1,5 +1,9 @@ diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte index cce0f4eeab..585445a03a 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/frontend" 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/CreateAutomationModal.svelte b/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte index 647a8081cf..ab53ff66b9 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 0cc61c69e6..37bea4fb8c 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte @@ -1,14 +1,7 @@
@@ -66,6 +74,7 @@
{ + builderStore.propertyFocus(key) bindingDrawer.show() }} > @@ -74,7 +83,7 @@ {/if}
0 $: updateAvailable = - $store.upgradableVersion && - $store.version && - $store.upgradableVersion !== $store.version + $appStore.upgradableVersion && + $appStore.version && + $appStore.upgradableVersion !== $appStore.version $: canPublish = !publishing && loaded $: lastDeployed = getLastDeployedString($deploymentStore) const initialiseApp = async () => { - const applicationPkg = await API.fetchAppPackage($store.devId) - await store.actions.initialise(applicationPkg) + const applicationPkg = await API.fetchAppPackage($appStore.devId) + await initialise(applicationPkg) } const getLastDeployedString = deployments => { @@ -66,10 +73,7 @@ } const previewApp = () => { - store.update(state => ({ - ...state, - showPreview: true, - })) + previewStore.showPreview(true) } const viewApp = () => { @@ -87,7 +91,7 @@ async function publishApp() { try { publishing = true - await API.publishAppChanges($store.appId) + await API.publishAppChanges($appStore.appId) notifications.send("App published successfully", { type: "success", icon: "GlobeCheck", @@ -131,7 +135,7 @@ const completePublish = async () => { try { await apps.load() - await deploymentStore.actions.load() + await deploymentStore.load() } catch (err) { notifications.error("Error refreshing app") } @@ -151,7 +155,7 @@
{/if} @@ -161,10 +165,7 @@ quiet icon="UserGroup" on:click={() => { - store.update(state => { - state.builderSidePanel = true - return state - }) + builderStore.showBuilderSidePanel() }} > Users @@ -232,7 +233,7 @@ } }} > - {$store.url} + {$appStore.url} {#if isPublished} {:else} @@ -313,10 +314,10 @@ { await initialiseApp() diff --git a/packages/builder/src/components/deploy/CreateWebhookDeploymentModal.svelte b/packages/builder/src/components/deploy/CreateWebhookDeploymentModal.svelte index ee6b163a3e..3ea5d1bc81 100644 --- a/packages/builder/src/components/deploy/CreateWebhookDeploymentModal.svelte +++ b/packages/builder/src/components/deploy/CreateWebhookDeploymentModal.svelte @@ -1,5 +1,5 @@ diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DuplicateRow.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DuplicateRow.svelte index 18711497ff..7146fa5d7f 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DuplicateRow.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DuplicateRow.svelte @@ -1,11 +1,11 @@ diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/S3Upload.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/S3Upload.svelte index 2e374f165f..0768c93843 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/S3Upload.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/S3Upload.svelte @@ -1,7 +1,7 @@ diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/TriggerAutomation.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/TriggerAutomation.svelte index 971a5ede44..46bf0361fa 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/TriggerAutomation.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/TriggerAutomation.svelte @@ -1,6 +1,6 @@ diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/index.js b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/index.js index ea6cc4ed37..0c86a4f58e 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/index.js +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/index.js @@ -1,6 +1,6 @@ import * as ActionComponents from "./actions" import { get } from "svelte/store" -import { store } from "builderStore" +import { appStore } from "stores/frontend" // @ts-ignore import ActionDefinitions from "./manifest.json" @@ -18,7 +18,7 @@ export const getAvailableActions = (getAllActions = false) => { if (getAllActions || !action.dependsOnFeature) { return true } - return get(store).clientFeatures?.[action.dependsOnFeature] === true + return get(appStore).clientFeatures?.[action.dependsOnFeature] === true }) .map(action => { // Then enrich the actions with real components diff --git a/packages/builder/src/components/design/settings/controls/ColorPicker.svelte b/packages/builder/src/components/design/settings/controls/ColorPicker.svelte index 5f9fcaf21a..39adb44a4d 100644 --- a/packages/builder/src/components/design/settings/controls/ColorPicker.svelte +++ b/packages/builder/src/components/design/settings/controls/ColorPicker.svelte @@ -1,8 +1,8 @@ - + 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 8e3079101a..d2e51156e1 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/frontend" import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" export let column @@ -42,7 +42,7 @@ (column.background = e.detail)} - spectrumTheme={$store.theme} + spectrumTheme={$themeStore.theme} /> @@ -50,7 +50,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..42b7dc2b4b 100644 --- a/packages/builder/src/components/design/settings/controls/ColumnEditor/ColumnEditor.svelte +++ b/packages/builder/src/components/design/settings/controls/ColumnEditor/ColumnEditor.svelte @@ -6,8 +6,8 @@ import { getDatasourceForProvider, getSchemaForDatasource, - } from "builderStore/dataBinding" - import { currentAsset } from "builderStore" + } from "builder/dataBinding" + import { currentAsset } from "stores/frontend" import { getFields } from "helpers/searchFields" export let componentInstance diff --git a/packages/builder/src/components/design/settings/controls/DataProviderSelect.svelte b/packages/builder/src/components/design/settings/controls/DataProviderSelect.svelte index 83255ec325..422199a1e0 100644 --- a/packages/builder/src/components/design/settings/controls/DataProviderSelect.svelte +++ b/packages/builder/src/components/design/settings/controls/DataProviderSelect.svelte @@ -1,14 +1,17 @@ diff --git a/packages/builder/src/components/design/settings/controls/DataSourceSelect.svelte b/packages/builder/src/components/design/settings/controls/DataSourceSelect.svelte index 29f32aa345..73acc18dcf 100644 --- a/packages/builder/src/components/design/settings/controls/DataSourceSelect.svelte +++ b/packages/builder/src/components/design/settings/controls/DataSourceSelect.svelte @@ -3,7 +3,7 @@ getContextProviderComponents, readableToRuntimeBinding, runtimeToReadableBinding, - } from "builderStore/dataBinding" + } from "builder/dataBinding" import { Button, Popover, @@ -20,7 +20,7 @@ notifications, } from "@budibase/bbui" import { createEventDispatcher } from "svelte" - import { store, currentAsset } from "builderStore" + import { currentAsset, componentStore } from "stores/frontend" import { tables as tablesStore, queries as queriesStore, @@ -77,7 +77,7 @@ })) $: contextProviders = getContextProviderComponents( $currentAsset, - $store.selectedComponentId + $componentStore.selectedComponentId ) $: dataProviders = contextProviders .filter(component => component._component?.endsWith("/dataprovider")) diff --git a/packages/builder/src/components/design/settings/controls/FieldConfiguration/EditFieldPopover.svelte b/packages/builder/src/components/design/settings/controls/FieldConfiguration/EditFieldPopover.svelte index 7d2eaae478..0845df1391 100644 --- a/packages/builder/src/components/design/settings/controls/FieldConfiguration/EditFieldPopover.svelte +++ b/packages/builder/src/components/design/settings/controls/FieldConfiguration/EditFieldPopover.svelte @@ -1,6 +1,6 @@ diff --git a/packages/builder/src/components/design/settings/controls/RelationshipFilterEditor.svelte b/packages/builder/src/components/design/settings/controls/RelationshipFilterEditor.svelte index 0010a22d15..53f20ec482 100644 --- a/packages/builder/src/components/design/settings/controls/RelationshipFilterEditor.svelte +++ b/packages/builder/src/components/design/settings/controls/RelationshipFilterEditor.svelte @@ -1,10 +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 0bff2ccce6..58b307c007 100644 --- a/packages/builder/src/components/design/settings/controls/ValidationEditor/ValidationDrawer.svelte +++ b/packages/builder/src/components/design/settings/controls/ValidationEditor/ValidationDrawer.svelte @@ -10,9 +10,9 @@ Input, DatePicker, } from "@budibase/bbui" - import { currentAsset, selectedComponent } from "builderStore" - import { findClosestMatchingComponent } from "builderStore/componentUtils" - import { getSchemaForDatasource } from "builderStore/dataBinding" + import { currentAsset, selectedComponent } from "stores/frontend" + import { findClosestMatchingComponent } from "stores/frontend/components/utils" + import { getSchemaForDatasource } from "builder/dataBinding" import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" import { generate } from "shortid" diff --git a/packages/builder/src/components/integration/QueryBindingBuilder.svelte b/packages/builder/src/components/integration/QueryBindingBuilder.svelte index af890302b0..d0f9c5bad6 100644 --- a/packages/builder/src/components/integration/QueryBindingBuilder.svelte +++ b/packages/builder/src/components/integration/QueryBindingBuilder.svelte @@ -3,7 +3,7 @@ import { readableToRuntimeBinding, runtimeToReadableBinding, - } from "builderStore/dataBinding" + } from "builder/dataBinding" import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" import { createEventDispatcher } from "svelte" diff --git a/packages/builder/src/components/integration/QueryEditor.svelte b/packages/builder/src/components/integration/QueryEditor.svelte index 51fdb4879e..97998c3d22 100644 --- a/packages/builder/src/components/integration/QueryEditor.svelte +++ b/packages/builder/src/components/integration/QueryEditor.svelte @@ -2,7 +2,7 @@ import CodeMirror from "./codemirror" import { Label } from "@budibase/bbui" import { onMount, createEventDispatcher } from "svelte" - import { themeStore } from "builderStore" + import { themeStore } from "stores/portal" const dispatch = createEventDispatcher() diff --git a/packages/builder/src/components/integration/QueryViewerBindingBuilder.svelte b/packages/builder/src/components/integration/QueryViewerBindingBuilder.svelte index 3d74e3f6b6..0cfce5fd24 100644 --- a/packages/builder/src/components/integration/QueryViewerBindingBuilder.svelte +++ b/packages/builder/src/components/integration/QueryViewerBindingBuilder.svelte @@ -1,9 +1,7 @@ diff --git a/packages/builder/src/components/start/CreateAppModal.svelte b/packages/builder/src/components/start/CreateAppModal.svelte index 9e831f5bd9..09bd628d6a 100644 --- a/packages/builder/src/components/start/CreateAppModal.svelte +++ b/packages/builder/src/components/start/CreateAppModal.svelte @@ -7,7 +7,8 @@ ModalContent, Dropzone, } from "@budibase/bbui" - import { store, automationStore } from "builderStore" + import { initialise as initialiseFrontend } from "stores/frontend" + import { initialise as initialiseBackend } from "stores/backend" import { API } from "api" import { apps, admin, auth } from "stores/portal" import { onMount } from "svelte" @@ -132,8 +133,10 @@ // 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 initialiseFrontend(pkg) + await initialiseBackend(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..411e5fc739 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/frontend" 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/helpers/formFields.js b/packages/builder/src/helpers/formFields.js index eaf260a9b6..aa22b65814 100644 --- a/packages/builder/src/helpers/formFields.js +++ b/packages/builder/src/helpers/formFields.js @@ -1,8 +1,8 @@ -import { findClosestMatchingComponent } from "builderStore/componentUtils" +import { findClosestMatchingComponent } from "stores/frontend/components/utils" import { getDatasourceForProvider, getSchemaForDatasource, -} from "builderStore/dataBinding" +} from "builder/dataBinding" export const getComponentFieldOptions = (asset, id, type, loose = true) => { const form = findClosestMatchingComponent( diff --git a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte index a7d9584330..6ccf92a3c0 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -14,7 +14,7 @@ Button, FancySelect, } from "@budibase/bbui" - import { store } from "builderStore" + import { builderStore, appStore } from "stores/frontend" import { groups, licensing, apps, users, auth, admin } from "stores/portal" import { fetchData, @@ -55,7 +55,7 @@ let inviteFailureResponse = "" $: validEmail = emailValidator(email) === true - $: prodAppId = apps.getProdAppID($store.appId) + $: prodAppId = apps.getProdAppID($appStore.appId) $: promptInvite = showInvite( filteredInvites, filteredUsers, @@ -182,7 +182,7 @@ const debouncedUpdateFetch = Utils.debounce(searchUsers, 250) $: debouncedUpdateFetch( query, - $store.builderSidePanel, + $builderStore.builderSidePanel, loaded, filterByAppAccess ) @@ -200,7 +200,7 @@ [prodAppId]: role, }, }) - await searchUsers(query, $store.builderSidePanel, loaded) + await searchUsers(query, $builderStore.builderSidePanel, loaded) } const onUpdateUser = async (user, role) => { @@ -486,7 +486,7 @@ loaded = true } - $: initSidePanel($store.builderSidePanel) + $: initSidePanel($builderStore.builderSidePanel) function handleKeyDown(evt) { if (evt.key === "Enter" && validEmail && !inviting) { @@ -523,12 +523,7 @@
{ - store.update(state => { - state.builderSidePanel = false - return state - }) - }} + use:clickOutside={builderStore.hideBuilderSidePanel} >
{ - store.update(state => { - state.builderSidePanel = false - return state - }) + builderStore.hideBuilderSidePanel() }} />
diff --git a/packages/builder/src/pages/builder/app/[application]/_components/PreviewOverlay.svelte b/packages/builder/src/pages/builder/app/[application]/_components/PreviewOverlay.svelte index eedff6c2a7..efbbcf57c6 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/PreviewOverlay.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/PreviewOverlay.svelte @@ -1,26 +1,25 @@ @@ -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..3bd608b5a0 100644 --- a/packages/builder/src/pages/builder/app/[application]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_layout.svelte @@ -1,11 +1,14 @@ -{#if $store.builderSidePanel} +{#if $builderStore.builderSidePanel} {/if} -
+
- {#if $store.initialised} + {#if $appStore.initialised}
- {$store.name} + {$appStore.name}
@@ -190,7 +191,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..0e48a83cb5 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 @@ 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..1a7aee2a56 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 @@ -3,10 +3,10 @@ import { syncURLToState } from "helpers/urlStateSync" import * as routify from "@roxi/routify" import { onDestroy } from "svelte" - import { store } from "builderStore" + import { builderStore } from "stores/frontend" $: id = $viewsV2.selectedViewId - $: store.actions.websocket.selectResource(id) + $: builderStore.selectResource(id) const stopSyncing = syncURLToState({ urlParam: "viewId", diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsPanel.svelte index afcada4138..6daa2c4c3c 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsPanel.svelte @@ -1,6 +1,10 @@ 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 383026c4f8..aafea25c80 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 @@ -16,11 +16,16 @@ notifications, Select, } from "@budibase/bbui" - import { selectedScreen, store } from "builderStore" + import { + themeStore, + selectedScreen, + screenStore, + navigationStore, + } from "stores/frontend" import { DefaultAppTheme } from "constants" const updateShowNavigation = async e => { - await store.actions.screens.updateSetting( + await screenStore.updateSetting( get(selectedScreen), "showNavigation", e.detail @@ -29,9 +34,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") } @@ -40,7 +45,7 @@ @@ -51,13 +56,13 @@
Show nav on this screen
- {#if $selectedScreen.showNavigation} + {#if $selectedScreen?.showNavigation}
@@ -76,25 +81,25 @@
update("navigation", "Top")} /> update("navigation", "Left")} /> - {#if $store.navigation.navigation === "Top"} + {#if $navigationStore.navigation === "Top"}
update("sticky", e.detail)} />
@@ -103,7 +108,7 @@ update("logoUrl", e.detail)} updateOnChange={false} /> @@ -128,15 +133,15 @@
update("hideTitle", !e.detail)} /> - {#if !$store.navigation.hideTitle} + {#if !$navigationStore.hideTitle}
update("title", e.detail)} updateOnChange={false} /> @@ -145,8 +150,8 @@
update("navBackground", e.detail)} /> @@ -154,8 +159,8 @@
update("navTextColor", e.detail)} />
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..5690e09179 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..c6b5cfbe1a 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/frontend" 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..22376c67a1 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} diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/index.js b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/index.js index 3b3ee6fd00..eb354d6557 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/index.js +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/index.js @@ -21,3 +21,4 @@ export { default as ShowNotification } from "./ShowNotification.svelte" export { default as PromptUser } from "./PromptUser.svelte" export { default as OpenSidePanel } from "./OpenSidePanel.svelte" export { default as CloseSidePanel } from "./CloseSidePanel.svelte" +export { default as ClearRowSelection } from "./ClearRowSelection.svelte" diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json index 6ed545f541..9391baf3dc 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json @@ -156,6 +156,11 @@ "type": "application", "component": "CloseSidePanel", "dependsOnFeature": "sidePanel" + }, + { + "name": "Clear Row Selection", + "type": "data", + "component": "ClearRowSelection" } ] } diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 6c7a254cfb..0fee0e7478 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -4639,6 +4639,7 @@ "illegalChildren": ["section"], "hasChildren": true, "showEmptyState": false, + "actions": ["ClearRowSelection"], "size": { "width": 600, "height": 400 diff --git a/packages/client/src/components/app/table/Table.svelte b/packages/client/src/components/app/table/Table.svelte index 0afaff0a36..f16e26bc45 100644 --- a/packages/client/src/components/app/table/Table.svelte +++ b/packages/client/src/components/app/table/Table.svelte @@ -156,13 +156,20 @@ } } + const actions = [ + { + type: ActionTypes.ClearRowSelection, + callback: () => (selectedRows = []), + }, + ] + onDestroy(() => { rowSelectionStore.actions.updateSelection($component.id, []) })
- + { return key(action.parameters.componentId, ActionTypes.ClearForm) case "Change Form Step": return key(action.parameters.componentId, ActionTypes.ChangeFormStep) + case "Clear Row Selection": + return key(action.parameters.componentId, ActionTypes.ClearRowSelection) default: return null } @@ -383,14 +385,14 @@ const showNotificationHandler = action => { const promptUserHandler = () => {} -const OpenSidePanelHandler = action => { +const openSidePanelHandler = action => { const { id } = action.parameters if (id) { sidePanelStore.actions.open(id) } } -const CloseSidePanelHandler = () => { +const closeSidePanelHandler = () => { sidePanelStore.actions.close() } @@ -410,8 +412,8 @@ const handlerMap = { ["Continue if / Stop if"]: continueIfHandler, ["Show Notification"]: showNotificationHandler, ["Prompt User"]: promptUserHandler, - ["Open Side Panel"]: OpenSidePanelHandler, - ["Close Side Panel"]: CloseSidePanelHandler, + ["Open Side Panel"]: openSidePanelHandler, + ["Close Side Panel"]: closeSidePanelHandler, } const confirmTextMap = { From 4d225b6d7fdcd6443c41936c34f38bfcad30200f Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 14 Feb 2024 10:20:46 +0000 Subject: [PATCH 79/83] Import fix --- .../ButtonActionEditor/actions/ClearRowSelection.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ClearRowSelection.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ClearRowSelection.svelte index 630d7dbc0b..30b33ca3a9 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ClearRowSelection.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ClearRowSelection.svelte @@ -1,6 +1,6 @@