Add relationships as data source
This commit is contained in:
parent
0e22a21303
commit
009d04a0a5
|
@ -73,18 +73,32 @@ const componentInstanceToBindable = walkResult => i => {
|
|||
|
||||
const contextToBindables = (models, walkResult) => context => {
|
||||
const contextParentPath = getParentPath(walkResult, context)
|
||||
const isModel = context.model?.isModel || typeof context.model === "string"
|
||||
const modelId =
|
||||
typeof context.model === "string" ? context.model : context.model.modelId
|
||||
const model = models.find(model => model._id === modelId)
|
||||
|
||||
let model, schema
|
||||
if (typeof context.model === "string" || context.model.type === "model") {
|
||||
const modelId =
|
||||
typeof context.model === "string" ? context.model : context.model.modelId
|
||||
model = models.find(model => model._id === modelId)
|
||||
schema = model?.schema
|
||||
} else if (context.model.type === "view") {
|
||||
const modelId = context.model.modelId
|
||||
model = models.find(model => model._id === modelId)
|
||||
schema = model?.views?.[context.model.name]?.schema
|
||||
} else if (context.model.type === "link") {
|
||||
console.log(context.model)
|
||||
const modelId = context.model.modelId
|
||||
model = models.find(model => model._id === modelId)
|
||||
schema = model?.schema
|
||||
}
|
||||
|
||||
// Avoid crashing whenever no data source has been selected
|
||||
if (model == null) {
|
||||
if (!schema) {
|
||||
return []
|
||||
}
|
||||
|
||||
const newBindable = key => ({
|
||||
const newBindable = ([key, fieldSchema]) => ({
|
||||
type: "context",
|
||||
fieldSchema,
|
||||
instance: context.instance,
|
||||
// how the binding expression persists, and is used in the app at runtime
|
||||
runtimeBinding: `${contextParentPath}data.${key}`,
|
||||
|
@ -92,15 +106,11 @@ const contextToBindables = (models, walkResult) => context => {
|
|||
readableBinding: `${context.instance._instanceName}.${model.name}.${key}`,
|
||||
})
|
||||
|
||||
// see ModelViewSelect.svelte for the format of context.model
|
||||
// ... this allows us to bind to Model schemas, or View schemas
|
||||
const schema = isModel ? model.schema : model.views[context.model.name].schema
|
||||
|
||||
return (
|
||||
Object.keys(schema)
|
||||
Object.entries(schema)
|
||||
.map(newBindable)
|
||||
// add _id and _rev fields - not part of schema, but always valid
|
||||
.concat([newBindable("_id"), newBindable("_rev")])
|
||||
.concat([newBindable(["_id", "string"]), newBindable(["_rev", "string"])])
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
? models.find(m => m._id === componentInstance.datasource.modelId)
|
||||
: null
|
||||
|
||||
$: type = componentInstance.datasource.type
|
||||
$: if (model) {
|
||||
options = componentInstance.datasource.isModel
|
||||
? Object.keys(model.schema)
|
||||
: Object.keys(model.views[componentInstance.datasource.name].schema)
|
||||
options =
|
||||
type === "model" || type === "link"
|
||||
? Object.keys(model.schema)
|
||||
: Object.keys(model.views[componentInstance.datasource.name].schema)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<script>
|
||||
import { Button, Icon, DropdownMenu, Spacer, Heading } from "@budibase/bbui"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { backendUiStore } from "builderStore"
|
||||
import { store, backendUiStore } from "builderStore"
|
||||
import fetchBindableProperties from "../../builderStore/fetchBindableProperties"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let anchorRight, dropdownRight
|
||||
|
@ -13,21 +14,39 @@
|
|||
dropdownRight.hide()
|
||||
}
|
||||
|
||||
const models = $backendUiStore.models.map(m => ({
|
||||
$: models = $backendUiStore.models.map(m => ({
|
||||
label: m.name,
|
||||
name: `all_${m._id}`,
|
||||
modelId: m._id,
|
||||
isModel: true,
|
||||
type: "model",
|
||||
}))
|
||||
|
||||
const views = $backendUiStore.models.reduce((acc, cur) => {
|
||||
$: views = $backendUiStore.models.reduce((acc, cur) => {
|
||||
let viewsArr = Object.entries(cur.views).map(([key, value]) => ({
|
||||
label: key,
|
||||
name: key,
|
||||
...value,
|
||||
type: "view",
|
||||
}))
|
||||
return [...acc, ...viewsArr]
|
||||
}, [])
|
||||
|
||||
$: bindableProperties = fetchBindableProperties({
|
||||
componentInstanceId: $store.currentComponentInfo._id,
|
||||
components: $store.components,
|
||||
screen: $store.currentPreviewItem,
|
||||
models: $backendUiStore.models,
|
||||
})
|
||||
|
||||
$: links = bindableProperties
|
||||
.filter(x => x.fieldSchema.type === "link")
|
||||
.map(property => ({
|
||||
label: property.readableBinding,
|
||||
fieldName: property.fieldSchema.name,
|
||||
name: `all_${property.fieldSchema.modelId}`,
|
||||
modelId: property.fieldSchema.modelId,
|
||||
type: "link",
|
||||
}))
|
||||
</script>
|
||||
|
||||
<div class="dropdownbutton" bind:this={anchorRight}>
|
||||
|
@ -63,6 +82,19 @@
|
|||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
<hr />
|
||||
<div class="title">
|
||||
<Heading extraSmall>Relationships</Heading>
|
||||
</div>
|
||||
<ul>
|
||||
{#each links as link}
|
||||
<li
|
||||
class:selected={value === link}
|
||||
on:click={() => handleSelected(link)}>
|
||||
{link.label}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const fs = require("fs")
|
||||
const sharp = require("sharp")
|
||||
// const sharp = require("sharp")
|
||||
const fsPromises = fs.promises
|
||||
|
||||
const FORMATS = {
|
||||
|
@ -7,14 +7,14 @@ const FORMATS = {
|
|||
}
|
||||
|
||||
async function processImage(file) {
|
||||
const imgMeta = await sharp(file.path)
|
||||
.resize(300)
|
||||
.toFile(file.outputPath)
|
||||
|
||||
return {
|
||||
...file,
|
||||
...imgMeta,
|
||||
}
|
||||
// const imgMeta = await sharp(file.path)
|
||||
// .resize(300)
|
||||
// .toFile(file.outputPath)
|
||||
//
|
||||
// return {
|
||||
// ...file,
|
||||
// ...imgMeta,
|
||||
// }
|
||||
}
|
||||
|
||||
async function process(file) {
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
onMount(async () => {
|
||||
if (!isEmpty(datasource)) {
|
||||
data = await fetchData(datasource)
|
||||
data = await fetchData(datasource, _bb)
|
||||
if (data && data.length) {
|
||||
await fetchModel(data[0].modelId)
|
||||
headers = Object.keys(schema).filter(shouldDisplayField)
|
||||
|
@ -99,7 +99,7 @@
|
|||
{#if schema[header].type === 'attachment'}
|
||||
<AttachmentList files={row[header]} />
|
||||
{:else if schema[header].type === 'link'}
|
||||
<td>{row[header] ? row[header].length : 0} related row(s)</td>
|
||||
<td>{row[header]} related row(s)</td>
|
||||
{:else if row[header]}
|
||||
<td>{row[header]}</td>
|
||||
{/if}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
onMount(async () => {
|
||||
if (!isEmpty(datasource)) {
|
||||
const data = await fetchData(datasource)
|
||||
const data = await fetchData(datasource, _bb)
|
||||
_bb.attachChildren(target, {
|
||||
hydrate: false,
|
||||
context: data,
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
async function fetchData() {
|
||||
const pathParts = window.location.pathname.split("/")
|
||||
|
||||
if (!model) {
|
||||
return
|
||||
}
|
||||
|
||||
let record
|
||||
// if srcdoc, then we assume this is the builder preview
|
||||
if (pathParts.length === 0 || pathParts[0] === "srcdoc") {
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
import api from "./api"
|
||||
|
||||
export default async function fetchData(datasource) {
|
||||
const { isModel, name } = datasource
|
||||
export default async function fetchData(datasource, _bb) {
|
||||
const { type, name } = datasource
|
||||
|
||||
if (name) {
|
||||
const records = isModel ? await fetchModelData() : await fetchViewData()
|
||||
let records
|
||||
if (type === "model") {
|
||||
records = await fetchModelData()
|
||||
} else if (type === "view") {
|
||||
records = await fetchViewData()
|
||||
} else if (type === "link") {
|
||||
records = await fetchLinkedRecordsData()
|
||||
}
|
||||
|
||||
// Fetch model schema so we can check for linked records
|
||||
if (records && records.length) {
|
||||
|
@ -53,4 +60,18 @@ export default async function fetchData(datasource) {
|
|||
const response = await api.get(QUERY_VIEW_URL)
|
||||
return await response.json()
|
||||
}
|
||||
|
||||
async function fetchLinkedRecordsData() {
|
||||
if (
|
||||
!_bb.store.state ||
|
||||
!_bb.store.state.data ||
|
||||
!_bb.store.state.data._id
|
||||
) {
|
||||
return []
|
||||
}
|
||||
const QUERY_URL = `/api/${_bb.store.state.data.modelId}/${_bb.store.state.data._id}/enrich`
|
||||
const response = await api.get(QUERY_URL)
|
||||
const record = await response.json()
|
||||
return record[datasource.fieldName]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue