
This is working implementation of links on log line numbers. Although it does the job, it's really hacky and involves overriding some of the ember's methods (resolvePath, routeMatcher) beacuse currently HistoryLocation can't handle hash additions in an easy way. This code should be fixed as soon as ember's router gets more powerful and gives much more granular control over matching routes.
382 lines
12 KiB
CoffeeScript
382 lines
12 KiB
CoffeeScript
require 'travis/location'
|
|
|
|
defaultRoute = Ember.Route.extend
|
|
route: '/'
|
|
index: 1000
|
|
|
|
lineNumberRoute = Ember.Route.extend
|
|
route: '#L:number'
|
|
index: 1
|
|
routeMatcher: Ember.computed(->
|
|
if route = @get 'route'
|
|
Ember._RouteMatcher.create
|
|
route: route
|
|
# TODO: overriding such things is not cool, I need to check what's the status of
|
|
# router rewrite and make sure we can do such stuff without overriding anything
|
|
init: ->
|
|
escapeForRegex = (text) ->
|
|
text.replace(/[\-\[\]{}()*+?.,\\\^\$|#\s]/g, "\\$&")
|
|
|
|
route = @route
|
|
identifiers = []
|
|
count = 1
|
|
|
|
if route.charAt(0) == '/'
|
|
route = @route = route.substr(1)
|
|
|
|
escaped = escapeForRegex(route)
|
|
|
|
regex = escaped.replace /:([a-z_]+)(?=$|\/)/gi, (match, id) ->
|
|
identifiers[count++] = id
|
|
"([0-9]+)"
|
|
|
|
@identifiers = identifiers
|
|
@regex = new RegExp(regex)
|
|
).cacheable()
|
|
|
|
|
|
nonHashRouteMatcher = Ember.computed(->
|
|
if route = @get 'route'
|
|
Ember._RouteMatcher.create
|
|
route: route
|
|
# TODO: overriding such things is not cool, I need to check what's the status of
|
|
# router rewrite and make sure we can do such stuff without overriding anything
|
|
init: ->
|
|
escapeForRegex = (text) ->
|
|
text.replace(/[\-\[\]{}()*+?.,\\\^\$|#\s]/g, "\\$&")
|
|
|
|
route = @route
|
|
identifiers = []
|
|
count = 1
|
|
|
|
if route.charAt(0) == '/'
|
|
route = @route = route.substr(1)
|
|
|
|
escaped = escapeForRegex(route)
|
|
|
|
regex = escaped.replace /:([a-z_]+)(?=$|\/)/gi, (match, id) ->
|
|
identifiers[count++] = id
|
|
"([^/#]+)"
|
|
|
|
@identifiers = identifiers
|
|
@regex = new RegExp("^/?" + regex)
|
|
).cacheable()
|
|
|
|
resolvePath = (manager, path) ->
|
|
if @get('isLeafRoute')
|
|
return Ember.A()
|
|
|
|
childStates = @get('childStates')
|
|
|
|
childStates = Ember.A(childStates.filterProperty('isRoutable'))
|
|
|
|
childStates = childStates.sort (a, b) ->
|
|
aDynamicSegments = a.get('routeMatcher.identifiers.length')
|
|
bDynamicSegments = b.get('routeMatcher.identifiers.length')
|
|
aRoute = a.get('route')
|
|
bRoute = b.get('route')
|
|
aIndex = a.get('index')
|
|
bIndex = b.get('index')
|
|
|
|
if aIndex && bIndex
|
|
return aIndex - bIndex
|
|
|
|
if aRoute.indexOf(bRoute) == 0
|
|
return -1
|
|
else if bRoute.indexOf(aRoute) == 0
|
|
return 1
|
|
|
|
if aDynamicSegments != bDynamicSegments
|
|
return aDynamicSegments - bDynamicSegments
|
|
|
|
return b.get('route.length') - a.get('route.length')
|
|
|
|
match = null
|
|
console.log(childStates.map( (s) -> s.get('route')))
|
|
state = childStates.find (state) ->
|
|
matcher = state.get('routeMatcher')
|
|
if match = matcher.match(path)
|
|
match
|
|
|
|
Ember.assert("Could not find state for path " + path, !!state)
|
|
|
|
resolvedState = Ember._ResolvedState.create
|
|
manager: manager
|
|
state: state
|
|
match: match
|
|
|
|
states = state.resolvePath(manager, match.remaining)
|
|
|
|
Ember.A([resolvedState]).pushObjects(states)
|
|
|
|
Travis.Router = Ember.Router.extend
|
|
location: 'travis'
|
|
enableLogging: true
|
|
initialState: 'loading'
|
|
|
|
showRoot: Ember.Route.transitionTo('root.home.show')
|
|
showStats: Ember.Route.transitionTo('root.stats')
|
|
|
|
showRepo: Ember.Route.transitionTo('root.home.repo.show')
|
|
showBuilds: Ember.Route.transitionTo('root.home.repo.builds.index')
|
|
showBuild: Ember.Route.transitionTo('root.home.repo.builds.show')
|
|
showPullRequests: Ember.Route.transitionTo('root.home.repo.pullRequests')
|
|
showBranches: Ember.Route.transitionTo('root.home.repo.branches')
|
|
showJob: Ember.Route.transitionTo('root.home.repo.job')
|
|
|
|
showProfile: Ember.Route.transitionTo('root.profile')
|
|
showAccount: Ember.Route.transitionTo('root.profile.account')
|
|
showUserProfile: Ember.Route.transitionTo('root.profile.account.profile')
|
|
|
|
signedIn: ->
|
|
!!Travis.app.get('auth.user')
|
|
|
|
needsAuth: (path) ->
|
|
path.indexOf('/profile') == 0 && !@signedIn()
|
|
|
|
loading: Ember.Route.extend
|
|
routePath: (router, path) ->
|
|
if match = path.match(/#.*$/)
|
|
router.set 'lineNumberHash', match[0]
|
|
|
|
|
|
sessionStorage.setItem('travis.path', path)
|
|
if router.needsAuth(path)
|
|
router.transitionTo('root.auth')
|
|
Travis.app.signIn()
|
|
else
|
|
router.transitionTo('authenticated')
|
|
|
|
authenticated: Ember.Route.extend
|
|
connectOutlets: (router) ->
|
|
path = sessionStorage.getItem('travis.path')
|
|
sessionStorage.removeItem('travis.path')
|
|
router.transitionTo('root')
|
|
router.route(path) if path
|
|
|
|
root: Ember.Route.extend
|
|
initialState: 'home'
|
|
loading: Ember.State.extend()
|
|
|
|
auth: Ember.Route.extend
|
|
route: '/auth'
|
|
connectOutlets: (router) ->
|
|
router.get('applicationController').connectOutlet('authLayout')
|
|
$('body').attr('id', 'auth')
|
|
router.get('authLayoutController').connectOutlet('top', 'top')
|
|
router.get('authLayoutController').connectOutlet('main', 'signin')
|
|
|
|
stats: Ember.Route.extend
|
|
route: '/stats'
|
|
connectOutlets: (router) ->
|
|
router.get('applicationController').connectOutlet 'statsLayout'
|
|
$('body').attr('id', 'stats')
|
|
router.get('statsLayoutController').connectOutlet 'top', 'top'
|
|
router.get('statsLayoutController').connectOutlet 'main', 'stats'
|
|
|
|
profile: Ember.Route.extend
|
|
initialState: 'index'
|
|
route: '/profile'
|
|
|
|
connectOutlets: (router) ->
|
|
router.get('applicationController').connectOutlet 'profileLayout'
|
|
$('body').attr('id', 'profile')
|
|
router.get('accountsController').set('content', Travis.Account.find())
|
|
router.get('profileLayoutController').connectOutlet 'top', 'top'
|
|
router.get('profileLayoutController').connectOutlet 'left', 'accounts'
|
|
|
|
index: Ember.Route.extend
|
|
route: '/'
|
|
connectOutlets: (router) ->
|
|
router.get('profileLayoutController').connectOutlet 'main', 'profile'
|
|
router.get('profileController').activate 'hooks'
|
|
|
|
account: Ember.Route.extend
|
|
initialState: 'index'
|
|
route: '/:login'
|
|
|
|
connectOutlets: (router, account) ->
|
|
if account
|
|
params = { login: account.get('login') }
|
|
router.get('profileController').setParams(params)
|
|
else
|
|
router.send 'showProfile'
|
|
|
|
deserialize: (router, params) ->
|
|
router.get('accountsController').findByLogin(params.login)
|
|
|
|
serialize: (router, account) ->
|
|
if account
|
|
{ login: account.get('login') }
|
|
else
|
|
{}
|
|
|
|
index: Ember.Route.extend
|
|
route: '/'
|
|
connectOutlets: (router) ->
|
|
router.get('profileController').activate 'hooks'
|
|
|
|
profile: Ember.Route.extend
|
|
route: '/profile'
|
|
|
|
connectOutlets: (router) ->
|
|
router.get('profileController').activate 'user'
|
|
|
|
home: Ember.Route.extend
|
|
initialState: 'show'
|
|
route: '/'
|
|
connectOutlets: (router) ->
|
|
router.get('applicationController').connectOutlet 'home'
|
|
$('body').attr('id', 'home')
|
|
router.get('homeController').connectOutlet 'left', 'repos'
|
|
router.get('homeController').connectOutlet 'right', 'sidebar'
|
|
router.get('homeController').connectOutlet 'top', 'top'
|
|
router.get('homeController').connectOutlet 'main', 'repo'
|
|
router.get('homeController').connectOutlet 'flash', 'flash'
|
|
|
|
show: Ember.Route.extend
|
|
route: '/'
|
|
connectOutlets: (router) ->
|
|
router.get('repoController').activate('index')
|
|
|
|
initialState: 'default'
|
|
default: defaultRoute
|
|
lineNumber: lineNumberRoute
|
|
resolvePath: resolvePath
|
|
|
|
showWithLineNumber: Ember.Route.extend
|
|
route: '/#/L:number'
|
|
connectOutlets: (router) ->
|
|
router.get('repoController').activate('index')
|
|
|
|
repo: Ember.Route.extend
|
|
initialState: 'show'
|
|
route: '/:owner/:name'
|
|
routeMatcher: nonHashRouteMatcher
|
|
|
|
connectOutlets: (router, repo) ->
|
|
router.get('repoController').set 'repo', repo
|
|
|
|
deserialize: (router, params) ->
|
|
slug = "#{params.owner}/#{params.name}"
|
|
repos = Travis.Repo.bySlug(slug)
|
|
deferred = $.Deferred()
|
|
|
|
observer = ->
|
|
if repos.get 'isLoaded'
|
|
repos.removeObserver 'isLoaded', observer
|
|
deferred.resolve repos.objectAt(0)
|
|
|
|
repos.addObserver 'isLoaded', observer
|
|
|
|
deferred.promise()
|
|
|
|
serialize: (router, repo) ->
|
|
if repo
|
|
{ owner: repo.get('owner'), name: repo.get('name') }
|
|
else
|
|
{}
|
|
|
|
show: Ember.Route.extend
|
|
route: '/'
|
|
connectOutlets: (router) ->
|
|
router.get('repoController').activate('current')
|
|
|
|
initialState: 'default'
|
|
default: defaultRoute
|
|
lineNumber: lineNumberRoute
|
|
resolvePath: resolvePath
|
|
|
|
builds: Ember.Route.extend
|
|
route: '/builds'
|
|
initialState: 'index'
|
|
|
|
index: Ember.Route.extend
|
|
route: '/'
|
|
connectOutlets: (router, repo) ->
|
|
router.get('repoController').activate 'builds'
|
|
|
|
show: Ember.Route.extend
|
|
route: '/:build_id'
|
|
connectOutlets: (router, build) ->
|
|
unless build.get
|
|
# TODO: apparently when I use id in url, it will pass it
|
|
# here, why doesn't it use deserialize?
|
|
build = Travis.Build.find(build)
|
|
router.get('repoController').set 'build', build
|
|
router.get('repoController').activate 'build'
|
|
|
|
serialize: (router, build) ->
|
|
if build.get
|
|
{ build_id: build.get('id') }
|
|
else
|
|
{ build_id: build }
|
|
|
|
deserialize: (router, params) ->
|
|
# Something is wrong here. If I don't use deferred, id is not
|
|
# initialized and url ends up being /jobs/null
|
|
# This should not be needed, as id should be immediately set on the
|
|
# record.
|
|
# TODO: find out why it happens
|
|
build = Travis.Build.find params.build_id
|
|
deferred = $.Deferred()
|
|
|
|
observer = ->
|
|
if build.get 'id'
|
|
build.removeObserver 'id', observer
|
|
deferred.resolve build
|
|
|
|
build.addObserver 'id', observer
|
|
|
|
deferred.promise()
|
|
|
|
# TODO: this is not dry, but for some weird
|
|
# reason Mixins don't play nice with Ember.Route
|
|
initialState: 'default'
|
|
default: defaultRoute
|
|
lineNumber: lineNumberRoute
|
|
routeMatcher: nonHashRouteMatcher
|
|
resolvePath: resolvePath
|
|
|
|
pullRequests: Ember.Route.extend
|
|
route: '/pull_requests'
|
|
connectOutlets: (router, repo) ->
|
|
router.get('repoController').activate 'pull_requests'
|
|
|
|
branches: Ember.Route.extend
|
|
route: '/branches'
|
|
connectOutlets: (router, repo) ->
|
|
router.get('repoController').activate 'branches'
|
|
|
|
job: Ember.Route.extend
|
|
route: '/jobs/:job_id'
|
|
connectOutlets: (router, job) ->
|
|
unless job.get
|
|
# In case I use id
|
|
job = Travis.Job.find(job)
|
|
router.get('repoController').set 'job', job
|
|
router.get('repoController').activate 'job'
|
|
|
|
serialize: (router, job) ->
|
|
if job.get
|
|
{ job_id: job.get('id') }
|
|
else
|
|
{ job_id: job }
|
|
|
|
deserialize: (router, params) ->
|
|
job = Travis.Job.find params.job_id
|
|
deferred = $.Deferred()
|
|
|
|
observer = ->
|
|
if job.get 'id'
|
|
job.removeObserver 'id', observer
|
|
deferred.resolve job
|
|
job.addObserver 'id', observer
|
|
deferred.promise()
|
|
|
|
initialState: 'default'
|
|
default: defaultRoute
|
|
lineNumber: lineNumberRoute
|
|
routeMatcher: nonHashRouteMatcher
|
|
resolvePath: resolvePath
|