Refactored the AccountSettingsView to be both in the site and in the PlayAccountModal.

This commit is contained in:
Scott Erickson 2014-11-25 12:43:17 -08:00
parent 426202d80a
commit 8f55b9bc1b
10 changed files with 275 additions and 203 deletions

View file

@ -21,7 +21,7 @@ module.exports = class CocoRouter extends Backbone.Router
'about': go('AboutView')
'account': go('account/MainAccountView')
'account/settings': go('account/AccountSettingsView')
'account/settings': go('account/AccountSettingsRootView')
'account/unsubscribe': go('account/UnsubscribeView')
'account/profile': go('user/JobProfileView') # legacy URL, sent in emails
'account/payments': go('account/PaymentsView')

View file

@ -1,6 +1,5 @@
#account-settings-view
#account-settings-root-view
//- Fixed save button
#site-content-area
@ -21,6 +20,10 @@
&.btn-info, &.btn-danger
opacity: 1.0
#account-settings-view
.row
padding-top: 20px
//- Panels

View file

@ -1,4 +1,13 @@
#play-account-modal
.account-view
color: black
.modal-dialog
min-width: 90%
.modal-header
margin-bottom: 20px
.modal-body
max-height: 500px
overflow: scroll
border-width: 2px 0
border-color: black
border-style: solid

View file

@ -0,0 +1,19 @@
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', true)
#save-button-container
button#save-button.btn-lg.btn.disabled(data-i18n="general.save" disabled="true") No Changes
#account-settings-view
block footer

View file

@ -1,164 +1,147 @@
extends /templates/base
if me.get('anonymous')
.alert.alert-danger(data-i18n="account_settings.not_logged_in") Log in or create an account to change your settings.
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
else
.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)
.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
.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")
.clearfix
.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
block footer
.clearfix

View file

@ -4,4 +4,7 @@ block modal-header-content
h3(data-i18n="play.account") Account
block modal-body-content
p TODO: show all dem account
#account-settings-view
block modal-footer-content
#save-button.btn-lg.btn.disabled(data-i18n="general.save" disabled="true") No Changes

View file

@ -0,0 +1,48 @@
RootView = require 'views/kinds/RootView'
template = require 'templates/account/account-settings-root-view'
AccountSettingsView = require './AccountSettingsView'
module.exports = class AccountSettingsRootView extends RootView
id: "account-settings-root-view"
template: template
events:
'click #save-button': -> @accountSettingsView.save()
shortcuts:
'enter': -> @
afterRender: ->
super()
@accountSettingsView = new AccountSettingsView()
@insertSubView(@accountSettingsView)
@listenTo @accountSettingsView, 'input-changed', @onInputChanged
@listenTo @accountSettingsView, 'save-user-began', @onUserSaveBegan
@listenTo @accountSettingsView, 'save-user-success', @onUserSaveSuccess
@listenTo @accountSettingsView, 'save-user-error', @onUserSaveError
onInputChanged: ->
@$el.find('#save-button')
.text($.i18n.t('common.save', defaultValue: 'Save'))
.addClass 'btn-info'
.removeClass 'disabled btn-danger'
.removeAttr 'disabled'
onUserSaveBegan: ->
@$el.find('#save-button')
.text($.i18n.t('common.saving', defaultValue: 'Saving...'))
.removeClass('btn-danger')
.addClass('btn-success').show()
onUserSaveSuccess: ->
@$el.find('#save-button')
.text($.i18n.t('account_settings.saved', defaultValue: 'Changes Saved'))
.removeClass('btn-success btn-info', 1000)
.attr('disabled', 'true')
onUserSaveError: ->
@$el.find('#save-button')
.text($.i18n.t('account_settings.error_saving', defaultValue: 'Error Saving'))
.removeClass('btn-success')
.addClass('btn-danger', 500)

View file

@ -1,26 +1,22 @@
RootView = require 'views/kinds/RootView'
CocoView = require 'views/kinds/CocoView'
template = require 'templates/account/account-settings-view'
{me} = require 'lib/auth'
forms = require 'lib/forms'
User = require 'models/User'
AuthModal = require 'views/modal/AuthModal'
module.exports = class AccountSettingsView extends RootView
module.exports = class AccountSettingsView extends CocoView
id: 'account-settings-view'
template: template
changedFields: [] # DOM input fields
className: 'countainer-fluid'
events:
'change .panel input': 'onInputChanged'
'change #name': 'checkNameExists'
'click #toggle-all-button': 'toggleEmailSubscriptions'
'click .profile-photo': 'onEditProfilePhoto'
'click #save-button': 'save'
'click #upload-photo-button': 'onEditProfilePhoto'
shortcuts:
'enter': 'save'
constructor: (options) ->
super options
require('lib/services/filepicker')() unless window.application.isIPadApp # Initialize if needed
@ -42,7 +38,7 @@ module.exports = class AccountSettingsView extends RootView
onInputChanged: (e) ->
$(e.target).addClass 'changed'
return @enableSaveButton()
@trigger 'input-changed'
toggleEmailSubscriptions: =>
subs = @getSubscriptions()
@ -95,23 +91,6 @@ module.exports = class AccountSettingsView extends RootView
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: ->
@ -123,7 +102,7 @@ module.exports = class AccountSettingsView extends RootView
#- Saving changes
save: (e) ->
save: ->
$('#settings-tabs input').removeClass 'changed'
forms.clearFormAlerts(@$el)
@grabData()
@ -138,17 +117,16 @@ module.exports = class AccountSettingsView extends RootView
res = me.patch()
return unless res
save = $('#save-button', @$el).text($.i18n.t('common.saving', defaultValue: 'Saving...'))
.removeClass('btn-danger').addClass('btn-success').show()
res.error ->
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)
@trigger 'save-user-error'
res.success (model, response, options) =>
@changedFields = []
save.text($.i18n.t('account_settings.saved', defaultValue: 'Changes Saved')).removeClass('btn-success btn-info', 1000).attr('disabled', 'true')
@trigger 'save-user-success'
@trigger 'save-user-began'
grabData: ->
@grabPasswordData()

View file

@ -1,15 +1,15 @@
ModalView = require 'views/kinds/ModalView'
template = require 'templates/play/modal/play-account-modal'
AccountSettingsView = require 'views/account/AccountSettingsView'
module.exports = class PlayAccountModal extends ModalView
className: 'modal fade play-modal'
template: template
modalWidthPercent: 90
plain: true
id: 'play-account-modal'
#instant: true
#events:
# 'change input.select': 'onSelectionChanged'
events:
'click #save-button': -> @accountSettingsView.save()
constructor: (options) ->
super options
@ -22,7 +22,32 @@ module.exports = class PlayAccountModal extends ModalView
super()
return unless @supermodel.finished()
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'game-menu-open', volume: 1
@accountSettingsView = new AccountSettingsView()
@insertSubView(@accountSettingsView)
@listenTo @accountSettingsView, 'input-changed', @onInputChanged
@listenTo @accountSettingsView, 'save-user-began', @onUserSaveBegan
@listenTo @accountSettingsView, 'save-user-success', @hide
@listenTo @accountSettingsView, 'save-user-error', @onUserSaveError
onHidden: ->
super()
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'game-menu-close', volume: 1
onInputChanged: ->
@$el.find('#save-button')
.text($.i18n.t('common.save', defaultValue: 'Save'))
.addClass 'btn-info'
.removeClass 'disabled btn-danger'
.removeAttr 'disabled'
onUserSaveBegan: ->
@$el.find('#save-button')
.text($.i18n.t('common.saving', defaultValue: 'Saving...'))
.removeClass('btn-danger')
.addClass('btn-success').show()
onUserSaveError: ->
@$el.find('#save-button')
.text($.i18n.t('account_settings.error_saving', defaultValue: 'Error Saving'))
.removeClass('btn-success')
.addClass('btn-danger', 500)

View file

@ -21,6 +21,10 @@ AchievablePlugin = (schema, options) ->
# Check if an achievement has been earned
schema.post 'save', (doc) ->
# sometimes post appears to be called twice. Handle this...
# TODO: Refactor this system to make it request-specific,
# perhaps by having POST/PUT requests store the copy on the request object themselves.
return if doc.isInit('_id') and not (doc.id of before)
isNew = not doc.isInit('_id') or not (doc.id of before)
originalDocObj = before[doc.id] unless isNew