refactor: improve SelectMenu implementation with object binding
- Change from ID-based selection to full object binding - Add custom label templates to display proper text - Simplify computed properties and watchers - Improve user experience with proper label display
This commit is contained in:
@@ -15,34 +15,40 @@
|
||||
<!-- Database Selector -->
|
||||
<UFieldGroup label="Base de datos">
|
||||
<USelectMenu
|
||||
v-model="selectedDatabaseId"
|
||||
:options="databaseOptions"
|
||||
v-model="selectedDatabase"
|
||||
:options="databases"
|
||||
placeholder="Seleccionar base de datos"
|
||||
:loading="loadingDatabases"
|
||||
:disabled="loadingDatabases"
|
||||
value-attribute="value"
|
||||
option-attribute="label"
|
||||
/>
|
||||
option-attribute="name"
|
||||
>
|
||||
<template #label>
|
||||
{{ selectedDatabase?.name || 'Seleccionar base de datos' }}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFieldGroup>
|
||||
|
||||
<!-- Table Selector -->
|
||||
<UFieldGroup label="Tabla" v-if="selectedDatabaseId">
|
||||
<UFieldGroup label="Tabla" v-if="selectedDatabase">
|
||||
<USelectMenu
|
||||
v-model="selectedTableId"
|
||||
:options="tableOptions"
|
||||
v-model="selectedTable"
|
||||
:options="tables"
|
||||
placeholder="Seleccionar tabla"
|
||||
:loading="loadingTables"
|
||||
:disabled="loadingTables || !selectedDatabaseId"
|
||||
value-attribute="value"
|
||||
option-attribute="label"
|
||||
/>
|
||||
:disabled="loadingTables || !selectedDatabase"
|
||||
option-attribute="name"
|
||||
>
|
||||
<template #label>
|
||||
{{ selectedTable?.display_name || selectedTable?.name || 'Seleccionar tabla' }}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFieldGroup>
|
||||
|
||||
<!-- Load Data Button -->
|
||||
<UButton
|
||||
v-if="selectedTableId"
|
||||
v-if="selectedTable"
|
||||
:loading="loadingData"
|
||||
:disabled="!selectedTableId"
|
||||
:disabled="!selectedTable"
|
||||
@click="loadTableData"
|
||||
color="primary"
|
||||
icon="i-lucide-refresh-cw"
|
||||
@@ -147,7 +153,7 @@
|
||||
</UCard>
|
||||
|
||||
<!-- Empty State -->
|
||||
<UCard v-else-if="selectedTableId" class="brand-card border border-transparent">
|
||||
<UCard v-else-if="selectedTable" class="brand-card border border-transparent">
|
||||
<div class="py-10 text-center text-sm text-[var(--brand-text-muted)]">
|
||||
<UIcon name="i-lucide-inbox" class="mx-auto mb-4 size-12 text-[var(--brand-text-muted)]" />
|
||||
<h3 class="text-lg font-semibold text-[var(--brand-text)] mb-2">No hay datos disponibles</h3>
|
||||
@@ -175,8 +181,8 @@ definePageMeta({
|
||||
})
|
||||
|
||||
// State
|
||||
const selectedDatabaseId = ref<number | null>(null)
|
||||
const selectedTableId = ref<number | null>(null)
|
||||
const selectedDatabase = ref<any | null>(null)
|
||||
const selectedTable = ref<any | null>(null)
|
||||
const loadingDatabases = ref(false)
|
||||
const loadingTables = ref(false)
|
||||
const loadingData = ref(false)
|
||||
@@ -190,23 +196,11 @@ const tableData = ref<any[]>([])
|
||||
const visibleColumns = ref<string[]>([])
|
||||
|
||||
// Computed
|
||||
const databaseOptions = computed(() => {
|
||||
return databases.value.map(db => ({
|
||||
label: db.name,
|
||||
value: db.id
|
||||
}))
|
||||
})
|
||||
|
||||
const tableOptions = computed(() => {
|
||||
return tables.value.map(table => ({
|
||||
label: `${table.display_name || table.name} (${table.row_count || 0} registros)`,
|
||||
value: table.id
|
||||
}))
|
||||
})
|
||||
const selectedDatabaseId = computed(() => selectedDatabase.value?.id)
|
||||
const selectedTableId = computed(() => selectedTable.value?.id)
|
||||
|
||||
const selectedTableName = computed(() => {
|
||||
const table = tables.value.find(t => t.id === selectedTableId.value)
|
||||
return table ? (table.display_name || table.name) : ''
|
||||
return selectedTable.value ? (selectedTable.value.display_name || selectedTable.value.name) : ''
|
||||
})
|
||||
|
||||
const tableColumns = computed(() => {
|
||||
@@ -252,7 +246,7 @@ async function loadDatabases() {
|
||||
|
||||
// Auto-select first database
|
||||
if (databases.value.length > 0) {
|
||||
selectedDatabaseId.value = databases.value[0].id
|
||||
selectedDatabase.value = databases.value[0]
|
||||
}
|
||||
} catch (err: any) {
|
||||
error.value = `Error al cargar bases de datos: ${err.message || 'Error desconocido'}`
|
||||
@@ -263,15 +257,15 @@ async function loadDatabases() {
|
||||
}
|
||||
|
||||
async function loadTables() {
|
||||
if (!selectedDatabaseId.value) return
|
||||
if (!selectedDatabase.value) return
|
||||
|
||||
loadingTables.value = true
|
||||
error.value = null
|
||||
selectedTableId.value = null
|
||||
selectedTable.value = null
|
||||
tableData.value = []
|
||||
|
||||
try {
|
||||
const response = await $fetch(`/api/metabase/tables/${selectedDatabaseId.value}`)
|
||||
const response = await $fetch(`/api/metabase/tables/${selectedDatabase.value.id}`)
|
||||
const metadata = response as any
|
||||
|
||||
// Metabase returns tables in the 'tables' property
|
||||
@@ -339,7 +333,7 @@ function toggleColumn(columnKey: string) {
|
||||
}
|
||||
|
||||
// Watchers
|
||||
watch(selectedDatabaseId, () => {
|
||||
watch(selectedDatabase, () => {
|
||||
loadTables()
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user