Merge pull request #2606 from Budibase/responsive-portal

Responsive portal
This commit is contained in:
Andrew Kingston 2021-09-16 17:28:21 +01:00 committed by GitHub
commit 00b12463f6
21 changed files with 2118 additions and 262 deletions

View File

@ -21,8 +21,5 @@
.wide { .wide {
max-width: none; max-width: none;
margin: 0; margin: 0;
padding: var(--spacing-xl) calc(var(--spacing-xl) * 2)
calc(var(--spacing-xl) * 2) calc(var(--spacing-xl) * 2);
min-height: calc(100% - var(--spacing-xl) * 3);
} }
</style> </style>

View File

@ -13,7 +13,7 @@
} }
} }
export let value = false export let value = null
export let minValue = 0 export let minValue = 0
export let maxValue = 100 export let maxValue = 100

View File

@ -13,6 +13,7 @@
class="spectrum-SideNav-item" class="spectrum-SideNav-item"
class:is-selected={selected} class:is-selected={selected}
class:is-disabled={disabled} class:is-disabled={disabled}
on:click
> >
{#if heading} {#if heading}
<h2 class="spectrum-SideNav-heading" id="nav-heading-{heading}"> <h2 class="spectrum-SideNav-heading" id="nav-heading-{heading}">

View File

@ -34,7 +34,7 @@ Cypress.Commands.add("createApp", name => {
cy.get(".spectrum-Modal") cy.get(".spectrum-Modal")
.within(() => { .within(() => {
cy.get("input").eq(0).type(name).should("have.value", name).blur() cy.get("input").eq(0).type(name).should("have.value", name).blur()
cy.contains("Create app").click() cy.get(".spectrum-ButtonGroup").contains("Create app").click()
}) })
.then(() => { .then(() => {
cy.expandBudibaseConnection() cy.expandBudibaseConnection()

View File

@ -8,9 +8,28 @@
} from "@budibase/bbui" } from "@budibase/bbui"
import { admin } from "stores/portal" import { admin } from "stores/portal"
import { goto } from "@roxi/routify" import { goto } from "@roxi/routify"
import { onMount } from "svelte"
let width = window.innerWidth
$: side = width < 500 ? "right" : "left"
const resizeObserver = new ResizeObserver(entries => {
if (entries?.[0]) {
width = entries[0].contentRect?.width
}
})
onMount(() => {
const doc = document.documentElement
resizeObserver.observe(doc)
return () => {
resizeObserver.unobserve(doc)
}
})
</script> </script>
<ActionMenu> <ActionMenu align={side}>
<div slot="control" class="icon"> <div slot="control" class="icon">
<ProgressCircle size="S" value={$admin.onboardingProgress} /> <ProgressCircle size="S" value={$admin.onboardingProgress} />
</div> </div>
@ -37,7 +56,7 @@
.item { .item {
display: grid; display: grid;
align-items: center; align-items: center;
grid-template-columns: 200px 20px; grid-template-columns: 175px 20px;
} }
.icon { .icon {
cursor: pointer; cursor: pointer;

View File

@ -104,8 +104,10 @@
// remove all iframe event listeners on component destroy // remove all iframe event listeners on component destroy
onDestroy(() => { onDestroy(() => {
if (iframe.contentWindow) {
iframe.contentWindow.removeEventListener("bb-event", handleBudibaseEvent) iframe.contentWindow.removeEventListener("bb-event", handleBudibaseEvent)
iframe.contentWindow.removeEventListener("keydown", handleKeydownEvent) iframe.contentWindow.removeEventListener("keydown", handleKeydownEvent)
}
}) })
const handleBudibaseEvent = event => { const handleBudibaseEvent = event => {
@ -123,17 +125,21 @@
} else { } else {
console.warning(`Client sent unknown event type: ${type}`) console.warning(`Client sent unknown event type: ${type}`)
} }
}; }
const handleKeydownEvent = event => { const handleKeydownEvent = event => {
if ((event.key === "Delete" || event.key === "Backspace") && if (
(event.key === "Delete" || event.key === "Backspace") &&
selectedComponentId && selectedComponentId &&
['input', 'textarea'].indexOf(iframe.contentWindow.document.activeElement?.tagName.toLowerCase()) === -1) { ["input", "textarea"].indexOf(
confirmDeleteComponent(selectedComponentId); iframe.contentWindow.document.activeElement?.tagName.toLowerCase()
) === -1
) {
confirmDeleteComponent(selectedComponentId)
} }
} }
const confirmDeleteComponent = (componentId) => { const confirmDeleteComponent = componentId => {
idToDelete = componentId idToDelete = componentId
confirmDeleteDialog.show() confirmDeleteDialog.show()
} }

View File

@ -28,7 +28,7 @@
</Heading> </Heading>
</div> </div>
</div> </div>
<div> <div class="desktop">
{#if app.updatedAt} {#if app.updatedAt}
{processStringSync("Updated {{ duration time 'millisecond' }} ago", { {processStringSync("Updated {{ duration time 'millisecond' }} ago", {
time: new Date().getTime() - new Date(app.updatedAt).getTime(), time: new Date().getTime() - new Date(app.updatedAt).getTime(),
@ -37,7 +37,7 @@
Never updated Never updated
{/if} {/if}
</div> </div>
<div> <div class="desktop">
<StatusLight <StatusLight
positive={!app.lockedYou && !app.lockedOther} positive={!app.lockedYou && !app.lockedOther}
notice={app.lockedYou} notice={app.lockedYou}
@ -52,7 +52,7 @@
{/if} {/if}
</StatusLight> </StatusLight>
</div> </div>
<div> <div class="desktop">
<StatusLight active={app.deployed} neutral={!app.deployed}> <StatusLight active={app.deployed} neutral={!app.deployed}>
{#if app.deployed}Published{:else}Unpublished{/if} {#if app.deployed}Published{:else}Unpublished{/if}
</StatusLight> </StatusLight>
@ -109,4 +109,10 @@
cursor: pointer; cursor: pointer;
transition: color 130ms ease; transition: color 130ms ease;
} }
@media (max-width: 640px) {
.desktop {
display: none !important;
}
}
</style> </style>

View File

@ -134,7 +134,7 @@
</script> </script>
<ModalContent <ModalContent
title={template ? "Import app" : "Create new app"} title={template ? "Import app" : "Create app"}
confirmText={template ? "Import app" : "Create app"} confirmText={template ? "Import app" : "Create app"}
onConfirm={createNewApp} onConfirm={createNewApp}
disabled={!valid} disabled={!valid}

View File

@ -41,17 +41,8 @@
<Page> <Page>
<div class="content"> <div class="content">
<Layout noPadding> <Layout noPadding>
<div class="header">
<img alt="logo" src={$organisation.logoUrl || Logo} /> <img alt="logo" src={$organisation.logoUrl || Logo} />
<div class="info-title">
<Layout noPadding gap="XS">
<Heading size="L">
Hey {$auth.user.firstName || $auth.user.email}
</Heading>
<Body>
Welcome to the {$organisation.company} portal. Below you'll find
the list of apps that you have access to.
</Body>
</Layout>
<ActionMenu align="right"> <ActionMenu align="right">
<div slot="control" class="avatar"> <div slot="control" class="avatar">
<Avatar <Avatar
@ -81,6 +72,15 @@
<MenuItem icon="LogOut" on:click={auth.logout}>Log out</MenuItem> <MenuItem icon="LogOut" on:click={auth.logout}>Log out</MenuItem>
</ActionMenu> </ActionMenu>
</div> </div>
<Layout noPadding gap="XS">
<Heading size="M">
Hey {$auth.user.firstName || $auth.user.email}
</Heading>
<Body>
Welcome to the {$organisation.company} portal. Below you'll find the
list of apps that you have access to.
</Body>
</Layout>
<Divider /> <Divider />
{#if publishedApps.length} {#if publishedApps.length}
<Heading>Apps</Heading> <Heading>Apps</Heading>
@ -137,18 +137,18 @@
overflow: auto; overflow: auto;
} }
.content { .content {
padding: 60px 0;
width: 100%; width: 100%;
} }
.header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
img { img {
width: 40px; width: 40px;
margin-bottom: -12px; margin-bottom: -12px;
} }
.info-title {
display: grid;
grid-template-columns: 1fr auto;
grid-gap: var(--spacing-xl);
}
.avatar { .avatar {
display: grid; display: grid;
grid-template-columns: auto auto; grid-template-columns: auto auto;
@ -160,7 +160,6 @@
filter: brightness(110%); filter: brightness(110%);
} }
.group { .group {
margin-top: var(--spacing-s);
} }
.app { .app {
display: grid; display: grid;

View File

@ -9,6 +9,7 @@
ActionMenu, ActionMenu,
MenuItem, MenuItem,
Modal, Modal,
clickOutside,
} from "@budibase/bbui" } from "@budibase/bbui"
import ConfigChecklist from "components/common/ConfigChecklist.svelte" import ConfigChecklist from "components/common/ConfigChecklist.svelte"
import { organisation, auth } from "stores/portal" import { organisation, auth } from "stores/portal"
@ -21,6 +22,7 @@
let loaded = false let loaded = false
let userInfoModal let userInfoModal
let changePasswordModal let changePasswordModal
let mobileMenuVisible = false
$: menu = buildMenu($auth.isAdmin) $: menu = buildMenu($auth.isAdmin)
@ -71,6 +73,9 @@
return menu return menu
} }
const showMobileMenu = () => (mobileMenuVisible = true)
const hideMobileMenu = () => (mobileMenuVisible = false)
onMount(async () => { onMount(async () => {
// Prevent non-builders from accessing the portal // Prevent non-builders from accessing the portal
if ($auth.user) { if ($auth.user) {
@ -86,7 +91,11 @@
{#if $auth.user && loaded} {#if $auth.user && loaded}
<div class="container"> <div class="container">
<div class="nav"> <div
class="nav"
class:visible={mobileMenuVisible}
use:clickOutside={hideMobileMenu}
>
<Layout paddingX="L" paddingY="L"> <Layout paddingX="L" paddingY="L">
<div class="branding"> <div class="branding">
<div class="name" on:click={() => $goto("./apps")}> <div class="name" on:click={() => $goto("./apps")}>
@ -100,7 +109,12 @@
<div class="menu"> <div class="menu">
<Navigation> <Navigation>
{#each menu as { title, href, heading }} {#each menu as { title, href, heading }}
<Item selected={$isActive(href)} {href} {heading}>{title}</Item> <Item
on:click={hideMobileMenu}
selected={$isActive(href)}
{href}
{heading}>{title}</Item
>
{/each} {/each}
</Navigation> </Navigation>
</div> </div>
@ -108,7 +122,16 @@
</div> </div>
<div class="main"> <div class="main">
<div class="toolbar"> <div class="toolbar">
<div /> <div class="mobile-toggle">
<Icon hoverable name="ShowMenu" on:click={showMobileMenu} />
</div>
<div class="mobile-logo">
<img
src={$organisation?.logoUrl || Logo}
alt={$organisation?.company || "Budibase"}
/>
</div>
<div class="user-dropdown">
<ActionMenu align="right"> <ActionMenu align="right">
<div slot="control" class="avatar"> <div slot="control" class="avatar">
<Avatar <Avatar
@ -133,6 +156,7 @@
<MenuItem icon="LogOut" on:click={auth.logout}>Log out</MenuItem> <MenuItem icon="LogOut" on:click={auth.logout}>Log out</MenuItem>
</ActionMenu> </ActionMenu>
</div> </div>
</div>
<div class="content"> <div class="content">
<slot /> <slot />
</div> </div>
@ -149,16 +173,20 @@
<style> <style>
.container { .container {
height: 100%; height: 100%;
display: grid; display: flex;
grid-template-columns: 250px 1fr; flex-direction: row;
justify-content: flex-start;
align-items: stretch; align-items: stretch;
} }
.nav { .nav {
background: var(--background); background: var(--background);
border-right: var(--border-light); border-right: var(--border-light);
overflow: auto; overflow: auto;
flex: 0 0 auto;
width: 250px;
} }
.main { .main {
flex: 1 1 auto;
display: grid; display: grid;
grid-template-rows: auto 1fr; grid-template-rows: auto 1fr;
overflow: hidden; overflow: hidden;
@ -192,11 +220,21 @@
.toolbar { .toolbar {
background: var(--background); background: var(--background);
border-bottom: var(--border-light); border-bottom: var(--border-light);
display: grid; display: flex;
grid-template-columns: 250px auto; flex-direction: row;
justify-content: space-between; justify-content: space-between;
padding: var(--spacing-m) calc(var(--spacing-xl) * 2);
align-items: center; align-items: center;
padding: var(--spacing-m) calc(var(--spacing-xl) * 2);
}
.mobile-toggle,
.mobile-logo {
display: none;
}
.user-dropdown {
flex: 1 1 auto;
display: flex;
flex-direction: row;
justify-content: flex-end;
} }
img { img {
width: 28px; width: 28px;
@ -210,4 +248,43 @@
.content { .content {
overflow: auto; overflow: auto;
} }
@media (max-width: 640px) {
.toolbar {
background: var(--background);
border-bottom: var(--border-light);
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: var(--spacing-m) calc(var(--spacing-xl) * 1.5);
}
.nav {
position: absolute;
left: -250px;
height: 100%;
transition: left ease-in-out 230ms;
z-index: 100;
}
.nav.visible {
left: 0;
box-shadow: 0 0 80px 20px rgba(0, 0, 0, 0.3);
}
.mobile-toggle,
.mobile-logo {
display: block;
}
.mobile-toggle,
.user-dropdown {
flex: 1 1 0;
}
/* Reduce BBUI page padding */
.content :global(> *) {
padding: calc(var(--spacing-xl) * 1.5) !important;
}
}
</style> </style>

View File

@ -201,7 +201,7 @@
<Heading>Apps</Heading> <Heading>Apps</Heading>
<ButtonGroup> <ButtonGroup>
<Button secondary on:click={initiateAppImport}>Import app</Button> <Button secondary on:click={initiateAppImport}>Import app</Button>
<Button cta on:click={initiateAppCreation}>Create new app</Button> <Button cta on:click={initiateAppCreation}>Create app</Button>
</ButtonGroup> </ButtonGroup>
</div> </div>
<div class="filter"> <div class="filter">
@ -347,4 +347,10 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
@media (max-width: 640px) {
.appTable {
grid-template-columns: 1fr auto;
}
}
</style> </style>

View File

@ -272,7 +272,7 @@
}) })
</script> </script>
<Layout> <Layout noPadding>
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<Heading size="M">Authentication</Heading> <Heading size="M">Authentication</Heading>
<Body> <Body>
@ -285,19 +285,17 @@
<Divider /> <Divider />
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<Heading size="S"> <Heading size="S">
<div> <div class="provider-title">
<GoogleLogo /> <GoogleLogo />
Google <span>Google</span>
<div class="google-save-button">
<div>
<Button <Button
disabled={googleSaveButtonDisabled} disabled={googleSaveButtonDisabled}
size="s" size="s"
cta cta
on:click={() => save([providers.google])}>Save</Button on:click={() => save([providers.google])}
> >
</div> Save
</div> </Button>
</div> </div>
</Heading> </Heading>
<Body size="S"> <Body size="S">
@ -317,12 +315,8 @@
</div> </div>
{/each} {/each}
<div class="form-row"> <div class="form-row">
<div class="field">
<Label size="L">Activated</Label> <Label size="L">Activated</Label>
<span class="alignedToggle">
<Toggle text="" bind:value={providers.google.config.activated} /> <Toggle text="" bind:value={providers.google.config.activated} />
</span>
</div>
</div> </div>
</Layout> </Layout>
{/if} {/if}
@ -330,21 +324,19 @@
<Divider /> <Divider />
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<Heading size="S"> <Heading size="S">
<div> <div class="provider-title">
<OidcLogo /> <OidcLogo />
OpenID Connect <span>OpenID Connect</span>
<div class="oidc-save-button">
<div>
<Button <Button
disabled={oidcSaveButtonDisabled} disabled={oidcSaveButtonDisabled}
size="s" size="s"
cta cta
on:click={() => save([providers.oidc])}>Save</Button on:click={() => save([providers.oidc])}
> >
Save
</Button>
</div> </div>
</div> </Heading>
</div></Heading
>
<Body size="S"> <Body size="S">
To allow users to authenticate using OIDC, fill out the fields below. To allow users to authenticate using OIDC, fill out the fields below.
</Body> </Body>
@ -360,7 +352,8 @@
/> />
</div> </div>
{/each} {/each}
<br /> </Layout>
<Layout gap="XS" noPadding>
<Body size="S"> <Body size="S">
To customize your login button, fill out the fields below. To customize your login button, fill out the fields below.
</Body> </Body>
@ -383,54 +376,37 @@
on:change={e => onFileSelected(e)} on:change={e => onFileSelected(e)}
bind:this={fileinput} bind:this={fileinput}
/> />
</Layout>
<div class="form-row"> <div class="form-row">
<div class="field">
<Label size="L">Activated</Label> <Label size="L">Activated</Label>
<span class="alignedToggle">
<Toggle <Toggle
text="" text=""
bind:value={providers.oidc.config.configs[0].activated} bind:value={providers.oidc.config.configs[0].activated}
/> />
</span>
</div>
</div> </div>
</Layout>
{/if} {/if}
</Layout> </Layout>
<style> <style>
.field {
display: flex;
align-items: center;
}
.alignedToggle {
margin-left: 63%;
}
.form-row { .form-row {
display: grid; display: grid;
grid-template-columns: 20% 1fr; grid-template-columns: 100px 1fr;
grid-gap: var(--spacing-l); grid-gap: var(--spacing-l);
align-items: center; align-items: center;
} }
span {
display: flex;
align-items: center;
gap: var(--spacing-s);
}
input { input[type="file"] {
display: none; display: none;
} }
.google-save-button { .provider-title {
display: inline-block; display: flex;
margin-left: 400px; flex-direction: row;
justify-content: space-between;
align-items: center;
gap: var(--spacing-m);
} }
.provider-title span {
.oidc-save-button { flex: 1 1 auto;
display: inline-block;
margin-left: 320px;
} }
</style> </style>

View File

@ -71,8 +71,9 @@
} }
</script> </script>
<Layout noPadding>
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<div class="back"> <div>
<ActionButton <ActionButton
on:click={() => $goto("./")} on:click={() => $goto("./")}
quiet quiet
@ -88,18 +89,20 @@
</Heading> </Heading>
<Button cta on:click={saveTemplate}>Save</Button> <Button cta on:click={saveTemplate}>Save</Button>
</header> </header>
<Detail>Description</Detail> <Body>
<Body>{description}</Body> {description}
<Body <br />
>Change the email template here. Add dynamic content by using the bindings Change the email template here. Add dynamic content by using the bindings menu
menu on the right.</Body on the right.
> </Body>
</Layout> </Layout>
<div>
<Tabs selected="Edit" on:select={fixMountBug}> <Tabs selected="Edit" on:select={fixMountBug}>
<Tab title="Edit"> <Tab title="Edit">
<div class="template-editor"> <div class="template-editor">
<div class="template-text-editor">
<Editor <Editor
editorHeight={800} editorHeight={640}
bind:this={htmlEditor} bind:this={htmlEditor}
mode="handlebars" mode="handlebars"
on:change={e => { on:change={e => {
@ -107,6 +110,7 @@
}} }}
value={selectedTemplate?.contents} value={selectedTemplate?.contents}
/> />
</div>
<div class="bindings-editor"> <div class="bindings-editor">
<Detail size="L">Bindings</Detail> <Detail size="L">Bindings</Detail>
{#if mounted} {#if mounted}
@ -136,25 +140,40 @@
</div> </div>
</Tab> </Tab>
</Tabs> </Tabs>
</div>
</Layout>
<style> <style>
.template-editor { .template-editor {
display: grid; display: flex;
grid-template-columns: 1fr minmax(250px, 20%); flex-direction: row;
justify-content: flex-start;
align-items: stretch;
flex-wrap: wrap;
grid-gap: var(--spacing-xl); grid-gap: var(--spacing-xl);
margin-top: var(--spacing-xl); margin-top: var(--spacing-xl);
} }
.template-text-editor {
flex: 1 1 0;
min-width: 250px;
}
.bindings-editor {
margin-top: var(--spacing-s);
max-height: 640px;
overflow: auto;
flex: 0 0 300px;
}
header { header {
display: flex; display: flex;
width: 100%; width: 100%;
justify-content: space-between; justify-content: space-between;
margin-top: var(--spacing-l); align-items: flex-start;
} }
.preview { .preview {
height: 800px; height: 640px;
padding: var(--spacing-xl) 0; margin-top: calc(var(--spacing-xl) + var(--spacing-s));
position: relative; position: relative;
} }
iframe { iframe {

View File

@ -107,7 +107,7 @@
fetchSmtp() fetchSmtp()
</script> </script>
<Layout> <Layout noPadding>
<Layout noPadding gap="XS"> <Layout noPadding gap="XS">
<Heading size="M">Email</Heading> <Heading size="M">Email</Heading>
<Body> <Body>
@ -186,7 +186,7 @@
<style> <style>
.form-row { .form-row {
display: grid; display: grid;
grid-template-columns: 25% 1fr; grid-template-columns: 120px 1fr;
grid-gap: var(--spacing-l); grid-gap: var(--spacing-l);
align-items: center; align-items: center;
} }

View File

@ -95,7 +95,7 @@
<Layout noPadding> <Layout noPadding>
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<div class="back"> <div>
<ActionButton <ActionButton
on:click={() => $goto("./")} on:click={() => $goto("./")}
quiet quiet

View File

@ -49,7 +49,7 @@
} }
</script> </script>
<Layout> <Layout noPadding>
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<Heading>Users</Heading> <Heading>Users</Heading>
<Body> <Body>

View File

@ -83,7 +83,7 @@
</script> </script>
{#if $auth.isAdmin} {#if $auth.isAdmin}
<Layout> <Layout noPadding>
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<Heading size="M">Organisation</Heading> <Heading size="M">Organisation</Heading>
<Body> <Body>
@ -99,7 +99,7 @@
</Layout> </Layout>
<div class="fields"> <div class="fields">
<div class="field"> <div class="field">
<Label size="L">Organization name</Label> <Label size="L">Org. name</Label>
<Input thin bind:value={$values.company} /> <Input thin bind:value={$values.company} />
</div> </div>
<div class="field logo"> <div class="field logo">
@ -138,12 +138,10 @@
please let us know below. please let us know below.
</Body> </Body>
</Layout> </Layout>
<div class="fields"> <Toggle
<div class="field"> text="Send Analytics to Budibase"
<Label size="L">Send Analytics to Budibase</Label> bind:value={$values.analytics}
<Toggle text="" bind:value={$values.analytics} /> />
</div>
</div>
<div> <div>
<Button disabled={loading} on:click={saveConfig} cta>Save</Button> <Button disabled={loading} on:click={saveConfig} cta>Save</Button>
</div> </div>
@ -158,7 +156,7 @@
} }
.field { .field {
display: grid; display: grid;
grid-template-columns: 33% 1fr; grid-template-columns: 100px 1fr;
align-items: center; align-items: center;
} }
.file { .file {

View File

@ -4,7 +4,7 @@
import { capitalise } from "helpers" import { capitalise } from "helpers"
</script> </script>
<Layout> <Layout noPadding>
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<Heading size="M">Theming</Heading> <Heading size="M">Theming</Heading>
<Body>Customize how Budibase looks and feels.</Body> <Body>Customize how Budibase looks and feels.</Body>
@ -30,7 +30,7 @@
} }
.field { .field {
display: grid; display: grid;
grid-template-columns: 33% 1fr; grid-template-columns: 120px 1fr;
align-items: center; align-items: center;
} }
</style> </style>

View File

@ -7,6 +7,7 @@
Button, Button,
Divider, Divider,
notifications, notifications,
Label,
} from "@budibase/bbui" } from "@budibase/bbui"
import api from "builderStore/api" import api from "builderStore/api"
import { auth } from "stores/portal" import { auth } from "stores/portal"
@ -47,36 +48,25 @@
</script> </script>
{#if $auth.isAdmin} {#if $auth.isAdmin}
<Layout> <Layout noPadding>
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<Heading size="M">Update</Heading> <Heading size="M">Updates</Heading>
<Body> <Body>
Keep your budibase installation up to date to take advantage of the Keep your budibase installation up to date to take advantage of the
latest features, security updates and much more. latest features, security updates and much more.
</Body> </Body>
</Layout> </Layout>
<Divider size="S" /> <Divider size="S" />
<div class="fields">
<div class="field">
{#if version} {#if version}
Current Version: {version} <div>
<Label size="L">Current version</Label>
<Heading size="XS">
{version}
</Heading>
</div>
{/if} {/if}
</div> <div>
<div class="field"> <Button cta on:click={updateBudibase}>Check for updates</Button>
<Button cta on:click={updateBudibase}>Check For Updates</Button>
</div>
</div> </div>
</Layout> </Layout>
{/if} {/if}
<style>
.fields {
display: grid;
grid-gap: var(--spacing-m);
}
.field {
display: grid;
grid-template-columns: 33% 1fr;
align-items: center;
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff