Merge branch 'feature/draft-apps' of github.com:Budibase/budibase into feature/draft-apps

This commit is contained in:
mike12345567 2021-05-13 18:10:20 +01:00
commit 332f0555a3
9 changed files with 70 additions and 59 deletions

View File

@ -11,47 +11,9 @@ class Replication {
this.target = getDB(target)
}
sync(opts) {
return new Promise((resolve, reject) => {
this.source
.sync(this.target, opts)
.on("change", function (info) {
// handle change
})
.on("paused", function (err) {
// replication paused (e.g. replication up to date, user went offline)
})
.on("active", function () {
// replicate resumed (e.g. new changes replicating, user went back online)
})
.on("denied", function (err) {
// a document failed to replicate (e.g. due to permissions)
return reject(
new Error(`Denied: Document failed to replicate ${err}`)
)
})
.on("complete", function (info) {
return resolve(info)
})
.on("error", function (err) {
return reject(new Error(`Replication Error: ${err}`))
})
})
}
replicate() {
return new Promise((resolve, reject) => {
this.replication = this.source.replicate
.to(this.target)
// .on("change", function (info) {
// // handle change
// })
// .on("paused", function (err) {
// // replication paused (e.g. replication up to date, user went offline)
// })
// .on("active", function () {
// // replicate resumed (e.g. new changes replicating, user went back online)
// })
promisify(operation, opts = {}) {
return new Promise(resolve => {
operation(this.target, opts)
.on("denied", function (err) {
// a document failed to replicate (e.g. due to permissions)
throw new Error(`Denied: Document failed to replicate ${err}`)
@ -65,6 +27,40 @@ class Replication {
})
}
/**
* Two way replication operation, intended to be promise based.
* @param {Object} opts - PouchDB replication options
*/
sync(opts) {
this.replication = this.promisify(this.source.sync, opts)
return this.replication
}
/**
* One way replication operation, intended to be promise based.
* @param {Object} opts - PouchDB replication options
*/
replicate(opts) {
this.replication = this.promisify(this.source.replicate.to, opts)
return this.replication
}
/**
* Set up an ongoing live sync between 2 CouchDB databases.
* @param {Object} opts - PouchDB replication options
*/
subscribe(opts = {}) {
this.replication = this.source.replicate
.to(this.target, {
live: true,
retry: true,
...opts,
})
.on("error", function (err) {
throw new Error(`Replication Error: ${err}`)
})
}
async rollback() {
await this.target.destroy()
await this.replicate()

View File

@ -1,5 +1,5 @@
<script>
import { General, DangerZone, APIKeys } from "./tabs"
import { General, DangerZone } from "./tabs"
import { ModalContent, Tab, Tabs } from "@budibase/bbui"
</script>
@ -13,9 +13,9 @@
<Tab title="General">
<General />
</Tab>
<Tab title="API Keys">
<!-- <Tab title="API Keys">
<APIKeys />
</Tab>
</Tab> -->
<Tab title="Danger Zone">
<DangerZone />
</Tab>

View File

@ -18,6 +18,7 @@
export let openApp
export let deleteApp
export let releaseLock
export let deletable
</script>
<div class="wrapper">
@ -34,9 +35,11 @@
<MenuItem on:click={() => exportApp(app)} icon="Download">
Export
</MenuItem>
<MenuItem on:click={() => deleteApp(app)} icon="Delete">
{#if deletable}
<MenuItem on:click={() => deleteApp(app)} icon="Delete">
Delete
</MenuItem>
{/if}
{#if app.lockedBy && app.lockedBy?.email === $auth.user?.email}
<MenuItem on:click={() => releaseLock(app._id)} icon="LockOpen">
Release Lock

View File

@ -16,13 +16,14 @@
export let openApp
export let exportApp
export let deleteApp
export let last
export let releaseLock
export let last
export let deletable
</script>
<div class="title" class:last>
<div class="preview" use:gradient={{ seed: app.name }} />
<Link on:click={openApp}>
<Link on:click={() => openApp(app)}>
<Heading size="XS">
{app.name}
</Heading>
@ -45,7 +46,9 @@
<ActionMenu align="right">
<Icon hoverable slot="control" name="More" />
<MenuItem on:click={() => exportApp(app)} icon="Download">Export</MenuItem>
<MenuItem on:click={() => deleteApp(app)} icon="Delete">Delete</MenuItem>
{#if deletable}
<MenuItem on:click={() => deleteApp(app)} icon="Delete">Delete</MenuItem>
{/if}
{#if app.lockedBy && app.lockedBy?.email === $auth.user?.email}
<MenuItem on:click={() => releaseLock(app._id)} icon="LockOpen">
Release Lock

View File

@ -11,6 +11,7 @@ export const FrontendTypes = {
export const AppStatus = {
DEV: "dev",
PUBLISHED: "published"
}
// fields on the user table that cannot be edited

View File

@ -37,7 +37,7 @@
<img src={Rocket} alt="Rocket flying through sky" />
<div>
<Heading size="M">It's time to shine!</Heading>
<Button size="XL" cta medium on:click={deployApp}>Deploy App</Button>
<Button size="XL" cta medium on:click={deployApp}>Publish App</Button>
</div>
</section>
<Modal bind:this={feedbackModal}>

View File

@ -26,7 +26,7 @@
import { AppStatus } from "constants"
let layout = "grid"
let appStatus = "deployed"
let appStatus = AppStatus.PUBLISHED
let template
let appToDelete
let creationModal
@ -95,6 +95,7 @@
await del(`/api/applications/${appToDelete?._id}`)
await apps.load()
appToDelete = null
notifications.success("App deleted successfully.")
}
const releaseLock = async appId => {
@ -131,8 +132,8 @@
<Select
bind:value={appStatus}
options={[
{ label: "Deployed", value: "deployed" },
{ label: "In Development", value: "dev" },
{ label: "Published", value: AppStatus.PUBLISHED },
{ label: "In Development", value: AppStatus.DEV },
]}
/>
</div>
@ -159,6 +160,7 @@
{#each $apps as app, idx (app._id)}
<svelte:component
this={layout === "grid" ? AppCard : AppRow}
deletable={appStatus === AppStatus.PUBLISHED}
{releaseLock}
{app}
{openApp}

View File

@ -57,24 +57,30 @@ async function storeLocalDeploymentHistory(deployment) {
async function deployApp(deployment) {
try {
const deployTarget = deployment.appId.replace("_dev", "")
const productionAppId = deployment.appId.replace("_dev", "")
const replication = new Replication({
source: deployment.appId,
target: deployTarget,
target: productionAppId,
})
await replication.replicate()
// Strip the _dev prefix and update the appID document in the new DB
const db = new PouchDB(deployTarget)
const db = new PouchDB(productionAppId)
const appDoc = await db.get(deployment.appId)
await db.remove(appDoc)
appDoc._id = deployTarget
appDoc._id = productionAppId
delete appDoc._rev
appDoc.instance._id = deployTarget
appDoc.instance._id = productionAppId
await db.put(appDoc)
// Set up live sync between the live and dev instances
const liveReplication = new Replication({
source: productionAppId,
target: deployment.appId,
})
liveReplication.subscribe()
deployment.setStatus(DeploymentStatus.SUCCESS)
await storeLocalDeploymentHistory(deployment)
} catch (err) {

View File

@ -17,7 +17,7 @@ const StaticDatabases = {
const AppStatus = {
DEV: "dev",
DEPLOYED: "deployed",
DEPLOYED: "PUBLISHED",
}
const DocumentTypes = {