Worked in a lot of changes Scott proposed

This commit is contained in:
Ruben Vereecken 2014-08-07 22:03:00 +02:00
parent 06ba50f5e2
commit 9f0add22a5
26 changed files with 287 additions and 314 deletions

View file

@ -4,6 +4,5 @@ EarnedAchievement = require 'models/EarnedAchievement'
module.exports = class EarnedAchievementCollection extends CocoCollection
model: EarnedAchievement
initialize: (me = require('lib/auth').me) ->
@url = "/db/user/#{me.id}/achievements"
initialize: (userID) ->
@url = "/db/user/#{userID}/achievements"

View file

@ -297,14 +297,12 @@ class CocoModel extends Backbone.Model
@pollAchievements: ->
NewAchievementCollection = require '../collections/NewAchievementCollection' # Nasty mutual inclusion if put on top
console.debug 'Polling for new achievements'
achievements = new NewAchievementCollection
achievements.fetch
success: (collection) ->
console.debug 'Polling for achievements success', collection
me.fetch (success: -> Backbone.Mediator.publish('achievements:new', collection)) unless _.isEmpty(collection.models)
error: (collection, res, options) ->
console.error 'Miserably failed to fetch unnotified achievements'
error: ->
console.error 'Miserably failed to fetch unnotified achievements', arguments
CocoModel.pollAchievements = _.debounce CocoModel.pollAchievements, 500

View file

@ -38,7 +38,7 @@ module.exports = class LevelSession extends CocoModel
false
isMultiplayer: ->
console.log @get 'levelName'
console.log @
console.log @get 'team'
@get('team')? # Only multiplayer level sessions have teams defined
completed: ->
@get('state')?.complete || false

View file

@ -42,51 +42,13 @@ module.exports = class User extends CocoModel
return "/file/#{photoURL}#{prefix}s=#{size}"
return "/db/user/#{@id}/avatar?s=#{size}&employerPageAvatar=#{useEmployerPageAvatar}"
# Callbacks can be either 'success' or 'error'
@getByID = (id, properties, force, callbacks={}) ->
{me} = require 'lib/auth'
if me.id is id
callbacks.success me if callbacks.success?
return me
user = cache[id] or new module.exports({_id: id})
if force or not cache[id]
user.loading = true
user.fetch(
success: ->
user.loading = false
Backbone.Mediator.publish('user:fetched')
callbacks.success arguments... if callbacks.success?
error: -> callbacks.error arguments... if callbacks.error?
)
cache[id] = user
user
getSlugOrID: -> @get('slug') or @get('_id')
set: ->
if arguments[0] is 'jobProfileApproved' and @get("jobProfileApproved") is false and not @get("jobProfileApprovedDate")
@set "jobProfileApprovedDate", (new Date()).toISOString()
super arguments...
# callbacks can be either success or error
@getByIDOrSlug: (idOrSlug, force, callbacks={}) ->
{me} = require 'lib/auth'
isID = util.isID idOrSlug
if me.id is idOrSlug or me.slug is idOrSlug
callbacks.success me if callbacks.success?
return me
cached = cache[idOrSlug]
user = cached or new @ _id: idOrSlug
if force or not cached
user.loading = true
user.fetch
success: ->
user.loading = false
Backbone.Mediator.publish 'user:fetched'
callbacks.success user if callbacks.success?
error: ->
user.loading = false
callbacks.error user if callbacks.error?
cache[idOrSlug] = user
user
@getUnconflictedName: (name, done) ->
$.ajax "/auth/name/#{name}",
success: (data) -> done data.name

View file

@ -35,7 +35,7 @@ MongoFindQuerySchema.definitions[MongoQueryOperatorSchema.id] = MongoQueryOperat
AchievementSchema = c.object()
c.extendNamedProperties AchievementSchema
c.extendBasicProperties AchievementSchema, 'achievement' # TODO What's this about?
c.extendBasicProperties AchievementSchema, 'achievement'
c.extendSearchableProperties AchievementSchema
_.extend AchievementSchema.properties,
@ -51,8 +51,8 @@ _.extend AchievementSchema.properties,
related: c.objectId(description: 'Related entity')
icon: {type: 'string', format: 'image-file', title: 'Icon'}
category:
type: 'string'
description: "E.g. 'level', 'ladder', 'contributor'..." # TODO might make this enum?
enum: ['level', 'ladder', 'contributor']
description: 'For categorizing and display purposes'
difficulty: c.int
description: 'The higher the more difficult'
default: 1

View file

@ -21,8 +21,8 @@ PatchSchema = c.object({title: 'Patch', required: ['target', 'delta', 'commitMes
minor: {type: 'number', minimum: 0}
})
_wasPending: type: 'boolean'
_newlyAccepted: type: 'boolean'
wasPending: type: 'boolean'
newlyAccepted: type: 'boolean'
})
c.extendBasicProperties(PatchSchema, 'patch')

View file

@ -6,7 +6,7 @@
margin-bottom: 0px
img#picture
max-width: 50%
max-width: 100%
.panel
margin-bottom: 10px
@ -14,5 +14,19 @@
h2
margin-bottom: 0px
a
font-size: 28px
margin-left: 5px
.panel-title > a
margin-left: 5px
color: rgb(11, 99, 188)
.panel-me
td
padding-left: 15px
.panel-emails
h4
font-family: $font-family-base

View file

@ -1,3 +1,5 @@
@import 'bootstrap/variables'
.locked
// This used to be a grayscale filter but they're mad intensive to paint
@ -22,7 +24,7 @@
background-image: url("/images/achievements/achievement_background_locked.png")
&:not(.locked)
.achievement-content
background-image: url("/images/achievements/achievement_background.png")
background-image: url("/images/achievements/achievement_background_light.png")
.achievement-content
background-size: 100% 100%
@ -30,18 +32,23 @@
overflow: hidden
> .achievement-title
font-family: Bangers
font-family: $font-family-base
font-weight: bold
white-space: nowrap
max-height: 2em
overflow: hidden
text-overflow: ellipsis
> .achievement-description
white-space: initial
font-size: 12px
line-height: 1.3em
overflow: hidden
max-height: 2.6em
margin-top: auto
margin-bottom: 0px !important
padding-left: 5px
overflow: hidden
text-overflow: ellipsis
// Specific to the user stats page
@ -75,7 +82,6 @@
.achievement-title
font-size: 20px
padding-left: -50px
.achievement-description
font-size: 12px
@ -105,12 +111,14 @@
bottom: 0
.achievement-content
background-image: url("/images/achievements/achievement_background.png")
position: relative
width: 450px
height: 160px
padding: 24px 30px 20px 60px
.achievement-title
font-family: Bangers
font-size: 28px
padding-left: -50px
@ -209,11 +217,14 @@
.user-level
z-index: 1000
box-shadow: 0 0 0 1px black, 0 0 0 3px lightgrey, 0 0 0 4px black
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif
font-family: $font-family-base
// Achievements page
h2.achievements-category
.achievement-category-title
margin-left: 20px
font-family: $font-family-base
font-weight: bold
color: #5a5a5a
.table-layout
#no-achievements

View file

@ -1,172 +1,138 @@
extends /templates/base
block content
.clearfix
.col-sm-6.clearfix
h2 Account Settings
hr
.panel.panel-default
.panel-heading
i.glyphicon.glyphicon-user.pull-left
h3.panel-title
a(href="account/settings#me") Me
.panel-body
dl
dt Name
dd=me.get('name')
dt Email
dd abe@lincoln
.panel.panel-default
.panel-heading
i.glyphicon.glyphicon-picture.pull-left
h3.panel-title
a(href="account/settings#picture") Picture
.panel-body.text-center
img#picture(src="#{me.getPhotoURL(150)}" alt="")
.panel.panel-default
.panel-heading
i.glyphicon.glyphicon-user.pull-left
h3.panel-title
a(href="account/settings#wizard") Wizard
//.panel-body
| Lorem Ipsum
.panel.panel-default
.panel-heading
i.glyphicon.glyphicon-envelope.pull-left
h3.panel-title
a(href="account/settings#emails") Emails
.panel-body
.form
.form-group.checkbox
label.control-label(for="email_archmageNews")
span General
input#email_archmageNews(name="email_archmageNews", type="checkbox", checked=subs.generalNews, disabled="true")
.form-group.checkbox
label.control-label(for="email_archmageNews")
span.spr(data-i18n="classes.archmage_title")
| Archmage
span(data-i18n="classes.archmage_title_description")
| (Coder)
input#email_archmageNews(name="email_archmageNews", type="checkbox", checked=subs.archmageNews, disabled="true")
.form-group.checkbox
label.control-label(for="email_artisanNews")
span.spr(data-i18n="classes.artisan_title")
| Artisan
span(data-i18n="classes.artisan_title_description")
| (Level Builder)
input#email_artisanNews(name="email_artisanNews", type="checkbox", checked=subs.artisanNews, disabled="true")
.form-group.checkbox
label.control-label(for="email_adventurerNews")
span.spr(data-i18n="classes.adventurer_title")
| Adventurer
span(data-i18n="classes.adventurer_title_description")
| (Level Playtester)
input#email_adventurerNews(name="email_adventurerNews", type="checkbox", checked=subs.adventurerNews, disabled="true")
.form-group.checkbox
label.control-label(for="email_scribeNews")
span.spr(data-i18n="classes.scribe_title")
| Scribe
span(data-i18n="classes.scribe_title_description")
| (Article Editor)
input#email_scribeNews(name="email_scribeNews", type="checkbox", checked=subs.scribeNews, disabled="true")
.form-group.checkbox
label.control-label(for="email_diplomatNews")
span.spr(data-i18n="classes.diplomat_title")
| Diplomat
span(data-i18n="classes.diplomat_title_description")
| (Translator)
input#email_diplomatNews(name="email_diplomatNews", type="checkbox", checked=subs.diplomatNews, disabled="true")
.form-group.checkbox
label.control-label(for="email_ambassadorNews")
span.spr(data-i18n="classes.ambassador_title")
| Ambassador
span(data-i18n="classes.ambassador_title_description")
| (Support)
input#email_ambassadorNews(name="email_ambassadorNews", type="checkbox", checked=subs.ambassadorNews, disabled="true")
.panel.panel-default
.panel-heading
i.glyphicon.glyphicon-wrench.pull-left
h3.panel-title
a(href="account/settings#password") Password
.panel.panel-default
.panel-heading
i.glyphicon.glyphicon-briefcase.pull-left
h3.panel-title
a(href="account/settings#job-profile") Job Profile
.col-sm-6
h2 Recently Played
hr
if !recentlyPlayed
div Loading...
else if recentlyPlayed.length
table.table
tr
th Level
th Last Played
th Status
each session in recentlyPlayed
if session.get('levelName')
tr
td
- var posturl = ''
- if (session.get('team')) posturl = '?team=' + session.get('team')
a(href="/play/level/#{session.get('levelID') + posturl}")= session.get('levelName') + (session.get('team') ? ' (' + session.get('team') + ')' : '')
td= moment(session.get('changed')).fromNow()
if session.get('state').complete === true
td Completed
else if ! session.isMultiplayer()
td Unfinished
else
td
else
.panel.panel-default
if !me.isAnonymous()
.clearfix
.col-sm-6.clearfix
h2 Account Settings
a.spl(href="settings")
i.glyphicon.glyphicon-cog
hr
.row
.col-xs-6
.panel.panel-default
.panel-heading
h3.panel-title
i.glyphicon.glyphicon-picture
a(href="account/settings#picture") Picture
.panel-body.text-center
img#picture(src="#{me.getPhotoURL(150)}" alt="")
.col-xs-6
.panel.panel-default
.panel-heading
h3.panel-title
i.glyphicon.glyphicon-user
a(href="account/settings#wizard") Wizard
if (wizardSource)
.panel-body.text-center
img(src="#{wizardSource}")
.panel.panel-default.panel-me
.panel-heading
h3.panel-title
i.glyphicon.glyphicon-user
a(href="account/settings#me") Me
.panel-body
div No games played during the past two weeks.
//block content
h2 Account
.col-sm-3.text-center
img#avatar(src="#{me.getPhotoURL(100)}")
h3=me.get('name') || 'Anoner'
.col-sm-6
dl.dl-horizontal
if me.get('firstName') || me.get('lastName')
dt Full name
dd=me.get('firstName') || '' + ' ' + me.get('lastName') || ''
dt Email
dd
span.spr=me.get('email')
//span (subscriptions)
hr
- var dateCreated = me.get('dateCreated');
- var signedCLA = me.get('signedCLA');
- console.log(moment)
dt Member since
dd= moment(dateCreated).format('MMMM Do YYYY')
if signedCLA
dt Signed CLA
dd= moment(signedCLA).format('MMMM Do YYYY')
// TODO Have social network icons here for easy linking
.col-sm-3
h3 Account
ul
li
a Settings
li
a Payment
h3 Public
ul
li
a Public profile
li
a Job Profile
li
a Statistics
li
a Code
table
tr
th Name
td=me.get('name') || 'Anoner'
tr
th Email
td=me.get('email')
.panel.panel-default.panel-emails
.panel-heading
h3.panel-title
i.glyphicon.glyphicon-envelope
a(href="account/settings#emails") Emails
.panel-body
if !hasEmailNotes && !hasEmailNews
p No email subscriptions.
if hasEmailNotes
h4 Notifications
ul
if subs.anyNotes
li(data-i18n="account_settings.email_any_notes") Any Notifications
if subs.recruitNotes
li(data-i18n="account_settings.email_recruit_notes") Job Opportunities
if hasEmailNews
h4 News
ul
if (subs.generalNews)
li(data-i18n="account_settings.email_announcements") General
if (subs.archmageNews)
li
span(data-i18n="classes.archmage_title")
| Archmage
span(data-i18n="classes.archmage_title_description")
| (Coder)
if (subs.artisanNews)
li
span.spr(data-i18n="classes.artisan_title")
| Artisan
span(data-i18n="classes.artisan_title_description")
| (Level Builder)
if (subs.adventurerNews)
li
span.spr(data-i18n="classes.adventurer_title")
| Adventurer
span(data-i18n="classes.adventurer_title_description")
| (Level Playtester)
if (subs.scribeNews)
li
span.spr(data-i18n="classes.scribe_title")
| Scribe
span(data-i18n="classes.scribe_title_description")
| (Article Editor)
if (subs.diplomatNews)
li
span.spr(data-i18n="classes.diplomat_title")
| Diplomat
span(data-i18n="classes.diplomat_title_description")
| (Translator)
if (subs.ambassadorNews)
li
span.spr(data-i18n="classes.ambassador_title")
| Ambassador
span(data-i18n="classes.ambassador_title_description")
| (Support)
.panel.panel-default
.panel-heading
h3.panel-title
i.glyphicon.glyphicon-wrench
a(href="account/settings#password") Password
.panel.panel-default
.panel-heading
h3.panel-title
i.glyphicon.glyphicon-briefcase
a(href="account/settings#job-profile") Job Profile
.col-sm-6
h2 Recently Played
hr
if !recentlyPlayed
div Loading...
else if recentlyPlayed.length
table.table
tr
th Level
th Last Played
th Status
each session in recentlyPlayed
if session.get('levelName')
tr
td
- var posturl = ''
- if (session.get('team')) posturl = '?team=' + session.get('team')
a(href="/play/level/#{session.get('levelID') + posturl}")= session.get('levelName') + (session.get('team') ? ' (' + session.get('team') + ')' : '')
td= moment(session.get('changed')).fromNow()
if session.get('state').complete === true
td Completed
else if ! session.isMultiplayer()
td Unfinished
else
td
else
.panel.panel-default
.panel-body
div No games played during the past two weeks.

View file

@ -6,14 +6,8 @@ block content
if user && viewName
ol.breadcrumb
li
a(href="/user/#{user.id}") #{user.displayName()}
a(href="/user/#{user.getSlugOrID()}") #{user.displayName()}
li.active
| #{viewName}
if !userLoaded
if !user || user.loading
| LOADING
else if !user
// TODO Ruben make this all fancy as soon as we can query users by name
| User not found.

View file

@ -9,7 +9,7 @@ block append content
.grid-layout
each achievements, category in achievementsByCategory
.row
h2.achievements-category=category
h2.achievement-category-title=category.charAt(0).toUpperCase() + category.slice(1)
each achievement, index in achievements
- var title = achievement.get('name');
- var description = achievement.get('description');
@ -33,7 +33,7 @@ block append content
th Date
th Amount
th XP
each earnedAchievement in earnedAchievements
each earnedAchievement in earnedAchievements.models
- var achievement = earnedAchievement.get('achievement');
tr
td= achievement.get('name')

View file

@ -13,9 +13,12 @@ block append content
div.extra-info Favorite language is
strong.spl.spr= favoriteLanguage
.btn-group-vertical.profile-menu
a.btn.btn-default(href="/user/#{user.get('slug') || user.get('_id')}/profile")
a.btn.btn-default(href="/user/#{user.getSlugOrID()}/profile")
i.glyphicon.glyphicon-briefcase
span Job Profile
a.btn.btn-default(href="/user/#{user.getSlugOrID()}/stats")
i.glyphicon.glyphicon-certificate
span Stats
a.btn.btn-default.disabled(href="#")
i.glyphicon.glyphicon-pencil
span Code
@ -52,10 +55,6 @@ block append content
a(href="/contribute#scribe") Scribe
.right-column
//.panel.panel-default
.panel-heading
h3.panel-title Achievements
.panel-body
.panel.panel-default
.panel-heading
h3.panel-title Singleplayer Levels
@ -65,9 +64,9 @@ block append content
else if (singlePlayerSessions.length)
table.table
tr
th Level
th Last Played
th Status
th.col-xs-4 Level
th.col-xs-4 Last Played
th.col-xs-4 Status
each session in singlePlayerSessions
if session.get('levelName')
tr
@ -90,17 +89,43 @@ block append content
else if (multiPlayerSessions.length)
table.table
tr
th Level
th Team
th Last Played
th.col-xs-4 Level
th.col-xs-4 Last Played
th.col-xs-4 Score
each session in multiPlayerSessions
tr
td
a(href="/play/level/#{session.get('levelID')}")= session.get('levelName')
td= session.get('team')
- var posturl = ''
- if (session.get('team')) posturl = '?team=' + session.get('team')
a(href="/play/level/#{session.get('levelID') + posturl}")= session.get('levelName') + (session.get('team') ? ' (' + session.get('team') + ')' : '')
td= moment(session.get('changed')).fromNow()
if session.get('state').complete === true
td Completed
if session.get('totalScore')
td= session.get('totalScore') * 100
else
td Unfinished
else
.panel-body
p No Multiplayer games played yet.
.panel.panel-default
.panel-heading
h3.panel-title Achievements
if ! earnedAchievements
.panel-body
p Loading...
else if ! earnedAchievements.length
.panel-body
p No achievements earned so far.
else
table.table
tr
th.col-xs-4 Achievement
th.col-xs-4 Last Earned
th.col-xs-4 Amount
each achievement in earnedAchievements.models
tr
td= achievement.get('achievementName')
td= moment().format("MMMM Do YY", achievement.get('changed'))
if achievement.get('achievedAmount')
td= achievement.get('achievedAmount')
else
td

View file

@ -4,6 +4,7 @@ template = require 'templates/account/home'
User = require 'models/User'
AuthModalView = require 'views/modal/AuthModal'
RecentlyPlayedCollection = require 'collections/RecentlyPlayedCollection'
ThangType = require 'models/ThangType'
module.exports = class MainAccountView extends View
id: 'account-home-view'
@ -12,15 +13,24 @@ module.exports = class MainAccountView extends View
constructor: (options) ->
super options
return unless me
@recentlyPlayed = @supermodel.loadCollection(new RecentlyPlayedCollection(me.get('_id')), 'recentlyPlayed').model
@wizardType = ThangType.loadUniversalWizard()
@recentlyPlayed = new RecentlyPlayedCollection me.get('_id')
@supermodel.loadModel @wizardType, 'thang'
@supermodel.loadCollection @recentlyPlayed, 'recentlyPlayed'
onLoaded: ->
super()
getRenderData: ->
c = super()
c.subs = {}
c.subs[sub] = 1 for sub in c.me.getEnabledEmails()
c.hasEmailNotes = _.any c.me.getEnabledEmails(), (sub) -> sub.contains 'Notes'
c.hasEmailNews = _.any c.me.getEnabledEmails(), (sub) -> sub.contains 'News'
c.wizardSource = @wizardType.getPortraitSource colorConfig: me.get('wizard')?.colorConfig if @wizardType.loaded
c.recentlyPlayed = @recentlyPlayed.models
c
afterRender: ->
super()
@openModelView new AuthModalView if me.isAnonymous()
@openModalView new AuthModalView if me.isAnonymous()

View file

@ -80,7 +80,7 @@ module.exports = class AchievementEditView extends RootView
$('#achievement-view-inner').notify data, options
openSaveModal: ->
'Maybe later' # TODO
'Maybe later' # TODO patch patch patch
saveAchievement: (e) ->
@treema.endExistingEdits()

View file

@ -47,13 +47,13 @@ module.exports = class RootView extends CocoView
achievedExp = achievement.get 'worth'
previousExp = currentExp - achievedExp
leveledUp = currentExp - achievedExp < currentLevelExp
console.debug 'Leveled up' if leveledUp
#console.debug 'Leveled up' if leveledUp
alreadyAchievedPercentage = 100 * (previousExp - currentLevelExp) / totalExpNeeded
alreadyAchievedPercentage = 0 if alreadyAchievedPercentage < 0 # In case of level up
newlyAchievedPercentage = if leveledUp then 100 * (currentExp - currentLevelExp) / totalExpNeeded else 100 * achievedExp / totalExpNeeded
console.debug "Current level is #{currentLevel} (#{currentLevelExp} xp), next level is #{nextLevel} (#{nextLevelExp} xp)."
console.debug "Need a total of #{nextLevelExp - currentLevelExp}, already had #{previousExp} and just now earned #{achievedExp} totalling on #{currentExp}"
#console.debug "Current level is #{currentLevel} (#{currentLevelExp} xp), next level is #{nextLevel} (#{nextLevelExp} xp)."
#console.debug "Need a total of #{nextLevelExp - currentLevelExp}, already had #{previousExp} and just now earned #{achievedExp} totalling on #{currentExp}"
alreadyAchievedBar = $("<div class='progress-bar exp-bar-accumulated' style='width:#{alreadyAchievedPercentage}%'></div>")
newlyAchievedBar = $("<div data-toggle='tooltip' class='progress-bar exp-bar-new' style='width:#{newlyAchievedPercentage}%'></div>")
@ -79,7 +79,6 @@ module.exports = class RootView extends CocoView
showNewAchievement: (achievement, earnedAchievement) ->
data = @createNotifyData achievement, earnedAchievement
console.debug data
options =
autoHideDelay: 5000
elementPosition: 'top left'
@ -89,7 +88,6 @@ module.exports = class RootView extends CocoView
autoHide: false
clickToHide: true
console.debug 'showing achievement', achievement.get 'name'
unless @timeout?
$.notify data, options
@timeout = 2000

View file

@ -9,40 +9,27 @@ module.exports = class UserView extends RootView
constructor: (@userID, options) ->
super options
@listenTo @, 'userLoaded', @onUserLoaded
@listenTo @, 'userNotFound', @ifUserNotFound
@userID ?= me.id # TODO Ruben really?
@fetchUser @userID
# TODO Ruben make this use the new getByNameOrID as soon as that is merged in
fetchUser: (id) ->
User.getByID id, {}, true,
success: (@user) =>
@userLoaded = true
@trigger 'userNotFound' unless @user
@trigger 'userLoaded', @user
error: =>
@userLoaded = true
@trigger 'userNotFound'
if @isMe()
@user = me
@onLoaded()
@user = new User _id: id
@supermodel.loadModel @user, 'user'
getRenderData: ->
context = super()
context.viewName = @viewName
context.user = @user unless @user?.isAnonymous()
context.userLoaded = @userLoaded
context
isMe: -> @userID is me.id
onUserLoaded: ->
console.log 'onUserLoaded', @user
@render()
onLoaded: ->
super()
ifUserNotFound: ->
console.warn 'user not found'
@render()
onLoaded: ->
super()

View file

@ -19,22 +19,22 @@ module.exports = class AchievementsView extends UserView
constructor: (userID, options) ->
super options, userID
onUserLoaded: (user) ->
@achievements = @supermodel.loadCollection(new AchievementCollection, 'achievements').model
@earnedAchievements = @supermodel.loadCollection(new EarnedAchievementCollection(@user), 'earnedAchievements').model
super user
onLoaded: ->
console.log @earnedAchievementsy
console.log @achievements
for earned in @earnedAchievements.models
return unless relatedAchievement = _.find @achievements.models, (achievement) ->
achievement.get('_id') is earned.get 'achievement'
relatedAchievement.set 'unlocked', true
earned.set 'achievement', relatedAchievement
deferredImages = (achievement.cacheLockedImage() for achievement in @achievements.models when not achievement.get 'unlocked')
whenever = $.when deferredImages...
whenever.done => @render()
unless @achievements or @earnedAchievements
@supermodel.resetProgress()
@achievements = new AchievementCollection
@earnedAchievements = new EarnedAchievementCollection @user.getSlugOrID()
@supermodel.loadCollection @achievements, 'achievements'
@supermodel.loadCollection @earnedAchievements, 'earnedAchievements'
else
for earned in @earnedAchievements.models
return unless relatedAchievement = _.find @achievements.models, (achievement) ->
achievement.get('_id') is earned.get 'achievement'
relatedAchievement.set 'unlocked', true
earned.set 'achievement', relatedAchievement
deferredImages = (achievement.cacheLockedImage() for achievement in @achievements.models when not achievement.get 'unlocked')
whenever = $.when deferredImages...
whenever.done => @render()
super()
layoutChanged: (e) ->
@ -47,8 +47,8 @@ module.exports = class AchievementsView extends UserView
# After user is loaded
if @user and not @user.isAnonymous()
context.earnedAchievements = @earnedAchievements.models
context.achievements = @achievements.models
context.earnedAchievements = @earnedAchievements
context.achievements = @achievements
context.achievementsByCategory = {}
for achievement in @achievements.models
context.achievementsByCategory[achievement.get('category')] ?= []

View file

@ -3,12 +3,13 @@ CocoCollection = require 'collections/CocoCollection'
LevelSession = require 'models/LevelSession'
template = require 'templates/user/home'
{me} = require 'lib/auth'
EarnedAchievementCollection = require 'collections/EarnedAchievementCollection'
class LevelSessionsCollection extends CocoCollection
model: LevelSession
constructor: (userID) ->
@url = "/db/user/#{userID}/level.sessions?project=state.complete,levelID,levelName,changed,team,submittedCodeLanguage&order=-1"
@url = "/db/user/#{userID}/level.sessions?project=state.complete,levelID,levelName,changed,team,submittedCodeLanguage,totalScore&order=-1"
super()
module.exports = class MainUserView extends UserView
@ -20,7 +21,8 @@ module.exports = class MainUserView extends UserView
getRenderData: ->
context = super()
if @user
if @levelSessions and @levelSessions.loaded
console.debug 'yep sessions loaded'
singlePlayerSessions = []
multiPlayerSessions = []
languageCounts = {}
@ -39,11 +41,19 @@ module.exports = class MainUserView extends UserView
context.singlePlayerSessions = singlePlayerSessions
context.multiPlayerSessions = multiPlayerSessions
context.favoriteLanguage = favoriteLanguage
if @earnedAchievements and @earnedAchievements.loaded
console.debug 'earned achievements loaded'
context.earnedAchievements = @earnedAchievements
context
onUserLoaded: (user) ->
@levelSessions = @supermodel.loadCollection(new LevelSessionsCollection(@userID), 'levelSessions').model
super user
onLoaded: ->
console.debug @earnedAchievements
console.debug @earnedAchievements?.loaded
if @user.loaded and not @earnedAchievements
@supermodel.resetProgress()
#@levelSessions = new LevelSessionsCollection @user.getSlugOrID()
@earnedAchievements = new EarnedAchievementCollection @user.getSlugOrID()
#@supermodel.loadCollection @levelSessions, 'levelSessions'
@supermodel.loadCollection @earnedAchievements, 'earnedAchievements'
super()

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

View file

@ -45,7 +45,7 @@ AchievementSchema.statics.loadAchievements = (done) ->
category = achievement.get 'collection'
AchievementSchema.statics.earnedAchievements[category] = [] unless category of AchievementSchema.statics.earnedAchievements
AchievementSchema.statics.earnedAchievements[category].push achievement
done(AchievementSchema.statics.earnedAchievements) if done?
done?(AchievementSchema.statics.earnedAchievements)
AchievementSchema.statics.getLoadedAchievements = ->
AchievementSchema.statics.earnedAchievements

View file

@ -29,7 +29,6 @@ class EarnedAchievementHandler extends Handler
achievementIDs = (thing for thing in callbackOrSlugsOrIDs when Handler.isID(thing))
else # just a callback
callback = callbackOrSlugsOrIDs
callback = if callback then callback else -> # Make a dummy just for ease of coding
onFinished = -> callback arguments...
filter = {}
@ -40,13 +39,13 @@ class EarnedAchievementHandler extends Handler
# Fetch all relevant achievements
Achievement.find filter, (err, achievements) ->
callback err if err?
callback new Error 'No achievements to recalculate' unless achievements.length
callback?(err) if err?
callback?(new Error 'No achievements to recalculate') unless achievements.length
log.info "Recalculating a total of #{achievements.length} achievements..."
# Fetch every single user
User.find {}, (err, users) ->
callback err if err?
callback?(err) if err?
log.info "for a total of #{users.length} users."
async.each users, ((user, doneWithUser) ->

View file

@ -57,12 +57,12 @@ PatchSchema.methods.isMiscPatch = ->
# Keep track of when a patch is pending and newly approved.
PatchSchema.path('status').set (newVal) ->
@set '_wasPending', @status is 'pending' and newVal isnt 'pending'
@set '_newlyAccepted', newVal is 'accepted' and not @get('_newlyAccepted') # Only true on the first accept
@set 'wasPending', @status is 'pending' and newVal isnt 'pending'
@set 'newlyAccepted', newVal is 'accepted' and not @get('newlyAccepted') # Only true on the first accept
newVal
PatchSchema.methods.isNewlyAccepted = -> @get('_newlyAccepted')
PatchSchema.methods.wasPending = -> @get '_wasPending'
PatchSchema.methods.isNewlyAccepted = -> @get('newlyAccepted')
PatchSchema.methods.wasPending = -> @get 'wasPending'
PatchSchema.pre 'save', (next) ->
User = require '../users/User'

View file

@ -142,7 +142,7 @@ UserSchema.statics.incrementStat = (id, statName, done, inc=1) ->
UserSchema.methods.incrementStat = (statName, done, inc=1) ->
@set statName, (@get(statName) or 0) + inc
@save (err) -> done err if done?
@save (err) -> done?(err)
UserSchema.statics.unconflictName = unconflictName = (name, done) ->
User.findOne {slug: _.str.slugify(name)}, (err, otherUser) ->