mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-15 13:47:33 +01:00
* Added text to locale * Added achievement to content and libs * Added achievement modal * Added achievement to notification model and controller * Added achievement to user schema * Grant achievement to inviter when user registers using emailed link * Fix icon name * Added integration test * Fix linting * Added sprite
This commit is contained in:
@@ -516,6 +516,28 @@ describe('POST /user/auth/local/register', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('awards achievement to inviter', async () => {
|
||||||
|
let { group, groupLeader } = await createAndPopulateGroup({
|
||||||
|
groupDetails: { type: 'party', privacy: 'private' },
|
||||||
|
});
|
||||||
|
|
||||||
|
let invite = encrypt(JSON.stringify({
|
||||||
|
id: group._id,
|
||||||
|
inviter: groupLeader._id,
|
||||||
|
sentAt: Date.now(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
await api.post(`/user/auth/local/register?groupInvite=${invite}`, {
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
confirmPassword: password,
|
||||||
|
});
|
||||||
|
|
||||||
|
await groupLeader.sync();
|
||||||
|
expect(groupLeader.achievements.invitedFriend).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
it('user not added to a party on expired invite', async () => {
|
it('user not added to a party on expired invite', async () => {
|
||||||
let { group, groupLeader } = await createAndPopulateGroup({
|
let { group, groupLeader } = await createAndPopulateGroup({
|
||||||
groupDetails: { type: 'party', privacy: 'private' },
|
groupDetails: { type: 'party', privacy: 'private' },
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
@@ -228,6 +228,10 @@ habitrpg.controller('NotificationCtrl',
|
|||||||
$rootScope.playSound('Achievement_Unlocked');
|
$rootScope.playSound('Achievement_Unlocked');
|
||||||
Achievement.displayAchievement('joinedChallenge', {size: 'md'});
|
Achievement.displayAchievement('joinedChallenge', {size: 'md'});
|
||||||
break;
|
break;
|
||||||
|
case 'INVITED_FRIEND_ACHIEVEMENT':
|
||||||
|
$rootScope.playSound('Achievement_Unlocked');
|
||||||
|
Achievement.displayAchievement('invitedFriend', {size: 'md'});
|
||||||
|
break;
|
||||||
case 'NEW_CONTRIBUTOR_LEVEL':
|
case 'NEW_CONTRIBUTOR_LEVEL':
|
||||||
$rootScope.playSound('Achievement_Unlocked');
|
$rootScope.playSound('Achievement_Unlocked');
|
||||||
Achievement.displayAchievement('contributor', {size: 'md'});
|
Achievement.displayAchievement('contributor', {size: 'md'});
|
||||||
|
|||||||
@@ -149,6 +149,8 @@
|
|||||||
"sendInvitations": "Send Invitations",
|
"sendInvitations": "Send Invitations",
|
||||||
"invitationsSent": "Invitations sent!",
|
"invitationsSent": "Invitations sent!",
|
||||||
"invitationSent": "Invitation sent!",
|
"invitationSent": "Invitation sent!",
|
||||||
|
"invitedFriend": "Invited a Friend",
|
||||||
|
"invitedFriendText": "This user invited a friend (or friends) who joined them on their adventure!",
|
||||||
"inviteAlertInfo2": "Or share this link (copy/paste):",
|
"inviteAlertInfo2": "Or share this link (copy/paste):",
|
||||||
"inviteLimitReached": "You have already sent the maximum number of email invitations. We have a limit to prevent spamming, however if you would like more, please contact us at <%= techAssistanceEmail %> and we'll be happy to discuss it!",
|
"inviteLimitReached": "You have already sent the maximum number of email invitations. We have a limit to prevent spamming, however if you would like more, please contact us at <%= techAssistanceEmail %> and we'll be happy to discuss it!",
|
||||||
"sendGiftHeading": "Send Gift to <%= name %>",
|
"sendGiftHeading": "Send Gift to <%= name %>",
|
||||||
|
|||||||
@@ -112,6 +112,11 @@ let basicAchievs = {
|
|||||||
titleKey: 'joinedChallenge',
|
titleKey: 'joinedChallenge',
|
||||||
textKey: 'joinedChallengeText',
|
textKey: 'joinedChallengeText',
|
||||||
},
|
},
|
||||||
|
invitedFriend: {
|
||||||
|
icon: 'achievement-friends',
|
||||||
|
titleKey: 'invitedFriend',
|
||||||
|
textKey: 'invitedFriendText',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
Object.assign(achievementsData, basicAchievs);
|
Object.assign(achievementsData, basicAchievs);
|
||||||
|
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ function _getBasicAchievements (user, language) {
|
|||||||
_addSimple(result, user, {path: 'joinedGuild', language});
|
_addSimple(result, user, {path: 'joinedGuild', language});
|
||||||
_addSimple(result, user, {path: 'royallyLoyal', language});
|
_addSimple(result, user, {path: 'royallyLoyal', language});
|
||||||
_addSimple(result, user, {path: 'joinedChallenge', language});
|
_addSimple(result, user, {path: 'joinedChallenge', language});
|
||||||
|
_addSimple(result, user, {path: 'invitedFriend', language});
|
||||||
|
|
||||||
_addSimpleWithMasterCount(result, user, {path: 'beastMaster', language});
|
_addSimpleWithMasterCount(result, user, {path: 'beastMaster', language});
|
||||||
_addSimpleWithMasterCount(result, user, {path: 'mountMaster', language});
|
_addSimpleWithMasterCount(result, user, {path: 'mountMaster', language});
|
||||||
|
|||||||
@@ -49,6 +49,14 @@ async function _handleGroupInvitation (user, invite) {
|
|||||||
} else {
|
} else {
|
||||||
user.invitations.guilds.push({id: group._id, name: group.name, inviter});
|
user.invitations.guilds.push({id: group._id, name: group.name, inviter});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// award the inviter with 'Invited a Friend' achievement
|
||||||
|
inviter = await User.findById(inviter);
|
||||||
|
if (!inviter.achievements.invitedFriend) {
|
||||||
|
inviter.achievements.invitedFriend = true;
|
||||||
|
inviter.addNotification('INVITED_FRIEND_ACHIEVEMENT');
|
||||||
|
await inviter.save();
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err);
|
logger.error(err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ let schema = new Schema({
|
|||||||
royallyLoyal: Boolean,
|
royallyLoyal: Boolean,
|
||||||
joinedGuild: Boolean,
|
joinedGuild: Boolean,
|
||||||
joinedChallenge: Boolean,
|
joinedChallenge: Boolean,
|
||||||
|
invitedFriend: Boolean,
|
||||||
},
|
},
|
||||||
|
|
||||||
backer: {
|
backer: {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ const NOTIFICATION_TYPES = [
|
|||||||
'GUILD_PROMPT',
|
'GUILD_PROMPT',
|
||||||
'GUILD_JOINED_ACHIEVEMENT',
|
'GUILD_JOINED_ACHIEVEMENT',
|
||||||
'CHALLENGE_JOINED_ACHIEVEMENT',
|
'CHALLENGE_JOINED_ACHIEVEMENT',
|
||||||
|
'INVITED_FRIEND_ACHIEVEMENT',
|
||||||
];
|
];
|
||||||
|
|
||||||
const Schema = mongoose.Schema;
|
const Schema = mongoose.Schema;
|
||||||
|
|||||||
@@ -174,3 +174,14 @@ script(id='modals/achievements/joinedChallenge.html', type='text/ng-template')
|
|||||||
br
|
br
|
||||||
button.btn.btn-primary(ng-click='$close()')=env.t('huzzah')
|
button.btn.btn-primary(ng-click='$close()')=env.t('huzzah')
|
||||||
+achievementFooter
|
+achievementFooter
|
||||||
|
|
||||||
|
// Invited Friend
|
||||||
|
script(id='modals/achievements/invitedFriend.html', type='text/ng-template')
|
||||||
|
.modal-content(style='min-width:28em')
|
||||||
|
.modal-body.text-center
|
||||||
|
h3(style='margin-bottom:0')=env.t('modalAchievement')
|
||||||
|
+achievementAvatar('friends',0)
|
||||||
|
p=env.t('invitedFriendText')
|
||||||
|
br
|
||||||
|
button.btn.btn-primary(ng-click='$close()')=env.t('huzzah')
|
||||||
|
+achievementFooter
|
||||||
|
|||||||
Reference in New Issue
Block a user