Move app list to admin portal
This commit is contained in:
parent
845054a5b1
commit
69345b0c01
|
@ -1,11 +1,19 @@
|
||||||
<script>
|
<script>
|
||||||
import { goto } from "@roxi/routify"
|
import {
|
||||||
import { ActionButton, Heading } from "@budibase/bbui"
|
Heading,
|
||||||
import { notifications } from "@budibase/bbui"
|
Icon,
|
||||||
import Spinner from "components/common/Spinner.svelte"
|
Body,
|
||||||
|
Layout,
|
||||||
|
ActionMenu,
|
||||||
|
MenuItem,
|
||||||
|
Link,
|
||||||
|
notifications,
|
||||||
|
} from "@budibase/bbui"
|
||||||
import download from "downloadjs"
|
import download from "downloadjs"
|
||||||
|
import { gradient } from "actions"
|
||||||
|
|
||||||
export let name, _id
|
export let name
|
||||||
|
export let _id
|
||||||
|
|
||||||
let appExportLoading = false
|
let appExportLoading = false
|
||||||
|
|
||||||
|
@ -15,58 +23,59 @@
|
||||||
download(
|
download(
|
||||||
`/api/backups/export?appId=${_id}&appname=${encodeURIComponent(name)}`
|
`/api/backups/export?appId=${_id}&appname=${encodeURIComponent(name)}`
|
||||||
)
|
)
|
||||||
notifications.success("App Export Complete.")
|
notifications.success("App export complete")
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
notifications.error("App Export Failed.")
|
notifications.error("App export failed")
|
||||||
} finally {
|
} finally {
|
||||||
appExportLoading = false
|
appExportLoading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="apps-card">
|
<Layout noPadding gap="XS">
|
||||||
<Heading size="S">{name}</Heading>
|
<div class="preview" use:gradient />
|
||||||
<div class="card-footer" data-cy={`app-${name}`}>
|
<div class="title">
|
||||||
<ActionButton on:click={() => $goto(`/builder/${_id}`)}>
|
<Link href={`/builder/${_id}`}>
|
||||||
Open
|
<Heading size="S">
|
||||||
{name}
|
{name}
|
||||||
→
|
</Heading>
|
||||||
</ActionButton>
|
</Link>
|
||||||
{#if appExportLoading}
|
<ActionMenu>
|
||||||
<Spinner size="10" />
|
<Icon slot="control" name="More" hoverable />
|
||||||
{:else}
|
<MenuItem on:click={exportApp} icon="Download">Export</MenuItem>
|
||||||
<ActionButton icon="Download" quiet />
|
</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}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Layout>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.apps-card {
|
.preview {
|
||||||
background-color: var(--background);
|
height: 135px;
|
||||||
padding: var(--spacing-xl) var(--spacing-xl) var(--spacing-xl)
|
border-radius: var(--border-radius-s);
|
||||||
var(--spacing-xl);
|
margin-bottom: var(--spacing-m);
|
||||||
max-width: 300px;
|
|
||||||
max-height: 150px;
|
|
||||||
border-radius: var(--border-radius-m);
|
|
||||||
border: var(--border-dark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-footer {
|
.title,
|
||||||
|
.status {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-top: var(--spacing-m);
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
.title :global(a) {
|
||||||
font-size: var(--font-size-l);
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.title :global(h1:hover) {
|
||||||
|
color: var(--spectrum-global-color-blue-600);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: 0.2s all;
|
transition: color 130ms ease;
|
||||||
}
|
|
||||||
|
|
||||||
i:hover {
|
|
||||||
color: var(--blue);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,50 +1,25 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { onMount } from "svelte"
|
||||||
import AppCard from "./AppCard.svelte"
|
import AppCard from "./AppCard.svelte"
|
||||||
import { Heading, Divider } from "@budibase/bbui"
|
import { apps } from "stores/portal"
|
||||||
import Spinner from "components/common/Spinner.svelte"
|
|
||||||
import { get } from "builderStore/api"
|
|
||||||
|
|
||||||
let promise = getApps()
|
onMount(apps.load)
|
||||||
|
|
||||||
async function getApps() {
|
|
||||||
const res = await get("/api/applications")
|
|
||||||
const json = await res.json()
|
|
||||||
|
|
||||||
if (res.ok) {
|
|
||||||
return json
|
|
||||||
} else {
|
|
||||||
throw new Error(json)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
{#if $apps.length}
|
||||||
<Heading size="M">Your Apps</Heading>
|
<div class="appList">
|
||||||
<Divider size="M" />
|
{#each $apps as app}
|
||||||
{#await promise}
|
|
||||||
<div class="spinner-container">
|
|
||||||
<Spinner size="30" />
|
|
||||||
</div>
|
|
||||||
{:then apps}
|
|
||||||
<div class="apps">
|
|
||||||
{#each apps as app}
|
|
||||||
<AppCard {...app} />
|
<AppCard {...app} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{:catch err}
|
{:else}
|
||||||
<h1 style="color:red">{err}</h1>
|
<div>No apps</div>
|
||||||
{/await}
|
{/if}
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.root {
|
.appList {
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
.apps {
|
|
||||||
margin-top: var(--layout-m);
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
grid-gap: 50px;
|
||||||
grid-gap: var(--layout-s);
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
justify-content: start;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import AppList from "components/start/AppList.svelte"
|
|
||||||
import { get } from "builderStore/api"
|
import { get } from "builderStore/api"
|
||||||
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
||||||
import { Button, Heading, Modal, ButtonGroup } from "@budibase/bbui"
|
import { Button, Heading, Modal, ButtonGroup } from "@budibase/bbui"
|
||||||
|
@ -72,8 +71,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <TemplateList onSelect={selectTemplate} /> -->
|
<!-- <TemplateList onSelect={selectTemplate} /> -->
|
||||||
|
|
||||||
<AppList />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Modal bind:this={modal} padding={false} width="600px" on:hide={closeModal}>
|
<Modal bind:this={modal} padding={false} width="600px" on:hide={closeModal}>
|
||||||
|
|
|
@ -10,8 +10,11 @@
|
||||||
SideNavigation as Navigation,
|
SideNavigation as Navigation,
|
||||||
SideNavigationItem as Item,
|
SideNavigationItem as Item,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { organisation } from "stores/portal"
|
import { organisation, apps } from "stores/portal"
|
||||||
organisation.init()
|
organisation.init()
|
||||||
|
apps.load()
|
||||||
|
|
||||||
|
console.log("loading")
|
||||||
|
|
||||||
let onBoardingProgress, user
|
let onBoardingProgress, user
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,58 @@
|
||||||
<script>
|
<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>
|
</script>
|
||||||
|
|
||||||
<Layout noPadding>
|
<Layout noPadding>
|
||||||
<div>
|
<div class="title">
|
||||||
<Heading>Apps</Heading>
|
<Heading>Apps</Heading>
|
||||||
|
<Button primary>Create new app</Button>
|
||||||
</div>
|
</div>
|
||||||
<div class="appList">
|
<div class="filter">
|
||||||
{#each new Array(10) as _}
|
<div class="select">
|
||||||
<div class="app" />
|
<Select quiet placeholder="Filter by groups" />
|
||||||
{/each}
|
|
||||||
</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>
|
||||||
|
{#if layout === "grid"}
|
||||||
|
<AppList />
|
||||||
|
{:else}
|
||||||
|
Table
|
||||||
|
{/if}
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.appList {
|
.title,
|
||||||
display: grid;
|
.filter {
|
||||||
grid-gap: 50px;
|
display: flex;
|
||||||
grid-template-columns: repeat(auto-fill, 300px);
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
.app {
|
|
||||||
height: 130px;
|
.select {
|
||||||
border-radius: 4px;
|
width: 110px;
|
||||||
background-color: var(--spectrum-global-color-gray-200);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -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()
|
|
@ -1,2 +1,3 @@
|
||||||
export { organisation } from "./organisation"
|
export { organisation } from "./organisation"
|
||||||
export { admin } from "./admin"
|
export { admin } from "./admin"
|
||||||
|
export { apps } from "./apps"
|
||||||
|
|
Loading…
Reference in New Issue