mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-07 18:44:29 -04:00
Fixed #1414. Also started lazily loading certain level editor tabs.
This commit is contained in:
parent
a284c8eb37
commit
5f132e55ba
12 changed files with 146 additions and 20 deletions
app
locale
schemas/subscriptions
styles/editor/level
templates/editor/level
views
server/levels
|
@ -953,6 +953,7 @@
|
|||
achievement: "Achievement"
|
||||
clas: "CLAs"
|
||||
play_counts: "Play Counts"
|
||||
feedback: "Feedback"
|
||||
|
||||
delta:
|
||||
added: "Added"
|
||||
|
|
|
@ -5,7 +5,8 @@ module.exports =
|
|||
major: {type: 'boolean'}
|
||||
commitMessage: {type: 'string'}
|
||||
|
||||
'editor:view-switched': c.object {title: 'Level View Switched', description: 'Published whenever the view switches'}
|
||||
'editor:view-switched': c.object {title: 'Level View Switched', description: 'Published whenever the view switches'},
|
||||
targetURL: {type: 'string'}
|
||||
|
||||
'editor:level-component-editing-ended': c.object {required: ['component']},
|
||||
component: {type: 'object'}
|
||||
|
|
9
app/styles/editor/level/level-feedback-view.sass
Normal file
9
app/styles/editor/level/level-feedback-view.sass
Normal file
|
@ -0,0 +1,9 @@
|
|||
#level-feedback-view
|
||||
height: 100%
|
||||
|
||||
.user-feedback-list
|
||||
height: 90%
|
||||
height: -webkit-calc(100% - 80px)
|
||||
height: calc(100% - 80px)
|
||||
overflow-y: scroll
|
||||
overflow-x: hidden
|
|
@ -37,6 +37,9 @@ block header
|
|||
a(href="#related-achievements-view", data-toggle="tab") Achievements
|
||||
li
|
||||
a(href="#editor-level-documentation", data-toggle="tab", data-i18n="editor.level_tab_docs") Documentation
|
||||
li
|
||||
a(href="#level-feedback-view", data-toggle="tab")
|
||||
.glyphicon.glyphicon-star
|
||||
.navbar-header
|
||||
span.navbar-brand #{level.attributes.name}
|
||||
|
||||
|
@ -137,6 +140,8 @@ block outer_content
|
|||
div.tab-pane#components-documentation-view
|
||||
div.tab-pane#systems-documentation-view
|
||||
|
||||
div.tab-pane#level-feedback-view
|
||||
|
||||
div#error-view
|
||||
|
||||
block footer
|
||||
|
|
17
app/templates/editor/level/level-feedback-view.jade
Normal file
17
app/templates/editor/level/level-feedback-view.jade
Normal file
|
@ -0,0 +1,17 @@
|
|||
h2 Average Rating: #{averageRating.toFixed(2)}, #{totalRatings} ratings
|
||||
ul.user-feedback-list.list-group
|
||||
for feedback in allFeedback
|
||||
li.list-group-item
|
||||
each i in Array(feedback.rating)
|
||||
.glyphicon.glyphicon-star
|
||||
if feedback.rating < 5
|
||||
each i in Array(5 - feedback.rating)
|
||||
.glyphicon.glyphicon-star-empty
|
||||
span.spl.spr -
|
||||
em= moment(new Date(feedback.created)).fromNow()
|
||||
span.spl.spr -
|
||||
a(href="/user/#{feedback.creator}")
|
||||
strong= feedback.creatorName
|
||||
if feedback.review
|
||||
span.spr :
|
||||
span= feedback.review
|
|
@ -1,9 +1,6 @@
|
|||
|
||||
button.btn.btn-primary#new-achievement-button(disabled=me.isAdmin() === true ? undefined : "true" data-i18n="editor.new_achievement_title") Create a New Achievement
|
||||
|
||||
if achievements.loading
|
||||
h2(data-i18n="common.loading") Loading...
|
||||
else if ! achievements.models.length
|
||||
if !achievements.models.length
|
||||
.panel
|
||||
.panel-body
|
||||
p(data-i18n="editor.no_achievements") No achievements added for this level yet.
|
||||
|
|
|
@ -17,10 +17,19 @@ module.exports = class ComponentsDocumentationView extends CocoView
|
|||
events:
|
||||
'click #toggle-all-component-code': 'onToggleAllCode'
|
||||
|
||||
subscriptions:
|
||||
'editor:view-switched': 'onViewSwitched'
|
||||
|
||||
constructor: (options) ->
|
||||
super(options)
|
||||
@componentDocs = new ComponentDocsCollection()
|
||||
@loadDocs() unless options.lazy
|
||||
|
||||
loadDocs: ->
|
||||
return if @loadingDocs
|
||||
@supermodel.loadCollection @componentDocs, 'components'
|
||||
@loadingDocs = true
|
||||
@render()
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
|
@ -33,3 +42,7 @@ module.exports = class ComponentsDocumentationView extends CocoView
|
|||
@collapsed = not @collapsed
|
||||
@$el.find('.collapse').collapse(if @collapsed then 'hide' else 'show')
|
||||
@$el.find('#toggle-all-component-code').toggleClass 'active', not @collapsed
|
||||
|
||||
onViewSwitched: (e) ->
|
||||
return unless e.targetURL is '#editor-level-documentation'
|
||||
@loadDocs()
|
||||
|
|
|
@ -17,10 +17,19 @@ module.exports = class SystemsDocumentationView extends CocoView
|
|||
events:
|
||||
'click #toggle-all-system-code': 'onToggleAllCode'
|
||||
|
||||
subscriptions:
|
||||
'editor:view-switched': 'onViewSwitched'
|
||||
|
||||
constructor: (options) ->
|
||||
super(options)
|
||||
@systemDocs = new SystemDocsCollection()
|
||||
@loadDocs() unless options.lazy
|
||||
|
||||
loadDocs: ->
|
||||
return if @loadingDocs
|
||||
@supermodel.loadCollection @systemDocs, 'systems'
|
||||
@loadingDocs = true
|
||||
@render()
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
|
@ -33,3 +42,7 @@ module.exports = class SystemsDocumentationView extends CocoView
|
|||
@collapsed = not @collapsed
|
||||
@$el.find('.collapse').collapse(if @collapsed then 'hide' else 'show')
|
||||
@$el.find('#toggle-all-system-code').toggleClass 'active', not @collapsed
|
||||
|
||||
onViewSwitched: (e) ->
|
||||
return unless e.targetURL is '#editor-level-documentation'
|
||||
@loadDocs()
|
||||
|
|
|
@ -19,6 +19,7 @@ RelatedAchievementsView = require 'views/editor/level/RelatedAchievementsView'
|
|||
VersionHistoryView = require './modals/LevelVersionsModal'
|
||||
ComponentsDocumentationView = require 'views/docs/ComponentsDocumentationView'
|
||||
SystemsDocumentationView = require 'views/docs/SystemsDocumentationView'
|
||||
LevelFeedbackView = require 'views/editor/level/LevelFeedbackView'
|
||||
storage = require 'lib/storage'
|
||||
|
||||
module.exports = class LevelEditView extends RootView
|
||||
|
@ -76,15 +77,16 @@ module.exports = class LevelEditView extends RootView
|
|||
super()
|
||||
return unless @supermodel.finished()
|
||||
@$el.find('a[data-toggle="tab"]').on 'shown.bs.tab', (e) =>
|
||||
Backbone.Mediator.publish 'editor:view-switched', {}
|
||||
Backbone.Mediator.publish 'editor:view-switched', {targetURL: $(e.target).attr('href')}
|
||||
@insertSubView new ThangsTabView world: @world, supermodel: @supermodel, level: @level
|
||||
@insertSubView new SettingsTabView supermodel: @supermodel
|
||||
@insertSubView new ScriptsTabView world: @world, supermodel: @supermodel, files: @files
|
||||
@insertSubView new ComponentsTabView supermodel: @supermodel
|
||||
@insertSubView new SystemsTabView supermodel: @supermodel
|
||||
@insertSubView new RelatedAchievementsView supermodel: @supermodel, level: @level
|
||||
@insertSubView new ComponentsDocumentationView # Don't give it the supermodel, it'll pollute it!
|
||||
@insertSubView new SystemsDocumentationView # Don't give it the supermodel, it'll pollute it!
|
||||
@insertSubView new ComponentsDocumentationView lazy: true # Don't give it the supermodel, it'll pollute it!
|
||||
@insertSubView new SystemsDocumentationView lazy: true # Don't give it the supermodel, it'll pollute it!
|
||||
@insertSubView new LevelFeedbackView level: @level
|
||||
|
||||
Backbone.Mediator.publish 'editor:level-loaded', level: @level
|
||||
@showReadOnly() if me.get('anonymous')
|
||||
|
|
53
app/views/editor/level/LevelFeedbackView.coffee
Normal file
53
app/views/editor/level/LevelFeedbackView.coffee
Normal file
|
@ -0,0 +1,53 @@
|
|||
CocoView = require 'views/kinds/CocoView'
|
||||
CocoCollection = require 'collections/CocoCollection'
|
||||
template = require 'templates/editor/level/level-feedback-view'
|
||||
Level = require 'models/Level'
|
||||
LevelFeedback = require 'models/LevelFeedback'
|
||||
|
||||
class LevelFeedbackCollection extends CocoCollection
|
||||
model: LevelFeedback
|
||||
initialize: (models, options) ->
|
||||
super models, options
|
||||
@url = "/db/level/#{options.level.get('slug')}/all_feedback"
|
||||
|
||||
comparator: (a, b) ->
|
||||
score = 0
|
||||
score -= 9001900190019001 if a.get('creator') is me.id
|
||||
score += 9001900190019001 if b.get('creator') is me.id
|
||||
score -= new Date(a.get 'created')
|
||||
score -= -(new Date(b.get 'created'))
|
||||
score -= 900190019001 if a.get('review')
|
||||
score += 900190019001 if b.get('review')
|
||||
if score < 0 then -1 else (if score > 0 then 1 else 0)
|
||||
|
||||
module.exports = class LevelFeedbackView extends CocoView
|
||||
id: 'level-feedback-view'
|
||||
template: template
|
||||
className: 'tab-pane'
|
||||
|
||||
subscriptions:
|
||||
'editor:view-switched': 'onViewSwitched'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
|
||||
getRenderData: (context={}) ->
|
||||
context = super(context)
|
||||
if @allFeedback
|
||||
context.allFeedback = (m.attributes for m in @allFeedback.models when @allFeedback.models.length < 20 or m.get('review'))
|
||||
context.averageRating = _.reduce((m.get('rating') for m in @allFeedback.models), (acc, x) -> acc + x) / @allFeedback.models.length
|
||||
context.totalRatings = @allFeedback.models.length
|
||||
else
|
||||
context.allFeedback = []
|
||||
context.averageRating = 0
|
||||
context.totalRatings = 0
|
||||
context.loading = true
|
||||
context.moment = moment
|
||||
context
|
||||
|
||||
onViewSwitched: (e) ->
|
||||
# Lazily load.
|
||||
return unless e.targetURL is '#level-feedback-view'
|
||||
unless @allFeedback
|
||||
@allFeedback = @supermodel.loadCollection(new LevelFeedbackCollection(null, level: @options.level), 'feedback').model
|
||||
@render()
|
|
@ -13,17 +13,20 @@ module.exports = class RelatedAchievementsView extends CocoView
|
|||
events:
|
||||
'click #new-achievement-button': 'makeNewAchievement'
|
||||
|
||||
subscriptions:
|
||||
'editor:view-switched': 'onViewSwitched'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
@level = options.level
|
||||
@relatedID = @level.get('original')
|
||||
@achievements = new RelatedAchievementsCollection @relatedID
|
||||
@supermodel.loadCollection @achievements, 'achievements'
|
||||
|
||||
onLoaded: ->
|
||||
console.debug 'related achievements loaded'
|
||||
@achievements.loading = false
|
||||
super()
|
||||
loadAchievements: ->
|
||||
return if @loadingAchievements
|
||||
@supermodel.loadCollection @achievements, 'achievements'
|
||||
@loadingAchievements = true
|
||||
@render()
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
|
@ -38,3 +41,8 @@ module.exports = class RelatedAchievementsView extends CocoView
|
|||
modal = new NewAchievementModal model: Achievement, modelLabel: 'Achievement', level: @level
|
||||
modal.once 'model-created', @onNewAchievementSaved
|
||||
@openModalView modal
|
||||
|
||||
onViewSwitched: (e) ->
|
||||
# Lazily load.
|
||||
return unless e.targetURL is '#related-achievements-view'
|
||||
@loadAchievements()
|
||||
|
|
|
@ -37,6 +37,7 @@ LevelHandler = class LevelHandler extends Handler
|
|||
return @getMyLeaderboardRank(req, res, args[0]) if args[1] is 'leaderboard_rank'
|
||||
return @getMySessions(req, res, args[0]) if args[1] is 'my_sessions'
|
||||
return @getFeedback(req, res, args[0]) if args[1] is 'feedback'
|
||||
return @getAllFeedback(req, res, args[0]) if args[1] is 'all_feedback'
|
||||
return @getRandomSessionPair(req, res, args[0]) if args[1] is 'random_session_pair'
|
||||
return @getLeaderboardFacebookFriends(req, res, args[0]) if args[1] is 'leaderboard_facebook_friends'
|
||||
return @getLeaderboardGPlusFriends(req, res, args[0]) if args[1] is 'leaderboard_gplus_friends'
|
||||
|
@ -266,18 +267,24 @@ LevelHandler = class LevelHandler extends Handler
|
|||
if map.length != 2 then return @sendDatabaseError res, 'There aren\'t sessions of 2 teams, so cannot choose random opponents!'
|
||||
@sendSuccess res, sessions
|
||||
|
||||
getFeedback: (req, res, id) ->
|
||||
getFeedback: (req, res, levelID) ->
|
||||
return @sendNotFoundError(res) unless req.user
|
||||
@fetchLevelByIDAndHandleErrors id, req, res, (err, level) =>
|
||||
@doGetFeedback req, res, levelID, false
|
||||
|
||||
getAllFeedback: (req, res, levelID) ->
|
||||
@doGetFeedback req, res, levelID, true
|
||||
|
||||
doGetFeedback: (req, res, levelID, multiple) ->
|
||||
@fetchLevelByIDAndHandleErrors levelID, req, res, (err, level) =>
|
||||
feedbackQuery =
|
||||
creator: mongoose.Types.ObjectId(req.user.id.toString())
|
||||
'level.original': level.original.toString()
|
||||
'level.majorVersion': level.version.major
|
||||
|
||||
Feedback.findOne(feedbackQuery).exec (err, doc) =>
|
||||
feedbackQuery.creator = mongoose.Types.ObjectId(req.user.id.toString()) unless multiple
|
||||
fn = if multiple then 'find' else 'findOne'
|
||||
Feedback[fn](feedbackQuery).exec (err, result) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res) unless doc?
|
||||
@sendSuccess(res, doc)
|
||||
return @sendNotFoundError(res) unless result?
|
||||
@sendSuccess(res, result)
|
||||
|
||||
getPlayCountsBySlugs: (req, res) ->
|
||||
# This is hella slow (4s on my box), so relying on some dumb caching for it.
|
||||
|
|
Loading…
Add table
Reference in a new issue