General tidying and refactoring. Updated the publish button behaviour to also take into account revert and version update behaviours.

This commit is contained in:
Dean 2023-06-20 12:33:18 +01:00
parent c1248eed12
commit 602ea9bc4e
13 changed files with 159 additions and 36 deletions

View File

@ -55,7 +55,7 @@
name: "Automations", name: "Automations",
description: "", description: "",
icon: "Compass", icon: "Compass",
action: () => $goto("./automate"), action: () => $goto("./automation"),
}, },
{ {
type: "Publish", type: "Publish",
@ -127,7 +127,7 @@
type: "Automation", type: "Automation",
name: automation.name, name: automation.name,
icon: "ShareAndroid", icon: "ShareAndroid",
action: () => $goto(`./automate/${automation._id}`), action: () => $goto(`./automation/${automation._id}`),
})), })),
...Constants.Themes.map(theme => ({ ...Constants.Themes.map(theme => ({
type: "Change Builder Theme", type: "Change Builder Theme",

View File

@ -24,12 +24,18 @@
import { onMount } from "svelte" import { onMount } from "svelte"
import DeployModal from "components/deploy/DeployModal.svelte" import DeployModal from "components/deploy/DeployModal.svelte"
import { apps } from "stores/portal" import { apps } from "stores/portal"
import { store } from "builderStore" import {
store,
screenHistoryStore,
automationHistoryStore,
} 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" import { url, goto } from "@roxi/routify"
import { isEqual, cloneDeep } from "lodash"
export let application export let application
export let loaded
let unpublishModal let unpublishModal
let updateAppModal let updateAppModal
@ -40,7 +46,7 @@
let appActionPopoverOpen = false let appActionPopoverOpen = false
let appActionPopoverAnchor let appActionPopoverAnchor
let publishing let publishing = false
$: 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
@ -58,6 +64,81 @@
$store.version && $store.version &&
$store.upgradableVersion !== $store.version $store.upgradableVersion !== $store.version
let cachedVersion = $store.version + ""
let versionAltered = false
let screensAltered = false
let automationsAltered = false
let publishRecord = {
screenHistory: null,
automationHistory: null,
}
//Meta Changes
let appMeta = {}
let appMetaUpdated = false
let appMetaInitialised = false
const unsub = store.subscribe(state => {
let { name, url: appUrl, navigation, theme, customTheme, icon } = state
const update = {
name,
url: appUrl,
navigation: { ...cloneDeep(navigation) },
theme,
customTheme,
icon,
}
if (!isEqual(update, appMeta)) {
if (!appMetaInitialised) {
appMetaInitialised = true
} else {
appMetaUpdated = true
}
appMeta = {
...(appMeta || {}),
...update,
}
}
})
const monitorHistoryStore = (historyStore, publishedHistoryId, cb) => {
if (!historyStore.history.length || historyStore.loading) {
return
}
if (!historyStore.canUndo) {
cb(publishedHistoryId != -1)
return
}
const historyEntry = historyStore.history[historyStore.position - 1]
if (historyEntry) {
cb(publishedHistoryId != historyEntry.id)
}
}
$: monitorHistoryStore(
$screenHistoryStore,
publishRecord.screenHistory,
updated => {
screensAltered = updated
}
)
$: monitorHistoryStore(
$automationHistoryStore,
publishRecord.automationHistory,
updated => {
automationsAltered = updated
}
)
$: versionAltered = cachedVersion != $store.version
$: altered =
screensAltered || appMetaUpdated || automationsAltered || versionAltered
$: canPublish = (!isPublished || altered) && !publishing && loaded
const initialiseApp = async () => { const initialiseApp = async () => {
const applicationPkg = await API.fetchAppPackage($store.devId) const applicationPkg = await API.fetchAppPackage($store.devId)
await store.actions.initialise(applicationPkg) await store.actions.initialise(applicationPkg)
@ -112,6 +193,27 @@
} }
} }
const resetAppHistory = (historyStore, historyKey) => {
if (historyStore.history.length) {
const historyEntryPos = historyStore.position
const historyEntry = historyStore.history[historyEntryPos - 1]
publishRecord = {
...publishRecord,
[historyKey]: historyEntry?.id || -1,
}
}
}
const resetStateTracking = () => {
resetAppHistory($automationHistoryStore, "automationHistory")
resetAppHistory($screenHistoryStore, "screenHistory")
automationsAltered = false
screensAltered = false
appMetaUpdated = false
cachedVersion = $store.version + ""
}
async function publishApp() { async function publishApp() {
try { try {
publishing = true publishing = true
@ -124,7 +226,9 @@
}) })
await completePublish() await completePublish()
resetStateTracking()
} catch (error) { } catch (error) {
console.error(error)
analytics.captureException(error) analytics.captureException(error)
notifications.error("Error publishing app") notifications.error("Error publishing app")
} }
@ -153,6 +257,7 @@
type: "success", type: "success",
icon: "GlobeStrike", icon: "GlobeStrike",
}) })
publishRecord = {}
} catch (err) { } catch (err) {
notifications.error("Error unpublishing app") notifications.error("Error unpublishing app")
} }
@ -176,7 +281,7 @@
</script> </script>
{#if $store.hasLock} {#if $store.hasLock}
<div class="action-top-nav"> <div class="action-top-nav" class:has-lock={$store.hasLock}>
<div class="action-buttons"> <div class="action-buttons">
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
{#if updateAvailable} {#if updateAvailable}
@ -317,7 +422,7 @@
cta cta
on:click={publishApp} on:click={publishApp}
id={"builder-app-publish-button"} id={"builder-app-publish-button"}
disabled={publishing} disabled={!canPublish}
> >
Publish Publish
</Button> </Button>
@ -349,8 +454,20 @@
/> />
</Modal> </Modal>
<RevertModal bind:this={revertModal} /> <RevertModal bind:this={revertModal} onComplete={resetStateTracking} />
<VersionModal hideIcon bind:this={versionModal} /> <VersionModal
hideIcon
bind:this={versionModal}
onComplete={resetStateTracking}
/>
{:else}
<div class="app-action-button preview-locked">
<div class="app-action">
<ActionButton quiet icon="PlayCircle" on:click={previewApp}>
Preview
</ActionButton>
</div>
</div>
{/if} {/if}
<style> <style>
@ -385,7 +502,7 @@
cursor: pointer; cursor: pointer;
} }
.app-action-popover-content .status-text { .app-action-popover-content .status-text {
color: #1ca872; color: var(--spectrum-global-color-green-500);
border-right: 1px solid var(--spectrum-global-color-gray-500); border-right: 1px solid var(--spectrum-global-color-gray-500);
padding-right: var(--spacing-m); padding-right: var(--spacing-m);
} }
@ -401,7 +518,7 @@
.publish-popover-status .publish-popover-status
.unpublish-link .unpublish-link
:global(.spectrum-Link) { :global(.spectrum-Link) {
color: #ee4331; color: var(--spectrum-global-color-red-400);
} }
.publish-popover-status { .publish-popover-status {
display: flex; display: flex;
@ -435,6 +552,10 @@
gap: var(--spectrum-actionbutton-icon-gap); gap: var(--spectrum-actionbutton-icon-gap);
} }
.app-action-button.preview-locked {
padding-right: 0px;
}
.app-action { .app-action {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -10,7 +10,7 @@
import { store } from "builderStore" import { store } from "builderStore"
import { API } from "api" import { API } from "api"
export let disabled = false export let onComplete = () => {}
let revertModal let revertModal
let appName let appName
@ -25,6 +25,7 @@
const applicationPkg = await API.fetchAppPackage(appId) const applicationPkg = await API.fetchAppPackage(appId)
await store.actions.initialise(applicationPkg) await store.actions.initialise(applicationPkg)
notifications.info("Changes reverted successfully") notifications.info("Changes reverted successfully")
onComplete()
} catch (error) { } catch (error) {
notifications.error(`Error reverting changes: ${error}`) notifications.error(`Error reverting changes: ${error}`)
} }

View File

@ -18,6 +18,7 @@
updateModal.hide() updateModal.hide()
} }
export let onComplete = () => {}
export let hideIcon = false export let hideIcon = false
let updateModal let updateModal
@ -47,6 +48,7 @@
notifications.success( notifications.success(
`App updated successfully to version ${$store.upgradableVersion}` `App updated successfully to version ${$store.upgradableVersion}`
) )
onComplete()
} catch (err) { } catch (err) {
notifications.error(`Error updating app: ${err}`) notifications.error(`Error updating app: ${err}`)
} }

View File

@ -143,7 +143,7 @@
{/if} {/if}
<div class="root" class:blur={$store.showPreview}> <div class="root" class:blur={$store.showPreview}>
<div class="top-nav"> <div class="top-nav" class:has-lock={$store.hasLock}>
{#if $store.initialised} {#if $store.initialised}
<div class="topleftnav"> <div class="topleftnav">
<span class="back-to-apps"> <span class="back-to-apps">
@ -171,7 +171,10 @@
{:else} {:else}
<div class="secondary-editor"> <div class="secondary-editor">
<Icon name="LockClosed" /> <Icon name="LockClosed" />
<div class="secondary-editor-body"> <div
class="secondary-editor-body"
title="Another user is currently editing your screens and automations"
>
Another user is currently editing your screens and automations Another user is currently editing your screens and automations
</div> </div>
</div> </div>
@ -184,7 +187,7 @@
<span class:nav-lock={!$store.hasLock}> <span class:nav-lock={!$store.hasLock}>
<UserAvatars users={$userStore} /> <UserAvatars users={$userStore} />
</span> </span>
<AppActions {application} /> <AppActions {application} {loaded} />
</div> </div>
{/if} {/if}
</div> </div>
@ -239,7 +242,6 @@
flex: 0 0 60px; flex: 0 0 60px;
background: var(--background); background: var(--background);
padding: 0 var(--spacing-xl); padding: 0 var(--spacing-xl);
padding-right: 0px;
display: grid; display: grid;
grid-template-columns: 1fr auto 1fr; grid-template-columns: 1fr auto 1fr;
flex-direction: row; flex-direction: row;
@ -249,6 +251,10 @@
z-index: 2; z-index: 2;
} }
.top-nav.has-lock {
padding-right: 0px;
}
.topcenternav { .topcenternav {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -259,16 +265,17 @@
.topcenternav :global(.spectrum-Heading) { .topcenternav :global(.spectrum-Heading) {
flex: 1 1 auto; flex: 1 1 auto;
/* width: 0; */
font-weight: 600; font-weight: 600;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
padding: 0px var(--spacing-m);
} }
.topleftnav { .topleftnav {
display: flex; display: flex;
position: relative; position: relative;
margin-bottom: -2px; margin-bottom: -2px;
overflow: hidden;
} }
.topleftnav :global(.spectrum-Tabs-itemLabel) { .topleftnav :global(.spectrum-Tabs-itemLabel) {
@ -291,6 +298,15 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
gap: 8px; gap: 8px;
min-width: 0px;
overflow: hidden;
}
.secondary-editor-body {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0px;
} }
.body { .body {

View File

@ -68,7 +68,7 @@
<style> <style>
.delete-action :global(span) { .delete-action :global(span) {
color: #ee4331; color: var(--spectrum-global-color-red-400);
} }
.delete-action { .delete-action {
display: contents; display: contents;

View File

@ -7,12 +7,6 @@
layout, layout,
route, route,
} from "@roxi/routify" } from "@roxi/routify"
// $: console.log("isChangingPage", $isChangingPage)
// $: console.log("page ", $page)
// $: console.log("is Active ", $isActive("../settings"))
$: indexCheck = $layout.meta.index
$: console.log("Index Check ", indexCheck)
$: console.log("layout", $layout)
$redirect("../settings/automation-history") $redirect("../settings/automation-history")
</script> </script>

View File

@ -23,9 +23,6 @@
$: appDeployed = app?.status === AppStatus.DEPLOYED $: appDeployed = app?.status === AppStatus.DEPLOYED
const initialiseApp = async () => { const initialiseApp = async () => {
// In order for these changes to make it back into the app, the app package must be reinitialied
// could this have negative side affects???
console.log("Reinitialise")
const applicationPkg = await API.fetchAppPackage(app.devId) const applicationPkg = await API.fetchAppPackage(app.devId)
await store.actions.initialise(applicationPkg) await store.actions.initialise(applicationPkg)
} }

View File

@ -103,7 +103,6 @@
$goto( $goto(
`/builder/app/${appId}/settings/automation-history?${params.toString()}` `/builder/app/${appId}/settings/automation-history?${params.toString()}`
) )
// $goto(`../overview/${appId}/automation-history?${params.toString()}`)
} }
const errorCount = errors => { const errorCount = errors => {

View File

@ -141,7 +141,7 @@
customPlaceholder customPlaceholder
allowEditRows={false} allowEditRows={false}
customRenderers={customAppTableRenderers} customRenderers={customAppTableRenderers}
on:click={e => $goto(`../../overview/${e.detail.devId}`)} on:click={e => $goto(`/builder/app/${e.detail.devId}`)}
> >
<div class="placeholder" slot="placeholder"> <div class="placeholder" slot="placeholder">
<Heading size="S">This group doesn't have access to any apps</Heading> <Heading size="S">This group doesn't have access to any apps</Heading>

View File

@ -346,7 +346,7 @@
customPlaceholder customPlaceholder
allowEditRows={false} allowEditRows={false}
customRenderers={customAppTableRenderers} customRenderers={customAppTableRenderers}
on:click={e => $goto(`../../overview/${e.detail.devId}`)} on:click={e => $goto(`/builder/app/${e.detail.devId}`)}
> >
<div class="placeholder" slot="placeholder"> <div class="placeholder" slot="placeholder">
<Heading size="S"> <Heading size="S">

View File

@ -10,7 +10,6 @@ export { licensing } from "./licensing"
export { groups } from "./groups" export { groups } from "./groups"
export { plugins } from "./plugins" export { plugins } from "./plugins"
export { backups } from "./backups" export { backups } from "./backups"
export { overview } from "./overview"
export { environment } from "./environment" export { environment } from "./environment"
export { menu } from "./menu" export { menu } from "./menu"
export { auditLogs } from "./auditLogs" export { auditLogs } from "./auditLogs"

View File

@ -86,12 +86,6 @@ export default async function builder(ctx: UserCtx) {
const referer = ctx.headers["referer"] const referer = ctx.headers["referer"]
const overviewPath = "/builder/portal/overview/"
const overviewContext = !referer ? false : referer.includes(overviewPath)
if (overviewContext) {
return
}
const hasAppId = !referer ? false : referer.includes(appId) const hasAppId = !referer ? false : referer.includes(appId)
const editingApp = referer ? hasAppId : false const editingApp = referer ? hasAppId : false
// check this is a builder call and editing // check this is a builder call and editing