Add search form
This commit is contained in:
parent
4e5ddc1d57
commit
7b44b65247
4 changed files with 131 additions and 19 deletions
69
src/settings/components/form/search-engine-form.jsx
Normal file
69
src/settings/components/form/search-engine-form.jsx
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import { h, Component } from 'preact';
|
||||||
|
import './search-engine-form.scss';
|
||||||
|
|
||||||
|
class SearchEngineForm extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let value = this.props.value;
|
||||||
|
if (!value) {
|
||||||
|
value = { default: '', engines: []};
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
default: defaultEngine,
|
||||||
|
engines
|
||||||
|
} = value;
|
||||||
|
|
||||||
|
return <div className='form-search-engine-form'>
|
||||||
|
<div className='form-search-engine-form-header'>
|
||||||
|
<div className='column-name'>Name</div>
|
||||||
|
<div className='column-url'>URL</div>
|
||||||
|
<div className='column-option'>Default</div>
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
engines.map((engine, index) => {
|
||||||
|
return <div key={index} className='form-search-engine-form-row'>
|
||||||
|
<input data-index={index} type='text' name='name'
|
||||||
|
className='column-name' value={engine[0]}
|
||||||
|
onChange={this.bindValue.bind(this)} />
|
||||||
|
<input data-index={index} type='text' name='url'
|
||||||
|
placeholder='http://example.com/?q={}'
|
||||||
|
className='column-url' value={engine[1]}
|
||||||
|
onChange={this.bindValue.bind(this)} />
|
||||||
|
<div className='column-option'>
|
||||||
|
<input data-index={index} type='radio' name='default'
|
||||||
|
checked={defaultEngine === engine[0]}
|
||||||
|
onChange={this.bindValue.bind(this)} />
|
||||||
|
<input data-index={index} type='button' name='delete'
|
||||||
|
value='✖'
|
||||||
|
onClick={this.bindValue.bind(this)} />
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
bindValue(e) {
|
||||||
|
if (!this.props.onChange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = e.target.name;
|
||||||
|
let index = e.target.getAttribute('data-index');
|
||||||
|
let next = Object.assign({}, this.props.value);
|
||||||
|
|
||||||
|
if (name === 'name') {
|
||||||
|
next.engines[index][0] = e.target.value;
|
||||||
|
} else if (name === 'url') {
|
||||||
|
next.engines[index][1] = e.target.value;
|
||||||
|
} else if (name === 'default') {
|
||||||
|
next.default = this.props.value.engines[index][0];
|
||||||
|
} else if (name === 'delete') {
|
||||||
|
next.engines.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.onChange(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SearchEngineForm;
|
38
src/settings/components/form/search-engine-form.scss
Normal file
38
src/settings/components/form/search-engine-form.scss
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
.form-search-engine-form {
|
||||||
|
@mixin row-base {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.column-name {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.column-url {
|
||||||
|
flex: 5;
|
||||||
|
}
|
||||||
|
.column-option {
|
||||||
|
text-align: right;
|
||||||
|
flex-basis: 5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-header {
|
||||||
|
@include row-base;
|
||||||
|
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-row {
|
||||||
|
@include row-base;
|
||||||
|
|
||||||
|
.column-option input[type='button'] {
|
||||||
|
border: none;
|
||||||
|
padding: 4;
|
||||||
|
display: inline;
|
||||||
|
background: none;
|
||||||
|
color: red;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: darkred;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import './site.scss';
|
import './site.scss';
|
||||||
import { h, Component } from 'preact';
|
import { h, Component } from 'preact';
|
||||||
import Input from './ui/input';
|
import Input from './ui/input';
|
||||||
|
import SearchEngineForm from './form/search-engine-form';
|
||||||
import * as settingActions from 'settings/actions/setting';
|
import * as settingActions from 'settings/actions/setting';
|
||||||
import * as validator from 'shared/validators/setting';
|
import * as validator from 'shared/validators/setting';
|
||||||
|
|
||||||
|
@ -116,6 +117,13 @@ class SettingsComponent extends Component {
|
||||||
{ keymapFields }
|
{ keymapFields }
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Search Engines</legend>
|
||||||
|
<SearchEngineForm
|
||||||
|
value={this.state.settings.form.search}
|
||||||
|
onChange={this.bindSearchForm.bind(this)}
|
||||||
|
/>
|
||||||
|
</fieldset>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +136,6 @@ class SettingsComponent extends Component {
|
||||||
spellCheck='false'
|
spellCheck='false'
|
||||||
error={this.state.errors.json}
|
error={this.state.errors.json}
|
||||||
onChange={this.bindValue.bind(this)}
|
onChange={this.bindValue.bind(this)}
|
||||||
onBlur={this.save.bind(this)}
|
|
||||||
value={this.state.settings.json}
|
value={this.state.settings.json}
|
||||||
/>
|
/>
|
||||||
</div>;
|
</div>;
|
||||||
|
@ -175,6 +182,13 @@ class SettingsComponent extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindSearchForm(value) {
|
||||||
|
let next = Object.assign({}, this.state);
|
||||||
|
next.settings.form.search = value;
|
||||||
|
this.setState(next);
|
||||||
|
this.context.store.dispatch(settingActions.save(next.settings));
|
||||||
|
}
|
||||||
|
|
||||||
bindValue(e) {
|
bindValue(e) {
|
||||||
let next = Object.assign({}, this.state);
|
let next = Object.assign({}, this.state);
|
||||||
|
|
||||||
|
@ -187,6 +201,7 @@ class SettingsComponent extends Component {
|
||||||
next.settings[e.target.name] = e.target.value;
|
next.settings[e.target.name] = e.target.value;
|
||||||
|
|
||||||
this.setState(next);
|
this.setState(next);
|
||||||
|
this.context.store.dispatch(settingActions.save(next.settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
bindFormKeymapsValue(e) {
|
bindFormKeymapsValue(e) {
|
||||||
|
@ -196,16 +211,6 @@ class SettingsComponent extends Component {
|
||||||
|
|
||||||
this.context.store.dispatch(settingActions.save(next.settings));
|
this.context.store.dispatch(settingActions.save(next.settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
|
||||||
try {
|
|
||||||
let json = this.state.settings.json;
|
|
||||||
validator.validate(JSON.parse(json));
|
|
||||||
this.context.store.dispatch(settingActions.save(this.state.settings));
|
|
||||||
} catch (err) {
|
|
||||||
// error already shown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SettingsComponent;
|
export default SettingsComponent;
|
||||||
|
|
|
@ -117,14 +117,14 @@ export default {
|
||||||
},
|
},
|
||||||
'search': {
|
'search': {
|
||||||
'default': 'google',
|
'default': 'google',
|
||||||
'engines': {
|
'engines': [
|
||||||
'google': 'https://google.com/search?q={}',
|
['google', 'https,//google.com/search?q={}'],
|
||||||
'yahoo': 'https://search.yahoo.com/search?p={}',
|
['yahoo', 'https,//search.yahoo.com/search?p={}'],
|
||||||
'bing': 'https://www.bing.com/search?q={}',
|
['bing', 'https,//www.bing.com/search?q={}'],
|
||||||
'duckduckgo': 'https://duckduckgo.com/?q={}',
|
['duckduckgo', 'https,//duckduckgo.com/?q={}'],
|
||||||
'twitter': 'https://twitter.com/search?q={}',
|
['twitter', 'https,//twitter.com/search?q={}'],
|
||||||
'wikipedia': 'https://en.wikipedia.org/w/index.php?search={}'
|
['wikipedia', 'https,//en.wikipedia.org/w/index.php?search={}'],
|
||||||
}
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Reference in a new issue