WIP - manually sharing records

This commit is contained in:
Francisco Gaona
2025-12-30 18:29:20 +01:00
parent 6c29d18696
commit e73126bcb7
9 changed files with 830 additions and 80 deletions

View File

@@ -2,9 +2,11 @@
import { computed, ref, onMounted } from 'vue'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import FieldRenderer from '@/components/fields/FieldRenderer.vue'
import PageLayoutRenderer from '@/components/PageLayoutRenderer.vue'
import RelatedList from '@/components/RelatedList.vue'
import RecordSharing from '@/components/RecordSharing.vue'
import { DetailViewConfig, ViewMode, FieldSection, FieldConfig, RelatedListConfig } from '@/types/field-types'
import { Edit, Trash2, ArrowLeft } from 'lucide-vue-next'
import {
@@ -20,11 +22,13 @@ interface Props {
loading?: boolean
objectId?: string // For fetching page layout
baseUrl?: string
showSharing?: boolean
}
const props = withDefaults(defineProps<Props>(), {
loading: false,
baseUrl: '/runtime/objects',
showSharing: true,
})
const emit = defineEmits<{
@@ -130,91 +134,123 @@ const usePageLayout = computed(() => {
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
</div>
<!-- Content with Page Layout -->
<Card v-else-if="usePageLayout">
<CardHeader>
<CardTitle>Details</CardTitle>
</CardHeader>
<CardContent>
<PageLayoutRenderer
:fields="config.fields"
:layout="pageLayout"
:model-value="data"
:readonly="true"
/>
</CardContent>
</Card>
<!-- Tabs for Details, Related, and Sharing -->
<Tabs v-else default-value="details" class="space-y-6">
<TabsList>
<TabsTrigger value="details">Details</TabsTrigger>
<TabsTrigger v-if="config.relatedLists && config.relatedLists.length > 0" value="related">
Related
</TabsTrigger>
<TabsTrigger v-if="showSharing && data.id" value="sharing">
Sharing
</TabsTrigger>
</TabsList>
<!-- Traditional Section-based Layout -->
<div v-else class="space-y-6">
<Card v-for="(section, idx) in sections" :key="idx">
<Collapsible
v-if="section.collapsible"
:default-open="!section.defaultCollapsed"
>
<!-- Details Tab -->
<TabsContent value="details" class="space-y-6">
<!-- Content with Page Layout -->
<Card v-if="usePageLayout">
<CardHeader>
<CollapsibleTrigger class="flex items-center justify-between w-full hover:bg-muted/50 -m-2 p-2 rounded">
<div>
<CardTitle>Details</CardTitle>
</CardHeader>
<CardContent>
<PageLayoutRenderer
:fields="config.fields"
:layout="pageLayout"
:model-value="data"
:readonly="true"
/>
</CardContent>
</Card>
<!-- Traditional Section-based Layout -->
<div v-else class="space-y-6">
<Card v-for="(section, idx) in sections" :key="idx">
<Collapsible
v-if="section.collapsible"
:default-open="!section.defaultCollapsed"
>
<CardHeader>
<CollapsibleTrigger class="flex items-center justify-between w-full hover:bg-muted/50 -m-2 p-2 rounded">
<div>
<CardTitle v-if="section.title">{{ section.title }}</CardTitle>
<CardDescription v-if="section.description">
{{ section.description }}
</CardDescription>
</div>
</CollapsibleTrigger>
</CardHeader>
<CollapsibleContent>
<CardContent>
<div class="grid gap-6 md:grid-cols-2">
<FieldRenderer
v-for="field in getFieldsBySection(section)"
:key="field.id"
:field="field"
:model-value="data[field.apiName]"
:record-data="data"
:mode="ViewMode.DETAIL"
:base-url="baseUrl"
/>
</div>
</CardContent>
</CollapsibleContent>
</Collapsible>
<template v-else>
<CardHeader v-if="section.title || section.description">
<CardTitle v-if="section.title">{{ section.title }}</CardTitle>
<CardDescription v-if="section.description">
{{ section.description }}
</CardDescription>
</div>
</CollapsibleTrigger>
</CardHeader>
<CollapsibleContent>
<CardContent>
<div class="grid gap-6 md:grid-cols-2">
<FieldRenderer
v-for="field in getFieldsBySection(section)"
:key="field.id"
:field="field"
:model-value="data[field.apiName]"
:record-data="data"
:mode="ViewMode.DETAIL"
:base-url="baseUrl"
/>
</div>
</CardContent>
</CollapsibleContent>
</Collapsible>
</CardHeader>
<CardContent>
<div class="grid gap-6 md:grid-cols-2">
<FieldRenderer
v-for="field in getFieldsBySection(section)"
:key="field?.id"
:field="field"
:model-value="data[field.apiName]"
:record-data="data"
:mode="ViewMode.DETAIL"
:base-url="baseUrl"
/>
</div>
</CardContent>
</template>
</Card>
</div>
</TabsContent>
<template v-else>
<CardHeader v-if="section.title || section.description">
<CardTitle v-if="section.title">{{ section.title }}</CardTitle>
<CardDescription v-if="section.description">
{{ section.description }}
</CardDescription>
</CardHeader>
<CardContent>
<div class="grid gap-6 md:grid-cols-2">
<FieldRenderer
v-for="field in getFieldsBySection(section)"
:key="field?.id"
:field="field"
:model-value="data[field.apiName]"
:record-data="data"
:mode="ViewMode.DETAIL"
:base-url="baseUrl"
/>
</div>
<!-- Related Lists Tab -->
<TabsContent value="related" class="space-y-6">
<div v-if="config.relatedLists && config.relatedLists.length > 0">
<RelatedList
v-for="relatedList in config.relatedLists"
:key="relatedList.relationName"
:config="relatedList"
:parent-id="data.id"
:related-records="data[relatedList.relationName]"
@navigate="(objectApiName, recordId) => emit('navigate', objectApiName, recordId)"
@create="(objectApiName, parentId) => emit('createRelated', objectApiName, parentId)"
/>
</div>
</TabsContent>
<!-- Sharing Tab -->
<TabsContent value="sharing">
<Card>
<CardContent class="pt-6">
<RecordSharing
v-if="data.id && config.objectApiName"
:object-api-name="config.objectApiName"
:record-id="data.id"
:owner-id="data.ownerId"
/>
</CardContent>
</template>
</Card>
</div>
<!-- Related Lists -->
<div v-if="config.relatedLists && config.relatedLists.length > 0" class="space-y-6">
<RelatedList
v-for="relatedList in config.relatedLists"
:key="relatedList.relationName"
:config="relatedList"
:parent-id="data.id"
:related-records="data[relatedList.relationName]"
@navigate="(objectApiName, recordId) => emit('navigate', objectApiName, recordId)"
@create="(objectApiName, parentId) => emit('createRelated', objectApiName, parentId)"
/>
</div>
</Card>
</TabsContent>
</Tabs>
</div>
</template>