@@ -70,23 +51,15 @@
- {#if app.deployed}
-
- {:else}
-
- {/if}
+
@@ -119,6 +92,7 @@
}
.app-status {
display: grid;
+ grid-gap: var(--spacing-s);
grid-template-columns: 24px 100px;
}
.app-status span.disabled {
diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte
index a25e7e2c6a..9b70068e10 100644
--- a/packages/builder/src/pages/builder/portal/apps/index.svelte
+++ b/packages/builder/src/pages/builder/portal/apps/index.svelte
@@ -182,6 +182,10 @@
window.open(`/${app.devId}`)
}
+ const appOverview = app => {
+ $goto(`../overview/${app.devId}`)
+ }
+
const editApp = app => {
if (app.lockedOther) {
notifications.error(
@@ -404,6 +408,7 @@
{deleteApp}
{updateApp}
{previewApp}
+ {appOverview}
/>
{/each}
diff --git a/packages/builder/src/pages/builder/portal/overview/[application]/index.svelte b/packages/builder/src/pages/builder/portal/overview/[application]/index.svelte
new file mode 100644
index 0000000000..46fd95c1e9
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/overview/[application]/index.svelte
@@ -0,0 +1,254 @@
+
+
+
+
+
+
+
+ {#await promise}
+
+ {:then _}
+
+ {
+ selectedTab = e.detail
+ }}
+ >
+
+
+
+
+ Automation History contents
+
+
+ Backups contents
+
+
+
+
+
+
+
+
+ {:catch error}
+ Something went wrong: {error.message}
+ {/await}
+
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/overview/_components/AutomationTab.svelte b/packages/builder/src/pages/builder/portal/overview/_components/AutomationTab.svelte
new file mode 100644
index 0000000000..56dcc40f87
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/overview/_components/AutomationTab.svelte
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/overview/_components/OverviewTab.svelte b/packages/builder/src/pages/builder/portal/overview/_components/OverviewTab.svelte
new file mode 100644
index 0000000000..4319f51e0c
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/overview/_components/OverviewTab.svelte
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
+ {#if isPublished}
+
+ Published
+ {:else}
+
+ Unpublished
+ {/if}
+
+
+
+ {#if deployments?.length}
+ {processStringSync(
+ "Last published {{ duration time 'millisecond' }} ago",
+ {
+ time:
+ new Date().getTime() -
+ new Date(deployments[0].updatedAt).getTime(),
+ }
+ )}
+ {/if}
+ {#if !deployments?.length}
+ -
+ {/if}
+
+
+
+
+ {app.updatedAt}
+
+
+
+
+
+
{app.updatedBy.firstName}
+
+
+ {#if app}
+ {processStringSync(
+ "Last edited {{ duration time 'millisecond' }} ago",
+ {
+ time: new Date().getTime() - new Date(app?.updatedAt).getTime(),
+ }
+ )}
+ {/if}
+
+
+
+
{
+ navigateTab("App Version")
+ }}
+ >
+
+
{app?.version}
+ {#if updateAvailable}
+
+ New version {clientPackage.version} is available -
+ {
+ if (typeof navigateTab === "function") {
+ navigateTab("App Version")
+ }
+ }}
+ >
+ Update
+
+
+ {:else}
+
You're running the latest!
+ {/if}
+
+
+
+
+
{
+ navigateTab("Automation History")
+ }}
+ >
+
+
+
+ test
+
+
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/overview/_components/SelfHostTab.svelte b/packages/builder/src/pages/builder/portal/overview/_components/SelfHostTab.svelte
new file mode 100644
index 0000000000..16804a8eb6
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/overview/_components/SelfHostTab.svelte
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+ Self-host Budibase
+
+
+
+ Self-host Budibase for free to get unlimited apps and more - and it
+ only takes a few minutes!
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/overview/_components/VersionModalBody.svelte b/packages/builder/src/pages/builder/portal/overview/_components/VersionModalBody.svelte
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/builder/src/pages/builder/portal/overview/_components/VersionTab.svelte b/packages/builder/src/pages/builder/portal/overview/_components/VersionTab.svelte
new file mode 100644
index 0000000000..583c6af603
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/overview/_components/VersionTab.svelte
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+ App Version
+
+
+ {#if updateAvailable}
+
+ The app is currently using version {app?.version}
+ but version {clientPackage.version} is available.
+
+ {:else}
+
+ The app is currently using version {app?.version}. You're running the latest!
+
+ {/if}
+
+ Updates can contain new features, performance improvements and bug
+ fixes.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/server/src/middleware/builder.js b/packages/server/src/middleware/builder.js
index f4568722c1..964efee451 100644
--- a/packages/server/src/middleware/builder.js
+++ b/packages/server/src/middleware/builder.js
@@ -6,7 +6,7 @@ const {
setDebounce,
} = require("../utilities/redis")
const { doWithDB } = require("@budibase/backend-core/db")
-const { DocumentTypes } = require("../db/utils")
+const { DocumentTypes, getGlobalIDFromUserMetadataID } = require("../db/utils")
const { PermissionTypes } = require("@budibase/backend-core/permissions")
const { app: appCache } = require("@budibase/backend-core/cache")
@@ -51,6 +51,21 @@ async function updateAppUpdatedAt(ctx) {
await doWithDB(appId, async db => {
const metadata = await db.get(DocumentTypes.APP_METADATA)
metadata.updatedAt = new Date().toISOString()
+
+ const getInitials = user => {
+ let initials = ""
+ initials += user.firstName ? user.firstName[0] : ""
+ initials += user.lastName ? user.lastName[0] : ""
+ return initials == "" ? undefined : initials
+ }
+
+ metadata.updatedBy = {
+ email: ctx.user.email,
+ firstName: ctx.user.firstName,
+ lastName: ctx.user.lastName,
+ initials: getInitials(ctx.user),
+ _id: getGlobalIDFromUserMetadataID(ctx.user.userId),
+ }
const response = await db.put(metadata)
metadata._rev = response.rev
await appCache.invalidateAppMetadata(appId, metadata)
@@ -67,7 +82,15 @@ module.exports = async (ctx, permType) => {
}
const isBuilderApi = permType === PermissionTypes.BUILDER
const referer = ctx.headers["referer"]
- const editingApp = referer ? referer.includes(appId) : false
+
+ const overviewPath = "/builder/portal/overview/"
+ const overviewContext = !referer ? false : referer.includes(overviewPath)
+ if (overviewContext) {
+ return
+ }
+
+ const hasAppId = !referer ? false : referer.includes(appId)
+ const editingApp = referer ? hasAppId : false
// check this is a builder call and editing
if (!isBuilderApi || !editingApp) {
return
diff --git a/packages/server/src/utilities/redis.js b/packages/server/src/utilities/redis.js
index ca2fa3254d..0c25bab27a 100644
--- a/packages/server/src/utilities/redis.js
+++ b/packages/server/src/utilities/redis.js
@@ -48,7 +48,9 @@ exports.updateLock = async (devAppId, user) => {
...user,
userId: globalId,
_id: globalId,
+ lockedAt: new Date().getTime(),
}
+
await devAppClient.store(devAppId, inputUser, APP_DEV_LOCK_SECONDS)
}