mirror of
				https://github.com/HabitRPG/habitica.git
				synced 2025-10-30 04:32:45 +01:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 0ffd3e5883 | 
							
								
								
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "habitica", | ||||
|   "version": "4.0.8", | ||||
|   "version": "4.0.6", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|   "name": "habitica", | ||||
|   "description": "A habit tracker app which treats your goals like a Role Playing Game.", | ||||
|   "version": "4.0.8", | ||||
|   "version": "4.0.6", | ||||
|   "main": "./website/server/index.js", | ||||
|   "dependencies": { | ||||
|     "@slack/client": "^3.8.1", | ||||
|   | ||||
| @@ -138,21 +138,12 @@ export default { | ||||
|     // @TODO split up this file, it's too big | ||||
|     // Set up Error interceptors | ||||
|     axios.interceptors.response.use((response) => { | ||||
|       if (this.user && response.data && response.data.notifications) { | ||||
|       if (this.user) { | ||||
|         this.$set(this.user, 'notifications', response.data.notifications); | ||||
|       } | ||||
|       return response; | ||||
|     }, (error) => { | ||||
|       if (error.response.status >= 400) { | ||||
|         // Don't show errors from getting user details. These users have delete their account, | ||||
|         // but their chat message still exists. | ||||
|         let configExists = Boolean(error.response) && Boolean(error.response.config); | ||||
|         if (configExists && error.response.config.method === 'get' && error.response.config.url.indexOf('/api/v3/members/') !== -1) { | ||||
|           // @TODO: We resolve the promise because we need our caching to cache this user as tried | ||||
|           // Chat paging should help this, but maybe we can also find another solution.. | ||||
|           return Promise.resolve(error); | ||||
|         } | ||||
|  | ||||
|         this.$store.state.notificationStore.push({ | ||||
|           title: 'Habitica', | ||||
|           text: error.response.data.message, | ||||
|   | ||||
| @@ -1,20 +1,14 @@ | ||||
| <template lang="pug"> | ||||
|   b-modal#quest-completed(v-if='user.party.quest.completed', :title="title", | ||||
|     size='md', :hide-footer="true") | ||||
|   b-modal#quest-completed(v-if='user.party.quest.completed', :title="quests[user.party.quest.completed].text() + '' + $t('completed')", | ||||
|     size='lg', :hide-footer="true") | ||||
|     .modal-body.text-center | ||||
|       .quest(:class='`quest_${user.party.quest.completed}`') | ||||
|       p(v-html='this.questData.completion()') | ||||
|       div(:class='`quest_${user.party.quest.completed}`') | ||||
|       p(v-html='quests[user.party.quest.completed].completion()') | ||||
|       .quest-rewards(key='user.party.quest.completed', header-participant="$t('youReceived')", header-quest-owner="$t('questOwnerReceived')") | ||||
|     .modal-footer | ||||
|       button.btn.btn-primary(@click='setQuestCompleted()') {{ $t('ok') }} | ||||
| </template> | ||||
|  | ||||
| <style scoped> | ||||
|   .quest { | ||||
|     margin: 0 auto; | ||||
|   } | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
| import bModal from 'bootstrap-vue/lib/components/modal'; | ||||
| import quests from 'common/script/content/quests'; | ||||
| @@ -35,12 +29,6 @@ export default { | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState({user: 'user.data'}), | ||||
|     questData () { | ||||
|       return this.quests.quests[this.user.party.quest.completed]; | ||||
|     }, | ||||
|     title () { | ||||
|       return `${this.questData.text()} ${this.$t('completed')}`; | ||||
|     }, | ||||
|     barStyle () { | ||||
|       return { | ||||
|         width: `${percent(this.user.stats.hp, maxHealth)}%`, | ||||
|   | ||||
| @@ -4,12 +4,12 @@ | ||||
|   modify-inventory(v-if="isUserLoaded") | ||||
|   footer.container-fluid | ||||
|     .row | ||||
|       .col-12.col-md-2 | ||||
|       .col-2 | ||||
|         h3 | ||||
|           a(href='https://itunes.apple.com/us/app/habitica/id994882113?ls=1&mt=8', target='_blank') {{ $t('mobileIOS') }} | ||||
|         h3 | ||||
|           a(href='https://play.google.com/store/apps/details?id=com.habitrpg.android.habitica', target='_blank') {{ $t('mobileAndroid') }} | ||||
|       .col-12.col-md-2 | ||||
|       .col-2 | ||||
|         h3 Company | ||||
|         ul | ||||
|           li | ||||
| @@ -28,7 +28,7 @@ | ||||
|             a(href='/static/press-kit') {{ $t('presskit') }} | ||||
|           li | ||||
|             a(href='/static/contact') {{ $t('contactUs') }} | ||||
|       .col-12.col-md-2 | ||||
|       .col-2 | ||||
|         h3 Community | ||||
|         ul | ||||
|           li | ||||
| @@ -47,7 +47,7 @@ | ||||
|             a(href='https://www.facebook.com/Habitica', target='_blank') {{ $t('communityFacebook') }} | ||||
|           li | ||||
|             a(href='https://www.reddit.com/r/habitrpg/', target='_blank') {{ $t('communityReddit') }} | ||||
|       .col-12.col-md-6 | ||||
|       .col-6 | ||||
|         .row | ||||
|           .col-6 | ||||
|             h3 Developers | ||||
| @@ -55,7 +55,7 @@ | ||||
|               li | ||||
|                 a(href='/apidoc', target='_blank') {{ $t('APIv3') }} | ||||
|               li | ||||
|                 a(href='https://oldgods.net/habitrpg/habitrpg_user_data_display.html', target='_blank') {{ $t('dataDisplayTool') }} | ||||
|                 a(href='http://data.habitrpg.com/?uuid=', target='_blank') {{ $t('dataDisplayTool') }} | ||||
|               li | ||||
|                 a(href='http://habitica.wikia.com/wiki/Guidance_for_Blacksmiths', target='_blank') {{ $t('guidanceForBlacksmiths') }} | ||||
|               li | ||||
|   | ||||
| @@ -52,7 +52,7 @@ div | ||||
|             a.dropdown-item(href="https://trello.com/c/odmhIqyW/440-read-first-table-of-contents", target='_blank') {{ $t('requestAF') }} | ||||
|             a.dropdown-item(href="http://habitica.wikia.com/wiki/Contributing_to_Habitica", target='_blank') {{ $t('contributing') }} | ||||
|             a.dropdown-item(href="http://habitica.wikia.com/wiki/Habitica_Wiki", target='_blank') {{ $t('wiki') }} | ||||
|       .item-with-icon(v-if="userHourglasses > 0") | ||||
|       .item-with-icon(v-if="userHourglasses != 0") | ||||
|         .svg-icon(v-html="icons.hourglasses") | ||||
|         span {{ userHourglasses }} | ||||
|       .item-with-icon | ||||
|   | ||||
| @@ -51,7 +51,7 @@ | ||||
|           ) | ||||
|  | ||||
|     .row | ||||
|       task-column.col-12.col-sm-6( | ||||
|       task-column.col-6( | ||||
|         v-for="column in columns", | ||||
|         :type="column", | ||||
|         :key="column", | ||||
|   | ||||
| @@ -16,7 +16,7 @@ | ||||
|           .svg-icon.positive-icon(v-html="icons.positiveIcon") | ||||
|           span(v-once) {{$t('createChallenge')}} | ||||
|     .row | ||||
|       .col-12.col-md-6(v-for='challenge in filteredChallenges', v-if='!memberOf(challenge)') | ||||
|       .col-6(v-for='challenge in filteredChallenges', v-if='!memberOf(challenge)') | ||||
|         challenge-item(:challenge='challenge') | ||||
| </template> | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
|         p(v-once) {{$t('challengeDescription2')}} | ||||
|  | ||||
|     .row | ||||
|       .col-12.col-md-6(v-for='challenge in filteredChallenges') | ||||
|       .col-6(v-for='challenge in filteredChallenges') | ||||
|         challenge-item(:challenge='challenge') | ||||
| </template> | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <template lang="pug"> | ||||
| .col-2.standard-sidebar.hidden-xs-down | ||||
| .col-2.standard-sidebar | ||||
|   .form-group | ||||
|     input.form-control.search(type="text", :placeholder="$t('search')", v-model='searchTerm') | ||||
|  | ||||
|   | ||||
| @@ -5,14 +5,14 @@ | ||||
|       copy-as-todo-modal(:copying-message='copyingMessage', :group-name='groupName', :group-id='groupId') | ||||
|       report-flag-modal | ||||
|  | ||||
|   div(v-for="(msg, index) in messages", v-if='chat && canViewFlag(msg)') | ||||
|   div(v-for="(msg, index) in chat", v-if='chat && canViewFlag(msg)') | ||||
|     // @TODO: is there a different way to do these conditionals? This creates an infinite loop | ||||
|     //.hr(v-if='displayDivider(msg)') | ||||
|       .hr-middle(v-once) {{ msg.timestamp }} | ||||
|     .row(v-if='user._id !== msg.uuid') | ||||
|       div(:class='inbox ? "col-4" : "col-2"') | ||||
|         avatar( | ||||
|           v-if='cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected', | ||||
|           v-if='cachedProfileData[msg.uuid]', | ||||
|           :member="cachedProfileData[msg.uuid]", | ||||
|           :avatarOnly="true", | ||||
|           :hideClassBadge='true', | ||||
| @@ -36,15 +36,13 @@ | ||||
|               .svg-icon(v-html="icons.like") | ||||
|               span(v-if='!msg.likes[user._id]') {{ $t('like') }} | ||||
|               span(v-if='msg.likes[user._id]') {{ $t('liked') }} | ||||
|             span.action(v-if='!inbox', @click='copyAsTodo(msg)') | ||||
|             span.action( @click='copyAsTodo(msg)') | ||||
|               .svg-icon(v-html="icons.copy") | ||||
|               | {{$t('copyAsTodo')}} | ||||
|               // @TODO make copyAsTodo work in the inbox | ||||
|             span.action(v-if='!inbox && user.flags.communityGuidelinesAccepted', @click='report(msg)') | ||||
|             span.action(v-if='user.contributor.admin || (msg.uuid !== user._id && user.flags.communityGuidelinesAccepted)', @click='report(msg)') | ||||
|               .svg-icon(v-html="icons.report") | ||||
|               | {{$t('report')}} | ||||
|               // @TODO make flagging/reporting work in the inbox. NOTE: it must work even if the communityGuidelines are not accepted and it MUST work for messages that you have SENT as well as received. -- Alys | ||||
|             span.action(v-if='msg.uuid === user._id || inbox || user.contributor.admin', @click='remove(msg, index)') | ||||
|             span.action(v-if='msg.uuid === user._id || inbox', @click='remove(msg, index)') | ||||
|               .svg-icon(v-html="icons.delete") | ||||
|               | {{$t('delete')}} | ||||
|             span.action.float-right.liked(v-if='likeCount(msg) > 0') | ||||
| @@ -72,15 +70,12 @@ | ||||
|               .svg-icon(v-html="icons.like") | ||||
|               span(v-if='!msg.likes[user._id]') {{ $t('like') }} | ||||
|               span(v-if='msg.likes[user._id]') {{ $t('liked') }} | ||||
|             span.action(v-if='!inbox', @click='copyAsTodo(msg)') | ||||
|             span.action( @click='copyAsTodo(msg)') | ||||
|               .svg-icon(v-html="icons.copy") | ||||
|               | {{$t('copyAsTodo')}} | ||||
|               // @TODO make copyAsTodo work in the inbox | ||||
|             span.action(v-if='user.flags.communityGuidelinesAccepted', @click='report(msg)') | ||||
|             span.action(v-if='!inbox && user.flags.communityGuidelinesAccepted', @click='report(msg)') | ||||
|               .svg-icon(v-html="icons.report") | ||||
|               | {{$t('report')}} | ||||
|               // @TODO make flagging/reporting work in the inbox. NOTE: it must work even if the communityGuidelines are not accepted and it MUST work for messages that you have SENT as well as received. -- Alys | ||||
|             span.action(v-if='msg.uuid === user._id', @click='remove(msg, index)') | ||||
|               .svg-icon(v-html="icons.delete") | ||||
|               | {{$t('delete')}} | ||||
| @@ -89,7 +84,7 @@ | ||||
|               | + {{ likeCount(msg) }} | ||||
|       div(:class='inbox ? "col-4" : "col-2"') | ||||
|         avatar( | ||||
|           v-if='cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected', | ||||
|           v-if='cachedProfileData[msg.uuid]', | ||||
|           :member="cachedProfileData[msg.uuid]", | ||||
|           :avatarOnly="true", | ||||
|           :hideClassBadge='true', | ||||
| @@ -243,7 +238,7 @@ import axios from 'axios'; | ||||
| import moment from 'moment'; | ||||
| import cloneDeep from 'lodash/cloneDeep'; | ||||
| import { mapState } from 'client/libs/store'; | ||||
| import debounce from 'lodash/debounce'; | ||||
| import throttle from 'lodash/throttle'; | ||||
| import markdownDirective from 'client/directives/markdown'; | ||||
| import Avatar from '../avatar'; | ||||
| import styleHelper from 'client/mixins/styleHelper'; | ||||
| @@ -282,10 +277,12 @@ export default { | ||||
|     this.loadProfileCache(); | ||||
|   }, | ||||
|   created () { | ||||
|     window.addEventListener('scroll', this.handleScroll); | ||||
|     window.addEventListener('scroll', throttle(() => { | ||||
|       this.loadProfileCache(window.scrollY / 1000); | ||||
|     }, 1000)); | ||||
|   }, | ||||
|   destroyed () { | ||||
|     window.removeEventListener('scroll', this.handleScroll); | ||||
|     // window.removeEventListener('scroll', this.handleScroll); | ||||
|   }, | ||||
|   data () { | ||||
|     return { | ||||
| @@ -311,7 +308,6 @@ export default { | ||||
|       cachedProfileData: {}, | ||||
|       currentProfileLoadedCount: 0, | ||||
|       currentProfileLoadedEnd: 10, | ||||
|       loading: false, | ||||
|     }; | ||||
|   }, | ||||
|   filters: { | ||||
| @@ -325,22 +321,17 @@ export default { | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState({user: 'user.data'}), | ||||
|     // @TODO: We need a different lazy load mechnism. | ||||
|     // But honestly, adding a paging route to chat would solve this | ||||
|     messages () { | ||||
|       return this.chat; | ||||
|     }, | ||||
|   }, | ||||
|   watch: { | ||||
|     messages (oldValue, newValue) { | ||||
|       if (newValue.length === oldValue.length) return; | ||||
|     messages () { | ||||
|       // @TODO: MAybe we should watch insert and remove? | ||||
|       this.loadProfileCache(); | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     handleScroll () { | ||||
|       this.loadProfileCache(window.scrollY / 1000); | ||||
|     }, | ||||
|     isUserMentioned (message) { | ||||
|       let user = this.user; | ||||
|  | ||||
| @@ -367,10 +358,7 @@ export default { | ||||
|       if (!message.flagCount || message.flagCount < 2) return true; | ||||
|       return this.user.contributor.admin; | ||||
|     }, | ||||
|     loadProfileCache: debounce(function loadProfileCache (screenPosition) { | ||||
|       this._loadProfileCache(screenPosition); | ||||
|     }, 1000), | ||||
|     async _loadProfileCache (screenPosition) { | ||||
|     async loadProfileCache (screenPosition) { | ||||
|       let promises = []; | ||||
|  | ||||
|       // @TODO: write an explination | ||||
| @@ -380,10 +368,11 @@ export default { | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       // @TODO: Not sure we need this hash | ||||
|       let aboutToCache = {}; | ||||
|       this.messages.forEach(message => { | ||||
|         let uuid = message.uuid; | ||||
|         if (Boolean(uuid) && !this.cachedProfileData[uuid] && !aboutToCache[uuid]) { | ||||
|         if (uuid && !this.cachedProfileData[uuid] && !aboutToCache[uuid]) { | ||||
|           if (uuid === 'system' || this.currentProfileLoadedCount === this.currentProfileLoadedEnd) return; | ||||
|           aboutToCache[uuid] = {}; | ||||
|           promises.push(axios.get(`/api/v3/members/${uuid}`)); | ||||
| @@ -393,21 +382,9 @@ export default { | ||||
|  | ||||
|       let results = await Promise.all(promises); | ||||
|       results.forEach(result => { | ||||
|         // We could not load the user. Maybe they were deleted. So, let's cache empty so we don't try again | ||||
|         if (!result || !result.data || result.status >= 400) { | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|         let userData = result.data.data; | ||||
|         this.$set(this.cachedProfileData, userData._id, userData); | ||||
|       }); | ||||
|  | ||||
|       // Merge in any attempts that were rejected so we don't attempt again | ||||
|       for (let uuid in aboutToCache) { | ||||
|         if (!this.cachedProfileData[uuid]) { | ||||
|           this.$set(this.cachedProfileData, uuid, {rejected: true}); | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     displayDivider (message) { | ||||
|       if (this.currentDayDividerDisplay !== moment(message.timestamp).day()) { | ||||
|   | ||||
| @@ -72,7 +72,7 @@ | ||||
|         v-on:taskEdited='taskEdited', | ||||
|       ) | ||||
|   .row | ||||
|     task-column.col-12.col-sm-6.col-3( | ||||
|     task-column.col-3( | ||||
|       v-for="column in columns", | ||||
|       :type="column", | ||||
|       :key="column", | ||||
|   | ||||
| @@ -3,8 +3,7 @@ | ||||
|   group-form-modal(v-if='isParty') | ||||
|   invite-modal(:group='this.group') | ||||
|   start-quest-modal(:group='this.group') | ||||
|   quest-details-modal(:group='this.group') | ||||
|   .col-12.col-sm-8.standard-page | ||||
|   .col-8.standard-page | ||||
|     .row | ||||
|       .col-6.title-details | ||||
|         h1 {{group.name}} | ||||
| @@ -46,7 +45,7 @@ | ||||
|           .col-12.hr | ||||
|           chat-message(:chat.sync='group.chat', :group-id='group._id', group-name='group.name') | ||||
|  | ||||
|   .col-12.col-sm-4.sidebar | ||||
|   .col-4.sidebar | ||||
|     .row(:class='{"guild-background": !isParty}') | ||||
|       .col-6 | ||||
|       .col-6 | ||||
| @@ -81,13 +80,9 @@ | ||||
|             p(v-once) {{ $t('questDescription') }} | ||||
|             button.btn.btn-secondary(v-once, @click="openStartQuestModal()", v-if='isLeader') {{ $t('startAQuest') }} | ||||
|         .row.quest-active-section(v-if='isParty && onPendingQuest && !onActiveQuest') | ||||
|           .col-2 | ||||
|             .quest(:class='`inventory_quest_scroll_${questData.key}`') | ||||
|           .col-6.titles | ||||
|             strong {{ questData.text() }} | ||||
|             p {{acceptedCount}} / {{group.memberCount}} | ||||
|           .col-4 | ||||
|             button.btn.btn-secondary(@click="openQuestDetails()") {{ $t('details') }} | ||||
|           h2 Pending quest | ||||
|           button.btn.btn-secondary(v-once, @click="questForceStart()") {{ $t('begin') }} | ||||
|           button.btn.btn-secondary(v-once, @click="questCancel()") {{ $t('cancel') }} | ||||
|         .row.quest-active-section(v-if='isParty && !onPendingQuest && onActiveQuest') | ||||
|           .col-12.text-center | ||||
|             .quest-boss(:class="'quest_' + questData.key") | ||||
| @@ -358,10 +353,6 @@ | ||||
|   } | ||||
|  | ||||
|   .quest-active-section { | ||||
|     .titles { | ||||
|         padding-top: .5em; | ||||
|     } | ||||
|  | ||||
|     .quest-box { | ||||
|       background-image: url('~client/assets/svg/for-css/quest-border.svg'); | ||||
|       background-size: 100% 100%; | ||||
| @@ -440,9 +431,6 @@ | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
| // @TODO: Break this down into components | ||||
|  | ||||
| import debounce from 'lodash/debounce'; | ||||
| import extend from 'lodash/extend'; | ||||
| import groupUtilities from 'client/mixins/groupsUtilities'; | ||||
| import styleHelper from 'client/mixins/styleHelper'; | ||||
| @@ -450,7 +438,6 @@ import { mapState } from 'client/libs/store'; | ||||
| import * as Analytics from 'client/libs/analytics'; | ||||
| import membersModal from './membersModal'; | ||||
| import startQuestModal from './startQuestModal'; | ||||
| import questDetailsModal from './questDetailsModal'; | ||||
| import quests from 'common/script/content/quests'; | ||||
| import percent from 'common/script/libs/percent'; | ||||
| import groupFormModal from './groupFormModal'; | ||||
| @@ -494,7 +481,6 @@ export default { | ||||
|     inviteModal, | ||||
|     groupChallenges, | ||||
|     autocomplete, | ||||
|     questDetailsModal, | ||||
|   }, | ||||
|   directives: { | ||||
|     bToggle, | ||||
| @@ -536,17 +522,6 @@ export default { | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState({user: 'user.data'}), | ||||
|     acceptedCount () { | ||||
|       let count = 0; | ||||
|  | ||||
|       if (!this.group || !this.group.quest) return count; | ||||
|  | ||||
|       for (let uuid in this.group.quest.members) { | ||||
|         if (this.group.quest.members[uuid]) count += 1; | ||||
|       } | ||||
|  | ||||
|       return count; | ||||
|     }, | ||||
|     communityGuidelinesAccepted () { | ||||
|       return this.user.flags.communityGuidelinesAccepted; | ||||
|     }, | ||||
| @@ -680,10 +655,7 @@ export default { | ||||
|       }; | ||||
|       document.body.removeChild(div); | ||||
|     }, | ||||
|     updateCarretPosition: debounce(function updateCarretPosition (eventUpdate) { | ||||
|       this._updateCarretPosition(eventUpdate); | ||||
|     }, 250), | ||||
|     _updateCarretPosition (eventUpdate) { | ||||
|     updateCarretPosition (eventUpdate) { | ||||
|       if (eventUpdate.metaKey && eventUpdate.keyCode === 13) { | ||||
|         this.sendMessage(); | ||||
|         return; | ||||
| @@ -745,9 +717,6 @@ export default { | ||||
|     openStartQuestModal () { | ||||
|       this.$root.$emit('show::modal', 'start-quest-modal'); | ||||
|     }, | ||||
|     openQuestDetails () { | ||||
|       this.$root.$emit('show::modal', 'quest-details'); | ||||
|     }, | ||||
|     checkForAchievements () { | ||||
|       // Checks if user's party has reached 2 players for the first time. | ||||
|       if (!this.user.achievements.partyUp && this.group.memberCount >= 2) { | ||||
| @@ -842,6 +811,11 @@ export default { | ||||
|       this.$store.state.profileOptions.startingPage = 'profile'; | ||||
|       this.$root.$emit('show::modal', 'profile'); | ||||
|     }, | ||||
|     async questCancel () { | ||||
|       if (!confirm(this.$t('sureCancel'))) return; | ||||
|       let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/cancel'}); | ||||
|       this.group.quest = quest; | ||||
|     }, | ||||
|     async questAbort () { | ||||
|       if (!confirm(this.$t('sureAbort'))) return; | ||||
|       if (!confirm(this.$t('doubleSureAbort'))) return; | ||||
| @@ -857,6 +831,10 @@ export default { | ||||
|       let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/accept'}); | ||||
|       this.group.quest = quest; | ||||
|     }, | ||||
|     async questForceStart () { | ||||
|       let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/force-start'}); | ||||
|       this.group.quest = quest; | ||||
|     }, | ||||
|     // @TODO: Move to notificaitons component? | ||||
|     async questReject () { | ||||
|       let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/reject'}); | ||||
|   | ||||
| @@ -1,210 +0,0 @@ | ||||
| <template lang="pug"> | ||||
|   b-modal#quest-details(title="Empty", size='md', :hide-footer="true", :hide-header="true") | ||||
|     .left-panel.content | ||||
|       h3.text-center {{ $t('participantsTitle') }} | ||||
|       .row | ||||
|         .col-10.offset-1.text-center | ||||
|           span.description(v-once) {{ $t('participantDesc') }} | ||||
|       .row | ||||
|         .col-12.member(v-for='member in members') | ||||
|           strong(:class="{'declined-name': member.accepted === false}") {{member.name}} | ||||
|           .accepted.float-right(v-if='member.accepted === true') {{ $t('accepted') }} | ||||
|           .declined.float-right(v-if='member.accepted === false') {{ $t('declined') }} | ||||
|           .pending.float-right(v-if='member.accepted === null') {{ $t('pending') }} | ||||
|     div(v-if='questData') | ||||
|       questDialogContent(:item="questData") | ||||
|     div.text-center.actions | ||||
|       div | ||||
|         button.btn.btn-secondary(v-once, @click="questForceStart()") {{ $t('begin') }} | ||||
|       div | ||||
|         .cancel(v-once, @click="questCancel()") {{ $t('cancel') }} | ||||
|     .side-panel(v-if='questData') | ||||
|       questDialogDrops(:item="questData") | ||||
| </template> | ||||
|  | ||||
| <style lang='scss' scoped> | ||||
|   @import '~client/assets/scss/colors.scss'; | ||||
|  | ||||
|   header { | ||||
|     background-color: $white !important; | ||||
|     border: none !important; | ||||
|  | ||||
|     h5 { | ||||
|       text-indent: -99999px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .quest-details { | ||||
|     margin: 0 auto; | ||||
|     text-align: left; | ||||
|     width: 180px; | ||||
|   } | ||||
|  | ||||
|   .btn-primary { | ||||
|     margin: 1em 0; | ||||
|   } | ||||
|  | ||||
|   .left-panel { | ||||
|     background: #4e4a57; | ||||
|     color: $white; | ||||
|     position: absolute; | ||||
|     height: 460px; | ||||
|     width: 320px; | ||||
|     top: 2.5em; | ||||
|     left: -22em; | ||||
|     z-index: -1; | ||||
|     padding: 2em; | ||||
|     overflow: scroll; | ||||
|  | ||||
|     h3 { | ||||
|       color: $white; | ||||
|     } | ||||
|  | ||||
|     .selected .quest-wrapper { | ||||
|       border: solid 1.5px #9a62ff; | ||||
|     } | ||||
|  | ||||
|     .quest-wrapper:hover { | ||||
|       cursor: pointer; | ||||
|     } | ||||
|  | ||||
|     .quest-col .quest-wrapper { | ||||
|       background: $white; | ||||
|       padding: .2em; | ||||
|       margin-bottom: 1em; | ||||
|       border-radius: 3px; | ||||
|     } | ||||
|  | ||||
|     .description { | ||||
|       text-align: center; | ||||
|       color: #a5a1ac; | ||||
|       font-size: 12px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .side-panel { | ||||
|     position: absolute; | ||||
|     right: -350px; | ||||
|     top: 25px; | ||||
|     border-radius: 8px; | ||||
|     background-color: $gray-600; | ||||
|     box-shadow: 0 2px 16px 0 rgba(26, 24, 29, 0.32); | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     flex-direction: column; | ||||
|     width: 364px; | ||||
|     z-index: -1; | ||||
|     height: 93%; | ||||
|   } | ||||
|  | ||||
|   .member { | ||||
|     padding: 1em .5em; | ||||
|     border-top: 1px solid #686274; | ||||
|  | ||||
|     .declined-name { | ||||
|       color: #878190; | ||||
|     } | ||||
|  | ||||
|     .accepted { | ||||
|       color: #1ed3a0; | ||||
|     } | ||||
|  | ||||
|     .declined { | ||||
|       color: #f19595; | ||||
|     } | ||||
|  | ||||
|     .pending { | ||||
|       color: #c3c0c7; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .actions { | ||||
|     padding-top: 2em; | ||||
|     padding-bottom: 2em; | ||||
|  | ||||
|     .cancel { | ||||
|       color: #f74e52; | ||||
|       margin-top: 3em; | ||||
|     } | ||||
|  | ||||
|     .cancel:hover { | ||||
|       cursor: pointer; | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
| import { mapState } from 'client/libs/store'; | ||||
| import bModal from 'bootstrap-vue/lib/components/modal'; | ||||
|  | ||||
| import quests from 'common/script/content/quests'; | ||||
|  | ||||
| import copyIcon from 'assets/svg/copy.svg'; | ||||
| import greyBadgeIcon from 'assets/svg/grey-badge.svg'; | ||||
| import qrCodeIcon from 'assets/svg/qrCode.svg'; | ||||
| import facebookIcon from 'assets/svg/facebook.svg'; | ||||
| import twitterIcon from 'assets/svg/twitter.svg'; | ||||
| import starIcon from 'assets/svg/star.svg'; | ||||
| import goldIcon from 'assets/svg/gold.svg'; | ||||
| import difficultyStarIcon from 'assets/svg/difficulty-star.svg'; | ||||
| import questDialogDrops from '../shops/quests/questDialogDrops'; | ||||
| import questDialogContent from '../shops/quests/questDialogContent'; | ||||
|  | ||||
| export default { | ||||
|   props: ['group'], | ||||
|   components: { | ||||
|     bModal, | ||||
|     questDialogDrops, | ||||
|     questDialogContent, | ||||
|   }, | ||||
|   data () { | ||||
|     return { | ||||
|       loading: false, | ||||
|       selectedQuest: {}, | ||||
|       icons: Object.freeze({ | ||||
|         copy: copyIcon, | ||||
|         greyBadge: greyBadgeIcon, | ||||
|         qrCode: qrCodeIcon, | ||||
|         facebook: facebookIcon, | ||||
|         twitter: twitterIcon, | ||||
|         starIcon, | ||||
|         goldIcon, | ||||
|         difficultyStarIcon, | ||||
|       }), | ||||
|     }; | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState({ | ||||
|       user: 'user.data', | ||||
|       partyMembers: 'party.members.data', | ||||
|     }), | ||||
|     questData () { | ||||
|       return quests.quests[this.group.quest.key]; | ||||
|     }, | ||||
|     members () { | ||||
|       return this.partyMembers.map(member => { | ||||
|         return { | ||||
|           name: member.profile.name, | ||||
|           accepted: this.group.quest.members[member._id], | ||||
|         }; | ||||
|       }); | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     async questForceStart () { | ||||
|       let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/force-start'}); | ||||
|       this.group.quest = quest; | ||||
|       this.close(); | ||||
|     }, | ||||
|     async questCancel () { | ||||
|       if (!confirm(this.$t('sureCancel'))) return; | ||||
|       let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/cancel'}); | ||||
|       this.group.quest = quest; | ||||
|       this.close(); | ||||
|     }, | ||||
|     close () { | ||||
|       this.$root.$emit('hide::modal', 'quest-details'); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
| @@ -1,5 +1,5 @@ | ||||
| <template lang="pug"> | ||||
| .standard-sidebar.hidden-xs-down | ||||
| .standard-sidebar | ||||
|   .form-group | ||||
|     input.form-control.search(type="text", :placeholder="$t('search')", v-model='searchTerm') | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <template lang="pug"> | ||||
| .row | ||||
|   .col-12.col-sm-8.clearfix.standard-page | ||||
|   .clearfix.col-8.standard-page | ||||
|     .row | ||||
|       .col-6.title-details | ||||
|         h1(v-once) {{ $t('welcomeToTavern') }} | ||||
| @@ -29,7 +29,7 @@ | ||||
|           .hr.col-12 | ||||
|           chat-message(:chat.sync='group.chat', :group-id='group._id', group-name='group.name') | ||||
|  | ||||
|   .col-12.col-sm-4.sidebar | ||||
|   .col-md-4.sidebar | ||||
|     .section | ||||
|       .grassy-meadow-backdrop | ||||
|         .daniel_front | ||||
| @@ -350,7 +350,6 @@ | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
| import debounce from 'lodash/debounce'; | ||||
| import { mapState } from 'client/libs/store'; | ||||
|  | ||||
| import { TAVERN_ID } from '../../../common/script/constants'; | ||||
| @@ -528,10 +527,7 @@ export default { | ||||
|       }; | ||||
|       document.body.removeChild(div); | ||||
|     }, | ||||
|     updateCarretPosition: debounce(function updateCarretPosition (eventUpdate) { | ||||
|       this._updateCarretPosition(eventUpdate); | ||||
|     }, 250), | ||||
|     _updateCarretPosition (eventUpdate) { | ||||
|     updateCarretPosition (eventUpdate) { | ||||
|       if (eventUpdate.metaKey && eventUpdate.keyCode === 13) { | ||||
|         this.sendMessage(); | ||||
|         return; | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| <template lang="pug"> | ||||
|   // @TODO: breakdown to componentes and use some SOLID | ||||
|   .row.stable(v-mousePosition="30", @mouseMoved="mouseMoved($event)") | ||||
|     .standard-sidebar.col-3.hidden-xs-down | ||||
|     .standard-sidebar | ||||
|       div | ||||
|         #npmMattStable.npc_matt | ||||
|         b-popover( | ||||
| @@ -54,7 +53,7 @@ | ||||
|             @change="updateHideMissing" | ||||
|           ) | ||||
|  | ||||
|     .standard-page.col-12.col-sm-9 | ||||
|     .standard-page | ||||
|       .clearfix | ||||
|         h1.float-left.mb-0.page-header(v-once) {{ $t('stable') }} | ||||
|  | ||||
| @@ -74,49 +73,55 @@ | ||||
|         span.badge.badge-pill.badge-default {{countOwnedAnimals(petGroups[0], 'pet')}} | ||||
|  | ||||
|       div( | ||||
|         v-for="(petGroup, index) in petGroups", | ||||
|         v-for="petGroup in petGroups", | ||||
|         v-if="viewOptions[petGroup.key].selected", | ||||
|         :key="petGroup.key" | ||||
|       ) | ||||
|         h4(v-if="viewOptions[petGroup.key].animalCount !== 0") {{ petGroup.label }} | ||||
|         h4(v-if="viewOptions[petGroup.key].animalCount != 0") {{ petGroup.label }} | ||||
|  | ||||
|         .pet-row.d-flex( | ||||
|           v-for="(group, key, index) in pets(petGroup, hideMissing, selectedSortBy, searchTextThrottled)", | ||||
|           v-if='index === 0 || showMore === petGroup.key') | ||||
|           .pet-group( | ||||
|             v-for='item in group' | ||||
|             v-drag.drop.food="item.key", | ||||
|             @itemDragOver="onDragOver($event, item)", | ||||
|             @itemDropped="onDrop($event, item)", | ||||
|             @itemDragLeave="onDragLeave()", | ||||
|             :class="{'last': item.isLastInRow}" | ||||
|           ) | ||||
|             petItem( | ||||
|               :item="item", | ||||
|               :itemContentClass="getPetItemClass(item)", | ||||
|               :popoverPosition="'top'", | ||||
|               :progress="item.progress", | ||||
|               :emptyItem="!item.isOwned()", | ||||
|               :showPopover="currentDraggingFood == null", | ||||
|               :highlightBorder="highlightPet == item.key", | ||||
|               @click="petClicked(item)" | ||||
|         itemRows( | ||||
|           :items="pets(petGroup, hideMissing, selectedSortBy, searchTextThrottled)", | ||||
|           :itemWidth=94, | ||||
|           :itemMargin=24, | ||||
|           :type="petGroup.key", | ||||
|         ) | ||||
|           template(slot="item", scope="context") | ||||
|             div( | ||||
|               v-drag.drop.food="context.item.key", | ||||
|               @itemDragOver="onDragOver($event, context.item)", | ||||
|               @itemDropped="onDrop($event, context.item)", | ||||
|               @itemDragLeave="onDragLeave()", | ||||
|               :class="{'last': context.item.isLastInRow}" | ||||
|             ) | ||||
|               span(slot="popoverContent") | ||||
|                 div.hatchablePopover(v-if="item.isHatchable()") | ||||
|                   h4.popover-content-title {{ item.name }} | ||||
|                   div.popover-content-text(v-html="$t('haveHatchablePet', { potion: item.potionName, egg: item.eggName })") | ||||
|                   div.potionEggGroup | ||||
|                     div.potionEggBackground | ||||
|                       div(:class="'Pet_HatchingPotion_'+item.potionKey") | ||||
|                     div.potionEggBackground | ||||
|                       div(:class="'Pet_Egg_'+item.eggKey") | ||||
|                 div(v-else) | ||||
|                   h4.popover-content-title {{ item.name }} | ||||
|               template(slot="itemBadge", scope="context") | ||||
|               starBadge(:selected="item.key === currentPet", :show="item.isOwned()", @click="selectPet(item)") | ||||
|               petItem( | ||||
|                 :item="context.item", | ||||
|                 :itemContentClass="getPetItemClass(context.item)", | ||||
|                 :popoverPosition="'top'", | ||||
|                 :progress="context.item.progress", | ||||
|                 :emptyItem="!context.item.isOwned()", | ||||
|                 :showPopover="currentDraggingFood == null", | ||||
|                 :highlightBorder="highlightPet == context.item.key", | ||||
|                 @click="petClicked(context.item)" | ||||
|               ) | ||||
|                 span(slot="popoverContent") | ||||
|                   div.hatchablePopover(v-if="context.item.isHatchable()") | ||||
|                     h4.popover-content-title {{ context.item.name }} | ||||
|                     div.popover-content-text(v-html="$t('haveHatchablePet', { potion: context.item.potionName, egg: context.item.eggName })") | ||||
|                     div.potionEggGroup | ||||
|                       div.potionEggBackground | ||||
|                         div(:class="'Pet_HatchingPotion_'+context.item.potionKey") | ||||
|                       div.potionEggBackground | ||||
|                         div(:class="'Pet_Egg_'+context.item.eggKey") | ||||
|  | ||||
|         .btn.btn-flat.btn-show-more(@click="setShowMore(petGroup.key)", v-if='petGroup.key !== "specialPets"') | ||||
|           | {{ showMore === petGroup.key ? $t('showLess') : $t('showMore') }} | ||||
|                   div(v-else) | ||||
|                     h4.popover-content-title {{ context.item.name }} | ||||
|  | ||||
|                 template(slot="itemBadge", scope="context") | ||||
|                   starBadge( | ||||
|                     :selected="context.item.key === currentPet", | ||||
|                     :show="context.item.isOwned()", | ||||
|                     @click="selectPet(context.item)", | ||||
|                   ) | ||||
|  | ||||
|       h2 | ||||
|         | {{ $t('mounts') }} | ||||
| @@ -130,30 +135,31 @@ | ||||
|       ) | ||||
|         h4(v-if="viewOptions[mountGroup.key].animalCount != 0") {{ mountGroup.label }} | ||||
|  | ||||
|         .pet-row.d-flex(v-for="(group, key, index) in mounts(mountGroup, hideMissing, selectedSortBy, searchTextThrottled)" | ||||
|           v-if='index === 0 || showMore === mountGroup.key') | ||||
|           .pet-group(v-for='item in group') | ||||
|         itemRows( | ||||
|           :items="mounts(mountGroup, hideMissing, selectedSortBy, searchTextThrottled)", | ||||
|           :itemWidth=94, | ||||
|           :itemMargin=24, | ||||
|           :type="mountGroup.key", | ||||
|         ) | ||||
|           template(slot="item", scope="context") | ||||
|             mountItem( | ||||
|               :item="item", | ||||
|               :itemContentClass="item.isOwned() ? ('Mount_Icon_' + item.key) : 'PixelPaw GreyedOut'", | ||||
|               :key="item.key", | ||||
|               :item="context.item", | ||||
|               :itemContentClass="context.item.isOwned() ? ('Mount_Icon_' + context.item.key) : 'PixelPaw GreyedOut'", | ||||
|               :key="context.item.key", | ||||
|               :popoverPosition="'top'", | ||||
|               :emptyItem="!item.isOwned()", | ||||
|               :emptyItem="!context.item.isOwned()", | ||||
|               :showPopover="true", | ||||
|               @click="selectMount(item)" | ||||
|               @click="selectMount(context.item)" | ||||
|             ) | ||||
|               span(slot="popoverContent") | ||||
|                 h4.popover-content-title {{ item.name }} | ||||
|                 h4.popover-content-title {{ context.item.name }} | ||||
|               template(slot="itemBadge", scope="context") | ||||
|                 starBadge( | ||||
|                   :selected="item.key === currentMount", | ||||
|                   :show="item.isOwned()", | ||||
|                   @click="selectMount(item)", | ||||
|                   :selected="context.item.key === currentMount", | ||||
|                   :show="context.item.isOwned()", | ||||
|                   @click="selectMount(context.item)", | ||||
|                 ) | ||||
|  | ||||
|         .btn.btn-flat.btn-show-more(@click="setShowMore(mountGroup.key)", v-if='mountGroup.key !== "specialMounts"') | ||||
|           | {{ showMore === mountGroup.key ? $t('showLess') : $t('showMore') }} | ||||
|  | ||||
|       drawer( | ||||
|         :title="$t('quickInventory')", | ||||
|         :errorMessage="(!hasDrawerTabItems(selectedDrawerTab)) ? ((selectedDrawerTab === 0) ?  $t('noFoodAvailable') : $t('noSaddlesAvailable')) : null" | ||||
| @@ -213,6 +219,7 @@ | ||||
|       :visible="hatchablePet != null", | ||||
|       @change="resetHatchablePet($event)" | ||||
|     ) | ||||
|  | ||||
|       div.content(v-if="hatchablePet") | ||||
|         div.potionEggGroup | ||||
|           div.potionEggBackground | ||||
| @@ -246,9 +253,11 @@ | ||||
|         div.food-icon(:class="'Pet_Food_'+currentDraggingFood.key") | ||||
|         div.popover | ||||
|           div.popover-content {{ $t('clickOnPetToFeed', {foodName: currentDraggingFood.text() }) }} | ||||
|  | ||||
| </template> | ||||
|  | ||||
| <style lang="scss"> | ||||
|  | ||||
|   @import '~client/assets/scss/colors.scss'; | ||||
|   @import '~client/assets/scss/modal.scss'; | ||||
|  | ||||
| @@ -274,20 +283,6 @@ | ||||
|     top: -16px !important; | ||||
|   } | ||||
|  | ||||
|   .group { | ||||
|     height: 130px; | ||||
|     overflow: hidden; | ||||
|   } | ||||
|  | ||||
|   .pet-row { | ||||
|     max-width: 100%; | ||||
|     flex-wrap: wrap; | ||||
|  | ||||
|     .item { | ||||
|       margin-right: .5em; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .hatchablePopover { | ||||
|     width: 180px | ||||
|   } | ||||
| @@ -505,7 +500,6 @@ | ||||
|   import _filter from 'lodash/filter'; | ||||
|   import _flatMap from 'lodash/flatMap'; | ||||
|   import _throttle from 'lodash/throttle'; | ||||
|   import groupBy from 'lodash/groupBy'; | ||||
|  | ||||
|   import Item from '../item'; | ||||
|   import ItemRows from 'client/components/ui/itemRows'; | ||||
| @@ -591,7 +585,6 @@ | ||||
|         currentDraggingFood: null, | ||||
|  | ||||
|         selectedDrawerTab: 0, | ||||
|         showMore: '', | ||||
|       }; | ||||
|     }, | ||||
|     watch: { | ||||
| @@ -719,13 +712,7 @@ | ||||
|       }, | ||||
|     }, | ||||
|     methods: { | ||||
|       setShowMore (key) { | ||||
|         if (this.showMore === key) { | ||||
|           this.showMore = ''; | ||||
|           return; | ||||
|         } | ||||
|         this.showMore = key; | ||||
|       }, | ||||
|  | ||||
|       getAnimalList (animalGroup, type) { | ||||
|         let key = animalGroup.key; | ||||
|  | ||||
| @@ -846,39 +833,11 @@ | ||||
|       }, | ||||
|  | ||||
|       pets (animalGroup, hideMissing, sortBy, searchText) { | ||||
|         let pets = this.listAnimals(animalGroup, 'pet', hideMissing, sortBy, searchText); | ||||
|  | ||||
|         // Don't group special | ||||
|         if (animalGroup.key === 'specialPets') { | ||||
|           return {none: pets}; | ||||
|         } | ||||
|  | ||||
|         let groupKey = 'eggKey'; | ||||
|         if (sortBy === 'sortByColor') { | ||||
|           groupKey = 'potionKey'; | ||||
|         } else if (sortBy === 'AZ') { | ||||
|           groupKey = ''; | ||||
|         } | ||||
|  | ||||
|         return groupBy(pets, groupKey); | ||||
|         return this.listAnimals(animalGroup, 'pet', hideMissing, sortBy, searchText); | ||||
|       }, | ||||
|  | ||||
|       mounts (animalGroup, hideMissing, sortBy, searchText) { | ||||
|         let mounts = this.listAnimals(animalGroup, 'mount', hideMissing, sortBy, searchText); | ||||
|  | ||||
|         // Don't group special | ||||
|         if (animalGroup.key === 'specialMounts') { | ||||
|           return {none: mounts}; | ||||
|         } | ||||
|  | ||||
|         let groupKey = 'eggKey'; | ||||
|         if (sortBy === 'sortByColor') { | ||||
|           groupKey = 'potionKey'; | ||||
|         } else if (sortBy === 'AZ') { | ||||
|           groupKey = ''; | ||||
|         } | ||||
|  | ||||
|         return groupBy(mounts, groupKey); | ||||
|         return this.listAnimals(animalGroup, 'mount', hideMissing, sortBy, searchText); | ||||
|       }, | ||||
|  | ||||
|       getPetItemClass (pet) { | ||||
|   | ||||
| @@ -37,11 +37,11 @@ div.item-with-icon.item-notifications.dropdown | ||||
|       @click='go("/user/profile")') | ||||
|       span.glyphicon.glyphicon-plus-sign | ||||
|       span {{ $t('haveUnallocated', {points: user.stats.points}) }} | ||||
|     a.dropdown-item(v-for='message in userNewMessages') | ||||
|       span(@click='navigateToGroup(message.key)') | ||||
|     a.dropdown-item(v-for='(message, key) in user.newMessages', v-if='message.value') | ||||
|       span(@click='navigateToGroup(key)') | ||||
|         span.glyphicon.glyphicon-comment | ||||
|         span {{message.name}} | ||||
|       span.clear-button(@click='clearMessages(message.key)', :popover="$t('clear')", | ||||
|       span.clear-button(@click='clearMessages(key)', :popover="$t('clear')", | ||||
|         popover-placement='right', popover-trigger='mouseenter', popover-append-to-body='true') Clear | ||||
|     a.dropdown-item(v-for='(notification, index) in user.groupNotifications', @click='viewGroupApprovalNotification(notification, index, true)') | ||||
|       span(:class="groupApprovalNotificationIcon(notification)") | ||||
| @@ -156,18 +156,6 @@ export default { | ||||
|       return {name: ''}; | ||||
|       // return this.user.party; | ||||
|     }, | ||||
|     userNewMessages () { | ||||
|       // @TODO: For some reason data becomes corrupted. We should fix this on the server | ||||
|       let userNewMessages = []; | ||||
|       for (let key in this.user.newMessages) { | ||||
|         let message = this.user.newMessages[key]; | ||||
|         if (message && message.name && message.value) { | ||||
|           message.key = key; | ||||
|           userNewMessages.push(message); | ||||
|         } | ||||
|       } | ||||
|       return userNewMessages; | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     // @TODO: I hate this function, we can do better with a hashmap | ||||
| @@ -256,8 +244,8 @@ export default { | ||||
|         count += this.user.stats.points > 0 ? 1 : 0; | ||||
|       } | ||||
|  | ||||
|       if (this.userNewMessages) { | ||||
|         count += Object.keys(this.userNewMessages).length; | ||||
|       if (this.user.newMessages) { | ||||
|         count += Object.keys(this.user.newMessages).length; | ||||
|       } | ||||
|  | ||||
|       return count; | ||||
|   | ||||
| @@ -303,10 +303,6 @@ export default { | ||||
|         this.$root.$emit('show::modal', 'avatar-modal'); | ||||
|       } | ||||
|  | ||||
|       if (this.questCompleted) { | ||||
|         this.$root.$emit('show::modal', 'quest-completed'); | ||||
|       } | ||||
|  | ||||
|       // @TODO: This is a timeout to ensure dom is loaded | ||||
|       window.setTimeout(() => { | ||||
|         this.initTour(); | ||||
|   | ||||
| @@ -36,9 +36,9 @@ | ||||
|         h6(v-once) {{ $t('class') + ': ' }} | ||||
|           // @TODO: what is classText | ||||
|           span(v-if='classText') {{ classText }}  | ||||
|           button.btn.btn-danger.btn-xs(@click='changeClassForUser(true)', v-once) {{ $t('changeClass') }} | ||||
|           small.cost   3 {{ $t('gems') }} | ||||
|             // @TODO add icon span.Pet_Currency_Gem1x.inline-gems | ||||
|           button.btn.btn-danger.btn-xs(@click='changeClass(null)', v-once) {{ $t('changeClass') }} | ||||
|           small.cost 3 | ||||
|             span.Pet_Currency_Gem1x.inline-gems | ||||
|       hr | ||||
|  | ||||
|       div | ||||
| @@ -82,7 +82,7 @@ | ||||
|  | ||||
|         button.btn.btn-primary(@click='showBailey()', popover-trigger='mouseenter', popover-placement='right', :popover="$t('showBaileyPop')") {{ $t('showBailey') }} | ||||
|         button.btn.btn-primary(@click='openRestoreModal()', popover-trigger='mouseenter', popover-placement='right', :popover="$t('fixValPop')") {{ $t('fixVal') }} | ||||
|         button.btn.btn-primary(v-if='user.preferences.disableClasses == true', @click='changeClassForUser(false)', | ||||
|         button.btn.btn-primary(v-if='user.preferences.disableClasses == true', @click='changeClass({})', | ||||
|           popover-trigger='mouseenter', popover-placement='right', :popover="$t('enableClassPop')") {{ $t('enableClass') }} | ||||
|  | ||||
|         hr | ||||
| @@ -378,8 +378,8 @@ export default { | ||||
|  | ||||
|       this.$router.go('/tasks'); | ||||
|     }, | ||||
|     async changeClassForUser (confirmationNeeded) { | ||||
|       if (confirmationNeeded && !confirm(this.$t('changeClassConfirmCost'))) return; | ||||
|     async changeClass () { | ||||
|       if (!confirm('Are you sure you want to change your class for 3 gems?')) return; | ||||
|       try { | ||||
|         changeClass(this.user); | ||||
|         await axios.post('/api/v3/user/change-class'); | ||||
|   | ||||
| @@ -5,7 +5,7 @@ div | ||||
|       .profile-actions | ||||
|         button.btn.btn-secondary(@click='sendMessage()') | ||||
|           .svg-icon.message-icon(v-html="icons.message") | ||||
|         button.btn.btn-secondary(v-if='user._id !== this.userLoggedIn._id && userLoggedIn.inbox.blocks.indexOf(user._id) === -1', :tooltip="$t('unblock')", | ||||
|         button.btn.btn-secondary(v-if='userLoggedIn.inbox.blocks.indexOf(user._id) === -1', :tooltip="$t('unblock')", | ||||
|           @click="blockUser()", tooltip-placement='right') | ||||
|           span.glyphicon.glyphicon-plus | ||||
|           | {{$t('block')}} | ||||
| @@ -795,7 +795,7 @@ export default { | ||||
|       return display; | ||||
|     }, | ||||
|     allocate (stat) { | ||||
|       allocate(this.user, {query: { stat }}); | ||||
|       allocate(this.user, stat); | ||||
|       axios.post(`/api/v3/user/allocate?stat=${stat}`); | ||||
|     }, | ||||
|     allocateNow () { | ||||
|   | ||||
| @@ -125,7 +125,6 @@ | ||||
|   "mystery": "Mystery", | ||||
|   "changeClass": "Change Class, Refund Attribute Points", | ||||
|   "lvl10ChangeClass": "To change class you must be at least level 10.", | ||||
|   "changeClassConfirmCost": "Are you sure you want to change your class for 3 Gems?", | ||||
|   "invalidClass":"Invalid class. Please specify 'warrior', 'rogue', 'wizard', or 'healer'.", | ||||
|   "levelPopover": "Each level earns you one point to assign to an attribute of your choice. You can do so manually, or let the game decide for you using one of the Automatic Allocation options.", | ||||
|   "unallocated": "Unallocated Attribute Points", | ||||
| @@ -159,7 +158,7 @@ | ||||
|   "respawn": "Respawn!", | ||||
|   "youDied": "You Died!", | ||||
|   "dieText": "You've lost a Level, all your Gold, and a random piece of Equipment. Arise, Habiteer, and try again! Curb those negative Habits, be vigilant in completion of Dailies, and hold death at arm's length with a Health Potion if you falter!", | ||||
|   "sureReset": "Are you sure? This will reset your character's class and allocated points (you'll get them all back to re-allocate), and costs 3 Gems.", | ||||
|   "sureReset": "Are you sure? This will reset your character's class and allocated points (you'll get them all back to re-allocate), and costs 3 gems.", | ||||
|   "purchaseFor": "Purchase for <%= cost %> Gems?", | ||||
|   "notEnoughMana": "Not enough mana.", | ||||
|   "invalidTarget": "You can't cast a skill on that.", | ||||
|   | ||||
| @@ -388,7 +388,5 @@ | ||||
|   "selectPartyMember": "Select a Party Member", | ||||
|   "areYouSureDeleteMessage": "Are you sure you want to delete this message?", | ||||
|   "reverseChat": "Reverse Chat", | ||||
|   "invites": "Invites", | ||||
|   "details": "Details", | ||||
|   "participantDesc": "Once all members have either accepted or declined, the Quest begins. Only those that clicked 'accept' will be able to participate in the Quest and receive the drops." | ||||
|   "invites": "Invites" | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user