github.com/replicatedhq/ship@v0.55.0/web/init/src/components/config_render/FileInput.jsx (about) 1 import React from "react"; 2 import map from "lodash/map"; 3 import after from "lodash/after"; 4 import forEach from "lodash/forEach"; 5 6 export default class FileInput extends React.Component { 7 8 constructor(props) { 9 super(props); 10 this.state = { 11 errText: "", 12 fileAdded: false, 13 fileName: "", 14 fileNames: [] 15 } 16 } 17 18 handleOnChange = (ev) => { 19 this.setState({ errText: "" }); 20 21 let files = []; 22 let error; 23 24 const done = after(ev.target.files.length, () => { 25 // this.refs.file.getDOMNode().value = ""; 26 if (error) { 27 this.setState({ errText: error }); 28 } else if (this.props.onChange) { 29 this.setState({ fileAdded: true }) 30 this.props.onChange( 31 map(files, "value"), 32 map(files, "data") 33 ); 34 } 35 }); 36 37 forEach(ev.target.files, (file) => { 38 var reader = new FileReader(); 39 reader.onload = () => { 40 var vals = reader.result.split(","); 41 if (vals.length !== 2) { 42 error = "Invalid file data"; 43 } else { 44 files.push({ value: file.name, data: vals[1] }); 45 if (this.props.multiple) { 46 this.setState({ fileNames: files.map(file => file.value) }) 47 } else { 48 this.setState({ fileName: files[0].value }) 49 } 50 } 51 done(); 52 }; 53 reader.readAsDataURL(file); 54 }); 55 } 56 57 render() { 58 let label; 59 this.props.label ? label = this.props.label : this.props.multiple 60 ? label = "Upload files" : label = "Upload a file"; 61 62 63 return ( 64 <div> 65 <div className={`${this.props.readonly ? "readonly" : ""} ${this.props.disabled ? "disabled" : ""}`}> 66 <p className="sub-header-color field-section-sub-header u-marginTop--small u-marginBottom--small u-marginTop--15">{label}</p> 67 <div className="flex flex-row"> 68 <div className={`${this.state.fileAdded || this.props.value ? "file-uploaded" : "custom-file-upload"}`}> 69 <input 70 ref={(file) => this.file = file} 71 type="file" 72 name={this.props.name} 73 className="inputfile" 74 id={`${this.props.name} selector`} 75 onChange={this.handleOnChange} 76 readOnly={this.props.readOnly} 77 multiple={this.props.multiple} 78 disabled={this.props.disabled} 79 /> 80 <label htmlFor={`${this.props.name} selector`} className="u-position--relative"> 81 <span className={`icon clickable ${this.state.fileAdded || this.props.value ? "u-smallCheckGreen" : "u-ovalIcon"} u-marginRight--normal u-top--3`}></span> 82 {this.state.fileAdded || this.props.value ? this.props.multiple ? this.state.fileNames.join(",") : this.state.fileName : `Browse files for ${this.props.title}`} 83 {this.state.fileAdded || this.props.value ? 84 <p className="u-color--astral u-textDecoration--underlineOnHover u-fontSize--small u-marginLeft--30 u-marginTop--5">Select a different file</p> 85 : null } 86 </label> 87 </div> 88 </div> 89 </div> 90 <small className="text-danger"> {this.state.errText}</small> 91 </div> 92 ); 93 } 94 }