diff --git a/app/components/travis-status.coffee b/app/components/travis-status.coffee new file mode 100644 index 00000000..3ae86598 --- /dev/null +++ b/app/components/travis-status.coffee @@ -0,0 +1,22 @@ +`import Ember from 'ember'` +`import Ajax from 'travis/utils/ajax'` +`import config from 'travis/config/environment'` + +TravisStatusComponent = Ember.Component.extend + status: null + + statusPageStatusUrl: (-> + config.statusPageStatusUrl + ).property() + + didInsertElement: -> + if url = @get('statusPageStatusUrl') + self = this + @getStatus(url).then (response) -> + if response.status and response.status.indicator + self.set('status', response.status.indicator) + + getStatus: (url) -> + $.ajax(url) + +`export default TravisStatusComponent` diff --git a/app/controllers/home.coffee b/app/controllers/home.coffee new file mode 100644 index 00000000..90babea0 --- /dev/null +++ b/app/controllers/home.coffee @@ -0,0 +1,5 @@ +`import Ember from 'ember'` + +Controller = Ember.Controller.extend() + +`export default Controller` diff --git a/app/controllers/repos.coffee b/app/controllers/repos.coffee index 390500f6..42a7e613 100644 --- a/app/controllers/repos.coffee +++ b/app/controllers/repos.coffee @@ -50,14 +50,10 @@ Controller = Ember.ArrayController.extend Visibility.every @config.intervals.updateTimes, @updateTimes.bind(this) recentRepos: (-> - Ember.ArrayProxy.extend( - isLoadedBinding: 'repos.isLoaded' - repos: Repo.withLastBuild(@store) - sorted: Ember.computed.sort('repos', 'sortedReposKeys') - content: limit('sorted', 'limit') - sortedReposKeys: ['sortOrder:asc'] - limit: 30 - ).create() + # I return an empty array here, because we're removing left sidebar, but + # I don't want to refactor too much code (it will be all changed anyway + # when we switch to new dashboard) + [] ).property() updateTimes: -> @@ -69,9 +65,6 @@ Controller = Ember.ArrayController.extend @set('tab', tab) this["view_#{tab}".camelize()](params) - viewRecent: -> - @set('content', @get('recentRepos')) - viewOwned: -> @set('content', @get('userRepos')) diff --git a/app/controllers/top.coffee b/app/controllers/top.coffee index 614d18ea..d70f1f6c 100644 --- a/app/controllers/top.coffee +++ b/app/controllers/top.coffee @@ -18,4 +18,8 @@ Controller = Ember.Controller.extend return false } + showCta: (-> + !@get('auth.signedIn') && !@get('config.pro') && !@get('landingPage') + ).property('auth.signedIn', 'landingPage') + `export default Controller` diff --git a/app/helpers/landing-page-last-build-time.coffee b/app/helpers/landing-page-last-build-time.coffee new file mode 100644 index 00000000..424bcde3 --- /dev/null +++ b/app/helpers/landing-page-last-build-time.coffee @@ -0,0 +1,7 @@ +`import { timeAgoInWords, safe } from 'travis/utils/helpers'` +`import Ember from "ember"` + +helper = Ember.Handlebars.makeBoundHelper (value, options) -> + safe timeAgoInWords(value) || 'currently running' + +`export default helper` diff --git a/app/models/repo.coffee b/app/models/repo.coffee index fdfe7ebf..b3083982 100644 --- a/app/models/repo.coffee +++ b/app/models/repo.coffee @@ -108,12 +108,12 @@ Repo = Model.extend ).property('_lastBuildDuration', 'lastBuildStartedAt', 'lastBuildFinishedAt') sortOrder: (-> - # cuz sortAscending seems buggy when set to false - if lastBuildFinishedAt = @get('lastBuildFinishedAt') - - new Date(lastBuildFinishedAt).getTime() + state = @get('lastBuildState') + if state != 'passed' && state != 'failed' + 0 else - - new Date('9999').getTime() - parseInt(@get('lastBuildId')) - ).property('lastBuildFinishedAt', 'lastBuildId') + parseInt(@get('lastBuildId')) + ).property('lastBuildId', 'lastBuildState') stats: (-> if @get('slug') diff --git a/app/router.coffee b/app/router.coffee index 22be0a06..708354c1 100644 --- a/app/router.coffee +++ b/app/router.coffee @@ -3,8 +3,26 @@ `import Location from 'travis/utils/location'` Router = Ember.Router.extend - # TODO: we should use TravisLocation here - location: if Ember.testing then 'none' else 'travis' + location: (-> + if Ember.testing + 'none' + else + # this is needed, because in the location + # we need to decide if repositories or home needs + # to be displayed, based on the current login status + # + # we should probably think about a more general way to + # do this, location should not know about auth status + Location.create(auth: @container.lookup('auth:main')) + ).property() + + # TODO: this is needed, because in the original version + # the router tries to run `this.location`, which fails + # with computed properties. It can be removed once this is + # changed in Ember.js + generate: -> + url = this.router.generate.apply(this.router, arguments) + return this.get('location').formatURL(url) handleURL: (url) -> url = url.replace(/#.*?$/, '') @@ -45,7 +63,8 @@ Router.map -> @route 'first_sync' @route 'insufficient_oauth_permissions' - @route 'auth', path: '/auth' + @route 'auth' + @route 'home' @resource 'profile', path: '/profile', -> @resource 'accounts', path: '/', -> diff --git a/app/routes/application.coffee b/app/routes/application.coffee index c46573fe..9838bfc5 100644 --- a/app/routes/application.coffee +++ b/app/routes/application.coffee @@ -51,6 +51,6 @@ Route = TravisRoute.extend BuildFaviconMixin, if @get('config').pro @transitionTo('auth') else - @transitionTo('main') + @transitionTo('home') `export default Route` diff --git a/app/routes/home.coffee b/app/routes/home.coffee new file mode 100644 index 00000000..c11760cc --- /dev/null +++ b/app/routes/home.coffee @@ -0,0 +1,68 @@ +`import BasicRoute from 'travis/routes/basic'` +`import config from 'travis/config/environment'` +`import limit from 'travis/utils/computed-limit'` + +Route = BasicRoute.extend + init: -> + store = @store + repos = Ember.ArrayProxy.extend( + isLoadedBinding: 'repos.isLoaded' + repos: @store.filter 'repo', (repo) -> + buildId = repo.get('lastBuildId') + if store.hasRecordForId('build', buildId) + state = repo.get('lastBuild.state') + state == 'passed' || state == 'failed' + external: [] + withExternal: Ember.computed.union('repos', 'external') + sorted: Ember.computed.sort('withExternal', 'sortedReposKeys') + content: limit('sorted', 'limit') + sortedReposKeys: ['sortOrder:desc'] + limit: 3 + ).create() + + @set('repos', repos) + + setInterval => + @set('letMoreReposThrough', true) + , 5000 + + setTimeout => + unless repos.get('length') + @store.find('repo').then (reposFromRequest) -> + repos.get('external').pushObjects reposFromRequest.toArray().slice(0, 3) + , 10000 + + @_super.apply this, arguments + + activate: -> + if !config.pro && @pusher + @pusher.subscribeAll(['common']) + + @store.addPusherEventHandlerGuard('landing-page', (event, data) => + @allowMoreRepos(event, data) + ) + + @_super.apply(this, arguments) + + @controllerFor('top').set('landingPage', true) + + allowMoreRepos: (event, data) -> + if @get('repos.length') < 3 + return true + + if event == 'build:finished' && + ['passed', 'failed'].indexOf(data.build.state) != -1 && + @get('letMoreReposThrough') + @set('letMoreReposThrough', false) + return true + + deactivate: -> + @_super.apply(this, arguments) + + @store.removePusherEventHandlerGuard('landing-page') + @controllerFor('top').set('landingPage', false) + + setupController: (controller, model) -> + controller.set('repos', @get('repos')) + +`export default Route` diff --git a/app/routes/main.coffee b/app/routes/main.coffee index 44376f91..f639e34d 100644 --- a/app/routes/main.coffee +++ b/app/routes/main.coffee @@ -14,8 +14,7 @@ Route = TravisRoute.extend setupController: (controller)-> # TODO: this is redundant with repositories and recent routes - toActivate = if @signedIn() then 'owned' else 'recent' - @container.lookup('controller:repos').activate(toActivate) + @container.lookup('controller:repos').activate('owned') activate: -> # subscribe to pusher only if we're at a main route diff --git a/app/routes/main/index.coffee b/app/routes/main/index.coffee index 4ebea1c0..6e01861f 100644 --- a/app/routes/main/index.coffee +++ b/app/routes/main/index.coffee @@ -2,7 +2,9 @@ Route = TravisRoute.extend redirect: -> - target = if @signedIn() then 'repositories' else 'recent' - @transitionTo("main.#{target}") + if @signedIn() + @transitionTo('main.repositories') + else + @transitionTo('home') `export default Route` diff --git a/app/routes/main/recent.coffee b/app/routes/main/recent.coffee index 4c00c403..caf6d5b9 100644 --- a/app/routes/main/recent.coffee +++ b/app/routes/main/recent.coffee @@ -1,15 +1,7 @@ -`import TravisRoute from 'travis/routes/basic'` -`import MainTabRoute from 'travis/routes/main-tab'` +`import Ember from 'ember'` -Route = MainTabRoute.extend - reposTabName: 'recent' - - activate: -> - @_super.apply(this, arguments) - @store.set('isRecentTabOpen', true) - - deactivate: -> - @_super.apply(this, arguments) - @store.set('isRecentTabOpen', false) +Route = Ember.Route.extend + redirect: -> + @transitionTo('main') `export default Route` diff --git a/app/routes/simple-layout.coffee b/app/routes/simple-layout.coffee index 95540a86..c6f045cc 100644 --- a/app/routes/simple-layout.coffee +++ b/app/routes/simple-layout.coffee @@ -3,8 +3,7 @@ Route = TravisRoute.extend setupController: -> $('body').attr('id', 'simple') - toActivate = if @signedIn() then 'owned' else 'recent' - @container.lookup('controller:repos').activate(toActivate) + @container.lookup('controller:repos').activate('owned') @_super.apply(this, arguments) renderTemplate: -> diff --git a/app/store.coffee b/app/store.coffee index a3eba84f..a76332c7 100644 --- a/app/store.coffee +++ b/app/store.coffee @@ -5,11 +5,20 @@ Store = DS.Store.extend defaultAdapter: 'application' adapter: 'application' - receivePusherEvent: (event, data) -> - [name, type] = event.split(':') + init: -> + @_super.apply(this, arguments) + @set('pusherEventHandlerGuards', {}) + addPusherEventHandlerGuard: (name, callback) -> + @get('pusherEventHandlerGuards')[name] = callback + + removePusherEventHandlerGuard: (name) -> + delete @get('pusherEventHandlerGuards')[name] + + canHandleEvent: (event, data) -> + [name, type] = event.split(':') auth = @container.lookup('auth:main') - if !@get('isRecentTabOpen') && event != 'job:log' && auth.get('signedIn') && + if event != 'job:log' && auth.get('signedIn') && !config.pro && !config.enterprise # if recent repos hasn't been opened yet, we can safely # drop any events that doesn't belong to repos owned by @@ -22,7 +31,18 @@ Store = DS.Store.extend else if name == 'build' id = data.repository.id - return if !@hasRecordForId('repo', id) && !permissions.contains(id) + return @hasRecordForId('repo', id) || permissions.contains(id) + + for name, callback of @get('pusherEventHandlerGuards') + unless callback(event, data) + return false + + return true + + receivePusherEvent: (event, data) -> + [name, type] = event.split(':') + + return unless @canHandleEvent(event, data) if name == 'job' && data.job?.commit @pushPayload(commits: [data.job.commit]) diff --git a/app/styles/app.scss b/app/styles/app.scss index 3403db9e..ef25d7a6 100644 --- a/app/styles/app.scss +++ b/app/styles/app.scss @@ -19,6 +19,7 @@ // @import "app/left"; @import "app/loading"; @import "app/main/annotations"; +@import "app/landing"; @import "app/main/list"; @import "app/main/log"; @import "app/main/sponsors"; diff --git a/app/styles/app/landing.sass b/app/styles/app/landing.sass new file mode 100644 index 00000000..695dd466 --- /dev/null +++ b/app/styles/app/landing.sass @@ -0,0 +1,554 @@ +.top.landing-page .topbar, +.wrapper.centered .topbar, +.wrapper.centered #top .cta p, +.top.landing-page .cta p + margin: 0 auto + max-width: 1024px + +.top.landing-page .topbar + background-color: #fff + + .button--signin + background-color: #ffffff + background-image: inline-image('landing-page/signingithub.svg') + background-size: 16px 16px + border: 2px solid #e4e7e7 + color: #a0a8a8 + + .button--signin:hover + background-color: #73c78d + background-image: inline-image('landing-page/signingithub-hover.svg') + border: 2px solid #73c78d + color: #fff + +.wrapper.centered .topbar + max-width: 1024px + +.wrapper.centered #top, +.wrapper.centered .topbar, +.wrapper.non-centered .topbar + background-color: #eff0ec + +#landing + margin: 0 auto 170px auto + font-weight: 300 + overflow: hidden + + h1 + font-size: 5em + line-height: 1em + font-weight: 300 + color: #8f9294 + margin-bottom: 0 + + h2 + font-size: 3.3em + line-height: 1.15em + font-weight: 300 + color: #39a85b + + p + font-color: #606162 + font-size: 1.7em + font-weight: 300 + + .hero, .oss-testing, .customers, .recent-builds, .free-for-oss, .private-repos, .features-list, .build-flows, .user-testimonials + padding: 70px 0 70px 0 + + h1, h2 + margin-top: 0 + + p + line-height: 1.5em + + .hero.z-1 + text-align: center + position: relative + z-index: 1 + + + .landing-centered-wrapper + max-width: 1024px + margin: 0 auto + + > .columns.medium-6:first-child + padding-right: 2em + > .columns.medium-6:last-child + padding-left: 2em + + #laptop + margin-bottom: -192px + + #laptop img + border: 2px solid #d8dadc + border-radius: 2px + + .hero + background-color: #faf9f6 + h1 + color: #339999 + line-height: 1.2em + margin-bottom: 0 + + p + margin: 0 + line-height: 1.5em + + br.mobile-break + display: none + + .button + background-color: #39a85b + color: #fff + font-size: 2em + font-weight: 300 + padding: 0.5em + margin: 1.3em 0 1.3em 0 + border-radius: 4px + border: 0 + + &:hover + background-color: #73c78d + + .sign-in-mascot + padding-right: 10px + + .oss-testing + background-color: #ffffff + text-align: center + position: relative + z-index: 1000 + + h2 + margin: 0 + + p + margin-top: 0.5em + margin-bottom: 2em + + br.mobile-break + display: none + + .customers + text-align: center + + .left + text-align: left + padding: 0 0 0 12% + + .recent-builds + background-color: #faf9f6 + text-align: center + min-height: 44rem + + h2 + color: #db4141 + text-align: right + margin: 0 + + a + color: #828282 + + p + text-align: right + margin-top: 0.5em + margin-bottom: 2em + + img + margin-bottom: 20px + + ul + padding-left: 0 + + li + background-color: #fff + border-radius: 4px + color: #828282 + font-weight: 400 + margin-bottom: 20px + list-style-type: none + position: relative + height: 120px + width: 100% + padding: 10px 0 0 60px + text-align: left + + .tile-status + position: absolute + top: 0 + left: 0 + bottom: 0 + + .owner, .name + display: block + + .owner + font-size: 14px + line-height: 1.8em + .name + font-size: 22px + + .state + display: inline-block + margin-left: 4px + + .commit, .number, .branch, .finished-at + position: absolute + display: block + background-repeat: no-repeat + background-position: left center + padding-left: 23px + + .number + left: 60px + top: 65px + background-image: inline-image('svg/build-number-icon.svg') + + .commit + left: 251px + top: 65px + background-image: inline-image('svg/commit-icon.svg') + + .branch + left: 250px + top: 90px + background-image: inline-image('dashboard/branch.svg') + background-size: 19px 19px + + .finished-at + left: 60px + top: 90px + background-image: inline-image('svg/finished-icon.svg') + background-size: 19px 19px + + &.started .tile-status, + &.created .tile-status, + &.received .tile-status, + &.queued .tile-status + background-color: $start-color + &.failed .tile-status + background-color: $fail-color + &.errored .tile-status + background-color: $error-color + &.canceled .tile-status + background-color: $cancel-color + &.passed .tile-status + background-color: $pass-color + &.inactive .tile-status + background-color: $cancel-color + + &.started .owner, + &.started .name, + &.created .owner, + &.created .name, + &.received .owner, + &.received .name, + &.queued .owner, + &.queued .name + color: $start-color + &.failed .owner, + &.failed .name + color: $fail-color + &.errored .owner, + &.errored .name + color: $error-color + &.canceled .owner, + &.canceled .name + color: $cancel-color + &.passed .owner, + &.passed .name + color: $pass-color + &.inactive .owner, + &.inactive .name + color: $cancel-color + + .free-for-oss + text-align: center + + h1 + margin-bottom: 0.3em + + p + margin: 0 + + span.bold-italic + font-weight: 600 + font-style: italic + + br.mobile-no-break + display: inline-block + + .private-repos + text-align: center + + h2 + color: #339999 + margin: 0 + text-align: right + + p + margin-top: 0.5em + margin-bottom: 2em + text-align: right + + a + text-decoration: underline + + .mobile-envelope + display: none + + .desktop-envelope + display: inline-block + + .features-list + background-color: #faf9f6 + + h2 + margin: 0 + + h3 + font-size: 1.4em + font-weight: 300 + color: #413c3c + text-align: center + margin-bottom: 35px + padding-top: 40px + + p + font-size: 1.15em + font-weight: 300 + color: #606162 + text-align: center + + br.mobile-break + display: none + + .features-callouts + text-align: center + @media #{$medium-only} + float: none + + #f-co-1, #f-co-2, #f-co-3, #f-co-4 + background-repeat: no-repeat; + background-position: 50% 0 + height: 32px + + #f-co-1, #f-co-2, #f-co-3, #f-co-4 + background-image: url('../images/landing-page/features-callouts-1.svg') + + #f-co-2 + background-image: url('../images/landing-page/features-callouts-2.svg') + + #f-co-3 + background-image: url('../images/landing-page/features-callouts-3.svg') + + #f-co-4 + background-image: url('../images/landing-page/features-callouts-4.svg') + + .features-checked + padding-left: 30px + @media #{$medium-only} + float: none + + h2 + @media #{$medium-only} + width: grid-calc(8, 12) + margin: 1em auto + ul + @media #{$medium-only} + width: grid-calc(5, 12) + margin: auto + + ul + @include resetul + margin-top: 1.6rem; + + li + font-color: #606162 + font-size: 1.7em + line-height: 1.7em + &:before + @extend %icon + content: "" + background-image: url('../images/landing-page/features-check.svg') + width: 0.7em + height: 0.7em + margin-right: .3em + + .build-flows + text-align: center + + h2 + color: #909295 + + h2#pr-bf-margin + margin-top: 90px + + .branch-bf + .bf + display: inline-block + width: 120px + + p + font-size: 1em + line-height: 1.5em + color: #5f6062 + + .divider-line-horizontal + width: 50px + height: 3px + background: #eaeaec + display: inline-block + margin-bottom: 75px + + .divider-line-vertical + display: none + + .user-testimonials + margin-bottom: 50px + + h2 + color: #418793 + text-align: right + + p + font-size: 1.2em + font-weight: 300 + color: #606162 + margin: 0 + display: inline-block + + img.avatar + max-width: 81px + float: right + + img.social + margin: -2px 3px 0 15px + display: inline-block + + .author + font-weight: 500 + margin: 6px 0 0 0 + + .title + margin: 0 0 20px 0 + + + a + font-size: 1.2em + + a:hover + text-decoration: underline + + @media (max-width: 900px) + .oss-testing br.mobile-break + display: inline-block + + .landing-centered-wrapper + width: 100% + + @media (max-width: 1024px) + .features-list .features-checked + margin-top: 40px + + .features-list .features-checked h2 + text-align: center + + @media (max-width: 886px) + #hero-copy + display: block + width: 100% + text-align: center + + .hero h1 + max-width: 100% + + .hero p + text-align: center + max-width: 100% + + .hero br.mobile-break + display: inline-block + + .features-list .features-callouts + padding: 0 60px 0 60px + + .features-list .features-checked + padding: 0 60px 0 60px + + @media (max-width: 846px) + .build-flows .branch-bf .bf + width: 100% + display: block + clear: all + + .build-flows .branch-bf .bf img + width: 120px + height: 120px + + .build-flows .branch-bf .bf p + font-size: 1.5em + + .build-flows .branch-bf .divider-line-horizontal + display: none + + .build-flows .branch-bf .divider-line-vertical + width: 3px + height: 40px + background: #eaeaec + display: inline-block + margin-bottom: 10px + + @media (max-width: 797px) + .customers .left + text-align: center + padding: 20px 0 0 0 + + .recent-builds h2 + text-align: center + + .recent-builds p + text-align: center + + .free-for-oss br.mobile-no-break + display: none + + .private-repos .desktop-envelope + display: none + + .private-repos .mobile-envelope + display: inline-block + margin-bottom: 40px + + .private-repos h2 + text-align: center + + .private-repos p + text-align: center + + .user-testimonials + margin-bottom: 50px + + .user-testimonials h2 + text-align: center + + .user-testimonails p + text-align: center + + @media (max-width: 640px) + .user-testimonials + margin-bottom: 140px + + @media (max-width: 608px) + br.mobile-break + display: inline-break + +.landing-vert-center-m + @media #{$medium-up} + position: relative + transform: translateY(65%) +.landing-vert-center-s + @media #{$medium-up} + position: relative + overflow: auto + transform: translateY(7%) diff --git a/app/styles/app/layout.sass b/app/styles/app/layout.sass index e75034fb..61fe2bd9 100644 --- a/app/styles/app/layout.sass +++ b/app/styles/app/layout.sass @@ -47,11 +47,13 @@ .wrapper overflow: hidden +.wrapper.non-centered #main, #left margin-bottom: -99999px padding-bottom: 100034px + @media #{$large-up} #left, #right, .wrapper-main @@ -63,30 +65,35 @@ margin-left: -100% max-width: 325px - .wrapper-main + .non-centered .wrapper-main width: grid-calc(18, 24) float: left margin-left: grid-calc(6, 24) overflow: visible + .centered .wrapper-main + max-width: 1024px + margin-left: auto + margin-right: auto + @media #{$xlarge-up} #left width: grid-calc(7, 36) - .wrapper-main + .non-centered .wrapper-main width: grid-calc(29, 36) margin-left: grid-calc(7, 36) @media #{$xxlarge-up} #left width: grid-calc(6, 36) - .wrapper-main + .non-centered .wrapper-main width: grid-calc(30, 36) margin-left: grid-calc(6, 36) @media screen and (min-width: 2200px) #left width: grid-calc(5, 36) - .wrapper-main + .non-centered .wrapper-main width: grid-calc(31, 36) margin-left: grid-calc(5, 36) diff --git a/app/styles/app/layouts/dashboard.sass b/app/styles/app/layouts/dashboard.sass index 68971f99..f3eac04c 100644 --- a/app/styles/app/layouts/dashboard.sass +++ b/app/styles/app/layouts/dashboard.sass @@ -214,3 +214,5 @@ $db-text-color: #ACAAAA h2, h3, p, button, .db-status opacity: .7 +.dashboard .topbar + background-color: transparent !important diff --git a/app/styles/app/layouts/footer.sass b/app/styles/app/layouts/footer.sass index 59d02b94..982ebbdb 100644 --- a/app/styles/app/layouts/footer.sass +++ b/app/styles/app/layouts/footer.sass @@ -2,11 +2,14 @@ * Footer on the dashboard */ +$footer-height: 204px + a color : $color-link text-decoration : none footer + position: relative padding : 20px 0 background-color : $footer-bg-color min-height : 334px @@ -24,12 +27,11 @@ footer height: auto @media (min-width: 640px) .wrapper - padding-bottom: 204px + padding-bottom: $footer-height + 50 footer - margin-top: -204px - min-height: 204px - + margin-top: - $footer-height + min-height: $footer-height footer h3 font-size : 15px @@ -43,6 +45,9 @@ footer .row p display : inline-block margin : 0 +footer .row + max-width: 1024px + footer .row ul, footer .row li display : block @@ -62,7 +67,6 @@ footer a:active text-decoration : underline .status-circle - background : $pass-color display : inline-block height : 11px width : 11px @@ -72,3 +76,16 @@ footer a:active -webkit-border-radius : 100px -moz-border-radius : 100px vertical-align: middle + +.status-circle.none + background: #2fcc66 + +.status-circle.degraded + background: #f1c40f + +.status-circle.minor + background: #e67e22 + +.status-circle.major + background: #e74c3c + diff --git a/app/styles/app/layouts/sidebar.sass b/app/styles/app/layouts/sidebar.sass index 12b5cd1e..88696923 100644 --- a/app/styles/app/layouts/sidebar.sass +++ b/app/styles/app/layouts/sidebar.sass @@ -75,7 +75,7 @@ $sb-font-size: 14px .icon--plus:after color: $teal1 &:after - bottom: 0 + bottom: -3px @media (min-width: #{lower-bound($large-range)}) ul diff --git a/app/styles/app/layouts/top.sass b/app/styles/app/layouts/top.sass index d4df65c5..a9fdb8c9 100644 --- a/app/styles/app/layouts/top.sass +++ b/app/styles/app/layouts/top.sass @@ -1,5 +1,35 @@ $top-height: 55px +#auth #top .cta + display: none + +#top .cta + border-bottom: 2px solid #E4E4E4 + border-top: 2px solid #E4E4E4 + line-height: 2.7em + font-size: 16px + color: #71AE76 + text-align: right + padding-right: 20px + background-color: #fff + + p + position: relative + margin-top: 0 + margin-bottom: 0 + padding-top: 0 + padding-bottom: 0 + + .arrow + display: block + position: absolute + top: -11px + right: 66px + background-image: inline-image('cta-arrow.svg') + background-repeat: no-repeat + width: 20px + height: 12px + .logo position: relative margin: 0 1.5rem 0 1.3rem @@ -39,7 +69,7 @@ $top-height: 55px .topbar font-size: $font-size-m - background-color: #eff0ec + background-color: #eff0ec color: $grey1 a @@ -84,7 +114,7 @@ $top-height: 55px height: $top-height > li display: inline-block - margin-right: 1rem + margin-right: 1rem a height: $top-height line-height: $top-height + 2px diff --git a/app/styles/app/modules/icons.sass b/app/styles/app/modules/icons.sass index c13230aa..8ad82bd9 100644 --- a/app/styles/app/modules/icons.sass +++ b/app/styles/app/modules/icons.sass @@ -1,11 +1,14 @@ -.icon - width: 1em - height: 1em +%icon display: inline-block background: size: 100% repeat: no-repeat +.icon + width: 1em + height: 1em + @extend %icon + .icon-cal, .icon--cal background-image: inline-image('svg/finished-icon.svg') diff --git a/app/templates/components/travis-status.hbs b/app/templates/components/travis-status.hbs new file mode 100644 index 00000000..a599939b --- /dev/null +++ b/app/templates/components/travis-status.hbs @@ -0,0 +1,8 @@ +{{#if statusPageStatusUrl}} +

Travis CI Status

+ +{{/if}} diff --git a/app/templates/footer.hbs b/app/templates/footer.hbs index c664390b..ab7656a4 100644 --- a/app/templates/footer.hbs +++ b/app/templates/footer.hbs @@ -1,5 +1,5 @@
-
+
@@ -31,11 +31,6 @@
{{/if}}
-

Travis CI Status

- + {{travis-status}}
diff --git a/app/templates/home.hbs b/app/templates/home.hbs new file mode 100644 index 00000000..29429343 --- /dev/null +++ b/app/templates/home.hbs @@ -0,0 +1,255 @@ +
+
+
+
+

Test and deploy with confidence

+

Easily sync your github projects with Travis CI
and you’ll be testing your code in minutes!

+ Sign Up +
+
+
+ +
+
+
+
+ +
+
+
+

The home of
open source testing

+

Over 200k open source projects
and 126k users are testing on Travis CI.

+ +
+
+
+ +
+
+
+ +
+
+

Some pretty awesome companies
and projects are using us.

+
+
+
+ +
+
+
+
+

Every minute there’s
a new build being run

+

Here are just a few projects
currently running on Travis CI

+
+
+
+
    + {{#each repo in repos}} +
  • + + + + {{repo.owner}} + {{repo.name}} + {{#link-to "build" repo repo.lastBuild.id class="number"}}{{repo.lastBuild.number}} {{repo.lastBuild.state}}{{/link-to}} + {{format-sha repo.lastBuild.commit.sha}} + {{repo.lastBuild.branch}} + + {{landing-page-last-build-time repo.lastBuild.finishedAt}} + +
  • + {{else}} + + {{/each}} +
+
+
+
+ +
+
+
+

Testing your open source
project is 10,000% free

+

Seriously. Always. We like to think of it as our way of giving
back to a community that gives us so much as well.

+
+
+
+ +
+
+
+ +
+ +
+
+

Have a private project
you’d like to test?

+

Travis CI for private repositories has
plans for every size project.

+
+
+
+ +
+
+
+ +
+
+
+
+
+

Get set up in seconds

+

Login with GitHub, tell Travis CI to test a project, and then push to GitHub. Could it be any simpler!

+
+
+

Multi-language support

+

Make sure your code runs against all versions of your favorite language without breaking a sweat.

+
+
+

Test your pull requests

+

Make sure every Pull Request to your project is tested before merging.

+
+
+

Deploy to s3 and Heroku

+

Updating staging or production as soon as your tests pass has never been easier!

+
+
+
+
+

Features created to
help your projects and teams

+
    +
  • Watch your tests as they run
  • +
  • Keep your config with your code
  • +
  • Slack, HipChat, Emails and more
  • +
  • A clean VM for every build
  • +
  • Run your tests in parallel
  • +
  • Linux and Mac (and iOS) supported
  • +
  • Great API and command line tool
  • +
  • Did we say Free for Open Source already?
  • +
+
+
+
+ +
+
+
+

Branch build flow

+
+
+ +

You push your
code to github

+
+
+
+
+
+
+ +

github triggers
Travis CI to build

+
+
+
+
+
+
+ +

Hooray!
Your build passes!

+
+
+
+
+
+
+ +

Travis CI deploys
to Heroku

+
+
+
+
+
+
+ +

Travis CI tells the
team all is good

+
+
+

Pull Request build flow

+
+
+ +

A pull request
is created

+
+
+
+
+
+
+ +

github tells Travis CI the build is mergeable

+
+
+
+
+
+
+ +

Hooray!
Your build passes!

+
+
+
+
+
+
+ +

Travis CI updates the PR that it passed

+
+
+
+
+
+
+ +

You merge in
the PR goodness

+
+
+
+
+
+ +
+
+
+

Some people have said some pretty nice things about us

+
+
+
+ +
+
+

Travis CI makes it so much easier for us to coordinate the thousands of commits and contributors that flow through the Rails code base. The test suite for such a large project is vast, and we wouldn’t be catching issues as quickly or smoothly without the help of Travis.

+

David Heinemeier Hansson

dhh +

Creator of Ruby on Rails

+
+ +
+ +
+
+

We love Travis CI at @TwitterOSS and use it for the majority of our open source projects on GitHub. Travis CI is simple to use, we love their API to build tooling and adore the new container infrastructure for speedier builds.

+

Chris Aniszczyk

cra +

Head of Open Source at Twitter

+
+ +
+ +
+
+

Not only is Travis CI the best way to test your software, it is the right way. rm -rf jenkins && touch .travis.yml

+

Alex Gaynor

alex +

PyPy and Python Core Team Member

+
+
+
+
+
diff --git a/app/templates/layouts/dashboard.hbs b/app/templates/layouts/dashboard.hbs index ebbffe2c..c1a87f20 100644 --- a/app/templates/layouts/dashboard.hbs +++ b/app/templates/layouts/dashboard.hbs @@ -1,14 +1,15 @@ -
-
-
+
+
+
{{render "top"}} -
+
+
+
{{yield}} -
- -
- {{render "footer"}} -
+ + diff --git a/app/templates/layouts/home.hbs b/app/templates/layouts/home.hbs index e0a94ab5..cb1e693f 100644 --- a/app/templates/layouts/home.hbs +++ b/app/templates/layouts/home.hbs @@ -1,5 +1,5 @@ -
- +
+
{{render "top"}}
@@ -12,8 +12,11 @@
-
+ + diff --git a/app/templates/layouts/landing-page.hbs b/app/templates/layouts/landing-page.hbs new file mode 100644 index 00000000..4a57bd79 --- /dev/null +++ b/app/templates/layouts/landing-page.hbs @@ -0,0 +1,11 @@ +
+ {{render "top"}} +
+ +{{render "flash"}} + +{{yield}} + + diff --git a/app/templates/layouts/profile.hbs b/app/templates/layouts/profile.hbs index 9b6bd508..027246bc 100644 --- a/app/templates/layouts/profile.hbs +++ b/app/templates/layouts/profile.hbs @@ -1,14 +1,20 @@ -
+
+
+
+ {{render "top"}} +
+
+
- {{render "top"}} -
-
+ {{render "flash"}} +
+ {{yield}} -
- {{render "flash"}} -
- {{yield}} - - {{outlet "left"}} + {{outlet "left"}} +
+ + \ No newline at end of file diff --git a/app/templates/repos/list/tabs.hbs b/app/templates/repos/list/tabs.hbs index eb04a74b..7faf4ba2 100644 --- a/app/templates/repos/list/tabs.hbs +++ b/app/templates/repos/list/tabs.hbs @@ -4,12 +4,6 @@ My Repositories - {{#unless config.pro}} -
  • - {{#link-to "main.recent"}}Recent{{/link-to}} -
  • - {{/unless}} - {{#if config.pro}}
  • Running ({{startedJobsCount}}/{{allJobsCount}}) diff --git a/app/templates/top.hbs b/app/templates/top.hbs index 741760d1..aeb14e4a 100644 --- a/app/templates/top.hbs +++ b/app/templates/top.hbs @@ -70,4 +70,13 @@ {{/if}}
  • - \ No newline at end of file + + +{{#if showCta}} +
    +

    + + Help make Open Source a better place and start building better software today! +

    +
    +{{/if}} diff --git a/app/utils/location.coffee b/app/utils/location.coffee index 0b5da2c9..789b3e37 100644 --- a/app/utils/location.coffee +++ b/app/utils/location.coffee @@ -1,8 +1,29 @@ `import Ember from 'ember'` Location = Ember.HistoryLocation.extend + init: -> + @_super.apply this, arguments + + if auth = @get('auth') + # location's getURL is first called before we even + # get to routes, so autoSignIn won't be called in + # such case + auth.autoSignIn() unless auth.get('signedIn') + getURL: -> - location = @get('location') - location.pathname + location.search + location.hash + url = this._super.apply(this, arguments) + if location.pathname == '/' + if @get('auth.signedIn') + return '/repositories' + else + return '/home' + + url + + formatURL: (logicalPath) -> + if logicalPath == '/repositories' || logicalPath == '/home' + '/' + else + @_super.apply this, arguments `export default Location` diff --git a/app/views/home.coffee b/app/views/home.coffee new file mode 100644 index 00000000..06446f76 --- /dev/null +++ b/app/views/home.coffee @@ -0,0 +1,6 @@ +`import BasicView from 'travis/views/basic'` + +View = BasicView.extend + layoutName: 'layouts/landing-page' + +`export default View` diff --git a/config/environment.js b/config/environment.js index bf78ba39..79a2ae34 100644 --- a/config/environment.js +++ b/config/environment.js @@ -29,7 +29,8 @@ module.exports = function(environment) { pro: false, enterprise: false, endpoints: {}, - intervals: { updateTimes: 1000 } + intervals: { updateTimes: 1000 }, + statusPageStatusUrl: 'https://pnpcptp8xh9k.statuspage.io/api/v2/status.json' }; if (typeof process !== 'undefined') { diff --git a/public/images/cta-arrow.svg b/public/images/cta-arrow.svg new file mode 100644 index 00000000..b192a869 --- /dev/null +++ b/public/images/cta-arrow.svg @@ -0,0 +1,7 @@ + + + + + + diff --git a/public/images/dashboard/branch.svg b/public/images/dashboard/branch.svg index b9c16743..2d2beace 100644 --- a/public/images/dashboard/branch.svg +++ b/public/images/dashboard/branch.svg @@ -2,11 +2,10 @@ - + diff --git a/public/images/landing-page/alex.png b/public/images/landing-page/alex.png new file mode 100644 index 00000000..b16caef4 Binary files /dev/null and b/public/images/landing-page/alex.png differ diff --git a/public/images/landing-page/chris.png b/public/images/landing-page/chris.png new file mode 100644 index 00000000..2f4566d0 Binary files /dev/null and b/public/images/landing-page/chris.png differ diff --git a/public/images/landing-page/customer-numbers.svg b/public/images/landing-page/customer-numbers.svg new file mode 100644 index 00000000..648bc04d --- /dev/null +++ b/public/images/landing-page/customer-numbers.svg @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/customers-facebook.svg b/public/images/landing-page/customers-facebook.svg new file mode 100644 index 00000000..45fbdc90 --- /dev/null +++ b/public/images/landing-page/customers-facebook.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/customers-heroku.svg b/public/images/landing-page/customers-heroku.svg new file mode 100644 index 00000000..0c7e4e60 --- /dev/null +++ b/public/images/landing-page/customers-heroku.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/customers-mozilla.svg b/public/images/landing-page/customers-mozilla.svg new file mode 100644 index 00000000..adbc23dd --- /dev/null +++ b/public/images/landing-page/customers-mozilla.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/customers-rails.svg b/public/images/landing-page/customers-rails.svg new file mode 100644 index 00000000..794714bd --- /dev/null +++ b/public/images/landing-page/customers-rails.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/customers-temp-together.svg b/public/images/landing-page/customers-temp-together.svg new file mode 100644 index 00000000..246fcbe9 --- /dev/null +++ b/public/images/landing-page/customers-temp-together.svg @@ -0,0 +1,473 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/customers-twitter.svg b/public/images/landing-page/customers-twitter.svg new file mode 100644 index 00000000..3aee1c30 --- /dev/null +++ b/public/images/landing-page/customers-twitter.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/customers-zendesk.svg b/public/images/landing-page/customers-zendesk.svg new file mode 100644 index 00000000..31b290e6 --- /dev/null +++ b/public/images/landing-page/customers-zendesk.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/dhh.png b/public/images/landing-page/dhh.png new file mode 100644 index 00000000..ba8ecc0a Binary files /dev/null and b/public/images/landing-page/dhh.png differ diff --git a/public/images/landing-page/envelope.svg b/public/images/landing-page/envelope.svg new file mode 100644 index 00000000..6071bcb8 --- /dev/null +++ b/public/images/landing-page/envelope.svg @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/features-callouts-1.svg b/public/images/landing-page/features-callouts-1.svg new file mode 100644 index 00000000..129a24ec --- /dev/null +++ b/public/images/landing-page/features-callouts-1.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/public/images/landing-page/features-callouts-2.svg b/public/images/landing-page/features-callouts-2.svg new file mode 100644 index 00000000..af3464dc --- /dev/null +++ b/public/images/landing-page/features-callouts-2.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/features-callouts-3.svg b/public/images/landing-page/features-callouts-3.svg new file mode 100644 index 00000000..ed9802a3 --- /dev/null +++ b/public/images/landing-page/features-callouts-3.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/features-callouts-4.svg b/public/images/landing-page/features-callouts-4.svg new file mode 100644 index 00000000..9a0afe1d --- /dev/null +++ b/public/images/landing-page/features-callouts-4.svg @@ -0,0 +1,23 @@ + + + + + + diff --git a/public/images/landing-page/features-check.svg b/public/images/landing-page/features-check.svg new file mode 100644 index 00000000..b07b6b6a --- /dev/null +++ b/public/images/landing-page/features-check.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/public/images/landing-page/github.svg b/public/images/landing-page/github.svg new file mode 100644 index 00000000..e6f628c6 --- /dev/null +++ b/public/images/landing-page/github.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/public/images/landing-page/laptop.png b/public/images/landing-page/laptop.png new file mode 100644 index 00000000..44959182 Binary files /dev/null and b/public/images/landing-page/laptop.png differ diff --git a/public/images/landing-page/pull-icon-1.svg b/public/images/landing-page/pull-icon-1.svg new file mode 100644 index 00000000..106fef73 --- /dev/null +++ b/public/images/landing-page/pull-icon-1.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + diff --git a/public/images/landing-page/pull-icon-2.svg b/public/images/landing-page/pull-icon-2.svg new file mode 100644 index 00000000..05d5577b --- /dev/null +++ b/public/images/landing-page/pull-icon-2.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/pull-icon-4.svg b/public/images/landing-page/pull-icon-4.svg new file mode 100644 index 00000000..7b7310c6 --- /dev/null +++ b/public/images/landing-page/pull-icon-4.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/pull-icon-5.svg b/public/images/landing-page/pull-icon-5.svg new file mode 100644 index 00000000..324e0d73 --- /dev/null +++ b/public/images/landing-page/pull-icon-5.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/public/images/landing-page/push-icon-1.svg b/public/images/landing-page/push-icon-1.svg new file mode 100644 index 00000000..25bded8d --- /dev/null +++ b/public/images/landing-page/push-icon-1.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/public/images/landing-page/push-icon-2.svg b/public/images/landing-page/push-icon-2.svg new file mode 100644 index 00000000..d849398a --- /dev/null +++ b/public/images/landing-page/push-icon-2.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/push-icon-3.svg b/public/images/landing-page/push-icon-3.svg new file mode 100644 index 00000000..b959ec57 --- /dev/null +++ b/public/images/landing-page/push-icon-3.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/push-icon-4.svg b/public/images/landing-page/push-icon-4.svg new file mode 100644 index 00000000..9b2e0e9f --- /dev/null +++ b/public/images/landing-page/push-icon-4.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/push-icon-5.svg b/public/images/landing-page/push-icon-5.svg new file mode 100644 index 00000000..ef68781c --- /dev/null +++ b/public/images/landing-page/push-icon-5.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/sign-in-mascot.svg b/public/images/landing-page/sign-in-mascot.svg new file mode 100644 index 00000000..127d9f80 --- /dev/null +++ b/public/images/landing-page/sign-in-mascot.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/signingithub-hover.svg b/public/images/landing-page/signingithub-hover.svg new file mode 100644 index 00000000..1a73bc6b --- /dev/null +++ b/public/images/landing-page/signingithub-hover.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/public/images/landing-page/signingithub.svg b/public/images/landing-page/signingithub.svg new file mode 100644 index 00000000..f8a37180 --- /dev/null +++ b/public/images/landing-page/signingithub.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/public/images/landing-page/temp-repo-green.svg b/public/images/landing-page/temp-repo-green.svg new file mode 100644 index 00000000..6d9db61d --- /dev/null +++ b/public/images/landing-page/temp-repo-green.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/temp-repo-red.svg b/public/images/landing-page/temp-repo-red.svg new file mode 100644 index 00000000..56a54648 --- /dev/null +++ b/public/images/landing-page/temp-repo-red.svg @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/temp-repo-yellow.svg b/public/images/landing-page/temp-repo-yellow.svg new file mode 100644 index 00000000..4eb69547 --- /dev/null +++ b/public/images/landing-page/temp-repo-yellow.svg @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/landing-page/twitter.svg b/public/images/landing-page/twitter.svg new file mode 100644 index 00000000..8c82a016 --- /dev/null +++ b/public/images/landing-page/twitter.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/tests/unit/components/travis-status-test.coffee b/tests/unit/components/travis-status-test.coffee new file mode 100644 index 00000000..16f678f2 --- /dev/null +++ b/tests/unit/components/travis-status-test.coffee @@ -0,0 +1,19 @@ +`import { test, moduleForComponent } from 'ember-qunit'` + +server = null +moduleForComponent 'travis-status', 'TravisStatusComponent', {} + +test 'adds incident class to .status-circle', -> + expect 3 + # creates the component instance + component = @subject() + component.getStatus = -> + new Ember.RSVP.Promise (resolve, reject) -> + resolve({ status: { indicator: 'major' } }) + + ok !component.get('status'), 'status is initially not set' + + @append() + + equal component.get('status'), 'major', 'status is updated from the API' + ok component.$('.status-circle').hasClass('major'), 'status class is set on .status-circle' diff --git a/waiter/lib/travis/web/app.rb b/waiter/lib/travis/web/app.rb index bf5ba49a..dd50fe42 100644 --- a/waiter/lib/travis/web/app.rb +++ b/waiter/lib/travis/web/app.rb @@ -169,7 +169,7 @@ class Travis::Web::App end def title - default_title = "Travis CI - Free Hosted Continuous Integration Platform for the Open Source Community" + default_title = "Travis CI - Test and deploy your code in confidence" ENV['SITE_TITLE'] || default_title end