Some fixes after testing and adding some basic work to the frontend.
This commit is contained in:
parent
a83b9835b2
commit
d282cd030f
|
@ -0,0 +1,51 @@
|
||||||
|
<script>
|
||||||
|
import { notifications, ModalContent, Dropzone, Body } from "@budibase/bbui"
|
||||||
|
import { post } from "builderStore/api"
|
||||||
|
import { goto } from "@roxi/routify"
|
||||||
|
|
||||||
|
let submitting = false
|
||||||
|
|
||||||
|
$: value = { file: null }
|
||||||
|
|
||||||
|
async function importApps() {
|
||||||
|
submitting = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create form data to create app
|
||||||
|
let data = new FormData()
|
||||||
|
data.append("importFile", value.file)
|
||||||
|
|
||||||
|
// Create App
|
||||||
|
const importResp = await post("/api/cloud/import", data, {})
|
||||||
|
const importJson = await importResp.json()
|
||||||
|
if (!importResp.ok) {
|
||||||
|
throw new Error(importJson.message)
|
||||||
|
}
|
||||||
|
// now login
|
||||||
|
$goto("../auth")
|
||||||
|
} catch (error) {
|
||||||
|
notifications.error(error)
|
||||||
|
submitting = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ModalContent
|
||||||
|
title="Import apps"
|
||||||
|
confirmText="Import apps"
|
||||||
|
onConfirm={importApps}
|
||||||
|
disabled={!value.file}
|
||||||
|
>
|
||||||
|
<Body
|
||||||
|
>Please upload the file that was exported from your Cloud environment to get
|
||||||
|
started</Body
|
||||||
|
>
|
||||||
|
<Dropzone
|
||||||
|
gallery={false}
|
||||||
|
label="File to import"
|
||||||
|
value={[value.file]}
|
||||||
|
on:change={e => {
|
||||||
|
value.file = e.detail?.[0]
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ModalContent>
|
|
@ -7,15 +7,18 @@
|
||||||
Input,
|
Input,
|
||||||
Body,
|
Body,
|
||||||
ActionButton,
|
ActionButton,
|
||||||
|
Modal,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import { admin, auth } from "stores/portal"
|
import { admin, auth } from "stores/portal"
|
||||||
import PasswordRepeatInput from "components/common/users/PasswordRepeatInput.svelte"
|
import PasswordRepeatInput from "components/common/users/PasswordRepeatInput.svelte"
|
||||||
|
import ImportAppsModal from "./_components/ImportAppsModal.svelte"
|
||||||
import Logo from "assets/bb-emblem.svg"
|
import Logo from "assets/bb-emblem.svg"
|
||||||
|
|
||||||
let adminUser = {}
|
let adminUser = {}
|
||||||
let error
|
let error
|
||||||
|
let modal
|
||||||
|
|
||||||
$: tenantId = $auth.tenantId
|
$: tenantId = $auth.tenantId
|
||||||
$: multiTenancyEnabled = $admin.multiTenancy
|
$: multiTenancyEnabled = $admin.multiTenancy
|
||||||
|
@ -38,6 +41,9 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Modal bind:this={modal} padding={false} width="600px">
|
||||||
|
<ImportAppsModal />
|
||||||
|
</Modal>
|
||||||
<section>
|
<section>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Layout>
|
<Layout>
|
||||||
|
@ -66,6 +72,15 @@
|
||||||
>
|
>
|
||||||
Change organisation
|
Change organisation
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
|
{:else}
|
||||||
|
<ActionButton
|
||||||
|
quiet
|
||||||
|
on:click={() => {
|
||||||
|
modal.show()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Import from cloud
|
||||||
|
</ActionButton>
|
||||||
{/if}
|
{/if}
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
@ -70,6 +70,15 @@
|
||||||
creatingApp = true
|
creatingApp = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const initiateAppsExport = () => {
|
||||||
|
try {
|
||||||
|
download(`/api/cloud/export`)
|
||||||
|
notifications.success("Apps exported successfully")
|
||||||
|
} catch (err) {
|
||||||
|
notifications.error(`Error exporting apps: ${err}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const initiateAppImport = () => {
|
const initiateAppImport = () => {
|
||||||
template = { fromFile: true }
|
template = { fromFile: true }
|
||||||
creationModal.show()
|
creationModal.show()
|
||||||
|
@ -190,6 +199,7 @@
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<Heading>Apps</Heading>
|
<Heading>Apps</Heading>
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
|
<Button secondary on:click={initiateAppsExport}>Export apps</Button>
|
||||||
<Button secondary on:click={initiateAppImport}>Import app</Button>
|
<Button secondary on:click={initiateAppImport}>Import app</Button>
|
||||||
<Button cta on:click={initiateAppCreation}>Create app</Button>
|
<Button cta on:click={initiateAppCreation}>Create app</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|
|
@ -37,7 +37,7 @@ async function init() {
|
||||||
const envFileJson = {
|
const envFileJson = {
|
||||||
PORT: 4001,
|
PORT: 4001,
|
||||||
MINIO_URL: "http://localhost:10000/",
|
MINIO_URL: "http://localhost:10000/",
|
||||||
COUCH_DB_URL: "http://@localhost:10000/db/",
|
COUCH_DB_URL: "http://budibase:budibase@localhost:10000/db/",
|
||||||
REDIS_URL: "localhost:6379",
|
REDIS_URL: "localhost:6379",
|
||||||
WORKER_URL: "http://localhost:4002",
|
WORKER_URL: "http://localhost:4002",
|
||||||
INTERNAL_API_KEY: "budibase",
|
INTERNAL_API_KEY: "budibase",
|
||||||
|
|
|
@ -31,7 +31,7 @@ const {
|
||||||
getDeployedApps,
|
getDeployedApps,
|
||||||
removeAppFromUserRoles,
|
removeAppFromUserRoles,
|
||||||
} = require("../../utilities/workerRequests")
|
} = require("../../utilities/workerRequests")
|
||||||
const { clientLibraryPath } = require("../../utilities")
|
const { clientLibraryPath, stringToReadStream } = require("../../utilities")
|
||||||
const { getAllLocks } = require("../../utilities/redis")
|
const { getAllLocks } = require("../../utilities/redis")
|
||||||
const {
|
const {
|
||||||
updateClientLibrary,
|
updateClientLibrary,
|
||||||
|
@ -115,7 +115,7 @@ async function createInstance(template) {
|
||||||
// replicate the template data to the instance DB
|
// replicate the template data to the instance DB
|
||||||
// this is currently very hard to test, downloading and importing template files
|
// this is currently very hard to test, downloading and importing template files
|
||||||
if (template && template.templateString) {
|
if (template && template.templateString) {
|
||||||
const { ok } = await db.load(template.templateString)
|
const { ok } = await db.load(stringToReadStream(template.templateString))
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
throw "Error loading database dump from memory."
|
throw "Error loading database dump from memory."
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ const {
|
||||||
sendTempFile,
|
sendTempFile,
|
||||||
readFileSync,
|
readFileSync,
|
||||||
} = require("../../utilities/fileSystem")
|
} = require("../../utilities/fileSystem")
|
||||||
|
const { stringToReadStream } = require("../../utilities")
|
||||||
const { getGlobalDBName, getGlobalDB } = require("@budibase/auth/tenancy")
|
const { getGlobalDBName, getGlobalDB } = require("@budibase/auth/tenancy")
|
||||||
const { create } = require("./application")
|
const { create } = require("./application")
|
||||||
|
|
||||||
|
@ -54,13 +55,15 @@ exports.importApps = async ctx => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const importFile = ctx.request.files.importFile
|
const importFile = ctx.request.files.importFile
|
||||||
const importString = readFileSync(importFile.file.path)
|
const importString = readFileSync(importFile.path)
|
||||||
const dbs = JSON.parse(importString)
|
const dbs = JSON.parse(importString)
|
||||||
const globalDb = dbs.global
|
const globalDb = dbs.global
|
||||||
|
// remove from the list of apps
|
||||||
|
delete dbs.global
|
||||||
const db = getGlobalDB()
|
const db = getGlobalDB()
|
||||||
// load the global db first
|
// load the global db first
|
||||||
await db.load(globalDb)
|
await db.load(stringToReadStream(globalDb))
|
||||||
for (let [appName, appImport] of Object.values(dbs)) {
|
for (let [appName, appImport] of Object.entries(dbs)) {
|
||||||
await createApp(appName, appImport)
|
await createApp(appName, appImport)
|
||||||
}
|
}
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
|
|
|
@ -24,6 +24,7 @@ const hostingRoutes = require("./hosting")
|
||||||
const backupRoutes = require("./backup")
|
const backupRoutes = require("./backup")
|
||||||
const metadataRoutes = require("./metadata")
|
const metadataRoutes = require("./metadata")
|
||||||
const devRoutes = require("./dev")
|
const devRoutes = require("./dev")
|
||||||
|
const cloudRoutes = require("./cloud")
|
||||||
|
|
||||||
exports.mainRoutes = [
|
exports.mainRoutes = [
|
||||||
authRoutes,
|
authRoutes,
|
||||||
|
@ -49,6 +50,7 @@ exports.mainRoutes = [
|
||||||
backupRoutes,
|
backupRoutes,
|
||||||
metadataRoutes,
|
metadataRoutes,
|
||||||
devRoutes,
|
devRoutes,
|
||||||
|
cloudRoutes,
|
||||||
// these need to be handled last as they still use /api/:tableId
|
// these need to be handled last as they still use /api/:tableId
|
||||||
// this could be breaking as koa may recognise other routes as this
|
// this could be breaking as koa may recognise other routes as this
|
||||||
tableRoutes,
|
tableRoutes,
|
||||||
|
|
|
@ -176,6 +176,15 @@ exports.storeTempFile = fileContents => {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function for getting a file read stream - a simple in memory buffered read
|
||||||
|
* stream doesn't work for pouchdb.
|
||||||
|
*/
|
||||||
|
exports.stringToFileStream = contents => {
|
||||||
|
const path = exports.storeTempFile(contents)
|
||||||
|
return fs.createReadStream(path)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a temp file and returns it from the API.
|
* Creates a temp file and returns it from the API.
|
||||||
* @param {string} fileContents the contents to be returned in file.
|
* @param {string} fileContents the contents to be returned in file.
|
||||||
|
|
|
@ -3,6 +3,7 @@ const { OBJ_STORE_DIRECTORY } = require("../constants")
|
||||||
const { sanitizeKey } = require("@budibase/auth/src/objectStore")
|
const { sanitizeKey } = require("@budibase/auth/src/objectStore")
|
||||||
const CouchDB = require("../db")
|
const CouchDB = require("../db")
|
||||||
const { generateMetadataID } = require("../db/utils")
|
const { generateMetadataID } = require("../db/utils")
|
||||||
|
const Readable = require("stream").Readable
|
||||||
|
|
||||||
const BB_CDN = "https://cdn.budi.live"
|
const BB_CDN = "https://cdn.budi.live"
|
||||||
|
|
||||||
|
@ -124,3 +125,12 @@ exports.escapeDangerousCharacters = string => {
|
||||||
.replace(/[\r]/g, "\\r")
|
.replace(/[\r]/g, "\\r")
|
||||||
.replace(/[\t]/g, "\\t")
|
.replace(/[\t]/g, "\\t")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.stringToReadStream = string => {
|
||||||
|
return new Readable({
|
||||||
|
read() {
|
||||||
|
this.push(string)
|
||||||
|
this.push(null)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue