From 85879177a6dec809576eb85cc5d48397eff1e144 Mon Sep 17 00:00:00 2001 From: hairlessbear Date: Tue, 2 Jun 2015 00:54:54 -0400 Subject: [PATCH 01/16] Added group leader to group description, and removed group leader from member list --- common/locales/en/groups.json | 2 ++ website/views/options/social/group.jade | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/common/locales/en/groups.json b/common/locales/en/groups.json index 6e5e0915d8..78ad3d162c 100644 --- a/common/locales/en/groups.json +++ b/common/locales/en/groups.json @@ -39,6 +39,8 @@ "editGroup": "Edit Group", "newGroupName": "<%= groupType %> Name", "groupName": "Group Name", + "groupLeader": "Group Leader: ", + "groupID": "Group ID: ", "groupDescr": "Description shown in public Guilds list (Markdown OK)", "logoUrl": "Logo URL", "assignLeader": "Assign Group Leader", diff --git a/website/views/options/social/group.jade b/website/views/options/social/group.jade index 850694e7e4..858df2adee 100644 --- a/website/views/options/social/group.jade +++ b/website/views/options/social/group.jade @@ -51,7 +51,12 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter img.pull-right(ng-show='group.logo', ng-src='{{group.logo}}') markdown(text='group.description') hr - small.muted Group ID: {{group._id}} + p=env.t('groupLeader') + a(class='badge badge-info', ng-click='clickMember(group.leader, true)') + | {{group.leader}} + .formatting-help + small.muted=env.t('groupID') + | {{group._id}} include ./challenge-box @@ -78,14 +83,14 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter ng-change='set({"party.orderAscending": user.party.orderAscending})' ) table.table.table-striped(bindonce='group') - tr(ng-repeat='member in group.members track by member._id') + tr(ng-repeat='member in group.members track by member._id' ng-if='member._id != group.leader') td.media // allow leaders to ban members - div.pull-left(ng-show='group.leader == user.id && user.id!=member._id') + div.pull-left(ng-show='group.leader == user.id') a.media-object(ng-click='removeMember(group, member, true)') span.glyphicon.glyphicon-ban-circle(tooltip=env.t('banTip')) a.media-body - span(ng-class='{"badge badge-info": group.leader==member._id}', ng-click='clickMember(member._id, true)') + span(ng-click='clickMember(member._id, true)') | {{member.profile.name}} tr(ng-if='group.memberCount > group.members.length') td From 90015134da2346b27dacbcf9ee54380c3ff47ad1 Mon Sep 17 00:00:00 2001 From: hairlessbear Date: Thu, 4 Jun 2015 15:18:09 -0400 Subject: [PATCH 02/16] Fixed 'group.leader.profile.name' issue and changed all instances of 'group.leader' to 'group.leader._id' --- website/src/controllers/groups.js | 1 + website/views/options/social/group.jade | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/website/src/controllers/groups.js b/website/src/controllers/groups.js index b9d2643c61..321a460760 100644 --- a/website/src/controllers/groups.js +++ b/website/src/controllers/groups.js @@ -41,6 +41,7 @@ var populateQuery = function(type, q, additionalFields){ else q.populate(guildPopulate); q.populate('invites', nameFields); + q.populate('leader', nameFields); q.populate({ path: 'challenges', match: (type=='habitrpg') ? {_id:{$ne:'95533e05-1ff9-4e46-970b-d77219f199e9'}} : undefined, // remove the Spread the Word Challenge for now, will revisit when we fix the closing-challenge bug diff --git a/website/views/options/social/group.jade b/website/views/options/social/group.jade index 858df2adee..50609912d8 100644 --- a/website/views/options/social/group.jade +++ b/website/views/options/social/group.jade @@ -22,7 +22,7 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter span.glyphicon.glyphicon-ban-circle =env.t('leave') a.btn.btn-success.pull-right(ng-if=':: !isMemberOfGroup(User.user._id, group)', ng-click='join(group)')=env.t('join') - span(ng-if='group.leader == user.id') + span(ng-if='group.leader._id == user.id') button.btn.btn-sm.btn-primary.pull-right(ng-click='save(group)', ng-show='group._editing')=env.t('save') button.btn.btn-sm.btn-default.pull-right(ng-click='group._editing = true', ng-hide='group._editing')=env.t('editGroup') @@ -52,8 +52,8 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter markdown(text='group.description') hr p=env.t('groupLeader') - a(class='badge badge-info', ng-click='clickMember(group.leader, true)') - | {{group.leader}} + a(class='badge badge-info', ng-click='clickMember(group.leader._id, true)') + | {{group.leader.profile.name}} .formatting-help small.muted=env.t('groupID') | {{group._id}} @@ -83,10 +83,10 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter ng-change='set({"party.orderAscending": user.party.orderAscending})' ) table.table.table-striped(bindonce='group') - tr(ng-repeat='member in group.members track by member._id' ng-if='member._id != group.leader') + tr(ng-repeat='member in group.members track by member._id' ng-if='member._id != group.leader._id') td.media // allow leaders to ban members - div.pull-left(ng-show='group.leader == user.id') + div.pull-left(ng-show='group.leader._id == user.id') a.media-object(ng-click='removeMember(group, member, true)') span.glyphicon.glyphicon-ban-circle(tooltip=env.t('banTip')) a.media-body @@ -103,7 +103,7 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter tr(ng-repeat='invite in group.invites') td.media // allow leaders to ban members - div.pull-left(ng-show='group.leader == user.id') + div.pull-left(ng-show='group.leader._id == user.id') a.media-object(ng-click='removeMember(group, invite, false)') span.glyphicon.glyphicon-ban-circle(tooltip=env.t('banTip')) a.media-body @@ -122,7 +122,7 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter td .popover.static-popover.fade.right.in.wide-popover .arrow - h3.popover-title {{Members.members[group.leader].profile.name}} + h3.popover-title {{group.leader.profile.name}} .popover-content markdown(text='group.leaderMessage') div(ng-controller='ChatCtrl') From 60ecdb2dcad1307140388864c31da9cc6f07c30e Mon Sep 17 00:00:00 2001 From: hairlessbear Date: Thu, 4 Jun 2015 17:48:31 -0400 Subject: [PATCH 03/16] Removed colons from JSON and 'formatting-help' class to 'slight-vertical-padding' --- common/locales/en/groups.json | 4 ++-- website/public/css/game-pane.styl | 2 +- website/views/options/social/group.jade | 5 +++-- website/views/shared/formatting-help.jade | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/common/locales/en/groups.json b/common/locales/en/groups.json index 78ad3d162c..78a6aac270 100644 --- a/common/locales/en/groups.json +++ b/common/locales/en/groups.json @@ -39,8 +39,8 @@ "editGroup": "Edit Group", "newGroupName": "<%= groupType %> Name", "groupName": "Group Name", - "groupLeader": "Group Leader: ", - "groupID": "Group ID: ", + "groupLeader": "Group Leader", + "groupID": "Group ID", "groupDescr": "Description shown in public Guilds list (Markdown OK)", "logoUrl": "Logo URL", "assignLeader": "Assign Group Leader", diff --git a/website/public/css/game-pane.styl b/website/public/css/game-pane.styl index 1b6b1976ad..ea2729910d 100644 --- a/website/public/css/game-pane.styl +++ b/website/public/css/game-pane.styl @@ -21,7 +21,7 @@ padding: 1em; margin-bottom: 0.5em; -.formatting-help +.slight-vertical-padding clear: both padding-top: 0.618em diff --git a/website/views/options/social/group.jade b/website/views/options/social/group.jade index 50609912d8..2e57cb49a1 100644 --- a/website/views/options/social/group.jade +++ b/website/views/options/social/group.jade @@ -52,11 +52,12 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter markdown(text='group.description') hr p=env.t('groupLeader') + |: a(class='badge badge-info', ng-click='clickMember(group.leader._id, true)') | {{group.leader.profile.name}} - .formatting-help + .slight-vertical-padding small.muted=env.t('groupID') - | {{group._id}} + |: {{group._id}} include ./challenge-box diff --git a/website/views/shared/formatting-help.jade b/website/views/shared/formatting-help.jade index c4500e03b3..9ad945093e 100644 --- a/website/views/shared/formatting-help.jade +++ b/website/views/shared/formatting-help.jade @@ -1,7 +1,7 @@ small.btn-link(ng-init='showHelp = false', ng-click='showHelp = !showHelp') | {{showHelp ? env.t('hideFormattingHelp') : env.t('showFormattingHelp')}} -.formatting-help(ng-if='showHelp') +.slight-vertical-padding(ng-if='showHelp') table.table.table-striped tr.info td.col-xs-6 #[b=env.t('youType')] From d26e4780fdaf4df1d41132717e671cc88994bf54 Mon Sep 17 00:00:00 2001 From: hairlessbear Date: Fri, 5 Jun 2015 09:26:33 -0400 Subject: [PATCH 04/16] Added links to multiple task help phrases --- common/locales/en/tasks.json | 2 +- website/views/shared/tasks/lists.jade | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/locales/en/tasks.json b/common/locales/en/tasks.json index 2353e9de2b..6d100164b6 100644 --- a/common/locales/en/tasks.json +++ b/common/locales/en/tasks.json @@ -95,5 +95,5 @@ "rewardHelp1": "The Equipment you buy for your avatar is stored in <%= linkStart %>Inventory > Equipment<%= linkEnd %>.", "rewardHelp2": "Equipment affects your stats (<%= linkStart %>Avatar > Stats<%= linkEnd %>).", "rewardHelp3": "Special equipment will appear here during World Events.", - "rewardHelp4": "Don't be afraid to set custom Rewards! Check out some samples here." + "rewardHelp4": "Don't be afraid to set custom Rewards! Check out <%= linkStart %>some samples here<%= linkEnd %>." } diff --git a/website/views/shared/tasks/lists.jade b/website/views/shared/tasks/lists.jade index 73567ff2cc..659d8bdb45 100644 --- a/website/views/shared/tasks/lists.jade +++ b/website/views/shared/tasks/lists.jade @@ -27,7 +27,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") ul li!=env.t('habitHelp1', {plusIcon:""}) li!=env.t('habitHelp2', {minusIcon:""}) - li!=env.t('habitHelp3') + li!=env.t('habitHelp3', {linkStart:"", linkEnd: ""}) li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) div(ng-switch-when='daily') ul @@ -35,21 +35,21 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") li!=env.t('dailyHelp2') li!=env.t('dailyHelp3', {emphasisStart:"", emphasisEnd:""}) li!=env.t('dailyHelp4', {linkStart:"", linkEnd:""}) - li!=env.t('dailyHelp5') + li!=env.t('dailyHelp5', {linkStart:"", linkEnd: ""}) li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) div(ng-switch-when='todo') ul li!=env.t('toDoHelp1') li!=env.t('toDoHelp2') li!=env.t('toDoHelp3') - li!=env.t('toDoHelp4') + li!=env.t('toDoHelp4', {linkStart:"", linkEnd: ""}) li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) div(ng-switch-when='reward') ul li!=env.t('rewardHelp1', {linkStart:"", linkEnd: ""}) li!=env.t('rewardHelp2', {linkStart:"", linkEnd: ""}) li!=env.t('rewardHelp3') - li!=env.t('rewardHelp4') + li!=env.t('rewardHelp4', {linkStart:"", linkEnd: ""}) li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) // Todo Chart From d415e9b0149cde09a0120b5424e34783cbd79170 Mon Sep 17 00:00:00 2001 From: hairlessbear Date: Fri, 5 Jun 2015 09:35:01 -0400 Subject: [PATCH 05/16] Slightly modified habitHelp3 --- common/locales/en/tasks.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/locales/en/tasks.json b/common/locales/en/tasks.json index 6d100164b6..5682c84be6 100644 --- a/common/locales/en/tasks.json +++ b/common/locales/en/tasks.json @@ -81,7 +81,7 @@ "dailiesRestingInInn": "You're Resting in the Inn! Your Dailies will NOT hurt you tonight, but they WILL still refresh every day. If you're in a quest, you won't deal damage/collect items until you check out of the Inn, but you can still be injured by a Boss if your Party mates skip their own Dailies.", "habitHelp1": "Good Habits are things that you do often. They award Gold and Experience every time you click the <%= plusIcon %>.", "habitHelp2": "Bad Habits are things you want to avoid doing. They remove Health every time you click the <%= minusIcon %>.", - "habitHelp3": "For inspiration, check out <%= linkStart %>these sample Habits<%= linkEnd %>.", + "habitHelp3": "For inspiration, check out these <%= linkStart %>sample Habits<%= linkEnd %>!", "newbieGuild": "More questions? Ask in the <%= linkStart %>Newbies Guild<%= linkEnd %>!", "dailyHelp1": "Dailies repeat <%= emphasisStart %>every day<%= emphasisEnd %> that they are active. Click the <%= pencilIcon %> to change the days a Daily is active.", "dailyHelp2": "If you don't complete active Dailies, you lose Health when your day rolls over.", From 16f0ece2f8d8ecb1bca801efa2288858b7a18911 Mon Sep 17 00:00:00 2001 From: hairlessbear Date: Fri, 5 Jun 2015 09:44:19 -0400 Subject: [PATCH 06/16] Removed ! from 'env.t' that don't have html characters --- website/views/shared/tasks/lists.jade | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/website/views/shared/tasks/lists.jade b/website/views/shared/tasks/lists.jade index 659d8bdb45..189a88f40f 100644 --- a/website/views/shared/tasks/lists.jade +++ b/website/views/shared/tasks/lists.jade @@ -32,23 +32,23 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") div(ng-switch-when='daily') ul li!=env.t('dailyHelp1', {emphasisStart:"", emphasisEnd:"", pencilIcon:""}) - li!=env.t('dailyHelp2') + li=env.t('dailyHelp2') li!=env.t('dailyHelp3', {emphasisStart:"", emphasisEnd:""}) li!=env.t('dailyHelp4', {linkStart:"", linkEnd:""}) li!=env.t('dailyHelp5', {linkStart:"", linkEnd: ""}) li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) div(ng-switch-when='todo') ul - li!=env.t('toDoHelp1') - li!=env.t('toDoHelp2') - li!=env.t('toDoHelp3') + li=env.t('toDoHelp1') + li=env.t('toDoHelp2') + li=env.t('toDoHelp3') li!=env.t('toDoHelp4', {linkStart:"", linkEnd: ""}) li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) div(ng-switch-when='reward') ul li!=env.t('rewardHelp1', {linkStart:"", linkEnd: ""}) li!=env.t('rewardHelp2', {linkStart:"", linkEnd: ""}) - li!=env.t('rewardHelp3') + li=env.t('rewardHelp3') li!=env.t('rewardHelp4', {linkStart:"", linkEnd: ""}) li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) From 58a816d584aa99d9ef6059e5c3712126559ce5e9 Mon Sep 17 00:00:00 2001 From: Kevin Gisi Date: Fri, 5 Jun 2015 20:54:47 -0400 Subject: [PATCH 07/16] Server-side mixpanel should only load in a production env --- website/src/utils.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/website/src/utils.js b/website/src/utils.js index 85ffb664ec..beb093e28e 100644 --- a/website/src/utils.js +++ b/website/src/utils.js @@ -179,8 +179,11 @@ module.exports.setupConfig = function(){ baseUrl = nconf.get('BASE_URL'); module.exports.ga = require('universal-analytics')(nconf.get('GA_ID')); - var mixpanel = require('mixpanel') - module.exports.mixpanel = mixpanel.init(nconf.get('MP_ID')); + + var mixpanel = isProd && require('mixpanel'); + module.exports.mixpanel = mixpanel + ? mixpanel.init(nconf.get('MP_ID')) + : { track: function() {} }; }; var algorithm = 'aes-256-ctr'; From b1b8dc18af4fd56b2e3bdfc888b631b99deef1a7 Mon Sep 17 00:00:00 2001 From: hairlessbear Date: Sun, 7 Jun 2015 13:17:57 -0400 Subject: [PATCH 08/16] Made links translatable --- common/locales/en/tasks.json | 8 ++++---- website/views/shared/tasks/lists.jade | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/locales/en/tasks.json b/common/locales/en/tasks.json index 5682c84be6..6f1f79e9a9 100644 --- a/common/locales/en/tasks.json +++ b/common/locales/en/tasks.json @@ -81,19 +81,19 @@ "dailiesRestingInInn": "You're Resting in the Inn! Your Dailies will NOT hurt you tonight, but they WILL still refresh every day. If you're in a quest, you won't deal damage/collect items until you check out of the Inn, but you can still be injured by a Boss if your Party mates skip their own Dailies.", "habitHelp1": "Good Habits are things that you do often. They award Gold and Experience every time you click the <%= plusIcon %>.", "habitHelp2": "Bad Habits are things you want to avoid doing. They remove Health every time you click the <%= minusIcon %>.", - "habitHelp3": "For inspiration, check out these <%= linkStart %>sample Habits<%= linkEnd %>!", + "habitHelp3": "For inspiration, check out these sample Habits!", "newbieGuild": "More questions? Ask in the <%= linkStart %>Newbies Guild<%= linkEnd %>!", "dailyHelp1": "Dailies repeat <%= emphasisStart %>every day<%= emphasisEnd %> that they are active. Click the <%= pencilIcon %> to change the days a Daily is active.", "dailyHelp2": "If you don't complete active Dailies, you lose Health when your day rolls over.", "dailyHelp3": "Dailies turn <%= emphasisStart %>redder<%= emphasisEnd %> when you miss them, and <%= emphasisStart %>bluer<%= emphasisEnd %> when you complete them. The redder the Daily, the more it will reward you... or hurt you.", "dailyHelp4": "To change when your day rolls over, go to <%= linkStart %> Settings > Site<%= linkEnd %> > Custom Day Start.", - "dailyHelp5": "For inspiration, check out these <%= linkStart %>sample Dailies<%= linkEnd %>!", + "dailyHelp5": "For inspiration, check out these sample Dailies!", "toDoHelp1": "To-Dos start yellow, and get redder (more valuable) the longer it takes to complete them.", "toDoHelp2": "To-Dos never hurt you! They only award Gold and Experience.", "toDoHelp3": "Breaking a To-Do down into a checklist of smaller items will make it less scary, and will increase your points!", - "toDoHelp4": "For inspiration, check out these <%= linkStart %>sample To-Dos<%= linkEnd %>!", + "toDoHelp4": "For inspiration, check out these sample To-Dos!", "rewardHelp1": "The Equipment you buy for your avatar is stored in <%= linkStart %>Inventory > Equipment<%= linkEnd %>.", "rewardHelp2": "Equipment affects your stats (<%= linkStart %>Avatar > Stats<%= linkEnd %>).", "rewardHelp3": "Special equipment will appear here during World Events.", - "rewardHelp4": "Don't be afraid to set custom Rewards! Check out <%= linkStart %>some samples here<%= linkEnd %>." + "rewardHelp4": "Don't be afraid to set custom Rewards! Check out some samples here." } diff --git a/website/views/shared/tasks/lists.jade b/website/views/shared/tasks/lists.jade index 189a88f40f..6b71c6140a 100644 --- a/website/views/shared/tasks/lists.jade +++ b/website/views/shared/tasks/lists.jade @@ -27,7 +27,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") ul li!=env.t('habitHelp1', {plusIcon:""}) li!=env.t('habitHelp2', {minusIcon:""}) - li!=env.t('habitHelp3', {linkStart:"", linkEnd: ""}) + li!=env.t('habitHelp3') li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) div(ng-switch-when='daily') ul @@ -35,21 +35,21 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") li=env.t('dailyHelp2') li!=env.t('dailyHelp3', {emphasisStart:"", emphasisEnd:""}) li!=env.t('dailyHelp4', {linkStart:"", linkEnd:""}) - li!=env.t('dailyHelp5', {linkStart:"", linkEnd: ""}) + li!=env.t('dailyHelp5') li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) div(ng-switch-when='todo') ul li=env.t('toDoHelp1') li=env.t('toDoHelp2') li=env.t('toDoHelp3') - li!=env.t('toDoHelp4', {linkStart:"", linkEnd: ""}) + li!=env.t('toDoHelp4') li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) div(ng-switch-when='reward') ul li!=env.t('rewardHelp1', {linkStart:"", linkEnd: ""}) li!=env.t('rewardHelp2', {linkStart:"", linkEnd: ""}) li=env.t('rewardHelp3') - li!=env.t('rewardHelp4', {linkStart:"", linkEnd: ""}) + li!=env.t('rewardHelp4') li!=env.t('newbieGuild', {linkStart:"", linkEnd: ""}) // Todo Chart From 099059462249c24e7181db142f511c00e3f84c36 Mon Sep 17 00:00:00 2001 From: agentx999 Date: Tue, 9 Jun 2015 10:53:54 -0700 Subject: [PATCH 09/16] removed unused text (untilNoFace) --- common/locales/en/generic.json | 1 - 1 file changed, 1 deletion(-) diff --git a/common/locales/en/generic.json b/common/locales/en/generic.json index c1aa3c2118..d92d82a524 100644 --- a/common/locales/en/generic.json +++ b/common/locales/en/generic.json @@ -70,7 +70,6 @@ "lastLoggedIn": "- Last logged in", "notPorted": "This feature is not yet ported from the original site.", "buyThis": "Buy this <%= text %> with <%= price %> of your <%= gems %> Gems?", - "untilNoFace": "Until we add Facebook, use your UUID and API Token to log in (found at https://habitrpg.com > Options > Settings).", "noReachServer": "Server not currently reachable, try again later", "errorUpCase": "ERROR:", "newPassSent": "New password sent.", From ef6fa13943b737aa1a4f1cedf0fdbf31cf78257f Mon Sep 17 00:00:00 2001 From: agentx999 Date: Tue, 9 Jun 2015 10:55:30 -0700 Subject: [PATCH 10/16] removed mention of "options" menu --- common/locales/en/quests.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/locales/en/quests.json b/common/locales/en/quests.json index c2aada5de6..41fa3627f0 100644 --- a/common/locales/en/quests.json +++ b/common/locales/en/quests.json @@ -3,7 +3,7 @@ "quest": "quest", "completed": "Completed!", "youReceived": "You've Received", - "questSend": "Clicking \"Invite\" will send an invitation to your party members. When all members have accepted or denied, the quest begins. See status under Options > Social > Party.", + "questSend": "Clicking \"Invite\" will send an invitation to your party members. When all members have accepted or denied, the quest begins. See status under Social > Party.", "inviteParty": "Invite Party", "questInvitation": "Quest Invitation: ", "questInvitationTitle": "Quest Invitation", From 87462043b6fd655f70c343fd90e19bb46b8070f6 Mon Sep 17 00:00:00 2001 From: agentx999 Date: Tue, 9 Jun 2015 10:57:22 -0700 Subject: [PATCH 11/16] changed comma to semicolon --- common/locales/en/character.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/locales/en/character.json b/common/locales/en/character.json index befd0d5f9c..25cb0e639d 100644 --- a/common/locales/en/character.json +++ b/common/locales/en/character.json @@ -48,7 +48,7 @@ "classBonusText": "Your class (Warrior, if you haven't unlocked or selected another 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.", "classEquipBonus": "Class Bonus", "battleGear": "Battle Gear", - "battleGearText": "This is the gear you wear into battle, it affects numbers when interacting with your tasks.", + "battleGearText": "This is the gear you wear into battle; it affects numbers when interacting with your tasks.", "costume": "Costume", "costumeText": "If you prefer the look of other gear to what you have equipped, check the \"Use Costume\" box to visually don a costume while wearing your battle gear underneath.", "useCostume": "Use Costume", From 738b78393cfe09ec4fb3b46dae45e5c9d6c72316 Mon Sep 17 00:00:00 2001 From: agentx999 Date: Tue, 9 Jun 2015 10:59:09 -0700 Subject: [PATCH 12/16] added a space to defaultHabit1Notes --- common/locales/en/defaultTasks.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/locales/en/defaultTasks.json b/common/locales/en/defaultTasks.json index 48e405ab6f..cf7e179494 100644 --- a/common/locales/en/defaultTasks.json +++ b/common/locales/en/defaultTasks.json @@ -1,7 +1,7 @@ { "defaultTaskNotes": " ", "defaultHabit1Text": "Productive Work (Click the pencil to edit)", - "defaultHabit1Notes": "Sample Good Habits: + Eat a vegetable +15 minutes productive work", + "defaultHabit1Notes": "Sample Good Habits: + Eat a vegetable + 15 minutes productive work", "defaultHabit2Text": "Eat Junk Food (Click the pencil to edit)", "defaultHabit2Notes": "Sample Bad Habits: - Smoke - Procrastinate", From 097e1ff70bea76a6a96bbb4bd6900b58fa0d4d8d Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 10 Jun 2015 08:18:08 -0500 Subject: [PATCH 13/16] Put popover in containing span --- website/views/shared/modals/classes.jade | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/views/shared/modals/classes.jade b/website/views/shared/modals/classes.jade index b199cd0e83..d9fdaa054d 100644 --- a/website/views/shared/modals/classes.jade +++ b/website/views/shared/modals/classes.jade @@ -67,6 +67,7 @@ script(type='text/ng-template', id='modals/chooseClass.html') .well(ng-show='selectedClass=="healer"')=env.t('healerText') .modal-footer - button.btn.btn-danger(ng-click='user.ops.disableClasses({}); $close()', popover-placement='top', popover-trigger='mouseenter', popover=env.t('optOutText'))=env.t('optOut') + span(popover-placement='left', popover-trigger='mouseenter', popover=env.t('optOutText')) + button.btn.btn-danger(ng-click='user.ops.disableClasses({}); $close()')=env.t('optOut') button.btn.btn-primary(ng-disabled='!selectedClass' ng-click='changeClass(selectedClass); $close()')=env.t('select') .pull-left!=env.t('chooseClassLearn') From ed43bec8cd8b38996bb45ed1b949e6ea46055ea0 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 10 Jun 2015 08:49:26 -0500 Subject: [PATCH 14/16] Allow default tasks to not have notes --- common/script/content.coffee | 8 ++++---- website/src/models/user.js | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/common/script/content.coffee b/common/script/content.coffee index cef86206aa..30a0760b87 100644 --- a/common/script/content.coffee +++ b/common/script/content.coffee @@ -1877,9 +1877,9 @@ _.each api.subscriptionBlocks, (b,k)->b.key = k repeat = {m:true,t:true,w:true,th:true,f:true,s:true,su:true} api.userDefaults = habits: [ - {type: 'habit', text: t('defaultHabit1Text'), notes: t('defaultTaskNotes'), value: 0, up: true, down: false, attribute: 'per' } - {type: 'habit', text: t('defaultHabit2Text'), notes: t('defaultTaskNotes'), value: 0, up: false, down: true, attribute: 'str'} - {type: 'habit', text: t('defaultHabit3Text'), notes: t('defaultTaskNotes'), value: 0, up: true, down: true, attribute: 'str'} + {type: 'habit', text: t('defaultHabit1Text'), value: 0, up: true, down: false, attribute: 'per' } + {type: 'habit', text: t('defaultHabit2Text'), value: 0, up: false, down: true, attribute: 'str'} + {type: 'habit', text: t('defaultHabit3Text'), value: 0, up: true, down: true, attribute: 'str'} ] dailys: [ @@ -1898,7 +1898,7 @@ api.userDefaults = ] rewards: [ - {type: 'reward', text: t('defaultReward1Text'), notes: t('defaultTaskNotes'), value: 10 } + {type: 'reward', text: t('defaultReward1Text'), value: 10 } # {type: 'reward', text: t('defaultReward2Text'), notes: t('defaultReward2Notes'), value: 10 } ] diff --git a/website/src/models/user.js b/website/src/models/user.js index b24acfd886..634bb61f07 100644 --- a/website/src/models/user.js +++ b/website/src/models/user.js @@ -406,7 +406,7 @@ var UserSchema = new Schema({ rewards: {type:[TaskSchemas.RewardSchema]}, extra: Schema.Types.Mixed, - + pushDevices: {type: [{ regId: {type: String}, type: {type: String} @@ -459,7 +459,9 @@ UserSchema.pre('save', function(next) { newTask.name = newTask.name(self.preferences.language); }else{ newTask.text = newTask.text(self.preferences.language); - newTask.notes = newTask.notes(self.preferences.language); + if(newTask.notes) { + newTask.notes = newTask.notes(self.preferences.language); + } if(newTask.checklist){ newTask.checklist = _.map(newTask.checklist, function(checklistItem){ From 8dde41d18a49efa3010ad9feead60a2fe1df04b3 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 10 Jun 2015 23:39:46 -0500 Subject: [PATCH 15/16] Wrie and refactor guild tests --- test/api/groups.coffee | 109 +++++++++++++++++++----------- website/src/controllers/groups.js | 2 +- 2 files changed, 71 insertions(+), 40 deletions(-) diff --git a/test/api/groups.coffee b/test/api/groups.coffee index 40de0e4077..6c2d922476 100644 --- a/test/api/groups.coffee +++ b/test/api/groups.coffee @@ -6,16 +6,16 @@ Group = require("../../website/src/models/group").model app = require("../../website/src/server") describe "Guilds", -> - before (done) -> - registerNewUser -> - User.findByIdAndUpdate user._id, - $set: - "balance": 10 - , (err, _user) -> - done() - , true - context "creating groups", -> + before (done) -> + registerNewUser -> + User.findByIdAndUpdate user._id, + $set: + "balance": 10 + , (err, _user) -> + done() + , true + it "can create a public guild", (done) -> request.post(baseURL + "/groups").send( name: "TestGroup" @@ -53,19 +53,42 @@ describe "Guilds", -> done() , false - context "finding groups", -> - it "can find a guild", (done) -> - guild = undefined + context "get guilds", -> + guild = undefined + + beforeEach (done)-> request.post(baseURL + "/groups").send( name: "TestGroup2" type: "guild" ).end (res) -> guild = res.body - request.get(baseURL + "/groups/" + guild._id) - .send() + done() + + it "can find a guild", (done) -> + request.get(baseURL + "/groups/" + guild._id) .end (res) -> expectCode res, 200 - expect(guild._id).to.equal res.body._id + expect(res.body._id).to.equal res.body._id + done() + + it "transforms members array to an arrray of user objects", (done) -> + request.get(baseURL + "/groups/" + guild._id) + .end (res) -> + expectCode res, 200 + members = res.body.members + # @TODO: would be more instructive if it had more members in guild :( + _(members).each (member) -> + expect(member).to.be.an 'object' + expect(member.profile.name).to.exist + done() + + it "transforms leader id to a user object", (done) -> + request.get(baseURL + "/groups/" + guild._id) + .end (res) -> + expectCode res, 200 + leader = res.body.leader + expect(leader).to.be.an 'object' + expect(leader.profile.name).to.exist done() it "can list guilds", (done) -> @@ -228,38 +251,46 @@ describe "Guilds", -> describe "Public Guilds", -> guild = undefined before (done) -> - request.post(baseURL + "/groups").send( - name: "TestPublicGroup" - type: "guild" - privacy: "public" - ).end (res) -> - expectCode res, 200 - guild = res.body - expect(guild.members.length).to.equal 1 - expect(guild.leader).to.equal user._id - #Add members to guild - async.waterfall [ - (cb) -> - registerManyUsers 15, cb + async.waterfall [ + (cb) -> + registerNewUser -> + User.findByIdAndUpdate user._id, {$set: { "balance": 10 } }, (err, _user) -> + cb() + , true + (cb) -> + request.post(baseURL + "/groups").send( + name: "TestPublicGroup" + type: "guild" + privacy: "public" + ).end (res) -> + guild = res.body + expect(guild.members.length).to.equal 1 + expect(guild.leader).to.equal user._id + #Add members to guild + cb() - (_members, cb) -> - members = _members + (cb) -> + registerManyUsers 15, cb - joinGuild = (member, callback) -> - request.post(baseURL + "/groups/" + guild._id + "/join") - .set("X-API-User", member._id) - .set("X-API-Key", member.apiToken) - .end -> - callback(null, null) + (_members, cb) -> + members = _members - async.map members, joinGuild, (err, results) -> cb() - ], done + joinGuild = (member, callback) -> + request.post(baseURL + "/groups/" + guild._id + "/join") + .set("X-API-User", member._id) + .set("X-API-Key", member.apiToken) + .end -> + callback(null, null) + + async.map members, joinGuild, (err, results) -> cb() + + ], done context "is a member", -> before (done) -> registerNewUser -> request.post(baseURL + "/groups/" + guild._id + "/join") - .end -> + .end (res)-> done() , true diff --git a/website/src/controllers/groups.js b/website/src/controllers/groups.js index 6c4bb13fed..acb893b1ec 100644 --- a/website/src/controllers/groups.js +++ b/website/src/controllers/groups.js @@ -40,8 +40,8 @@ var populateQuery = function(type, q, additionalFields){ q.populate('members', partyFields + (additionalFields ? (' ' + additionalFields) : '')); else q.populate(guildPopulate); - q.populate('invites', nameFields); q.populate('leader', nameFields); + q.populate('invites', nameFields); q.populate({ path: 'challenges', match: (type=='habitrpg') ? {_id:{$ne:'95533e05-1ff9-4e46-970b-d77219f199e9'}} : undefined, // remove the Spread the Word Challenge for now, will revisit when we fix the closing-challenge bug From 5d84ead3f86b883d5357512057ec65f500c8d8df Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Thu, 11 Jun 2015 22:17:34 +0200 Subject: [PATCH 16/16] add image for bulk email --- .../emails/images/PROMO-Enchanted-Armoire-v1.png | Bin 0 -> 9225 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 website/public/emails/images/PROMO-Enchanted-Armoire-v1.png diff --git a/website/public/emails/images/PROMO-Enchanted-Armoire-v1.png b/website/public/emails/images/PROMO-Enchanted-Armoire-v1.png new file mode 100644 index 0000000000000000000000000000000000000000..9a42b70e4288cc39bc8da49e52d0c047129a6267 GIT binary patch literal 9225 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 literal 0 HcmV?d00001