Template fixes and updates to the file picker. Error handling added to display a warning when navigating to an unpublished or invalid app url.
This commit is contained in:
parent
5e84020849
commit
bfd7e49c72
|
@ -7,6 +7,7 @@
|
||||||
export let value = null
|
export let value = null
|
||||||
export let title = "Upload file"
|
export let title = "Upload file"
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
|
export let allowClear = null
|
||||||
export let extensions = null
|
export let extensions = null
|
||||||
export let handleFileTooLarge = null
|
export let handleFileTooLarge = null
|
||||||
export let fileSizeLimit = BYTES_IN_MB * 20
|
export let fileSizeLimit = BYTES_IN_MB * 20
|
||||||
|
@ -65,14 +66,14 @@
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if !disabled}
|
{#if !disabled || (allowClear === true && disabled)}
|
||||||
<div class="delete-button" on:click={clearFile}>
|
<div class="delete-button" on:click={clearFile}>
|
||||||
<Icon name="Close" size="XS" />
|
<Icon name="Close" size="XS" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<ActionButton on:click={fileInput.click()}>{title}</ActionButton>
|
<ActionButton {disabled} on:click={fileInput.click()}>{title}</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
export let label = null
|
export let label = null
|
||||||
export let labelPosition = "above"
|
export let labelPosition = "above"
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
|
export let allowClear = null
|
||||||
export let handleFileTooLarge = () => {}
|
export let handleFileTooLarge = () => {}
|
||||||
export let previewUrl = null
|
export let previewUrl = null
|
||||||
export let extensions = null
|
export let extensions = null
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
<CoreFile
|
<CoreFile
|
||||||
{error}
|
{error}
|
||||||
{disabled}
|
{disabled}
|
||||||
|
{allowClear}
|
||||||
{title}
|
{title}
|
||||||
{value}
|
{value}
|
||||||
{previewUrl}
|
{previewUrl}
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
$: platformTitleText = $organisation.platformTitle
|
$: platformTitleText = $organisation.platformTitle
|
||||||
$: platformTitleText,
|
$: platformTitleText,
|
||||||
(platformTitle =
|
(platformTitle =
|
||||||
!$admin.isCloud && !$auth.user ? platformTitleText : "Budibase")
|
!$admin.isCloud || !$auth.user ? platformTitleText : "Budibase")
|
||||||
|
|
||||||
|
$: faviconUrl = $organisation.faviconUrl || "https://i.imgur.com/Xhdt1YP.png"
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await organisation.init()
|
await organisation.init()
|
||||||
|
@ -23,37 +25,10 @@
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>{platformTitle}</title>
|
<title>{platformTitle}</title>
|
||||||
|
|
||||||
{#if loaded && !$auth.user}
|
{#if loaded && !$auth.user && faviconUrl}
|
||||||
<link
|
<link rel="icon" href={faviconUrl} />
|
||||||
rel="icon"
|
|
||||||
href={$organisation.faviconUrl || "https://i.imgur.com/Xhdt1YP.png"}
|
|
||||||
/>
|
|
||||||
{:else}
|
{:else}
|
||||||
<!-- A default must be set or the browser defaults to favicon.ico behaviour -->
|
<!-- A default must be set or the browser defaults to favicon.ico behaviour -->
|
||||||
<link rel="icon" href={"https://i.imgur.com/Xhdt1YP.png"} />
|
<link rel="icon" href={"https://i.imgur.com/Xhdt1YP.png"} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- Primary Meta Tags -->
|
|
||||||
<!-- <meta name="title" content={metaTitle} /> -->
|
|
||||||
<!--
|
|
||||||
metaTitle should match the title...
|
|
||||||
should title override metaTitle, if set??
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- <meta name="description" content={metaDescription} /> -->
|
|
||||||
|
|
||||||
<!-- Opengraph Meta Tags -->
|
|
||||||
<!-- <meta property="og:site_name" content="Budibase" />
|
|
||||||
<meta property="og:title" content="{title} - built with Budibase" />
|
|
||||||
<meta property="og:description" content={metaDescription} />
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta property="og:image" content={metaImage} /> -->
|
|
||||||
|
|
||||||
<!-- Twitter -->
|
|
||||||
<!-- <meta name="twitter:card" content="summary_large_image" />
|
|
||||||
<meta name="twitter:site" content="@budibase" />
|
|
||||||
<meta name="twitter:image" content={metaImage} /> -->
|
|
||||||
<!-- Consider adding this twitter:image:alt -->
|
|
||||||
<!-- <meta name="twitter:title" content="{title} - built with Budibase" />
|
|
||||||
<meta property="twitter:description" content={metaDescription} /> -->
|
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
async function login() {
|
async function login() {
|
||||||
form.validate()
|
form.validate()
|
||||||
if (Object.keys(errors).length > 0) {
|
if (Object.keys(errors).length > 0) {
|
||||||
console.log("errors")
|
console.log("errors", errors)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -135,7 +135,7 @@
|
||||||
disabled={Object.keys(errors).length > 0}
|
disabled={Object.keys(errors).length > 0}
|
||||||
on:click={login}
|
on:click={login}
|
||||||
>
|
>
|
||||||
{$organisation.loginButton || `Log in to {company}`}
|
{$organisation.loginButton || `Log in to ${company}`}
|
||||||
</Button>
|
</Button>
|
||||||
</Layout>
|
</Layout>
|
||||||
<Layout gap="XS" noPadding justifyItems="center">
|
<Layout gap="XS" noPadding justifyItems="center">
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
import { auth, organisation, licensing, admin } from "stores/portal"
|
import { auth, organisation, licensing, admin } from "stores/portal"
|
||||||
import { API } from "api"
|
import { API } from "api"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
import { goto } from "@roxi/routify"
|
||||||
|
|
||||||
const imageExtensions = [
|
const imageExtensions = [
|
||||||
".png",
|
".png",
|
||||||
|
@ -32,25 +33,32 @@
|
||||||
|
|
||||||
const faviconExtensions = [".png", ".ico", ".gif"]
|
const faviconExtensions = [".png", ".ico", ".gif"]
|
||||||
|
|
||||||
let loaded = false
|
let mounted = false
|
||||||
let saving = false
|
let saving = false
|
||||||
|
|
||||||
let logoFile = null
|
let logoFile = null
|
||||||
let logoPreview = null
|
let logoPreview = null
|
||||||
|
|
||||||
let faviconFile = null
|
let faviconFile = null
|
||||||
let faviconPreview = null
|
let faviconPreview = null
|
||||||
|
|
||||||
let config = {}
|
let config = {}
|
||||||
let updated = false
|
let updated = false
|
||||||
$: onConfigUpdate(config)
|
|
||||||
|
$: onConfigUpdate(config, mounted)
|
||||||
|
$: init = Object.keys(config).length > 0
|
||||||
|
|
||||||
|
$: cloudPremium = !$licensing.isFreePlan
|
||||||
|
$: selfhostPremium = $licensing.isEnterprisePlan || $licensing.isBusinessPlan
|
||||||
|
$: isCloud = $admin.cloud
|
||||||
|
|
||||||
|
$: isLicenseLocked =
|
||||||
|
(isCloud && !cloudPremium) || (!isCloud && !selfhostPremium)
|
||||||
|
|
||||||
const onConfigUpdate = config => {
|
const onConfigUpdate = config => {
|
||||||
if (!loaded || updated) {
|
if (!mounted || updated || !init) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
updated = true
|
updated = true
|
||||||
console.log("config updated ", config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$: logo = config.logoUrl
|
$: logo = config.logoUrl
|
||||||
|
@ -61,9 +69,6 @@
|
||||||
? { url: config.faviconUrl, type: "image", name: "Favicon" }
|
? { url: config.faviconUrl, type: "image", name: "Favicon" }
|
||||||
: null
|
: null
|
||||||
|
|
||||||
//If type of file do this IN the picker
|
|
||||||
//If string use the string
|
|
||||||
//If object?.url us that
|
|
||||||
const previewUrl = async localFile => {
|
const previewUrl = async localFile => {
|
||||||
if (!localFile) {
|
if (!localFile) {
|
||||||
return Promise.resolve(null)
|
return Promise.resolve(null)
|
||||||
|
@ -123,7 +128,7 @@
|
||||||
|
|
||||||
async function saveConfig() {
|
async function saveConfig() {
|
||||||
saving = true
|
saving = true
|
||||||
console.log("SAVING CONFIG ")
|
|
||||||
if (logoFile) {
|
if (logoFile) {
|
||||||
const logoResp = await uploadLogo(logoFile)
|
const logoResp = await uploadLogo(logoFile)
|
||||||
if (logoResp.url) {
|
if (logoResp.url) {
|
||||||
|
@ -147,7 +152,6 @@
|
||||||
faviconPreview = null
|
faviconPreview = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log("SAVE CONFIG ", config)
|
|
||||||
try {
|
try {
|
||||||
// Update settings
|
// Update settings
|
||||||
await organisation.save(config)
|
await organisation.save(config)
|
||||||
|
@ -157,7 +161,7 @@
|
||||||
console.error("Branding updated failed", e)
|
console.error("Branding updated failed", e)
|
||||||
notifications.error("Branding updated failed")
|
notifications.error("Branding updated failed")
|
||||||
}
|
}
|
||||||
|
updated = false
|
||||||
saving = false
|
saving = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +173,6 @@
|
||||||
logoUrl: $organisation.logoUrl,
|
logoUrl: $organisation.logoUrl,
|
||||||
platformTitle: $organisation.platformTitle,
|
platformTitle: $organisation.platformTitle,
|
||||||
emailBrandingEnabled: $organisation.emailBrandingEnabled,
|
emailBrandingEnabled: $organisation.emailBrandingEnabled,
|
||||||
appFooterEnabled: $organisation.appFooterEnabled,
|
|
||||||
loginHeading: $organisation.loginHeading,
|
loginHeading: $organisation.loginHeading,
|
||||||
loginButton: $organisation.loginButton,
|
loginButton: $organisation.loginButton,
|
||||||
licenseAgreementEnabled: $organisation.licenseAgreementEnabled,
|
licenseAgreementEnabled: $organisation.licenseAgreementEnabled,
|
||||||
|
@ -178,21 +181,25 @@
|
||||||
metaImageUrl: $organisation.metaImageUrl,
|
metaImageUrl: $organisation.metaImageUrl,
|
||||||
metaTitle: $organisation.metaTitle,
|
metaTitle: $organisation.metaTitle,
|
||||||
}
|
}
|
||||||
|
mounted = true
|
||||||
loaded = true
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $auth.isAdmin && loaded}
|
{#if $auth.isAdmin && mounted}
|
||||||
<Layout noPadding>
|
<Layout noPadding>
|
||||||
<Layout gap="XS" noPadding>
|
<Layout gap="XS" noPadding>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<Heading size="M">Branding</Heading>
|
<Heading size="M">Branding</Heading>
|
||||||
{#if !$licensing.isBusinessPlan}
|
{#if !isCloud && !selfhostPremium}
|
||||||
<Tags>
|
<Tags>
|
||||||
<Tag icon="LockClosed">Business</Tag>
|
<Tag icon="LockClosed">Business</Tag>
|
||||||
</Tags>
|
</Tags>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if isCloud && !cloudPremium}
|
||||||
|
<Tags>
|
||||||
|
<Tag icon="LockClosed">Pro</Tag>
|
||||||
|
</Tags>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<Body>Remove all Budibase branding and use your own.</Body>
|
<Body>Remove all Budibase branding and use your own.</Body>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -208,7 +215,6 @@
|
||||||
extensions={imageExtensions}
|
extensions={imageExtensions}
|
||||||
previewUrl={logoPreview || logo?.url}
|
previewUrl={logoPreview || logo?.url}
|
||||||
on:change={e => {
|
on:change={e => {
|
||||||
console.log("Updated Logo")
|
|
||||||
let clone = { ...config }
|
let clone = { ...config }
|
||||||
if (e.detail) {
|
if (e.detail) {
|
||||||
logoFile = e.detail
|
logoFile = e.detail
|
||||||
|
@ -220,6 +226,8 @@
|
||||||
config = clone
|
config = clone
|
||||||
}}
|
}}
|
||||||
value={logoFile || logo}
|
value={logoFile || logo}
|
||||||
|
disabled={isLicenseLocked || saving}
|
||||||
|
allowClear={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -243,19 +251,24 @@
|
||||||
config = clone
|
config = clone
|
||||||
}}
|
}}
|
||||||
value={faviconFile || favicon}
|
value={faviconFile || favicon}
|
||||||
|
disabled={isLicenseLocked || saving}
|
||||||
|
allowClear={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
{#if !isCloud}
|
||||||
<Label size="L">Title</Label>
|
<div class="field">
|
||||||
<Input
|
<Label size="L">Title</Label>
|
||||||
on:change={e => {
|
<Input
|
||||||
let clone = { ...config }
|
on:change={e => {
|
||||||
clone.platformTitle = e.detail ? e.detail : ""
|
let clone = { ...config }
|
||||||
config = clone
|
clone.platformTitle = e.detail ? e.detail : ""
|
||||||
}}
|
config = clone
|
||||||
value={config.platformTitle || ""}
|
}}
|
||||||
/>
|
value={config.platformTitle || ""}
|
||||||
</div>
|
disabled={!selfhostPremium || saving}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
<div>
|
<div>
|
||||||
<Toggle
|
<Toggle
|
||||||
text={"Remove Budibase brand from emails"}
|
text={"Remove Budibase brand from emails"}
|
||||||
|
@ -265,24 +278,16 @@
|
||||||
config = clone
|
config = clone
|
||||||
}}
|
}}
|
||||||
value={!config.emailBrandingEnabled}
|
value={!config.emailBrandingEnabled}
|
||||||
/>
|
disabled={isLicenseLocked || saving}
|
||||||
<Toggle
|
|
||||||
text={"Remove Budibase footer from apps"}
|
|
||||||
on:change={e => {
|
|
||||||
let clone = { ...config }
|
|
||||||
clone.appFooterEnabled = !e.detail
|
|
||||||
config = clone
|
|
||||||
}}
|
|
||||||
value={!config.appFooterEnabled}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if !$admin.cloud}
|
{#if !isCloud}
|
||||||
<Divider />
|
<Divider />
|
||||||
<Layout gap="XS" noPadding>
|
<Layout gap="XS" noPadding>
|
||||||
<Heading size="S">Login page (Self host)</Heading>
|
<Heading size="S">Login page</Heading>
|
||||||
<Body>You can only customise your login page in self host</Body>
|
<Body />
|
||||||
</Layout>
|
</Layout>
|
||||||
<div class="login">
|
<div class="login">
|
||||||
<div class="fields">
|
<div class="fields">
|
||||||
|
@ -295,6 +300,7 @@
|
||||||
config = clone
|
config = clone
|
||||||
}}
|
}}
|
||||||
value={config.loginHeading || ""}
|
value={config.loginHeading || ""}
|
||||||
|
disabled={!selfhostPremium || saving}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -307,6 +313,7 @@
|
||||||
config = clone
|
config = clone
|
||||||
}}
|
}}
|
||||||
value={config.loginButton || ""}
|
value={config.loginButton || ""}
|
||||||
|
disabled={!selfhostPremium || saving}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -318,6 +325,7 @@
|
||||||
config = clone
|
config = clone
|
||||||
}}
|
}}
|
||||||
value={!config.testimonialsEnabled}
|
value={!config.testimonialsEnabled}
|
||||||
|
disabled={!selfhostPremium || saving}
|
||||||
/>
|
/>
|
||||||
<Toggle
|
<Toggle
|
||||||
text={"Remove license agreement"}
|
text={"Remove license agreement"}
|
||||||
|
@ -327,6 +335,7 @@
|
||||||
config = clone
|
config = clone
|
||||||
}}
|
}}
|
||||||
value={!config.licenseAgreementEnabled}
|
value={!config.licenseAgreementEnabled}
|
||||||
|
disabled={!selfhostPremium || saving}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -348,6 +357,7 @@
|
||||||
config = clone
|
config = clone
|
||||||
}}
|
}}
|
||||||
value={config.metaImageUrl}
|
value={config.metaImageUrl}
|
||||||
|
disabled={isLicenseLocked || saving}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
@ -359,6 +369,7 @@
|
||||||
config = clone
|
config = clone
|
||||||
}}
|
}}
|
||||||
value={config.metaTitle}
|
value={config.metaTitle}
|
||||||
|
disabled={isLicenseLocked || saving}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
@ -370,12 +381,28 @@
|
||||||
config = clone
|
config = clone
|
||||||
}}
|
}}
|
||||||
value={config.metaDescription}
|
value={config.metaDescription}
|
||||||
|
disabled={isLicenseLocked || saving}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="buttons">
|
||||||
<Button on:click={saveConfig} cta disabled={saving || !updated}>
|
{#if isLicenseLocked}
|
||||||
|
<Button
|
||||||
|
on:click={() => {
|
||||||
|
if (isCloud && $auth?.user?.accountPortalAccess) {
|
||||||
|
window.open($admin.accountPortalUrl + "/portal/upgrade", "_blank")
|
||||||
|
} else if ($auth.isAdmin) {
|
||||||
|
$goto("/builder/portal/account/upgrade")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
secondary
|
||||||
|
disabled={saving}
|
||||||
|
>
|
||||||
|
Upgrade
|
||||||
|
</Button>
|
||||||
|
{/if}
|
||||||
|
<Button on:click={saveConfig} cta disabled={saving || !updated || !init}>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -383,6 +410,10 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--spacing-m);
|
||||||
|
}
|
||||||
.title {
|
.title {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
|
@ -5,22 +5,17 @@ import _ from "lodash"
|
||||||
|
|
||||||
const DEFAULT_CONFIG = {
|
const DEFAULT_CONFIG = {
|
||||||
platformUrl: "",
|
platformUrl: "",
|
||||||
|
|
||||||
logoUrl: undefined,
|
logoUrl: undefined,
|
||||||
|
|
||||||
faviconUrl: undefined,
|
faviconUrl: undefined,
|
||||||
emailBrandingEnabled: true,
|
emailBrandingEnabled: true,
|
||||||
appFooterEnabled: true,
|
|
||||||
testimonialsEnabled: true,
|
testimonialsEnabled: true,
|
||||||
licenseAgreementEnabled: true,
|
licenseAgreementEnabled: true,
|
||||||
platformTitle: "Budibase",
|
platformTitle: "Budibase",
|
||||||
loginHeading: undefined,
|
loginHeading: undefined,
|
||||||
loginButton: undefined,
|
loginButton: undefined,
|
||||||
|
|
||||||
metaDescription: undefined,
|
metaDescription: undefined,
|
||||||
metaImageUrl: undefined,
|
metaImageUrl: undefined,
|
||||||
metaTitle: undefined,
|
metaTitle: undefined,
|
||||||
|
|
||||||
docsUrl: undefined,
|
docsUrl: undefined,
|
||||||
company: "Budibase",
|
company: "Budibase",
|
||||||
oidc: undefined,
|
oidc: undefined,
|
||||||
|
|
|
@ -16,6 +16,7 @@ export { rowSelectionStore } from "./rowSelection.js"
|
||||||
export { blockStore } from "./blocks.js"
|
export { blockStore } from "./blocks.js"
|
||||||
export { environmentStore } from "./environment"
|
export { environmentStore } from "./environment"
|
||||||
export { eventStore } from "./events.js"
|
export { eventStore } from "./events.js"
|
||||||
|
export { orgStore } from "./org.js"
|
||||||
export {
|
export {
|
||||||
dndStore,
|
dndStore,
|
||||||
dndIndex,
|
dndIndex,
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import { routeStore } from "./routes"
|
import { routeStore } from "./routes"
|
||||||
import { appStore } from "./app"
|
import { appStore } from "./app"
|
||||||
|
import { orgStore } from "./org"
|
||||||
|
|
||||||
export async function initialise() {
|
export async function initialise() {
|
||||||
await routeStore.actions.fetchRoutes()
|
await routeStore.actions.fetchRoutes()
|
||||||
await appStore.actions.fetchAppDefinition()
|
await appStore.actions.fetchAppDefinition()
|
||||||
|
await orgStore.init()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { API } from "api"
|
||||||
|
import { writable, get } from "svelte/store"
|
||||||
|
import { appStore } from "./app"
|
||||||
|
|
||||||
|
const createOrgStore = () => {
|
||||||
|
const store = writable(null)
|
||||||
|
|
||||||
|
const { subscribe, set } = store
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
const tenantId = get(appStore).application?.tenantId
|
||||||
|
if (!tenantId) return
|
||||||
|
try {
|
||||||
|
const settingsConfigDoc = await API.getTenantConfig(tenantId)
|
||||||
|
set({ logoUrl: settingsConfigDoc.config.logoUrl })
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Could not init org ", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
init,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const orgStore = createOrgStore()
|
|
@ -2,6 +2,7 @@ import { derived } from "svelte/store"
|
||||||
import { routeStore } from "./routes"
|
import { routeStore } from "./routes"
|
||||||
import { builderStore } from "./builder"
|
import { builderStore } from "./builder"
|
||||||
import { appStore } from "./app"
|
import { appStore } from "./app"
|
||||||
|
import { orgStore } from "./org"
|
||||||
import { dndIndex, dndParent, dndIsNewComponent, dndBounds } from "./dnd.js"
|
import { dndIndex, dndParent, dndIsNewComponent, dndBounds } from "./dnd.js"
|
||||||
import { RoleUtils } from "@budibase/frontend-core"
|
import { RoleUtils } from "@budibase/frontend-core"
|
||||||
import { findComponentById, findComponentParent } from "../utils/components.js"
|
import { findComponentById, findComponentParent } from "../utils/components.js"
|
||||||
|
@ -14,6 +15,7 @@ const createScreenStore = () => {
|
||||||
appStore,
|
appStore,
|
||||||
routeStore,
|
routeStore,
|
||||||
builderStore,
|
builderStore,
|
||||||
|
orgStore,
|
||||||
dndParent,
|
dndParent,
|
||||||
dndIndex,
|
dndIndex,
|
||||||
dndIsNewComponent,
|
dndIsNewComponent,
|
||||||
|
@ -23,6 +25,7 @@ const createScreenStore = () => {
|
||||||
$appStore,
|
$appStore,
|
||||||
$routeStore,
|
$routeStore,
|
||||||
$builderStore,
|
$builderStore,
|
||||||
|
$orgStore,
|
||||||
$dndParent,
|
$dndParent,
|
||||||
$dndIndex,
|
$dndIndex,
|
||||||
$dndIsNewComponent,
|
$dndIsNewComponent,
|
||||||
|
@ -146,6 +149,11 @@ const createScreenStore = () => {
|
||||||
if (!navigationSettings.title && !navigationSettings.hideTitle) {
|
if (!navigationSettings.title && !navigationSettings.hideTitle) {
|
||||||
navigationSettings.title = $appStore.application?.name
|
navigationSettings.title = $appStore.application?.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!navigationSettings.logoUrl) {
|
||||||
|
navigationSettings.logoUrl =
|
||||||
|
$orgStore?.logoUrl || navigationSettings.logoUrl
|
||||||
|
}
|
||||||
}
|
}
|
||||||
activeLayout = {
|
activeLayout = {
|
||||||
_id: "layout",
|
_id: "layout",
|
||||||
|
|
|
@ -99,40 +99,71 @@ export const deleteObjects = async function (ctx: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const serveApp = async function (ctx: any) {
|
export const serveApp = async function (ctx: any) {
|
||||||
|
//Public Settings
|
||||||
const { config } = await configs.getSettingsConfigDoc()
|
const { config } = await configs.getSettingsConfigDoc()
|
||||||
|
let db
|
||||||
|
try {
|
||||||
|
db = context.getAppDB({ skip_setup: true })
|
||||||
|
const appInfo = await db.get(DocumentType.APP_METADATA)
|
||||||
|
let appId = context.getAppId()
|
||||||
|
|
||||||
const db = context.getAppDB({ skip_setup: true })
|
if (!env.isJest()) {
|
||||||
const appInfo = await db.get(DocumentType.APP_METADATA)
|
const App = require("./templates/BudibaseApp.svelte").default
|
||||||
let appId = context.getAppId()
|
const plugins = objectStore.enrichPluginURLs(appInfo.usedPlugins)
|
||||||
|
const { head, html, css } = App.render({
|
||||||
|
metaImage:
|
||||||
|
config?.metaImageUrl ||
|
||||||
|
"https://res.cloudinary.com/daog6scxm/image/upload/v1666109324/meta-images/budibase-meta-image_uukc1m.png",
|
||||||
|
metaDescription: config?.metaDescription || "",
|
||||||
|
metaTitle: config?.metaTitle || `${appInfo.name} - built with Budibase`,
|
||||||
|
title: appInfo.name,
|
||||||
|
production: env.isProd(),
|
||||||
|
appId,
|
||||||
|
clientLibPath: objectStore.clientLibraryUrl(appId!, appInfo.version),
|
||||||
|
usedPlugins: plugins,
|
||||||
|
favicon:
|
||||||
|
config.faviconUrl !== ""
|
||||||
|
? objectStore.getGlobalFileUrl("settings", "faviconUrl")
|
||||||
|
: "",
|
||||||
|
logo:
|
||||||
|
config?.logoUrl !== ""
|
||||||
|
? objectStore.getGlobalFileUrl("settings", "logoUrl")
|
||||||
|
: "",
|
||||||
|
})
|
||||||
|
const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`)
|
||||||
|
ctx.body = await processString(appHbs, {
|
||||||
|
head,
|
||||||
|
body: html,
|
||||||
|
style: css.code,
|
||||||
|
appId,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// just return the app info for jest to assert on
|
||||||
|
ctx.body = appInfo
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (!env.isJest()) {
|
||||||
|
const App = require("./templates/BudibaseApp.svelte").default
|
||||||
|
const { head, html, css } = App.render({
|
||||||
|
title: config?.metaTitle,
|
||||||
|
metaTitle: config?.metaTitle,
|
||||||
|
metaImage:
|
||||||
|
config?.metaImageUrl ||
|
||||||
|
"https://res.cloudinary.com/daog6scxm/image/upload/v1666109324/meta-images/budibase-meta-image_uukc1m.png",
|
||||||
|
metaDescription: config?.metaDescription || "",
|
||||||
|
favicon:
|
||||||
|
config.faviconUrl !== ""
|
||||||
|
? objectStore.getGlobalFileUrl("settings", "faviconUrl")
|
||||||
|
: "",
|
||||||
|
})
|
||||||
|
|
||||||
if (!env.isJest()) {
|
const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`)
|
||||||
const App = require("./templates/BudibaseApp.svelte").default
|
ctx.body = await processString(appHbs, {
|
||||||
const plugins = objectStore.enrichPluginURLs(appInfo.usedPlugins)
|
head,
|
||||||
const { head, html, css } = App.render({
|
body: html,
|
||||||
metaImage:
|
style: css.code,
|
||||||
config?.metaImageUrl ||
|
})
|
||||||
"https://res.cloudinary.com/daog6scxm/image/upload/v1666109324/meta-images/budibase-meta-image_uukc1m.png",
|
}
|
||||||
metaDescription: config?.metaDescription || "",
|
|
||||||
metaTitle: `${appInfo.name} - built with Budibase` || config?.metaTitle,
|
|
||||||
title: appInfo.name,
|
|
||||||
production: env.isProd(),
|
|
||||||
appId,
|
|
||||||
clientLibPath: objectStore.clientLibraryUrl(appId!, appInfo.version),
|
|
||||||
usedPlugins: plugins,
|
|
||||||
favicon: objectStore.getGlobalFileUrl("settings", "faviconUrl"),
|
|
||||||
//logo: objectStore.getGlobalFileUrl("settings", "logoUrl"),
|
|
||||||
})
|
|
||||||
|
|
||||||
const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`)
|
|
||||||
ctx.body = await processString(appHbs, {
|
|
||||||
head,
|
|
||||||
body: html,
|
|
||||||
style: css.code,
|
|
||||||
appId,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// just return the app info for jest to assert on
|
|
||||||
ctx.body = appInfo
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,6 @@
|
||||||
<meta name="title" content={metaTitle} />
|
<meta name="title" content={metaTitle} />
|
||||||
<meta name="description" content={metaDescription} />
|
<meta name="description" content={metaDescription} />
|
||||||
|
|
||||||
<!--
|
|
||||||
metaTitle should match the title...
|
|
||||||
should title override metaTitle, if set??
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- Opengraph Meta Tags -->
|
<!-- Opengraph Meta Tags -->
|
||||||
<meta property="og:site_name" content="Budibase" />
|
<meta property="og:site_name" content="Budibase" />
|
||||||
<meta property="og:title" content="{title} - built with Budibase" />
|
<meta property="og:title" content="{title} - built with Budibase" />
|
||||||
|
@ -37,12 +32,17 @@
|
||||||
<meta property="twitter:card" content="summary_large_image" />
|
<meta property="twitter:card" content="summary_large_image" />
|
||||||
<meta property="twitter:site" content="@budibase" />
|
<meta property="twitter:site" content="@budibase" />
|
||||||
<meta property="twitter:image" content={metaImage} />
|
<meta property="twitter:image" content={metaImage} />
|
||||||
<!-- Consider adding this twitter:image:alt -->
|
<meta property="twitter:image:alt" content="{title} - built with Budibase" />
|
||||||
<meta property="twitter:title" content="{title} - built with Budibase" />
|
<meta property="twitter:title" content="{title} - built with Budibase" />
|
||||||
<meta property="twitter:description" content={metaDescription} />
|
<meta property="twitter:description" content={metaDescription} />
|
||||||
|
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
<link rel="icon" type="image/png" href={favicon} />
|
{#if favicon !== ""}
|
||||||
|
<link rel="icon" type="image/png" href={favicon} />
|
||||||
|
{:else}
|
||||||
|
<link rel="icon" type="image/png" href="https://i.imgur.com/Xhdt1YP.png" />
|
||||||
|
{/if}
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||||
<link
|
<link
|
||||||
|
@ -101,11 +101,16 @@
|
||||||
|
|
||||||
<body id="app">
|
<body id="app">
|
||||||
<div id="error">
|
<div id="error">
|
||||||
<h1>There was an error loading your app</h1>
|
{#if clientLibPath}
|
||||||
<h2>
|
<h1>There was an error loading your app</h1>
|
||||||
The Budibase client library could not be loaded. Try republishing your
|
<h2>
|
||||||
app.
|
The Budibase client library could not be loaded. Try republishing your
|
||||||
</h2>
|
app.
|
||||||
|
</h2>
|
||||||
|
{:else}
|
||||||
|
<h2>We couldn't find that application</h2>
|
||||||
|
<p />
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
window.INIT_TIME = Date.now()
|
window.INIT_TIME = Date.now()
|
||||||
|
|
|
@ -32,7 +32,6 @@ export interface SettingsInnerConfig {
|
||||||
faviconUrlEtag?: string
|
faviconUrlEtag?: string
|
||||||
|
|
||||||
emailBrandingEnabled?: boolean
|
emailBrandingEnabled?: boolean
|
||||||
appFooterEnabled?: boolean
|
|
||||||
testimonialsEnabled?: boolean
|
testimonialsEnabled?: boolean
|
||||||
licenseAgreementEnabled?: boolean
|
licenseAgreementEnabled?: boolean
|
||||||
platformTitle?: string
|
platformTitle?: string
|
||||||
|
|
|
@ -10,16 +10,18 @@
|
||||||
>
|
>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding:0 35px;" cellpadding="0" cellspacing="0">
|
<td
|
||||||
|
style="padding:0 35px; padding-top: 15px;"
|
||||||
|
cellpadding="0"
|
||||||
|
cellspacing="0"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
width="32px"
|
width="32px"
|
||||||
style="margin-right:16px; vertical-align: middle;"
|
style="margin-right:16px; vertical-align: middle;"
|
||||||
alt="Budibase Logo"
|
alt="Budibase Logo"
|
||||||
src="https://i.imgur.com/Xhdt1YP.png"
|
src="https://i.imgur.com/Xhdt1YP.png"
|
||||||
/>
|
/>
|
||||||
<strong
|
<strong style="vertical-align: middle; font-size: 1.1em">
|
||||||
style="color:#333333; vertical-align: middle; font-size: 1.1em"
|
|
||||||
>
|
|
||||||
Budibase
|
Budibase
|
||||||
</strong>
|
</strong>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -26,9 +26,7 @@ export async function getSettingsTemplateContext(
|
||||||
[InternalTemplateBinding.CURRENT_YEAR]: new Date().getFullYear(),
|
[InternalTemplateBinding.CURRENT_YEAR]: new Date().getFullYear(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to be careful with the binding as it shouldn't be surfacable
|
context["enableEmailBranding"] = settings.emailBrandingEnabled === true
|
||||||
// Also default to false if not explicit
|
|
||||||
context["enableEmailBranding"] = settings.emailBrandingEnabled
|
|
||||||
|
|
||||||
// attach purpose specific context
|
// attach purpose specific context
|
||||||
switch (purpose) {
|
switch (purpose) {
|
||||||
|
|
Loading…
Reference in New Issue