Merge branch 'plugins-dev-experience' of github.com:Budibase/budibase into plugins-dev-experience
This commit is contained in:
commit
bab20e5744
|
@ -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) => {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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({
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue