104 lines
3.3 KiB
JavaScript
104 lines
3.3 KiB
JavaScript
import { makePropSafe as safe } from "@budibase/string-templates"
|
|
import { API } from "../api/index.js"
|
|
|
|
// Map of data types to component types for search fields inside blocks
|
|
const schemaComponentMap = {
|
|
string: "stringfield",
|
|
options: "optionsfield",
|
|
number: "numberfield",
|
|
bigint: "bigintfield",
|
|
datetime: "datetimefield",
|
|
boolean: "booleanfield",
|
|
formula: "stringfield",
|
|
}
|
|
|
|
/**
|
|
* Determine data types for search fields and only use those that are valid
|
|
* @param searchColumns the search columns to use
|
|
* @param schema the datasource schema
|
|
*/
|
|
export const enrichSearchColumns = async (searchColumns, schema) => {
|
|
if (!searchColumns?.length || !schema) {
|
|
return []
|
|
}
|
|
let enrichedColumns = []
|
|
for (let column of searchColumns) {
|
|
let schemaType = schema[column]?.type
|
|
|
|
// Check if this is a field in another related table. The only way we can
|
|
// check this is checking for a "." inside the column, then checking if we
|
|
// have a link field named the same as that field prefix.
|
|
if (column.includes(".")) {
|
|
const split = column.split(".")
|
|
const sourceField = split[0]
|
|
const linkField = split.slice(1).join(".")
|
|
const linkSchema = schema[sourceField]
|
|
if (linkSchema?.type === "link") {
|
|
const linkedDef = await API.fetchTableDefinition(linkSchema.tableId)
|
|
schemaType = linkedDef?.schema?.[linkField]?.type
|
|
}
|
|
}
|
|
|
|
const componentType = schemaComponentMap[schemaType]
|
|
if (componentType) {
|
|
enrichedColumns.push({
|
|
name: column,
|
|
componentType,
|
|
type: schemaType,
|
|
})
|
|
}
|
|
}
|
|
return enrichedColumns.slice(0, 5)
|
|
}
|
|
|
|
/**
|
|
* Enriches a normal datasource filter with bindings representing the additional
|
|
* search fields configured as part of a searchable block. These bindings are
|
|
* fields inside a form used as part of the block.
|
|
* @param filter the normal data provider filter
|
|
* @param columns the enriched search column structure
|
|
* @param formId the ID of the form containing the search fields
|
|
*/
|
|
export const enrichFilter = (filter, columns, formId) => {
|
|
let enrichedFilter = [...(filter || [])]
|
|
columns?.forEach(column => {
|
|
const safePath = column.name.split(".").map(safe).join(".")
|
|
const stringType = column.type === "string" || column.type === "formula"
|
|
const dateType = column.type === "datetime"
|
|
const binding = `${safe(formId)}.${safePath}`
|
|
|
|
// For dates, use a range of the entire day selected
|
|
if (dateType) {
|
|
enrichedFilter.push({
|
|
field: column.name,
|
|
type: column.type,
|
|
operator: "rangeLow",
|
|
valueType: "Binding",
|
|
value: `{{ ${binding} }}`,
|
|
})
|
|
const format = "YYYY-MM-DDTHH:mm:ss.SSSZ"
|
|
let hbs = `{{ date (add (date ${binding} "x") 86399999) "${format}" }}`
|
|
hbs = `{{#if ${binding} }}${hbs}{{/if}}`
|
|
enrichedFilter.push({
|
|
field: column.name,
|
|
type: column.type,
|
|
operator: "rangeHigh",
|
|
valueType: "Binding",
|
|
value: hbs,
|
|
})
|
|
}
|
|
|
|
// For other fields, do an exact match
|
|
else {
|
|
enrichedFilter.push({
|
|
field: column.name,
|
|
type: column.type,
|
|
operator: stringType ? "string" : "equal",
|
|
valueType: "Binding",
|
|
value: `{{ ${binding} }}`,
|
|
})
|
|
}
|
|
})
|
|
return enrichedFilter
|
|
}
|