Merge pull request #1735 from Budibase/feature/layout-poc
Responsive layouts, responsive autoscreens, sections and navigation customisation
This commit is contained in:
commit
064690c85a
|
@ -63,9 +63,9 @@
|
|||
on:focus={() => (focus = true)}
|
||||
on:blur={() => (focus = false)}
|
||||
on:change={onChange}
|
||||
{value}
|
||||
value={value || ""}
|
||||
placeholder={placeholder || ""}
|
||||
{disabled}
|
||||
{placeholder}
|
||||
class="spectrum-Textfield-input spectrum-InputGroup-input"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -359,7 +359,7 @@
|
|||
background-color: var(--spectrum-alias-background-color-secondary);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
"posthog-js": "1.4.5",
|
||||
"remixicon": "2.5.0",
|
||||
"shortid": "2.2.15",
|
||||
"svelte-dnd-action": "^0.8.9",
|
||||
"svelte-dnd-action": "^0.9.8",
|
||||
"svelte-loading-spinners": "^0.1.1",
|
||||
"svelte-portal": "0.1.0",
|
||||
"uuid": "8.3.1",
|
||||
|
|
|
@ -333,7 +333,7 @@ const buildFormSchema = component => {
|
|||
*/
|
||||
export function removeBindings(obj) {
|
||||
for (let [key, value] of Object.entries(obj)) {
|
||||
if (typeof value === "object") {
|
||||
if (value && typeof value === "object") {
|
||||
obj[key] = removeBindings(value)
|
||||
} else if (typeof value === "string") {
|
||||
obj[key] = value.replace(CAPTURE_HBS_TEMPLATE, "Invalid binding")
|
||||
|
|
|
@ -305,7 +305,6 @@ export const getFrontendStore = () => {
|
|||
_id: uuid(),
|
||||
_component: definition.component,
|
||||
_styles: { normal: {}, hover: {}, active: {} },
|
||||
_transition: "",
|
||||
_instanceName: `New ${definition.name}`,
|
||||
...cloneDeep(props),
|
||||
...extras,
|
||||
|
@ -508,15 +507,6 @@ export const getFrontendStore = () => {
|
|||
selected._styles = { normal: {}, hover: {}, active: {} }
|
||||
await store.actions.preview.saveSelected()
|
||||
},
|
||||
updateTransition: async transition => {
|
||||
const selected = get(selectedComponent)
|
||||
if (transition == null || transition === "") {
|
||||
selected._transition = ""
|
||||
} else {
|
||||
selected._transition = transition
|
||||
}
|
||||
await store.actions.preview.saveSelected()
|
||||
},
|
||||
updateProp: async (name, value) => {
|
||||
let component = get(selectedComponent)
|
||||
if (!name || !component) {
|
||||
|
@ -536,37 +526,50 @@ export const getFrontendStore = () => {
|
|||
return
|
||||
}
|
||||
|
||||
// Find a nav bar in the main layout
|
||||
const nav = findComponentType(
|
||||
layout.props,
|
||||
"@budibase/standard-components/navigation"
|
||||
)
|
||||
if (!nav) {
|
||||
return
|
||||
}
|
||||
|
||||
let newLink
|
||||
if (nav._children && nav._children.length) {
|
||||
// Clone an existing link if one exists
|
||||
newLink = cloneDeep(nav._children[0])
|
||||
|
||||
// Set our new props
|
||||
newLink._id = uuid()
|
||||
newLink._instanceName = `${title} Link`
|
||||
newLink.url = url
|
||||
newLink.text = title
|
||||
} else {
|
||||
// Otherwise create vanilla new link
|
||||
newLink = {
|
||||
...store.actions.components.createInstance("link"),
|
||||
url,
|
||||
// Add link setting to main layout
|
||||
if (layout.props._component.endsWith("layout")) {
|
||||
// If using a new SDK, add to the layout component settings
|
||||
if (!layout.props.links) {
|
||||
layout.props.links = []
|
||||
}
|
||||
layout.props.links.push({
|
||||
text: title,
|
||||
_instanceName: `${title} Link`,
|
||||
url,
|
||||
})
|
||||
} else {
|
||||
// If using an old SDK, add to the navigation component
|
||||
// TODO: remove this when we can assume everyone has updated
|
||||
const nav = findComponentType(
|
||||
layout.props,
|
||||
"@budibase/standard-components/navigation"
|
||||
)
|
||||
if (!nav) {
|
||||
return
|
||||
}
|
||||
|
||||
let newLink
|
||||
if (nav._children && nav._children.length) {
|
||||
// Clone an existing link if one exists
|
||||
newLink = cloneDeep(nav._children[0])
|
||||
|
||||
// Set our new props
|
||||
newLink._id = uuid()
|
||||
newLink._instanceName = `${title} Link`
|
||||
newLink.url = url
|
||||
newLink.text = title
|
||||
} else {
|
||||
// Otherwise create vanilla new link
|
||||
newLink = {
|
||||
...store.actions.components.createInstance("link"),
|
||||
url,
|
||||
text: title,
|
||||
_instanceName: `${title} Link`,
|
||||
}
|
||||
nav._children = [...nav._children, newLink]
|
||||
}
|
||||
}
|
||||
|
||||
// Save layout
|
||||
nav._children = [...nav._children, newLink]
|
||||
await store.actions.layouts.save(layout)
|
||||
},
|
||||
},
|
||||
|
|
|
@ -128,7 +128,6 @@ const createScreen = table => {
|
|||
background: "white",
|
||||
"border-radius": "0.5rem",
|
||||
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
||||
"margin-top": "20px",
|
||||
"border-width": "2px",
|
||||
"border-color": "rgba(0, 0, 0, 0.1)",
|
||||
"border-style": "None",
|
||||
|
@ -136,7 +135,6 @@ const createScreen = table => {
|
|||
"padding-bottom": "48px",
|
||||
"padding-right": "48px",
|
||||
"padding-left": "48px",
|
||||
"margin-bottom": "20px",
|
||||
})
|
||||
.customProps({
|
||||
direction: "column",
|
||||
|
|
|
@ -14,7 +14,6 @@ export class Component extends BaseStructure {
|
|||
active: {},
|
||||
selected: {},
|
||||
},
|
||||
_transition: "",
|
||||
_instanceName: "",
|
||||
_children: [],
|
||||
}
|
||||
|
@ -40,11 +39,6 @@ export class Component extends BaseStructure {
|
|||
return this
|
||||
}
|
||||
|
||||
transition(transition) {
|
||||
this._json._transition = transition
|
||||
return this
|
||||
}
|
||||
|
||||
// Shorthand for custom props "type"
|
||||
type(type) {
|
||||
this._json.type = type
|
||||
|
|
|
@ -40,12 +40,10 @@ export function makeMainForm() {
|
|||
padding: "0px",
|
||||
"border-radius": "0.5rem",
|
||||
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
||||
"margin-top": "20px",
|
||||
"padding-top": "48px",
|
||||
"padding-bottom": "48px",
|
||||
"padding-right": "48px",
|
||||
"padding-left": "48px",
|
||||
"margin-bottom": "20px",
|
||||
})
|
||||
.instanceName("Form")
|
||||
}
|
||||
|
@ -58,6 +56,8 @@ export function makeBreadcrumbContainer(tableName, text, capitalise = false) {
|
|||
.normalStyle({
|
||||
"margin-right": "4px",
|
||||
"margin-left": "4px",
|
||||
"margin-top": "0px",
|
||||
"margin-bottom": "0px",
|
||||
})
|
||||
.customStyle(spectrumColor(700))
|
||||
.text(">")
|
||||
|
@ -65,6 +65,8 @@ export function makeBreadcrumbContainer(tableName, text, capitalise = false) {
|
|||
|
||||
const textStyling = {
|
||||
color: "#000000",
|
||||
"margin-top": "0px",
|
||||
"margin-bottom": "0px",
|
||||
}
|
||||
if (capitalise) {
|
||||
textStyling["text-transform"] = "capitalize"
|
||||
|
@ -140,10 +142,6 @@ export function makeTitleContainer(title) {
|
|||
const heading = new Component("@budibase/standard-components/heading")
|
||||
.normalStyle({
|
||||
margin: "0px",
|
||||
"margin-bottom": "0px",
|
||||
"margin-right": "0px",
|
||||
"margin-top": "0px",
|
||||
"margin-left": "0px",
|
||||
flex: "1 1 auto",
|
||||
})
|
||||
.customStyle(spectrumColor(900))
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
<script>
|
||||
import { ActionMenu, ActionButton, MenuItem, Icon } from "@budibase/bbui"
|
||||
import { store, currentAssetName } from "builderStore"
|
||||
import { store, currentAssetName, selectedComponent } from "builderStore"
|
||||
import structure from "./componentStructure.json"
|
||||
|
||||
$: enrichedStructure = enrichStructure(structure, $store.components)
|
||||
|
||||
const isChildAllowed = ({ name }, selectedComponent) => {
|
||||
const currentComponent = store.actions.components.getDefinition(
|
||||
selectedComponent?._component
|
||||
)
|
||||
return currentComponent?.illegalChildren?.includes(name.toLowerCase())
|
||||
}
|
||||
|
||||
const enrichStructure = (structure, definitions) => {
|
||||
let enrichedStructure = []
|
||||
structure.forEach(item => {
|
||||
|
@ -39,6 +46,7 @@
|
|||
<ActionMenu disabled={!item.isCategory}>
|
||||
<ActionButton
|
||||
icon={item.icon}
|
||||
disabled={isChildAllowed(item, $selectedComponent)}
|
||||
quiet
|
||||
size="S"
|
||||
slot="control"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[
|
||||
"section",
|
||||
"container",
|
||||
"dataprovider",
|
||||
"table",
|
||||
|
@ -61,8 +62,7 @@
|
|||
"name": "Other",
|
||||
"icon": "More",
|
||||
"children": [
|
||||
"screenslot",
|
||||
"navigation"
|
||||
"screenslot"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -12,16 +12,24 @@ export default `
|
|||
rel="stylesheet"
|
||||
/>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
html, body {
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
html {
|
||||
height: calc(100% - 16px);
|
||||
width: calc(100% - 16px);
|
||||
overflow: hidden;
|
||||
margin: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
body {
|
||||
padding: 2px;
|
||||
flex: 1 1 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
*,
|
||||
|
|
|
@ -10,11 +10,10 @@
|
|||
|
||||
$: screen = $allScreens.find(screen => screen._id === screenId)
|
||||
|
||||
const deleteScreen = () => {
|
||||
const deleteScreen = async () => {
|
||||
try {
|
||||
store.actions.screens.delete(screen)
|
||||
store.actions.routing.fetch()
|
||||
confirmDeleteDialog.hide()
|
||||
await store.actions.screens.delete(screen)
|
||||
await store.actions.routing.fetch()
|
||||
$goto("../")
|
||||
notifications.success("Deleted screen successfully.")
|
||||
} catch (err) {
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
if (routeError) return false
|
||||
|
||||
draftScreen.props._instanceName = name
|
||||
draftScreen.props._transition = "fade"
|
||||
draftScreen.props._component = baseComponent
|
||||
draftScreen.routing = { route, roleId }
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { TextArea, DetailSummary, Button, Select } from "@budibase/bbui"
|
||||
import { TextArea, DetailSummary, Button } from "@budibase/bbui"
|
||||
import PropertyGroup from "./PropertyControls/PropertyGroup.svelte"
|
||||
import FlatButtonGroup from "./PropertyControls/FlatButtonGroup"
|
||||
import { allStyles } from "./componentStyles"
|
||||
|
@ -8,7 +8,6 @@
|
|||
export let componentInstance = {}
|
||||
export let onStyleChanged = () => {}
|
||||
export let onCustomStyleChanged = () => {}
|
||||
export let onUpdateTransition = () => {}
|
||||
export let onResetStyles = () => {}
|
||||
|
||||
let selectedCategory = "normal"
|
||||
|
@ -24,16 +23,6 @@
|
|||
{ value: "active", text: "Active" },
|
||||
]
|
||||
|
||||
const transitions = [
|
||||
"none",
|
||||
"fade",
|
||||
"blur",
|
||||
"fly",
|
||||
"scale", // slide is hidden because it does not seem to result in any effect
|
||||
]
|
||||
|
||||
const capitalize = ([first, ...rest]) => first.toUpperCase() + rest.join("")
|
||||
|
||||
$: groups = componentDefinition?.styleable ? Object.keys(allStyles) : []
|
||||
</script>
|
||||
|
||||
|
@ -78,18 +67,6 @@
|
|||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if componentDefinition?.transitionable}
|
||||
<div class="transitions">
|
||||
<Select
|
||||
value={componentInstance._transition}
|
||||
on:change={event => onUpdateTransition(event.detail)}
|
||||
name="transition"
|
||||
label="Transition"
|
||||
options={transitions}
|
||||
getOptionLabel={capitalize}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { setWith } from "lodash"
|
||||
|
||||
$: definition = store.actions.components.getDefinition(
|
||||
$selectedComponent._component
|
||||
$selectedComponent?._component
|
||||
)
|
||||
$: isComponentOrScreen =
|
||||
$store.currentView === "component" ||
|
||||
|
@ -18,7 +18,6 @@
|
|||
|
||||
const onStyleChanged = store.actions.components.updateStyle
|
||||
const onCustomStyleChanged = store.actions.components.updateCustomStyle
|
||||
const onUpdateTransition = store.actions.components.updateTransition
|
||||
const onResetStyles = store.actions.components.resetStyles
|
||||
|
||||
function setAssetProps(name, value) {
|
||||
|
@ -64,7 +63,6 @@
|
|||
componentDefinition={definition}
|
||||
{onStyleChanged}
|
||||
{onCustomStyleChanged}
|
||||
{onUpdateTransition}
|
||||
{onResetStyles}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { Button, Drawer } from "@budibase/bbui"
|
||||
import { ActionButton, Button, Drawer } from "@budibase/bbui"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { notifications } from "@budibase/bbui"
|
||||
import EventEditor from "./EventEditor.svelte"
|
||||
|
@ -51,7 +51,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<Button secondary on:click={drawer.show}>Define Actions</Button>
|
||||
<ActionButton on:click={drawer.show}>Define Actions</ActionButton>
|
||||
<Drawer bind:this={drawer} title={"Actions"}>
|
||||
<svelte:fragment slot="description">
|
||||
Define what actions to run.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import {
|
||||
notifications,
|
||||
ActionButton,
|
||||
Button,
|
||||
Drawer,
|
||||
Body,
|
||||
|
@ -46,7 +47,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<Button secondary on:click={drawer.show}>Define Filters</Button>
|
||||
<ActionButton on:click={drawer.show}>Define Filters</ActionButton>
|
||||
<Drawer bind:this={drawer} title="Filtering">
|
||||
<Button cta slot="buttons" on:click={saveFilter}>Save</Button>
|
||||
<DrawerContent slot="body">
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</script>
|
||||
|
||||
<script>
|
||||
import { Popover, Button, Input } from "@budibase/bbui"
|
||||
import { Popover, ActionButton, Button, Input } from "@budibase/bbui"
|
||||
import { createEventDispatcher, tick } from "svelte"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
@ -117,7 +117,7 @@
|
|||
</script>
|
||||
|
||||
<div bind:this={buttonAnchor}>
|
||||
<Button secondary small on:click={dropdown.show}>{displayValue}</Button>
|
||||
<ActionButton on:click={dropdown.show}>{displayValue}</ActionButton>
|
||||
</div>
|
||||
<Popover bind:this={dropdown} on:open={setSelectedUI} anchor={buttonAnchor}>
|
||||
<div class="container">
|
||||
|
|
|
@ -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>
|
|
@ -15,6 +15,8 @@
|
|||
import FieldSelect from "./PropertyControls/FieldSelect.svelte"
|
||||
import MultiFieldSelect from "./PropertyControls/MultiFieldSelect.svelte"
|
||||
import SchemaSelect from "./PropertyControls/SchemaSelect.svelte"
|
||||
import SectionSelect from "./PropertyControls/SectionSelect.svelte"
|
||||
import NavigationEditor from "./PropertyControls/NavigationEditor/NavigationEditor.svelte"
|
||||
import EventsEditor from "./PropertyControls/EventsEditor"
|
||||
import FilterEditor from "./PropertyControls/FilterEditor/FilterEditor.svelte"
|
||||
import { IconSelect } from "./PropertyControls/IconSelect"
|
||||
|
@ -62,6 +64,8 @@
|
|||
field: FieldSelect,
|
||||
multifield: MultiFieldSelect,
|
||||
schema: SchemaSelect,
|
||||
section: SectionSelect,
|
||||
navigation: NavigationEditor,
|
||||
filter: FilterEditor,
|
||||
"field/string": StringFieldSelect,
|
||||
"field/number": NumberFieldSelect,
|
||||
|
|
|
@ -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"
|
|
@ -190,11 +190,10 @@
|
|||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
gap: var(--spacing-l);
|
||||
padding: var(--spacing-l) 40px var(--spacing-xl) 40px;
|
||||
gap: var(--spacing-m);
|
||||
padding: var(--spacing-xl) 40px;
|
||||
}
|
||||
.preview-content {
|
||||
box-shadow: 0 0 12px rgba(0, 0, 0, 0.05);
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -65,7 +65,9 @@
|
|||
>
|
||||
<Provider key="user" data={$authStore} {actions}>
|
||||
<div id="app-root">
|
||||
<Component instance={$screenStore.activeLayout.props} />
|
||||
{#key $screenStore.activeLayout._id}
|
||||
<Component instance={$screenStore.activeLayout.props} />
|
||||
{/key}
|
||||
</div>
|
||||
<NotificationDisplay />
|
||||
<!-- Key block needs to be outside the if statement or it breaks -->
|
||||
|
@ -95,8 +97,6 @@
|
|||
#app-root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
children: children.length,
|
||||
styles: { ...instance._styles, id, empty, interactive },
|
||||
empty,
|
||||
transition: instance._transition,
|
||||
selected,
|
||||
props: componentProps,
|
||||
name,
|
||||
|
|
|
@ -41,6 +41,5 @@
|
|||
<style>
|
||||
div {
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
// Vertically, always render above unless no room, then render inside
|
||||
let newTop = elBounds.top + scrollY - verticalOffset - height
|
||||
if (newTop < 0) {
|
||||
newTop = elBounds.top + scrollY + verticalOffset
|
||||
newTop = 0
|
||||
}
|
||||
|
||||
// Horizontally, try to center first.
|
||||
|
|
|
@ -7,7 +7,6 @@ import {
|
|||
builderStore,
|
||||
} from "./store"
|
||||
import { styleable } from "./utils/styleable"
|
||||
import transition from "./utils/transition"
|
||||
import { linkable } from "./utils/linkable"
|
||||
import { getAction } from "./utils/getAction"
|
||||
import Provider from "./components/Provider.svelte"
|
||||
|
@ -21,7 +20,6 @@ export default {
|
|||
screenStore,
|
||||
builderStore,
|
||||
styleable,
|
||||
transition,
|
||||
linkable,
|
||||
getAction,
|
||||
Provider,
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
import { fade, blur, scale, fly } from "svelte/transition"
|
||||
|
||||
// Default options
|
||||
const transitions = new Map([
|
||||
["fade", { tn: fade, opt: {} }],
|
||||
["blur", { tn: blur, opt: {} }],
|
||||
// This one seems to not result in any effect
|
||||
// ["slide", { tn: slide, opt: {} }],
|
||||
["scale", { tn: scale, opt: {} }],
|
||||
["fly", { tn: fly, opt: { y: 80 } }],
|
||||
])
|
||||
|
||||
export default function transition(node, { type, options = {} }) {
|
||||
const { tn, opt } = transitions.get(type) || { tn: () => {}, opt: {} }
|
||||
return tn(node, { ...opt, ...options })
|
||||
}
|
|
@ -28,10 +28,10 @@
|
|||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@budibase/bbui@^0.9.46":
|
||||
version "0.9.46"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.46.tgz#3109666b618daa65b29d1c7c45549420c62e6489"
|
||||
integrity sha512-PRW8kR9+QrMiom6hVzisMYd268dj03ojC0ruzEkDhKMONg2I021ST62hzKXdb7zh5LgoYXtapmM9qsKwoHfkPg==
|
||||
"@budibase/bbui@^0.9.47":
|
||||
version "0.9.47"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.47.tgz#d8664a05203432d522cd91a0bad1cdd8518baf93"
|
||||
integrity sha512-LXvJCgUSoc4EJKafBaKfUzU4GUOQGmts/8F4V6LTFtTyMZavgq2/KFAgPbR3QeYvidLsshtwop/pQfoszXTQnQ==
|
||||
dependencies:
|
||||
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
|
||||
"@spectrum-css/actionbutton" "^1.0.1"
|
||||
|
@ -108,12 +108,12 @@
|
|||
to-gfm-code-block "^0.1.1"
|
||||
year "^0.2.1"
|
||||
|
||||
"@budibase/standard-components@^0.9.46":
|
||||
version "0.9.46"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.46.tgz#a31a253ca51a2029c3aaf5d8aca5c953358e1d67"
|
||||
integrity sha512-QjW4tukMw4Xa477wGTle2UPz85ygodQ3KG+WEdPAWKq7j0IDv0Fad0oDmWtzLvGxxB+AiRbEnM6T1QV6X1ItCA==
|
||||
"@budibase/standard-components@^0.9.47":
|
||||
version "0.9.47"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.47.tgz#8e4f27c43b5a6f65d3d296c61f842195e297f061"
|
||||
integrity sha512-0+Ndg67Jgk7cqOYluGKpixNFvEqvy2oguKLEr1l83Sf0oWTQ3RCmUGs2mU66ljwnE+o4/JN/EdkA2uSqKInQtg==
|
||||
dependencies:
|
||||
"@budibase/bbui" "^0.9.46"
|
||||
"@budibase/bbui" "^0.9.47"
|
||||
"@spectrum-css/page" "^3.0.1"
|
||||
"@spectrum-css/vars" "^3.0.1"
|
||||
apexcharts "^3.22.1"
|
||||
|
@ -121,10 +121,10 @@
|
|||
svelte-apexcharts "^1.0.2"
|
||||
svelte-flatpickr "^3.1.0"
|
||||
|
||||
"@budibase/string-templates@^0.9.46":
|
||||
version "0.9.46"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.46.tgz#e43f87513977879a892ae52f3941d3320cb9ff88"
|
||||
integrity sha512-yOVS7Y/QLATj31QuBu8KP78Oyzhs60V09JEQKa7n4vRP8TBemcev/LFShln8Iiv70YZSpdJviguQuJ6Ow0aUNA==
|
||||
"@budibase/string-templates@^0.9.47":
|
||||
version "0.9.47"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.47.tgz#484ce5ce29a6ddaef3480368b1a24ce8c3852324"
|
||||
integrity sha512-I16Ps4AW7VW8MrSdsoZdwLutiX7GhRkiH6m1AdFcmzh2mZI6YyFM000PuKGEt+sREXK2NI6cBzmi9ZpKIAPJJw==
|
||||
dependencies:
|
||||
"@budibase/handlebars-helpers" "^0.11.4"
|
||||
dayjs "^1.10.4"
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
const { EMPTY_LAYOUT } = require("../../constants/layouts")
|
||||
const {
|
||||
EMPTY_LAYOUT,
|
||||
BASE_LAYOUT_PROP_IDS,
|
||||
} = require("../../constants/layouts")
|
||||
const CouchDB = require("../../db")
|
||||
const { generateLayoutID, getScreenParams } = require("../../db/utils")
|
||||
|
||||
|
@ -26,15 +29,19 @@ exports.destroy = async function (ctx) {
|
|||
const layoutId = ctx.params.layoutId,
|
||||
layoutRev = ctx.params.layoutRev
|
||||
|
||||
const layoutsUsedByScreens = (
|
||||
await db.allDocs(
|
||||
getScreenParams(null, {
|
||||
include_docs: true,
|
||||
})
|
||||
)
|
||||
).rows.map(element => element.doc.layoutId)
|
||||
if (layoutsUsedByScreens.includes(layoutId)) {
|
||||
ctx.throw(400, "Cannot delete a layout that's being used by a screen")
|
||||
if (Object.values(BASE_LAYOUT_PROP_IDS).includes(layoutId)) {
|
||||
ctx.throw(400, "Cannot delete a built-in layout")
|
||||
} else {
|
||||
const layoutsUsedByScreens = (
|
||||
await db.allDocs(
|
||||
getScreenParams(null, {
|
||||
include_docs: true,
|
||||
})
|
||||
)
|
||||
).rows.map(element => element.doc.layoutId)
|
||||
if (layoutsUsedByScreens.includes(layoutId)) {
|
||||
ctx.throw(400, "Cannot delete a layout that's being used by a screen")
|
||||
}
|
||||
}
|
||||
|
||||
await db.remove(layoutId, layoutRev)
|
||||
|
|
|
@ -10,7 +10,7 @@ const EMPTY_LAYOUT = {
|
|||
stylesheets: [],
|
||||
props: {
|
||||
_id: "30b8822a-d07b-49f4-9531-551e37c6899b",
|
||||
_component: "@budibase/standard-components/container",
|
||||
_component: "@budibase/standard-components/layout",
|
||||
_children: [
|
||||
{
|
||||
_id: "7fcf11e4-6f5b-4085-8e0d-9f3d44c98967",
|
||||
|
@ -22,9 +22,6 @@ const EMPTY_LAYOUT = {
|
|||
"flex-direction": "column",
|
||||
"justify-content": "flex-start",
|
||||
"align-items": "stretch",
|
||||
"max-width": "100%",
|
||||
width: "1400px",
|
||||
padding: "20px",
|
||||
},
|
||||
hover: {},
|
||||
active: {},
|
||||
|
@ -36,16 +33,17 @@ const EMPTY_LAYOUT = {
|
|||
_styles: {
|
||||
active: {},
|
||||
hover: {},
|
||||
normal: {
|
||||
"min-height": "100%",
|
||||
"background-image": "#f5f5f5",
|
||||
},
|
||||
normal: {},
|
||||
selected: {},
|
||||
},
|
||||
direction: "column",
|
||||
hAlign: "center",
|
||||
vAlign: "top",
|
||||
size: "grow",
|
||||
navigation: "Top",
|
||||
width: "Large",
|
||||
links: [
|
||||
{
|
||||
text: "Home",
|
||||
url: "/",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -56,83 +54,11 @@ const BASE_LAYOUTS = [
|
|||
title: "{{ name }}",
|
||||
favicon: "./_shared/favicon.png",
|
||||
stylesheets: [],
|
||||
name: "Top Navigation Layout",
|
||||
name: "Navigation Layout",
|
||||
props: {
|
||||
_id: "4f569166-a4f3-47ea-a09e-6d218c75586f",
|
||||
_component: "@budibase/standard-components/container",
|
||||
_component: "@budibase/standard-components/layout",
|
||||
_children: [
|
||||
{
|
||||
_id: "c74f07266980c4b6eafc33e2a6caa783d",
|
||||
_component: "@budibase/standard-components/container",
|
||||
_styles: {
|
||||
normal: {
|
||||
background: "#fff",
|
||||
width: "100%",
|
||||
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
||||
},
|
||||
hover: {},
|
||||
active: {},
|
||||
selected: {},
|
||||
},
|
||||
_instanceName: "Header",
|
||||
_children: [
|
||||
{
|
||||
_id: "49e0e519-9e5e-4127-885a-ee6a0a49e2c1",
|
||||
_component: "@budibase/standard-components/navigation",
|
||||
_styles: {
|
||||
normal: {
|
||||
"max-width": "1400px",
|
||||
padding: "20px",
|
||||
"font-weight": "400",
|
||||
"font-size": "16px",
|
||||
flex: "1 1 auto",
|
||||
},
|
||||
hover: {},
|
||||
active: {},
|
||||
selected: {},
|
||||
},
|
||||
title: "",
|
||||
backgroundColor: "",
|
||||
color: "",
|
||||
borderWidth: "",
|
||||
borderColor: "",
|
||||
borderStyle: "",
|
||||
_instanceName: "Navigation",
|
||||
_children: [
|
||||
{
|
||||
_id: "48b35328-4c91-4343-a6a3-1a1fd77b3386",
|
||||
_component: "@budibase/standard-components/link",
|
||||
_styles: {
|
||||
normal: {
|
||||
"font-weight": "600",
|
||||
"text-decoration-line": "none",
|
||||
"font-size": "16px",
|
||||
},
|
||||
hover: {
|
||||
color: "#4285f4",
|
||||
},
|
||||
active: {},
|
||||
selected: {},
|
||||
},
|
||||
url: "/",
|
||||
openInNewTab: false,
|
||||
text: "Home",
|
||||
color: "",
|
||||
hoverColor: "",
|
||||
underline: false,
|
||||
fontSize: "",
|
||||
fontFamily: "initial",
|
||||
_instanceName: "Home Link",
|
||||
_children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
direction: "row",
|
||||
hAlign: "center",
|
||||
vAlign: "middle",
|
||||
size: "shrink",
|
||||
},
|
||||
{
|
||||
_id: "7fcf11e4-6f5b-4085-8e0d-9f3d44c98967",
|
||||
_component: "@budibase/standard-components/screenslot",
|
||||
|
@ -143,9 +69,6 @@ const BASE_LAYOUTS = [
|
|||
"flex-direction": "column",
|
||||
"justify-content": "flex-start",
|
||||
"align-items": "stretch",
|
||||
"max-width": "100%",
|
||||
width: "1400px",
|
||||
padding: "20px",
|
||||
},
|
||||
hover: {},
|
||||
active: {},
|
||||
|
@ -157,16 +80,17 @@ const BASE_LAYOUTS = [
|
|||
_styles: {
|
||||
active: {},
|
||||
hover: {},
|
||||
normal: {
|
||||
"min-height": "100%",
|
||||
background: "#f5f5f5",
|
||||
},
|
||||
normal: {},
|
||||
selected: {},
|
||||
},
|
||||
direction: "column",
|
||||
hAlign: "center",
|
||||
vAlign: "top",
|
||||
size: "grow",
|
||||
navigation: "Top",
|
||||
width: "Large",
|
||||
links: [
|
||||
{
|
||||
text: "Home",
|
||||
url: "/",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -178,7 +102,7 @@ const BASE_LAYOUTS = [
|
|||
name: "Empty Layout",
|
||||
props: {
|
||||
_id: "3723ffa1-f9e0-4c05-8013-98195c788ed6",
|
||||
_component: "@budibase/standard-components/container",
|
||||
_component: "@budibase/standard-components/layout",
|
||||
_children: [
|
||||
{
|
||||
_id: "7fcf11e4-6f5b-4085-8e0d-9f3d44c98967",
|
||||
|
@ -190,9 +114,6 @@ const BASE_LAYOUTS = [
|
|||
"flex-direction": "column",
|
||||
"justify-content": "flex-start",
|
||||
"align-items": "stretch",
|
||||
"max-width": "100%",
|
||||
width: "1400px",
|
||||
padding: "20px",
|
||||
},
|
||||
hover: {},
|
||||
active: {},
|
||||
|
@ -204,16 +125,17 @@ const BASE_LAYOUTS = [
|
|||
_styles: {
|
||||
active: {},
|
||||
hover: {},
|
||||
normal: {
|
||||
"min-height": "100%",
|
||||
background: "#f5f5f5",
|
||||
},
|
||||
normal: {},
|
||||
selected: {},
|
||||
},
|
||||
direction: "column",
|
||||
hAlign: "center",
|
||||
vAlign: "top",
|
||||
size: "grow",
|
||||
navigation: "Top",
|
||||
width: "Large",
|
||||
links: [
|
||||
{
|
||||
text: "Home",
|
||||
url: "/",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
|
|
@ -930,10 +930,10 @@
|
|||
"@babel/helper-validator-identifier" "^7.14.0"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@budibase/auth@^0.9.39":
|
||||
version "0.9.39"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.39.tgz#8a890b4713aea23a96076578aead702453fadd76"
|
||||
integrity sha512-+3zPSD4DF6E5ZNjpod5JMehcvjREepgISgw603kVQOksuX/cJItj0+EOHbK/P++4DYFr1dVgc0K3aylbCpxfjA==
|
||||
"@budibase/auth@^0.9.47":
|
||||
version "0.9.47"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.47.tgz#d0518f6bb7b29780799eee4574a0354ce9c07065"
|
||||
integrity sha512-H2fbhVIZ4zwvN4XD3JcqhhwmxuAuL23Cssld7S8qNXYHNj84NdjPYVuGHQPzZudT9htiOKtOgpLkRzSWXUyxjw==
|
||||
dependencies:
|
||||
aws-sdk "^2.901.0"
|
||||
bcryptjs "^2.4.3"
|
||||
|
@ -951,10 +951,10 @@
|
|||
uuid "^8.3.2"
|
||||
zlib "^1.0.5"
|
||||
|
||||
"@budibase/bbui@^0.9.39":
|
||||
version "0.9.39"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.39.tgz#3bccaa86ed7ae02f67661dadc57becd3db5ca9b6"
|
||||
integrity sha512-5cPMFOGBOpvu3fMWLGBvgVpw+O8gvUh2g6xgWTZi2bCAgtXej+ryL0s7Xs4/mmoS2Y4z5ggc+wE4mOtCM9eFUQ==
|
||||
"@budibase/bbui@^0.9.47":
|
||||
version "0.9.47"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.47.tgz#d8664a05203432d522cd91a0bad1cdd8518baf93"
|
||||
integrity sha512-LXvJCgUSoc4EJKafBaKfUzU4GUOQGmts/8F4V6LTFtTyMZavgq2/KFAgPbR3QeYvidLsshtwop/pQfoszXTQnQ==
|
||||
dependencies:
|
||||
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
|
||||
"@spectrum-css/actionbutton" "^1.0.1"
|
||||
|
@ -999,20 +999,22 @@
|
|||
svelte-flatpickr "^3.1.0"
|
||||
svelte-portal "^1.0.0"
|
||||
|
||||
"@budibase/client@^0.9.39":
|
||||
version "0.9.39"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.39.tgz#5916ab01f11a9f1835ccac57fffdaa63265704e4"
|
||||
integrity sha512-1+teUP/OFZZT1j3wPu7+oXO6Htuhc938aOyI8Le13hkS9r4RuZBmnzI6QeZ4oVOWgwhxn9pczxcbeW4U3Upa0w==
|
||||
"@budibase/client@^0.9.47":
|
||||
version "0.9.47"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.47.tgz#d0871246f69ebe2d9b8a3ab7663d1e687a81a323"
|
||||
integrity sha512-RhN8lDavcPnSdlHpFIfjKeuiWi7Y+0YhIQMcXav5p7SgOAsJde+Bq1ubZLgKCEl7OMTMrdHO/b7mHj9naXuyTA==
|
||||
dependencies:
|
||||
"@budibase/string-templates" "^0.9.39"
|
||||
"@budibase/bbui" "^0.9.47"
|
||||
"@budibase/standard-components" "^0.9.47"
|
||||
"@budibase/string-templates" "^0.9.47"
|
||||
regexparam "^1.3.0"
|
||||
shortid "^2.2.15"
|
||||
svelte-spa-router "^3.0.5"
|
||||
|
||||
"@budibase/handlebars-helpers@^0.11.3":
|
||||
version "0.11.3"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.11.3.tgz#b6e5c91b83e8906e7d7ff10ddde277a3d561016e"
|
||||
integrity sha512-MS1ptZEYq8o9J3tNLM7cZ2RGSSJIer4GiMIUHtbBI3sC9UKqZebao1JYNfmZKpNjntuqhZKgjqc5GfnVIEjsYQ==
|
||||
"@budibase/handlebars-helpers@^0.11.4":
|
||||
version "0.11.4"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.11.4.tgz#8acfa2ee84134f7be4b2906e710fce6d25c5d000"
|
||||
integrity sha512-AJNJYlJnxZmn9QJ8tBl8nrm4YxbwHP4AR0pbiVGK+EoOylkNBlUnZ/QDL1VyqM5fTkAE/Z2IZVLKrrG3kxuWLA==
|
||||
dependencies:
|
||||
arr-flatten "^1.1.0"
|
||||
array-sort "^0.1.4"
|
||||
|
@ -1041,12 +1043,12 @@
|
|||
to-gfm-code-block "^0.1.1"
|
||||
year "^0.2.1"
|
||||
|
||||
"@budibase/standard-components@^0.9.39":
|
||||
version "0.9.39"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.39.tgz#69807bb5f91c4ef367878ee042a625a6a578ca8e"
|
||||
integrity sha512-6iuPMsYQSgVOuDq20oIeBkTHlWMB9CPNAQiteZSrAZfLxcSpHx/6ArTA0unxE6n2OwxBwCfxIU+nsWTmQmlFtA==
|
||||
"@budibase/standard-components@^0.9.47":
|
||||
version "0.9.47"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.47.tgz#8e4f27c43b5a6f65d3d296c61f842195e297f061"
|
||||
integrity sha512-0+Ndg67Jgk7cqOYluGKpixNFvEqvy2oguKLEr1l83Sf0oWTQ3RCmUGs2mU66ljwnE+o4/JN/EdkA2uSqKInQtg==
|
||||
dependencies:
|
||||
"@budibase/bbui" "^0.9.39"
|
||||
"@budibase/bbui" "^0.9.47"
|
||||
"@spectrum-css/page" "^3.0.1"
|
||||
"@spectrum-css/vars" "^3.0.1"
|
||||
apexcharts "^3.22.1"
|
||||
|
@ -1054,12 +1056,12 @@
|
|||
svelte-apexcharts "^1.0.2"
|
||||
svelte-flatpickr "^3.1.0"
|
||||
|
||||
"@budibase/string-templates@^0.9.39":
|
||||
version "0.9.39"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.39.tgz#25c7a0fd2ad72b109116a3de76563860ed9f0fd6"
|
||||
integrity sha512-DS7V01uerBoEAmgoQq6lOwJD1w3i5UQ30wtCPoZBj0Bz8NsKbhWEMyjTU2PrtOelBMjksAMdwyBHsxzJAuSn+Q==
|
||||
"@budibase/string-templates@^0.9.47":
|
||||
version "0.9.47"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.47.tgz#484ce5ce29a6ddaef3480368b1a24ce8c3852324"
|
||||
integrity sha512-I16Ps4AW7VW8MrSdsoZdwLutiX7GhRkiH6m1AdFcmzh2mZI6YyFM000PuKGEt+sREXK2NI6cBzmi9ZpKIAPJJw==
|
||||
dependencies:
|
||||
"@budibase/handlebars-helpers" "^0.11.3"
|
||||
"@budibase/handlebars-helpers" "^0.11.4"
|
||||
dayjs "^1.10.4"
|
||||
handlebars "^4.7.6"
|
||||
handlebars-utils "^1.0.6"
|
||||
|
|
|
@ -1,11 +1,67 @@
|
|||
{
|
||||
"layout": {
|
||||
"name": "Layout",
|
||||
"description": "This component is specific only to layouts",
|
||||
"icon": "Sandbox",
|
||||
"hasChildren": true,
|
||||
"styleable": true,
|
||||
"illegalChildren": [],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
"label": "Logo URL",
|
||||
"key": "logoUrl"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"label": "Title",
|
||||
"key": "title"
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Navigation",
|
||||
"key": "navigation",
|
||||
"options": ["Top", "Left", "None"],
|
||||
"defaultValue": "Top"
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Width",
|
||||
"key": "width",
|
||||
"options": ["Small", "Medium", "Large"],
|
||||
"defaultValue": "Large"
|
||||
},
|
||||
{
|
||||
"type": "navigation",
|
||||
"label": "Links",
|
||||
"key": "links"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Hide title",
|
||||
"key": "hideTitle",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Hide logo",
|
||||
"key": "hideLogo",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Sticky header",
|
||||
"key": "sticky",
|
||||
"defaultValue": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"container": {
|
||||
"name": "Container",
|
||||
"description": "This component contains things within itself",
|
||||
"icon": "Sandbox",
|
||||
"hasChildren": true,
|
||||
"styleable": true,
|
||||
"transitionable": true,
|
||||
"showSettingsBar": true,
|
||||
"settings": [
|
||||
{
|
||||
|
@ -118,6 +174,23 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"section": {
|
||||
"name": "Section",
|
||||
"description": "Add a section to your application",
|
||||
"icon": "ColumnTwoB",
|
||||
"hasChildren": true,
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"showEmptyState": false,
|
||||
"settings": [
|
||||
{
|
||||
"type": "section",
|
||||
"label": "Type",
|
||||
"key": "type",
|
||||
"defaultValue": "mainSidebar"
|
||||
}
|
||||
]
|
||||
},
|
||||
"screenslot": {
|
||||
"name": "Screenslot",
|
||||
"icon": "WebPage",
|
||||
|
@ -128,6 +201,7 @@
|
|||
"name": "Button",
|
||||
"description": "A basic html button that is ready for styling",
|
||||
"icon": "Button",
|
||||
"illegalChildren": ["section"],
|
||||
"styleable": true,
|
||||
"settings": [
|
||||
{
|
||||
|
@ -135,15 +209,15 @@
|
|||
"label": "Text",
|
||||
"key": "text"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Disabled",
|
||||
"key": "disabled"
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"label": "On Click",
|
||||
"key": "onClick"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Disabled",
|
||||
"key": "disabled"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -152,6 +226,7 @@
|
|||
"description": "A configurable data list that attaches to your backend tables.",
|
||||
"icon": "ViewList",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"hasChildren": true,
|
||||
"settings": [
|
||||
{
|
||||
|
@ -180,6 +255,7 @@
|
|||
"icon": "TaskList",
|
||||
"description": "A basic card component that can contain content and actions.",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -209,6 +285,7 @@
|
|||
"description": "A basic card component that can contain content and actions.",
|
||||
"icon": "ViewColumn",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -269,6 +346,7 @@
|
|||
"description": "A component for displaying paragraph text.",
|
||||
"icon": "TextParagraph",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -282,6 +360,7 @@
|
|||
"icon": "TextBold",
|
||||
"description": "A component for displaying heading text",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -302,6 +381,7 @@
|
|||
"description": "A basic component for displaying images",
|
||||
"icon": "Image",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -315,6 +395,7 @@
|
|||
"description": "A background image",
|
||||
"icon": "Images",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -372,6 +453,7 @@
|
|||
"description": "A basic component for displaying icons",
|
||||
"icon": "Bell",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "icon",
|
||||
|
@ -419,6 +501,7 @@
|
|||
"description": "A component for handling the navigation within your app.",
|
||||
"icon": "BreadcrumbNavigation",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"hasChildren": true,
|
||||
"settings": [
|
||||
{
|
||||
|
@ -439,6 +522,7 @@
|
|||
"description": "A basic link component for internal and external links",
|
||||
"icon": "Link",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -468,6 +552,7 @@
|
|||
"description": "A basic card component that can contain content and actions.",
|
||||
"icon": "ViewRow",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -540,6 +625,7 @@
|
|||
"description": "A card component for displaying numbers.",
|
||||
"icon": "Card",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -566,6 +652,7 @@
|
|||
"icon": "Code",
|
||||
"description": "Embed content from 3rd party sources",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -579,6 +666,7 @@
|
|||
"description": "Bar chart",
|
||||
"icon": "GraphBarVertical",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -679,6 +767,7 @@
|
|||
"description": "Line chart",
|
||||
"icon": "GraphTrend",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -780,6 +869,7 @@
|
|||
"description": "Line chart",
|
||||
"icon": "GraphAreaStacked",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -893,6 +983,7 @@
|
|||
"description": "Pie chart",
|
||||
"icon": "GraphPie",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -970,6 +1061,7 @@
|
|||
"description": "Donut chart",
|
||||
"icon": "GraphDonut",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -1047,6 +1139,7 @@
|
|||
"description": "Candlestick chart",
|
||||
"icon": "GraphBarVerticalStacked",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -1129,6 +1222,7 @@
|
|||
"icon": "Form",
|
||||
"styleable": true,
|
||||
"hasChildren": true,
|
||||
"illegalChildren": ["section"],
|
||||
"actions": [
|
||||
"ValidateForm"
|
||||
],
|
||||
|
@ -1200,6 +1294,7 @@
|
|||
"name": "Field Group",
|
||||
"icon": "Group",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"hasChildren": true,
|
||||
"settings": [
|
||||
{
|
||||
|
@ -1228,6 +1323,7 @@
|
|||
"name": "Text Field",
|
||||
"icon": "Text",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "field/string",
|
||||
|
@ -1256,6 +1352,7 @@
|
|||
"name": "Number Field",
|
||||
"icon": "123",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "field/number",
|
||||
|
@ -1284,6 +1381,7 @@
|
|||
"name": "Password Field",
|
||||
"icon": "LockClosed",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "field/string",
|
||||
|
@ -1312,6 +1410,7 @@
|
|||
"name": "Options Picker",
|
||||
"icon": "ViewList",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "field/options",
|
||||
|
@ -1341,6 +1440,7 @@
|
|||
"name": "Checkbox",
|
||||
"icon": "Checkmark",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "field/boolean",
|
||||
|
@ -1369,6 +1469,7 @@
|
|||
"name": "Rich Text",
|
||||
"icon": "TextParagraph",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "field/longform",
|
||||
|
@ -1398,6 +1499,7 @@
|
|||
"name": "Date Picker",
|
||||
"icon": "DateInput",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "field/datetime",
|
||||
|
@ -1432,6 +1534,7 @@
|
|||
"name": "Attachment",
|
||||
"icon": "Attach",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "field/attachment",
|
||||
|
@ -1455,6 +1558,7 @@
|
|||
"name": "Relationship Picker",
|
||||
"icon": "TaskList",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "field/link",
|
||||
|
@ -1484,6 +1588,7 @@
|
|||
"info": "Pagination is only available for data stored in internal tables.",
|
||||
"icon": "Data",
|
||||
"styleable": false,
|
||||
"illegalChildren": ["section"],
|
||||
"hasChildren": true,
|
||||
"settings": [
|
||||
{
|
||||
|
@ -1547,6 +1652,7 @@
|
|||
"name": "Table",
|
||||
"icon": "Table",
|
||||
"styleable": true,
|
||||
"illegalChildren": ["section"],
|
||||
"hasChildren": true,
|
||||
"showEmptyState": false,
|
||||
"settings": [
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
"license": "MIT",
|
||||
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc",
|
||||
"dependencies": {
|
||||
"@spectrum-css/link": "^3.1.3",
|
||||
"@budibase/bbui": "^0.9.51",
|
||||
"@spectrum-css/page": "^3.0.1",
|
||||
"@spectrum-css/vars": "^3.0.1",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import { getContext } from "svelte"
|
||||
|
||||
const { styleable, transition } = getContext("sdk")
|
||||
const { styleable } = getContext("sdk")
|
||||
const component = getContext("component")
|
||||
|
||||
export let direction
|
||||
|
@ -17,7 +17,6 @@
|
|||
|
||||
<div
|
||||
class={[directionClass, hAlignClass, vAlignClass, sizeClass].join(" ")}
|
||||
in:transition={{ type: $component.transition }}
|
||||
use:styleable={$component.styles}
|
||||
>
|
||||
<slot />
|
||||
|
|
|
@ -0,0 +1,337 @@
|
|||
<script>
|
||||
import { getContext } from "svelte"
|
||||
import { Heading, Icon } from "@budibase/bbui"
|
||||
|
||||
const { styleable, linkable } = getContext("sdk")
|
||||
const component = getContext("component")
|
||||
|
||||
export let title
|
||||
export let hideTitle = false
|
||||
export let logoUrl
|
||||
export let hideLogo = false
|
||||
export let navigation = "Top"
|
||||
export let sticky = false
|
||||
export let links
|
||||
export let width = "Large"
|
||||
|
||||
const navigationClasses = {
|
||||
Top: "top",
|
||||
Left: "left",
|
||||
None: "none",
|
||||
}
|
||||
const widthClasses = {
|
||||
Large: "l",
|
||||
Medium: "m",
|
||||
Small: "s",
|
||||
}
|
||||
|
||||
$: validLinks = links?.filter(link => link.text && link.url) || []
|
||||
$: typeClass = navigationClasses[navigation] || "none"
|
||||
$: widthClass = widthClasses[width] || "l"
|
||||
let mobileOpen = false
|
||||
|
||||
const isInternal = url => {
|
||||
return url.startsWith("/")
|
||||
}
|
||||
|
||||
const ensureExternal = url => {
|
||||
return !url.startsWith("http") ? `http://${url}` : url
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
mobileOpen = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="layout layout--{typeClass}" use:styleable={$component.styles}>
|
||||
{#if typeClass !== "none"}
|
||||
<div class="nav-wrapper" class:sticky>
|
||||
<div class="nav nav--{typeClass} size--{widthClass}">
|
||||
<div class="nav-header">
|
||||
{#if validLinks?.length}
|
||||
<div class="burger">
|
||||
<Icon
|
||||
hoverable
|
||||
name="ShowMenu"
|
||||
on:click={() => (mobileOpen = !mobileOpen)}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="logo">
|
||||
{#if !hideLogo}
|
||||
<img
|
||||
src={logoUrl || "https://i.imgur.com/Xhdt1YP.png"}
|
||||
alt={title}
|
||||
/>
|
||||
{/if}
|
||||
{#if !hideTitle && title}
|
||||
<Heading size="S">{title}</Heading>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="portal">
|
||||
<Icon
|
||||
hoverable
|
||||
name="Apps"
|
||||
on:click={() => (window.location.href = "/builder/apps")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mobile-click-handler"
|
||||
class:visible={mobileOpen}
|
||||
on:click={() => (mobileOpen = false)}
|
||||
/>
|
||||
{#if validLinks?.length}
|
||||
<div class="links" class:visible={mobileOpen}>
|
||||
{#each validLinks as { text, url }}
|
||||
{#if isInternal(url)}
|
||||
<a class="link" href={url} use:linkable on:click={close}>
|
||||
{text}
|
||||
</a>
|
||||
{:else}
|
||||
<a class="link" href={ensureExternal(url)} on:click={close}>
|
||||
{text}
|
||||
</a>
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="close">
|
||||
<Icon
|
||||
hoverable
|
||||
name="Close"
|
||||
on:click={() => (mobileOpen = false)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="main-wrapper">
|
||||
<div class="main size--{widthClass}">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Main components */
|
||||
.layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
background: white;
|
||||
z-index: 1;
|
||||
box-shadow: 0 0 8px -1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.layout--top .nav-wrapper.sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
padding: var(--spacing-xl) 32px;
|
||||
max-width: 100%;
|
||||
gap: var(--spacing-xl);
|
||||
}
|
||||
.nav-header {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: var(--spacing-xl);
|
||||
}
|
||||
.main-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
padding: 32px;
|
||||
}
|
||||
.size--s {
|
||||
width: 800px;
|
||||
}
|
||||
.size--m {
|
||||
width: 1100px;
|
||||
}
|
||||
.size--l {
|
||||
width: 1400px;
|
||||
}
|
||||
|
||||
/* Nav components */
|
||||
.burger {
|
||||
display: none;
|
||||
}
|
||||
.logo {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
gap: var(--spacing-m);
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.logo img {
|
||||
height: 36px;
|
||||
}
|
||||
.logo :global(h1) {
|
||||
font-weight: 600;
|
||||
flex: 1 1 auto;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.portal {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
.links {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
gap: var(--spacing-xl);
|
||||
margin-top: var(--spacing-xl);
|
||||
}
|
||||
.link {
|
||||
color: var(--spectrum-alias-text-color);
|
||||
font-size: var(--spectrum-global-dimension-font-size-200);
|
||||
font-weight: 600;
|
||||
transition: color 130ms ease-out;
|
||||
}
|
||||
.link:hover {
|
||||
color: var(--spectrum-global-color-blue-600);
|
||||
}
|
||||
.close {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: var(--spacing-xl);
|
||||
right: var(--spacing-xl);
|
||||
}
|
||||
.mobile-click-handler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Desktop nav overrides */
|
||||
@media (min-width: 600px) {
|
||||
.layout--left {
|
||||
flex-direction: row;
|
||||
overflow: hidden;
|
||||
}
|
||||
.layout--left .main-wrapper {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.nav--left {
|
||||
width: 250px;
|
||||
padding: var(--spacing-xl);
|
||||
}
|
||||
|
||||
.nav--left .links {
|
||||
margin-top: var(--spacing-m);
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
}
|
||||
.nav--left .link {
|
||||
font-size: var(--spectrum-global-dimension-font-size-150);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile nav overrides */
|
||||
@media (max-width: 600px) {
|
||||
.nav-wrapper {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
box-shadow: 0 0 8px -1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
/* Show close button in drawer */
|
||||
.close {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Force standard top bar */
|
||||
.nav {
|
||||
padding: var(--spacing-m) 16px;
|
||||
}
|
||||
.burger {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
.logo {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.logo :global(h1) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Reduce padding */
|
||||
.main {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
/* Transform links into drawer */
|
||||
.links {
|
||||
margin-top: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: -250px;
|
||||
transform: translateX(0);
|
||||
width: 250px;
|
||||
transition: transform 0.26s ease-in-out, opacity 0.26s ease-in-out;
|
||||
height: 100vh;
|
||||
opacity: 0;
|
||||
background: white;
|
||||
z-index: 999;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
padding: var(--spacing-xl);
|
||||
}
|
||||
.link {
|
||||
width: calc(100% - 30px);
|
||||
font-size: 120%;
|
||||
}
|
||||
.links.visible {
|
||||
opacity: 1;
|
||||
transform: translateX(250px);
|
||||
box-shadow: 0 0 40px 20px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.mobile-click-handler.visible {
|
||||
position: fixed;
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 998;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -7,7 +7,7 @@
|
|||
const component = getContext("component")
|
||||
</script>
|
||||
|
||||
<div use:styleable={$component.styles}>
|
||||
<div use:styleable={{ ...$component.styles, empty: true }}>
|
||||
<h1>Screen Slot</h1>
|
||||
<span>
|
||||
The screens that you create will be displayed inside this box.
|
||||
|
@ -20,13 +20,16 @@
|
|||
div {
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
padding: 20px !important;
|
||||
align-items: center !important;
|
||||
padding: 32px !important;
|
||||
text-align: center !important;
|
||||
border-style: dashed !important;
|
||||
border-width: 1px !important;
|
||||
color: #000000 !important;
|
||||
background-color: rgba(0, 0, 0, 0.05) !important;
|
||||
}
|
||||
h1 {
|
||||
color: var(--spectrum-alias-text-color);
|
||||
}
|
||||
span {
|
||||
font-size: var(--font-size-s);
|
||||
color: var(--grey-6);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
<script>
|
||||
import { getContext } from "svelte"
|
||||
import Placeholder from "./Placeholder.svelte"
|
||||
|
||||
const { styleable, builderStore } = getContext("sdk")
|
||||
const component = getContext("component")
|
||||
|
||||
export let type = "mainSidebar"
|
||||
export let minSize = 250
|
||||
|
||||
let layoutMap = {
|
||||
mainSidebar: 2,
|
||||
sidebarMain: 2,
|
||||
twoColumns: 2,
|
||||
threeColumns: 3,
|
||||
}
|
||||
|
||||
let containerWidth
|
||||
$: columnsDependingOnSize = calculateColumns(containerWidth)
|
||||
|
||||
function calculateColumns(parentWidth) {
|
||||
const numberOfAllowedColumns = Math.floor(parentWidth / minSize) || 100
|
||||
if (layoutMap[type] <= numberOfAllowedColumns) {
|
||||
return false
|
||||
} else if (layoutMap[type] > numberOfAllowedColumns) {
|
||||
return numberOfAllowedColumns
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:clientWidth={containerWidth}
|
||||
class="{type} columns-{columnsDependingOnSize}"
|
||||
use:styleable={$component.styles}
|
||||
>
|
||||
<slot />
|
||||
{#if layoutMap[type] - $component.children > 0}
|
||||
{#each new Array(layoutMap[type] - $component.children) as _}
|
||||
<div class:placeholder={$builderStore.inBuilder}>
|
||||
<Placeholder />
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: grid;
|
||||
grid-gap: 16px;
|
||||
}
|
||||
.mainSidebar {
|
||||
grid-template-columns: 3fr 1fr;
|
||||
}
|
||||
.sidebarMain {
|
||||
grid-template-columns: 1fr 3fr;
|
||||
}
|
||||
.twoColumns {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.threeColumns {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
.columns-1 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.columns-2 {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.placeholder {
|
||||
border: 2px dashed var(--grey-5);
|
||||
padding: var(--spacing-l);
|
||||
}
|
||||
</style>
|
|
@ -15,6 +15,7 @@ export { default as Placeholder } from "./Placeholder.svelte"
|
|||
|
||||
// User facing components
|
||||
export { default as container } from "./Container.svelte"
|
||||
export { default as section } from "./Section.svelte"
|
||||
export { default as dataprovider } from "./DataProvider.svelte"
|
||||
export { default as screenslot } from "./ScreenSlot.svelte"
|
||||
export { default as button } from "./Button.svelte"
|
||||
|
@ -23,6 +24,7 @@ export { default as stackedlist } from "./StackedList.svelte"
|
|||
export { default as card } from "./Card.svelte"
|
||||
export { default as text } from "./Text.svelte"
|
||||
export { default as navigation } from "./Navigation.svelte"
|
||||
export { default as layout } from "./Layout.svelte"
|
||||
export { default as link } from "./Link.svelte"
|
||||
export { default as heading } from "./Heading.svelte"
|
||||
export { default as image } from "./Image.svelte"
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@adobe/spectrum-css-workflow-icons/-/spectrum-css-workflow-icons-1.2.1.tgz#7e2cb3fcfb5c8b12d7275afafbb6ec44913551b4"
|
||||
integrity sha512-uVgekyBXnOVkxp+CUssjN/gefARtudZC8duEn1vm0lBQFwGRZFlDEzU1QC+aIRWCrD1Z8OgRpmBYlSZ7QS003w==
|
||||
|
||||
"@budibase/bbui@^0.9.41":
|
||||
version "0.9.45"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.45.tgz#c37e84ffbf99daf0ebaa5c19b9109e7222463591"
|
||||
integrity sha512-+wojKap0kieYoeCqhah1V9EswVbR+Pg1k9Nlw1n/zTsuGtjA0kUH652yKjz7zNzZgFm+s5oYS1CoPieIMehhSw==
|
||||
"@budibase/bbui@^0.9.47":
|
||||
version "0.9.47"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.47.tgz#d8664a05203432d522cd91a0bad1cdd8518baf93"
|
||||
integrity sha512-LXvJCgUSoc4EJKafBaKfUzU4GUOQGmts/8F4V6LTFtTyMZavgq2/KFAgPbR3QeYvidLsshtwop/pQfoszXTQnQ==
|
||||
dependencies:
|
||||
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
|
||||
"@spectrum-css/actionbutton" "^1.0.1"
|
||||
|
@ -140,7 +140,7 @@
|
|||
resolved "https://registry.yarnpkg.com/@spectrum-css/label/-/label-2.0.10.tgz#2368651d7636a19385b5d300cdf6272db1916001"
|
||||
integrity sha512-xCbtEiQkZIlLdWFikuw7ifDCC21DOC/KMgVrrVJHXFc4KRQe9LTZSqmGF3tovm+CSq1adE59mYoTbojVQ9YuEQ==
|
||||
|
||||
"@spectrum-css/link@^3.1.1":
|
||||
"@spectrum-css/link@^3.1.1", "@spectrum-css/link@^3.1.3":
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@spectrum-css/link/-/link-3.1.3.tgz#b0e560a7e0acdb4a2b329b6669696aa3438f5993"
|
||||
integrity sha512-8Pmy5d73MwKcATTPaj+fSrZYnIw7GmfX40AvpC1xx5LauOxsbUb4AVNp1kn2H8rrOBmxF7czyhoBBhEiv66QUg==
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue