Merge pull request #8054 from Budibase/plugin-improvements

Plugin fixes + improvements
This commit is contained in:
Andrew Kingston 2022-09-30 16:20:20 +01:00 committed by GitHub
commit 8c561239dd
8 changed files with 81 additions and 58 deletions

View File

@ -143,7 +143,10 @@ export const getComponentSettings = componentType => {
}
// Ensure whole component name is used
if (!componentType.startsWith("@budibase")) {
if (
!componentType.startsWith("plugin/") &&
!componentType.startsWith("@budibase")
) {
componentType = `@budibase/standard-components/${componentType}`
}

View File

@ -243,18 +243,18 @@ export const getDatasourceForProvider = (asset, component) => {
return null
}
// There are different types of setting which can be a datasource, for
// example an actual datasource object, or a table ID string.
// Convert the datasource setting into a proper datasource object so that
// we can use it properly
if (datasourceSetting.type === "table") {
// For legacy compatibility, we need to be able to handle datasources that are
// just strings. These are not generated any more, so could be removed in
// future.
// TODO: remove at some point
const datasource = component[datasourceSetting?.key]
if (typeof datasource === "string") {
return {
tableId: component[datasourceSetting?.key],
tableId: datasource,
type: "table",
}
} else {
return component[datasourceSetting?.key]
}
return datasource
}
/**

View File

@ -88,27 +88,12 @@ export const getFrontendStore = () => {
initialise: async pkg => {
const { layouts, screens, application, clientLibPath } = pkg
// Fetch component definitions.
// Allow errors to propagate.
const components = await API.fetchComponentLibDefinitions(
application.appId
)
// Filter out custom component keys so we can flag them
const customComponents = Object.keys(components).filter(name =>
name.startsWith("plugin/")
)
await store.actions.components.refreshDefinitions(application.appId)
// Reset store state
store.update(state => ({
...state,
libraries: application.componentLibraries,
components,
customComponents,
clientFeatures: {
...INITIAL_FRONTEND_STATE.clientFeatures,
...components.features,
},
name: application.name,
description: application.description,
appId: application.appId,
@ -385,6 +370,29 @@ export const getFrontendStore = () => {
},
},
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
@ -428,7 +436,7 @@ export const getFrontendStore = () => {
_id: Helpers.uuid(),
_component: definition.component,
_styles: { normal: {}, hover: {}, active: {} },
_instanceName: `New ${definition.name}`,
_instanceName: `New ${definition.friendlyName || definition.name}`,
...cloneDeep(props),
...extras,
}

View File

@ -1,26 +1,28 @@
<script>
import { Select } from "@budibase/bbui"
import { tables } from "stores/backend"
import { createEventDispatcher } from "svelte"
import { tables as tablesStore } from "stores/backend"
export let value
const dispatch = createEventDispatcher()
$: tables = $tablesStore.list.map(m => ({
label: m.name,
tableId: m._id,
type: "table",
}))
const onChange = e => {
const dataSource = tables?.find(x => x.tableId === e.detail)
dispatch("change", dataSource)
}
</script>
<div>
<Select extraThin secondary wide on:change {value}>
<option value="">Choose a table</option>
{#each $tables.list as table}
<option value={table._id}>{table.name}</option>
{/each}
</Select>
</div>
<style>
div {
flex: 1 1 auto;
display: flex;
flex-direction: row;
}
div :global(> *) {
flex: 1 1 auto;
}
</style>
<Select
on:change={onChange}
value={value?.tableId}
options={tables}
getOptionValue={x => x.tableId}
getOptionLabel={x => x.label}
/>

View File

@ -198,6 +198,8 @@
block: "center",
})
}
} else if (type === "reload-plugin") {
await store.actions.components.refreshDefinitions()
} else {
console.warn(`Client sent unknown event type: ${type}`)
}

View File

@ -98,6 +98,9 @@ const createBuilderStore = () => {
return state
})
}
// Notify the builder so we can reload component definitions
dispatchEvent("reload-plugin")
},
}
return {

View File

@ -1,13 +1,19 @@
import { builderStore, environmentStore } from "./stores/index.js"
import {
builderStore,
environmentStore,
notificationStore,
} from "./stores/index.js"
import { get } from "svelte/store"
import { io } from "socket.io-client"
let socket
export const initWebsocket = () => {
const { inBuilder, location } = get(builderStore)
const { cloud } = get(environmentStore)
// Only connect when we're inside the builder preview, for now
if (!inBuilder || !location || cloud) {
if (!inBuilder || !location || cloud || socket) {
return
}
@ -16,20 +22,20 @@ export const initWebsocket = () => {
const proto = tls ? "wss:" : "ws:"
const host = location.hostname
const port = location.port || (tls ? 443 : 80)
const socket = io(`${proto}//${host}:${port}`, {
socket = io(`${proto}//${host}:${port}`, {
path: "/socket/client",
// Cap reconnection attempts to 10 (total of 95 seconds before giving up)
reconnectionAttempts: 10,
// Delay initial reconnection attempt by 5 seconds
// Cap reconnection attempts to 3 (total of 15 seconds before giving up)
reconnectionAttempts: 3,
// Delay reconnection attempt by 5 seconds
reconnectionDelay: 5000,
// Then decrease to 10 second intervals
reconnectionDelayMax: 10000,
// Timeout after 5 seconds so we never stack requests
timeout: 5000,
reconnectionDelayMax: 5000,
// Timeout after 4 seconds so we never stack requests
timeout: 4000,
})
// Event handlers
socket.on("plugin-update", data => {
builderStore.actions.updateUsedPlugin(data.name, data.hash)
notificationStore.actions.info(`"${data.name}" plugin reloaded`)
})
}

View File

@ -8,10 +8,9 @@ export const buildRowEndpoints = API => ({
if (!tableId || !rowId) {
return null
}
const row = await API.get({
return await API.get({
url: `/api/${tableId}/rows/${rowId}`,
})
return (await API.enrichRows([row], tableId))[0]
},
/**