All files / components/migrations MigrationsTable.tsx

88.88% Statements 8/9
83.33% Branches 10/12
87.5% Functions 7/8
88.88% Lines 8/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                                      44x           97x                               97x                     97x                         97x             97x                           44x       97x                
import { Badge } from '@/components/ui/badge';
import { format } from 'date-fns';
import type { MigrationRevision } from '@/types/migrations';
import { DataTable, type Column } from '@/components/common/DataTable';
import MigrationStatusBadge from './MigrationStatusBadge';
 
interface MigrationsTableProps {
    migrations: MigrationRevision[];
    currentRevision: string | null;
    onView: (migration: MigrationRevision) => void;
    isLoading?: boolean;
}
 
export default function MigrationsTable({
    migrations,
    currentRevision,
    onView,
    isLoading,
}: MigrationsTableProps) {
    const columns: Column<MigrationRevision>[] = [
        {
            header: 'Revision',
            accessorKey: 'revision',
            className: 'font-mono text-xs max-w-[120px]',
            render: (migration) => (
                <span
                    className="truncate block"
                    title={migration.revision}
                >
                    {migration.revision.substring(0, 12)}
                </span>
            ),
        },
        {
            header: 'Description',
            accessorKey: 'description',
            className: 'font-medium',
        },
        {
            header: 'Type',
            render: (migration) => (
                <Badge
                    variant={migration.is_dynamic ? 'secondary' : 'outline'}
                    className={migration.is_dynamic ? 'bg-purple-500 hover:bg-purple-600 text-white' : ''}
                >
                    {migration.is_dynamic ? 'Dynamic' : 'Core'}
                </Badge>
            ),
        },
        {
            header: 'Status',
            render: (migration) => (
                <MigrationStatusBadge
                    isApplied={migration.is_applied}
                    isHead={migration.is_head}
                    isCurrent={migration.revision === currentRevision}
                />
            ),
        },
        {
            header: 'Created',
            accessorKey: 'created_at',
            sortable: true,
            className: 'whitespace-nowrap',
            render: (migration) =>
                migration.created_at
                    ? format(new Date(migration.created_at), 'yyyy-MM-dd HH:mm')
                    : '-',
        },
        {
            header: 'Branch Labels',
            render: (migration) =>
                migration.branch_labels && migration.branch_labels.length > 0 ? (
                    <div className="flex gap-1 flex-wrap">
                        {migration.branch_labels.map((label) => (
                            <Badge key={label} variant="outline" className="text-xs">
                                {label}
                            </Badge>
                        ))}
                    </div>
                ) : (
                    <span className="text-muted-foreground">-</span>
                ),
        },
    ];
 
    return (
        <DataTable
            data={migrations}
            columns={columns}
            keyExtractor={(migration) => migration.revision}
            isLoading={isLoading}
            totalItems={migrations.length}
            onRowClick={onView}
            noDataMessage="No migrations found."
        />
    );
}