Skip to content

Commit

Permalink
feat(archive-viewer): Add breadcrumbs (#1119)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingze authored and mergify[bot] committed Dec 17, 2019
1 parent b8c60e9 commit d09738f
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 40 deletions.
2 changes: 2 additions & 0 deletions src/i18n/en-US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
84 changes: 47 additions & 37 deletions src/lib/viewers/archive/ArchiveExplorer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -63,6 +65,7 @@ class ArchiveExplorer extends React.Component {

this.state = {
fullPath: props.itemCollection.find(info => !info.parent).absolute_path,
view: VIEWS.VIEW_FOLDER,
};
}

Expand Down Expand Up @@ -121,53 +124,60 @@ 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
*
* @return {jsx} VirtualizedTable
*/
render() {
const { itemCollection } = this.props;
const { fullPath } = this.state;
const { fullPath, view } = this.state;
const itemList = this.getItemList(itemCollection, fullPath);

return (
<Internationalize language={language} messages={elementsMessages}>
<VirtualizedTable
className="ArchiveFilesTable"
rowData={itemList}
rowGetter={this.getRowData(itemList)}
>
{intl => [
<Column
key={KEY_NAME}
cellRenderer={itemNameCellRenderer(intl, this.handleClick)}
dataKey={KEY_NAME}
disableSort
flexGrow={3}
label={__('filename')}
width={1}
/>,
<Column
key={KEY_MODIFIED_AT}
cellRenderer={readableTimeCellRenderer}
dataKey={KEY_MODIFIED_AT}
disableSort
flexGrow={2}
label={__('last_modified_date')}
width={1}
/>,
<Column
key={KEY_SIZE}
cellRenderer={sizeCellRenderer()}
dataKey={KEY_SIZE}
disableSort
flexGrow={1}
label={__('size')}
width={1}
/>,
]}
</VirtualizedTable>
<div className="bp-ArchiveExplorer">
<Breadcrumbs fullPath={fullPath} onClick={this.handleClickFullPath} view={view} />
<VirtualizedTable rowData={itemList} rowGetter={this.getRowData(itemList)}>
{intl => [
<Column
key={KEY_NAME}
cellRenderer={itemNameCellRenderer(intl, this.handleClick)}
dataKey={KEY_NAME}
disableSort
flexGrow={3}
label={__('filename')}
width={1}
/>,
<Column
key={KEY_MODIFIED_AT}
cellRenderer={readableTimeCellRenderer}
dataKey={KEY_MODIFIED_AT}
disableSort
flexGrow={2}
label={__('last_modified_date')}
width={1}
/>,
<Column
key={KEY_SIZE}
cellRenderer={sizeCellRenderer()}
dataKey={KEY_SIZE}
disableSort
flexGrow={1}
label={__('size')}
width={1}
/>,
]}
</VirtualizedTable>
</div>
</Internationalize>
);
}
Expand Down
6 changes: 6 additions & 0 deletions src/lib/viewers/archive/ArchiveExplorer.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.bp-ArchiveExplorer {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
58 changes: 58 additions & 0 deletions src/lib/viewers/archive/Breadcrumbs.js
Original file line number Diff line number Diff line change
@@ -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<Object>} 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 (
<div className="bp-Breadcrumbs">
<Breadcrumb>
{view === VIEWS.VIEW_SEARCH ? (
<span>{__('search_results')}</span>
) : (
this.getPathItems(fullPath).map(pathItem => (
<PlainButton key={pathItem.path} onClick={() => onClick(pathItem.path)} type="button">
{pathItem.name}
</PlainButton>
))
)}
</Breadcrumb>
</div>
);
}
}

export default Breadcrumbs;
11 changes: 11 additions & 0 deletions src/lib/viewers/archive/Breadcrumbs.scss
Original file line number Diff line number Diff line change
@@ -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;
}
14 changes: 13 additions & 1 deletion src/lib/viewers/archive/__tests__/ArchiveExplorer-test-react.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ describe('lib/viewers/archive/ArchiveExplorer', () => {
});

describe('render()', () => {
it('should render VirtualizedTable', () => {
it('should render correct components', () => {
const component = shallow(<ArchiveExplorer itemCollection={data} />);

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);
});
Expand All @@ -86,6 +88,16 @@ describe('lib/viewers/archive/ArchiveExplorer', () => {
});
});

describe('handleClickFullPath()', () => {
it('should set state when handleClickFullPath() is called', () => {
const component = shallow(<ArchiveExplorer itemCollection={data} />);

component.instance().handleClickFullPath('test/subfolder/');

expect(component.state().fullPath).to.equal('test/subfolder/');
});
});

describe('getRowData()', () => {
it('should return correct row data', () => {
const component = shallow(<ArchiveExplorer itemCollection={data} />);
Expand Down
57 changes: 57 additions & 0 deletions src/lib/viewers/archive/__tests__/Breadcrumbs-test-react.js
Original file line number Diff line number Diff line change
@@ -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(<Breadcrumbs fullPath={fullPath} onClick={onClick} view={view} />);

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(<Breadcrumbs fullPath={fullPath} onClick={onClick} view={VIEWS.VIEW_SEARCH} />);

expect(component.find('span').text()).to.equal(__('search_results'));
});
});

describe('getPathItems()', () => {
it('should return correct path items', () => {
const component = shallow(<Breadcrumbs fullPath={fullPath} onClick={onClick} view={view} />);

const pathItems = component.instance().getPathItems(fullPath);

expect(pathItems).to.eql([
{
name: 'test',
path: 'test/',
},
{
name: 'subfolder',
path: 'test/subfolder/',
},
]);
});
});
});
8 changes: 6 additions & 2 deletions src/lib/viewers/archive/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 };

0 comments on commit d09738f

Please sign in to comment.