From f68af69c01c35ba6609c938f2c4aa41ec7f5cca2 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 19:14:26 +0100 Subject: [PATCH 01/22] Create search input --- src/js/components/footer.js | 13 ++++---- src/js/components/search-input.js | 35 ++++++++++++++++++++++ src/less/style.less | 50 +++++++++++++++++++++++++++---- 3 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 src/js/components/search-input.js diff --git a/src/js/components/footer.js b/src/js/components/footer.js index 3aff9fd1e..55f9f83f8 100644 --- a/src/js/components/footer.js +++ b/src/js/components/footer.js @@ -1,9 +1,9 @@ var React = require('react'); var remote = window.require('remote'); var shell = remote.require('shell'); +var SearchInput = require('./search-input'); var Footer = React.createClass({ - openRepoBrowser: function () { shell.openExternal('http://www.github.com/ekonstantinidis/gitify'); }, @@ -12,11 +12,14 @@ var Footer = React.createClass({ return (
-
+
+ +
+
+ Fork me on -
+ +
); diff --git a/src/js/components/search-input.js b/src/js/components/search-input.js new file mode 100644 index 000000000..c9968ae8d --- /dev/null +++ b/src/js/components/search-input.js @@ -0,0 +1,35 @@ +var React = require('react'); + +var SearchInput = React.createClass({ + onChange: function (event) { + this.setState({ + searchTerm: event.target.value + }); + }, + + clearSearch: function () { + this.setState({ + searchTerm: undefined + }); + }, + + getInitialState: function() { + return {}; + }, + + render: function () { + return ( +
+ + +
+ ); + } +}); + +module.exports = SearchInput; diff --git a/src/less/style.less b/src/less/style.less index 7df0ebefa..0411fcf8e 100644 --- a/src/less/style.less +++ b/src/less/style.less @@ -147,6 +147,10 @@ html, body { } } +.right { + text-align: right; +} + /* @end Misc */ @@ -213,12 +217,8 @@ html, body { } } - &.right { - text-align: right; - - .fa { - margin: 0 10px; - } + &.right .fa { + margin: 0 10px; } } } @@ -367,6 +367,9 @@ html, body { /* @group Component / Footer */ +@SearchHeight: 24px; +@SearchFontSize: 14px; + .footer { margin: 0; padding: 5px 20px; @@ -379,6 +382,41 @@ html, body { left: 0; right: 0; text-align: center; + line-height: @SearchHeight; +} + +.github-link { + cursor: pointer; +} + +/* @group Search input */ + +.search-wrapper { + position: relative; + overflow: hidden; + + .octicon-x { + position: absolute; + text-align: center; + top: 0; + right: 0; + color: @ThemeBlack; + cursor: pointer; + height: @SearchHeight; + width: @SearchHeight; + line-height: @SearchHeight; + } } +.search { + width: 100%; + border-radius: @SearchHeight / 2; + height: @SearchHeight; + padding: 0 8px; + color: @ThemeBlack; + font-size: @SearchFontSize; +} + +/* @end Search input */ + /* @end Component / Footer */ From ea479ebab8be95f4b24e427f585f44ee48195b92 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 19:41:38 +0100 Subject: [PATCH 02/22] Setup search store --- src/js/actions/actions.js | 4 +++- src/js/components/search-input.js | 15 +++++++++------ src/js/stores/search.js | 22 ++++++++++++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 src/js/stores/search.js diff --git a/src/js/actions/actions.js b/src/js/actions/actions.js index 7a1533010..5a0eeac9e 100644 --- a/src/js/actions/actions.js +++ b/src/js/actions/actions.js @@ -4,7 +4,9 @@ var Actions = Reflux.createActions({ 'login': {}, 'logout': {}, - 'getNotifications': {asyncResult: true} + 'getNotifications': {asyncResult: true}, + 'updateSearchTerm': {}, + 'clearSearchTerm': {} }); diff --git a/src/js/components/search-input.js b/src/js/components/search-input.js index c9968ae8d..9e0ec2034 100644 --- a/src/js/components/search-input.js +++ b/src/js/components/search-input.js @@ -1,16 +1,19 @@ var React = require('react'); +var Reflux = require('reflux'); +var SearchStore = require('../stores/search'); +var Actions = require('../actions/actions'); var SearchInput = React.createClass({ + mixins: [ + Reflux.connect(SearchStore, 'searchTerm') + ], + onChange: function (event) { - this.setState({ - searchTerm: event.target.value - }); + Actions.updateSearchTerm(event.target.value); }, clearSearch: function () { - this.setState({ - searchTerm: undefined - }); + Actions.clearSearchTerm(); }, getInitialState: function() { diff --git a/src/js/stores/search.js b/src/js/stores/search.js new file mode 100644 index 000000000..ba5002a16 --- /dev/null +++ b/src/js/stores/search.js @@ -0,0 +1,22 @@ +var Reflux = require('reflux'); +var Actions = require('../actions/actions'); + +var SearchStore = Reflux.createStore({ + listenables: Actions, + + onUpdateSearchTerm: function (searchTerm) { + this._searchTerm = searchTerm; + this.trigger(this.searchTerm()); + }, + + onClearSearchTerm: function () { + this._searchTerm = undefined; + this.trigger(this.searchTerm()); + }, + + searchTerm: function () { + return this._searchTerm; + } +}); + +module.exports = SearchStore; From 8004907b0089f4d1b3c5b3a25e5039611b6c05d1 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 20:03:35 +0100 Subject: [PATCH 03/22] Filter repos by searchTerm --- src/js/components/notifications.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/js/components/notifications.js b/src/js/components/notifications.js index 76d137d8f..be5577f78 100644 --- a/src/js/components/notifications.js +++ b/src/js/components/notifications.js @@ -2,16 +2,30 @@ var React = require('react'); var Reflux = require('reflux'); var Loading = require('reloading'); var _ = require('underscore'); -var remote = window.require('remote'); -var shell = remote.require('shell'); var Actions = require('../actions/actions'); var NotificationsStore = require('../stores/notifications'); +var SearchStore = require('../stores/search'); var Repository = require('../components/repository'); var Notifications = React.createClass({ + areIn: function (repoFullName, searchTerm) { + if (!searchTerm) { + return false; + } + return repoFullName.toLowerCase().indexOf(searchTerm.toLowerCase()) >= 0; + }, + + matchesSearchTerm: function (obj) { + var repoFullName = obj[0].repository.full_name; + var searchTerms = this.state.searchTerm.split(/\s+?/); + + return _.any(searchTerms, this.areIn.bind(null, repoFullName)); + }, + mixins: [ Reflux.connect(NotificationsStore, 'notifications'), + Reflux.connect(SearchStore, 'searchTerm'), Reflux.listenTo(Actions.getNotifications.completed, 'completedNotifications'), Reflux.listenTo(Actions.getNotifications.failed, 'failedNotifications') ], @@ -66,8 +80,14 @@ var Notifications = React.createClass({ ); } else { + if (this.state.searchTerm) { + notifications = _.filter(this.state.notifications, this.matchesSearchTerm); + } else { + notifications = this.state.notifications; + } + notifications = ( - this.state.notifications.map(function (obj) { + notifications.map(function (obj) { var repoFullName = obj[0].repository.full_name; return ; }) From 96f6834b8566f2d25326848a59a83302b0fc8b19 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 20:10:09 +0100 Subject: [PATCH 04/22] Return only repos that match all of the search terms --- src/js/components/notifications.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/js/components/notifications.js b/src/js/components/notifications.js index be5577f78..bb61db1b2 100644 --- a/src/js/components/notifications.js +++ b/src/js/components/notifications.js @@ -10,17 +10,15 @@ var Repository = require('../components/repository'); var Notifications = React.createClass({ areIn: function (repoFullName, searchTerm) { - if (!searchTerm) { - return false; - } return repoFullName.toLowerCase().indexOf(searchTerm.toLowerCase()) >= 0; }, matchesSearchTerm: function (obj) { var repoFullName = obj[0].repository.full_name; - var searchTerms = this.state.searchTerm.split(/\s+?/); + var searchTerm = this.state.searchTerm.replace(/^\s+/, '').replace(/\s+$/, ''); + var searchTerms = searchTerm.split(/\s+/); - return _.any(searchTerms, this.areIn.bind(null, repoFullName)); + return _.all(searchTerms, this.areIn.bind(null, repoFullName)); }, mixins: [ From f1302be4bd0efb92003b206d5461947d7b6972f8 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 20:41:53 +0100 Subject: [PATCH 05/22] Fix jshint errors --- src/js/components/repository.js | 3 +-- src/js/components/search-input.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/js/components/repository.js b/src/js/components/repository.js index a03807a83..1559ecc69 100644 --- a/src/js/components/repository.js +++ b/src/js/components/repository.js @@ -1,5 +1,4 @@ var React = require('react'); -var _ = require('underscore'); var remote = window.require('remote'); var shell = remote.require('shell'); @@ -24,7 +23,7 @@ var Repository = React.createClass({
{this.props.repoName}
- {this.props.repo.map(function (obj, i) { + {this.props.repo.map(function (obj) { return ; })} diff --git a/src/js/components/search-input.js b/src/js/components/search-input.js index 9e0ec2034..6bf644e93 100644 --- a/src/js/components/search-input.js +++ b/src/js/components/search-input.js @@ -16,7 +16,7 @@ var SearchInput = React.createClass({ Actions.clearSearchTerm(); }, - getInitialState: function() { + getInitialState: function () { return {}; }, From 07dab60435c5ceeaf813ad20f6bd417a6892b6eb Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 20:42:10 +0100 Subject: [PATCH 06/22] Adjust input height --- src/less/style.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/less/style.less b/src/less/style.less index 0411fcf8e..c2cf0780a 100644 --- a/src/less/style.less +++ b/src/less/style.less @@ -367,7 +367,7 @@ html, body { /* @group Component / Footer */ -@SearchHeight: 24px; +@SearchHeight: 22px; @SearchFontSize: 14px; .footer { From f07e5a793080589ff4e4f7f4172c3f0a487d1c1d Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 20:46:55 +0100 Subject: [PATCH 07/22] Remove input outline --- src/less/style.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/less/style.less b/src/less/style.less index c2cf0780a..4d073c7a5 100644 --- a/src/less/style.less +++ b/src/less/style.less @@ -151,6 +151,10 @@ html, body { text-align: right; } +input { + outline: none; +} + /* @end Misc */ From 767725058485e26022b0fbec93a38b61bb3222d0 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 21:17:34 +0100 Subject: [PATCH 08/22] Display search input only when logged in --- src/js/components/footer.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/js/components/footer.js b/src/js/components/footer.js index 55f9f83f8..eaf4fc767 100644 --- a/src/js/components/footer.js +++ b/src/js/components/footer.js @@ -1,19 +1,35 @@ var React = require('react'); +var Reflux = require('reflux'); var remote = window.require('remote'); var shell = remote.require('shell'); var SearchInput = require('./search-input'); +var AuthStore = require('../stores/auth'); var Footer = React.createClass({ + mixins: [ + Reflux.connect(AuthStore, 'authStatus') + ], + openRepoBrowser: function () { shell.openExternal('http://www.github.com/ekonstantinidis/gitify'); }, + getInitialState: function () { + return {}; + }, + render: function () { + console.log(this.state.authStatus); + return (
- + { + this.state.authStatus ? ( + + ) : undefined + }
From e1ae7adb25ff0fcfb5f116f97e0e115c93e179bc Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 21:26:42 +0100 Subject: [PATCH 09/22] Remove search input border & add inset shadow --- src/less/style.less | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/less/style.less b/src/less/style.less index 4d073c7a5..49cd7ad4a 100644 --- a/src/less/style.less +++ b/src/less/style.less @@ -419,6 +419,8 @@ input { padding: 0 8px; color: @ThemeBlack; font-size: @SearchFontSize; + border: none; + box-shadow: inset 0 1px 3px 0 rgba(0, 0, 0, 0.5); } /* @end Search input */ From 543653ce894329118876e54bdb927ba735891b87 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 22:24:49 +0100 Subject: [PATCH 10/22] Footer get auth state on getInitialState --- src/js/components/footer.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/js/components/footer.js b/src/js/components/footer.js index eaf4fc767..0593217d8 100644 --- a/src/js/components/footer.js +++ b/src/js/components/footer.js @@ -15,7 +15,9 @@ var Footer = React.createClass({ }, getInitialState: function () { - return {}; + return { + authStatus: AuthStore.authStatus() + }; }, render: function () { From cef651c6d41c9eb1b02bc58b06034d75b937d041 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 22:25:18 +0100 Subject: [PATCH 11/22] Remove console log --- src/js/components/footer.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/js/components/footer.js b/src/js/components/footer.js index 0593217d8..89aa9f0e3 100644 --- a/src/js/components/footer.js +++ b/src/js/components/footer.js @@ -21,8 +21,6 @@ var Footer = React.createClass({ }, render: function () { - console.log(this.state.authStatus); - return (
From 071a065cc391df77f10f814ab22f59201c489521 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 22:37:22 +0100 Subject: [PATCH 12/22] Search store tests --- src/js/__tests__/components/footer.js | 13 +++++++++++ src/js/__tests__/stores/search.js | 31 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/js/__tests__/stores/search.js diff --git a/src/js/__tests__/components/footer.js b/src/js/__tests__/components/footer.js index e8516c2d5..cd160bed7 100644 --- a/src/js/__tests__/components/footer.js +++ b/src/js/__tests__/components/footer.js @@ -11,6 +11,19 @@ describe('Test for Footer', function () { var Actions, Footer; + window.localStorage = { + item: false, + setItem: function (item) { + this.item = item; + }, + getItem: function () { + return this.item; + }, + clear: function () { + this.item = false; + } + }; + beforeEach(function () { // Mock Electron's window.require // and remote.require('shell') diff --git a/src/js/__tests__/stores/search.js b/src/js/__tests__/stores/search.js new file mode 100644 index 000000000..2fde6a084 --- /dev/null +++ b/src/js/__tests__/stores/search.js @@ -0,0 +1,31 @@ +/*global jest, describe, it, expect, beforeEach */ + +'use strict'; + +jest.dontMock('reflux'); +jest.dontMock('../../stores/search'); +jest.dontMock('../../actions/actions'); + +describe('Tests for AuthStore', function () { + + var SearchStore, Actions; + + beforeEach(function () { + Actions = require('../../actions/actions'); + SearchStore = require('../../stores/search'); + }); + + it('should login - store the token', function () { + var searchTerm = 'test'; + SearchStore.onUpdateSearchTerm(searchTerm); + expect(SearchStore._searchTerm).toEqual(searchTerm); + expect(SearchStore.searchTerm()).toEqual(searchTerm); + }); + + it('should logout - remove the token', function () { + SearchStore.onClearSearchTerm(); + expect(SearchStore._searchTerm).toEqual(undefined); + expect(SearchStore.searchTerm()).toEqual(undefined); + }); + +}); From d058e3b9333f18b55fd2bf454796ba0496c64e4d Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Thu, 11 Jun 2015 22:41:46 +0100 Subject: [PATCH 13/22] Add search files to coverage --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index e2e8fc897..c5ab90df6 100644 --- a/package.json +++ b/package.json @@ -70,8 +70,10 @@ "src/js/components/notifications.js": true, "src/js/components/repository.js": true, "src/js/components/footer.js": true, + "src/js/components/search-input.js": true, "src/js/stores/auth.js": true, - "src/js/stores/notifications.js": true + "src/js/stores/notifications.js": true, + "src/js/stores/search.js": true }, "unmockedModulePathPatterns": [ "node_modules/react", From 46964d221c3c3de6e992c0f757802bda791e893a Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Fri, 12 Jun 2015 09:39:28 +0100 Subject: [PATCH 14/22] Search input tests --- src/js/__tests__/components/search-input.js | 77 +++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/js/__tests__/components/search-input.js diff --git a/src/js/__tests__/components/search-input.js b/src/js/__tests__/components/search-input.js new file mode 100644 index 000000000..d50866918 --- /dev/null +++ b/src/js/__tests__/components/search-input.js @@ -0,0 +1,77 @@ +/* global jest, describe, beforeEach, it, expect, spyOn */ + +jest.dontMock('reflux'); +jest.dontMock('../../actions/actions.js'); +jest.dontMock('../../components/search-input.js'); +jest.dontMock('../../stores/auth.js'); + +var React = require('react/addons'); +var TestUtils = React.addons.TestUtils; + +describe('Test for Search Input Component', function () { + + var Actions, AuthStore, SearchInput; + + beforeEach(function () { + // Mock Electron's window.require + // and remote.require('shell') + window.require = function () { + return { + require: function () { + return { + openExternal: function () { + return {}; + } + }; + } + }; + }; + + // Mock localStorage + window.localStorage = { + item: false, + getItem: function () { + return this.item; + } + }; + + Actions = require('../../actions/actions.js'); + AuthStore = require('../../stores/auth.js'); + SearchInput = require('../../components/search-input.js'); + }); + + it('Should make a search', function () { + + spyOn(Actions, 'updateSearchTerm'); + spyOn(Actions, 'clearSearchTerm'); + + var instance = TestUtils.renderIntoDocument(); + + var wrapper = TestUtils.scryRenderedDOMComponentsWithClass(instance, 'search-wrapper'); + expect(wrapper.length).toBe(1); + + instance.clearSearch(); + + instance.onChange({ + target: { + value: 'hello' + } + }); + + expect(Actions.updateSearchTerm).toHaveBeenCalledWith('hello'); + }); + + it('Should clear the search', function () { + spyOn(Actions, 'clearSearchTerm'); + + var instance = TestUtils.renderIntoDocument(); + var clearButton = TestUtils.scryRenderedDOMComponentsWithClass(instance, 'octicon-x')[0]; + + expect(Actions.clearSearchTerm).not.toHaveBeenCalled(); + + TestUtils.Simulate.click(clearButton); + + expect(Actions.clearSearchTerm).toHaveBeenCalled(); + }); + +}); From 977ca070d9631931f7cb594fa62f389abec59000 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Fri, 12 Jun 2015 09:45:40 +0100 Subject: [PATCH 15/22] Searching notifications tests --- src/js/__tests__/components/notifications.js | 41 ++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/js/__tests__/components/notifications.js b/src/js/__tests__/components/notifications.js index d2687b90e..7b69d6463 100644 --- a/src/js/__tests__/components/notifications.js +++ b/src/js/__tests__/components/notifications.js @@ -82,6 +82,47 @@ describe('Test for Notifications Component', function () { errors = TestUtils.scryRenderedDOMComponentsWithClass(instance, 'errored'); expect(errors.length).toBe(1); + expect(instance.areIn('ekonstantinidis/gitify', 'gitify')).toBeTruthy(); + expect(instance.areIn('ekonstantinidis/gitify', 'hello')).toBeFalsy(); + + instance.state.searchTerm = 'hello'; + var matches = instance.matchesSearchTerm(response[0]); + expect(matches).toBeFalsy(); + + instance.state.searchTerm = 'gitify'; + matches = instance.matchesSearchTerm(response[0]); + expect(matches).toBeTruthy(); + }); + + it('Should only render repos that match the search term', function () { + AuthStore.authStatus = function () { + return true; + }; + + var instance = TestUtils.renderIntoDocument(); + + var response = [[{ + 'repository': { + 'full_name': 'ekonstantinidis/gitify', + 'owner': { + 'avatar_url': 'http://avatar.url' + } + }, + 'subject': { + 'type': 'Issue' + } + }]]; + + NotificationsStore.trigger(response); + + var notifications = TestUtils.scryRenderedDOMComponentsWithClass(instance, 'repository'); + expect(notifications.length).toBe(1); + + instance.state.searchTerm = 'hello'; + instance.forceUpdate(); + + notifications = TestUtils.scryRenderedDOMComponentsWithClass(instance, 'repository'); + expect(notifications.length).toBe(0); }); }); From 5fe3a743f6ff756fdf1dcd7cc502b682baa924f0 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Fri, 12 Jun 2015 12:14:48 +0100 Subject: [PATCH 16/22] Allow selecting search input text --- main.js | 5 +++++ src/less/style.less | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/main.js b/main.js index c8e1bfec4..dcaddbc58 100644 --- a/main.js +++ b/main.js @@ -64,6 +64,11 @@ app.on('ready', function(){ label: 'Paste', accelerator: 'Command+V', selector: 'paste:' + }, + { + label: 'Select All', + accelerator: 'Command+A', + selector: 'selectAll:' } ] }]; diff --git a/src/less/style.less b/src/less/style.less index 49cd7ad4a..7a5e244d7 100644 --- a/src/less/style.less +++ b/src/less/style.less @@ -110,16 +110,15 @@ /* @group Misc */ +html, body { + -webkit-user-select: none; +} + body { .FontOpenSansRegular(); cursor: default; } -::selection { - color: inherit; - background: inherit; -} - html, body { height: 100%; overflow: hidden; @@ -421,6 +420,7 @@ input { font-size: @SearchFontSize; border: none; box-shadow: inset 0 1px 3px 0 rgba(0, 0, 0, 0.5); + -webkit-user-select: text; } /* @end Search input */ From 156656102a5ad5fe81c32db2c821cddbb4907c59 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Fri, 12 Jun 2015 13:42:05 +0100 Subject: [PATCH 17/22] No search results message --- src/js/components/notifications.js | 33 +++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/js/components/notifications.js b/src/js/components/notifications.js index bb61db1b2..f50b49bdb 100644 --- a/src/js/components/notifications.js +++ b/src/js/components/notifications.js @@ -57,9 +57,9 @@ var Notifications = React.createClass({ render: function () { var notifications, errors; var wrapperClass = 'container-fluid main-container notifications'; + var notificationsEmpty = _.isEmpty(this.state.notifications); if (this.state.errors) { - wrapperClass += ' errored'; errors = (

Oops something went wrong.

@@ -68,8 +68,7 @@ var Notifications = React.createClass({
); } else { - if (_.isEmpty(this.state.notifications)) { - wrapperClass += ' all-read'; + if (notificationsEmpty) { notifications = (

There are no notifications for you.

@@ -84,17 +83,31 @@ var Notifications = React.createClass({ notifications = this.state.notifications; } - notifications = ( - notifications.map(function (obj) { - var repoFullName = obj[0].repository.full_name; - return ; - }) - ); + if (notifications.length) { + notifications = ( + notifications.map(function (obj) { + var repoFullName = obj[0].repository.full_name; + return ; + }) + ); + } else { + errors = ( +
+

No Search Results.

+

No Organisations or Repositories match your search term.

+ +
+ ); + } } } return ( -
+
working on it
From c4fb5676d909f7ed1dcefbcdcc9dfb88c02c19df Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Fri, 12 Jun 2015 13:43:53 +0100 Subject: [PATCH 18/22] Only display clear icon if search term entered --- src/js/components/search-input.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/js/components/search-input.js b/src/js/components/search-input.js index 6bf644e93..026408943 100644 --- a/src/js/components/search-input.js +++ b/src/js/components/search-input.js @@ -21,9 +21,17 @@ var SearchInput = React.createClass({ }, render: function () { + var clearSearchIcon; + + if (this.state.searchTerm) { + clearSearchIcon = ( + + ); + } + return (
- + {clearSearchIcon} Date: Fri, 12 Jun 2015 13:46:50 +0100 Subject: [PATCH 19/22] Change ternary for all-read class --- src/js/components/notifications.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/js/components/notifications.js b/src/js/components/notifications.js index f50b49bdb..d1711089a 100644 --- a/src/js/components/notifications.js +++ b/src/js/components/notifications.js @@ -91,6 +91,7 @@ var Notifications = React.createClass({ }) ); } else { + notificationsEmpty = true; errors = (

No Search Results.

@@ -106,7 +107,7 @@ var Notifications = React.createClass({
working on it
From 950d5d049b7e97c3431c8f3d3573eec6faba26ea Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Fri, 12 Jun 2015 13:48:17 +0100 Subject: [PATCH 20/22] Fix class name --- src/js/components/notifications.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/components/notifications.js b/src/js/components/notifications.js index d1711089a..3f0a32f89 100644 --- a/src/js/components/notifications.js +++ b/src/js/components/notifications.js @@ -106,7 +106,7 @@ var Notifications = React.createClass({ return (
From 20f7c78a2c76861fa099717d6f93ffc309ddd6f8 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Fri, 12 Jun 2015 13:58:40 +0100 Subject: [PATCH 21/22] Update clear search input test --- src/js/__tests__/components/search-input.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/js/__tests__/components/search-input.js b/src/js/__tests__/components/search-input.js index d50866918..e13e7906b 100644 --- a/src/js/__tests__/components/search-input.js +++ b/src/js/__tests__/components/search-input.js @@ -65,12 +65,9 @@ describe('Test for Search Input Component', function () { spyOn(Actions, 'clearSearchTerm'); var instance = TestUtils.renderIntoDocument(); - var clearButton = TestUtils.scryRenderedDOMComponentsWithClass(instance, 'octicon-x')[0]; - expect(Actions.clearSearchTerm).not.toHaveBeenCalled(); - TestUtils.Simulate.click(clearButton); - + instance.clearSearch(); expect(Actions.clearSearchTerm).toHaveBeenCalled(); }); From 0039735de5dc5de27b68bd7b934992cbf8b1f787 Mon Sep 17 00:00:00 2001 From: JakeSidSmith Date: Fri, 12 Jun 2015 13:58:48 +0100 Subject: [PATCH 22/22] Test rendering of clear button --- src/js/__tests__/components/search-input.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/js/__tests__/components/search-input.js b/src/js/__tests__/components/search-input.js index e13e7906b..a0575e70e 100644 --- a/src/js/__tests__/components/search-input.js +++ b/src/js/__tests__/components/search-input.js @@ -71,4 +71,17 @@ describe('Test for Search Input Component', function () { expect(Actions.clearSearchTerm).toHaveBeenCalled(); }); + it('Should only render clear button if search term is not empty', function () { + var instance = TestUtils.renderIntoDocument(); + + var clearButton = TestUtils.scryRenderedDOMComponentsWithClass(instance, 'octicon-x'); + expect(clearButton.length).toBe(0); + + instance.state.searchTerm = 'hello'; + instance.forceUpdate(); + + clearButton = TestUtils.scryRenderedDOMComponentsWithClass(instance, 'octicon-x'); + expect(clearButton.length).toBe(1); + }); + });