mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-02-17 08:50:58 -05:00
Reworked the MainAccountView, AccountSettingsView, and MainUserView to try and simplify things a bit.
This commit is contained in:
parent
6b8a9593ef
commit
bb766e9610
19 changed files with 375 additions and 742 deletions
|
@ -99,9 +99,7 @@ module.exports = class CocoRouter extends Backbone.Router
|
|||
'test(/*subpath)': go('TestView')
|
||||
|
||||
'user/:slugOrID': go('user/MainUserView')
|
||||
'user/:slugOrID/stats': go('user/AchievementsView')
|
||||
'user/:slugOrID/profile': go('user/JobProfileView')
|
||||
#'user/:slugOrID/code': go('user/CodeView')
|
||||
|
||||
'*name': 'showNotFoundView'
|
||||
|
||||
|
|
|
@ -791,6 +791,7 @@
|
|||
account:
|
||||
recently_played: "Recently Played"
|
||||
no_recent_games: "No games played during the past two weeks."
|
||||
payments: "Payments"
|
||||
|
||||
loading_error:
|
||||
could_not_load: "Error loading from server"
|
||||
|
|
46
app/styles/account/account-settings-view.sass
Normal file
46
app/styles/account/account-settings-view.sass
Normal file
|
@ -0,0 +1,46 @@
|
|||
#account-settings-view
|
||||
|
||||
|
||||
//- Fixed save button
|
||||
|
||||
#site-content-area
|
||||
padding-bottom: 44px
|
||||
|
||||
#save-button-container
|
||||
position: fixed
|
||||
bottom: 0
|
||||
left: 0
|
||||
right: 0
|
||||
z-index: 10
|
||||
background: gray
|
||||
padding: 5px
|
||||
|
||||
#save-button
|
||||
width: 100%
|
||||
|
||||
&.btn-info, &.btn-danger
|
||||
opacity: 1.0
|
||||
|
||||
|
||||
//- Panels
|
||||
|
||||
.panel-heading
|
||||
font-family: Open Sans Condensed
|
||||
font-weight: bold
|
||||
|
||||
.panel-title
|
||||
font-size: 20px
|
||||
|
||||
//- Panel specific stuff
|
||||
|
||||
.profile-photo
|
||||
max-width: 100%
|
||||
max-height: 200px
|
||||
display: block
|
||||
margin-bottom: 10px
|
||||
|
||||
#email-panel
|
||||
#specific-notification-settings
|
||||
padding-left: 20px
|
||||
margin-left: 20px
|
||||
border-left: 1px solid gray
|
|
@ -1,32 +0,0 @@
|
|||
@import "app/styles/bootstrap/variables"
|
||||
@import "app/styles/mixins"
|
||||
|
||||
#account-home
|
||||
dl
|
||||
margin-bottom: 0px
|
||||
|
||||
img#picture
|
||||
max-width: 100%
|
||||
|
||||
.panel
|
||||
margin-bottom: 10px
|
||||
|
||||
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
|
||||
|
9
app/styles/account/main-account-view.sass
Normal file
9
app/styles/account/main-account-view.sass
Normal file
|
@ -0,0 +1,9 @@
|
|||
@import "app/styles/bootstrap/variables"
|
||||
@import "app/styles/mixins"
|
||||
|
||||
#main-account-view
|
||||
#account-links
|
||||
width: 300px
|
||||
|
||||
#account-links .btn
|
||||
width: 100%
|
|
@ -1,91 +0,0 @@
|
|||
#account-settings-view
|
||||
.nav
|
||||
margin-bottom: 10px
|
||||
|
||||
.tab-content
|
||||
border: 1px solid #aaa
|
||||
padding: 20px
|
||||
background: #eee
|
||||
border-radius: 5px
|
||||
|
||||
#save-button-container
|
||||
position: fixed
|
||||
top: 100px
|
||||
width: 1000px
|
||||
z-index: 10
|
||||
|
||||
#save-button
|
||||
float: right
|
||||
|
||||
&.btn-info, &.btn-danger
|
||||
opacity: 1.0
|
||||
|
||||
.gravatar-fallback
|
||||
margin-top: 10px
|
||||
|
||||
input.range
|
||||
position: relative
|
||||
top: 4px
|
||||
|
||||
div.range-color
|
||||
position: relative
|
||||
top: 6px
|
||||
height: 16px
|
||||
width: 16px
|
||||
display: inline-block
|
||||
margin-left: 10px
|
||||
|
||||
.help-inline
|
||||
position: relative
|
||||
top: 3px
|
||||
left: 10px
|
||||
font-size: 12px
|
||||
|
||||
.form
|
||||
max-width: 600px
|
||||
|
||||
#email-pane
|
||||
#specific-notification-settings
|
||||
padding-left: 20px
|
||||
margin-left: 20px
|
||||
border-left: 1px solid gray
|
||||
|
||||
#job-profile-view
|
||||
.profile-preview-button
|
||||
&.bottom-preview
|
||||
margin: 15px 0 0 0
|
||||
|
||||
.sample-profile-thumbnail
|
||||
margin-top: -60px
|
||||
|
||||
.profile-completion-progress
|
||||
width: 100%
|
||||
display: inline-block
|
||||
height: 33px
|
||||
|
||||
.progress-bar
|
||||
line-height: 33px
|
||||
|
||||
.progress-next-item
|
||||
margin-top: -20px
|
||||
margin-bottom: 15px
|
||||
|
||||
#job-profile-treema
|
||||
background-color: white
|
||||
|
||||
input
|
||||
width: 790px
|
||||
|
||||
.treema-description
|
||||
font-size: 14px
|
||||
line-height: 22px
|
||||
opacity: 1
|
||||
|
||||
.treema-row
|
||||
padding-top: 6px
|
||||
|
||||
.treema-image-file
|
||||
img
|
||||
display: block
|
||||
clear: both
|
||||
max-width: 300px
|
|
@ -66,37 +66,6 @@ $user-achievements-scale: 0.8
|
|||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
|
||||
// Specific to the user stats page
|
||||
#user-achievements-view
|
||||
.achievement-body
|
||||
width: 335px
|
||||
height: 120px
|
||||
margin: 10px 0px
|
||||
|
||||
.achievement-icon
|
||||
width: $overall-scale * $icon-size * $user-achievements-scale
|
||||
height: $overall-scale * $icon-size * $user-achievements-scale
|
||||
top: -5px
|
||||
|
||||
.achievement-image
|
||||
img
|
||||
width: $overall-scale * $user-achievements-scale * $icon-image-size
|
||||
|
||||
.achievement-content
|
||||
margin-left: 60px
|
||||
margin-right: 5px
|
||||
width: 260px
|
||||
height: 100px
|
||||
padding: 15px 10px 20px 60px
|
||||
|
||||
.achievement-title
|
||||
font-size: 20px
|
||||
|
||||
.achievement-description
|
||||
font-size: 12px
|
||||
line-height: 1.3em
|
||||
max-height: 2.6em
|
||||
|
||||
.achievement-popup
|
||||
padding: $overall-scale * 20px 0px
|
||||
position: relative
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
color: #555555
|
||||
font-size: 15px
|
||||
margin-left: 5px
|
||||
|
||||
.panel-footer
|
||||
text-align: right
|
||||
|
||||
.contributor-categories
|
||||
list-style: none
|
164
app/templates/account/account-settings-view.jade
Normal file
164
app/templates/account/account-settings-view.jade
Normal file
|
@ -0,0 +1,164 @@
|
|||
extends /templates/base
|
||||
|
||||
block content
|
||||
|
||||
ol.breadcrumb
|
||||
li
|
||||
a(href="/")
|
||||
span.glyphicon.glyphicon-home
|
||||
li
|
||||
a(href="/account")(data-i18n="nav.account")
|
||||
li.active(data-i18n="account_settings.title")
|
||||
|
||||
if me.get('anonymous')
|
||||
.alert.alert-danger(data-i18n="account_settings.not_logged_in") Log in or create an account to change your settings.
|
||||
|
||||
else
|
||||
#save-button-container
|
||||
button#save-button.btn-lg.btn.disabled(data-i18n="general.save" disabled="true") No Changes
|
||||
|
||||
.row
|
||||
.col-md-6
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
.panel-title(data-i18n="account_settings.me_tab")
|
||||
.panel-body
|
||||
.form
|
||||
- var name = me.get('name') || '';
|
||||
- var email = me.get('email');
|
||||
- var admin = me.get('permissions', true).indexOf('admin') != -1;
|
||||
.form-group
|
||||
label.control-label(for="name", data-i18n="general.name") Name
|
||||
input#name.form-control(name="name", type="text", value="#{name}")
|
||||
.form-group
|
||||
label.control-label(for="email", data-i18n="general.email") Email
|
||||
input#email.form-control(name="email", type="text", value="#{email}")
|
||||
if !isProduction
|
||||
.form-group.checkbox
|
||||
label(for="admin", data-i18n="account_settings.admin") Admin
|
||||
input#admin(name="admin", type="checkbox", checked=admin)
|
||||
|
||||
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
.panel-title(data-i18n="account_settings.picture_tab")
|
||||
.panel-body
|
||||
img.profile-photo(src=me.getPhotoURL(230), draggable="false")
|
||||
input#photoURL(type="hidden", value=me.get('photoURL')||'')
|
||||
button#upload-photo-button.btn.form-control.btn-primary(data-i18n="account_settings.upload_picture")
|
||||
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
.panel-title(data-i18n="account_settings.password_tab")
|
||||
.panel-body
|
||||
.form
|
||||
.form-group
|
||||
label.control-label(for="password", data-i18n="account_settings.new_password") New Password
|
||||
input#password.form-control(name="password", type="password")
|
||||
.form-group
|
||||
label.control-label(for="password2", data-i18n="account_settings.new_password_verify") Verify
|
||||
input#password2.form-control(name="password2", type="password")
|
||||
|
||||
.col-md-6
|
||||
|
||||
#email-panel.panel.panel-default
|
||||
.panel-heading
|
||||
.panel-title(data-i18n="account_settings.emails_tab")
|
||||
.panel-body
|
||||
|
||||
.form
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_generalNews", data-i18n="account_settings.email_announcements") Announcements
|
||||
input#email_generalNews(name="email_generalNews", type="checkbox", checked=subs.generalNews)
|
||||
span.help-block(data-i18n="account_settings.email_announcements_description") Get emails on the latest news and developments at CodeCombat.
|
||||
|
||||
hr
|
||||
h4(data-i18n="account_settings.email_notifications") Notifications
|
||||
span(data-i18n="account_settings.email_notifications_summary") Controls for personalized, automatic email notifications related to your CodeCombat activity.
|
||||
|
||||
.form
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_anyNotes", data-i18n="account_settings.email_any_notes") Any Notifications
|
||||
input#email_anyNotes(name="email_anyNotes", type="checkbox", checked=subs.anyNotes)
|
||||
span.help-block(data-i18n="account_settings.email_any_notes_description") Disable to stop all activity notification emails.
|
||||
|
||||
fieldset#specific-notification-settings
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_recruitNotes", data-i18n="account_settings.email_recruit_notes") Job Opportunities
|
||||
input#email_recruitNotes(name="email_recruitNotes", type="checkbox", checked=subs.recruitNotes)
|
||||
span.help-block(data-i18n="account_settings.email_recruit_notes_description") If you play really well, we may contact you about getting you a (better) job.
|
||||
|
||||
hr
|
||||
|
||||
h4(data-i18n="account_settings.contributor_emails") Contributor Class Emails
|
||||
span(data-i18n="account_settings.contribute_prefix") We're looking for people to join our party! Check out the
|
||||
a(href="/contribute", data-i18n="account_settings.contribute_page") contribute page
|
||||
span(data-i18n="account_settings.contribute_suffix") to find out more.
|
||||
|
||||
.form
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_archmageNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.archmage_subscribe_desc").help-block Get emails about general news and announcements about CodeCombat.
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_artisanNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.artisan_subscribe_desc").help-block Get emails on level editor updates and announcements.
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_adventurerNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.adventurer_subscribe_desc").help-block Get emails when there are new levels to test.
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_scribeNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.scribe_subscribe_desc").help-block Get emails about article writing announcements.
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_diplomatNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.diplomat_subscribe_desc").help-block Get emails about i18n developments and, eventually, levels to translate.
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_ambassadorNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.ambassador_subscribe_desc").help-block Get emails on support updates and multiplayer developments.
|
||||
|
||||
button#toggle-all-button.btn.btn-primary.form-control(data-i18n="account_settings.email_toggle") Toggle All
|
||||
|
||||
.clearfix
|
||||
|
||||
block footer
|
|
@ -1,141 +0,0 @@
|
|||
extends /templates/base
|
||||
|
||||
block content
|
||||
if !me.isAnonymous()
|
||||
.clearfix
|
||||
.col-sm-6.clearfix
|
||||
h2
|
||||
span(data-i18n="account_settings.title") Account Settings
|
||||
a.spl(href="/account/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" data-i18n="account_settings.picture_tab") Picture
|
||||
.panel-body.text-center
|
||||
img#picture(src="#{me.getPhotoURL(150)}" alt="Picture")
|
||||
.col-xs-6
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
h3.panel-title
|
||||
i.glyphicon.glyphicon-user
|
||||
a(href="account/settings#wizard" data-i18n="account_settings.wizard_tab") 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" data-i18n="account_settings.me_tab") Me
|
||||
.panel-body
|
||||
table
|
||||
tr
|
||||
th(data-i18n="general.name") Name
|
||||
td=me.displayName()
|
||||
tr
|
||||
th(data-i18n="general.email") Email
|
||||
td=me.get('email')
|
||||
.panel.panel-default.panel-emails
|
||||
.panel-heading
|
||||
h3.panel-title
|
||||
i.glyphicon.glyphicon-envelope
|
||||
a(href="account/settings#emails" data-i18n="account_settings.emails_tab") Emails
|
||||
.panel-body
|
||||
if !hasEmailNotes && !hasEmailNews && !hasGeneralNews
|
||||
p(data-i18n="account_settings.email_subscriptions_none") No email subscriptions.
|
||||
if hasGeneralNews
|
||||
h4(data-i18n="account_settings.email_news") News
|
||||
ul
|
||||
li(data-i18n="account_settings.email_announcements") Announcements
|
||||
if hasEmailNotes
|
||||
h4(data-i18n="account_settings.email_notifications") 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(data-i18n="account_settings.contributor_emails") Contributor Emails
|
||||
ul
|
||||
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" data-i18n="general.password") Password
|
||||
//.panel.panel-default
|
||||
// .panel-heading
|
||||
// h3.panel-title
|
||||
// i.glyphicon.glyphicon-briefcase
|
||||
// a(href="account/settings#job-profile" data-i18n="account_settings.job_profile") Job Profile
|
||||
.col-sm-6
|
||||
h2(data-i18n="user.recently_played") Recently Played
|
||||
hr
|
||||
if !recentlyPlayed
|
||||
div(data-i18n="common.loading") Loading...
|
||||
else if recentlyPlayed.length
|
||||
table.table
|
||||
tr
|
||||
th(data-i18n="resources.level") Level
|
||||
th(data-i18n="user.last_played") Last Played
|
||||
th(data-i18n="user.status") 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(data-i18n="user.status_completed") Completed
|
||||
else if ! session.isMultiplayer()
|
||||
td(data-i18n="user.status_unfinished") Unfinished
|
||||
else
|
||||
td
|
||||
|
||||
else
|
||||
.panel.panel-default
|
||||
.panel-body
|
||||
div(data-i18n="account.no_recent_games") No games played during the past two weeks.
|
21
app/templates/account/main-account-view.jade
Normal file
21
app/templates/account/main-account-view.jade
Normal file
|
@ -0,0 +1,21 @@
|
|||
extends /templates/base
|
||||
|
||||
block content
|
||||
|
||||
if me.get('anonymous')
|
||||
p(data-i18n="account_settings.not_logged_in") Log in or create an account to change your settings.
|
||||
|
||||
else
|
||||
ol.breadcrumb
|
||||
li
|
||||
a(href="/")
|
||||
span.glyphicon.glyphicon-home
|
||||
li.active(data-i18n="nav.account")
|
||||
|
||||
#account-links.panel.panel-default
|
||||
.panel-heading(data-i18n="nav.account")
|
||||
ul.list-group
|
||||
li.list-group-item
|
||||
a.btn.btn-lg.btn-primary(href="/account/settings", data-i18n="play.settings")
|
||||
li.list-group-item
|
||||
a.btn.btn-lg.btn-primary(href="/account/payments", data-i18n="account.payments")
|
|
@ -1,165 +0,0 @@
|
|||
extends /templates/base
|
||||
|
||||
block content
|
||||
|
||||
h2(data-i18n="account_settings.title") Account Settings
|
||||
|
||||
if me.get('anonymous')
|
||||
p(data-i18n="account_settings.not_logged_in") Log in or create an account to change your settings.
|
||||
|
||||
else
|
||||
#save-button-container
|
||||
button.btn#save-button.disabled(data-i18n="general.save" disabled="true") No Changes
|
||||
|
||||
ul.nav.nav-pills#settings-tabs
|
||||
li
|
||||
a(href="#general-pane", data-toggle="tab", data-i18n="account_settings.me_tab") Me
|
||||
li
|
||||
a(href="#picture-pane", data-toggle="tab", data-i18n="account_settings.picture_tab") Picture
|
||||
li
|
||||
a(href="#wizard-pane", data-toggle="tab", data-i18n="account_settings.wizard_tab") Wizard
|
||||
li
|
||||
a(href="#password-pane", data-toggle="tab", data-i18n="account_settings.password_tab") Password
|
||||
li
|
||||
a(href="#email-pane", data-toggle="tab", data-i18n="account_settings.emails_tab") Emails
|
||||
if showsJobProfileTab
|
||||
li
|
||||
a(href="#job-profile-pane", data-toggle="tab", data-i18n="account_settings.job_profile_tab") Job Profile
|
||||
|
||||
.tab-content#settings-panes
|
||||
#general-pane.tab-pane
|
||||
p
|
||||
.form
|
||||
- var name = me.get('name') || '';
|
||||
- var email = me.get('email');
|
||||
- var admin = me.get('permissions', true).indexOf('admin') != -1;
|
||||
.form-group
|
||||
label.control-label(for="name", data-i18n="general.name") Name
|
||||
input#name.form-control(name="name", type="text", value="#{name}")
|
||||
.form-group
|
||||
label.control-label(for="email", data-i18n="general.email") Email
|
||||
input#email.form-control(name="email", type="text", value="#{email}")
|
||||
if !isProduction
|
||||
.form-group.checkbox
|
||||
label(for="admin", data-i18n="account_settings.admin") Admin
|
||||
input#admin(name="admin", type="checkbox", checked=admin)
|
||||
|
||||
|
||||
#picture-pane.tab-pane
|
||||
h3(data-i18n="account_settings.upload_picture") Upload a picture
|
||||
#picture-treema
|
||||
.gravatar-fallback
|
||||
img(src=me.getPhotoURL(256), alt="Gravatar", title="Gravatar fallback image")
|
||||
|
||||
#wizard-pane.tab-pane
|
||||
#wizard-settings-view
|
||||
|
||||
#password-pane.tab-pane
|
||||
p
|
||||
.form
|
||||
.form-group
|
||||
label.control-label(for="password", data-i18n="account_settings.new_password") New Password
|
||||
input#password.form-control(name="password", type="password")
|
||||
.form-group
|
||||
label.control-label(for="password2", data-i18n="account_settings.new_password_verify") Verify
|
||||
input#password2.form-control(name="password2", type="password")
|
||||
|
||||
#email-pane.tab-pane
|
||||
h3(data-i18n="account_settings.email_subscriptions") Email Subscriptions
|
||||
|
||||
p
|
||||
.form
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_generalNews", data-i18n="account_settings.email_announcements") Announcements
|
||||
input#email_generalNews(name="email_generalNews", type="checkbox", checked=subs.generalNews)
|
||||
span.help-block(data-i18n="account_settings.email_announcements_description") Get emails on the latest news and developments at CodeCombat.
|
||||
|
||||
hr
|
||||
h4(data-i18n="account_settings.email_notifications") Notifications
|
||||
span(data-i18n="account_settings.email_notifications_summary") Controls for personalized, automatic email notifications related to your CodeCombat activity.
|
||||
|
||||
.form
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_anyNotes", data-i18n="account_settings.email_any_notes") Any Notifications
|
||||
input#email_anyNotes(name="email_anyNotes", type="checkbox", checked=subs.anyNotes)
|
||||
span.help-block(data-i18n="account_settings.email_any_notes_description") Disable to stop all activity notification emails.
|
||||
|
||||
fieldset#specific-notification-settings
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_recruitNotes", data-i18n="account_settings.email_recruit_notes") Job Opportunities
|
||||
input#email_recruitNotes(name="email_recruitNotes", type="checkbox", checked=subs.recruitNotes)
|
||||
span.help-block(data-i18n="account_settings.email_recruit_notes_description") If you play really well, we may contact you about getting you a (better) job.
|
||||
|
||||
hr
|
||||
|
||||
h4(data-i18n="account_settings.contributor_emails") Contributor Class Emails
|
||||
span(data-i18n="account_settings.contribute_prefix") We're looking for people to join our party! Check out the
|
||||
a(href="/contribute", data-i18n="account_settings.contribute_page") contribute page
|
||||
span(data-i18n="account_settings.contribute_suffix") to find out more.
|
||||
|
||||
.form
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_archmageNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.archmage_subscribe_desc").help-block Get emails about general news and announcements about CodeCombat.
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_artisanNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.artisan_subscribe_desc").help-block Get emails on level editor updates and announcements.
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_adventurerNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.adventurer_subscribe_desc").help-block Get emails when there are new levels to test.
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_scribeNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.scribe_subscribe_desc").help-block Get emails about article writing announcements.
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_diplomatNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.diplomat_subscribe_desc").help-block Get emails about i18n developments and, eventually, levels to translate.
|
||||
|
||||
.form-group.checkbox
|
||||
label.control-label(for="email_ambassadorNews")
|
||||
span(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)
|
||||
span(data-i18n="contribute.ambassador_subscribe_desc").help-block Get emails on support updates and multiplayer developments.
|
||||
|
||||
button.btn#toggle-all-button(data-i18n="account_settings.email_toggle") Toggle All
|
||||
|
||||
#job-profile-pane.tab-pane
|
||||
#job-profile-view
|
|
@ -1,54 +0,0 @@
|
|||
extends /templates/kinds/user
|
||||
|
||||
block append content
|
||||
.btn-group.pull-right
|
||||
button#grid-layout-button.btn.btn-default(data-layout='grid', class=activeLayout==='grid' ? 'active' : '')
|
||||
i.glyphicon.glyphicon-th
|
||||
button#table-layout-button.btn.btn-default(data-layout='table', class=activeLayout==='table' ? 'active' : '')
|
||||
i.glyphicon.glyphicon-th-list
|
||||
if achievementsByCategory
|
||||
if activeLayout === 'grid'
|
||||
.grid-layout
|
||||
each achievements, category in achievementsByCategory
|
||||
.row
|
||||
h2.achievement-category-title(data-i18n="achievements.category_#{category}")=category
|
||||
each achievement, index in achievements
|
||||
- var title = achievement.i18nName();
|
||||
- var description = achievement.i18nDescription();
|
||||
- var locked = ! achievement.get('unlocked');
|
||||
- var style = achievement.getStyle()
|
||||
- var imgURL = achievement.getImageURL();
|
||||
if locked
|
||||
- var imgURL = achievement.getLockedImageURL();
|
||||
else
|
||||
- var imgURL = achievement.getImageURL();
|
||||
.col-lg-4.col-xs-12
|
||||
include ../achievements/achievement-popup
|
||||
else if activeLayout === 'table'
|
||||
.table-layout
|
||||
if earnedAchievements.length
|
||||
table.table
|
||||
tr
|
||||
th(data-i18n="general.name") Name
|
||||
th(data-i18n="general.description") Description
|
||||
th(data-i18n="general.date") Date
|
||||
th(data-i18n="achievements.amount_achieved") Amount
|
||||
th XP
|
||||
each earnedAchievement in earnedAchievements.models
|
||||
- var achievement = earnedAchievement.get('achievement');
|
||||
if achievement.get('category')
|
||||
// No level-specific achievements in here.
|
||||
tr
|
||||
td= achievement.i18nName()
|
||||
td= achievement.i18nDescription()
|
||||
td= moment().format("MMMM Do YYYY", earnedAchievement.get('changed'))
|
||||
if achievement.isRepeatable()
|
||||
td= earnedAchievement.get('achievedAmount')
|
||||
else
|
||||
td
|
||||
td= earnedAchievement.get('earnedPoints')
|
||||
else
|
||||
.panel#no-achievements
|
||||
.panel-body(data-i18n="user.no_achievements") No achievements earned yet.
|
||||
else
|
||||
div How did you even do that?
|
|
@ -14,17 +14,8 @@ block append content
|
|||
span(data-i18n="user.favorite_prefix") Favorite language is
|
||||
strong.favorite-language= favoriteLanguage
|
||||
span(data-i18n="user.favorite_postfix") .
|
||||
.btn-group-vertical.profile-menu
|
||||
a.btn.btn-default(href="/user/#{user.getSlugOrID()}/profile")
|
||||
i.glyphicon.glyphicon-briefcase
|
||||
span(data-i18n="account_settings.job_profile") Job Profile
|
||||
a.btn.btn-default(href="/user/#{user.getSlugOrID()}/stats")
|
||||
i.glyphicon.glyphicon-certificate
|
||||
span(data-i18n="user.stats") Stats
|
||||
a.btn.btn-default.disabled(href="#")
|
||||
i.glyphicon.glyphicon-pencil
|
||||
span(data-i18n="general.code") Code
|
||||
- var emails = user.get('emails')
|
||||
- var emails = user.getEnabledEmails()
|
||||
// TODO: fix this, use some other method for finding contributor classes other than email settings, since they're private... Maybe achievements?
|
||||
if emails
|
||||
ul.contributor-categories
|
||||
//li.contributor-category
|
||||
|
@ -69,9 +60,11 @@ block append content
|
|||
th.col-xs-4(data-i18n="resources.level") Level
|
||||
th.col-xs-4(data-i18n="user.last_played") Last Played
|
||||
th.col-xs-4(data-i18n="user.status") Status
|
||||
each session in singlePlayerSessions
|
||||
- var count = 0
|
||||
each session, index in singlePlayerSessions
|
||||
if session.get('levelName')
|
||||
tr
|
||||
tr(class=count > 4 ? 'hide' : '')
|
||||
- count++;
|
||||
td
|
||||
a(href="/play/level/#{session.get('levelID')}")= session.get('levelName')
|
||||
td= moment(session.get('changed')).fromNow()
|
||||
|
@ -79,6 +72,9 @@ block append content
|
|||
td(data-i18n="user.status_completed") Completed
|
||||
else
|
||||
td(data-i18n="user.status_unfinished") Unfinished
|
||||
if count > 4
|
||||
.panel-footer
|
||||
button.btn.btn-info.btn-sm.more-button(data-i18n="editor.more")
|
||||
else
|
||||
.panel-body
|
||||
p(data-i18n="user.no_singleplayer") No Singleplayer games played yet.
|
||||
|
@ -94,17 +90,20 @@ block append content
|
|||
th.col-xs-4(data-i18n="resources.level") Level
|
||||
th.col-xs-4(data-i18n="user.last_played") Last Played
|
||||
th.col-xs-4(data-i18n="general.score") Score
|
||||
each session in multiPlayerSessions
|
||||
tr
|
||||
each session, index in multiPlayerSessions
|
||||
tr(class=index > 4 ? 'hide' : '')
|
||||
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('totalScore')
|
||||
td= session.get('totalScore') * 100
|
||||
td= parseInt(session.get('totalScore') * 100)
|
||||
else
|
||||
td(data-i18n="user.status_unfinished") Unfinished
|
||||
if multiPlayerSessions.length > 4
|
||||
.panel-footer
|
||||
button.btn.btn-info.btn-sm.more-button(data-i18n="editor.more")
|
||||
else
|
||||
.panel-body
|
||||
p(data-i18n="user.no_multiplayer") No Multiplayer games played yet.
|
||||
|
@ -123,11 +122,15 @@ block append content
|
|||
th.col-xs-4(data-i18n="achievements.achievement") Achievement
|
||||
th.col-xs-4(data-i18n="achievements.last_earned") Last Earned
|
||||
th.col-xs-4(data-i18n="achievements.amount_achieved") Amount
|
||||
each achievement in earnedAchievements.models
|
||||
tr
|
||||
each achievement, index in earnedAchievements.models
|
||||
tr(class=index > 4 ? 'hide' : '')
|
||||
td= achievement.get('achievementName')
|
||||
td= moment().format("MMMM Do YYYY", achievement.get('changed'))
|
||||
if achievement.get('achievedAmount')
|
||||
td= achievement.get('achievedAmount')
|
||||
else
|
||||
td
|
||||
if earnedAchievements.length > 4
|
||||
.panel-footer
|
||||
button.btn.btn-info.btn-sm.more-button(data-i18n="editor.more")
|
||||
|
|
@ -1,73 +1,54 @@
|
|||
RootView = require 'views/kinds/RootView'
|
||||
template = require 'templates/account/settings'
|
||||
template = require 'templates/account/account-settings-view'
|
||||
{me} = require 'lib/auth'
|
||||
forms = require 'lib/forms'
|
||||
User = require 'models/User'
|
||||
AuthModal = require 'views/modal/AuthModal'
|
||||
|
||||
WizardSettingsView = require './WizardSettingsView'
|
||||
JobProfileTreemaView = require './JobProfileTreemaView'
|
||||
|
||||
module.exports = class AccountSettingsView extends RootView
|
||||
id: 'account-settings-view'
|
||||
template: template
|
||||
changedFields: [] # DOM input fields
|
||||
|
||||
events:
|
||||
'click #save-button': 'save'
|
||||
'change #settings-panes input:checkbox': (e) -> @trigger 'checkboxToggled', e
|
||||
'keyup #settings-panes input:text, #settings-panes input:password': (e) -> @trigger 'inputChanged', e
|
||||
'keyup #name': 'onNameChange'
|
||||
'change .panel input': 'onInputChanged'
|
||||
'change #name': 'checkNameExists'
|
||||
'click #toggle-all-button': 'toggleEmailSubscriptions'
|
||||
'keypress #settings-panes': 'onKeyPress'
|
||||
'click .profile-photo': 'onEditProfilePhoto'
|
||||
'click #save-button': 'save'
|
||||
'click #upload-photo-button': 'onEditProfilePhoto'
|
||||
|
||||
shortcuts:
|
||||
'enter': 'save'
|
||||
|
||||
constructor: (options) ->
|
||||
@save = _.debounce(@save, 200)
|
||||
@onNameChange = _.debounce @checkNameExists, 500
|
||||
super options
|
||||
return unless me
|
||||
require('lib/services/filepicker')() unless window.application.isIPadApp # Initialize if needed
|
||||
@uploadFilePath = "db/user/#{me.id}"
|
||||
|
||||
@listenTo(me, 'invalid', (errors) -> forms.applyErrorsToForm(@$el, me.validationError))
|
||||
@on 'checkboxToggled', @onToggle
|
||||
@on 'checkboxToggled', @onInputChanged
|
||||
@on 'inputChanged', @onInputChanged
|
||||
@on 'enterPressed', @onEnter
|
||||
afterInsert: ->
|
||||
super()
|
||||
@openModalView new AuthModal() if me.get('anonymous')
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
return c unless me
|
||||
c.subs = {}
|
||||
c.subs[sub] = 1 for sub in me.getEnabledEmails()
|
||||
c
|
||||
|
||||
|
||||
#- Form input callbacks
|
||||
|
||||
onInputChanged: (e) ->
|
||||
return @enableSaveButton() unless e?.currentTarget
|
||||
that = e.currentTarget
|
||||
$that = $(that)
|
||||
savedValue = $that.data 'saved-value'
|
||||
currentValue = $that.val()
|
||||
if savedValue isnt currentValue
|
||||
@changedFields.push that unless that in @changedFields
|
||||
@enableSaveButton()
|
||||
else
|
||||
_.pull @changedFields, that
|
||||
@disableSaveButton() if _.isEmpty @changedFields
|
||||
$(e.target).addClass 'changed'
|
||||
return @enableSaveButton()
|
||||
|
||||
onToggle: (e) ->
|
||||
$that = $(e.currentTarget)
|
||||
$that.val $that[0].checked
|
||||
|
||||
onEnter: ->
|
||||
toggleEmailSubscriptions: =>
|
||||
subs = @getSubscriptions()
|
||||
$('#email-panel input[type="checkbox"]', @$el).prop('checked', not _.any(_.values(subs))).addClass('changed')
|
||||
@save()
|
||||
|
||||
onKeyPress: (e) ->
|
||||
@trigger 'enterPressed', e if e.which is 13
|
||||
|
||||
enableSaveButton: ->
|
||||
$('#save-button', @$el).removeClass 'disabled'
|
||||
$('#save-button', @$el).removeClass 'btn-danger'
|
||||
$('#save-button', @$el).removeAttr 'disabled'
|
||||
$('#save-button', @$el).text 'Save'
|
||||
|
||||
disableSaveButton: ->
|
||||
$('#save-button', @$el).addClass 'disabled'
|
||||
$('#save-button', @$el).removeClass 'btn-danger'
|
||||
$('#save-button', @$el).attr 'disabled', "true"
|
||||
$('#save-button', @$el).text 'No Changes'
|
||||
|
||||
checkNameExists: =>
|
||||
name = $('#name', @$el).val()
|
||||
return if name is me.get 'name'
|
||||
|
@ -79,87 +60,69 @@ module.exports = class AccountSettingsView extends RootView
|
|||
@suggestedName = newName
|
||||
forms.setErrorToProperty @$el, 'name', "That name is taken! How about #{newName}?", true
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
$('#settings-tabs a', @$el).click((e) =>
|
||||
e.preventDefault()
|
||||
$(e.target).tab('show')
|
||||
|
||||
# make sure errors show up in the general pane, but keep the password pane clean
|
||||
$('#password-pane input').val('')
|
||||
#@save() unless $(e.target).attr('href') is '#password-pane'
|
||||
forms.clearFormAlerts($('#password-pane', @$el))
|
||||
)
|
||||
|
||||
@chooseTab(location.hash.replace('#', ''))
|
||||
|
||||
wizardSettingsView = new WizardSettingsView()
|
||||
@listenTo wizardSettingsView, 'change', @enableSaveButton
|
||||
@insertSubView wizardSettingsView
|
||||
|
||||
@jobProfileTreemaView = new JobProfileTreemaView()
|
||||
@listenTo @jobProfileTreemaView, 'change', @enableSaveButton
|
||||
@insertSubView @jobProfileTreemaView
|
||||
_.defer => @buildPictureTreema() # Not sure why, but the Treemas don't fully build without this if you reload the page.
|
||||
|
||||
afterInsert: ->
|
||||
super()
|
||||
$('#email-pane input[type="checkbox"]').on 'change', ->
|
||||
$(@).addClass 'changed'
|
||||
if me.get('anonymous')
|
||||
@openModalView new AuthModal()
|
||||
@updateSavedValues()
|
||||
|
||||
chooseTab: (category) ->
|
||||
id = "##{category}-pane"
|
||||
pane = $(id, @$el)
|
||||
return @chooseTab('general') unless pane.length or category is 'general'
|
||||
loc = "a[href=#{id}]"
|
||||
$(loc, @$el).tab('show')
|
||||
$('.tab-pane').removeClass('active')
|
||||
pane.addClass('active')
|
||||
@currentTab = category
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
return c unless me
|
||||
c.subs = {}
|
||||
c.subs[sub] = 1 for sub in c.me.getEnabledEmails()
|
||||
c.showsJobProfileTab = me.isAdmin() or me.get('jobProfile') or location.hash.search('job-profile-') isnt -1
|
||||
c
|
||||
|
||||
getSubscriptions: ->
|
||||
inputs = ($(i) for i in $('#email-pane input[type="checkbox"].changed', @$el))
|
||||
emailNames = (i.attr('name').replace('email_', '') for i in inputs)
|
||||
enableds = (i.prop('checked') for i in inputs)
|
||||
_.zipObject emailNames, enableds
|
||||
|
||||
toggleEmailSubscriptions: =>
|
||||
subs = @getSubscriptions()
|
||||
$('#email-pane input[type="checkbox"]', @$el).prop('checked', not _.any(_.values(subs))).addClass('changed')
|
||||
@save()
|
||||
|
||||
buildPictureTreema: ->
|
||||
data = photoURL: me.get('photoURL')
|
||||
data.photoURL = null if data.photoURL?.search('gravatar') isnt -1 # Old style
|
||||
schema = $.extend true, {}, me.schema()
|
||||
schema.properties = _.pick me.schema().properties, 'photoURL'
|
||||
schema.required = ['photoURL']
|
||||
treemaOptions =
|
||||
filePath: "db/user/#{me.id}"
|
||||
schema: schema
|
||||
data: data
|
||||
callbacks: {change: @onPictureChanged}
|
||||
|
||||
@pictureTreema = @$el.find('#picture-treema').treema treemaOptions
|
||||
@pictureTreema?.build()
|
||||
@pictureTreema?.open()
|
||||
@$el.find('.gravatar-fallback').toggle not me.get 'photoURL'
|
||||
|
||||
onPictureChanged: (e) =>
|
||||
@trigger 'inputChanged', e
|
||||
@$el.find('.gravatar-fallback').toggle not me.get 'photoURL'
|
||||
|
||||
|
||||
#- Just copied from OptionsView, TODO refactor
|
||||
|
||||
onEditProfilePhoto: (e) ->
|
||||
return if window.application.isIPadApp # TODO: have an iPad-native way of uploading a photo, since we don't want to load FilePicker on iPad (memory)
|
||||
photoContainer = @$el.find('.profile-photo')
|
||||
onSaving = =>
|
||||
photoContainer.addClass('saving')
|
||||
onSaved = (uploadingPath) =>
|
||||
@$el.find('#photoURL').val(uploadingPath)
|
||||
@onInputChanged() # cause for some reason editing the value doesn't trigger the jquery event
|
||||
me.set('photoURL', uploadingPath)
|
||||
photoContainer.removeClass('saving').attr('src', me.getPhotoURL(photoContainer.width()))
|
||||
filepicker.pick {mimetypes: 'image/*'}, @onImageChosen(onSaving, onSaved)
|
||||
|
||||
formatImagePostData: (inkBlob) ->
|
||||
url: inkBlob.url, filename: inkBlob.filename, mimetype: inkBlob.mimetype, path: @uploadFilePath, force: true
|
||||
|
||||
onImageChosen: (onSaving, onSaved) ->
|
||||
(inkBlob) =>
|
||||
onSaving()
|
||||
uploadingPath = [@uploadFilePath, inkBlob.filename].join('/')
|
||||
data = @formatImagePostData(inkBlob)
|
||||
success = @onImageUploaded(onSaved, uploadingPath)
|
||||
$.ajax '/file', type: 'POST', data: data, success: success
|
||||
|
||||
onImageUploaded: (onSaved, uploadingPath) ->
|
||||
(e) =>
|
||||
onSaved uploadingPath
|
||||
|
||||
|
||||
#- Save button enable/disable
|
||||
|
||||
enableSaveButton: ->
|
||||
$('#save-button', @$el)
|
||||
.addClass 'btn-info'
|
||||
.removeClass 'disabled btn-danger'
|
||||
.removeAttr 'disabled'
|
||||
.text 'Save'
|
||||
|
||||
disableSaveButton: ->
|
||||
$('#save-button', @$el)
|
||||
.addClass 'disabled'
|
||||
.removeClass 'btn-danger btn-info'
|
||||
.attr 'disabled', "true"
|
||||
.text 'No Changes'
|
||||
|
||||
|
||||
#- Misc
|
||||
|
||||
getSubscriptions: ->
|
||||
inputs = ($(i) for i in $('#email-panel input[type="checkbox"].changed', @$el))
|
||||
emailNames = (i.attr('name').replace('email_', '') for i in inputs)
|
||||
enableds = (i.prop('checked') for i in inputs)
|
||||
_.zipObject emailNames, enableds
|
||||
|
||||
|
||||
#- Saving changes
|
||||
|
||||
save: (e) ->
|
||||
$('#settings-tabs input').removeClass 'changed'
|
||||
forms.clearFormAlerts(@$el)
|
||||
|
@ -168,6 +131,7 @@ module.exports = class AccountSettingsView extends RootView
|
|||
if res?
|
||||
console.error 'Couldn\'t save because of validation errors:', res
|
||||
forms.applyErrorsToForm(@$el, res)
|
||||
$('.nano').nanoScroller({scrollTo: @$el.find('.has-error')})
|
||||
return
|
||||
|
||||
return unless me.hasLocalChanges()
|
||||
|
@ -180,11 +144,11 @@ module.exports = class AccountSettingsView extends RootView
|
|||
res.error ->
|
||||
errors = JSON.parse(res.responseText)
|
||||
forms.applyErrorsToForm(@$el, errors)
|
||||
$('.nano').nanoScroller({scrollTo: @$el.find('.has-error')})
|
||||
save.text($.i18n.t('account_settings.error_saving', defaultValue: 'Error Saving')).removeClass('btn-success').addClass('btn-danger', 500)
|
||||
res.success (model, response, options) =>
|
||||
@changedFields = []
|
||||
@updateSavedValues()
|
||||
save.text($.i18n.t('account_settings.saved', defaultValue: 'Changes Saved')).removeClass('btn-success', 500).attr('disabled', 'true')
|
||||
save.text($.i18n.t('account_settings.saved', defaultValue: 'Changes Saved')).removeClass('btn-success btn-info', 1000).attr('disabled', 'true')
|
||||
|
||||
grabData: ->
|
||||
@grabPasswordData()
|
||||
|
@ -198,6 +162,7 @@ module.exports = class AccountSettingsView extends RootView
|
|||
message = $.i18n.t('account_settings.password_mismatch', defaultValue: 'Password does not match.')
|
||||
err = [message: message, property: 'password2', formatted: true]
|
||||
forms.applyErrorsToForm(@$el, err)
|
||||
$('.nano').nanoScroller({scrollTo: @$el.find('.has-error')})
|
||||
return
|
||||
if bothThere
|
||||
me.set('password', password1)
|
||||
|
@ -205,36 +170,19 @@ module.exports = class AccountSettingsView extends RootView
|
|||
message = $.i18n.t('account_settings.password_repeat', defaultValue: 'Please repeat your password.')
|
||||
err = [message: message, property: 'password2', formatted: true]
|
||||
forms.applyErrorsToForm(@$el, err)
|
||||
$('.nano').nanoScroller({scrollTo: @$el.find('.has-error')})
|
||||
|
||||
grabOtherData: ->
|
||||
$('#name', @$el).val @suggestedName if @suggestedName
|
||||
me.set 'name', $('#name', @$el).val()
|
||||
me.set 'email', $('#email', @$el).val()
|
||||
@$el.find('#name').val @suggestedName if @suggestedName
|
||||
me.set 'name', @$el.find('#name').val()
|
||||
me.set 'email', @$el.find('#email').val()
|
||||
for emailName, enabled of @getSubscriptions()
|
||||
me.setEmailSubscription emailName, enabled
|
||||
me.set 'photoURL', @pictureTreema.get('/photoURL')
|
||||
|
||||
me.set('photoURL', @$el.find('#photoURL').val())
|
||||
|
||||
adminCheckbox = @$el.find('#admin')
|
||||
if adminCheckbox.length
|
||||
permissions = []
|
||||
permissions.push 'admin' if adminCheckbox.prop('checked')
|
||||
me.set('permissions', permissions)
|
||||
|
||||
jobProfile = me.get('jobProfile') ? {}
|
||||
updated = false
|
||||
for key, val of @jobProfileTreemaView.getData()
|
||||
updated = updated or not _.isEqual jobProfile[key], val
|
||||
jobProfile[key] = val
|
||||
if updated
|
||||
jobProfile.updated = (new Date()).toISOString()
|
||||
me.set 'jobProfile', jobProfile
|
||||
|
||||
updateSavedValues: ->
|
||||
$('#settings-panes input:text').each ->
|
||||
$(@).data 'saved-value', $(@).val()
|
||||
$('#settings-panes input:checkbox').each ->
|
||||
$(@).data 'saved-value', JSON.stringify $(@)[0].checked
|
||||
|
||||
destroy: ->
|
||||
@pictureTreema?.destroy()
|
||||
super()
|
|
@ -1,5 +1,5 @@
|
|||
View = require 'views/kinds/RootView'
|
||||
template = require 'templates/account/account_home'
|
||||
template = require 'templates/account/main-account-view'
|
||||
{me} = require 'lib/auth'
|
||||
User = require 'models/User'
|
||||
AuthModalView = require 'views/modal/AuthModal'
|
||||
|
@ -7,7 +7,7 @@ RecentlyPlayedCollection = require 'collections/RecentlyPlayedCollection'
|
|||
ThangType = require 'models/ThangType'
|
||||
|
||||
module.exports = class MainAccountView extends View
|
||||
id: 'account-home'
|
||||
id: 'main-account-view'
|
||||
template: template
|
||||
|
||||
constructor: (options) ->
|
||||
|
|
|
@ -25,6 +25,7 @@ module.exports = class AuthModal extends ModalView
|
|||
'auth:logging-in-with-facebook': 'onLoggingInWithFacebook'
|
||||
|
||||
constructor: (options) ->
|
||||
options ?= {}
|
||||
@onNameChange = _.debounce @checkNameExists, 500
|
||||
super options
|
||||
@mode = options.mode if options.mode
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
UserView = require 'views/kinds/UserView'
|
||||
template = require 'templates/user/achievements'
|
||||
{me} = require 'lib/auth'
|
||||
Achievement = require 'models/Achievement'
|
||||
EarnedAchievement = require 'models/EarnedAchievement'
|
||||
AchievementCollection = require 'collections/AchievementCollection'
|
||||
EarnedAchievementCollection = require 'collections/EarnedAchievementCollection'
|
||||
|
||||
module.exports = class AchievementsView extends UserView
|
||||
id: 'user-achievements-view'
|
||||
template: template
|
||||
viewName: 'Stats'
|
||||
activeLayout: 'grid'
|
||||
|
||||
events:
|
||||
'click #grid-layout-button': 'layoutChanged'
|
||||
'click #table-layout-button': 'layoutChanged'
|
||||
|
||||
constructor: (userID, options) ->
|
||||
super options, userID
|
||||
|
||||
onLoaded: ->
|
||||
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) ->
|
||||
@activeLayout = $(e.currentTarget).data 'layout'
|
||||
@render()
|
||||
|
||||
getRenderData: ->
|
||||
context = super()
|
||||
context.activeLayout = @activeLayout
|
||||
|
||||
# After user is loaded
|
||||
if @user and not @user.isAnonymous()
|
||||
context.earnedAchievements = @earnedAchievements
|
||||
context.achievementsByCategory = {}
|
||||
for achievement in @achievements.models when achievement.get('category')
|
||||
context.achievementsByCategory[achievement.get('category')] ?= []
|
||||
context.achievementsByCategory[achievement.get('category')].push achievement
|
||||
context
|
|
@ -1,7 +1,7 @@
|
|||
UserView = require 'views/kinds/UserView'
|
||||
CocoCollection = require 'collections/CocoCollection'
|
||||
LevelSession = require 'models/LevelSession'
|
||||
template = require 'templates/user/user_home'
|
||||
template = require 'templates/user/main-user-view'
|
||||
{me} = require 'lib/auth'
|
||||
EarnedAchievementCollection = require 'collections/EarnedAchievementCollection'
|
||||
|
||||
|
@ -15,6 +15,9 @@ class LevelSessionsCollection extends CocoCollection
|
|||
module.exports = class MainUserView extends UserView
|
||||
id: 'user-home'
|
||||
template: template
|
||||
|
||||
events:
|
||||
'click .more-button': 'onClickMoreButton'
|
||||
|
||||
constructor: (userID, options) ->
|
||||
super options
|
||||
|
@ -54,3 +57,8 @@ module.exports = class MainUserView extends UserView
|
|||
@supermodel.loadCollection @levelSessions, 'levelSessions'
|
||||
@supermodel.loadCollection @earnedAchievements, 'earnedAchievements'
|
||||
super()
|
||||
|
||||
onClickMoreButton: (e) ->
|
||||
panel = $(e.target).closest('.panel')
|
||||
panel.find('tr.hide').removeClass('hide')
|
||||
panel.find('.panel-footer').remove()
|
Loading…
Reference in a new issue