Merge commit
This commit is contained in:
parent
0dda7afee7
commit
e8f28113da
1 changed files with 271 additions and 100 deletions
|
@ -7,9 +7,15 @@
|
||||||
Body,
|
Body,
|
||||||
Button,
|
Button,
|
||||||
ActionButton,
|
ActionButton,
|
||||||
|
Icon,
|
||||||
|
Link,
|
||||||
|
Modal,
|
||||||
|
StatusLight,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import RevertModal from "components/deploy/RevertModal.svelte"
|
import RevertModal from "components/deploy/RevertModal.svelte"
|
||||||
import VersionModal from "components/deploy/VersionModal.svelte"
|
import VersionModal from "components/deploy/VersionModal.svelte"
|
||||||
|
import UpdateAppModal from "components/start/UpdateAppModal.svelte"
|
||||||
|
|
||||||
import { processStringSync } from "@budibase/string-templates"
|
import { processStringSync } from "@budibase/string-templates"
|
||||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
import analytics, { Events, EventSource } from "analytics"
|
import analytics, { Events, EventSource } from "analytics"
|
||||||
|
@ -21,16 +27,22 @@
|
||||||
import { store } from "builderStore"
|
import { store } from "builderStore"
|
||||||
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"
|
||||||
|
import { url, goto } from "@roxi/routify"
|
||||||
|
|
||||||
export let application
|
export let application
|
||||||
|
|
||||||
let publishPopover
|
|
||||||
let publishPopoverAnchor
|
|
||||||
let unpublishModal
|
let unpublishModal
|
||||||
|
let updateAppModal
|
||||||
|
let revertModal
|
||||||
|
let versionModal
|
||||||
|
|
||||||
$: filteredApps = $apps.filter(
|
let appActionPopover
|
||||||
app => app.devId === application && app.status === "published"
|
let appActionPopoverOpen = false
|
||||||
)
|
let appActionPopoverAnchor
|
||||||
|
|
||||||
|
let publishing
|
||||||
|
|
||||||
|
$: filteredApps = $apps.filter(app => app.devId === application)
|
||||||
$: selectedApp = filteredApps?.length ? filteredApps[0] : null
|
$: selectedApp = filteredApps?.length ? filteredApps[0] : null
|
||||||
|
|
||||||
$: deployments = []
|
$: deployments = []
|
||||||
|
@ -38,7 +50,30 @@
|
||||||
.filter(deployment => deployment.status === "SUCCESS")
|
.filter(deployment => deployment.status === "SUCCESS")
|
||||||
.sort((a, b) => a.updatedAt > b.updatedAt)
|
.sort((a, b) => a.updatedAt > b.updatedAt)
|
||||||
|
|
||||||
$: isPublished = selectedApp && latestDeployments?.length > 0
|
$: isPublished =
|
||||||
|
selectedApp?.status === "published" && latestDeployments?.length > 0
|
||||||
|
|
||||||
|
$: updateAvailable =
|
||||||
|
$store.upgradableVersion &&
|
||||||
|
$store.version &&
|
||||||
|
$store.upgradableVersion !== $store.version
|
||||||
|
|
||||||
|
const initialiseApp = async () => {
|
||||||
|
console.log("AppActions :: Reinitialise")
|
||||||
|
const applicationPkg = await API.fetchAppPackage($store.devId)
|
||||||
|
await store.actions.initialise(applicationPkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateDeploymentString = () => {
|
||||||
|
return deployments?.length
|
||||||
|
? processStringSync("Published {{ duration time 'millisecond' }} ago", {
|
||||||
|
time:
|
||||||
|
new Date().getTime() - new Date(deployments[0].updatedAt).getTime(),
|
||||||
|
})
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
$: deploymentString = updateDeploymentString(deployments)
|
||||||
|
|
||||||
const reviewPendingDeployments = (deployments, newDeployments) => {
|
const reviewPendingDeployments = (deployments, newDeployments) => {
|
||||||
if (deployments.length > 0) {
|
if (deployments.length > 0) {
|
||||||
|
@ -77,11 +112,35 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function publishApp() {
|
||||||
|
try {
|
||||||
|
publishing = true
|
||||||
|
|
||||||
|
let published = await API.publishAppChanges($store.appId)
|
||||||
|
|
||||||
|
notifications.send("App published", {
|
||||||
|
type: "success",
|
||||||
|
icon: "GlobeCheck",
|
||||||
|
})
|
||||||
|
|
||||||
|
await completePublish()
|
||||||
|
} catch (error) {
|
||||||
|
analytics.captureException(error)
|
||||||
|
notifications.error("Error publishing app")
|
||||||
|
}
|
||||||
|
publishing = false
|
||||||
|
}
|
||||||
|
|
||||||
const unpublishApp = () => {
|
const unpublishApp = () => {
|
||||||
publishPopover.hide()
|
appActionPopover.hide()
|
||||||
unpublishModal.show()
|
unpublishModal.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const revertApp = () => {
|
||||||
|
appActionPopover.hide()
|
||||||
|
revertModal.show()
|
||||||
|
}
|
||||||
|
|
||||||
const confirmUnpublishApp = async () => {
|
const confirmUnpublishApp = async () => {
|
||||||
if (!application || !isPublished) {
|
if (!application || !isPublished) {
|
||||||
//confirm the app has loaded.
|
//confirm the app has loaded.
|
||||||
|
@ -90,7 +149,10 @@
|
||||||
try {
|
try {
|
||||||
await API.unpublishApp(selectedApp.prodId)
|
await API.unpublishApp(selectedApp.prodId)
|
||||||
await apps.load()
|
await apps.load()
|
||||||
notifications.success("App unpublished successfully")
|
notifications.send("App unpublished", {
|
||||||
|
type: "success",
|
||||||
|
icon: "GlobeStrike",
|
||||||
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notifications.error("Error unpublishing app")
|
notifications.error("Error unpublishing app")
|
||||||
}
|
}
|
||||||
|
@ -116,81 +178,25 @@
|
||||||
{#if $store.hasLock}
|
{#if $store.hasLock}
|
||||||
<div class="action-top-nav">
|
<div class="action-top-nav">
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
<div class="version">
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<VersionModal />
|
{#if updateAvailable}
|
||||||
|
<div class="app-action-button version" on:click={versionModal.show}>
|
||||||
|
<div class="app-action">
|
||||||
|
<StatusLight notice />
|
||||||
|
Update
|
||||||
</div>
|
</div>
|
||||||
<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}
|
{/if}
|
||||||
|
|
||||||
{#if !isPublished}
|
|
||||||
<ActionButton
|
|
||||||
quiet
|
|
||||||
icon="GlobeStrike"
|
|
||||||
size="M"
|
|
||||||
tooltip="Your app has not been published yet"
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<TourWrap
|
<TourWrap
|
||||||
tourStepKey={$store.onboarding
|
tourStepKey={$store.onboarding
|
||||||
? TOUR_STEP_KEYS.BUILDER_USER_MANAGEMENT
|
? TOUR_STEP_KEYS.BUILDER_USER_MANAGEMENT
|
||||||
: TOUR_STEP_KEYS.FEATURE_USER_MANAGEMENT}
|
: TOUR_STEP_KEYS.FEATURE_USER_MANAGEMENT}
|
||||||
>
|
>
|
||||||
<span id="builder-app-users-button">
|
<div class="app-action-button users">
|
||||||
<ActionButton
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
quiet
|
<div
|
||||||
icon="UserGroup"
|
class="app-action"
|
||||||
size="M"
|
id="builder-app-users-button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
state.builderSidePanel = true
|
state.builderSidePanel = true
|
||||||
|
@ -198,13 +204,124 @@
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Icon name={"UserGroup"} />
|
||||||
Users
|
Users
|
||||||
</ActionButton>
|
</div>
|
||||||
|
</div>
|
||||||
|
</TourWrap>
|
||||||
|
|
||||||
|
<div class="app-action-button preview">
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<div class="app-action" on:click={previewApp}>
|
||||||
|
<Icon name={"PlayCircle"} />
|
||||||
|
|
||||||
|
Preview
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="app-action-button publish app-action-popover">
|
||||||
|
<div bind:this={appActionPopoverAnchor}>
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<div
|
||||||
|
class="app-action"
|
||||||
|
on:click={() => {
|
||||||
|
appActionPopover.show()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon name={isPublished ? "GlobeCheck" : "GlobeStrike"} />
|
||||||
|
<TourWrap tourStepKey={TOUR_STEP_KEYS.BUILDER_APP_PUBLISH}>
|
||||||
|
<span class="publish-open" id="builder-app-publish-button">
|
||||||
|
Publish
|
||||||
|
<Icon
|
||||||
|
name={appActionPopoverOpen ? "ChevronUp" : "ChevronDown"}
|
||||||
|
size="M"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
</TourWrap>
|
</TourWrap>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Popover
|
||||||
|
bind:this={appActionPopover}
|
||||||
|
align="right"
|
||||||
|
disabled={!isPublished}
|
||||||
|
anchor={appActionPopoverAnchor}
|
||||||
|
offset={10}
|
||||||
|
on:close={() => {
|
||||||
|
appActionPopoverOpen = false
|
||||||
|
}}
|
||||||
|
on:open={() => {
|
||||||
|
appActionPopoverOpen = true
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class="app-action-popover-content">
|
||||||
|
<Layout noPadding gap="M">
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<Body size="M">
|
||||||
|
<span
|
||||||
|
class="app-link"
|
||||||
|
on:click={() => {
|
||||||
|
if (isPublished) {
|
||||||
|
viewApp()
|
||||||
|
} else {
|
||||||
|
appActionPopover.hide()
|
||||||
|
updateAppModal.show()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{selectedApp ? `${selectedApp?.url}` : ""}
|
||||||
|
{#if isPublished}
|
||||||
|
<Icon size="S" name="LinkOut" />
|
||||||
|
{:else}
|
||||||
|
<Icon size="S" name="Edit" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
</Body>
|
||||||
|
|
||||||
|
<Body size="S">
|
||||||
|
<span class="publish-popover-status">
|
||||||
|
{#if isPublished}
|
||||||
|
<span class="status-text">{deploymentString}</span>
|
||||||
|
<span class="unpublish-link">
|
||||||
|
<Link quiet on:click={unpublishApp}>Unpublish</Link>
|
||||||
|
</span>
|
||||||
|
<span class="revert-link">
|
||||||
|
<Link quiet secondary on:click={revertApp}>Revert</Link>
|
||||||
|
</span>
|
||||||
|
{:else}
|
||||||
|
<span class="status-text unpublished">Not published</span>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
</Body>
|
||||||
|
<div class="action-buttons">
|
||||||
|
{#if $store.hasLock}
|
||||||
|
<Button
|
||||||
|
secondary
|
||||||
|
icon="Code"
|
||||||
|
on:click={() => {
|
||||||
|
$goto("./settings/embed")
|
||||||
|
appActionPopover.hide()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Embed
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
cta
|
||||||
|
on:click={publishApp}
|
||||||
|
id={"builder-app-publish-button"}
|
||||||
|
disabled={publishing}
|
||||||
|
>
|
||||||
|
Publish
|
||||||
|
</Button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modals -->
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
bind:this={unpublishModal}
|
bind:this={unpublishModal}
|
||||||
title="Confirm unpublish"
|
title="Confirm unpublish"
|
||||||
|
@ -213,45 +330,99 @@
|
||||||
>
|
>
|
||||||
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>
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="buttons">
|
<Modal bind:this={updateAppModal} padding={false} width="600px">
|
||||||
<Button on:click={previewApp} secondary>Preview</Button>
|
<UpdateAppModal
|
||||||
{#if $store.hasLock}
|
app={selectedApp}
|
||||||
<DeployModal onOk={completePublish} />
|
onUpdateComplete={async () => {
|
||||||
|
await initialiseApp()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
<RevertModal bind:this={revertModal} />
|
||||||
|
<VersionModal hideIcon bind:this={versionModal} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* .banner-btn {
|
.app-action-popover-content {
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--spacing-s);
|
|
||||||
} */
|
|
||||||
.popover-content {
|
|
||||||
padding: var(--spacing-xl);
|
padding: var(--spacing-xl);
|
||||||
}
|
}
|
||||||
.buttons {
|
|
||||||
display: flex;
|
.app-action-popover-content :global(.icon svg.spectrum-Icon) {
|
||||||
flex-direction: row;
|
height: 0.8em;
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--spacing-l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-buttons {
|
.action-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
/* gap: var(--spacing-s); */
|
height: 100%;
|
||||||
}
|
|
||||||
.version {
|
|
||||||
margin-right: var(--spacing-s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-top-nav {
|
.action-top-nav {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.app-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-s);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.app-action-popover-content .status-text {
|
||||||
|
color: #1ca872;
|
||||||
|
border-right: 1px solid var(--spectrum-global-color-gray-500);
|
||||||
|
padding-right: var(--spacing-m);
|
||||||
|
}
|
||||||
|
.app-action-popover-content .status-text.unpublished {
|
||||||
|
color: var(--spectrum-global-color-gray-600);
|
||||||
|
border-right: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
|
}
|
||||||
|
.app-action-popover-content .action-buttons {
|
||||||
|
gap: var(--spacing-m);
|
||||||
|
}
|
||||||
|
.app-action-popover-content
|
||||||
|
.publish-popover-status
|
||||||
|
.unpublish-link
|
||||||
|
:global(.spectrum-Link) {
|
||||||
|
color: #ee4331;
|
||||||
|
}
|
||||||
|
.publish-popover-status {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--spacing-m);
|
||||||
|
}
|
||||||
|
.app-action-popover .publish-open {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-action-button {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0px var(--spacing-l);
|
||||||
|
/* border-left: var(--border-light); */
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-action-button:hover {
|
||||||
|
background-color: var(--spectrum-global-color-gray-200);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-action-button.publish {
|
||||||
|
border-left: var(--border-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-action {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-s);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue