Adding feature to allow configured the builder to point at a self hosted system instead of production (for deployment).
This commit is contained in:
parent
f5a9c68c69
commit
21978007cf
|
@ -1,6 +1,8 @@
|
||||||
import { getFrontendStore } from "./store/frontend"
|
import { getFrontendStore } from "./store/frontend"
|
||||||
import { getBackendUiStore } from "./store/backend"
|
import { getBackendUiStore } from "./store/backend"
|
||||||
import { getAutomationStore } from "./store/automation/"
|
import { getAutomationStore } from "./store/automation"
|
||||||
|
import { getHostingStore } from "./store/hosting"
|
||||||
|
|
||||||
import { getThemeStore } from "./store/theme"
|
import { getThemeStore } from "./store/theme"
|
||||||
import { derived } from "svelte/store"
|
import { derived } from "svelte/store"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
@ -11,6 +13,7 @@ export const store = getFrontendStore()
|
||||||
export const backendUiStore = getBackendUiStore()
|
export const backendUiStore = getBackendUiStore()
|
||||||
export const automationStore = getAutomationStore()
|
export const automationStore = getAutomationStore()
|
||||||
export const themeStore = getThemeStore()
|
export const themeStore = getThemeStore()
|
||||||
|
export const hostingStore = getHostingStore()
|
||||||
|
|
||||||
export const currentAsset = derived(store, $store => {
|
export const currentAsset = derived(store, $store => {
|
||||||
const layout = $store.layouts
|
const layout = $store.layouts
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
import api from "../api"
|
||||||
|
|
||||||
|
const INITIAL_BACKEND_UI_STATE = {
|
||||||
|
hostingInfo: {},
|
||||||
|
appUrl: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getHostingStore = () => {
|
||||||
|
const store = writable({...INITIAL_BACKEND_UI_STATE})
|
||||||
|
store.actions = {
|
||||||
|
fetch: async () => {
|
||||||
|
const response = await api.get("/api/hosting/")
|
||||||
|
const info = await response.json()
|
||||||
|
store.update(state => {
|
||||||
|
state.hostingInfo = info
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
return info
|
||||||
|
},
|
||||||
|
save: async hostingInfo => {
|
||||||
|
const response = await api.post("/api/hosting", hostingInfo)
|
||||||
|
const revision = (await response.json()).rev
|
||||||
|
store.update(state => {
|
||||||
|
state.hostingInfo = {
|
||||||
|
...hostingInfo,
|
||||||
|
_rev: revision,
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return store
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<script>
|
||||||
|
import { TextButton as Button, Modal } from "@budibase/bbui"
|
||||||
|
import BuilderSettingsModal from "./BuilderSettingsModal.svelte"
|
||||||
|
|
||||||
|
let modal
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Button text on:click={modal.show}>
|
||||||
|
<i class="ri-settings-3-fill"></i>
|
||||||
|
<p>Settings</p>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<Modal bind:this={modal} width="30%">
|
||||||
|
<BuilderSettingsModal />
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div i {
|
||||||
|
font-size: 26px;
|
||||||
|
color: var(--grey-7);
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div p {
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
font-size: var(--font-size-s);
|
||||||
|
color: var(--ink);
|
||||||
|
font-weight: 400;
|
||||||
|
margin: 0 0 0 12px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,51 @@
|
||||||
|
<script>
|
||||||
|
import { notifier } from "builderStore/store/notifications"
|
||||||
|
import { hostingStore } from "builderStore"
|
||||||
|
import { Input, ModalContent, Toggle } from "@budibase/bbui"
|
||||||
|
import analytics from "analytics"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
let selfhosted = false
|
||||||
|
let hostingInfo
|
||||||
|
|
||||||
|
async function save() {
|
||||||
|
if (!selfhosted) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hostingInfo.type = selfhosted ? "self" : "cloud"
|
||||||
|
try {
|
||||||
|
await hostingStore.actions.save(hostingInfo)
|
||||||
|
notifier.success(`Settings saved.`)
|
||||||
|
} catch (err) {
|
||||||
|
notifier.danger(`Failed to update builder settings.`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
hostingInfo = await hostingStore.actions.fetch()
|
||||||
|
selfhosted = hostingInfo.type === "self"
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ModalContent title="Builder settings" confirmText="Save" onConfirm={save} showConfirmButton={selfhosted}>
|
||||||
|
<h5>Hosting</h5>
|
||||||
|
<p>This section contains settings that relate to the deployment and hosting of apps made in this builder.</p>
|
||||||
|
<Toggle thin text="Self hosted" bind:checked={selfhosted} />
|
||||||
|
{#if selfhosted}
|
||||||
|
<Input bind:value={hostingInfo.appServerUrl} label="Apps URL" />
|
||||||
|
<Input bind:value={hostingInfo.objectStoreUrl} label="Object store URL" />
|
||||||
|
<Toggle thin text="HTTPS" bind:checked={hostingInfo.useHttps} />
|
||||||
|
{/if}
|
||||||
|
</ModalContent>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
h5 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -7,6 +7,9 @@
|
||||||
CommunityIcon,
|
CommunityIcon,
|
||||||
BugIcon,
|
BugIcon,
|
||||||
} from "components/common/Icons"
|
} from "components/common/Icons"
|
||||||
|
import BuilderSettingsButton from "components/start/BuilderSettingsButton.svelte"
|
||||||
|
|
||||||
|
let modal
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -16,27 +19,30 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="nav-section">
|
<div class="nav-section">
|
||||||
<Link icon={AppsIcon} title="Apps" href="/" active />
|
<div class="nav-top">
|
||||||
<Link
|
<Link icon={AppsIcon} title="Apps" href="/" active />
|
||||||
icon={HostingIcon}
|
<Link
|
||||||
title="Hosting"
|
icon={HostingIcon}
|
||||||
href="https://portal.budi.live/" />
|
title="Hosting"
|
||||||
<Link
|
href="https://portal.budi.live/" />
|
||||||
icon={DocumentationIcon}
|
<Link
|
||||||
title="Documentation"
|
icon={DocumentationIcon}
|
||||||
href="https://docs.budibase.com/" />
|
title="Documentation"
|
||||||
<Link
|
href="https://docs.budibase.com/" />
|
||||||
icon={CommunityIcon}
|
<Link
|
||||||
title="Community"
|
icon={CommunityIcon}
|
||||||
href="https://github.com/Budibase/budibase/discussions" />
|
title="Community"
|
||||||
|
href="https://github.com/Budibase/budibase/discussions" />
|
||||||
<Link
|
<Link
|
||||||
icon={BugIcon}
|
icon={BugIcon}
|
||||||
title="Raise an issue"
|
title="Raise an issue"
|
||||||
href="https://github.com/Budibase/budibase/issues/new/choose" />
|
href="https://github.com/Budibase/budibase/issues/new/choose" />
|
||||||
|
</div>
|
||||||
|
<div class="nav-bottom">
|
||||||
|
<BuilderSettingsButton/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
@ -76,8 +82,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-section {
|
.nav-section {
|
||||||
margin: 20px 0px;
|
margin: 20px 0 0 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -18,14 +18,14 @@ exports.save = async ctx => {
|
||||||
if (type === HostingTypes.CLOUD) {
|
if (type === HostingTypes.CLOUD) {
|
||||||
ctx.throw(400, "Cannot update Cloud hosting information")
|
ctx.throw(400, "Cannot update Cloud hosting information")
|
||||||
}
|
}
|
||||||
await db.put({
|
const response = await db.put({
|
||||||
_id: HOSTING_DOC,
|
_id: HOSTING_DOC,
|
||||||
type,
|
type,
|
||||||
appServerUrl,
|
appServerUrl,
|
||||||
objectStoreUrl,
|
objectStoreUrl,
|
||||||
useHttps,
|
useHttps,
|
||||||
})
|
})
|
||||||
ctx.body = "Hosting information saved successfully"
|
ctx.body = response
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.fetch = async ctx => {
|
exports.fetch = async ctx => {
|
||||||
|
|
|
@ -6,8 +6,8 @@ const { BUILDER } = require("../../utilities/security/permissions")
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
router
|
router
|
||||||
.fetch("/api/hosting/info", authorized(BUILDER), controller.fetchInfo)
|
.get("/api/hosting/info", authorized(BUILDER), controller.fetchInfo)
|
||||||
.fetch("/api/hosting", authorized(BUILDER), controller.fetch)
|
.get("/api/hosting", authorized(BUILDER), controller.fetch)
|
||||||
.post("/api/hosting", authorized(BUILDER), controller.save)
|
.post("/api/hosting", authorized(BUILDER), controller.save)
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|
|
@ -17,6 +17,7 @@ const templatesRoutes = require("./templates")
|
||||||
const analyticsRoutes = require("./analytics")
|
const analyticsRoutes = require("./analytics")
|
||||||
const routingRoutes = require("./routing")
|
const routingRoutes = require("./routing")
|
||||||
const permissionRoutes = require("./permission")
|
const permissionRoutes = require("./permission")
|
||||||
|
const hostingRoutes = require("./hosting")
|
||||||
|
|
||||||
exports.mainRoutes = [
|
exports.mainRoutes = [
|
||||||
deployRoutes,
|
deployRoutes,
|
||||||
|
@ -34,6 +35,7 @@ exports.mainRoutes = [
|
||||||
webhookRoutes,
|
webhookRoutes,
|
||||||
routingRoutes,
|
routingRoutes,
|
||||||
permissionRoutes,
|
permissionRoutes,
|
||||||
|
hostingRoutes,
|
||||||
// these need to be handled last as they still use /api/:tableId
|
// these need to be handled last as they still use /api/:tableId
|
||||||
// this could be breaking as koa may recognise other routes as this
|
// this could be breaking as koa may recognise other routes as this
|
||||||
tableRoutes,
|
tableRoutes,
|
||||||
|
|
Loading…
Reference in New Issue