Skip to content

feat: Add clickable rows to table detail page and new expand/collapse arrow icons #1897

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions frontend/amundsen_application/static/.betterer.results
Original file line number Diff line number Diff line change
Expand Up @@ -614,14 +614,8 @@ exports[`eslint`] = {
[168, 15, 20, "Script URL is a form of eval.", "3959800777"],
[189, 16, 160, "A control must be associated with a text label.", "1834626670"]
],
"js/pages/TableDetailPage/RequestDescriptionText/index.spec.tsx:2570104867": [
[7, 7, 11, "\'globalState\' is defined but never used.", "1130616505"],
[14, 0, 50, "\`./constants\` import should occur before import of \`.\`", "1670547063"],
[45, 14, 5, "\'props\' is assigned a value but never used.", "187023499"]
],
"js/pages/TableDetailPage/RequestDescriptionText/index.tsx:1276941631": [
[29, 4, 39, "Must use destructuring props assignment", "4072624518"],
[38, 13, 20, "Script URL is a form of eval.", "3373049033"]
"js/pages/TableDetailPage/RequestDescriptionText/index.tsx:1601553334": [
[39, 11, 20, "Script URL is a form of eval.", "3373049033"]
],
"js/pages/TableDetailPage/RequestMetadataForm/index.spec.tsx:1512093594": [
[17, 0, 338, "\`./constants\` import should occur before import of \`.\`", "263963311"],
Expand Down Expand Up @@ -652,7 +646,7 @@ exports[`eslint`] = {
"js/pages/TableDetailPage/WatermarkLabel/index.tsx:2189911402": [
[29, 22, 21, "Must use destructuring props assignment", "587844958"]
],
"js/pages/TableDetailPage/index.tsx:105919838": [
"js/pages/TableDetailPage/index.tsx:1880896433": [
[161, 2, 20, "key should be placed after componentDidUpdate", "3916788587"],
[208, 6, 13, "Do not use setState in componentDidUpdate", "57229240"]
],
Expand Down
4 changes: 4 additions & 0 deletions frontend/amundsen_application/static/css/_layouts.scss
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ $close-btn-size: 24px;
margin-top: $aside-separation-space;
position: relative;
}

.editable-text {
font-size: 16px;
}
}

> .main-content-panel {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0

import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';

import { IconSizes } from 'interfaces';
import { IconProps } from './types';
import { DEFAULT_FILL_COLOR } from './constants';

export const DownTriangleIcon: React.FC<IconProps> = ({
size = IconSizes.REGULAR,
fill = DEFAULT_FILL_COLOR,
}: IconProps) => {
const id = `down_triangle_${uuidv4()}`;

return (
<svg
width={size}
height={size}
id={id}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.1783 19.569C11.3643 19.839 11.6723 20 12.0003 20C12.3283 20 12.6363 19.839 12.8223 19.569L21.8223 6.569C22.0343 6.263 22.0583 5.865 21.8853 5.536C21.7133 5.207 21.3723 5 21.0003 5H3.0003C2.6283 5 2.2873 5.207 2.1143 5.536C1.9413 5.865 1.9663 6.263 2.1783 6.569L11.1783 19.569Z"
fill={fill}
/>
</svg>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0

import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';

import { IconSizes } from 'interfaces';
import { IconProps } from './types';
import { DEFAULT_FILL_COLOR } from './constants';

export const RightTriangleIcon: React.FC<IconProps> = ({
size = IconSizes.REGULAR,
fill = DEFAULT_FILL_COLOR,
}: IconProps) => {
const id = `right_triangle_${uuidv4()}`;

return (
<svg
width={size}
height={size}
id={id}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M5.536 21.886C5.682 21.962 5.841 22 6 22C6.2 22 6.398 21.9401 6.569 21.8221L19.569 12.822C19.839 12.635 20 12.328 20 12C20 11.672 19.839 11.3651 19.569 11.1781L6.569 2.17805C6.264 1.96705 5.865 1.94205 5.536 2.11405C5.206 2.28705 5 2.62805 5 3.00005V21C5 21.372 5.206 21.713 5.536 21.886Z"
fill={fill}
/>
</svg>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ export * from './Chat';
export * from './TableIcon';
export * from './DoubleChevronUp';
export * from './DoubleChevronDown';
export * from './RightTriangleIcon';
export * from './DownTriangleIcon';
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as React from 'react';
import { mount } from 'enzyme';
import { mocked } from 'ts-jest/utils';

import { DoubleChevronDown, DoubleChevronUp } from 'components/SVGIcons';
import { RightTriangleIcon, DownTriangleIcon } from 'components/SVGIcons';
import TestDataBuilder from './testDataBuilder';
import Table, { TableProps } from '.';

Expand Down Expand Up @@ -629,6 +629,74 @@ describe('Table', () => {
});
});

describe('when onRowClick is passed', () => {
const {
columns,
data,
} = new TestDataBuilder().withFourColumns().build();

describe('when clicking on row', () => {
it('calls the onRowClick handler', () => {
const onRowClickSpy = jest.fn();
const { wrapper } = setup({
data,
columns,
options: {
onRowClick: onRowClickSpy,
},
});
const expected = 1;

wrapper.find('.ams-table-row').at(0).simulate('click');

const actual = onRowClickSpy.mock.calls.length;

expect(actual).toEqual(expected);
});

it('calls the onRowClick handler with the row values and the index', () => {
const onRowClickSpy = jest.fn();
const { wrapper } = setup({
data,
columns,
options: {
onRowClick: onRowClickSpy,
},
});
const expected = [
data[0],
'database://cluster.schema/table/rowName',
];

wrapper.find('.ams-table-row').at(0).simulate('click');

const [actual] = onRowClickSpy.mock.calls;
expect(actual).toEqual(expected);
});
});

describe('when clicking on multiple rows', () => {
it('calls the onRowClick handler several times', () => {
const onRowClickSpy = jest.fn();
const { wrapper } = setup({
data,
columns,
options: {
onRowClick: onRowClickSpy,
},
});
const expected = 2;

wrapper.find('.ams-table-row').at(0).simulate('click');
wrapper.find('.ams-table-row').at(1).simulate('click');

const actual = onRowClickSpy.mock.calls.length;

expect(actual).toEqual(expected);
});
});
});

describe('when emptyMessage is passed', () => {
const { columns, data } = dataBuilder.withEmptyData().build();
const TEST_EMPTY_MESSAGE = 'Test Empty Message';
Expand Down Expand Up @@ -830,7 +898,7 @@ describe('Table', () => {
.find(
'.ams-table-header .ams-table-heading-cell .ams-table-expanding-button'
)
.find(DoubleChevronUp).length;
.find(DownTriangleIcon).length;

expect(actual).toEqual(expected);
});
Expand All @@ -852,7 +920,7 @@ describe('Table', () => {
.find(
'.ams-table-header .ams-table-heading-cell .ams-table-expanding-button'
)
.find(DoubleChevronUp).length;
.find(DownTriangleIcon).length;

expect(actual).toEqual(expected);
});
Expand All @@ -874,7 +942,7 @@ describe('Table', () => {
.find(
'.ams-table-header .ams-table-heading-cell .ams-table-expanding-button'
)
.find(DoubleChevronDown).length;
.find(RightTriangleIcon).length;

expect(actual).toEqual(expected);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,11 @@

import * as React from 'react';

import { FormattedDataType } from 'interfaces/ColumnList';
import { ContentType, FormattedDataType } from 'interfaces/ColumnList';
import { IconSizes } from 'interfaces/Enums';

import ShimmeringResourceLoader from '../ShimmeringResourceLoader';
import {
UpIcon,
DownIcon,
DoubleChevronUp,
DoubleChevronDown,
} from '../SVGIcons';
import { RightTriangleIcon, DownTriangleIcon } from '../SVGIcons';

import {
ARRAY_KIND,
Expand Down Expand Up @@ -70,6 +66,8 @@ export interface TableOptions {
onExpand?: (rowValues: any, key: string) => void;
/** Callback when a row is collapsed */
onCollapse?: (rowValues: any, key: string) => void;
/** Callback when a row is clicked */
onRowClick?: (rowValues: any, index: string) => void;
/** Optional empty table message to be shown */
emptyMessage?: string;
/** Row key of the currently seleected row */
Expand Down Expand Up @@ -104,6 +102,7 @@ export interface TableRowProps {
rowStyles: { height: string };
onExpand?: (rowValues: any, key: string) => void;
onCollapse?: (rowValues: any, key: string) => void;
onRowClick?: (rowValues: any, key: string) => void;
expandRowRef?: React.RefObject<HTMLTableRowElement>;
expandedRows: RowKey[];
setExpandedRows: (key) => void;
Expand All @@ -128,6 +127,7 @@ type TableRowDetails = {
rowStyles: { height: string };
onExpand?: (rowValues: any, key: string) => void;
onCollapse?: (rowValues: any, key: string) => void;
onRowClick?: (rowValues: any, key: string) => void;
expandRowRef?: React.RefObject<HTMLTableRowElement>;
expandedRows: RowKey[];
setExpandedRows: (keys: string[]) => void;
Expand Down Expand Up @@ -490,14 +490,14 @@ const ExpandCollapseAllButton: React.FC<ExpandCollapseAllButtonProps> = ({
{hasRowsToExpand && hasRowsToExpand() && (
<button
type="button"
className="ams-table-expanding-button"
className="btn ams-table-expanding-button is-expand-collapse-all"
onClick={toggleExpandingRows}
>
<span className="sr-only">{EXPAND_ROW_TEXT}</span>
{shouldExpandAllRows || shouldExpandAllRows === undefined ? (
<DoubleChevronUp />
<DownTriangleIcon size={IconSizes.SMALL} />
) : (
<DoubleChevronDown />
<RightTriangleIcon size={IconSizes.SMALL} />
)}
</button>
)}
Expand All @@ -512,7 +512,6 @@ type ExpandingButtonProps = {
onClick: (index) => void;
onExpand?: (rowValues: any, key: string) => void;
onCollapse?: (rowValues: any, key: string) => void;
isSelectedRow: boolean;
nestedLevel: number;
};
const ExpandingButton: React.FC<ExpandingButtonProps> = ({
Expand All @@ -522,7 +521,6 @@ const ExpandingButton: React.FC<ExpandingButtonProps> = ({
onCollapse,
rowValues,
expandedRows,
isSelectedRow,
nestedLevel,
}: ExpandingButtonProps) => {
const isExpanded = expandedRows.includes(rowKey);
Expand All @@ -538,10 +536,10 @@ const ExpandingButton: React.FC<ExpandingButtonProps> = ({
<button
key={rowKey}
type="button"
className={`btn ams-table-expanding-button ${
rowValues.isNestedColumn ? 'is-nested-column-row' : ''
} ${isSelectedRow ? 'is-selected-row' : ''}`}
onClick={() => {
className="btn ams-table-expanding-button"
onClick={(event) => {
event.stopPropagation();

const newExpandedRows = isExpanded
? expandedRows.filter((k) => k !== rowKey)
: [...expandedRows, rowKey];
Expand All @@ -557,7 +555,11 @@ const ExpandingButton: React.FC<ExpandingButtonProps> = ({
}}
>
<span className="sr-only">{EXPAND_ROW_TEXT}</span>
{isExpanded ? <UpIcon /> : <DownIcon />}
{isExpanded ? (
<DownTriangleIcon size={IconSizes.SMALL} />
) : (
<RightTriangleIcon size={IconSizes.SMALL} />
)}
</button>
</span>
);
Expand All @@ -571,6 +573,7 @@ const TableRow: React.FC<TableRowProps> = ({
rowStyles,
onExpand,
onCollapse,
onRowClick,
expandRowRef,
expandedRows,
setExpandedRows,
Expand All @@ -585,20 +588,31 @@ const TableRow: React.FC<TableRowProps> = ({
onCollapse={onCollapse}
rowValues={rowValues}
onClick={setExpandedRows}
isSelectedRow={currentSelectedKey === columnKey}
nestedLevel={nestedLevel}
/>
);
const handleRowClick = () => {
onRowClick?.(rowValues, columnKey);
};
const frontendParsedNestedLevel = (rowValues.content as ContentType)
?.nestedLevel;
const isFrontendParsedNestedColumn =
frontendParsedNestedLevel !== undefined && frontendParsedNestedLevel > 0;

return (
<React.Fragment key={columnKey}>
<tr
className={`ams-table-row ${
rowValues.isNestedColumn ? 'is-nested-column-row' : ''
} ${currentSelectedKey === columnKey ? 'is-selected-row' : ''}`}
} ${currentSelectedKey === columnKey ? 'is-selected-row' : ''} ${
onRowClick && !isFrontendParsedNestedColumn
? 'is-interactive-row'
: ''
}`}
key={columnKey}
style={rowStyles}
ref={expandRowRef}
onClick={!isFrontendParsedNestedColumn ? handleRowClick : undefined}
>
<>
{Object.entries(rowValues)
Expand Down Expand Up @@ -671,6 +685,7 @@ const getTableRows = (tableRowDetails: TableRowDetails) => {
rowStyles,
onExpand,
onCollapse,
onRowClick,
expandRowRef,
expandedRows,
setExpandedRows,
Expand All @@ -694,6 +709,7 @@ const getTableRows = (tableRowDetails: TableRowDetails) => {
rowStyles={rowStyles}
onExpand={onExpand}
onCollapse={onCollapse}
onRowClick={onRowClick}
expandRowRef={
item.key && item.key === preExpandPanelKey ? expandRowRef : undefined
}
Expand Down Expand Up @@ -811,6 +827,7 @@ const Table: React.FC<TableProps> = ({
emptyMessage,
onExpand,
onCollapse,
onRowClick,
preExpandPanelKey,
currentSelectedKey,
tableKey,
Expand Down Expand Up @@ -854,6 +871,7 @@ const Table: React.FC<TableProps> = ({
rowStyles,
onExpand,
onCollapse,
onRowClick,
expandRowRef,
expandedRows,
setExpandedRows,
Expand Down
Loading