2016-03-30 13:57:19 -07:00
go = (path, options) -> -> @ routeDirectly path , arguments , options
redirect = (path) -> -> @ navigate ( path , { trigger: true , replace: true } )
2016-04-13 09:54:24 -07:00
utils = require ' ./utils '
2016-04-07 19:06:57 -07:00
2014-01-03 10:32:13 -08:00
module.exports = class CocoRouter extends Backbone . Router
2014-07-23 07:02:45 -07:00
initialize: ->
2016-03-30 16:20:37 -07:00
# http://nerds.airbnb.com/how-to-add-google-analytics-page-tracking-to-57536
2014-07-23 07:02:45 -07:00
@ bind ' route ' , @ _trackPageView
2014-01-03 10:32:13 -08:00
Backbone . Mediator . subscribe ' router:navigate ' , @ onNavigate , @
2014-10-15 16:43:26 -04:00
@initializeSocialMediaServices = _ . once @ initializeSocialMediaServices
2014-01-03 10:32:13 -08:00
routes:
2016-01-26 16:28:29 -08:00
' ' : ->
2016-02-16 20:39:59 -08:00
if window . serverConfig . picoCTF
return @ routeDirectly ' play/CampaignView ' , [ ' picoctf ' ] , { }
2016-04-13 09:54:24 -07:00
if utils . getQueryVariable ' hour_of_code '
return @ navigate " /play " , { trigger: true , replace: true }
2016-03-01 09:48:50 -08:00
return @ routeDirectly ( ' NewHomeView ' , [ ] )
2014-07-18 17:06:20 -07:00
2014-07-17 17:16:32 -07:00
' about ' : go ( ' AboutView ' )
2014-08-13 19:17:26 -07:00
2014-07-29 17:28:13 +02:00
' account ' : go ( ' account/MainAccountView ' )
2014-11-25 12:43:17 -08:00
' account/settings ' : go ( ' account/AccountSettingsRootView ' )
2014-07-23 07:02:45 -07:00
' account/unsubscribe ' : go ( ' account/UnsubscribeView ' )
2014-11-25 11:09:29 -08:00
' account/payments ' : go ( ' account/PaymentsView ' )
2014-12-10 13:42:12 -08:00
' account/subscription ' : go ( ' account/SubscriptionView ' )
2015-03-04 15:40:32 -08:00
' account/invoices ' : go ( ' account/InvoicesView ' )
2015-09-25 10:03:44 -07:00
' account/prepaid ' : go ( ' account/PrepaidView ' )
2014-08-13 19:17:26 -07:00
2014-07-23 07:02:45 -07:00
' admin ' : go ( ' admin/MainAdminView ' )
' admin/clas ' : go ( ' admin/CLAsView ' )
2016-01-06 16:11:28 -08:00
' admin/design-elements ' : go ( ' admin/DesignElementsView ' )
2014-07-23 07:02:45 -07:00
' admin/files ' : go ( ' admin/FilesView ' )
2015-11-04 10:54:40 -08:00
' admin/analytics ' : go ( ' admin/AnalyticsView ' )
2015-03-27 11:22:21 -07:00
' admin/analytics/subscriptions ' : go ( ' admin/AnalyticsSubscriptionsView ' )
2014-07-23 07:02:45 -07:00
' admin/level-sessions ' : go ( ' admin/LevelSessionsView ' )
' admin/users ' : go ( ' admin/UsersView ' )
2014-08-30 20:27:58 -07:00
' admin/base ' : go ( ' admin/BaseView ' )
2016-05-11 11:52:30 -07:00
' admin/demo-requests ' : go ( ' admin/DemoRequestsView ' )
2015-06-05 06:48:09 -07:00
' admin/trial-requests ' : go ( ' admin/TrialRequestsView ' )
2014-10-24 15:11:55 -07:00
' admin/user-code-problems ' : go ( ' admin/UserCodeProblemsView ' )
2015-03-28 13:54:44 -07:00
' admin/pending-patches ' : go ( ' admin/PendingPatchesView ' )
2016-02-08 14:24:08 -08:00
' admin/codelogs ' : go ( ' admin/CodeLogsView ' )
2014-07-18 17:06:20 -07:00
2016-04-04 11:03:07 -07:00
' artisans ' : go ( ' artisans/ArtisansView ' )
' artisans/level-tasks ' : go ( ' artisans/LevelTasksView ' )
2016-05-16 11:45:06 -07:00
' artisans/solution-problems ' : go ( ' artisans/SolutionProblemsView ' )
2016-04-04 11:03:07 -07:00
' artisans/thang-tasks ' : go ( ' artisans/ThangTasksView ' )
2014-07-18 17:06:20 -07:00
' beta ' : go ( ' HomeView ' )
2015-09-25 15:49:00 -07:00
' careers ' : => window . location.href = ' https://jobs.lever.co/codecombat '
2015-10-26 20:39:36 -07:00
' Careers ' : => window . location.href = ' https://jobs.lever.co/codecombat '
2015-09-14 17:38:18 -07:00
2014-07-17 17:16:32 -07:00
' cla ' : go ( ' CLAView ' )
2015-03-31 13:28:57 -07:00
' clans ' : go ( ' clans/ClansView ' )
' clans/:clanID ' : go ( ' clans/ClanDetailsView ' )
2014-07-17 17:16:32 -07:00
' community ' : go ( ' CommunityView ' )
2014-08-13 19:17:26 -07:00
2014-07-17 17:16:32 -07:00
' contribute ' : go ( ' contribute/MainContributeView ' )
' contribute/adventurer ' : go ( ' contribute/AdventurerView ' )
' contribute/ambassador ' : go ( ' contribute/AmbassadorView ' )
' contribute/archmage ' : go ( ' contribute/ArchmageView ' )
' contribute/artisan ' : go ( ' contribute/ArtisanView ' )
' contribute/diplomat ' : go ( ' contribute/DiplomatView ' )
' contribute/scribe ' : go ( ' contribute/ScribeView ' )
2014-07-18 17:06:20 -07:00
2016-03-30 13:57:19 -07:00
' courses ' : go ( ' courses/CoursesView ' ) # , { studentsOnly: true }) # TODO: Enforce after session-less play for teachers
' Courses ' : go ( ' courses/CoursesView ' ) # , { studentsOnly: true })
' courses/students ' : redirect ( ' /courses ' )
' courses/teachers ' : redirect ( ' /teachers/classes ' )
2016-05-25 05:52:43 -07:00
' courses/purchase ' : redirect ( ' /teachers/licenses ' )
' courses/enroll(/:courseID) ' : redirect ( ' /teachers/licenses ' )
2016-05-16 14:33:20 -07:00
' courses/update-account ' : go ( ' courses/CoursesUpdateAccountView ' )
2016-03-30 13:57:19 -07:00
' courses/:classroomID ' : go ( ' courses/ClassroomView ' ) #, { studentsOnly: true })
2015-11-30 14:14:27 -05:00
' courses/:courseID/:courseInstanceID ' : go ( ' courses/CourseDetailsView ' )
2015-06-29 12:15:07 -07:00
2014-07-23 07:02:45 -07:00
' db/*path ' : ' routeToServer '
2014-07-18 17:06:20 -07:00
' demo(/*subpath) ' : go ( ' DemoView ' )
2014-08-28 22:32:55 -07:00
' docs/components ' : go ( ' docs/ComponentsDocumentationView ' )
' docs/systems ' : go ( ' docs/SystemsDocumentationView ' )
2014-08-13 19:17:26 -07:00
2014-08-26 17:34:00 -07:00
' editor ' : go ( ' CommunityView ' )
2014-07-23 07:02:45 -07:00
' editor/achievement ' : go ( ' editor/achievement/AchievementSearchView ' )
2014-08-03 23:58:51 +02:00
' editor/achievement/:articleID ' : go ( ' editor/achievement/AchievementEditView ' )
2014-07-23 07:02:45 -07:00
' editor/article ' : go ( ' editor/article/ArticleSearchView ' )
' editor/article/preview ' : go ( ' editor/article/ArticlePreviewView ' )
' editor/article/:articleID ' : go ( ' editor/article/ArticleEditView ' )
' editor/level ' : go ( ' editor/level/LevelSearchView ' )
' editor/level/:levelID ' : go ( ' editor/level/LevelEditView ' )
' editor/thang ' : go ( ' editor/thang/ThangTypeSearchView ' )
' editor/thang/:thangID ' : go ( ' editor/thang/ThangTypeEditView ' )
2014-12-16 17:46:24 -08:00
' editor/campaign/:campaignID ' : go ( ' editor/campaign/CampaignEditorView ' )
2015-03-07 16:30:25 -08:00
' editor/poll ' : go ( ' editor/poll/PollSearchView ' )
' editor/poll/:articleID ' : go ( ' editor/poll/PollEditView ' )
2015-12-21 12:44:22 -08:00
' editor/thang-tasks ' : go ( ' editor/ThangTasksView ' )
2016-04-07 19:06:57 -07:00
' editor/verifier ' : go ( ' editor/verifier/VerifierView ' )
' editor/verifier/:levelID ' : go ( ' editor/verifier/VerifierView ' )
2014-08-13 19:17:26 -07:00
2014-07-23 07:02:45 -07:00
' file/*path ' : ' routeToServer '
2014-08-15 16:20:45 +02:00
' github/*path ' : ' routeToServer '
2016-05-16 14:50:34 -07:00
' hoc ' : ->
# Matching /?hour_of_code=true behavior
@ navigate " /play " , { trigger: true , replace: true }
2016-01-26 16:28:29 -08:00
' home ' : go ( ' NewHomeView ' )
2015-10-12 16:25:23 -07:00
2014-10-27 17:11:48 -07:00
' i18n ' : go ( ' i18n/I18NHomeView ' )
' i18n/thang/:handle ' : go ( ' i18n/I18NEditThangTypeView ' )
' i18n/component/:handle ' : go ( ' i18n/I18NEditComponentView ' )
' i18n/level/:handle ' : go ( ' i18n/I18NEditLevelView ' )
' i18n/achievement/:handle ' : go ( ' i18n/I18NEditAchievementView ' )
2015-01-29 09:07:25 -08:00
' i18n/campaign/:handle ' : go ( ' i18n/I18NEditCampaignView ' )
2015-03-07 16:30:25 -08:00
' i18n/poll/:handle ' : go ( ' i18n/I18NEditPollView ' )
2014-10-27 17:11:48 -07:00
2015-04-30 13:35:21 -07:00
' identify ' : go ( ' user/IdentifyView ' )
2014-07-18 17:06:20 -07:00
' legal ' : go ( ' LegalView ' )
2014-08-13 19:17:26 -07:00
2014-07-18 17:06:20 -07:00
' multiplayer ' : go ( ' MultiplayerView ' )
2015-10-21 16:34:25 -07:00
' play(/) ' : go ( ' play/CampaignView ' ) # extra slash is to get Facebook app to work
2015-08-15 06:45:38 -07:00
' play/ladder/:levelID/:leagueType/:leagueID ' : go ( ' ladder/LadderView ' )
2014-11-29 16:46:36 -08:00
' play/ladder/:levelID ' : go ( ' ladder/LadderView ' )
' play/ladder ' : go ( ' ladder/MainLadderView ' )
2014-07-23 07:02:45 -07:00
' play/level/:levelID ' : go ( ' play/level/PlayLevelView ' )
' play/spectate/:levelID ' : go ( ' play/SpectateView ' )
2014-12-28 13:55:20 -08:00
' play/:map ' : go ( ' play/CampaignView ' )
2014-07-23 07:02:45 -07:00
2014-07-18 17:06:20 -07:00
' preview ' : go ( ' HomeView ' )
2016-02-01 08:39:00 -08:00
' privacy ' : go ( ' PrivacyView ' )
2016-02-05 13:47:32 -08:00
' schools ' : go ( ' NewHomeView ' )
2016-05-17 10:50:25 -07:00
' seen ' : go ( ' NewHomeView ' )
' SEEN ' : go ( ' NewHomeView ' )
2015-12-14 20:43:34 -08:00
2016-04-05 09:34:45 -07:00
' teachers ' : redirect ( ' /teachers/classes ' )
2016-03-30 13:57:19 -07:00
' teachers/classes ' : go ( ' courses/TeacherClassesView ' ) #, { teachersOnly: true })
' teachers/classes/:classroomID ' : go ( ' courses/TeacherClassView ' ) #, { teachersOnly: true })
' teachers/courses ' : go ( ' courses/TeacherCoursesView ' )
2016-03-09 14:40:52 -08:00
' teachers/demo ' : go ( ' teachers/RequestQuoteView ' )
2016-05-25 05:52:43 -07:00
' teachers/enrollments ' : redirect ( ' /teachers/licenses ' )
' teachers/licenses ' : go ( ' courses/EnrollmentsView ' ) #, { teachersOnly: true })
2016-03-09 14:40:52 -08:00
' teachers/freetrial ' : go ( ' teachers/RequestQuoteView ' )
' teachers/quote ' : go ( ' teachers/RequestQuoteView ' )
' teachers/signup ' : ->
return @ routeDirectly ( ' teachers/CreateTeacherAccountView ' , [ ] ) if me . isAnonymous ( )
2016-04-05 09:16:22 -07:00
@ navigate ( ' /teachers/update-account ' , { trigger: true , replace: true } )
' teachers/update-account ' : ->
2016-03-09 14:40:52 -08:00
return @ navigate ( ' /teachers/signup ' , { trigger: true , replace: true } ) if me . isAnonymous ( )
@ routeDirectly ( ' teachers/ConvertToTeacherAccountView ' , [ ] )
2014-08-13 19:17:26 -07:00
2014-07-18 17:06:20 -07:00
' test(/*subpath) ' : go ( ' TestView ' )
2014-07-21 19:49:16 +02:00
' user/:slugOrID ' : go ( ' user/MainUserView ' )
2016-05-11 14:39:26 -07:00
' user/:userID/verify/:verificationCode ' : go ( ' user/EmailVerifiedView ' )
2014-07-06 20:45:27 +02:00
2015-10-21 16:34:25 -07:00
' *name/ ' : ' removeTrailingSlash '
2015-06-24 14:46:59 -07:00
' *name ' : go ( ' NotFoundView ' )
2014-07-13 22:34:32 +02:00
2014-07-23 07:02:45 -07:00
routeToServer: (e) ->
window . location.href = window . location . href
2014-07-10 20:50:16 +02:00
2015-10-21 16:34:25 -07:00
removeTrailingSlash: (e) ->
@ navigate e , { trigger: true }
2016-03-30 13:57:19 -07:00
routeDirectly: (path, args=[], options={}) ->
if options . teachersOnly and not me . isTeacher ( )
return @ routeDirectly ( ' teachers/RestrictedToTeachersView ' )
if options . studentsOnly and me . isTeacher ( )
return @ routeDirectly ( ' courses/RestrictedToStudentsView ' )
2016-04-19 10:20:56 -07:00
leavingMessage = _ . result ( window . currentView , ' onLeaveMessage ' )
if leavingMessage
if not confirm ( leavingMessage )
return @ navigate ( this . path , { replace: true } )
else
window . currentView.onLeaveMessage = _ . noop # to stop repeat confirm calls
2016-04-07 19:06:57 -07:00
2016-02-17 09:53:45 -08:00
path = ' play/CampaignView ' if window . serverConfig . picoCTF and not /^(views)?\/?play/ . test ( path )
2015-01-04 08:05:38 -08:00
path = " views/ #{ path } " if not _ . string . startsWith ( path , ' views/ ' )
2014-07-23 07:02:45 -07:00
ViewClass = @ tryToLoadModule path
2014-11-28 16:38:50 -08:00
if not ViewClass and application . moduleLoader . load ( path )
@ listenToOnce application . moduleLoader , ' load-complete ' , ->
2016-01-26 16:28:29 -08:00
@ routeDirectly ( path , args , options )
2014-11-28 16:38:50 -08:00
return
2014-07-23 07:02:45 -07:00
return @ openView @ notFoundView ( ) if not ViewClass
2016-01-26 16:28:29 -08:00
view = new ViewClass ( options , args . . . ) # options, then any path fragment args
2014-07-23 07:02:45 -07:00
view . render ( )
@ openView ( view )
2014-07-10 20:50:16 +02:00
2014-07-23 07:02:45 -07:00
tryToLoadModule: (path) ->
try
return require ( path )
catch error
if error . toString ( ) . search ( ' Cannot find module " ' + path + ' " from ' ) is - 1
throw error
2014-01-03 10:32:13 -08:00
openView: (view) ->
@ closeCurrentView ( )
$ ( ' # page-container ' ) . empty ( ) . append view . el
window . currentView = view
@ activateTab ( )
view . afterInsert ( )
2014-07-23 07:02:45 -07:00
view . didReappear ( )
2016-04-19 10:20:56 -07:00
@path = document . location . pathname + document . location . search
2014-07-23 07:02:45 -07:00
closeCurrentView: ->
if window . currentView ? . reloadOnClose
return document . location . reload ( )
window . currentModal ? . hide ? ( )
return unless window . currentView ?
window . currentView . destroy ( )
2014-10-06 18:09:27 -07:00
$ ( ' .popover ' ) . popover ' hide '
2016-02-17 09:59:08 -08:00
$ ( ' # flying-focus ' ) . css ( { top: 0 , left: 0 } ) # otherwise it might make the page unnecessarily tall
2016-03-30 13:57:19 -07:00
_ . delay ( ->
2016-02-17 11:21:43 -08:00
$ ( ' html ' ) [ 0 ] . scrollTop = 0
$ ( ' body ' ) [ 0 ] . scrollTop = 0
) , 10
2014-01-03 10:32:13 -08:00
2014-10-15 16:43:26 -04:00
initializeSocialMediaServices: ->
return if application . testing or application . demoing
2016-03-15 13:50:33 -07:00
application . facebookHandler . loadAPI ( )
2016-02-25 15:24:16 -08:00
application . gplusHandler . loadAPI ( )
2014-11-28 17:49:41 -08:00
require ( ' core/services/twitter ' ) ( )
2014-01-03 10:32:13 -08:00
2016-03-15 13:50:33 -07:00
renderSocialButtons: =>
2016-03-30 16:20:37 -07:00
# TODO: Refactor remaining services to Handlers, use loadAPI success callback
2014-10-15 16:43:26 -04:00
@ initializeSocialMediaServices ( )
2014-01-06 23:45:33 -08:00
$ ( ' .share-buttons, .partner-badges ' ) . addClass ( ' fade-in ' ) . delay ( 10000 ) . removeClass ( ' fade-in ' , 5000 )
2016-03-15 13:50:33 -07:00
application . facebookHandler . renderButtons ( )
application . gplusHandler . renderButtons ( )
2014-01-09 10:48:51 -08:00
twttr ? . widgets ? . load ? ( )
2016-04-07 19:06:57 -07:00
2014-01-03 10:32:13 -08:00
activateTab: ->
base = _ . string . words ( document . location . pathname [ 1 . . ] , ' / ' ) [ 0 ]
$ ( " ul.nav li. #{ base } " ) . addClass ( ' active ' )
_trackPageView: ->
2015-02-27 16:07:41 -08:00
window . tracker ? . trackPageView ( )
2014-01-03 10:32:13 -08:00
onNavigate: (e) ->
2014-11-29 16:46:36 -08:00
if _ . isString e . viewClass
ViewClass = @ tryToLoadModule e . viewClass
if not ViewClass and application . moduleLoader . load ( e . viewClass )
@ listenToOnce application . moduleLoader , ' load-complete ' , ->
@ onNavigate ( e )
return
e.viewClass = ViewClass
2014-01-03 10:32:13 -08:00
manualView = e . view or e . viewClass
2014-11-07 08:54:22 -08:00
if ( e . route is document . location . pathname ) and not manualView
return document . location . reload ( )
2014-03-16 21:33:46 -07:00
@ navigate e . route , { trigger: not manualView }
2015-03-09 12:46:34 -07:00
@ _trackPageView ( )
2014-01-03 10:32:13 -08:00
return unless manualView
if e . viewClass
args = e . viewArgs or [ ]
view = new e . viewClass ( args . . . )
view . render ( )
@ openView view
else
@ openView e . view
2014-10-01 10:58:19 -07:00
navigate: (fragment, options) ->
super fragment , options
Backbone . Mediator . publish ' router:navigated ' , route: fragment
2016-03-09 14:40:52 -08:00
reload: ->
2016-03-30 16:20:37 -07:00
document . location . reload ( )