|
1 |
| -import React from 'react'; |
2 |
| -import { Table, Tag, Empty, Spin, Badge, Tooltip } from 'antd'; |
3 |
| -import { |
4 |
| - DatabaseOutlined, |
5 |
| - UserOutlined, |
6 |
| - CheckCircleOutlined, |
7 |
| - CloseCircleOutlined |
8 |
| -} from '@ant-design/icons'; |
9 |
| -import { DataSourceWithMeta } from '../types/datasource.types'; |
| 1 | +// components/DataSourcesList.tsx |
| 2 | +// Create this new file |
| 3 | + |
| 4 | +import React, { useState } from 'react'; |
| 5 | +import { Table, Switch, Button, Space, Tooltip, Tag } from 'antd'; |
| 6 | +import { CloudUploadOutlined } from '@ant-design/icons'; |
| 7 | +import { DataSource } from '../types/datasource.types'; |
| 8 | +import { Environment } from '../types/environment.types'; |
| 9 | +import { ColumnsType } from 'antd/lib/table'; |
| 10 | +import DeployDataSourceModal from './DeployDataSourceModal'; |
10 | 11 |
|
11 | 12 | interface DataSourcesListProps {
|
12 |
| - dataSources: DataSourceWithMeta[]; |
| 13 | + dataSources: DataSource[]; |
13 | 14 | loading: boolean;
|
14 |
| - error?: string | null; |
| 15 | + error: string | null; |
| 16 | + environment: Environment; |
| 17 | + onToggleManaged: (dataSource: DataSource, checked: boolean) => Promise<void>; |
| 18 | + onRefresh?: () => void; |
15 | 19 | }
|
16 | 20 |
|
17 |
| -/** |
18 |
| - * Component to display a list of data sources in a table |
19 |
| - */ |
20 | 21 | const DataSourcesList: React.FC<DataSourcesListProps> = ({
|
21 | 22 | dataSources,
|
22 | 23 | loading,
|
23 | 24 | error,
|
| 25 | + environment, |
| 26 | + onToggleManaged, |
| 27 | + onRefresh, |
24 | 28 | }) => {
|
25 |
| - // Format timestamp to date string |
26 |
| - const formatDate = (timestamp?: number): string => { |
27 |
| - if (!timestamp) return 'N/A'; |
28 |
| - const date = new Date(timestamp); |
29 |
| - return `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`; |
30 |
| - }; |
| 29 | + const [deployModalVisible, setDeployModalVisible] = useState(false); |
| 30 | + const [selectedDataSource, setSelectedDataSource] = useState<DataSource | null>(null); |
31 | 31 |
|
32 |
| - // Get icon for data source type |
33 |
| - const getDataSourceTypeIcon = (type: string) => { |
34 |
| - return <DatabaseOutlined />; |
| 32 | + const handleDeploy = (dataSource: DataSource) => { |
| 33 | + setSelectedDataSource(dataSource); |
| 34 | + setDeployModalVisible(true); |
35 | 35 | };
|
36 | 36 |
|
37 |
| - // Get color for data source status |
38 |
| - const getStatusColor = (status: string) => { |
39 |
| - switch (status) { |
40 |
| - case 'NORMAL': |
41 |
| - return 'green'; |
42 |
| - case 'ERROR': |
43 |
| - return 'red'; |
44 |
| - case 'WARNING': |
45 |
| - return 'orange'; |
46 |
| - default: |
47 |
| - return 'default'; |
48 |
| - } |
49 |
| - }; |
50 |
| - |
51 |
| - // Table columns definition |
52 |
| - const columns = [ |
| 37 | + const columns: ColumnsType<DataSource> = [ |
53 | 38 | {
|
54 | 39 | title: 'Name',
|
| 40 | + dataIndex: 'name', |
55 | 41 | key: 'name',
|
56 |
| - render: (record: DataSourceWithMeta) => ( |
57 |
| - <div style={{ display: 'flex', alignItems: 'center' }}> |
58 |
| - {getDataSourceTypeIcon(record.datasource.type)} |
59 |
| - <span style={{ marginLeft: 8 }}>{record.datasource.name}</span> |
60 |
| - </div> |
61 |
| - ), |
| 42 | + sorter: (a, b) => a.name.localeCompare(b.name), |
62 | 43 | },
|
63 | 44 | {
|
64 | 45 | title: 'Type',
|
65 |
| - dataIndex: ['datasource', 'type'], |
| 46 | + dataIndex: 'type', |
66 | 47 | key: 'type',
|
67 |
| - render: (type: string) => ( |
68 |
| - <Tag color="blue">{type.toUpperCase()}</Tag> |
69 |
| - ), |
| 48 | + filters: Array.from(new Set(dataSources.map(ds => ds.type))) |
| 49 | + .map(type => ({ text: type, value: type })), |
| 50 | + onFilter: (value, record) => record.type === value, |
70 | 51 | },
|
71 | 52 | {
|
72 |
| - title: 'Created By', |
73 |
| - dataIndex: 'creatorName', |
74 |
| - key: 'creatorName', |
75 |
| - render: (creatorName: string) => ( |
76 |
| - <div style={{ display: 'flex', alignItems: 'center' }}> |
77 |
| - <UserOutlined style={{ marginRight: 8 }} /> |
78 |
| - <span>{creatorName}</span> |
79 |
| - </div> |
| 53 | + title: 'Status', |
| 54 | + dataIndex: 'datasourceStatus', |
| 55 | + key: 'status', |
| 56 | + render: (status: string) => ( |
| 57 | + <Tag color={status === 'ACTIVE' ? 'green' : 'orange'}> |
| 58 | + {status} |
| 59 | + </Tag> |
80 | 60 | ),
|
| 61 | + filters: Array.from(new Set(dataSources.map(ds => ds.datasourceStatus))) |
| 62 | + .map(status => ({ text: status, value: status })), |
| 63 | + onFilter: (value, record) => record.datasourceStatus === value, |
81 | 64 | },
|
82 | 65 | {
|
83 |
| - title: 'Created', |
84 |
| - key: 'createTime', |
85 |
| - render: (record: DataSourceWithMeta) => formatDate(record.datasource.createTime), |
| 66 | + title: 'DB Name', |
| 67 | + dataIndex: ['datasourceConfig', 'database'], |
| 68 | + key: 'database', |
| 69 | + render: (database: string | null) => database || 'N/A', |
86 | 70 | },
|
87 | 71 | {
|
88 |
| - title: 'Status', |
89 |
| - key: 'status', |
90 |
| - render: (record: DataSourceWithMeta) => ( |
91 |
| - <Tag color={getStatusColor(record.datasource.datasourceStatus)}> |
92 |
| - {record.datasource.datasourceStatus} |
93 |
| - </Tag> |
| 72 | + title: 'Managed', |
| 73 | + dataIndex: 'managed', |
| 74 | + key: 'managed', |
| 75 | + render: (managed: boolean, record: DataSource) => ( |
| 76 | + <Space> |
| 77 | + <Switch |
| 78 | + checked={managed} |
| 79 | + onChange={(checked) => onToggleManaged(record, checked)} |
| 80 | + /> |
| 81 | + <Tag color={managed ? 'blue' : 'gray'}> |
| 82 | + {managed ? 'Managed' : 'Unmanaged'} |
| 83 | + </Tag> |
| 84 | + </Space> |
94 | 85 | ),
|
| 86 | + filters: [ |
| 87 | + { text: 'Managed', value: true }, |
| 88 | + { text: 'Unmanaged', value: false }, |
| 89 | + ], |
| 90 | + onFilter: (value, record) => record.managed === Boolean(value), |
95 | 91 | },
|
96 | 92 | {
|
97 |
| - title: 'Edit Access', |
98 |
| - dataIndex: 'edit', |
99 |
| - key: 'edit', |
100 |
| - render: (edit: boolean) => ( |
101 |
| - <Tooltip title={edit ? 'You can edit this data source' : 'You cannot edit this data source'}> |
102 |
| - {edit ? |
103 |
| - <CheckCircleOutlined style={{ color: '#52c41a' }} /> : |
104 |
| - <CloseCircleOutlined style={{ color: '#f5222d' }} /> |
105 |
| - } |
106 |
| - </Tooltip> |
| 93 | + title: 'Actions', |
| 94 | + key: 'actions', |
| 95 | + render: (_, record: DataSource) => ( |
| 96 | + <Space> |
| 97 | + <Tooltip title="Deploy to another environment"> |
| 98 | + <Button |
| 99 | + icon={<CloudUploadOutlined />} |
| 100 | + onClick={() => handleDeploy(record)} |
| 101 | + type="primary" |
| 102 | + ghost |
| 103 | + > |
| 104 | + Deploy |
| 105 | + </Button> |
| 106 | + </Tooltip> |
| 107 | + </Space> |
107 | 108 | ),
|
108 | 109 | },
|
109 | 110 | ];
|
110 | 111 |
|
111 |
| - // If loading, show spinner |
112 |
| - if (loading) { |
113 |
| - return ( |
114 |
| - <div style={{ display: 'flex', justifyContent: 'center', padding: '20px' }}> |
115 |
| - <Spin tip="Loading data sources..." /> |
116 |
| - </div> |
117 |
| - ); |
118 |
| - } |
119 |
| - |
120 |
| - // If no data sources or error, show empty state |
121 |
| - if (!dataSources || dataSources.length === 0 || error) { |
122 |
| - return ( |
123 |
| - <Empty |
124 |
| - description={error || "No data sources found"} |
125 |
| - image={Empty.PRESENTED_IMAGE_SIMPLE} |
126 |
| - /> |
127 |
| - ); |
128 |
| - } |
129 |
| - |
130 | 112 | return (
|
131 |
| - <Table |
132 |
| - columns={columns} |
133 |
| - dataSource={dataSources} |
134 |
| - rowKey={(record) => record.datasource.id} |
135 |
| - pagination={{ pageSize: 10 }} |
136 |
| - size="middle" |
137 |
| - /> |
| 113 | + <> |
| 114 | + <Table |
| 115 | + dataSource={dataSources} |
| 116 | + columns={columns} |
| 117 | + rowKey="id" |
| 118 | + loading={loading} |
| 119 | + pagination={{ pageSize: 10 }} |
| 120 | + locale={{ |
| 121 | + emptyText: error ? error : 'No data sources found', |
| 122 | + }} |
| 123 | + /> |
| 124 | + |
| 125 | + <DeployDataSourceModal |
| 126 | + visible={deployModalVisible} |
| 127 | + dataSource={selectedDataSource} |
| 128 | + currentEnvironment={environment} |
| 129 | + onClose={() => setDeployModalVisible(false)} |
| 130 | + onSuccess={onRefresh} |
| 131 | + /> |
| 132 | + </> |
138 | 133 | );
|
139 | 134 | };
|
140 | 135 |
|
|
0 commit comments