Merge pull request #336 from travis-ci/favicon-changing
Change favicon color based on the build state
|
@ -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`
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<title>{{title}}</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/png" href="/images/favicon.png" />
|
||||
|
||||
{{content-for 'head'}}
|
||||
|
||||
|
|
30
app/mixins/build-favicon.coffee
Normal file
|
@ -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`
|
|
@ -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))
|
||||
|
|
|
@ -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: ->
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -10,6 +10,7 @@ Route = AbstractBuildsRoute.extend(
|
|||
this.controllerFor('builds').set('isPullRequestsList', true)
|
||||
|
||||
deactivate: ->
|
||||
@_super.apply(this, arguments)
|
||||
this.controllerFor('builds').set('isPullRequestsList', false)
|
||||
)
|
||||
|
||||
|
|
|
@ -16,4 +16,6 @@ Route = TravisRoute.extend
|
|||
@controllerFor('build').set('build', null)
|
||||
@controllerFor('job').set('job', null)
|
||||
|
||||
@_super.apply(this, arguments)
|
||||
|
||||
`export default Route`
|
||||
|
|
13
app/utils/favicon-data-uris.js
Normal file
|
@ -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;
|
||||
}
|
38
app/utils/favicon-manager.coffee
Normal file
|
@ -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`
|
|
@ -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",
|
||||
|
|
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 4.2 KiB |
BIN
public/images/favicon-gray.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
public/images/favicon-green.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
public/images/favicon-red.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
public/images/favicon-yellow.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
public/images/favicon.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 4.2 KiB |
51
tests/unit/utils/favicon-manager-test.coffee
Normal file
|
@ -0,0 +1,51 @@
|
|||
`import Ember from 'ember'`
|
||||
`import FaviconManager from 'travis/utils/favicon-manager'`
|
||||
|
||||
manager = null
|
||||
fakeHead = null
|
||||
|
||||
module("Favicon manager",
|
||||
beforeEach: ->
|
||||
fakeHead = $('<div id="fake-head"></div>').appendTo($('#qunit-fixture'))
|
||||
manager = new FaviconManager(fakeHead[0])
|
||||
afterEach: ->
|
||||
fakeHead.remove()
|
||||
manager = null
|
||||
)
|
||||
|
||||
test 'use <head> 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($('<link id="foo" rel="icon"></link>'))
|
||||
|
||||
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($('<link id="foo" rel="foo"></link>'))
|
||||
ok !manager.getLinkTag()
|