Update apps list page and app rows to match new styles and behaviours

This commit is contained in:
Andrew Kingston 2022-06-10 12:16:28 +01:00
parent 4219b2251a
commit 3a33f5b376
3 changed files with 20 additions and 180 deletions

View File

@ -87,7 +87,7 @@
{#if lockedByYou && getExpiryDuration(app) > 0}
<span class="lock-expiry-body">
{processStringSync(
"This lock will expire in {{ duration time 'millisecond' }} from now",
"This lock will expire in {{ duration time 'millisecond' }} from now.",
{
time: getExpiryDuration(app),
}
@ -141,4 +141,8 @@
gap: var(--spacing-s);
max-width: 175px;
}
.lock-status-text {
font-weight: 400;
color: var(--spectrum-global-color-gray-800);
}
</style>

View File

@ -1,18 +1,11 @@
<script>
import { Heading, Button, Icon, ActionMenu, MenuItem } from "@budibase/bbui"
import { Heading, Button, Icon } from "@budibase/bbui"
import AppLockModal from "../common/AppLockModal.svelte"
import { processStringSync } from "@budibase/string-templates"
export let app
export let exportApp
export let editApp
export let updateApp
export let deleteApp
export let unpublishApp
export let appOverview
export let releaseLock
export let editIcon
export let copyAppId
</script>
<div class="title" data-cy={`${app.devId}`}>
@ -20,7 +13,7 @@
<div class="app-icon" style="color: {app.icon?.color || ''}">
<Icon size="XL" name={app.icon?.name || "Apps"} />
</div>
<div class="name" data-cy="app-name-link" on:click={() => appOverview(app)}>
<div class="name" data-cy="app-name-link" on:click={() => editApp(app)}>
<Heading size="XS">
{app.name}
</Heading>
@ -37,7 +30,7 @@
{/if}
</div>
<div class="desktop">
<AppLockModal {app} buttonSize="S" />
<AppLockModal {app} buttonSize="M" />
</div>
<div class="desktop">
<div class="app-status">
@ -52,47 +45,27 @@
</div>
<div data-cy={`row_actions_${app.appId}`}>
<div class="app-row-actions">
<Button size="S" secondary newStyles on:click={() => appOverview(app)}>
Manage
</Button>
<Button
size="S"
secondary
quiet
primary
newStyles
disabled={app.lockedOther}
on:click={() => editApp(app)}
>Edit
>
Edit
</Button>
<Button size="S" cta on:click={() => appOverview(app)}>View</Button>
</div>
<ActionMenu align="right" dataCy="app-row-actions-menu-popover">
<span slot="control" class="app-row-actions-icon">
<Icon hoverable name="More" />
</span>
{#if app.lockedYou}
<MenuItem on:click={() => releaseLock(app)} icon="LockOpen">
Release lock
</MenuItem>
{/if}
<MenuItem on:click={() => exportApp(app)} icon="Download">Export</MenuItem>
{#if app.deployed}
<MenuItem on:click={() => unpublishApp(app)} icon="GlobeRemove">
Unpublish
</MenuItem>
<MenuItem on:click={() => copyAppId(app)} icon="Copy">
Copy App ID
</MenuItem>
{/if}
{#if !app.deployed}
<MenuItem on:click={() => updateApp(app)} icon="Edit">Edit</MenuItem>
<MenuItem on:click={() => deleteApp(app)} icon="Delete">Delete</MenuItem>
{/if}
<MenuItem on:click={() => editIcon(app)} icon="Brush">Edit icon</MenuItem>
</ActionMenu>
</div>
<style>
.app-row-actions {
grid-gap: var(--spacing-s);
display: grid;
grid-template-columns: 75px 75px;
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.app-status {
display: grid;

View File

@ -3,20 +3,17 @@
Heading,
Layout,
Button,
Input,
Select,
Modal,
Page,
notifications,
Body,
Search,
Helpers,
} from "@budibase/bbui"
import TemplateDisplay from "components/common/TemplateDisplay.svelte"
import Spinner from "components/common/Spinner.svelte"
import CreateAppModal from "components/start/CreateAppModal.svelte"
import UpdateAppModal from "components/start/UpdateAppModal.svelte"
import ChooseIconModal from "components/start/ChooseIconModal.svelte"
import ExportAppModal from "components/start/ExportAppModal.svelte"
import { store, automationStore } from "builderStore"
@ -25,10 +22,9 @@
import { apps, auth, admin, templates } from "stores/portal"
import download from "downloadjs"
import { goto } from "@roxi/routify"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import AppRow from "components/start/AppRow.svelte"
import { AppStatus } from "constants"
import analytics, { Events, EventSource } from "analytics"
import analytics, { Events } from "analytics"
import Logo from "assets/bb-space-man.svg"
let sortBy = "name"
@ -36,15 +32,11 @@
let selectedApp
let creationModal
let updatingModal
let deletionModal
let unpublishModal
let exportModal
let iconModal
let creatingApp = false
let loaded = $apps?.length || $templates?.length
let searchTerm = ""
let cloud = $admin.cloud
let appName = ""
let creatingFromTemplate = false
const resolveWelcomeMessage = (auth, apps) => {
@ -170,18 +162,6 @@
creatingApp = false
}
const viewApp = app => {
analytics.captureEvent(Events.APP.VIEW_PUBLISHED, {
appId: app.appId,
eventSource: EventSource.PORTAL,
})
if (app.url) {
window.open(`/app${app.url}`)
} else {
window.open(`/${app.prodId}`)
}
}
const appOverview = app => {
$goto(`../overview/${app.devId}`)
}
@ -196,79 +176,6 @@
$goto(`../../app/${app.devId}`)
}
const editIcon = app => {
selectedApp = app
iconModal.show()
}
const exportApp = app => {
exportModal.show()
selectedApp = app
}
const unpublishApp = app => {
selectedApp = app
unpublishModal.show()
}
const confirmUnpublishApp = async () => {
if (!selectedApp) {
return
}
try {
analytics.captureEvent(Events.APP.UNPUBLISHED, {
appId: selectedApp.appId,
})
await API.unpublishApp(selectedApp.prodId)
await apps.load()
notifications.success("App unpublished successfully")
} catch (err) {
notifications.error("Error unpublishing app")
}
}
const deleteApp = app => {
selectedApp = app
deletionModal.show()
}
const confirmDeleteApp = async () => {
if (!selectedApp) {
return
}
try {
await API.deleteApp(selectedApp?.devId)
await apps.load()
// Get checklist, just in case that was the last app
await admin.init()
notifications.success("App deleted successfully")
} catch (err) {
notifications.error("Error deleting app")
}
selectedApp = null
appName = null
}
const updateApp = async app => {
selectedApp = app
updatingModal.show()
}
const releaseLock = async app => {
try {
await API.releaseAppLock(app.devId)
await apps.load()
notifications.success("Lock released successfully")
} catch (err) {
notifications.error("Error releasing lock")
}
}
const copyAppId = async app => {
await Helpers.copyToClipboard(app.prodId)
notifications.success("App ID copied to clipboard.")
}
function createAppFromTemplateUrl(templateKey) {
// validate the template key just to make sure
const templateParts = templateKey.split("/")
@ -416,19 +323,7 @@
<div class="appTable" class:unlocked>
{#each filteredApps as app (app.appId)}
<AppRow
{copyAppId}
{releaseLock}
{editIcon}
{app}
{unpublishApp}
{viewApp}
{editApp}
{exportApp}
{deleteApp}
{updateApp}
{appOverview}
/>
<AppRow {app} {editApp} {appOverview} />
{/each}
</div>
</Layout>
@ -462,35 +357,6 @@
<ExportAppModal app={selectedApp} />
</Modal>
<ConfirmDialog
bind:this={deletionModal}
title="Confirm deletion"
okText="Delete app"
onOk={confirmDeleteApp}
onCancel={() => (appName = null)}
disabled={appName !== selectedApp?.name}
>
Are you sure you want to delete the app <b>{selectedApp?.name}</b>?
<p>Please enter the app name below to confirm.</p>
<Input
bind:value={appName}
data-cy="delete-app-confirmation"
placeholder={selectedApp?.name}
/>
</ConfirmDialog>
<ConfirmDialog
bind:this={unpublishModal}
title="Confirm unpublish"
okText="Unpublish app"
onOk={confirmUnpublishApp}
dataCy={"unpublish-modal"}
>
Are you sure you want to unpublish the app <b>{selectedApp?.name}</b>?
</ConfirmDialog>
<ChooseIconModal app={selectedApp} bind:this={iconModal} />
<style>
.appTable {
border-top: var(--border-light);
@ -547,12 +413,9 @@
height: 70px;
display: grid;
align-items: center;
grid-gap: var(--spacing-xl);
grid-template-columns: auto 1fr;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 0 var(--spacing-s);
}
.appTable :global(> div) {
border-bottom: var(--border-light);