Fix loading states and issues with overview tab

This commit is contained in:
Andrew Kingston 2022-08-08 12:08:37 +01:00
parent 3d42c9cfeb
commit 50c04c801f
2 changed files with 225 additions and 225 deletions

View File

@ -34,15 +34,19 @@
export let application export let application
let promise = getPackage()
let loaded = false let loaded = false
let deletionModal let deletionModal
let unpublishModal let unpublishModal
let appName = "" let appName = ""
let deployments = []
// App // App
$: filteredApps = $apps.filter(app => app.devId === application) $: filteredApps = $apps.filter(app => app.devId === application)
$: selectedApp = filteredApps?.length ? filteredApps[0] : null $: selectedApp = filteredApps?.length ? filteredApps[0] : null
$: loaded && !selectedApp && backToAppList()
$: isPublished =
selectedApp?.status === AppStatus.DEPLOYED && latestDeployments?.length > 0
$: appUrl = `${window.origin}/app${selectedApp?.url}`
// Locking // Locking
$: lockedBy = selectedApp?.lockedBy $: lockedBy = selectedApp?.lockedBy
@ -54,18 +58,11 @@
}` }`
// App deployments // App deployments
$: deployments = []
$: latestDeployments = deployments $: latestDeployments = deployments
.filter( .filter(x => x.status === "SUCCESS" && application === x.appId)
deployment =>
deployment.status === "SUCCESS" && application === deployment.appId
)
.sort((a, b) => a.updatedAt > b.updatedAt) .sort((a, b) => a.updatedAt > b.updatedAt)
$: isPublished = // Tabs
selectedApp?.status === AppStatus.DEPLOYED && latestDeployments?.length > 0
$: appUrl = `${window.origin}/app${selectedApp?.url}`
$: tabs = ["Overview", "Automation History", "Backups", "Settings", "Access"] $: tabs = ["Overview", "Automation History", "Backups", "Settings", "Access"]
$: selectedTab = "Overview" $: selectedTab = "Overview"
@ -83,17 +80,6 @@
} }
} }
async function getPackage() {
try {
const pkg = await API.fetchAppPackage(application)
await store.actions.initialise(pkg)
loaded = true
return pkg
} catch (error) {
notifications.error(`Error initialising app: ${error?.message}`)
}
}
const reviewPendingDeployments = (deployments, newDeployments) => { const reviewPendingDeployments = (deployments, newDeployments) => {
if (deployments.length > 0) { if (deployments.length > 0) {
const pending = checkIncomingDeploymentStatus(deployments, newDeployments) const pending = checkIncomingDeploymentStatus(deployments, newDeployments)
@ -185,35 +171,46 @@
appName = null appName = null
} }
onDestroy(() => {
store.actions.reset()
})
onMount(async () => { onMount(async () => {
const params = new URLSearchParams(window.location.search) const params = new URLSearchParams(window.location.search)
if (params.get("tab")) { if (params.get("tab")) {
selectedTab = params.get("tab") selectedTab = params.get("tab")
} }
// Check app exists
try { try {
const pkg = await API.fetchAppPackage(application)
await store.actions.initialise(pkg)
} catch (error) {
// Swallow
backToAppList()
}
// Initialise application
try {
await API.syncApp(application)
deployments = await fetchDeployments()
if (!apps.length) { if (!apps.length) {
await apps.load() await apps.load()
} }
await API.syncApp(application)
deployments = await fetchDeployments()
} catch (error) { } catch (error) {
notifications.error("Error initialising app overview") notifications.error("Error initialising app overview")
} }
loaded = true
})
onDestroy(() => {
store.actions.reset()
}) })
</script> </script>
{#if selectedApp}
<span class="overview-wrap"> <span class="overview-wrap">
<Page wide noPadding> <Page wide noPadding>
{#await promise} {#if !loaded || !selectedApp}
<div class="loading"> <div class="loading">
<ProgressCircle size="XL" /> <ProgressCircle size="XL" />
</div> </div>
{:then _} {:else}
<Layout paddingX="XXL" paddingY="XL" gap="L"> <Layout paddingX="XXL" paddingY="XL" gap="L">
<span class="page-header" class:loaded> <span class="page-header" class:loaded>
<ActionButton secondary icon={"ArrowLeft"} on:click={backToAppList}> <ActionButton secondary icon={"ArrowLeft"} on:click={backToAppList}>
@ -287,10 +284,7 @@
</MenuItem> </MenuItem>
{/if} {/if}
{#if !isPublished} {#if !isPublished}
<MenuItem <MenuItem on:click={() => deleteApp(selectedApp)} icon="Delete">
on:click={() => deleteApp(selectedApp)}
icon="Delete"
>
Delete Delete
</MenuItem> </MenuItem>
{/if} {/if}
@ -358,12 +352,9 @@
> >
Are you sure you want to unpublish the app <b>{selectedApp?.name}</b>? Are you sure you want to unpublish the app <b>{selectedApp?.name}</b>?
</ConfirmDialog> </ConfirmDialog>
{:catch error} {/if}
<p>Something went wrong: {error.message}</p>
{/await}
</Page> </Page>
</span> </span>
{/if}
<style> <style>
.app-url { .app-url {

View File

@ -6,17 +6,26 @@
import clientPackage from "@budibase/client/package.json" import clientPackage from "@budibase/client/package.json"
import { processStringSync } from "@budibase/string-templates" import { processStringSync } from "@budibase/string-templates"
import { users, auth, apps } from "stores/portal" import { users, auth, apps } from "stores/portal"
import { createEventDispatcher, onMount } from "svelte" import { createEventDispatcher } from "svelte"
import { fetchData } from "@budibase/frontend-core"
import { API } from "api"
export let app export let app
export let deployments export let deployments
export let navigateTab export let navigateTab
let userCount
const dispatch = createEventDispatcher()
const unpublishApp = () => { const dispatch = createEventDispatcher()
dispatch("unpublish", app) const appUsersFetch = fetchData({
} API,
datasource: {
type: "user",
},
options: {
query: {
appId: apps.getProdAppID(app.devId),
},
},
})
let appEditor, appEditorPromise let appEditor, appEditorPromise
@ -25,6 +34,11 @@
$: appEditorId = !app?.updatedBy ? $auth.user._id : app?.updatedBy $: appEditorId = !app?.updatedBy ? $auth.user._id : app?.updatedBy
$: appEditorText = appEditor?.firstName || appEditor?.email $: appEditorText = appEditor?.firstName || appEditor?.email
$: fetchAppEditor(appEditorId) $: fetchAppEditor(appEditorId)
$: appUsers = $appUsersFetch.rows || []
const unpublishApp = () => {
dispatch("unpublish", app)
}
async function fetchAppEditor(editorId) { async function fetchAppEditor(editorId) {
appEditorPromise = users.get(editorId) appEditorPromise = users.get(editorId)
@ -36,16 +50,8 @@
initials += user.firstName ? user.firstName[0] : "" initials += user.firstName ? user.firstName[0] : ""
initials += user.lastName ? user.lastName[0] : "" initials += user.lastName ? user.lastName[0] : ""
return initials == "" ? user.email[0] : initials return initials === "" ? user.email[0] : initials
} }
onMount(async () => {
let resp = await users.getUserCountByApp({
appId: apps.getProdAppID(app.devId),
})
userCount = resp.userCount
await users.search({ appId: apps.getProdAppID(app.devId), limit: 4 })
})
</script> </script>
<div class="overview-tab"> <div class="overview-tab">
@ -141,6 +147,7 @@
{/if} {/if}
</div> </div>
</DashCard> </DashCard>
{#if $appUsersFetch.loaded}
<DashCard <DashCard
title={"Access"} title={"Access"}
showIcon={true} showIcon={true}
@ -150,17 +157,18 @@
dataCy={"access"} dataCy={"access"}
> >
<div class="last-edited-content"> <div class="last-edited-content">
{#if $users?.data?.length} {#if appUsers.length}
<Layout noPadding gap="S"> <Layout noPadding gap="S">
<div class="users-tab"> <div class="users-tab">
{#each $users?.data as user} {#each appUsers.slice(0, 4) as user}
<Avatar size="M" initials={getInitials(user)} /> <Avatar size="M" initials={getInitials(user)} />
{/each} {/each}
</div> </div>
<div class="users-text"> <div class="users-text">
{userCount} {appUsers.length}
{userCount > 1 ? `users have` : `user has`} access to this app {appUsers.length > 1 ? `users have` : `user has`} access to this
app
</div> </div>
</Layout> </Layout>
{:else} {:else}
@ -173,6 +181,7 @@
{/if} {/if}
</div> </div>
</DashCard> </DashCard>
{/if}
</div> </div>
{#if false} {#if false}
<div class="bottom"> <div class="bottom">
@ -229,7 +238,7 @@
.users-tab { .users-tab {
display: flex; display: flex;
gap: var(--spacing-m); gap: var(--spacing-s);
} }
.users-text { .users-text {