Skip to content

Commit

Permalink
feat(archive-viewer): add archive loader, viewer, and archive explorer
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingze Xiao committed Dec 13, 2019
1 parent dc71bed commit 2c13107
Show file tree
Hide file tree
Showing 22 changed files with 1,134 additions and 23 deletions.
2 changes: 2 additions & 0 deletions build/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ module.exports = config =>
`src/third-party/model3d/${MODEL3D_STATIC_ASSETS_VERSION}/**/*.js`,
`src/third-party/swf/${SWF_STATIC_ASSETS_VERSION}/**/*.js`,
`src/third-party/text/${TEXT_STATIC_ASSETS_VERSION}/**/*.js`,
'build/karma.setup.react.js',
].concat(getTestFile(config.src)),

preprocessors: {
'build/karma.setup.react.js': ['webpack', 'sourcemap'],
'src/**/__tests__/**/*-test.js': ['webpack', 'sourcemap'],
'src/**/__tests__/**/*-test.html': ['html2js'],
},
Expand Down
10 changes: 10 additions & 0 deletions build/karma.setup.react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

function importAll(r) {
r.keys().forEach(r);
}

importAll(require.context('../src/lib/viewers/archive/__tests__', true, /-test-react\.js$/));
6 changes: 5 additions & 1 deletion build/webpack.common.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ module.exports = language => {
{
test: /\.s?css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'],
include: [path.resolve('src/lib'), path.resolve('node_modules/box-annotations')],
include: [
path.resolve('src/lib'),
path.resolve('node_modules/box-annotations'),
path.resolve('node_modules/box-ui-elements'),
],
},
{
test: /\.(svg|html)$/,
Expand Down
1 change: 1 addition & 0 deletions build/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ function updateConfig(conf, language, index) {
annotations: ['box-annotations'],
preview: [`${lib}/Preview.js`],
csv: [`${lib}/viewers/text/BoxCSV.js`],
archive: [`${lib}/viewers/archive/BoxArchive.js`],
},
mode: isProd ? 'production' : 'development',
optimization: {
Expand Down
10 changes: 1 addition & 9 deletions build/webpack.karma.config.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
require('babel-polyfill');

const { argv } = process;
const isDebug = argv.find(arg => {
return arg === '--auto-watch' || arg === '--no-single-run';
});

const { IgnorePlugin } = require('webpack');
const commonConfig = require('./webpack.common.config');

const baseConfig = commonConfig('en-US');

const config = {
...baseConfig,
devtool: 'inline-source-map',
mode: 'development',
resolve: {
alias: {
Expand All @@ -20,10 +16,6 @@ const config = {
},
};

if (isDebug) {
config.devtool = 'inline-source-map';
}

config.plugins.push(
new IgnorePlugin(/react\/addons/),
new IgnorePlugin(/react\/lib\/ReactContext/),
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"babel-plugin-react-remove-properties": "^0.3.0",
"babel-plugin-transform-require-ignore": "^0.1.1",
"box-annotations": "^2.3.0",
"box-react-ui": "^22.7.0",
"box-ui-elements": "^11.1.0-beta.18",
"chai": "^4.2.0",
"chai-dom": "^1.8.1",
"conventional-changelog-cli": "^2.0.23",
Expand All @@ -36,6 +36,8 @@
"css-loader": "^3.1.0",
"cssnano-cli": "^1.0.5",
"cypress": "^3.4.1",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.15.1",
"eslint": "^6.3.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-config-prettier": "^6.2.0",
Expand Down Expand Up @@ -89,6 +91,8 @@
"raw-loader": "^3.1.0",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-intl": "^2.9.0",
"react-tether": "^1.0.0",
"react-virtualized": "^9.13.0",
"sass-loader": "^7.1.0",
"sinon": "^7.4.2",
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/en-US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ error_not_downloadable=Oops! It looks like something is wrong with this file. We
# Preview error message shown when flash is not enabled on their browser
error_flash_not_enabled=We’re sorry, the preview didn’t load because Flash is not enabled on your browser. If possible, please enable Flash and refresh the page.

# Archive Preview
# Label for filename column name
filename=Filename
# Label for last modified date column name
last_modified_date=Last modified date
# Label for size column name
size=Size

# Media Preview
# Label for autoplay in media player
media_autoplay=Autoplay
Expand Down
1 change: 1 addition & 0 deletions src/lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export const STATUS_SUCCESS = 'success';
export const STATUS_VIEWABLE = 'viewable';

// X-Rep-Hints for Representations API
export const X_REP_HINT_ARCHIVE = '[json]';
export const X_REP_HINT_BASE = '[3d][pdf][text][mp3]';
export const X_REP_HINT_DOC_THUMBNAIL = '[jpg?dimensions=1024x1024&paged=false]';
export const X_REP_HINT_IMAGE = '[jpg?dimensions=2048x2048,png?dimensions=2048x2048]';
Expand Down
2 changes: 1 addition & 1 deletion src/lib/util.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Uri from 'jsuri';
import { decode } from 'box-react-ui/lib/utils/keys';
import { decode } from 'box-ui-elements/es/utils/keys';
import DownloadReachability from './DownloadReachability';
import Location from './Location';
import PreviewError from './PreviewError';
Expand Down
8 changes: 8 additions & 0 deletions src/lib/viewers/archive/Archive.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@import '../../boxuiVariables';

.bp-archive {
display: flex;
width: 100%;
height: 100%;
background: $white;
}
170 changes: 170 additions & 0 deletions src/lib/viewers/archive/ArchiveExplorer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import get from 'lodash/get';
import Internationalize from 'box-ui-elements/es/elements/common/Internationalize';
import {
readableTimeCellRenderer,
sizeCellRenderer,
itemNameCellRenderer,
} from 'box-ui-elements/es/features/virtualized-table-renderers';
import VirtualizedTable from 'box-ui-elements/es/features/virtualized-table';
import { Column } from 'react-virtualized/dist/es/Table/index';
import { TABLE_COLUMNS } from './constants';

const { KEY_NAME, KEY_MODIFIED_AT, KEY_SIZE } = TABLE_COLUMNS;

class ArchiveExplorer extends React.Component {
static propTypes = {
itemCollection: PropTypes.arrayOf(
PropTypes.shape({
type: PropTypes.string.isRequired,
absolute_path: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
modified_at: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
path_collection: PropTypes.shape({
total_count: PropTypes.number,
entries: PropTypes.arrayOf(
PropTypes.shape({
type: PropTypes.string,
absolute_path: PropTypes.string,
name: PropTypes.string,
}),
),
}),
parent: PropTypes.string,
item_collection: PropTypes.shape({
total_count: PropTypes.number,
entries: PropTypes.arrayOf(
PropTypes.shape({
type: PropTypes.string,
absolute_path: PropTypes.string.isRequired,
name: PropTypes.string,
}),
).isRequired,
}).isRequired,
}),
).isRequired,
};

/**
* [constructor]
*
* @param {Object} props - React element properties
*/
constructor(props) {
super(props);

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

/**
* Filter itemlist for target folder
*
* @param {Array<Object>} itemCollection - raw data
* @param {string} fullPath - target folder path
* @return {Array<Object>} filtered itemlist for target folder
*/
getItemList = (itemCollection, fullPath) => {
const folderInfo = itemCollection.find(item => item.absolute_path === fullPath);
const subItems = get(folderInfo, 'item_collection.entries');
if (!subItems) {
return [];
}
const subItemsPath = subItems.map(item => item.absolute_path);

return itemCollection.filter(item => subItemsPath.includes(item.absolute_path));
};

/**
* Prepare data to render
* Will be passed as row getter into VirtaulizedTable
*
* @param {Array<Object>} itemList - list of data object
* @param {number} index - row index of the data to selected
* @return {Object} formatted data
*/
getRowData = itemList => ({ index }) => {
const { modified_at: modifiedAt, name, size, type, ...rest } = itemList[index];

return {
[KEY_NAME]: {
isExternal: false,
name,
type,
},
// TODO: fix when conversion changes it to standard date format
[KEY_MODIFIED_AT]: `20${modifiedAt}`,
[KEY_SIZE]: size,
...rest,
};
};

/**
* Handle click event, update fullPath state
*
* @param {Object} cellValue - the cell being clicked
* @return {void}
*/
handleClick = ({ name }) => {
const { fullPath } = this.state;
this.setState({
fullPath: `${fullPath}${name}/`,
});
};

/**
* render data
*
* @return {jsx} VirtualizedTable
*/
render() {
const { itemCollection } = this.props;
const { fullPath } = this.state;
const itemList = this.getItemList(itemCollection, fullPath);

return (
<Internationalize language="en-us" messages={{}}>
<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>
</Internationalize>
);
}
}

export default ArchiveExplorer;
17 changes: 17 additions & 0 deletions src/lib/viewers/archive/ArchiveLoader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import AssetLoader from '../AssetLoader';
import ArchiveViewer from './ArchiveViewer';

const VIEWERS = [
{
NAME: 'Archive',
CONSTRUCTOR: ArchiveViewer,
REP: 'json',
EXT: ['jar', 'zip'],
},
];

class ArchiveLoader extends AssetLoader {
viewers = VIEWERS;
}

export default new ArchiveLoader();
Loading

0 comments on commit 2c13107

Please sign in to comment.