fix: agregar paginación y límite configurable en explorer
- Agregar selector de límite de registros (10 a 10,000) - Implementar paginación client-side con UPagination - Mostrar información detallada de registros cargados y filtrados - Usar límite seleccionado en lugar de hardcoded 1000 - Resetear página al cambiar búsqueda o cargar datos - Indicar cuando hay más datos disponibles (limitado) - Mejorar UX con paginación de 50 filas por página por defecto
This commit is contained in:
@@ -34,6 +34,15 @@
|
||||
/>
|
||||
</UFieldGroup>
|
||||
|
||||
<!-- Limit Selector -->
|
||||
<UFieldGroup label="Límite de registros" v-if="selectedTable">
|
||||
<USelectMenu
|
||||
v-model="selectedLimit"
|
||||
:items="limitOptions"
|
||||
placeholder="Seleccionar límite"
|
||||
/>
|
||||
</UFieldGroup>
|
||||
|
||||
<!-- Load Data Button -->
|
||||
<UButton
|
||||
v-if="selectedTable"
|
||||
@@ -81,7 +90,7 @@
|
||||
</h2>
|
||||
<div class="flex flex-wrap gap-2 text-xs text-[var(--brand-text-muted)]">
|
||||
<span class="brand-pill inline-flex items-center gap-2 rounded-full px-3 py-1 text-xs">
|
||||
{{ tableData.length }} registros
|
||||
{{ tableData.length }} registros cargados{{ hasMoreData ? ` (limitado a ${selectedLimit})` : '' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -129,15 +138,24 @@
|
||||
|
||||
<!-- Table -->
|
||||
<UTable
|
||||
:data="filteredData"
|
||||
:data="paginatedData"
|
||||
:columns="displayColumns"
|
||||
:loading="loadingData"
|
||||
class="h-96"
|
||||
/>
|
||||
|
||||
<!-- Table Footer -->
|
||||
<div class="px-4 py-3.5 text-sm text-muted">
|
||||
{{ filteredData.length }} de {{ tableData.length }} filas mostradas.
|
||||
<!-- Pagination -->
|
||||
<div class="flex items-center justify-between px-4 py-3.5">
|
||||
<div class="text-sm text-muted">
|
||||
Mostrando {{ startRow }} a {{ endRow }} de {{ filteredData.length }} filas{{ filteredData.length !== tableData.length ? ` (filtradas de ${tableData.length} totales)` : '' }}
|
||||
</div>
|
||||
<UPagination
|
||||
v-if="filteredData.length > rowsPerPage"
|
||||
v-model="page"
|
||||
:page-count="rowsPerPage"
|
||||
:total="filteredData.length"
|
||||
:max="5"
|
||||
size="xs"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</UCard>
|
||||
@@ -177,12 +195,15 @@ const router = useRouter()
|
||||
// State
|
||||
const selectedDatabase = ref<any | null>(null)
|
||||
const selectedTable = ref<any | null>(null)
|
||||
const selectedLimit = ref(100)
|
||||
const loadingDatabases = ref(false)
|
||||
const loadingTables = ref(false)
|
||||
const loadingData = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
const searchQuery = ref('')
|
||||
const showColumnSelector = ref(false)
|
||||
const page = ref(1)
|
||||
const rowsPerPage = ref(50)
|
||||
|
||||
const databases = ref<any[]>([])
|
||||
const tables = ref<any[]>([])
|
||||
@@ -192,6 +213,12 @@ const visibleColumns = ref<string[]>([])
|
||||
// Track if we should auto-load data from URL params
|
||||
const shouldAutoLoad = ref(false)
|
||||
|
||||
// Limit options
|
||||
const limitOptions = [10, 50, 100, 500, 1000, 5000, 10000]
|
||||
|
||||
// Track if there might be more data
|
||||
const hasMoreData = computed(() => tableData.value.length >= selectedLimit.value)
|
||||
|
||||
// Computed
|
||||
const databaseOptions = computed(() => {
|
||||
return databases.value.map(db => db.name)
|
||||
@@ -249,6 +276,24 @@ const filteredData = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
// Paginated data
|
||||
const paginatedData = computed(() => {
|
||||
const start = (page.value - 1) * rowsPerPage.value
|
||||
const end = start + rowsPerPage.value
|
||||
return filteredData.value.slice(start, end)
|
||||
})
|
||||
|
||||
// Pagination helpers
|
||||
const startRow = computed(() => {
|
||||
if (filteredData.value.length === 0) return 0
|
||||
return (page.value - 1) * rowsPerPage.value + 1
|
||||
})
|
||||
|
||||
const endRow = computed(() => {
|
||||
const end = page.value * rowsPerPage.value
|
||||
return Math.min(end, filteredData.value.length)
|
||||
})
|
||||
|
||||
// Methods
|
||||
async function loadDatabases() {
|
||||
loadingDatabases.value = true
|
||||
@@ -339,7 +384,7 @@ async function loadTableData() {
|
||||
databaseId: selectedDatabaseId.value,
|
||||
tableId: selectedTableId.value,
|
||||
query: {
|
||||
limit: 1000 // Limitar a 1000 registros por defecto
|
||||
limit: selectedLimit.value
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -408,6 +453,16 @@ watch(selectedTable, (newTable) => {
|
||||
}
|
||||
})
|
||||
|
||||
// Reset page when search changes
|
||||
watch(searchQuery, () => {
|
||||
page.value = 1
|
||||
})
|
||||
|
||||
// Reset page when data loads
|
||||
watch(tableData, () => {
|
||||
page.value = 1
|
||||
})
|
||||
|
||||
// Lifecycle
|
||||
onMounted(() => {
|
||||
loadDatabases()
|
||||
|
||||
Reference in New Issue
Block a user