From 60c622f1c17ec598554edfdc4e74a6d2f8cb3087 Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Sun, 22 Dec 2013 08:32:39 -0600 Subject: [PATCH 01/41] Initial commit: unlock notification, new modals --- public/js/services/guideServices.js | 5 +++- src/models/user.js | 6 +++-- views/shared/modals/index.jade | 3 ++- views/shared/modals/rebirth.jade | 38 +++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 views/shared/modals/rebirth.jade diff --git a/public/js/services/guideServices.js b/public/js/services/guideServices.js index 3535086828..d90db16475 100644 --- a/public/js/services/guideServices.js +++ b/public/js/services/guideServices.js @@ -139,7 +139,10 @@ angular.module('guideServices', []). } }); - + $rootScope.$watch('user.flags.rebirthEnabled', function(after, before) { + if (alreadyShown(before, after)) return; + $rootScope.modals.rebirthEnabled = true; + }); /** diff --git a/src/models/user.js b/src/models/user.js index 6fdd789e55..d47530cfec 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -45,7 +45,8 @@ var UserSchema = new Schema({ veteran: Boolean, snowball: Number, streak: Number, - challenges: Array + challenges: Array, + rebirth: Array }, auth: { facebook: Schema.Types.Mixed, @@ -94,7 +95,8 @@ var UserSchema = new Schema({ partyEnabled: Boolean, // FIXME do we need this? contributor: Boolean, classSelected: {type: Boolean, 'default': false}, - mathUpdates: Boolean + mathUpdates: Boolean, + rebirthEnabled: {type: Boolean, 'default': false} }, history: { exp: Array, // [{date: Date, value: Number}], // big peformance issues if these are defined diff --git a/views/shared/modals/index.jade b/views/shared/modals/index.jade index 339424984e..d8b098ac8a 100644 --- a/views/shared/modals/index.jade +++ b/views/shared/modals/index.jade @@ -7,4 +7,5 @@ include ./buy-gems include ./members include ./settings include ./pets -include ./classes \ No newline at end of file +include ./classes +include ./rebirth diff --git a/views/shared/modals/rebirth.jade b/views/shared/modals/rebirth.jade new file mode 100644 index 0000000000..1a65ec1a6b --- /dev/null +++ b/views/shared/modals/rebirth.jade @@ -0,0 +1,38 @@ +// Created by Sabe on 12/22/13. + +div(modal='modals.rebirthEnabled') + .modal-header + h3 Rebirth: New Adventure Available! + .modal-body + p + span. + You've unlocked Rebirth! This special Market item allows you to begin a new game at level 1 while keeping your tasks, achievements, pets, and more. Use it to breathe new life into HabitRPG if you feel you've achieved it all, or to experience new features with the fresh eyes of a beginning character! + .modal-footer + button.btn.btn-default.cancel(ng-click='modals.rebirthEnabled = false') Close + +div(modal='modals.rebirth') + .modal-header + h3 Rebirth: Begin a New Adventure + .modal-body + include ../gems + p. + Rebirth sets your game to a starting state, as if you'd created a new account, but keeps your most hard-earned or paid-for items intact. When you are reborn: + ul + li You become a Level 1 Warrior with full Health but no Experience. You may choose a new class at Level 10 as normal. + li You lose all Gold and all purchased equipment. + li Your tasks are reset to neutral (yellow color), but their history remains. + li Your Dailies' streaks are reset to 0. + li You keep your Achievements, your Gems, your backer and contributor tiers, and any purchased avatar customizations, such as hair styles. + li You keep whatever Challenges, Guilds, and Party you are a member of. + li You keep your Pets and Mounts, though you will not be able to access them until you unlock the Stable again. + li You earn an Achievement for beginning a new adventure! + p. + Consider using this feature if you would like to replay the early game with Habit's newest features, or if your motivation drops when you've attained all the best gear! + .modal-footer + button.btn.btn-large.cancel(ng-click='modals.rebirth = false') Never mind + span(ng-if='user.balance < 1') + a.btn.btn-success.btn-large(ng-click="modals.buyGems = true") Buy More Gems + span.gem-cost Not enough Gems + span(ng-if='user.balance >= 1', ng-controller='SettingsCtrl') + a.btn.btn-danger.btn-large(ng-click='rebirth()') Be Reborn + span.gem-cost 8 Gems From cc3632b6115f17831a249aa2ec721fbc98af2061 Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Tue, 24 Dec 2013 09:57:04 -0600 Subject: [PATCH 02/41] Add Orb of Rebirth to shop, image to modals, tweak modal text --- views/options/inventory/inventory.jade | 5 +++++ views/shared/modals/rebirth.jade | 12 +++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/views/options/inventory/inventory.jade b/views/options/inventory/inventory.jade index 0e2e0143b2..fb7cc9fc77 100644 --- a/views/options/inventory/inventory.jade +++ b/views/options/inventory/inventory.jade @@ -122,3 +122,8 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html') p | {{Content.spells.special.snowball.value}} span.Pet_Currency_Gem1x.inline-gems + div(ng-show='user.flags.rebirthEnabled') + button.customize-option(popover='Begin a new character at Level 1 while retaining achievements, collectibles, and tasks with history.', popover-title='Orb of Rebirth', popover-trigger='mouseenter', popover-placement='left', ng-click='modals.rebirth = true', class='rebirth_orb') + p + | 8 + span.Pet_Currency_Gem1x.inline-gems diff --git a/views/shared/modals/rebirth.jade b/views/shared/modals/rebirth.jade index 1a65ec1a6b..a975f957ff 100644 --- a/views/shared/modals/rebirth.jade +++ b/views/shared/modals/rebirth.jade @@ -4,6 +4,7 @@ div(modal='modals.rebirthEnabled') .modal-header h3 Rebirth: New Adventure Available! .modal-body + .rebirth_orb.pull-left(style='margin-right: 5px') p span. You've unlocked Rebirth! This special Market item allows you to begin a new game at level 1 while keeping your tasks, achievements, pets, and more. Use it to breathe new life into HabitRPG if you feel you've achieved it all, or to experience new features with the fresh eyes of a beginning character! @@ -15,9 +16,10 @@ div(modal='modals.rebirth') h3 Rebirth: Begin a New Adventure .modal-body include ../gems - p. - Rebirth sets your game to a starting state, as if you'd created a new account, but keeps your most hard-earned or paid-for items intact. When you are reborn: - ul + .rebirth_orb.pull-left(style='margin-right: 5px') + p Rebirth sets your game to a starting state, as if you'd created a new account, but keeps your most hard-earned or paid-for items intact. + br + .unordered li You become a Level 1 Warrior with full Health but no Experience. You may choose a new class at Level 10 as normal. li You lose all Gold and all purchased equipment. li Your tasks are reset to neutral (yellow color), but their history remains. @@ -26,8 +28,8 @@ div(modal='modals.rebirth') li You keep whatever Challenges, Guilds, and Party you are a member of. li You keep your Pets and Mounts, though you will not be able to access them until you unlock the Stable again. li You earn an Achievement for beginning a new adventure! - p. - Consider using this feature if you would like to replay the early game with Habit's newest features, or if your motivation drops when you've attained all the best gear! + br + p Use this feature to replay the early game with Habit's newest features, or to bring back the motivation of equipment Rewards when you have it all! .modal-footer button.btn.btn-large.cancel(ng-click='modals.rebirth = false') Never mind span(ng-if='user.balance < 1') From 3b94b18bb6acb19a5146e0982a2ad47083684ae6 Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Tue, 24 Dec 2013 18:09:32 -0600 Subject: [PATCH 03/41] Implement Rebirth in controllers and API, revise modal per @wc8 feedback --- public/js/controllers/settingsCtrl.js | 6 ++++++ src/routes/apiv2.js | 3 ++- views/shared/modals/rebirth.jade | 29 ++++++++++++++++----------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/public/js/controllers/settingsCtrl.js b/public/js/controllers/settingsCtrl.js index 0efd6504c1..8ad6419a14 100644 --- a/public/js/controllers/settingsCtrl.js +++ b/public/js/controllers/settingsCtrl.js @@ -59,6 +59,12 @@ habitrpg.controller('SettingsCtrl', $rootScope.$state.go('tasks'); } + $scope.rebirth = function(){ + User.user.ops.rebirth({}); + $rootScope.modals.rebirth = false; + $rootScope.$state.go('tasks'); + } + $scope.changePassword = function(changePass){ if (!changePass.oldPassword || !changePass.newPassword || !changePass.confirmNewPassword) { return alert("Please fill out all fields"); diff --git a/src/routes/apiv2.js b/src/routes/apiv2.js index b80c092c3a..8c7ca55742 100644 --- a/src/routes/apiv2.js +++ b/src/routes/apiv2.js @@ -62,7 +62,8 @@ router['delete']('/user', auth.auth, user['delete']); router.post('/user/revive', auth.auth, cron, user.revive); // Shared.ops router.post('/user/reroll', auth.auth, cron, user.reroll); // Shared.ops router.post('/user/reset', auth.auth, user.reset); // Shared.ops -router.post('/user/sleep', auth.auth, cron, user.sleep); //Shared.opss +router.post('/user/sleep', auth.auth, cron, user.sleep); //Shared.ops +router.post('/user/rebirth', auth.auth, cron, user.rebirth); //Shared.ops router.post('/user/class/change', auth.auth, cron, user.changeClass); //Shared.ops | query={class} router.post('/user/class/allocate', auth.auth, cron, user.allocate); //Shared.ops | query={stat} diff --git a/views/shared/modals/rebirth.jade b/views/shared/modals/rebirth.jade index a975f957ff..0139276afd 100644 --- a/views/shared/modals/rebirth.jade +++ b/views/shared/modals/rebirth.jade @@ -17,24 +17,29 @@ div(modal='modals.rebirth') .modal-body include ../gems .rebirth_orb.pull-left(style='margin-right: 5px') - p Rebirth sets your game to a starting state, as if you'd created a new account, but keeps your most hard-earned or paid-for items intact. + p Rebirth starts your character over from Level 1, as if you had created a new account. br + p Your adventure begins anew with a clean slate: .unordered - li You become a Level 1 Warrior with full Health but no Experience. You may choose a new class at Level 10 as normal. - li You lose all Gold and all purchased equipment. - li Your tasks are reset to neutral (yellow color), but their history remains. - li Your Dailies' streaks are reset to 0. - li You keep your Achievements, your Gems, your backer and contributor tiers, and any purchased avatar customizations, such as hair styles. - li You keep whatever Challenges, Guilds, and Party you are a member of. - li You keep your Pets and Mounts, though you will not be able to access them until you unlock the Stable again. - li You earn an Achievement for beginning a new adventure! + li You return to full Health. + li You have no Experience, Gold, or equipment. + li Your Habits, Dailies, and To-Dos reset to yellow, and streaks reset. + li You have the starting class of Warrior until you earn a new class. br - p Use this feature to replay the early game with Habit's newest features, or to bring back the motivation of equipment Rewards when you have it all! + p Your new character inherits a few things from their predecessor: + .unordered + li Tasks, history, and settings remain. + li Challenge, Guild, and Party memberships remain. + li Gems, backer tiers, and contributor levels remain. + li Items obtained from Gems or drops (such as pets and mounts) remain, though you cannot access them until you unlock them again. + br + .achievement-sun.pull-left(style='margin-right: 5px') + p You also earn an Achievement for beginning a new adventure! .modal-footer button.btn.btn-large.cancel(ng-click='modals.rebirth = false') Never mind - span(ng-if='user.balance < 1') + span(ng-if='user.balance < 2') a.btn.btn-success.btn-large(ng-click="modals.buyGems = true") Buy More Gems span.gem-cost Not enough Gems - span(ng-if='user.balance >= 1', ng-controller='SettingsCtrl') + span(ng-if='user.balance >= 2', ng-controller='SettingsCtrl') a.btn.btn-danger.btn-large(ng-click='rebirth()') Be Reborn span.gem-cost 8 Gems From f38b8e41af1f792f55b1e923a0f5ba49de44a0b3 Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Wed, 25 Dec 2013 17:56:55 -0600 Subject: [PATCH 04/41] Final commit for Rebirth feature! Implement achievement and prestige icon --- public/js/controllers/notificationCtrl.js | 5 +++++ src/models/user.js | 3 ++- views/shared/header/avatar.jade | 1 + views/shared/modals/achievements.jade | 18 +++++++++++++----- views/shared/profiles/achievements.jade | 9 ++++++++- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/public/js/controllers/notificationCtrl.js b/public/js/controllers/notificationCtrl.js index 03d418ffd0..f0e2da347c 100644 --- a/public/js/controllers/notificationCtrl.js +++ b/public/js/controllers/notificationCtrl.js @@ -61,6 +61,11 @@ habitrpg.controller('NotificationCtrl', $rootScope.modals.achievements.beastMaster = true; }, true); + $rootScope.$watch('user.achievements.rebirths', function(after, before){ + if(after === before) return; + $rootScope.modals.achievements.rebirth = true; + }); + /*_.each(['weapon', 'head', 'chest', 'shield'], function(watched){ $rootScope.$watch('user.items.' + watched, function(before, after){ if (after == before) return; diff --git a/src/models/user.js b/src/models/user.js index d47530cfec..a43f0292cc 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -46,7 +46,8 @@ var UserSchema = new Schema({ snowball: Number, streak: Number, challenges: Array, - rebirth: Array + rebirths: Number, + rebirthLevel: Number }, auth: { facebook: Schema.Types.Mixed, diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index fd9ed71529..eb90fa239a 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -46,3 +46,4 @@ figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember( .avatar-level(ng-class='userLevelStyle(profile,"label")') i.icon-circle-arrow-up.icon-white(ng-show='profile.stats.buffs.str || profile.stats.buffs.per || profile.stats.buffs.con || profile.stats.buffs.int || profile.stats.buffs.stealth', tooltip='Buffed', style='margin-right:5px;') | Lvl {{profile.stats.lvl}} + i.icon-plus-sign.icon-white(ng-show='profile.achievements.rebirths', tooltip='Reborn, max level {{profile.achievements.rebirthLevel}}', style='margin-left:5px') diff --git a/views/shared/modals/achievements.jade b/views/shared/modals/achievements.jade index a30a15d2bd..ef14be21bf 100644 --- a/views/shared/modals/achievements.jade +++ b/views/shared/modals/achievements.jade @@ -7,7 +7,7 @@ div(modal='modals.achievements.streak') .achievement.achievement-thermometer | You have stacked your "Streaker" Achievement! Every 21 days of streak, you gain 1 achievement point here. .modal-footer - button.btn.btn-default.cancel(ng-click='modals.achievements.streak = false') Ok + button.btn.btn-default.cancel(ng-click='modals.achievements.streak = false') OK // Max Gear div(modal='modals.achievements.ultimateGear') @@ -17,7 +17,7 @@ div(modal='modals.achievements.ultimateGear') .achievement.achievement-armor | You have earned the "Ultimate Gear" Achievement for upgrading to the maximum gear set! .modal-footer - button.btn.btn-default.cancel(ng-click='modals.achievements.ultimateGear = false') Ok + button.btn.btn-default.cancel(ng-click='modals.achievements.ultimateGear = false') OK // Beast Master div(modal='modals.achievements.beastMaster') @@ -28,7 +28,7 @@ div(modal='modals.achievements.beastMaster') .achievement.achievement-rat | You have earned the "Beast Master" Achievement for collecting all the pets! .modal-footer - button.btn.btn-default.cancel(ng-click='modals.achievements.beastMaster = false') Ok + button.btn.btn-default.cancel(ng-click='modals.achievements.beastMaster = false') OK // Contributor div(modal='user.flags.contributor') @@ -40,7 +40,15 @@ div(modal='user.flags.contributor') {{user.profile.name}}, you awesome person! You're now a level {{user.contributor.level}} contributor for helping HabitRPG. See what prizes you've earned for your contribution! .modal-footer - button.btn.btn-default.cancel(ng-click='set({"flags.contributor":false})') Ok - + button.btn.btn-default.cancel(ng-click='set({"flags.contributor":false})') OK +//Rebirth +div(modal='modals.achievements.rebirth') + .modal-header + h3 Achievement! + .modal-body + .achievement.achievement-sun + | You've begun a new adventure! This is Rebirth {{user.achievements.rebirths}} for you, and the highest Level you've attained is {{user.achievements.rebirthLevel}}. To stack this Achievement, begin your next new adventure when you've reached an even higher Level! + .modal-footer + button.btn.btn-default.cancel(ng-click='modals.achievements.rebirth = false') OK diff --git a/views/shared/profiles/achievements.jade b/views/shared/profiles/achievements.jade index fefd37bf82..f95a284d61 100644 --- a/views/shared/profiles/achievements.jade +++ b/views/shared/profiles/achievements.jade @@ -3,7 +3,6 @@ //
//
//
- //
//
//
//
@@ -57,6 +56,14 @@ small Has found all 90 pets (insanely difficult, give this user props!) hr + div(ng-if='profile.achievements.rebirths') + .achievement.achievement-sun + h5(ng-if='profile.achievements.rebirths == 1') Began a New Adventure + h5(ng-if='profile.achievements.rebirths > 1') Began {{profile.achievements.rebirths}} New Adventures + small. + Used an Orb of Rebirth to start over after attaining Level {{profile.achievements.rebirthLevel}}. + hr + div(ng-if='profile.achievements.helpedHabit') .achievement.achievement-tree h5 Helped Habit Grow From 50d241e2c801425ba7e4c6f124b0ac1b156697d0 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 29 Dec 2013 17:34:21 -0700 Subject: [PATCH 05/41] #2083 add list-item notes at top-level element --- views/shared/tasks/lists.jade | 16 ++++++++-------- views/shared/tasks/task.jade | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/views/shared/tasks/lists.jade b/views/shared/tasks/lists.jade index 1de3dd95a7..be8b21e6cd 100644 --- a/views/shared/tasks/lists.jade +++ b/views/shared/tasks/lists.jade @@ -46,10 +46,10 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") // Static Rewards ul.items.rewards(ng-if='main && list.type=="reward" && user.flags.itemsEnabled') - li.task.reward-item(ng-repeat='item in itemStore') + li.task.reward-item(ng-repeat='item in itemStore',popover-trigger='mouseenter', popover-placement='top', popover='{{item.notes}}') // right-hand side control buttons .task-meta-controls - span.task-notes(popover-trigger='mouseenter', popover-placement='left', popover='{{item.notes}}', popover-title='{{item.text}}') + span.task-notes i.icon-comment //left-hand size commands .task-controls @@ -62,9 +62,9 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") // Winter Event ul.items.rewards(ng-if='main && list.type=="reward" && (user.items.special.snowball>0 || user.stats.buffs.snowball)') - li.task.reward-item(ng-if='user.items.special.snowball>0') + li.task.reward-item(ng-if='user.items.special.snowball>0',popover-trigger='mouseenter', popover-placement='top', popover='{{Content.spells.special.snowball.notes}}') .task-meta-controls - span.task-notes(popover-trigger='mouseenter', popover-placement='left', popover='{{Content.spells.special.snowball.notes}}', popover-title='{{Content.spells.special.snowball.text}}') + span.task-notes i.icon-comment //left-hand size commands .task-controls @@ -73,9 +73,9 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") span.shop_snowball(style='display:inline-block;vertical-align:top;') // main content p.task-text {{Content.spells.special.snowball.text}} - li.task.reward-item(ng-if='user.stats.buffs.snowball') + li.task.reward-item(ng-if='user.stats.buffs.snowball',popover-trigger='mouseenter', popover-placement='top', popover='{{Content.spells.special.salt.notes}}') .task-meta-controls - span.task-notes(popover-trigger='mouseenter', popover-placement='left', popover='{{Content.spells.special.salt.notes}}', popover-title='{{Content.spells.special.salt.text}}') + span.task-notes i.icon-comment //left-hand size commands .task-controls @@ -88,9 +88,9 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") // Spells ul.items(ng-if='main && list.type=="reward" && user.stats.class && !user.preferences.disableClasses') - li.task.reward-item(ng-repeat='(k,spell) in Content.spells[user.stats.class]', ng-show='user.stats.lvl >= spell.lvl') + li.task.reward-item(ng-repeat='(k,spell) in Content.spells[user.stats.class]', ng-if='user.stats.lvl >= spell.lvl',popover-trigger='mouseenter', popover-placement='top', popover='{{spell.notes}}') .task-meta-controls - span.task-notes(popover-trigger='mouseenter', popover-placement='left', popover='{{spell.notes}}', popover-title='{{spell.text}}') + span.task-notes i.icon-comment //left-hand size commands .task-controls diff --git a/views/shared/tasks/task.jade b/views/shared/tasks/task.jade index 5f4922267d..99e69f2b1a 100644 --- a/views/shared/tasks/task.jade +++ b/views/shared/tasks/task.jade @@ -1,4 +1,4 @@ -li(bindonce='list', ng-repeat='task in obj[list.type+"s"] | completedFilter: list.showCompleted', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && castEnd(task, "task", $event)', ng-class='{"cast-target":spell}') +li(bindonce='list', ng-repeat='task in obj[list.type+"s"] | completedFilter: list.showCompleted', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && castEnd(task, "task", $event)', ng-class='{"cast-target":spell}', popover-trigger='mouseenter', popover-placement='top', popover='{{task.notes}}') // right-hand side control buttons .task-meta-controls @@ -36,7 +36,7 @@ li(bindonce='list', ng-repeat='task in obj[list.type+"s"] | completedFilter: lis a(ng-show='task.history', ng-click='toggleChart(obj._id+task.id, task)', tooltip='Progress') i.icon-signal // notes - span.task-notes(ng-show='task.notes && !task._editing', popover-trigger='mouseenter', popover-placement='left', popover='{{task.notes}}', popover-title='{{task.text}}') + span.task-notes(ng-show='task.notes && !task._editing') i.icon-comment // left-hand side checkbox From c3aed6fb282d5a6a99510cafdb66a8ec52baa131 Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Sun, 29 Dec 2013 20:58:35 -0600 Subject: [PATCH 06/41] RPG demystification, cont'd --- views/options/profile.jade | 8 ++++---- views/shared/modals/classes.jade | 19 +++++++++---------- views/shared/profiles/stats.jade | 27 ++++++++++++++++----------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/views/options/profile.jade b/views/options/profile.jade index 872b7d529f..552e63d2a9 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -154,25 +154,25 @@ script(id='partials/options.profile.stats.html', type='text/ng-template') table.table.table-striped tr td - i.icon-question-sign(popover-title='Strength', popover='Strength increases damage you inflict to tasks (reducing redness), and increases critical hit chance.', popover-trigger='mouseenter') + i.icon-question-sign(popover-title='Strength', popover='Strength reduces task threat (redness), increases the Gold and Experience boost from random "critical hits," and helps deal damage to boss monsters.', popover-trigger='mouseenter') |  STR: {{user.stats.str}} td a.btn.btn-primary(ng-show='user.stats.points', ng-click='allocate("str")') + tr td - i.icon-question-sign(popover-title='Constitution', popover='Constitution decreases damage inflicted by tasks, and increases the effectiveness of healing and buff spells.', popover-trigger='mouseenter') + i.icon-question-sign(popover-title='Constitution', popover='Constitution reduces the damage you take, whether from negative Habits, missed Dailies, or the attacks of boss monsters.', popover-trigger='mouseenter') |  CON: {{user.stats.con}} td a.btn.btn-primary(ng-show='user.stats.points', ng-click='allocate("con")') + tr td - i.icon-question-sign(popover-title='Perception', popover='Perception increases drops and gold, and can help with critical hits by spells.', popover-trigger='mouseenter') + i.icon-question-sign(popover-title='Perception', popover='Perception increases how much Gold you earn, and increases the chance of finding items when scoring tasks.', popover-trigger='mouseenter') |  PER: {{user.stats.per}} td a.btn.btn-primary(ng-show='user.stats.points', ng-click='allocate("per")') + tr td - i.icon-question-sign(popover-title='Intelligence', popover='Intelligence increases your overall mana, spell effectiveness, and experience gain.', popover-trigger='mouseenter') + i.icon-question-sign(popover-title='Intelligence', popover='Intelligence increases how much Experience you earn, and determines your maximum Mana available for class abilities.', popover-trigger='mouseenter') |  INT: {{user.stats.int}} td a.btn.btn-primary(ng-show='user.stats.points', ng-click='allocate("int")') + diff --git a/views/shared/modals/classes.jade b/views/shared/modals/classes.jade index cc598ecac6..49c4ac808e 100644 --- a/views/shared/modals/classes.jade +++ b/views/shared/modals/classes.jade @@ -1,11 +1,10 @@ .modal(ng-if='!user.flags.classSelected && user.stats.lvl >= 10', data-backdrop=true, ng-controller='UserCtrl') .modal-header - h3 Choose Your Class! + h3 Choose Your Class! .modal-body.select-class - p Select your class. Click each class for more information. See Wikia for thorough details. .row-fluid .span3(ng-click='selectedClass = "warrior"') - h5 Warrior + h5 Warrior figure.herobox(ng-class='{"selected-class": selectedClass=="warrior"}') .character-sprites span(class='skin_{{user.preferences.skin}}') @@ -19,7 +18,7 @@ span(class='shield_warrior_5') span(class='weapon_warrior_6') .span3(ng-click='selectedClass = "wizard"') - h5 Mage + h5 Mage figure.herobox(ng-class='{"selected-class": selectedClass=="wizard"}') .character-sprites span(class='skin_{{user.preferences.skin}}') @@ -33,7 +32,7 @@ span(class='shield_wizard_5') span(class='weapon_wizard_6') .span3(ng-click='selectedClass = "rogue"') - h5 Rogue + h5 Rogue figure.herobox(ng-class='{"selected-class": selectedClass=="rogue"}') .character-sprites span(class='skin_{{user.preferences.skin}}') @@ -47,7 +46,7 @@ span(class='shield_rogue_6') span(class='weapon_rogue_6') .span3(ng-click='selectedClass = "healer"') - h5 Healer + h5 Healer figure.herobox(ng-class='{"selected-class": selectedClass=="healer"}') .character-sprites span(class='skin_{{user.preferences.skin}}') @@ -61,10 +60,10 @@ span(class='shield_healer_5') span(class='weapon_healer_6') br - .well(ng-show='selectedClass=="warrior"') Warriors deal damage to tasks (reducing redness), have moderate defense, and improved critical hits. - .well(ng-show='selectedClass=="wizard"') Mages deal damage to tasks (reducing redness), can debuff tasks, and they gain experience rapidly. - .well(ng-show='selectedClass=="rogue"') Rogues finds more drops and gold. They can also "go stealth" to avoid damage at the end of a day. - .well(ng-show='selectedClass=="healer"') Healers have high defense against damage, and can heal themselves and other players in the party, as well as buff players. + .well(ng-show='selectedClass=="warrior"') Warriors keep tasks in line, each success making later slip-ups less harsh. They also score impressive "critical hits," which randomly give bonus Gold and Experience for scoring a task. Play a Warrior if you don't want to be punished too hard for inconsistency, or if you find strong motivation from unpredictable jackpot-style rewards! + .well(ng-show='selectedClass=="wizard"') Mages learn swiftly, gaining Experience and Levels faster than other classes. They also get a great deal of Mana for using special abilities. Play a Mage if you enjoy the tactical game aspects of Habit, or if you are strongly motivated by leveling up and unlocking advanced features! + .well(ng-show='selectedClass=="rogue"') Rogues love to accumulate wealth, gaining more Gold than anyone else, and are adept at finding random items. Their iconic Stealth ability lets them duck the consequences of missed Dailies. Play a Rogue if you find strong motivation from Rewards and Achievements, striving for loot and badges! + .well(ng-show='selectedClass=="healer"') Healers stand impervious against harm, and extend that protection to others. Missed Dailies and bad Habits don't faze them much, and they have ways to recover Health from failure. Play a Healer if you enjoy assisting others in your Party, or if the idea of cheating Death through hard work inspires you! .modal-footer button.btn.btn-small.btn-danger.cancel(ng-click='user.ops.disableClasses({})', popover-placement='top', popover-trigger='mouseenter', popover="Can't be bothered with classes? Opt out - you'll be a warrior and your points handled automatically. You can enable classes later under Settings") Opt Out diff --git a/views/shared/profiles/stats.jade b/views/shared/profiles/stats.jade index e6c25bd009..75b645fa6b 100644 --- a/views/shared/profiles/stats.jade +++ b/views/shared/profiles/stats.jade @@ -30,17 +30,22 @@ table.table.table-striped td strong {{v}}: {{profile._statsComputed[k]}} td - ul - li Level: {{(profile.stats.lvl - 1) / 2}}  - i.icon-question-sign(popover-title='Level Bonus', popover-trigger='mouseenter', popover-placement='right', popover="Each attribute gets a bonus equal to half your Level.") - li Equipment: {{Content.gear.flat[profile.items.gear.equipped.weapon][k] + Content.gear.flat[profile.items.gear.equipped.armor][k] + Content.gear.flat[profile.items.gear.equipped.head][k] + Content.gear.flat[profile.items.gear.equipped.shield][k] || 0}}  - i.icon-question-sign(popover-title='Equipment', popover-trigger='mouseenter', popover-placement='right', popover="Attribute bonuses provided by your equipped battle gear. See the Equipment tab under Inventory to select your battle gear.") - li Class Equip Bonus: {{profile._statsComputed[k] - profile.stats.buffs[k] - ((profile.stats.lvl - 1) / 2) - Content.gear.flat[profile.items.gear.equipped.weapon][k] - Content.gear.flat[profile.items.gear.equipped.armor][k] - Content.gear.flat[profile.items.gear.equipped.head][k] - Content.gear.flat[profile.items.gear.equipped.shield][k]}}  - i.icon-question-sign(popover-title='Class Equipment Bonus', popover-trigger='mouseenter', popover-placement='right', popover="Your class uses its own equipment more effectively than gear from other classes. Equipped gear from your current class gets a 50% boost to the attribute bonus it grants.") - li Allocated: {{profile.stats[k] || 0}}  - i.icon-question-sign(popover-title='Allocated Points', popover-trigger='mouseenter', popover-placement='right', popover="Attribute points you've earned and assigned. Assign points using the Character Build column.") - li Buffs: {{profile.stats.buffs[k] || 0}}  - i.icon-question-sign(popover-title='Buffs', popover-trigger='mouseenter', popover-placement='right', popover="Attribute bonuses provided by abilities you or your party members have used. The abilities you can use are found in the Rewards column on your Tasks page.") + ul(style='list-style-type:none') + li + i.icon-question-sign(popover-title='Level Bonus', popover-trigger='mouseenter', popover-placement='top', popover="Each attribute gets a bonus equal to half your Level.") + | Level: {{(profile.stats.lvl - 1) / 2}}  + li + i.icon-question-sign(popover-title='Equipment', popover-trigger='mouseenter', popover-placement='top', popover="Attribute bonuses provided by your equipped battle gear. See the Equipment tab under Inventory to select your battle gear.") + | Equipment: {{Content.gear.flat[profile.items.gear.equipped.weapon][k] + Content.gear.flat[profile.items.gear.equipped.armor][k] + Content.gear.flat[profile.items.gear.equipped.head][k] + Content.gear.flat[profile.items.gear.equipped.shield][k] || 0}}  + li + i.icon-question-sign(popover-title='Class Equipment Bonus', popover-trigger='mouseenter', popover-placement='top', popover="Your class uses its own equipment more effectively than gear from other classes. Equipped gear from your current class gets a 50% boost to the attribute bonus it grants.") + | Class Equip Bonus: {{profile._statsComputed[k] - profile.stats.buffs[k] - ((profile.stats.lvl - 1) / 2) - Content.gear.flat[profile.items.gear.equipped.weapon][k] - Content.gear.flat[profile.items.gear.equipped.armor][k] - Content.gear.flat[profile.items.gear.equipped.head][k] - Content.gear.flat[profile.items.gear.equipped.shield][k]}}  + li + i.icon-question-sign(popover-title='Allocated Points', popover-trigger='mouseenter', popover-placement='top', popover="Attribute points you've earned and assigned. Assign points using the Character Build column.") + | Allocated: {{profile.stats[k] || 0}}  + li + i.icon-question-sign(popover-title='Buffs', popover-trigger='mouseenter', popover-placement='top', popover="Attribute bonuses provided by abilities you or your party members have used. The abilities you can use are found in the Rewards column on your Tasks page.") + | Buffs: {{profile.stats.buffs[k] || 0}}  tr(ng-if='profile.stats.buffs.stealth') td strong Stealth: {{profile.stats.buffs.stealth}}  From 199a74d8a9c47c63c159a662dd0061a0d599c65b Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Mon, 30 Dec 2013 07:33:17 -0600 Subject: [PATCH 07/41] Fix #2181 (allocated points showing up in Class Equip Bonus) --- views/shared/profiles/stats.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/shared/profiles/stats.jade b/views/shared/profiles/stats.jade index 75b645fa6b..882b4aabb6 100644 --- a/views/shared/profiles/stats.jade +++ b/views/shared/profiles/stats.jade @@ -39,7 +39,7 @@ table.table.table-striped | Equipment: {{Content.gear.flat[profile.items.gear.equipped.weapon][k] + Content.gear.flat[profile.items.gear.equipped.armor][k] + Content.gear.flat[profile.items.gear.equipped.head][k] + Content.gear.flat[profile.items.gear.equipped.shield][k] || 0}}  li i.icon-question-sign(popover-title='Class Equipment Bonus', popover-trigger='mouseenter', popover-placement='top', popover="Your class uses its own equipment more effectively than gear from other classes. Equipped gear from your current class gets a 50% boost to the attribute bonus it grants.") - | Class Equip Bonus: {{profile._statsComputed[k] - profile.stats.buffs[k] - ((profile.stats.lvl - 1) / 2) - Content.gear.flat[profile.items.gear.equipped.weapon][k] - Content.gear.flat[profile.items.gear.equipped.armor][k] - Content.gear.flat[profile.items.gear.equipped.head][k] - Content.gear.flat[profile.items.gear.equipped.shield][k]}}  + | Class Equip Bonus: {{profile._statsComputed[k] - profile.stats.buffs[k] - ((profile.stats.lvl - 1) / 2) - Content.gear.flat[profile.items.gear.equipped.weapon][k] - Content.gear.flat[profile.items.gear.equipped.armor][k] - Content.gear.flat[profile.items.gear.equipped.head][k] - Content.gear.flat[profile.items.gear.equipped.shield][k] - profile.stats[k]}}  li i.icon-question-sign(popover-title='Allocated Points', popover-trigger='mouseenter', popover-placement='top', popover="Attribute points you've earned and assigned. Assign points using the Character Build column.") | Allocated: {{profile.stats[k] || 0}}  From 9a32cfd7e1d8ad796ef1adeaa2836b27ae19f08c Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Mon, 30 Dec 2013 08:46:40 -0600 Subject: [PATCH 08/41] Remove extraneous techy characters from boss fight and spellcasting chat notifications --- src/controllers/user.js | 2 +- src/models/group.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controllers/user.js b/src/controllers/user.js index baf8a37055..4937e57892 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -371,7 +371,7 @@ api.cast = function(req, res) { if (group) { series.push(function(cb2){ - var message = '`'+user.profile.name+' casts '+spell.text + (type=='user' ? ' on @'+found.profile.name : ' for the party')+'.`'; + var message = '`'+user.profile.name+' casts '+spell.text + (type=='user' ? ' on '+found.profile.name : ' for the party')+'.`'; group.sendChat(message); group.save(cb2); }) diff --git a/src/models/group.js b/src/models/group.js index 7ce332e39d..9d17f5d55d 100644 --- a/src/models/group.js +++ b/src/models/group.js @@ -182,7 +182,7 @@ GroupSchema.statics.collectQuest = function(user, progress, cb) { return m; }, []); foundText = foundText ? foundText.join(', ') : 'nothing'; - group.sendChat("`<" + user.profile.name + "> found "+foundText+".`"); + group.sendChat("`" + user.profile.name + " found "+foundText+".`"); group.markModified('quest.progress.collect'); // Still needs completing @@ -210,7 +210,7 @@ GroupSchema.statics.bossQuest = function(user, progress, cb) { var down = progress.down * quest.boss.str; // multiply by boss strength group.quest.progress.hp -= progress.up; - group.sendChat("`<" + user.profile.name + "> attacks <" + quest.boss.name + "> for " + (progress.up.toFixed(1)) + " damage, <" + quest.boss.name + "> attacks party for " + Math.abs(down).toFixed(1) + " damage.`"); + group.sendChat("`" + user.profile.name + " attacks " + quest.boss.name + " for " + (progress.up.toFixed(1)) + " damage, " + quest.boss.name + " attacks party for " + Math.abs(down).toFixed(1) + " damage.`"); // Everyone takes damage var series = [ From 6f0046dffc9045b8f4ed149f10f38305723895d8 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Mon, 30 Dec 2013 10:19:57 -0700 Subject: [PATCH 09/41] Revert b4ff7d4 b20a3b7 . Temporarily remove todo-filter. This brings back the big performance issue of always displaying completed-todos, but fixes #2180 #2189. See #2180 for discussion. --- public/js/filters/filters.js | 6 ------ views/shared/tasks/task.jade | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/public/js/filters/filters.js b/public/js/filters/filters.js index e20db4aadf..9d2255d9e2 100644 --- a/public/js/filters/filters.js +++ b/public/js/filters/filters.js @@ -8,10 +8,4 @@ angular.module('habitrpg') return function (gp) { return Math.floor((gp - Math.floor(gp))*100); } - }) - .filter('completedFilter', function(){ - return function(tasks,_showCompleted) { - if (!tasks[0] || tasks[0].type != 'todo') return tasks; - return _.where(tasks, {completed:!!_showCompleted}); - } }) \ No newline at end of file diff --git a/views/shared/tasks/task.jade b/views/shared/tasks/task.jade index 5f4922267d..6653db1568 100644 --- a/views/shared/tasks/task.jade +++ b/views/shared/tasks/task.jade @@ -1,4 +1,4 @@ -li(bindonce='list', ng-repeat='task in obj[list.type+"s"] | completedFilter: list.showCompleted', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && castEnd(task, "task", $event)', ng-class='{"cast-target":spell}') +li(bindonce='list', ng-repeat='task in obj[list.type+"s"]', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && castEnd(task, "task", $event)', ng-class='{"cast-target":spell}') // right-hand side control buttons .task-meta-controls From 74c905f1e1d1ff39bcb6354217e4c1ce9f1f7ccf Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 29 Dec 2013 21:10:27 -0700 Subject: [PATCH 10/41] checklists WIP --- bower.json | 2 +- package.json | 2 +- public/css/index.styl | 3 ++- public/css/tasks.styl | 25 ++++++++++++++++++- public/js/controllers/tasksCtrl.js | 39 ++++++++++++++++++++++++++++-- src/models/task.js | 11 ++++++++- views/shared/tasks/task.jade | 19 ++++++++++++++- 7 files changed, 93 insertions(+), 8 deletions(-) diff --git a/bower.json b/bower.json index 7433383b0d..3e898dea40 100644 --- a/bower.json +++ b/bower.json @@ -29,7 +29,7 @@ "bootstrap": "v2.3.2", "bootstrap-datepicker": "~1.2.0", "bootstrap-growl": "~1.1.0", - "habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared.git#develop", + "habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared.git#checklists", "BrowserQuest": "https://github.com/mozilla/BrowserQuest.git", "github-buttons": "git://github.com/mdo/github-buttons.git", "marked": "~0.2.9", diff --git a/package.json b/package.json index 9e2ac50493..2efeddc301 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.0-152", "main": "./src/server.js", "dependencies": { - "habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared#develop", + "habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared#checklists", "derby-auth": "git://github.com/lefnire/derby-auth#master", "connect-mongo": "*", "passport-facebook": "~1.0.0", diff --git a/public/css/index.styl b/public/css/index.styl index 796dc2e278..7fbb6f7615 100644 --- a/public/css/index.styl +++ b/public/css/index.styl @@ -1,4 +1,5 @@ -@import "nib/vendor" +@import "nib" +//@import "nib/vendor" // Vendor Includes - include first so we can override // Import only styles that do not have urls to images! Include them directly in the page! diff --git a/public/css/tasks.styl b/public/css/tasks.styl index 78a02d007e..4cc0af1fe3 100644 --- a/public/css/tasks.styl +++ b/public/css/tasks.styl @@ -407,4 +407,27 @@ form color: #333 &:hover border-top: 0 - margin-top: 2px \ No newline at end of file + margin-top: 2px + +// Checklists +// -------- +.checklist-form + /* Make an input blend into its parent */ + input.inline-edit + reset-box-model() + reset-font() + line-height: inherit + text-align: inherit + background-color:inherit + box-shadow: none + + /* Add interaction cues on hover and focus */ + input.inline-edit:hover,input.inline-edit:focus + background-color: #FFD + transition: background-color 0.5s + + .checklist-icons + opacity:0 + + label:hover .checklist-icons + opacity:1 diff --git a/public/js/controllers/tasksCtrl.js b/public/js/controllers/tasksCtrl.js index f2d82ff08b..4d18fbb782 100644 --- a/public/js/controllers/tasksCtrl.js +++ b/public/js/controllers/tasksCtrl.js @@ -1,7 +1,7 @@ "use strict"; -habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','Notification', '$http', 'API_URL', - function($scope, $rootScope, $location, User, Notification, $http, API_URL) { +habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','Notification', '$http', 'API_URL', '$timeout', + function($scope, $rootScope, $location, User, Notification, $http, API_URL, $timeout) { $scope.obj = User.user; // used for task-lists $scope.user = User.user; @@ -68,6 +68,41 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N }); }; + /* + ------------------------ + Checklists + ------------------------ + */ + var ws = window.setTimeout; + $scope.addChecklist = function(task) { + task.checklist = [{completed:false,text:""}]; + ws(function(){ + $('#task-'+task.id+' .checklist-form .inline-edit')[0].focus(); + }); + } + $scope.checkChecklistItem = function(task){ + User.user.ops.updateTask({params:{id:task.id},body:task}); + } + $scope.saveChecklist = function(task,$event,$index) { + User.user.ops.updateTask({params:{id:task.id},body:task}); + task.checklist = _.filter(task.checklist,function(i){return !!i.text}); + $event.target.blur(); + if ($index == task.checklist.length-1){ + task.checklist.push({completed:false,text:''}); + ws(function(){ + var list = $('#task-'+task.id+' .checklist-form .inline-edit'); + list[list.length-1].focus(); + },100); + } + } + $scope.removeChecklistItem = function(task,$index){ + task.checklist.splice($index,1); + User.user.ops.updateTask({params:{id:task.id},body:task}); + } + $scope.checklistCompletion = function(checklist){ + return _.reduce(checklist,function(m,i){return m+(i.completed ? 1 : 0);},0) + } + /* ------------------------ Items diff --git a/src/models/task.js b/src/models/task.js index e160a09971..865c2558a1 100644 --- a/src/models/task.js +++ b/src/models/task.js @@ -39,6 +39,13 @@ var HabitSchema = new Schema( , { _id: false } ); +var checklist = [{ + completed:{type:Boolean,'default':false}, + text: String, + _id:false, + id: {type:String,'default':shared.uuid} +}]; + var DailySchema = new Schema( _.defaults({ type: {type:String, 'default': 'daily'}, @@ -53,6 +60,7 @@ var DailySchema = new Schema( s: {type: Boolean, 'default': true}, su: {type: Boolean, 'default': true} }, + checklist:checklist, streak: {type: Number, 'default': 0} }, TaskSchema) , { _id: false } @@ -62,7 +70,8 @@ var TodoSchema = new Schema( _.defaults({ type: {type:String, 'default': 'todo'}, completed: {type: Boolean, 'default': false}, - date: String // due date for todos // FIXME we're getting parse errors, people have stored as "today" and "3/13". Need to run a migration & put this back to type: Date + date: String, // due date for todos // FIXME we're getting parse errors, people have stored as "today" and "3/13". Need to run a migration & put this back to type: Date + checklist:checklist }, TaskSchema) , { _id: false } ); diff --git a/views/shared/tasks/task.jade b/views/shared/tasks/task.jade index 4075faec67..e99c8186c8 100644 --- a/views/shared/tasks/task.jade +++ b/views/shared/tasks/task.jade @@ -1,4 +1,4 @@ -li(bindonce='list', ng-repeat='task in obj[list.type+"s"]', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && castEnd(task, "task", $event)', ng-class='{"cast-target":spell}', popover-trigger='mouseenter', popover-placement='top', popover='{{task.notes}}') +li(bindonce='list', bo-id='"task-"+task.id', ng-repeat='task in obj[list.type+"s"]', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && castEnd(task, "task", $event)', ng-class='{"cast-target":spell}', popover-trigger='mouseenter', popover-placement='top', popover='{{task.notes}}') // right-hand side control buttons .task-meta-controls @@ -12,6 +12,9 @@ li(bindonce='list', ng-repeat='task in obj[list.type+"s"]', class='task {{Shared // Icons only available if you own the tasks (aka, hidden from challenge stats) span(ng-if='!obj._locked') + span.badge(ng-if='task.checklist[0]', ng-class='{"badge-success":checklistCompletion(task.checklist) == task.checklist.length}') + {{checklistCompletion(task.checklist)}}/{{task.checklist.length}} + i.icon-tags(tooltip='{{appliedTags(user.tags, task.tags)}}', ng-hide='Shared.noTags(task.tags)') // edit a(ng-hide='task._editing', ng-click='editTask(task)', tooltip='Edit') @@ -96,6 +99,20 @@ li(bindonce='list', ng-repeat='task in obj[list.type+"s"]', class='task {{Shared |  |  a(ng-click="unlink(task, 'remove-all')") Remove Them + // Checklists + a.btn.btn-small(ng-if='!task.checklist[0] && (task.type=="daily" || task.type=="todo")',ng-click='addChecklist(task)') + i.icon-tasks + | Add Checklist + form.checklist-form(ng-if='task.checklist') + fieldset.option-group.task-checklist(ng-if='!$state.includes("options.social.challenges")') + legend.option-title Checklist + label.checkbox(ng-repeat='item in task.checklist') + a.pull-right.checklist-icons(ng-click='removeChecklistItem(task,$index)') + i.icon-trash(tooltip='Delete') + input(type='checkbox',ng-model='item.completed',ng-change='checkChecklistItem(task)') + input.inline-edit(type='text',ng-model='item.text',ui-keypress="{13:'saveChecklist(task,$event,$index)'}",ng-blur='saveChecklist(task,$event,$index)') + + form(ng-submit='saveTask(task)') // text & notes fieldset.option-group From 1ace999cb7a38b9dc990f8051f95200796d18e62 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 29 Dec 2013 23:49:19 -0700 Subject: [PATCH 11/41] Tasks: add double-click to edit, and date-picker-popup for due-dates. Show red dates when overdue (basic) --- public/js/controllers/tasksCtrl.js | 7 +++++++ views/shared/tasks/task.jade | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/public/js/controllers/tasksCtrl.js b/public/js/controllers/tasksCtrl.js index 4d18fbb782..0ed412fa7d 100644 --- a/public/js/controllers/tasksCtrl.js +++ b/public/js/controllers/tasksCtrl.js @@ -68,6 +68,13 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N }); }; + /* + ------------------------ + To-Dos + ------------------------ + */ + $scope._today = moment().add('days',1); + /* ------------------------ Checklists diff --git a/views/shared/tasks/task.jade b/views/shared/tasks/task.jade index e99c8186c8..eaa6ed70bc 100644 --- a/views/shared/tasks/task.jade +++ b/views/shared/tasks/task.jade @@ -1,10 +1,10 @@ -li(bindonce='list', bo-id='"task-"+task.id', ng-repeat='task in obj[list.type+"s"]', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && castEnd(task, "task", $event)', ng-class='{"cast-target":spell}', popover-trigger='mouseenter', popover-placement='top', popover='{{task.notes}}') +li(bindonce='list', bo-id='"task-"+task.id', ng-repeat='task in obj[list.type+"s"]', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && castEnd(task, "task", $event)', ng-class='{"cast-target":spell}', popover-trigger='mouseenter', popover-placement='top', popover='{{task.notes}}', ng-dblclick='editTask(task)') // right-hand side control buttons .task-meta-controls // Due Date span.task-date(ng-if='task.type=="todo" && task.date') - | {{task.date}} + span(ng-class='{"label label-important":moment(task.date).isBefore(_today)}') {{moment(task.date).format('MM/DD')}} // Streak span(ng-show='task.streak') {{task.streak}} span(tooltip='Streak Counter') @@ -155,7 +155,7 @@ li(bindonce='list', bo-id='"task-"+task.id', ng-repeat='task in obj[list.type+"s // if Todos, the due date fieldset.option-group(ng-if='task.type=="todo" && !task.challenge.id') legend.option-title Due Date - input.option-content.datepicker(type='text', data-date-format='mm/dd/yyyy', ng-model='task.date') + input.option-content.datepicker(type='text', datepicker-popup='MM/dd/yyyy', ng-model='task.date') fieldset.option-group(ng-if='!$state.includes("options.social.challenges")') legend.option-title Tags From 968b091ccd14c8a4c6e71b9882cf6d876f187a04 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Mon, 30 Dec 2013 00:17:15 -0700 Subject: [PATCH 12/41] checklists: checklist as
  • instead of