diff --git a/src/lib/viewers/archive/ArchiveExplorer.js b/src/lib/viewers/archive/ArchiveExplorer.js index cb127f553..8541ac219 100644 --- a/src/lib/viewers/archive/ArchiveExplorer.js +++ b/src/lib/viewers/archive/ArchiveExplorer.js @@ -15,7 +15,7 @@ import { import { addLocaleData } from 'react-intl'; import Breadcrumbs from './Breadcrumbs'; import SearchBar from './SearchBar'; -import { TABLE_COLUMNS, VIEWS } from './constants'; +import { ROOT_FOLDER, TABLE_COLUMNS, VIEWS } from './constants'; import './ArchiveExplorer.scss'; const language = __LANGUAGE__; // eslint-disable-line @@ -24,6 +24,7 @@ const { VIEW_FOLDER, VIEW_SEARCH } = VIEWS; class ArchiveExplorer extends React.Component { static propTypes = { + filename: PropTypes.string.isRequired, itemCollection: PropTypes.arrayOf( PropTypes.shape({ type: PropTypes.string.isRequired, @@ -47,10 +48,7 @@ class ArchiveExplorer extends React.Component { addLocaleData(intlLocaleData); this.state = { - // Trying to find the root folder - // The only way to tell what the root folder is - // is by comparing the name and absolute path, which differs by '/' - fullPath: props.itemCollection.find(info => info.name === info.absolute_path.slice(0, -1)).absolute_path, + fullPath: ROOT_FOLDER, searchQuery: '', sortBy: '', sortDirection: SortDirection.ASC, @@ -66,6 +64,16 @@ class ArchiveExplorer extends React.Component { * @return {Array} filtered itemlist for target folder */ getItemList = (itemCollection, fullPath) => { + if (fullPath === ROOT_FOLDER) { + // Trying to find the root items + // The only way to tell what the root items are + // is by comparing the name and absolute path, + // which are the same for files and differ by '/' for folders + return itemCollection.filter( + ({ name, absolute_path: path }) => name === path || name === path.slice(0, -1), + ); + } + const { item_collection: folderItems = [] } = itemCollection.find(item => item.absolute_path === fullPath); return itemCollection.filter(item => folderItems.includes(item.absolute_path)); }; @@ -176,7 +184,7 @@ class ArchiveExplorer extends React.Component { * @return {jsx} VirtualizedTable */ render() { - const { itemCollection } = this.props; + const { filename, itemCollection } = this.props; const { fullPath, searchQuery, sortBy, sortDirection, view } = this.state; const itemList = this.sortItemList( view === VIEW_SEARCH @@ -188,7 +196,12 @@ class ArchiveExplorer extends React.Component {
- +
{({ height }) => ( diff --git a/src/lib/viewers/archive/ArchiveViewer.js b/src/lib/viewers/archive/ArchiveViewer.js index 22eeaf28f..ddd8fd0af 100644 --- a/src/lib/viewers/archive/ArchiveViewer.js +++ b/src/lib/viewers/archive/ArchiveViewer.js @@ -71,7 +71,7 @@ class ArchiveViewer extends BaseViewer { try { /* global BoxArchive loaded from archive.js */ - this.archiveComponent = new BoxArchive(this.archiveEl, data); + this.archiveComponent = new BoxArchive(this.archiveEl, this.options.file.name, data); } catch (error) { throw new PreviewError(ERROR_CODE.LOAD_VIEWER, __('error_reupload'), error); } diff --git a/src/lib/viewers/archive/BoxArchive.js b/src/lib/viewers/archive/BoxArchive.js index 9c4227660..37cf0e697 100644 --- a/src/lib/viewers/archive/BoxArchive.js +++ b/src/lib/viewers/archive/BoxArchive.js @@ -10,9 +10,12 @@ class BoxArchive { * @param {Object} data - Archive data * @return {BoxArchive} Instance */ - constructor(archiveEl, data) { + constructor(archiveEl, filename, data) { this.archiveEl = archiveEl; - ReactDOM.render(, this.archiveEl); + ReactDOM.render( + , + this.archiveEl, + ); } /** diff --git a/src/lib/viewers/archive/Breadcrumbs.js b/src/lib/viewers/archive/Breadcrumbs.js index dd3189808..56140280b 100644 --- a/src/lib/viewers/archive/Breadcrumbs.js +++ b/src/lib/viewers/archive/Breadcrumbs.js @@ -2,11 +2,12 @@ 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 { ROOT_FOLDER, VIEWS } from './constants'; import './Breadcrumbs.scss'; class Breadcrumbs extends React.PureComponent { static propTypes = { + filename: PropTypes.string.isRequired, fullPath: PropTypes.string.isRequired, onClick: PropTypes.func.isRequired, view: PropTypes.string.isRequired, @@ -19,14 +20,14 @@ class Breadcrumbs extends React.PureComponent { * @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) => ({ + const { filename } = this.props; + const pathNames = fullPath === ROOT_FOLDER ? [] : fullPath.split('/').slice(0, -1); + const getPath = index => pathNames.slice(0, index + 1).join('/'); + const pathItems = pathNames.map((name, index) => ({ name, - path: `${getAbsolutePath(index)}/`, + path: `${getPath(index)}/`, })); + return [{ name: filename, path: ROOT_FOLDER }, ...pathItems]; }; /** diff --git a/src/lib/viewers/archive/__tests__/ArchiveExplorer-test-react.js b/src/lib/viewers/archive/__tests__/ArchiveExplorer-test-react.js index 6a32f8236..2e53cf4b5 100644 --- a/src/lib/viewers/archive/__tests__/ArchiveExplorer-test-react.js +++ b/src/lib/viewers/archive/__tests__/ArchiveExplorer-test-react.js @@ -2,15 +2,17 @@ import React from 'react'; import { shallow } from 'enzyme'; import sinon from 'sinon'; import ArchiveExplorer from '../ArchiveExplorer'; -import { TABLE_COLUMNS, VIEWS } from '../constants'; +import { TABLE_COLUMNS, VIEWS, ROOT_FOLDER } from '../constants'; const sandbox = sinon.sandbox.create(); let data; +let filename; const getComponent = props => shallow(); // eslint-disable-line describe('lib/viewers/archive/ArchiveExplorer', () => { beforeEach(() => { + filename = 'test.zip'; data = [ { type: 'folder', @@ -44,6 +46,14 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { size: 57379, item_collection: null, }, + { + type: 'file', + absolute_path: 'level-0.txt', + name: 'level-0.txt', + modified_at: '19-Nov-04 16:11', + size: 1, + item_collection: null, + }, ]; }); @@ -53,7 +63,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { describe('render()', () => { it('should render correct components', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); expect(component.find('.bp-ArchiveExplorer').length).to.equal(1); expect(component.find('SearchBar').length).to.equal(1); @@ -64,7 +74,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { describe('handleItemClick()', () => { it('should set state when handleItemClick() is called', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); component.instance().handleItemClick({ fullPath: 'test/subfolder/' }); @@ -76,7 +86,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { describe('handleBreadcrumbClick()', () => { it('should set state when handleBreadcrumbClick() is called', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); component.instance().handleBreadcrumbClick('test/subfolder/'); @@ -86,7 +96,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { describe('getRowData()', () => { it('should return correct row data', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); const rowData = component.instance().getRowData(data)({ index: 0 }); @@ -112,9 +122,13 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { describe('getItemList()', () => { it('should return correct item list', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); + + let itemList = component.instance().getItemList(data, ROOT_FOLDER); + + expect(itemList).to.eql([data[0], data[4]]); - const itemList = component.instance().getItemList(data, 'test/'); + itemList = component.instance().getItemList(data, 'test/'); expect(itemList).to.eql([data[1], data[2]]); }); @@ -122,7 +136,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { describe('handleSearch()', () => { it('should set correct state when search query is not empty', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); component.instance().handleSearch('test'); expect(component.state().searchQuery).to.equal('test'); @@ -140,7 +154,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { describe('getSearchResult()', () => { it('should return correct item list', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); const itemList = component.instance().getSearchResult(data, 'level-1'); const fuzzyList = component.instance().getSearchResult(data, 'leel1'); @@ -152,7 +166,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { describe('handleSort()', () => { it('should set the sort direction and type', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); const instance = component.instance(); instance.handleSort({ sortBy: 'name', sortDirection: 'DESC' }); @@ -164,7 +178,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { describe('sortItemList()', () => { it('should sort itemList by size and be in ASC order', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); const instance = component.instance(); const itemList = instance.getItemList(data, 'test/'); @@ -175,7 +189,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { }); it('should sort itemList by name and be in DESC order', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); const instance = component.instance(); const itemList = instance.getItemList(data, 'test/'); @@ -186,7 +200,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { }); it('should sort itemList by name and be in ASC order', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); const instance = component.instance(); const itemList = instance.getItemList(data, 'test/'); @@ -197,7 +211,7 @@ describe('lib/viewers/archive/ArchiveExplorer', () => { }); it('should not sort itemList', () => { - const component = getComponent({ itemCollection: data }); + const component = getComponent({ filename, itemCollection: data }); const instance = component.instance(); const itemList = instance.getItemList(data, 'test/'); diff --git a/src/lib/viewers/archive/__tests__/BoxArchive-test.js b/src/lib/viewers/archive/__tests__/BoxArchive-test.js index 8c79e2a7f..cf6ff2495 100644 --- a/src/lib/viewers/archive/__tests__/BoxArchive-test.js +++ b/src/lib/viewers/archive/__tests__/BoxArchive-test.js @@ -31,7 +31,7 @@ describe('lib/viewers/archive/BoxArchive', () => { sandbox.stub(ReactDOM, 'render'); sandbox.stub(ReactDOM, 'unmountComponentAtNode'); - archiveComponent = new BoxArchive(containerEl, []); + archiveComponent = new BoxArchive(containerEl, 'test.zip', []); archiveComponent.archiveExplorer = {}; archiveComponent.destroy(); archiveComponent = null; @@ -45,7 +45,7 @@ describe('lib/viewers/archive/BoxArchive', () => { const renderStub = sandbox.stub(ReactDOM, 'render'); const data = [{ name: 'test.json' }]; - archiveComponent = new BoxArchive(containerEl, data); + archiveComponent = new BoxArchive(containerEl, 'test.zip', data); const archiveExplorer = renderStub.firstCall.args[0]; expect(archiveExplorer.props.itemCollection).to.equal(data); diff --git a/src/lib/viewers/archive/__tests__/Breadcrumbs-test-react.js b/src/lib/viewers/archive/__tests__/Breadcrumbs-test-react.js index 7c507dbee..861655c83 100644 --- a/src/lib/viewers/archive/__tests__/Breadcrumbs-test-react.js +++ b/src/lib/viewers/archive/__tests__/Breadcrumbs-test-react.js @@ -2,15 +2,19 @@ import React from 'react'; import { shallow } from 'enzyme'; import sinon from 'sinon'; import Breadcrumbs from '../Breadcrumbs'; -import { VIEWS } from '../constants'; +import { ROOT_FOLDER, VIEWS } from '../constants'; const sandbox = sinon.sandbox.create(); +let filename; let fullPath; let onClick; let view; +const getComponent = props => shallow(); + describe('lib/viewers/archive/Breadcrumbs', () => { beforeEach(() => { + filename = 'test.zip'; fullPath = 'test/subfolder/'; onClick = sandbox.stub(); view = VIEWS.VIEW_FOLDER; @@ -22,27 +26,43 @@ describe('lib/viewers/archive/Breadcrumbs', () => { describe('render()', () => { it('should render correct components', () => { - const component = shallow(); + const component = getComponent({ filename, fullPath, onClick, 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); + expect(component.find('PlainButton').length).to.equal(3); }); it('should render search result if view is search', () => { - const component = shallow(); + const component = getComponent({ filename, fullPath, onClick, view: VIEWS.VIEW_SEARCH }); expect(component.find('span').text()).to.equal(__('search_results')); }); }); describe('getPathItems()', () => { + it('should return root folder', () => { + const component = getComponent({ filename, fullPath, onClick, view }); + const pathItems = component.instance().getPathItems(ROOT_FOLDER); + + expect(pathItems).to.eql([ + { + name: filename, + path: ROOT_FOLDER, + }, + ]); + }); + it('should return correct path items', () => { - const component = shallow(); + const component = getComponent({ filename, fullPath, onClick, view }); const pathItems = component.instance().getPathItems(fullPath); expect(pathItems).to.eql([ + { + name: filename, + path: ROOT_FOLDER, + }, { name: 'test', path: 'test/', diff --git a/src/lib/viewers/archive/constants.js b/src/lib/viewers/archive/constants.js index 9b6d16efa..0f6ca7d19 100644 --- a/src/lib/viewers/archive/constants.js +++ b/src/lib/viewers/archive/constants.js @@ -1,3 +1,5 @@ +const ROOT_FOLDER = 'root/'; + const TABLE_COLUMNS = { KEY_MODIFIED_AT: 'modified_at', KEY_NAME: 'name', @@ -9,4 +11,4 @@ const VIEWS = { VIEW_SEARCH: 'search', }; -export { TABLE_COLUMNS, VIEWS }; +export { ROOT_FOLDER, TABLE_COLUMNS, VIEWS };