diff --git a/.github/workflows/release-singleimage-test.yml b/.github/workflows/release-singleimage-test.yml
deleted file mode 100644
index c3a14226ce..0000000000
--- a/.github/workflows/release-singleimage-test.yml
+++ /dev/null
@@ -1,72 +0,0 @@
-name: Test
-
-on:
- workflow_dispatch:
-
-env:
- CI: true
- PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
- REGISTRY_URL: registry.hub.docker.com
- NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
-jobs:
- build:
- name: "build"
- runs-on: ubuntu-latest
- strategy:
- matrix:
- node-version: [18.x]
- steps:
- - name: "Checkout"
- uses: actions/checkout@v4
- with:
- submodules: true
- token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
-
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v3
- with:
- node-version: ${{ matrix.node-version }}
- cache: "yarn"
- - name: Setup QEMU
- uses: docker/setup-qemu-action@v3
- - name: Setup Docker Buildx
- id: buildx
- uses: docker/setup-buildx-action@v3
- - name: Run Yarn
- run: yarn
- - name: Run Yarn Build
- run: yarn build --scope @budibase/server --scope @budibase/worker
- - name: Login to Docker Hub
- uses: docker/login-action@v2
- with:
- username: ${{ secrets.DOCKER_USERNAME }}
- password: ${{ secrets.DOCKER_API_KEY }}
- - name: Get the latest release version
- id: version
- run: |
- release_version=$(cat lerna.json | jq -r '.version')
- echo $release_version
- echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
- - name: Tag and release Budibase service docker image
- uses: docker/build-push-action@v5
- with:
- context: .
- push: true
- pull: true
- platforms: linux/amd64,linux/arm64
- build-args: BUDIBASE_VERSION=0.0.0+test
- tags: budibase/budibase-test:test
- file: ./hosting/single/Dockerfile.v2
- cache-from: type=registry,ref=budibase/budibase-test:test
- cache-to: type=inline
- - name: Tag and release Budibase Azure App Service docker image
- uses: docker/build-push-action@v2
- with:
- context: .
- push: true
- platforms: linux/amd64
- build-args: |
- TARGETBUILD=aas
- BUDIBASE_VERSION=0.0.0+test
- tags: budibase/budibase-test:aas
- file: ./hosting/single/Dockerfile.v2
diff --git a/hosting/proxy/nginx.prod.conf b/hosting/proxy/nginx.prod.conf
index 365765ccbb..6da2e4a1c3 100644
--- a/hosting/proxy/nginx.prod.conf
+++ b/hosting/proxy/nginx.prod.conf
@@ -51,7 +51,7 @@ http {
proxy_buffering off;
set $csp_default "default-src 'self'";
- set $csp_script "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.budibase.net https://cdn.budi.live https://js.intercomcdn.com https://widget.intercom.io";
+ set $csp_script "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.budibase.net https://cdn.budi.live https://js.intercomcdn.com https://widget.intercom.io https://d2l5prqdbvm3op.cloudfront.net";
set $csp_style "style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com https://rsms.me https://maxcdn.bootstrapcdn.com";
set $csp_object "object-src 'none'";
set $csp_base_uri "base-uri 'self'";
diff --git a/lerna.json b/lerna.json
index 7d14875c97..384473120b 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
{
- "version": "2.11.44",
+ "version": "2.11.45",
"npmClient": "yarn",
"packages": [
"packages/*"
diff --git a/package.json b/package.json
index 100a306a35..d3f4903e6c 100644
--- a/package.json
+++ b/package.json
@@ -33,7 +33,6 @@
"build:sdk": "lerna run --stream build:sdk",
"deps:circular": "madge packages/server/dist/index.js packages/worker/src/index.ts packages/backend-core/dist/src/index.js packages/cli/src/index.js --circular",
"release": "lerna publish from-package --yes --force-publish --no-git-tag-version --no-push --no-git-reset",
- "release:develop": "yarn release --dist-tag develop",
"restore": "yarn run clean && yarn && yarn run build",
"nuke": "yarn run nuke:packages && yarn run nuke:docker",
"nuke:packages": "yarn run restore",
diff --git a/packages/builder/src/builderStore/store/screenTemplates/rowListScreen.js b/packages/builder/src/builderStore/store/screenTemplates/rowListScreen.js
index b17bd99e10..59bcd0d5e8 100644
--- a/packages/builder/src/builderStore/store/screenTemplates/rowListScreen.js
+++ b/packages/builder/src/builderStore/store/screenTemplates/rowListScreen.js
@@ -2,14 +2,14 @@ import sanitizeUrl from "./utils/sanitizeUrl"
import { Screen } from "./utils/Screen"
import { Component } from "./utils/Component"
-export default function (datasources) {
+export default function (datasources, mode = "table") {
if (!Array.isArray(datasources)) {
return []
}
return datasources.map(datasource => {
return {
name: `${datasource.label} - List`,
- create: () => createScreen(datasource),
+ create: () => createScreen(datasource, mode),
id: ROW_LIST_TEMPLATE,
resourceId: datasource.resourceId,
}
@@ -40,10 +40,24 @@ const generateTableBlock = datasource => {
return tableBlock
}
-const createScreen = datasource => {
+const generateGridBlock = datasource => {
+ const gridBlock = new Component("@budibase/standard-components/gridblock")
+ gridBlock
+ .customProps({
+ table: datasource,
+ })
+ .instanceName(`${datasource.label} - Grid block`)
+ return gridBlock
+}
+
+const createScreen = (datasource, mode) => {
return new Screen()
.route(rowListUrl(datasource))
.instanceName(`${datasource.label} - List`)
- .addChild(generateTableBlock(datasource))
+ .addChild(
+ mode === "table"
+ ? generateTableBlock(datasource)
+ : generateGridBlock(datasource)
+ )
.json()
}
diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte
index 7b51e6c839..467ae413c3 100644
--- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte
+++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte
@@ -777,7 +777,8 @@
disabled={deleteColName !== originalName}
>
- Are you sure you wish to delete the column {originalName}?
+ Are you sure you wish to delete the column
+ (deleteColName = originalName)}>{originalName}?
Your data will be deleted and this action cannot be undone - enter the column
name to confirm.
@@ -810,4 +811,11 @@
gap: 8px;
display: flex;
}
+ b {
+ transition: color 130ms ease-out;
+ }
+ b:hover {
+ cursor: pointer;
+ color: var(--spectrum-global-color-gray-900);
+ }
diff --git a/packages/builder/src/components/integration/RestQueryViewer.svelte b/packages/builder/src/components/integration/RestQueryViewer.svelte
index 254f65fcaf..e6913b0953 100644
--- a/packages/builder/src/components/integration/RestQueryViewer.svelte
+++ b/packages/builder/src/components/integration/RestQueryViewer.svelte
@@ -196,8 +196,36 @@
}
}
+ const validateQuery = async () => {
+ const forbiddenBindings = /{{\s?user(\.(\w|\$)*\s?|\s?)}}/g
+ const bindingError = new Error(
+ "'user' is a protected binding and cannot be used"
+ )
+
+ if (forbiddenBindings.test(url)) {
+ throw bindingError
+ }
+
+ if (forbiddenBindings.test(query.fields.requestBody ?? "")) {
+ throw bindingError
+ }
+
+ Object.values(requestBindings).forEach(bindingValue => {
+ if (forbiddenBindings.test(bindingValue)) {
+ throw bindingError
+ }
+ })
+
+ Object.values(query.fields.headers).forEach(headerValue => {
+ if (forbiddenBindings.test(headerValue)) {
+ throw bindingError
+ }
+ })
+ }
+
async function runQuery() {
try {
+ await validateQuery()
response = await queries.preview(buildQuery())
if (response.rows.length === 0) {
notifications.info("Request did not return any data")
diff --git a/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/index.svelte
index 414722a177..a68a782bed 100644
--- a/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/index.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/index.svelte
@@ -53,7 +53,8 @@
}
.alert-wrap {
display: flex;
- width: 100%;
+ flex: 0 0 auto;
+ margin: -28px -40px 14px -40px;
}
.alert-wrap :global(> *) {
flex: 1;
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte
index 40353bef52..f833464d8c 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte
@@ -126,7 +126,7 @@
{#if section.visible}
{#if section.info}
diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/CreateScreenModal.svelte b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/CreateScreenModal.svelte
index 9a96242b30..92ed3dcfc7 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/CreateScreenModal.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/CreateScreenModal.svelte
@@ -12,6 +12,7 @@
import { capitalise } from "helpers"
import { goto } from "@roxi/routify"
+ let mode
let pendingScreen
// Modal refs
@@ -100,14 +101,15 @@
}
// Handler for NewScreenModal
- export const show = mode => {
+ export const show = newMode => {
+ mode = newMode
selectedTemplates = null
blankScreenUrl = null
screenMode = mode
pendingScreen = null
screenAccessRole = Roles.BASIC
- if (mode === "table") {
+ if (mode === "table" || mode === "grid") {
datasourceModal.show()
} else if (mode === "blank") {
let templates = getTemplates($tables.list)
@@ -123,6 +125,7 @@
// Handler for DatasourceModal confirmation, move to screen access select
const confirmScreenDatasources = async ({ templates }) => {
+ console.log(templates)
selectedTemplates = templates
screenAccessRoleModal.show()
}
@@ -177,6 +180,7 @@
diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/DatasourceModal.svelte b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/DatasourceModal.svelte
index a866cd23d4..731c60a406 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/DatasourceModal.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/DatasourceModal.svelte
@@ -7,6 +7,7 @@
import rowListScreen from "builderStore/store/screenTemplates/rowListScreen"
import DatasourceTemplateRow from "./DatasourceTemplateRow.svelte"
+ export let mode
export let onCancel
export let onConfirm
export let initialScreens = []
@@ -24,7 +25,10 @@
screen => screen.resourceId !== resourceId
)
} else {
- selectedScreens = [...selectedScreens, rowListScreen([datasource])[0]]
+ selectedScreens = [
+ ...selectedScreens,
+ rowListScreen([datasource], mode)[0],
+ ]
}
}
diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/grid.png b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/grid.png
new file mode 100644
index 0000000000..c3efa30a67
Binary files /dev/null and b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/grid.png differ
diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/index.svelte
index b504940ca7..6b080747b0 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/index.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/index.svelte
@@ -3,6 +3,7 @@
import CreationPage from "components/common/CreationPage.svelte"
import blankImage from "./blank.png"
import tableImage from "./table.png"
+ import gridImage from "./grid.png"
import CreateScreenModal from "./CreateScreenModal.svelte"
import { store } from "builderStore"
@@ -43,6 +44,16 @@
View, edit and delete rows on a table
+
+ createScreenModal.show("grid")}>
+
+
+
+
+ Grid
+ View and manipulate rows on a grid
+
+
diff --git a/packages/frontend-core/src/components/grid/cells/DataCell.svelte b/packages/frontend-core/src/components/grid/cells/DataCell.svelte
index f9cdef3756..cdaf28978a 100644
--- a/packages/frontend-core/src/components/grid/cells/DataCell.svelte
+++ b/packages/frontend-core/src/components/grid/cells/DataCell.svelte
@@ -21,6 +21,7 @@
export let invertX = false
export let invertY = false
export let contentLines = 1
+ export let hidden = false
const emptyError = writable(null)
@@ -78,6 +79,7 @@
{focused}
{selectedUser}
{readonly}
+ {hidden}
error={$error}
on:click={() => focusedCellId.set(cellId)}
on:contextmenu={e => menu.actions.open(cellId, e)}
diff --git a/packages/frontend-core/src/components/grid/cells/GridCell.svelte b/packages/frontend-core/src/components/grid/cells/GridCell.svelte
index fe4bd70ba4..dcc76b9c75 100644
--- a/packages/frontend-core/src/components/grid/cells/GridCell.svelte
+++ b/packages/frontend-core/src/components/grid/cells/GridCell.svelte
@@ -10,6 +10,7 @@
export let defaultHeight = false
export let center = false
export let readonly = false
+ export let hidden = false
$: style = getStyle(width, selectedUser)
@@ -30,6 +31,7 @@
class:error
class:center
class:readonly
+ class:hidden
class:default-height={defaultHeight}
class:selected-other={selectedUser != null}
class:alt={rowIdx % 2 === 1}
@@ -81,6 +83,9 @@
.cell.center {
align-items: center;
}
+ .cell.hidden {
+ content-visibility: hidden;
+ }
/* Cell border */
.cell.focused:after,
diff --git a/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte b/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte
index a7b232c487..38dfd0f9eb 100644
--- a/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte
+++ b/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte
@@ -17,7 +17,7 @@
isResizing,
rand,
sort,
- renderedColumns,
+ visibleColumns,
dispatch,
subscribe,
config,
@@ -50,7 +50,7 @@
$: sortedBy = column.name === $sort.column
$: canMoveLeft = orderable && idx > 0
- $: canMoveRight = orderable && idx < $renderedColumns.length - 1
+ $: canMoveRight = orderable && idx < $visibleColumns.length - 1
$: sortingLabels = getSortingLabels(column.schema?.type)
$: searchable = isColumnSearchable(column)
$: resetSearchValue(column.name)
diff --git a/packages/frontend-core/src/components/grid/layout/GridBody.svelte b/packages/frontend-core/src/components/grid/layout/GridBody.svelte
index 762985a4db..0bb2a51fb4 100644
--- a/packages/frontend-core/src/components/grid/layout/GridBody.svelte
+++ b/packages/frontend-core/src/components/grid/layout/GridBody.svelte
@@ -7,7 +7,7 @@
const {
bounds,
renderedRows,
- renderedColumns,
+ visibleColumns,
rowVerticalInversionIndex,
hoveredRowId,
dispatch,
@@ -17,7 +17,7 @@
let body
- $: renderColumnsWidth = $renderedColumns.reduce(
+ $: columnsWidth = $visibleColumns.reduce(
(total, col) => (total += col.width),
0
)
@@ -47,7 +47,7 @@
($hoveredRowId = BlankRowID)}
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
on:click={() => dispatch("add-row-inline")}
diff --git a/packages/frontend-core/src/components/grid/layout/GridRow.svelte b/packages/frontend-core/src/components/grid/layout/GridRow.svelte
index 4754d493bf..4a0db40ee8 100644
--- a/packages/frontend-core/src/components/grid/layout/GridRow.svelte
+++ b/packages/frontend-core/src/components/grid/layout/GridRow.svelte
@@ -10,7 +10,7 @@
focusedCellId,
reorder,
selectedRows,
- renderedColumns,
+ visibleColumns,
hoveredRowId,
selectedCellMap,
focusedRow,
@@ -19,6 +19,7 @@
isDragging,
dispatch,
rows,
+ columnRenderMap,
} = getContext("grid")
$: rowSelected = !!$selectedRows[row._id]
@@ -34,7 +35,7 @@
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
on:click={() => dispatch("rowclick", rows.actions.cleanRow(row))}
>
- {#each $renderedColumns as column, columnIdx (column.name)}
+ {#each $visibleColumns as column, columnIdx}
{@const cellId = `${row._id}-${column.name}`}
{/each}
diff --git a/packages/frontend-core/src/components/grid/layout/GridScrollWrapper.svelte b/packages/frontend-core/src/components/grid/layout/GridScrollWrapper.svelte
index 05bd261721..2a131809a9 100644
--- a/packages/frontend-core/src/components/grid/layout/GridScrollWrapper.svelte
+++ b/packages/frontend-core/src/components/grid/layout/GridScrollWrapper.svelte
@@ -11,7 +11,6 @@
maxScrollLeft,
bounds,
hoveredRowId,
- hiddenColumnsWidth,
menu,
} = getContext("grid")
@@ -23,10 +22,10 @@
let initialTouchX
let initialTouchY
- $: style = generateStyle($scroll, $rowHeight, $hiddenColumnsWidth)
+ $: style = generateStyle($scroll, $rowHeight)
- const generateStyle = (scroll, rowHeight, hiddenWidths) => {
- const offsetX = scrollHorizontally ? -1 * scroll.left + hiddenWidths : 0
+ const generateStyle = (scroll, rowHeight) => {
+ const offsetX = scrollHorizontally ? -1 * scroll.left : 0
const offsetY = scrollVertically ? -1 * (scroll.top % rowHeight) : 0
return `transform: translate3d(${offsetX}px, ${offsetY}px, 0);`
}
diff --git a/packages/frontend-core/src/components/grid/layout/HeaderRow.svelte b/packages/frontend-core/src/components/grid/layout/HeaderRow.svelte
index 97b7d054f3..b8655b98b3 100644
--- a/packages/frontend-core/src/components/grid/layout/HeaderRow.svelte
+++ b/packages/frontend-core/src/components/grid/layout/HeaderRow.svelte
@@ -5,14 +5,14 @@
import HeaderCell from "../cells/HeaderCell.svelte"
import { TempTooltip, TooltipType } from "@budibase/bbui"
- const { renderedColumns, config, hasNonAutoColumn, datasource, loading } =
+ const { visibleColumns, config, hasNonAutoColumn, datasource, loading } =
getContext("grid")