Add info display in user side panel to warn builders if they haven't published their app

This commit is contained in:
Andrew Kingston 2024-10-24 16:19:43 +01:00
parent c8a7837868
commit be5564621c
No known key found for this signature in database
5 changed files with 56 additions and 25 deletions

View File

@ -25,6 +25,7 @@
appStore, appStore,
deploymentStore, deploymentStore,
sortedScreens, sortedScreens,
appPublished,
} from "stores/builder" } from "stores/builder"
import TourWrap from "components/portal/onboarding/TourWrap.svelte" import TourWrap from "components/portal/onboarding/TourWrap.svelte"
import { TOUR_STEP_KEYS } from "components/portal/onboarding/tours.js" import { TOUR_STEP_KEYS } from "components/portal/onboarding/tours.js"
@ -45,11 +46,6 @@
$: filteredApps = $appsStore.apps.filter(app => app.devId === application) $: filteredApps = $appsStore.apps.filter(app => app.devId === application)
$: selectedApp = filteredApps?.length ? filteredApps[0] : null $: selectedApp = filteredApps?.length ? filteredApps[0] : null
$: latestDeployments = $deploymentStore
.filter(deployment => deployment.status === "SUCCESS")
.sort((a, b) => a.updatedAt > b.updatedAt)
$: isPublished =
selectedApp?.status === "published" && latestDeployments?.length > 0
$: updateAvailable = $: updateAvailable =
$appStore.upgradableVersion && $appStore.upgradableVersion &&
$appStore.version && $appStore.version &&
@ -117,7 +113,7 @@
} }
const confirmUnpublishApp = async () => { const confirmUnpublishApp = async () => {
if (!application || !isPublished) { if (!application || !$appPublished) {
//confirm the app has loaded. //confirm the app has loaded.
return return
} }
@ -204,7 +200,7 @@
> >
<div bind:this={appActionPopoverAnchor}> <div bind:this={appActionPopoverAnchor}>
<div class="app-action"> <div class="app-action">
<Icon name={isPublished ? "GlobeCheck" : "GlobeStrike"} /> <Icon name={$appPublished ? "GlobeCheck" : "GlobeStrike"} />
<TourWrap stepKeys={[TOUR_STEP_KEYS.BUILDER_APP_PUBLISH]}> <TourWrap stepKeys={[TOUR_STEP_KEYS.BUILDER_APP_PUBLISH]}>
<span class="publish-open" id="builder-app-publish-button"> <span class="publish-open" id="builder-app-publish-button">
Publish Publish
@ -219,7 +215,7 @@
<Popover <Popover
bind:this={appActionPopover} bind:this={appActionPopover}
align="right" align="right"
disabled={!isPublished} disabled={!$appPublished}
anchor={appActionPopoverAnchor} anchor={appActionPopoverAnchor}
offset={35} offset={35}
on:close={() => { on:close={() => {
@ -236,13 +232,13 @@
class="app-link" class="app-link"
on:click={() => { on:click={() => {
appActionPopover.hide() appActionPopover.hide()
if (isPublished) { if ($appPublished) {
viewApp() viewApp()
} }
}} }}
> >
{$appStore.url} {$appStore.url}
{#if isPublished} {#if $appPublished}
<Icon size="S" name="LinkOut" /> <Icon size="S" name="LinkOut" />
{/if} {/if}
</span> </span>
@ -250,7 +246,7 @@
<Body size="S"> <Body size="S">
<span class="publish-popover-status"> <span class="publish-popover-status">
{#if isPublished} {#if $appPublished}
<span class="status-text"> <span class="status-text">
{lastDeployed} {lastDeployed}
</span> </span>
@ -279,7 +275,7 @@
</span> </span>
</Body> </Body>
<div class="action-buttons"> <div class="action-buttons">
{#if isPublished} {#if $appPublished}
<ActionButton <ActionButton
quiet quiet
icon="Code" icon="Code"

View File

@ -14,7 +14,7 @@
Button, Button,
FancySelect, FancySelect,
} from "@budibase/bbui" } from "@budibase/bbui"
import { builderStore, appStore, roles } from "stores/builder" import { builderStore, appStore, roles, appPublished } from "stores/builder"
import { import {
groups, groups,
licensing, licensing,
@ -36,6 +36,7 @@
import UpgradeModal from "components/common/users/UpgradeModal.svelte" import UpgradeModal from "components/common/users/UpgradeModal.svelte"
import { emailValidator } from "helpers/validation" import { emailValidator } from "helpers/validation"
import { fly } from "svelte/transition" import { fly } from "svelte/transition"
import InfoDisplay from "../design/[screenId]/[componentId]/_components/Component/InfoDisplay.svelte"
let query = null let query = null
let loaded = false let loaded = false
@ -608,6 +609,17 @@
</div> </div>
<div class="body"> <div class="body">
{#if !$appPublished}
<div class="alert">
<InfoDisplay
icon="AlertCircleFilled"
warning
title="App unpublished"
body="Users won't be able to access your app until you've published it"
/>
</div>
{/if}
{#if promptInvite && !userOnboardResponse} {#if promptInvite && !userOnboardResponse}
<Layout gap="S" paddingX="XL"> <Layout gap="S" paddingX="XL">
<div class="invite-header"> <div class="invite-header">
@ -623,7 +635,7 @@
{/if} {/if}
{#if !promptInvite} {#if !promptInvite}
<Layout gap="L" noPadding> <Layout gap="M" noPadding>
{#if filteredInvites?.length} {#if filteredInvites?.length}
<Layout noPadding gap="XS"> <Layout noPadding gap="XS">
<div class="auth-entity-header"> <div class="auth-entity-header">
@ -926,7 +938,7 @@
.auth-entity, .auth-entity,
.auth-entity-header { .auth-entity-header {
display: grid; display: grid;
grid-template-columns: 1fr 180px; grid-template-columns: 1fr 220px;
align-items: center; align-items: center;
gap: var(--spacing-xl); gap: var(--spacing-xl);
} }
@ -957,7 +969,7 @@
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
position: absolute; position: absolute;
width: 440px; width: 480px;
right: 0; right: 0;
height: 100%; height: 100%;
box-shadow: 0 0 40px 10px rgba(0, 0, 0, 0.1); box-shadow: 0 0 40px 10px rgba(0, 0, 0, 0.1);
@ -1034,4 +1046,7 @@
gap: var(--spacing-xl); gap: var(--spacing-xl);
padding: var(--spacing-xl) 0; padding: var(--spacing-xl) 0;
} }
.alert {
padding: 0 var(--spacing-xl);
}
</style> </style>

View File

@ -7,9 +7,17 @@
export let quiet = false export let quiet = false
export let warning = false export let warning = false
export let error = false export let error = false
export let info = false
</script> </script>
<div class="info" class:noTitle={!title} class:warning class:error class:quiet> <div
class="container"
class:info
class:noTitle={!title}
class:warning
class:error
class:quiet
>
{#if title} {#if title}
<div class="title"> <div class="title">
<Icon name={icon} /> <Icon name={icon} />
@ -27,7 +35,7 @@
</div> </div>
<style> <style>
.info { .container {
padding: var(--spacing-m) var(--spacing-l); padding: var(--spacing-m) var(--spacing-l);
background-color: var(--spectrum-global-color-gray-200); background-color: var(--spectrum-global-color-gray-200);
border-radius: var(--border-radius-s); border-radius: var(--border-radius-s);
@ -39,6 +47,9 @@
.error { .error {
background: rgba(255, 0, 0, 0.2); background: rgba(255, 0, 0, 0.2);
} }
.info {
background: var(--spectrum-global-color-blue-100);
}
.noTitle { .noTitle {
display: flex; display: flex;
align-items: center; align-items: center;
@ -57,13 +68,7 @@
} }
.title, .title,
.icon { .icon {
color: var(--spectrum-global-color-gray-600); color: var(--spectrum-global-color-gray-700);
}
.info {
background-color: var(--background-alt);
padding: var(--spacing-m) var(--spacing-l) var(--spacing-m) var(--spacing-l);
border-radius: var(--border-radius-s);
font-size: 13px;
} }
.quiet { .quiet {
background: none; background: none;

View File

@ -30,6 +30,7 @@ import { queries } from "./queries"
import { flags } from "./flags" import { flags } from "./flags"
import { rowActions } from "./rowActions" import { rowActions } from "./rowActions"
import componentTreeNodesStore from "./componentTreeNodes" import componentTreeNodesStore from "./componentTreeNodes"
import { appPublished } from "./published"
export { export {
componentTreeNodesStore, componentTreeNodesStore,
@ -65,6 +66,7 @@ export {
hoverStore, hoverStore,
snippets, snippets,
rowActions, rowActions,
appPublished,
} }
export const reset = () => { export const reset = () => {

View File

@ -0,0 +1,13 @@
import { appStore } from "./app"
import { appsStore } from "stores/portal/apps"
import { deploymentStore } from "./deployments"
import { derived } from "svelte/store"
export const appPublished = derived(
[appStore, appsStore, deploymentStore],
([$appStore, $appsStore, $deploymentStore]) => {
const app = $appsStore.apps.find(app => app.devId === $appStore.appId)
const deployments = $deploymentStore.filter(x => x.status === "SUCCESS")
return app?.status === "published" && deployments.length > 0
}
)