forked from amundsen-io/amundsen
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Improve Nested Column Types UI (amundsen-io#627)
* feat: Create ColumnType component (amundsen-io#604) * Create ColumnType component Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Update Modal UI Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Code cleanup; Add a test file * Prevent ColumnListItem expand/collapse from being triggered * Lint fix Signed-off-by: Tamika Tannis <ttannis@lyft.com> * feat: Parse column types (amundsen-io#611) * WIP: Create a parser & render parsed text Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Cleanup logic Signed-off-by: Tamika Tannis <ttannis@lyft.com> * More cleanup Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Lint fix Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Code cleanup Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Code cleanup Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Code cleanup Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Use more appropriate elements; Fix typo Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Parser tests Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Fix button; Fix test; Remove obsolete style Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Fix duplicate test name Signed-off-by: Tamika Tannis <ttannis@lyft.com> * style: Improve UI styles and interactions (amundsen-io#617) * Vertically center modal Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Match design font specifications Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Miscellaneous cleanup Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Use variables Signed-off-by: Tamika Tannis <ttannis@lyft.com> * test: Improves unit tests for ColumnType + QA fixes (amundsen-io#625) * Parser tests Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Updates from design qa Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Improve ColumnType tests Signed-off-by: Tamika Tannis <ttannis@lyft.com> * log support Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Code cleanup Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Fix some lint warning Signed-off-by: Tamika Tannis <ttannis@lyft.com> * Betterer update Signed-off-by: Tamika Tannis <ttannis@lyft.com>
- Loading branch information
Showing
15 changed files
with
720 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
...sen_application/static/js/components/TableDetail/ColumnListItem/ColumnType/index.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Copyright Contributors to the Amundsen project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import * as React from 'react'; | ||
import { mount } from 'enzyme'; | ||
|
||
import { Modal } from 'react-bootstrap'; | ||
|
||
import * as UtilMethods from 'ducks/utilMethods'; | ||
import ColumnType, { ColumnTypeProps } from '.'; | ||
|
||
const logClickSpy = jest.spyOn(UtilMethods, 'logClick'); | ||
logClickSpy.mockImplementation(() => null); | ||
|
||
const setup = (propOverrides?: Partial<ColumnTypeProps>) => { | ||
const props = { | ||
columnName: 'test', | ||
database: 'presto', | ||
type: | ||
'row(test_id varchar,test2 row(test2_id varchar,started_at timestamp,ended_at timestamp))', | ||
...propOverrides, | ||
}; | ||
const wrapper = mount<ColumnType>(<ColumnType {...props} />); | ||
return { wrapper, props }; | ||
}; | ||
const { wrapper, props } = setup(); | ||
|
||
describe('ColumnType', () => { | ||
describe('lifecycle', () => { | ||
describe('when clicking on column-type-btn', () => { | ||
it('should call showModal on the instance', () => { | ||
const clickSpy = jest.spyOn(wrapper.instance(), 'showModal'); | ||
wrapper.instance().forceUpdate(); | ||
wrapper.find('.column-type-btn').simulate('click'); | ||
|
||
expect(clickSpy).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should log the interaction', () => { | ||
logClickSpy.mockClear(); | ||
wrapper.find('.column-type-btn').simulate('click'); | ||
|
||
expect(logClickSpy).toHaveBeenCalled(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('render', () => { | ||
it('renders the column type string for simple types', () => { | ||
const { wrapper, props } = setup({ type: 'varchar(32)' }); | ||
expect(wrapper.find('.column-type').text()).toBe(props.type); | ||
}); | ||
|
||
describe('for nested types', () => { | ||
it('renders the truncated column type string', () => { | ||
const actual = wrapper.find('.column-type-btn').text(); | ||
const expected = 'row(...)'; | ||
|
||
expect(actual).toBe(expected); | ||
}); | ||
|
||
describe('renders a modal', () => { | ||
it('exists', () => { | ||
const actual = wrapper.find(Modal).exists(); | ||
const expected = true; | ||
|
||
expect(actual).toBe(expected); | ||
}); | ||
|
||
it('renders props.type in modal body', () => { | ||
const actual = wrapper.find('.sub-title').text(); | ||
const expected = props.columnName; | ||
|
||
expect(actual).toBe(expected); | ||
}); | ||
|
||
it('renders props.type in modal body', () => { | ||
const actual = wrapper.find('.modal-body').text(); | ||
const expected = props.type; | ||
|
||
expect(actual).toBe(expected); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
149 changes: 149 additions & 0 deletions
149
...amundsen_application/static/js/components/TableDetail/ColumnListItem/ColumnType/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
// Copyright Contributors to the Amundsen project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import * as React from 'react'; | ||
import { Modal, OverlayTrigger, Popover } from 'react-bootstrap'; | ||
|
||
import { logClick } from 'ducks/utilMethods'; | ||
|
||
import './styles.scss'; | ||
|
||
import { | ||
getTruncatedText, | ||
parseNestedType, | ||
NestedType, | ||
ParsedType, | ||
} from './parser'; | ||
|
||
const CTA_TEXT = 'Click to see nested fields'; | ||
const MODAL_TITLE = 'Nested Type'; | ||
const TEXT_INDENT = 8; | ||
|
||
export interface ColumnTypeProps { | ||
columnName: string; | ||
database: string; | ||
type: string; | ||
} | ||
|
||
export interface ColumnTypeState { | ||
showModal: boolean; | ||
} | ||
|
||
export class ColumnType extends React.Component< | ||
ColumnTypeProps, | ||
ColumnTypeState | ||
> { | ||
nestedType: NestedType | null; | ||
|
||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
showModal: false, | ||
}; | ||
const { database, type } = this.props; | ||
this.nestedType = parseNestedType(type, database); | ||
} | ||
|
||
hideModal = (e) => { | ||
this.stopPropagation(e); | ||
this.setState({ showModal: false }); | ||
}; | ||
|
||
showModal = (e) => { | ||
logClick(e); | ||
this.stopPropagation(e); | ||
this.setState({ showModal: true }); | ||
}; | ||
|
||
stopPropagation = (e) => { | ||
if (e) { | ||
e.stopPropagation(); | ||
} | ||
}; | ||
|
||
createLineItem = (text: string, textIndent: number) => { | ||
return ( | ||
<div key={`lineitem:${text}`} style={{ textIndent: `${textIndent}px` }}> | ||
{text} | ||
</div> | ||
); | ||
}; | ||
|
||
renderParsedChildren = (children: ParsedType[], level: number) => { | ||
const textIndent = level * TEXT_INDENT; | ||
return children.map((item) => { | ||
if (typeof item === 'string') { | ||
return this.createLineItem(item, textIndent); | ||
} | ||
return this.renderNestedType(item, level); | ||
}); | ||
}; | ||
|
||
renderNestedType = (nestedType: NestedType, level: number = 0) => { | ||
const { head, tail, children } = nestedType; | ||
const textIndent = level * TEXT_INDENT; | ||
return ( | ||
<div key={`nesteditem:${head}${tail}`}> | ||
{this.createLineItem(head, textIndent)} | ||
{this.renderParsedChildren(children, level + 1)} | ||
{this.createLineItem(tail, textIndent)} | ||
</div> | ||
); | ||
}; | ||
|
||
render = () => { | ||
const { columnName, type } = this.props; | ||
|
||
if (this.nestedType === null) { | ||
return <p className="column-type">{type}</p>; | ||
} | ||
|
||
const popoverHover = ( | ||
<Popover | ||
className="column-type-popover" | ||
id={`column-type-popover:${columnName}`} | ||
> | ||
{CTA_TEXT} | ||
</Popover> | ||
); | ||
return ( | ||
<div onClick={this.stopPropagation}> | ||
<OverlayTrigger | ||
trigger={['hover', 'focus']} | ||
placement="top" | ||
overlay={popoverHover} | ||
rootClose | ||
> | ||
<button | ||
data-type="column-type" | ||
type="button" | ||
className="column-type-btn" | ||
onClick={this.showModal} | ||
> | ||
{getTruncatedText(this.nestedType)} | ||
</button> | ||
</OverlayTrigger> | ||
<Modal | ||
className="column-type-modal" | ||
show={this.state.showModal} | ||
onHide={this.hideModal} | ||
> | ||
<Modal.Header closeButton> | ||
<Modal.Title> | ||
<h5 className="main-title">{MODAL_TITLE}</h5> | ||
<div className="sub-title">{columnName}</div> | ||
</Modal.Title> | ||
</Modal.Header> | ||
<Modal.Body> | ||
<div className="column-type-modal-content"> | ||
{this.renderNestedType(this.nestedType)} | ||
</div> | ||
</Modal.Body> | ||
</Modal> | ||
</div> | ||
); | ||
}; | ||
} | ||
|
||
export default ColumnType; |
Oops, something went wrong.