Skip to content

Commit

Permalink
Basic mode for FileUpload and refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Çağatay Çivici committed Sep 9, 2017
1 parent 0a1d725 commit dbb8471
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 62 deletions.
5 changes: 1 addition & 4 deletions src/components/fileupload/FileUpload.css
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,4 @@

.ui-fluid .ui-fileupload-content .ui-button-icon-only {
width: 2em;
}



}
184 changes: 131 additions & 53 deletions src/components/fileupload/FileUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class FileUpload extends Component {
id: null,
name: null,
url: null,
mode: 'advanced',
multiple: false,
accept: null,
disabled: false,
Expand All @@ -21,6 +22,7 @@ export class FileUpload extends Component {
invalidFileSizeMessageDetail: 'maximum upload size is {0}.',
style: null,
className: null,
widthCredentials: false,
previewWidth: 50,
chooseLabel: 'Choose',
uploadLabel: 'Upload',
Expand All @@ -30,13 +32,15 @@ export class FileUpload extends Component {
onUpload: null,
onError: null,
onClear: null,
onSelect: null
onSelect: null,
onProgress: null
}

static propTypes = {
id: PropTypes.string,
name: PropTypes.string,
url: PropTypes.string,
mode: PropTypes.string,
multiple: PropTypes.bool,
accept: PropTypes.string,
disabled: PropTypes.bool,
Expand All @@ -46,6 +50,7 @@ export class FileUpload extends Component {
invalidFileSizeMessageDetail: PropTypes.string,
style: PropTypes.object,
className: PropTypes.string,
widthCredentials: PropTypes.bool,
previewWidth: PropTypes.number,
chooseLabel: PropTypes.string,
uploadLabel: PropTypes.string,
Expand All @@ -55,19 +60,27 @@ export class FileUpload extends Component {
onUpload: PropTypes.func,
onError: PropTypes.func,
onClear: PropTypes.func,
onSelect: PropTypes.func
onSelect: PropTypes.func,
onProgress: PropTypes.func
};

constructor(props) {
super(props);
this.state = {files:[], msgs: []};
this.state = {
files:[],
msgs: []
};

this.upload = this.upload.bind(this);
this.clear = this.clear.bind(this);
this.onFileSelect = this.onFileSelect.bind(this);
this.onDragEnter = this.onDragEnter.bind(this);
this.onDragOver = this.onDragOver.bind(this);
this.onDragLeave = this.onDragLeave.bind(this);
this.onDrop = this.onDrop.bind(this);
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
this.onSimpleUploaderClick = this.onSimpleUploaderClick.bind(this);
}

hasFiles() {
Expand All @@ -79,10 +92,15 @@ export class FileUpload extends Component {
}

remove(index) {
var currentFiles = [...this.state.files];
this.clearInputElement();
let currentFiles = [...this.state.files];
currentFiles.splice(index, 1);
this.setState({files: currentFiles});
}

clearInputElement() {
this.fileInput.value = '';
}

formatSize(bytes) {
if(bytes === 0) {
Expand All @@ -98,9 +116,9 @@ export class FileUpload extends Component {

onFileSelect(event) {
this.setState({msgs:[]});
var selectedFiles = event.dataTransfer ? event.dataTransfer.files : event.target.files;
for(let i = 0; i < selectedFiles.length; i++) {
let file = selectedFiles[i];
let files = event.dataTransfer ? event.dataTransfer.files : event.target.files;

for(let file of files) {
if(this.validate(file)) {
if(this.isImage(file)) {
file.objectURL = window.URL.createObjectURL(file);
Expand All @@ -109,14 +127,20 @@ export class FileUpload extends Component {
this.setState({files: [...this.state.files, file]});
}
}

if(this.props.onSelect) {
this.props.onSelect({originalEvent: event, files: this.state.files});
}

if(this.hasFiles() && this.props.auto) {
this.upload();
}

this.clearInputElement();

if(this.props.mode === 'basic') {
this.fileInput.style.display = 'none';
}
}

validate(file) {
Expand All @@ -136,8 +160,8 @@ export class FileUpload extends Component {

upload() {
this.setState({msgs:[]});
var xhr = new XMLHttpRequest();
var formData = new FormData();
let xhr = new XMLHttpRequest();
let formData = new FormData();

if(this.props.onBeforeUpload) {
this.props.onBeforeUpload({
Expand All @@ -146,27 +170,36 @@ export class FileUpload extends Component {
});
}

for(var file of this.state.files) {
for(let file of this.state.files) {
formData.append(this.props.name, file, file.name);
}

xhr.upload.addEventListener('progress', (event) => {
if(event.lengthComputable) {
this.setState({progress: Math.round((event.loaded * 100) / event.total)});
this.setState({progress: Math.round((event.loaded * 100) / event.total)});
}
}, false);

if(this.props.onProgress) {
this.props.onProgress({
originalEvent: event,
progress: this.progress
});
};
});

xhr.onreadystatechange = () => {
if(xhr.readyState === 4) {
this.setState({progress: 0});

if(xhr.status >= 200 && xhr.status < 300) {
if(this.props.onUpload)
if(this.props.onUpload) {
this.props.onUpload({xhr: xhr, files: this.files});
}
}
else {
if(this.props.onError)
this.props.onError.emit({xhr: xhr, files: this.files});
if(this.props.onError) {
this.props.onError({xhr: xhr, files: this.files});
}
}

this.clear();
Expand All @@ -182,15 +215,25 @@ export class FileUpload extends Component {
});
}

xhr.withCredentials = this.props.withCredentials;

xhr.send(formData);
}

clear() {
this.setState({files:[]});

if(this.props.onClear) {
this.props.onClear();
}
this.clearInputElement();
}

onFocus(event) {
DomHandler.addClass(event.currentTarget.parentElement, 'ui-state-focus');
}

onBlur(event) {
DomHandler.removeClass(event.currentTarget.parentElement, 'ui-state-focus');
}

onDragEnter(event) {
Expand Down Expand Up @@ -220,58 +263,93 @@ export class FileUpload extends Component {
event.stopPropagation();
event.preventDefault();

this.onFileSelect(event);
let files = event.dataTransfer ? event.dataTransfer.files : event.target.files;
let allowDrop = this.props.multiple||(files && files.length === 1);

if(allowDrop) {
this.onFileSelect(event);
}
}
}

render() {
var className = classNames('ui-fileupload ui-widget', this.props.className);
var chooseButton = <Button label={this.props.chooseLabel} icon="fa-plus" className="ui-fileupload-choose" disabled={this.props.disabled}>
<input type="file" onChange={this.onFileSelect} multiple={this.props.multiple} accept={this.props.accept} disabled={this.props.disabled}/>
</Button>;

if(!this.props.auto) {
var uploadButton = <Button label={this.props.uploadLabel} icon="fa-upload" onClick={this.upload} disabled={this.props.disabled} />;
var cancelButton = <Button label={this.props.cancelLabel }icon="fa-close" onClick={this.clear} disabled={this.props.disabled} />;

onSimpleUploaderClick() {
if(this.hasFiles()) {
this.upload();
this.fileInput.style.display = 'inline';
}
}

componentWillUnmount() {

}

if(this.hasFiles()) {
var filesList = <div className="ui-fileupload-files">
{
this.state.files.map((file,index) => {
var preview = this.isImage(file) ? <div><img alt={file.name} role="presentation" src={file.objectURL} width={this.props.previewWidth} /></div> : null;
var fileName = <div>{file.name}</div>;
var size = <div>{this.formatSize(file.size)}</div>;
var removeButton = <div><Button type="button" icon="fa-close" onClick={(event) => this.remove(index)} /></div>
render() {
var element;

if(this.props.mode === 'advanced') {
let className = classNames('ui-fileupload ui-widget', this.props.className);
let chooseButtonClassName = classNames('ui-fileupload-choose ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left', {'ui-fileupload-choose-selected': this.hasFiles()});
let chooseButton = <span icon="fa-plus" className={chooseButtonClassName}>
<input ref={(el) => this.fileInput = el} type="file" onChange={this.onFileSelect} onFocus={this.onFocus} onBlur={this.onBlur}
multiple={this.props.multiple} accept={this.props.accept} disabled={this.props.disabled} />
<span className="ui-button-icon-left ui-clickable fa fa-fw fa-plus"></span>
<span className="ui-button-text ui-clickable">{this.props.chooseLabel}</span>
</span>;
let uploadButton, cancelButton, filesList, progressBar;

if(!this.props.auto) {
uploadButton = <Button label={this.props.uploadLabel} icon="fa-upload" onClick={this.upload} disabled={this.props.disabled || !this.hasFiles()} />;
cancelButton = <Button label={this.props.cancelLabel} icon="fa-close" onClick={this.clear} disabled={this.props.disabled || !this.hasFiles()} />;
}

return <div className="ui-fileupload-row" key={file.name + file.type}>
{preview}
{fileName}
{size}
{removeButton}
</div>
})
}
</div>;
if(this.hasFiles()) {
filesList = <div className="ui-fileupload-files">
{
this.state.files.map((file, index) => {
let preview = this.isImage(file) ? <div><img alt={file.name} role="presentation" src={file.objectURL} width={this.props.previewWidth} /></div> : null;
let fileName = <div>{file.name}</div>;
let size = <div>{this.formatSize(file.size)}</div>;
let removeButton = <div><Button type="button" icon="fa-close" onClick={() => this.remove(index)} /></div>

var progressBar = <ProgressBar value={this.state.progress} showValue={false} />;
}

return <div className="ui-fileupload-row" key={file.name + file.type + file.size}>
{preview}
{fileName}
{size}
{removeButton}
</div>
})
}
</div>;

return (
<div id={this.props.id} className={className} style={this.props.style}>
progressBar = <ProgressBar value={this.state.progress} showValue={false} />;
}

element = <div id={this.props.id} className={className} style={this.props.style}>
<div className="ui-fileupload-buttonbar ui-widget-header ui-corner-top">
{chooseButton}
{uploadButton}
{cancelButton}
</div>
<div className="ui-fileupload-content ui-widget-content ui-corner-bottom" onDragEnter={this.onDragEnter} onDragOver={this.onDragOver} onDragLeave={this.onDragLeave} onDrop={this.onDrop}
ref={(el) => {this.content = el;}}>
<div ref={(el) => {this.content = el;}} className="ui-fileupload-content ui-widget-content ui-corner-bottom"
onDragEnter={this.onDragEnter} onDragOver={this.onDragOver} onDragLeave={this.onDragLeave} onDrop={this.onDrop}>
{progressBar}
<Messages value={this.state.msgs} />
{filesList}
</div>
</div>
);
}
else if(this.props.mode === 'basic') {
let buttonClassName = classNames('ui-button ui-fileupload-choose ui-widget ui-state-default ui-corner-all ui-button-text-icon-left', {'ui-fileupload-choose-selected': this.hasFiles()});
let iconClassName = classNames('ui-button-icon-left fa', {'fa-plus': !this.hasFiles() || this.props.auto, 'fa-upload': this.hasFiles() && !this.props.auto});

element = <span className={buttonClassName} onMouseUp={this.onSimpleUploaderClick}>
<span className={iconClassName}></span>
<span className="ui-button-text ui-clickable">{this.props.auto ? this.props.chooseLabel : this.hasFiles() ? this.state.files[0].name : this.props.chooseLabel}</span>
<input ref={(el) => this.fileInput = el} type="file" multiple={this.props.multiple} accept={this.props.accept} disabled={this.props.disabled}
onChange={this.onFileSelect} onFocus={this.onFocus} onBlur={this.onBlur} />
</span>;
}

return element;
}
}
Loading

0 comments on commit dbb8471

Please sign in to comment.