Merge branch 'master' of github.com:Budibase/budibase into develop

This commit is contained in:
mike12345567 2022-07-19 14:12:48 +01:00
commit 1c02c3d3c3
33 changed files with 465 additions and 392 deletions

View File

@ -1,5 +1,5 @@
{ {
"version": "1.1.15-alpha.3", "version": "1.1.17",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*" "packages/*"

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/backend-core", "name": "@budibase/backend-core",
"version": "1.1.15-alpha.3", "version": "1.1.17",
"description": "Budibase backend core libraries used in server and worker", "description": "Budibase backend core libraries used in server and worker",
"main": "dist/src/index.js", "main": "dist/src/index.js",
"types": "dist/src/index.d.ts", "types": "dist/src/index.d.ts",
@ -20,7 +20,7 @@
"test:watch": "jest --watchAll" "test:watch": "jest --watchAll"
}, },
"dependencies": { "dependencies": {
"@budibase/types": "^1.1.15-alpha.3", "@budibase/types": "^1.1.17",
"@techpass/passport-openidconnect": "0.3.2", "@techpass/passport-openidconnect": "0.3.2",
"aws-sdk": "2.1030.0", "aws-sdk": "2.1030.0",
"bcrypt": "5.0.1", "bcrypt": "5.0.1",

View File

@ -67,6 +67,10 @@ export const getTenantIDFromAppID = (appId: string) => {
// used for automations, API endpoints should always be in context already // used for automations, API endpoints should always be in context already
export const doInTenant = (tenantId: string | null, task: any) => { export const doInTenant = (tenantId: string | null, task: any) => {
// make sure default always selected in single tenancy
if (!env.MULTI_TENANCY) {
tenantId = tenantId || DEFAULT_TENANT_ID
}
// the internal function is so that we can re-use an existing // the internal function is so that we can re-use an existing
// context - don't want to close DB on a parent context // context - don't want to close DB on a parent context
async function internal(opts = { existing: false }) { async function internal(opts = { existing: false }) {

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/bbui", "name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.", "description": "A UI solution used in the different Budibase projects.",
"version": "1.1.15-alpha.3", "version": "1.1.17",
"license": "MPL-2.0", "license": "MPL-2.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"module": "dist/bbui.es.js", "module": "dist/bbui.es.js",
@ -38,7 +38,7 @@
], ],
"dependencies": { "dependencies": {
"@adobe/spectrum-css-workflow-icons": "^1.2.1", "@adobe/spectrum-css-workflow-icons": "^1.2.1",
"@budibase/string-templates": "^1.1.15-alpha.3", "@budibase/string-templates": "^1.1.17",
"@spectrum-css/actionbutton": "^1.0.1", "@spectrum-css/actionbutton": "^1.0.1",
"@spectrum-css/actiongroup": "^1.0.1", "@spectrum-css/actiongroup": "^1.0.1",
"@spectrum-css/avatar": "^3.0.2", "@spectrum-css/avatar": "^3.0.2",

View File

@ -82,6 +82,7 @@
} }
.fillWidth { .fillWidth {
left: 260px !important;
width: calc(100% - 260px) !important; width: calc(100% - 260px) !important;
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/builder", "name": "@budibase/builder",
"version": "1.1.15-alpha.3", "version": "1.1.17",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
@ -69,10 +69,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.1.15-alpha.3", "@budibase/bbui": "^1.1.17",
"@budibase/client": "^1.1.15-alpha.3", "@budibase/client": "^1.1.17",
"@budibase/frontend-core": "^1.1.15-alpha.3", "@budibase/frontend-core": "^1.1.17",
"@budibase/string-templates": "^1.1.15-alpha.3", "@budibase/string-templates": "^1.1.17",
"@sentry/browser": "5.19.1", "@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1", "@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1", "@spectrum-css/vars": "^3.0.1",

View File

@ -2,7 +2,6 @@ import { getFrontendStore } from "./store/frontend"
import { getAutomationStore } from "./store/automation" import { getAutomationStore } from "./store/automation"
import { getThemeStore } from "./store/theme" import { getThemeStore } from "./store/theme"
import { derived } from "svelte/store" import { derived } from "svelte/store"
import { LAYOUT_NAMES } from "../constants"
import { findComponent, findComponentPath } from "./componentUtils" import { findComponent, findComponentPath } from "./componentUtils"
import { RoleUtils } from "@budibase/frontend-core" import { RoleUtils } from "@budibase/frontend-core"
@ -28,6 +27,10 @@ export const selectedComponent = derived(
} }
) )
// 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 => { export const sortedScreens = derived(store, $store => {
return $store.screens.slice().sort((a, b) => { return $store.screens.slice().sort((a, b) => {
// Sort by role first // Sort by role first
@ -66,12 +69,3 @@ export const selectedComponentPath = derived(
).map(component => component._id) ).map(component => component._id)
} }
) )
export const mainLayout = derived(store, $store => {
return $store.layouts?.find(
layout => layout._id === LAYOUT_NAMES.MASTER.PRIVATE
)
})
// For compatibility
export const currentAsset = selectedScreen

View File

@ -1,6 +1,6 @@
import { get, writable } from "svelte/store" import { get, writable } from "svelte/store"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { currentAsset, mainLayout, selectedComponent } from "builderStore" import { selectedScreen, selectedComponent } from "builderStore"
import { import {
datasources, datasources,
integrations, integrations,
@ -11,7 +11,6 @@ import {
import { API } from "api" import { API } from "api"
import analytics, { Events } from "analytics" import analytics, { Events } from "analytics"
import { import {
findComponentType,
findComponentParent, findComponentParent,
findClosestMatchingComponent, findClosestMatchingComponent,
findAllMatchingComponents, findAllMatchingComponents,
@ -21,6 +20,7 @@ import {
} from "../componentUtils" } from "../componentUtils"
import { Helpers } from "@budibase/bbui" import { Helpers } from "@budibase/bbui"
import { DefaultAppTheme, LAYOUT_NAMES } from "../../constants" import { DefaultAppTheme, LAYOUT_NAMES } from "../../constants"
import { Utils } from "@budibase/frontend-core"
const INITIAL_FRONTEND_STATE = { const INITIAL_FRONTEND_STATE = {
apps: [], apps: [],
@ -61,6 +61,26 @@ const INITIAL_FRONTEND_STATE = {
export const getFrontendStore = () => { export const getFrontendStore = () => {
const store = writable({ ...INITIAL_FRONTEND_STATE }) const store = writable({ ...INITIAL_FRONTEND_STATE })
// 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 = { store.actions = {
reset: () => { reset: () => {
store.set({ ...INITIAL_FRONTEND_STATE }) store.set({ ...INITIAL_FRONTEND_STATE })
@ -137,12 +157,12 @@ export const getFrontendStore = () => {
theme: { theme: {
save: async theme => { save: async theme => {
const appId = get(store).appId const appId = get(store).appId
await API.saveAppMetadata({ const app = await API.saveAppMetadata({
appId, appId,
metadata: { theme }, metadata: { theme },
}) })
store.update(state => { store.update(state => {
state.theme = theme state.theme = app.theme
return state return state
}) })
}, },
@ -150,12 +170,12 @@ export const getFrontendStore = () => {
customTheme: { customTheme: {
save: async customTheme => { save: async customTheme => {
const appId = get(store).appId const appId = get(store).appId
await API.saveAppMetadata({ const app = await API.saveAppMetadata({
appId, appId,
metadata: { customTheme }, metadata: { customTheme },
}) })
store.update(state => { store.update(state => {
state.customTheme = customTheme state.customTheme = app.customTheme
return state return state
}) })
}, },
@ -163,33 +183,35 @@ export const getFrontendStore = () => {
navigation: { navigation: {
save: async navigation => { save: async navigation => {
const appId = get(store).appId const appId = get(store).appId
await API.saveAppMetadata({ const app = await API.saveAppMetadata({
appId, appId,
metadata: { navigation }, metadata: { navigation },
}) })
store.update(state => { store.update(state => {
state.navigation = navigation state.navigation = app.navigation
return state
})
},
},
routing: {
fetch: async () => {
const response = await API.fetchAppRoutes()
store.update(state => {
state.routes = response.routes
return state return state
}) })
}, },
}, },
screens: { screens: {
select: screenId => { select: screenId => {
store.update(state => { // Check this screen exists
let screens = state.screens const state = get(store)
let screen = const screen = state.screens.find(screen => screen._id === screenId)
screens.find(screen => screen._id === screenId) || screens[0] if (!screen) {
if (!screen) return state return
}
// Check screen isn't already selected
if (
state.selectedScreenId === screen._id &&
state.selectedComponentId === screen.props?._id
) {
return
}
// Select new screen
store.update(state => {
state.selectedScreenId = screen._id state.selectedScreenId = screen._id
state.selectedComponentId = screen.props?._id state.selectedComponentId = screen.props?._id
return state return state
@ -198,25 +220,40 @@ export const getFrontendStore = () => {
save: async screen => { save: async screen => {
const creatingNewScreen = screen._id === undefined const creatingNewScreen = screen._id === undefined
const savedScreen = await API.saveScreen(screen) const savedScreen = await API.saveScreen(screen)
const routesResponse = await API.fetchAppRoutes()
store.update(state => { store.update(state => {
// Update screen object
const idx = state.screens.findIndex(x => x._id === savedScreen._id) const idx = state.screens.findIndex(x => x._id === savedScreen._id)
if (idx !== -1) { if (idx !== -1) {
state.screens.splice(idx, 1, savedScreen) state.screens.splice(idx, 1, savedScreen)
} else { } else {
state.screens.push(savedScreen) 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
return state return state
}) })
// Refresh routes
await store.actions.routing.fetch()
// Select the new screen if creating a new one
if (creatingNewScreen) {
store.actions.screens.select(savedScreen._id)
}
return savedScreen 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)
},
delete: async screens => { delete: async screens => {
const screensToDelete = Array.isArray(screens) ? screens : [screens] const screensToDelete = Array.isArray(screens) ? screens : [screens]
@ -238,60 +275,78 @@ export const getFrontendStore = () => {
promises.push(store.actions.links.delete(deleteUrls)) promises.push(store.actions.links.delete(deleteUrls))
await Promise.all(promises) await Promise.all(promises)
const deletedIds = screensToDelete.map(screen => screen._id) const deletedIds = screensToDelete.map(screen => screen._id)
const routesResponse = await API.fetchAppRoutes()
store.update(state => { store.update(state => {
// Remove deleted screens from state // Remove deleted screens from state
state.screens = state.screens.filter(screen => { state.screens = state.screens.filter(screen => {
return !deletedIds.includes(screen._id) return !deletedIds.includes(screen._id)
}) })
// Deselect the current screen if it was deleted // Deselect the current screen if it was deleted
if (deletedIds.includes(state.selectedScreenId)) { if (deletedIds.includes(state.selectedScreenId)) {
state.selectedScreenId = null state.selectedScreenId = null
state.selectedComponentId = null
} }
// Update routing
state.routes = routesResponse.routes
return state return state
}) })
// Refresh routes
await store.actions.routing.fetch()
}, },
updateHomeScreen: async (screen, makeHomeScreen = true) => { updateSetting: async (screen, name, value) => {
let promises = [] if (!screen || !name) {
return
// Find any existing home screen for this role so we can remove it,
// if we are setting this to be the new home screen
if (makeHomeScreen) {
const roleId = screen.routing.roleId
let existingHomeScreen = get(store).screens.find(s => {
return (
s.routing.roleId === roleId &&
s.routing.homeScreen &&
s._id !== screen._id
)
})
if (existingHomeScreen) {
existingHomeScreen.routing.homeScreen = false
promises.push(store.actions.screens.save(existingHomeScreen))
}
} }
// Update the passed in screen // Apply setting update
screen.routing.homeScreen = makeHomeScreen const patch = screen => {
promises.push(store.actions.screens.save(screen)) if (!screen) {
return await Promise.all(promises) 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) {
const patch = screen => {
screen.routing.homeScreen = false
}
for (let otherHomeScreen of otherHomeScreens) {
await store.actions.screens.patch(patch, otherHomeScreen._id)
}
}
}, },
removeCustomLayout: async screen => { removeCustomLayout: async screen => {
// Pull relevant settings from old layout, if required // Pull relevant settings from old layout, if required
const layout = get(store).layouts.find(x => x._id === screen.layoutId) const layout = get(store).layouts.find(x => x._id === screen.layoutId)
screen.layoutId = null const patch = screen => {
screen.showNavigation = layout?.props.navigation !== "None" screen.layoutId = null
screen.width = layout?.props.width || "Large" screen.showNavigation = layout?.props.navigation !== "None"
await store.actions.screens.save(screen) screen.width = layout?.props.width || "Large"
}
await store.actions.screens.patch(patch, screen._id)
}, },
}, },
preview: { preview: {
saveSelected: async () => {
const selectedAsset = get(currentAsset)
return await store.actions.screens.save(selectedAsset)
},
setDevice: device => { setDevice: device => {
store.update(state => { store.update(state => {
state.previewDevice = device state.previewDevice = device
@ -301,41 +356,28 @@ export const getFrontendStore = () => {
}, },
layouts: { layouts: {
select: layoutId => { 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 => { store.update(state => {
const layout =
store.actions.layouts.find(layoutId) || get(store).layouts[0]
if (!layout) return
state.selectedLayoutId = layout._id state.selectedLayoutId = layout._id
state.selectedComponentId = layout.props?._id state.selectedComponentId = layout.props?._id
return state return state
}) })
}, },
save: async layout => {
const creatingNewLayout = layout._id === undefined
const savedLayout = await API.saveLayout(layout)
store.update(state => {
const idx = state.layouts.findIndex(x => x._id === savedLayout._id)
if (idx !== -1) {
state.layouts.splice(idx, 1, savedLayout)
} else {
state.layouts.push(savedLayout)
}
return state
})
// Select layout if creating a new one
if (creatingNewLayout) {
store.actions.layouts.select(savedLayout._id)
}
return savedLayout
},
find: layoutId => {
if (!layoutId) {
return get(mainLayout)
}
const storeContents = get(store)
return storeContents.layouts.find(layout => layout._id === layoutId)
},
delete: async layout => { delete: async layout => {
if (!layout?._id) { if (!layout?._id) {
return return
@ -345,10 +387,6 @@ export const getFrontendStore = () => {
layoutRev: layout._rev, layoutRev: layout._rev,
}) })
store.update(state => { store.update(state => {
// Select main layout if we deleted the selected layout
if (layout._id === state.selectedLayoutId) {
state.selectedLayoutId = get(mainLayout)._id
}
state.layouts = state.layouts.filter(x => x._id !== layout._id) state.layouts = state.layouts.filter(x => x._id !== layout._id)
return state return state
}) })
@ -386,7 +424,7 @@ export const getFrontendStore = () => {
} }
if (componentName.endsWith("/formstep")) { if (componentName.endsWith("/formstep")) {
const parentForm = findClosestMatchingComponent( const parentForm = findClosestMatchingComponent(
get(currentAsset).props, get(selectedScreen).props,
get(selectedComponent)._id, get(selectedComponent)._id,
component => component._component.endsWith("/form") component => component._component.endsWith("/form")
) )
@ -407,48 +445,59 @@ export const getFrontendStore = () => {
} }
}, },
create: async (componentName, presetProps) => { create: async (componentName, presetProps) => {
const selected = get(selectedComponent) const state = get(store)
const asset = get(currentAsset)
// Create new component
const componentInstance = store.actions.components.createInstance( const componentInstance = store.actions.components.createInstance(
componentName, componentName,
presetProps presetProps
) )
if (!componentInstance || !asset) { if (!componentInstance) {
return return
} }
// Find parent node to attach this component to // Patch selected screen
let parentComponent await store.actions.screens.patch(screen => {
if (selected) { // Find the selected component
// Use current screen or layout as parent if no component is selected const currentComponent = findComponent(
const definition = store.actions.components.getDefinition( screen.props,
selected._component state.selectedComponentId
) )
if (definition?.hasChildren) { if (!currentComponent) {
// Use selected component if it allows children return false
parentComponent = selected
} else {
// Otherwise we need to use the parent of this component
parentComponent = findComponentParent(asset?.props, selected._id)
} }
} else {
// Use screen or layout if no component is selected
parentComponent = asset?.props
}
// Attach component // Find parent node to attach this component to
if (!parentComponent) { let parentComponent
return if (currentComponent) {
} // Use selected component as parent if one is selected
if (!parentComponent._children) { const definition = store.actions.components.getDefinition(
parentComponent._children = [] currentComponent._component
} )
parentComponent._children.push(componentInstance) 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
}
// Save components and update UI // Attach new component
await store.actions.preview.saveSelected() if (!parentComponent) {
return false
}
if (!parentComponent._children) {
parentComponent._children = []
}
parentComponent._children.push(componentInstance)
})
// Select new component
store.update(state => { store.update(state => {
state.selectedComponentId = componentInstance._id state.selectedComponentId = componentInstance._id
return state return state
@ -461,50 +510,58 @@ export const getFrontendStore = () => {
return componentInstance return componentInstance
}, },
patch: async (patchFn, componentId, screenId) => {
// Use selected component by default
if (!componentId && !screenId) {
const state = get(store)
componentId = state.selectedComponentId
screenId = state.selectedScreenId
}
// Invalid if only a screen or component ID provided
if (!componentId || !screenId || !patchFn) {
return
}
const patchScreen = screen => {
let component = findComponent(screen.props, componentId)
if (!component) {
return false
}
return patchFn(component, screen)
}
await store.actions.screens.patch(patchScreen, screenId)
},
delete: async component => { delete: async component => {
if (!component) { if (!component) {
return return
} }
const asset = get(currentAsset) let parentId
if (!asset) {
return
}
// Fetch full definition // Patch screen
component = findComponent(asset.props, component._id) await store.actions.screens.patch(screen => {
// Check component exists
component = findComponent(screen.props, component._id)
if (!component) {
return false
}
// Ensure we aren't deleting the screen slot // Check component has a valid parent
if (component._component?.endsWith("/screenslot")) { const parent = findComponentParent(screen.props, component._id)
throw "You can't delete the screen slot" if (!parent) {
} return false
}
// Ensure we aren't deleting something that contains the screen slot parentId = parent._id
const screenslot = findComponentType(
component,
"@budibase/standard-components/screenslot"
)
if (screenslot != null) {
throw "You can't delete a component that contains the screen slot"
}
const parent = findComponentParent(asset.props, component._id)
if (parent) {
parent._children = parent._children.filter( parent._children = parent._children.filter(
child => child._id !== component._id child => child._id !== component._id
) )
store.update(state => { })
state.selectedComponentId = parent._id
return state // Select the deleted component's parent
}) store.update(state => {
} state.selectedComponentId = parentId
await store.actions.preview.saveSelected() return state
})
}, },
copy: (component, cut = false, selectParent = true) => { copy: (component, cut = false, selectParent = true) => {
const selectedAsset = get(currentAsset)
if (!selectedAsset) {
return null
}
// Update store with copied component // Update store with copied component
store.update(state => { store.update(state => {
state.componentToPaste = cloneDeep(component) state.componentToPaste = cloneDeep(component)
@ -512,13 +569,11 @@ export const getFrontendStore = () => {
return state return state
}) })
// Remove the component from its parent if we're cutting // Select the parent if cutting
if (cut) { if (cut) {
const parent = findComponentParent(selectedAsset.props, component._id) const screen = get(selectedScreen)
const parent = findComponentParent(screen?.props, component._id)
if (parent) { if (parent) {
parent._children = parent._children.filter(
child => child._id !== component._id
)
if (selectParent) { if (selectParent) {
store.update(state => { store.update(state => {
state.selectedComponentId = parent._id state.selectedComponentId = parent._id
@ -528,24 +583,42 @@ export const getFrontendStore = () => {
} }
} }
}, },
paste: async (targetComponent, mode) => { paste: async (targetComponent, mode, targetScreen) => {
let promises = [] const state = get(store)
store.update(state => { if (!state.componentToPaste) {
// Stop if we have nothing to paste return
if (!state.componentToPaste) { }
return state let newComponentId
// Patch screen
const patch = screen => {
// Get up to date ref to target
targetComponent = findComponent(screen.props, targetComponent._id)
if (!targetComponent) {
return
} }
const cut = state.componentToPaste.isCut const cut = state.componentToPaste.isCut
const originalId = state.componentToPaste._id
// Clone the component to paste and make unique if copying
delete state.componentToPaste.isCut
let componentToPaste = cloneDeep(state.componentToPaste) let componentToPaste = cloneDeep(state.componentToPaste)
if (cut) { delete componentToPaste.isCut
state.componentToPaste = null
} else { // Make new component unique if copying
if (!cut) {
makeComponentUnique(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
)
}
}
// Paste new component
if (mode === "inside") { if (mode === "inside") {
// Paste inside target component if chosen // Paste inside target component if chosen
if (!targetComponent._children) { if (!targetComponent._children) {
@ -553,66 +626,106 @@ export const getFrontendStore = () => {
} }
targetComponent._children.push(componentToPaste) targetComponent._children.push(componentToPaste)
} else { } else {
// Otherwise find the parent so we can paste in the correct order // Otherwise paste in the correct order in the parent's children
// in the parents child components
const selectedAsset = get(currentAsset)
if (!selectedAsset) {
return state
}
const parent = findComponentParent( const parent = findComponentParent(
selectedAsset.props, screen.props,
targetComponent._id targetComponent._id
) )
if (!parent) { if (!parent?._children) {
return state return false
} }
const targetIndex = parent._children.findIndex(component => {
// Insert the component in the correct position return component._id === targetComponent._id
const targetIndex = parent._children.indexOf(targetComponent) })
const index = mode === "above" ? targetIndex : targetIndex + 1 const index = mode === "above" ? targetIndex : targetIndex + 1
parent._children.splice(index, 0, cloneDeep(componentToPaste)) parent._children.splice(index, 0, componentToPaste)
} }
}
const targetScreenId = targetScreen?._id || state.selectedScreenId
await store.actions.screens.patch(patch, targetScreenId)
// Save and select the new component store.update(state => {
promises.push(store.actions.preview.saveSelected()) // Remove copied component if cutting
state.selectedComponentId = componentToPaste._id if (state.componentToPaste.isCut) {
delete state.componentToPaste
}
state.selectedScreenId = targetScreenId
state.selectedComponentId = newComponentId
return state return state
}) })
await Promise.all(promises) },
moveUp: async component => {
await store.actions.screens.patch(screen => {
const componentId = component?._id
const parent = findComponentParent(screen.props, componentId)
if (!parent?._children?.length) {
return false
}
const currentIndex = parent._children.findIndex(
child => child._id === componentId
)
if (currentIndex === 0) {
return false
}
const originalComponent = cloneDeep(parent._children[currentIndex])
const newChildren = parent._children.filter(
component => component._id !== componentId
)
newChildren.splice(currentIndex - 1, 0, originalComponent)
parent._children = newChildren
})
},
moveDown: async component => {
await store.actions.screens.patch(screen => {
const componentId = component?._id
const parent = findComponentParent(screen.props, componentId)
if (!parent?._children?.length) {
return false
}
const currentIndex = parent._children.findIndex(
child => child._id === componentId
)
if (currentIndex === parent._children.length - 1) {
return false
}
const originalComponent = cloneDeep(parent._children[currentIndex])
const newChildren = parent._children.filter(
component => component._id !== componentId
)
newChildren.splice(currentIndex + 1, 0, originalComponent)
parent._children = newChildren
})
}, },
updateStyle: async (name, value) => { updateStyle: async (name, value) => {
const selected = get(selectedComponent) await store.actions.components.patch(component => {
if (value == null || value === "") { if (value == null || value === "") {
delete selected._styles.normal[name] delete component._styles.normal[name]
} else { } else {
selected._styles.normal[name] = value component._styles.normal[name] = value
} }
await store.actions.preview.saveSelected() })
}, },
updateCustomStyle: async style => { updateCustomStyle: async style => {
const selected = get(selectedComponent) await store.actions.components.patch(component => {
selected._styles.custom = style component._styles.custom = style
await store.actions.preview.saveSelected() })
}, },
updateConditions: async conditions => { updateConditions: async conditions => {
const selected = get(selectedComponent) await store.actions.components.patch(component => {
selected._conditions = conditions component._conditions = conditions
await store.actions.preview.saveSelected() })
}, },
updateProp: async (name, value) => { updateSetting: async (name, value) => {
let component = get(selectedComponent) await store.actions.components.patch(component => {
if (!name || !component) { if (!name || !component) {
return return false
} }
if (component[name] === value) { // Skip update if the value is the same
return if (component[name] === value) {
} return false
component[name] = value }
store.update(state => { component[name] = value
state.selectedComponentId = component._id
return state
}) })
await store.actions.preview.saveSelected()
}, },
}, },
links: { links: {

View File

@ -18,7 +18,7 @@
const dataSource = form?.dataSource const dataSource = form?.dataSource
const fields = makeDatasourceFormComponents(dataSource) const fields = makeDatasourceFormComponents(dataSource)
try { try {
await store.actions.components.updateProp( await store.actions.components.updateSetting(
"_children", "_children",
fields.map(field => field.json()) fields.map(field => field.json())
) )

View File

@ -17,7 +17,8 @@
getOptionValue={x => x._id} getOptionValue={x => x._id}
getOptionIcon={x => (x.routing.homeScreen ? "Home" : "WebPage")} getOptionIcon={x => (x.routing.homeScreen ? "Home" : "WebPage")}
getOptionColour={x => RoleUtils.getRoleColour(x.routing.roleId)} getOptionColour={x => RoleUtils.getRoleColour(x.routing.roleId)}
bind:value={$store.selectedScreenId} value={$store.selectedScreenId}
on:change={e => store.actions.screens.select(e.detail)}
/> />
</div> </div>
<div class="header-right"> <div class="header-right">

View File

@ -85,6 +85,10 @@
previewDevice: $store.previewDevice, previewDevice: $store.previewDevice,
messagePassing: $store.clientFeatures.messagePassing, messagePassing: $store.clientFeatures.messagePassing,
navigation: $store.navigation, navigation: $store.navigation,
hiddenComponentIds:
$store.componentToPaste?._id && $store.componentToPaste?.isCut
? [$store.componentToPaste?._id]
: [],
isBudibaseEvent: true, isBudibaseEvent: true,
} }
@ -138,7 +142,7 @@
$goto("./components") $goto("./components")
} }
} else if (type === "update-prop") { } else if (type === "update-prop") {
await store.actions.components.updateProp(data.prop, data.value) await store.actions.components.updateSetting(data.prop, data.value)
} else if (type === "delete-component" && data.id) { } else if (type === "delete-component" && data.id) {
confirmDeleteComponent(data.id) confirmDeleteComponent(data.id)
} else if (type === "duplicate-component" && data.id) { } else if (type === "duplicate-component" && data.id) {

View File

@ -65,7 +65,8 @@ export default `
theme, theme,
customTheme, customTheme,
previewDevice, previewDevice,
navigation navigation,
hiddenComponentIds
} = parsed } = parsed
// Set some flags so the app knows we're in the builder // Set some flags so the app knows we're in the builder
@ -79,6 +80,7 @@ export default `
window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"] = customTheme window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"] = customTheme
window["##BUDIBASE_PREVIEW_DEVICE##"] = previewDevice window["##BUDIBASE_PREVIEW_DEVICE##"] = previewDevice
window["##BUDIBASE_PREVIEW_NAVIGATION##"] = navigation window["##BUDIBASE_PREVIEW_NAVIGATION##"] = navigation
window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"] = hiddenComponentIds
// Initialise app // Initialise app
try { try {

View File

@ -1,8 +1,6 @@
<script> <script>
import { get } from "svelte/store" import { store } from "builderStore"
import { store, currentAsset } from "builderStore"
import ConfirmDialog from "components/common/ConfirmDialog.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { findComponentParent } from "builderStore/componentUtils"
import { ActionMenu, MenuItem, Icon, notifications } from "@budibase/bbui" import { ActionMenu, MenuItem, Icon, notifications } from "@budibase/bbui"
export let component export let component
@ -19,43 +17,19 @@
// not show a context menu. // not show a context menu.
$: showMenu = definition?.editable !== false && definition?.static !== true $: showMenu = definition?.editable !== false && definition?.static !== true
const moveUpComponent = () => { const moveUpComponent = async () => {
const asset = get(currentAsset)
const parent = findComponentParent(asset?.props, component._id)
if (!parent) {
return
}
const currentIndex = parent._children.indexOf(component)
if (currentIndex === 0) {
return
}
try { try {
const newChildren = parent._children.filter(c => c !== component) await store.actions.components.moveUp(component)
newChildren.splice(currentIndex - 1, 0, component)
parent._children = newChildren
store.actions.preview.saveSelected()
} catch (error) { } catch (error) {
notifications.error("Error saving screen") notifications.error("Error moving component up")
} }
} }
const moveDownComponent = () => { const moveDownComponent = async () => {
const asset = get(currentAsset)
const parent = findComponentParent(asset?.props, component._id)
if (!parent) {
return
}
const currentIndex = parent._children.indexOf(component)
if (currentIndex === parent._children.length - 1) {
return
}
try { try {
const newChildren = parent._children.filter(c => c !== component) await store.actions.components.moveDown(component)
newChildren.splice(currentIndex + 1, 0, component)
parent._children = newChildren
store.actions.preview.saveSelected()
} catch (error) { } catch (error) {
notifications.error("Error saving screen") notifications.error("Error moving component down")
} }
} }

View File

@ -18,6 +18,13 @@
let closedNodes = {} let closedNodes = {}
$: filteredComponents = components?.filter(component => {
return (
!$store.componentToPaste?.isCut ||
component._id !== $store.componentToPaste?._id
)
})
const dragover = (component, index) => e => { const dragover = (component, index) => e => {
const mousePosition = e.offsetY / e.currentTarget.offsetHeight const mousePosition = e.offsetY / e.currentTarget.offsetHeight
dndStore.actions.dragover({ dndStore.actions.dragover({
@ -91,7 +98,7 @@
</script> </script>
<ul> <ul>
{#each components || [] as component, index (component._id)} {#each filteredComponents || [] as component, index (component._id)}
{@const opened = isOpen(component, $selectedComponentPath, closedNodes)} {@const opened = isOpen(component, $selectedComponentPath, closedNodes)}
<li <li
on:click|stopPropagation={() => { on:click|stopPropagation={() => {

View File

@ -5,7 +5,6 @@
import PropertyControl from "components/design/settings/controls/PropertyControl.svelte" import PropertyControl from "components/design/settings/controls/PropertyControl.svelte"
import ResetFieldsButton from "components/design/settings/controls/ResetFieldsButton.svelte" import ResetFieldsButton from "components/design/settings/controls/ResetFieldsButton.svelte"
import { getComponentForSetting } from "components/design/settings/componentSettings" import { getComponentForSetting } from "components/design/settings/componentSettings"
import { Utils } from "@budibase/frontend-core"
export let componentDefinition export let componentDefinition
export let componentInstance export let componentInstance
@ -29,13 +28,13 @@
] ]
} }
const updateProp = Utils.sequential(async (key, value) => { const updateSetting = async (key, value) => {
try { try {
await store.actions.components.updateProp(key, value) await store.actions.components.updateSetting(key, value)
} catch (error) { } catch (error) {
notifications.error("Error updating component prop") notifications.error("Error updating component prop")
} }
}) }
const canRenderControl = setting => { const canRenderControl = setting => {
const control = getComponentForSetting(setting) const control = getComponentForSetting(setting)
@ -84,7 +83,7 @@
label="Name" label="Name"
key="_instanceName" key="_instanceName"
value={componentInstance._instanceName} value={componentInstance._instanceName}
onChange={val => updateProp("_instanceName", val)} onChange={val => updateSetting("_instanceName", val)}
/> />
{/if} {/if}
{#each section.settings as setting (setting.key)} {#each section.settings as setting (setting.key)}
@ -97,7 +96,7 @@
value={componentInstance[setting.key]} value={componentInstance[setting.key]}
defaultValue={setting.defaultValue} defaultValue={setting.defaultValue}
nested={setting.nested} nested={setting.nested}
onChange={val => updateProp(setting.key, val)} onChange={val => updateSetting(setting.key, val)}
highlighted={$store.highlightedSettingKey === setting.key} highlighted={$store.highlightedSettingKey === setting.key}
props={{ props={{
// Generic settings // Generic settings

View File

@ -13,7 +13,7 @@
indentLevel={0} indentLevel={0}
selected={$store.selectedLayoutId === layout._id} selected={$store.selectedLayoutId === layout._id}
text={layout.name} text={layout.name}
on:click={() => ($store.selectedLayoutId = layout._id)} on:click={() => store.actions.layouts.select(layout._id)}
> >
<LayoutDropdownMenu {layout} /> <LayoutDropdownMenu {layout} />
</NavItem> </NavItem>

View File

@ -23,7 +23,7 @@
const pasteComponent = mode => { const pasteComponent = mode => {
try { try {
store.actions.components.paste(screen.props, mode) store.actions.components.paste(screen.props, mode, screen)
} catch (error) { } catch (error) {
notifications.error("Error saving component") notifications.error("Error saving component")
} }

View File

@ -60,7 +60,7 @@
indentLevel={0} indentLevel={0}
selected={$store.selectedScreenId === screen._id} selected={$store.selectedScreenId === screen._id}
text={screen.routing.route} text={screen.routing.route}
on:click={() => ($store.selectedScreenId = screen._id)} on:click={() => store.actions.screens.select(screen._id)}
color={RoleUtils.getRoleColour(screen.routing.roleId)} color={RoleUtils.getRoleColour(screen.routing.roleId)}
> >
<ScreenDropdownMenu screenId={screen._id} /> <ScreenDropdownMenu screenId={screen._id} />

View File

@ -1,7 +1,7 @@
<script> <script>
import Panel from "components/design/Panel.svelte" import Panel from "components/design/Panel.svelte"
import { get } from "svelte/store" import { get } from "svelte/store"
import { get as deepGet, setWith } from "lodash" import { Helpers } from "@budibase/bbui"
import { import {
Input, Input,
Layout, Layout,
@ -42,7 +42,7 @@
) )
} }
const setScreenSetting = (setting, value) => { const setScreenSetting = async (setting, value) => {
const { key, parser, validate } = setting const { key, parser, validate } = setting
// Parse value if required // Parse value if required
@ -67,29 +67,11 @@
} }
} }
// Home screen changes need to be handled manually // Update screen setting
if (key === "routing.homeScreen") {
store.actions.screens.updateHomeScreen(get(selectedScreen), value)
return
}
// Update screen object in store
// If there are 2 home screens after this change, remove this screen as a
// home screen
const screen = get(selectedScreen)
setWith(screen, key.split("."), value, Object)
const roleId = screen.routing.roleId
const homeScreens = get(store).screens.filter(screen => {
return screen.routing.roleId === roleId && screen.routing.homeScreen
})
if (homeScreens.length > 1) {
screen.routing.homeScreen = false
}
// Save new definition
try { try {
store.actions.screens.save(screen) await store.actions.screens.updateSetting(get(selectedScreen), key, value)
} catch (error) { } catch (error) {
console.log(error)
notifications.error("Error saving screen settings") notifications.error("Error saving screen settings")
} }
} }
@ -184,7 +166,7 @@
control={setting.control} control={setting.control}
label={setting.label} label={setting.label}
key={setting.key} key={setting.key}
value={deepGet($selectedScreen, setting.key)} value={Helpers.deepGet($selectedScreen, setting.key)}
onChange={val => setScreenSetting(setting, val)} onChange={val => setScreenSetting(setting, val)}
props={{ ...setting.props, error: errors[setting.key] }} props={{ ...setting.props, error: errors[setting.key] }}
{bindings} {bindings}

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/cli", "name": "@budibase/cli",
"version": "1.1.15-alpha.3", "version": "1.1.17",
"description": "Budibase CLI, for developers, self hosting and migrations.", "description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "src/index.js", "main": "src/index.js",
"bin": { "bin": {

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/client", "name": "@budibase/client",
"version": "1.1.15-alpha.3", "version": "1.1.17",
"license": "MPL-2.0", "license": "MPL-2.0",
"module": "dist/budibase-client.js", "module": "dist/budibase-client.js",
"main": "dist/budibase-client.js", "main": "dist/budibase-client.js",
@ -19,9 +19,9 @@
"dev:builder": "rollup -cw" "dev:builder": "rollup -cw"
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.1.15-alpha.3", "@budibase/bbui": "^1.1.17",
"@budibase/frontend-core": "^1.1.15-alpha.3", "@budibase/frontend-core": "^1.1.17",
"@budibase/string-templates": "^1.1.15-alpha.3", "@budibase/string-templates": "^1.1.17",
"@spectrum-css/button": "^3.0.3", "@spectrum-css/button": "^3.0.3",
"@spectrum-css/card": "^3.0.3", "@spectrum-css/card": "^3.0.3",
"@spectrum-css/divider": "^1.0.3", "@spectrum-css/divider": "^1.0.3",

View File

@ -121,6 +121,8 @@
!isScreen && !isScreen &&
definition?.draggable !== false definition?.draggable !== false
$: droppable = interactive && !isLayout && !isScreen $: droppable = interactive && !isLayout && !isScreen
$: builderHidden =
$builderStore.inBuilder && $builderStore.hiddenComponentIds?.includes(id)
// Empty components are those which accept children but do not have any. // Empty components are those which accept children but do not have any.
// Empty states can be shown for these components, but can be disabled // Empty states can be shown for these components, but can be disabled
@ -434,7 +436,7 @@
}) })
</script> </script>
{#if constructor && initialSettings && (visible || inSelectedPath)} {#if constructor && initialSettings && (visible || inSelectedPath) && !builderHidden}
<!-- The ID is used as a class because getElementsByClassName is O(1) --> <!-- The ID is used as a class because getElementsByClassName is O(1) -->
<!-- and the performance matters for the selection indicators --> <!-- and the performance matters for the selection indicators -->
<div <div

View File

@ -20,6 +20,7 @@ const loadBudibase = () => {
customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"], customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"],
previewDevice: window["##BUDIBASE_PREVIEW_DEVICE##"], previewDevice: window["##BUDIBASE_PREVIEW_DEVICE##"],
navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"], navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"],
hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"],
}) })
// Set app ID - this window flag is set by both the preview and the real // Set app ID - this window flag is set by both the preview and the real

View File

@ -17,6 +17,7 @@ const createBuilderStore = () => {
previewDevice: "desktop", previewDevice: "desktop",
isDragging: false, isDragging: false,
navigation: null, navigation: null,
hiddenComponentIds: [],
// Legacy - allow the builder to specify a layout // Legacy - allow the builder to specify a layout
layout: null, layout: null,

View File

@ -1,12 +1,12 @@
{ {
"name": "@budibase/frontend-core", "name": "@budibase/frontend-core",
"version": "1.1.15-alpha.3", "version": "1.1.17",
"description": "Budibase frontend core libraries used in builder and client", "description": "Budibase frontend core libraries used in builder and client",
"author": "Budibase", "author": "Budibase",
"license": "MPL-2.0", "license": "MPL-2.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.1.15-alpha.3", "@budibase/bbui": "^1.1.17",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"svelte": "^3.46.2" "svelte": "^3.46.2"
} }

View File

@ -5,13 +5,17 @@
* @return {Promise} a sequential version of the function * @return {Promise} a sequential version of the function
*/ */
export const sequential = fn => { export const sequential = fn => {
let promise let queue = []
return async (...params) => { return async (...params) => {
if (promise) { queue.push(async () => {
await promise await fn(...params)
queue.shift()
if (queue.length) {
await queue[0]()
}
})
if (queue.length === 1) {
await queue[0]()
} }
promise = fn(...params)
await promise
promise = null
} }
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/server", "name": "@budibase/server",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "1.1.15-alpha.3", "version": "1.1.17",
"description": "Budibase Web Server", "description": "Budibase Web Server",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -77,11 +77,11 @@
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@apidevtools/swagger-parser": "10.0.3", "@apidevtools/swagger-parser": "10.0.3",
"@budibase/backend-core": "^1.1.15-alpha.3", "@budibase/backend-core": "^1.1.17",
"@budibase/client": "^1.1.15-alpha.3", "@budibase/client": "^1.1.17",
"@budibase/pro": "1.1.15-alpha.3", "@budibase/pro": "1.1.17",
"@budibase/string-templates": "^1.1.15-alpha.3", "@budibase/string-templates": "^1.1.17",
"@budibase/types": "^1.1.15-alpha.3", "@budibase/types": "^1.1.17",
"@bull-board/api": "3.7.0", "@bull-board/api": "3.7.0",
"@bull-board/koa": "3.9.4", "@bull-board/koa": "3.9.4",
"@elastic/elasticsearch": "7.10.0", "@elastic/elasticsearch": "7.10.0",

View File

@ -3,9 +3,7 @@ const actions = require("../automations/actions")
const automationUtils = require("../automations/automationUtils") const automationUtils = require("../automations/automationUtils")
const AutomationEmitter = require("../events/AutomationEmitter") const AutomationEmitter = require("../events/AutomationEmitter")
const { processObject } = require("@budibase/string-templates") const { processObject } = require("@budibase/string-templates")
const { DEFAULT_TENANT_ID } = require("@budibase/backend-core/constants")
const { DocumentTypes } = require("../db/utils") const { DocumentTypes } = require("../db/utils")
const { doInTenant } = require("@budibase/backend-core/tenancy")
const { definitions: triggerDefs } = require("../automations/triggerInfo") const { definitions: triggerDefs } = require("../automations/triggerInfo")
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context") const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
const { AutomationErrors, LoopStepTypes } = require("../constants") const { AutomationErrors, LoopStepTypes } = require("../constants")
@ -134,7 +132,6 @@ class Orchestrator {
async execute() { async execute() {
let automation = this._automation let automation = this._automation
const app = await this.getApp()
let stopped = false let stopped = false
let loopStep = null let loopStep = null
@ -161,7 +158,7 @@ class Orchestrator {
let originalStepInput = cloneDeep(step.inputs) let originalStepInput = cloneDeep(step.inputs)
// Handle if the user has set a max iteration count or if it reaches the max limit set by us // Handle if the user has set a max iteration count or if it reaches the max limit set by us
if (loopStep) { if (loopStep && input.binding) {
let newInput = await processObject( let newInput = await processObject(
loopStep.inputs, loopStep.inputs,
cloneDeep(this._context) cloneDeep(this._context)
@ -264,14 +261,11 @@ class Orchestrator {
inputs = automationUtils.cleanInputValues(inputs, step.schema.inputs) inputs = automationUtils.cleanInputValues(inputs, step.schema.inputs)
try { try {
// appId is always passed // appId is always passed
let tenantId = app.tenantId || DEFAULT_TENANT_ID const outputs = await stepFn({
const outputs = await doInTenant(tenantId, () => { inputs: inputs,
return stepFn({ appId: this._appId,
inputs: inputs, emitter: this._emitter,
appId: this._appId, context: this._context,
emitter: this._emitter,
context: this._context,
})
}) })
this._context.steps[stepCount] = outputs this._context.steps[stepCount] = outputs
// if filter causes us to stop execution don't break the loop, set a var // if filter causes us to stop execution don't break the loop, set a var

View File

@ -1094,12 +1094,12 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/backend-core@1.1.15-alpha.1": "@budibase/backend-core@1.1.17":
version "1.1.15-alpha.1" version "1.1.17"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.15-alpha.1.tgz#fb2b726a9afe301aaedbf09a5bcfa82ef14fa7b9" resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.17.tgz#5102a6b457823735e4da71eb9bca8218a667f57b"
integrity sha512-tVujXhAA7E8h9DbmAeRmje/CcJKwWvPIk8og6o46kmkdLx+7lwm4AG4ImrsR9PoRtvhkdUClAUwuGtFGcsafwg== integrity sha512-SQQA3IvlD+ARMIXnAErFzOAzC67e9hM72qgZvOc3cqfBpvObSg1VnmNAuuG4GB0y3dm21ldLpCBQFzPH2Ylkkg==
dependencies: dependencies:
"@budibase/types" "^1.1.15-alpha.1" "@budibase/types" "^1.1.17"
"@techpass/passport-openidconnect" "0.3.2" "@techpass/passport-openidconnect" "0.3.2"
aws-sdk "2.1030.0" aws-sdk "2.1030.0"
bcrypt "5.0.1" bcrypt "5.0.1"
@ -1177,13 +1177,13 @@
svelte-flatpickr "^3.2.3" svelte-flatpickr "^3.2.3"
svelte-portal "^1.0.0" svelte-portal "^1.0.0"
"@budibase/pro@1.1.15-alpha.1": "@budibase/pro@1.1.17":
version "1.1.15-alpha.1" version "1.1.17"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.15-alpha.1.tgz#8013b5bdb6adea291bf29a32f9c572e5cc1f9fc8" resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.17.tgz#6d6493b4df1c796469c0925c9d7b83e5f12b7b92"
integrity sha512-8DwIs12un59YnLNlqUFQgGqclf4Dmpp76Yo4cVDeRkaKDvbRJoUUK7jkYsDpstU6FVXD8m6/0l8Pwr3gWN5iyQ== integrity sha512-k0tfmeTf1Hh6m9U17wpUqfC0U2XvwhIf1Bbh7cbk8c41esm8blO0LxRpQGCS49lM85bfMFJvAGDr3+BHkiN7HA==
dependencies: dependencies:
"@budibase/backend-core" "1.1.15-alpha.1" "@budibase/backend-core" "1.1.17"
"@budibase/types" "1.1.15-alpha.1" "@budibase/types" "1.1.17"
node-fetch "^2.6.1" node-fetch "^2.6.1"
"@budibase/standard-components@^0.9.139": "@budibase/standard-components@^0.9.139":
@ -1204,15 +1204,10 @@
svelte-apexcharts "^1.0.2" svelte-apexcharts "^1.0.2"
svelte-flatpickr "^3.1.0" svelte-flatpickr "^3.1.0"
"@budibase/types@1.1.15-alpha.1": "@budibase/types@1.1.17", "@budibase/types@^1.1.17":
version "1.1.15-alpha.1" version "1.1.17"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.15-alpha.1.tgz#4abb0830e3c1dca4a49bc974371edda922f8253b" resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.17.tgz#fa58e86f3858c04a8b79094193ff87ac57a499fe"
integrity sha512-x00f0/JY2CayjGEBR9R2cH/87nFV1dg2bZHXdMIWN6djcQjBsMjkaq+Qx2xJtWPMcld9yufPbBWdfgVQsiPc0A== integrity sha512-3sTH3tjPd+NEk5CIN23bgwyGXXNYq/hwaxKMbYLKGr45K6m9WDZs6saWxJ2JwguNtKGB9RggzCVR/DFJH2zI1A==
"@budibase/types@^1.1.15-alpha.1":
version "1.1.16"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.16.tgz#4dd1f0b1e630abd46749414d74a1fdd07820df54"
integrity sha512-jaOdsCOx0CJ2tyKodTI6PMo9CNHTo1nsMMrRi/XFIFQtGOypkiNoskb5u0Ee3GtpN6LNXgwPdrYnh+vcIL9lRw==
"@bull-board/api@3.7.0": "@bull-board/api@3.7.0":
version "3.7.0" version "3.7.0"

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/string-templates", "name": "@budibase/string-templates",
"version": "1.1.15-alpha.3", "version": "1.1.17",
"description": "Handlebars wrapper for Budibase templating.", "description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs", "main": "src/index.cjs",
"module": "dist/bundle.mjs", "module": "dist/bundle.mjs",

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/types", "name": "@budibase/types",
"version": "1.1.15-alpha.3", "version": "1.1.17",
"description": "Budibase types", "description": "Budibase types",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/worker", "name": "@budibase/worker",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "1.1.15-alpha.3", "version": "1.1.17",
"description": "Budibase background service", "description": "Budibase background service",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -35,10 +35,10 @@
"author": "Budibase", "author": "Budibase",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@budibase/backend-core": "^1.1.15-alpha.3", "@budibase/backend-core": "^1.1.17",
"@budibase/pro": "1.1.15-alpha.3", "@budibase/pro": "1.1.17",
"@budibase/string-templates": "^1.1.15-alpha.3", "@budibase/string-templates": "^1.1.17",
"@budibase/types": "^1.1.15-alpha.3", "@budibase/types": "^1.1.17",
"@koa/router": "8.0.8", "@koa/router": "8.0.8",
"@sentry/node": "6.17.7", "@sentry/node": "6.17.7",
"@techpass/passport-openidconnect": "0.3.2", "@techpass/passport-openidconnect": "0.3.2",

View File

@ -291,12 +291,12 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/backend-core@1.1.15-alpha.1": "@budibase/backend-core@1.1.17":
version "1.1.15-alpha.1" version "1.1.17"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.15-alpha.1.tgz#fb2b726a9afe301aaedbf09a5bcfa82ef14fa7b9" resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.17.tgz#5102a6b457823735e4da71eb9bca8218a667f57b"
integrity sha512-tVujXhAA7E8h9DbmAeRmje/CcJKwWvPIk8og6o46kmkdLx+7lwm4AG4ImrsR9PoRtvhkdUClAUwuGtFGcsafwg== integrity sha512-SQQA3IvlD+ARMIXnAErFzOAzC67e9hM72qgZvOc3cqfBpvObSg1VnmNAuuG4GB0y3dm21ldLpCBQFzPH2Ylkkg==
dependencies: dependencies:
"@budibase/types" "^1.1.15-alpha.1" "@budibase/types" "^1.1.17"
"@techpass/passport-openidconnect" "0.3.2" "@techpass/passport-openidconnect" "0.3.2"
aws-sdk "2.1030.0" aws-sdk "2.1030.0"
bcrypt "5.0.1" bcrypt "5.0.1"
@ -324,24 +324,19 @@
uuid "8.3.2" uuid "8.3.2"
zlib "1.0.5" zlib "1.0.5"
"@budibase/pro@1.1.15-alpha.1": "@budibase/pro@1.1.17":
version "1.1.15-alpha.1" version "1.1.17"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.15-alpha.1.tgz#8013b5bdb6adea291bf29a32f9c572e5cc1f9fc8" resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.17.tgz#6d6493b4df1c796469c0925c9d7b83e5f12b7b92"
integrity sha512-8DwIs12un59YnLNlqUFQgGqclf4Dmpp76Yo4cVDeRkaKDvbRJoUUK7jkYsDpstU6FVXD8m6/0l8Pwr3gWN5iyQ== integrity sha512-k0tfmeTf1Hh6m9U17wpUqfC0U2XvwhIf1Bbh7cbk8c41esm8blO0LxRpQGCS49lM85bfMFJvAGDr3+BHkiN7HA==
dependencies: dependencies:
"@budibase/backend-core" "1.1.15-alpha.1" "@budibase/backend-core" "1.1.17"
"@budibase/types" "1.1.15-alpha.1" "@budibase/types" "1.1.17"
node-fetch "^2.6.1" node-fetch "^2.6.1"
"@budibase/types@1.1.15-alpha.1": "@budibase/types@1.1.17", "@budibase/types@^1.1.17":
version "1.1.15-alpha.1" version "1.1.17"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.15-alpha.1.tgz#4abb0830e3c1dca4a49bc974371edda922f8253b" resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.17.tgz#fa58e86f3858c04a8b79094193ff87ac57a499fe"
integrity sha512-x00f0/JY2CayjGEBR9R2cH/87nFV1dg2bZHXdMIWN6djcQjBsMjkaq+Qx2xJtWPMcld9yufPbBWdfgVQsiPc0A== integrity sha512-3sTH3tjPd+NEk5CIN23bgwyGXXNYq/hwaxKMbYLKGr45K6m9WDZs6saWxJ2JwguNtKGB9RggzCVR/DFJH2zI1A==
"@budibase/types@^1.1.15-alpha.1":
version "1.1.16"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.16.tgz#4dd1f0b1e630abd46749414d74a1fdd07820df54"
integrity sha512-jaOdsCOx0CJ2tyKodTI6PMo9CNHTo1nsMMrRi/XFIFQtGOypkiNoskb5u0Ee3GtpN6LNXgwPdrYnh+vcIL9lRw==
"@cspotcode/source-map-consumer@0.8.0": "@cspotcode/source-map-consumer@0.8.0":
version "0.8.0" version "0.8.0"