Merge branch 'spectrum-bbui' of github.com:Budibase/budibase into spectrum-bbui-forms
This commit is contained in:
commit
b823f2bed1
|
@ -51,9 +51,13 @@
|
|||
"@spectrum-css/modal": "^3.0.1",
|
||||
"@spectrum-css/picker": "^1.0.1",
|
||||
"@spectrum-css/popover": "^3.0.1",
|
||||
"@spectrum-css/progressbar": "^1.0.2",
|
||||
"@spectrum-css/progresscircle": "^1.0.2",
|
||||
"@spectrum-css/table": "^3.0.1",
|
||||
"@spectrum-css/textfield": "^3.0.1",
|
||||
"@spectrum-css/tabs": "^3.0.1",
|
||||
"@spectrum-css/toast": "^3.0.1",
|
||||
"@spectrum-css/typography": "^3.0.1",
|
||||
"@spectrum-css/underlay": "^2.0.9",
|
||||
"@spectrum-css/vars": "^3.0.1",
|
||||
"dayjs": "^1.10.4",
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<script>
|
||||
import "@spectrum-css/divider/dist/index-vars.css"
|
||||
export let l = false
|
||||
export let m = false
|
||||
export let s = false
|
||||
|
||||
export let vertical = false
|
||||
</script>
|
||||
|
||||
<hr
|
||||
class:spectrum-Divider--sizeL={l}
|
||||
class:spectrum-Divider--sizeM={m}
|
||||
class:spectrum-Divider--sizeS={s}
|
||||
class="spectrum-Divider spectrum-Divider--{vertical ? 'vertical' : 'horizontal'} spectrum-Dialog-divider">
|
|
@ -1,8 +1,7 @@
|
|||
<script>
|
||||
import "@spectrum-css/dialog/dist/index-vars.css"
|
||||
import "@spectrum-css/modal/dist/index-vars.css"
|
||||
import "@spectrum-css/underlay/dist/index-vars.css"
|
||||
import { createEventDispatcher, setContext } from "svelte"
|
||||
import { createEventDispatcher, setContext, tick } from "svelte"
|
||||
import { fade, fly } from "svelte/transition"
|
||||
import Portal from "svelte-portal"
|
||||
import Context from "../context"
|
||||
|
@ -31,6 +30,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
async function focusFirstInput(node) {
|
||||
const inputs = node.querySelectorAll("input")
|
||||
if (inputs) {
|
||||
await tick()
|
||||
inputs[0].focus()
|
||||
}
|
||||
}
|
||||
|
||||
setContext(Context.Modal, { show, hide })
|
||||
</script>
|
||||
|
||||
|
@ -45,6 +52,7 @@
|
|||
<div class="modal-wrapper" on:click|self={hide}>
|
||||
<div class="modal-inner-wrapper" on:click|self={hide}>
|
||||
<div
|
||||
use:focusFirstInput
|
||||
class="spectrum-Modal is-open"
|
||||
transition:fly={{ y: 30, duration: 200 }}>
|
||||
<slot />
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script>
|
||||
import "@spectrum-css/divider/dist/index-vars.css"
|
||||
|
||||
import { getContext } from "svelte"
|
||||
import Button from "../Button/Button.svelte"
|
||||
import Heading from "../Typography/Heading.svelte"
|
||||
import Divider from "../Divider/Divider.svelte"
|
||||
import Icon from "../Icons/Icon.svelte"
|
||||
import Context from "../context"
|
||||
|
||||
|
@ -35,10 +35,8 @@
|
|||
tabindex="-1"
|
||||
aria-modal="true">
|
||||
<div class="spectrum-Dialog-grid">
|
||||
<h1 class="spectrum-Dialog-heading">{title}</h1>
|
||||
<hr
|
||||
class="spectrum-Divider spectrum-Divider--sizeS spectrum-Divider--horizontal spectrum-Dialog-divider" />
|
||||
|
||||
<Heading m h2>{title}</Heading>
|
||||
<Divider m />
|
||||
<!-- TODO: Remove content-grid class once Layout components are in bbui -->
|
||||
<section class="spectrum-Dialog-content content-grid">
|
||||
<slot />
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<script>
|
||||
import "@spectrum-css/progressbar/dist/index-vars.css"
|
||||
import { tweened } from 'svelte/motion';
|
||||
import { cubicOut } from 'svelte/easing';
|
||||
|
||||
export let value = false
|
||||
export let easing = cubicOut
|
||||
export let duration = 1000;
|
||||
export let width = false;
|
||||
export let sideLabel = false
|
||||
export let overBackground = false
|
||||
|
||||
export let s = false;
|
||||
export let m = false;
|
||||
export let l = false;
|
||||
export let xl = false;
|
||||
|
||||
const progress = tweened(0, {
|
||||
duration: duration,
|
||||
easing: easing
|
||||
});
|
||||
|
||||
$: if (value) $progress = value
|
||||
</script>
|
||||
|
||||
|
||||
<div class:spectrum-ProgressBar--indeterminate={!value} class:spectrum-ProgressBar--sideLabel={sideLabel} class:spectrum-ProgressBar--sizeS={s} class:spectrum-ProgressBar--sizeM={m} class:spectrum-ProgressBar--sizeL={l} class:spectrum-ProgressBar--sizeXL={xl} class="spectrum-ProgressBar" value={$progress} role="progressbar" aria-valuenow={$progress} aria-valuemin="0" aria-valuemax="100" style={width ? `width: ${width}px;` : ''}>
|
||||
{#if $$slots}
|
||||
<div class:spectrum-FieldLabel--sizeS={s} class:spectrum-FieldLabel--sizeM={m} class:spectrum-FieldLabel--sizeL={l} class:spectrum-FieldLabel--sizeXL={xl} class="spectrum-FieldLabel spectrum-ProgressBar-label"><slot /></div>
|
||||
{/if}
|
||||
{#if value}
|
||||
<div class:spectrum-FieldLabel--sizeS={s} class:spectrum-FieldLabel--sizeM={m} class:spectrum-FieldLabel--sizeL={l} class:spectrum-FieldLabel--sizeXL={xl} class="spectrum-FieldLabel spectrum-ProgressBar-percentage">{Math.round($progress)}%</div>
|
||||
{/if}
|
||||
<div class="spectrum-ProgressBar-track">
|
||||
<div class="spectrum-ProgressBar-fill" style={value ? `width: ${$progress}%` : ''}></div>
|
||||
</div>
|
||||
<div class="spectrum-ProgressBar-label" hidden=""></div>
|
||||
</div>
|
|
@ -0,0 +1,29 @@
|
|||
<script>
|
||||
// WIP! Does not yet work.
|
||||
import "@spectrum-css/progresscircle/dist/index-vars.css"
|
||||
import { tweened } from 'svelte/motion';
|
||||
import { cubicOut } from 'svelte/easing';
|
||||
|
||||
export let value = false
|
||||
export let small;
|
||||
export let large;
|
||||
|
||||
export let overBackground;
|
||||
</script>
|
||||
|
||||
<div class:spectrum-ProgressBar--indeterminate={!value} class:spectrum-ProgressCircle--small={small} class:spectrum-ProgressCircle--large={large} class="spectrum-ProgressCircle">
|
||||
<div class="spectrum-ProgressCircle-track"></div>
|
||||
<div class="spectrum-ProgressCircle-fills">
|
||||
<div class="spectrum-ProgressCircle-fillMask1">
|
||||
<div class="spectrum-ProgressCircle-fillSubMask1">
|
||||
<div class="spectrum-ProgressCircle-fill"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="spectrum-ProgressCircle-fillMask2">
|
||||
<div class="spectrum-ProgressCircle-fillSubMask2">
|
||||
<div class="spectrum-ProgressCircle-fill"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<script>
|
||||
import { getContext, onMount } from 'svelte'
|
||||
import Portal from "svelte-portal"
|
||||
export let title
|
||||
export let icon = '';
|
||||
|
||||
const selected = getContext('tab')
|
||||
let tab;
|
||||
let tabInfo
|
||||
const setTabInfo = () => {
|
||||
tabInfo = tab.getBoundingClientRect()
|
||||
if ($selected.title === title) {
|
||||
$selected.info = tabInfo
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
setTabInfo()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<div bind:this={tab} on:click={() => $selected = {...$selected, title, info: tab.getBoundingClientRect()} } class:is-selected={$selected.title === title} class="spectrum-Tabs-item" tabindex="0">
|
||||
{#if icon}
|
||||
<svg class="spectrum-Icon spectrum-Icon--sizeM" focusable="false" aria-hidden="true" aria-label="Folder">
|
||||
<use xlink:href="#spectrum-icon-18-{icon}" />
|
||||
</svg>
|
||||
{/if}
|
||||
<span class="spectrum-Tabs-itemLabel">{title}</span>
|
||||
</div>
|
||||
{#if $selected.title === title}
|
||||
<Portal target=".spectrum-Tabs-content-{$selected.id}">
|
||||
<slot />
|
||||
</Portal>
|
||||
{/if}
|
|
@ -0,0 +1,71 @@
|
|||
<script>
|
||||
import "@spectrum-css/tabs/dist/index-vars.css"
|
||||
import { writable } from 'svelte/store'
|
||||
import { onMount, setContext, createEventDispatcher } from 'svelte'
|
||||
|
||||
export let selected;
|
||||
export let vertical = false
|
||||
let _id = id()
|
||||
const tab = writable({title: selected, id: _id})
|
||||
setContext('tab', tab)
|
||||
|
||||
let container;
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
$: selected = $tab.title
|
||||
$: selected = dispatch('select', selected)
|
||||
|
||||
let top, left, width, height;
|
||||
$: calculateIndicatorLength($tab)
|
||||
$: calculateIndicatorOffset($tab)
|
||||
|
||||
function calculateIndicatorLength() {
|
||||
if (!vertical) {
|
||||
width = $tab.info?.width + 24 + 'px'
|
||||
height = $tab.info?.height
|
||||
} else {
|
||||
height = $tab.info?.height + 4 + 'px'
|
||||
width = $tab.info?.width
|
||||
}
|
||||
}
|
||||
|
||||
function calculateIndicatorOffset() {
|
||||
if (!vertical) {
|
||||
left = $tab.info?.left - container?.getBoundingClientRect().left - 12 + 'px'
|
||||
top = $tab.info?.top
|
||||
} else {
|
||||
top = $tab.info?.top - container?.getBoundingClientRect().top + 'px'
|
||||
left = $tab.info?.left
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
calculateIndicatorLength()
|
||||
calculateIndicatorOffset()
|
||||
})
|
||||
|
||||
function id() {
|
||||
return (
|
||||
"_" +
|
||||
Math.random()
|
||||
.toString(36)
|
||||
.substr(2, 9)
|
||||
)
|
||||
}
|
||||
</script>
|
||||
<div bind:this={container} class="selected-border spectrum-Tabs spectrum-Tabs--{vertical ? 'vertical' : 'horizontal'}">
|
||||
<slot />
|
||||
<div class="spectrum-Tabs-selectionIndicator indicator-transition" style="width: {width}; height: {height}; left: {left}; top: {top};"></div>
|
||||
</div>
|
||||
|
||||
<div class="spectrum-Tabs-content spectrum-Tabs-content-{_id}" />
|
||||
|
||||
<style>
|
||||
.spectrum-Tabs-content {
|
||||
margin-top: var(--spectrum-global-dimension-static-size-150);
|
||||
}
|
||||
.indicator-transition {
|
||||
transition: all 200ms
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
<script>
|
||||
import "@spectrum-css/typography/dist/index-vars.css"
|
||||
|
||||
// Sizes
|
||||
export let xxxl = false;
|
||||
export let xxl = false;
|
||||
export let xl = false;
|
||||
export let l = false;
|
||||
export let m = false;
|
||||
export let s = false;
|
||||
export let xs = false;
|
||||
export let xxs = false;
|
||||
|
||||
export let serif = false;
|
||||
|
||||
</script>
|
||||
|
||||
<p class="spectrum-Body"
|
||||
class:spectrum-Body--serif={serif}
|
||||
class:spectrum-Body--sizeXXXL={xxxl}
|
||||
class:spectrum-Body--sizeXXL={xxl}
|
||||
class:spectrum-Body--sizeXL={xl}
|
||||
class:spectrum-Body--sizeL={l}
|
||||
class:spectrum-Body--sizeM={m}
|
||||
class:spectrum-Body--sizeS={s}
|
||||
class:spectrum-Body--sizeXS={xs}
|
||||
class:spectrum-Body--sizeXXS={xxs}>
|
||||
<slot />
|
||||
</p>
|
|
@ -0,0 +1,20 @@
|
|||
<script>
|
||||
import "@spectrum-css/typography/dist/index-vars.css"
|
||||
|
||||
// Sizes
|
||||
export let xl = false;
|
||||
export let l = false;
|
||||
export let m = false;
|
||||
export let s = false;
|
||||
export let xs = false;
|
||||
|
||||
</script>
|
||||
|
||||
<code class="spectrum-Code"
|
||||
class:spectrum-Code--sizeXL={xl}
|
||||
class:spectrum-Code--sizeL={l}
|
||||
class:spectrum-Code--sizeM={m}
|
||||
class:spectrum-Code--sizeS={s}
|
||||
class:spectrum-Code--sizeXS={xs}>
|
||||
<slot />
|
||||
</code>
|
|
@ -0,0 +1,21 @@
|
|||
<script>
|
||||
import "@spectrum-css/typography/dist/index-vars.css"
|
||||
|
||||
// Sizes
|
||||
export let xl = false;
|
||||
export let l = false;
|
||||
export let m = false;
|
||||
export let s = false;
|
||||
|
||||
export let serif = false;
|
||||
|
||||
</script>
|
||||
|
||||
<p class="spectrum-Detail"
|
||||
class:spectrum-Detail--serif={serif}
|
||||
class:spectrum-Detail--sizeXL={xl}
|
||||
class:spectrum-Detail--sizeL={l}
|
||||
class:spectrum-Detail--sizeM={m}
|
||||
class:spectrum-Detail--sizeS={s}>
|
||||
<slot />
|
||||
</p>
|
|
@ -0,0 +1,78 @@
|
|||
<script>
|
||||
import "@spectrum-css/typography/dist/index-vars.css"
|
||||
|
||||
// Level
|
||||
export let h1 = false;
|
||||
export let h2 = false;
|
||||
export let h3 = false;
|
||||
export let h4 = false;
|
||||
|
||||
// Sizes
|
||||
export let xxxl = false;
|
||||
export let xxl = false;
|
||||
export let xl = false;
|
||||
export let l = false;
|
||||
export let m = false;
|
||||
export let s = false;
|
||||
export let xs = false;
|
||||
export let xxs = false;
|
||||
|
||||
export let serif = false;
|
||||
|
||||
</script>
|
||||
|
||||
{#if h1}
|
||||
<h1 class="spectrum-Heading"
|
||||
class:spectrum-Heading--serif={serif}
|
||||
class:spectrum-Heading--sizeXXXL={xxxl}
|
||||
class:spectrum-Heading--sizeXXL={xxl}
|
||||
class:spectrum-Heading--sizeXL={xl}
|
||||
class:spectrum-Heading--sizeL={l}
|
||||
class:spectrum-Heading--sizeM={m}
|
||||
class:spectrum-Heading--sizeS={s}
|
||||
class:spectrum-Heading--sizeXS={xs}
|
||||
class:spectrum-Heading--sizeXXS={xxs}>
|
||||
<slot />
|
||||
</h1>
|
||||
{:else if h2}
|
||||
<h2 class="spectrum-Heading"
|
||||
class:spectrum-Heading--serif={serif}
|
||||
class:spectrum-Heading--sizeXXXL={xxxl}
|
||||
class:spectrum-Heading--sizeXXL={xxl}
|
||||
class:spectrum-Heading--sizeXL={xl}
|
||||
class:spectrum-Heading--sizeL={l}
|
||||
class:spectrum-Heading--sizeM={m}
|
||||
class:spectrum-Heading--sizeS={s}
|
||||
class:spectrum-Heading--sizeXS={xs}
|
||||
class:spectrum-Heading--sizeXXS={xxs}>
|
||||
<slot />
|
||||
</h2>
|
||||
{:else if h3}
|
||||
<h3 class="spectrum-Heading"
|
||||
class:spectrum-Heading--serif={serif}
|
||||
class:spectrum-Heading--sizeXXXL={xxxl}
|
||||
class:spectrum-Heading--sizeXXL={xxl}
|
||||
class:spectrum-Heading--sizeXL={xl}
|
||||
class:spectrum-Heading--sizeL={l}
|
||||
class:spectrum-Heading--sizeM={m}
|
||||
class:spectrum-Heading--sizeS={s}
|
||||
class:spectrum-Heading--sizeXS={xs}
|
||||
class:spectrum-Heading--sizeXXS={xxs}>
|
||||
<slot />
|
||||
</h3>
|
||||
{:else if h4}
|
||||
<h4 class="spectrum-Heading"
|
||||
class:spectrum-Heading--serif={serif}
|
||||
class:spectrum-Heading--sizeXXXL={xxxl}
|
||||
class:spectrum-Heading--sizeXXL={xxl}
|
||||
class:spectrum-Heading--sizeXL={xl}
|
||||
class:spectrum-Heading--sizeL={l}
|
||||
class:spectrum-Heading--sizeM={m}
|
||||
class:spectrum-Heading--sizeS={s}
|
||||
class:spectrum-Heading--sizeXS={xs}
|
||||
class:spectrum-Heading--sizeXXS={xxs}>
|
||||
<slot />
|
||||
</h4>
|
||||
{:else}
|
||||
SPECIFY HEADING SIZE!
|
||||
{/if}
|
|
@ -21,8 +21,8 @@ export { default as DetailSummary } from "./List/Items/DetailSummary.svelte"
|
|||
export { default as Switcher } from "./Switcher/Switcher.svelte"
|
||||
export { default as DropdownMenu } from "./DropdownMenu/DropdownMenu.svelte"
|
||||
export { default as Popover } from "./Popover/Popover.svelte"
|
||||
export { default as Body } from "./Styleguide/Body.svelte"
|
||||
export { default as Heading } from "./Styleguide/Heading.svelte"
|
||||
export { default as ProgressBar } from "./ProgressBar/ProgressBar.svelte"
|
||||
export { default as ProgressCircle } from "./ProgressCircle/ProgressCircle.svelte"
|
||||
export { default as Label } from "./Styleguide/Label.svelte"
|
||||
export { default as Link } from "./Link/Link.svelte"
|
||||
export { default as Close } from "./Button/Close.svelte"
|
||||
|
@ -39,6 +39,16 @@ export { default as Multiselect } from "./Form/Multiselect.svelte"
|
|||
export { default as Slider } from "./Form/Slider.svelte"
|
||||
export { default as Context } from "./context"
|
||||
export { default as Table } from "./Table/Table.svelte"
|
||||
export { default as Tabs } from "./Tabs/Tabs.svelte"
|
||||
export { default as Tab } from "./Tabs/Tab.svelte"
|
||||
export { default as Divider } from "./Divider/Divider.svelte"
|
||||
|
||||
// Typography
|
||||
export { default as Body } from "./Typography/Body.svelte"
|
||||
export { default as Heading } from "./Typography/Heading.svelte"
|
||||
export { default as Detail } from "./Typography/Detail.svelte"
|
||||
export { default as Code } from "./Typography/Code.svelte"
|
||||
|
||||
|
||||
// Core form components to be used elsewhere (standard components)
|
||||
export * from "./Form/Core"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -46,12 +46,12 @@
|
|||
|
||||
<div class="container">
|
||||
<div class="list">
|
||||
<Heading small>Available bindings</Heading>
|
||||
<Heading s h3>Available bindings</Heading>
|
||||
<Spacer medium />
|
||||
<Input extraThin placeholder="Search" bind:value={search} />
|
||||
<Spacer medium />
|
||||
{#each categories as [categoryName, bindings]}
|
||||
<Heading extraSmall>{categoryName}</Heading>
|
||||
<Heading xs h4>{categoryName}</Heading>
|
||||
<Spacer extraSmall />
|
||||
{#each bindableProperties.filter(binding =>
|
||||
binding.label.match(searchRgx)
|
||||
|
@ -64,7 +64,7 @@
|
|||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
<Heading extraSmall>Helpers</Heading>
|
||||
<Heading xs h3>Helpers</Heading>
|
||||
<Spacer extraSmall />
|
||||
{#each helpers.filter(helper => helper.label.match(searchRgx) || helper.description.match(searchRgx)) as helper}
|
||||
<div class="binding" on:click={() => addToText(helper)}>
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
<Input extraThin placeholder="Search" bind:value={search} />
|
||||
<Spacer medium />
|
||||
{#if context}
|
||||
<Heading extraSmall>Columns</Heading>
|
||||
<Heading xs h3>Columns</Heading>
|
||||
<Spacer small />
|
||||
<ul>
|
||||
{#each context.filter(context =>
|
||||
|
@ -77,7 +77,7 @@
|
|||
{/if}
|
||||
<Spacer small />
|
||||
{#if instance}
|
||||
<Heading extraSmall>Components</Heading>
|
||||
<Heading xs h3>Components</Heading>
|
||||
<Spacer small />
|
||||
<ul>
|
||||
{#each instance.filter(instance =>
|
||||
|
@ -90,7 +90,7 @@
|
|||
</ul>
|
||||
{/if}
|
||||
<Spacer small />
|
||||
<Heading extraSmall>Helpers</Heading>
|
||||
<Heading xs h3>Helpers</Heading>
|
||||
<Spacer small />
|
||||
<ul>
|
||||
{#each helpers.filter(helper => helper.label.match(searchRgx) || helper.description.match(searchRgx)) as helper}
|
||||
|
|
|
@ -137,7 +137,7 @@
|
|||
<DropdownMenu bind:this={dropdownRight} anchor={anchorRight}>
|
||||
<div class="dropdown">
|
||||
<div class="title">
|
||||
<Heading extraSmall>Tables</Heading>
|
||||
<Heading xs h3>Tables</Heading>
|
||||
</div>
|
||||
<ul>
|
||||
{#each tables as table}
|
||||
|
@ -150,7 +150,7 @@
|
|||
</ul>
|
||||
<hr />
|
||||
<div class="title">
|
||||
<Heading extraSmall>Views</Heading>
|
||||
<Heading xs h3>Views</Heading>
|
||||
</div>
|
||||
<ul>
|
||||
{#each views as view}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
</script>
|
||||
|
||||
<div class="apps-card">
|
||||
<Heading small black>{name}</Heading>
|
||||
<Heading s h3>{name}</Heading>
|
||||
<Spacer medium />
|
||||
<div class="card-footer" data-cy={`app-${name}`}>
|
||||
<ActionButton text medium blue on:click={() => $goto(`/builder/${_id}`)}>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import AppCard from "./AppCard.svelte"
|
||||
import { Heading } from "@budibase/bbui"
|
||||
import { Heading, Divider } from "@budibase/bbui"
|
||||
import Spinner from "components/common/Spinner.svelte"
|
||||
import { get } from "builderStore/api"
|
||||
|
||||
|
@ -19,23 +19,18 @@
|
|||
</script>
|
||||
|
||||
<div class="root">
|
||||
<Heading lh medium black>Your Apps</Heading>
|
||||
<Heading m h2>Your Apps</Heading>
|
||||
<Divider s />
|
||||
{#await promise}
|
||||
<div class="spinner-container">
|
||||
<Spinner size="30" />
|
||||
</div>
|
||||
{:then apps}
|
||||
<div class="inner">
|
||||
<div>
|
||||
<div>
|
||||
<div class="apps">
|
||||
{#each apps as app}
|
||||
<AppCard {...app} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:catch err}
|
||||
<h1 style="color:red">{err}</h1>
|
||||
{/await}
|
||||
|
@ -43,6 +38,7 @@
|
|||
|
||||
<style>
|
||||
.apps {
|
||||
margin-top: var(--spectrum-global-dimension-static-size-150);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
grid-gap: var(--layout-m);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import AppList from "components/start/AppList.svelte"
|
||||
import { get } from "builderStore/api"
|
||||
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
||||
import { Button, Heading, Modal, Spacer, Menu, MenuSection, MenuItem } from "@budibase/bbui"
|
||||
import { Button, Heading, Modal, Spacer, Divider } from "@budibase/bbui"
|
||||
import TemplateList from "components/start/TemplateList.svelte"
|
||||
import analytics from "analytics"
|
||||
import Banner from "/assets/orange-landscape.png"
|
||||
|
@ -57,7 +57,7 @@
|
|||
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<Heading medium black>Welcome to the Budibase Beta</Heading>
|
||||
<Heading m h1>Welcome to the Budibase Beta</Heading>
|
||||
<div class="button-group">
|
||||
<Button secondary on:click={initiateAppImport}>Import Web App</Button>
|
||||
<Spacer medium />
|
||||
|
|
|
@ -18,58 +18,5 @@ function hasResource(ctx) {
|
|||
}
|
||||
|
||||
module.exports = (permType, permLevel = null) => async (ctx, next) => {
|
||||
if (env.isProd() && ctx.headers["x-api-key"] && ctx.headers["x-instanceid"]) {
|
||||
// api key header passed by external webhook
|
||||
if (await isAPIKeyValid(ctx.headers["x-api-key"])) {
|
||||
ctx.auth = {
|
||||
authenticated: AuthTypes.EXTERNAL,
|
||||
apiKey: ctx.headers["x-api-key"],
|
||||
}
|
||||
ctx.user = {
|
||||
appId: ctx.headers["x-instanceid"],
|
||||
}
|
||||
return next()
|
||||
}
|
||||
|
||||
return ctx.throw(403, "API key invalid")
|
||||
}
|
||||
|
||||
if (!ctx.user) {
|
||||
return ctx.throw(403, "No user info found")
|
||||
}
|
||||
|
||||
const role = ctx.user.role
|
||||
const isAdmin = ADMIN_ROLES.includes(role._id)
|
||||
const isAuthed = ctx.auth.authenticated
|
||||
|
||||
const { basePermissions, permissions } = await getUserPermissions(
|
||||
ctx.appId,
|
||||
role._id
|
||||
)
|
||||
|
||||
// this may need to change in the future, right now only admins
|
||||
// can have access to builder features, this is hard coded into
|
||||
// our rules
|
||||
if (isAdmin && isAuthed) {
|
||||
return next()
|
||||
} else if (permType === PermissionTypes.BUILDER) {
|
||||
return ctx.throw(403, "Not Authorized")
|
||||
}
|
||||
|
||||
if (
|
||||
hasResource(ctx) &&
|
||||
doesHaveResourcePermission(permissions, permLevel, ctx)
|
||||
) {
|
||||
return next()
|
||||
}
|
||||
|
||||
if (!isAuthed) {
|
||||
ctx.throw(403, "Session not authenticated")
|
||||
}
|
||||
|
||||
if (!doesHaveBasePermission(permType, permLevel, basePermissions)) {
|
||||
ctx.throw(403, "User does not have permission")
|
||||
}
|
||||
|
||||
return next()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue