forked from tsai/budibase
committed by
GitHub
180 changed files with 3724 additions and 6300 deletions
@ -0,0 +1,126 @@ |
|||||
|
<script> |
||||
|
export let width = "100" |
||||
|
export let height = "100" |
||||
|
</script> |
||||
|
|
||||
|
<svg |
||||
|
version="1.1" |
||||
|
id="Layer_1" |
||||
|
xmlns="http://www.w3.org/2000/svg" |
||||
|
xmlns:xlink="http://www.w3.org/1999/xlink" |
||||
|
x="0px" |
||||
|
y="0px" |
||||
|
viewBox="0 0 48 48" |
||||
|
style="enable-background:new 0 0 48 48;" |
||||
|
xml:space="preserve" |
||||
|
{height} |
||||
|
{width} |
||||
|
> |
||||
|
<style type="text/css"> |
||||
|
.st0 { |
||||
|
fill: #393c44; |
||||
|
} |
||||
|
.st1 { |
||||
|
fill: #ffffff; |
||||
|
} |
||||
|
.st2 { |
||||
|
fill: #4285f4; |
||||
|
} |
||||
|
</style> |
||||
|
<rect x="-152.17" y="-24.17" class="st0" width="96.17" height="96.17" /> |
||||
|
<path |
||||
|
class="st1" |
||||
|
d="M-83.19,48h-41.79c-1.76,0-3.19-1.43-3.19-3.19V3.02c0-1.76,1.43-3.19,3.19-3.19h41.79 |
||||
|
c1.76,0,3.19,1.43,3.19,3.19v41.79C-80,46.57-81.43,48-83.19,48z" |
||||
|
/> |
||||
|
<g> |
||||
|
<g> |
||||
|
<path |
||||
|
class="st0" |
||||
|
d="M-99.62,12.57v9.94c1.15-1.21,2.59-1.81,4.32-1.81c1.03,0,1.97,0.19,2.82,0.58c0.86,0.39,1.59,0.91,2.19,1.57 |
||||
|
c0.6,0.66,1.08,1.43,1.42,2.32c0.34,0.89,0.51,1.84,0.51,2.85c0,1.03-0.18,1.99-0.53,2.89c-0.35,0.9-0.84,1.68-1.47,2.35 |
||||
|
c-0.63,0.67-1.37,1.19-2.23,1.58c-0.86,0.39-1.78,0.58-2.77,0.58c-1.8,0-3.22-0.66-4.27-1.97V35h-4.89V12.57H-99.62z |
||||
|
M-93.46,28.11c0-0.43-0.08-0.84-0.24-1.23c-0.16-0.39-0.39-0.72-0.68-1.01c-0.29-0.29-0.62-0.52-1-0.69 |
||||
|
c-0.38-0.17-0.79-0.26-1.24-0.26c-0.43,0-0.84,0.08-1.22,0.24c-0.38,0.16-0.71,0.39-0.99,0.68c-0.28,0.29-0.5,0.63-0.68,1.01 |
||||
|
c-0.17,0.39-0.26,0.8-0.26,1.23c0,0.43,0.08,0.84,0.24,1.22c0.16,0.38,0.39,0.71,0.68,0.99c0.29,0.28,0.63,0.5,1.01,0.68 |
||||
|
c0.39,0.17,0.8,0.26,1.23,0.26c0.43,0,0.84-0.08,1.22-0.24c0.38-0.16,0.71-0.39,0.99-0.68c0.28-0.29,0.5-0.62,0.68-1 |
||||
|
C-93.55,28.92-93.46,28.52-93.46,28.11z" |
||||
|
/> |
||||
|
</g> |
||||
|
<g> |
||||
|
<path |
||||
|
class="st0" |
||||
|
d="M-114.76,12.57v9.94c1.15-1.21,2.59-1.81,4.32-1.81c1.03,0,1.97,0.19,2.82,0.58 |
||||
|
c0.86,0.39,1.59,0.91,2.19,1.57c0.6,0.66,1.08,1.43,1.42,2.32c0.34,0.89,0.51,1.84,0.51,2.85c0,1.03-0.18,1.99-0.53,2.89 |
||||
|
c-0.35,0.9-0.84,1.68-1.47,2.35c-0.63,0.67-1.37,1.19-2.23,1.58c-0.86,0.39-1.78,0.58-2.77,0.58c-1.8,0-3.22-0.66-4.27-1.97V35 |
||||
|
h-4.89V12.57H-114.76z M-108.6,28.11c0-0.43-0.08-0.84-0.24-1.23c-0.16-0.39-0.39-0.72-0.68-1.01c-0.29-0.29-0.62-0.52-1-0.69 |
||||
|
c-0.38-0.17-0.79-0.26-1.24-0.26c-0.43,0-0.84,0.08-1.22,0.24c-0.38,0.16-0.71,0.39-0.99,0.68c-0.28,0.29-0.5,0.63-0.68,1.01 |
||||
|
c-0.17,0.39-0.26,0.8-0.26,1.23c0,0.43,0.08,0.84,0.24,1.22c0.16,0.38,0.39,0.71,0.68,0.99c0.29,0.28,0.63,0.5,1.01,0.68 |
||||
|
c0.39,0.17,0.8,0.26,1.23,0.26c0.43,0,0.84-0.08,1.22-0.24c0.38-0.16,0.71-0.39,0.99-0.68c0.28-0.29,0.5-0.62,0.68-1 |
||||
|
C-108.68,28.92-108.6,28.52-108.6,28.11z" |
||||
|
/> |
||||
|
</g> |
||||
|
</g> |
||||
|
<path |
||||
|
class="st2" |
||||
|
d="M44.81,159H3.02c-1.76,0-3.19-1.43-3.19-3.19v-41.79c0-1.76,1.43-3.19,3.19-3.19h41.79 |
||||
|
c1.76,0,3.19,1.43,3.19,3.19v41.79C48,157.57,46.57,159,44.81,159z" |
||||
|
/> |
||||
|
<g> |
||||
|
<g> |
||||
|
<path |
||||
|
class="st1" |
||||
|
d="M28.38,123.57v9.94c1.15-1.21,2.59-1.81,4.32-1.81c1.03,0,1.97,0.19,2.82,0.58c0.86,0.39,1.59,0.91,2.19,1.57 |
||||
|
c0.6,0.66,1.08,1.43,1.42,2.32c0.34,0.89,0.51,1.84,0.51,2.85c0,1.03-0.18,1.99-0.53,2.89c-0.35,0.9-0.84,1.68-1.47,2.35 |
||||
|
c-0.63,0.67-1.37,1.19-2.23,1.58c-0.86,0.39-1.78,0.58-2.77,0.58c-1.8,0-3.22-0.66-4.27-1.97V146h-4.89v-22.43H28.38z |
||||
|
M34.54,139.11c0-0.43-0.08-0.84-0.24-1.23c-0.16-0.39-0.39-0.72-0.68-1.01c-0.29-0.29-0.62-0.52-1-0.69 |
||||
|
c-0.38-0.17-0.79-0.26-1.24-0.26c-0.43,0-0.84,0.08-1.22,0.24c-0.38,0.16-0.71,0.39-0.99,0.68c-0.28,0.29-0.5,0.63-0.68,1.01 |
||||
|
c-0.17,0.39-0.26,0.8-0.26,1.23c0,0.43,0.08,0.84,0.24,1.22c0.16,0.38,0.39,0.71,0.68,0.99c0.29,0.28,0.63,0.5,1.01,0.68 |
||||
|
c0.39,0.17,0.8,0.26,1.23,0.26c0.43,0,0.84-0.08,1.22-0.24c0.38-0.16,0.71-0.39,0.99-0.68c0.28-0.29,0.5-0.62,0.68-1 |
||||
|
C34.45,139.92,34.54,139.52,34.54,139.11z" |
||||
|
/> |
||||
|
</g> |
||||
|
<g> |
||||
|
<path |
||||
|
class="st1" |
||||
|
d="M13.24,123.57v9.94c1.15-1.21,2.59-1.81,4.32-1.81c1.03,0,1.97,0.19,2.82,0.58c0.86,0.39,1.59,0.91,2.19,1.57 |
||||
|
c0.6,0.66,1.08,1.43,1.42,2.32c0.34,0.89,0.51,1.84,0.51,2.85c0,1.03-0.18,1.99-0.53,2.89c-0.35,0.9-0.84,1.68-1.47,2.35 |
||||
|
c-0.63,0.67-1.37,1.19-2.23,1.58c-0.86,0.39-1.78,0.58-2.77,0.58c-1.8,0-3.22-0.66-4.27-1.97V146H8.35v-22.43H13.24z M19.4,139.11 |
||||
|
c0-0.43-0.08-0.84-0.24-1.23c-0.16-0.39-0.39-0.72-0.68-1.01c-0.29-0.29-0.62-0.52-1-0.69c-0.38-0.17-0.79-0.26-1.24-0.26 |
||||
|
c-0.43,0-0.84,0.08-1.22,0.24c-0.38,0.16-0.71,0.39-0.99,0.68c-0.28,0.29-0.5,0.63-0.68,1.01c-0.17,0.39-0.26,0.8-0.26,1.23 |
||||
|
c0,0.43,0.08,0.84,0.24,1.22c0.16,0.38,0.39,0.71,0.68,0.99c0.29,0.28,0.63,0.5,1.01,0.68c0.39,0.17,0.8,0.26,1.23,0.26 |
||||
|
c0.43,0,0.84-0.08,1.22-0.24c0.38-0.16,0.71-0.39,0.99-0.68c0.28-0.29,0.5-0.62,0.68-1C19.32,139.92,19.4,139.52,19.4,139.11z" |
||||
|
/> |
||||
|
</g> |
||||
|
</g> |
||||
|
<g> |
||||
|
<path |
||||
|
class="st0" |
||||
|
d="M44,48H4c-2.21,0-4-1.79-4-4V4c0-2.21,1.79-4,4-4h40c2.21,0,4,1.79,4,4v40C48,46.21,46.21,48,44,48z" |
||||
|
/> |
||||
|
<g> |
||||
|
<path |
||||
|
class="st1" |
||||
|
d="M28.48,12v10.44c1.18-1.27,2.65-1.9,4.42-1.9c1.05,0,2.01,0.2,2.89,0.61c0.87,0.41,1.62,0.96,2.24,1.65 |
||||
|
c0.62,0.69,1.1,1.5,1.45,2.44c0.35,0.94,0.52,1.93,0.52,2.99c0,1.08-0.18,2.09-0.54,3.04c-0.36,0.95-0.86,1.77-1.51,2.47 |
||||
|
c-0.64,0.7-1.4,1.25-2.28,1.66C34.8,35.8,33.86,36,32.84,36c-1.84,0-3.3-0.69-4.37-2.07v1.62h-5V12H28.48z M34.78,28.31 |
||||
|
c0-0.45-0.08-0.88-0.25-1.29c-0.17-0.41-0.4-0.76-0.69-1.06c-0.3-0.3-0.64-0.54-1.02-0.72c-0.39-0.18-0.81-0.27-1.27-0.27 |
||||
|
c-0.44,0-0.86,0.09-1.24,0.26c-0.39,0.17-0.72,0.41-1.01,0.71c-0.29,0.3-0.52,0.66-0.69,1.06c-0.18,0.41-0.26,0.84-0.26,1.29 |
||||
|
s0.08,0.88,0.25,1.28c0.17,0.4,0.4,0.74,0.69,1.04c0.29,0.29,0.64,0.53,1.04,0.71c0.4,0.18,0.82,0.27,1.26,0.27 |
||||
|
c0.44,0,0.86-0.09,1.24-0.26c0.39-0.17,0.72-0.41,1.01-0.71c0.29-0.3,0.52-0.65,0.69-1.05C34.69,29.16,34.78,28.75,34.78,28.31z" |
||||
|
/> |
||||
|
</g> |
||||
|
<g> |
||||
|
<path |
||||
|
class="st1" |
||||
|
d="M13,12v10.44c1.18-1.27,2.65-1.9,4.42-1.9c1.05,0,2.01,0.2,2.89,0.61c0.87,0.41,1.62,0.96,2.24,1.65 |
||||
|
c0.62,0.69,1.1,1.5,1.45,2.44c0.35,0.94,0.52,1.93,0.52,2.99c0,1.08-0.18,2.09-0.54,3.04c-0.36,0.95-0.86,1.77-1.51,2.47 |
||||
|
c-0.64,0.7-1.4,1.25-2.28,1.66C19.32,35.8,18.38,36,17.37,36c-1.84,0-3.3-0.69-4.37-2.07v1.62H8V12H13z M19.3,28.31 |
||||
|
c0-0.45-0.08-0.88-0.25-1.29c-0.17-0.41-0.4-0.76-0.69-1.06c-0.3-0.3-0.64-0.54-1.02-0.72c-0.39-0.18-0.81-0.27-1.27-0.27 |
||||
|
c-0.44,0-0.86,0.09-1.24,0.26c-0.39,0.17-0.72,0.41-1.01,0.71c-0.29,0.3-0.52,0.66-0.69,1.06c-0.18,0.41-0.26,0.84-0.26,1.29 |
||||
|
s0.08,0.88,0.25,1.28c0.17,0.4,0.4,0.74,0.69,1.04c0.29,0.29,0.64,0.53,1.04,0.71c0.4,0.18,0.82,0.27,1.26,0.27 |
||||
|
c0.44,0,0.86-0.09,1.24-0.26c0.39-0.17,0.72-0.41,1.01-0.71c0.29-0.3,0.52-0.65,0.69-1.05C19.21,29.16,19.3,28.75,19.3,28.31z" |
||||
|
/> |
||||
|
</g> |
||||
|
</g> |
||||
|
</svg> |
||||
@ -0,0 +1,17 @@ |
|||||
|
<script> |
||||
|
import { Icon } from "@budibase/bbui" |
||||
|
</script> |
||||
|
|
||||
|
<a target="_blank" href="https://github.com/Budibase/budibase/discussions"> |
||||
|
<Icon hoverable name="Help" size="XXL" /> |
||||
|
</a> |
||||
|
|
||||
|
<style> |
||||
|
a { |
||||
|
color: inherit; |
||||
|
position: absolute; |
||||
|
bottom: var(--spacing-m); |
||||
|
right: var(--spacing-m); |
||||
|
border-radius: 55%; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,14 @@ |
|||||
|
<script> |
||||
|
import { Body } from "@budibase/bbui" |
||||
|
</script> |
||||
|
|
||||
|
<div class="root"> |
||||
|
<Body size="S">This action doesn't require any additional settings.</Body> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
.root { |
||||
|
max-width: 800px; |
||||
|
margin: 0 auto; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,114 @@ |
|||||
|
<script> |
||||
|
import { |
||||
|
Button, |
||||
|
Icon, |
||||
|
DrawerContent, |
||||
|
Layout, |
||||
|
Input, |
||||
|
Combobox, |
||||
|
} from "@budibase/bbui" |
||||
|
import { flip } from "svelte/animate" |
||||
|
import { dndzone } from "svelte-dnd-action" |
||||
|
import { generate } from "shortid" |
||||
|
import { store } from "builderStore" |
||||
|
|
||||
|
export let links = [] |
||||
|
|
||||
|
const flipDurationMs = 150 |
||||
|
|
||||
|
$: links.forEach(link => { |
||||
|
if (!link.id) { |
||||
|
link.id = generate() |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
$: urlOptions = $store.screens |
||||
|
.map(screen => screen.routing?.route) |
||||
|
.filter(x => x != null) |
||||
|
|
||||
|
const addLink = () => { |
||||
|
links = [...links, {}] |
||||
|
} |
||||
|
|
||||
|
const removeLink = id => { |
||||
|
links = links.filter(link => link.id !== id) |
||||
|
} |
||||
|
|
||||
|
const updateLinks = e => { |
||||
|
links = e.detail.items |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<DrawerContent> |
||||
|
<div class="container"> |
||||
|
<Layout> |
||||
|
{#if links?.length} |
||||
|
<div |
||||
|
class="links" |
||||
|
use:dndzone={{ |
||||
|
items: links, |
||||
|
flipDurationMs, |
||||
|
dropTargetStyle: { outline: "none" }, |
||||
|
}} |
||||
|
on:finalize={updateLinks} |
||||
|
on:consider={updateLinks} |
||||
|
> |
||||
|
{#each links as link (link.id)} |
||||
|
<div class="link" animate:flip={{ duration: flipDurationMs }}> |
||||
|
<Icon name="DragHandle" size="XL" /> |
||||
|
<Input bind:value={link.text} placeholder="Text" /> |
||||
|
<Combobox |
||||
|
bind:value={link.url} |
||||
|
placeholder="URL" |
||||
|
options={urlOptions} |
||||
|
/> |
||||
|
<Icon |
||||
|
name="Close" |
||||
|
hoverable |
||||
|
size="S" |
||||
|
on:click={() => removeLink(link.id)} |
||||
|
/> |
||||
|
</div> |
||||
|
{/each} |
||||
|
</div> |
||||
|
{/if} |
||||
|
<div class="button-container"> |
||||
|
<Button secondary icon="Add" on:click={addLink}>Add Link</Button> |
||||
|
</div> |
||||
|
</Layout> |
||||
|
</div> |
||||
|
</DrawerContent> |
||||
|
|
||||
|
<style> |
||||
|
.container { |
||||
|
width: 100%; |
||||
|
max-width: 600px; |
||||
|
margin: var(--spacing-m) auto; |
||||
|
} |
||||
|
.links { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: flex-start; |
||||
|
align-items: stretch; |
||||
|
} |
||||
|
.link { |
||||
|
padding: 4px 8px; |
||||
|
gap: var(--spacing-l); |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
border-radius: var(--border-radius-s); |
||||
|
transition: background-color ease-in-out 130ms; |
||||
|
} |
||||
|
.link:hover { |
||||
|
background-color: var(--spectrum-global-color-gray-100); |
||||
|
} |
||||
|
.link > :global(.spectrum-Form-item) { |
||||
|
flex: 1 1 auto; |
||||
|
width: 0; |
||||
|
} |
||||
|
.button-container { |
||||
|
margin-left: var(--spacing-l); |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,23 @@ |
|||||
|
<script> |
||||
|
import { Button, ActionButton, Drawer } from "@budibase/bbui" |
||||
|
import { createEventDispatcher } from "svelte" |
||||
|
import NavigationDrawer from "./NavigationDrawer.svelte" |
||||
|
|
||||
|
export let value = [] |
||||
|
let drawer |
||||
|
|
||||
|
const dispatch = createEventDispatcher() |
||||
|
const save = () => { |
||||
|
dispatch("change", value) |
||||
|
drawer.hide() |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<ActionButton on:click={drawer.show}>Configure Links</ActionButton> |
||||
|
<Drawer bind:this={drawer} title={"Navigation Links"}> |
||||
|
<svelte:fragment slot="description"> |
||||
|
Configure the links in your navigation bar. |
||||
|
</svelte:fragment> |
||||
|
<Button cta slot="buttons" on:click={save}>Save</Button> |
||||
|
<NavigationDrawer slot="body" bind:links={value} /> |
||||
|
</Drawer> |
||||
@ -0,0 +1,75 @@ |
|||||
|
<script> |
||||
|
import { createEventDispatcher } from "svelte" |
||||
|
import { ActionButton, Body, Icon, Modal, ModalContent } from "@budibase/bbui" |
||||
|
|
||||
|
const dispatch = createEventDispatcher() |
||||
|
|
||||
|
export let value = "" |
||||
|
let selected = value |
||||
|
|
||||
|
let modal |
||||
|
let layoutMap = { |
||||
|
mainSidebar: { |
||||
|
name: "Main with Sidebar", |
||||
|
icon: "ColumnTwoB", |
||||
|
}, |
||||
|
sidebarMain: { |
||||
|
name: "Sidebar with Main", |
||||
|
icon: "ColumnTwoC", |
||||
|
}, |
||||
|
twoColumns: { |
||||
|
name: "Two columns", |
||||
|
icon: "ColumnTwoA", |
||||
|
}, |
||||
|
threeColumns: { |
||||
|
name: "Three columns", |
||||
|
icon: "ViewColumn", |
||||
|
}, |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<ActionButton on:click={modal.show}>{layoutMap[value].name}</ActionButton> |
||||
|
<Modal bind:this={modal}> |
||||
|
<ModalContent |
||||
|
onConfirm={() => dispatch("change", selected)} |
||||
|
size="L" |
||||
|
title="Select layout" |
||||
|
> |
||||
|
<div class="container"> |
||||
|
{#each Object.entries(layoutMap) as [key, value]} |
||||
|
<button |
||||
|
class:selected={selected === key} |
||||
|
on:click={() => (selected = key)} |
||||
|
class="layout" |
||||
|
> |
||||
|
<Icon color="white" size="L" name={value.icon} /> |
||||
|
<Body size="XS">{value.name}</Body> |
||||
|
</button> |
||||
|
{/each} |
||||
|
</div> |
||||
|
</ModalContent> |
||||
|
</Modal> |
||||
|
|
||||
|
<style> |
||||
|
.container { |
||||
|
display: grid; |
||||
|
grid-gap: 20px; |
||||
|
grid-template-columns: 1fr 1fr 1fr; |
||||
|
} |
||||
|
|
||||
|
.layout { |
||||
|
color: var(--spectrum-body-m-text-color, var(--spectrum-alias-text-color)); |
||||
|
border: none; |
||||
|
box-sizing: border-box; |
||||
|
display: grid; |
||||
|
place-items: center; |
||||
|
background: var(--background-alt); |
||||
|
grid-gap: var(--spectrum-alias-grid-margin-xsmall); |
||||
|
padding: var(--spectrum-alias-item-padding-s); |
||||
|
transition: 0.3s all; |
||||
|
border-radius: var(--spacing-s); |
||||
|
} |
||||
|
.selected { |
||||
|
background: var(--spectrum-alias-background-color-tertiary); |
||||
|
} |
||||
|
</style> |
||||
@ -1,54 +0,0 @@ |
|||||
<script> |
|
||||
import { Button } from "@budibase/bbui" |
|
||||
export let remove = false |
|
||||
</script> |
|
||||
|
|
||||
<div class="container"> |
|
||||
<div class="content"> |
|
||||
<div class="img"><img src="https://picsum.photos/60/60" alt="zoom" /></div> |
|
||||
<div class="body"> |
|
||||
<div class="title">Zoom</div> |
|
||||
<div class="description"> |
|
||||
Lorem, ipsum dolor sit amet consectetur adipisicing elit |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="footer"> |
|
||||
<Button wide error={remove} secondary={!remove} on:click> |
|
||||
<span>{remove ? "Remove" : "Add"}</span> |
|
||||
</Button> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.container { |
|
||||
display: grid; |
|
||||
padding: 12px; |
|
||||
background: var(--light-grey); |
|
||||
grid-gap: 20px; |
|
||||
} |
|
||||
span { |
|
||||
font-size: 12px; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
.content { |
|
||||
display: grid; |
|
||||
grid-gap: 12px; |
|
||||
grid-template-columns: 60px auto; |
|
||||
} |
|
||||
.title { |
|
||||
font-size: 14px; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
.description { |
|
||||
font-size: 12px; |
|
||||
} |
|
||||
.img { |
|
||||
border-radius: 3px; |
|
||||
overflow: hidden; |
|
||||
} |
|
||||
img { |
|
||||
height: 60px; |
|
||||
width: 60px; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,33 +0,0 @@ |
|||||
<script> |
|
||||
import SettingsModal from "./SettingsModal.svelte" |
|
||||
import { Modal, Icon } from "@budibase/bbui" |
|
||||
|
|
||||
let modal |
|
||||
</script> |
|
||||
|
|
||||
<div |
|
||||
class="topnavitemright settings" |
|
||||
data-cy="settings-icon" |
|
||||
on:click={modal.show} |
|
||||
> |
|
||||
<Icon hoverable name="Settings" /> |
|
||||
</div> |
|
||||
<Modal bind:this={modal} width="600px"> |
|
||||
<SettingsModal /> |
|
||||
</Modal> |
|
||||
|
|
||||
<style> |
|
||||
.topnavitemright { |
|
||||
cursor: pointer; |
|
||||
color: var(--grey-7); |
|
||||
margin: 0 12px 0 0; |
|
||||
font-weight: 600; |
|
||||
font-size: 1rem; |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
height: 24px; |
|
||||
width: 24px; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,34 +0,0 @@ |
|||||
<script> |
|
||||
import { General, DangerZone } from "./tabs" |
|
||||
import { ModalContent, Tab, Tabs } from "@budibase/bbui" |
|
||||
</script> |
|
||||
|
|
||||
<ModalContent |
|
||||
title="Settings" |
|
||||
showConfirmButton={false} |
|
||||
showCancelButton={false} |
|
||||
> |
|
||||
<div class="container"> |
|
||||
<Tabs selected="General"> |
|
||||
<Tab title="General"> |
|
||||
<General /> |
|
||||
</Tab> |
|
||||
<!-- <Tab title="API Keys"> |
|
||||
<APIKeys /> |
|
||||
</Tab> --> |
|
||||
<Tab title="Danger Zone"> |
|
||||
<DangerZone /> |
|
||||
</Tab> |
|
||||
</Tabs> |
|
||||
</div> |
|
||||
</ModalContent> |
|
||||
|
|
||||
<style> |
|
||||
.container :global(section > header) { |
|
||||
/* Fix margin defined in BBUI as L rather than XL */ |
|
||||
margin-bottom: var(--spacing-xl); |
|
||||
} |
|
||||
.container :global(textarea) { |
|
||||
min-height: 60px; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,62 +0,0 @@ |
|||||
<script> |
|
||||
import { Input, Label, Link } from "@budibase/bbui" |
|
||||
import api from "builderStore/api" |
|
||||
import { notifications } from "@budibase/bbui" |
|
||||
import { database } from "stores/backend" |
|
||||
import analytics from "analytics" |
|
||||
|
|
||||
let keys = { budibase: "" } |
|
||||
|
|
||||
async function updateKey([key, value]) { |
|
||||
if (key === "budibase") { |
|
||||
const isValid = await analytics.identifyByApiKey(value) |
|
||||
if (!isValid) { |
|
||||
notifications.error("Your API Key is invalid.") |
|
||||
keys = { ...keys } |
|
||||
return |
|
||||
} |
|
||||
} |
|
||||
const response = await api.put(`/api/keys/${key}`, { value }) |
|
||||
const res = await response.json() |
|
||||
keys = { ...keys, ...res } |
|
||||
notifications.success("API Key saved.") |
|
||||
} |
|
||||
|
|
||||
// Get Keys |
|
||||
async function fetchKeys() { |
|
||||
const response = await api.get(`/api/keys/`) |
|
||||
const res = await response.json() |
|
||||
// dont want this to ever be editable, as its fetched based on Api Key |
|
||||
if (res.userId) delete res.userId |
|
||||
keys = res |
|
||||
} |
|
||||
|
|
||||
fetchKeys() |
|
||||
</script> |
|
||||
|
|
||||
<div class="container"> |
|
||||
<Input |
|
||||
on:change={e => updateKey(["budibase", e.detail])} |
|
||||
value={keys.budibase} |
|
||||
label="Budibase Cloud API Key" |
|
||||
/> |
|
||||
<Link primary href="https://portal.budi.live"> |
|
||||
Log in to the Budibase Hosting Portal to get your API Key. → |
|
||||
</Link> |
|
||||
<div> |
|
||||
<Label extraSmall grey>Instance ID (Webhooks)</Label> |
|
||||
<span>{$database._id}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.container { |
|
||||
display: grid; |
|
||||
grid-gap: var(--spacing-xl); |
|
||||
} |
|
||||
|
|
||||
span { |
|
||||
font-size: var(--font-size-xs); |
|
||||
font-weight: 600; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,56 +0,0 @@ |
|||||
<script> |
|
||||
import { params, goto } from "@roxi/routify" |
|
||||
import { Input, Button, Body } from "@budibase/bbui" |
|
||||
import { del } from "builderStore/api" |
|
||||
|
|
||||
let value = "" |
|
||||
let loading = false |
|
||||
|
|
||||
async function deleteApp() { |
|
||||
loading = true |
|
||||
const id = $params.application |
|
||||
await del(`/api/applications/${id}`) |
|
||||
loading = false |
|
||||
$goto("/builder") |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<div class="background"> |
|
||||
<Body> |
|
||||
Type |
|
||||
<b>DELETE</b> |
|
||||
into the textbox, then click the following button to delete your entire web app. |
|
||||
</Body> |
|
||||
<Input |
|
||||
on:change={e => (value = e.detail)} |
|
||||
disabled={loading} |
|
||||
placeholder="" |
|
||||
/> |
|
||||
<div class="buttons"> |
|
||||
<Button |
|
||||
warning |
|
||||
disabled={value !== "DELETE" || loading} |
|
||||
on:click={deleteApp} |
|
||||
> |
|
||||
Delete Entire App |
|
||||
</Button> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.background { |
|
||||
display: grid; |
|
||||
grid-gap: var(--spacing-xl); |
|
||||
} |
|
||||
.background :global(p) { |
|
||||
line-height: 1.2; |
|
||||
margin: 0; |
|
||||
} |
|
||||
|
|
||||
.buttons { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: flex-end; |
|
||||
align-items: center; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,97 +0,0 @@ |
|||||
<script> |
|
||||
import { Input, TextArea } from "@budibase/bbui" |
|
||||
import { store, hostingStore } from "builderStore" |
|
||||
import api from "builderStore/api" |
|
||||
import { object, string } from "yup" |
|
||||
import { onMount } from "svelte" |
|
||||
import { get } from "svelte/store" |
|
||||
|
|
||||
let nameValidation, nameError |
|
||||
let urlValidation, urlError |
|
||||
|
|
||||
$: checkName($store.name) |
|
||||
$: checkUrl($store.url) |
|
||||
|
|
||||
async function updateApplication(data) { |
|
||||
const response = await api.put(`/api/applications/${$store.appId}`, data) |
|
||||
await response.json() |
|
||||
store.update(state => { |
|
||||
state = { |
|
||||
...state, |
|
||||
...data, |
|
||||
} |
|
||||
return state |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
async function checkValidation(input, validation) { |
|
||||
if (!input || !validation) { |
|
||||
return |
|
||||
} |
|
||||
try { |
|
||||
await object(validation).validate(input, { abortEarly: false }) |
|
||||
} catch (error) { |
|
||||
if (!error || !error.inner) return "" |
|
||||
return error.inner.reduce((acc, err) => { |
|
||||
return acc + err.message |
|
||||
}, "") |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
async function checkName(name) { |
|
||||
nameError = await checkValidation({ name }, nameValidation) |
|
||||
} |
|
||||
|
|
||||
async function checkUrl(url) { |
|
||||
urlError = await checkValidation({ url: url.toLowerCase() }, urlValidation) |
|
||||
} |
|
||||
|
|
||||
onMount(async () => { |
|
||||
const nameError = "Your application must have a name.", |
|
||||
urlError = "Your application must have a URL." |
|
||||
await hostingStore.actions.fetchDeployedApps() |
|
||||
const existingAppNames = get(hostingStore).deployedAppNames |
|
||||
const existingAppUrls = get(hostingStore).deployedAppUrls |
|
||||
const nameIdx = existingAppNames.indexOf(get(store).name) |
|
||||
const urlIdx = existingAppUrls.indexOf(get(store).url) |
|
||||
if (nameIdx !== -1) { |
|
||||
existingAppNames.splice(nameIdx, 1) |
|
||||
} |
|
||||
if (urlIdx !== -1) { |
|
||||
existingAppUrls.splice(urlIdx, 1) |
|
||||
} |
|
||||
nameValidation = { |
|
||||
name: string().required(nameError).notOneOf(existingAppNames), |
|
||||
} |
|
||||
urlValidation = { |
|
||||
url: string().required(urlError).notOneOf(existingAppUrls), |
|
||||
} |
|
||||
}) |
|
||||
</script> |
|
||||
|
|
||||
<div class="container"> |
|
||||
<Input |
|
||||
on:change={e => updateApplication({ name: e.detail })} |
|
||||
value={$store.name} |
|
||||
error={nameError} |
|
||||
label="App Name" |
|
||||
/> |
|
||||
<Input |
|
||||
on:change={e => updateApplication({ url: e.detail })} |
|
||||
value={$store.url} |
|
||||
error={urlError} |
|
||||
label="App URL" |
|
||||
/> |
|
||||
<TextArea |
|
||||
on:change={e => updateApplication({ description: e.detail })} |
|
||||
value={$store.description} |
|
||||
label="App Description" |
|
||||
/> |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.container { |
|
||||
display: grid; |
|
||||
grid-gap: var(--spacing-xl); |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,40 +0,0 @@ |
|||||
<script> |
|
||||
import Integration from "../Integration.svelte" |
|
||||
</script> |
|
||||
|
|
||||
<div class="container"> |
|
||||
<div class="title">Your Integrations</div> |
|
||||
<div class="integrations"> |
|
||||
<Integration remove /> |
|
||||
<Integration remove /> |
|
||||
<Integration remove /> |
|
||||
<Integration remove /> |
|
||||
</div> |
|
||||
<div class="apps">Recommended apps</div> |
|
||||
<div class="integrations"> |
|
||||
<Integration /> |
|
||||
<Integration /> |
|
||||
<Integration /> |
|
||||
<Integration /> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<style> |
|
||||
.container { |
|
||||
display: grid; |
|
||||
grid-gap: 16px; |
|
||||
} |
|
||||
.integrations { |
|
||||
display: grid; |
|
||||
grid-template-columns: 1fr 1fr; |
|
||||
grid-gap: 20px; |
|
||||
} |
|
||||
.title { |
|
||||
font-size: 18px; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
.apps { |
|
||||
font-size: 14px; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1 +0,0 @@ |
|||||
Permissions |
|
||||
@ -1,5 +0,0 @@ |
|||||
export { default as General } from "./General.svelte" |
|
||||
export { default as Integrations } from "./Integrations.svelte" |
|
||||
export { default as Permissions } from "./Permissions.svelte" |
|
||||
export { default as APIKeys } from "./APIKeys.svelte" |
|
||||
export { default as DangerZone } from "./DangerZone.svelte" |
|
||||
@ -1,13 +1 @@ |
|||||
<script> |
|
||||
import { params } from "@roxi/routify" |
|
||||
import { queries } from "stores/backend" |
|
||||
|
|
||||
if ($params.query) { |
|
||||
const query = $queries.list.find(m => m._id === $params.query) |
|
||||
if (query) { |
|
||||
queries.select(query) |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<slot /> |
<slot /> |
||||
|
|||||
@ -0,0 +1,81 @@ |
|||||
|
<script> |
||||
|
import { Button, Heading, Body, Layout, Modal, Divider } from "@budibase/bbui" |
||||
|
import CreateTableModal from "components/backend/TableNavigator/modals/CreateTableModal.svelte" |
||||
|
import ICONS from "components/backend/DatasourceNavigator/icons" |
||||
|
import { tables } from "stores/backend" |
||||
|
import { goto } from "@roxi/routify" |
||||
|
|
||||
|
let modal |
||||
|
</script> |
||||
|
|
||||
|
<Modal bind:this={modal}> |
||||
|
<CreateTableModal /> |
||||
|
</Modal> |
||||
|
|
||||
|
<section> |
||||
|
<Layout> |
||||
|
<header> |
||||
|
<svelte:component this={ICONS.BUDIBASE} height="26" width="26" /> |
||||
|
<Heading size="M">Budibase Internal</Heading> |
||||
|
</header> |
||||
|
<Body size="S" grey lh |
||||
|
>Budibase internal tables are part of your app, the data will be stored in |
||||
|
your apps context.</Body |
||||
|
> |
||||
|
<Divider /> |
||||
|
<Heading size="S">Tables</Heading> |
||||
|
<div class="table-list"> |
||||
|
{#each $tables.list.filter(table => table.type !== "external") as table} |
||||
|
<div |
||||
|
class="table-list-item" |
||||
|
on:click={$goto(`../../table/${table._id}`)} |
||||
|
> |
||||
|
<Body size="S">{table.name}</Body> |
||||
|
{#if table.primaryDisplay} |
||||
|
<Body size="S">display column: {table.primaryDisplay}</Body> |
||||
|
{/if} |
||||
|
</div> |
||||
|
{/each} |
||||
|
</div> |
||||
|
<div> |
||||
|
<Button cta on:click={modal.show}>Create new table</Button> |
||||
|
</div> |
||||
|
</Layout> |
||||
|
</section> |
||||
|
|
||||
|
<style> |
||||
|
section { |
||||
|
margin: 0 auto; |
||||
|
width: 640px; |
||||
|
} |
||||
|
|
||||
|
header { |
||||
|
margin: 0 0 var(--spacing-xs) 0; |
||||
|
display: flex; |
||||
|
gap: var(--spacing-l); |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.table-list { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: var(--spacing-m); |
||||
|
} |
||||
|
|
||||
|
.table-list-item { |
||||
|
border-radius: var(--border-radius-m); |
||||
|
background: var(--background); |
||||
|
border: var(--border-dark); |
||||
|
display: grid; |
||||
|
grid-template-columns: 2fr 0.75fr 20px; |
||||
|
align-items: center; |
||||
|
padding: var(--spacing-m); |
||||
|
gap: var(--layout-xs); |
||||
|
transition: 200ms background ease; |
||||
|
} |
||||
|
|
||||
|
.table-list-item:hover { |
||||
|
background: var(--grey-1); |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,13 @@ |
|||||
|
<script> |
||||
|
import { params } from "@roxi/routify" |
||||
|
import { tables } from "stores/backend" |
||||
|
|
||||
|
if ($params.selectedTable) { |
||||
|
const table = $tables.list.find(m => m._id === $params.selectedTable) |
||||
|
if (table) { |
||||
|
tables.select(table) |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<slot /> |
||||
@ -0,0 +1,16 @@ |
|||||
|
<script> |
||||
|
import TableDataTable from "components/backend/DataTable/DataTable.svelte" |
||||
|
import { tables, database } from "stores/backend" |
||||
|
</script> |
||||
|
|
||||
|
{#if $database?._id && $tables?.selected?.name} |
||||
|
<TableDataTable /> |
||||
|
{:else}<i>Create your first table to start building</i>{/if} |
||||
|
|
||||
|
<style> |
||||
|
i { |
||||
|
font-size: var(--font-size-m); |
||||
|
color: var(--grey-5); |
||||
|
margin-top: 2px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,10 @@ |
|||||
|
<script> |
||||
|
import { params } from "@roxi/routify" |
||||
|
import RelationshipDataTable from "components/backend/DataTable/RelationshipDataTable.svelte" |
||||
|
</script> |
||||
|
|
||||
|
<RelationshipDataTable |
||||
|
tableId={$params.selectedTable} |
||||
|
rowId={$params.selectedRow} |
||||
|
fieldName={decodeURI($params.selectedField)} |
||||
|
/> |
||||
@ -0,0 +1,6 @@ |
|||||
|
<script> |
||||
|
import { goto } from "@roxi/routify" |
||||
|
$goto("../../") |
||||
|
</script> |
||||
|
|
||||
|
<!-- routify:options index=false --> |
||||
@ -0,0 +1,6 @@ |
|||||
|
<script> |
||||
|
import { goto } from "@roxi/routify" |
||||
|
$goto("../") |
||||
|
</script> |
||||
|
|
||||
|
<!-- routify:options index=false --> |
||||
@ -0,0 +1,19 @@ |
|||||
|
<script> |
||||
|
import { tables } from "stores/backend" |
||||
|
import { goto, leftover } from "@roxi/routify" |
||||
|
import { onMount } from "svelte" |
||||
|
|
||||
|
onMount(async () => { |
||||
|
// navigate to first table in list, if not already selected |
||||
|
// and this is the final url (i.e. no selectedTable) |
||||
|
if ( |
||||
|
!$leftover && |
||||
|
$tables.list.length > 0 |
||||
|
// (!$tables.selected || !$tables.selected._id) |
||||
|
) { |
||||
|
$goto(`./${$tables.list[0]._id}`) |
||||
|
} |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<slot /> |
||||
@ -0,0 +1,21 @@ |
|||||
|
<script> |
||||
|
import { goto } from "@roxi/routify" |
||||
|
import { onMount } from "svelte" |
||||
|
import { tables } from "stores/backend" |
||||
|
|
||||
|
onMount(async () => { |
||||
|
$tables.list.length > 0 && $goto(`./${$tables.list[0]._id}`) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
{#if $tables.list.length === 0} |
||||
|
<i>Create your first table to start building</i> |
||||
|
{:else}<i>Select a table to edit</i>{/if} |
||||
|
|
||||
|
<style> |
||||
|
i { |
||||
|
font-size: var(--font-size-m); |
||||
|
color: var(--grey-5); |
||||
|
margin-top: 2px; |
||||
|
} |
||||
|
</style> |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue