new client misc fixes (#9033)

* show quests and open quest dialog on click

* extract questDialogContent/Drops to separate components & use those in startQuestModal & buyQuestModal

* fix market search

* remove & readd pinned gear on revive

* remove listener once destroyed
This commit is contained in:
negue
2017-09-16 23:09:31 +02:00
committed by GitHub
parent 8ccec0ed9d
commit 0b0baf2195
9 changed files with 241 additions and 134 deletions

View File

@@ -3,43 +3,20 @@
.left-panel.content
h3.text-center Quests
.row
.col-4.quest-col(v-for='(value, key, index) in user.items.quests', @click='selectQuest(key)', :class="{selected: key === selectedQuest}", v-if='value > 0')
.col-4.quest-col(v-for='(value, key, index) in user.items.quests', @click='selectQuest({key})', :class="{selected: key === selectedQuest}", v-if='value > 0')
.quest-wrapper
.quest(:class="'inventory_quest_scroll_' + key")
.row
.col-10.offset-1.text-center
span.description Cant find a quest to start? Try checking out the Quest Shop in the Market for new releases!
span.description(v-once) {{ $t('noQuestToStart') }}
div(v-if='questData')
.quest-image(:class="'quest_' + questData.key")
h2.text-center {{questData.text()}}
//- span by: Keith Holliday @TODO: Add author
p(v-html="questData.notes()")
div.quest-details
div(v-if=' questData.collect')
Strong {{$t('collect')}}:  
span(v-for="(value, key, index) in questData.collect")
| {{$t('collectionItems', { number: questData.collect[key].count, items: questData.collect[key].text() })}}
div
Strong {{$t('difficulty')}}:  
span
.svg-icon.difficulty-star(v-html="icons.difficultyStarIcon")
questDialogContent(:item="questData")
div.text-center
button.btn.btn-primary(@click='questInit()') {{$t('inviteToPartyOrQuest')}}
div.text-center
p {{$t('inviteInformation')}}
.side-panel(v-if='questData')
h4.text-center {{$t('rewards')}}
.box
.svg-icon.rewards-icon(v-html="icons.starIcon")
strong {{questData.drop.exp}} {{$t('experience')}}
.box
.svg-icon.rewards-icon(v-html="icons.goldIcon")
strong {{questData.drop.gp}} {{$t('gold')}}
h4.text-center(v-if='questData.drop.items') {{$t('questOwnerRewards')}}
.box(v-for='item in questData.drop.items')
.rewards-icon(v-if='item.type === "quest"', :class="'quest_' + item.key")
.drop-rewards-icon(v-if='item.type === "gear"', :class="'shop_' + item.key")
strong.quest-reward-text {{item.text()}}
questDialogDrops(:item="questData")
</template>
<style lang='scss' scoped>
@@ -54,11 +31,7 @@
}
}
.quest-image {
margin: 0 auto;
margin-bottom: 1em;
margin-top: 1.5em;
}
.quest-details {
margin: 0 auto;
@@ -96,7 +69,7 @@
.quest-col .quest-wrapper {
background: $white;
padding: .7em;
padding: .2em;
margin-bottom: 1em;
border-radius: 3px;
}
@@ -109,52 +82,18 @@
}
.side-panel {
background: #edecee;
position: absolute;
height: 460px;
width: 320px;
top: 2.5em;
left: 35em;
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;
padding-top: 1em;
border-radius: 4px;
.drop-rewards-icon {
width: 35px;
height: 35px;
float: left;
}
.rewards-icon {
float: left;
width: 30px;
height: 30px;
svg {
width: 30px;
height: 30px;
}
}
.quest-reward-text {
font-size: 12px;
}
.box {
width: 220px;
height: 64px;
border-radius: 2px;
background-color: #ffffff;
margin: 0 auto;
margin-bottom: 1em;
padding: 1em;
}
}
.difficulty-star {
width: 20px;
display: inline-block;
vertical-align: bottom;
height: 93%;
}
</style>
@@ -174,10 +113,16 @@ 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 {
@@ -198,6 +143,11 @@ export default {
mounted () {
let questKeys = Object.keys(this.user.items.quests);
this.selectedQuest = questKeys[0];
this.$root.$on('selectQuest', this.selectQuest);
},
destroyed () {
this.$root.$off('selectQuest', this.selectQuest);
},
computed: {
...mapState({user: 'user.data'}),
@@ -207,8 +157,9 @@ export default {
},
methods: {
selectQuest (quest) {
this.selectedQuest = quest;
this.selectedQuest = quest.key;
},
async questInit () {
Analytics.updateUser({
partyID: this.group._id,

View File

@@ -115,7 +115,7 @@
)
template(slot="popoverContent", scope="context")
h4.popover-content-title {{ context.item.text }}
.popover-content-text {{ context.item.notes }}
.popover-content-text(v-html="context.item.notes")
template(slot="itemBadge", scope="context")
countBadge(
:show="true",
@@ -145,6 +145,10 @@
@change="resetSpell($event)",
@memberSelected="memberSelected($event)",
)
startQuestModal(
group="user.party"
)
</template>
<style lang="scss" scoped>
@@ -184,6 +188,8 @@ import CountBadge from 'client/components/ui/countBadge';
import SelectMembersModal from 'client/components/selectMembersModal';
import HatchedPetDialog from '../stable/hatchedPetDialog';
import startQuestModal from '../../groups/startQuestModal';
import createAnimal from 'client/libs/createAnimal';
import moment from 'moment';
@@ -198,6 +204,7 @@ const groups = [
['hatchingPotions', 'Pet_HatchingPotion_'],
['food', 'Pet_Food_'],
['special', 'inventory_special_', allowedSpecialItems],
['quests', 'inventory_quest_scroll_'],
].map(([group, classPrefix, allowedItems]) => {
return {
key: group,
@@ -221,6 +228,7 @@ export default {
HatchedPetDialog,
CountBadge,
SelectMembersModal,
startQuestModal,
},
directives: {
drag: DragDropDirective,
@@ -403,6 +411,10 @@ export default {
} else {
this.selectedSpell = item;
}
} else if (groupKey === 'quests') {
this.$root.$emit('show::modal', 'start-quest-modal');
this.$root.$emit('selectQuest', item);
}
},

View File

@@ -642,7 +642,7 @@ export default {
}
if (searchBy) {
let foundPosition = gear.text().toLowerCase().indexOf(searchBy);
let foundPosition = gear.text.toLowerCase().indexOf(searchBy);
if (foundPosition === -1) {
return false;
}
@@ -672,7 +672,7 @@ export default {
}
if (searchBy) {
let foundPosition = item.text().toLowerCase().indexOf(searchBy);
let foundPosition = item.text.toLowerCase().indexOf(searchBy);
if (foundPosition === -1) {
return false;
}

View File

@@ -18,12 +18,7 @@
div.content(v-if="item != null")
div.inner-content
slot(name="item", :item="item")
h4.title {{ itemText }}
div.text(v-html="itemNotes")
questInfo.questInfo(:quest="item")
questDialogContent(:item="item")
div
span.svg-icon.inline.icon-32(aria-hidden="true", v-html="(priceType === 'gems') ? icons.gem : icons.gold")
@@ -42,17 +37,7 @@
) {{ $t('buyNow') }}
div.right-sidebar(v-if="item.drop")
h3(v-once) {{ $t('rewards') }}
div.reward-item
span.svg-icon.inline.icon(v-html="icons.experience")
span.reward-text {{ $t('amountExperience', { amount: item.drop.exp }) }}
div.reward-item(v-if="item.drop.gp != 0")
span.svg-icon.inline.icon(v-html="icons.gold")
span.reward-text {{ $t('amountGold', { amount: item.drop.gp }) }}
div.reward-item(v-for="drop in item.drop.items")
span.icon
div(:class="getDropIcon(drop)")
span.reward-text {{ getDropName(drop) }}
questDialogDrops(:item="item")
div.clearfix(slot="modal-footer")
span.balance.float-left {{ $t('yourBalance') }}
@@ -73,6 +58,8 @@
.content {
text-align: center;
max-height: 80vh;
overflow-y: scroll;
}
.item-wrapper {
@@ -83,12 +70,7 @@
margin: 33px auto auto;
width: 400px;
}
.text {
max-height: 220px;
margin-bottom: 8px;
overflow-y: scroll;
text-overflow: ellipsis;
}
.questInfo {
width: 70%;
@@ -117,34 +99,6 @@
width: 364px;
z-index: -1;
height: 100%;
h3 {
margin-top: 24px;
margin-bottom: 16px;
}
.reward-item {
width: 306px;
height: 84px;
border-radius: 2px;
background-color: $white;
margin-bottom: 8px;
display: flex;
flex-direction: row;
align-items: center;
.icon {
margin: 18px;
height: 48px;
width: 48px;
}
.reward-text {
font-weight: bold;
}
}
}
span.svg-icon.inline.icon-32 {
@@ -237,12 +191,17 @@
import QuestInfo from './questInfo.vue';
import notifications from 'client/mixins/notifications';
import questDialogDrops from './questDialogDrops';
import questDialogContent from './questDialogContent';
export default {
mixins: [currencyMixin, notifications],
components: {
bModal,
BalanceInfo,
QuestInfo,
questDialogDrops,
questDialogContent,
},
data () {
return {

View File

@@ -0,0 +1,65 @@
<template lang="pug">
div.quest-content
.quest-image(:class="'quest_' + item.key")
h4.title {{ itemText }}
div.text(v-html="itemNotes")
questInfo.questInfo(:quest="item")
</template>
<style lang="scss" scoped>
@import '~client/assets/scss/colors.scss';
.quest-image {
margin: 0 auto;
margin-bottom: 1em;
margin-top: 1.5em;
}
.text {
max-height: 220px;
margin-bottom: 8px;
overflow-y: scroll;
text-overflow: ellipsis;
}
.questInfo {
width: 70%;
margin: 0 auto;
margin-bottom: 10px;
}
</style>
<script>
import QuestInfo from './questInfo.vue';
export default {
components: {
QuestInfo,
},
computed: {
itemText () {
if (this.item.text instanceof Function) {
return this.item.text();
} else {
return this.item.text;
}
},
itemNotes () {
if (this.item.notes instanceof Function) {
return this.item.notes();
} else {
return this.item.notes;
}
},
},
props: {
item: {
type: Object,
},
},
};
</script>

View File

@@ -0,0 +1,106 @@
<template lang="pug">
div.questRewards
h3.text-center(v-once) {{ $t('rewards') }}
div.reward-item
span.svg-icon.inline.icon(v-html="icons.experience")
span.reward-text {{ $t('amountExperience', { amount: item.drop.exp }) }}
div.reward-item(v-if="item.drop.gp != 0")
span.svg-icon.inline.icon(v-html="icons.gold")
span.reward-text {{ $t('amountGold', { amount: item.drop.gp }) }}
h3.text-center(v-if='item.drop.items') {{$t('questOwnerRewards')}}
div.reward-item(v-for="drop in item.drop.items")
span.icon
div(:class="getDropIcon(drop)")
span.reward-text {{ getDropName(drop) }}
</template>
<style lang="scss" scoped>
.questRewards {
overflow-y: auto;
width: 364px;
z-index: -1;
height: 100%;
h3 {
margin-top: 24px;
margin-bottom: 16px;
margin-left: auto;
margin-right: auto;
}
.reward-item {
width: 306px;
height: 84px;
border-radius: 2px;
background-color: #ffffff;
margin: 0 auto;
margin-bottom: 1em;
padding: 1em;
display: flex;
flex-direction: row;
align-items: center;
.icon:not(.svg-icon) {
height: 68px;
width: 68px;
}
.svg-icon {
margin: 15px;
height: 38px;
width: 38px;
}
.reward-text {
font-weight: bold;
}
}
}
</style>
<script>
import svgGold from 'assets/svg/gold.svg';
import svgExperience from 'assets/svg/experience.svg';
export default {
mixins: [],
components: {
},
data () {
return {
icons: Object.freeze({
gold: svgGold,
experience: svgExperience,
}),
};
},
methods: {
getDropIcon (drop) {
switch (drop.type) {
case 'gear':
return `shop_${drop.key}`;
case 'hatchingPotions':
return `Pet_HatchingPotion_${drop.key}`;
case 'food':
return `Pet_Food_${drop.key}`;
case 'eggs':
return `Pet_Egg_${drop.key}`;
case 'quests':
return `inventory_quest_scroll_${drop.key}`;
default:
return '';
}
},
getDropName (drop) {
return drop.text();
},
},
props: {
item: {
type: Object,
},
},
};
</script>

View File

@@ -3,7 +3,7 @@
span.col-4(v-if="quest.collect") {{ $t('collect') }}
span.col-8(v-if="quest.collect")
div(v-for="(collect, key) of quest.collect")
span {{ collect.count }} {{ collect.text }}
span {{ collect.count }} {{ getCollectText(collect) }}
span.col-4 {{ $t('difficulty') }}
span.col-8
@@ -78,6 +78,13 @@
return result;
},
getCollectText (collect) {
if (collect.text instanceof Function) {
return collect.text();
} else {
return collect.text;
}
},
},
props: {
quest: {

View File

@@ -117,5 +117,6 @@
"loginReward": "<%= count %> Check-ins",
"createAccountQuest": "You received this quest when you joined Habitica! If a friend joins, they'll get one too.",
"questBundles": "Discounted Quest Bundles",
"buyQuestBundle": "Buy Quest Bundle"
"buyQuestBundle": "Buy Quest Bundle",
"noQuestToStart": "Cant find a quest to start? Try checking out the Quest Shop in the Market for new releases!"
}

View File

@@ -9,6 +9,8 @@ import {
import randomVal from '../libs/randomVal';
import predictableRandom from '../fns/predictableRandom';
import { removePinnedGearByClass, addPinnedGearByClass } from './pinnedGearUtils';
module.exports = function revive (user, req = {}, analytics) {
if (user.stats.hp > 0) {
throw new NotAuthorized(i18n.t('cannotRevive', req.language));
@@ -81,8 +83,12 @@ module.exports = function revive (user, req = {}, analytics) {
let item = content.gear.flat[lostItem];
if (item) {
removePinnedGearByClass(user);
user.items.gear.owned[lostItem] = false;
addPinnedGearByClass(user);
if (user.items.gear.equipped[item.type] === lostItem) {
user.items.gear.equipped[item.type] = `${item.type}_base_0`;
}