This commit is contained in:
Simon Pocrnjič
2025-12-26 22:39:58 +01:00
parent f8623a6071
commit dea7432deb
55 changed files with 7977 additions and 1983 deletions
@@ -1,5 +1,10 @@
<script setup>
import Modal from '@/Components/Modal.vue'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/Components/ui/dialog";
import { Button } from "@/Components/ui/button";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/Components/ui/select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/Components/ui/table";
import { Badge } from "@/Components/ui/badge";
import { Label } from "@/Components/ui/label";
const props = defineProps({
show: Boolean,
limit: Number,
@@ -13,49 +18,69 @@ const emits = defineEmits(['close','change-limit','refresh'])
function onLimit(e){ emits('change-limit', Number(e.target.value)); emits('refresh') }
</script>
<template>
<Modal :show="show" max-width="wide" @close="$emit('close')">
<div class="p-4">
<div class="flex items-center justify-between mb-3">
<h3 class="font-semibold text-lg">CSV Preview ({{ rows.length }} / {{ limit }})</h3>
<button class="text-sm px-2 py-1 rounded border" @click="$emit('close')">Close</button>
</div>
<div class="mb-2 flex items-center gap-3 text-sm">
<div>
<label class="mr-1 text-gray-600">Limit:</label>
<select :value="limit" class="border rounded p-1" @change="onLimit">
<option :value="50">50</option>
<option :value="100">100</option>
<option :value="200">200</option>
<option :value="300">300</option>
<option :value="500">500</option>
</select>
<Dialog :open="show" @update:open="(val) => !val && $emit('close')">
<DialogContent class="max-w-6xl max-h-[90vh] overflow-hidden flex flex-col">
<DialogHeader>
<DialogTitle>CSV Preview ({{ rows.length }} / {{ limit }})</DialogTitle>
</DialogHeader>
<div class="flex items-center gap-3 pb-3 border-b">
<div class="flex items-center gap-2">
<Label for="limit-select" class="text-sm text-gray-600">Limit:</Label>
<Select :model-value="String(limit)" @update:model-value="(val) => { emits('change-limit', Number(val)); emits('refresh'); }">
<SelectTrigger id="limit-select" class="w-24 h-8">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="50">50</SelectItem>
<SelectItem value="100">100</SelectItem>
<SelectItem value="200">200</SelectItem>
<SelectItem value="300">300</SelectItem>
<SelectItem value="500">500</SelectItem>
</SelectContent>
</Select>
</div>
<button @click="$emit('refresh')" class="px-2 py-1 border rounded" :disabled="loading">{{ loading ? 'Loading…' : 'Refresh' }}</button>
<span v-if="truncated" class="text-xs text-amber-600">Truncated at limit</span>
<Button @click="$emit('refresh')" variant="outline" size="sm" :disabled="loading">
{{ loading ? 'Loading…' : 'Refresh' }}
</Button>
<Badge v-if="truncated" variant="outline" class="bg-amber-50 text-amber-700 border-amber-200">
Truncated at limit
</Badge>
</div>
<div class="overflow-auto max-h-[60vh] border rounded">
<table class="min-w-full text-xs">
<thead class="bg-gray-50 sticky top-0">
<tr>
<th class="p-2 border bg-white">#</th>
<th v-for="col in columns" :key="col" class="p-2 border text-left">{{ col }}</th>
</tr>
</thead>
<tbody>
<tr v-if="loading">
<td :colspan="columns.length + 1" class="p-4 text-center text-gray-500">Loading</td>
</tr>
<tr v-for="(r, idx) in rows" :key="idx" class="border-t hover:bg-gray-50">
<td class="p-2 border text-gray-500">{{ idx + 1 }}</td>
<td v-for="col in columns" :key="col" class="p-2 border whitespace-pre-wrap">{{ r[col] }}</td>
</tr>
<tr v-if="!loading && !rows.length">
<td :colspan="columns.length + 1" class="p-4 text-center text-gray-500">No rows</td>
</tr>
</tbody>
</table>
<div class="flex-1 overflow-auto border rounded-lg">
<Table>
<TableHeader class="sticky top-0 bg-white z-10">
<TableRow>
<TableHead class="w-16">#</TableHead>
<TableHead v-for="col in columns" :key="col">{{ col }}</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow v-if="loading">
<TableCell :colspan="columns.length + 1" class="text-center text-gray-500">
Loading…
</TableCell>
</TableRow>
<TableRow v-for="(r, idx) in rows" :key="idx">
<TableCell class="text-gray-500 font-medium">{{ idx + 1 }}</TableCell>
<TableCell v-for="col in columns" :key="col" class="whitespace-pre-wrap">
{{ r[col] }}
</TableCell>
</TableRow>
<TableRow v-if="!loading && !rows.length">
<TableCell :colspan="columns.length + 1" class="text-center text-gray-500">
No rows
</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<p class="mt-2 text-xs text-gray-500">Showing up to {{ limit }} rows from source file. Header detection: {{ hasHeader ? 'header present' : 'no header' }}.</p>
</div>
</Modal>
<div class="text-xs text-gray-500 pt-3 border-t">
Showing up to {{ limit }} rows from source file.
Header detection: <span class="font-medium">{{ hasHeader ? 'header present' : 'no header' }}</span>
</div>
</DialogContent>
</Dialog>
</template>