Export app without rows
This commit is contained in:
parent
11b8d2a8e8
commit
955b9a4d63
|
@ -0,0 +1,16 @@
|
||||||
|
<script>
|
||||||
|
import { ModalContent, Toggle } from "@budibase/bbui"
|
||||||
|
|
||||||
|
export let app
|
||||||
|
let includeRows = true
|
||||||
|
|
||||||
|
const exportApp = () => {
|
||||||
|
const id = app.deployed ? app.prodId : app.devId
|
||||||
|
const appName = encodeURIComponent(app.name)
|
||||||
|
window.location = `/api/backups/export?appId=${id}&appname=${appName}&includeRows=${includeRows}`
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ModalContent title={"Export"} confirmText={"Export"} onConfirm={exportApp}>
|
||||||
|
<Toggle text="Include Data" bind:value={includeRows} />
|
||||||
|
</ModalContent>
|
|
@ -18,6 +18,7 @@
|
||||||
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
||||||
import UpdateAppModal from "components/start/UpdateAppModal.svelte"
|
import UpdateAppModal from "components/start/UpdateAppModal.svelte"
|
||||||
import ChooseIconModal from "components/start/ChooseIconModal.svelte"
|
import ChooseIconModal from "components/start/ChooseIconModal.svelte"
|
||||||
|
import ExportAppModal from "components/start/ExportAppModal.svelte"
|
||||||
|
|
||||||
import { store, automationStore } from "builderStore"
|
import { store, automationStore } from "builderStore"
|
||||||
import { API } from "api"
|
import { API } from "api"
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
let updatingModal
|
let updatingModal
|
||||||
let deletionModal
|
let deletionModal
|
||||||
let unpublishModal
|
let unpublishModal
|
||||||
|
let exportModal
|
||||||
let iconModal
|
let iconModal
|
||||||
let creatingApp = false
|
let creatingApp = false
|
||||||
let loaded = $apps?.length || $templates?.length
|
let loaded = $apps?.length || $templates?.length
|
||||||
|
@ -198,9 +200,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const exportApp = app => {
|
const exportApp = app => {
|
||||||
const id = app.deployed ? app.prodId : app.devId
|
exportModal.show()
|
||||||
const appName = encodeURIComponent(app.name)
|
selectedApp = app
|
||||||
window.location = `/api/backups/export?appId=${id}&appname=${appName}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const unpublishApp = app => {
|
const unpublishApp = app => {
|
||||||
|
@ -434,6 +435,10 @@
|
||||||
<UpdateAppModal app={selectedApp} />
|
<UpdateAppModal app={selectedApp} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<Modal bind:this={exportModal} padding={false} width="600px">
|
||||||
|
<ExportAppModal app={selectedApp} />
|
||||||
|
</Modal>
|
||||||
|
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
bind:this={deletionModal}
|
bind:this={deletionModal}
|
||||||
title="Confirm deletion"
|
title="Confirm deletion"
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
const { streamBackup } = require("../../utilities/fileSystem")
|
const { streamBackup } = require("../../utilities/fileSystem")
|
||||||
|
|
||||||
exports.exportAppDump = async function (ctx) {
|
exports.exportAppDump = async function (ctx) {
|
||||||
const { appId } = ctx.query
|
let { appId, includeRows } = ctx.query
|
||||||
const appName = decodeURI(ctx.query.appname)
|
const appName = decodeURI(ctx.query.appname)
|
||||||
|
includeRows = includeRows === "true"
|
||||||
const backupIdentifier = `${appName}-export-${new Date().getTime()}.txt`
|
const backupIdentifier = `${appName}-export-${new Date().getTime()}.txt`
|
||||||
ctx.attachment(backupIdentifier)
|
ctx.attachment(backupIdentifier)
|
||||||
ctx.body = await streamBackup(appId)
|
|
||||||
|
ctx.body = await streamBackup(appId, includeRows)
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@ exports.isDevAppID = isDevAppID
|
||||||
exports.isProdAppID = isProdAppID
|
exports.isProdAppID = isProdAppID
|
||||||
exports.USER_METDATA_PREFIX = `${DocumentTypes.ROW}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`
|
exports.USER_METDATA_PREFIX = `${DocumentTypes.ROW}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`
|
||||||
exports.LINK_USER_METADATA_PREFIX = `${DocumentTypes.LINK}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`
|
exports.LINK_USER_METADATA_PREFIX = `${DocumentTypes.LINK}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`
|
||||||
|
exports.TABLE_ROW_PREFIX = `${DocumentTypes.ROW}${SEPARATOR}${DocumentTypes.TABLE}`
|
||||||
exports.ViewNames = ViewNames
|
exports.ViewNames = ViewNames
|
||||||
exports.InternalTables = InternalTables
|
exports.InternalTables = InternalTables
|
||||||
exports.DocumentTypes = DocumentTypes
|
exports.DocumentTypes = DocumentTypes
|
||||||
|
|
|
@ -21,6 +21,7 @@ const env = require("../../environment")
|
||||||
const {
|
const {
|
||||||
USER_METDATA_PREFIX,
|
USER_METDATA_PREFIX,
|
||||||
LINK_USER_METADATA_PREFIX,
|
LINK_USER_METADATA_PREFIX,
|
||||||
|
TABLE_ROW_PREFIX,
|
||||||
} = require("../../db/utils")
|
} = require("../../db/utils")
|
||||||
const MemoryStream = require("memorystream")
|
const MemoryStream = require("memorystream")
|
||||||
const { getAppId } = require("@budibase/backend-core/context")
|
const { getAppId } = require("@budibase/backend-core/context")
|
||||||
|
@ -109,6 +110,23 @@ exports.apiFileReturn = contents => {
|
||||||
return fs.createReadStream(path)
|
return fs.createReadStream(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.defineFilter = includeRows => {
|
||||||
|
if (includeRows) {
|
||||||
|
return doc =>
|
||||||
|
!(
|
||||||
|
doc._id.includes(USER_METDATA_PREFIX) ||
|
||||||
|
doc._id.includes(LINK_USER_METADATA_PREFIX)
|
||||||
|
)
|
||||||
|
} else if (!includeRows) {
|
||||||
|
return doc =>
|
||||||
|
!(
|
||||||
|
doc._id.includes(USER_METDATA_PREFIX) ||
|
||||||
|
doc._id.includes(LINK_USER_METADATA_PREFIX) ||
|
||||||
|
doc._id.includes(TABLE_ROW_PREFIX)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Local utility to back up the database state for an app, excluding global user
|
* Local utility to back up the database state for an app, excluding global user
|
||||||
* data or user relationships.
|
* data or user relationships.
|
||||||
|
@ -116,14 +134,10 @@ exports.apiFileReturn = contents => {
|
||||||
* @param {object} config Config to send to export DB
|
* @param {object} config Config to send to export DB
|
||||||
* @returns {*} either a string or a stream of the backup
|
* @returns {*} either a string or a stream of the backup
|
||||||
*/
|
*/
|
||||||
const backupAppData = async (appId, config) => {
|
const backupAppData = async (appId, config, noRows) => {
|
||||||
return await exports.exportDB(appId, {
|
return await exports.exportDB(appId, {
|
||||||
...config,
|
...config,
|
||||||
filter: doc =>
|
filter: exports.defineFilter(noRows),
|
||||||
!(
|
|
||||||
doc._id.includes(USER_METDATA_PREFIX) ||
|
|
||||||
doc._id.includes(LINK_USER_METADATA_PREFIX)
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,8 +156,8 @@ exports.performBackup = async (appId, backupName) => {
|
||||||
* @param {string} appId The ID of the app which is to be backed up.
|
* @param {string} appId The ID of the app which is to be backed up.
|
||||||
* @returns {*} a readable stream of the backup which is written in real time
|
* @returns {*} a readable stream of the backup which is written in real time
|
||||||
*/
|
*/
|
||||||
exports.streamBackup = async appId => {
|
exports.streamBackup = async (appId, includeRows) => {
|
||||||
return await backupAppData(appId, { stream: true })
|
return await backupAppData(appId, { stream: true }, includeRows)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue