Notifications v2 and Bailey API (#9716)
* Added initial bailey api
* wip
* implement new panel header
* Fixed lint
* add ability to mark notification as seen
* add notification count, remove top badge from user and add ability to mark multiple notifications as seen
* add support dismissall and mark all as read
* do not dismiss actionable notif
* mark as seen when menu is opened instead of closed
* implement ordering, list of actionable notifications
* add groups messages and fix badges count
* add notifications for received cards
* send card received notification to target not sender
* rename notificaion field
* fix integration tests
* mark cards notifications as read and update tests
* add mystery items notifications
* add unallocated stats points notifications
* fix linting
* simplify code
* refactoring and fixes
* fix dropdown opening
* start splitting notifications into their own component
* add notifications for inbox messages
* fix unit tests
* fix default buttons styles
* add initial bailey support
* add title and tests to new stuff notification
* add notification if a group task needs more work
* add tests and fixes for marking a task as needing more work
* make sure user._v is updated
* remove console.log
* notification: hover status and margins
* start styling notifications, add separate files and basic functionalities
* fix tests
* start adding mystery items notification
* wip card notification
* fix cards text
* initial implementation inbox messages
* initial implementation group messages
* disable inbox notifications until mobile is ready
* wip group chat messages
* finish mystery and card notifications
* add bailey notification and fix a lot of stuff
* start adding guilds and parties invitations
* misc invitation fixes
* fix lint issues
* remove old code and add key to notifications
* fix tests
* remove unused code
* add link for public guilds invite
* starts to implement needs work notification design and feature
* fixes to needs work, add group task approved notification
* finish needs work feature
* lots of fixes
* implement quest notification
* bailey fixes and static page
* routing fixes
* fixes # this.$store.dispatch(guilds:join, {groupId: group.id, type: party});
* read notifications on click
* chat notifications
* fix tests for chat notifications
* fix chat notification test
* fix tests
* fix tests (again)
* try awaiting
* remove only
* more sleep
* add bailey tests
* fix icons alignment
* fix issue with multiple points notifications
* remove merge code
* fix rejecting guild invitation
* make remove area bigger
* fix error with notifications and add migration
* fix migration
* fix typos
* add cleanup migration too
* notifications empty state, new counter color, fix marking messages as seen in guilds
* fixes
* add image and install correct packages
* fix mongoose version
* update bailey
* typo
* make sure chat is marked as read after other requests
This commit is contained in:
@@ -64,7 +64,7 @@
|
||||
"groupPlansTitle": "Group Plans",
|
||||
"newGroupTitle": "New Group",
|
||||
"subscriberItem": "Mystery Item",
|
||||
"newSubscriberItem": "New Mystery Item",
|
||||
"newSubscriberItem": "You have new <span class=\"notification-bold-blue\">Mystery Items</span>",
|
||||
"subscriberItemText": "Each month, subscribers will receive a mystery item. This is usually released about one week before the end of the month. See the wiki's 'Mystery Item' page for more information.",
|
||||
"all": "All",
|
||||
"none": "None",
|
||||
@@ -173,8 +173,7 @@
|
||||
"achievementBewilderText": "Helped defeat the Be-Wilder during the 2016 Spring Fling Event!",
|
||||
"checkOutProgress": "Check out my progress in Habitica!",
|
||||
"cards": "Cards",
|
||||
"cardReceived": "Received a card!",
|
||||
"cardReceivedFrom": "<%= cardType %> from <%= userName %>",
|
||||
"cardReceived": "You received a <span class=\"notification-bold-blue\"><%= card %></span>",
|
||||
"greetingCard": "Greeting Card",
|
||||
"greetingCardExplanation": "You both receive the Cheery Chum achievement!",
|
||||
"greetingCardNotes": "Send a greeting card to a party member.",
|
||||
@@ -281,10 +280,11 @@
|
||||
"spirituality": "Spirituality",
|
||||
"time_management": "Time-Management + Accountability",
|
||||
"recovery_support_groups": "Recovery + Support Groups",
|
||||
|
||||
"dismissAll": "Dismiss All",
|
||||
"messages": "Messages",
|
||||
"emptyMessagesLine1": "You don't have any messages",
|
||||
"emptyMessagesLine2": "Send a message to start a conversation!",
|
||||
"userSentMessage": "<span class=\"notification-bold\"><%= user %></span> sent you a message",
|
||||
"letsgo": "Let's Go!",
|
||||
"selected": "Selected",
|
||||
"howManyToBuy": "How many would you like to buy?",
|
||||
|
||||
@@ -48,8 +48,9 @@
|
||||
"userId": "User ID",
|
||||
"invite": "Invite",
|
||||
"leave": "Leave",
|
||||
"invitedTo": "Invited to <%= name %>",
|
||||
"invitedToNewParty": "You were invited to join a party! Do you want to leave this party, reject all other party invitations and join <%= partyName %>?",
|
||||
"invitedToParty": "You were invited to join the Party <span class=\"notification-bold\"><%= party %></span>",
|
||||
"invitedToPrivateGuild": "You were invited to join the private Guild <span class=\"notification-bold\"><%= guild %></span>",
|
||||
"invitedToPublicGuild": "You were invited to join the Guild <span class=\"notification-bold-blue\"><%= guild %></span>",
|
||||
"partyInvitationsText": "You have <%= numberInvites %> party invitations! Choose wisely, because you can only be in one party at a time.",
|
||||
"joinPartyConfirmationText": "Are you sure you want to join the party \"<%= partyName %>\"? You can only be in one party at a time. If you join, all other party invitations will be rejected.",
|
||||
"invitationAcceptedHeader": "Your Invitation has been Accepted",
|
||||
@@ -61,7 +62,8 @@
|
||||
"partyLoading3": "Your party is gathering. Please wait...",
|
||||
"partyLoading4": "Your party is materializing. Please wait...",
|
||||
"systemMessage": "System Message",
|
||||
"newMsg": "New message in \"<%= name %>\"",
|
||||
"newMsgGuild": "There are new posts in the Guild <span class=\"notification-bold-blue\"><%= name %></span>",
|
||||
"newMsgParty": "There are new posts in your Party <span class=\"notification-bold-blue\"><%= name %></span>",
|
||||
"chat": "Chat",
|
||||
"sendChat": "Send Chat",
|
||||
"toolTipMsg": "Fetch Recent Messages",
|
||||
@@ -154,8 +156,6 @@
|
||||
"copyAsTodo": "Copy as To-Do",
|
||||
"messageAddedAsToDo": "Message copied as To-Do.",
|
||||
"messageWroteIn": "<%= user %> wrote in <%= group %>",
|
||||
"taskFromInbox": "<%= from %> wrote '<%= message %>'",
|
||||
"taskTextFromInbox": "Message from <%= from %>",
|
||||
"msgPreviewHeading": "Message Preview",
|
||||
"leaderOnlyChallenges": "Only group leader can create challenges",
|
||||
"sendGift": "Send Gift",
|
||||
@@ -246,6 +246,7 @@
|
||||
"confirmClaim": "Are you sure you want to claim this task?",
|
||||
"confirmUnClaim": "Are you sure you want to unclaim this task?",
|
||||
"confirmApproval": "Are you sure you want to approve this task?",
|
||||
"confirmNeedsWork": "Are you sure you want to mark this task as needing work?",
|
||||
"userRequestsApproval": "<%= userName %> requests approval",
|
||||
"userCountRequestsApproval": "<%= userCount %> request approval",
|
||||
"youAreRequestingApproval": "You are requesting approval",
|
||||
@@ -264,10 +265,15 @@
|
||||
"assignTask": "Assign Task",
|
||||
"desktopNotificationsText": "We need your permission to enable desktop notifications for new messages in party chat! Follow your browser's instructions to turn them on.<br><br>You'll receive these notifications only while you have Habitica open. If you decide you don't like them, they can be disabled in your browser's settings.<br><br>This box will close automatically when a decision is made.",
|
||||
"claim": "Claim",
|
||||
"removeClaim": "Remove Claim",
|
||||
"onlyGroupLeaderCanManageSubscription": "Only the group leader can manage the group's subscription",
|
||||
"yourTaskHasBeenApproved": "Your task \"<%= taskText %>\" has been approved",
|
||||
"userHasRequestedTaskApproval": "<%= user %> has requested task approval for <%= taskName %>",
|
||||
"yourTaskHasBeenApproved": "Your task <span class=\"notification-green\"><%= taskText %></span> has been approved.",
|
||||
"taskNeedsWork": "<span class=\"notification-bold\"><%= managerName %></span> marked <span class=\"notification-bold\"><%= taskText %></span> as needing additional work.",
|
||||
"userHasRequestedTaskApproval": "<span class=\"notification-bold\"><%= user %></span> requests approval for <span class=\"notification-bold\"><%= taskName %></span>",
|
||||
"approve": "Approve",
|
||||
"approveTask": "Approve Task",
|
||||
"needsWork": "Needs Work",
|
||||
"viewRequests": "View Requests",
|
||||
"approvalTitle": "<%= userName %> has completed <%= type %>: \"<%= text %>\"",
|
||||
"confirmTaskApproval": "Do you want to reward <%= username %> for completing this task?",
|
||||
"groupSubscriptionPrice": "$9 every month + $3 a month for every additional group member",
|
||||
|
||||
@@ -66,5 +66,7 @@
|
||||
"messageNotificationNotFound": "Notification not found.",
|
||||
|
||||
"notificationsRequired": "Notification ids are required.",
|
||||
"unallocatedStatsPoints": "You have <span class=\"notification-bold-blue\"><%= points %> unallocated Stat Points</span>",
|
||||
|
||||
"beginningOfConversation": "This is the beginning of your conversation with <%= userName %>. Remember to be kind, respectful, and follow the Community Guidelines!"
|
||||
}
|
||||
|
||||
@@ -102,8 +102,9 @@
|
||||
"alreadyUnlockedPart": "Full set already partially unlocked.",
|
||||
|
||||
"USD": "(USD)",
|
||||
"newStuff": "New Stuff by [Bailey](https://twitter.com/Mihakuu)",
|
||||
"cool": "Tell Me Later",
|
||||
"newStuff": "New Stuff by <a href=\"https://twitter.com/Mihakuu\" target=\"_blank\">Bailey</a>",
|
||||
"newBaileyUpdate": "New Bailey Update!",
|
||||
"tellMeLater": "Tell Me Later",
|
||||
"dismissAlert": "Dismiss This Alert",
|
||||
"donateText1": "Adds 20 Gems to your account. Gems are used to buy special in-game items, such as shirts and hairstyles.",
|
||||
"donateText2": "Help support Habitica",
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"questInvitation": "Quest Invitation: ",
|
||||
"questInvitationTitle": "Quest Invitation",
|
||||
"questInvitationInfo": "Invitation for the Quest <%= quest %>",
|
||||
"invitedToQuest": "You were invited to the Quest <span class=\"notification-bold-blue\"><%= quest %></span>",
|
||||
"askLater": "Ask Later",
|
||||
"questLater": "Quest Later",
|
||||
"buyQuest": "Buy Quest",
|
||||
|
||||
@@ -172,6 +172,7 @@
|
||||
"habitCounterDown": "Negative Counter (Resets <%= frequency %>)",
|
||||
"taskRequiresApproval": "This task must be approved before you can complete it. Approval has already been requested",
|
||||
"taskApprovalHasBeenRequested": "Approval has been requested",
|
||||
"taskApprovalWasNotRequested": "Only a task waiting for approval can be marked as needing more work",
|
||||
"approvals": "Approvals",
|
||||
"approvalRequired": "Needs Approval",
|
||||
"repeatZero": "Daily is never due",
|
||||
|
||||
@@ -399,9 +399,16 @@ spells.special = {
|
||||
}
|
||||
|
||||
if (!target.items.special.nyeReceived) target.items.special.nyeReceived = [];
|
||||
target.items.special.nyeReceived.push(user.profile.name);
|
||||
const senderName = user.profile.name;
|
||||
target.items.special.nyeReceived.push(senderName);
|
||||
|
||||
if (!target.flags) target.flags = {};
|
||||
if (target.addNotification) target.addNotification('CARD_RECEIVED', {
|
||||
card: 'nye',
|
||||
from: {
|
||||
id: user._id,
|
||||
name: senderName,
|
||||
},
|
||||
});
|
||||
target.flags.cardReceived = true;
|
||||
|
||||
user.stats.gp -= 10;
|
||||
@@ -427,9 +434,16 @@ spells.special = {
|
||||
}
|
||||
|
||||
if (!target.items.special.valentineReceived) target.items.special.valentineReceived = [];
|
||||
target.items.special.valentineReceived.push(user.profile.name);
|
||||
const senderName = user.profile.name;
|
||||
target.items.special.valentineReceived.push(senderName);
|
||||
|
||||
if (!target.flags) target.flags = {};
|
||||
if (target.addNotification) target.addNotification('CARD_RECEIVED', {
|
||||
card: 'valentine',
|
||||
from: {
|
||||
id: user._id,
|
||||
name: senderName,
|
||||
},
|
||||
});
|
||||
target.flags.cardReceived = true;
|
||||
|
||||
user.stats.gp -= 10;
|
||||
@@ -445,6 +459,7 @@ spells.special = {
|
||||
notes: t('greetingCardNotes'),
|
||||
cast (user, target) {
|
||||
if (user === target) {
|
||||
if (!user.achievements.greeting) user.achievements.greeting = 0;
|
||||
user.achievements.greeting++;
|
||||
} else {
|
||||
each([user, target], (u) => {
|
||||
@@ -454,9 +469,16 @@ spells.special = {
|
||||
}
|
||||
|
||||
if (!target.items.special.greetingReceived) target.items.special.greetingReceived = [];
|
||||
target.items.special.greetingReceived.push(user.profile.name);
|
||||
const senderName = user.profile.name;
|
||||
target.items.special.greetingReceived.push(senderName);
|
||||
|
||||
if (!target.flags) target.flags = {};
|
||||
if (target.addNotification) target.addNotification('CARD_RECEIVED', {
|
||||
card: 'greeting',
|
||||
from: {
|
||||
id: user._id,
|
||||
name: senderName,
|
||||
},
|
||||
});
|
||||
target.flags.cardReceived = true;
|
||||
|
||||
user.stats.gp -= 10;
|
||||
@@ -482,9 +504,16 @@ spells.special = {
|
||||
}
|
||||
|
||||
if (!target.items.special.thankyouReceived) target.items.special.thankyouReceived = [];
|
||||
target.items.special.thankyouReceived.push(user.profile.name);
|
||||
const senderName = user.profile.name;
|
||||
target.items.special.thankyouReceived.push(senderName);
|
||||
|
||||
if (!target.flags) target.flags = {};
|
||||
if (target.addNotification) target.addNotification('CARD_RECEIVED', {
|
||||
card: 'thankyou',
|
||||
from: {
|
||||
id: user._id,
|
||||
name: senderName,
|
||||
},
|
||||
});
|
||||
target.flags.cardReceived = true;
|
||||
|
||||
user.stats.gp -= 10;
|
||||
@@ -510,9 +539,16 @@ spells.special = {
|
||||
}
|
||||
|
||||
if (!target.items.special.birthdayReceived) target.items.special.birthdayReceived = [];
|
||||
target.items.special.birthdayReceived.push(user.profile.name);
|
||||
const senderName = user.profile.name;
|
||||
target.items.special.birthdayReceived.push(senderName);
|
||||
|
||||
if (!target.flags) target.flags = {};
|
||||
if (target.addNotification) target.addNotification('CARD_RECEIVED', {
|
||||
card: 'birthday',
|
||||
from: {
|
||||
id: user._id,
|
||||
name: senderName,
|
||||
},
|
||||
});
|
||||
target.flags.cardReceived = true;
|
||||
|
||||
user.stats.gp -= 10;
|
||||
@@ -538,9 +574,16 @@ spells.special = {
|
||||
}
|
||||
|
||||
if (!target.items.special.congratsReceived) target.items.special.congratsReceived = [];
|
||||
target.items.special.congratsReceived.push(user.profile.name);
|
||||
const senderName = user.profile.name;
|
||||
target.items.special.congratsReceived.push(senderName);
|
||||
|
||||
if (!target.flags) target.flags = {};
|
||||
if (target.addNotification) target.addNotification('CARD_RECEIVED', {
|
||||
card: 'congrats',
|
||||
from: {
|
||||
id: user._id,
|
||||
name: senderName,
|
||||
},
|
||||
});
|
||||
target.flags.cardReceived = true;
|
||||
|
||||
user.stats.gp -= 10;
|
||||
@@ -566,9 +609,16 @@ spells.special = {
|
||||
}
|
||||
|
||||
if (!target.items.special.getwellReceived) target.items.special.getwellReceived = [];
|
||||
target.items.special.getwellReceived.push(user.profile.name);
|
||||
const senderName = user.profile.name;
|
||||
target.items.special.getwellReceived.push(senderName);
|
||||
|
||||
if (!target.flags) target.flags = {};
|
||||
if (target.addNotification) target.addNotification('CARD_RECEIVED', {
|
||||
card: 'getwell',
|
||||
from: {
|
||||
id: user._id,
|
||||
name: senderName,
|
||||
},
|
||||
});
|
||||
target.flags.cardReceived = true;
|
||||
|
||||
user.stats.gp -= 10;
|
||||
@@ -594,9 +644,16 @@ spells.special = {
|
||||
}
|
||||
|
||||
if (!target.items.special.goodluckReceived) target.items.special.goodluckReceived = [];
|
||||
target.items.special.goodluckReceived.push(user.profile.name);
|
||||
const senderName = user.profile.name;
|
||||
target.items.special.goodluckReceived.push(senderName);
|
||||
|
||||
if (!target.flags) target.flags = {};
|
||||
if (target.addNotification) target.addNotification('CARD_RECEIVED', {
|
||||
card: 'goodluck',
|
||||
from: {
|
||||
id: user._id,
|
||||
name: senderName,
|
||||
},
|
||||
});
|
||||
target.flags.cardReceived = true;
|
||||
|
||||
user.stats.gp -= 10;
|
||||
|
||||
@@ -43,7 +43,6 @@ module.exports = function buyMysterySet (user, req = {}, analytics) {
|
||||
|
||||
user.purchased.plan.consecutive.trinkets--;
|
||||
|
||||
|
||||
return [
|
||||
{ items: user.items, purchasedPlanConsecutive: user.purchased.plan.consecutive },
|
||||
i18n.t('hourglassPurchaseSet', req.language),
|
||||
|
||||
@@ -5,13 +5,24 @@ import {
|
||||
} from '../libs/errors';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
|
||||
function markNotificationAsRead (user) {
|
||||
const index = user.notifications.findIndex(notification => {
|
||||
return notification.type === 'NEW_MYSTERY_ITEMS';
|
||||
});
|
||||
|
||||
if (index !== -1) user.notifications.splice(index, 1);
|
||||
}
|
||||
|
||||
module.exports = function openMysteryItem (user, req = {}, analytics) {
|
||||
let item = user.purchased.plan.mysteryItems.shift();
|
||||
const mysteryItems = user.purchased.plan.mysteryItems;
|
||||
let item = mysteryItems.shift();
|
||||
|
||||
if (!item) {
|
||||
throw new BadRequest(i18n.t('mysteryItemIsEmpty', req.language));
|
||||
}
|
||||
|
||||
if (mysteryItems.length === 0) markNotificationAsRead(user);
|
||||
|
||||
item = cloneDeep(content.gear.flat[item]);
|
||||
user.items.gear.owned[item.key] = true;
|
||||
|
||||
|
||||
@@ -7,6 +7,19 @@ import {
|
||||
} from '../libs/errors';
|
||||
import content from '../content/index';
|
||||
|
||||
// @TODO move in the servercontroller or keep here?
|
||||
function markNotificationAsRead (user, cardType) {
|
||||
const indexToRemove = user.notifications.findIndex(notification => {
|
||||
if (
|
||||
notification.type === 'CARD_RECEIVED' &&
|
||||
notification.data.card === cardType
|
||||
) return true;
|
||||
});
|
||||
|
||||
if (indexToRemove !== -1) user.notifications.splice(indexToRemove, 1);
|
||||
}
|
||||
|
||||
|
||||
module.exports = function readCard (user, req = {}) {
|
||||
let cardType = get(req.params, 'cardType');
|
||||
|
||||
@@ -21,6 +34,8 @@ module.exports = function readCard (user, req = {}) {
|
||||
user.items.special[`${cardType}Received`].shift();
|
||||
user.flags.cardReceived = false;
|
||||
|
||||
markNotificationAsRead(user, cardType);
|
||||
|
||||
return [
|
||||
{ specialItems: user.items.special, cardReceived: user.flags.cardReceived },
|
||||
i18n.t('readCard', {cardType}, req.language),
|
||||
|
||||
Reference in New Issue
Block a user