Adding a mapping layer to search queries so that we can map search inputs based on the table schema if desired - primarily for the user column.
This commit is contained in:
parent
4bbd575cb0
commit
3de8c53166
|
@ -191,7 +191,7 @@
|
|||
}
|
||||
|
||||
const getValidOperatorsForType = filter => {
|
||||
if (!filter) {
|
||||
if (!filter.field) {
|
||||
return []
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import { cleanExportRows } from "../utils"
|
|||
import { utils } from "@budibase/shared-core"
|
||||
import { ExportRowsParams, ExportRowsResult } from "../search"
|
||||
import { HTTPError, db } from "@budibase/backend-core"
|
||||
import { searchInputMapping } from "./utils"
|
||||
import pick from "lodash/pick"
|
||||
import { outputProcessing } from "../../../../utilities/rowProcessor"
|
||||
|
||||
|
@ -50,7 +51,10 @@ export async function search(options: SearchParams) {
|
|||
[params.sort]: { direction },
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const table = await sdk.tables.getTable(tableId)
|
||||
options = searchInputMapping(table, options)
|
||||
let rows = (await handleRequest(Operation.READ, tableId, {
|
||||
filters: query,
|
||||
sort,
|
||||
|
@ -76,7 +80,6 @@ export async function search(options: SearchParams) {
|
|||
rows = rows.map((r: any) => pick(r, fields))
|
||||
}
|
||||
|
||||
const table = await sdk.tables.getTable(tableId)
|
||||
rows = await outputProcessing(table, rows, { preserveLinks: true })
|
||||
|
||||
// need wrapper object for bookmarks etc when paginating
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
} from "../../../../api/controllers/view/utils"
|
||||
import sdk from "../../../../sdk"
|
||||
import { ExportRowsParams, ExportRowsResult } from "../search"
|
||||
import { searchInputMapping } from "./utils"
|
||||
import pick from "lodash/pick"
|
||||
|
||||
export async function search(options: SearchParams) {
|
||||
|
@ -47,9 +48,9 @@ export async function search(options: SearchParams) {
|
|||
disableEscaping: options.disableEscaping,
|
||||
}
|
||||
|
||||
let table
|
||||
let table = await sdk.tables.getTable(tableId)
|
||||
options = searchInputMapping(table, options)
|
||||
if (params.sort && !params.sortType) {
|
||||
table = await sdk.tables.getTable(tableId)
|
||||
const schema = table.schema
|
||||
const sortField = schema[params.sort]
|
||||
params.sortType = sortField.type === "number" ? "number" : "string"
|
||||
|
@ -68,7 +69,6 @@ export async function search(options: SearchParams) {
|
|||
if (tableId === InternalTables.USER_METADATA) {
|
||||
response.rows = await getGlobalUsersFromMetadata(response.rows)
|
||||
}
|
||||
table = table || (await sdk.tables.getTable(tableId))
|
||||
|
||||
if (options.fields) {
|
||||
const fields = [...options.fields, ...db.CONSTANT_INTERNAL_ROW_COLS]
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import { searchInputMapping } from "../utils"
|
||||
import { db as dbCore } from "@budibase/backend-core"
|
||||
import {
|
||||
FieldType,
|
||||
FieldTypeSubtypes,
|
||||
Table,
|
||||
SearchParams,
|
||||
} from "@budibase/types"
|
||||
|
||||
const tableId = "ta_a"
|
||||
const tableWithUserCol: Table = {
|
||||
_id: tableId,
|
||||
name: "table",
|
||||
schema: {
|
||||
user: {
|
||||
name: "user",
|
||||
type: FieldType.BB_REFERENCE,
|
||||
subtype: FieldTypeSubtypes.BB_REFERENCE.USER,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
describe("searchInputMapping", () => {
|
||||
it("should be able to map ro_ to global user IDs", () => {
|
||||
const globalUserId = dbCore.generateGlobalUserID()
|
||||
const userMedataId = dbCore.generateUserMetadataID(globalUserId)
|
||||
const params: SearchParams = {
|
||||
tableId,
|
||||
query: {
|
||||
equal: {
|
||||
"1:user": userMedataId,
|
||||
},
|
||||
},
|
||||
}
|
||||
const output = searchInputMapping(tableWithUserCol, params)
|
||||
expect(output.query.equal!["1:user"]).toBe(globalUserId)
|
||||
})
|
||||
|
||||
it("shouldn't change any other input", () => {
|
||||
const params: SearchParams = {
|
||||
tableId,
|
||||
query: {
|
||||
equal: {
|
||||
"1:user": "test@test.com",
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
|
@ -0,0 +1,53 @@
|
|||
import {
|
||||
FieldType,
|
||||
FieldTypeSubtypes,
|
||||
SearchParams,
|
||||
Table,
|
||||
DocumentType,
|
||||
SEPARATOR,
|
||||
} from "@budibase/types"
|
||||
import { db as dbCore } from "@budibase/backend-core"
|
||||
|
||||
function findColumnInQueries(
|
||||
column: string,
|
||||
options: SearchParams,
|
||||
callback: <T>(filter: T) => T
|
||||
) {
|
||||
for (let filterBlock of Object.values(options.query)) {
|
||||
if (typeof filterBlock !== "object") {
|
||||
continue
|
||||
}
|
||||
for (let [key, filter] of Object.entries(filterBlock)) {
|
||||
if (key.endsWith(column)) {
|
||||
filterBlock[key] = callback(filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function userColumnMapping(column: string, options: SearchParams) {
|
||||
findColumnInQueries(column, options, (filterValue: any): string => {
|
||||
if (typeof filterValue !== "string") {
|
||||
return filterValue
|
||||
}
|
||||
const rowPrefix = DocumentType.ROW + SEPARATOR
|
||||
// TODO: at some point in future might want to handle mapping emails to IDs
|
||||
if (filterValue.startsWith(rowPrefix)) {
|
||||
return dbCore.getGlobalIDFromUserMetadataID(filterValue)
|
||||
}
|
||||
return filterValue
|
||||
})
|
||||
}
|
||||
|
||||
export function searchInputMapping(table: Table, options: SearchParams) {
|
||||
for (let [key, column] of Object.entries(table.schema)) {
|
||||
switch (column.type) {
|
||||
case FieldType.BB_REFERENCE:
|
||||
if (column.subtype === FieldTypeSubtypes.BB_REFERENCE.USER) {
|
||||
userColumnMapping(key, options)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return options
|
||||
}
|
|
@ -14,7 +14,6 @@ const HBS_REGEX = /{{([^{].*?)}}/g
|
|||
|
||||
/**
|
||||
* Returns the valid operator options for a certain data type
|
||||
* @param type the data type
|
||||
*/
|
||||
export const getValidOperatorsForType = (
|
||||
type: FieldType,
|
||||
|
|
Loading…
Reference in New Issue