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",
"packages": [
"packages/*"

View File

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

View File

@ -1,7 +1,7 @@
{
"name": "@budibase/bbui",
"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",
"svelte": "src/index.js",
"module": "dist/bbui.es.js",

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/builder",
"version": "0.9.190-alpha.8",
"version": "0.9.190-alpha.12",
"license": "GPL-3.0",
"private": true,
"scripts": {
@ -65,10 +65,10 @@
}
},
"dependencies": {
"@budibase/bbui": "^0.9.190-alpha.8",
"@budibase/client": "^0.9.190-alpha.8",
"@budibase/bbui": "^0.9.190-alpha.12",
"@budibase/client": "^0.9.190-alpha.12",
"@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",
"@spectrum-css/page": "^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 = []
store.update(state => {
// Stop if we have nothing to paste
@ -536,7 +536,7 @@ export const getFrontendStore = () => {
const cut = state.componentToPaste.isCut
// immediately need to remove bindings, currently these aren't valid when pasted
if (!cut) {
if (!cut && !preserveBindings) {
state.componentToPaste = removeBindings(state.componentToPaste)
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/client",
"version": "0.9.190-alpha.8",
"version": "0.9.190-alpha.12",
"license": "MPL-2.0",
"module": "dist/budibase-client.js",
"main": "dist/budibase-client.js",
@ -19,9 +19,9 @@
"dev:builder": "rollup -cw"
},
"dependencies": {
"@budibase/bbui": "^0.9.190-alpha.8",
"@budibase/bbui": "^0.9.190-alpha.12",
"@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",
"shortid": "^2.2.15",
"svelte-spa-router": "^3.0.5"

View File

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

View File

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

View File

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

View File

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

View File

@ -54,6 +54,17 @@ export enum IncludeRelationships {
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 {
type: QueryTypes
displayName?: string

View File

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

View File

@ -348,27 +348,7 @@ module OracleModule {
this.schemaErrors = final.errors
}
/**
* 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>> {
private async internalQuery<T>(query: SqlQuery): Promise<Result<T>> {
let connection
try {
connection = await this.getConnection()
@ -376,13 +356,6 @@ module OracleModule {
const options: ExecuteOptions = { autoCommit: true }
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>(
query.sql,
bindings,
@ -441,13 +414,46 @@ module OracleModule {
}
async query(json: QueryJson) {
const primaryKeys = json.meta!.table!.primary
const primaryKey = primaryKeys ? primaryKeys[0] : undefined
const queryFn = (query: any, operation: string) =>
this.internalQuery(query, primaryKey, operation)
const processFn = (response: any) => (response.rows ? response.rows : [])
const output = await this.queryWithReturning(json, queryFn, processFn)
return output
const operation = this._operation(json)
const input = this._query(json, { disableReturning: true })
if (Array.isArray(input)) {
const responses = []
for (let query of input) {
responses.push(await this.internalQuery(query))
}
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",
"version": "0.9.190-alpha.8",
"version": "0.9.190-alpha.12",
"description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs",
"module": "dist/bundle.mjs",

View File

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