Skip to content

Commit

Permalink
add uploader w/ test files
Browse files Browse the repository at this point in the history
  • Loading branch information
n7best committed Feb 26, 2016
1 parent aeca971 commit 065c51d
Show file tree
Hide file tree
Showing 14 changed files with 325 additions and 4 deletions.
Binary file modified .DS_Store
Binary file not shown.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
coverage
lib
node_modules
npm-debug.log
npm-debug.log
.DS_Store
Binary file added example/.DS_Store
Binary file not shown.
Binary file added example/pages/.DS_Store
Binary file not shown.
Binary file added example/pages/cell/.DS_Store
Binary file not shown.
Binary file added example/pages/cell/images/.DS_Store
Binary file not shown.
Binary file added example/pages/cell/images/avatar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 45 additions & 1 deletion example/pages/cell/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,37 @@ import { ButtonArea,
Switch,
Radio,
Checkbox,
Select
Select,
Uploader
} from '../../../src/index';
import Page from '../../component/page';
import iconSrc from './images/icon.png';
import vcodeSrc from './images/vcode.jpg';
import avatarSrc from './images/avatar.jpg';

export default class CellDemo extends React.Component {
state = {
demoFiles : [
{
url: avatarSrc,
onClick: e=>alert('事件测试')
},
{
url: avatarSrc
},
{
url: avatarSrc
},
{
url: avatarSrc,
error: true
},
{
url: avatarSrc,
status: '50%'
}
]
};

render() {
return (
Expand Down Expand Up @@ -207,6 +231,26 @@ export default class CellDemo extends React.Component {
<Button type="default">取消</Button>
</ButtonArea>

<CellsTitle>上传</CellsTitle>
<Form>
<FormCell>
<CellBody>
<Uploader
title="图片上传"
maxCount={6}
files={this.state.demoFiles}
onError={msg => alert(msg)}
onChange={file => {
let newFiles = [...this.state.demoFiles, {url:file.data}];
this.setState({
demoFiles: newFiles
});
}}
/>
</CellBody>
</FormCell>
</Form>

<CellsTitle>文本域</CellsTitle>
<Form>
<FormCell>
Expand Down
Binary file added src/.DS_Store
Binary file not shown.
Binary file added src/components/.DS_Store
Binary file not shown.
4 changes: 3 additions & 1 deletion src/components/form/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Switch from './switch';
import Radio from './radio';
import Checkbox from './checkbox';
import Select from './select';
import Uploader from './uploader';

export default {
Form,
Expand All @@ -21,5 +22,6 @@ export default {
Switch,
Radio,
Checkbox,
Select
Select,
Uploader
};
134 changes: 134 additions & 0 deletions src/components/form/uploader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**
* Created by n7best
*/


import React, { Component, PropTypes } from 'react';
import classNames from 'classnames';

export default class Uploader extends React.Component {
static propTypes = {
title: PropTypes.string,
maxCount: PropTypes.number,
maxWidth: PropTypes.number,
onChange: PropTypes.func,
onError: PropTypes.func,
files: PropTypes.array,
lang: PropTypes.object
};

static defaultProps = {
title: '图片上传',
maxCount: 4,
maxWidth: 500,
files: [],
onChange: undefined,
onError: undefined,
lang:{
maxError: maxCount => `最多只能上传${maxCount}张图片`
}
};

handleFile(file,cb) {
let reader = new FileReader();
reader.onload = e => {
let img = new Image();
img.onload = ()=>{
let w = Math.min(this.props.maxWidth, img.width);
let h = img.height * (w / img.width);
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
canvas.width = w;
canvas.height = h;
ctx.drawImage(img, 0, 0, w, h);
let base64 = canvas.toDataURL('image/png');
cb({
lastModified: file.lastModified,
lastModifiedDate: file.lastModifiedDate,
name: file.name,
size: file.size,
type: file.type,
data: base64
});
};
img.src = e.target.result;
}
reader.readAsDataURL(file);
}

handleChange(e) {
const langs = this.props.lang;
let _files = e.target.files;

if(_files.length === 0) return;

if(this.props.files.length >= this.props.maxCount) {
this.props.onError(langs.maxError(this.props.maxCount));
return;
}

for(let key in _files) {
if (!_files.hasOwnProperty(key)) continue;
let file = _files[key];
this.handleFile(file, _file=>{
if(this.props.onChange) this.props.onChange(_file, e);
});
}
}

renderFiles(){
return this.props.files.map((file, idx)=>{
let {url, error, status, ...others} = file;
let fileStyle = {
backgroundImage: `url(${url})`
};
let cls = classNames({
weui_uploader_file: true,
weui_uploader_status: error || status
});

return (
<li className={cls} key={idx} style={fileStyle} {...others}>
{
error || status ?
<div className="weui_uploader_status_content">
{ error ? <i className="weui_icon_warn"></i> : status }
</div>
: false
}
</li>
);
});
}

render(){
const { className, title, maxCount, files, onChange, ...others } = this.props;
const cls = classNames({
weui_uploader: true,
[className]: className
});

return (
<div className={cls}>
<div className="weui_uploader_hd weui_cell">
<div className="weui_cell_bd weui_cell_primary">{title}</div>
<div className="weui_cell_ft">{files.length}/{maxCount}</div>
</div>
<div className="weui_uploader_bd">
<ul className="weui_uploader_files">
{this.renderFiles()}
</ul>
<div className="weui_uploader_input_wrp">
<input
className="weui_uploader_input"
type="file"
accept="image/jpg,image/jpeg,image/png,image/gif"
onChange={this.handleChange.bind(this)}
{...others}
/>
</div>
</div>
</div>
);
}
};
3 changes: 2 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import {Button, ButtonArea} from './components/button/index';
import {Cells, CellsTitle, CellsTips, Cell, CellHeader, CellBody, CellFooter} from './components/cell/index';
import Mask from './components/mask/index';
import {Form, FormCell, TextArea, Input, Switch, Radio, Checkbox, Select} from './components/form/index';
import {Form, FormCell, TextArea, Input, Switch, Radio, Checkbox, Select, Uploader} from './components/form/index';
import Label from './components/label/index';
import Toast from './components/toast/index';
import Progress from './components/progress/index';
Expand Down Expand Up @@ -35,6 +35,7 @@ export default {
TextArea,
Switch,
Select,
Uploader,
Label,
Toast,
Progress,
Expand Down
139 changes: 139 additions & 0 deletions test/uploader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/**
* Created by n7best.
*/

"use strict";

import React from 'react';
import { shallow } from 'enzyme';
import assert from 'assert';
import WeUI from '../src/index';

const {Uploader} = WeUI;
const files = [
{
data: 'http://mmrmb.github.io/avatar/bear.jpg',
onClick: e=>alert('事件测试')
},
{
data: 'http://mmrmb.github.io/avatar/bear.jpg'
},
{
data: 'http://mmrmb.github.io/avatar/bear.jpg'
},
{
data: 'http://mmrmb.github.io/avatar/bear.jpg',
error: true
},
{
data: 'http://mmrmb.github.io/avatar/bear.jpg',
status: '50%'
}
];
const title = '提示';
const enlang = {
maxError: maxCount => `Max ${maxCount} photos allowed`
};
describe('<Uploader></Uploader>', ()=> {
[enlang, undefined].map(lang=> {
[undefined, 5, 30].map(maxCount=> {
[files, []].map(files=> {
describe(`<Uploader lang=${lang} title=${title} files=${files} maxCount=${maxCount}></Uploader>`, ()=> {
let verifyFiles = {};
let verifyErrors;
const wrapper = shallow(
<Uploader lang={lang} title={title} files={files} maxCount={maxCount} onError={msg=>verifyErrors=msg} onChange={_files=>verifyFiles=_files}/>
);

it('should render <Uploader></Uploader> component', () => {
assert(wrapper.instance() instanceof Uploader);
assert(wrapper.hasClass('weui_uploader'));
});

it('should render header with class weui_uploader_hd, weui_cell', () => {
assert(wrapper.children().first().hasClass('weui_uploader_hd'));
assert(wrapper.children().first().hasClass('weui_cell'));
});

it('should render body with class weui_uploader_bd', () => {
assert(wrapper.children().last().hasClass('weui_uploader_bd'));
});

let bd = wrapper.children().last().children();

it('should render lists container with weui_uploader_files', () => {
assert(bd.find('ul').hasClass('weui_uploader_files'));
});

it('should render input wrapper with weui_uploader_input_wrp', () => {
assert(bd.last().hasClass('weui_uploader_input_wrp'));
});

it('should render input with weui_uploader_input', () => {
assert(bd.last().find('input').hasClass('weui_uploader_input'));
});

it('should render file preview with weui_uploader_file', () => {
if(files.length > 0){
assert(bd.first().find('ul').children().first().hasClass('weui_uploader_file'));
}
});

it('should render file preview with weui_uploader_status when error is true or status is set', () => {
if(files.length > 0){
assert(bd.first().find('ul').children().at(3).hasClass('weui_uploader_status'));
assert(bd.first().find('ul').children().at(4).hasClass('weui_uploader_status'));
}
});

it('should render div with weui_uploader_status_content when error is true or status is set', () => {
if(files.length > 0){
assert(bd.first().find('ul').children().at(3).find('div').hasClass('weui_uploader_status_content'));
assert(bd.first().find('ul').children().at(4).find('div').hasClass('weui_uploader_status_content'));
}
});

it('should render icon with weui_icon_warn when error is true', () => {
if(files.length > 0){
assert(bd.first().find('ul').children().at(3).find('div').find('i').hasClass('weui_icon_warn'));
}
});

it('should render status when status is set', () => {
if(files.length > 0){
assert.equal('50%',bd.first().find('ul').children().at(4).find('div').text());
}
});

it('should render chinese error message', () => {
let _maxCount = maxCount ? maxCount : 4;
if(files.length > _maxCount && !lang){
verifyErrors = '';
let expectedmsg = `最多只能上传${_maxCount}张图片`;
let input = assert(bd.last().find('input'));
let changefiles = { 0: {name:'foo', size: 500001} };
bd.last().find('input').simulate('change',{target:{files:changefiles}});
assert.equal(expectedmsg,verifyErrors);
}
});

it('should render english error message', () => {
let _maxCount = maxCount ? maxCount : 4;
if(files.length > _maxCount && lang){
verifyErrors = '';
let expectedmsg = `Max ${_maxCount} photos allowed`;
let input = assert(bd.last().find('input'));
let changefiles = { 0: {name:'foo', size: 500001} };
bd.last().find('input').simulate('change',{target:{files:changefiles}});
assert.equal(expectedmsg,verifyErrors);
}
});

it('should render files', () => {
//currently can't test filereaders
});
});
});
});
});
});

0 comments on commit 065c51d

Please sign in to comment.