Merge branch 'plugins-dev-experience' of github.com:Budibase/budibase into plugins-dev-experience

This commit is contained in:
mike12345567 2022-08-10 17:30:18 +01:00
commit bab20e5744
7 changed files with 121 additions and 33 deletions

View File

@ -92,11 +92,41 @@ export const getFrontendStore = () => {
// Allow errors to propagate. // Allow errors to propagate.
let components = await API.fetchComponentLibDefinitions(application.appId) let components = await API.fetchComponentLibDefinitions(application.appId)
// Extend definitions with custom components
components["test"] = {
component: "test",
name: "Super cool component",
icon: "Text",
description: "A custom component",
showSettingsBar: false,
hasChildren: true,
settings: [
{
type: "text",
key: "text",
label: "Text",
},
],
context: {
type: "static",
values: [
{
label: "Text prop",
key: "text",
},
],
},
}
// Filter out custom component keys so we can flag them
let customComponents = ["test"]
// Reset store state // Reset store state
store.update(state => ({ store.update(state => ({
...state, ...state,
libraries: application.componentLibraries, libraries: application.componentLibraries,
components, components,
customComponents,
clientFeatures: { clientFeatures: {
...INITIAL_FRONTEND_STATE.clientFeatures, ...INITIAL_FRONTEND_STATE.clientFeatures,
...components.features, ...components.features,
@ -397,9 +427,6 @@ export const getFrontendStore = () => {
if (!componentName) { if (!componentName) {
return null return null
} }
if (!componentName.startsWith("@budibase")) {
componentName = `@budibase/standard-components/${componentName}`
}
return get(store).components[componentName] return get(store).components[componentName]
}, },
createInstance: (componentName, presetProps) => { createInstance: (componentName, presetProps) => {

View File

@ -37,6 +37,9 @@ export default `
} }
</style> </style>
<script src='{{ CLIENT_LIB_PATH }}'></script> <script src='{{ CLIENT_LIB_PATH }}'></script>
<script
type="application/javascript"
src="https://cdn.kingston.dev/plugin.min.js"></script>
<script> <script>
function receiveMessage(event) { function receiveMessage(event) {
if (!event.data) { if (!event.data) {

View File

@ -24,7 +24,11 @@
$: currentDefinition = store.actions.components.getDefinition( $: currentDefinition = store.actions.components.getDefinition(
$selectedComponent?._component $selectedComponent?._component
) )
$: enrichedStructure = enrichStructure(structure, $store.components) $: enrichedStructure = enrichStructure(
structure,
$store.components,
$store.customComponents
)
$: filteredStructure = filterStructure( $: filteredStructure = filterStructure(
enrichedStructure, enrichedStructure,
section, section,
@ -46,8 +50,18 @@
// Parses the structure in the manifest and returns an enriched structure with // Parses the structure in the manifest and returns an enriched structure with
// explicit categories // explicit categories
const enrichStructure = (structure, definitions) => { const enrichStructure = (structure, definitions, customComponents) => {
let enrichedStructure = [] let enrichedStructure = []
// Add custom components category
if (customComponents?.length) {
enrichedStructure.push({
name: "Custom components",
isCategory: true,
children: customComponents.map(x => definitions[x]),
})
}
structure.forEach(item => { structure.forEach(item => {
if (typeof item === "string") { if (typeof item === "string") {
const def = definitions[`@budibase/standard-components/${item}`] const def = definitions[`@budibase/standard-components/${item}`]
@ -65,6 +79,7 @@
}) })
} }
}) })
return enrichedStructure return enrichedStructure
} }
@ -225,7 +240,7 @@
position: fixed; position: fixed;
right: 0; right: 0;
z-index: 1; z-index: 1;
height: 100%; height: calc(100% - 60px);
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: stretch; align-items: stretch;

View File

@ -85,18 +85,8 @@
builderStore.actions.notifyLoaded() builderStore.actions.notifyLoaded()
} }
}) })
// TODO: remove. this is a test to render the first custom component
console.log(window["##BUDIBASE_CUSTOM_COMPONENTS##"]?.[0])
const custom = window["##BUDIBASE_CUSTOM_COMPONENTS##"]?.[0]?.Component
</script> </script>
{#if custom}
<div style="padding: 20px;">
<svelte:component this={custom} />
</div>
{/if}
{#if dataLoaded} {#if dataLoaded}
<div <div
id="spectrum-root" id="spectrum-root"

View File

@ -11,8 +11,6 @@
<script> <script>
import { getContext, setContext, onMount, onDestroy } from "svelte" import { getContext, setContext, onMount, onDestroy } from "svelte"
import { writable, get } from "svelte/store" import { writable, get } from "svelte/store"
import * as AppComponents from "components/app"
import Router from "./Router.svelte"
import { import {
enrichProps, enrichProps,
propsAreSame, propsAreSame,
@ -180,7 +178,7 @@
// Pull definition and constructor // Pull definition and constructor
const component = instance._component const component = instance._component
constructor = getComponentConstructor(component) constructor = componentStore.actions.getComponentConstructor(component)
definition = componentStore.actions.getComponentDefinition(component) definition = componentStore.actions.getComponentDefinition(component)
if (!definition) { if (!definition) {
return return
@ -237,16 +235,6 @@
}) })
} }
// Gets the component constructor for the specified component
const getComponentConstructor = component => {
const split = component?.split("/")
const name = split?.[split.length - 1]
if (name === "screenslot" && !insideScreenslot) {
return Router
}
return AppComponents[name]
}
const getSettingsDefinitionMap = settingsDefinition => { const getSettingsDefinitionMap = settingsDefinition => {
let map = {} let map = {}
settingsDefinition?.forEach(setting => { settingsDefinition?.forEach(setting => {

View File

@ -1,5 +1,5 @@
import ClientApp from "./components/ClientApp.svelte" import ClientApp from "./components/ClientApp.svelte"
import { builderStore, appStore, devToolsStore } from "./stores" import { componentStore, builderStore, appStore, devToolsStore } from "./stores"
import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-rollup.js" import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-rollup.js"
import { get } from "svelte/store" import { get } from "svelte/store"
@ -38,6 +38,13 @@ const loadBudibase = () => {
const enableDevTools = !get(builderStore).inBuilder && get(appStore).isDevApp const enableDevTools = !get(builderStore).inBuilder && get(appStore).isDevApp
devToolsStore.actions.setEnabled(enableDevTools) devToolsStore.actions.setEnabled(enableDevTools)
// Register any custom components
if (window["##BUDIBASE_CUSTOM_COMPONENTS##"]) {
window["##BUDIBASE_CUSTOM_COMPONENTS##"].forEach(component => {
componentStore.actions.registerCustomComponent(component)
})
}
// Create app if one hasn't been created yet // Create app if one hasn't been created yet
if (!app) { if (!app) {
app = new ClientApp({ app = new ClientApp({

View File

@ -4,6 +4,10 @@ import { findComponentById, findComponentPathById } from "../utils/components"
import { devToolsStore } from "./devTools" import { devToolsStore } from "./devTools"
import { screenStore } from "./screens" import { screenStore } from "./screens"
import { builderStore } from "./builder" import { builderStore } from "./builder"
import Router from "../components/Router.svelte"
import * as AppComponents from "../components/app/index.js"
const budibasePrefix = "@budibase/standard-components/"
const createComponentStore = () => { const createComponentStore = () => {
const store = writable({}) const store = writable({})
@ -34,6 +38,7 @@ const createComponentStore = () => {
findComponentPathById(asset?.props, selectedComponentId) || [] findComponentPathById(asset?.props, selectedComponentId) || []
return { return {
customComponentManifest: $store.customComponentManifest,
selectedComponentInstance: $store[selectedComponentId], selectedComponentInstance: $store[selectedComponentId],
selectedComponent: component, selectedComponent: component,
selectedComponentDefinition: definition, selectedComponentDefinition: definition,
@ -68,9 +73,60 @@ const createComponentStore = () => {
} }
const getComponentDefinition = type => { const getComponentDefinition = type => {
const prefix = "@budibase/standard-components/" if (!type) {
type = type?.replace(prefix, "") return null
return type ? Manifest[type] : null }
// Screenslot is an edge case
if (type === "screenslot") {
type = `${budibasePrefix}${type}`
}
// Handle built-in components
if (type.startsWith(budibasePrefix)) {
type = type.replace(budibasePrefix, "")
return type ? Manifest[type] : null
}
// Handle custom components
const { customComponentManifest } = get(store)
return customComponentManifest?.[type]?.schema?.schema
}
const getComponentConstructor = type => {
if (!type) {
return null
}
if (type === "screenslot") {
return Router
}
// Handle budibase components
if (type.startsWith(budibasePrefix)) {
const split = type.split("/")
const name = split[split.length - 1]
return AppComponents[name]
}
// Handle custom components
const { customComponentManifest } = get(store)
return customComponentManifest?.[type]?.Component
}
const registerCustomComponent = ({ Component, schema }) => {
if (!Component || !schema?.schema?.name) {
return
}
store.update(state => {
if (!state.customComponentManifest) {
state.customComponentManifest = {}
}
state.customComponentManifest[schema.schema.name] = {
schema,
Component,
}
return state
})
} }
return { return {
@ -81,6 +137,8 @@ const createComponentStore = () => {
isComponentRegistered, isComponentRegistered,
getComponentById, getComponentById,
getComponentDefinition, getComponentDefinition,
getComponentConstructor,
registerCustomComponent,
}, },
} }
} }