Add record access strategy
This commit is contained in:
206
frontend/pages/central/tenants/[[recordId]]/[[view]].vue
Normal file
206
frontend/pages/central/tenants/[[recordId]]/[[view]].vue
Normal file
@@ -0,0 +1,206 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useApi } from '@/composables/useApi'
|
||||
import { useViewState } from '@/composables/useFieldViews'
|
||||
import {
|
||||
tenantFields,
|
||||
tenantListConfig,
|
||||
tenantDetailConfig,
|
||||
tenantEditConfig,
|
||||
} from '@/composables/useCentralEntities'
|
||||
import ListView from '@/components/views/ListView.vue'
|
||||
import DetailView from '@/components/views/DetailViewEnhanced.vue'
|
||||
import EditView from '@/components/views/EditViewEnhanced.vue'
|
||||
import TenantUserDialog from '@/components/TenantUserDialog.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { api } = useApi()
|
||||
|
||||
// Tenant user dialog state
|
||||
const showTenantUserDialog = ref(false)
|
||||
const tenantUserDialogTenantId = ref('')
|
||||
|
||||
const recordId = computed(() => route.params.recordId as string)
|
||||
const view = computed(() => {
|
||||
if (route.params.recordId === 'new' && !route.params.view) {
|
||||
return 'edit'
|
||||
}
|
||||
return (route.params.view as 'list' | 'detail' | 'edit') || 'list'
|
||||
})
|
||||
|
||||
// Use view state composable
|
||||
const {
|
||||
records,
|
||||
currentRecord,
|
||||
loading: dataLoading,
|
||||
saving,
|
||||
fetchRecords,
|
||||
fetchRecord,
|
||||
deleteRecords,
|
||||
handleSave,
|
||||
} = useViewState('/central/tenants')
|
||||
|
||||
// Navigation handlers
|
||||
const handleRowClick = (row: any) => {
|
||||
router.push(`/central/tenants/${row.id}/detail`)
|
||||
}
|
||||
|
||||
const handleCreate = () => {
|
||||
router.push(`/central/tenants/new`)
|
||||
}
|
||||
|
||||
const handleEdit = (row?: any) => {
|
||||
const id = row?.id || recordId.value
|
||||
router.push(`/central/tenants/${id}/edit`)
|
||||
}
|
||||
|
||||
const handleBack = () => {
|
||||
if (view.value === 'detail') {
|
||||
router.push('/central/tenants')
|
||||
} else if (view.value === 'edit') {
|
||||
if (recordId.value && recordId.value !== 'new') {
|
||||
router.push(`/central/tenants/${recordId.value}/detail`)
|
||||
} else {
|
||||
router.push('/central/tenants')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
handleBack()
|
||||
}
|
||||
|
||||
const handleDelete = async (rows: any[]) => {
|
||||
if (confirm(`Delete ${rows.length} tenant(s)? This action cannot be undone.`)) {
|
||||
try {
|
||||
const ids = rows.map(r => r.id)
|
||||
await deleteRecords(ids)
|
||||
if (view.value !== 'list') {
|
||||
await router.push('/central/tenants')
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.error('Failed to delete tenants:', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle navigation to related records
|
||||
const handleNavigate = (objectApiName: string, recordId: string) => {
|
||||
router.push(`/central/${objectApiName}/${recordId}/detail`)
|
||||
}
|
||||
|
||||
// Handle creating related records
|
||||
const handleCreateRelated = (objectApiName: string, parentId: string) => {
|
||||
// Special handling for tenant users
|
||||
if (objectApiName.includes('tenants/:parentId/users')) {
|
||||
tenantUserDialogTenantId.value = parentId
|
||||
showTenantUserDialog.value = true
|
||||
return
|
||||
}
|
||||
|
||||
// Navigate to create page with parent context
|
||||
router.push({
|
||||
path: `/central/${objectApiName}/new`,
|
||||
query: { tenantId: parentId }
|
||||
})
|
||||
}
|
||||
|
||||
// Handle tenant user created
|
||||
const handleTenantUserCreated = async () => {
|
||||
// Refresh the current record to update related lists
|
||||
if (recordId.value && recordId.value !== 'new') {
|
||||
await fetchRecord(recordId.value)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSaveRecord = async (data: any) => {
|
||||
try {
|
||||
const savedRecord = await handleSave(data)
|
||||
if (savedRecord?.id) {
|
||||
router.push(`/central/tenants/${savedRecord.id}/detail`)
|
||||
} else {
|
||||
router.push('/central/tenants')
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.error('Failed to save tenant:', e)
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize
|
||||
onMounted(async () => {
|
||||
if (view.value === 'list') {
|
||||
await fetchRecords()
|
||||
} else if (recordId.value && recordId.value !== 'new') {
|
||||
await fetchRecord(recordId.value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NuxtLayout name="default">
|
||||
<div class="object-view-container">
|
||||
<!-- Page Header -->
|
||||
<div v-if="view === 'list'" class="mb-6">
|
||||
<h1 class="text-3xl font-bold">Tenants</h1>
|
||||
<p class="text-muted-foreground mt-2">
|
||||
Manage tenant organizations and their database configurations
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- List View -->
|
||||
<ListView
|
||||
v-if="view === 'list'"
|
||||
:config="tenantListConfig"
|
||||
:data="records"
|
||||
:loading="dataLoading"
|
||||
selectable
|
||||
@row-click="handleRowClick"
|
||||
@create="handleCreate"
|
||||
@edit="handleEdit"
|
||||
@delete="handleDelete"
|
||||
/>
|
||||
|
||||
<!-- Detail View -->
|
||||
<DetailView
|
||||
v-else-if="view === 'detail' && currentRecord"
|
||||
:config="tenantDetailConfig"
|
||||
:data="currentRecord"
|
||||
:loading="dataLoading"
|
||||
@edit="handleEdit"
|
||||
@delete="() => handleDelete([currentRecord])"
|
||||
@back="handleBack"
|
||||
@navigate="handleNavigate"
|
||||
@create-related="handleCreateRelated"
|
||||
/>
|
||||
|
||||
<!-- Edit View -->
|
||||
<EditView
|
||||
v-else-if="(view === 'edit' || recordId === 'new') && tenantEditConfig"
|
||||
:config="tenantEditConfig"
|
||||
:data="currentRecord || {}"
|
||||
:loading="dataLoading"
|
||||
:saving="saving"
|
||||
@save="handleSaveRecord"
|
||||
@cancel="handleCancel"
|
||||
@back="handleBack"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Tenant User Creation Dialog -->
|
||||
<TenantUserDialog
|
||||
v-model:open="showTenantUserDialog"
|
||||
:tenant-id="tenantUserDialogTenantId"
|
||||
:tenant-name="(currentRecord as any)?.name"
|
||||
@created="handleTenantUserCreated"
|
||||
/>
|
||||
</NuxtLayout>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.object-view-container {
|
||||
min-height: 100vh;
|
||||
padding: 2rem;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user