1
0
Fork 0
mirror of synced 2024-09-06 12:41:24 +12:00

Merge branch 'develop' of github.com:Budibase/budibase into feature/json-backend

This commit is contained in:
mike12345567 2021-11-30 11:32:50 +00:00
commit 39bb1f3e2c
22 changed files with 164 additions and 103 deletions

View file

@ -1,5 +1,5 @@
{ {
"version": "0.9.190-alpha.8", "version": "0.9.190-alpha.12",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*" "packages/*"

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/auth", "name": "@budibase/auth",
"version": "0.9.190-alpha.8", "version": "0.9.190-alpha.12",
"description": "Authentication middlewares for budibase builder and apps", "description": "Authentication middlewares for budibase builder and apps",
"main": "src/index.js", "main": "src/index.js",
"author": "Budibase", "author": "Budibase",

View file

@ -1,7 +1,7 @@
{ {
"name": "@budibase/bbui", "name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.", "description": "A UI solution used in the different Budibase projects.",
"version": "0.9.190-alpha.8", "version": "0.9.190-alpha.12",
"license": "MPL-2.0", "license": "MPL-2.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"module": "dist/bbui.es.js", "module": "dist/bbui.es.js",

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/builder", "name": "@budibase/builder",
"version": "0.9.190-alpha.8", "version": "0.9.190-alpha.12",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
@ -65,10 +65,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^0.9.190-alpha.8", "@budibase/bbui": "^0.9.190-alpha.12",
"@budibase/client": "^0.9.190-alpha.8", "@budibase/client": "^0.9.190-alpha.12",
"@budibase/colorpicker": "1.1.2", "@budibase/colorpicker": "1.1.2",
"@budibase/string-templates": "^0.9.190-alpha.8", "@budibase/string-templates": "^0.9.190-alpha.12",
"@sentry/browser": "5.19.1", "@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1", "@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1", "@spectrum-css/vars": "^3.0.1",

View file

@ -524,7 +524,7 @@ export const getFrontendStore = () => {
} }
} }
}, },
paste: async (targetComponent, mode) => { paste: async (targetComponent, mode, preserveBindings = false) => {
let promises = [] let promises = []
store.update(state => { store.update(state => {
// Stop if we have nothing to paste // Stop if we have nothing to paste
@ -536,7 +536,7 @@ export const getFrontendStore = () => {
const cut = state.componentToPaste.isCut const cut = state.componentToPaste.isCut
// immediately need to remove bindings, currently these aren't valid when pasted // immediately need to remove bindings, currently these aren't valid when pasted
if (!cut) { if (!cut && !preserveBindings) {
state.componentToPaste = removeBindings(state.componentToPaste) state.componentToPaste = removeBindings(state.componentToPaste)
} }

View file

@ -53,7 +53,7 @@
const duplicateComponent = () => { const duplicateComponent = () => {
storeComponentForCopy(false) storeComponentForCopy(false)
pasteComponent("below") pasteComponent("below", true)
} }
const deleteComponent = async () => { const deleteComponent = async () => {
@ -69,9 +69,9 @@
store.actions.components.copy(component, cut) store.actions.components.copy(component, cut)
} }
const pasteComponent = mode => { const pasteComponent = (mode, preserveBindings = false) => {
// lives in store - also used by drag drop // lives in store - also used by drag drop
store.actions.components.paste(component, mode) store.actions.components.paste(component, mode, preserveBindings)
} }
</script> </script>

View file

@ -25,8 +25,7 @@
key: "layout", key: "layout",
}, },
] ]
let newLayoutModal
let modal
$: selected = tabs.find(t => t.key === $params.assetType)?.title || "Screens" $: selected = tabs.find(t => t.key === $params.assetType)?.title || "Screens"
const navigate = ({ detail }) => { const navigate = ({ detail }) => {
@ -93,14 +92,18 @@
{#each $store.layouts as layout, idx (layout._id)} {#each $store.layouts as layout, idx (layout._id)}
<Layout {layout} border={idx > 0} /> <Layout {layout} border={idx > 0} />
{/each} {/each}
<Modal bind:this={modal}> <Modal bind:this={newLayoutModal}>
<NewLayoutModal /> <NewLayoutModal />
</Modal> </Modal>
</div> </div>
</Tab> </Tab>
</Tabs> </Tabs>
<div class="add-button"> <div class="add-button">
<Icon hoverable name="AddCircle" on:click={showModal()} /> <Icon
hoverable
name="AddCircle"
on:click={selected === "Layouts" ? newLayoutModal.show() : showModal()}
/>
</div> </div>
</div> </div>

View file

@ -10,16 +10,39 @@
ProgressCircle, ProgressCircle,
} from "@budibase/bbui" } from "@budibase/bbui"
import getTemplates from "builderStore/store/screenTemplates" import getTemplates from "builderStore/store/screenTemplates"
import { onDestroy } from "svelte"
import { createEventDispatcher } from "svelte"
export let selectedScreens = []
export let chooseModal export let chooseModal
export let save export let save
export let showProgressCircle = false export let showProgressCircle = false
let selectedScreens = []
const blankScreen = "createFromScratch" const blankScreen = "createFromScratch"
const dispatch = createEventDispatcher()
function setScreens() {
dispatch("save", {
screens: selectedScreens,
})
}
$: blankSelected = selectedScreens?.length === 1 $: blankSelected = selectedScreens?.length === 1
$: autoSelected = selectedScreens?.length > 0 && !blankSelected $: autoSelected = selectedScreens?.length > 0 && !blankSelected
let templates = getTemplates($store, $tables.list) let templates = getTemplates($store, $tables.list)
const confirm = async () => {
if (autoSelected) {
setScreens()
await save()
} else {
setScreens()
chooseModal(1)
}
}
const toggleScreenSelection = table => { const toggleScreenSelection = table => {
if (selectedScreens.find(s => s.table === table.name)) { if (selectedScreens.find(s => s.table === table.name)) {
selectedScreens = selectedScreens.filter( selectedScreens = selectedScreens.filter(
@ -32,14 +55,18 @@
selectedScreens = [...partialTemplates, ...selectedScreens] selectedScreens = [...partialTemplates, ...selectedScreens]
} }
} }
onDestroy(() => {
selectedScreens = []
})
</script> </script>
<div style="overflow-y: auto; max-height: 1000px"> <div>
<ModalContent <ModalContent
title="Add screens" title="Add screens"
confirmText="Add Screens" confirmText="Add Screens"
cancelText="Cancel" cancelText="Cancel"
onConfirm={() => (autoSelected ? save() : chooseModal(1))} onConfirm={() => confirm()}
disabled={!selectedScreens.length} disabled={!selectedScreens.length}
size="L" size="L"
> >
@ -70,6 +97,7 @@
{/if} {/if}
</div> </div>
</div> </div>
{#if $tables.list.filter(table => table._id !== "ta_users").length > 0}
<Detail size="S">Autogenerated Screens</Detail> <Detail size="S">Autogenerated Screens</Detail>
{#each $tables.list.filter(table => table._id !== "ta_users") as table} {#each $tables.list.filter(table => table._id !== "ta_users") as table}
@ -93,6 +121,7 @@
</div> </div>
</div> </div>
{/each} {/each}
{/if}
</Layout> </Layout>
<div slot="footer"> <div slot="footer">
{#if showProgressCircle} {#if showProgressCircle}

View file

@ -2,6 +2,7 @@
import { ModalContent, Input, ProgressCircle } from "@budibase/bbui" import { ModalContent, Input, ProgressCircle } from "@budibase/bbui"
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl" import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
import { selectedAccessRole, allScreens } from "builderStore" import { selectedAccessRole, allScreens } from "builderStore"
import { onDestroy } from "svelte"
export let screenName export let screenName
export let url export let url
@ -32,6 +33,11 @@
screen.routing.roleId === roleId screen.routing.roleId === roleId
) )
} }
onDestroy(() => {
screenName = ""
url = ""
})
</script> </script>
<ModalContent <ModalContent

View file

@ -4,7 +4,6 @@
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl" import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
import { Modal } from "@budibase/bbui" import { Modal } from "@budibase/bbui"
import { store, selectedAccessRole, allScreens } from "builderStore" import { store, selectedAccessRole, allScreens } from "builderStore"
import { onDestroy } from "svelte"
import analytics, { Events } from "analytics" import analytics, { Events } from "analytics"
let newScreenModal let newScreenModal
@ -34,7 +33,6 @@
for (let screen of createdScreens) { for (let screen of createdScreens) {
await saveScreens(screen) await saveScreens(screen)
} }
await store.actions.routing.fetch() await store.actions.routing.fetch()
selectedScreens = [] selectedScreens = []
createdScreens = [] createdScreens = []
@ -42,6 +40,7 @@
url = "" url = ""
showProgressCircle = false showProgressCircle = false
} }
const saveScreens = async draftScreen => { const saveScreens = async draftScreen => {
let existingScreenCount = $store.screens.filter( let existingScreenCount = $store.screens.filter(
s => s.props._instanceName == draftScreen.props._instanceName s => s.props._instanceName == draftScreen.props._instanceName
@ -90,17 +89,14 @@
) )
} }
onDestroy(() => {
selectedScreens = []
screenName = ""
url = ""
createdScreens = []
})
export const showModal = () => { export const showModal = () => {
newScreenModal.show() newScreenModal.show()
} }
const setScreens = evt => {
selectedScreens = evt.detail.screens
}
const chooseModal = index => { const chooseModal = index => {
/* /*
0 = newScreenModal 0 = newScreenModal
@ -119,7 +115,7 @@
<Modal bind:this={newScreenModal}> <Modal bind:this={newScreenModal}>
<NewScreenModal <NewScreenModal
bind:selectedScreens on:save={setScreens}
{showProgressCircle} {showProgressCircle}
{save} {save}
{chooseModal} {chooseModal}

View file

@ -2,13 +2,15 @@
import { Button, ActionButton, Drawer } from "@budibase/bbui" import { Button, ActionButton, Drawer } from "@budibase/bbui"
import { createEventDispatcher } from "svelte" import { createEventDispatcher } from "svelte"
import NavigationDrawer from "./NavigationDrawer.svelte" import NavigationDrawer from "./NavigationDrawer.svelte"
import { cloneDeep } from "lodash/fp"
export let value = [] export let value = []
let drawer let drawer
let links = cloneDeep(value)
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
const save = () => { const save = () => {
dispatch("change", value) dispatch("change", links)
drawer.hide() drawer.hide()
} }
</script> </script>
@ -19,5 +21,5 @@
Configure the links in your navigation bar. Configure the links in your navigation bar.
</svelte:fragment> </svelte:fragment>
<Button cta slot="buttons" on:click={save}>Save</Button> <Button cta slot="buttons" on:click={save}>Save</Button>
<NavigationDrawer slot="body" bind:links={value} /> <NavigationDrawer slot="body" bind:links />
</Drawer> </Drawer>

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/cli", "name": "@budibase/cli",
"version": "0.9.190-alpha.8", "version": "0.9.190-alpha.12",
"description": "Budibase CLI, for developers, self hosting and migrations.", "description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "src/index.js", "main": "src/index.js",
"bin": { "bin": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/client", "name": "@budibase/client",
"version": "0.9.190-alpha.8", "version": "0.9.190-alpha.12",
"license": "MPL-2.0", "license": "MPL-2.0",
"module": "dist/budibase-client.js", "module": "dist/budibase-client.js",
"main": "dist/budibase-client.js", "main": "dist/budibase-client.js",
@ -19,9 +19,9 @@
"dev:builder": "rollup -cw" "dev:builder": "rollup -cw"
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^0.9.190-alpha.8", "@budibase/bbui": "^0.9.190-alpha.12",
"@budibase/standard-components": "^0.9.139", "@budibase/standard-components": "^0.9.139",
"@budibase/string-templates": "^0.9.190-alpha.8", "@budibase/string-templates": "^0.9.190-alpha.12",
"regexparam": "^1.3.0", "regexparam": "^1.3.0",
"shortid": "^2.2.15", "shortid": "^2.2.15",
"svelte-spa-router": "^3.0.5" "svelte-spa-router": "^3.0.5"

View file

@ -313,6 +313,9 @@
height: 100%; height: 100%;
overflow: auto; overflow: auto;
} }
.desktop.layout--left .links {
overflow-y: auto;
}
.desktop .nav--left { .desktop .nav--left {
width: 250px; width: 250px;
@ -379,6 +382,7 @@
justify-content: flex-start; justify-content: flex-start;
align-items: stretch; align-items: stretch;
padding: var(--spacing-xl); padding: var(--spacing-xl);
overflow-y: auto;
} }
.mobile .link { .mobile .link {
width: calc(100% - 30px); width: calc(100% - 30px);

View file

@ -1,7 +1,7 @@
{ {
"name": "@budibase/server", "name": "@budibase/server",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "0.9.190-alpha.8", "version": "0.9.190-alpha.12",
"description": "Budibase Web Server", "description": "Budibase Web Server",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -69,9 +69,9 @@
"author": "Budibase", "author": "Budibase",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@budibase/auth": "^0.9.190-alpha.8", "@budibase/auth": "^0.9.190-alpha.12",
"@budibase/client": "^0.9.190-alpha.8", "@budibase/client": "^0.9.190-alpha.12",
"@budibase/string-templates": "^0.9.190-alpha.8", "@budibase/string-templates": "^0.9.190-alpha.12",
"@bull-board/api": "^3.7.0", "@bull-board/api": "^3.7.0",
"@bull-board/koa": "^3.7.0", "@bull-board/koa": "^3.7.0",
"@elastic/elasticsearch": "7.10.0", "@elastic/elasticsearch": "7.10.0",

View file

@ -4,7 +4,7 @@
version: "3.8" version: "3.8"
services: services:
db: db:
container_name: oracle-xe restart: always
platform: linux/x86_64 platform: linux/x86_64
image: container-registry.oracle.com/database/express:18.4.0-xe image: container-registry.oracle.com/database/express:18.4.0-xe
environment: environment:

View file

@ -1,4 +1,5 @@
import { import {
FilterTypes,
IncludeRelationships, IncludeRelationships,
Operation, Operation,
PaginationJson, PaginationJson,
@ -118,8 +119,13 @@ module External {
} }
// check the row and filters to make sure they aren't a key of some sort // check the row and filters to make sure they aren't a key of some sort
if (config.filters) { if (config.filters) {
for (let filter of Object.values(config.filters)) { for (let [key, filter] of Object.entries(config.filters)) {
if (typeof filter !== "object" || Object.keys(filter).length === 0) { // oneOf is an array, don't iterate it
if (
typeof filter !== "object" ||
Object.keys(filter).length === 0 ||
key === FilterTypes.ONE_OF
) {
continue continue
} }
iterateObject(filter) iterateObject(filter)

View file

@ -54,6 +54,17 @@ export enum IncludeRelationships {
EXCLUDE = 0, EXCLUDE = 0,
} }
export enum FilterTypes {
STRING = "string",
FUZZY = "fuzzy",
RANGE = "range",
EQUAL = "equal",
NOT_EQUAL = "notEqual",
EMPTY = "empty",
NOT_EMPTY = "notEmpty",
ONE_OF = "oneOf",
}
export interface QueryDefinition { export interface QueryDefinition {
type: QueryTypes type: QueryTypes
displayName?: string displayName?: string

View file

@ -93,7 +93,7 @@ class InternalBuilder {
if (filters.oneOf) { if (filters.oneOf) {
iterate(filters.oneOf, (key, array) => { iterate(filters.oneOf, (key, array) => {
const fnc = allOr ? "orWhereIn" : "whereIn" const fnc = allOr ? "orWhereIn" : "whereIn"
query = query[fnc](key, array) query = query[fnc](key, Array.isArray(array) ? array : [array])
}) })
} }
if (filters.string) { if (filters.string) {
@ -435,8 +435,6 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
id = results?.[0].id id = results?.[0].id
} else if (sqlClient === SqlClients.MY_SQL) { } else if (sqlClient === SqlClients.MY_SQL) {
id = results?.insertId id = results?.insertId
} else if (sqlClient === SqlClients.ORACLE) {
id = response.outBinds[0][0]
} }
row = processFn( row = processFn(
await this.getReturningRow(queryFn, this.checkLookupKeys(id, json)) await this.getReturningRow(queryFn, this.checkLookupKeys(id, json))

View file

@ -348,27 +348,7 @@ module OracleModule {
this.schemaErrors = final.errors this.schemaErrors = final.errors
} }
/** private async internalQuery<T>(query: SqlQuery): Promise<Result<T>> {
* Knex default returning behaviour does not work with oracle
* Manually add the behaviour for the return column
*/
private addReturning(
query: SqlQuery,
bindings: BindParameters,
returnColumn: string
) {
if (bindings instanceof Array) {
bindings.push({ dir: oracledb.BIND_OUT })
query.sql =
query.sql + ` returning \"${returnColumn}\" into :${bindings.length}`
}
}
private async internalQuery<T>(
query: SqlQuery,
returnColum?: string,
operation?: string
): Promise<Result<T>> {
let connection let connection
try { try {
connection = await this.getConnection() connection = await this.getConnection()
@ -376,13 +356,6 @@ module OracleModule {
const options: ExecuteOptions = { autoCommit: true } const options: ExecuteOptions = { autoCommit: true }
const bindings: BindParameters = query.bindings || [] const bindings: BindParameters = query.bindings || []
if (
returnColum &&
(operation === Operation.CREATE || operation === Operation.UPDATE)
) {
this.addReturning(query, bindings, returnColum)
}
const result: Result<T> = await connection.execute<T>( const result: Result<T> = await connection.execute<T>(
query.sql, query.sql,
bindings, bindings,
@ -441,13 +414,46 @@ module OracleModule {
} }
async query(json: QueryJson) { async query(json: QueryJson) {
const primaryKeys = json.meta!.table!.primary const operation = this._operation(json)
const primaryKey = primaryKeys ? primaryKeys[0] : undefined const input = this._query(json, { disableReturning: true })
const queryFn = (query: any, operation: string) => if (Array.isArray(input)) {
this.internalQuery(query, primaryKey, operation) const responses = []
const processFn = (response: any) => (response.rows ? response.rows : []) for (let query of input) {
const output = await this.queryWithReturning(json, queryFn, processFn) responses.push(await this.internalQuery(query))
return output }
return responses
} else {
// read the row to be deleted up front for the return
let deletedRows
if (operation === Operation.DELETE) {
const queryFn = (query: any) => this.internalQuery(query)
deletedRows = await this.getReturningRow(queryFn, json)
}
// run the query
const response = await this.internalQuery(input)
// get the results or return the created / updated / deleted row
if (deletedRows?.rows?.length) {
return deletedRows.rows
} else if (response.rows?.length) {
return response.rows
} else {
// get the last row that was updated
if (
response.lastRowid &&
json.endpoint?.entityId &&
operation !== Operation.DELETE
) {
const lastRow = await this.internalQuery({
sql: `SELECT * FROM \"${json.endpoint.entityId}\" WHERE ROWID = '${response.lastRowid}'`,
})
return lastRow.rows
} else {
return [{ [ operation.toLowerCase() ]: true }]
}
}
}
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/string-templates", "name": "@budibase/string-templates",
"version": "0.9.190-alpha.8", "version": "0.9.190-alpha.12",
"description": "Handlebars wrapper for Budibase templating.", "description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs", "main": "src/index.cjs",
"module": "dist/bundle.mjs", "module": "dist/bundle.mjs",

View file

@ -1,7 +1,7 @@
{ {
"name": "@budibase/worker", "name": "@budibase/worker",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "0.9.190-alpha.8", "version": "0.9.190-alpha.12",
"description": "Budibase background service", "description": "Budibase background service",
"main": "src/index.js", "main": "src/index.js",
"repository": { "repository": {
@ -29,8 +29,8 @@
"author": "Budibase", "author": "Budibase",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@budibase/auth": "^0.9.190-alpha.8", "@budibase/auth": "^0.9.190-alpha.12",
"@budibase/string-templates": "^0.9.190-alpha.8", "@budibase/string-templates": "^0.9.190-alpha.12",
"@koa/router": "^8.0.0", "@koa/router": "^8.0.0",
"@sentry/node": "^6.0.0", "@sentry/node": "^6.0.0",
"@techpass/passport-openidconnect": "^0.3.0", "@techpass/passport-openidconnect": "^0.3.0",