Skip to content

Commit f05db47

Browse files
Aleksy Lisowskipiotrczarnas
Aleksy Lisowski
authored andcommitted
Merged PR 2671: global_tables_columns_spinner_sorting_margins_fonts
- added margin and disabled sorting on table and column list - added spinner if results are loading - spinner - Moved TableListView to 1 component - Using 1 ColumnListView component - refresh button - decreased size of dimesion overview - aligned spinner correctly - not displaying actions if data_quality_status is undefined - decreased size of font - tooltip
2 parents 00bef18 + 1270e0e commit f05db47

File tree

16 files changed

+379
-1037
lines changed

16 files changed

+379
-1037
lines changed

dqops/src/main/frontend/src/components/ColumnList/ColumnListItem.tsx

+58-32
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Tooltip } from '@material-tailwind/react';
12
import React from 'react';
23
import { useDispatch } from 'react-redux';
34
import { useHistory } from 'react-router-dom';
@@ -136,21 +137,21 @@ export default function SchemaTableItem({
136137
};
137138

138139
return (
139-
<tr className="text-sm my-3">
140+
<tr className="text-xs my-3">
140141
{(!checkTypes || !connection || !schema) && (
141142
<>
142143
{!connection && (
143144
<td className="content-start pt-2 max-w-72 min-w-50 whitespace-normal break-all">
144145
<Button
145-
className="ml-4 !px-0 underline cursor-pointer text-sm py-0 text-start "
146+
className="ml-4 !px-0 underline cursor-pointer text-xs py-0 text-start "
146147
label={item.connection_name}
147148
onClick={() => goToConnection(item)}
148149
/>
149150
</td>
150151
)}
151152
<td className="content-start pt-2 max-w-72 min-w-50 whitespace-normal break-all">
152153
<Button
153-
className="ml-4 !px-0 underline cursor-pointer text-sm py-0 text-start"
154+
className="ml-4 !px-0 underline cursor-pointer text-xs py-0 text-start"
154155
label={item.schema}
155156
onClick={() => goToSchema(item)}
156157
/>
@@ -159,55 +160,80 @@ export default function SchemaTableItem({
159160
)}
160161
<td className="content-start pt-2 max-w-72 min-w-50 whitespace-normal break-all">
161162
<Button
162-
className="ml-4 !px-0 underline cursor-pointer text-sm py-0 text-start"
163+
className="ml-4 !px-0 underline cursor-pointer text-xs py-0 text-start"
163164
label={item.table?.table_name}
164165
onClick={() => goToTable(item, checkTypes)}
165166
/>
166167
</td>
167168
<td className="content-start pt-2 max-w-72 min-w-50 whitespace-normal break-all">
168169
<Button
169-
className="ml-4 !px-0 underline cursor-pointer text-sm py-0 text-start"
170+
className="ml-4 !px-0 underline cursor-pointer text-xs py-0 text-start"
170171
label={item.column_name}
171172
onClick={() => goToColumn(item, checkTypes)}
172173
/>
173174
</td>{' '}
174-
<td className="px-4 text-sm content-start pt-2">
175+
<td className="px-4 text-xs content-start pt-2">
175176
{prepareString(item.type_snapshot?.column_type, 15)}
176177
</td>
177-
<td className="px-4 text-sm content-start pt-2">
178+
<td className="px-4 text-xs content-start pt-2">
178179
{getLabelsOverview(item?.labels ?? [])}
179180
</td>
180181
{item?.data_quality_status?.dimensions ? (
181-
<SchemaTableItemDimensions item={item} dimensionKeys={dimensionKeys} />
182+
<>
183+
<SchemaTableItemDimensions
184+
item={item}
185+
dimensionKeys={dimensionKeys}
186+
/>
187+
<td>
188+
<div className="flex gap-x-2 items-center justify-center mx-3">
189+
<Tooltip
190+
content={'Add a new connection and manage its settings'}
191+
className="max-w-80 py-4 px-4 bg-gray-800 delay-700"
192+
>
193+
<SvgIcon
194+
name="data_sources"
195+
className="w-5 h-5 cursor-pointer"
196+
onClick={() => goToTable(item, CheckTypes.SOURCES)}
197+
/>
198+
</Tooltip>
199+
<Tooltip
200+
content={'Profiling'}
201+
className="max-w-80 py-4 px-4 bg-gray-800 delay-700"
202+
>
203+
<SvgIcon
204+
name="profiling"
205+
className="w-5 h-5 cursor-pointer"
206+
onClick={() => goToTable(item, CheckTypes.PROFILING)}
207+
/>
208+
</Tooltip>
209+
<Tooltip
210+
content={'Monitoring Checks'}
211+
className="max-w-80 py-4 px-4 bg-gray-800 delay-700"
212+
>
213+
<SvgIcon
214+
name="monitoring_checks"
215+
className="w-5 h-5 cursor-pointer"
216+
onClick={() => goToTable(item, CheckTypes.MONITORING)}
217+
/>
218+
</Tooltip>
219+
<Tooltip
220+
content={'Partitioned Checks'}
221+
className="max-w-80 py-4 px-4 bg-gray-800 delay-700"
222+
>
223+
<SvgIcon
224+
name="partitioned_checks"
225+
className="w-5 h-5 cursor-pointer"
226+
onClick={() => goToTable(item, CheckTypes.PARTITIONED)}
227+
/>
228+
</Tooltip>
229+
</div>
230+
</td>
231+
</>
182232
) : (
183233
<td className="content-start pt-2">
184234
<SvgIcon name="hourglass" className="w-4 h-4" />
185235
</td>
186236
)}
187-
<td>
188-
<div className="flex gap-x-2 items-center justify-center mr-3">
189-
<SvgIcon
190-
name="data_sources"
191-
className="w-5 h-5"
192-
onClick={() => goToColumn(item, CheckTypes.SOURCES)}
193-
/>
194-
<SvgIcon
195-
name="profiling"
196-
className="w-5 h-5"
197-
onClick={() => goToColumn(item, CheckTypes.PROFILING)}
198-
/>
199-
<SvgIcon
200-
name="monitoring_checks"
201-
className="w-5 h-5"
202-
onClick={() => goToColumn(item, CheckTypes.MONITORING)}
203-
/>
204-
<SvgIcon
205-
name="partitioned_checks"
206-
className="w-5 h-5"
207-
onClick={() => goToColumn(item, CheckTypes.PARTITIONED)}
208-
/>
209-
</div>
210-
</td>
211237
</tr>
212238
);
213239
}

dqops/src/main/frontend/src/components/ColumnList/index.tsx

+43-95
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,14 @@
11
import clsx from 'clsx';
2-
import React, { useState } from 'react';
2+
import React from 'react';
33
import { ColumnListModel, LabelModel } from '../../api';
44
import { CheckTypes } from '../../shared/routes';
55
import { useDecodedParams } from '../../utils';
66
import SectionWrapper from '../Dashboard/SectionWrapper';
77
import { Pagination } from '../Pagination';
8-
import SvgIcon from '../SvgIcon';
9-
import ColumnListItem from './ColumnListItem';
10-
function getValueForKey<T>(obj: T, key: string): string | undefined {
11-
const keys = key.split('.');
12-
let value: any = obj;
13-
14-
for (const k of keys) {
15-
value = value?.[k];
16-
if (value === undefined) {
17-
break;
18-
}
19-
}
208

21-
return value?.toString();
22-
}
9+
import Loader from '../Loader';
10+
import ColumnListItem from './ColumnListItem';
11+
import renderItem from './renderItem';
2312

2413
type TButtonTabs = {
2514
label: string;
@@ -51,27 +40,27 @@ const headeritems: TButtonTabs[] = [
5140
label: 'Labels',
5241
value: 'labels'
5342
},
54-
{ label: 'Data Quality KPI', value: 'data-quality-kpi', sortable: false }
43+
{ label: 'Data Quality KPI', value: 'data-quality-kpi' }
5544
];
5645

5746
type TColumnListProps = {
5847
columns: TColumnWithSchema[];
59-
setColumns: any;
6048
filters: any;
6149
onChangeFilters: (filters: any) => void;
6250
labels: TLabel[];
6351
onChangeLabels: (index: number) => void;
52+
loading: boolean;
6453
};
6554

6655
type TLabel = LabelModel & { clicked: boolean };
6756

6857
function ColumnList({
6958
columns,
70-
setColumns,
7159
filters,
7260
onChangeFilters,
7361
labels,
74-
onChangeLabels
62+
onChangeLabels,
63+
loading
7564
}: TColumnListProps) {
7665
const {
7766
checkTypes,
@@ -82,48 +71,6 @@ function ColumnList({
8271
connection: string;
8372
schema: string;
8473
} = useDecodedParams();
85-
const [sortingDir, setSortingDir] = useState<'asc' | 'desc'>('asc');
86-
87-
const renderItem = (
88-
label: string,
89-
key: string,
90-
sortable?: boolean,
91-
toRotate?: boolean
92-
) => {
93-
const sortTables = (key: string): void => {
94-
setColumns((prev: any) => {
95-
const array = [...prev];
96-
array.sort((a, b) => {
97-
const valueA = getValueForKey(a, key);
98-
const valueB = getValueForKey(b, key);
99-
100-
return sortingDir === 'asc'
101-
? (valueA || '').localeCompare(valueB || '')
102-
: (valueB || '').localeCompare(valueA || '');
103-
});
104-
105-
setSortingDir((prev) => (prev === 'asc' ? 'desc' : 'asc'));
106-
return array;
107-
});
108-
};
109-
return (
110-
<th
111-
className="px-4 cursor-pointer"
112-
onClick={() => sortable !== false && sortTables(key)}
113-
key={key}
114-
>
115-
<div className="flex text-sm items-center relative">
116-
<span className={clsx(toRotate ? ' z-9' : '')}>{label}</span>
117-
{sortable !== false && (
118-
<div className="flex flex-col items-center">
119-
<SvgIcon name="chevron-up" className="w-3 h-2" />
120-
<SvgIcon name="chevron-down" className="w-3 h-2" />
121-
</div>
122-
)}
123-
</div>
124-
</th>
125-
);
126-
};
12774

12875
const getDimensionKey = () => {
12976
const uniqueDimensions: string[] = [];
@@ -158,20 +105,17 @@ function ColumnList({
158105
...basicDimensionTypes.map((x) => ({
159106
label: x,
160107
value: x,
161-
sortable: false,
162108
toRotate: true
163109
})),
164110

165111
...getDimensionKey().map((x) => ({
166112
label: x,
167113
value: x,
168-
sortable: false,
169114
toRotate: true
170115
})),
171116
{
172117
label: 'Actions',
173-
value: 'actions',
174-
sortable: false
118+
value: 'actions'
175119
}
176120
];
177121

@@ -191,7 +135,7 @@ function ColumnList({
191135
<div className="w-[280px]">
192136
<SectionWrapper
193137
title="Filter by labels"
194-
className="text-sm w-[250px] mx-4 mb-4 mt-6 "
138+
className="text-xs w-[250px] mx-4 mb-4 mt-6 "
195139
>
196140
{labels.map((label, index) => (
197141
<div
@@ -212,48 +156,52 @@ function ColumnList({
212156
</div>
213157

214158
<div className="overflow-x-auto">
215-
<table>
159+
<table className="absolute top-25">
216160
<thead>
217161
<tr className="mb-2">
218162
{headerItems.map(
219163
(item) =>
220164
item?.label &&
221165
item.value &&
222-
renderItem(
223-
item.label,
224-
item.value,
225-
item.sortable,
226-
item.toRotate
227-
)
166+
renderItem(item.label, item.value, item.toRotate)
228167
)}
229168
</tr>
230169
</thead>
231-
<tbody>
232-
{columns.map((item, index) => (
233-
<ColumnListItem
234-
key={index}
235-
item={item}
236-
dimensionKeys={getDimensionKey()}
170+
{loading ? (
171+
<div className="ml-5 flex items-start justify-normal">
172+
<Loader
173+
isFull={false}
174+
className="w-8 h-8 fill-green-700 mt-5"
237175
/>
238-
))}
239-
</tbody>
176+
</div>
177+
) : (
178+
<tbody>
179+
{columns.map((item, index) => (
180+
<ColumnListItem
181+
key={index}
182+
item={item}
183+
dimensionKeys={getDimensionKey()}
184+
/>
185+
))}
186+
</tbody>
187+
)}
188+
<div className="px-4 my-5 pb-6 flex justify-end">
189+
<Pagination
190+
page={filters.page || 1}
191+
pageSize={filters.pageSize || 50}
192+
isEnd={isEnd}
193+
totalPages={10}
194+
onChange={(page, pageSize) =>
195+
onChangeFilters({
196+
page,
197+
pageSize
198+
})
199+
}
200+
/>
201+
</div>
240202
</table>
241203
</div>
242204
</div>
243-
<div className="px-4 my-5">
244-
<Pagination
245-
page={filters.page || 1}
246-
pageSize={filters.pageSize || 50}
247-
isEnd={isEnd}
248-
totalPages={10}
249-
onChange={(page, pageSize) =>
250-
onChangeFilters({
251-
page,
252-
pageSize
253-
})
254-
}
255-
/>
256-
</div>
257205
</div>
258206
);
259207
}

0 commit comments

Comments
 (0)