initial home screen redesign layout

This commit is contained in:
Peter Clement 2021-12-06 11:55:23 +00:00
parent 68978c5ed1
commit 53557e1bb1
2 changed files with 104 additions and 92 deletions

View File

@ -1,14 +1,6 @@
<script> <script>
import { gradient } from "actions" import { gradient } from "actions"
import { import { Heading, Button, Icon, ActionMenu, MenuItem } from "@budibase/bbui"
Heading,
Button,
Icon,
ActionMenu,
MenuItem,
StatusLight,
} from "@budibase/bbui"
import { processStringSync } from "@budibase/string-templates"
export let app export let app
export let exportApp export let exportApp
@ -28,40 +20,15 @@
</Heading> </Heading>
</div> </div>
</div> </div>
<div class="desktop"> <div class="desktop" />
{#if app.updatedAt} <div class="desktop" />
{processStringSync("Updated {{ duration time 'millisecond' }} ago", { <div class="desktop" />
time: new Date().getTime() - new Date(app.updatedAt).getTime(),
})}
{:else}
Never updated
{/if}
</div>
<div class="desktop">
<StatusLight
positive={!app.lockedYou && !app.lockedOther}
notice={app.lockedYou}
negative={app.lockedOther}
>
{#if app.lockedYou}
Locked by you
{:else if app.lockedOther}
Locked by {app.lockedBy.email}
{:else}
Open
{/if}
</StatusLight>
</div>
<div class="desktop">
<StatusLight active={app.deployed} neutral={!app.deployed}>
{#if app.deployed}Published{:else}Unpublished{/if}
</StatusLight>
</div>
<div> <div>
<Button <Button
disabled={app.lockedOther} disabled={app.lockedOther}
on:click={() => editApp(app)} on:click={() => editApp(app)}
size="S" size="S"
quiet
secondary>Open</Button secondary>Open</Button
> >
<ActionMenu align="right"> <ActionMenu align="right">

View File

@ -2,15 +2,15 @@
import { import {
Heading, Heading,
Layout, Layout,
Detail,
Button, Button,
ActionButton,
ActionGroup,
ButtonGroup, ButtonGroup,
Input, Input,
Select, Select,
Modal, Modal,
Page, Page,
notifications, notifications,
Body,
Search, Search,
} from "@budibase/bbui" } from "@budibase/bbui"
import Spinner from "components/common/Spinner.svelte" import Spinner from "components/common/Spinner.svelte"
@ -23,12 +23,10 @@
import download from "downloadjs" import download from "downloadjs"
import { goto } from "@roxi/routify" import { goto } from "@roxi/routify"
import ConfirmDialog from "components/common/ConfirmDialog.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import AppCard from "components/start/AppCard.svelte"
import AppRow from "components/start/AppRow.svelte" import AppRow from "components/start/AppRow.svelte"
import { AppStatus } from "constants" import { AppStatus } from "constants"
import analytics, { Events } from "analytics" import analytics, { Events } from "analytics"
let layout = "grid"
let sortBy = "name" let sortBy = "name"
let template let template
let selectedApp let selectedApp
@ -42,7 +40,7 @@
let cloud = $admin.cloud let cloud = $admin.cloud
let appName = "" let appName = ""
let creatingFromTemplate = false let creatingFromTemplate = false
let templates = []
$: enrichedApps = enrichApps($apps, $auth.user, sortBy) $: enrichedApps = enrichApps($apps, $auth.user, sortBy)
$: filteredApps = enrichedApps.filter(app => $: filteredApps = enrichedApps.filter(app =>
app?.name?.toLowerCase().includes(searchTerm.toLowerCase()) app?.name?.toLowerCase().includes(searchTerm.toLowerCase())
@ -260,8 +258,15 @@
} }
} }
async function fetchTemplates() {
const response = await api.get("/api/templates?type=app")
templates = await response.json()
console.log(templates)
}
onMount(async () => { onMount(async () => {
await apps.load() await apps.load()
await fetchTemplates()
// if the portal is loaded from an external URL with a template param // if the portal is loaded from an external URL with a template param
const initInfo = await auth.getInitInfo() const initInfo = await auth.getInitInfo()
if (initInfo?.init_template) { if (initInfo?.init_template) {
@ -274,10 +279,10 @@
</script> </script>
<Page wide> <Page wide>
{#if loaded && enrichedApps.length} <Layout gap="S" noPadding>
<Layout noPadding>
<div class="title"> <div class="title">
<Heading>Apps</Heading> <Heading size="S">Welcome to Budibase</Heading>
<ButtonGroup> <ButtonGroup>
{#if cloud} {#if cloud}
<Button secondary on:click={initiateAppsExport}>Export apps</Button> <Button secondary on:click={initiateAppsExport}>Export apps</Button>
@ -286,6 +291,38 @@
<Button cta on:click={initiateAppCreation}>Create app</Button> <Button cta on:click={initiateAppCreation}>Create app</Button>
</ButtonGroup> </ButtonGroup>
</div> </div>
<Body size="XS">Manage your apps and get a head start with templates</Body>
<Detail>Quick Start Templates</Detail>
<div class="grid">
{#each templates as val}
<div class="template-card">
<div class="card-body">
<div style="color: {val.background}" class="iconAlign">
<svg
width="26px"
height="26px"
class="spectrum-Icon"
style="color:{val.background};"
focusable="false"
>
<use xlink:href="#spectrum-icon-18-{val.icon}" />
</svg>
</div>
<div class="iconAlign">
<Body weight="900" size="XS">{val.name}</Body>
<div style="font-size: 10px;">
<Body size="XS">{val.category.toUpperCase()}</Body>
</div>
</div>
</div>
</div>
{/each}
</div>
{#if loaded && enrichedApps.length}
<div class="title">
<Detail>My Apps</Detail>
</div>
<div class="filter"> <div class="filter">
<div class="select"> <div class="select">
<Select <Select
@ -302,31 +339,14 @@
<Search placeholder="Search" bind:value={searchTerm} /> <Search placeholder="Search" bind:value={searchTerm} />
</div> </div>
</div> </div>
<ActionGroup>
<ActionButton
on:click={() => (layout = "grid")}
selected={layout === "grid"}
quiet
icon="ClassicGridView"
/>
<ActionButton
on:click={() => (layout = "table")}
selected={layout === "table"}
quiet
icon="ViewRow"
/>
</ActionGroup>
</div> </div>
<div class="mobile-search"> <div class="mobile-search">
<Search placeholder="Search" bind:value={searchTerm} /> <Search placeholder="Search" bind:value={searchTerm} />
</div> </div>
<div <div class="appTable">
class:appGrid={layout === "grid"}
class:appTable={layout === "table"}
>
{#each filteredApps as app (app.appId)} {#each filteredApps as app (app.appId)}
<svelte:component <svelte:component
this={layout === "grid" ? AppCard : AppRow} this={AppRow}
{releaseLock} {releaseLock}
{app} {app}
{unpublishApp} {unpublishApp}
@ -338,7 +358,6 @@
/> />
{/each} {/each}
</div> </div>
</Layout>
{/if} {/if}
{#if !enrichedApps.length && !creatingApp && loaded} {#if !enrichedApps.length && !creatingApp && loaded}
<div class="empty-wrapper"> <div class="empty-wrapper">
@ -353,6 +372,7 @@
<Spinner size="10" /> <Spinner size="10" />
</div> </div>
{/if} {/if}
</Layout>
</Page> </Page>
<Modal <Modal
bind:this={creationModal} bind:this={creationModal}
@ -405,6 +425,36 @@
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
} }
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
.iconAlign {
padding: 0 0 0 var(--spacing-m);
display: inline-block;
}
.template-card {
height: 60px;
width: 255px;
border-radius: var(--border-radius-s);
margin-bottom: var(--spacing-m);
border: 1px solid var(--spectrum-global-color-gray-300);
}
.card-body {
display: flex;
align-items: center;
padding: 12px;
}
.grid {
display: grid;
grid-gap: 5px;
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
}
@media (min-width: 200px) {
} }
.select { .select {
@ -419,11 +469,6 @@
display: none; display: none;
} }
.appGrid {
display: grid;
grid-gap: 50px;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.appTable { .appTable {
display: grid; display: grid;
grid-template-rows: auto; grid-template-rows: auto;