Merge branch 'master' of github.com:Budibase/budibase into form-builder

This commit is contained in:
Andrew Kingston 2021-02-04 12:59:34 +00:00
commit de4b87a208
9 changed files with 60 additions and 45 deletions

View File

@ -64,7 +64,11 @@
{:else if value.customType === 'password'} {:else if value.customType === 'password'}
<Input type="password" extraThin bind:value={block.inputs[key]} /> <Input type="password" extraThin bind:value={block.inputs[key]} />
{:else if value.customType === 'email'} {:else if value.customType === 'email'}
<Input type="email" extraThin bind:value={block.inputs[key]} /> <BindableInput
type={'email'}
extraThin
bind:value={block.inputs[key]}
{bindings} />
{:else if value.customType === 'table'} {:else if value.customType === 'table'}
<TableSelector bind:value={block.inputs[key]} /> <TableSelector bind:value={block.inputs[key]} />
{:else if value.customType === 'row'} {:else if value.customType === 'row'}
@ -75,7 +79,7 @@
<SchemaSetup bind:value={block.inputs[key]} /> <SchemaSetup bind:value={block.inputs[key]} />
{:else if value.type === 'string' || value.type === 'number'} {:else if value.type === 'string' || value.type === 'number'}
<BindableInput <BindableInput
type="string" type={value.customType}
extraThin extraThin
bind:value={block.inputs[key]} bind:value={block.inputs[key]}
{bindings} /> {bindings} />

View File

@ -20,13 +20,12 @@
let exportFormat = FORMATS[0].key let exportFormat = FORMATS[0].key
async function exportView() { async function exportView() {
const response = await api.post( download(
`/api/views/export?format=${exportFormat}`, `/api/views/export?view=${encodeURIComponent(
view view.name
)}&format=${exportFormat}`
) )
const downloadInfo = await response.json()
onClosed() onClosed()
window.location = downloadInfo.url
} }
</script> </script>

View File

@ -1,6 +1,7 @@
<script> <script>
import { Popover } from "@budibase/bbui" import { Popover } from "@budibase/bbui"
import { store } from "builderStore" import { store } from "builderStore"
import { onMount } from "svelte"
import FeedbackIframe from "./FeedbackIframe.svelte" import FeedbackIframe from "./FeedbackIframe.svelte"
import analytics from "analytics" import analytics from "analytics"
@ -10,9 +11,15 @@
let iconContainer let iconContainer
let popover let popover
setInterval(() => { onMount(() => {
$store.highlightFeedbackIcon = analytics.highlightFeedbackIcon() const interval = setInterval(() => {
}, FIVE_MINUTES) store.update(state => {
state.highlightFeedbackIcon = analytics.highlightFeedbackIcon()
return state
})
}, FIVE_MINUTES)
return () => clearInterval(interval)
})
</script> </script>
<div class="container" bind:this={iconContainer} on:click={popover.show}> <div class="container" bind:this={iconContainer} on:click={popover.show}>

View File

@ -14,9 +14,10 @@
async function exportApp() { async function exportApp() {
appExportLoading = true appExportLoading = true
try { try {
download(`/api/backups/export?appId=${_id}`) download(`/api/backups/export?appId=${_id}&appname=${name}`)
notifier.success("App Export Complete.") notifier.success("App Export Complete.")
} catch (err) { } catch (err) {
console.error(err)
notifier.danger("App Export Failed.") notifier.danger("App Export Failed.")
} finally { } finally {
appExportLoading = false appExportLoading = false

View File

@ -4,12 +4,12 @@ const os = require("os")
const fs = require("fs-extra") const fs = require("fs-extra")
exports.exportAppDump = async function(ctx) { exports.exportAppDump = async function(ctx) {
const { appId } = ctx.query const { appId, appname } = ctx.query
const backupsDir = path.join(os.homedir(), ".budibase", "backups") const backupsDir = path.join(os.homedir(), ".budibase", "backups")
fs.ensureDirSync(backupsDir) fs.ensureDirSync(backupsDir)
const backupIdentifier = `${appId} Backup: ${new Date()}.txt` const backupIdentifier = `${appname}Backup${new Date().getTime()}.txt`
await performDump({ await performDump({
dir: backupsDir, dir: backupsDir,
@ -23,19 +23,4 @@ exports.exportAppDump = async function(ctx) {
ctx.attachment(backupIdentifier) ctx.attachment(backupIdentifier)
ctx.body = fs.createReadStream(backupFile) ctx.body = fs.createReadStream(backupFile)
// ctx.body = {
// url: `/api/backups/download/${backupIdentifier}`,
// }
} }
// exports.downloadAppDump = async function(ctx) {
// const fileName = ctx.params.fileName
// const backupsDir = path.join(os.homedir(), ".budibase", "backups")
// fs.ensureDirSync(backupsDir)
// const backupFile = path.join(backupsDir, fileName)
// ctx.attachment(fileName)
// ctx.body = fs.createReadStream(backupFile)
// }

View File

@ -83,23 +83,42 @@ const controller = {
ctx.message = `View ${ctx.params.viewName} saved successfully.` ctx.message = `View ${ctx.params.viewName} saved successfully.`
}, },
exportView: async ctx => { exportView: async ctx => {
const view = ctx.query.view const db = new CouchDB(ctx.user.appId)
const designDoc = await db.get("_design/database")
const viewName = decodeURI(ctx.query.view)
const view = designDoc.views[viewName]
const format = ctx.query.format const format = ctx.query.format
// Fetch view rows if (view) {
ctx.params.viewName = view.name ctx.params.viewName = viewName
ctx.query.group = view.groupBy // Fetch view rows
if (view.field) { ctx.query = {
ctx.query.stats = true group: view.meta.groupBy,
ctx.query.field = view.field calculation: view.meta.calculation,
stats: !!view.meta.field,
field: view.meta.field,
}
} else {
// table all_ view
ctx.params.viewName = viewName
} }
await fetchView(ctx) await fetchView(ctx)
let schema = view && view.meta && view.meta.schema
if (!schema) {
const tableId = ctx.params.tableId || view.meta.tableId
const table = await db.get(tableId)
schema = table.schema
}
// Export part // Export part
let headers = Object.keys(view.schema) let headers = Object.keys(schema)
const exporter = exporters[format] const exporter = exporters[format]
const exportedFile = exporter(headers, ctx.body) const exportedFile = exporter(headers, ctx.body)
const filename = `${view.name}.${format}` const filename = `${viewName}.${format}`
fs.writeFileSync(join(os.tmpdir(), filename), exportedFile) fs.writeFileSync(join(os.tmpdir(), filename), exportedFile)
ctx.attachment(filename) ctx.attachment(filename)

View File

@ -6,10 +6,5 @@ const { BUILDER } = require("../../utilities/security/permissions")
const router = Router() const router = Router()
router.get("/api/backups/export", authorized(BUILDER), controller.exportAppDump) router.get("/api/backups/export", authorized(BUILDER), controller.exportAppDump)
// .get(
// "/api/backups/download/:fileName",
// authorized(BUILDER),
// controller.downloadAppDump
// )
module.exports = router module.exports = router

View File

@ -12,6 +12,7 @@ const usage = require("../../middleware/usageQuota")
const router = Router() const router = Router()
router router
.get("/api/views/export", authorized(BUILDER), viewController.exportView)
.get( .get(
"/api/views/:viewName", "/api/views/:viewName",
authorized(PermissionTypes.VIEW, PermissionLevels.READ), authorized(PermissionTypes.VIEW, PermissionLevels.READ),
@ -25,6 +26,5 @@ router
viewController.destroy viewController.destroy
) )
.post("/api/views", authorized(BUILDER), usage, viewController.save) .post("/api/views", authorized(BUILDER), usage, viewController.save)
.post("/api/views/export", authorized(BUILDER), viewController.exportView)
module.exports = router module.exports = router

View File

@ -63,13 +63,18 @@
.nav__menu { .nav__menu {
display: flex; display: flex;
margin-top: 40px; margin-top: 40px;
gap: 16px;
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
} }
.nav__menu > a {
.nav__menu > * {
margin-right: 16px;
}
:global(.nav__menu > a) {
font-size: 1.5em; font-size: 1.5em;
text-decoration: none; text-decoration: none;
margin-right: 16px;
} }
</style> </style>