Add search form

jh-changes
Shin'ya Ueoka 7 years ago
parent 4e5ddc1d57
commit 7b44b65247
  1. 69
      src/settings/components/form/search-engine-form.jsx
  2. 38
      src/settings/components/form/search-engine-form.scss
  3. 27
      src/settings/components/index.jsx
  4. 16
      src/shared/default-settings.js

@ -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='&#x2716;'
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;

@ -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={}'],
} ]
} }
} }
}; };