mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-04-14 19:56:23 +00:00
Client fixed sept 4 (#9019)
* Fixed background purchasing * Added challenge export * Fixed is leader filter * Fixed staff icon * Add block to profile modal * Added initial send gems modal * Added modal stack * Fixed lint issues * Updated notification styles * Updated level up styles * Fixed many achievement styles * Fixed notification navigate to same route with different param * Added mark chat seen and remove new messages * Added scroll to notifications * Updated hall loading
This commit is contained in:
parent
d051bdf2c9
commit
36a933d0c4
33 changed files with 606 additions and 238 deletions
|
|
@ -162,6 +162,42 @@ export default {
|
|||
console.error('Impossible to fetch user. Clean up localStorage and refresh.', err); // eslint-disable-line no-console
|
||||
});
|
||||
}
|
||||
|
||||
// Manage modals
|
||||
this.$root.$on('show::modal', (modalId, data) => {
|
||||
if (data && data.fromRoot) return;
|
||||
|
||||
// Get last modal on stack and hide
|
||||
let modalStackLength = this.$store.state.modalStack.length;
|
||||
let modalOnTop = this.$store.state.modalStack[modalStackLength - 1];
|
||||
|
||||
// Add new modal to the stack
|
||||
this.$store.state.modalStack.push(modalId);
|
||||
|
||||
// Hide the previous top modal
|
||||
if (modalOnTop) this.$root.$emit('hide::modal', modalOnTop, {fromRoot: true});
|
||||
});
|
||||
|
||||
// @TODO: This part is hacky and could be solved with two options:
|
||||
// 1 - Find a way to pass fromRoot to hidden
|
||||
// 2 - Enforce that all modals use the hide::modal event
|
||||
this.$root.$on('hidden::modal', (modalId) => {
|
||||
let modalStackLength = this.$store.state.modalStack.length;
|
||||
let modalOnTop = this.$store.state.modalStack[modalStackLength - 1];
|
||||
let modalSecondToTop = this.$store.state.modalStack[modalStackLength - 2];
|
||||
// Don't remove modal if hid was called from main app
|
||||
// @TODO: I'd reather use this, but I don't know how to pass data to hidden event
|
||||
// if (data && data.fromRoot) return;
|
||||
if (modalId === modalSecondToTop) return;
|
||||
|
||||
// Remove modal from stack
|
||||
this.$store.state.modalStack.pop();
|
||||
|
||||
// Recalculate and show the last modal if there is one
|
||||
modalStackLength = this.$store.state.modalStack.length;
|
||||
modalOnTop = this.$store.state.modalStack[modalStackLength - 1];
|
||||
if (modalOnTop) this.$root.$emit('show::modal', modalOnTop, {fromRoot: true});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
resetItemToBuy ($event) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template lang="pug">
|
||||
div(:class='achievementClass')
|
||||
//- +generatedAvatar({sleep: false})
|
||||
avatar(:member='user')
|
||||
avatar(:member='user', :avatarOnly='true', :withBackground='true')
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
|
|||
|
|
@ -1,27 +1,78 @@
|
|||
<template lang="pug">
|
||||
.modal-footer(style='margin-top:0', ng-init='loadWidgets()')
|
||||
.container-fluid
|
||||
.row.text-center
|
||||
.col-4
|
||||
a.twitter-share-button(:href='twitterLink') {{ $t('tweet') }}
|
||||
.col-4
|
||||
.fb-share-button(:data-href='achievementLink', data-layout='button')
|
||||
.col-4
|
||||
a.tumblr-share-button(:data-href='achievementLink', data-notes='none')
|
||||
.container-fluid.share-buttons
|
||||
.row
|
||||
.col-12.text-center
|
||||
a.twitter-share-button.share-button(:href='twitterLink', target='_blank')
|
||||
.social-icon.twitter.svg-icon(v-html='icons.twitter')
|
||||
| {{ $t('tweet') }}
|
||||
a.fb-share-button.share-button(:href='facebookLink', target='_blank')
|
||||
.social-icon.facebook.svg-icon(v-html='icons.facebook')
|
||||
| {{ $t('share') }}
|
||||
// @TODO: Still want this? .col-4
|
||||
a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.share-buttons {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.share-button {
|
||||
display: inline-block;
|
||||
width: 77px;
|
||||
padding: .5em;
|
||||
border-radius: 2px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.fb-share-button {
|
||||
background-color: #2995cd;
|
||||
}
|
||||
|
||||
.twitter-share-button {
|
||||
margin-right: .5em;
|
||||
background-color: #3bcad7;
|
||||
}
|
||||
|
||||
.social-icon {
|
||||
width: 16px;
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
.social-icon.facebook svg {
|
||||
width: 7.5px;
|
||||
margin-bottom: .2em;
|
||||
}
|
||||
|
||||
.social-icon.twitter {
|
||||
margin-bottom: .2em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// @TODO:
|
||||
let BASE_URL = 'https://habitica.com';
|
||||
import twitter from 'assets/svg/twitter.svg';
|
||||
import facebook from 'assets/svg/facebook.svg';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
let tweet = this.$t('achievementShare');
|
||||
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
twitter,
|
||||
facebook,
|
||||
}),
|
||||
tweet,
|
||||
achievementLink: `${BASE_URL}/social/achievement`,
|
||||
twitterLink: `https://twitter.com/intent/tweet?text=${tweet}&via=habitica&url=${BASE_URL}/social/achievement&count=none`,
|
||||
facebookLink: `https://www.facebook.com/sharer/sharer.php?text=${tweet}&u=${BASE_URL}/social/achievement`,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
<template lang="pug">
|
||||
b-modal#contributor(:title="$t('modalContribAchievement')", size='lg', :hide-footer="true")
|
||||
b-modal#contributor(:title="$t('modalContribAchievement')", size='md', :hide-footer="true")
|
||||
.modal-body
|
||||
.col-6.offset-3.text-center
|
||||
.col-12
|
||||
achievement-avatar.avatar
|
||||
.col-6.offset-3.text-center
|
||||
| {{ $t('contribModal', {name: user.profile.name, level: user.contributor.level}) }}
|
||||
a(:href="$t('conRewardsURL')", target='_blank') {{ $t('contribLink') }}
|
||||
br
|
||||
|
|
@ -13,7 +14,8 @@
|
|||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
margin-left: 4em;
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,20 @@
|
|||
<template lang="pug">
|
||||
b-modal#death(:title="$t('lostAllHealth')", size='lg', :hide-footer="true")
|
||||
.info
|
||||
.row
|
||||
.col-6
|
||||
.hero-stats
|
||||
.meter-label(:tooltip="$t('health')")
|
||||
span.glyphicon.glyphicon-heart
|
||||
.meter.health(:tooltip='Math.round(user.stats.hp * 100) / 100')
|
||||
.bar(:style='barStyle')
|
||||
// span.meter-text.value
|
||||
| {{Math.ceil(user.stats.hp)}} / {{maxHealth}}
|
||||
avatar(:member='user', :sleep='true')
|
||||
// @TOOD: Sleep +generatedAvatar({sleep:true})
|
||||
span(class='knockout')
|
||||
.col-6
|
||||
h4.dont-despair {{ $t('dontDespair') }}
|
||||
p.death-penalty {{ $t('deathPenaltyDetails') }}
|
||||
b-modal#death(:title="$t('lostAllHealth')", size='md', :hide-footer="true")
|
||||
.row
|
||||
.col-12
|
||||
.hero-stats
|
||||
.meter-label(:tooltip="$t('health')")
|
||||
span.glyphicon.glyphicon-heart
|
||||
.meter.health(:tooltip='Math.round(user.stats.hp * 100) / 100')
|
||||
.bar(:style='barStyle')
|
||||
// span.meter-text.value
|
||||
| {{Math.ceil(user.stats.hp)}} / {{maxHealth}}
|
||||
avatar(:member='user', :sleep='true', :avatarOnly='true', :withBackground='true')
|
||||
// @TOOD: Sleep +generatedAvatar({sleep:true})
|
||||
span(class='knockout')
|
||||
.col-6.offset-3
|
||||
h4.dont-despair {{ $t('dontDespair') }}
|
||||
p.death-penalty {{ $t('deathPenaltyDetails') }}
|
||||
.modal-footer
|
||||
.col-12.text-center
|
||||
button.btn.btn-danger(@click='revive()') {{ $t('refillHealthTryAgain') }}
|
||||
|
|
@ -23,8 +22,11 @@
|
|||
</template>
|
||||
|
||||
<style scoped>
|
||||
.info {
|
||||
height: 220px;
|
||||
.avatar {
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
<template lang="pug">
|
||||
b-modal#invited-friend(:title="$t('modalAchievement')", size='lg', :hide-footer="true")
|
||||
.modal-body.text-center
|
||||
// @TODO: +achievementAvatar('friends',0)
|
||||
achievement-avatar.avatar
|
||||
p {{ $t('invitedFriendText') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
b-modal#invited-friend(:title="$t('modalAchievement')", size='md', :hide-footer="true")
|
||||
.modal-body
|
||||
.col-12
|
||||
// @TODO: +achievementAvatar('friends',0)
|
||||
achievement-avatar.avatar
|
||||
.col-6.offset-3.text-center
|
||||
p {{ $t('invitedFriendText') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
achievement-footer
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
margin-left: 10.2em;
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
<template lang="pug">
|
||||
b-modal#joined-challenge(:title="$t('modalAchievement')", size='lg', :hide-footer="true")
|
||||
.modal-body.text-center
|
||||
// @TODO: +achievementAvatar('challenge',0)
|
||||
achievement-avatar.avatar
|
||||
p {{ $t('joinedChallengeText') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
b-modal#joined-challenge(:title="$t('modalAchievement')", size='md', :hide-footer="true")
|
||||
.modal-body
|
||||
.col-12
|
||||
// @TODO: +achievementAvatar('challenge',0)
|
||||
achievement-avatar.avatar
|
||||
.col-6.offset-3.text-center
|
||||
p {{ $t('joinedChallengeText') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
achievement-footer
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
margin-left: 10.2em;
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
<template lang="pug">
|
||||
b-modal#joined-guild(:title="$t('modalAchievement')", size='lg', :hide-footer="true")
|
||||
.modal-body.text-center
|
||||
// @TODO: +achievementAvatar('guild',0)
|
||||
achievement-avatar.avatar
|
||||
p {{ $t('joinedGuildText') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
b-modal#joined-guild(:title="$t('modalAchievement')", size='md', :hide-footer="true")
|
||||
.modal-body
|
||||
.col-12
|
||||
// @TODO: +achievementAvatar('guild',0)
|
||||
achievement-avatar.avatar
|
||||
.col-6.offset-3.text-center
|
||||
p {{ $t('joinedGuildText') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
achievement-footer
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
margin-left: 10.2em;
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,43 @@
|
|||
<template lang="pug">
|
||||
b-modal#level-up(:title="$t('levelUpShare')", size='sm', :hide-footer="true")
|
||||
b-modal#level-up(:title="$t('levelUpShare')", size='sm', :hide-footer="true", :hide-header="true")
|
||||
.modal-body.text-center
|
||||
h3 {{ $t('gainedLevel') }}
|
||||
h2 {{ $t('reachedLevel', {level: user.stats.lvl}) }}
|
||||
|
||||
avatar.avatar(:member='user')
|
||||
h4.avatar-level(:class='userLevelStyle(user)') {{ $t('level') + ' ' + user.stats.lvl }}
|
||||
h4(v-html="$t('leveledUp', {level: user.stats.lvl})")
|
||||
p {{ $t('fullyHealed') }}
|
||||
|
||||
p.text {{ $t('levelup') }}
|
||||
|
||||
button.btn.btn-primary(@click='close()') {{ $t('onwards') }}
|
||||
br
|
||||
div(v-if='showAllocation')
|
||||
a.btn.btn-default(@click='statsAllocationBoxIsOpen = !statsAllocationBoxIsOpen')
|
||||
| {{statsAllocationBoxIsOpen ? $t('hideQuickAllocation') : $t('showQuickAllocation')}}
|
||||
p
|
||||
#stat-allocation(v-if='statsAllocationBoxIsOpen')
|
||||
p(v-if='user.stats.lvl >= 100') {{ $t('noMoreAllocate') }}
|
||||
p(v-if='user.stats.points || user.stats.lvl < 100')
|
||||
strong.inline
|
||||
| {{user.stats.points}}
|
||||
strong.hint(popover-trigger='mouseenter',
|
||||
popover-placement='right', :popover="$t('quickAllocationLevelPopover')") {{ $t('unallocated') }}
|
||||
// @TODO: +statAllocation
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
.checkbox
|
||||
// @TODO: Keep this? .checkbox
|
||||
input(type='checkbox', v-model='user.preferences.suppressModals.levelUp', @change='changeLevelupSuppress()')
|
||||
label(style='display:inline-block') {{ $t('dontShowAgain') }}
|
||||
.modal-footer
|
||||
.container-fluid
|
||||
.row
|
||||
.col-4
|
||||
a.twitter-share-button(:href='twitterLink') {{ $t('tweet') }}
|
||||
.col-4
|
||||
.fb-share-button(:data-href='socialLevelLink', data-layout='button')
|
||||
.col-4
|
||||
a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')
|
||||
|
||||
.container-fluid.share-buttons
|
||||
.row
|
||||
.col-12.text-center
|
||||
a.twitter-share-button.share-button(:href='twitterLink', target='_blank')
|
||||
.social-icon.twitter.svg-icon(v-html='icons.twitter')
|
||||
| {{ $t('tweet') }}
|
||||
a.fb-share-button.share-button(:href='facebookLink', target='_blank')
|
||||
.social-icon.facebook.svg-icon(v-html='icons.facebook')
|
||||
| {{ $t('share') }}
|
||||
// @TODO: Still want this? .col-4
|
||||
a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
#level-up {
|
||||
h2 {
|
||||
color: #4f2a93;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
min-width: 28em;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding-top: 1em;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +57,53 @@
|
|||
margin: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
color: #686274;
|
||||
margin-top: 1em;
|
||||
min-height: 0px;
|
||||
}
|
||||
|
||||
.share-buttons {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.share-button {
|
||||
display: inline-block;
|
||||
width: 77px;
|
||||
padding: .5em;
|
||||
border-radius: 2px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.fb-share-button {
|
||||
background-color: #2995cd;
|
||||
}
|
||||
|
||||
.twitter-share-button {
|
||||
margin-right: .5em;
|
||||
background-color: #3bcad7;
|
||||
}
|
||||
|
||||
.social-icon {
|
||||
width: 16px;
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
.social-icon.facebook svg {
|
||||
width: 7.5px;
|
||||
margin-bottom: .2em;
|
||||
}
|
||||
|
||||
.social-icon.twitter {
|
||||
margin-bottom: .2em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -77,8 +120,10 @@ import Avatar from '../avatar';
|
|||
import { mapState } from 'client/libs/store';
|
||||
import {maxHealth} from '../../../common/script/index';
|
||||
import styleHelper from 'client/mixins/styleHelper';
|
||||
import twitter from 'assets/svg/twitter.svg';
|
||||
import facebook from 'assets/svg/facebook.svg';
|
||||
|
||||
let BASE_URL = '@TODO';
|
||||
let BASE_URL = 'https://habitica.com';
|
||||
|
||||
export default {
|
||||
mixins: [styleHelper],
|
||||
|
|
@ -89,11 +134,16 @@ export default {
|
|||
data () {
|
||||
let tweet = this.$t('levelUpShare');
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
twitter,
|
||||
facebook,
|
||||
}),
|
||||
statsAllocationBoxIsOpen: true,
|
||||
maxHealth,
|
||||
tweet,
|
||||
socialLevelLink: `${BASE_URL}/social/level-up`,
|
||||
twitterLink: `https://twitter.com/intent/tweet?text=${tweet}&via=habitica&url=${BASE_URL}/social/level-up&count=none`,
|
||||
facebookLink: `https://www.facebook.com/sharer/sharer.php?text=${tweet}&u=${BASE_URL}/social/level-up`,
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
span.meter-text.value
|
||||
| {{healthLeft}}
|
||||
.col-12
|
||||
avatar(:member='user')
|
||||
avatar(:member='user', :avatarOnly='true', :withBackground='true')
|
||||
.col-12
|
||||
p {{ $t('losingHealthWarning2') }}
|
||||
h4 {{ $t('toRegainHealth') }}
|
||||
|
|
@ -46,6 +46,13 @@
|
|||
.modal-footer {
|
||||
margin-top: 0em;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
import quests from 'common/script/content/quests';
|
||||
|
||||
import Avatar from '../avatar';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import percent from '../../../common/script/libs/percent';
|
||||
import { maxHealth } from '../../../common/script/index';
|
||||
|
|
@ -21,7 +20,6 @@ import { maxHealth } from '../../../common/script/index';
|
|||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
Avatar,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@
|
|||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import quests from 'common/script/content/quests';
|
||||
import Avatar from '../avatar';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import revive from '../../../common/script/ops/revive';
|
||||
import percent from '../../../common/script/libs/percent';
|
||||
|
|
@ -57,7 +56,6 @@ import {maxHealth} from '../../../common/script/index';
|
|||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
Avatar,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,28 @@
|
|||
<template lang="pug">
|
||||
b-modal#rebirth(:title="$t('modalAchievement')", size='md', :hide-footer="true")
|
||||
.modal-body.text-center
|
||||
// @TODO: +achievementAvatar('sun',0)
|
||||
achievement-avatar
|
||||
div(v-if='user.achievements.rebirthLevel < 100')
|
||||
| {{ $t('rebirthAchievement', {number: user.achievements.rebirths, level: user.achievements.rebirthLevel}) }}
|
||||
div(v-if='user.achievements.rebirthLevel >= 100')
|
||||
| {{ $t('rebirthAchievement100', {number: user.achievements.rebirths}) }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
.modal-body
|
||||
.col-12
|
||||
// @TODO: +achievementAvatar('sun',0)
|
||||
achievement-avatar.avatar
|
||||
.col-6.offset-3.text-center
|
||||
div(v-if='user.achievements.rebirthLevel < 100')
|
||||
| {{ $t('rebirthAchievement', {number: user.achievements.rebirths, level: user.achievements.rebirthLevel}) }}
|
||||
div(v-if='user.achievements.rebirthLevel >= 100')
|
||||
| {{ $t('rebirthAchievement100', {number: user.achievements.rebirths}) }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
achievement-footer
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
import achievementFooter from './achievementFooter';
|
||||
|
|
|
|||
|
|
@ -1,20 +1,31 @@
|
|||
<template lang="pug">
|
||||
b-modal#streak(:title="$t('streakAchievement')", size='md', :hide-footer="true")
|
||||
.modal-body.text-center
|
||||
// @TODO: +achievementAvatar('thermometer',2.5)
|
||||
achievement-avatar
|
||||
h3(v-if='user.achievements.streak === 1') {{ $t('firstStreakAchievement') }}
|
||||
h3(v-if='user.achievements.streak > 1') {{ $t('streakAchievementCount', {streaks: user.achievements.streak}) }}
|
||||
p {{ $t('twentyOneDays') }}
|
||||
p {{ $t('dontBreakStreak') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('dontStop') }}
|
||||
.checkbox
|
||||
input(type='checkbox', v-model='user.preferences.suppressModals.streak', @change='suppressModals')
|
||||
label {{ $t('dontShowAgain') }}
|
||||
.modal-body
|
||||
.col-12
|
||||
// @TODO: +achievementAvatar('thermometer',2.5)
|
||||
achievement-avatar.avatar
|
||||
.col-6.offset-3.text-center
|
||||
h3(v-if='user.achievements.streak === 1') {{ $t('firstStreakAchievement') }}
|
||||
h3(v-if='user.achievements.streak > 1') {{ $t('streakAchievementCount', {streaks: user.achievements.streak}) }}
|
||||
p {{ $t('twentyOneDays') }}
|
||||
p {{ $t('dontBreakStreak') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('dontStop') }}
|
||||
.checkbox
|
||||
input(type='checkbox', v-model='user.preferences.suppressModals.streak', @change='suppressModals')
|
||||
label {{ $t('dontShowAgain') }}
|
||||
achievement-footer
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
import achievementFooter from './achievementFooter';
|
||||
|
|
|
|||
|
|
@ -1,32 +1,34 @@
|
|||
<template lang="pug">
|
||||
b-modal#ultimate-gear(:title="$t('modalAchievement')", size='md', :hide-footer="true")
|
||||
.modal-body.text-center
|
||||
// @TODO: +achievementAvatar('armor',2.5)
|
||||
achievement-avatar
|
||||
p {{ $t('gearAchievement') }}
|
||||
br
|
||||
table.multi-achievement
|
||||
tr
|
||||
td(v-if='user.achievements.ultimateGearSets.healer').multi-achievement
|
||||
.achievement-ultimate-healer2x.multi-achievement
|
||||
| {{ $t('healer') }}
|
||||
td(v-if='user.achievements.ultimateGearSets.wizard').multi-achievement
|
||||
.achievement-ultimate-mage2x.multi-achievement
|
||||
| {{ $t('mage') }}
|
||||
td(v-if='user.achievements.ultimateGearSets.rogue').multi-achievement
|
||||
.achievement-ultimate-rogue2x.multi-achievement
|
||||
| {{ $t('rogue') }}
|
||||
td(v-if='user.achievements.ultimateGearSets.warrior').multi-achievement
|
||||
.achievement-ultimate-warrior2x.multi-achievement
|
||||
| {{ $t('warrior') }}
|
||||
br
|
||||
div(v-if='!(user.achievements.ultimateGearSets.healer && user.achievements.ultimateGearSets.wizard && user.achievements.ultimateGearSets.rogue && user.achievements.ultimateGearSets.warrior)')
|
||||
p(v-html="$t('moreGearAchievements')")
|
||||
.modal-body
|
||||
.col-12
|
||||
// @TODO: +achievementAvatar('armor',2.5)
|
||||
achievement-avatar.avatar
|
||||
.col-12.text-center
|
||||
p {{ $t('gearAchievement') }}
|
||||
br
|
||||
.shop_armoire
|
||||
p(v-html='$t("armoireUnlocked")')
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
table.multi-achievement
|
||||
tr
|
||||
td(v-if='user.achievements.ultimateGearSets.healer').multi-achievement
|
||||
.achievement-ultimate-healer2x.multi-achievement
|
||||
| {{ $t('healer') }}
|
||||
td(v-if='user.achievements.ultimateGearSets.wizard').multi-achievement
|
||||
.achievement-ultimate-mage2x.multi-achievement
|
||||
| {{ $t('mage') }}
|
||||
td(v-if='user.achievements.ultimateGearSets.rogue').multi-achievement
|
||||
.achievement-ultimate-rogue2x.multi-achievement
|
||||
| {{ $t('rogue') }}
|
||||
td(v-if='user.achievements.ultimateGearSets.warrior').multi-achievement
|
||||
.achievement-ultimate-warrior2x.multi-achievement
|
||||
| {{ $t('warrior') }}
|
||||
br
|
||||
div(v-if='!(user.achievements.ultimateGearSets.healer && user.achievements.ultimateGearSets.wizard && user.achievements.ultimateGearSets.rogue && user.achievements.ultimateGearSets.warrior)')
|
||||
p(v-html="$t('moreGearAchievements')")
|
||||
br
|
||||
.shop_armoire
|
||||
p(v-html='$t("armoireUnlocked")')
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
achievement-footer
|
||||
</template>
|
||||
|
||||
|
|
@ -34,6 +36,13 @@
|
|||
.shop_armoire {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
.achievement-karaoke-2x
|
||||
.col-4
|
||||
// @TODO: +generatedAvatar({sleep: false})
|
||||
avatar(:member='user', :avatar-only='true')
|
||||
avatar.avatar(:member='user', :avatar-only='true')
|
||||
.col-4
|
||||
.achievement-karaoke-2x
|
||||
p {{ $t('congratulations') }}
|
||||
|
|
@ -29,7 +29,10 @@
|
|||
}
|
||||
|
||||
.avatar {
|
||||
margin-left: 0em;
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
li
|
||||
a(href='/static/community-guidelines') {{ $t('communityGuidelines') }}
|
||||
li
|
||||
a(href='/hall') {{ $t('hall') }}
|
||||
router-link(to='/hall/contributors') {{ $t('hall') }}
|
||||
li
|
||||
router-link(to='/groups/a29da26b-37de-4a71-b0c6-48e72a900dac') {{ $t('reportBug') }}
|
||||
li
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@
|
|||
button.btn.btn-secondary(v-once, @click='edit()') {{$t('editChallenge')}}
|
||||
div(v-if='isLeader')
|
||||
button.btn.btn-danger(v-once, @click='closeChallenge()') {{$t('endChallenge')}}
|
||||
div(v-if='isLeader')
|
||||
button.btn.btn-secondary(v-once, @click='exportChallengeCsv()') {{$t('exportChallengeCsv')}}
|
||||
.description-section
|
||||
h2 {{$t('challengeSummary')}}
|
||||
p {{challenge.summary}}
|
||||
|
|
@ -305,6 +307,12 @@ export default {
|
|||
this.progressMemberId = memberId;
|
||||
this.$root.$emit('show::modal', 'challenge-member-modal');
|
||||
},
|
||||
async exportChallengeCsv () {
|
||||
// let response = await this.$store.dispatch('challenges:exportChallengeCsv', {
|
||||
// challengeId: this.challengeId,
|
||||
// });
|
||||
window.location = `/api/v3/challenges/${this.challengeId}/export/csv`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -203,8 +203,8 @@ import tier5 from 'assets/svg/tier-5.svg';
|
|||
import tier6 from 'assets/svg/tier-6.svg';
|
||||
import tier7 from 'assets/svg/tier-7.svg';
|
||||
import tier8 from 'assets/svg/tier-mod.svg';
|
||||
import tier9 from 'assets/svg/tier-npc.svg';
|
||||
import tier10 from 'assets/svg/tier-staff.svg';
|
||||
import tier9 from 'assets/svg/tier-staff.svg';
|
||||
import tier10 from 'assets/svg/tier-npc.svg';
|
||||
|
||||
export default {
|
||||
props: ['chat', 'groupId', 'groupName', 'inbox'],
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
|
|||
strong {{backgroundShopSets[0].text}}
|
||||
.row.incentive-background-row
|
||||
.col-2(v-for='bg in backgroundShopSets[0].items',
|
||||
@click='unlock("background." + bg.key)',
|
||||
@click='buy("background." + bg.key)',
|
||||
:popover-title='bg.text',
|
||||
:popover='bg.notes',
|
||||
popover-trigger='mouseenter')
|
||||
|
|
@ -197,7 +197,7 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
|
|||
strong {{set.text}}
|
||||
.col-12(v-if='showPlainBackgroundBlurb(set.identifier, set.items)') {{ $t('incentiveBackgroundsUnlockedWithCheckins') }}
|
||||
.col-4.text-center.customize-option.background-button(v-for='bg in set.items',
|
||||
@click='backgroundSelected(bg)',
|
||||
@click='!user.purchased.background[bg.key] ? backgroundSelected(bg) : unlock("background." + bg.key)',
|
||||
:popover-title='bg.text',
|
||||
:popover='bg.notes',
|
||||
popover-trigger='mouseenter')
|
||||
|
|
@ -868,6 +868,9 @@ export default {
|
|||
},
|
||||
mounted () {
|
||||
if (this.editing) this.modalPage = 2;
|
||||
|
||||
// Buy modal is global, so we listen at root. I'd like to not
|
||||
this.$root.$on('buyModal::boughtItem', this.backgroundPurchased);
|
||||
},
|
||||
data () {
|
||||
let backgroundShopSets = getBackgroundShopSets();
|
||||
|
|
@ -1066,6 +1069,9 @@ export default {
|
|||
backgroundSelected (bg) {
|
||||
this.$root.$emit('buyModal::showItem', bg);
|
||||
},
|
||||
backgroundPurchased () {
|
||||
this.backgroundUpdate = new Date();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -542,20 +542,17 @@ export default {
|
|||
},
|
||||
},
|
||||
mounted () {
|
||||
this.searchId = this.groupId;
|
||||
if (this.isParty) {
|
||||
this.searchId = 'party';
|
||||
// @TODO: Set up from old client. Decide what we need and what we don't
|
||||
// Check Desktop notifs
|
||||
// Mark Chat seen
|
||||
// Load invites
|
||||
}
|
||||
this.fetchGuild();
|
||||
if (!this.searchId) this.searchId = this.groupId;
|
||||
|
||||
this.$root.$on('updatedGroup', group => {
|
||||
let updatedGroup = extend(this.group, group);
|
||||
this.$set(this.group, updatedGroup);
|
||||
});
|
||||
this.load();
|
||||
|
||||
if (this.user.newMessages[this.searchId]) {
|
||||
this.$store.dispatch('chat:markChatSeen', {groupId: this.searchId});
|
||||
}
|
||||
},
|
||||
beforeRouteUpdate (to, from, next) {
|
||||
this.searchId = to.params.groupId;
|
||||
next();
|
||||
},
|
||||
watch: {
|
||||
// call again the method if the route changes (when this route is already active)
|
||||
|
|
@ -570,6 +567,21 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
load () {
|
||||
if (this.isParty) {
|
||||
this.searchId = 'party';
|
||||
// @TODO: Set up from old client. Decide what we need and what we don't
|
||||
// Check Desktop notifs
|
||||
// Mark Chat seen
|
||||
// Load invites
|
||||
}
|
||||
this.fetchGuild();
|
||||
|
||||
this.$root.$on('updatedGroup', group => {
|
||||
let updatedGroup = extend(this.group, group);
|
||||
this.$set(this.group, updatedGroup);
|
||||
});
|
||||
},
|
||||
// @TODO: abstract autocomplete
|
||||
// https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a
|
||||
getCoord (e, text) {
|
||||
|
|
|
|||
|
|
@ -1,69 +1,73 @@
|
|||
<template lang="pug">
|
||||
.row
|
||||
.row.standard-page
|
||||
small.muted(v-html="$t('blurbHallContributors')")
|
||||
.well(v-if='user.contributor.admin')
|
||||
h2 {{ $t('rewardUser') }}
|
||||
form(submit='loadHero(heroID)') // @TODO: make click
|
||||
.form-group
|
||||
input.form-control(type='text', v-model='heroID', placeholder="$t('UUID')")
|
||||
.form-group
|
||||
input.btn.btn-default(type='submit')
|
||||
| {{ $t('loadUser') }}
|
||||
form(v-if='hero && hero.profile', submit='saveHero(hero)') // @TODO: make click
|
||||
a(v-click='clickMember(hero._id, true)')
|
||||
h3 {{hero.profile.name}}
|
||||
.form-group
|
||||
input.form-control(type='text', v-model='hero.contributor.text', placeholder {{ $t('contribTitle') }})
|
||||
.form-group
|
||||
label {{ $t('contribLevel') }}
|
||||
input.form-control(type='number', v-model='hero.contributor.level')
|
||||
small {{ $t('contribHallText') }}
|
||||
|
|
||||
a(target='_blank', href='https://trello.com/c/wkFzONhE/277-contributor-gear') {{ $t('moreDetails') }}
|
||||
|,
|
||||
a(target='_blank', href='https://github.com/HabitRPG/habitica/issues/3801') {{ $t('moreDetails2') }}
|
||||
.form-group
|
||||
textarea.form-control(cols=5, placeholder {{ $t('contributions') }}, v-model='hero.contributor.contributions')
|
||||
//include ../../shared/formattiv-help
|
||||
hr
|
||||
|
||||
.form-group
|
||||
label {{ $t('balance') }}
|
||||
input.form-control(type='number', step="any", v-model='hero.balance')
|
||||
small {{ '`user.balance`' + this.$t('notGems') }}
|
||||
accordion
|
||||
accordion-group(heading='Items')
|
||||
h4 Update Item
|
||||
.form-group.well
|
||||
input.form-control(type='text',placeholder='Path (eg, items.pets.BearCub-Base)',v-model='hero.itemPath')
|
||||
small.muted Enter the <strong>item path</strong>. E.g., <code>items.pets.BearCub-Zombie</code> or <code>items.gear.owned.head_special_0</code> or <code>items.gear.equipped.head</code>. You can find all the item paths below.
|
||||
br
|
||||
input.form-control(type='text',placeholder='Value (eg, 5)',v-model='hero.itemVal')
|
||||
small.muted Enter the <strong>item value</strong>. E.g., <code>5</code> or <code>false</code> or <code>head_warrior_3</code>. All values are listed in the All Item Paths section below.
|
||||
accordion
|
||||
accordion-group(heading='All Item Paths')
|
||||
pre {{allItemPaths}}
|
||||
accordion-group(heading='Current Items')
|
||||
pre {{toJson(hero.items, true)}}
|
||||
accordion-group(heading='Auth')
|
||||
h4 Auth
|
||||
pre {{toJson(hero.auth)}}
|
||||
.form-group
|
||||
.checkbox
|
||||
label
|
||||
input(type='checkbox', v-model='hero.flags.chatRevoked')
|
||||
| Chat Privileges Revoked
|
||||
.form-group
|
||||
.checkbox
|
||||
label
|
||||
input(type='checkbox', v-model='hero.auth.blocked')
|
||||
| Blocked
|
||||
.row
|
||||
.form.col-6(v-if='!hero.profile')
|
||||
.form-group
|
||||
input.form-control(type='text', v-model='heroID', :placeholder="$t('UUID')")
|
||||
.form-group
|
||||
button.btn.btn-default(@click='loadHero(heroID)')
|
||||
| {{ $t('loadUser') }}
|
||||
|
||||
// h4 Backer Status
|
||||
// Add backer stuff like tier, disable adds, etcs
|
||||
.form-group
|
||||
input.form-control.btn.btn-primary(type='submit')
|
||||
| {{ $t('save') }}
|
||||
.row
|
||||
.form.col-6(v-if='hero && hero.profile', submit='saveHero(hero)')
|
||||
a(@click='clickMember(hero._id, true)')
|
||||
h3 {{hero.profile.name}}
|
||||
.form-group
|
||||
input.form-control(type='text', v-model='hero.contributor.text', :placeholder="$t('contribTitle')")
|
||||
.form-group
|
||||
label {{ $t('contribLevel') }}
|
||||
input.form-control(type='number', v-model='hero.contributor.level')
|
||||
small {{ $t('contribHallText') }}
|
||||
|
|
||||
a(target='_blank', href='https://trello.com/c/wkFzONhE/277-contributor-gear') {{ $t('moreDetails') }}
|
||||
|,
|
||||
a(target='_blank', href='https://github.com/HabitRPG/habitica/issues/3801') {{ $t('moreDetails2') }}
|
||||
.form-group
|
||||
textarea.form-control(cols=5, :placeholder="$t('contributions')", v-model='hero.contributor.contributions')
|
||||
//include ../../shared/formattiv-help
|
||||
hr
|
||||
|
||||
.form-group
|
||||
label {{ $t('balance') }}
|
||||
input.form-control(type='number', step="any", v-model='hero.balance')
|
||||
small {{ '`user.balance`' + this.$t('notGems') }}
|
||||
.accordion
|
||||
.accordion-group(heading='Items')
|
||||
h4 Update Item
|
||||
.form-group.well
|
||||
input.form-control(type='text',placeholder='Path (eg, items.pets.BearCub-Base)',v-model='hero.itemPath')
|
||||
small.muted Enter the <strong>item path</strong>. E.g., <code>items.pets.BearCub-Zombie</code> or <code>items.gear.owned.head_special_0</code> or <code>items.gear.equipped.head</code>. You can find all the item paths below.
|
||||
br
|
||||
input.form-control(type='text',placeholder='Value (eg, 5)',v-model='hero.itemVal')
|
||||
small.muted Enter the <strong>item value</strong>. E.g., <code>5</code> or <code>false</code> or <code>head_warrior_3</code>. All values are listed in the All Item Paths section below.
|
||||
.accordion
|
||||
.accordion-group(heading='All Item Paths')
|
||||
pre {{allItemPaths}}
|
||||
.accordion-group(heading='Current Items')
|
||||
pre {{hero.items}}
|
||||
.accordion-group(heading='Auth')
|
||||
h4 Auth
|
||||
pre {{hero.auth}}
|
||||
.form-group
|
||||
.checkbox
|
||||
label
|
||||
input(type='checkbox', v-if='hero.flags', v-model='hero.flags.chatRevoked')
|
||||
| Chat Privileges Revoked
|
||||
.form-group
|
||||
.checkbox
|
||||
label
|
||||
input(type='checkbox', v-model='hero.auth.blocked')
|
||||
| Blocked
|
||||
|
||||
// h4 Backer Status
|
||||
// Add backer stuff like tier, disable adds, etcs
|
||||
.form-group
|
||||
button.form-control.btn.btn-primary
|
||||
| {{ $t('save') }}
|
||||
|
||||
.table-responsive
|
||||
table.table.table-striped
|
||||
|
|
@ -75,25 +79,26 @@
|
|||
th {{ $t('title') }}
|
||||
th {{ $t('contributions') }}
|
||||
tbody
|
||||
tr(v-for='(hero, $index) in heroes')
|
||||
tr(v-for='(hero, index) in heroes')
|
||||
td
|
||||
span(v-if='hero.contributor && hero.contributor.admin', :popover="$t('gamemaster')", popover-trigger='mouseenter', popover-placement='right')
|
||||
a.label.label-default(v-class='userLevelStyle(hero)', v-click='clickMember(hero._id, true)')
|
||||
a.label.label-default(:class='userLevelStyle(hero)', @click='clickMember(hero._id, true)')
|
||||
| {{hero.profile.name}}
|
||||
span(v-class='userAdminGlyphiconStyle(hero)')
|
||||
//- span(v-class='userAdminGlyphiconStyle(hero)')
|
||||
span(v-if='!hero.contributor || !hero.contributor.admin')
|
||||
a.label.label-default(v-if='hero.profile', v-class='userLevelStyle(hero)', v-click='clickMember(hero._id, true)') {{hero.profile.name}}
|
||||
td(v-if='user.contributor.admin', v-click='populateContributorInput(hero._id, $index)').btn-link {{hero._id}}
|
||||
a.label.label-default(v-if='hero.profile', v-class='userLevelStyle(hero)', @click='clickMember(hero._id, true)') {{hero.profile.name}}
|
||||
td(v-if='user.contributor.admin', @click='populateContributorInput(hero._id, index)').btn-link {{hero._id}}
|
||||
td {{hero.contributor.level}}
|
||||
td {{hero.contributor.text}}
|
||||
td
|
||||
markdown(text='hero.contributor.contributions', target='_blank')
|
||||
div(v-markdown='hero.contributor.contributions', target='_blank')
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import keys from 'lodash/keys';
|
||||
import each from 'lodash/each';
|
||||
|
||||
import markdownDirective from 'client/directives/markdown';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import quests from 'common/script/content/quests';
|
||||
import { mountInfo, petInfo } from 'common/script/content/stable';
|
||||
|
|
@ -117,6 +122,9 @@ export default {
|
|||
gear,
|
||||
};
|
||||
},
|
||||
directives: {
|
||||
markdown: markdownDirective,
|
||||
},
|
||||
async mounted () {
|
||||
this.heroes = await this.$store.dispatch('hall:getHeroes');
|
||||
},
|
||||
|
|
@ -153,7 +161,6 @@ export default {
|
|||
},
|
||||
async loadHero (uuid, heroIndex) {
|
||||
this.currentHeroIndex = heroIndex;
|
||||
if (!heroIndex) return;
|
||||
let hero = await this.$store.dispatch('hall:getHero', { uuid });
|
||||
this.hero = hero;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -37,10 +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, key) in user.newMessages', v-if='message.value', @click='navigateToGroup(key)')
|
||||
span.glyphicon.glyphicon-comment
|
||||
span {{message.name}}
|
||||
span.clear-button(@click='clearMessages(k)', :popover="$t('clear')",
|
||||
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(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)")
|
||||
|
|
@ -79,6 +80,11 @@ div.item-with-icon.item-notifications.dropdown
|
|||
margin-top: .2em;
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
max-height: 350px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
/* @TODO: Move to shared css */
|
||||
.dropdown:hover .dropdown-menu {
|
||||
display: block;
|
||||
|
|
@ -211,8 +217,9 @@ export default {
|
|||
}
|
||||
return questInfo;
|
||||
},
|
||||
clearMessages () {
|
||||
this.$store.dispatch('chat:markChatSeen');
|
||||
clearMessages (key) {
|
||||
this.$store.dispatch('chat:markChatSeen', {groupId: key});
|
||||
this.$delete(this.user.newMessages, key);
|
||||
},
|
||||
clearCards () {
|
||||
this.$store.dispatch('chat:clearCards');
|
||||
|
|
@ -278,7 +285,8 @@ export default {
|
|||
this.go('/party');
|
||||
return;
|
||||
}
|
||||
this.go(`/groups/guild/${key}`);
|
||||
|
||||
this.$router.push({ name: 'guild', params: { groupId: key }});
|
||||
},
|
||||
async reject (group) {
|
||||
await this.$store.dispatch('guilds:rejectInvite', {groupId: group.id});
|
||||
|
|
|
|||
105
website/client/components/payments/sendGemsModal.vue
Normal file
105
website/client/components/payments/sendGemsModal.vue
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
<template lang="pug">
|
||||
b-modal#send-gems(:title="title", :hide-footer="true", size='lg')
|
||||
.modal-body(v-if='userReceivingGems', )
|
||||
.panel.panel-default(:class="gift.type === 'gems' ? 'panel-primary' : 'transparent'", @click='gift.type = "gems"')
|
||||
.panel-heading
|
||||
.pull-right
|
||||
span(v-if='gift.gems.fromBalance') {{ $t('sendGiftGemsBalance', {number: userLoggedIn.balance * 4}) }}
|
||||
span(v-if='!gift.gems.fromBalance') {{ $t('sendGiftCost', {cost: gift.gems.amount / 4}) }}
|
||||
| {{ $t('gemsPopoverTitle') }}
|
||||
.panel-body
|
||||
.row
|
||||
.col-md-6
|
||||
.form-group
|
||||
input.form-control(type='number', placeholder='Number of Gems',
|
||||
min='0', :max='gift.gems.fromBalance ? userLoggedIn.balance * 4 : 0',
|
||||
v-model='amount')
|
||||
.col-md-6
|
||||
.btn-group
|
||||
a.btn.btn-default(:class="{active: gift.gems.fromBalance}", @click="gift.gems.fromBalance = true") {{ $t('sendGiftFromBalance') }}
|
||||
a.btn.btn-default(:class="{active: !gift.gems.fromBalance}", @click="gift.gems.fromBalance = false") {{ $t('sendGiftPurchase') }}
|
||||
.row
|
||||
.col-md-12
|
||||
p.small.muted {{ $t('gemGiftsAreOptional', assistanceEmailObject) }}
|
||||
|
||||
.panel.panel-default(:class="gift.type=='subscription' ? 'panel-primary' : 'transparent'", @click='gift.type = "subscription"')
|
||||
.panel-heading {{ $t('subscription') }}
|
||||
.panel-body
|
||||
.form-group
|
||||
.radio(v-for='block in subscriptionBlocks', v-if="block.target !== 'group' && block.canSubscribe === true")
|
||||
label
|
||||
input(type="radio", name="subRadio", :value="block.key", v-model='gift.subscription.key')
|
||||
| {{ $t('sendGiftSubscription', {price: block.price, months: block.months}) }}
|
||||
|
||||
textarea.form-control(rows='3', v-model='gift.message', :placeholder="$t('sendGiftMessagePlaceholder')")
|
||||
//include ../formatting-help
|
||||
|
||||
.modal-footer
|
||||
button.btn.btn-primary(v-if='fromBal', ng-click='sendGift(profile._id)') {{ $t("send") }}
|
||||
button.btn.btn-primary(v-if='!fromBal', ng-click='Payments.showStripe({gift:gift, uuid:profile._id})') {{ $t('card') }}
|
||||
button.btn.btn-warning(v-if='!fromBal', ng-click='Payments.payPalPayment({gift: gift, giftedTo: profile._id})') PayPal
|
||||
button.btn.btn-success(v-if='!fromBal', ng-click="Payments.amazonPayments.init({type: 'single', gift: gift, giftedTo: profile._id})") Amazon Payments
|
||||
button.btn.btn-default(@click='close()') {{$t('cancel')}}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import toArray from 'lodash/toArray';
|
||||
import omitBy from 'lodash/omitBy';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import planGemLimits from '../../../common/script/libs/planGemLimits';
|
||||
import subscriptionBlocksContent from 'common/script/content/subscriptionBlocks';
|
||||
|
||||
// @TODO: EMAILS.TECH_ASSISTANCE_EMAIL
|
||||
let TECH_ASSISTANCE_EMAIL = 'admin@habitica.com';
|
||||
|
||||
export default {
|
||||
props: ['userReceivingGems'],
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
planGemLimits,
|
||||
amount: 0,
|
||||
gift: {
|
||||
type: 'gems',
|
||||
gems: {
|
||||
amount: 0,
|
||||
fromBalance: true,
|
||||
},
|
||||
subscription: {key: ''},
|
||||
message: '',
|
||||
},
|
||||
assistanceEmailObject: {
|
||||
hrefTechAssistanceEmail: `<a href="mailto:${TECH_ASSISTANCE_EMAIL}">${TECH_ASSISTANCE_EMAIL}</a>`,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({userLoggedIn: 'user.data'}),
|
||||
subscriptionBlocks () {
|
||||
let subscriptionBlocks = toArray(subscriptionBlocksContent);
|
||||
subscriptionBlocks = omitBy(subscriptionBlocks, (block) => {
|
||||
return block.discount === true;
|
||||
});
|
||||
subscriptionBlocks = orderBy(subscriptionBlocks, ['months']);
|
||||
|
||||
return subscriptionBlocks;
|
||||
},
|
||||
fromBal () {
|
||||
return this.gift.type === 'gems' && this.gift.gems.fromBalance;
|
||||
},
|
||||
title () {
|
||||
if (!this.userReceivingGems) return '';
|
||||
return this.$t('sendGiftHeading', {name: this.userReceivingGems.profile.name});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'send-gems');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -66,9 +66,8 @@
|
|||
:currencyNeeded="getPriceClass()",
|
||||
:amountNeeded="item.value"
|
||||
).float-right
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ transition(name="fade")
|
|||
.row(v-if='notification.type === "error"')
|
||||
.text.col-12
|
||||
div(v-html='notification.text')
|
||||
.row(v-if='notification.type !== "info" && notification.type !== "error" && notification.type !== "drop"')
|
||||
.row(v-if='["hp", "gp", "xp", "mp"].indexOf(notification.type) !== -1')
|
||||
.text.col-7.offset-1
|
||||
div
|
||||
| {{message}}
|
||||
|
|
@ -14,10 +14,10 @@ transition(name="fade")
|
|||
div.svg-icon(v-html="icons.star", v-if='notification.type === "xp"')
|
||||
div.svg-icon(v-html="icons.mana", v-if='notification.type === "mp"')
|
||||
div(v-html='notification.text')
|
||||
.row(v-if='notification.type === "info"')
|
||||
.row(v-if='["info", "success", "crit", "lvl"].indexOf(notification.type) !== -1')
|
||||
.text.col-12
|
||||
div(v-html='notification.text')
|
||||
.row(v-if='notification.type !== "info" && notification.type !== "error" && notification.type === "drop"')
|
||||
.row(v-if='notification.type === "drop"')
|
||||
.col-2
|
||||
.icon-item
|
||||
div(:class='notification.icon')
|
||||
|
|
|
|||
|
|
@ -4,6 +4,15 @@ div
|
|||
.row
|
||||
.col-6.offset-3
|
||||
button.btn.btn-secondary(@click='sendMessage()') Message
|
||||
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')}}
|
||||
button.btn.btn-secondary(v-if='user._id !== this.userLoggedIn._id && userLoggedIn.inbox.blocks.indexOf(user._id) !== -1',
|
||||
:tooltip="$t('unblock')", @click="unblockUser()", tooltip-placement='right')
|
||||
span.glyphicon.glyphicon-ban-circle
|
||||
| {{$t('unblock')}}
|
||||
button.btn.btn-secondary(@click='openSendGemsModal()') {{ $t('sendGems') }}
|
||||
.row
|
||||
.col-6.offset-3.text-center.nav
|
||||
.nav-item(@click='selectedPage = "profile"', :class="{active: selectedPage === 'profile'}") Profile
|
||||
|
|
@ -255,6 +264,7 @@ div
|
|||
button.btn.btn-primary(popover-trigger='mouseenter', popover-placement='right',
|
||||
:popover='$t(statInfo.allocatepop)') +
|
||||
private-message-modal(:userIdToMessage='userIdToMessage')
|
||||
send-gems-modal(:userReceivingGems='userReceivingGems')
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
@ -322,6 +332,7 @@ div
|
|||
</style>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
import each from 'lodash/each';
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
|
@ -333,6 +344,7 @@ import autoAllocate from '../../../common/script/fns/autoAllocate';
|
|||
import allocate from '../../../common/script/ops/allocate';
|
||||
|
||||
import privateMessageModal from 'client/components/private-message-modal';
|
||||
import sendGemsModal from 'client/components/payments/sendGemsModal';
|
||||
import markdown from 'client/directives/markdown';
|
||||
import achievementsLib from '../../../common/script/libs/achievements';
|
||||
// @TODO: EMAILS.COMMUNITY_MANAGER_EMAIL
|
||||
|
|
@ -348,10 +360,12 @@ export default {
|
|||
components: {
|
||||
bModal,
|
||||
privateMessageModal,
|
||||
sendGemsModal,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
userIdToMessage: '',
|
||||
userReceivingGems: '',
|
||||
editing: false,
|
||||
editingProfile: {
|
||||
name: '',
|
||||
|
|
@ -536,6 +550,19 @@ export default {
|
|||
allocateNow () {
|
||||
autoAllocate(this.user);
|
||||
},
|
||||
blockUser () {
|
||||
this.userLoggedIn.inbox.blocks.push(this.user._id);
|
||||
axios.post(`/api/v3/user/block/${this.user._id}`);
|
||||
},
|
||||
unblockUser () {
|
||||
let index = this.userLoggedIn.inbox.blocks.indexOf(this.user._id);
|
||||
this.userLoggedIn.inbox.blocks.splice(index, 1);
|
||||
axios.post(`/api/v3/user/block/${this.user._id}`);
|
||||
},
|
||||
openSendGemsModal () {
|
||||
this.userReceivingGems = this.user;
|
||||
this.$root.$emit('show::modal', 'send-gems');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export default {
|
|||
return false;
|
||||
},
|
||||
isLeaderOfGroup (user, group) {
|
||||
return user._id === group.leader._id;
|
||||
return user._id === group.leader || user._id === group.leader._id;
|
||||
},
|
||||
filterGuild (group, filters, search, user) {
|
||||
let passedSearch = true;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export async function clearFlagCount (store, payload) {
|
|||
}
|
||||
|
||||
export async function markChatSeen (store, payload) {
|
||||
if (store.user.newMessages) delete store.user.newMessages[payload.groupId];
|
||||
if (store.state.user.newMessages) delete store.state.user.newMessages[payload.groupId];
|
||||
let url = `/api/v3/groups/${payload.groupId}/chat/seen`;
|
||||
let response = await axios.post(url);
|
||||
return response.data.data;
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ export default function () {
|
|||
profileUser: {},
|
||||
upgradingGroup: {},
|
||||
notificationStore: [],
|
||||
modalStack: [],
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
6
website/common/locales/en/achievements.json
Normal file
6
website/common/locales/en/achievements.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"share": "Share",
|
||||
"onwards": "Onwards!",
|
||||
"levelup": "By accomplishing your real life goals, you leveled up and are now fully healed!",
|
||||
"reachedLevel": "You Reached Level <%= level %>"
|
||||
}
|
||||
|
|
@ -114,5 +114,6 @@
|
|||
"shortNamePlaceholder": "What short tag should be used to identify your Challenge?",
|
||||
"updateChallenge": "Update Challenge",
|
||||
"haveNoChallenges": "You don't have any Challenges",
|
||||
"loadMore": "Load More"
|
||||
"loadMore": "Load More",
|
||||
"exportChallengeCsv": "Export Challenge"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
"subscription": "Subscription",
|
||||
"subscriptions": "Subscriptions",
|
||||
"subDescription": "Buy Gems with gold, get monthly mystery items, retain progress history, double daily drop-caps, support the devs. Click for more info.",
|
||||
"sendGems": "Send Gems",
|
||||
"buyGemsGold": "Buy Gems with Gold",
|
||||
"buyGemsGoldText": "Alexander the Merchant will sell you Gems at a cost of 20 Gold per Gem. His monthly shipments are initially capped at 25 Gems per month, but for every 3 consecutive months that you are subscribed, this cap increases by 5 Gems, up to a maximum of 50 Gems per month!",
|
||||
"mustSubscribeToPurchaseGems": "Must subscribe to purchase gems with GP",
|
||||
|
|
|
|||
Loading…
Reference in a new issue