mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
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:
@@ -3,8 +3,10 @@
|
||||
size='md', :hide-footer="true")
|
||||
.modal-body.text-center
|
||||
.quest(:class='`quest_${user.party.quest.completed}`')
|
||||
p(v-html='this.questData.completion()')
|
||||
.quest-rewards(key='user.party.quest.completed', header-participant="$t('youReceived')", header-quest-owner="$t('questOwnerReceived')")
|
||||
p(v-html='questData.completion()')
|
||||
.quest-rewards.text-center
|
||||
h3 {{ $t('youReceived') }}
|
||||
questDialogDrops(:item="questData")
|
||||
.modal-footer
|
||||
button.btn.btn-primary(@click='setQuestCompleted()') {{ $t('ok') }}
|
||||
</template>
|
||||
@@ -13,11 +15,16 @@
|
||||
.quest {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.quest-rewards .questRewards {
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
import quests from 'common/script/content/quests';
|
||||
import questDialogDrops from 'client/components/shops/quests/questDialogDrops';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
import percent from '../../../common/script/libs/percent';
|
||||
@@ -26,6 +33,7 @@ import { maxHealth } from '../../../common/script/index';
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
questDialogDrops,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
@@ -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') }}
|
||||
#style.row(v-if='activeSubPage === "style"')
|
||||
.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',
|
||||
:class='{active: option.active, locked: option.locked}')
|
||||
.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') }}
|
||||
#facialhair.row(v-if='activeSubPage === "facialhair"')
|
||||
.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',
|
||||
:class='{active: option.active, locked: option.locked}')
|
||||
.base.sprite.customize-option(:class="`hair_beard_${option.key}_${user.preferences.hair.color}`", @click='option.click')
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template lang="pug">
|
||||
.row
|
||||
group-form-modal
|
||||
secondary-menu.col-12
|
||||
router-link.nav-link(:to="{name: 'groupPlanDetailTaskInformation', params: {groupId}}",
|
||||
exact, :class="{'active': $route.name === 'groupPlanDetailTaskInformation'}") {{ $t('groupTaskBoard') }}
|
||||
@@ -16,6 +17,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import groupFormModal from 'client/components/groups/groupFormModal';
|
||||
import SecondaryMenu from 'client/components/secondaryMenu';
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
@@ -23,6 +25,7 @@ export default {
|
||||
props: ['groupId'],
|
||||
components: {
|
||||
SecondaryMenu,
|
||||
groupFormModal,
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
|
||||
@@ -349,10 +349,10 @@ export default {
|
||||
groupId: this.searchId,
|
||||
});
|
||||
|
||||
let groupedApprovals = this.loadApprovals();
|
||||
let groupedApprovals = await this.loadApprovals();
|
||||
|
||||
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);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
group-form-modal
|
||||
</template>
|
||||
<!-- .col-md-2
|
||||
button.btn.btn-primary(b-btn, @click="$root.$emit('show::modal','guild-form')") {{ $t('createGuild') }} -->
|
||||
|
||||
<script>
|
||||
import groupFormModal from './groupFormModal';
|
||||
|
||||
@@ -32,7 +32,7 @@ div
|
||||
span.dropdown-icon-item
|
||||
.svg-icon.inline(v-html="icons.removeIcon", v-if='isLeader')
|
||||
span.text {{$t('removeMember')}}
|
||||
b-dropdown-item(@click='sendMessage(member._id)')
|
||||
b-dropdown-item(@click='sendMessage(member)')
|
||||
span.dropdown-icon-item
|
||||
.svg-icon.inline(v-html="icons.messageIcon")
|
||||
span.text {{$t('sendMessage')}}
|
||||
@@ -40,11 +40,11 @@ div
|
||||
span.dropdown-icon-item
|
||||
.svg-icon.inline(v-html="icons.starIcon")
|
||||
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
|
||||
.svg-icon.inline(v-html="icons.starIcon")
|
||||
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
|
||||
.svg-icon.inline(v-html="icons.removeIcon")
|
||||
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 { mapState } from 'client/libs/store';
|
||||
|
||||
import privateMessageModal from 'client/components/private-message-modal';
|
||||
import removeMemberModal from 'client/components/members/removeMemberModal';
|
||||
import MemberDetails from '../memberDetails';
|
||||
import removeIcon from 'assets/members/remove.svg';
|
||||
@@ -193,7 +192,6 @@ export default {
|
||||
bDropdown,
|
||||
bDropdownItem,
|
||||
MemberDetails,
|
||||
privateMessageModal,
|
||||
removeMemberModal,
|
||||
},
|
||||
data () {
|
||||
@@ -289,9 +287,11 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
sendMessage () {
|
||||
this.$store.state.userIdToMessage = this.user._id;
|
||||
this.$root.$emit('show::modal', 'private-message');
|
||||
sendMessage (member) {
|
||||
this.$root.$emit('habitica::new-inbox-message', {
|
||||
userIdToMessage: member._id,
|
||||
userName: member.profile.name,
|
||||
});
|
||||
},
|
||||
async getMembers () {
|
||||
let groupId = this.groupId;
|
||||
@@ -342,22 +342,19 @@ export default {
|
||||
this.group.memberCount -= 1;
|
||||
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) {
|
||||
await this.$store.dispatch('group:addManager', {
|
||||
await this.$store.dispatch('guilds:addManager', {
|
||||
groupId: this.groupId,
|
||||
memberId,
|
||||
});
|
||||
alert(this.$t('managerAdded'));
|
||||
},
|
||||
async removeManager (memberId) {
|
||||
await this.$store.dispatch('group:removeManager', {
|
||||
await this.$store.dispatch('guilds:removeManager', {
|
||||
groupId: this.groupId,
|
||||
memberId,
|
||||
});
|
||||
alert(this.$t('managerRemoved'));
|
||||
},
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'members-modal');
|
||||
|
||||
@@ -526,8 +526,10 @@ export default {
|
||||
}
|
||||
break;
|
||||
case 'LOGIN_INCENTIVE':
|
||||
if (this.user.flags.tour.intro === this.TOUR_END && this.user.flags.welcomed) {
|
||||
this.notificationData = notification.data;
|
||||
this.$root.$emit('show::modal', 'login-incentives');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (notification.data.headerText && notification.data.bodyText) {
|
||||
|
||||
@@ -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>
|
||||
@@ -100,6 +100,8 @@
|
||||
return drop.text();
|
||||
},
|
||||
getDropsList (drops, ownerOnly) {
|
||||
if (!drops) return [];
|
||||
|
||||
return drops.filter(function dropsList (drop) {
|
||||
if (ownerOnly) {
|
||||
return drop.onlyOwner;
|
||||
|
||||
@@ -26,21 +26,23 @@
|
||||
p(v-once) {{$t('emptyMessagesLine2')}}
|
||||
.conversations(v-if='filtersConversations.length > 0')
|
||||
.conversation(v-for='conversation in filtersConversations', @click='selectConversation(conversation.key)',
|
||||
:class="{active: selectedConversation === conversation.key}")
|
||||
:class="{active: selectedConversation.key === conversation.key}")
|
||||
div
|
||||
span(:class="userLevelStyle(conversation)") {{conversation.name}}
|
||||
span.timeago {{conversation.date | timeAgo}}
|
||||
div {{conversation.lastMessageText.substring(0, 30)}}
|
||||
.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")
|
||||
h4(v-once) Nothing Here Yet
|
||||
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")
|
||||
|
||||
// @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')
|
||||
button.btn.btn-secondary(@click='sendPrivateMessage()') Send
|
||||
</template>
|
||||
@@ -175,6 +177,33 @@ export default {
|
||||
bFormInput,
|
||||
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 () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
@@ -182,7 +211,7 @@ export default {
|
||||
svgClose,
|
||||
}),
|
||||
displayCreate: true,
|
||||
selectedConversation: '',
|
||||
selectedConversation: {},
|
||||
search: '',
|
||||
newMessage: '',
|
||||
activeChat: [],
|
||||
@@ -222,7 +251,7 @@ export default {
|
||||
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].date = message.timestamp;
|
||||
}
|
||||
@@ -234,10 +263,6 @@ export default {
|
||||
|
||||
return conversations;
|
||||
},
|
||||
currentMessages () {
|
||||
if (!this.selectedConversation) return;
|
||||
return this.conversations[this.selectedConversation].messages;
|
||||
},
|
||||
filtersConversations () {
|
||||
if (!this.search) return this.conversations;
|
||||
return filter(this.conversations, (conversation) => {
|
||||
@@ -250,12 +275,11 @@ export default {
|
||||
this.displayCreate = !this.displayCreate;
|
||||
},
|
||||
selectConversation (key) {
|
||||
this.selectedConversation = key;
|
||||
|
||||
let convoFound = this.conversations.find((conversation) => {
|
||||
return conversation.key === key;
|
||||
});
|
||||
|
||||
this.selectedConversation = convoFound;
|
||||
let activeChat = convoFound.messages;
|
||||
|
||||
activeChat = sortBy(activeChat, [(o) => {
|
||||
@@ -273,11 +297,11 @@ export default {
|
||||
if (!this.newMessage) return;
|
||||
|
||||
let convoFound = this.conversations.find((conversation) => {
|
||||
return conversation.key === this.selectedConversation;
|
||||
return conversation.key === this.selectedConversation.key;
|
||||
});
|
||||
|
||||
this.$store.dispatch('members:sendPrivateMessage', {
|
||||
toUserId: this.selectedConversation,
|
||||
toUserId: this.selectedConversation.key,
|
||||
message: this.newMessage,
|
||||
});
|
||||
|
||||
|
||||
@@ -279,7 +279,6 @@ div
|
||||
.points {{$t('pts')}}
|
||||
.col-4
|
||||
.up(v-if='user.stats.points', @click='allocate(stat)')
|
||||
private-message-modal
|
||||
send-gems-modal(:userReceivingGems='userReceivingGems')
|
||||
</template>
|
||||
|
||||
@@ -559,7 +558,6 @@ import allocate from '../../../common/script/ops/allocate';
|
||||
|
||||
import MemberDetails from '../memberDetails';
|
||||
import bPopover from 'bootstrap-vue/lib/components/popover';
|
||||
import privateMessageModal from 'client/components/private-message-modal';
|
||||
import sendGemsModal from 'client/components/payments/sendGemsModal';
|
||||
import markdown from 'client/directives/markdown';
|
||||
import toggleSwitch from 'client/components/ui/toggleSwitch';
|
||||
@@ -580,7 +578,6 @@ export default {
|
||||
},
|
||||
components: {
|
||||
bModal,
|
||||
privateMessageModal,
|
||||
sendGemsModal,
|
||||
MemberDetails,
|
||||
toggleSwitch,
|
||||
@@ -710,8 +707,10 @@ export default {
|
||||
this.$store.state.profileOptions.startingPage = page;
|
||||
},
|
||||
sendMessage () {
|
||||
this.$store.state.userIdToMessage = this.user._id;
|
||||
this.$root.$emit('show::modal', 'private-message');
|
||||
this.$root.$emit('habitica::new-inbox-message', {
|
||||
userIdToMessage: this.user._id,
|
||||
userName: this.user.profile.name,
|
||||
});
|
||||
},
|
||||
getProgressDisplay () {
|
||||
// let currentLoginDay = Content.loginIncentives[this.user.loginIncentives];
|
||||
|
||||
@@ -132,7 +132,6 @@ export default function () {
|
||||
upgradingGroup: {},
|
||||
notificationStore: [],
|
||||
modalStack: [],
|
||||
userIdToMessage: '',
|
||||
brokenChallengeTask: {},
|
||||
equipmentDrawerOpen: true,
|
||||
recentlyPurchased: {},
|
||||
|
||||
@@ -397,5 +397,7 @@
|
||||
"groupTaskBoard": "Task Board",
|
||||
"groupInformation": "Group Information",
|
||||
"groupBilling": "Group Billing",
|
||||
"wouldYouParticipate": "Would you like to participate?"
|
||||
"wouldYouParticipate": "Would you like to participate?",
|
||||
"managerAdded": "Manager added successfully",
|
||||
"managerRemoved": "Manager removed successfully"
|
||||
}
|
||||
|
||||
@@ -64,5 +64,6 @@
|
||||
"messageUserOperationNotFound": "<%= operation %> operation 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!"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user