From a5120a756edc59ab674c46bab63c9d54ecb7e567 Mon Sep 17 00:00:00 2001 From: Mingze Xiao Date: Mon, 16 Dec 2019 16:39:15 -0800 Subject: [PATCH] feat(archive-viewer): Add breadcrumbs --- src/i18n/en-US.properties | 2 + src/lib/viewers/archive/ArchiveExplorer.js | 84 +++++++++++-------- src/lib/viewers/archive/ArchiveExplorer.scss | 6 ++ src/lib/viewers/archive/Breadcrumbs.js | 58 +++++++++++++ src/lib/viewers/archive/Breadcrumbs.scss | 11 +++ .../__tests__/ArchiveExplorer-test-react.js | 14 +++- .../__tests__/Breadcrumbs-test-react.js | 57 +++++++++++++ src/lib/viewers/archive/constants.js | 8 +- 8 files changed, 200 insertions(+), 40 deletions(-) create mode 100644 src/lib/viewers/archive/ArchiveExplorer.scss create mode 100644 src/lib/viewers/archive/Breadcrumbs.js create mode 100644 src/lib/viewers/archive/Breadcrumbs.scss create mode 100644 src/lib/viewers/archive/__tests__/Breadcrumbs-test-react.js diff --git a/src/i18n/en-US.properties b/src/i18n/en-US.properties index edc9f4699..69f66c989 100644 --- a/src/i18n/en-US.properties +++ b/src/i18n/en-US.properties @@ -86,6 +86,8 @@ filename=Filename last_modified_date=Last modified date # Label for size column name size=Size +# Shown as the title in the breadcrumbs while searching. +search_results=Search Results # Media Preview # Label for autoplay in media player diff --git a/src/lib/viewers/archive/ArchiveExplorer.js b/src/lib/viewers/archive/ArchiveExplorer.js index 9e23d7b25..894bff8ad 100644 --- a/src/lib/viewers/archive/ArchiveExplorer.js +++ b/src/lib/viewers/archive/ArchiveExplorer.js @@ -12,7 +12,9 @@ import { import VirtualizedTable from 'box-ui-elements/es/features/virtualized-table'; import { addLocaleData } from 'react-intl'; import { Column } from 'react-virtualized/dist/es/Table/index'; -import { TABLE_COLUMNS } from './constants'; +import Breadcrumbs from './Breadcrumbs'; +import { TABLE_COLUMNS, VIEWS } from './constants'; +import './ArchiveExplorer.scss'; const language = __LANGUAGE__; // eslint-disable-line const { KEY_NAME, KEY_MODIFIED_AT, KEY_SIZE } = TABLE_COLUMNS; @@ -63,6 +65,7 @@ class ArchiveExplorer extends React.Component { this.state = { fullPath: props.itemCollection.find(info => !info.parent).absolute_path, + view: VIEWS.VIEW_FOLDER, }; } @@ -121,6 +124,14 @@ class ArchiveExplorer extends React.Component { }); }; + /** + * Handle click event, update fullPath state + * + * @param {string} fullPath - target folder path + * @return {void} + */ + handleClickFullPath = fullPath => this.setState({ fullPath }); + /** * render data * @@ -128,46 +139,45 @@ class ArchiveExplorer extends React.Component { */ render() { const { itemCollection } = this.props; - const { fullPath } = this.state; + const { fullPath, view } = this.state; const itemList = this.getItemList(itemCollection, fullPath); return ( - - {intl => [ - , - , - , - ]} - +
+ + + {intl => [ + , + , + , + ]} + +
); } diff --git a/src/lib/viewers/archive/ArchiveExplorer.scss b/src/lib/viewers/archive/ArchiveExplorer.scss new file mode 100644 index 000000000..8eaac2ed4 --- /dev/null +++ b/src/lib/viewers/archive/ArchiveExplorer.scss @@ -0,0 +1,6 @@ +.bp-ArchiveExplorer { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; +} diff --git a/src/lib/viewers/archive/Breadcrumbs.js b/src/lib/viewers/archive/Breadcrumbs.js new file mode 100644 index 000000000..724fe2436 --- /dev/null +++ b/src/lib/viewers/archive/Breadcrumbs.js @@ -0,0 +1,58 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Breadcrumb from 'box-ui-elements/es/components/breadcrumb'; +import PlainButton from 'box-ui-elements/es/components/plain-button/PlainButton'; +import { VIEWS } from './constants'; +import './Breadcrumbs.scss'; + +class Breadcrumbs extends React.PureComponent { + static propTypes = { + fullPath: PropTypes.string.isRequired, + onClick: PropTypes.func.isRequired, + view: PropTypes.string.isRequired, + }; + + /** + * Split full path string to path items + * + * @param {string} fullPath - Full path for current folder + * @return {Array} path items including name and path string + */ + getPathItems = fullPath => { + const pathNames = fullPath.split('/').slice(0, -1); + // join path names from root to current index to get absolute path + const getAbsolutePath = index => pathNames.slice(0, index + 1).join('/'); + + return pathNames.map((name, index) => ({ + name, + path: `${getAbsolutePath(index)}/`, + })); + }; + + /** + * render breadcrumbs + * + * @return {jsx} Breadcrumbs + */ + render() { + const { fullPath, onClick, view } = this.props; + + return ( +
+ + {view === VIEWS.VIEW_SEARCH ? ( + {__('search_results')} + ) : ( + this.getPathItems(fullPath).map(pathItem => ( + onClick(pathItem.path)} type="button"> + {pathItem.name} + + )) + )} + +
+ ); + } +} + +export default Breadcrumbs; diff --git a/src/lib/viewers/archive/Breadcrumbs.scss b/src/lib/viewers/archive/Breadcrumbs.scss new file mode 100644 index 000000000..4a8404f36 --- /dev/null +++ b/src/lib/viewers/archive/Breadcrumbs.scss @@ -0,0 +1,11 @@ +@import '~box-ui-elements/es/styles/variables'; + +.bp-Breadcrumbs { + display: flex; + flex: 0 0 50px; + align-items: center; + justify-content: space-between; + padding: 0 20px 0 25px; + border-bottom: 1px solid $bdl-gray-10; + box-shadow: 0 4px 6px -2px $transparent-black; +} diff --git a/src/lib/viewers/archive/__tests__/ArchiveExplorer-test-react.js b/src/lib/viewers/archive/__tests__/ArchiveExplorer-test-react.js index 9877d3c3f..2ba5a019e 100644 --- a/src/lib/viewers/archive/__tests__/ArchiveExplorer-test-react.js +++ b/src/lib/viewers/archive/__tests__/ArchiveExplorer-test-react.js @@ -68,9 +68,11 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { }); describe('render()', () => { - it('should render VirtualizedTable', () => { + it('should render correct components', () => { const component = shallow(); + expect(component.find('.bp-ArchiveExplorer').length).to.equal(1); + expect(component.find('Breadcrumbs').length).to.equal(1); expect(component.find('Internationalize').length).to.equal(1); expect(component.find('InjectIntl(VirtualizedTable)').length).to.equal(1); }); @@ -86,6 +88,16 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { }); }); + describe('handleClickFullPath()', () => { + it('should set state when handleClickFullPath() is called', () => { + const component = shallow(); + + component.instance().handleClickFullPath('test/subfolder/'); + + expect(component.state().fullPath).to.equal('test/subfolder/'); + }); + }); + describe('getRowData()', () => { it('should return correct row data', () => { const component = shallow(); diff --git a/src/lib/viewers/archive/__tests__/Breadcrumbs-test-react.js b/src/lib/viewers/archive/__tests__/Breadcrumbs-test-react.js new file mode 100644 index 000000000..7c507dbee --- /dev/null +++ b/src/lib/viewers/archive/__tests__/Breadcrumbs-test-react.js @@ -0,0 +1,57 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import Breadcrumbs from '../Breadcrumbs'; +import { VIEWS } from '../constants'; + +const sandbox = sinon.sandbox.create(); +let fullPath; +let onClick; +let view; + +describe('lib/viewers/archive/Breadcrumbs', () => { + beforeEach(() => { + fullPath = 'test/subfolder/'; + onClick = sandbox.stub(); + view = VIEWS.VIEW_FOLDER; + }); + + afterEach(() => { + sandbox.verifyAndRestore(); + }); + + describe('render()', () => { + it('should render correct components', () => { + const component = shallow(); + + expect(component.find('.bp-Breadcrumbs').length).to.equal(1); + expect(component.find('InjectIntl(Breadcrumb)').length).to.equal(1); + expect(component.find('PlainButton').length).to.equal(2); + }); + + it('should render search result if view is search', () => { + const component = shallow(); + + expect(component.find('span').text()).to.equal(__('search_results')); + }); + }); + + describe('getPathItems()', () => { + it('should return correct path items', () => { + const component = shallow(); + + const pathItems = component.instance().getPathItems(fullPath); + + expect(pathItems).to.eql([ + { + name: 'test', + path: 'test/', + }, + { + name: 'subfolder', + path: 'test/subfolder/', + }, + ]); + }); + }); +}); diff --git a/src/lib/viewers/archive/constants.js b/src/lib/viewers/archive/constants.js index c5b2c697f..2ad6b50d9 100644 --- a/src/lib/viewers/archive/constants.js +++ b/src/lib/viewers/archive/constants.js @@ -4,5 +4,9 @@ const TABLE_COLUMNS = { KEY_SIZE: 'key_size', }; -// eslint-disable-next-line import/prefer-default-export -export { TABLE_COLUMNS }; +const VIEWS = { + VIEW_FOLDER: 'folder', + VIEW_SEARCH: 'search', +}; + +export { TABLE_COLUMNS, VIEWS };