Files
habitica/website/client/components/notificationMenu.vue
Keith Holliday f529a5c64c New client many fixes (#8981)
* Footer style fixes

* Limited string display

* Fixed background reload

* Began adding more avatar items

* Fixed challenge updated cats and official to be seen by admins

* Fixed min prize

* Fixed required fields

* Added my challenges and find challenges to menu

* Removed nav to party page when have no party

* Updated user and notifications icon

* Added accept, reject and messages

* Added selfcare

* Underline links

* Added forgot password

* Fixed task adding

* Disabled habit options that should be

* Added markdown to tags

* Added confirm to delete

* Fixed cancel/delete style

* Fixed rounding

* Added gold icon

* Fixed task icon styles

* Fixed margin botton

* Fixed some repeat styles

* Fixed custom reward style

* Hide like count 0

* Added new tavern images

* Redirect to party page after create

* Hid leader options from non leaders

* Removed manager options from non group plan

* Fixed some nav styles

* Fixed overlay color

* Prevented edit data from being transfered to create

* Added hover state for spells

* Add performance fixes for chat avatars

* Fixed merge conflicts

* Updated fron navigation

* Fixed reg gryphon logo

* Began adding gem modal functionality

* Added purchase gems with gold

* Fixed restore

* Replaced description with summary

* Spells that target tasks fix

* Added initial challenge task load

* Fixed lint issue
2017-08-22 21:58:13 -06:00

287 lines
9.2 KiB
Vue

<template lang="pug">
div.item-with-icon.item-notifications.dropdown
.svg-icon.notifications(v-html="icons.notifications")
// span.glyphicon(:class='iconClasses()')
// span.notification-counter(v-if='getNotificationsCount()') {{getNotificationsCount()}}
.dropdown-menu.dropdown-menu-right.user-dropdown
h4.dropdown-item.dropdown-separated(v-if='!hasNoNotifications()') {{ $t('notifications') }}
h4.dropdown-item.toolbar-notifs-no-messages(v-if='hasNoNotifications()') {{ $t('noNotifications') }}
a.dropdown-item(v-if='user.purchased.plan.mysteryItems.length', @click='go("/inventory/items")')
span.glyphicon.glyphicon-gift
span {{ $t('newSubscriberItem') }}
a.dropdown-item(v-for='party in user.invitations.parties')
div
span.glyphicon.glyphicon-user
span {{ $t('invitedTo', {name: party.name}) }}
div
span(@click='accept(party)') Accept
span(@click='reject(party)') Reject
a.dropdown-item(v-if='user.flags.cardReceived', @click='go("/inventory/items")')
span.glyphicon.glyphicon-envelope
span {{ $t('cardReceived') }}
a.dropdown-item(@click='clearCards()', :popover="$t('clear')",
popover-placement='right', popover-trigger='mouseenter', popover-append-to-body='true')
a.dropdown-item(v-for='guild in user.invitations.guilds')
div
span.glyphicon.glyphicon-user
span {{ $t('invitedTo', {name: guild.name}) }}
div
span(@click='accept(guild)') Accept
span(@click='reject(guild)') Reject
a.dropdown-item(v-if='user.flags.classSelected && !user.preferences.disableClasses && user.stats.points',
@click='go("/user/profile")')
span.glyphicon.glyphicon-plus-sign
span {{ $t('haveUnallocated', {points: user.stats.points}) }}
a.dropdown-item(v-for='(message, key) in user.newMessages', v-if='message.value', @click='navigateToGroup(key)')
span.glyphicon.glyphicon-comment
span {{message.name}}
a.dropdown-item(@click='clearMessages(k)', :popover="$t('clear')", popover-placement='right', popover-trigger='mouseenter',popover-append-to-body='true')
a.dropdown-item(v-for='(notification, index) in user.groupNotifications', @click='viewGroupApprovalNotification(notification, index, true)')
span(:class="groupApprovalNotificationIcon(notification)")
span
| {{notification.data.message}}
a.dropdown-item(@click='viewGroupApprovalNotification(notification, $index)',
:popover="$t('clear')",
popover-placement='right',
popover-trigger='mouseenter',
popover-append-to-body='true')
span.glyphicon.glyphicon-remove-circle
</template>
<style lang='scss' scoped>
@import '~client/assets/scss/colors.scss';
.item-notifications {
width: 44px;
}
.item-notifications:hover {
cursor: pointer;
}
.notifications {
vertical-align: bottom;
display: inline-block;
width: 20px;
height: 20px;
margin-right: 8px;
margin-left: 8px;
margin-top: .2em;
}
/* @TODO: Move to shared css */
.dropdown:hover .dropdown-menu {
display: block;
margin-top: 0; // remove the gap so it doesn't close
}
.dropdown + .dropdown {
margin-left: 0px;
}
.dropdown-separated {
border-bottom: 1px solid $gray-500;
}
.dropdown-menu:not(.user-dropdown) {
background: $purple-200;
border-radius: 0px;
border: none;
box-shadow: none;
padding: 0px;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
.dropdown-item {
font-size: 16px;
box-shadow: none;
color: $white;
border: none;
line-height: 1.5;
&.active {
background: $purple-300;
}
&:hover {
background: $purple-300;
&:last-child {
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
}
}
}
</style>
<script>
import isEmpty from 'lodash/isEmpty';
import map from 'lodash/map';
import { mapState } from 'client/libs/store';
import quests from 'common/script/content/quests';
import notificationsIcon from 'assets/svg/notifications.svg';
export default {
data () {
return {
icons: Object.freeze({
notifications: notificationsIcon,
}),
};
},
computed: {
...mapState({user: 'user.data'}),
party () {
return {name: ''};
// return this.user.party;
},
},
methods: {
// @TODO: I hate this function, we can do better with a hashmap
selectNotificationValue (mysteryValue, invitationValue, cardValue,
unallocatedValue, messageValue, noneValue, groupApprovalRequested, groupApproved) {
let user = this.user;
if (user.purchased && user.purchased.plan && user.purchased.plan.mysteryItems && user.purchased.plan.mysteryItems.length) {
return mysteryValue;
} else if (user.invitations.parties && user.invitations.parties.length > 0 || user.invitations.guilds && user.invitations.guilds.length > 0) {
return invitationValue;
} else if (user.flags.cardReceived) {
return cardValue;
} else if (user.flags.classSelected && !(user.preferences && user.preferences.disableClasses) && user.stats.points) {
return unallocatedValue;
} else if (!isEmpty(user.newMessages)) {
return messageValue;
} else if (!isEmpty(user.groupNotifications)) {
let groupNotificationTypes = map(user.groupNotifications, 'type');
if (groupNotificationTypes.indexOf('GROUP_TASK_APPROVAL') !== -1) {
return groupApprovalRequested;
} else if (groupNotificationTypes.indexOf('GROUP_TASK_APPROVED') !== -1) {
return groupApproved;
}
return noneValue;
} else {
return noneValue;
}
},
hasQuestProgress () {
let user = this.user;
if (user.party.quest) {
let userQuest = quests[user.party.quest.key];
if (!userQuest) {
return false;
}
if (userQuest.boss && user.party.quest.progress.up > 0) {
return true;
}
if (userQuest.collect && user.party.quest.progress.collectedItems > 0) {
return true;
}
}
return false;
},
getQuestInfo () {
let user = this.user;
let questInfo = {};
if (user.party.quest) {
let userQuest = quests[user.party.quest.key];
questInfo.title = userQuest.text();
if (userQuest.boss) {
questInfo.body = this.$t('questTaskDamage', { damage: user.party.quest.progress.up.toFixed(1) });
} else if (userQuest.collect) {
questInfo.body = this.$t('questTaskCollection', { items: user.party.quest.progress.collectedItems });
}
}
return questInfo;
},
clearMessages () {
this.$store.dispatch('chat:markChatSeen');
},
clearCards () {
this.$store.dispatch('chat:clearCards');
},
getNotificationsCount () {
let count = 0;
if (this.user.invitations.parties) {
count += this.user.invitations.parties.length;
}
if (this.user.purchased.plan && this.user.purchased.plan.mysteryItems.length) {
count++;
}
if (this.user.invitations.guilds) {
count += this.user.invitations.guilds.length;
}
if (this.user.flags.classSelected && !this.user.preferences.disableClasses && this.user.stats.points) {
count += this.user.stats.points > 0 ? 1 : 0;
}
if (this.user.newMessages) {
count += Object.keys(this.user.newMessages).length;
}
return count;
},
iconClasses () {
return this.selectNotificationValue(
'glyphicon-gift',
'glyphicon-user',
'glyphicon-envelope',
'glyphicon-plus-sign',
'glyphicon-comment',
'glyphicon-comment inactive',
'glyphicon-question-sign',
'glyphicon-ok-sign'
);
},
hasNoNotifications () {
return this.selectNotificationValue(false, false, false, false, false, true, false, false);
},
viewGroupApprovalNotification (notification, index, navigate) {
// @TODO: USe notifications: User.readNotification(notification.id);
this.user.groupNotifications.splice(index, 1);
return navigate; // @TODO: remove
// @TODO: this.$router.go if (navigate) go('options.social.guilds.detail', {gid: notification.data.groupId});
},
groupApprovalNotificationIcon (notification) {
if (notification.type === 'GROUP_TASK_APPROVAL') {
return 'glyphicon glyphicon-question-sign';
} else if (notification.type === 'GROUP_TASK_APPROVED') {
return 'glyphicon glyphicon-ok-sign';
}
},
go (path) {
this.$router.push(path);
},
navigateToGroup (key) {
if (key === this.party._id || key === this.user.party._id) {
this.go('/party');
return;
}
this.go(`/groups/guild/${key}`);
},
async reject (group) {
await this.$store.dispatch('guilds:rejectInvite', {groupId: group.id});
// @TODO: User.sync();
},
async accept (group) {
if (group.cancelledPlan && !confirm(this.$t('aboutToJoinCancelledGroupPlan'))) {
return;
}
// @TODO: check for party , type: 'myGuilds'
await this.$store.dispatch('guilds:join', {guildId: group.id});
// this.user.guilds.push(this.group._id);
},
},
};
</script>