Skip to content

Commit

Permalink
Merged PR 2671: global_tables_columns_spinner_sorting_margins_fonts
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
Aleksy Lisowski authored and piotrczarnas committed May 23, 2024
2 parents 00bef18 + 1270e0e commit f05db47
Show file tree
Hide file tree
Showing 16 changed files with 379 additions and 1,037 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Tooltip } from '@material-tailwind/react';
import React from 'react';
import { useDispatch } from 'react-redux';
import { useHistory } from 'react-router-dom';
Expand Down Expand Up @@ -136,21 +137,21 @@ export default function SchemaTableItem({
};

return (
<tr className="text-sm my-3">
<tr className="text-xs my-3">
{(!checkTypes || !connection || !schema) && (
<>
{!connection && (
<td className="content-start pt-2 max-w-72 min-w-50 whitespace-normal break-all">
<Button
className="ml-4 !px-0 underline cursor-pointer text-sm py-0 text-start "
className="ml-4 !px-0 underline cursor-pointer text-xs py-0 text-start "
label={item.connection_name}
onClick={() => goToConnection(item)}
/>
</td>
)}
<td className="content-start pt-2 max-w-72 min-w-50 whitespace-normal break-all">
<Button
className="ml-4 !px-0 underline cursor-pointer text-sm py-0 text-start"
className="ml-4 !px-0 underline cursor-pointer text-xs py-0 text-start"
label={item.schema}
onClick={() => goToSchema(item)}
/>
Expand All @@ -159,55 +160,80 @@ export default function SchemaTableItem({
)}
<td className="content-start pt-2 max-w-72 min-w-50 whitespace-normal break-all">
<Button
className="ml-4 !px-0 underline cursor-pointer text-sm py-0 text-start"
className="ml-4 !px-0 underline cursor-pointer text-xs py-0 text-start"
label={item.table?.table_name}
onClick={() => goToTable(item, checkTypes)}
/>
</td>
<td className="content-start pt-2 max-w-72 min-w-50 whitespace-normal break-all">
<Button
className="ml-4 !px-0 underline cursor-pointer text-sm py-0 text-start"
className="ml-4 !px-0 underline cursor-pointer text-xs py-0 text-start"
label={item.column_name}
onClick={() => goToColumn(item, checkTypes)}
/>
</td>{' '}
<td className="px-4 text-sm content-start pt-2">
<td className="px-4 text-xs content-start pt-2">
{prepareString(item.type_snapshot?.column_type, 15)}
</td>
<td className="px-4 text-sm content-start pt-2">
<td className="px-4 text-xs content-start pt-2">
{getLabelsOverview(item?.labels ?? [])}
</td>
{item?.data_quality_status?.dimensions ? (
<SchemaTableItemDimensions item={item} dimensionKeys={dimensionKeys} />
<>
<SchemaTableItemDimensions
item={item}
dimensionKeys={dimensionKeys}
/>
<td>
<div className="flex gap-x-2 items-center justify-center mx-3">
<Tooltip
content={'Add a new connection and manage its settings'}
className="max-w-80 py-4 px-4 bg-gray-800 delay-700"
>
<SvgIcon
name="data_sources"
className="w-5 h-5 cursor-pointer"
onClick={() => goToTable(item, CheckTypes.SOURCES)}
/>
</Tooltip>
<Tooltip
content={'Profiling'}
className="max-w-80 py-4 px-4 bg-gray-800 delay-700"
>
<SvgIcon
name="profiling"
className="w-5 h-5 cursor-pointer"
onClick={() => goToTable(item, CheckTypes.PROFILING)}
/>
</Tooltip>
<Tooltip
content={'Monitoring Checks'}
className="max-w-80 py-4 px-4 bg-gray-800 delay-700"
>
<SvgIcon
name="monitoring_checks"
className="w-5 h-5 cursor-pointer"
onClick={() => goToTable(item, CheckTypes.MONITORING)}
/>
</Tooltip>
<Tooltip
content={'Partitioned Checks'}
className="max-w-80 py-4 px-4 bg-gray-800 delay-700"
>
<SvgIcon
name="partitioned_checks"
className="w-5 h-5 cursor-pointer"
onClick={() => goToTable(item, CheckTypes.PARTITIONED)}
/>
</Tooltip>
</div>
</td>
</>
) : (
<td className="content-start pt-2">
<SvgIcon name="hourglass" className="w-4 h-4" />
</td>
)}
<td>
<div className="flex gap-x-2 items-center justify-center mr-3">
<SvgIcon
name="data_sources"
className="w-5 h-5"
onClick={() => goToColumn(item, CheckTypes.SOURCES)}
/>
<SvgIcon
name="profiling"
className="w-5 h-5"
onClick={() => goToColumn(item, CheckTypes.PROFILING)}
/>
<SvgIcon
name="monitoring_checks"
className="w-5 h-5"
onClick={() => goToColumn(item, CheckTypes.MONITORING)}
/>
<SvgIcon
name="partitioned_checks"
className="w-5 h-5"
onClick={() => goToColumn(item, CheckTypes.PARTITIONED)}
/>
</div>
</td>
</tr>
);
}
138 changes: 43 additions & 95 deletions dqops/src/main/frontend/src/components/ColumnList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
import clsx from 'clsx';
import React, { useState } from 'react';
import React from 'react';
import { ColumnListModel, LabelModel } from '../../api';
import { CheckTypes } from '../../shared/routes';
import { useDecodedParams } from '../../utils';
import SectionWrapper from '../Dashboard/SectionWrapper';
import { Pagination } from '../Pagination';
import SvgIcon from '../SvgIcon';
import ColumnListItem from './ColumnListItem';
function getValueForKey<T>(obj: T, key: string): string | undefined {
const keys = key.split('.');
let value: any = obj;

for (const k of keys) {
value = value?.[k];
if (value === undefined) {
break;
}
}

return value?.toString();
}
import Loader from '../Loader';
import ColumnListItem from './ColumnListItem';
import renderItem from './renderItem';

type TButtonTabs = {
label: string;
Expand Down Expand Up @@ -51,27 +40,27 @@ const headeritems: TButtonTabs[] = [
label: 'Labels',
value: 'labels'
},
{ label: 'Data Quality KPI', value: 'data-quality-kpi', sortable: false }
{ label: 'Data Quality KPI', value: 'data-quality-kpi' }
];

type TColumnListProps = {
columns: TColumnWithSchema[];
setColumns: any;
filters: any;
onChangeFilters: (filters: any) => void;
labels: TLabel[];
onChangeLabels: (index: number) => void;
loading: boolean;
};

type TLabel = LabelModel & { clicked: boolean };

function ColumnList({
columns,
setColumns,
filters,
onChangeFilters,
labels,
onChangeLabels
onChangeLabels,
loading
}: TColumnListProps) {
const {
checkTypes,
Expand All @@ -82,48 +71,6 @@ function ColumnList({
connection: string;
schema: string;
} = useDecodedParams();
const [sortingDir, setSortingDir] = useState<'asc' | 'desc'>('asc');

const renderItem = (
label: string,
key: string,
sortable?: boolean,
toRotate?: boolean
) => {
const sortTables = (key: string): void => {
setColumns((prev: any) => {
const array = [...prev];
array.sort((a, b) => {
const valueA = getValueForKey(a, key);
const valueB = getValueForKey(b, key);

return sortingDir === 'asc'
? (valueA || '').localeCompare(valueB || '')
: (valueB || '').localeCompare(valueA || '');
});

setSortingDir((prev) => (prev === 'asc' ? 'desc' : 'asc'));
return array;
});
};
return (
<th
className="px-4 cursor-pointer"
onClick={() => sortable !== false && sortTables(key)}
key={key}
>
<div className="flex text-sm items-center relative">
<span className={clsx(toRotate ? ' z-9' : '')}>{label}</span>
{sortable !== false && (
<div className="flex flex-col items-center">
<SvgIcon name="chevron-up" className="w-3 h-2" />
<SvgIcon name="chevron-down" className="w-3 h-2" />
</div>
)}
</div>
</th>
);
};

const getDimensionKey = () => {
const uniqueDimensions: string[] = [];
Expand Down Expand Up @@ -158,20 +105,17 @@ function ColumnList({
...basicDimensionTypes.map((x) => ({
label: x,
value: x,
sortable: false,
toRotate: true
})),

...getDimensionKey().map((x) => ({
label: x,
value: x,
sortable: false,
toRotate: true
})),
{
label: 'Actions',
value: 'actions',
sortable: false
value: 'actions'
}
];

Expand All @@ -191,7 +135,7 @@ function ColumnList({
<div className="w-[280px]">
<SectionWrapper
title="Filter by labels"
className="text-sm w-[250px] mx-4 mb-4 mt-6 "
className="text-xs w-[250px] mx-4 mb-4 mt-6 "
>
{labels.map((label, index) => (
<div
Expand All @@ -212,48 +156,52 @@ function ColumnList({
</div>

<div className="overflow-x-auto">
<table>
<table className="absolute top-25">
<thead>
<tr className="mb-2">
{headerItems.map(
(item) =>
item?.label &&
item.value &&
renderItem(
item.label,
item.value,
item.sortable,
item.toRotate
)
renderItem(item.label, item.value, item.toRotate)
)}
</tr>
</thead>
<tbody>
{columns.map((item, index) => (
<ColumnListItem
key={index}
item={item}
dimensionKeys={getDimensionKey()}
{loading ? (
<div className="ml-5 flex items-start justify-normal">
<Loader
isFull={false}
className="w-8 h-8 fill-green-700 mt-5"
/>
))}
</tbody>
</div>
) : (
<tbody>
{columns.map((item, index) => (
<ColumnListItem
key={index}
item={item}
dimensionKeys={getDimensionKey()}
/>
))}
</tbody>
)}
<div className="px-4 my-5 pb-6 flex justify-end">
<Pagination
page={filters.page || 1}
pageSize={filters.pageSize || 50}
isEnd={isEnd}
totalPages={10}
onChange={(page, pageSize) =>
onChangeFilters({
page,
pageSize
})
}
/>
</div>
</table>
</div>
</div>
<div className="px-4 my-5">
<Pagination
page={filters.page || 1}
pageSize={filters.pageSize || 50}
isEnd={isEnd}
totalPages={10}
onChange={(page, pageSize) =>
onChangeFilters({
page,
pageSize
})
}
/>
</div>
</div>
);
}
Expand Down
Loading

0 comments on commit f05db47

Please sign in to comment.