WIP - use objection and working lookup field to owner

This commit is contained in:
Francisco Gaona
2025-12-24 21:43:58 +01:00
parent 4520f94b69
commit c5305490c1
14 changed files with 334 additions and 112 deletions

View File

@@ -30,10 +30,6 @@ const emit = defineEmits<{
const { api } = useApi()
// For relationship fields, store the related record for display
const relatedRecord = ref<any | null>(null)
const loadingRelated = ref(false)
const value = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val),
@@ -49,80 +45,36 @@ const isRelationshipField = computed(() => {
return [FieldType.BELONGS_TO].includes(props.field.type)
})
// Get relation object name (e.g., 'tenants' -> singular 'tenant')
// Get relation object name from field apiName (e.g., 'ownerId' -> 'owner')
const getRelationPropertyName = () => {
const relationObject = props.field.relationObject || props.field.apiName.replace('Id', '')
// Convert plural to singular for property name (e.g., 'tenants' -> 'tenant')
return relationObject.endsWith('s') ? relationObject.slice(0, -1) : relationObject
}
// Fetch related record for display
const fetchRelatedRecord = async () => {
if (!isRelationshipField.value || !props.modelValue) return
const relationObject = props.field.relationObject || props.field.apiName.replace('Id', '')
const displayField = props.field.relationDisplayField || 'name'
loadingRelated.value = true
try {
const record = await api.get(`${props.baseUrl}/${relationObject}/${props.modelValue}`)
relatedRecord.value = record
} catch (err) {
console.error('Error fetching related record:', err)
relatedRecord.value = null
} finally {
loadingRelated.value = false
}
// Backend attaches related object using field apiName without 'Id' suffix, lowercase
// e.g., ownerId -> owner, accountId -> account
return props.field.apiName.replace(/Id$/, '').toLowerCase()
}
// Display value for relationship fields
const relationshipDisplayValue = computed(() => {
if (!isRelationshipField.value) return props.modelValue || '-'
// First, check if the parent record data includes the related object
// This happens when backend uses .withGraphFetched()
if (props.recordData) {
const relationPropertyName = getRelationPropertyName()
const relatedObject = props.recordData[relationPropertyName]
if (relatedObject && typeof relatedObject === 'object') {
const displayField = props.field.relationDisplayField || 'name'
return relatedObject[displayField] || relatedObject.id || props.modelValue
}
}
// Otherwise use the fetched related record
if (relatedRecord.value) {
const displayField = props.field.relationDisplayField || 'name'
return relatedRecord.value[displayField] || relatedRecord.value.id
}
// Show loading state
if (loadingRelated.value) {
return 'Loading...'
}
// Fallback to ID
// If no related object found in recordData, just show the ID
// (The fetch mechanism is removed to avoid N+1 queries)
return props.modelValue || '-'
})
// Watch for changes in modelValue for relationship fields
watch(() => props.modelValue, () => {
if (isRelationshipField.value && (isDetailMode.value || isListMode.value)) {
fetchRelatedRecord()
}
})
// Load related record on mount if needed
onMounted(() => {
if (isRelationshipField.value && props.modelValue && (isDetailMode.value || isListMode.value)) {
fetchRelatedRecord()
}
})
const formatValue = (val: any): string => {
if (val === null || val === undefined) return '-'
switch (props.field.type) {
case FieldType.BELONGS_TO:
return relationshipDisplayValue.value
@@ -168,6 +120,7 @@ const formatValue = (val: any): string => {
{{ formatValue(value) }}
</Badge>
<template v-else>
{{ formatValue(value) }}
</template>
</div>

View File

@@ -56,7 +56,8 @@ const filteredRecords = computed(() => {
const fetchRecords = async () => {
loading.value = true
try {
const response = await api.get(`${props.baseUrl}/${relationObject.value}`)
const endpoint = `${props.baseUrl}/${relationObject.value}/records`
const response = await api.get(endpoint)
records.value = response || []
// If we have a modelValue, find the selected record