Consistent file uploads (#4699)
* FileSelect component * Use FileSelect component in Actionbar * Convert CreateAccount/Import to FileSelect
This commit is contained in:
parent
88449671a1
commit
190ed76e30
@ -14,19 +14,14 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import { FloatingActionButton } from 'material-ui';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Form, Input } from '~/ui';
|
import { Form, FileSelect, Input } from '~/ui';
|
||||||
import { AttachFileIcon } from '~/ui/Icons';
|
|
||||||
|
|
||||||
import styles from '../createAccount.css';
|
import styles from '../createAccount.css';
|
||||||
|
|
||||||
const STYLE_HIDDEN = { display: 'none' };
|
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export default class NewImport extends Component {
|
export default class NewImport extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -34,7 +29,7 @@ export default class NewImport extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { name, nameError, password, passwordHint, walletFile, walletFileError } = this.props.store;
|
const { name, nameError, password, passwordHint } = this.props.store;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
@ -93,58 +88,48 @@ export default class NewImport extends Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
{ this.renderFileSelector() }
|
||||||
<Input
|
|
||||||
disabled
|
|
||||||
error={ walletFileError }
|
|
||||||
hint={
|
|
||||||
<FormattedMessage
|
|
||||||
id='createAccount.newImport.file.hint'
|
|
||||||
defaultMessage='the wallet file for import'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={
|
|
||||||
<FormattedMessage
|
|
||||||
id='createAccount.newImport.file.label'
|
|
||||||
defaultMessage='wallet file'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
value={ walletFile }
|
|
||||||
/>
|
|
||||||
<div className={ styles.upload }>
|
|
||||||
<FloatingActionButton
|
|
||||||
mini
|
|
||||||
onTouchTap={ this.openFileDialog }
|
|
||||||
>
|
|
||||||
<AttachFileIcon />
|
|
||||||
</FloatingActionButton>
|
|
||||||
<input
|
|
||||||
onChange={ this.onFileChange }
|
|
||||||
ref='fileUpload'
|
|
||||||
style={ STYLE_HIDDEN }
|
|
||||||
type='file'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onFileChange = (event) => {
|
renderFileSelector () {
|
||||||
const { store } = this.props;
|
const { walletFile, walletFileError } = this.props.store;
|
||||||
|
|
||||||
if (event.target.files.length) {
|
return walletFile
|
||||||
const reader = new FileReader();
|
? (
|
||||||
|
<Input
|
||||||
reader.onload = (event) => store.setWalletJson(event.target.result);
|
disabled
|
||||||
reader.readAsText(event.target.files[0]);
|
error={ walletFileError }
|
||||||
}
|
hint={
|
||||||
|
<FormattedMessage
|
||||||
store.setWalletFile(event.target.value);
|
id='createAccount.newImport.file.hint'
|
||||||
|
defaultMessage='the wallet file for import'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='createAccount.newImport.file.label'
|
||||||
|
defaultMessage='wallet file'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
value={ walletFile }
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<FileSelect
|
||||||
|
className={ styles.fileImport }
|
||||||
|
error={ walletFileError }
|
||||||
|
onSelect={ this.onFileSelect }
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
openFileDialog = () => {
|
onFileSelect = (fileName, fileContent) => {
|
||||||
ReactDOM.findDOMNode(this.refs.fileUpload).click();
|
const { store } = this.props;
|
||||||
|
|
||||||
|
store.setWalletFile(fileName);
|
||||||
|
store.setWalletJson(fileContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditName = (event, name) => {
|
onEditName = (event, name) => {
|
||||||
|
@ -101,17 +101,6 @@
|
|||||||
width: 10% !important;
|
width: 10% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload {
|
|
||||||
text-align: right;
|
|
||||||
float: right;
|
|
||||||
margin-left: -100%;
|
|
||||||
margin-top: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload>div {
|
|
||||||
margin-right: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox {
|
.checkbox {
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
}
|
}
|
||||||
@ -131,6 +120,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fileImport {
|
||||||
|
height: 9em;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.summary {
|
.summary {
|
||||||
line-height: 1.618em;
|
line-height: 1.618em;
|
||||||
padding: 0 4em 1.5em 4em;
|
padding: 0 4em 1.5em 4em;
|
||||||
|
@ -93,8 +93,11 @@ export default class Store {
|
|||||||
this.phrase = '';
|
this.phrase = '';
|
||||||
this.name = '';
|
this.name = '';
|
||||||
this.nameError = null;
|
this.nameError = null;
|
||||||
|
this.rawKey = '';
|
||||||
this.rawKeyError = null;
|
this.rawKeyError = null;
|
||||||
|
this.walletFile = '';
|
||||||
this.walletFileError = null;
|
this.walletFileError = null;
|
||||||
|
this.walletJson = '';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,13 +64,24 @@ describe('modals/CreateAccount/Store', () => {
|
|||||||
|
|
||||||
describe('@action', () => {
|
describe('@action', () => {
|
||||||
describe('clearErrors', () => {
|
describe('clearErrors', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
store.setName('');
|
||||||
|
store.setPassword('123');
|
||||||
|
store.setRawKey('test');
|
||||||
|
store.setWalletFile('test');
|
||||||
|
store.setWalletJson('test');
|
||||||
|
});
|
||||||
|
|
||||||
it('clears all errors', () => {
|
it('clears all errors', () => {
|
||||||
store.clearErrors();
|
store.clearErrors();
|
||||||
|
|
||||||
expect(store.nameError).to.be.null;
|
expect(store.nameError).to.be.null;
|
||||||
expect(store.passwordRepeatError).to.be.null;
|
expect(store.passwordRepeatError).to.be.null;
|
||||||
|
expect(store.rawKey).to.equal('');
|
||||||
expect(store.rawKeyError).to.be.null;
|
expect(store.rawKeyError).to.be.null;
|
||||||
|
expect(store.walletFile).to.equal('');
|
||||||
expect(store.walletFileError).to.be.null;
|
expect(store.walletFileError).to.be.null;
|
||||||
|
expect(store.walletJson).to.equal('');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
24
js/src/ui/Actionbar/Import/import.css
vendored
24
js/src/ui/Actionbar/Import/import.css
vendored
@ -15,30 +15,6 @@
|
|||||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.importZone {
|
|
||||||
width: 100%;
|
|
||||||
height: 200px;
|
|
||||||
border-width: 2px;
|
|
||||||
border-color: #666;
|
|
||||||
border-style: dashed;
|
|
||||||
border-radius: 10px;
|
|
||||||
|
|
||||||
background-color: rgba(50, 50, 50, 0.2);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 1.2em;
|
|
||||||
|
|
||||||
transition: all 0.5s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 0;
|
|
||||||
background-color: rgba(50, 50, 50, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.desc {
|
.desc {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import Dropzone from 'react-dropzone';
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { nodeOrStringProptype } from '~/util/proptypes';
|
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||||
|
|
||||||
import Button from '../../Button';
|
import Button from '../../Button';
|
||||||
|
import FileSelect from '../../Form/FileSelect';
|
||||||
import { CancelIcon, DoneIcon, FileUploadIcon } from '../../Icons';
|
import { CancelIcon, DoneIcon, FileUploadIcon } from '../../Icons';
|
||||||
import Portal from '../../Portal';
|
import Portal from '../../Portal';
|
||||||
|
|
||||||
@ -184,25 +184,8 @@ export default class ActionbarImport extends Component {
|
|||||||
return this.renderValidation();
|
return this.renderValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.renderFileSelect();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderFileSelect () {
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<FileSelect onSelect={ this.onFileSelect } />
|
||||||
<Dropzone
|
|
||||||
onDrop={ this.onDrop }
|
|
||||||
multiple={ false }
|
|
||||||
className={ styles.importZone }
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<FormattedMessage
|
|
||||||
id='ui.actiobar.import.dropzone'
|
|
||||||
defaultMessage='Drop a file here, or click to select a file to upload.'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Dropzone>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,39 +207,30 @@ export default class ActionbarImport extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDrop = (files) => {
|
onFileSelect = (file, content) => {
|
||||||
const { renderValidation } = this.props;
|
const { renderValidation } = this.props;
|
||||||
|
|
||||||
const file = files[0];
|
if (typeof renderValidation !== 'function') {
|
||||||
const reader = new FileReader();
|
this.props.onConfirm(content);
|
||||||
|
return this.onCloseModal();
|
||||||
|
}
|
||||||
|
|
||||||
reader.onload = (e) => {
|
const validationBody = renderValidation(content);
|
||||||
const content = e.target.result;
|
|
||||||
|
|
||||||
if (typeof renderValidation !== 'function') {
|
if (validationBody && validationBody.error) {
|
||||||
this.props.onConfirm(content);
|
return this.setState({
|
||||||
return this.onCloseModal();
|
|
||||||
}
|
|
||||||
|
|
||||||
const validationBody = renderValidation(content);
|
|
||||||
|
|
||||||
if (validationBody && validationBody.error) {
|
|
||||||
return this.setState({
|
|
||||||
step: 1,
|
|
||||||
error: true,
|
|
||||||
errorText: validationBody.error
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
step: 1,
|
step: 1,
|
||||||
validate: true,
|
error: true,
|
||||||
validationBody,
|
errorText: validationBody.error
|
||||||
content
|
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
reader.readAsText(file);
|
this.setState({
|
||||||
|
step: 1,
|
||||||
|
validate: true,
|
||||||
|
validationBody,
|
||||||
|
content
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onConfirm = () => {
|
onConfirm = () => {
|
||||||
|
52
js/src/ui/Form/FileSelect/fileSelect.css
Normal file
52
js/src/ui/Form/FileSelect/fileSelect.css
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
/* This file is part of Parity.
|
||||||
|
/*
|
||||||
|
/* Parity is free software: you can redistribute it and/or modify
|
||||||
|
/* it under the terms of the GNU General Public License as published by
|
||||||
|
/* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
/* (at your option) any later version.
|
||||||
|
/*
|
||||||
|
/* Parity is distributed in the hope that it will be useful,
|
||||||
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
/* GNU General Public License for more details.
|
||||||
|
/*
|
||||||
|
/* You should have received a copy of the GNU General Public License
|
||||||
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$backgroundNormal: rgba(0, 0, 0, 0.2);
|
||||||
|
$backgroundNormalHover: rgba(0, 0, 0, 0.5);
|
||||||
|
$backgroundError: rgba(255, 0, 0, 0.1);
|
||||||
|
$backgroundErrorHover: rgba(255, 0, 0, 0.2);
|
||||||
|
|
||||||
|
.dropzone {
|
||||||
|
align-items: center;
|
||||||
|
background: $backgroundNormal;
|
||||||
|
border: 2px dashed #666;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.2em;
|
||||||
|
height: 12em;
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $backgroundNormalHover;
|
||||||
|
border-radius: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
background: $backgroundError;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $backgroundErrorHover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
}
|
76
js/src/ui/Form/FileSelect/fileSelect.js
Normal file
76
js/src/ui/Form/FileSelect/fileSelect.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
import Dropzone from 'react-dropzone';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||||
|
|
||||||
|
import styles from './fileSelect.css';
|
||||||
|
|
||||||
|
export default class FileSelect extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
error: nodeOrStringProptype(),
|
||||||
|
label: nodeOrStringProptype(),
|
||||||
|
onSelect: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
label: (
|
||||||
|
<FormattedMessage
|
||||||
|
id='ui.fileSelect.defaultLabel'
|
||||||
|
defaultMessage='Drop a file here, or click to select a file to upload'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { className, error, label } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropzone
|
||||||
|
onDrop={ this.onDrop }
|
||||||
|
multiple={ false }
|
||||||
|
className={
|
||||||
|
[
|
||||||
|
styles.dropzone,
|
||||||
|
error
|
||||||
|
? styles.error
|
||||||
|
: '',
|
||||||
|
className
|
||||||
|
].join(' ') }
|
||||||
|
>
|
||||||
|
<div className={ styles.label }>
|
||||||
|
{ error || label }
|
||||||
|
</div>
|
||||||
|
</Dropzone>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDrop = (files) => {
|
||||||
|
const { onSelect } = this.props;
|
||||||
|
const reader = new FileReader();
|
||||||
|
const file = files[0];
|
||||||
|
|
||||||
|
reader.onload = (event) => {
|
||||||
|
onSelect(file.name, event.target.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsText(file);
|
||||||
|
}
|
||||||
|
}
|
118
js/src/ui/Form/FileSelect/fileSelect.spec.js
Normal file
118
js/src/ui/Form/FileSelect/fileSelect.spec.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import React from 'react';
|
||||||
|
import sinon from 'sinon';
|
||||||
|
|
||||||
|
import FileSelect from './';
|
||||||
|
|
||||||
|
const FILE = {
|
||||||
|
content: 'some test content',
|
||||||
|
name: 'someName'
|
||||||
|
};
|
||||||
|
|
||||||
|
let component;
|
||||||
|
let globalFileReader;
|
||||||
|
let instance;
|
||||||
|
let onSelect;
|
||||||
|
let processedFile;
|
||||||
|
|
||||||
|
function stubReader () {
|
||||||
|
globalFileReader = global.FileReader;
|
||||||
|
|
||||||
|
global.FileReader = class {
|
||||||
|
readAsText (file) {
|
||||||
|
processedFile = file;
|
||||||
|
|
||||||
|
this.onload({
|
||||||
|
target: {
|
||||||
|
result: file.content
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreReader () {
|
||||||
|
global.FileReader = globalFileReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render (props = {}) {
|
||||||
|
onSelect = sinon.stub();
|
||||||
|
component = shallow(
|
||||||
|
<FileSelect
|
||||||
|
onSelect={ onSelect }
|
||||||
|
{ ...props }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
instance = component.instance();
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('ui/Form/FileSelect', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
stubReader();
|
||||||
|
render();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
restoreReader();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders defaults', () => {
|
||||||
|
expect(component).to.be.ok;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DropZone', () => {
|
||||||
|
let label;
|
||||||
|
let zone;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
label = component.find('FormattedMessage');
|
||||||
|
zone = component.find('Dropzone');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the label', () => {
|
||||||
|
expect(label.props().id).to.equal('ui.fileSelect.defaultLabel');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('attaches the onDrop event', () => {
|
||||||
|
expect(zone.props().onDrop).to.equal(instance.onDrop);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not allow multiples', () => {
|
||||||
|
expect(zone.props().multiple).to.be.false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('event methods', () => {
|
||||||
|
describe('onDrop', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
instance.onDrop([ FILE ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reads the file as dropped', () => {
|
||||||
|
expect(processedFile).to.deep.equal(FILE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls prop onSelect with file & content', () => {
|
||||||
|
expect(onSelect).to.have.been.calledWith(FILE.name, FILE.content);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
17
js/src/ui/Form/FileSelect/index.js
Normal file
17
js/src/ui/Form/FileSelect/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export default from './fileSelect';
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
export AddressSelect from './AddressSelect';
|
export AddressSelect from './AddressSelect';
|
||||||
export DappUrlInput from './DappUrlInput';
|
export DappUrlInput from './DappUrlInput';
|
||||||
|
export FileSelect from './FileSelect';
|
||||||
export FormWrap from './FormWrap';
|
export FormWrap from './FormWrap';
|
||||||
export Input from './Input';
|
export Input from './Input';
|
||||||
export InputAddress from './InputAddress';
|
export InputAddress from './InputAddress';
|
||||||
|
@ -30,7 +30,7 @@ export DappCard from './DappCard';
|
|||||||
export DappIcon from './DappIcon';
|
export DappIcon from './DappIcon';
|
||||||
export Errors from './Errors';
|
export Errors from './Errors';
|
||||||
export Features, { FEATURES, FeaturesStore } from './Features';
|
export Features, { FEATURES, FeaturesStore } from './Features';
|
||||||
export Form, { AddressSelect, DappUrlInput, FormWrap, Input, InputAddress, InputAddressSelect, InputChip, InputDate, InputInline, InputTime, Label, RadioButtons, Select, TypedInput } from './Form';
|
export Form, { AddressSelect, DappUrlInput, FileSelect, FormWrap, Input, InputAddress, InputAddressSelect, InputChip, InputDate, InputInline, InputTime, Label, RadioButtons, Select, TypedInput } from './Form';
|
||||||
export GasPriceEditor from './GasPriceEditor';
|
export GasPriceEditor from './GasPriceEditor';
|
||||||
export GasPriceSelector from './GasPriceSelector';
|
export GasPriceSelector from './GasPriceSelector';
|
||||||
export Icons from './Icons';
|
export Icons from './Icons';
|
||||||
|
Loading…
Reference in New Issue
Block a user