Merge branch 'feature/draft-apps' of github.com:Budibase/budibase into feature/draft-apps
This commit is contained in:
commit
332f0555a3
|
@ -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()
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -11,6 +11,7 @@ export const FrontendTypes = {
|
|||
|
||||
export const AppStatus = {
|
||||
DEV: "dev",
|
||||
PUBLISHED: "published"
|
||||
}
|
||||
|
||||
// fields on the user table that cannot be edited
|
||||
|
|
|
@ -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}>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -17,7 +17,7 @@ const StaticDatabases = {
|
|||
|
||||
const AppStatus = {
|
||||
DEV: "dev",
|
||||
DEPLOYED: "deployed",
|
||||
DEPLOYED: "PUBLISHED",
|
||||
}
|
||||
|
||||
const DocumentTypes = {
|
||||
|
|
Loading…
Reference in New Issue