Merge branch 'next' of github.com:Budibase/budibase into feature/password-reset
This commit is contained in:
commit
82687bad26
|
@ -33,7 +33,7 @@ static_resources:
|
||||||
route:
|
route:
|
||||||
cluster: server-dev
|
cluster: server-dev
|
||||||
|
|
||||||
- match: { prefix: "/builder/" }
|
- match: { prefix: "/" }
|
||||||
route:
|
route:
|
||||||
cluster: builder-dev
|
cluster: builder-dev
|
||||||
|
|
||||||
|
@ -41,10 +41,6 @@ static_resources:
|
||||||
route:
|
route:
|
||||||
cluster: builder-dev
|
cluster: builder-dev
|
||||||
prefix_rewrite: "/builder/"
|
prefix_rewrite: "/builder/"
|
||||||
|
|
||||||
# special case in dev to redirect no path to builder
|
|
||||||
- match: { path: "/" }
|
|
||||||
redirect: { path_redirect: "/builder/" }
|
|
||||||
|
|
||||||
# minio is on the default route because this works
|
# minio is on the default route because this works
|
||||||
# best, minio + AWS SDK doesn't handle path proxy
|
# best, minio + AWS SDK doesn't handle path proxy
|
||||||
|
|
|
@ -132,29 +132,32 @@ const determineScopedConfig = async function (db, { type, user, group }) {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
const configs = response.rows.map(row => {
|
|
||||||
|
function determineScore(row) {
|
||||||
const config = row.doc
|
const config = row.doc
|
||||||
|
|
||||||
// Config is specific to a user and a group
|
// Config is specific to a user and a group
|
||||||
if (config._id.includes(generateConfigID({ type, user, group }))) {
|
if (config._id.includes(generateConfigID({ type, user, group }))) {
|
||||||
config.score = 4
|
return 4
|
||||||
} else if (config._id.includes(generateConfigID({ type, user }))) {
|
} else if (config._id.includes(generateConfigID({ type, user }))) {
|
||||||
// Config is specific to a user only
|
// Config is specific to a user only
|
||||||
config.score = 3
|
return 3
|
||||||
} else if (config._id.includes(generateConfigID({ type, group }))) {
|
} else if (config._id.includes(generateConfigID({ type, group }))) {
|
||||||
// Config is specific to a group only
|
// Config is specific to a group only
|
||||||
config.score = 2
|
return 2
|
||||||
} else if (config._id.includes(generateConfigID({ type }))) {
|
} else if (config._id.includes(generateConfigID({ type }))) {
|
||||||
// Config is specific to a type only
|
// Config is specific to a type only
|
||||||
config.score = 1
|
return 1
|
||||||
}
|
}
|
||||||
return config
|
return 0
|
||||||
})
|
}
|
||||||
|
|
||||||
// Find the config with the most granular scope based on context
|
// Find the config with the most granular scope based on context
|
||||||
const scopedConfig = configs.sort((a, b) => b.score - a.score)[0]
|
const scopedConfig = response.rows.sort(
|
||||||
|
(a, b) => determineScore(a) - determineScore(b)
|
||||||
|
)[0]
|
||||||
|
|
||||||
return scopedConfig
|
return scopedConfig.doc
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.generateConfigID = generateConfigID
|
exports.generateConfigID = generateConfigID
|
||||||
|
|
|
@ -1,12 +1,58 @@
|
||||||
<script>
|
<script>
|
||||||
import "@spectrum-css/avatar/dist/index-vars.css"
|
import "@spectrum-css/avatar/dist/index-vars.css"
|
||||||
|
let sizes = new Map([
|
||||||
|
["XXS", "--spectrum-alias-avatar-size-50"],
|
||||||
|
["XS", "--spectrum-alias-avatar-size-75"],
|
||||||
|
["S", "--spectrum-alias-avatar-size-200"],
|
||||||
|
["M", "--spectrum-alias-avatar-size-300"],
|
||||||
|
["L", "--spectrum-alias-avatar-size-500"],
|
||||||
|
["XL", "--spectrum-alias-avatar-size-600"],
|
||||||
|
["XXL", "--spectrum-alias-avatar-size-700"],
|
||||||
|
])
|
||||||
|
export let size = "M"
|
||||||
export let url = ""
|
export let url = ""
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
|
export let name = "John Doe"
|
||||||
|
|
||||||
|
function getInitials(name) {
|
||||||
|
let parts = name.split(" ")
|
||||||
|
return parts.map((name) => name[0]).join("")
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<img
|
{#if url}
|
||||||
class:is-disabled={disabled}
|
<img
|
||||||
class="spectrum-Avatar"
|
class:is-disabled={disabled}
|
||||||
src={url}
|
class="spectrum-Avatar"
|
||||||
alt="Avatar"
|
src={url}
|
||||||
/>
|
alt="Avatar"
|
||||||
|
style="width: var({sizes.get(size)}); height: var({sizes.get(size)});"
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<div
|
||||||
|
class:is-disabled={disabled}
|
||||||
|
style="width: var({sizes.get(size)}); height: var({sizes.get(
|
||||||
|
size
|
||||||
|
)}); font-size: calc(var({sizes.get(size)}) / 2)"
|
||||||
|
>
|
||||||
|
{getInitials(name)}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
color: white;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
font-weight: 500;
|
||||||
|
background: rgb(63, 94, 251);
|
||||||
|
background: linear-gradient(
|
||||||
|
155deg,
|
||||||
|
rgba(63, 94, 251, 1) 0%,
|
||||||
|
rgba(53, 199, 86, 1) 47%
|
||||||
|
);
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,31 +1,60 @@
|
||||||
<script>
|
<script>
|
||||||
// WIP! Does not yet work.
|
|
||||||
import "@spectrum-css/progresscircle/dist/index-vars.css"
|
import "@spectrum-css/progresscircle/dist/index-vars.css"
|
||||||
import { tweened } from "svelte/motion"
|
|
||||||
import { cubicOut } from "svelte/easing"
|
export let size = "M"
|
||||||
|
function convertSize(size) {
|
||||||
|
switch (size) {
|
||||||
|
case "S":
|
||||||
|
return "small"
|
||||||
|
case "L":
|
||||||
|
return "large"
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export let value = false
|
export let value = false
|
||||||
export let small
|
export let minValue = 0
|
||||||
export let large
|
export let maxValue = 100
|
||||||
|
|
||||||
|
let subMask1Style
|
||||||
|
let subMask2Style
|
||||||
|
$: calculateSubMasks(value)
|
||||||
|
|
||||||
|
function calculateSubMasks(value) {
|
||||||
|
if (value) {
|
||||||
|
let percentage = ((value - minValue) / (maxValue - minValue)) * 100
|
||||||
|
let angle
|
||||||
|
if (percentage > 0 && percentage <= 50) {
|
||||||
|
angle = -180 + (percentage / 50) * 180
|
||||||
|
subMask1Style = `transform: rotate(${angle}deg);`
|
||||||
|
subMask2Style = "transform: rotate(-180deg);"
|
||||||
|
} else if (percentage > 50) {
|
||||||
|
angle = -180 + ((percentage - 50) / 50) * 180
|
||||||
|
subMask1Style = "transform: rotate(0deg);"
|
||||||
|
subMask2Style = `transform: rotate(${angle}deg);`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export let overBackground
|
export let overBackground
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
on:click
|
||||||
class:spectrum-ProgressBar--indeterminate={!value}
|
class:spectrum-ProgressBar--indeterminate={!value}
|
||||||
class:spectrum-ProgressCircle--small={small}
|
class:spectrum-ProgressCircle--overBackground={overBackground}
|
||||||
class:spectrum-ProgressCircle--large={large}
|
class="spectrum-ProgressCircle spectrum-ProgressCircle--{convertSize(size)}"
|
||||||
class="spectrum-ProgressCircle"
|
|
||||||
>
|
>
|
||||||
<div class="spectrum-ProgressCircle-track" />
|
<div class="spectrum-ProgressCircle-track" />
|
||||||
<div class="spectrum-ProgressCircle-fills">
|
<div class="spectrum-ProgressCircle-fills">
|
||||||
<div class="spectrum-ProgressCircle-fillMask1">
|
<div class="spectrum-ProgressCircle-fillMask1">
|
||||||
<div class="spectrum-ProgressCircle-fillSubMask1">
|
<div class="spectrum-ProgressCircle-fillSubMask1" style={subMask1Style}>
|
||||||
<div class="spectrum-ProgressCircle-fill" />
|
<div class="spectrum-ProgressCircle-fill" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="spectrum-ProgressCircle-fillMask2">
|
<div class="spectrum-ProgressCircle-fillMask2">
|
||||||
<div class="spectrum-ProgressCircle-fillSubMask2">
|
<div class="spectrum-ProgressCircle-fillSubMask2" style={subMask2Style}>
|
||||||
<div class="spectrum-ProgressCircle-fill" />
|
<div class="spectrum-ProgressCircle-fill" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset='utf8'>
|
<meta charset='utf8'>
|
||||||
<meta name='viewport' content='width=device-width'>
|
<meta name='viewport' content='width=device-width'>
|
||||||
<title>Budibase Builder</title>
|
<title>Budibase</title>
|
||||||
<link rel='icon' type='image/png' href='./src/favicon.png'>
|
<link rel='icon' type='image/png' href='./src/favicon.png'>
|
||||||
</head>
|
</head>
|
||||||
<body id="app">
|
<body id="app">
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { getFrontendStore } from "./store/frontend"
|
||||||
import { getAutomationStore } from "./store/automation"
|
import { getAutomationStore } from "./store/automation"
|
||||||
import { getHostingStore } from "./store/hosting"
|
import { getHostingStore } from "./store/hosting"
|
||||||
import { getThemeStore } from "./store/theme"
|
import { getThemeStore } from "./store/theme"
|
||||||
|
import { getAdminStore } from "./store/admin"
|
||||||
import { derived, writable } from "svelte/store"
|
import { derived, writable } from "svelte/store"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
import { FrontendTypes, LAYOUT_NAMES } from "../constants"
|
import { FrontendTypes, LAYOUT_NAMES } from "../constants"
|
||||||
|
@ -11,6 +12,7 @@ export const store = getFrontendStore()
|
||||||
export const automationStore = getAutomationStore()
|
export const automationStore = getAutomationStore()
|
||||||
export const themeStore = getThemeStore()
|
export const themeStore = getThemeStore()
|
||||||
export const hostingStore = getHostingStore()
|
export const hostingStore = getHostingStore()
|
||||||
|
export const adminPanelStore = getAdminStore()
|
||||||
|
|
||||||
export const currentAsset = derived(store, $store => {
|
export const currentAsset = derived(store, $store => {
|
||||||
const type = $store.currentFrontEndType
|
const type = $store.currentFrontEndType
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
|
||||||
|
const INITIAL_ADMIN_STATE = {
|
||||||
|
oauth: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAdminStore = () => {
|
||||||
|
const store = writable({ ...INITIAL_ADMIN_STATE })
|
||||||
|
store.actions = {}
|
||||||
|
return store
|
||||||
|
}
|
|
@ -119,10 +119,6 @@
|
||||||
top: var(--spacing-l);
|
top: var(--spacing-l);
|
||||||
right: var(--spacing-xl);
|
right: var(--spacing-xl);
|
||||||
}
|
}
|
||||||
.title i:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
color: var(--blue);
|
|
||||||
}
|
|
||||||
|
|
||||||
.role-select {
|
.role-select {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -16,11 +16,14 @@
|
||||||
{#if $auth.user}
|
{#if $auth.user}
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<div class="ui-nav">
|
<div class="ui-nav">
|
||||||
<div class="home-logo"><img src={Logo} alt="Budibase icon" /></div>
|
<div class="home-logo">
|
||||||
|
<img src={Logo} alt="Budibase icon" />
|
||||||
|
</div>
|
||||||
<div class="nav-section">
|
<div class="nav-section">
|
||||||
<div class="nav-top">
|
<div class="nav-top">
|
||||||
<Navigation>
|
<Navigation>
|
||||||
<Item href="/builder/" icon="Apps" selected>Apps</Item>
|
<Item href="/builder/" icon="Apps" selected>Apps</Item>
|
||||||
|
<Item href="/builder/oauth/" icon="OAuth" selected>OAuth</Item>
|
||||||
<Item external href="https://portal.budi.live/" icon="Servers">
|
<Item external href="https://portal.budi.live/" icon="Servers">
|
||||||
Hosting
|
Hosting
|
||||||
</Item>
|
</Item>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Index route
|
|
@ -0,0 +1,126 @@
|
||||||
|
<script>
|
||||||
|
import { isActive, url } from "@roxi/routify"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
import {
|
||||||
|
Icon,
|
||||||
|
Avatar,
|
||||||
|
Search,
|
||||||
|
Layout,
|
||||||
|
ProgressCircle,
|
||||||
|
SideNavigation as Navigation,
|
||||||
|
SideNavigationItem as Item,
|
||||||
|
} from "@budibase/bbui"
|
||||||
|
|
||||||
|
let orgName, orgLogo, onBoardingProgress, user
|
||||||
|
|
||||||
|
async function getInfo() {
|
||||||
|
// fetch orgInfo
|
||||||
|
orgName = "ACME Inc."
|
||||||
|
orgLogo = "https://via.placeholder.com/150"
|
||||||
|
|
||||||
|
// set onBoardingProgress
|
||||||
|
onBoardingProgress = 20
|
||||||
|
user = { name: "John Doe" }
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(getInfo)
|
||||||
|
|
||||||
|
let menu = [
|
||||||
|
{ title: "Apps", href: "/portal" },
|
||||||
|
{ title: "Drafts", href: "/portal/drafts" },
|
||||||
|
{ title: "Users", href: "/portal/users", heading: "Manage" },
|
||||||
|
{ title: "Groups", href: "/portal/groups" },
|
||||||
|
{ title: "Auth", href: "/portal/oauth" },
|
||||||
|
{ title: "Email", href: "/portal/email" },
|
||||||
|
{ title: "General", href: "/portal/general", heading: "Settings" },
|
||||||
|
{ title: "Theming", href: "/portal/theming" },
|
||||||
|
{ title: "Account", href: "/portal/account" },
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<Layout>
|
||||||
|
<div class="nav">
|
||||||
|
<div class="branding">
|
||||||
|
<div class="name">
|
||||||
|
<img src={orgLogo} alt="Logotype" />
|
||||||
|
<span>{orgName}</span>
|
||||||
|
</div>
|
||||||
|
<div class="onboarding">
|
||||||
|
<ProgressCircle size="S" value={onBoardingProgress} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="menu">
|
||||||
|
<Navigation>
|
||||||
|
{#each menu as { title, href, heading }}
|
||||||
|
<Item selected={$isActive(href)} href={$url(href)} {heading}>
|
||||||
|
{title}
|
||||||
|
</Item>
|
||||||
|
{/each}
|
||||||
|
</Navigation>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
<div class="main">
|
||||||
|
<div class="toolbar">
|
||||||
|
<Search />
|
||||||
|
<div class="avatar">
|
||||||
|
<Avatar size="M" name="John Doe" />
|
||||||
|
<Icon size="XL" name="ChevronDown" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 250px 1fr;
|
||||||
|
}
|
||||||
|
.main {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
border-left: 2px solid var(--spectrum-alias-background-color-primary);
|
||||||
|
}
|
||||||
|
.branding {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: var(--spacing-xl);
|
||||||
|
}
|
||||||
|
.name {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
grid-gap: var(--spacing-m);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: var(--spacing-m);
|
||||||
|
}
|
||||||
|
.avatar {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
place-items: center;
|
||||||
|
grid-gap: var(--spacing-xs);
|
||||||
|
}
|
||||||
|
.avatar:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
filter: brightness(110%);
|
||||||
|
}
|
||||||
|
.toolbar {
|
||||||
|
border-bottom: 2px solid var(--spectrum-alias-background-color-primary);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 250px auto;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: var(--spacing-m) calc(var(--spacing-xl) * 2);
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,118 @@
|
||||||
|
<script>
|
||||||
|
import GoogleLogo from "./logos/Google.svelte"
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Heading,
|
||||||
|
Divider,
|
||||||
|
Label,
|
||||||
|
notifications,
|
||||||
|
Layout,
|
||||||
|
Input,
|
||||||
|
Body,
|
||||||
|
} from "@budibase/bbui"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
import api from "builderStore/api"
|
||||||
|
|
||||||
|
const ConfigTypes = {
|
||||||
|
Google: "google",
|
||||||
|
// Github: "github",
|
||||||
|
// AzureAD: "ad",
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConfigFields = {
|
||||||
|
Google: ["clientID", "clientSecret", "callbackURL"],
|
||||||
|
}
|
||||||
|
|
||||||
|
let google
|
||||||
|
|
||||||
|
async function save(doc) {
|
||||||
|
try {
|
||||||
|
// Save an oauth config
|
||||||
|
const response = await api.post(`/api/admin/configs`, doc)
|
||||||
|
const json = await response.json()
|
||||||
|
if (response.status !== 200) throw new Error(json.message)
|
||||||
|
google._rev = json._rev
|
||||||
|
google._id = json._id
|
||||||
|
|
||||||
|
notifications.success(`Settings saved.`)
|
||||||
|
} catch (err) {
|
||||||
|
notifications.error(`Failed to update OAuth settings. ${err}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
// fetch the configs for oauth
|
||||||
|
const googleResponse = await api.get(
|
||||||
|
`/api/admin/configs/${ConfigTypes.Google}`
|
||||||
|
)
|
||||||
|
const googleDoc = await googleResponse.json()
|
||||||
|
|
||||||
|
if (!googleDoc._id) {
|
||||||
|
google = {
|
||||||
|
type: ConfigTypes.Google,
|
||||||
|
config: {},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
google = googleDoc
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class="container">
|
||||||
|
<header>
|
||||||
|
<Heading size="M">OAuth</Heading>
|
||||||
|
<Body size="S">
|
||||||
|
Every budibase app comes with basic authentication (email/password)
|
||||||
|
included. You can add additional authentication methods from the options
|
||||||
|
below.
|
||||||
|
</Body>
|
||||||
|
</header>
|
||||||
|
<Divider />
|
||||||
|
{#if google}
|
||||||
|
<div class="config-form">
|
||||||
|
<Layout gap="S">
|
||||||
|
<Heading size="S">
|
||||||
|
<span>
|
||||||
|
<GoogleLogo />
|
||||||
|
Google
|
||||||
|
</span>
|
||||||
|
</Heading>
|
||||||
|
{#each ConfigFields.Google as field}
|
||||||
|
<div class="form-row">
|
||||||
|
<Label>{field}</Label>
|
||||||
|
<Input bind:value={google.config[field]} />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</Layout>
|
||||||
|
<Button primary on:click={() => save(google)}>Save</Button>
|
||||||
|
</div>
|
||||||
|
<Divider />
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
section {
|
||||||
|
margin: 60px 320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-form {
|
||||||
|
margin-top: 42px;
|
||||||
|
margin-bottom: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 20% 1fr;
|
||||||
|
grid-gap: var(--spacing-l);
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
margin-bottom: 42px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<svg
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
viewBox="0 0 268 268"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0)">
|
||||||
|
<path
|
||||||
|
d="M58.8037 109.043C64.0284 93.2355 74.1116 79.4822 87.615 69.7447C101.118
|
||||||
|
60.0073 117.352 54.783 134 54.8172C152.872 54.8172 169.934 61.5172 183.334
|
||||||
|
72.4828L222.328 33.5C198.566 12.7858 168.114 0 134 0C81.1817 0 35.711
|
||||||
|
30.1277 13.8467 74.2583L58.8037 109.043Z"
|
||||||
|
fill="#EA4335" />
|
||||||
|
<path
|
||||||
|
d="M179.113 201.145C166.942 208.995 151.487 213.183 134 213.183C117.418
|
||||||
|
213.217 101.246 208.034 87.7727 198.369C74.2993 188.703 64.2077 175.044
|
||||||
|
58.9265 159.326L13.8132 193.574C24.8821 215.978 42.012 234.828 63.2572
|
||||||
|
247.984C84.5024 261.14 109.011 268.075 134 268C166.752 268 198.041 256.353
|
||||||
|
221.48 234.5L179.125 201.145H179.113Z"
|
||||||
|
fill="#34A853" />
|
||||||
|
<path
|
||||||
|
d="M221.48 234.5C245.991 211.631 261.903 177.595 261.903 134C261.903
|
||||||
|
126.072 260.686 117.552 258.866 109.634H134V161.414H205.869C202.329
|
||||||
|
178.823 192.804 192.301 179.125 201.145L221.48 234.5Z"
|
||||||
|
fill="#4A90E2" />
|
||||||
|
<path
|
||||||
|
d="M58.9265 159.326C56.1947 151.162 54.8068 142.609 54.8172 134C54.8172
|
||||||
|
125.268 56.213 116.882 58.8037 109.043L13.8467 74.2584C4.64957 92.825
|
||||||
|
-0.0915078 113.28 1.86708e-05 134C1.86708e-05 155.44 4.96919 175.652
|
||||||
|
13.8132 193.574L58.9265 159.326Z"
|
||||||
|
fill="#FBBC05" />
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0">
|
||||||
|
<rect width="268" height="268" fill="white" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -6,7 +6,7 @@ import path from "path"
|
||||||
export default ({ mode }) => {
|
export default ({ mode }) => {
|
||||||
const isProduction = mode === "production"
|
const isProduction = mode === "production"
|
||||||
return {
|
return {
|
||||||
base: "/builder/",
|
base: "/",
|
||||||
build: {
|
build: {
|
||||||
minify: isProduction,
|
minify: isProduction,
|
||||||
outDir: "../server/builder",
|
outDir: "../server/builder",
|
||||||
|
|
|
@ -12,13 +12,10 @@ const GLOBAL_DB = StaticDatabases.GLOBAL.name
|
||||||
|
|
||||||
exports.save = async function (ctx) {
|
exports.save = async function (ctx) {
|
||||||
const db = new CouchDB(GLOBAL_DB)
|
const db = new CouchDB(GLOBAL_DB)
|
||||||
const { type, config } = ctx.request.body
|
const { type, group, user, config } = ctx.request.body
|
||||||
const { group, user } = config
|
|
||||||
// insert the type into the doc
|
|
||||||
config.type = type
|
|
||||||
|
|
||||||
// Config does not exist yet
|
// Config does not exist yet
|
||||||
if (!config._id) {
|
if (!ctx.request.body._id) {
|
||||||
config._id = generateConfigID({
|
config._id = generateConfigID({
|
||||||
type,
|
type,
|
||||||
group,
|
group,
|
||||||
|
|
|
@ -44,6 +44,9 @@ function googleValidation() {
|
||||||
function buildConfigSaveValidation() {
|
function buildConfigSaveValidation() {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return joiValidator.body(Joi.object({
|
return joiValidator.body(Joi.object({
|
||||||
|
_id: Joi.string(),
|
||||||
|
_rev: Joi.string(),
|
||||||
|
group: Joi.string(),
|
||||||
type: Joi.string().valid(...Object.values(Configs)).required(),
|
type: Joi.string().valid(...Object.values(Configs)).required(),
|
||||||
config: Joi.alternatives()
|
config: Joi.alternatives()
|
||||||
.conditional("type", {
|
.conditional("type", {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const CouchDB = require("../db")
|
const CouchDB = require("../db")
|
||||||
const { getConfigParams, StaticDatabases } = require("@budibase/auth").db
|
const { determineScopedConfig, StaticDatabases } = require("@budibase/auth").db
|
||||||
const {
|
const {
|
||||||
Configs,
|
Configs,
|
||||||
TemplateBindings,
|
TemplateBindings,
|
||||||
|
@ -14,12 +14,8 @@ const BASE_COMPANY = "Budibase"
|
||||||
|
|
||||||
exports.getSettingsTemplateContext = async (purpose, code = null) => {
|
exports.getSettingsTemplateContext = async (purpose, code = null) => {
|
||||||
const db = new CouchDB(StaticDatabases.GLOBAL.name)
|
const db = new CouchDB(StaticDatabases.GLOBAL.name)
|
||||||
const response = await db.allDocs(
|
// TODO: use more granular settings in the future if required
|
||||||
getConfigParams(Configs.SETTINGS, {
|
const settings = await determineScopedConfig(db, { type: Configs.SETTINGS })
|
||||||
include_docs: true,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
let settings = response.rows.map(row => row.doc)[0] || {}
|
|
||||||
if (!settings.platformUrl) {
|
if (!settings.platformUrl) {
|
||||||
settings.platformUrl = LOCAL_URL
|
settings.platformUrl = LOCAL_URL
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue