From 72764c21f19575d2dc7015332dffcc2a2628af37 Mon Sep 17 00:00:00 2001 From: Marcos Iglesias Date: Wed, 9 Sep 2020 15:52:50 -0700 Subject: [PATCH 01/10] Trying bootstrap dropdown for actions Signed-off-by: Marcos Iglesias --- .../js/components/common/Table/index.tsx | 4 +- .../components/common/Table/table.story.tsx | 11 +++++ .../common/Table/testDataBuilder.tsx | 44 +++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/amundsen_application/static/js/components/common/Table/index.tsx b/amundsen_application/static/js/components/common/Table/index.tsx index a60bd8a05..2620dc00b 100644 --- a/amundsen_application/static/js/components/common/Table/index.tsx +++ b/amundsen_application/static/js/components/common/Table/index.tsx @@ -13,7 +13,7 @@ export interface TableColumn { title: string; field: string; horAlign?: TextAlignmentValues; - component?: (value: any) => React.ReactNode; + component?: (value: any, index: number) => React.ReactNode; // className?: string; // width?: number; // sortable?: bool (false) @@ -116,7 +116,7 @@ const Table: React.FC = ({ // TODO: Improve the typing of this let cellContent: React.ReactNode | typeof value = value; if (columnInfo && columnInfo.component) { - cellContent = columnInfo.component(value); + cellContent = columnInfo.component(value, index); } return ( diff --git a/amundsen_application/static/js/components/common/Table/table.story.tsx b/amundsen_application/static/js/components/common/Table/table.story.tsx index a1ae350e7..1735cb79f 100644 --- a/amundsen_application/static/js/components/common/Table/table.story.tsx +++ b/amundsen_application/static/js/components/common/Table/table.story.tsx @@ -22,6 +22,10 @@ const { columns: multipleCustomColumns, data: multipleCustomComlumnsData, } = dataBuilder.withMultipleComponentsColumn().build(); +const { + columns: columnsWithAction, + data: dataWithAction, +} = dataBuilder.withActionCell().build(); const stories = storiesOf('Components/Table', module); @@ -56,5 +60,12 @@ stories.add('Table', () => ( options={{ rowHeight: 40 }} /> + + + )); diff --git a/amundsen_application/static/js/components/common/Table/testDataBuilder.tsx b/amundsen_application/static/js/components/common/Table/testDataBuilder.tsx index 5dd2ce05d..b75839bf6 100644 --- a/amundsen_application/static/js/components/common/Table/testDataBuilder.tsx +++ b/amundsen_application/static/js/components/common/Table/testDataBuilder.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import * as React from 'react'; +import { Dropdown, MenuItem } from 'react-bootstrap'; const defaultData = [ { name: 'rowName', type: 'rowType', value: 1 }, @@ -78,6 +79,49 @@ function TestDataBuilder(config = {}) { return new this.Klass(attr); }; + this.withActionCell = () => { + const attr = { + data: [ + { name: 'rowName', type: 'rowType', value: 'Action Text' }, + { name: 'rowName2', type: 'rowType2', value: 'Action Text' }, + { name: 'rowName3', type: 'rowType3', value: 'Action Text' }, + ], + columns: [ + { + title: 'Name', + field: 'name', + }, + { + title: 'Type', + field: 'type', + }, + { + title: 'Value', + field: 'value', + component: (value, index) => ( + + + More info + + + + console.log('index', index)}> + {value} + + + + ), + }, + ], + }; + + return new this.Klass(attr); + }; + this.withMultipleComponentsColumn = () => { const attr = { data: [ From b115cea8201bd8abb7ca1f6c4a283b158bc6ec1e Mon Sep 17 00:00:00 2001 From: Marcos Iglesias Date: Wed, 9 Sep 2020 17:28:13 -0700 Subject: [PATCH 02/10] Expandable row Signed-off-by: Marcos Iglesias --- .../js/components/common/Table/index.spec.tsx | 93 ++++++++++++++++ .../js/components/common/Table/index.tsx | 105 +++++++++++++----- .../components/common/Table/table.story.tsx | 16 +++ .../common/Table/testDataBuilder.tsx | 22 ++++ 4 files changed, 206 insertions(+), 30 deletions(-) diff --git a/amundsen_application/static/js/components/common/Table/index.spec.tsx b/amundsen_application/static/js/components/common/Table/index.spec.tsx index 5542bc640..b0705a733 100644 --- a/amundsen_application/static/js/components/common/Table/index.spec.tsx +++ b/amundsen_application/static/js/components/common/Table/index.spec.tsx @@ -477,6 +477,99 @@ describe('Table', () => { }); }); }); + + describe('when expandRow is passed', () => { + const { columns, data } = dataBuilder.withCollapsedRow().build(); + const expandRowComponent = (rowValue, index) => ( + + {index}:{rowValue.value} + + ); + + describe('table header', () => { + it('renders a table header', () => { + const { wrapper } = setup({ + data, + columns, + options: { + expandRow: expandRowComponent, + }, + }); + const expected = 1; + const actual = wrapper.find('.ams-table-header').length; + + expect(actual).toEqual(expected); + }); + + it('renders one cell more than columns length inside the header', () => { + const { wrapper } = setup({ + data, + columns, + options: { + expandRow: expandRowComponent, + }, + }); + const expected = columns.length + 1; + const actual = wrapper.find( + '.ams-table-header .ams-table-heading-cell' + ).length; + + expect(actual).toEqual(expected); + }); + }); + + describe('table body', () => { + it('renders the first column as a expansion cell', () => { + const { wrapper } = setup({ + data, + columns, + options: { + expandRow: expandRowComponent, + }, + }); + const expected = data.length; + const actual = wrapper.find( + '.ams-table-body .ams-table-expanding-cell' + ).length; + + expect(actual).toEqual(expected); + }); + + it('renders buttons for expansion', () => { + const { wrapper } = setup({ + data, + columns, + options: { + expandRow: expandRowComponent, + }, + }); + const expected = data.length; + const actual = wrapper.find( + '.ams-table-body .ams-table-expanding-button' + ).length; + + expect(actual).toEqual(expected); + }); + + describe('expanded row', () => { + it('renders it with multiple colspan', () => { + const { wrapper } = setup({ + data, + columns, + options: { + expandRow: expandRowComponent, + }, + }); + const expected = columns.length + 1; + const actual = wrapper + .find('.ams-table-body .ams-table-expanded-row .ams-table-cell') + .get(0).props.colSpan; + + expect(actual).toEqual(expected); + }); + }); + }); + }); }); }); diff --git a/amundsen_application/static/js/components/common/Table/index.tsx b/amundsen_application/static/js/components/common/Table/index.tsx index 2620dc00b..bbede5bb9 100644 --- a/amundsen_application/static/js/components/common/Table/index.tsx +++ b/amundsen_application/static/js/components/common/Table/index.tsx @@ -17,8 +17,6 @@ export interface TableColumn { // className?: string; // width?: number; // sortable?: bool (false) - // data?: () => React.ReactNode ((row,index) =>
{index}
) - // actions?: Action[] } export interface TableOptions { @@ -26,6 +24,7 @@ export interface TableOptions { isLoading?: boolean; numLoadingBlocks?: number; rowHeight?: number; + expandRow?: (rowValue: any, index: number) => React.ReactNode; } export interface TableProps { @@ -81,6 +80,28 @@ const ShimmeringBody: React.FC = ({ ); +type ExpandingCellProps = { + index: number; +}; +const ExpandingCell: React.FC = ({ + index, +}: ExpandingCellProps) => ( +
+); + const Table: React.FC = ({ data, columns, @@ -91,9 +112,11 @@ const Table: React.FC = ({ isLoading = false, numLoadingBlocks = DEFAULT_LOADING_ITEMS, rowHeight = DEFAULT_ROW_HEIGHT, + expandRow = null, } = options; const fields = columns.map(({ field }) => field); const rowStyles = { height: `${rowHeight}px` }; + const isExpandable: boolean = !!expandRow; let body: React.ReactNode = ( @@ -102,40 +125,62 @@ const Table: React.FC = ({ if (data.length) { body = data.map((item, index) => { return ( - - {Object.entries(item) - .filter(([key]) => fields.includes(key)) - .map(([key, value], index) => { - const columnInfo = columns.find(({ field }) => field === key); - const horAlign = columnInfo - ? columnInfo.horAlign || DEFAULT_TEXT_ALIGNMENT - : DEFAULT_TEXT_ALIGNMENT; - const cellStyle = { - textAlign: `${horAlign}` as TextAlignmentValues, - }; - // TODO: Improve the typing of this - let cellContent: React.ReactNode | typeof value = value; - if (columnInfo && columnInfo.component) { - cellContent = columnInfo.component(value, index); - } - - return ( - - ); - })} - + <> + + <> + {isExpandable ? : null} + {Object.entries(item) + .filter(([key]) => fields.includes(key)) + .map(([key, value], index) => { + const columnInfo = columns.find(({ field }) => field === key); + const horAlign = columnInfo + ? columnInfo.horAlign || DEFAULT_TEXT_ALIGNMENT + : DEFAULT_TEXT_ALIGNMENT; + const cellStyle = { + textAlign: `${horAlign}` as TextAlignmentValues, + }; + // TODO: Improve the typing of this + let cellContent: React.ReactNode | typeof value = value; + if (columnInfo && columnInfo.component) { + cellContent = columnInfo.component(value, index); + } + + return ( + + ); + })} + + + {isExpandable ? ( + + + + ) : null} + ); }); } let header: React.ReactNode = ( + {isExpandable && ( +
+ +
- {cellContent} -
+ {cellContent} +
+ {expandRow(item, index)} +
+ )} {columns.map(({ title, horAlign = DEFAULT_TEXT_ALIGNMENT }, index) => { const cellStyle = { textAlign: `${horAlign}` as TextAlignmentValues, diff --git a/amundsen_application/static/js/components/common/Table/table.story.tsx b/amundsen_application/static/js/components/common/Table/table.story.tsx index 1735cb79f..c776d472a 100644 --- a/amundsen_application/static/js/components/common/Table/table.story.tsx +++ b/amundsen_application/static/js/components/common/Table/table.story.tsx @@ -26,6 +26,15 @@ const { columns: columnsWithAction, data: dataWithAction, } = dataBuilder.withActionCell().build(); +const { + columns: columnsWithCollapsedRow, + data: dataWithCollapsedRow, +} = dataBuilder.withCollapsedRow().build(); +const expandRowComponent = (rowValue, index) => ( + + {index}:{rowValue.value} + +); const stories = storiesOf('Components/Table', module); @@ -67,5 +76,12 @@ stories.add('Table', () => ( options={{ rowHeight: 40 }} /> + + + )); diff --git a/amundsen_application/static/js/components/common/Table/testDataBuilder.tsx b/amundsen_application/static/js/components/common/Table/testDataBuilder.tsx index b75839bf6..b96a8eafd 100644 --- a/amundsen_application/static/js/components/common/Table/testDataBuilder.tsx +++ b/amundsen_application/static/js/components/common/Table/testDataBuilder.tsx @@ -56,6 +56,28 @@ function TestDataBuilder(config = {}) { return new this.Klass(attr); }; + this.withCollapsedRow = () => { + const attr = { + data: [ + { name: 'rowName', type: 'rowType', value: 1 }, + { name: 'rowName2', type: 'rowType2', value: 2 }, + { name: 'rowName3', type: 'rowType3', value: 3 }, + ], + columns: [ + { + title: 'Name', + field: 'name', + }, + { + title: 'Type', + field: 'type', + }, + ], + }; + + return new this.Klass(attr); + }; + this.withOneComponentColumn = () => { const attr = { data: [...this.config.data], From f19d2c899ea68f59b7d62a7503ab0eece01ff9f2 Mon Sep 17 00:00:00 2001 From: Marcos Iglesias Date: Thu, 10 Sep 2020 09:18:26 -0700 Subject: [PATCH 03/10] Hidden expanded rows by default Signed-off-by: Marcos Iglesias --- .../js/components/common/Table/index.spec.tsx | 16 ++++++++++++++++ .../static/js/components/common/Table/index.tsx | 11 ++++++++--- .../js/components/common/Table/styles.scss | 8 ++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/amundsen_application/static/js/components/common/Table/index.spec.tsx b/amundsen_application/static/js/components/common/Table/index.spec.tsx index b0705a733..bbade149a 100644 --- a/amundsen_application/static/js/components/common/Table/index.spec.tsx +++ b/amundsen_application/static/js/components/common/Table/index.spec.tsx @@ -567,6 +567,22 @@ describe('Table', () => { expect(actual).toEqual(expected); }); + + it('renders hidden by default', () => { + const { wrapper } = setup({ + data, + columns, + options: { + expandRow: expandRowComponent, + }, + }); + const expected = 0; + const actual = wrapper.find( + '.ams-table-body .ams-table-expanded-row.is-expanded' + ).length; + + expect(actual).toEqual(expected); + }); }); }); }); diff --git a/amundsen_application/static/js/components/common/Table/index.tsx b/amundsen_application/static/js/components/common/Table/index.tsx index bbede5bb9..f0e92aa51 100644 --- a/amundsen_application/static/js/components/common/Table/index.tsx +++ b/amundsen_application/static/js/components/common/Table/index.tsx @@ -102,6 +102,8 @@ const ExpandingCell: React.FC = ({ ); +type RowIndex = number; + const Table: React.FC = ({ data, columns, @@ -117,6 +119,7 @@ const Table: React.FC = ({ const fields = columns.map(({ field }) => field); const rowStyles = { height: `${rowHeight}px` }; const isExpandable: boolean = !!expandRow; + const [expandedRows, setExpandedRows] = React.useState([]); let body: React.ReactNode = ( @@ -125,7 +128,7 @@ const Table: React.FC = ({ if (data.length) { body = data.map((item, index) => { return ( - <> + = ({ {isExpandable ? ( ) : null} - + ); }); } diff --git a/amundsen_application/static/js/components/common/Table/styles.scss b/amundsen_application/static/js/components/common/Table/styles.scss index 8ab4d650a..28fbd9582 100644 --- a/amundsen_application/static/js/components/common/Table/styles.scss +++ b/amundsen_application/static/js/components/common/Table/styles.scss @@ -48,6 +48,14 @@ $shimmer-block-width: 40%; } } +.ams-table-expanded-row { + display: none; + + &.is-expanded { + display: block; + } +} + // Loading State .ams-table-heading-loading-cell { padding: $spacer-1; From 9d367d3ff49939ef10153493487bb71e3e468e73 Mon Sep 17 00:00:00 2001 From: Marcos Iglesias Date: Thu, 10 Sep 2020 09:45:55 -0700 Subject: [PATCH 04/10] Expand row functionality, missing arrows Signed-off-by: Marcos Iglesias --- .../js/components/common/Table/index.spec.tsx | 88 ++++++++++++++++++- .../js/components/common/Table/index.tsx | 21 ++++- 2 files changed, 105 insertions(+), 4 deletions(-) diff --git a/amundsen_application/static/js/components/common/Table/index.spec.tsx b/amundsen_application/static/js/components/common/Table/index.spec.tsx index bbade149a..097b61085 100644 --- a/amundsen_application/static/js/components/common/Table/index.spec.tsx +++ b/amundsen_application/static/js/components/common/Table/index.spec.tsx @@ -589,5 +589,91 @@ describe('Table', () => { }); }); - describe('lifetime', () => {}); + describe('lifetime', () => { + describe('when expandRow is passed', () => { + const { columns, data } = dataBuilder.withCollapsedRow().build(); + const expandRowComponent = (rowValue, index) => ( + + {index}:{rowValue.value} + + ); + + describe('when clicking on expand button', () => { + it('shows the expand row', () => { + const { wrapper } = setup({ + data, + columns, + options: { + expandRow: expandRowComponent, + }, + }); + const expected = 1; + + wrapper + .find('.ams-table-body .ams-table-expanding-button') + .at(0) + .simulate('click'); + + const actual = wrapper.find( + '.ams-table-body .ams-table-expanded-row.is-expanded' + ).length; + + expect(actual).toEqual(expected); + }); + + describe('when clicking again', () => { + it('hides the expand row', () => { + const { wrapper } = setup({ + data, + columns, + options: { + expandRow: expandRowComponent, + }, + }); + const expected = 0; + + wrapper + .find('.ams-table-body .ams-table-expanding-button') + .at(0) + .simulate('click') + .simulate('click'); + + const actual = wrapper.find( + '.ams-table-body .ams-table-expanded-row.is-expanded' + ).length; + + expect(actual).toEqual(expected); + }); + }); + }); + + describe('when clicking on multiple expand buttons', () => { + it('shows all those expand rows', () => { + const { wrapper } = setup({ + data, + columns, + options: { + expandRow: expandRowComponent, + }, + }); + const expected = 2; + + wrapper + .find('.ams-table-body .ams-table-expanding-button') + .at(0) + .simulate('click'); + wrapper + .find('.ams-table-body .ams-table-expanding-button') + .at(1) + .simulate('click'); + + const actual = wrapper.find( + '.ams-table-body .ams-table-expanded-row.is-expanded' + ).length; + + expect(actual).toEqual(expected); + }); + }); + }); + }); }); diff --git a/amundsen_application/static/js/components/common/Table/index.tsx b/amundsen_application/static/js/components/common/Table/index.tsx index f0e92aa51..1eb4454b0 100644 --- a/amundsen_application/static/js/components/common/Table/index.tsx +++ b/amundsen_application/static/js/components/common/Table/index.tsx @@ -34,6 +34,7 @@ export interface TableProps { } const DEFAULT_EMPTY_MESSAGE = 'No Results'; +const EXPAND_ROW_TEXT = 'Expand Row'; const DEFAULT_LOADING_ITEMS = 3; const DEFAULT_ROW_HEIGHT = 30; const DEFAULT_TEXT_ALIGNMENT = 'left'; @@ -82,9 +83,13 @@ const ShimmeringBody: React.FC = ({ type ExpandingCellProps = { index: number; + expandedRows: RowIndex[]; + onClick: (index) => void; }; const ExpandingCell: React.FC = ({ index, + onClick, + expandedRows, }: ExpandingCellProps) => ( ); @@ -135,7 +144,13 @@ const Table: React.FC = ({ style={rowStyles} > <> - {isExpandable ? : null} + {isExpandable ? ( + + ) : null} {Object.entries(item) .filter(([key]) => fields.includes(key)) .map(([key, value], index) => { From a3f41229eee77afb7e6c767f1f6d9fca667fab51 Mon Sep 17 00:00:00 2001 From: Marcos Iglesias Date: Thu, 10 Sep 2020 09:56:07 -0700 Subject: [PATCH 05/10] Up and Down SVG icons Signed-off-by: Marcos Iglesias --- .../components/common/SVGIcons/AlertIcon.tsx | 7 +--- .../components/common/SVGIcons/DownIcon.tsx | 33 ++++++++++++++++ .../js/components/common/SVGIcons/UpIcon.tsx | 38 +++++++++++++++++++ .../js/components/common/SVGIcons/index.tsx | 8 ++++ .../common/SVGIcons/svgIcons.story.tsx | 8 +++- 5 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 amundsen_application/static/js/components/common/SVGIcons/DownIcon.tsx create mode 100644 amundsen_application/static/js/components/common/SVGIcons/UpIcon.tsx diff --git a/amundsen_application/static/js/components/common/SVGIcons/AlertIcon.tsx b/amundsen_application/static/js/components/common/SVGIcons/AlertIcon.tsx index de5d6c2b8..d1f57e060 100644 --- a/amundsen_application/static/js/components/common/SVGIcons/AlertIcon.tsx +++ b/amundsen_application/static/js/components/common/SVGIcons/AlertIcon.tsx @@ -3,15 +3,10 @@ import * as React from 'react'; -import { IconSizes } from '.'; +import { IconSizes, IconProps } from '.'; const DEFAULT_STROKE_COLOR = 'currentColor'; -export interface IconProps { - stroke?: string; - size?: number; -} - export const AlertIcon: React.FC = ({ stroke = DEFAULT_STROKE_COLOR, size = IconSizes.REGULAR, diff --git a/amundsen_application/static/js/components/common/SVGIcons/DownIcon.tsx b/amundsen_application/static/js/components/common/SVGIcons/DownIcon.tsx new file mode 100644 index 000000000..9ccfceb42 --- /dev/null +++ b/amundsen_application/static/js/components/common/SVGIcons/DownIcon.tsx @@ -0,0 +1,33 @@ +// Copyright Contributors to the Amundsen project. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from 'react'; + +import { IconSizes, IconProps } from '.'; + +const DEFAULT_STROKE_COLOR = ''; +const DEFAULT_FILL_COLOR = '#D6D9DB'; + +export const DownIcon: React.FC = ({ + stroke = DEFAULT_STROKE_COLOR, + size = IconSizes.REGULAR, + fill = DEFAULT_FILL_COLOR, +}: IconProps) => { + return ( + + Down + + + + + + + + + + + ); +}; diff --git a/amundsen_application/static/js/components/common/SVGIcons/UpIcon.tsx b/amundsen_application/static/js/components/common/SVGIcons/UpIcon.tsx new file mode 100644 index 000000000..332121fb7 --- /dev/null +++ b/amundsen_application/static/js/components/common/SVGIcons/UpIcon.tsx @@ -0,0 +1,38 @@ +// Copyright Contributors to the Amundsen project. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from 'react'; + +import { IconSizes, IconProps } from '.'; + +const DEFAULT_STROKE_COLOR = ''; +const DEFAULT_FILL_COLOR = '#D6D9DB'; + +export const UpIcon: React.FC = ({ + stroke = DEFAULT_STROKE_COLOR, + size = IconSizes.REGULAR, + fill = DEFAULT_FILL_COLOR, +}: IconProps) => { + return ( + + Up + + + + + + + + + + + ); +}; diff --git a/amundsen_application/static/js/components/common/SVGIcons/index.tsx b/amundsen_application/static/js/components/common/SVGIcons/index.tsx index ed4e8b8e8..455798b2e 100644 --- a/amundsen_application/static/js/components/common/SVGIcons/index.tsx +++ b/amundsen_application/static/js/components/common/SVGIcons/index.tsx @@ -2,8 +2,16 @@ // SPDX-License-Identifier: Apache-2.0 export * from './AlertIcon'; +export * from './DownIcon'; +export * from './UpIcon'; export enum IconSizes { REGULAR = 24, SMALL = 16, } + +export interface IconProps { + stroke?: string; + size?: number; + fill?: string; +} diff --git a/amundsen_application/static/js/components/common/SVGIcons/svgIcons.story.tsx b/amundsen_application/static/js/components/common/SVGIcons/svgIcons.story.tsx index b1f553505..827d35400 100644 --- a/amundsen_application/static/js/components/common/SVGIcons/svgIcons.story.tsx +++ b/amundsen_application/static/js/components/common/SVGIcons/svgIcons.story.tsx @@ -5,7 +5,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import StorySection from '../StorySection'; -import { AlertIcon } from '.'; +import { AlertIcon, DownIcon, UpIcon } from '.'; const stories = storiesOf('Attributes/Iconography', module); @@ -14,5 +14,11 @@ stories.add('SVG Icons', () => ( + + + + + + )); From f0f879f465f24e8813f36978c7e4fb4651a957f7 Mon Sep 17 00:00:00 2001 From: Marcos Iglesias Date: Thu, 10 Sep 2020 10:00:12 -0700 Subject: [PATCH 06/10] Extracting icon types Signed-off-by: Marcos Iglesias --- .../js/components/common/SVGIcons/AlertIcon.tsx | 2 +- .../js/components/common/SVGIcons/DownIcon.tsx | 2 +- .../static/js/components/common/SVGIcons/UpIcon.tsx | 2 +- .../static/js/components/common/SVGIcons/index.tsx | 11 ----------- .../static/js/components/common/SVGIcons/types.ts | 13 +++++++++++++ 5 files changed, 16 insertions(+), 14 deletions(-) create mode 100644 amundsen_application/static/js/components/common/SVGIcons/types.ts diff --git a/amundsen_application/static/js/components/common/SVGIcons/AlertIcon.tsx b/amundsen_application/static/js/components/common/SVGIcons/AlertIcon.tsx index d1f57e060..3a13c1062 100644 --- a/amundsen_application/static/js/components/common/SVGIcons/AlertIcon.tsx +++ b/amundsen_application/static/js/components/common/SVGIcons/AlertIcon.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; -import { IconSizes, IconProps } from '.'; +import { IconSizes, IconProps } from './types'; const DEFAULT_STROKE_COLOR = 'currentColor'; diff --git a/amundsen_application/static/js/components/common/SVGIcons/DownIcon.tsx b/amundsen_application/static/js/components/common/SVGIcons/DownIcon.tsx index 9ccfceb42..5db10e8d4 100644 --- a/amundsen_application/static/js/components/common/SVGIcons/DownIcon.tsx +++ b/amundsen_application/static/js/components/common/SVGIcons/DownIcon.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; -import { IconSizes, IconProps } from '.'; +import { IconSizes, IconProps } from './types'; const DEFAULT_STROKE_COLOR = ''; const DEFAULT_FILL_COLOR = '#D6D9DB'; diff --git a/amundsen_application/static/js/components/common/SVGIcons/UpIcon.tsx b/amundsen_application/static/js/components/common/SVGIcons/UpIcon.tsx index 332121fb7..87c02385b 100644 --- a/amundsen_application/static/js/components/common/SVGIcons/UpIcon.tsx +++ b/amundsen_application/static/js/components/common/SVGIcons/UpIcon.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; -import { IconSizes, IconProps } from '.'; +import { IconSizes, IconProps } from './types'; const DEFAULT_STROKE_COLOR = ''; const DEFAULT_FILL_COLOR = '#D6D9DB'; diff --git a/amundsen_application/static/js/components/common/SVGIcons/index.tsx b/amundsen_application/static/js/components/common/SVGIcons/index.tsx index 455798b2e..3b6ca08b7 100644 --- a/amundsen_application/static/js/components/common/SVGIcons/index.tsx +++ b/amundsen_application/static/js/components/common/SVGIcons/index.tsx @@ -4,14 +4,3 @@ export * from './AlertIcon'; export * from './DownIcon'; export * from './UpIcon'; - -export enum IconSizes { - REGULAR = 24, - SMALL = 16, -} - -export interface IconProps { - stroke?: string; - size?: number; - fill?: string; -} diff --git a/amundsen_application/static/js/components/common/SVGIcons/types.ts b/amundsen_application/static/js/components/common/SVGIcons/types.ts new file mode 100644 index 000000000..9152f0da9 --- /dev/null +++ b/amundsen_application/static/js/components/common/SVGIcons/types.ts @@ -0,0 +1,13 @@ +// Copyright Contributors to the Amundsen project. +// SPDX-License-Identifier: Apache-2.0 + +export enum IconSizes { + REGULAR = 24, + SMALL = 16, +} + +export interface IconProps { + stroke?: string; + size?: number; + fill?: string; +} From 0d037e0cb59be8b68e611a0c1eda27c526afb242 Mon Sep 17 00:00:00 2001 From: Marcos Iglesias Date: Thu, 10 Sep 2020 10:01:31 -0700 Subject: [PATCH 07/10] Fixing alert issue Signed-off-by: Marcos Iglesias --- .../static/js/components/common/Alert/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/amundsen_application/static/js/components/common/Alert/index.tsx b/amundsen_application/static/js/components/common/Alert/index.tsx index f3e159a11..6501da05f 100644 --- a/amundsen_application/static/js/components/common/Alert/index.tsx +++ b/amundsen_application/static/js/components/common/Alert/index.tsx @@ -3,7 +3,8 @@ import * as React from 'react'; -import { AlertIcon, IconSizes } from '../SVGIcons'; +import { AlertIcon } from '../SVGIcons'; +import { IconSizes } from '../SVGIcons/types'; import './styles.scss'; From 93c3b4e0841a93e964ed6c3f235a039dab50017e Mon Sep 17 00:00:00 2001 From: Marcos Iglesias Date: Thu, 10 Sep 2020 10:36:17 -0700 Subject: [PATCH 08/10] Basic expand button styling Signed-off-by: Marcos Iglesias --- .../js/components/common/Table/index.tsx | 47 +++++++++++-------- .../js/components/common/Table/styles.scss | 11 ++++- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/amundsen_application/static/js/components/common/Table/index.tsx b/amundsen_application/static/js/components/common/Table/index.tsx index 1eb4454b0..a3a7c77fa 100644 --- a/amundsen_application/static/js/components/common/Table/index.tsx +++ b/amundsen_application/static/js/components/common/Table/index.tsx @@ -4,6 +4,7 @@ import * as React from 'react'; import ShimmeringResourceLoader from '../ShimmeringResourceLoader'; +import { DownIcon, UpIcon } from '../SVGIcons'; import './styles.scss'; @@ -37,6 +38,7 @@ const DEFAULT_EMPTY_MESSAGE = 'No Results'; const EXPAND_ROW_TEXT = 'Expand Row'; const DEFAULT_LOADING_ITEMS = 3; const DEFAULT_ROW_HEIGHT = 30; +const EXPANDING_CELL_WIDTH = '70px'; const DEFAULT_TEXT_ALIGNMENT = 'left'; type RowStyles = { @@ -90,26 +92,33 @@ const ExpandingCell: React.FC = ({ index, onClick, expandedRows, -}: ExpandingCellProps) => ( - -); + + + ); +}; type RowIndex = number; diff --git a/amundsen_application/static/js/components/common/Table/styles.scss b/amundsen_application/static/js/components/common/Table/styles.scss index 28fbd9582..4c1050802 100644 --- a/amundsen_application/static/js/components/common/Table/styles.scss +++ b/amundsen_application/static/js/components/common/Table/styles.scss @@ -52,7 +52,16 @@ $shimmer-block-width: 40%; display: none; &.is-expanded { - display: block; + display: table-row; + } +} + +.ams-table-expanding-button { + border: 0; + background-color: white; + + svg { + vertical-align: bottom; } } From 963e89fb1ed0b291cc2a439ed28951ca6031b8f4 Mon Sep 17 00:00:00 2001 From: Marcos Iglesias Date: Thu, 10 Sep 2020 14:34:45 -0700 Subject: [PATCH 09/10] Adds fixed column widths Signed-off-by: Marcos Iglesias --- .../js/components/common/Table/index.spec.tsx | 84 ++++++++++++++++--- .../js/components/common/Table/index.tsx | 41 +++++---- .../components/common/Table/table.story.tsx | 34 ++++++-- .../common/Table/testDataBuilder.tsx | 27 ++++++ 4 files changed, 151 insertions(+), 35 deletions(-) diff --git a/amundsen_application/static/js/components/common/Table/index.spec.tsx b/amundsen_application/static/js/components/common/Table/index.spec.tsx index 097b61085..7214f7117 100644 --- a/amundsen_application/static/js/components/common/Table/index.spec.tsx +++ b/amundsen_application/static/js/components/common/Table/index.spec.tsx @@ -212,10 +212,10 @@ describe('Table', () => { data, columns, }); - const expected = { textAlign: 'left' }; + const expected = 'left'; const actual = wrapper .find('.ams-table-header .ams-table-heading-cell') - .get(0).props.style; + .get(0).props.style.textAlign; expect(actual).toEqual(expected); }); @@ -225,10 +225,10 @@ describe('Table', () => { data, columns, }); - const expected = { textAlign: 'center' }; + const expected = 'center'; const actual = wrapper .find('.ams-table-header .ams-table-heading-cell') - .get(1).props.style; + .get(1).props.style.textAlign; expect(actual).toEqual(expected); }); @@ -238,10 +238,10 @@ describe('Table', () => { data, columns, }); - const expected = { textAlign: 'right' }; + const expected = 'right'; const actual = wrapper .find('.ams-table-header .ams-table-heading-cell') - .get(2).props.style; + .get(2).props.style.textAlign; expect(actual).toEqual(expected); }); @@ -253,10 +253,10 @@ describe('Table', () => { data, columns, }); - const expected = { textAlign: 'left' }; + const expected = 'left'; const actual = wrapper .find('.ams-table-body .ams-table-cell') - .get(0).props.style; + .get(0).props.style.textAlign; expect(actual).toEqual(expected); }); @@ -266,10 +266,10 @@ describe('Table', () => { data, columns, }); - const expected = { textAlign: 'center' }; + const expected = 'center'; const actual = wrapper .find('.ams-table-body .ams-table-cell') - .get(1).props.style; + .get(1).props.style.textAlign; expect(actual).toEqual(expected); }); @@ -279,10 +279,70 @@ describe('Table', () => { data, columns, }); - const expected = { textAlign: 'right' }; + const expected = 'right'; const actual = wrapper .find('.ams-table-body .ams-table-cell') - .get(2).props.style; + .get(2).props.style.textAlign; + + expect(actual).toEqual(expected); + }); + }); + }); + + describe('when column width is passed', () => { + const { columns, data } = dataBuilder.withFixedWidthColumns().build(); + + describe('table header', () => { + it('renders the first column as a 50px column', () => { + const { wrapper } = setup({ + data, + columns, + }); + const expected = '50px'; + const actual = wrapper + .find('.ams-table-header .ams-table-heading-cell') + .get(0).props.style.width; + + expect(actual).toEqual(expected); + }); + + it('renders the second column as a 200px column', () => { + const { wrapper } = setup({ + data, + columns, + }); + const expected = '200px'; + const actual = wrapper + .find('.ams-table-header .ams-table-heading-cell') + .get(1).props.style.width; + + expect(actual).toEqual(expected); + }); + }); + + describe('table body', () => { + it('renders the first column as a 50px column', () => { + const { wrapper } = setup({ + data, + columns, + }); + const expected = '50px'; + const actual = wrapper + .find('.ams-table-body .ams-table-cell') + .get(0).props.style.width; + + expect(actual).toEqual(expected); + }); + + it('renders the second column as a 200px column', () => { + const { wrapper } = setup({ + data, + columns, + }); + const expected = '200px'; + const actual = wrapper + .find('.ams-table-body .ams-table-cell') + .get(1).props.style.width; expect(actual).toEqual(expected); }); diff --git a/amundsen_application/static/js/components/common/Table/index.tsx b/amundsen_application/static/js/components/common/Table/index.tsx index a3a7c77fa..8b970ee9f 100644 --- a/amundsen_application/static/js/components/common/Table/index.tsx +++ b/amundsen_application/static/js/components/common/Table/index.tsx @@ -15,8 +15,8 @@ export interface TableColumn { field: string; horAlign?: TextAlignmentValues; component?: (value: any, index: number) => React.ReactNode; + width?: number; // className?: string; - // width?: number; // sortable?: bool (false) } @@ -40,6 +40,7 @@ const DEFAULT_LOADING_ITEMS = 3; const DEFAULT_ROW_HEIGHT = 30; const EXPANDING_CELL_WIDTH = '70px'; const DEFAULT_TEXT_ALIGNMENT = 'left'; +const DEFAULT_CELL_WIDTH = 'auto'; type RowStyles = { height: string; @@ -167,7 +168,12 @@ const Table: React.FC = ({ const horAlign = columnInfo ? columnInfo.horAlign || DEFAULT_TEXT_ALIGNMENT : DEFAULT_TEXT_ALIGNMENT; + const width = + columnInfo && columnInfo.width + ? `${columnInfo.width}px` + : DEFAULT_CELL_WIDTH; const cellStyle = { + width, textAlign: `${horAlign}` as TextAlignmentValues, }; // TODO: Improve the typing of this @@ -210,21 +216,24 @@ const Table: React.FC = ({ {isExpandable && ( - ); - })} + {columns.map( + ({ title, horAlign = DEFAULT_TEXT_ALIGNMENT, width = null }, index) => { + const cellStyle = { + width: width ? `${width}px` : DEFAULT_CELL_WIDTH, + textAlign: `${horAlign}` as TextAlignmentValues, + }; + + return ( + + ); + } + )} ); diff --git a/amundsen_application/static/js/components/common/Table/table.story.tsx b/amundsen_application/static/js/components/common/Table/table.story.tsx index c776d472a..71bc5eac3 100644 --- a/amundsen_application/static/js/components/common/Table/table.story.tsx +++ b/amundsen_application/static/js/components/common/Table/table.story.tsx @@ -14,6 +14,9 @@ const { columns: alignedColumns, data: alignedData, } = dataBuilder.withAlignedColumns().build(); +const { + columns: differentWidthColumns, +} = dataBuilder.withFixedWidthColumns().build(); const { columns: customColumns, data: customColumnsData, @@ -38,7 +41,7 @@ const expandRowComponent = (rowValue, index) => ( const stories = storiesOf('Components/Table', module); -stories.add('Table', () => ( +stories.add('Table States', () => ( <>
@@ -171,7 +176,7 @@ const Table: React.FC = ({
= ({ type="button" className="ams-table-expanding-button" onClick={() => { - console.log('expand!', index); + const newExpandedRows = expandedRows.includes(index) + ? expandedRows.filter((i) => i !== index) + : [...expandedRows, index]; + + onClick(newExpandedRows); }} > - Expand + {EXPAND_ROW_TEXT} - - {EXPAND_ROW_TEXT} - - )} - {columns.map(({ title, horAlign = DEFAULT_TEXT_ALIGNMENT }, index) => { - const cellStyle = { - textAlign: `${horAlign}` as TextAlignmentValues, - }; - - return ( - - {title} - + {title} +
@@ -49,34 +52,51 @@ stories.add('Table', () => (
- + +)); + +stories.add('Styled Table', () => ( + <> +
- +
- + +
+ + +)); + +stories.add('Customized Table', () => ( + <> +
- +
- +
- +
{ + const attr = { + data: [...this.config.data], + columns: [ + { + title: 'Name', + field: 'name', + width: 50, + horAlign: 'left', + }, + { + title: 'Type', + field: 'type', + width: 200, + horAlign: 'center', + }, + { + title: 'Value', + field: 'value', + horAlign: 'right', + }, + ], + }; + + return new this.Klass(attr); + }; + this.withEmptyData = () => { const attr = { data: [], From fd4a37aa43e2c2227e2fb388457a4ee21679e358 Mon Sep 17 00:00:00 2001 From: Marcos Iglesias Date: Thu, 10 Sep 2020 14:51:01 -0700 Subject: [PATCH 10/10] Fixes checks Signed-off-by: Marcos Iglesias --- amundsen_application/static/.betterer.results | 8 ++++---- .../common/ResourceList/ResourceListHeader/styles.scss | 5 +++++ .../static/js/components/common/Table/index.tsx | 7 +++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/amundsen_application/static/.betterer.results b/amundsen_application/static/.betterer.results index 61ecc12c8..64a77d83c 100644 --- a/amundsen_application/static/.betterer.results +++ b/amundsen_application/static/.betterer.results @@ -99,8 +99,8 @@ exports[`strict null compilation`] = { [255, 6, 11, "No overload matches this call.\\n The last overload gave the following error.\\n Type \'(() => SubmitSearchRequest) | null\' is not assignable to type \'ActionCreator\'.\\n Type \'null\' is not assignable to type \'ActionCreator\'.", "2296208050"], [270, 4, 18, "No overload matches this call.\\n The last overload gave the following error.\\n Argument of type \'(dispatch: any, ownProps: any) => ActionCreator\' is not assignable to parameter of type \'DispatchFromProps\'.\\n Type \'(dispatch: any, ownProps: any) => ActionCreator\' is missing the following properties from type \'DispatchFromProps\': submitSearch, onInputChange, onSelectInlineResult", "2926224796"] ], - "js/components/common/Table/index.tsx:2876532157": [ - [127, 18, 13, "Type \'unknown\' is not assignable to type \'ReactNode\'.\\n Type \'unknown\' is not assignable to type \'ReactPortal\'.", "971959308"] + "js/components/common/Table/index.tsx:2645527205": [ + [190, 22, 13, "Type \'unknown\' is not assignable to type \'ReactNode\'.\\n Type \'unknown\' is not assignable to type \'ReactPortal\'.", "971959308"] ], "js/components/common/Tags/TagInput/index.tsx:3754832290": [ [63, 22, 6, "Type \'undefined\' is not assignable to type \'GetAllTagsRequest\'.", "1979467425"], @@ -364,8 +364,8 @@ exports[`strict null compilation`] = { "js/utils/navigationUtils.ts:1127210474": [ [19, 50, 21, "Type \'undefined\' cannot be used as an index type.", "602535635"] ], - "webpack.common.ts:545199363": [ - [33, 24, 20, "No overload matches this call.\\n Overload 1 of 2, \'(...items: ConcatArray[]): never[]\', gave the following error.\\n Argument of type \'string\' is not assignable to parameter of type \'ConcatArray\'.\\n Overload 2 of 2, \'(...items: ConcatArray[]): never[]\', gave the following error.\\n Argument of type \'string\' is not assignable to parameter of type \'ConcatArray\'.", "806093104"] + "webpack.common.ts:368637609": [ + [34, 24, 20, "No overload matches this call.\\n Overload 1 of 2, \'(...items: ConcatArray[]): never[]\', gave the following error.\\n Argument of type \'string\' is not assignable to parameter of type \'ConcatArray\'.\\n Overload 2 of 2, \'(...items: ConcatArray[]): never[]\', gave the following error.\\n Argument of type \'string\' is not assignable to parameter of type \'ConcatArray\'.", "806093104"] ] }` }; diff --git a/amundsen_application/static/js/components/common/ResourceList/ResourceListHeader/styles.scss b/amundsen_application/static/js/components/common/ResourceList/ResourceListHeader/styles.scss index daca54109..6771be617 100644 --- a/amundsen_application/static/js/components/common/ResourceList/ResourceListHeader/styles.scss +++ b/amundsen_application/static/js/components/common/ResourceList/ResourceListHeader/styles.scss @@ -6,6 +6,7 @@ .resource-list-header { @extend %text-caption-w2; + display: flex; flex-direction: row; align-items: center; @@ -15,18 +16,22 @@ .dataset { flex: 7; margin-right: $spacer-2; + .dataset-text { margin-left: $spacer-5; } } + .source { flex: 2; } + .badges { display: flex; flex: 3; flex-wrap: wrap; margin-left: $spacer-3; + .badges-text { margin-left: $spacer-3; } diff --git a/amundsen_application/static/js/components/common/Table/index.tsx b/amundsen_application/static/js/components/common/Table/index.tsx index 8b970ee9f..3f503dce8 100644 --- a/amundsen_application/static/js/components/common/Table/index.tsx +++ b/amundsen_application/static/js/components/common/Table/index.tsx @@ -137,7 +137,6 @@ const Table: React.FC = ({ } = options; const fields = columns.map(({ field }) => field); const rowStyles = { height: `${rowHeight}px` }; - const isExpandable: boolean = !!expandRow; const [expandedRows, setExpandedRows] = React.useState([]); let body: React.ReactNode = ( @@ -154,7 +153,7 @@ const Table: React.FC = ({ style={rowStyles} > <> - {isExpandable ? ( + {expandRow ? ( = ({ })} - {isExpandable ? ( + {expandRow ? ( = ({ let header: React.ReactNode = ( - {isExpandable && ( + {expandRow && (
)} {columns.map(