Skip to content

Commit

Permalink
feat(archive): Add root folder (#1149)
Browse files Browse the repository at this point in the history
* feat(archive): Add root folder

* feat(archive): Address comments

* feat(archive): Add missed files for root folder

* feat(archive): Address comments

* feat(archive): Address comments

* feat(archive): Change root folder name to filename

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
Mingze and mergify[bot] committed Jan 14, 2020
1 parent 7e4abd3 commit c47e6b6
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 39 deletions.
27 changes: 20 additions & 7 deletions src/lib/viewers/archive/ArchiveExplorer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -66,6 +64,16 @@ class ArchiveExplorer extends React.Component {
* @return {Array<Object>} 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));
};
Expand Down Expand Up @@ -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
Expand All @@ -188,7 +196,12 @@ class ArchiveExplorer extends React.Component {
<Internationalize language={language} messages={elementsMessages}>
<div className="bp-ArchiveExplorer" data-resin-feature="archive">
<SearchBar onSearch={this.handleSearch} searchQuery={searchQuery} />
<Breadcrumbs fullPath={fullPath} onClick={this.handleBreadcrumbClick} view={view} />
<Breadcrumbs
filename={filename}
fullPath={fullPath}
onClick={this.handleBreadcrumbClick}
view={view}
/>
<div className="bp-ArchiveExplorer-table">
<AutoSizer disableWidth>
{({ height }) => (
Expand Down
2 changes: 1 addition & 1 deletion src/lib/viewers/archive/ArchiveViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
7 changes: 5 additions & 2 deletions src/lib/viewers/archive/BoxArchive.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(<ArchiveExplorer ref={this.setRef} itemCollection={data} />, this.archiveEl);
ReactDOM.render(
<ArchiveExplorer ref={this.setRef} filename={filename} itemCollection={data} />,
this.archiveEl,
);
}

/**
Expand Down
15 changes: 8 additions & 7 deletions src/lib/viewers/archive/Breadcrumbs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -19,14 +20,14 @@ class Breadcrumbs extends React.PureComponent {
* @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) => ({
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];
};

/**
Expand Down
42 changes: 28 additions & 14 deletions src/lib/viewers/archive/__tests__/ArchiveExplorer-test-react.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(<ArchiveExplorer {...props} />); // eslint-disable-line

describe('lib/viewers/archive/ArchiveExplorer', () => {
beforeEach(() => {
filename = 'test.zip';
data = [
{
type: 'folder',
Expand Down Expand Up @@ -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,
},
];
});

Expand All @@ -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);
Expand All @@ -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/' });

Expand All @@ -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/');

Expand All @@ -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 });

Expand All @@ -112,17 +122,21 @@ 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]]);
});
});

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');
Expand All @@ -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');
Expand All @@ -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' });
Expand All @@ -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/');

Expand All @@ -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/');

Expand All @@ -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/');

Expand All @@ -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/');

Expand Down
4 changes: 2 additions & 2 deletions src/lib/viewers/archive/__tests__/BoxArchive-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
30 changes: 25 additions & 5 deletions src/lib/viewers/archive/__tests__/Breadcrumbs-test-react.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(<Breadcrumbs {...props} />);

describe('lib/viewers/archive/Breadcrumbs', () => {
beforeEach(() => {
filename = 'test.zip';
fullPath = 'test/subfolder/';
onClick = sandbox.stub();
view = VIEWS.VIEW_FOLDER;
Expand All @@ -22,27 +26,43 @@ describe('lib/viewers/archive/Breadcrumbs', () => {

describe('render()', () => {
it('should render correct components', () => {
const component = shallow(<Breadcrumbs fullPath={fullPath} onClick={onClick} view={view} />);
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(<Breadcrumbs fullPath={fullPath} onClick={onClick} view={VIEWS.VIEW_SEARCH} />);
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(<Breadcrumbs fullPath={fullPath} onClick={onClick} view={view} />);
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/',
Expand Down
4 changes: 3 additions & 1 deletion src/lib/viewers/archive/constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const ROOT_FOLDER = 'root/';

const TABLE_COLUMNS = {
KEY_MODIFIED_AT: 'modified_at',
KEY_NAME: 'name',
Expand All @@ -9,4 +11,4 @@ const VIEWS = {
VIEW_SEARCH: 'search',
};

export { TABLE_COLUMNS, VIEWS };
export { ROOT_FOLDER, TABLE_COLUMNS, VIEWS };

0 comments on commit c47e6b6

Please sign in to comment.