forked from Guepard-Corp/qwery-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtable.tsx
More file actions
117 lines (104 loc) · 3.56 KB
/
table.tsx
File metadata and controls
117 lines (104 loc) · 3.56 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { useMemo } from 'react';
import { useParams, Link } from 'react-router';
import { useTranslation } from 'react-i18next';
import {
Columns,
type ColumnListItem,
} from '@qwery/ui/qwery/datasource/columns';
import { useGetDatasourceMetadata } from '~/lib/queries/use-get-datasource-metadata';
import type { Column, Table } from '@qwery/domain/entities';
import { GetDatasourceBySlugService } from '@qwery/domain/services';
import { DomainException } from '@qwery/domain/exceptions';
import type { Route } from './+types/table';
import { getRepositoriesForLoader } from '~/lib/loaders/create-repositories';
export async function loader(args: Route.LoaderArgs) {
const slug = args.params.slug;
if (!slug) return { datasource: null };
const repositories = await getRepositoriesForLoader(args.request);
const getDatasourceService = new GetDatasourceBySlugService(
repositories.datasource,
);
try {
const datasource = await getDatasourceService.execute(slug);
return { datasource };
} catch (error) {
if (error instanceof DomainException) return { datasource: null };
throw error;
}
}
export default function TablePage(props: Route.ComponentProps) {
const params = useParams();
const slug = params.slug as string;
const schemaParam = params.schema as string;
const tableNameParam = params.tableName as string;
const schema = schemaParam ? decodeURIComponent(schemaParam) : '';
const tableName = tableNameParam ? decodeURIComponent(tableNameParam) : '';
const { t } = useTranslation();
const { datasource } = props.loaderData;
const { data: metadata, isLoading } = useGetDatasourceMetadata(datasource, {
enabled: !!datasource,
});
const table = useMemo(() => {
if (!metadata?.tables || !schema || !tableName) return null;
const tables = metadata.tables as Table[];
return (
tables.find(
(t) => (t.schema ?? 'main') === schema && t.name === tableName,
) ?? null
);
}, [metadata, schema, tableName]);
const columns = useMemo(() => {
if (!metadata?.columns || !table) return [];
const allColumns = metadata.columns as Column[];
return allColumns.filter(
(col) =>
col.table_id === table.id &&
col.table === table.name &&
(col.schema ?? 'main') === (table.schema ?? 'main'),
);
}, [metadata, table]);
const columnListItems: ColumnListItem[] = useMemo(() => {
return columns.map((col) => ({
name: col.name,
description: col.comment,
dataType: col.data_type,
format: col.format,
}));
}, [columns]);
if (isLoading) {
return (
<div className="flex items-center justify-center p-8">
<p className="text-muted-foreground text-sm">
{t('datasource.table.loading', {
defaultValue: 'Loading table...',
})}
</p>
</div>
);
}
if (!metadata || !table) {
return (
<div className="flex items-center justify-center p-8">
<p className="text-muted-foreground text-sm">
{t('datasource.table.error', {
defaultValue: 'Table not found',
})}
</p>
</div>
);
}
const tablesPath = `/ds/${slug}/tables`;
return (
<div className="space-y-4 p-6">
<h1 className="text-2xl font-semibold">
<Link to={tablesPath} className="text-primary hover:underline">
{t('datasource.table.title', {
defaultValue: 'Tables',
})}
</Link>{' '}
<span className="text-muted-foreground">></span> {table.name}
</h1>
<Columns columns={columnListItems} />
</div>
);
}