1
0
Fork 0
mirror of synced 2024-09-08 05:31:47 +12:00

Merge remote-tracking branch 'origin/master' into fix/inclusion-row-parsing

This commit is contained in:
Dean 2023-05-05 15:22:49 +01:00
commit 03c048f978
52 changed files with 256 additions and 164 deletions

View file

@ -1,5 +1,5 @@
{ {
"version": "2.6.0", "version": "2.6.6",
"npmClient": "yarn", "npmClient": "yarn",
"useWorkspaces": true, "useWorkspaces": true,
"packages": ["packages/*"], "packages": ["packages/*"],

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/backend-core", "name": "@budibase/backend-core",
"version": "2.6.0", "version": "2.6.6",
"description": "Budibase backend core libraries used in server and worker", "description": "Budibase backend core libraries used in server and worker",
"main": "dist/src/index.js", "main": "dist/src/index.js",
"types": "dist/src/index.d.ts", "types": "dist/src/index.d.ts",
@ -24,7 +24,7 @@
"dependencies": { "dependencies": {
"@budibase/nano": "10.1.2", "@budibase/nano": "10.1.2",
"@budibase/pouchdb-replication-stream": "1.2.10", "@budibase/pouchdb-replication-stream": "1.2.10",
"@budibase/types": "^2.6.0", "@budibase/types": "^2.6.6",
"@shopify/jest-koa-mocks": "5.0.1", "@shopify/jest-koa-mocks": "5.0.1",
"@techpass/passport-openidconnect": "0.3.2", "@techpass/passport-openidconnect": "0.3.2",
"aws-cloudfront-sign": "2.2.0", "aws-cloudfront-sign": "2.2.0",

View file

@ -96,6 +96,7 @@ const environment = {
SALT_ROUNDS: process.env.SALT_ROUNDS, SALT_ROUNDS: process.env.SALT_ROUNDS,
REDIS_URL: process.env.REDIS_URL || "localhost:6379", REDIS_URL: process.env.REDIS_URL || "localhost:6379",
REDIS_PASSWORD: process.env.REDIS_PASSWORD || "budibase", REDIS_PASSWORD: process.env.REDIS_PASSWORD || "budibase",
REDIS_CLUSTERED: process.env.REDIS_CLUSTERED,
MOCK_REDIS: process.env.MOCK_REDIS, MOCK_REDIS: process.env.MOCK_REDIS,
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY, MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY, MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,

View file

@ -40,6 +40,12 @@ function logging(queue: Queue, jobQueue: JobQueue) {
case JobQueue.APP_BACKUP: case JobQueue.APP_BACKUP:
eventType = "app-backup-event" eventType = "app-backup-event"
break break
case JobQueue.AUDIT_LOG:
eventType = "audit-log-event"
break
case JobQueue.SYSTEM_EVENT_QUEUE:
eventType = "system-event"
break
} }
if (process.env.NODE_DEBUG?.includes("bull")) { if (process.env.NODE_DEBUG?.includes("bull")) {
queue queue

View file

@ -12,7 +12,7 @@ import * as timers from "../timers"
const RETRY_PERIOD_MS = 2000 const RETRY_PERIOD_MS = 2000
const STARTUP_TIMEOUT_MS = 5000 const STARTUP_TIMEOUT_MS = 5000
const CLUSTERED = false const CLUSTERED = env.REDIS_CLUSTERED
const DEFAULT_SELECT_DB = SelectableDatabase.DEFAULT const DEFAULT_SELECT_DB = SelectableDatabase.DEFAULT
// for testing just generate the client once // for testing just generate the client once
@ -81,7 +81,7 @@ function init(selectDb = DEFAULT_SELECT_DB) {
if (client) { if (client) {
client.disconnect() client.disconnect()
} }
const { redisProtocolUrl, opts, host, port } = getRedisOptions(CLUSTERED) const { redisProtocolUrl, opts, host, port } = getRedisOptions()
if (CLUSTERED) { if (CLUSTERED) {
client = new Redis.Cluster([{ host, port }], opts) client = new Redis.Cluster([{ host, port }], opts)

View file

@ -57,7 +57,7 @@ export enum SelectableDatabase {
UNUSED_14 = 15, UNUSED_14 = 15,
} }
export function getRedisOptions(clustered = false) { export function getRedisOptions() {
let password = env.REDIS_PASSWORD let password = env.REDIS_PASSWORD
let url: string[] | string = env.REDIS_URL.split("//") let url: string[] | string = env.REDIS_URL.split("//")
// get rid of the protocol // get rid of the protocol
@ -83,7 +83,7 @@ export function getRedisOptions(clustered = false) {
const opts: any = { const opts: any = {
connectTimeout: CONNECT_TIMEOUT_MS, connectTimeout: CONNECT_TIMEOUT_MS,
} }
if (clustered) { if (env.REDIS_CLUSTERED) {
opts.redisOptions = {} opts.redisOptions = {}
opts.redisOptions.tls = {} opts.redisOptions.tls = {}
opts.redisOptions.password = password opts.redisOptions.password = password

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": "2.6.0", "version": "2.6.6",
"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",
@ -38,8 +38,8 @@
], ],
"dependencies": { "dependencies": {
"@adobe/spectrum-css-workflow-icons": "1.2.1", "@adobe/spectrum-css-workflow-icons": "1.2.1",
"@budibase/shared-core": "^2.6.0", "@budibase/shared-core": "^2.6.6",
"@budibase/string-templates": "^2.6.0", "@budibase/string-templates": "^2.6.6",
"@spectrum-css/accordion": "3.0.24", "@spectrum-css/accordion": "3.0.24",
"@spectrum-css/actionbutton": "1.0.1", "@spectrum-css/actionbutton": "1.0.1",
"@spectrum-css/actiongroup": "1.0.1", "@spectrum-css/actiongroup": "1.0.1",

View file

@ -1,4 +1,8 @@
const ignoredClasses = [".flatpickr-calendar", ".spectrum-Popover"] const ignoredClasses = [
".flatpickr-calendar",
".spectrum-Popover",
".download-js-link",
]
let clickHandlers = [] let clickHandlers = []
/** /**
@ -22,8 +26,8 @@ const handleClick = event => {
} }
// Ignore clicks for modals, unless the handler is registered from a modal // Ignore clicks for modals, unless the handler is registered from a modal
const sourceInModal = handler.anchor.closest(".spectrum-Modal") != null const sourceInModal = handler.anchor.closest(".spectrum-Underlay") != null
const clickInModal = event.target.closest(".spectrum-Modal") != null const clickInModal = event.target.closest(".spectrum-Underlay") != null
if (clickInModal && !sourceInModal) { if (clickInModal && !sourceInModal) {
return return
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"> <g id="Make-App-Icon-Circle" transform="translate(3757 -1767)"> <circle id="Ellipse_10" data-name="Ellipse 10" cx="256" cy="256" r="256" transform="translate(-3757 1767)" fill="#6d00cc"/> <path id="Path_141560" data-name="Path 141560" d="M244.78,14.544a7.187,7.187,0,0,0-7.186,7.192V213.927a7.19,7.19,0,0,0,7.186,7.192h52.063a7.187,7.187,0,0,0,7.186-7.192V21.736a7.183,7.183,0,0,0-7.186-7.192ZM92.066,17.083,5.77,188.795a7.191,7.191,0,0,0,3.192,9.654l46.514,23.379a7.184,7.184,0,0,0,9.654-3.2l86.3-171.711a7.184,7.184,0,0,0-3.2-9.654L101.719,13.886a7.2,7.2,0,0,0-9.654,3.2m72.592.614L127.731,204.876a7.189,7.189,0,0,0,5.632,8.442l51.028,10.306a7.2,7.2,0,0,0,8.481-5.665L229.8,30.786a7.19,7.19,0,0,0-5.637-8.442L173.133,12.038a7.391,7.391,0,0,0-1.427-.144,7.194,7.194,0,0,0-7.048,5.8" transform="translate(-3676.356 1905.425)" fill="#fff"/> </g> </svg>

After

Width:  |  Height:  |  Size: 951 B

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/builder", "name": "@budibase/builder",
"version": "2.6.0", "version": "2.6.6",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
@ -58,10 +58,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^2.6.0", "@budibase/bbui": "^2.6.6",
"@budibase/frontend-core": "^2.6.0", "@budibase/frontend-core": "^2.6.6",
"@budibase/shared-core": "^2.6.0", "@budibase/shared-core": "^2.6.6",
"@budibase/string-templates": "^2.6.0", "@budibase/string-templates": "^2.6.6",
"@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-brands-svg-icons": "^6.2.1", "@fortawesome/free-brands-svg-icons": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1", "@fortawesome/free-solid-svg-icons": "^6.2.1",

View file

@ -94,7 +94,7 @@
/> />
<span class="icon-spacing"> <span class="icon-spacing">
<Body size="XS"> <Body size="XS">
{idx.charAt(0).toUpperCase() + idx.slice(1)} {action.stepTitle || idx.charAt(0).toUpperCase() + idx.slice(1)}
</Body> </Body>
</span> </span>
</div> </div>

View file

@ -1,11 +1,11 @@
import DiscordLogo from "assets/discord.svg" import DiscordLogo from "assets/discord.svg"
import ZapierLogo from "assets/zapier.png" import ZapierLogo from "assets/zapier.png"
import IntegromatLogo from "assets/integromat.png" import MakeLogo from "assets/make.svg"
import SlackLogo from "assets/slack.svg" import SlackLogo from "assets/slack.svg"
export const externalActions = { export const externalActions = {
zapier: { name: "zapier", icon: ZapierLogo }, zapier: { name: "zapier", icon: ZapierLogo },
discord: { name: "discord", icon: DiscordLogo }, discord: { name: "discord", icon: DiscordLogo },
slack: { name: "slack", icon: SlackLogo }, slack: { name: "slack", icon: SlackLogo },
integromat: { name: "integromat", icon: IntegromatLogo }, integromat: { name: "integromat", icon: MakeLogo },
} }

View file

@ -39,7 +39,7 @@
{#if datasource} {#if datasource}
<div> <div>
<ActionButton icon="DataCorrelated" primary quiet on:click={modal.show}> <ActionButton icon="DataCorrelated" primary quiet on:click={modal.show}>
Define existing relationship Define relationship
</ActionButton> </ActionButton>
</div> </div>
<Modal bind:this={modal}> <Modal bind:this={modal}>

View file

@ -9,13 +9,21 @@
$: selectedRowArray = Object.keys($selectedRows).map(id => ({ _id: id })) $: selectedRowArray = Object.keys($selectedRows).map(id => ({ _id: id }))
</script> </script>
<ExportButton <span data-ignore-click-outside="true">
{disabled} <ExportButton
view={$tableId} {disabled}
filters={$filter} view={$tableId}
sorting={{ filters={$filter}
sortColumn: $sort.column, sorting={{
sortOrder: $sort.order, sortColumn: $sort.column,
}} sortOrder: $sort.order,
selectedRows={selectedRowArray} }}
/> selectedRows={selectedRowArray}
/>
</span>
<style>
span {
display: contents;
}
</style>

View file

@ -2,19 +2,19 @@
import TableFilterButton from "../TableFilterButton.svelte" import TableFilterButton from "../TableFilterButton.svelte"
import { getContext } from "svelte" import { getContext } from "svelte"
const { columns, config, filter, table } = getContext("grid") const { columns, tableId, filter, table } = getContext("grid")
const onFilter = e => { const onFilter = e => {
filter.set(e.detail || []) filter.set(e.detail || [])
} }
</script> </script>
{#key $config.tableId} {#key $tableId}
<TableFilterButton <TableFilterButton
schema={$table?.schema} schema={$table?.schema}
filters={$filter} filters={$filter}
on:change={onFilter} on:change={onFilter}
disabled={!$columns.length} disabled={!$columns.length}
tableId={$config.tableId} tableId={$tableId}
/> />
{/key} {/key}

View file

@ -2,7 +2,7 @@
import ManageAccessButton from "../ManageAccessButton.svelte" import ManageAccessButton from "../ManageAccessButton.svelte"
import { getContext } from "svelte" import { getContext } from "svelte"
const { config } = getContext("grid") const { tableId } = getContext("grid")
</script> </script>
<ManageAccessButton resourceId={$config.tableId} /> <ManageAccessButton resourceId={$tableId} />

View file

@ -147,6 +147,9 @@ const buildUsersAboveLimitBanner = EXPIRY_KEY => {
return { return {
key: EXPIRY_KEY, key: EXPIRY_KEY,
type: BANNER_TYPES.WARNING, type: BANNER_TYPES.WARNING,
onChange: () => {
defaultCacheFn(EXPIRY_KEY)
},
criteria: () => { criteria: () => {
return userLicensing.warnUserLimit return userLicensing.warnUserLimit
}, },

View file

@ -261,7 +261,7 @@
header={`Users will soon be limited to ${staticUserLimit}`} header={`Users will soon be limited to ${staticUserLimit}`}
message={`Our free plan is going to be limited to ${staticUserLimit} users in ${$licensing.userLimitDays}. message={`Our free plan is going to be limited to ${staticUserLimit} users in ${$licensing.userLimitDays}.
This means any users exceeding the limit have been de-activated. This means any users exceeding the limit will be de-activated.
De-activated users will not able to access the builder or any published apps until you upgrade to one of our paid plans. De-activated users will not able to access the builder or any published apps until you upgrade to one of our paid plans.
`} `}

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/cli", "name": "@budibase/cli",
"version": "2.6.0", "version": "2.6.6",
"description": "Budibase CLI, for developers, self hosting and migrations.", "description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "dist/index.js", "main": "dist/index.js",
"bin": { "bin": {
@ -29,9 +29,9 @@
"outputPath": "build" "outputPath": "build"
}, },
"dependencies": { "dependencies": {
"@budibase/backend-core": "^2.6.0", "@budibase/backend-core": "^2.6.6",
"@budibase/string-templates": "^2.6.0", "@budibase/string-templates": "^2.6.6",
"@budibase/types": "^2.6.0", "@budibase/types": "^2.6.6",
"axios": "0.21.2", "axios": "0.21.2",
"chalk": "4.1.0", "chalk": "4.1.0",
"cli-progress": "3.11.2", "cli-progress": "3.11.2",

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/client", "name": "@budibase/client",
"version": "2.6.0", "version": "2.6.6",
"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,11 +19,11 @@
"dev:builder": "rollup -cw" "dev:builder": "rollup -cw"
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^2.6.0", "@budibase/bbui": "^2.6.6",
"@budibase/frontend-core": "^2.6.0", "@budibase/frontend-core": "^2.6.6",
"@budibase/shared-core": "^2.6.0", "@budibase/shared-core": "^2.6.6",
"@budibase/string-templates": "^2.6.0", "@budibase/string-templates": "^2.6.6",
"@budibase/types": "^2.6.0", "@budibase/types": "^2.6.6",
"@spectrum-css/button": "^3.0.3", "@spectrum-css/button": "^3.0.3",
"@spectrum-css/card": "^3.0.3", "@spectrum-css/card": "^3.0.3",
"@spectrum-css/divider": "^1.0.3", "@spectrum-css/divider": "^1.0.3",

View file

@ -384,7 +384,7 @@ const confirmTextMap = {
["Save Row"]: "Are you sure you want to save this row?", ["Save Row"]: "Are you sure you want to save this row?",
["Execute Query"]: "Are you sure you want to execute this query?", ["Execute Query"]: "Are you sure you want to execute this query?",
["Trigger Automation"]: "Are you sure you want to trigger this automation?", ["Trigger Automation"]: "Are you sure you want to trigger this automation?",
["Prompt User"]: "Are you sure you want to contiune?", ["Prompt User"]: "Are you sure you want to continue?",
} }
/** /**

View file

@ -1,13 +1,13 @@
{ {
"name": "@budibase/frontend-core", "name": "@budibase/frontend-core",
"version": "2.6.0", "version": "2.6.6",
"description": "Budibase frontend core libraries used in builder and client", "description": "Budibase frontend core libraries used in builder and client",
"author": "Budibase", "author": "Budibase",
"license": "MPL-2.0", "license": "MPL-2.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"dependencies": { "dependencies": {
"@budibase/bbui": "^2.6.0", "@budibase/bbui": "^2.6.6",
"@budibase/shared-core": "^2.6.0", "@budibase/shared-core": "^2.6.6",
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"socket.io-client": "^4.6.1", "socket.io-client": "^4.6.1",

View file

@ -70,7 +70,15 @@
</div> </div>
{/if} {/if}
{/if} {/if}
{#if $config.allowExpandRows} {#if rowSelected && $config.allowDeleteRows}
<div class="delete" on:click={() => dispatch("request-bulk-delete")}>
<Icon
name="Delete"
size="S"
color="var(--spectrum-global-color-red-400)"
/>
</div>
{:else if $config.allowExpandRows}
<div <div
class="expand" class="expand"
class:visible={!disableExpand && (rowFocused || rowHovered)} class:visible={!disableExpand && (rowFocused || rowHovered)}
@ -111,9 +119,12 @@
.number.visible { .number.visible {
display: flex; display: flex;
} }
.delete,
.expand {
margin-right: 4px;
}
.expand { .expand {
opacity: 0; opacity: 0;
margin-right: 4px;
} }
.expand :global(.spectrum-Icon) { .expand :global(.spectrum-Icon) {
pointer-events: none; pointer-events: none;
@ -124,4 +135,11 @@
.expand.visible :global(.spectrum-Icon) { .expand.visible :global(.spectrum-Icon) {
pointer-events: all; pointer-events: all;
} }
.delete:hover {
cursor: pointer;
}
.delete:hover :global(.spectrum-Icon) {
color: var(--spectrum-global-color-red-600) !important;
}
</style> </style>

View file

@ -1,8 +1,8 @@
<script> <script>
import { Modal, ModalContent, Button, notifications } from "@budibase/bbui" import { Modal, ModalContent, notifications } from "@budibase/bbui"
import { getContext, onMount } from "svelte" import { getContext, onMount } from "svelte"
const { selectedRows, rows, config, subscribe } = getContext("grid") const { selectedRows, rows, subscribe } = getContext("grid")
let modal let modal
@ -27,20 +27,6 @@
onMount(() => subscribe("request-bulk-delete", () => modal?.show())) onMount(() => subscribe("request-bulk-delete", () => modal?.show()))
</script> </script>
{#if selectedRowCount}
<div class="delete-button" data-ignore-click-outside="true">
<Button
icon="Delete"
size="M"
on:click={modal.show}
disabled={!$config.allowEditRows}
cta
>
Delete {selectedRowCount} row{selectedRowCount === 1 ? "" : "s"}
</Button>
</div>
{/if}
<Modal bind:this={modal}> <Modal bind:this={modal}>
<ModalContent <ModalContent
title="Delete rows" title="Delete rows"
@ -53,14 +39,3 @@
row{selectedRowCount === 1 ? "" : "s"}? row{selectedRowCount === 1 ? "" : "s"}?
</ModalContent> </ModalContent>
</Modal> </Modal>
<style>
.delete-button :global(.spectrum-Button:not(:disabled)) {
background-color: var(--spectrum-global-color-red-400);
border-color: var(--spectrum-global-color-red-400);
}
.delete-button :global(.spectrum-Button:not(:disabled):hover) {
background-color: var(--spectrum-global-color-red-500);
border-color: var(--spectrum-global-color-red-500);
}
</style>

View file

@ -3,7 +3,7 @@
import { ActionButton, Popover } from "@budibase/bbui" import { ActionButton, Popover } from "@budibase/bbui"
import { DefaultColumnWidth } from "../lib/constants" import { DefaultColumnWidth } from "../lib/constants"
const { stickyColumn, columns } = getContext("grid") const { stickyColumn, columns, compact } = getContext("grid")
const smallSize = 120 const smallSize = 120
const mediumSize = DefaultColumnWidth const mediumSize = DefaultColumnWidth
const largeSize = DefaultColumnWidth * 1.5 const largeSize = DefaultColumnWidth * 1.5
@ -59,12 +59,13 @@
on:click={() => (open = !open)} on:click={() => (open = !open)}
selected={open} selected={open}
disabled={!allCols.length} disabled={!allCols.length}
tooltip={$compact ? "Width" : null}
> >
Width {$compact ? "" : "Width"}
</ActionButton> </ActionButton>
</div> </div>
<Popover bind:open {anchor} align="left"> <Popover bind:open {anchor} align={$compact ? "right" : "left"}>
<div class="content"> <div class="content">
{#each sizeOptions as option} {#each sizeOptions as option}
<ActionButton <ActionButton

View file

@ -1,8 +1,9 @@
<script> <script>
import { getContext } from "svelte" import { getContext } from "svelte"
import { ActionButton, Popover, Toggle } from "@budibase/bbui" import { ActionButton, Popover, Toggle, Icon } from "@budibase/bbui"
import { getColumnIcon } from "../lib/utils"
const { columns, stickyColumn } = getContext("grid") const { columns, stickyColumn, compact } = getContext("grid")
let open = false let open = false
let anchor let anchor
@ -47,25 +48,32 @@
on:click={() => (open = !open)} on:click={() => (open = !open)}
selected={open || anyHidden} selected={open || anyHidden}
disabled={!$columns.length} disabled={!$columns.length}
tooltip={$compact ? "Columns" : ""}
> >
Columns {$compact ? "" : "Columns"}
</ActionButton> </ActionButton>
</div> </div>
<Popover bind:open {anchor} align="left"> <Popover bind:open {anchor} align={$compact ? "right" : "left"}>
<div class="content"> <div class="content">
<div class="columns"> <div class="columns">
{#if $stickyColumn} {#if $stickyColumn}
<div class="column">
<Icon size="S" name={getColumnIcon($stickyColumn)} />
{$stickyColumn.label}
</div>
<Toggle disabled size="S" value={true} /> <Toggle disabled size="S" value={true} />
<span>{$stickyColumn.label}</span>
{/if} {/if}
{#each $columns as column} {#each $columns as column}
<div class="column">
<Icon size="S" name={getColumnIcon(column)} />
{column.label}
</div>
<Toggle <Toggle
size="S" size="S"
value={column.visible} value={column.visible}
on:change={e => toggleVisibility(column, e.detail)} on:change={e => toggleVisibility(column, e.detail)}
/> />
<span>{column.label}</span>
{/each} {/each}
</div> </div>
<div class="buttons"> <div class="buttons">
@ -90,6 +98,13 @@
.columns { .columns {
display: grid; display: grid;
align-items: center; align-items: center;
grid-template-columns: auto 1fr; grid-template-columns: 1fr auto;
}
.columns :global(.spectrum-Switch) {
margin-right: 0;
}
.column {
display: flex;
gap: 8px;
} }
</style> </style>

View file

@ -7,7 +7,7 @@
SmallRowHeight, SmallRowHeight,
} from "../lib/constants" } from "../lib/constants"
const { rowHeight, columns, table } = getContext("grid") const { rowHeight, columns, table, compact } = getContext("grid")
const sizeOptions = [ const sizeOptions = [
{ {
label: "Small", label: "Small",
@ -41,12 +41,13 @@
size="M" size="M"
on:click={() => (open = !open)} on:click={() => (open = !open)}
selected={open} selected={open}
tooltip={$compact ? "Height" : null}
> >
Height {$compact ? "" : "Height"}
</ActionButton> </ActionButton>
</div> </div>
<Popover bind:open {anchor} align="left"> <Popover bind:open {anchor} align={$compact ? "right" : "left"}>
<div class="content"> <div class="content">
{#each sizeOptions as option} {#each sizeOptions as option}
<ActionButton <ActionButton

View file

@ -2,7 +2,7 @@
import { getContext } from "svelte" import { getContext } from "svelte"
import { ActionButton, Popover, Select } from "@budibase/bbui" import { ActionButton, Popover, Select } from "@budibase/bbui"
const { sort, columns, stickyColumn } = getContext("grid") const { sort, columns, stickyColumn, compact } = getContext("grid")
let open = false let open = false
let anchor let anchor
@ -90,12 +90,13 @@
on:click={() => (open = !open)} on:click={() => (open = !open)}
selected={open} selected={open}
disabled={!columnOptions.length} disabled={!columnOptions.length}
tooltip={$compact ? "Sort" : ""}
> >
Sort {$compact ? "" : "Sort"}
</ActionButton> </ActionButton>
</div> </div>
<Popover bind:open {anchor} align="left"> <Popover bind:open {anchor} align={$compact ? "right" : "left"}>
<div class="content"> <div class="content">
<Select <Select
placeholder={null} placeholder={null}

View file

@ -6,7 +6,7 @@
import { createEventManagers } from "../lib/events" import { createEventManagers } from "../lib/events"
import { createAPIClient } from "../../../api" import { createAPIClient } from "../../../api"
import { attachStores } from "../stores" import { attachStores } from "../stores"
import DeleteButton from "../controls/DeleteButton.svelte" import BulkDeleteHandler from "../controls/BulkDeleteHandler.svelte"
import BetaButton from "../controls/BetaButton.svelte" import BetaButton from "../controls/BetaButton.svelte"
import GridBody from "./GridBody.svelte" import GridBody from "./GridBody.svelte"
import ResizeOverlay from "../overlays/ResizeOverlay.svelte" import ResizeOverlay from "../overlays/ResizeOverlay.svelte"
@ -112,13 +112,12 @@
<AddRowButton /> <AddRowButton />
<AddColumnButton /> <AddColumnButton />
<slot name="controls" /> <slot name="controls" />
<SortButton />
<HideColumnsButton />
<ColumnWidthButton /> <ColumnWidthButton />
<RowHeightButton /> <RowHeightButton />
<HideColumnsButton />
<SortButton />
</div> </div>
<div class="controls-right"> <div class="controls-right">
<DeleteButton />
<UserAvatars /> <UserAvatars />
</div> </div>
</div> </div>
@ -131,7 +130,9 @@
<GridBody /> <GridBody />
</div> </div>
<BetaButton /> <BetaButton />
<NewRow /> {#if allowAddRows}
<NewRow />
{/if}
<div class="overlays"> <div class="overlays">
<ResizeOverlay /> <ResizeOverlay />
<ReorderOverlay /> <ReorderOverlay />
@ -146,6 +147,9 @@
<ProgressCircle /> <ProgressCircle />
</div> </div>
{/if} {/if}
{#if allowDeleteRows}
<BulkDeleteHandler />
{/if}
<KeyboardManager /> <KeyboardManager />
</div> </div>
@ -214,6 +218,7 @@
padding: var(--cell-padding); padding: var(--cell-padding);
gap: var(--cell-spacing); gap: var(--cell-spacing);
background: var(--background); background: var(--background);
z-index: 2;
} }
.controls-left, .controls-left,
.controls-right { .controls-right {
@ -239,7 +244,7 @@
height: 100%; height: 100%;
display: grid; display: grid;
place-items: center; place-items: center;
z-index: 10; z-index: 100;
} }
.grid-loading:before { .grid-loading:before {
content: ""; content: "";

View file

@ -4,8 +4,14 @@
import HeaderCell from "../cells/HeaderCell.svelte" import HeaderCell from "../cells/HeaderCell.svelte"
import { Icon } from "@budibase/bbui" import { Icon } from "@budibase/bbui"
const { renderedColumns, dispatch, scroll, hiddenColumnsWidth, width } = const {
getContext("grid") renderedColumns,
dispatch,
scroll,
hiddenColumnsWidth,
width,
config,
} = getContext("grid")
$: columnsWidth = $renderedColumns.reduce( $: columnsWidth = $renderedColumns.reduce(
(total, col) => (total += col.width), (total, col) => (total += col.width),
@ -23,13 +29,15 @@
{/each} {/each}
</div> </div>
</GridScrollWrapper> </GridScrollWrapper>
<div {#if $config.allowAddColumns}
class="add" <div
style="left:{left}px" class="add"
on:click={() => dispatch("add-column")} style="left:{left}px"
> on:click={() => dispatch("add-column")}
<Icon name="Add" /> >
</div> <Icon name="Add" />
</div>
{/if}
</div> </div>
<style> <style>
@ -38,7 +46,6 @@
border-bottom: var(--cell-border); border-bottom: var(--cell-border);
position: relative; position: relative;
height: var(--default-row-height); height: var(--default-row-height);
z-index: 1;
} }
.row { .row {
display: flex; display: flex;
@ -54,6 +61,7 @@
border-right: var(--cell-border); border-right: var(--cell-border);
border-bottom: var(--cell-border); border-bottom: var(--cell-border);
background: var(--spectrum-global-color-gray-100); background: var(--spectrum-global-color-gray-100);
z-index: 20;
} }
.add:hover { .add:hover {
background: var(--spectrum-global-color-gray-200); background: var(--spectrum-global-color-gray-200);

View file

@ -270,7 +270,7 @@
z-index: 3; z-index: 3;
position: absolute; position: absolute;
top: calc(var(--row-height) + var(--offset) + 24px); top: calc(var(--row-height) + var(--offset) + 24px);
left: var(--gutter-width); left: 18px;
} }
.button-with-keys { .button-with-keys {
display: flex; display: flex;

View file

@ -21,6 +21,9 @@ const TypeIconMap = {
} }
export const getColumnIcon = column => { export const getColumnIcon = column => {
if (column.schema.autocolumn) {
return "MagicWand"
}
const type = column.schema.type const type = column.schema.type
return TypeIconMap[type] || "Text" return TypeIconMap[type] || "Text"
} }

View file

@ -13,6 +13,7 @@
clipboard, clipboard,
dispatch, dispatch,
selectedRows, selectedRows,
config,
} = getContext("grid") } = getContext("grid")
const ignoredOriginSelectors = [ const ignoredOriginSelectors = [
@ -37,10 +38,12 @@
e.preventDefault() e.preventDefault()
focusFirstCell() focusFirstCell()
} else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) { } else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
e.preventDefault() if ($config.allowAddRows) {
dispatch("add-row-inline") e.preventDefault()
dispatch("add-row-inline")
}
} else if (e.key === "Delete" || e.key === "Backspace") { } else if (e.key === "Delete" || e.key === "Backspace") {
if (Object.keys($selectedRows).length) { if (Object.keys($selectedRows).length && $config.allowDeleteRows) {
dispatch("request-bulk-delete") dispatch("request-bulk-delete")
} }
} }
@ -88,7 +91,9 @@
} }
break break
case "Enter": case "Enter":
dispatch("add-row-inline") if ($config.allowAddRows) {
dispatch("add-row-inline")
}
} }
} else { } else {
switch (e.key) { switch (e.key) {
@ -106,7 +111,7 @@
break break
case "Delete": case "Delete":
case "Backspace": case "Backspace":
if (Object.keys($selectedRows).length) { if (Object.keys($selectedRows).length && $config.allowDeleteRows) {
dispatch("request-bulk-delete") dispatch("request-bulk-delete")
} else { } else {
deleteSelectedCell() deleteSelectedCell()
@ -117,7 +122,9 @@
break break
case " ": case " ":
case "Space": case "Space":
toggleSelectRow() if ($config.allowDeleteRows) {
toggleSelectRow()
}
break break
default: default:
startEnteringValue(e.key, e.which) startEnteringValue(e.key, e.which)

View file

@ -2,6 +2,7 @@ import { writable, get, derived } from "svelte/store"
import { tick } from "svelte" import { tick } from "svelte"
import { import {
DefaultRowHeight, DefaultRowHeight,
GutterWidth,
LargeRowHeight, LargeRowHeight,
MediumRowHeight, MediumRowHeight,
NewRowID, NewRowID,
@ -43,6 +44,8 @@ export const deriveStores = context => {
enrichedRows, enrichedRows,
rowLookupMap, rowLookupMap,
rowHeight, rowHeight,
stickyColumn,
width,
} = context } = context
// Derive the row that contains the selected cell // Derive the row that contains the selected cell
@ -70,6 +73,7 @@ export const deriveStores = context => {
hoveredRowId.set(null) hoveredRowId.set(null)
} }
// Derive the amount of content lines to show in cells depending on row height
const contentLines = derived(rowHeight, $rowHeight => { const contentLines = derived(rowHeight, $rowHeight => {
if ($rowHeight === LargeRowHeight) { if ($rowHeight === LargeRowHeight) {
return 3 return 3
@ -79,9 +83,15 @@ export const deriveStores = context => {
return 1 return 1
}) })
// Derive whether we should use the compact UI, depending on width
const compact = derived([stickyColumn, width], ([$stickyColumn, $width]) => {
return ($stickyColumn?.width || 0) + $width + GutterWidth < 1100
})
return { return {
focusedRow, focusedRow,
contentLines, contentLines,
compact,
ui: { ui: {
actions: { actions: {
blur, blur,

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/sdk", "name": "@budibase/sdk",
"version": "2.6.0", "version": "2.6.6",
"description": "Budibase Public API SDK", "description": "Budibase Public API SDK",
"author": "Budibase", "author": "Budibase",
"license": "MPL-2.0", "license": "MPL-2.0",

View file

@ -1,7 +1,7 @@
{ {
"name": "@budibase/server", "name": "@budibase/server",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "2.6.0", "version": "2.6.6",
"description": "Budibase Web Server", "description": "Budibase Web Server",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -45,12 +45,12 @@
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@apidevtools/swagger-parser": "10.0.3", "@apidevtools/swagger-parser": "10.0.3",
"@budibase/backend-core": "^2.6.0", "@budibase/backend-core": "^2.6.6",
"@budibase/client": "^2.6.0", "@budibase/client": "^2.6.6",
"@budibase/pro": "2.6.0", "@budibase/pro": "2.6.6",
"@budibase/shared-core": "^2.6.0", "@budibase/shared-core": "^2.6.6",
"@budibase/string-templates": "^2.6.0", "@budibase/string-templates": "^2.6.6",
"@budibase/types": "^2.6.0", "@budibase/types": "^2.6.6",
"@bull-board/api": "3.7.0", "@bull-board/api": "3.7.0",
"@bull-board/koa": "3.9.4", "@bull-board/koa": "3.9.4",
"@elastic/elasticsearch": "7.10.0", "@elastic/elasticsearch": "7.10.0",

View file

@ -69,9 +69,9 @@ export async function validate({
if (type === FieldTypes.FORMULA || column.autocolumn) { if (type === FieldTypes.FORMULA || column.autocolumn) {
continue continue
} }
// special case for options, need to always allow unselected (null) // special case for options, need to always allow unselected (empty)
if (type === FieldTypes.OPTIONS && constraints.inclusion) { if (type === FieldTypes.OPTIONS && constraints.inclusion) {
constraints.inclusion.push(null) constraints.inclusion.push(null, "")
} }
let res let res

View file

@ -42,8 +42,14 @@ if (!env.isTest()) {
host: REDIS_OPTS.host, host: REDIS_OPTS.host,
port: REDIS_OPTS.port, port: REDIS_OPTS.port,
}, },
password: REDIS_OPTS.opts.password, password:
database: 1, REDIS_OPTS.opts.password || REDIS_OPTS.opts.redisOptions.password,
}
if (!env.REDIS_CLUSTERED) {
// Can't set direct redis db in clustered env
// @ts-ignore
options.database = 1
} }
} }
rateLimitStore = new Stores.Redis(options) rateLimitStore = new Stores.Redis(options)

View file

@ -212,6 +212,7 @@ describe("/rows", () => {
attachmentNull: attachment, attachmentNull: attachment,
attachmentUndefined: attachment, attachmentUndefined: attachment,
attachmentEmpty: attachment, attachmentEmpty: attachment,
attachmentEmptyArrayStr: attachment
}, },
}) })
@ -239,6 +240,7 @@ describe("/rows", () => {
attachmentNull: null, attachmentNull: null,
attachmentUndefined: undefined, attachmentUndefined: undefined,
attachmentEmpty: "", attachmentEmpty: "",
attachmentEmptyArrayStr: "[]",
} }
const id = (await config.createRow(row))._id const id = (await config.createRow(row))._id
@ -268,6 +270,7 @@ describe("/rows", () => {
expect(saved.attachmentNull).toEqual([]) expect(saved.attachmentNull).toEqual([])
expect(saved.attachmentUndefined).toBe(undefined) expect(saved.attachmentUndefined).toBe(undefined)
expect(saved.attachmentEmpty).toEqual([]) expect(saved.attachmentEmpty).toEqual([])
expect(saved.attachmentEmptyArrayStr).toEqual([])
}) })
}) })

View file

@ -9,7 +9,7 @@ import * as serverLog from "./steps/serverLog"
import * as discord from "./steps/discord" import * as discord from "./steps/discord"
import * as slack from "./steps/slack" import * as slack from "./steps/slack"
import * as zapier from "./steps/zapier" import * as zapier from "./steps/zapier"
import * as integromat from "./steps/integromat" import * as make from "./steps/make"
import * as filter from "./steps/filter" import * as filter from "./steps/filter"
import * as delay from "./steps/delay" import * as delay from "./steps/delay"
import * as queryRow from "./steps/queryRows" import * as queryRow from "./steps/queryRows"
@ -43,7 +43,7 @@ const ACTION_IMPLS: Record<
discord: discord.run, discord: discord.run,
slack: slack.run, slack: slack.run,
zapier: zapier.run, zapier: zapier.run,
integromat: integromat.run, integromat: make.run,
} }
export const BUILTIN_ACTION_DEFINITIONS: Record<string, AutomationStepSchema> = export const BUILTIN_ACTION_DEFINITIONS: Record<string, AutomationStepSchema> =
{ {
@ -63,7 +63,7 @@ export const BUILTIN_ACTION_DEFINITIONS: Record<string, AutomationStepSchema> =
discord: discord.definition, discord: discord.definition,
slack: slack.definition, slack: slack.definition,
zapier: zapier.definition, zapier: zapier.definition,
integromat: integromat.definition, integromat: make.definition,
} }
// don't add the bash script/definitions unless in self host // don't add the bash script/definitions unless in self host

View file

@ -9,10 +9,11 @@ import {
} from "@budibase/types" } from "@budibase/types"
export const definition: AutomationStepSchema = { export const definition: AutomationStepSchema = {
name: "Integromat Integration", name: "Make Integration",
tagline: "Trigger an Integromat scenario", stepTitle: "Make",
tagline: "Trigger a Make scenario",
description: description:
"Performs a webhook call to Integromat and gets the response (if configured)", "Performs a webhook call to Make and gets the response (if configured)",
icon: "ri-shut-down-line", icon: "ri-shut-down-line",
stepId: AutomationActionStepId.integromat, stepId: AutomationActionStepId.integromat,
type: AutomationStepType.ACTION, type: AutomationStepType.ACTION,

View file

@ -34,8 +34,6 @@ function parseIntSafe(number?: string) {
} }
} }
let inThread = false
const environment = { const environment = {
// important - prefer app port to generic port // important - prefer app port to generic port
PORT: process.env.APP_PORT || process.env.PORT, PORT: process.env.APP_PORT || process.env.PORT,
@ -47,6 +45,7 @@ const environment = {
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY, MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
REDIS_URL: process.env.REDIS_URL, REDIS_URL: process.env.REDIS_URL,
REDIS_PASSWORD: process.env.REDIS_PASSWORD, REDIS_PASSWORD: process.env.REDIS_PASSWORD,
REDIS_CLUSTERED: process.env.REDIS_CLUSTERED,
HTTP_MIGRATIONS: process.env.HTTP_MIGRATIONS, HTTP_MIGRATIONS: process.env.HTTP_MIGRATIONS,
API_REQ_LIMIT_PER_SEC: process.env.API_REQ_LIMIT_PER_SEC, API_REQ_LIMIT_PER_SEC: process.env.API_REQ_LIMIT_PER_SEC,
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID, GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
@ -94,12 +93,8 @@ const environment = {
isProd: () => { isProd: () => {
return !isDev() return !isDev()
}, },
// used to check if already in a thread, don't thread further
setInThread: () => {
inThread = true
},
isInThread: () => { isInThread: () => {
return inThread return process.env.FORKED_PROCESS
}, },
} }

View file

@ -39,6 +39,12 @@ export class Thread {
const workerOpts: any = { const workerOpts: any = {
autoStart: true, autoStart: true,
maxConcurrentWorkers: this.count, maxConcurrentWorkers: this.count,
workerOptions: {
env: {
...process.env,
FORKED_PROCESS: "1",
},
},
} }
if (opts.timeoutMs) { if (opts.timeoutMs) {
this.timeoutMs = opts.timeoutMs this.timeoutMs = opts.timeoutMs

View file

@ -25,11 +25,9 @@ function makeVariableKey(queryId: string, variable: string) {
export function threadSetup() { export function threadSetup() {
// don't run this if not threading // don't run this if not threading
if (env.isTest() || env.DISABLE_THREADING) { if (env.isTest() || env.DISABLE_THREADING || !env.isInThread()) {
return return
} }
// when thread starts, make sure it is recorded
env.setInThread()
db.init() db.init()
} }

View file

@ -1,5 +1,6 @@
// @ts-nocheck // @ts-nocheck
import { FieldTypes } from "../../constants" import { FieldTypes } from "../../constants"
import { logging } from "@budibase/backend-core"
/** /**
* A map of how we convert various properties in rows to each other based on the row type. * A map of how we convert various properties in rows to each other based on the row type.
@ -67,9 +68,23 @@ export const TYPE_TRANSFORM_MAP: any = {
}, },
}, },
[FieldTypes.ATTACHMENT]: { [FieldTypes.ATTACHMENT]: {
"": [],
[null]: [], [null]: [],
[undefined]: undefined, [undefined]: undefined,
parse: attachments => {
if (typeof attachments === "string") {
if (attachments === "") {
return []
}
let result
try {
result = JSON.parse(attachments)
} catch (e) {
logging.logAlert("Could not parse attachments", e)
}
return result
}
return attachments
},
}, },
[FieldTypes.BOOLEAN]: { [FieldTypes.BOOLEAN]: {
"": null, "": null,

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/shared-core", "name": "@budibase/shared-core",
"version": "2.6.0", "version": "2.6.6",
"description": "Shared data utils", "description": "Shared data utils",
"main": "dist/cjs/src/index.js", "main": "dist/cjs/src/index.js",
"types": "dist/mjs/src/index.d.ts", "types": "dist/mjs/src/index.d.ts",
@ -20,7 +20,7 @@
"dev:builder": "yarn prebuild && concurrently \"tsc -p tsconfig.build.json --watch\" \"tsc -p tsconfig-cjs.build.json --watch\"" "dev:builder": "yarn prebuild && concurrently \"tsc -p tsconfig.build.json --watch\" \"tsc -p tsconfig-cjs.build.json --watch\""
}, },
"dependencies": { "dependencies": {
"@budibase/types": "^2.6.0" "@budibase/types": "^2.6.6"
}, },
"devDependencies": { "devDependencies": {
"concurrently": "^7.6.0", "concurrently": "^7.6.0",

View file

@ -1,6 +1,6 @@
{ {
"name": "@budibase/string-templates", "name": "@budibase/string-templates",
"version": "2.6.0", "version": "2.6.6",
"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,6 +1,6 @@
{ {
"name": "@budibase/types", "name": "@budibase/types",
"version": "2.6.0", "version": "2.6.6",
"description": "Budibase types", "description": "Budibase types",
"main": "dist/cjs/index.js", "main": "dist/cjs/index.js",
"types": "dist/mjs/index.d.ts", "types": "dist/mjs/index.d.ts",

View file

@ -104,6 +104,7 @@ interface InputOutputBlock {
export interface AutomationStepSchema { export interface AutomationStepSchema {
name: string name: string
stepTitle?: string
tagline: string tagline: string
icon: string icon: string
description: string description: string

View file

@ -1,7 +1,7 @@
{ {
"name": "@budibase/worker", "name": "@budibase/worker",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "2.6.0", "version": "2.6.6",
"description": "Budibase background service", "description": "Budibase background service",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -37,10 +37,10 @@
"author": "Budibase", "author": "Budibase",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@budibase/backend-core": "^2.6.0", "@budibase/backend-core": "^2.6.6",
"@budibase/pro": "2.6.0", "@budibase/pro": "2.6.6",
"@budibase/string-templates": "^2.6.0", "@budibase/string-templates": "^2.6.6",
"@budibase/types": "^2.6.0", "@budibase/types": "^2.6.6",
"@koa/router": "8.0.8", "@koa/router": "8.0.8",
"@sentry/node": "6.17.7", "@sentry/node": "6.17.7",
"@techpass/passport-openidconnect": "0.3.2", "@techpass/passport-openidconnect": "0.3.2",

View file

@ -1486,15 +1486,15 @@
pouchdb-promise "^6.0.4" pouchdb-promise "^6.0.4"
through2 "^2.0.0" through2 "^2.0.0"
"@budibase/pro@2.5.10": "@budibase/pro@2.6.5":
version "2.5.10" version "2.6.5"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.5.10.tgz#b7d81c1615df7ba51a199c29d5c87dadad3f004e" resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.6.5.tgz#93cababe9e5f846b85222c9b6b31138baeda76cb"
integrity sha512-c3uAYPyn3BXZyZc1940kIAbNoFOxWVJHQOCz+4AQLRUmMDznSNsOZGhzhdqlc2IL7xL51Oz3Ry5eAVhdPJWb7A== integrity sha512-NHpwFKwTVOQ9xloiidvNgYf41xKYm6TmqJgt8xSO4R7Wbo/lGE4agDFjuivabiaVrnTYHm98heu0t+MFP9uZBg==
dependencies: dependencies:
"@budibase/backend-core" "2.5.10" "@budibase/backend-core" "2.6.5"
"@budibase/shared-core" "2.5.9" "@budibase/shared-core" "2.5.9"
"@budibase/string-templates" "2.5.9" "@budibase/string-templates" "2.5.9"
"@budibase/types" "2.5.10" "@budibase/types" "2.6.5"
"@koa/router" "8.0.8" "@koa/router" "8.0.8"
bull "4.10.1" bull "4.10.1"
joi "17.6.0" joi "17.6.0"