Add optional enrichment of relationship fields when determining datasource schema and update block filters to properly reference relationship fields

This commit is contained in:
Andrew Kingston 2022-01-17 14:03:47 +00:00
parent aae2dc86d3
commit 0502e62e1c
5 changed files with 51 additions and 49 deletions

View File

@ -2958,7 +2958,7 @@
"key": "dataSource"
},
{
"type": "multifield",
"type": "searchfield",
"label": "Search Columns",
"key": "searchColumns",
"placeholder": "Choose search columns"

View File

@ -71,12 +71,13 @@
const enrichFilter = (filter, columns, formId) => {
let enrichedFilter = [...(filter || [])]
columns?.forEach(column => {
const safePath = column.name.split(".").map(safe).join(".")
enrichedFilter.push({
field: column.name,
operator: column.type === "string" ? "string" : "equal",
type: column.type === "string" ? "string" : "number",
valueType: "Binding",
value: `{{ [${formId}].[${column.name}] }}`,
value: `{{ ${safe(formId)}.${safePath} }}`,
})
})
return enrichedFilter
@ -112,7 +113,9 @@
// Load the datasource schema so we can determine column types
const fetchSchema = async dataSource => {
if (dataSource) {
schema = await fetchDatasourceSchema(dataSource)
schema = await fetchDatasourceSchema(dataSource, {
enrichRelationships: true,
})
}
schemaLoaded = true
}

View File

@ -41,11 +41,9 @@
let dataProviderId
let schema
let schemaLoaded = false
let enrichedSearchColumns
let enrichedSearchColumnsLoaded = false
$: fetchSchema(dataSource)
$: enrichSearchColumns(searchColumns, schema)
$: enrichedSearchColumns = enrichSearchColumns(searchColumns, schema)
$: enrichedFilter = enrichFilter(filter, enrichedSearchColumns, formId)
$: titleButtonAction = [
{
@ -61,21 +59,22 @@
const enrichFilter = (filter, columns, formId) => {
let enrichedFilter = [...(filter || [])]
columns?.forEach(column => {
const safePath = column.name.split(".").map(safe).join(".")
enrichedFilter.push({
field: column.name,
operator: column.type === "string" ? "string" : "equal",
type: column.type === "string" ? "string" : "number",
valueType: "Binding",
value: `{{ ${safe(formId)}.${safe(column.name)} }}`,
value: `{{ ${safe(formId)}.${safePath} }}`,
})
})
return enrichedFilter
}
// Determine data types for search fields and only use those that are valid
const enrichSearchColumns = async (searchColumns, schema) => {
const enrichSearchColumns = (searchColumns, schema) => {
let enrichedColumns = []
const addType = column => {
searchColumns?.forEach(column => {
const schemaType = schema?.[column]?.type
const componentType = schemaComponentMap[schemaType]
if (componentType) {
@ -84,51 +83,23 @@
componentType,
type: schemaType,
})
return true
}
return false
}
for (let column of searchColumns || []) {
// if addType returns false, it didn't find one, look for SQL relationships
if (!addType(column) && column.includes(".")) {
const [tableName, linkColumn] = column.split(".")
for (let colSchema of Object.values(schema || {})) {
// found the related table
if (
colSchema.type === "link" &&
colSchema.tableId &&
colSchema.tableId.endsWith(tableName)
) {
try {
const linkSchema = await fetchDatasourceSchema({
...dataSource,
tableId: colSchema.tableId,
})
if (linkSchema) {
schema[column] = linkSchema[linkColumn]
addType(column)
}
} catch (err) {
// ignore the error, couldn't get table
}
}
}
}
}
enrichedSearchColumns = enrichedColumns.slice(0, 3)
enrichedSearchColumnsLoaded = true
})
return enrichedColumns.slice(0, 3)
}
// Load the datasource schema so we can determine column types
const fetchSchema = async dataSource => {
if (dataSource) {
schema = await fetchDatasourceSchema(dataSource)
schema = await fetchDatasourceSchema(dataSource, {
enrichRelationships: true,
})
}
schemaLoaded = true
}
</script>
{#if schemaLoaded && enrichedSearchColumnsLoaded}
{#if schemaLoaded}
<Block>
<div class={size} use:styleable={$component.styles}>
<BlockComponent type="form" bind:id={formId} props={{ dataSource }}>

View File

@ -67,7 +67,6 @@ export default class DataFetch {
this.getPage = this.getPage.bind(this)
this.getInitialData = this.getInitialData.bind(this)
this.determineFeatureFlags = this.determineFeatureFlags.bind(this)
this.enrichSchema = this.enrichSchema.bind(this)
this.refresh = this.refresh.bind(this)
this.update = this.update.bind(this)
this.hasNextPage = this.hasNextPage.bind(this)
@ -129,7 +128,7 @@ export default class DataFetch {
// Fetch and enrich schema
let schema = this.constructor.getSchema(datasource, definition)
schema = this.enrichSchema(schema)
schema = DataFetch.enrichSchema(schema)
if (!schema) {
return
}
@ -248,7 +247,7 @@ export default class DataFetch {
* @param schema the datasource schema
* @return {object} the enriched datasource schema
*/
enrichSchema(schema) {
static enrichSchema(schema) {
if (schema == null) {
return null
}

View File

@ -6,13 +6,19 @@ import RelationshipFetch from "./fetch/RelationshipFetch.js"
import NestedProviderFetch from "./fetch/NestedProviderFetch.js"
import FieldFetch from "./fetch/FieldFetch.js"
import JSONArrayFetch from "./fetch/JSONArrayFetch.js"
import DataFetch from "./fetch/DataFetch.js"
/**
* Fetches the schema of any kind of datasource.
* All datasource fetch classes implement their own functionality to get the
* schema of a datasource of their respective types.
* @param datasource the datasource to fetch the schema for
* @param options options for enriching the schema
*/
export const fetchDatasourceSchema = async datasource => {
export const fetchDatasourceSchema = async (
datasource,
options = { enrichRelationships: false }
) => {
const handler = {
table: TableFetch,
view: ViewFetch,
@ -28,7 +34,7 @@ export const fetchDatasourceSchema = async datasource => {
// Get the datasource definition and then schema
const definition = await handler.getDefinition(datasource)
const schema = handler.getSchema(datasource, definition)
let schema = handler.getSchema(datasource, definition)
if (!schema) {
return null
}
@ -49,5 +55,28 @@ export const fetchDatasourceSchema = async datasource => {
})
}
})
return { ...schema, ...jsonAdditions }
schema = { ...schema, ...jsonAdditions }
// Check for any relationship fields if required
if (options?.enrichRelationships) {
let relationshipAdditions = {}
for (let fieldKey of Object.keys(schema)) {
const fieldSchema = schema[fieldKey]
if (fieldSchema?.type === "link") {
const linkSchema = await fetchDatasourceSchema({
type: "table",
tableId: fieldSchema?.tableId,
})
Object.keys(linkSchema || {}).forEach(linkKey => {
relationshipAdditions[`${fieldKey}.${linkKey}`] = {
type: linkSchema[linkKey].type,
}
})
}
}
schema = { ...schema, ...relationshipAdditions }
}
// Ensure schema structure is correct
return DataFetch.enrichSchema(schema)
}