From d195890eb957e5b6e40f7c01ce34d07e7ccf22b5 Mon Sep 17 00:00:00 2001
From: Shin'ya Ueoka <ueokande@i-beam.org>
Date: Sun, 26 Nov 2017 11:37:25 +0900
Subject: rename serach engine

---
 src/settings/components/form/search-form.jsx | 73 ++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 src/settings/components/form/search-form.jsx

(limited to 'src/settings/components/form/search-form.jsx')

diff --git a/src/settings/components/form/search-form.jsx b/src/settings/components/form/search-form.jsx
new file mode 100644
index 0000000..9bafb8d
--- /dev/null
+++ b/src/settings/components/form/search-form.jsx
@@ -0,0 +1,73 @@
+import './search-form.scss';
+import { h, Component } from 'preact';
+import AddButton from '../ui/add-button';
+import DeleteButton from '../ui/delete-button';
+
+class SearchForm extends Component {
+
+  render() {
+    let value = this.props.value;
+    if (!value) {
+      value = { default: '', engines: []};
+    }
+    let {
+      default: defaultEngine,
+      engines
+    } = value;
+
+    return <div className='form-search-form'>
+      <div className='form-search-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-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)} />
+              <DeleteButton data-index={index} name='delete'
+                onClick={this.bindValue.bind(this)} />
+            </div>
+          </div>;
+        })
+      }
+      <AddButton name='add' onClick={this.bindValue.bind(this)} />
+    </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 === 'add') {
+      next.engines.push(['', '']);
+    } else if (name === 'delete') {
+      next.engines.splice(index, 1);
+    }
+
+    this.props.onChange(next);
+  }
+}
+
+export default SearchForm;
-- 
cgit v1.2.3


From 0967304ebe713bc24078b20ac3a710fd42f2f611 Mon Sep 17 00:00:00 2001
From: Shin'ya Ueoka <ueokande@i-beam.org>
Date: Sun, 26 Nov 2017 12:18:12 +0900
Subject: add SearchForm test

---
 src/settings/components/form/search-form.jsx       |  18 ++--
 .../components/form/search-engine-form.test.jsx    | 104 +++++++++++++++++++++
 2 files changed, 115 insertions(+), 7 deletions(-)
 create mode 100644 test/settings/components/form/search-engine-form.test.jsx

(limited to 'src/settings/components/form/search-form.jsx')

diff --git a/src/settings/components/form/search-form.jsx b/src/settings/components/form/search-form.jsx
index 9bafb8d..98b0655 100644
--- a/src/settings/components/form/search-form.jsx
+++ b/src/settings/components/form/search-form.jsx
@@ -10,10 +10,9 @@ class SearchForm extends Component {
     if (!value) {
       value = { default: '', engines: []};
     }
-    let {
-      default: defaultEngine,
-      engines
-    } = value;
+    if (!value.engines) {
+      value.engines = [];
+    }
 
     return <div className='form-search-form'>
       <div className='form-search-form-header'>
@@ -22,7 +21,7 @@ class SearchForm extends Component {
         <div className='column-option'>Default</div>
       </div>
       {
-        engines.map((engine, index) => {
+        value.engines.map((engine, index) => {
           return <div key={index} className='form-search-form-row'>
             <input data-index={index} type='text' name='name'
               className='column-name' value={engine[0]}
@@ -33,7 +32,7 @@ class SearchForm extends Component {
               onChange={this.bindValue.bind(this)} />
             <div className='column-option'>
               <input data-index={index} type='radio' name='default'
-                checked={defaultEngine === engine[0]}
+                checked={value.default === engine[0]}
                 onChange={this.bindValue.bind(this)} />
               <DeleteButton data-index={index} name='delete'
                 onClick={this.bindValue.bind(this)} />
@@ -50,12 +49,17 @@ class SearchForm extends Component {
       return;
     }
 
+    let value = this.props.value;
     let name = e.target.name;
     let index = e.target.getAttribute('data-index');
-    let next = Object.assign({}, this.props.value);
+    let next = Object.assign({}, {
+      default: value.default,
+      engines: value.engines ? value.engines.slice() : [],
+    });
 
     if (name === 'name') {
       next.engines[index][0] = e.target.value;
+      next.default = this.props.value.engines[index][0];
     } else if (name === 'url') {
       next.engines[index][1] = e.target.value;
     } else if (name === 'default') {
diff --git a/test/settings/components/form/search-engine-form.test.jsx b/test/settings/components/form/search-engine-form.test.jsx
new file mode 100644
index 0000000..9600cae
--- /dev/null
+++ b/test/settings/components/form/search-engine-form.test.jsx
@@ -0,0 +1,104 @@
+import { expect } from 'chai';
+import { h, render } from 'preact';
+import SearchForm from 'settings/components/form/search-form'
+
+describe("settings/form/SearchForm", () => {
+  beforeEach(() => {
+    document.body.innerHTML = '';
+  });
+
+  describe('render', () => {
+    it('renders SearchForm', () => {
+      render(<SearchForm value={{
+        default: 'google',
+        engines: [['google', 'google.com'], ['yahoo', 'yahoo.com']],
+      }} />, document.body);
+
+      let names = document.querySelectorAll('input[name=name]');
+      expect(names).to.have.lengthOf(2);
+      expect(names[0].value).to.equal('google');
+      expect(names[1].value).to.equal('yahoo');
+
+      let urls = document.querySelectorAll('input[name=url]');
+      expect(urls).to.have.lengthOf(2);
+      expect(urls[0].value).to.equal('google.com');
+      expect(urls[1].value).to.equal('yahoo.com');
+    });
+
+    it('renders blank value', () => {
+      render(<SearchForm />, document.body);
+
+      let names = document.querySelectorAll('input[name=name]');
+      let urls = document.querySelectorAll('input[name=url]');
+      expect(names).to.have.lengthOf(0);
+      expect(urls).to.have.lengthOf(0);
+    });
+
+    it('renders blank engines', () => {
+      render(<SearchForm value={{ default: 'google' }} />, document.body);
+
+      let names = document.querySelectorAll('input[name=name]');
+      let urls = document.querySelectorAll('input[name=url]');
+      expect(names).to.have.lengthOf(0);
+      expect(urls).to.have.lengthOf(0);
+    });
+  });
+
+  describe('onChange event', () => {
+    it('invokes onChange event on edit', (done) => {
+      render(<SearchForm
+        value={{
+          default: 'google',
+          engines: [['google', 'google.com'], ['yahoo', 'yahoo.com']]
+        }}
+        onChange={value => {
+          expect(value.default).to.equal('louvre');
+          expect(value.engines).to.have.lengthOf(2)
+            .and.have.deep.members([['louvre', 'google.com'], ['yahoo', 'yahoo.com']])
+
+          done();
+        }} />, document.body);
+
+      let radio = document.querySelectorAll('input[type=radio]');
+      radio.checked = true;
+
+      let name = document.querySelector('input[name=name]');
+      name.value = 'louvre';
+      name.dispatchEvent(new Event('change'))
+    });
+
+    it('invokes onChange event on delete', (done) => {
+      render(<SearchForm value={{
+          default: 'yahoo',
+          engines: [['louvre', 'google.com'], ['yahoo', 'yahoo.com']]
+        }}
+        onChange={value => {
+          expect(value.default).to.equal('yahoo');
+          expect(value.engines).to.have.lengthOf(1)
+            .and.have.deep.members([['yahoo', 'yahoo.com']])
+
+          done();
+        }} />, document.body);
+
+      let button = document.querySelector('input[type=button]');
+      button.click();
+    });
+
+    it('invokes onChange event on add', (done) => {
+      render(<SearchForm value={{
+          default: 'yahoo',
+          engines: [['google', 'google.com']]
+        }}
+        onChange={value => {
+          expect(value.default).to.equal('yahoo');
+          expect(value.engines).to.have.lengthOf(2)
+            .and.have.deep.members([['google', 'google.com'], ['', '']])
+
+          done();
+        }} />, document.body);
+
+      let button = document.querySelector('input[type=button].ui-add-button');
+      button.click();
+    });
+  });
+});
-- 
cgit v1.2.3


From 26777d9e309dbc328b59581adb92f160c18f812c Mon Sep 17 00:00:00 2001
From: Shin'ya Ueoka <ueokande@i-beam.org>
Date: Sun, 26 Nov 2017 16:41:34 +0900
Subject: fix form css

---
 src/settings/components/form/blacklist-form.jsx |  3 ++-
 src/settings/components/form/keymaps-form.scss  |  2 +-
 src/settings/components/form/search-form.jsx    |  3 ++-
 src/settings/components/form/search-form.scss   |  2 ++
 src/settings/components/site.scss               |  2 +-
 src/settings/components/ui/add-button.jsx       |  2 +-
 src/settings/components/ui/add-button.scss      | 12 +++++++++++-
 src/settings/components/ui/delete-button.scss   |  1 +
 src/settings/components/ui/input.scss           |  3 ++-
 9 files changed, 23 insertions(+), 7 deletions(-)

(limited to 'src/settings/components/form/search-form.jsx')

diff --git a/src/settings/components/form/blacklist-form.jsx b/src/settings/components/form/blacklist-form.jsx
index 4333929..7ae9652 100644
--- a/src/settings/components/form/blacklist-form.jsx
+++ b/src/settings/components/form/blacklist-form.jsx
@@ -23,7 +23,8 @@ class BlacklistForm extends Component {
           </div>;
         })
       }
-      <AddButton name='add' onClick={this.bindValue.bind(this)} />
+      <AddButton name='add' style='float:right'
+        onClick={this.bindValue.bind(this)} />
     </div>;
   }
 
diff --git a/src/settings/components/form/keymaps-form.scss b/src/settings/components/form/keymaps-form.scss
index 8b86c80..3a83910 100644
--- a/src/settings/components/form/keymaps-form.scss
+++ b/src/settings/components/form/keymaps-form.scss
@@ -1,5 +1,5 @@
 .form-keymaps-form {
-  column-count: 2;
+  column-count: 3;
   .keymap-fields-group {
     margin-top: 24px;
   }
diff --git a/src/settings/components/form/search-form.jsx b/src/settings/components/form/search-form.jsx
index 98b0655..e85761f 100644
--- a/src/settings/components/form/search-form.jsx
+++ b/src/settings/components/form/search-form.jsx
@@ -40,7 +40,8 @@ class SearchForm extends Component {
           </div>;
         })
       }
-      <AddButton name='add' onClick={this.bindValue.bind(this)} />
+      <AddButton name='add' style='float:right'
+        onClick={this.bindValue.bind(this)} />
     </div>;
   }
 
diff --git a/src/settings/components/form/search-form.scss b/src/settings/components/form/search-form.scss
index 8814ef5..26b2f44 100644
--- a/src/settings/components/form/search-form.scss
+++ b/src/settings/components/form/search-form.scss
@@ -4,9 +4,11 @@
 
     .column-name {
       flex: 1;
+      min-width: 0;
     }
     .column-url {
       flex: 5;
+      min-width: 0;
     }
     .column-option {
       text-align: right;
diff --git a/src/settings/components/site.scss b/src/settings/components/site.scss
index c8dd422..c0c4f9e 100644
--- a/src/settings/components/site.scss
+++ b/src/settings/components/site.scss
@@ -20,7 +20,7 @@
 
     legend {
       font-size: 1.5rem;
-      line-height: 1.5rem;
+      padding: .5rem 0;
       font-weight: bold;
     }
   }
diff --git a/src/settings/components/ui/add-button.jsx b/src/settings/components/ui/add-button.jsx
index c8d8856..79292d8 100644
--- a/src/settings/components/ui/add-button.jsx
+++ b/src/settings/components/ui/add-button.jsx
@@ -4,7 +4,7 @@ import { h, Component } from 'preact';
 class AddButton extends Component {
   render() {
     return <input
-      className='ui-add-button' type='button' value='Add'
+      className='ui-add-button' type='button' value='&#x271a;'
       {...this.props} />;
   }
 }
diff --git a/src/settings/components/ui/add-button.scss b/src/settings/components/ui/add-button.scss
index 1c893ae..beb5688 100644
--- a/src/settings/components/ui/add-button.scss
+++ b/src/settings/components/ui/add-button.scss
@@ -1,3 +1,13 @@
 .ui-add-button {
-  font-size: 80%
+  border: none;
+  padding: 4;
+  display: inline;
+  background: none;
+  font-weight: bold;
+  color: green;
+  cursor: pointer;
+
+  &:hover {
+    color: darkgreen;
+  }
 }
diff --git a/src/settings/components/ui/delete-button.scss b/src/settings/components/ui/delete-button.scss
index 7aa2f39..5932a72 100644
--- a/src/settings/components/ui/delete-button.scss
+++ b/src/settings/components/ui/delete-button.scss
@@ -5,6 +5,7 @@
   display: inline;
   background: none;
   color: red;
+  cursor: pointer;
 
   &:hover {
     color: darkred;
diff --git a/src/settings/components/ui/input.scss b/src/settings/components/ui/input.scss
index 92df712..ad4daf8 100644
--- a/src/settings/components/ui/input.scss
+++ b/src/settings/components/ui/input.scss
@@ -11,8 +11,9 @@
     display: inline-block;
   }
 
-  input {
+  input[type='text'] {
     padding: 4px;
+    width: 8rem;
   }
 
   input.input-crror,
-- 
cgit v1.2.3

