Oct 11 fxes (#9181)

* Added unqequip for hair styles

* Added quest rewards to quest completed modal

* Fixed display of task approvals

* Ensured the user is welcomed before showing login notification

* Added new message modal

* fixed manager functions

* Fixed group edit on group plan
This commit is contained in:
Keith Holliday
2017-10-13 06:40:53 +02:00
committed by GitHub
parent 9ca6da0f75
commit fac1889776
14 changed files with 83 additions and 109 deletions

View File

@@ -3,8 +3,10 @@
size='md', :hide-footer="true") size='md', :hide-footer="true")
.modal-body.text-center .modal-body.text-center
.quest(:class='`quest_${user.party.quest.completed}`') .quest(:class='`quest_${user.party.quest.completed}`')
p(v-html='this.questData.completion()') p(v-html='questData.completion()')
.quest-rewards(key='user.party.quest.completed', header-participant="$t('youReceived')", header-quest-owner="$t('questOwnerReceived')") .quest-rewards.text-center
h3 {{ $t('youReceived') }}
questDialogDrops(:item="questData")
.modal-footer .modal-footer
button.btn.btn-primary(@click='setQuestCompleted()') {{ $t('ok') }} button.btn.btn-primary(@click='setQuestCompleted()') {{ $t('ok') }}
</template> </template>
@@ -13,11 +15,16 @@
.quest { .quest {
margin: 0 auto; margin: 0 auto;
} }
.quest-rewards .questRewards {
margin: 0 auto;
}
</style> </style>
<script> <script>
import bModal from 'bootstrap-vue/lib/components/modal'; import bModal from 'bootstrap-vue/lib/components/modal';
import quests from 'common/script/content/quests'; import quests from 'common/script/content/quests';
import questDialogDrops from 'client/components/shops/quests/questDialogDrops';
import { mapState } from 'client/libs/store'; import { mapState } from 'client/libs/store';
import percent from '../../../common/script/libs/percent'; import percent from '../../../common/script/libs/percent';
@@ -26,6 +33,7 @@ import { maxHealth } from '../../../common/script/index';
export default { export default {
components: { components: {
bModal, bModal,
questDialogDrops,
}, },
data () { data () {
return { return {

View File

@@ -108,6 +108,7 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
button.btn.btn-secondary.purchase-all(v-if='!hideSet(set) && !userOwnsSet("hair", set.keys, "color")', @click='unlock(`hair.color.${set.keys.join(",hair.color.")}`)') {{ $t('purchaseAll') }} button.btn.btn-secondary.purchase-all(v-if='!hideSet(set) && !userOwnsSet("hair", set.keys, "color")', @click='unlock(`hair.color.${set.keys.join(",hair.color.")}`)') {{ $t('purchaseAll') }}
#style.row(v-if='activeSubPage === "style"') #style.row(v-if='activeSubPage === "style"')
.col-12.customize-options(v-if='editing') .col-12.customize-options(v-if='editing')
.head_0.option(@click='set({"preferences.hair.base": 0})', :class="[{ active: user.preferences.hair.base === 0 }, 'hair_base_0_' + user.preferences.hair.color]")
.option(v-for='option in baseHair3', .option(v-for='option in baseHair3',
:class='{active: option.active, locked: option.locked}') :class='{active: option.active, locked: option.locked}')
.base.sprite.customize-option(:class="`hair_base_${option.key}_${user.preferences.hair.color}`", @click='option.click') .base.sprite.customize-option(:class="`hair_base_${option.key}_${user.preferences.hair.color}`", @click='option.click')
@@ -149,6 +150,7 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("hair", baseHair2Keys, "base")', @click='unlock(`hair.base.${baseHair2Keys.join(",hair.base.")}`)') {{ $t('purchaseAll') }} button.btn.btn-secondary.purchase-all(v-if='!userOwnsSet("hair", baseHair2Keys, "base")', @click='unlock(`hair.base.${baseHair2Keys.join(",hair.base.")}`)') {{ $t('purchaseAll') }}
#facialhair.row(v-if='activeSubPage === "facialhair"') #facialhair.row(v-if='activeSubPage === "facialhair"')
.col-12.customize-options(v-if='editing') .col-12.customize-options(v-if='editing')
.head_0.option(@click='set({"preferences.hair.beard": 0})', :class="[{ active: user.preferences.hair.beard === 0 }, 'hair_base_0_' + user.preferences.hair.color]")
.option(v-for='option in baseHair5', .option(v-for='option in baseHair5',
:class='{active: option.active, locked: option.locked}') :class='{active: option.active, locked: option.locked}')
.base.sprite.customize-option(:class="`hair_beard_${option.key}_${user.preferences.hair.color}`", @click='option.click') .base.sprite.customize-option(:class="`hair_beard_${option.key}_${user.preferences.hair.color}`", @click='option.click')

View File

@@ -1,5 +1,6 @@
<template lang="pug"> <template lang="pug">
.row .row
group-form-modal
secondary-menu.col-12 secondary-menu.col-12
router-link.nav-link(:to="{name: 'groupPlanDetailTaskInformation', params: {groupId}}", router-link.nav-link(:to="{name: 'groupPlanDetailTaskInformation', params: {groupId}}",
exact, :class="{'active': $route.name === 'groupPlanDetailTaskInformation'}") {{ $t('groupTaskBoard') }} exact, :class="{'active': $route.name === 'groupPlanDetailTaskInformation'}") {{ $t('groupTaskBoard') }}
@@ -16,6 +17,7 @@
</template> </template>
<script> <script>
import groupFormModal from 'client/components/groups/groupFormModal';
import SecondaryMenu from 'client/components/secondaryMenu'; import SecondaryMenu from 'client/components/secondaryMenu';
import { mapState } from 'client/libs/store'; import { mapState } from 'client/libs/store';
@@ -23,6 +25,7 @@ export default {
props: ['groupId'], props: ['groupId'],
components: { components: {
SecondaryMenu, SecondaryMenu,
groupFormModal,
}, },
computed: { computed: {
...mapState({ ...mapState({

View File

@@ -349,10 +349,10 @@ export default {
groupId: this.searchId, groupId: this.searchId,
}); });
let groupedApprovals = this.loadApprovals(); let groupedApprovals = await this.loadApprovals();
tasks.forEach((task) => { tasks.forEach((task) => {
if (groupedApprovals.length > 0) task.approvals = groupedApprovals[task._id]; if (groupedApprovals[task._id] && groupedApprovals[task._id].length > 0) task.approvals = groupedApprovals[task._id];
this.tasksByType[task.type].push(task); this.tasksByType[task.type].push(task);
}); });
}, },

View File

@@ -10,8 +10,6 @@
group-form-modal group-form-modal
</template> </template>
<!-- .col-md-2
button.btn.btn-primary(b-btn, @click="$root.$emit('show::modal','guild-form')") {{ $t('createGuild') }} -->
<script> <script>
import groupFormModal from './groupFormModal'; import groupFormModal from './groupFormModal';

View File

@@ -32,7 +32,7 @@ div
span.dropdown-icon-item span.dropdown-icon-item
.svg-icon.inline(v-html="icons.removeIcon", v-if='isLeader') .svg-icon.inline(v-html="icons.removeIcon", v-if='isLeader')
span.text {{$t('removeMember')}} span.text {{$t('removeMember')}}
b-dropdown-item(@click='sendMessage(member._id)') b-dropdown-item(@click='sendMessage(member)')
span.dropdown-icon-item span.dropdown-icon-item
.svg-icon.inline(v-html="icons.messageIcon") .svg-icon.inline(v-html="icons.messageIcon")
span.text {{$t('sendMessage')}} span.text {{$t('sendMessage')}}
@@ -40,11 +40,11 @@ div
span.dropdown-icon-item span.dropdown-icon-item
.svg-icon.inline(v-html="icons.starIcon") .svg-icon.inline(v-html="icons.starIcon")
span.text {{$t('promoteToLeader')}} span.text {{$t('promoteToLeader')}}
b-dropdown-item(@click='sort(option.value)', v-if='isLeader && groupIsSubscribed') b-dropdown-item(@click='addManager(member)', v-if='isLeader && groupIsSubscribed')
span.dropdown-icon-item span.dropdown-icon-item
.svg-icon.inline(v-html="icons.starIcon") .svg-icon.inline(v-html="icons.starIcon")
span.text {{$t('addManager')}} span.text {{$t('addManager')}}
b-dropdown-item(@click='sort(option.value)', v-if='isLeader && groupIsSubscribed') b-dropdown-item(@click='removeManager(member)', v-if='isLeader && groupIsSubscribed')
span.dropdown-icon-item span.dropdown-icon-item
.svg-icon.inline(v-html="icons.removeIcon") .svg-icon.inline(v-html="icons.removeIcon")
span.text {{$t('removeManager2')}} span.text {{$t('removeManager2')}}
@@ -178,7 +178,6 @@ import bDropdown from 'bootstrap-vue/lib/components/dropdown';
import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item'; import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
import { mapState } from 'client/libs/store'; import { mapState } from 'client/libs/store';
import privateMessageModal from 'client/components/private-message-modal';
import removeMemberModal from 'client/components/members/removeMemberModal'; import removeMemberModal from 'client/components/members/removeMemberModal';
import MemberDetails from '../memberDetails'; import MemberDetails from '../memberDetails';
import removeIcon from 'assets/members/remove.svg'; import removeIcon from 'assets/members/remove.svg';
@@ -193,7 +192,6 @@ export default {
bDropdown, bDropdown,
bDropdownItem, bDropdownItem,
MemberDetails, MemberDetails,
privateMessageModal,
removeMemberModal, removeMemberModal,
}, },
data () { data () {
@@ -289,9 +287,11 @@ export default {
}, },
}, },
methods: { methods: {
sendMessage () { sendMessage (member) {
this.$store.state.userIdToMessage = this.user._id; this.$root.$emit('habitica::new-inbox-message', {
this.$root.$emit('show::modal', 'private-message'); userIdToMessage: member._id,
userName: member.profile.name,
});
}, },
async getMembers () { async getMembers () {
let groupId = this.groupId; let groupId = this.groupId;
@@ -342,22 +342,19 @@ export default {
this.group.memberCount -= 1; this.group.memberCount -= 1;
this.memberToRemove = {}; this.memberToRemove = {};
}, },
async quickReply (uid) {
this.memberToReply = uid;
await this.$store.dispatch('members:selectMember', {
memberId: uid,
});
this.$root.$emit('show::modal', 'private-message'); // MemberModalCtrl
},
async addManager (memberId) { async addManager (memberId) {
await this.$store.dispatch('group:addManager', { await this.$store.dispatch('guilds:addManager', {
groupId: this.groupId,
memberId, memberId,
}); });
alert(this.$t('managerAdded'));
}, },
async removeManager (memberId) { async removeManager (memberId) {
await this.$store.dispatch('group:removeManager', { await this.$store.dispatch('guilds:removeManager', {
groupId: this.groupId,
memberId, memberId,
}); });
alert(this.$t('managerRemoved'));
}, },
close () { close () {
this.$root.$emit('hide::modal', 'members-modal'); this.$root.$emit('hide::modal', 'members-modal');

View File

@@ -526,8 +526,10 @@ export default {
} }
break; break;
case 'LOGIN_INCENTIVE': case 'LOGIN_INCENTIVE':
if (this.user.flags.tour.intro === this.TOUR_END && this.user.flags.welcomed) {
this.notificationData = notification.data; this.notificationData = notification.data;
this.$root.$emit('show::modal', 'login-incentives'); this.$root.$emit('show::modal', 'login-incentives');
}
break; break;
default: default:
if (notification.data.headerText && notification.data.bodyText) { if (notification.data.headerText && notification.data.bodyText) {

View File

@@ -1,63 +0,0 @@
<template lang="pug">
b-modal#private-message(title="Message", size='md', :hide-footer="true")
.content
textarea.form-control(v-model='privateMessage')
button.btn.btn-primary(@click='sendPrivateMessage()', :disabled='loading') Send
</template>
<style lang="scss" scoped>
.content {
padding: 1em;
textarea {
margin-bottom: 1em;
}
}
</style>
<script>
import bModal from 'bootstrap-vue/lib/components/modal';
import notifications from 'client/mixins/notifications';
export default {
mixins: [notifications],
components: {
bModal,
},
data () {
return {
privateMessage: '',
loading: false,
userIdToMessage: '',
};
},
computed: {
userIdToMessageStore () {
return this.$store.state.userIdToMessage;
},
},
watch: {
userIdToMessageStore () {
this.userIdToMessage = this.userIdToMessageStore;
},
},
methods: {
async sendPrivateMessage () {
if (!this.privateMessage || !this.userIdToMessage) return;
this.loading = true;
await this.$store.dispatch('members:sendPrivateMessage', {
message: this.privateMessage,
toUserId: this.userIdToMessage,
});
this.loading = false;
this.text(this.$t('messageSentAlert'));
this.privateMessage = '';
},
},
};
</script>

View File

@@ -100,6 +100,8 @@
return drop.text(); return drop.text();
}, },
getDropsList (drops, ownerOnly) { getDropsList (drops, ownerOnly) {
if (!drops) return [];
return drops.filter(function dropsList (drop) { return drops.filter(function dropsList (drop) {
if (ownerOnly) { if (ownerOnly) {
return drop.onlyOwner; return drop.onlyOwner;

View File

@@ -26,21 +26,23 @@
p(v-once) {{$t('emptyMessagesLine2')}} p(v-once) {{$t('emptyMessagesLine2')}}
.conversations(v-if='filtersConversations.length > 0') .conversations(v-if='filtersConversations.length > 0')
.conversation(v-for='conversation in filtersConversations', @click='selectConversation(conversation.key)', .conversation(v-for='conversation in filtersConversations', @click='selectConversation(conversation.key)',
:class="{active: selectedConversation === conversation.key}") :class="{active: selectedConversation.key === conversation.key}")
div div
span(:class="userLevelStyle(conversation)") {{conversation.name}} span(:class="userLevelStyle(conversation)") {{conversation.name}}
span.timeago {{conversation.date | timeAgo}} span.timeago {{conversation.date | timeAgo}}
div {{conversation.lastMessageText.substring(0, 30)}} div {{conversation.lastMessageText.substring(0, 30)}}
.col-8.messages .col-8.messages
.empty-messages.text-center(v-if='activeChat.length === 0') .empty-messages.text-center(v-if='activeChat.length === 0 && !selectedConversation.key')
.svg-icon.envelope(v-html="icons.messageIcon") .svg-icon.envelope(v-html="icons.messageIcon")
h4(v-once) Nothing Here Yet h4(v-once) Nothing Here Yet
p(v-once) Select a conversation on the left p(v-once) Select a conversation on the left
.empty-messages.text-center(v-if='activeChat.length === 0 && selectedConversation.key')
p {{ $t('beginningOfConversation', {userName: selectedConversation.name})}}
chat-message.message-scroll(:chat.sync='activeChat', :inbox='true', ref="chatscroll") chat-message.message-scroll(:chat.sync='activeChat', :inbox='true', ref="chatscroll")
// @TODO: Implement new message header here when we fix the above // @TODO: Implement new message header here when we fix the above
.new-message-row(v-if='selectedConversation') .new-message-row(v-if='selectedConversation.key')
textarea(v-model='newMessage') textarea(v-model='newMessage')
button.btn.btn-secondary(@click='sendPrivateMessage()') Send button.btn.btn-secondary(@click='sendPrivateMessage()') Send
</template> </template>
@@ -175,6 +177,33 @@ export default {
bFormInput, bFormInput,
chatMessage, chatMessage,
}, },
mounted () {
this.$root.$on('habitica::new-inbox-message', (data) => {
this.$root.$emit('show::modal', 'inbox-modal');
const conversation = this.conversations.find(convo => {
return convo.key === data.userIdToMessage;
});
if (conversation) {
this.selectConversation(data.userIdToMessage);
return;
}
const newMessage = {
text: '',
timestamp: new Date(),
user: data.userName,
uuid: data.userIdToMessage,
id: '',
};
this.$set(this.user.inbox.messages, data.userIdToMessage, newMessage);
this.selectConversation(data.userIdToMessage);
});
},
destroyed () {
this.$root.$off('habitica::new-inbox-message');
},
data () { data () {
return { return {
icons: Object.freeze({ icons: Object.freeze({
@@ -182,7 +211,7 @@ export default {
svgClose, svgClose,
}), }),
displayCreate: true, displayCreate: true,
selectedConversation: '', selectedConversation: {},
search: '', search: '',
newMessage: '', newMessage: '',
activeChat: [], activeChat: [],
@@ -222,7 +251,7 @@ export default {
newMessage.uuid = this.user._id; newMessage.uuid = this.user._id;
} }
conversations[userId].messages.push(newMessage); if (newMessage.text) conversations[userId].messages.push(newMessage);
conversations[userId].lastMessageText = message.text; conversations[userId].lastMessageText = message.text;
conversations[userId].date = message.timestamp; conversations[userId].date = message.timestamp;
} }
@@ -234,10 +263,6 @@ export default {
return conversations; return conversations;
}, },
currentMessages () {
if (!this.selectedConversation) return;
return this.conversations[this.selectedConversation].messages;
},
filtersConversations () { filtersConversations () {
if (!this.search) return this.conversations; if (!this.search) return this.conversations;
return filter(this.conversations, (conversation) => { return filter(this.conversations, (conversation) => {
@@ -250,12 +275,11 @@ export default {
this.displayCreate = !this.displayCreate; this.displayCreate = !this.displayCreate;
}, },
selectConversation (key) { selectConversation (key) {
this.selectedConversation = key;
let convoFound = this.conversations.find((conversation) => { let convoFound = this.conversations.find((conversation) => {
return conversation.key === key; return conversation.key === key;
}); });
this.selectedConversation = convoFound;
let activeChat = convoFound.messages; let activeChat = convoFound.messages;
activeChat = sortBy(activeChat, [(o) => { activeChat = sortBy(activeChat, [(o) => {
@@ -273,11 +297,11 @@ export default {
if (!this.newMessage) return; if (!this.newMessage) return;
let convoFound = this.conversations.find((conversation) => { let convoFound = this.conversations.find((conversation) => {
return conversation.key === this.selectedConversation; return conversation.key === this.selectedConversation.key;
}); });
this.$store.dispatch('members:sendPrivateMessage', { this.$store.dispatch('members:sendPrivateMessage', {
toUserId: this.selectedConversation, toUserId: this.selectedConversation.key,
message: this.newMessage, message: this.newMessage,
}); });

View File

@@ -279,7 +279,6 @@ div
.points {{$t('pts')}} .points {{$t('pts')}}
.col-4 .col-4
.up(v-if='user.stats.points', @click='allocate(stat)') .up(v-if='user.stats.points', @click='allocate(stat)')
private-message-modal
send-gems-modal(:userReceivingGems='userReceivingGems') send-gems-modal(:userReceivingGems='userReceivingGems')
</template> </template>
@@ -559,7 +558,6 @@ import allocate from '../../../common/script/ops/allocate';
import MemberDetails from '../memberDetails'; import MemberDetails from '../memberDetails';
import bPopover from 'bootstrap-vue/lib/components/popover'; import bPopover from 'bootstrap-vue/lib/components/popover';
import privateMessageModal from 'client/components/private-message-modal';
import sendGemsModal from 'client/components/payments/sendGemsModal'; import sendGemsModal from 'client/components/payments/sendGemsModal';
import markdown from 'client/directives/markdown'; import markdown from 'client/directives/markdown';
import toggleSwitch from 'client/components/ui/toggleSwitch'; import toggleSwitch from 'client/components/ui/toggleSwitch';
@@ -580,7 +578,6 @@ export default {
}, },
components: { components: {
bModal, bModal,
privateMessageModal,
sendGemsModal, sendGemsModal,
MemberDetails, MemberDetails,
toggleSwitch, toggleSwitch,
@@ -710,8 +707,10 @@ export default {
this.$store.state.profileOptions.startingPage = page; this.$store.state.profileOptions.startingPage = page;
}, },
sendMessage () { sendMessage () {
this.$store.state.userIdToMessage = this.user._id; this.$root.$emit('habitica::new-inbox-message', {
this.$root.$emit('show::modal', 'private-message'); userIdToMessage: this.user._id,
userName: this.user.profile.name,
});
}, },
getProgressDisplay () { getProgressDisplay () {
// let currentLoginDay = Content.loginIncentives[this.user.loginIncentives]; // let currentLoginDay = Content.loginIncentives[this.user.loginIncentives];

View File

@@ -132,7 +132,6 @@ export default function () {
upgradingGroup: {}, upgradingGroup: {},
notificationStore: [], notificationStore: [],
modalStack: [], modalStack: [],
userIdToMessage: '',
brokenChallengeTask: {}, brokenChallengeTask: {},
equipmentDrawerOpen: true, equipmentDrawerOpen: true,
recentlyPurchased: {}, recentlyPurchased: {},

View File

@@ -397,5 +397,7 @@
"groupTaskBoard": "Task Board", "groupTaskBoard": "Task Board",
"groupInformation": "Group Information", "groupInformation": "Group Information",
"groupBilling": "Group Billing", "groupBilling": "Group Billing",
"wouldYouParticipate": "Would you like to participate?" "wouldYouParticipate": "Would you like to participate?",
"managerAdded": "Manager added successfully",
"managerRemoved": "Manager removed successfully"
} }

View File

@@ -64,5 +64,6 @@
"messageUserOperationNotFound": "<%= operation %> operation not found", "messageUserOperationNotFound": "<%= operation %> operation not found",
"messageNotificationNotFound": "Notification not found.", "messageNotificationNotFound": "Notification not found.",
"notificationsRequired": "Notification ids are required." "notificationsRequired": "Notification ids are required.",
"beginningOfConversation": "This is the beginning of your conversation with <%= userName %>. Remember to be kind, respectful, and follow the Community Guidelines!"
} }