Files
habitica/website/views/options/settings.jade
T
carolstone 3fa3b491dc Modified common/script/index.coffee to display dayStart, but send back a
variable of dayStart for processing, instead of having the object directly
updated at the time of edit.

Modified website/views/options/settings.jade to allow a timestamp to be
cast to an iso timestamp because lastCron is saved as an iso timestamp,
and as a straight moment()-based timestamp in order to compare timestamps.

Modified website/public/js/controllers/settingsCtrl.js to do the
following:
   Accept the new proposed dayStart
   Calculate the timestamp of the old dayStart and the new dayStart

     These two steps were necessary because dayStart is an integer between
     and including 0 and 23. I tested and confirmed the current production
     dayStart does not allow 24 to be entered but does allow 0. I was
     careful to NOT change how that worked.

   Cast the old dayStart, the new dayStart and lastCron to the moment()
   version of time so they could be compared.

   Cast the new dayStart to the iso timestamp for storage in lastCron

   The important change is the following:

   if oldDayStart < lastCron AND lastCron < newDayStart then lastCron
   should be set to newDayStart. I modified this to include if oldDayStart
   = lastCron, although I think that's pretty unlikely to be possible.
   When I tested this, my lastCron was a mere 17 seconds after my
   oldDayStart, so it seemed to me that the equal case should be included
   with the less than case.
2015-07-17 21:17:07 -04:00

344 lines
21 KiB
Plaintext

script(id='partials/options.settings.html', type="text/ng-template")
ul.options-menu
li(ng-class="{ active: $state.includes('options.settings.settings') }")
a(ui-sref='options.settings.settings')
=env.t('site')
li(ng-class="{ active: $state.includes('options.settings.api') }")
a(ui-sref='options.settings.api')
=env.t('API')
li(ng-class="{ active: $state.includes('options.settings.export') }")
a(ui-sref='options.settings.export')
=env.t('dataExport')
li(ng-class="{ active: $state.includes('options.settings.promo') }")
a(ui-sref='options.settings.promo')
=env.t('promoCode')
li(ng-class="{ active: $state.includes('options.settings.subscription') }")
a(ui-sref='options.settings.subscription')=env.t('subscription')
li(ng-class="{ active: $state.includes('options.settings.notifications') }")
a(ui-sref='options.settings.notifications')=env.t('notifications')
.tab-content
.tab-pane.active
div(ui-view)
script(type='text/ng-template', id='partials/options.settings.settings.html')
.container-fluid
.row
.personal-options.col-md-6
.panel.panel-default
.panel-heading
=env.t('settings')
.panel-body
.form-horizontal
h5=env.t('language')
select.form-control(ng-model='language.code', ng-options='lang.code as lang.name for lang in avalaibleLanguages', ng-change='changeLanguage()')
small
!=env.t('americanEnglishGovern')
br
strong
!=env.t('helpWithTranslation')
.form-horizontal
h5=env.t('dateFormat')
select.form-control(ng-model='user.preferences.dateFormat', ng-options='DF for DF in availableFormats', ng-change='set({"preferences.dateFormat": user.preferences.dateFormat})')
.checkbox
label
input(type='checkbox', ng-click='hideHeader() ', ng-checked='user.preferences.hideHeader!==true')
span.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('showHeaderPop'))=env.t('showHeader')
.checkbox
label
input(type='checkbox', ng-click='toggleStickyHeader()', ng-checked='user.preferences.stickyHeader!==false', ng-disabled="user.preferences.hideHeader!==false")
span.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('stickyHeaderPop'))=env.t('stickyHeader')
.checkbox
label
input(type='checkbox', ng-model='user.preferences.newTaskEdit', ng-change='set({"preferences.newTaskEdit": user.preferences.newTaskEdit?true: false})')
span.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('newTaskEditPop'))=env.t('newTaskEdit')
.checkbox
label
input(type='checkbox', ng-model='user.preferences.tagsCollapsed', ng-change='set({"preferences.tagsCollapsed": user.preferences.tagsCollapsed?true: false})')
span.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('startCollapsedPop'))=env.t('startCollapsed')
.checkbox
label
input(type='checkbox', ng-model='user.preferences.advancedCollapsed', ng-change='set({"preferences.advancedCollapsed": user.preferences.advancedCollapsed?true: false})')
span.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('startAdvCollapsedPop'))=env.t('startAdvCollapsed')
.checkbox
label
input(type='checkbox', ng-model='user.preferences.dailyDueDefaultView', ng-change='set({"preferences.dailyDueDefaultView": user.preferences.dailyDueDefaultView?true: false})')
span.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('dailyDueDefaultViewPop'))=env.t('dailyDueDefaultView')
.checkbox(ng-if='party.memberCount === 1')
label
input(type='checkbox', ng-model='user.preferences.displayInviteToPartyWhenPartyIs1', ng-change='set({"preferences.displayInviteToPartyWhenPartyIs1": user.preferences.displayInviteToPartyWhenPartyIs1 ? true : false})')
span.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('displayInviteToPartyWhenPartyIs1'))=env.t('displayInviteToPartyWhenPartyIs1')
// button.btn.btn-default(ng-click='showTour()', popover-placement='right', popover-trigger='mouseenter', popover=env.t('restartTour'))= env.t('showTour')
button.btn.btn-default(ng-click='showBailey()', popover-trigger='mouseenter', popover-placement='right', popover=env.t('showBaileyPop'))= env.t('showBailey')
button.btn.btn-default(ng-click='openRestoreModal()', popover-trigger='mouseenter', popover-placement='right', popover=env.t('fixValPop'))= env.t('fixVal')
button.btn.btn-default(ng-if='user.preferences.disableClasses==true', ng-click='user.ops.changeClass({})', popover-trigger='mouseenter', popover-placement='right', popover=env.t('enableClassPop'))= env.t('enableClass')
button.btn.btn-default(ng-if='!user.preferences.disableClasses && user.flags.classSelected', ng-click='showClassesTour()', popover-trigger='mouseenter', popover-placement='right', popover=env.t('classTourPop'))= env.t('showClass')
div.alert.alert-warning(style='padding:2px;margin-top:7px')
h5=env.t('customDayStart')
h5=env.t('customDayStartInfo1')
a(ng-click='showCustomDayStartInfo = !showCustomDayStartInfo') {{!showCustomDayStartInfo ? env.t('showMoreMore') : env.t('showMoreLess')}}
h5(ng-if='showCustomDayStartInfo')!=env.t('customDayStartInfo4')
.form-group
.input-group
input.form-control(type='number', min='0', max='23', ng-model='passDayStart', ng-blur='saveDayStart(passDayStart)')
span.input-group-addon= ':00 (' + env.t('24HrClock') + ')'
.personal-options.col-md-6
.panel.panel-default
.panel-heading
span Registration
.panel-body
div(ng-if='user.auth.facebook.id')
button.btn.btn-primary(disabled='disabled', ng-if='!user.auth.local.username')=env.t('registeredWithFb')
button.btn.btn-danger(ng-click='http("delete","/api/v2/user/auth/social",null,"detachedFacebook")', ng-if='user.auth.local.username')=env.t('detachFacebook')
hr
div(ng-if='!user.auth.local.username')
p Add local authentication:
form(ng-submit='http("post","/api/v2/register",localAuth,"addedLocalAuth")', ng-init='localAuth={}', name='localAuth', novalidate)
//-.alert.alert-danger(ng-messages='changeUsername.$error && changeUsername.submitted')=env.t('fillAll')
.form-group
input.form-control(type='text', placeholder=env.t('username'), ng-model='localAuth.username', required)
.form-group
input.form-control(type='text', placeholder=env.t('email'), ng-model='localAuth.email', required)
.form-group
input.form-control(type='password', placeholder=env.t('password'), ng-model='localAuth.password', required)
.form-group
input.form-control(type='password', placeholder=env.t('confirmPass'), ng-model='localAuth.confirmPassword', required)
input.btn.btn-default(type='submit', ng-disabled='localAuth.$invalid', value=env.t('submit'))
div(ng-if='user.auth.local.username')
p=env.t('username')
|: {{user.auth.local.username}}
p
small.muted
=env.t('loginNameDescription1')
|&nbsp;
a(href='/#/options/profile/profile')=env.t('loginNameDescription2')
|&nbsp;
=env.t('loginNameDescription3')
p=env.t('email')
|: {{user.auth.local.email}}
hr
h5=env.t('changeUsername')
form(ng-submit='changeUser("username", usernameUpdates)', ng-init='usernameUpdates={}', ng-show='user.auth.local', name='changeUsername', novalidate)
//-.alert.alert-danger(ng-messages='changeUsername.$error && changeUsername.submitted')=env.t('fillAll')
.form-group
input.form-control(type='text', placeholder=env.t('newUsername'), ng-model='usernameUpdates.username', required)
.form-group
input.form-control(type='password', placeholder=env.t('password'), ng-model='usernameUpdates.password', required)
input.btn.btn-default(type='submit', ng-disabled='changeUsername.$invalid', value=env.t('submit'))
h5=env.t('changeEmail')
form(ng-submit='changeUser("email", emailUpdates)', ng-show='user.auth.local', name='changeEmail', novalidate)
.form-group
input.form-control(type='text', placeholder=env.t('newEmail'), ng-model='emailUpdates.email', required)
.form-group
input.form-control(type='password', placeholder=env.t('password'), ng-model='emailUpdates.password', required)
input.btn.btn-default(type='submit', ng-disabled='changeEmail.$invalid', value=env.t('submit'))
h5=env.t('changePass')
form(ng-submit='changeUser("password", passwordUpdates)', ng-show='user.auth.local', name='changePassword', novalidate)
.form-group
input.form-control(type='password', placeholder=env.t('oldPass'), ng-model='passwordUpdates.oldPassword', required)
.form-group
input.form-control(type='password', placeholder=env.t('newPass'), ng-model='passwordUpdates.newPassword', required)
.form-group
input.form-control(type='password', placeholder=env.t('confirmPass'), ng-model='passwordUpdates.confirmNewPassword', required)
input.btn.btn-default(type='submit', ng-disabled='changePassword.$invalid', value=env.t('submit'))
.panel.panel-default
.panel-heading
span=env.t('dangerZone')
.panel-body
a.btn.btn-danger(ng-click='openModal("reset", {controller:"SettingsCtrl"})', popover-trigger='mouseenter', popover-placement='right', popover=env.t('resetAccPop'))= env.t('resetAccount')
a.btn.btn-danger(ng-click='openModal("delete", {controller:"SettingsCtrl"})', popover-trigger='mouseenter', popover=env.t('deleteAccPop'))= env.t('deleteAccount')
script(type='text/ng-template', id='partials/options.settings.promo.html')
.container-fluid
.row
.col-md-6
h2=env.t('promoCode')
form.form-inline(role='form',ng-submit='enterCoupon(_couponCode)')
input.form-control(type='text', ng-model='_couponCode', placeholder=env.t('promoPlaceholder'))
button.btn.btn-primary(type='submit')= env.t('submit')
div
small= env.t('couponText')
div(ng-if='user.contributor.sudo')
hr
h4 Generate Codes
form.form(role='form',ng-submit='generateCodes(_codes)',ng-init='_codes={}')
.form-group
input.form-control(type='text',ng-model='_codes.event',placeholder="Event code (eg, 'wondercon')")
.form-group
input.form-control(type='number',ng-model='_codes.count',placeholder="Number of codes to generate (eg, 250)")
.form-group
button.btn.btn-primary(type='submit') Generate
a.btn.btn-default(href='/api/v2/coupons?_id={{user._id}}&apiToken={{user.apiToken}}') Get Codes
script(type='text/ng-template', id='partials/options.settings.api.html')
.container-fluid
.row
.col-md-6
h2=env.t('API')
small=env.t('APIText')
h6=env.t('userId')
pre.prettyprint {{user.id}}
h6=env.t('APIToken')
pre.prettyprint {{user.apiToken}}
h6=env.t('qrCode')
img(src='https://chart.googleapis.com/chart?cht=qr&chs=200x200&chl=%7B%22address%22%3A%22https%3A%2F%2Fhabitrpg.com%22%2C%22user%22%3A%22{{user.id}}%22%2C%22key%22%3A%22{{user.apiToken}}%22%7D&choe=UTF-8&chld=L', alt='qrcode')
hr
h2 Webhooks
table.table.table-striped
thead(ng-if='hasWebhooks')
tr
th Enabled
th Webhook URL
th
tbody
tr(ng-repeat="webhook in user.preferences.webhooks | toArray:true | orderBy:'sort'")
td
input(type='checkbox', ng-model='webhook.enabled', ng-change='saveWebhook(webhook.$key,webhook)')
td
input.form-control(type='url', ng-model='webhook.url', ng-change='webhook._editing=true', ui-keyup="{13:'saveWebhook(webhook.$key,webhook)'}")
td
span.pull-left(ng-show='webhook._editing') *
a.checklist-icons(ng-click='deleteWebhook(webhook.$key)')
span.glyphicon.glyphicon-trash(tooltip=env.t('delete'))
tr
td(colspan=2)
form.form-horizontal(ng-submit='addWebhook(_newWebhook.url)')
.form-group.col-sm-10
input.form-control(type='url', ng-model='_newWebhook.url', placeholder='Webhook URL')
.col-sm-2
button.btn.btn-sm.btn-primary(type='submit') Add
script(id='partials/options.settings.export.html', type="text/ng-template")
.container-fluid
.row
.col-md-6
h2=env.t('dataExport')
small=env.t('saveData')
h4=env.t('habitHistory')
=env.t('exportHistory')
a(href="/export/history.csv")= ' ' + env.t('csv')
h4=env.t('userData')
=env.t('exportUserData')
a(href="/export/userdata.xml")= ' ' + env.t('xml') + ' '
a(href="/export/userdata.json")= env.t('json')
mixin subPerks()
table.table.table-striped
tr
td
span.hint(popover=env.t('buyGemsGoldText', {gemCost: "{{Shared.planGemLimits.convRate}}", gemLimit: "{{Shared.planGemLimits.convCap}}"}),popover-trigger='mouseenter',popover-placement='right') #{env.t('buyGemsGold')}&nbsp;
span.badge.badge-success(ng-show='_subscription.key!="basic_earned"') Cap raised to {{ [25 + user.purchased.plan.consecutive.gemCapExtra + Math.floor(Content.subscriptionBlocks[_subscription.key].months/3*5), 50] | min }}
tr
td
span.hint(popover=env.t('retainHistoryText'),popover-trigger='mouseenter',popover-placement='right')=env.t('retainHistory')
tr
td
span.hint(popover=env.t('doubleDropsText'),popover-trigger='mouseenter',popover-placement='right')=env.t('doubleDrops')
tr
td
span.hint(popover=env.t('mysteryItemText'),popover-trigger='mouseenter',popover-placement='right') #{env.t('mysteryItem')}&nbsp;
div(ng-show='_subscription.key!="basic_earned"')
.badge.badge-success +{{Math.floor(Content.subscriptionBlocks[_subscription.key].months/3)}} Mystic Hourglass
.small.muted Mystic Hourglasses allow purchasing a previous month's Mystery Item set.
tr
td
span.hint(popover=env.t('supportDevsText'),popover-trigger='mouseenter',popover-placement='right')=env.t('supportDevs')
script(id='partials/feature-matrix-check.html',type='text/ng-template')
span.task-checker.action-yesno
input.focusable(type='checkbox', checked)
label
script(id='partials/options.settings.notifications.html', type="text/ng-template")
.container-fluid
.row
.personal-options.col-md-6
.panel.panel-default
.panel-heading
=env.t('emailNotifications')
.panel-body
each notification in ['newPM', 'wonChallenge', 'giftedGems', 'giftedSubscription', 'invitedParty', 'invitedGuild', 'kickedGroup', 'questStarted', 'invitedQuest', 'inactivityEmails', 'weeklyRecaps']
-var preference = 'user.preferences.emailNotifications.' + notification
-var unsubscribeFromAll = 'user.preferences.emailNotifications.unsubscribeFromAll'
.checkbox: label
input(type='checkbox', ng-model='#{preference}',
ng-disabled='#{unsubscribeFromAll} === true',
ng-checked='#{unsubscribeFromAll} === false && #{preference} === true',
ng-change='set({"preferences.emailNotifications.#{notification}": #{preference} ? true: false})')
span=env.t(notification)
hr
.checkbox
label
input(type='checkbox', ng-model='user.preferences.emailNotifications.unsubscribeFromAll', ng-change='set({"preferences.emailNotifications.unsubscribeFromAll": user.preferences.emailNotifications.unsubscribeFromAll ? true: false})')
span=env.t('unsubscribeAllEmails')
small=env.t('unsubscribeAllEmailsText')
script(id='partials/options.settings.subscription.html',type='text/ng-template')
//-h2=env.t('individualSub')
.container-fluid(ng-init='_subscription={key:"basic_earned"}')
.row
.col-md-6
h3= env.t('benefits')
+subPerks()
.col-md-6
table.table.alert.alert-info(ng-if='user.purchased.plan.customerId')
tr(ng-if='user.purchased.plan.dateTerminated'): td.alert.alert-warning
i.glyphicon.glyphicon-time
| #{env.t('subCanceled')} <strong>{{moment(user.purchased.plan.dateTerminated).format('MM/DD/YYYY')}}</strong>
tr(ng-if='!user.purchased.plan.dateTerminated'): td
h4=env.t('subscribed')
p(ng-if='user.purchased.plan.planId') Recurring ${{Content.subscriptionBlocks[user.purchased.plan.planId].price}} each {{Content.subscriptionBlocks[user.purchased.plan.planId].months}} Month(s) ({{user.purchased.plan.paymentMethod}})
tr(ng-if='user.purchased.plan.extraMonths'): td
span.glyphicon.glyphicon-credit-card
| You have {{user.purchased.plan.extraMonths | number:2}} months of subscription credit.
tr(ng-if='user.purchased.plan.consecutive.count || user.purchased.plan.consecutive.offset'): td
span.glyphicon.glyphicon-forward
| &nbsp;Consecutive Subscription
ul.list-unstyled
li Consecutive Months: {{user.purchased.plan.consecutive.count + user.purchased.plan.consecutive.offset}}
li Gem Cap Extra: {{user.purchased.plan.consecutive.gemCapExtra}}
li Mystic Hourglasses: {{user.purchased.plan.consecutive.trinkets}}
div(ng-if='!user.purchased.plan.customerId || (user.purchased.plan.customerId && user.purchased.plan.dateTerminated)')
.form-group
.radio(ng-repeat='block in Content.subscriptionBlocks | toArray | omit: "discount==true" | orderBy:"months"')
label
input(type="radio", name="subRadio", ng-value="block.key", ng-model='_subscription.key')
span(ng-show='block.original')
span.label.label-success.line-through
| ${{:: block.original }}
=env.t('subscriptionRateText', {price:'{{::block.price}}', months: '{{::block.months}}'})
span(ng-hide='block.original')
=env.t('subscriptionRateText', {price: '{{::block.price}}', months: '{{block.months}}'})
.form-inline
.form-group
input.form-control(type='text', ng-model='_subscription.coupon', placeholder= env.t('couponPlaceholder'))
.form-group
button.btn.btn-small(type='button',ng-click='applyCoupon(_subscription.coupon)')= env.t("apply")
h3(ng-if='(user.purchased.plan.customerId && user.purchased.plan.dateTerminated)')= env.t("resubscribe")
a.btn.btn-primary(ng-click='Payments.showStripe({subscription:_subscription.key, coupon:_subscription.coupon})', ng-disabled='!_subscription.key')= env.t('card')
a.btn.btn-warning(href='/paypal/subscribe?_id={{user._id}}&apiToken={{user.apiToken}}&sub={{_subscription.key}}{{_subscription.coupon ? "&coupon="+_subscription.coupon : ""}}', ng-disabled='!_subscription.key') PayPal
a.btn.btn-default(ng-click="Payments.amazonPayments.init({type: 'subscription', subscription:_subscription.key, coupon:_subscription.coupon})") Amazon Payments
div(ng-if='user.purchased.plan.customerId')
.btn.btn-primary(ng-if='!user.purchased.plan.dateTerminated && user.purchased.plan.paymentMethod=="Stripe"', ng-click='Payments.showStripeEdit()')=env.t('subUpdateCard')
.btn.btn-sm.btn-danger(ng-if='!user.purchased.plan.dateTerminated', ng-click='Payments.cancelSubscription()')=env.t('cancelSub')