Merge pull request #14664 from Budibase/fix/view-user-columns

Fix user column searching with logical operators
This commit is contained in:
Michael Drury 2024-09-30 16:39:11 +01:00 committed by GitHub
commit b04af04e3b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 23 deletions

View File

@ -408,7 +408,6 @@ describe.each([
}) })
}) })
// We've decided not to try and support binding for in-memory search just now.
!isInMemory && !isInMemory &&
describe("bindings", () => { describe("bindings", () => {
let globalUsers: any = [] let globalUsers: any = []
@ -528,6 +527,20 @@ describe.each([
]) ])
}) })
!isLucene &&
it("should return all rows matching the session user firstname when logical operator used", async () => {
await expectQuery({
$and: {
conditions: [{ equal: { name: "{{ [user].firstName }}" } }],
},
}).toContainExactly([
{
name: config.getUser().firstName,
appointment: future.toISOString(),
},
])
})
it("should parse the date binding and return all rows after the resolved value", async () => { it("should parse the date binding and return all rows after the resolved value", async () => {
await tk.withFreeze(serverTime, async () => { await tk.withFreeze(serverTime, async () => {
await expectQuery({ await expectQuery({

View File

@ -11,7 +11,7 @@ import {
RowSearchParams, RowSearchParams,
} from "@budibase/types" } from "@budibase/types"
import { db as dbCore, context } from "@budibase/backend-core" import { db as dbCore, context } from "@budibase/backend-core"
import { utils } from "@budibase/shared-core" import { utils, dataFilters } from "@budibase/shared-core"
export async function paginatedSearch( export async function paginatedSearch(
query: SearchFilters, query: SearchFilters,
@ -31,13 +31,13 @@ export async function fullSearch(
function findColumnInQueries( function findColumnInQueries(
column: string, column: string,
options: RowSearchParams, filters: SearchFilters,
callback: (filter: any) => any callback: (filter: any) => any
) { ) {
if (!options.query) { if (!filters) {
return return
} }
for (let filterBlock of Object.values(options.query)) { for (let filterBlock of Object.values(filters)) {
if (typeof filterBlock !== "object") { if (typeof filterBlock !== "object") {
continue continue
} }
@ -49,8 +49,8 @@ function findColumnInQueries(
} }
} }
function userColumnMapping(column: string, options: RowSearchParams) { function userColumnMapping(column: string, filters: SearchFilters) {
findColumnInQueries(column, options, (filterValue: any): any => { findColumnInQueries(column, filters, (filterValue: any): any => {
const isArray = Array.isArray(filterValue), const isArray = Array.isArray(filterValue),
isString = typeof filterValue === "string" isString = typeof filterValue === "string"
if (!isString && !isArray) { if (!isString && !isArray) {
@ -83,26 +83,31 @@ function userColumnMapping(column: string, options: RowSearchParams) {
// maps through the search parameters to check if any of the inputs are invalid // maps through the search parameters to check if any of the inputs are invalid
// based on the table schema, converts them to something that is valid. // based on the table schema, converts them to something that is valid.
export function searchInputMapping(table: Table, options: RowSearchParams) { export function searchInputMapping(table: Table, options: RowSearchParams) {
for (let [key, column] of Object.entries(table.schema || {})) { // need an internal function to loop over filters, because this takes the full options
switch (column.type) { function checkFilters(filters: SearchFilters) {
case FieldType.BB_REFERENCE_SINGLE: { for (let [key, column] of Object.entries(table.schema || {})) {
const subtype = column.subtype switch (column.type) {
switch (subtype) { case FieldType.BB_REFERENCE_SINGLE: {
case BBReferenceFieldSubType.USER: const subtype = column.subtype
userColumnMapping(key, options) switch (subtype) {
break case BBReferenceFieldSubType.USER:
userColumnMapping(key, filters)
break
default: default:
utils.unreachable(subtype) utils.unreachable(subtype)
}
break
}
case FieldType.BB_REFERENCE: {
userColumnMapping(key, filters)
break
} }
break
}
case FieldType.BB_REFERENCE: {
userColumnMapping(key, options)
break
} }
} }
return dataFilters.recurseLogicalOperators(filters, checkFilters)
} }
options.query = checkFilters(options.query)
return options return options
} }

View File

@ -124,7 +124,7 @@ export function recurseLogicalOperators(
fn: (f: SearchFilters) => SearchFilters fn: (f: SearchFilters) => SearchFilters
) { ) {
for (const logical of LOGICAL_OPERATORS) { for (const logical of LOGICAL_OPERATORS) {
if (filters[logical]) { if (filters?.[logical]) {
filters[logical]!.conditions = filters[logical]!.conditions.map( filters[logical]!.conditions = filters[logical]!.conditions.map(
condition => fn(condition) condition => fn(condition)
) )