diff --git a/app/controllers/build.coffee b/app/controllers/build.coffee index 91c14983..1f86f62c 100644 --- a/app/controllers/build.coffee +++ b/app/controllers/build.coffee @@ -8,6 +8,7 @@ Controller = Ember.Controller.extend GithubUrlPropertievs, commitBinding: 'build.commit' currentUserBinding: 'controllers.repo.currentUser' tabBinding: 'controllers.repo.tab' + sendFaviconStateChanges: true currentItemBinding: 'build' @@ -23,4 +24,9 @@ Controller = Ember.Controller.extend GithubUrlPropertievs, gravatarImage(@get('commit.authorEmail'), 40) ).property('commit.authorEmail') + buildStateDidChange: (-> + if @get('sendFaviconStateChanges') + @send('faviconStateDidChange', @get('build.state')) + ).observes('build.state') + `export default Controller` diff --git a/app/controllers/job.coffee b/app/controllers/job.coffee index f05e44ad..f262a0e4 100644 --- a/app/controllers/job.coffee +++ b/app/controllers/job.coffee @@ -16,4 +16,8 @@ Controller = Ember.Controller.extend githubCommit(@get('repo.slug'), @get('commit.sha')) ).property('repo.slug', 'commit.sha') + jobStateDidChange: (-> + @send('faviconStateDidChange', @get('job.state')) + ).observes('job.state') + `export default Controller` diff --git a/app/index.html b/app/index.html index 7d63a71d..c6a62dfc 100644 --- a/app/index.html +++ b/app/index.html @@ -6,6 +6,7 @@ {{title}} + {{content-for 'head'}} diff --git a/app/mixins/build-favicon.coffee b/app/mixins/build-favicon.coffee new file mode 100644 index 00000000..1d7bbed2 --- /dev/null +++ b/app/mixins/build-favicon.coffee @@ -0,0 +1,30 @@ +`import Ember from 'ember'` +`import { colorForState } from 'travis/utils/helpers'` +`import FaviconManager from 'travis/utils/favicon-manager'` +`import getFaviconUri from 'travis/utils/favicon-data-uris'` + +Mixin = Ember.Mixin.create + actions: + faviconStateDidChange: (state) -> + if state + @setFaviconForState(state) + else + @setDefault() + + init: -> + @faviconManager = new FaviconManager() + + @_super.apply this, arguments + + setFaviconForState: (state) -> + color = colorForState(state) + + @setFavicon(getFaviconUri(color)) + + setDefault: -> + @setFavicon(getFaviconUri('default')) + + setFavicon: (href) -> + @faviconManager.setFavicon(href) + +`export default Mixin` diff --git a/app/routes/abstract-builds.coffee b/app/routes/abstract-builds.coffee index 1fc355ba..1a79b7ec 100644 --- a/app/routes/abstract-builds.coffee +++ b/app/routes/abstract-builds.coffee @@ -15,6 +15,8 @@ Route = TravisRoute.extend deactivate: -> @controllerFor('repo').removeObserver(@get('path'), this, 'contentDidChange') + @_super.apply(this, arguments) + contentDidChange: -> path = @get('path') @controllerFor('builds').set('model', @controllerFor('repo').get(path)) diff --git a/app/routes/application.coffee b/app/routes/application.coffee index 2e17f470..c46573fe 100644 --- a/app/routes/application.coffee +++ b/app/routes/application.coffee @@ -1,7 +1,8 @@ `import TravisRoute from 'travis/routes/basic'` `import config from 'travis/config/environment'` +`import BuildFaviconMixin from 'travis/mixins/build-favicon'` -Route = TravisRoute.extend +Route = TravisRoute.extend BuildFaviconMixin, needsAuth: false renderTemplate: -> diff --git a/app/routes/build.coffee b/app/routes/build.coffee index a1227588..2703be70 100644 --- a/app/routes/build.coffee +++ b/app/routes/build.coffee @@ -22,6 +22,7 @@ Route = TravisRoute.extend @store.find('build', params.build_id) deactivate: -> + @_super.apply(this, arguments) @controllerFor('job').set('job', null) @controllerFor('build').set('build', null) diff --git a/app/routes/job.coffee b/app/routes/job.coffee index f5b39c25..e207df5f 100644 --- a/app/routes/job.coffee +++ b/app/routes/job.coffee @@ -20,13 +20,24 @@ Route = TravisRoute.extend if build = model.get('build') build = @store.recordForId('build', build.get('id')) - @controllerFor('build').set('build', build) + buildController = @controllerFor('build') + + # this is a hack to not set favicon changes from build + # controller while we're viewing job, this should go away + # after refactoring of controllers + buildController.set('sendFaviconStateChanges', false) + + buildController.set('build', build) model: (params) -> @store.find('job', params.job_id) deactivate: -> + buildController = @controllerFor('build') + buildController.set('sendFaviconStateChanges', true) @controllerFor('build').set('build', null) @controllerFor('job').set('job', null) + @_super.apply(this, arguments) + `export default Route` diff --git a/app/routes/main-tab.coffee b/app/routes/main-tab.coffee index d35a328a..bbc1d4da 100644 --- a/app/routes/main-tab.coffee +++ b/app/routes/main-tab.coffee @@ -17,6 +17,8 @@ Route = TravisRoute.extend deactivate: -> @controllerFor('repos').removeObserver('firstObject', this, 'currentRepoDidChange') + @_super.apply(this, arguments) + currentRepoDidChange: -> if repo = @controllerFor('repos').get('firstObject') @controllerFor('repo').set('repo', repo) diff --git a/app/routes/pull-requests.coffee b/app/routes/pull-requests.coffee index 121aa633..4253f7c0 100644 --- a/app/routes/pull-requests.coffee +++ b/app/routes/pull-requests.coffee @@ -10,6 +10,7 @@ Route = AbstractBuildsRoute.extend( this.controllerFor('builds').set('isPullRequestsList', true) deactivate: -> + @_super.apply(this, arguments) this.controllerFor('builds').set('isPullRequestsList', false) ) diff --git a/app/routes/repo/index.coffee b/app/routes/repo/index.coffee index 348425cf..0715b315 100644 --- a/app/routes/repo/index.coffee +++ b/app/routes/repo/index.coffee @@ -16,4 +16,6 @@ Route = TravisRoute.extend @controllerFor('build').set('build', null) @controllerFor('job').set('job', null) + @_super.apply(this, arguments) + `export default Route` diff --git a/app/utils/favicon-data-uris.js b/app/utils/favicon-data-uris.js new file mode 100644 index 00000000..088a1937 --- /dev/null +++ b/app/utils/favicon-data-uris.js @@ -0,0 +1,13 @@ +var __inlineImageDataUri__ = function() {}; // in case image inliner doesn't run + +var uris = { + default: __inlineImageDataUri__('favicon.png'), + red: __inlineImageDataUri__('favicon-red.png'), + gray: __inlineImageDataUri__('favicon-gray.png'), + green: __inlineImageDataUri__('favicon-green.png'), + yellow: __inlineImageDataUri__('favicon-yellow.png') +}; + +export default function(type) { + return uris[type] || uris.default; +} diff --git a/app/utils/favicon-manager.coffee b/app/utils/favicon-manager.coffee new file mode 100644 index 00000000..4be9c524 --- /dev/null +++ b/app/utils/favicon-manager.coffee @@ -0,0 +1,38 @@ +`import Ember from 'ember'` + +manager = (headTag) -> + @headTag = headTag if headTag + + return this + +manager.prototype.getHeadTag = -> + @headTag || document.getElementsByTagName('head')[0] + +manager.prototype.setFavicon = (href) -> + head = @getHeadTag() + + if oldLink = @getLinkTag() + head.removeChild(oldLink) + + link = @createLinkTag() + head.appendChild(link) + + link.setAttribute('href', href) + setTimeout -> + link.setAttribute('href', href) + , 1 + +manager.prototype.getLinkTag = -> + links = @getHeadTag().getElementsByTagName('link') + if links.length + for link in links + if (link.getAttribute('rel') || '').trim() == 'icon' + return link + +manager.prototype.createLinkTag = -> + link = document.createElement('link') + link.setAttribute('rel', 'icon') + link.setAttribute('type', 'image/png') + @getHeadTag().appendChild(link) + +`export default manager` diff --git a/package.json b/package.json index 498c2e91..e75e0df1 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "ember-cli-htmlbars": "^0.6.0", "ember-cli-ic-ajax": "0.1.1", "ember-cli-inject-live-reload": "^1.3.0", - "ember-cli-inline-images": "^0.0.3", + "ember-cli-inline-images": "^0.0.4", "ember-cli-pretender": "0.3.1", "ember-cli-qunit": "0.3.0", "ember-cli-sauce": "0.0.7", diff --git a/public/cancelled-favicon.ico b/public/cancelled-favicon.ico deleted file mode 100644 index e82838fa..00000000 Binary files a/public/cancelled-favicon.ico and /dev/null differ diff --git a/public/failed-favicon.ico b/public/failed-favicon.ico deleted file mode 100644 index 81497d53..00000000 Binary files a/public/failed-favicon.ico and /dev/null differ diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index acb338dc..00000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/images/favicon-gray.png b/public/images/favicon-gray.png new file mode 100644 index 00000000..e33f5dce Binary files /dev/null and b/public/images/favicon-gray.png differ diff --git a/public/images/favicon-green.png b/public/images/favicon-green.png new file mode 100644 index 00000000..3a243de1 Binary files /dev/null and b/public/images/favicon-green.png differ diff --git a/public/images/favicon-red.png b/public/images/favicon-red.png new file mode 100644 index 00000000..ec9e8f49 Binary files /dev/null and b/public/images/favicon-red.png differ diff --git a/public/images/favicon-yellow.png b/public/images/favicon-yellow.png new file mode 100644 index 00000000..b005d9f4 Binary files /dev/null and b/public/images/favicon-yellow.png differ diff --git a/public/images/favicon.png b/public/images/favicon.png new file mode 100644 index 00000000..4cd61479 Binary files /dev/null and b/public/images/favicon.png differ diff --git a/public/passed-favicon.ico b/public/passed-favicon.ico deleted file mode 100644 index b43783e2..00000000 Binary files a/public/passed-favicon.ico and /dev/null differ diff --git a/public/queued-favicon.ico b/public/queued-favicon.ico deleted file mode 100644 index 558bf72e..00000000 Binary files a/public/queued-favicon.ico and /dev/null differ diff --git a/tests/unit/utils/favicon-manager-test.coffee b/tests/unit/utils/favicon-manager-test.coffee new file mode 100644 index 00000000..d5013381 --- /dev/null +++ b/tests/unit/utils/favicon-manager-test.coffee @@ -0,0 +1,51 @@ +`import Ember from 'ember'` +`import FaviconManager from 'travis/utils/favicon-manager'` + +manager = null +fakeHead = null + +module("Favicon manager", + beforeEach: -> + fakeHead = $('
').appendTo($('#qunit-fixture')) + manager = new FaviconManager(fakeHead[0]) + afterEach: -> + fakeHead.remove() + manager = null +) + +test 'use tag by default', -> + manager = new FaviconManager() + equal manager.getHeadTag(), $('head')[0] + +test 'set favicon if there is no link tag in head', -> + equal fakeHead.find('link').length, 0, 'there should be no link tags initially' + + manager.setFavicon('foobar') + + link = fakeHead.find('link')[0] + + ok link, 'link tag should be added by favicon manager' + equal link.getAttribute('href'), 'foobar', 'href attribute for the link should be properly set' + equal link.getAttribute('rel'), 'icon', 'rel attribute for the link should be properly set' + equal link.getAttribute('type'), 'image/png', 'type attribute for the link should be properly set' + +test 'replace exisiting link tag', -> + fakeHead.append($('')) + + ok 'foo', fakeHead.find('link').attr('id'), 'initially link should exist' + + manager.setFavicon('foobar') + + links = fakeHead.find('link') + equal links.length, 1, 'there should be only one link in head' + + link = links[0] + + ok !link.getAttribute('id'), 'existing link should be replaced with a new one' + equal link.getAttribute('href'), 'foobar', 'href attribute for the link should be properly set' + equal link.getAttribute('rel'), 'icon', 'rel attribute for the link should be properly set' + equal link.getAttribute('type'), 'image/png', 'type attribute for the link should be properly set' + +test 'find link with rel=icon only', -> + fakeHead.append($('')) + ok !manager.getLinkTag()