mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-05-03 17:33:31 -04:00
Migrates Artisan helpers to their own directory and begins implementation of level tasks view
This commit is contained in:
parent
abe9d5c267
commit
0436f18279
13 changed files with 265 additions and 0 deletions
app
core
styles/artisans
templates/artisans
views/artisans
|
@ -43,6 +43,12 @@ module.exports = class CocoRouter extends Backbone.Router
|
||||||
'admin/pending-patches': go('admin/PendingPatchesView')
|
'admin/pending-patches': go('admin/PendingPatchesView')
|
||||||
'admin/codelogs': go('admin/CodeLogsView')
|
'admin/codelogs': go('admin/CodeLogsView')
|
||||||
|
|
||||||
|
'artisans': go('artisans/ArtisansView')
|
||||||
|
|
||||||
|
'artisans/level-analytics': go('artisans/LevelAnalyticsView')
|
||||||
|
'artisans/level-tasks': go('artisans/LevelTasksView')
|
||||||
|
'artisans/thang-tasks': go('artisans/ThangTasksView')
|
||||||
|
|
||||||
'beta': go('HomeView')
|
'beta': go('HomeView')
|
||||||
|
|
||||||
'careers': => window.location.href = 'https://jobs.lever.co/codecombat'
|
'careers': => window.location.href = 'https://jobs.lever.co/codecombat'
|
||||||
|
|
6
app/styles/artisans/artisansView.sass
Normal file
6
app/styles/artisans/artisansView.sass
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#artisans-view
|
||||||
|
text-align: center
|
||||||
|
a
|
||||||
|
font-size: xx-large
|
||||||
|
img
|
||||||
|
border-radius: 8px
|
1
app/styles/artisans/levelAnalyticsView.sass
Normal file
1
app/styles/artisans/levelAnalyticsView.sass
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#level-analytics-view
|
12
app/styles/artisans/levelTasksView.sass
Normal file
12
app/styles/artisans/levelTasksView.sass
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#level-tasks-view
|
||||||
|
#levelTable
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.tasksTable
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.tasks
|
||||||
|
width: 87.5%
|
||||||
|
|
||||||
|
.taskOwner
|
||||||
|
width: 12.5%
|
12
app/styles/artisans/thangTasksView.sass
Normal file
12
app/styles/artisans/thangTasksView.sass
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#thang-tasks-view
|
||||||
|
#thangTable
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.tasksTable
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.tasks
|
||||||
|
width: 87.5%
|
||||||
|
|
||||||
|
.taskOwner
|
||||||
|
width: 12.5%
|
10
app/templates/artisans/artisansView.jade
Normal file
10
app/templates/artisans/artisansView.jade
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
extends /templates/base
|
||||||
|
|
||||||
|
block content
|
||||||
|
img(src='/images/pages/user/artisan.png')
|
||||||
|
div
|
||||||
|
a(href='artisans/thang-tasks')
|
||||||
|
|Thang Tasks
|
||||||
|
div
|
||||||
|
a(href="artisans/level-tasks")
|
||||||
|
|Level Tasks
|
4
app/templates/artisans/levelAnalyticsView.jade
Normal file
4
app/templates/artisans/levelAnalyticsView.jade
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
extends /templates/base
|
||||||
|
|
||||||
|
block content
|
||||||
|
table#levelTable
|
34
app/templates/artisans/levelTasksView.jade
Normal file
34
app/templates/artisans/levelTasksView.jade
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
extends /templates/base
|
||||||
|
|
||||||
|
block content
|
||||||
|
#level-tasks-view
|
||||||
|
div
|
||||||
|
a(href='./')
|
||||||
|
| < Artisans Home
|
||||||
|
input#nameSearch(placeholder='Filter: Level Name')
|
||||||
|
br
|
||||||
|
input#descSearch(placeholder='Filter: Task Description')
|
||||||
|
hr
|
||||||
|
if view.processedLevels
|
||||||
|
table.table.table-striped#levelTable
|
||||||
|
tr
|
||||||
|
th Level Name
|
||||||
|
th Task List
|
||||||
|
for level in view.processedLevels
|
||||||
|
if view.hasIncompleteTasks(level)
|
||||||
|
+levelRow(level)
|
||||||
|
else
|
||||||
|
div ole?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mixin levelRow(level)
|
||||||
|
tr
|
||||||
|
td.taskOwner
|
||||||
|
a(href= 'level/' + level.slug)= level.name
|
||||||
|
td.tasks
|
||||||
|
table.table-striped.table-hover.tasksTable
|
||||||
|
for task in (level.tasks2 || [])
|
||||||
|
if !task.complete
|
||||||
|
tr
|
||||||
|
td= task.name
|
32
app/templates/artisans/thangTasksView.jade
Normal file
32
app/templates/artisans/thangTasksView.jade
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
extends /templates/base
|
||||||
|
|
||||||
|
block content
|
||||||
|
#thang-tasks-view
|
||||||
|
div
|
||||||
|
a(href='./')
|
||||||
|
| < Artisans Home
|
||||||
|
input#nameSearch(placeholder='Filter: Thang Name')
|
||||||
|
br
|
||||||
|
input#descSearch(placeholder='Filter: Task Description')
|
||||||
|
hr
|
||||||
|
if view.processedThangs
|
||||||
|
table.table.table-striped#thangTable
|
||||||
|
tr
|
||||||
|
th Thang Name
|
||||||
|
th Task List
|
||||||
|
for thang in view.processedThangs
|
||||||
|
if view.hasIncompleteTasks(thang)
|
||||||
|
+thangRow(thang)
|
||||||
|
else
|
||||||
|
span No view.processedThangs
|
||||||
|
|
||||||
|
mixin thangRow(thang)
|
||||||
|
tr
|
||||||
|
td.taskOwner
|
||||||
|
a(href= 'thang/' + thang.get('slug'))= thang.get('name')
|
||||||
|
td.tasks
|
||||||
|
table.table-striped.table-hover.tasksTable
|
||||||
|
for task in (thang.tasks || [])
|
||||||
|
if !task.complete
|
||||||
|
tr
|
||||||
|
td= task.name
|
8
app/views/artisans/ArtisansView.coffee
Normal file
8
app/views/artisans/ArtisansView.coffee
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
RootView = require 'views/core/RootView'
|
||||||
|
template = require 'templates/artisans/artisansView'
|
||||||
|
|
||||||
|
module.exports = class ArtisansView extends RootView
|
||||||
|
template: template
|
||||||
|
id: 'artisans-view'
|
||||||
|
constructor: (options) ->
|
||||||
|
super options
|
35
app/views/artisans/LevelAnalyticsView.coffee
Normal file
35
app/views/artisans/LevelAnalyticsView.coffee
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
RootView = require 'views/core/RootView'
|
||||||
|
template = require 'templates/artisans/levelAnalyticsView'
|
||||||
|
Level = require 'models/Level'
|
||||||
|
Campaign = require 'models/Campaign'
|
||||||
|
CocoCollection = require 'collections/CocoCollection'
|
||||||
|
|
||||||
|
module.exports = class LevelAnalyticsView extends RootView
|
||||||
|
template: template
|
||||||
|
id: 'level-analytics-view'
|
||||||
|
constructor: (options) ->
|
||||||
|
super options
|
||||||
|
@campaigns = new CocoCollection([],
|
||||||
|
url: '/db/campaign?project=name,slug,tasks'
|
||||||
|
model: Campaign
|
||||||
|
)
|
||||||
|
@campaigns.fetch()
|
||||||
|
@listenTo(@campaigns, 'sync', @onCampaignsLoaded)
|
||||||
|
@supermodel.loadCollection(@campaigns, 'campaigns')
|
||||||
|
onCampaignsLoaded: ->
|
||||||
|
@levels = []
|
||||||
|
for campaign in @campaigns.models
|
||||||
|
continue unless campaign.get('slug') is 'dungeon'
|
||||||
|
levels = campaign.get('levels')
|
||||||
|
for key, level of levels
|
||||||
|
@levels.push level.slug
|
||||||
|
@stats = new CocoCollection([],
|
||||||
|
url: '/db/analytics_perday/-/level_completions?slug=dungeons-of-kithgard&startDay=20151022&endDay=20151104'
|
||||||
|
model: {}
|
||||||
|
)
|
||||||
|
@stats.fetch()
|
||||||
|
@listenTo(@stats, 'sync', @onStatsLoaded)
|
||||||
|
@supermodel.loadCollection(@stats, 'stats')
|
||||||
|
@renderSelectors '#levelTable'
|
||||||
|
onStatsLoaded: ->
|
||||||
|
console.log @stats
|
57
app/views/artisans/LevelTasksView.coffee
Normal file
57
app/views/artisans/LevelTasksView.coffee
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
RootView = require 'views/core/RootView'
|
||||||
|
template = require 'templates/artisans/levelTasksView'
|
||||||
|
#ThangType = require 'models/ThangType'
|
||||||
|
Level = require 'models/Level'
|
||||||
|
Campaign = require 'models/Campaign'
|
||||||
|
CocoCollection = require 'collections/CocoCollection'
|
||||||
|
|
||||||
|
module.exports = class LevelTasksView extends RootView
|
||||||
|
template: template
|
||||||
|
id: 'level-tasks-view'
|
||||||
|
events:
|
||||||
|
'input input': 'searchUpdate'
|
||||||
|
'change input': 'searchUpdate'
|
||||||
|
excludedCampaigns = [
|
||||||
|
"picoctf"
|
||||||
|
"auditions"
|
||||||
|
]
|
||||||
|
constructor: (options) ->
|
||||||
|
super options
|
||||||
|
@campaigns = new CocoCollection([],
|
||||||
|
url: '/db/campaign?project=name,slug,tasks'
|
||||||
|
model: Campaign
|
||||||
|
)
|
||||||
|
@campaigns.fetch()
|
||||||
|
@listenTo(@campaigns, 'sync', @onCampaignsLoaded)
|
||||||
|
@supermodel.loadCollection(@campaigns, 'campaigns')
|
||||||
|
|
||||||
|
onCampaignsLoaded: ->
|
||||||
|
@levels = {}
|
||||||
|
sum = 0
|
||||||
|
for campaign in @campaigns.models
|
||||||
|
continue unless excludedCampaigns.indexOf(campaign.get 'slug') is -1
|
||||||
|
levels = campaign.get('levels')
|
||||||
|
sum += Object.keys(levels).length
|
||||||
|
for key, level of levels
|
||||||
|
continue unless ///#{$('#nameSearch')[0].value}///i.test level.name
|
||||||
|
levelSlug = level.slug
|
||||||
|
@levels[levelSlug] = level
|
||||||
|
@processedLevels = @levels
|
||||||
|
for key, level of @processedLevels
|
||||||
|
level.tasks2 = _.filter level.tasks, (_elem) ->
|
||||||
|
return ///#{$('#descSearch')[0].value}///i.test _elem.name
|
||||||
|
@renderSelectors '#levelTable'
|
||||||
|
|
||||||
|
searchUpdate: ->
|
||||||
|
if not @lastLoad? or (new Date()).getTime() - @lastLoad > 60 * 1000 * 1 # Update only after a minute from last update.
|
||||||
|
@campaigns.fetch()
|
||||||
|
@listenTo(@campaigns, 'sync', @onCampaignsLoaded)
|
||||||
|
@supermodel.loadCollection(@campaigns, 'campaigns')
|
||||||
|
@lastLoad = (new Date()).getTime()
|
||||||
|
else
|
||||||
|
@onCampaignsLoaded()
|
||||||
|
|
||||||
|
|
||||||
|
# Jade helper
|
||||||
|
hasIncompleteTasks: (level) ->
|
||||||
|
return level.tasks2 and level.tasks2.filter((_elem) -> return not _elem.complete).length > 0
|
48
app/views/artisans/ThangTasksView.coffee
Normal file
48
app/views/artisans/ThangTasksView.coffee
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
RootView = require 'views/core/RootView'
|
||||||
|
template = require 'templates/artisans/thangTasksView'
|
||||||
|
ThangType = require 'models/ThangType'
|
||||||
|
CocoCollection = require 'collections/CocoCollection'
|
||||||
|
|
||||||
|
module.exports = class ThangTasksView extends RootView
|
||||||
|
template: template
|
||||||
|
id: 'thang-tasks-view'
|
||||||
|
events:
|
||||||
|
'input input': 'searchUpdate'
|
||||||
|
'change input': 'searchUpdate'
|
||||||
|
|
||||||
|
constructor: (options) ->
|
||||||
|
super options
|
||||||
|
@thangs = new CocoCollection([],
|
||||||
|
url: '/db/thang.type?project=name,tasks,slug'
|
||||||
|
model: ThangType
|
||||||
|
comparator: @sortThangs
|
||||||
|
)
|
||||||
|
@lastLoad = (new Date()).getTime()
|
||||||
|
@listenTo(@thangs, 'sync', @onThangsLoaded)
|
||||||
|
@supermodel.loadCollection(@thangs, 'thangs')
|
||||||
|
|
||||||
|
searchUpdate: ->
|
||||||
|
if not @lastLoad? or (new Date()).getTime() - @lastLoad > 60 * 1000 * 1 # Update only after a minute from last update.
|
||||||
|
@thangs.fetch()
|
||||||
|
@listenTo(@thangs, 'sync', @onThangsLoaded)
|
||||||
|
@supermodel.loadCollection(@thangs, 'thangs')
|
||||||
|
@lastLoad = (new Date()).getTime()
|
||||||
|
else
|
||||||
|
@onThangsLoaded()
|
||||||
|
|
||||||
|
onThangsLoaded: ->
|
||||||
|
@processedThangs = @thangs.filter (_elem) ->
|
||||||
|
# Case-insensitive search of input vs name.
|
||||||
|
return ///#{$('#nameSearch')[0].value}///i.test _elem.get('name')
|
||||||
|
for thang in @processedThangs
|
||||||
|
thang.tasks = _.filter thang.attributes.tasks, (_elem) ->
|
||||||
|
# Similar case-insensitive search of input vs description (name).
|
||||||
|
return ///#{$('#descSearch')[0].value}///i.test _elem.name
|
||||||
|
@renderSelectors '#thangTable'
|
||||||
|
|
||||||
|
sortThangs: (a, b) ->
|
||||||
|
a.get('name').localeCompare(b.get('name'))
|
||||||
|
|
||||||
|
# Jade helper
|
||||||
|
hasIncompleteTasks: (thang) ->
|
||||||
|
return thang.tasks and thang.tasks.filter((_elem) -> return not _elem.complete).length > 0
|
Loading…
Add table
Add a link
Reference in a new issue