Add PropertiesForm
This commit is contained in:
parent
e19f89f162
commit
86df54067f
4 changed files with 168 additions and 0 deletions
60
src/settings/components/form/properties-form.jsx
Normal file
60
src/settings/components/form/properties-form.jsx
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import './properties-form.scss';
|
||||||
|
import { h, Component } from 'preact';
|
||||||
|
|
||||||
|
class PropertiesForm extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let types = this.props.types;
|
||||||
|
let value = this.props.value;
|
||||||
|
if (!value) {
|
||||||
|
value = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className='form-properties-form'>
|
||||||
|
{
|
||||||
|
Object.keys(types).map((name) => {
|
||||||
|
let type = types[name];
|
||||||
|
let inputType = null;
|
||||||
|
if (type === 'string') {
|
||||||
|
inputType = 'text';
|
||||||
|
} else if (type === 'number') {
|
||||||
|
inputType = 'number';
|
||||||
|
} else if (type === 'boolean') {
|
||||||
|
inputType = 'checkbox';
|
||||||
|
}
|
||||||
|
return <div key={name} className='form-properties-form-row'>
|
||||||
|
<label>
|
||||||
|
<span className='column-name'>{name}</span>
|
||||||
|
<input type={inputType} name={name}
|
||||||
|
className='column-input'
|
||||||
|
value={value[name] ? value[name] : ''}
|
||||||
|
onChange={this.bindValue.bind(this)}
|
||||||
|
checked={value[name]}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
bindValue(e) {
|
||||||
|
if (!this.props.onChange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = e.target.name;
|
||||||
|
let next = Object.assign({}, this.props.value);
|
||||||
|
if (e.target.type.toLowerCase() === 'checkbox') {
|
||||||
|
next[name] = e.target.checked;
|
||||||
|
} else if (e.target.type.toLowerCase() === 'number') {
|
||||||
|
next[name] = Number(e.target.value);
|
||||||
|
} else {
|
||||||
|
next[name] = e.target.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.onChange(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PropertiesForm;
|
12
src/settings/components/form/properties-form.scss
Normal file
12
src/settings/components/form/properties-form.scss
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
.form-properties-form {
|
||||||
|
&-row {
|
||||||
|
.column-name {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.column-input {
|
||||||
|
line-height: 2.2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,8 @@ import Input from './ui/input';
|
||||||
import SearchForm from './form/search-form';
|
import SearchForm from './form/search-form';
|
||||||
import KeymapsForm from './form/keymaps-form';
|
import KeymapsForm from './form/keymaps-form';
|
||||||
import BlacklistForm from './form/blacklist-form';
|
import BlacklistForm from './form/blacklist-form';
|
||||||
|
import PropertiesForm from './form/properties-form';
|
||||||
|
import PropertyTypes from 'shared/settings/property-types';
|
||||||
import * as settingActions from 'settings/actions/setting';
|
import * as settingActions from 'settings/actions/setting';
|
||||||
import * as validator from 'shared/settings/validator';
|
import * as validator from 'shared/settings/validator';
|
||||||
import * as settingsValues from 'shared/settings/values';
|
import * as settingsValues from 'shared/settings/values';
|
||||||
|
@ -65,6 +67,14 @@ class SettingsComponent extends Component {
|
||||||
onChange={value => this.bindForm('blacklist', value)}
|
onChange={value => this.bindForm('blacklist', value)}
|
||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Properties</legend>
|
||||||
|
<PropertiesForm
|
||||||
|
types={PropertyTypes}
|
||||||
|
value={this.state.settings.form.properties}
|
||||||
|
onChange={value => this.bindForm('properties', value)}
|
||||||
|
/>
|
||||||
|
</fieldset>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
86
test/settings/components/form/properties-form.test.jsx
Normal file
86
test/settings/components/form/properties-form.test.jsx
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import { h, render } from 'preact';
|
||||||
|
import PropertiesForm from 'settings/components/form/properties-form'
|
||||||
|
|
||||||
|
describe("settings/form/PropertiesForm", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
document.body.innerHTML = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('render', () => {
|
||||||
|
it('renders PropertiesForm', () => {
|
||||||
|
let types = {
|
||||||
|
mystr: 'string',
|
||||||
|
mynum: 'number',
|
||||||
|
mybool: 'boolean',
|
||||||
|
empty: 'string',
|
||||||
|
}
|
||||||
|
let value = {
|
||||||
|
mystr: 'abc',
|
||||||
|
mynum: 123,
|
||||||
|
mybool: true,
|
||||||
|
};
|
||||||
|
render(<PropertiesForm types={types} value={value} />, document.body);
|
||||||
|
|
||||||
|
let strInput = document.querySelector('input[name=mystr]');
|
||||||
|
let numInput = document.querySelector('input[name=mynum]');
|
||||||
|
let boolInput = document.querySelector('input[name=mybool]');
|
||||||
|
let emptyInput = document.querySelector('input[name=empty]');
|
||||||
|
|
||||||
|
expect(strInput.type).to.equals('text');
|
||||||
|
expect(strInput.value).to.equal('abc');
|
||||||
|
expect(numInput.type).to.equals('number');
|
||||||
|
expect(numInput.value).to.equal('123');
|
||||||
|
expect(boolInput.type).to.equals('checkbox');
|
||||||
|
expect(boolInput.checked).to.be.true;
|
||||||
|
expect(emptyInput.type).to.equals('text');
|
||||||
|
expect(emptyInput.value).to.be.empty;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onChange', () => {
|
||||||
|
it('invokes onChange event on text changed', (done) => {
|
||||||
|
render(<PropertiesForm
|
||||||
|
types={{ 'myvalue': 'string' }}
|
||||||
|
value={{ 'myvalue': 'abc' }}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value).to.have.property('myvalue', 'abcd');
|
||||||
|
done();
|
||||||
|
}}
|
||||||
|
/>, document.body);
|
||||||
|
|
||||||
|
let input = document.querySelector('input[name=myvalue]');
|
||||||
|
input.value = 'abcd'
|
||||||
|
input.dispatchEvent(new Event('change'))
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on number changeed', (done) => {
|
||||||
|
render(<PropertiesForm
|
||||||
|
types={{ 'myvalue': 'number' }}
|
||||||
|
value={{ '': 123 }}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value).to.have.property('myvalue', 1234);
|
||||||
|
done();
|
||||||
|
}}
|
||||||
|
/>, document.body);
|
||||||
|
|
||||||
|
let input = document.querySelector('input[name=myvalue]');
|
||||||
|
input.value = '1234'
|
||||||
|
input.dispatchEvent(new Event('change'))
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on checkbox changed', (done) => {
|
||||||
|
render(<PropertiesForm
|
||||||
|
types={{ 'myvalue': 'boolean' }}
|
||||||
|
value={{ 'myvalue': false }}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value).to.have.property('myvalue', true);
|
||||||
|
done();
|
||||||
|
}}
|
||||||
|
/>, document.body);
|
||||||
|
|
||||||
|
let input = document.querySelector('input[name=myvalue]');
|
||||||
|
input.click();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Reference in a new issue