Update top bar when not the primary builder and prevent flashing during loading states

This commit is contained in:
Andrew Kingston 2023-05-12 14:16:10 +01:00
parent 7f96fbf741
commit 5f81584a14
3 changed files with 182 additions and 155 deletions

View File

@ -39,6 +39,7 @@ import { makePropSafe as safe } from "@budibase/string-templates"
import { getComponentFieldOptions } from "helpers/formFields" import { getComponentFieldOptions } from "helpers/formFields"
const INITIAL_FRONTEND_STATE = { const INITIAL_FRONTEND_STATE = {
initialised: false,
apps: [], apps: [],
name: "", name: "",
url: "", url: "",
@ -70,6 +71,7 @@ const INITIAL_FRONTEND_STATE = {
previewDevice: "desktop", previewDevice: "desktop",
highlightedSettingKey: null, highlightedSettingKey: null,
builderSidePanel: false, builderSidePanel: false,
hasLock: true,
// URL params // URL params
selectedScreenId: null, selectedScreenId: null,
@ -112,7 +114,7 @@ export const getFrontendStore = () => {
store.set({ ...INITIAL_FRONTEND_STATE }) store.set({ ...INITIAL_FRONTEND_STATE })
}, },
initialise: async pkg => { initialise: async pkg => {
const { layouts, screens, application, clientLibPath } = pkg const { layouts, screens, application, clientLibPath, hasLock } = pkg
await store.actions.components.refreshDefinitions(application.appId) await store.actions.components.refreshDefinitions(application.appId)
@ -137,6 +139,8 @@ export const getFrontendStore = () => {
upgradableVersion: application.upgradableVersion, upgradableVersion: application.upgradableVersion,
navigation: application.navigation || {}, navigation: application.navigation || {},
usedPlugins: application.usedPlugins || [], usedPlugins: application.usedPlugins || [],
hasLock,
initialised: true,
})) }))
screenHistoryStore.reset() screenHistoryStore.reset()
automationHistoryStore.reset() automationHistoryStore.reset()

View File

@ -113,109 +113,113 @@
}) })
</script> </script>
<div class="action-top-nav"> {#if $store.hasLock}
<div class="action-buttons"> <div class="action-top-nav">
<div class="version"> <div class="action-buttons">
<VersionModal /> <div class="version">
</div> <VersionModal />
<RevertModal />
{#if isPublished}
<div class="publish-popover">
<div bind:this={publishPopoverAnchor}>
<ActionButton
quiet
icon="Globe"
size="M"
tooltip="Your published app"
on:click={publishPopover.show()}
/>
</div>
<Popover
bind:this={publishPopover}
align="right"
disabled={!isPublished}
anchor={publishPopoverAnchor}
offset={10}
>
<div class="popover-content">
<Layout noPadding gap="M">
<Heading size="XS">Your published app</Heading>
<Body size="S">
<span class="publish-popover-message">
{processStringSync(
"Last published {{ duration time 'millisecond' }} ago",
{
time:
new Date().getTime() -
new Date(latestDeployments[0].updatedAt).getTime(),
}
)}
</span>
</Body>
<div class="buttons">
<Button
warning={true}
icon="GlobeStrike"
disabled={!isPublished}
on:click={unpublishApp}
>
Unpublish
</Button>
<Button cta on:click={viewApp}>View app</Button>
</div>
</Layout>
</div>
</Popover>
</div> </div>
{/if} <RevertModal />
{#if !isPublished} {#if isPublished}
<ActionButton <div class="publish-popover">
quiet <div bind:this={publishPopoverAnchor}>
icon="GlobeStrike" <ActionButton
size="M" quiet
tooltip="Your app has not been published yet" icon="Globe"
disabled size="M"
/> tooltip="Your published app"
{/if} on:click={publishPopover.show()}
/>
</div>
<Popover
bind:this={publishPopover}
align="right"
disabled={!isPublished}
anchor={publishPopoverAnchor}
offset={10}
>
<div class="popover-content">
<Layout noPadding gap="M">
<Heading size="XS">Your published app</Heading>
<Body size="S">
<span class="publish-popover-message">
{processStringSync(
"Last published {{ duration time 'millisecond' }} ago",
{
time:
new Date().getTime() -
new Date(latestDeployments[0].updatedAt).getTime(),
}
)}
</span>
</Body>
<div class="buttons">
<Button
warning={true}
icon="GlobeStrike"
disabled={!isPublished}
on:click={unpublishApp}
>
Unpublish
</Button>
<Button cta on:click={viewApp}>View app</Button>
</div>
</Layout>
</div>
</Popover>
</div>
{/if}
<TourWrap {#if !isPublished}
tourStepKey={$store.onboarding
? TOUR_STEP_KEYS.BUILDER_USER_MANAGEMENT
: TOUR_STEP_KEYS.FEATURE_USER_MANAGEMENT}
>
<span id="builder-app-users-button">
<ActionButton <ActionButton
quiet quiet
icon="UserGroup" icon="GlobeStrike"
size="M" size="M"
on:click={() => { tooltip="Your app has not been published yet"
store.update(state => { disabled
state.builderSidePanel = true />
return state {/if}
})
}}
>
Users
</ActionButton>
</span>
</TourWrap>
</div>
</div>
<ConfirmDialog <TourWrap
bind:this={unpublishModal} tourStepKey={$store.onboarding
title="Confirm unpublish" ? TOUR_STEP_KEYS.BUILDER_USER_MANAGEMENT
okText="Unpublish app" : TOUR_STEP_KEYS.FEATURE_USER_MANAGEMENT}
onOk={confirmUnpublishApp} >
> <span id="builder-app-users-button">
Are you sure you want to unpublish the app <b>{selectedApp?.name}</b>? <ActionButton
</ConfirmDialog> quiet
icon="UserGroup"
size="M"
on:click={() => {
store.update(state => {
state.builderSidePanel = true
return state
})
}}
>
Users
</ActionButton>
</span>
</TourWrap>
</div>
</div>
<ConfirmDialog
bind:this={unpublishModal}
title="Confirm unpublish"
okText="Unpublish app"
onOk={confirmUnpublishApp}
>
Are you sure you want to unpublish the app <b>{selectedApp?.name}</b>?
</ConfirmDialog>
{/if}
<div class="buttons"> <div class="buttons">
<Button on:click={previewApp} secondary>Preview</Button> <Button on:click={previewApp} secondary>Preview</Button>
<DeployModal onOk={completePublish} /> {#if $store.hasLock}
<DeployModal onOk={completePublish} />
{/if}
</div> </div>
<style> <style>

View File

@ -134,68 +134,80 @@
<div class="root"> <div class="root">
<div class="top-nav"> <div class="top-nav">
<div class="topleftnav"> {#if $store.initialised}
<ActionMenu> <div class="topleftnav">
<div slot="control"> <ActionMenu>
<Icon size="M" hoverable name="ShowMenu" /> <div slot="control">
</div> <Icon size="M" hoverable name="ShowMenu" />
<MenuItem on:click={() => $goto("../../portal/apps")}> </div>
Exit to portal <MenuItem on:click={() => $goto("../../portal/apps")}>
</MenuItem> Exit to portal
<MenuItem </MenuItem>
on:click={() => $goto(`../../portal/overview/${application}`)} <MenuItem
> on:click={() => $goto(`../../portal/overview/${application}`)}
Overview >
</MenuItem> Overview
<MenuItem </MenuItem>
on:click={() => $goto(`../../portal/overview/${application}/access`)} <MenuItem
> on:click={() =>
Access $goto(`../../portal/overview/${application}/access`)}
</MenuItem> >
<MenuItem Access
on:click={() => </MenuItem>
$goto(`../../portal/overview/${application}/automation-history`)} <MenuItem
> on:click={() =>
Automation history $goto(`../../portal/overview/${application}/automation-history`)}
</MenuItem> >
<MenuItem Automation history
on:click={() => $goto(`../../portal/overview/${application}/backups`)} </MenuItem>
> <MenuItem
Backups on:click={() =>
</MenuItem> $goto(`../../portal/overview/${application}/backups`)}
>
Backups
</MenuItem>
<MenuItem <MenuItem
on:click={() => on:click={() =>
$goto(`../../portal/overview/${application}/name-and-url`)} $goto(`../../portal/overview/${application}/name-and-url`)}
> >
Name and URL Name and URL
</MenuItem> </MenuItem>
<MenuItem <MenuItem
on:click={() => $goto(`../../portal/overview/${application}/version`)} on:click={() =>
> $goto(`../../portal/overview/${application}/version`)}
Version >
</MenuItem> Version
</ActionMenu> </MenuItem>
<Heading size="XS">{$store.name}</Heading> </ActionMenu>
</div> <Heading size="XS">{$store.name}</Heading>
<div class="topcenternav"> </div>
<Tabs {selected} size="M"> <div class="topcenternav">
{#each $layout.children as { path, title }} {#if $store.hasLock}
<TourWrap tourStepKey={`builder-${title}-section`}> <Tabs {selected} size="M">
<Tab {#each $layout.children as { path, title }}
quiet <TourWrap tourStepKey={`builder-${title}-section`}>
selected={$isActive(path)} <Tab
on:click={topItemNavigate(path)} quiet
title={capitalise(title)} selected={$isActive(path)}
id={`builder-${title}-tab`} on:click={topItemNavigate(path)}
/> title={capitalise(title)}
</TourWrap> id={`builder-${title}-tab`}
{/each} />
</Tabs> </TourWrap>
</div> {/each}
<div class="toprightnav"> </Tabs>
<AppActions {application} /> {:else}
</div> <div class="secondary-editor">
<Icon name="LockClosed" />
Another user is currently editing your screens and automations
</div>
{/if}
</div>
<div class="toprightnav">
<AppActions {application} />
</div>
{/if}
</div> </div>
{#await promise} {#await promise}
<!-- This should probably be some kind of loading state? --> <!-- This should probably be some kind of loading state? -->
@ -270,4 +282,11 @@
align-items: center; align-items: center;
gap: var(--spacing-l); gap: var(--spacing-l);
} }
.secondary-editor {
align-self: center;
display: flex;
flex-direction: row;
gap: 8px;
}
</style> </style>