Move app list to admin portal

This commit is contained in:
Andrew Kingston 2021-05-06 13:59:06 +01:00
parent 613f914589
commit 6164f38cf9
7 changed files with 139 additions and 96 deletions

View File

@ -1,11 +1,19 @@
<script>
import { goto } from "@roxi/routify"
import { ActionButton, Heading } from "@budibase/bbui"
import { notifications } from "@budibase/bbui"
import Spinner from "components/common/Spinner.svelte"
import {
Heading,
Icon,
Body,
Layout,
ActionMenu,
MenuItem,
Link,
notifications,
} from "@budibase/bbui"
import download from "downloadjs"
import { gradient } from "actions"
export let name, _id
export let name
export let _id
let appExportLoading = false
@ -15,58 +23,59 @@
download(
`/api/backups/export?appId=${_id}&appname=${encodeURIComponent(name)}`
)
notifications.success("App Export Complete.")
notifications.success("App export complete")
} catch (err) {
console.error(err)
notifications.error("App Export Failed.")
notifications.error("App export failed")
} finally {
appExportLoading = false
}
}
</script>
<div class="apps-card">
<Heading size="S">{name}</Heading>
<div class="card-footer" data-cy={`app-${name}`}>
<ActionButton on:click={() => $goto(`/builder/${_id}`)}>
Open
<Layout noPadding gap="XS">
<div class="preview" use:gradient />
<div class="title">
<Link href={`/builder/${_id}`}>
<Heading size="S">
{name}
</ActionButton>
{#if appExportLoading}
<Spinner size="10" />
{:else}
<ActionButton icon="Download" quiet />
</Heading>
</Link>
<ActionMenu>
<Icon slot="control" name="More" hoverable />
<MenuItem on:click={exportApp} icon="Download">Export</MenuItem>
</ActionMenu>
</div>
<div class="status">
<Body noPadding>Edited {Math.floor(1 + Math.random() * 10)} months ago</Body
>
{#if Math.random() > 0.5}
<Icon name="LockClosed" />
{/if}
</div>
</div>
</Layout>
<style>
.apps-card {
background-color: var(--background);
padding: var(--spacing-xl) var(--spacing-xl) var(--spacing-xl)
var(--spacing-xl);
max-width: 300px;
max-height: 150px;
border-radius: var(--border-radius-m);
border: var(--border-dark);
.preview {
height: 135px;
border-radius: var(--border-radius-s);
margin-bottom: var(--spacing-m);
}
.card-footer {
.title,
.status {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin-top: var(--spacing-m);
align-items: center;
}
i {
font-size: var(--font-size-l);
.title :global(a) {
text-decoration: none;
}
.title :global(h1:hover) {
color: var(--spectrum-global-color-blue-600);
cursor: pointer;
transition: 0.2s all;
}
i:hover {
color: var(--blue);
transition: color 130ms ease;
}
</style>

View File

@ -1,50 +1,25 @@
<script>
import { onMount } from "svelte"
import AppCard from "./AppCard.svelte"
import { Heading, Divider } from "@budibase/bbui"
import Spinner from "components/common/Spinner.svelte"
import { get } from "builderStore/api"
import { apps } from "stores/portal"
let promise = getApps()
async function getApps() {
const res = await get("/api/applications")
const json = await res.json()
if (res.ok) {
return json
} else {
throw new Error(json)
}
}
onMount(apps.load)
</script>
<div class="root">
<Heading size="M">Your Apps</Heading>
<Divider size="M" />
{#await promise}
<div class="spinner-container">
<Spinner size="30" />
</div>
{:then apps}
<div class="apps">
{#each apps as app}
{#if $apps.length}
<div class="appList">
{#each $apps as app}
<AppCard {...app} />
{/each}
</div>
{:catch err}
<h1 style="color:red">{err}</h1>
{/await}
</div>
{:else}
<div>No apps</div>
{/if}
<style>
.root {
margin-top: 10px;
}
.apps {
margin-top: var(--layout-m);
.appList {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-gap: var(--layout-s);
justify-content: start;
grid-gap: 50px;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
</style>

View File

@ -1,6 +1,5 @@
<script>
import api from "builderStore/api"
import AppList from "components/start/AppList.svelte"
import { get } from "builderStore/api"
import CreateAppModal from "components/start/CreateAppModal.svelte"
import { Button, Heading, Modal, ButtonGroup } from "@budibase/bbui"
@ -72,8 +71,6 @@
</div>
<!-- <TemplateList onSelect={selectTemplate} /> -->
<AppList />
</div>
<Modal bind:this={modal} padding={false} width="600px" on:hide={closeModal}>

View File

@ -10,8 +10,11 @@
SideNavigation as Navigation,
SideNavigationItem as Item,
} from "@budibase/bbui"
import { organisation } from "stores/portal"
import { organisation, apps } from "stores/portal"
organisation.init()
apps.load()
console.log("loading")
let onBoardingProgress, user

View File

@ -1,27 +1,58 @@
<script>
import { Heading, Layout } from "@budibase/bbui"
import {
Heading,
Layout,
Button,
ActionButton,
ActionGroup,
Select,
} from "@budibase/bbui"
import AppList from "components/start/AppList.svelte"
let layout = "grid"
</script>
<Layout noPadding>
<div>
<div class="title">
<Heading>Apps</Heading>
<Button primary>Create new app</Button>
</div>
<div class="appList">
{#each new Array(10) as _}
<div class="app" />
{/each}
<div class="filter">
<div class="select">
<Select quiet placeholder="Filter by groups" />
</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>
{#if layout === "grid"}
<AppList />
{:else}
Table
{/if}
</Layout>
<style>
.appList {
display: grid;
grid-gap: 50px;
grid-template-columns: repeat(auto-fill, 300px);
.title,
.filter {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.app {
height: 130px;
border-radius: 4px;
background-color: var(--spectrum-global-color-gray-200);
.select {
width: 110px;
}
</style>

View File

@ -0,0 +1,27 @@
import { writable } from "svelte/store"
import { get } from "builderStore/api"
export function createAppStore() {
const store = writable([])
async function load() {
try {
const res = await get("/api/applications")
const json = await res.json()
if (res.ok && Array.isArray(json)) {
store.set(json)
} else {
store.set([])
}
} catch (error) {
store.set([])
}
}
return {
subscribe: store.subscribe,
load,
}
}
export const apps = createAppStore()

View File

@ -1,2 +1,3 @@
export { organisation } from "./organisation"
export { admin } from "./admin"
export { apps } from "./apps"