Add table app list view
This commit is contained in:
parent
93b4a3bd78
commit
e6e47a6d03
|
@ -7,43 +7,28 @@
|
||||||
ActionMenu,
|
ActionMenu,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
Link,
|
Link,
|
||||||
notifications,
|
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import download from "downloadjs"
|
|
||||||
import { gradient } from "actions"
|
import { gradient } from "actions"
|
||||||
|
import { url } from "@roxi/routify"
|
||||||
|
|
||||||
export let name
|
export let app
|
||||||
export let _id
|
export let exportApp
|
||||||
|
|
||||||
let appExportLoading = false
|
let appExportLoading = false
|
||||||
|
|
||||||
async function exportApp() {
|
|
||||||
appExportLoading = true
|
|
||||||
try {
|
|
||||||
download(
|
|
||||||
`/api/backups/export?appId=${_id}&appname=${encodeURIComponent(name)}`
|
|
||||||
)
|
|
||||||
notifications.success("App export complete")
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err)
|
|
||||||
notifications.error("App export failed")
|
|
||||||
} finally {
|
|
||||||
appExportLoading = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Layout noPadding gap="XS">
|
<Layout noPadding gap="XS">
|
||||||
<div class="preview" use:gradient />
|
<div class="preview" use:gradient />
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<Link href={`/builder/app/${_id}`}>
|
<Link href={$url(`../../app/${app._id}`)}>
|
||||||
<Heading size="XS">
|
<Heading size="XS">
|
||||||
{name}
|
{app.name}
|
||||||
</Heading>
|
</Heading>
|
||||||
</Link>
|
</Link>
|
||||||
<ActionMenu>
|
<ActionMenu>
|
||||||
<Icon slot="control" name="More" hoverable />
|
<Icon slot="control" name="More" hoverable />
|
||||||
<MenuItem on:click={exportApp} icon="Download">Export</MenuItem>
|
<MenuItem on:click={() => exportApp(app)} icon="Download">Export</MenuItem
|
||||||
|
>
|
||||||
</ActionMenu>
|
</ActionMenu>
|
||||||
</div>
|
</div>
|
||||||
<div class="status">
|
<div class="status">
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
<script>
|
<script>
|
||||||
import AppCard from "./AppCard.svelte"
|
import AppCard from "./AppCard.svelte"
|
||||||
import { apps } from "stores/portal"
|
import { apps } from "stores/portal"
|
||||||
|
|
||||||
|
export let exportApp
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $apps.length}
|
{#if $apps.length}
|
||||||
<div class="appList">
|
<div class="appList">
|
||||||
{#each $apps as app}
|
{#each $apps as app}
|
||||||
<AppCard {...app} />
|
<AppCard {exportApp} {app} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
|
||||||
<div>No apps found.</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,23 +1,105 @@
|
||||||
<script>
|
<script>
|
||||||
import AppCard from "./AppCard.svelte"
|
|
||||||
import { apps } from "stores/portal"
|
import { apps } from "stores/portal"
|
||||||
import { Table } from "@budibase/bbui"
|
import { gradient } from "actions"
|
||||||
|
import {
|
||||||
|
Heading,
|
||||||
|
Button,
|
||||||
|
Icon,
|
||||||
|
ActionMenu,
|
||||||
|
MenuItem,
|
||||||
|
Link,
|
||||||
|
} from "@budibase/bbui"
|
||||||
|
import { goto, url } from "@roxi/routify"
|
||||||
|
|
||||||
|
export let exportApp
|
||||||
|
|
||||||
|
const openApp = app => {
|
||||||
|
$goto(`../../app/${app._id}`)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $apps.length}
|
{#if $apps.length}
|
||||||
<div class="appList">
|
<div class="appTable">
|
||||||
{#each $apps as app}
|
{#each $apps as app}
|
||||||
<AppCard {...app} />
|
<div class="title">
|
||||||
|
<div class="preview" use:gradient />
|
||||||
|
<Link href={$url(`../../app/${app._id}`)}>
|
||||||
|
<Heading size="XS">
|
||||||
|
{app.name}
|
||||||
|
</Heading>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Edited {Math.round(Math.random() * 10 + 1)} months ago
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{#if Math.random() < 0.33}
|
||||||
|
<div class="status status--open" />
|
||||||
|
Open
|
||||||
|
{:else if Math.random() < 0.33}
|
||||||
|
<div class="status status--locked-other" />
|
||||||
|
Locked by Will Wheaton
|
||||||
|
{:else}
|
||||||
|
<div class="status status--locked-you" />
|
||||||
|
Locked by you
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<Button on:click={() => openApp(app)} size="S" secondary>Open</Button>
|
||||||
|
<ActionMenu align="right">
|
||||||
|
<Icon hoverable slot="control" name="More" />
|
||||||
|
<MenuItem on:click={() => exportApp(app)} icon="Download">
|
||||||
|
Export
|
||||||
|
</MenuItem>
|
||||||
|
</ActionMenu>
|
||||||
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
|
||||||
<div>No apps found.</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.appList {
|
.appTable {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-gap: 50px;
|
grid-template-rows: auto;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
grid-template-columns: 1fr 1fr 1fr auto;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.appTable > div {
|
||||||
|
border-bottom: var(--border-light);
|
||||||
|
height: 70px;
|
||||||
|
display: grid;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-xl);
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
}
|
||||||
|
.preview {
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
border-radius: var(--border-radius-s);
|
||||||
|
}
|
||||||
|
.title :global(a) {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.title :global(h1:hover) {
|
||||||
|
color: var(--spectrum-global-color-blue-600);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 130ms ease;
|
||||||
|
}
|
||||||
|
.status {
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.status--locked-you {
|
||||||
|
background-color: var(--spectrum-global-color-orange-600);
|
||||||
|
}
|
||||||
|
.status--locked-other {
|
||||||
|
background-color: var(--spectrum-global-color-red-600);
|
||||||
|
}
|
||||||
|
.status--open {
|
||||||
|
background-color: var(--spectrum-global-color-green-600);
|
||||||
|
}
|
||||||
|
.actions {
|
||||||
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import Logo from "/assets/bb-logo.svg"
|
import Logo from "/assets/bb-logo.svg"
|
||||||
import { capitalise } from "../../helpers"
|
import { capitalise } from "../../helpers"
|
||||||
|
import { goto } from "@roxi/routify"
|
||||||
|
|
||||||
export let template
|
export let template
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@
|
||||||
}
|
}
|
||||||
const userResp = await api.post(`/api/users/metadata/self`, user)
|
const userResp = await api.post(`/api/users/metadata/self`, user)
|
||||||
await userResp.json()
|
await userResp.json()
|
||||||
window.location = `/builder/app/${appJson._id}`
|
$goto(`/builder/app/${appJson._id}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
notifications.error(error)
|
notifications.error(error)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
Select,
|
Select,
|
||||||
Modal,
|
Modal,
|
||||||
Page,
|
Page,
|
||||||
|
notifications,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import AppGridView from "components/start/AppGridView.svelte"
|
import AppGridView from "components/start/AppGridView.svelte"
|
||||||
import AppTableView from "components/start/AppTableView.svelte"
|
import AppTableView from "components/start/AppTableView.svelte"
|
||||||
|
@ -17,12 +18,13 @@
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { apps } from "stores/portal"
|
import { apps } from "stores/portal"
|
||||||
|
import download from "downloadjs"
|
||||||
|
|
||||||
let layout = "grid"
|
let layout = "grid"
|
||||||
let modal
|
let modal
|
||||||
let template
|
let template
|
||||||
|
|
||||||
async function checkKeys() {
|
const checkKeys = async () => {
|
||||||
const response = await api.get(`/api/keys/`)
|
const response = await api.get(`/api/keys/`)
|
||||||
const keys = await response.json()
|
const keys = await response.json()
|
||||||
if (keys.userId) {
|
if (keys.userId) {
|
||||||
|
@ -30,11 +32,25 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initiateAppImport() {
|
const initiateAppImport = () => {
|
||||||
template = { fromFile: true }
|
template = { fromFile: true }
|
||||||
modal.show()
|
modal.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const exportApp = app => {
|
||||||
|
try {
|
||||||
|
download(
|
||||||
|
`/api/backups/export?appId=${app._id}&appname=${encodeURIComponent(
|
||||||
|
app.name
|
||||||
|
)}`
|
||||||
|
)
|
||||||
|
notifications.success("App export complete")
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
notifications.error("App export failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
checkKeys()
|
checkKeys()
|
||||||
apps.load()
|
apps.load()
|
||||||
|
@ -70,9 +86,9 @@
|
||||||
</ActionGroup>
|
</ActionGroup>
|
||||||
</div>
|
</div>
|
||||||
{#if layout === "grid"}
|
{#if layout === "grid"}
|
||||||
<AppGridView />
|
<AppGridView {exportApp} />
|
||||||
{:else}
|
{:else}
|
||||||
<AppTableView />
|
<AppTableView {exportApp} />
|
||||||
{/if}
|
{/if}
|
||||||
</Layout>
|
</Layout>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
Loading…
Reference in New Issue