From 3fa3b491dc8ce0d4235aa7aaa660dd8940a8a843 Mon Sep 17 00:00:00 2001 From: carolstone Date: Fri, 17 Jul 2015 21:17:07 -0400 Subject: [PATCH 01/13] 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. --- common/script/index.coffee | 12 ++++++++++++ website/public/js/controllers/settingsCtrl.js | 17 ++++++++++++++--- website/views/options/settings.jade | 4 ++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index 789ba7ecae..af7f1efe3d 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -349,6 +349,18 @@ Friendly timestamp ### api.friendlyTimestamp = (timestamp) -> moment(timestamp).format('MM/DD h:mm:ss a') +### +ISO timestamp +### +api.isoTimestamp = (timestamp) -> moment(timestamp).toISOString() + +### +plain timestamp +### +api.momentTimestamp = (timestamp) -> moment(timestamp) + + + ### Does user have new chat messages? ### diff --git a/website/public/js/controllers/settingsCtrl.js b/website/public/js/controllers/settingsCtrl.js index 5c83b5756c..c59fe7bb3b 100644 --- a/website/public/js/controllers/settingsCtrl.js +++ b/website/public/js/controllers/settingsCtrl.js @@ -66,12 +66,23 @@ habitrpg.controller('SettingsCtrl', User.set({'flags.newStuff':true}); } - $scope.saveDayStart = function(){ - var dayStart = +User.user.preferences.dayStart; - if (_.isNaN(dayStart) || dayStart < 0 || dayStart > 24) { + $scope.passDayStart = User.user.preferences.dayStart; + + $scope.saveDayStart = function(newDayStart){ + var oldDayStart = User.user.preferences.dayStart; + var dayStart = newDayStart; + var lastCron = User.user.lastCron; + var getOldStart = Shared.startOfDay({ dayStart: oldDayStart}); + var getNewStart = Shared.startOfDay({ dayStart: dayStart}); + var isoNewStart = Shared.isoTimestamp(getNewStart); + + if (dayStart == undefined || _.isNaN(dayStart) || dayStart < 0 || dayStart > 24) { dayStart = 0; return alert(window.env.t('enterNumber')); } + if (Shared.momentTimestamp(getOldStart) <= Shared.momentTimestamp(lastCron) && Shared.momentTimestamp(lastCron) < Shared.momentTimestamp(getNewStart)) { + User.set({ 'lastCron' : isoNewStart}); + } User.set({'preferences.dayStart': dayStart}); } diff --git a/website/views/options/settings.jade b/website/views/options/settings.jade index 8aafb9529f..9b7ffb8628 100644 --- a/website/views/options/settings.jade +++ b/website/views/options/settings.jade @@ -83,7 +83,7 @@ script(type='text/ng-template', id='partials/options.settings.settings.html') h5(ng-if='showCustomDayStartInfo')!=env.t('customDayStartInfo4') .form-group .input-group - input.form-control(type='number', min='0', max='23', ng-model='user.preferences.dayStart', ng-blur='saveDayStart()') + 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 @@ -270,7 +270,7 @@ script(id='partials/options.settings.notifications.html', type="text/ng-template =env.t('emailNotifications') .panel-body - each notification in ['newPM', 'wonChallenge', 'giftedGems', 'giftedSubscription', 'invitedParty', 'invitedGuild', 'kickedGroup', 'questStarted', 'invitedQuest', 'inactivityEmails', 'weeklyRecaps'] + 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' From 9fe96b7f9454a7f571e5032ef362b863abb9f357 Mon Sep 17 00:00:00 2001 From: carolstone Date: Wed, 5 Aug 2015 22:47:45 -0400 Subject: [PATCH 02/13] Renamed variables for clarity. Moved calculation to actually change lastcron into its own function. Changed validation errormessage to run: if ( dayStart != Math.floor(dayStart) || dayStart < 0 || dayStart > 24 ) {error message}. Created new calculation for daystart because daystart could never be future to the current timestamp. This "fix" has broken the whole endeavor, though, because cron runs immedately when newlastcron > now and now > oldlastcron. --- common/script/index.coffee | 7 ++++ website/public/js/controllers/settingsCtrl.js | 33 +++++++++++-------- website/views/options/settings.jade | 2 +- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index af7f1efe3d..52c37eaf26 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -66,6 +66,13 @@ api.startOfDay = (options={}) -> dayStart.subtract({days:1}) dayStart + +api.startOfDayAllowsFuture = (options={}) -> + # Use this version to use if you need the result even if the offset would cause today's day start to be in the future. + o = sanitizeOptions(options) + moment(o.now).startOf('day').add({hours:o.dayStart}) + + api.dayMapping = {0:'su',1:'m',2:'t',3:'w',4:'th',5:'f',6:'s'} ### diff --git a/website/public/js/controllers/settingsCtrl.js b/website/public/js/controllers/settingsCtrl.js index c59fe7bb3b..4632f13c95 100644 --- a/website/public/js/controllers/settingsCtrl.js +++ b/website/public/js/controllers/settingsCtrl.js @@ -66,24 +66,31 @@ habitrpg.controller('SettingsCtrl', User.set({'flags.newStuff':true}); } - $scope.passDayStart = User.user.preferences.dayStart; + $scope.dayStart = User.user.preferences.dayStart; - $scope.saveDayStart = function(newDayStart){ - var oldDayStart = User.user.preferences.dayStart; - var dayStart = newDayStart; + function updateLastCron(oldDayStart, newDayStart){ + var getOldStart = Shared.startOfDayAllowsFuture({ dayStart: oldDayStart}); + var getNewStart = Shared.startOfDayAllowsFuture({ dayStart: newDayStart}); var lastCron = User.user.lastCron; - var getOldStart = Shared.startOfDay({ dayStart: oldDayStart}); - var getNewStart = Shared.startOfDay({ dayStart: dayStart}); + var momentLastCron = Shared.momentTimestamp(lastCron); var isoNewStart = Shared.isoTimestamp(getNewStart); - - if (dayStart == undefined || _.isNaN(dayStart) || dayStart < 0 || dayStart > 24) { - dayStart = 0; - return alert(window.env.t('enterNumber')); - } - if (Shared.momentTimestamp(getOldStart) <= Shared.momentTimestamp(lastCron) && Shared.momentTimestamp(lastCron) < Shared.momentTimestamp(getNewStart)) { + alert('Times are oldstart'+Shared.friendlyTimestamp(getOldStart)+' lastcron '+Shared.friendlyTimestamp(lastCron)+' and newstart '+Shared.friendlyTimestamp(getNewStart)); + if (getOldStart < momentLastCron && momentLastCron < getNewStart) { + alert('Setting lastcron to '+Shared.friendlyTimestamp(getNewStart)); User.set({ 'lastCron' : isoNewStart}); } - User.set({'preferences.dayStart': dayStart}); + }; + + $scope.saveDayStart = function(varDayStart){ + var oldDayStart = User.user.preferences.dayStart; + var newDayStart = varDayStart; + + if ( newDayStart != Math.floor(newDayStart) || newDayStart < 0 || newDayStart > 24 ) { + newDayStart = 0; + return alert(window.env.t('enterNumber')); + } + updateLastCron( oldDayStart, newDayStart); + User.set({'preferences.dayStart': Math.floor(newDayStart)}); } $scope.language = window.env.language; diff --git a/website/views/options/settings.jade b/website/views/options/settings.jade index 9b7ffb8628..483955da67 100644 --- a/website/views/options/settings.jade +++ b/website/views/options/settings.jade @@ -83,7 +83,7 @@ script(type='text/ng-template', id='partials/options.settings.settings.html') 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)') + input.form-control(type='number', min='0', max='23', ng-model='dayStart', ng-blur='saveDayStart(dayStart)') span.input-group-addon= ':00 (' + env.t('24HrClock') + ')' .personal-options.col-md-6 From 310bb3dfd92740c0abb87ae5f69608932807431f Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 5 Sep 2015 09:39:30 -0500 Subject: [PATCH 03/13] Format settings page --- website/views/options/settings.jade | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/website/views/options/settings.jade b/website/views/options/settings.jade index ebd3db8df8..ad5bdf7c7e 100644 --- a/website/views/options/settings.jade +++ b/website/views/options/settings.jade @@ -39,9 +39,14 @@ script(type='text/ng-template', id='partials/options.settings.settings.html') strong !=env.t('helpWithTranslation') + hr + .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})') + + hr + .checkbox label input(type='checkbox', ng-click='hideHeader() ', ng-checked='user.preferences.hideHeader!==true') @@ -71,19 +76,24 @@ script(type='text/ng-template', id='partials/options.settings.settings.html') 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') + + hr + 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') - div.alert.alert-warning(style='padding:2px;margin-top:7px') - h5=env.t('customDayStart') + hr + + h5=env.t('customDayStart') + .alert.alert-warning 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='dayStart', ng-blur='saveDayStart(dayStart)') - span.input-group-addon= ':00 (' + env.t('24HrClock') + ')' + .form-group + .input-group + input.form-control(type='number', min='0', max='23', ng-model='dayStart', ng-blur='saveDayStart(dayStart)') + span.input-group-addon= ':00 (' + env.t('24HrClock') + ')' .personal-options.col-md-6 .panel.panel-default From d45602c3404bb24792e5f77be616a745787a1ab8 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 5 Sep 2015 09:45:08 -0500 Subject: [PATCH 04/13] Adjust spacing --- website/public/js/controllers/settingsCtrl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/public/js/controllers/settingsCtrl.js b/website/public/js/controllers/settingsCtrl.js index 4e6bfb7268..fcb41a57ab 100644 --- a/website/public/js/controllers/settingsCtrl.js +++ b/website/public/js/controllers/settingsCtrl.js @@ -77,7 +77,7 @@ habitrpg.controller('SettingsCtrl', } }; - $scope.saveDayStart = function(varDayStart){ + $scope.saveDayStart = function(varDayStart) { var oldDayStart = User.user.preferences.dayStart; var newDayStart = varDayStart; From 9ce6144fa4804df8ca0a551bd0cf2c973a404844 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 5 Sep 2015 15:32:49 -0500 Subject: [PATCH 05/13] Adjustments to custom day start --- common/locales/en/settings.json | 3 + common/script/index.coffee | 19 --- test/spec/controllers/settingsCtrlSpec.js | 109 ++++++++++++++++++ website/public/js/controllers/settingsCtrl.js | 50 ++++---- website/views/options/settings.jade | 14 ++- website/views/shared/modals/index.jade | 4 + .../modals/settings/change-day-start.jade | 15 +++ 7 files changed, 170 insertions(+), 44 deletions(-) create mode 100644 test/spec/controllers/settingsCtrlSpec.js create mode 100644 website/views/shared/modals/settings/change-day-start.jade diff --git a/common/locales/en/settings.json b/common/locales/en/settings.json index 587055ae78..06ec86887b 100644 --- a/common/locales/en/settings.json +++ b/common/locales/en/settings.json @@ -39,6 +39,9 @@ "xml": "(XML)", "json": "(JSON)", "customDayStart": "Custom Day Start", + "changeCustomDayStart": "Change Custom Day Start?", + "sureChangeCustomDayStart": "Are you sure you want to change your custom day start?", + "nextCron": "WARNING: Your dailies will reset next on <%= time %>.", "24HrClock": "24Hr Clock", "customDayStartInfo1": "Habitica defaults to check and reset your Dailies at midnight in your own time zone each day. It is recommended that you read the following information before changing it: ", "customDayStartInfo4": "Complete all your Dailies before changing the Custom Day Start or Rest in the Inn that day. Changing your Custom Day Start may cause Cron to run immediately, but after the first day it works as expected.

Allow a window of two hours for the change to take effect. For example, if it is currently set to 0 (midnight), change it before 10pm; if you want to set it to 9pm, change it before 7pm.

Enter an hour from 0 to 23 (it uses a 24 hour clock). Typing is more effective than arrow keys. Once set, reload the page to confirm that the new value is being displayed.", diff --git a/common/script/index.coffee b/common/script/index.coffee index 2985dbfe43..f0dd2536fa 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -66,13 +66,6 @@ api.startOfDay = (options={}) -> dayStart.subtract({days:1}) dayStart - -api.startOfDayAllowsFuture = (options={}) -> - # Use this version to use if you need the result even if the offset would cause today's day start to be in the future. - o = sanitizeOptions(options) - moment(o.now).startOf('day').add({hours:o.dayStart}) - - api.dayMapping = {0:'su',1:'m',2:'t',3:'w',4:'th',5:'f',6:'s'} ### @@ -360,18 +353,6 @@ Friendly timestamp ### api.friendlyTimestamp = (timestamp) -> moment(timestamp).format('MM/DD h:mm:ss a') -### -ISO timestamp -### -api.isoTimestamp = (timestamp) -> moment(timestamp).toISOString() - -### -plain timestamp -### -api.momentTimestamp = (timestamp) -> moment(timestamp) - - - ### Does user have new chat messages? ### diff --git a/test/spec/controllers/settingsCtrlSpec.js b/test/spec/controllers/settingsCtrlSpec.js new file mode 100644 index 0000000000..33d3ffe601 --- /dev/null +++ b/test/spec/controllers/settingsCtrlSpec.js @@ -0,0 +1,109 @@ +'use strict'; + +describe('Settings Controller', function() { + var rootScope, scope, user, User, ctrl; + + beforeEach(function() { + module(function($provide) { + user = specHelper.newUser(); + User = { + set: sandbox.stub(), + user: user + }; + $provide.value('User', User); + $provide.value('Guide', sandbox.stub()); + }); + + inject(function(_$rootScope_, _$controller_) { + scope = _$rootScope_.$new(); + rootScope = _$rootScope_; + + // Load RootCtrl to ensure shared behaviors are loaded + _$controller_('RootCtrl', {$scope: scope, User: User}); + + ctrl = _$controller_('SettingsCtrl', {$scope: scope, User: User}); + }); + }); + + describe('#openDayStartModal', function() { + beforeEach(function() { + sandbox.stub(rootScope, 'openModal'); + sandbox.stub(window, 'alert'); + }); + + context('failures', function() { + var tests = { + 'blank': '', + 'not a whole number': 5.3, + 'not a number': 'foo', + 'less than 0': -5, + 'more than 24': 25 + }; + + for (var test in tests) { + it('returns with an alert if number is ' + test, function() { + scope.openDayStartModal(tests[test]); + + expect(rootScope.openModal).to.not.be.called; + expect(window.alert).to.be.calledOnce; + expect(window.alert).to.be.calledWith(env.t('enterNumber')); + }); + } + }); + + context('success', function() { + it('opens the day start modal', function() { + scope.openDayStartModal(5); + + expect(rootScope.openModal).to.be.calledOnce; + expect(rootScope.openModal).to.be.calledWith('change-day-start', {scope: scope}); + }); + + it('sets nextCron variable', function() { + expect(scope.nextCron).to.not.exist; + + scope.openDayStartModal(5); + + expect(scope.nextCron).to.exist; + }); + + it('calculates the next time cron will run', function() { + var fakeCurrentTime = new Date(2013, 3, 1, 3, 12).getTime(); + var expectedTime = new Date(2013, 3, 1, 5, 0, 0).getTime(); + sandbox.useFakeTimers(fakeCurrentTime); + + scope.openDayStartModal(5); + + expect(scope.nextCron).to.eq(expectedTime); + }); + + it('calculates the next time cron will run and adds a day if cron would have already passed', function() { + var fakeCurrentTime = new Date(2013, 3, 1, 8, 12).getTime(); + var expectedTime = new Date(2013, 3, 2, 5, 0, 0).getTime(); + sandbox.useFakeTimers(fakeCurrentTime); + + scope.openDayStartModal(5); + + expect(scope.nextCron).to.eq(expectedTime); + }); + }); + }); + + describe('#saveDayStart', function() { + + it('updates user\'s custom day start and last cron', function() { + + var fakeCurrentTime = new Date(2013, 3, 1, 8, 12).getTime(); + var expectedTime = fakeCurrentTime; + sandbox.useFakeTimers(fakeCurrentTime); + scope.dayStart = 5; + scope.saveDayStart(); + + expect(User.set).to.be.calledOnce; + expect(User.set).to.be.calledWith({ + 'preferences.dayStart': 5, + 'lastCron': expectedTime + }); + }); + }); +}); diff --git a/website/public/js/controllers/settingsCtrl.js b/website/public/js/controllers/settingsCtrl.js index fcb41a57ab..2d07e7cb45 100644 --- a/website/public/js/controllers/settingsCtrl.js +++ b/website/public/js/controllers/settingsCtrl.js @@ -64,30 +64,25 @@ habitrpg.controller('SettingsCtrl', $scope.dayStart = User.user.preferences.dayStart; - function updateLastCron(oldDayStart, newDayStart){ - var getOldStart = Shared.startOfDayAllowsFuture({ dayStart: oldDayStart}); - var getNewStart = Shared.startOfDayAllowsFuture({ dayStart: newDayStart}); - var lastCron = User.user.lastCron; - var momentLastCron = Shared.momentTimestamp(lastCron); - var isoNewStart = Shared.isoTimestamp(getNewStart); - alert('Times are oldstart'+Shared.friendlyTimestamp(getOldStart)+' lastcron '+Shared.friendlyTimestamp(lastCron)+' and newstart '+Shared.friendlyTimestamp(getNewStart)); - if (getOldStart < momentLastCron && momentLastCron < getNewStart) { - alert('Setting lastcron to '+Shared.friendlyTimestamp(getNewStart)); - User.set({ 'lastCron' : isoNewStart}); - } - }; + $scope.openDayStartModal = function(dayStart) { + var flooredDayStart = Math.floor(dayStart); - $scope.saveDayStart = function(varDayStart) { - var oldDayStart = User.user.preferences.dayStart; - var newDayStart = varDayStart; - - if ( newDayStart != Math.floor(newDayStart) || newDayStart < 0 || newDayStart > 24 ) { - newDayStart = 0; + if (dayStart !== flooredDayStart || dayStart < 0 || dayStart > 24 ) { return alert(window.env.t('enterNumber')); } - updateLastCron( oldDayStart, newDayStart); - User.set({'preferences.dayStart': Math.floor(newDayStart)}); - } + + $scope.dayStart = dayStart; + $scope.nextCron = _calculateNextCron(); + + $rootScope.openModal('change-day-start', { scope: $scope }); + }; + + $scope.saveDayStart = function() { + User.set({ + 'preferences.dayStart': Math.floor($scope.dayStart), + 'lastCron': +new Date + }); + }; $scope.language = window.env.language; $scope.avalaibleLanguages = window.env.avalaibleLanguages; @@ -210,5 +205,18 @@ habitrpg.controller('SettingsCtrl', subs["google_6mo"].discount = false; }); } + + function _calculateNextCron() { + $scope.dayStart; + + var nextCron = moment().hours($scope.dayStart).minutes(0).seconds(0).milliseconds(0); + + var currentHour = moment().format('H'); + if (currentHour >= $scope.dayStart) { + nextCron = nextCron.add(1, 'day');; + } + + return +nextCron.format('x'); + } } ]); diff --git a/website/views/options/settings.jade b/website/views/options/settings.jade index ad5bdf7c7e..039fe9f7a8 100644 --- a/website/views/options/settings.jade +++ b/website/views/options/settings.jade @@ -90,10 +90,16 @@ script(type='text/ng-template', id='partials/options.settings.settings.html') 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='dayStart', ng-blur='saveDayStart(dayStart)') - span.input-group-addon= ':00 (' + env.t('24HrClock') + ')' + .form-horizontal + .form-group + .col-sm-7 + .input-group + input.form-control(type='number', min='0', max='23', ng-model='dayStart') + .input-group-addon= ':00 (' + env.t('24HrClock') + ')' + + .col-sm-5 + br.visible-xs + button.btn.btn-block.btn-primary(ng-click='openDayStartModal(dayStart)') Save Custom Day Start .personal-options.col-md-6 .panel.panel-default diff --git a/website/views/shared/modals/index.jade b/website/views/shared/modals/index.jade index 8146882046..a70803cf49 100644 --- a/website/views/shared/modals/index.jade +++ b/website/views/shared/modals/index.jade @@ -14,3 +14,7 @@ include ./limited include ./invite-friends include ./welcome.jade include ./low-health.jade + +//- Settings +script(type='text/ng-template', id='modals/change-day-start.html') + include ./settings/change-day-start.jade diff --git a/website/views/shared/modals/settings/change-day-start.jade b/website/views/shared/modals/settings/change-day-start.jade new file mode 100644 index 0000000000..603b6b76c5 --- /dev/null +++ b/website/views/shared/modals/settings/change-day-start.jade @@ -0,0 +1,15 @@ +.text-center + .modal-header + h3=env.t('changeCustomDayStart') + + .modal-body + .alert.alert-danger + p=env.t('nextCron', {time: '{{nextCron | date: "M/d/yy \'@\' h:mm a"}}'}) + p=env.t('sureChangeCustomDayStart') + + .alert.alert-info + div last cron {{user.lastCron}} + + .modal-footer + a.btn.btn-default(ng-click='$close()')=env.t('close') + a.btn.btn-danger(ng-click='saveDayStart(); $close()')=env.t('confirm') From 3a8eda6c1a48d0d8797fe3b5b79a8b3a32173224 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 5 Sep 2015 15:35:07 -0500 Subject: [PATCH 06/13] Remove extraneous info about last cron --- website/views/shared/modals/settings/change-day-start.jade | 3 --- 1 file changed, 3 deletions(-) diff --git a/website/views/shared/modals/settings/change-day-start.jade b/website/views/shared/modals/settings/change-day-start.jade index 603b6b76c5..1e0e8dae31 100644 --- a/website/views/shared/modals/settings/change-day-start.jade +++ b/website/views/shared/modals/settings/change-day-start.jade @@ -7,9 +7,6 @@ p=env.t('nextCron', {time: '{{nextCron | date: "M/d/yy \'@\' h:mm a"}}'}) p=env.t('sureChangeCustomDayStart') - .alert.alert-info - div last cron {{user.lastCron}} - .modal-footer a.btn.btn-default(ng-click='$close()')=env.t('close') a.btn.btn-danger(ng-click='saveDayStart(); $close()')=env.t('confirm') From 085a785e4d28146f5853ad4aa5e294e8835cee59 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 6 Sep 2015 09:22:40 -0500 Subject: [PATCH 07/13] Convert input to select box --- website/public/js/controllers/settingsCtrl.js | 6 +++--- website/views/options/settings.jade | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/website/public/js/controllers/settingsCtrl.js b/website/public/js/controllers/settingsCtrl.js index 2d07e7cb45..f296f571ae 100644 --- a/website/public/js/controllers/settingsCtrl.js +++ b/website/public/js/controllers/settingsCtrl.js @@ -65,13 +65,13 @@ habitrpg.controller('SettingsCtrl', $scope.dayStart = User.user.preferences.dayStart; $scope.openDayStartModal = function(dayStart) { - var flooredDayStart = Math.floor(dayStart); + $scope.dayStart = +dayStart; + var flooredDayStart = Math.floor($scope.dayStart); - if (dayStart !== flooredDayStart || dayStart < 0 || dayStart > 24 ) { + if ($scope.dayStart !== flooredDayStart || $scope.dayStart < 0 || $scope.dayStart > 24 ) { return alert(window.env.t('enterNumber')); } - $scope.dayStart = dayStart; $scope.nextCron = _calculateNextCron(); $rootScope.openModal('change-day-start', { scope: $scope }); diff --git a/website/views/options/settings.jade b/website/views/options/settings.jade index 039fe9f7a8..bc19a2970a 100644 --- a/website/views/options/settings.jade +++ b/website/views/options/settings.jade @@ -91,11 +91,15 @@ script(type='text/ng-template', id='partials/options.settings.settings.html') a(ng-click='showCustomDayStartInfo = !showCustomDayStartInfo') {{!showCustomDayStartInfo ? env.t('showMoreMore') : env.t('showMoreLess')}} h5(ng-if='showCustomDayStartInfo')!=env.t('customDayStartInfo4') .form-horizontal + .form-group .col-sm-7 - .input-group - input.form-control(type='number', min='0', max='23', ng-model='dayStart') - .input-group-addon= ':00 (' + env.t('24HrClock') + ')' + select.form-control(ng-model='dayStart') + - var number = 0 + while number < 24 + - var hour = number++ % 12 + - var meridian = number < 12 ? 'AM' : 'PM' + option(value=number) #{hour ? hour : 12}:00 #{meridian} .col-sm-5 br.visible-xs From f1224bc6be329b50a6ee03697ccd79f569a83568 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 6 Sep 2015 09:36:29 -0500 Subject: [PATCH 08/13] Use select instead of an input for cds --- test/spec/controllers/settingsCtrlSpec.js | 67 ++++++------------- website/public/js/controllers/settingsCtrl.js | 6 -- website/views/options/settings.jade | 5 +- 3 files changed, 25 insertions(+), 53 deletions(-) diff --git a/test/spec/controllers/settingsCtrlSpec.js b/test/spec/controllers/settingsCtrlSpec.js index 33d3ffe601..2950b235d6 100644 --- a/test/spec/controllers/settingsCtrlSpec.js +++ b/test/spec/controllers/settingsCtrlSpec.js @@ -31,68 +31,45 @@ describe('Settings Controller', function() { sandbox.stub(window, 'alert'); }); - context('failures', function() { - var tests = { - 'blank': '', - 'not a whole number': 5.3, - 'not a number': 'foo', - 'less than 0': -5, - 'more than 24': 25 - }; + it('opens the day start modal', function() { + scope.openDayStartModal(5); - for (var test in tests) { - it('returns with an alert if number is ' + test, function() { - scope.openDayStartModal(tests[test]); - - expect(rootScope.openModal).to.not.be.called; - expect(window.alert).to.be.calledOnce; - expect(window.alert).to.be.calledWith(env.t('enterNumber')); - }); - } + expect(rootScope.openModal).to.be.calledOnce; + expect(rootScope.openModal).to.be.calledWith('change-day-start', {scope: scope}); }); - context('success', function() { - it('opens the day start modal', function() { - scope.openDayStartModal(5); + it('sets nextCron variable', function() { + expect(scope.nextCron).to.not.exist; - expect(rootScope.openModal).to.be.calledOnce; - expect(rootScope.openModal).to.be.calledWith('change-day-start', {scope: scope}); - }); + scope.openDayStartModal(5); - it('sets nextCron variable', function() { - expect(scope.nextCron).to.not.exist; + expect(scope.nextCron).to.exist; + }); - scope.openDayStartModal(5); + it('calculates the next time cron will run', function() { + var fakeCurrentTime = new Date(2013, 3, 1, 3, 12).getTime(); + var expectedTime = new Date(2013, 3, 1, 5, 0, 0).getTime(); + sandbox.useFakeTimers(fakeCurrentTime); - expect(scope.nextCron).to.exist; - }); + scope.openDayStartModal(5); - it('calculates the next time cron will run', function() { - var fakeCurrentTime = new Date(2013, 3, 1, 3, 12).getTime(); - var expectedTime = new Date(2013, 3, 1, 5, 0, 0).getTime(); - sandbox.useFakeTimers(fakeCurrentTime); + expect(scope.nextCron).to.eq(expectedTime); + }); - scope.openDayStartModal(5); + it('calculates the next time cron will run and adds a day if cron would have already passed', function() { + var fakeCurrentTime = new Date(2013, 3, 1, 8, 12).getTime(); + var expectedTime = new Date(2013, 3, 2, 5, 0, 0).getTime(); + sandbox.useFakeTimers(fakeCurrentTime); - expect(scope.nextCron).to.eq(expectedTime); - }); + scope.openDayStartModal(5); - it('calculates the next time cron will run and adds a day if cron would have already passed', function() { - var fakeCurrentTime = new Date(2013, 3, 1, 8, 12).getTime(); - var expectedTime = new Date(2013, 3, 2, 5, 0, 0).getTime(); - sandbox.useFakeTimers(fakeCurrentTime); - - scope.openDayStartModal(5); - - expect(scope.nextCron).to.eq(expectedTime); - }); + expect(scope.nextCron).to.eq(expectedTime); }); }); describe('#saveDayStart', function() { it('updates user\'s custom day start and last cron', function() { - var fakeCurrentTime = new Date(2013, 3, 1, 8, 12).getTime(); var expectedTime = fakeCurrentTime; sandbox.useFakeTimers(fakeCurrentTime); diff --git a/website/public/js/controllers/settingsCtrl.js b/website/public/js/controllers/settingsCtrl.js index f296f571ae..a61eb3bd31 100644 --- a/website/public/js/controllers/settingsCtrl.js +++ b/website/public/js/controllers/settingsCtrl.js @@ -66,12 +66,6 @@ habitrpg.controller('SettingsCtrl', $scope.openDayStartModal = function(dayStart) { $scope.dayStart = +dayStart; - var flooredDayStart = Math.floor($scope.dayStart); - - if ($scope.dayStart !== flooredDayStart || $scope.dayStart < 0 || $scope.dayStart > 24 ) { - return alert(window.env.t('enterNumber')); - } - $scope.nextCron = _calculateNextCron(); $rootScope.openModal('change-day-start', { scope: $scope }); diff --git a/website/views/options/settings.jade b/website/views/options/settings.jade index bc19a2970a..b02eaf92b2 100644 --- a/website/views/options/settings.jade +++ b/website/views/options/settings.jade @@ -97,9 +97,10 @@ script(type='text/ng-template', id='partials/options.settings.settings.html') select.form-control(ng-model='dayStart') - var number = 0 while number < 24 - - var hour = number++ % 12 + - var value = number - var meridian = number < 12 ? 'AM' : 'PM' - option(value=number) #{hour ? hour : 12}:00 #{meridian} + - var hour = number++ % 12 + option(value=value) #{hour ? hour : 12}:00 #{meridian} .col-sm-5 br.visible-xs From a44cd748af81058812afd57deca6e70ab4a8c466 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 6 Sep 2015 09:42:48 -0500 Subject: [PATCH 09/13] Use the user's preferred date format --- website/views/shared/modals/settings/change-day-start.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/views/shared/modals/settings/change-day-start.jade b/website/views/shared/modals/settings/change-day-start.jade index 1e0e8dae31..af9248b1f3 100644 --- a/website/views/shared/modals/settings/change-day-start.jade +++ b/website/views/shared/modals/settings/change-day-start.jade @@ -4,7 +4,7 @@ .modal-body .alert.alert-danger - p=env.t('nextCron', {time: '{{nextCron | date: "M/d/yy \'@\' h:mm a"}}'}) + p=env.t('nextCron', {time: '{{nextCron | date: user.preferences.dateFormat + " @ h:mm a"}}'}) p=env.t('sureChangeCustomDayStart') .modal-footer From 0508f77ed4937cd0d475fc21c17ba1ee21dc07be Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 6 Sep 2015 09:45:12 -0500 Subject: [PATCH 10/13] Change wording of cds modal message --- common/locales/en/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/locales/en/settings.json b/common/locales/en/settings.json index 06ec86887b..4eb0af141c 100644 --- a/common/locales/en/settings.json +++ b/common/locales/en/settings.json @@ -41,7 +41,7 @@ "customDayStart": "Custom Day Start", "changeCustomDayStart": "Change Custom Day Start?", "sureChangeCustomDayStart": "Are you sure you want to change your custom day start?", - "nextCron": "WARNING: Your dailies will reset next on <%= time %>.", + "nextCron": "Your Dailies will next reset the first time you use Habitica after <%= time %>. Make sure you have completed your Dailies before this time!", "24HrClock": "24Hr Clock", "customDayStartInfo1": "Habitica defaults to check and reset your Dailies at midnight in your own time zone each day. It is recommended that you read the following information before changing it: ", "customDayStartInfo4": "Complete all your Dailies before changing the Custom Day Start or Rest in the Inn that day. Changing your Custom Day Start may cause Cron to run immediately, but after the first day it works as expected.

Allow a window of two hours for the change to take effect. For example, if it is currently set to 0 (midnight), change it before 10pm; if you want to set it to 9pm, change it before 7pm.

Enter an hour from 0 to 23 (it uses a 24 hour clock). Typing is more effective than arrow keys. Once set, reload the page to confirm that the new value is being displayed.", From 074e683ba728cbd4ae5f81b4b716db8ecd45204b Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 6 Sep 2015 09:57:44 -0500 Subject: [PATCH 11/13] Change formatting of cds modal --- website/views/shared/modals/settings/change-day-start.jade | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/website/views/shared/modals/settings/change-day-start.jade b/website/views/shared/modals/settings/change-day-start.jade index af9248b1f3..8dfa3abb63 100644 --- a/website/views/shared/modals/settings/change-day-start.jade +++ b/website/views/shared/modals/settings/change-day-start.jade @@ -3,10 +3,9 @@ h3=env.t('changeCustomDayStart') .modal-body - .alert.alert-danger - p=env.t('nextCron', {time: '{{nextCron | date: user.preferences.dateFormat + " @ h:mm a"}}'}) - p=env.t('sureChangeCustomDayStart') + p!=env.t('nextCron', {time: '{{::nextCron | date: user.preferences.dateFormat + " @ h:mm a"}}'}) .modal-footer + p.pull-left-sm=env.t('sureChangeCustomDayStart') a.btn.btn-default(ng-click='$close()')=env.t('close') - a.btn.btn-danger(ng-click='saveDayStart(); $close()')=env.t('confirm') + a.btn.btn-primary(ng-click='saveDayStart(); $close()')=env.t('confirm') From ee50fec2c1bc59874a305dc4ef062120eca1cb37 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 6 Sep 2015 10:11:28 -0500 Subject: [PATCH 12/13] Tweak wording of custom day start warning --- common/locales/en/settings.json | 4 +--- website/views/options/settings.jade | 7 ++----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/common/locales/en/settings.json b/common/locales/en/settings.json index 4eb0af141c..10026384f6 100644 --- a/common/locales/en/settings.json +++ b/common/locales/en/settings.json @@ -42,9 +42,7 @@ "changeCustomDayStart": "Change Custom Day Start?", "sureChangeCustomDayStart": "Are you sure you want to change your custom day start?", "nextCron": "Your Dailies will next reset the first time you use Habitica after <%= time %>. Make sure you have completed your Dailies before this time!", - "24HrClock": "24Hr Clock", - "customDayStartInfo1": "Habitica defaults to check and reset your Dailies at midnight in your own time zone each day. It is recommended that you read the following information before changing it: ", - "customDayStartInfo4": "Complete all your Dailies before changing the Custom Day Start or Rest in the Inn that day. Changing your Custom Day Start may cause Cron to run immediately, but after the first day it works as expected.

Allow a window of two hours for the change to take effect. For example, if it is currently set to 0 (midnight), change it before 10pm; if you want to set it to 9pm, change it before 7pm.

Enter an hour from 0 to 23 (it uses a 24 hour clock). Typing is more effective than arrow keys. Once set, reload the page to confirm that the new value is being displayed.", + "customDayStartInfo1": "Habitica defaults to check and reset your Dailies at midnight in your own time zone each day. You can customize that time here.", "misc": "Misc", "showHeader": "Show Header", "changePass": "Change Password", diff --git a/website/views/options/settings.jade b/website/views/options/settings.jade index b02eaf92b2..beb0895604 100644 --- a/website/views/options/settings.jade +++ b/website/views/options/settings.jade @@ -86,12 +86,9 @@ script(type='text/ng-template', id='partials/options.settings.settings.html') hr h5=env.t('customDayStart') - .alert.alert-warning - h5=env.t('customDayStartInfo1') - a(ng-click='showCustomDayStartInfo = !showCustomDayStartInfo') {{!showCustomDayStartInfo ? env.t('showMoreMore') : env.t('showMoreLess')}} - h5(ng-if='showCustomDayStartInfo')!=env.t('customDayStartInfo4') - .form-horizontal + alert.alert-warning=env.t('customDayStartInfo1') + .form-horizontal .form-group .col-sm-7 select.form-control(ng-model='dayStart') From 346440d32c55ade8b861cd49a1da51a3ff570502 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 6 Sep 2015 10:14:44 -0500 Subject: [PATCH 13/13] Disable cds button if cds == user's preference --- website/views/options/settings.jade | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/website/views/options/settings.jade b/website/views/options/settings.jade index beb0895604..c2445a04a8 100644 --- a/website/views/options/settings.jade +++ b/website/views/options/settings.jade @@ -101,7 +101,9 @@ script(type='text/ng-template', id='partials/options.settings.settings.html') .col-sm-5 br.visible-xs - button.btn.btn-block.btn-primary(ng-click='openDayStartModal(dayStart)') Save Custom Day Start + button.btn.btn-block.btn-primary(ng-click='openDayStartModal(dayStart)', + ng-disabled='dayStart == user.preferences.dayStart') + | Save Custom Day Start .personal-options.col-md-6 .panel.panel-default