mirror of
https://github.com/sudoxnym/habitica-self-host.git
synced 2026-07-17 19:42:15 +00:00
New client popups profile andmore (#8907)
* Added more styles to user profile modal and replaced memberDetail * Added notify library * Added edit avator * Added notification menu updates * Fixed lint issues * Added group invite functionality * Added many achievement modals * Added initial quest modals * Added guild, drops, and rebirth modals * Added the reset of the achievement modals and fixed lint
This commit is contained in:
parent
bca52cb6fa
commit
0dba37008f
39 changed files with 1624 additions and 348 deletions
|
|
@ -125,6 +125,7 @@
|
|||
"vue": "^2.1.0",
|
||||
"vue-loader": "^11.0.0",
|
||||
"vue-mugen-scroll": "^0.2.1",
|
||||
"vue-notification": "^1.3.2",
|
||||
"vue-router": "^2.0.0-rc.5",
|
||||
"vue-style-loader": "^3.0.0",
|
||||
"vue-template-compiler": "^2.1.10",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
<template lang="pug">
|
||||
#app
|
||||
notifications
|
||||
router-view(v-if="!isUserLoggedIn || isStaticPage")
|
||||
template(v-else)
|
||||
#loading-screen.h-100.w-100.d-flex.justify-content-center.align-items-center(v-if="!isUserLoaded")
|
||||
p Loading...
|
||||
template(v-else)
|
||||
notifications
|
||||
notifications-display
|
||||
app-menu
|
||||
.container-fluid
|
||||
app-header
|
||||
|
|
@ -18,7 +19,7 @@
|
|||
import AppMenu from './components/appMenu';
|
||||
import AppHeader from './components/appHeader';
|
||||
import AppFooter from './components/appFooter';
|
||||
import notifications from './components/notifications';
|
||||
import notificationsDisplay from './components/notifications';
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
|
|
@ -27,7 +28,7 @@ export default {
|
|||
AppMenu,
|
||||
AppHeader,
|
||||
AppFooter,
|
||||
notifications,
|
||||
notificationsDisplay,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
|
|||
6
website/client/assets/svg/backgrounds.svg
Normal file
6
website/client/assets/svg/backgrounds.svg
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="29.6" height="29.6" x="1.2" y="1.2" stroke="#A5A1AC" stroke-width="2.4" rx="4"/>
|
||||
<path fill="#A5A1AC" d="M11 11l2-1-2-1-1-2-1 2-2 1 2 1 1 2zM23 14l2-1-2-1-1-2-1 2-2 1 2 1 1 2zM15.333 22.333L18 21l-2.667-1.333L14 17l-1.333 2.667L10 21l2.667 1.333L14 25z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 425 B |
26
website/client/components/achievements/armoireEmpty.vue
Normal file
26
website/client/components/achievements/armoireEmpty.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<template lang="pug">
|
||||
b-modal#armoire-empty(:title="$t('armoireText')", size='lg', :hide-footer="true")
|
||||
.modal-header
|
||||
.shop_armoire.pull-right
|
||||
.modal-body
|
||||
p {{$t('armoireLastItem')}}
|
||||
br
|
||||
p {{$t('armoireNotesEmpty')}}
|
||||
.modal-footer
|
||||
button.btn.btn-default(@click='close()') {{$t('close')}}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'armoire-empty');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
120
website/client/components/achievements/chooseClass.vue
Normal file
120
website/client/components/achievements/chooseClass.vue
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<template lang="pug">
|
||||
b-modal#choose-class(:title="$t('chooseClassHeading')", size='lg', :hide-footer="true")
|
||||
.modal-body.select-class
|
||||
.container-fluid
|
||||
.row
|
||||
.col-md-3(@click='selectedClass = "warrior"')
|
||||
h5 {{ $t('warriorWiki') }}
|
||||
figure.herobox(:class='{"selected-class": selectedClass === "warrior"}')
|
||||
.character-sprites
|
||||
span(:class='`skin_${user.preferences.skin}`')
|
||||
span(class='head_0')
|
||||
span(:class='`${user.preferences.size}_armor_warrior_5`')
|
||||
span(:class='`hair_base_${user.preferences.hair.base}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_bangs_${user.preferences.hair.bangs}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_beard_${user.preferences.hair.beard}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_mustache_${user.preferences.hair.mustache}_${user.preferences.hair.color}`')
|
||||
span(class='head_warrior_5')
|
||||
span(class='shield_warrior_5')
|
||||
span(class='weapon_warrior_6')
|
||||
.col-md-3(@click='selectedClass = "wizard"')
|
||||
h5 {{ $t('mageWiki') }}
|
||||
figure.herobox(:class='{"selected-class": selectedClass === "wizard"}')
|
||||
.character-sprites
|
||||
span(class='`skin_${user.preferences.skin}`')
|
||||
span(class='head_0')
|
||||
span(:class='`${user.preferences.size}_armor_wizard_5`')
|
||||
span(:class='`hair_base_${user.preferences.hair.base}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_bangs_${user.preferences.hair.bangs}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_beard_${user.preferences.hair.beard}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_mustache_${user.preferences.hair.mustache}_${user.preferences.hair.color}`')
|
||||
span(class='head_wizard_5')
|
||||
span(class='shield_wizard_5')
|
||||
span(class='weapon_wizard_6')
|
||||
.col-md-3(@click='selectedClass = "rogue"')
|
||||
h5 {{ $t('rogueWiki') }}
|
||||
figure.herobox(:class='{"selected-class": selectedClass === "rogue"}')
|
||||
.character-sprites
|
||||
span(:class='`skin_${user.preferences.skin}`')
|
||||
span(class='head_0')
|
||||
span(:class='`${user.preferences.size}_armor_rogue_5`')
|
||||
span(:class='`hair_base_${user.preferences.hair.base}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_bangs_${user.preferences.hair.bangs}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_beard_${user.preferences.hair.beard}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_mustache_${user.preferences.hair.mustache}_${user.preferences.hair.color}`')
|
||||
span(class='head_rogue_5')
|
||||
span(class='shield_rogue_6')
|
||||
span(class='weapon_rogue_6')
|
||||
.col-md-3(@click='selectedClass = "healer"')
|
||||
h5 {{ $t('healerWiki') }}
|
||||
figure.herobox(ng-class='{"selected-class": selectedClass === "healer"}')
|
||||
.character-sprites
|
||||
span(:class='`skin_${user.preferences.skin}`')
|
||||
span(class='head_0')
|
||||
span(:class='`${user.preferences.size}_armor_healer_5`')
|
||||
span(:class='`hair_base_${user.preferences.hair.base}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_bangs_${user.preferences.hair.bangs}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_beard_${user.preferences.hair.beard}_${user.preferences.hair.color}`')
|
||||
span(:class='`hair_mustache_${user.preferences.hair.mustache}_${user.preferences.hair.color}`')
|
||||
span(class='head_healer_5')
|
||||
span(class='shield_healer_5')
|
||||
span(class='weapon_healer_6')
|
||||
br
|
||||
.well(v-if='selectedClass === "warrior"') {{ $t('warriorText') }}
|
||||
.well(v-if='selectedClass === "wizard"') {{ $t('mageText') }}
|
||||
.well(v-if='selectedClass === "rogue"') {{ $t('rogueText') }}
|
||||
.well(v-if='selectedClass === "healer"') {{ $t('healerText') }}
|
||||
|
||||
.modal-footer
|
||||
span(popover-placement='left', popover-trigger='mouseenter', :popover="$t('optOutOfClassesText')")
|
||||
button.btn.btn-danger(@click='disableClasses({}); close()') {{ $t('optOutOfClasses') }}
|
||||
button.btn.btn-primary(:disabled='!selectedClass' @click='changeClass(selectedClass); selectedClass = undefined; close()') {{ $t('select') }}
|
||||
.pull-left {{ $t('chooseClassLearn') }}
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import Avatar from '../avatar';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import percent from '../../../common/script/libs/percent';
|
||||
import {maxHealth} from '../../../common/script/index';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
Avatar,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
maxHealth,
|
||||
selectedClass: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
barStyle () {
|
||||
return {
|
||||
width: `${percent(this.user.stats.hp, maxHealth)}%`,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'choose-class');
|
||||
},
|
||||
disableClasses () {
|
||||
// @TODO:
|
||||
},
|
||||
changeClass () {
|
||||
// @TODO:
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
38
website/client/components/achievements/contributor.vue
Normal file
38
website/client/components/achievements/contributor.vue
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<template lang="pug">
|
||||
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
|
||||
.modal-content(style='min-width:28em')
|
||||
.modal-body.text-center
|
||||
h3(style='margin-bottom:0') {{ $t('modalContribAchievement') }}
|
||||
// @TODO: +achievementAvatar('boot',0)
|
||||
| {{ $t('contribModal', {name: user.profile.name, level: user.contributor.level}) }}
|
||||
a(:href="$t('conRewardsURL')", target='_blank') {{ $t('contribLink') }}
|
||||
br
|
||||
button.btn.btn-primary(style='margin-top:1em' @click='close()') {{ $t('huzzah') }}
|
||||
// @TODO: +achievementFooter
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'testing');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
70
website/client/components/achievements/death.vue
Normal file
70
website/client/components/achievements/death.vue
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<template lang="pug">
|
||||
b-modal#death(:title="$t('lostAllHealth')", size='lg', :hide-footer="true")
|
||||
.modal-body
|
||||
.container-fluid
|
||||
.row
|
||||
.col-6.col-xs-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}}
|
||||
figure.herobox.text-center
|
||||
.character-sprites
|
||||
avatar(:member='user')
|
||||
// @TOOD: Sleep +generatedAvatar({sleep:true})
|
||||
span(class='knockout')
|
||||
.col-6.col-xs-12
|
||||
h4.dont-despair {{ $t('dontDespair') }}
|
||||
p.death-penalty {{ $t('deathPenaltyDetails') }}
|
||||
.modal-footer
|
||||
a.btn.btn-danger.btn-lg.flex-column.btn-wrap(@click='revive(); close()') {{ $t('refillHealthTryAgain') }}
|
||||
h4.text-center {{ $t('dyingOftenTips') }}
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import Avatar from '../avatar';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import revive from '../../../common/script/ops/revive';
|
||||
import percent from '../../../common/script/libs/percent';
|
||||
import {maxHealth} from '../../../common/script/index';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
Avatar,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
maxHealth,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
barStyle () {
|
||||
return {
|
||||
width: `${percent(this.user.stats.hp, maxHealth)}%`,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'death');
|
||||
},
|
||||
revive () {
|
||||
// @TODO: Post
|
||||
revive(this.user);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
55
website/client/components/achievements/dropsEnabled.vue
Normal file
55
website/client/components/achievements/dropsEnabled.vue
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<template lang="pug">
|
||||
b-modal#drops-enabled(:title="$t('dropsEnabled')", size='lg', :hide-footer="true")
|
||||
.modal-header
|
||||
h4 {{ $t('dropsEnabled') }}
|
||||
.modal-body
|
||||
p
|
||||
figure
|
||||
.item-drop-icon(class='Pet_Egg_Wolf')
|
||||
span {{ firstDropText }}
|
||||
br
|
||||
p
|
||||
figure
|
||||
.item-drop-icon(class='Pet_Currency_Gem')
|
||||
span {{ $t('useGems') }}
|
||||
.modal-footer
|
||||
button.btn.btn-default(@click='close()') {{ $t('close') }}
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
import eggs from '../../../common/script/content/eggs';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
eggs,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
firstDropText () {
|
||||
return this.$t('firstDrop', {
|
||||
eggText: this.eggs.all.Wolf.text(),
|
||||
eggNotes: this.eggs.all.Wolf.notes(),
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'drops-enabled');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
32
website/client/components/achievements/invitedFriend.vue
Normal file
32
website/client/components/achievements/invitedFriend.vue
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<template lang="pug">
|
||||
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
|
||||
.modal-content(style='min-width:28em')
|
||||
.modal-body.text-center
|
||||
h3(style='margin-bottom:0') {{ $t('modalAchievement') }}
|
||||
// @TODO: +achievementAvatar('friends',0)
|
||||
p {{ $t('invitedFriendText') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
// @TODO: +achievementFooter
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'testing');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
32
website/client/components/achievements/joinedChallenge.vue
Normal file
32
website/client/components/achievements/joinedChallenge.vue
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<template lang="pug">
|
||||
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
|
||||
.modal-content(style='min-width:28em')
|
||||
.modal-body.text-center
|
||||
h3(style='margin-bottom:0') {{ $t('modalAchievement') }}
|
||||
// @TODO: +achievementAvatar('challenge',0)
|
||||
p {{ $t('joinedChallengeText') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
// @TODO: +achievementFooter
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'testing');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
32
website/client/components/achievements/joinedGuild.vue
Normal file
32
website/client/components/achievements/joinedGuild.vue
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<template lang="pug">
|
||||
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
|
||||
.modal-content(style='min-width:28em')
|
||||
.modal-body.text-center
|
||||
h3(style='margin-bottom:0') {{ $t('modalAchievement') }}
|
||||
// @TODO: +achievementAvatar('guild',0)
|
||||
p {{ $t('joinedGuildText') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
// @TODO: +achievementFooter
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'testing');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
120
website/client/components/achievements/levelUp.vue
Normal file
120
website/client/components/achievements/levelUp.vue
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<template lang="pug">
|
||||
b-modal#level-up(:title="$t('levelUpShare')", size='sm', :hide-footer="true")
|
||||
.modal-content
|
||||
.modal-body.text-center
|
||||
h3 {{ $t('gainedLevel') }}
|
||||
.container-fluid
|
||||
.row
|
||||
.herobox
|
||||
.character-sprites
|
||||
// @TODO: ({sleep: false})
|
||||
avatar(:member='user')
|
||||
.row
|
||||
.herobox
|
||||
.avatar-level(:class='userLevelStyle(user)') {{ $t('level') + user.stats.lvl }}
|
||||
h4 {{ $t('leveledUp', {level: user.stats.lvl}) }}
|
||||
p {{ $t('fullyHealed') }}
|
||||
br
|
||||
div(v-if='user.flags.classSelected && !user.preferences.disableClasses && !user.preferences.automaticAllocation')
|
||||
a.btn.btn-default(@click='statsAllocationBoxIsOpen = !statsAllocationBoxIsOpen',
|
||||
data-toggle='collapse', data-target='#stat-allocation', aria-expanded='false', aria-controls='stat-allocation')
|
||||
| {{statsAllocationBoxIsOpen ? $t('hideQuickAllocation') : $t('showQuickAllocation')}}
|
||||
p
|
||||
.collapse#stat-allocation
|
||||
table.table.text-left
|
||||
tr
|
||||
td
|
||||
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') }}
|
||||
td
|
||||
// @TODO: +statAllocation
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
.checkbox
|
||||
label(style='display:inline-block') {{ $t('dontShowAgain') }}
|
||||
input(type='checkbox', v-model='user.preferences.suppressModals.levelUp', @change='changeLevelupSuppress()')
|
||||
.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')
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.modal-content {
|
||||
min-width: 28em;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.herobox {
|
||||
margin:auto 8.3em;
|
||||
width: 6em;
|
||||
height: 9em;
|
||||
padding-top: 0;
|
||||
cursor:default;
|
||||
}
|
||||
|
||||
.character-sprites {
|
||||
margin: 0;
|
||||
width: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import Avatar from '../avatar';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import {maxHealth} from '../../../common/script/index';
|
||||
import styleHelper from 'client/mixins/styleHelper';
|
||||
|
||||
let BASE_URL = '@TODO';
|
||||
|
||||
export default {
|
||||
mixins: [styleHelper],
|
||||
components: {
|
||||
bModal,
|
||||
Avatar,
|
||||
},
|
||||
data () {
|
||||
let tweet = this.$t('levelUpShare');
|
||||
return {
|
||||
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`,
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
this.loadWidgets();
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'level-up');
|
||||
},
|
||||
loadWidgets () {
|
||||
// @TODO:
|
||||
},
|
||||
changeLevelupSuppress () {
|
||||
// @TODO: dispatch set({"preferences.suppressModals.levelUp": user.preferences.suppressModals.levelUp?true: false})
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
88
website/client/components/achievements/lowHealth.vue
Normal file
88
website/client/components/achievements/lowHealth.vue
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
<template lang="pug">
|
||||
b-modal#low-health(:title="$t('losingHealthWarning')", size='lg', :hide-footer="true")
|
||||
.modal-body
|
||||
.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
|
||||
| {{healthLeft}}
|
||||
.herobox.inline-block
|
||||
.character-sprites
|
||||
avatar(:member='user')
|
||||
p {{ $t('losingHealthWarning2') }}
|
||||
h4 {{ $t('toRegainHealth') }}
|
||||
ul
|
||||
li.spaced {{ $t('lowHealthTips1') }}
|
||||
li.spaced {{ $t('lowHealthTips2') }}
|
||||
h4 {{ $t('losingHealthQuickly') }}
|
||||
ul
|
||||
li.spaced {{ $t('lowHealthTips3') }}
|
||||
li.spaced {{ $t('lowHealthTips4') }}
|
||||
h4 {{ $t('goodLuck') }}
|
||||
.modal-footer
|
||||
a.btn.btn-primary(@click='acknowledgeHealthWarning(); close()') {{ $t('ok') }}
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.hero-stats {
|
||||
position: absolute;
|
||||
margin-left: 9em;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.character-sprites {
|
||||
display: inline-flex;
|
||||
margin: 3em auto;
|
||||
}
|
||||
|
||||
.herobox {
|
||||
padding-top: 0em;
|
||||
margin-left: 16em;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
margin-top: 0em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import Avatar from '../avatar';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import percent from '../../../common/script/libs/percent';
|
||||
import {maxHealth} from '../../../common/script/index';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
Avatar,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
maxHealth,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
barStyle () {
|
||||
return {
|
||||
width: `${percent(this.user.stats.hp, maxHealth)}%`,
|
||||
};
|
||||
},
|
||||
healthLeft () {
|
||||
return `${Math.ceil(this.user.stats.hp)} / ${this.maxHealth}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'low-health');
|
||||
},
|
||||
acknowledgeHealthWarning () {
|
||||
// @TODO: {'flags.warnedLowHealth':true}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
45
website/client/components/achievements/newStuff.vue
Normal file
45
website/client/components/achievements/newStuff.vue
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<template lang="pug">
|
||||
b-modal#new-stuff(:title="$t('newStuff')", size='lg', :hide-footer="true")
|
||||
.modal-header
|
||||
| {{ this.$t('newStuff') }} by
|
||||
a(target='_blank', href='https://twitter.com/Mihakuu') Bailey
|
||||
.modal-body.new-stuff-modal.modal-fixed-height
|
||||
div(:class="baileyClass")
|
||||
br
|
||||
br
|
||||
div(ng-bind-html='latestBaileyMessage')
|
||||
.modal-footer
|
||||
a.btn.btn-info(href='http://habitica.wikia.com/wiki/Whats_New', target='_blank') {{ this.$t('newsArchive') }}
|
||||
button.btn.btn-default(@click='close()') {{ this.$t('cool') }}
|
||||
button.btn.btn-warning(@click='dismissAlert(); close()') {{ this.$t('dismissAlert') }}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
data () {
|
||||
let worldDmg = {
|
||||
bailey: true,
|
||||
};
|
||||
|
||||
return {
|
||||
baileyClass: {
|
||||
'npc_bailey_broken': worldDmg.bailey, // eslint-disable-line
|
||||
'npc_bailey': !worldDmg.bailey, // eslint-disable-line
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
// @TODO: $http.get('/new-stuff.html') ?
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'new-stuff');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
56
website/client/components/achievements/questCompleted.vue
Normal file
56
website/client/components/achievements/questCompleted.vue
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<template lang="pug">
|
||||
b-modal#quest-completed(:title="$t('lostAllHealth')", size='lg', :hide-footer="true")
|
||||
.modal-header
|
||||
h4 "{{quests[user.party.quest.completed].text()}}"
|
||||
| {{ $t('completed') }}
|
||||
.modal-body
|
||||
.col-centered(: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 scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import Avatar from '../avatar';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import percent from '../../../common/script/libs/percent';
|
||||
import {maxHealth} from '../../../common/script/index';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
Avatar,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
maxHealth,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
barStyle () {
|
||||
return {
|
||||
width: `${percent(this.user.stats.hp, maxHealth)}%`,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'quest-completed');
|
||||
},
|
||||
setQuestCompleted () {
|
||||
// @TODO: set({"party.quest.completed":""})
|
||||
this.close();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
92
website/client/components/achievements/questInvitation.vue
Normal file
92
website/client/components/achievements/questInvitation.vue
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<template lang="pug">
|
||||
b-modal#quest-invitation(:title="$t('questInvitation')", size='lg', :hide-footer="true")
|
||||
.modal-header
|
||||
h4 {{ $t('questInvitation') }}
|
||||
| {{quests[user.party.quest.key].text()}}
|
||||
.modal-body
|
||||
.pull-right-sm.text-center
|
||||
.col-centered(:class='`quest_${quests[user.party.quest.key].key}`')
|
||||
div(ng-if='quests[user.party.quest.key].boss')
|
||||
h4 {{quests[user.party.quest.key].boss.name()}}
|
||||
p
|
||||
strong {{ $t('bossHP') }} + ': '
|
||||
| {{quests[user.party.quest.key].boss.hp}}
|
||||
p
|
||||
strong {{ $t('bossStrength') }} + ': '
|
||||
| {{quests[user.party.quest.key].boss.str}}
|
||||
div(ng-if='quests[user.party.quest.key].collect')
|
||||
p(ng-repeat='(k,v) in quests[user.party.quest.key].collect')
|
||||
strong {{ $t('collect') }} + ': '
|
||||
| {{quests[user.party.quest.key].collect[k].count}} {{quests[user.party.quest.key].collect[k].text()}}
|
||||
div(ng-bind-html='quests[user.party.quest.key].notes()')
|
||||
.quest-rewards(:key='user.party.quest.key', header-participant="$t('rewardsAllParticipants')", header-quest-owner="$t('rewardsQuestOwner')")
|
||||
hr
|
||||
h5 {{headerParticipant}}
|
||||
table.table.table-striped
|
||||
tr(ng-repeat='drop in _.reject(quest.drop.items, \'onlyOwner\')')
|
||||
td {{drop.text()}}
|
||||
tr(ng-if='quest.drop.exp > 0')
|
||||
td {{quest.drop.exp}}
|
||||
| {{ $t('experience') }}
|
||||
tr(ng-if='quest.drop.gp > 0')
|
||||
td {{quest.drop.gp}}
|
||||
| {{ $t('gold') }}
|
||||
tr(ng-if='quest.drop.unlock()')
|
||||
td {{quest.drop.unlock()}}
|
||||
div(ng-if='getQuestOwnerRewards(quest).length > 0')
|
||||
h5 {{headerQuestOwner}}
|
||||
table.table.table-striped
|
||||
tr(ng-repeat='drop in getQuestOwnerRewards(quest)')
|
||||
td {{drop.text()}}
|
||||
.modal-footer
|
||||
button.btn.btn-default(ng-click='questHold = true; $close()') {{ $t('askLater') }}
|
||||
button.btn.btn-default(ng-click='questReject(); $close()') {{ $t('reject') }}
|
||||
button.btn.btn-primary(ng-click='questAccept(); $close()') {{ $t('accept') }}
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
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';
|
||||
import {maxHealth} from '../../../common/script/index';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
Avatar,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
maxHealth,
|
||||
quests,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
barStyle () {
|
||||
return {
|
||||
width: `${percent(this.user.stats.hp, maxHealth)}%`,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'death');
|
||||
},
|
||||
revive () {
|
||||
// @TODO: Post
|
||||
revive(this.user);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
40
website/client/components/achievements/rebirth.vue
Normal file
40
website/client/components/achievements/rebirth.vue
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<template lang="pug">
|
||||
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
|
||||
.modal-content(style='min-width:28em')
|
||||
.modal-body.text-center
|
||||
h3(style='margin-bottom:0') {{ $t('modalAchievement') }}
|
||||
// @TODO: +achievementAvatar('sun',0)
|
||||
div(ng-if='user.achievements.rebirthLevel < 100')
|
||||
| {{ $t('rebirthAchievement', {number: user.achievements.rebirths, level: user.achievements.rebirthLevel}) }}
|
||||
div(ng-if='user.achievements.rebirthLevel >= 100')
|
||||
| {{ $t('rebirthAchievement100', {number: user.achievements.rebirths}) }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
// @TODO: +achievementFooter
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'testing');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
38
website/client/components/achievements/rebirthEnabled.vue
Normal file
38
website/client/components/achievements/rebirthEnabled.vue
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<template lang="pug">
|
||||
b-modal#rebirth-enabled(:title="$t('rebirthNew')", size='lg', :hide-footer="true")
|
||||
.modal-header
|
||||
h4 {{ $t('rebirthNew') }}
|
||||
.modal-body
|
||||
figure
|
||||
.rebirth_orb
|
||||
p
|
||||
span {{ $t('rebirthUnlock') }}
|
||||
.modal-footer
|
||||
button.btn.btn-default(@click='close()') {{ $t('close') }}
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'rebirth-enabled');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
43
website/client/components/achievements/streak.vue
Normal file
43
website/client/components/achievements/streak.vue
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<template lang="pug">
|
||||
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
|
||||
.modal-content(style='min-width:28em')
|
||||
.modal-body.text-center
|
||||
h3(style='margin-bottom: 0') {{ $t('streakAchievement') }}
|
||||
// @TODO: +achievementAvatar('thermometer',2.5)
|
||||
h4(ng-if='user.achievements.streak === 1') {{ $t('firstStreakAchievement') }}
|
||||
h4(ng-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
|
||||
label(style='display:inline-block') {{ $t('dontShowAgain') }}
|
||||
input(type='checkbox', ng-model='user.preferences.suppressModals.streak', ng-change='set({"preferences.suppressModals.streak": user.preferences.suppressModals.streak?true: false})')
|
||||
// @TOOD: +achievementFooter
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'testing');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
38
website/client/components/achievements/testing.vue
Normal file
38
website/client/components/achievements/testing.vue
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<template lang="pug">
|
||||
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
|
||||
.modal-content
|
||||
.modal-body.text-center
|
||||
h3 {{ $t('guildReminderTitle') }}
|
||||
br
|
||||
.scene_guilds.center-block
|
||||
br
|
||||
h4 {{ $t('guildReminderText1') }}
|
||||
.modal-footer
|
||||
.container-fluid
|
||||
.row
|
||||
.col-xs-6.text-center
|
||||
button.btn-lg.btn-default(@click='close()') {{ $t('guildReminderDismiss') }}
|
||||
.col-xs-6.text-center
|
||||
button.btn-lg.btn-primary(ui-sref='options.social.guilds.public', href='/#/options/groups/guilds/public', ng-click='$close()') {{ $t('guildReminderCTA') }}
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'testing');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
38
website/client/components/achievements/testingletiant.vue
Normal file
38
website/client/components/achievements/testingletiant.vue
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<template lang="pug">
|
||||
b-modal#testingletiant(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
|
||||
.modal-content
|
||||
.modal-body.text-center
|
||||
h3 {{ $t('guildReminderTitle') }}
|
||||
br
|
||||
.scene_guilds.center-block
|
||||
br
|
||||
h4 {{ $t('guildReminderText2') }}
|
||||
.modal-footer
|
||||
.container-fluid
|
||||
.row
|
||||
.col-xs-6.text-center
|
||||
button.btn-lg.btn-default(@click='close()') {{ $t('guildReminderDismiss') }}
|
||||
.col-xs-6.text-center
|
||||
button.btn-lg.btn-primary(ui-sref='options.social.guilds.public', href='/#/options/groups/guilds/public', ng-click='$close()') {{ $t('guildReminderCTA') }}
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'testingletiant');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
53
website/client/components/achievements/ultimateGear.vue
Normal file
53
website/client/components/achievements/ultimateGear.vue
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<template lang="pug">
|
||||
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
|
||||
.modal-content(style='min-width:28em')
|
||||
.modal-body.text-center
|
||||
h3(style='margin-bottom:0') {{ $t('modalAchievement') }}
|
||||
// @TODO: +achievementAvatar('armor',2.5)
|
||||
p {{ $t('gearAchievement') }}
|
||||
br
|
||||
table.multi-achievement
|
||||
tr
|
||||
td(ng-if='::user.achievements.ultimateGearSets.healer').multi-achievement
|
||||
.achievement-ultimate-healer2x.multi-achievement
|
||||
| {{ $t('healer') }}
|
||||
td(ng-if='::user.achievements.ultimateGearSets.wizard').multi-achievement
|
||||
.achievement-ultimate-mage2x.multi-achievement
|
||||
| {{ $t('mage') }}
|
||||
td(ng-if='::user.achievements.ultimateGearSets.rogue').multi-achievement
|
||||
.achievement-ultimate-rogue2x.multi-achievement
|
||||
| {{ $t('rogue') }}
|
||||
td(ng-if='::user.achievements.ultimateGearSets.warrior').multi-achievement
|
||||
.achievement-ultimate-warrior2x.multi-achievement
|
||||
| {{ $t('warrior') }}
|
||||
br
|
||||
div(ng-if='!(user.achievements.ultimateGearSets.healer && user.achievements.ultimateGearSets.wizard && user.achievements.ultimateGearSets.rogue && user.achievements.ultimateGearSets.warrior)')
|
||||
p {{ $t('moreGearAchievements') }}
|
||||
br
|
||||
.shop_armoire.pull-right
|
||||
p {{ $t("armoireUnlocked") }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
// @TODO: +achievementFooter
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'testing');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
64
website/client/components/achievements/wonChallenge.vue
Normal file
64
website/client/components/achievements/wonChallenge.vue
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<template lang="pug">
|
||||
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
|
||||
.modal-content(style='min-width:28em')
|
||||
.modal-body.text-center
|
||||
h3(style='margin-bottom: 0') {{ $t('wonChallenge') }}
|
||||
// @TODO: h4: markdown(text='user.achievements.challenges[user.achievements.challenges.length - 1]')
|
||||
.container-fluid
|
||||
.row(style='margin-bottom:1em')
|
||||
.col-xs-4(style='padding:0')
|
||||
.container-fluid
|
||||
.row
|
||||
.col-xs-4(style='padding:0')
|
||||
.col-xs-4(style='padding:0')
|
||||
.achievement-karaoke-2x(style='margin-top: 2em')
|
||||
.col-xs-4(style='padding:0')
|
||||
.herobox(style='padding:0; width:0; height:7em')
|
||||
.character-sprites(style='width:0')
|
||||
// @TODO: +generatedAvatar({sleep: false})
|
||||
.col-xs-4(style='padding:0')
|
||||
.container-fluid
|
||||
.row
|
||||
.col-xs-4(style='padding:0')
|
||||
.col-xs-4(style='padding:0')
|
||||
.achievement-karaoke-2x(style='margin-top: 2em')
|
||||
p {{ $t('congratulations') }}
|
||||
br
|
||||
button.btn.btn-primary(@click='close()') {{ $t('hurray') }}
|
||||
.modal-footer(style='margin-top:0', ng-init='loadWidgets()')
|
||||
.container-fluid
|
||||
.row
|
||||
.col-xs-3
|
||||
a.twitter-share-button(href='https://twitter.com/intent/tweet?text=#{tweet}&via=habitica&url=#{env.BASE_URL}/social/won-challenge&count=none') {{ $t('tweet') }}
|
||||
.col-xs-4(style='margin-left:.8em')
|
||||
.fb-share-button(data-href='#{env.BASE_URL}/social/won-challenge', data-layout='button')
|
||||
.col-xs-4(style='margin-left:.8em')
|
||||
a.tumblr-share-button(data-href='#{env.BASE_URL}/social/won-challenge', data-notes='none')
|
||||
</template>
|
||||
|
||||
<style scope>
|
||||
.dont-despair, .death-penalty {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
data () {
|
||||
let tweet = this.$t('wonChallengeShare');
|
||||
return {
|
||||
tweet,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'testing');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<template lang='pug'>
|
||||
<template lang="pug">
|
||||
.row
|
||||
modify-inventory
|
||||
footer.container-fluid
|
||||
|
|
@ -93,6 +93,7 @@
|
|||
a.btn.btn-default(@click='addTenGems()') +10 Gems
|
||||
a.btn.btn-default(@click='addHourglass()') +1 Mystic Hourglass
|
||||
a.btn.btn-default(@click='addGold()') +500GP
|
||||
a.btn.btn-default(@click='plusTenHealth()') + 10HP
|
||||
a.btn.btn-default(@click='addMana()') +MP
|
||||
a.btn.btn-default(@click='addLevelsAndGold()') +Exp +GP +MP
|
||||
a.btn.btn-default(@click='addOneLevel()') +1 Level
|
||||
|
|
@ -166,6 +167,11 @@ export default {
|
|||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
plusTenHealth () {
|
||||
this.$store.dispatch('user:set', {
|
||||
'stats.hp': this.user.stats.hp += 10,
|
||||
});
|
||||
},
|
||||
setHealthLow () {
|
||||
this.$store.dispatch('user:set', {
|
||||
'stats.hp': 1,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<template lang="pug">
|
||||
div
|
||||
inbox-modal
|
||||
creator-intro
|
||||
nav.navbar.navbar-inverse.fixed-top.navbar-toggleable-sm
|
||||
.navbar-header
|
||||
.logo.svg-icon(v-html="icons.logo")
|
||||
|
|
@ -50,10 +51,10 @@ div
|
|||
.svg-icon(v-html="icons.gold")
|
||||
span {{user.stats.gp | roundBigNumber}}
|
||||
notification-menu
|
||||
router-link.dropdown.item-with-icon.item-user(:to="{name: 'avatar'}")
|
||||
a.dropdown.item-with-icon.item-user(@click='showAvatar()')
|
||||
.svg-icon(v-html="icons.user")
|
||||
.dropdown-menu.dropdown-menu-right.user-dropdown
|
||||
router-link.dropdown-item.edit-avatar(:to="{name: 'avatar'}")
|
||||
a.dropdown-item.edit-avatar(@click='showAvatar()')
|
||||
h3 {{ user.profile.name }}
|
||||
span.small-text {{ $t('editAvatar') }}
|
||||
a.nav-link.dropdown-item(@click.prevent='showInbox()') {{ $t('inbox') }}
|
||||
|
|
@ -180,7 +181,7 @@ div
|
|||
|
||||
.svg-icon {
|
||||
margin-right: 0px;
|
||||
color: inherit;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,11 +210,13 @@ import userIcon from 'assets/svg/user.svg';
|
|||
import logo from 'assets/svg/logo.svg';
|
||||
import InboxModal from './userMenu/inbox.vue';
|
||||
import notificationMenu from './notificationMenu';
|
||||
import creatorIntro from './creatorIntro';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
InboxModal,
|
||||
notificationMenu,
|
||||
creatorIntro,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
@ -239,6 +242,10 @@ export default {
|
|||
showInbox () {
|
||||
this.$root.$emit('show::modal', 'inbox-modal');
|
||||
},
|
||||
showAvatar () {
|
||||
this.$store.state.avatarEditorOptions.editingUser = true;
|
||||
this.$root.$emit('show::modal', 'avatar-modal');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template lang="pug">
|
||||
b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='true')
|
||||
.section.row.welcome-section(v-if='modalPage == 1')
|
||||
.section.row.welcome-section(v-if='modalPage === 1 && !editing')
|
||||
.col-6.offset-3.text-center
|
||||
h3(v-once) {{$t('welcomeTo')}}
|
||||
.svg-icon.logo(v-html='icons.logoPurple')
|
||||
|
|
@ -11,7 +11,7 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
|
|||
avatar(:member='user')
|
||||
|
||||
div(v-if='modalPage == 2')
|
||||
.section.row
|
||||
// @TODO Implement in V2 .section.row
|
||||
.col-12.text-center
|
||||
button.btn.btn-secondary(v-once) {{$t('randomize')}}
|
||||
.section.row.text-center.customize-menu
|
||||
|
|
@ -31,6 +31,10 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
|
|||
.menu-item(@click='changeTopPage("extra", "glasses")')
|
||||
.svg-icon(v-html='icons.accessoriesIcon')
|
||||
strong(v-once) {{$t('extra')}}
|
||||
.col-3
|
||||
.menu-item(@click='changeTopPage("backgrounds", "2017")')
|
||||
.svg-icon(v-html='icons.backgroundsIcon')
|
||||
strong(v-once) {{$t('backgrounds')}}
|
||||
.section.customize-section(v-if='activeTopPage === "body"')
|
||||
.row.sub-menu
|
||||
.col-2.offset-4.sub-menu-item(@click='changeSubPage("size")', :class='{active: activeSubPage === "size"}')
|
||||
|
|
@ -49,6 +53,8 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
|
|||
.slim_shirt_pink.option(@click='set({"preferences.shirt":"pink"})', :class='{active: user.preferences.shirt === "pink"}')
|
||||
.slim_shirt_white.option(@click='set({"preferences.shirt":"white"})', :class='{active: user.preferences.shirt === "white"}')
|
||||
.slim_shirt_yellow.option(@click='set({"preferences.shirt":"yellow"})', :class='{active: user.preferences.shirt === "yellow"}')
|
||||
.col-12
|
||||
.broad_shirt_convict.option(@click='set({"preferences.shirt":"convict"})', :class='{active: user.preferences.shirt === "convict"}')
|
||||
|
||||
.section.customize-section(v-if='activeTopPage === "skin"')
|
||||
.row.sub-menu
|
||||
|
|
@ -136,7 +142,34 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
|
|||
.hair_flower_5.option(@click='set({"preferences.hair.flower":5})', :class='{active: user.preferences.hair.flower === 5}')
|
||||
.hair_flower_6.option(@click='set({"preferences.hair.flower":6})', :class='{active: user.preferences.hair.flower === 6}')
|
||||
|
||||
.container.interests-section(v-if='modalPage == 3')
|
||||
.section.container.customize-section(v-if='activeTopPage === "backgrounds"')
|
||||
.row.sub-menu
|
||||
.col-3.text-center.sub-menu-item(@click='changeSubPage("2017")', :class='{active: activeSubPage === "2017"}')
|
||||
strong(v-once) 2017
|
||||
.col-3.text-center.sub-menu-item(@click='changeSubPage("2016")', :class='{active: activeSubPage === "2016"}')
|
||||
strong(v-once) 2016
|
||||
.col-3.text-center.sub-menu-item(@click='changeSubPage("2015")', :class='{active: activeSubPage === "2015"}')
|
||||
strong(v-once) 2015
|
||||
.col-3.text-center.sub-menu-item(@click='changeSubPage("2014")', :class='{active: activeSubPage === "2014"}')
|
||||
strong(v-once) 2014
|
||||
.row.customize-menu(v-for='(sets, key) in backgroundShopSetsByYear')
|
||||
div(v-for='set in sets', v-if='activeSubPage === key')
|
||||
h2 {{set.text}}
|
||||
div(v-if='showPlainBackgroundBlurb(set.identifier, set.items)') {{ $t('incentiveBackgroundsUnlockedWithCheckins') }}
|
||||
div(v-if='!ownsSet("background", set.items) && set.identifier !== "incentiveBackgrounds"')
|
||||
//+gemCost(7)
|
||||
button.btn.btn-primary(@click='unlock(setKeys("background", set.items))') {{ $t('unlockSet', {cost: 15}) }}
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
button.customize-option(v-for='bg in set.items',
|
||||
type='button',
|
||||
:class='[`background_${bg.key}`, backgroundLockedStatus(bg.key)]',
|
||||
@click='unlock("background." + bg.key)',
|
||||
:popover-title='bg.text',
|
||||
:popover='bg.notes',
|
||||
popover-trigger='mouseenter')
|
||||
i.glyphicon.glyphicon-lock(v-if='!user.purchased.background[bg.key]')
|
||||
|
||||
.container.interests-section(v-if='modalPage === 3 && !editing')
|
||||
.section.row
|
||||
.col-12.text-center
|
||||
h2 I want to work on:
|
||||
|
|
@ -187,7 +220,7 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
|
|||
.justin-message(v-if='modalPage > 1')
|
||||
p(v-once) {{$t('justinIntroMessage3')}}
|
||||
|
||||
.section.container.footer
|
||||
.section.container.footer(v-if='!editing')
|
||||
.row
|
||||
.col-3.offset-1.text-center
|
||||
div(v-if='modalPage > 1', @click='prev()')
|
||||
|
|
@ -339,7 +372,7 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
|
|||
.customize-section {
|
||||
background-color: #f9f9f9;
|
||||
padding-top: 1em;
|
||||
height: 250px;
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
.interests-section {
|
||||
|
|
@ -395,10 +428,12 @@ b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='tru
|
|||
</style>
|
||||
|
||||
<script>
|
||||
// @TODO: Wait for my other PR (login/register) to fix the background and hiding the header
|
||||
|
||||
import map from 'lodash/map';
|
||||
import get from 'lodash/get';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import avatar from './avatar';
|
||||
import { getBackgroundShopSets } from '../../common/script/libs/shops';
|
||||
import unlock from '../../common/script/ops/unlock';
|
||||
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
|
|
@ -407,6 +442,7 @@ import bodyIcon from 'assets/svg/body.svg';
|
|||
import accessoriesIcon from 'assets/svg/accessories.svg';
|
||||
import skinIcon from 'assets/svg/skin.svg';
|
||||
import hairIcon from 'assets/svg/hair.svg';
|
||||
import backgroundsIcon from 'assets/svg/backgrounds.svg';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -414,24 +450,50 @@ export default {
|
|||
bModal,
|
||||
},
|
||||
mounted () {
|
||||
this.$root.$emit('show::modal', 'avatar-modal');
|
||||
if (this.editing) this.modalPage = 2;
|
||||
},
|
||||
data () {
|
||||
let backgroundShopSets = getBackgroundShopSets();
|
||||
|
||||
// @TODO: add dates to backgrounds
|
||||
let backgroundShopSetsByYear = {
|
||||
2014: [],
|
||||
2015: [],
|
||||
2016: [],
|
||||
2017: [],
|
||||
};
|
||||
backgroundShopSets.forEach((set) => {
|
||||
let year = set.identifier.substr(set.identifier.length - 4);
|
||||
if (!backgroundShopSetsByYear[year]) return;
|
||||
backgroundShopSetsByYear[year].push(set);
|
||||
});
|
||||
|
||||
return {
|
||||
backgroundShopSets,
|
||||
backgroundShopSetsByYear,
|
||||
icons: Object.freeze({
|
||||
logoPurple,
|
||||
bodyIcon,
|
||||
accessoriesIcon,
|
||||
skinIcon,
|
||||
hairIcon,
|
||||
backgroundsIcon,
|
||||
}),
|
||||
modalPage: 1,
|
||||
activeTopPage: 'body',
|
||||
activeSubPage: 'size',
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
editing () {
|
||||
if (this.editing) this.modalPage = 2;
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
editing () {
|
||||
return this.$store.state.avatarEditorOptions.editingUser;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
prev () {
|
||||
|
|
@ -457,6 +519,73 @@ export default {
|
|||
this.$root.$emit('hide::modal', 'avatar-modal');
|
||||
this.$router.push('/');
|
||||
},
|
||||
showPlainBackgroundBlurb (identifier, set) {
|
||||
return identifier === 'incentiveBackgrounds' && !this.ownsSet('background', set);
|
||||
},
|
||||
ownsSet (type, set) {
|
||||
let setOwnedByUser = false;
|
||||
|
||||
for (let key in set) {
|
||||
let value = set[key];
|
||||
if (type === 'background') key = value.key;
|
||||
if (this.user.purchased[type][key]) setOwnedByUser = true;
|
||||
}
|
||||
// let setOwnedByUser = find(set, (value, key) => {
|
||||
// console.log(type)
|
||||
// if (type === 'background') key = value.key;
|
||||
// return this.user.purchased[type][key];
|
||||
// });
|
||||
|
||||
return Boolean(setOwnedByUser);
|
||||
},
|
||||
/**
|
||||
* For gem-unlockable preferences, (a) if owned, select preference (b) else, purchase
|
||||
* @param path: User.preferences <-> User.purchased maps like User.preferences.skin=abc <-> User.purchased.skin.abc.
|
||||
* Pass in this paramater as "skin.abc". Alternatively, pass as an array ["skin.abc", "skin.xyz"] to unlock sets
|
||||
*/
|
||||
async unlock (path) {
|
||||
let fullSet = path.indexOf(',') !== -1;
|
||||
let isBackground = Boolean(path.indexOf('background.'));
|
||||
|
||||
let cost;
|
||||
|
||||
if (isBackground) {
|
||||
cost = fullSet ? 3.75 : 1.75; // (Backgrounds) 15G per set, 7G per individual
|
||||
} else {
|
||||
cost = fullSet ? 1.25 : 0.5; // (Hair, skin, etc) 5G per set, 2G per individual
|
||||
}
|
||||
|
||||
let loginIncentives = ['background.blue', 'background.green', 'background.red', 'background.purple', 'background.yellow', 'background.violet'];
|
||||
if (loginIncentives.indexOf(path) === -1) {
|
||||
if (fullSet) {
|
||||
if (confirm(this.$t('purchaseFor', {cost: cost * 4})) !== true) return;
|
||||
// @TODO: implement gem modal
|
||||
// if (this.user.balance < cost) return $rootScope.openModal('buyGems');
|
||||
} else if (!get(this.user, `purchased.${path}`)) {
|
||||
if (confirm(this.$t('purchaseFor', {cost: cost * 4})) !== true) return;
|
||||
// @TODO: implement gem modal
|
||||
// if (this.user.balance < cost) return $rootScope.openModal('buyGems');
|
||||
}
|
||||
}
|
||||
// @TODO: Add when we implment the user calls
|
||||
// let response = await axios.post('/api/v3/user/unlock');
|
||||
unlock(this.user, {
|
||||
query: {
|
||||
path,
|
||||
},
|
||||
});
|
||||
},
|
||||
setKeys (type, _set) {
|
||||
return map(_set, (v, k) => {
|
||||
if (type === 'background') k = v.key;
|
||||
return `${type}.${k}`;
|
||||
}).join(',');
|
||||
},
|
||||
backgroundLockedStatus (bgKey) {
|
||||
let backgroundClass = 'background-locked';
|
||||
if (this.user.purchased.background[bgKey]) backgroundClass = 'background-unlocked';
|
||||
return backgroundClass;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template lang="pug">
|
||||
.row(v-if="group")
|
||||
group-form-modal
|
||||
invite-modal
|
||||
invite-modal(:group='this.group')
|
||||
start-quest-modal(:group='this.group')
|
||||
.col-8.standard-page
|
||||
.row
|
||||
|
|
@ -361,7 +361,6 @@ import quests from 'common/script/content/quests';
|
|||
import percent from 'common/script/libs/percent';
|
||||
import groupFormModal from './groupFormModal';
|
||||
import inviteModal from './inviteModal';
|
||||
import memberModal from '../members/memberModal';
|
||||
import chatMessage from '../chat/chatMessages';
|
||||
import groupChallenges from '../challenges/groupChallenges';
|
||||
|
||||
|
|
@ -388,7 +387,6 @@ export default {
|
|||
props: ['groupId'],
|
||||
components: {
|
||||
membersModal,
|
||||
memberModal,
|
||||
startQuestModal,
|
||||
bCollapse,
|
||||
bCard,
|
||||
|
|
@ -521,6 +519,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
showMemberModal () {
|
||||
this.$store.state.groupId = this.group._id;
|
||||
this.$root.$emit('show::modal', 'members-modal');
|
||||
},
|
||||
async sendMessage () {
|
||||
|
|
|
|||
|
|
@ -54,8 +54,10 @@ import { mapState } from 'client/libs/store';
|
|||
import filter from 'lodash/filter';
|
||||
import map from 'lodash/map';
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
import notifications from 'client/mixins/notifications';
|
||||
|
||||
export default {
|
||||
mixins: [notifications],
|
||||
props: ['group'],
|
||||
data () {
|
||||
return {
|
||||
|
|
@ -72,8 +74,9 @@ export default {
|
|||
return this.user.profile.name;
|
||||
},
|
||||
sendInviteText () {
|
||||
if (!this.group) return 'Send Invites';
|
||||
return this.group.sendInviteText;
|
||||
return 'Send Invites';
|
||||
// if (!this.group) return 'Send Invites';
|
||||
// return this.group.sendInviteText;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -97,38 +100,41 @@ export default {
|
|||
|
||||
this.inviteByMethod(inviteMethod);
|
||||
},
|
||||
// inviteByMethod (inviteMethod) {
|
||||
// let invitationDetails;
|
||||
//
|
||||
// if (inviteMethod === 'email') {
|
||||
// let emails = this.getEmails();
|
||||
// invitationDetails = { inviter: this.inviter, emails };
|
||||
// } else if (inviteMethod === 'uuid') {
|
||||
// let uuids = this.getOnlyUuids();
|
||||
// invitationDetails = { uuids };
|
||||
// } else {
|
||||
// return alert('Invalid invite method.');
|
||||
// }
|
||||
async inviteByMethod (inviteMethod) {
|
||||
let invitationDetails;
|
||||
|
||||
// @TODO: Add dispatch
|
||||
// Groups.Group.invite(this.group._id, invitationDetails)
|
||||
// .then(function () {
|
||||
// let invitesSent = invitationDetails.emails || invitationDetails.uuids;
|
||||
// let invitationString = invitesSent.length > 1 ? 'invitationsSent' : 'invitationSent';
|
||||
//
|
||||
// Notification.text(window.env.t(invitationString));
|
||||
//
|
||||
// _resetInvitees();
|
||||
//
|
||||
// if (this.group.type === 'party') {
|
||||
// $rootScope.hardRedirect('/#/options/groups/party');
|
||||
// } else {
|
||||
// $rootScope.hardRedirect('/#/options/groups/guilds/' + this.group._id);
|
||||
// }
|
||||
// }, function(){
|
||||
// _resetInvitees();
|
||||
// });
|
||||
// },
|
||||
if (inviteMethod === 'email') {
|
||||
let emails = this.getEmails();
|
||||
invitationDetails = { inviter: this.inviter, emails };
|
||||
} else if (inviteMethod === 'uuid') {
|
||||
let uuids = this.getOnlyUuids();
|
||||
invitationDetails = { uuids };
|
||||
} else {
|
||||
return alert('Invalid invite method.');
|
||||
}
|
||||
|
||||
await this.$store.dispatch('guilds:invite', {
|
||||
invitationDetails,
|
||||
groupId: this.group._id,
|
||||
});
|
||||
|
||||
let invitesSent = invitationDetails.emails || invitationDetails.uuids;
|
||||
let invitationString = invitesSent.length > 1 ? 'invitationsSent' : 'invitationSent';
|
||||
|
||||
this.text(this.$t(invitationString));
|
||||
|
||||
// @TODO: This function didn't make it over this.resetInvitees();
|
||||
|
||||
// @TODO: Sync group invites?
|
||||
// if (this.group.type === 'party') {
|
||||
// this.$router.push('//party');
|
||||
// } else {
|
||||
// this.$router.push(`/groups/guilds/${this.group._id}`);
|
||||
// }
|
||||
this.$root.$emit('hide:modal', 'invite-modal');
|
||||
// @TODO: error?
|
||||
// _resetInvitees();
|
||||
},
|
||||
getOnlyUuids () {
|
||||
let uuids = map(this.invitees, 'uuid');
|
||||
let filteredUuids = filter(uuids, (id) => {
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ div
|
|||
</style>
|
||||
|
||||
<script>
|
||||
// @TODO: Move this under members directory
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
import bDropdown from 'bootstrap-vue/lib/components/dropdown';
|
||||
import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
|
||||
|
|
@ -158,15 +159,16 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
async getMembers () {
|
||||
if (this.group._id) {
|
||||
let groupId = this.group._id || this.$store.state.groupId;
|
||||
if (groupId) {
|
||||
let members = await this.$store.dispatch('members:getGroupMembers', {
|
||||
groupId: this.group._id,
|
||||
groupId,
|
||||
includeAllPublicFields: true,
|
||||
});
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
if (this.$store.state.viewingMembers) this.members = this.$store.state.viewingMembers;
|
||||
if (this.$store.state.viewingMembers.length > 1) this.members = this.$store.state.viewingMembers;
|
||||
},
|
||||
async clickMember (uid, forceShow) {
|
||||
let user = this.$store.state.user.data;
|
||||
|
|
|
|||
|
|
@ -1,32 +1,33 @@
|
|||
<template lang="pug">
|
||||
.d-flex.member-details(:class="{ condensed, expanded }", @click='showMemberModal()')
|
||||
avatar(:member="member",
|
||||
@click.native="$emit('click')",
|
||||
@mouseover.native="$emit('onHover')",
|
||||
@mouseout.native="$emit('onHover')",
|
||||
)
|
||||
member-modal(:profile='member')
|
||||
.member-stats
|
||||
h3.character-name
|
||||
| {{member.profile.name}}
|
||||
.is-buffed(v-if="isBuffed")
|
||||
.svg-icon(v-html="icons.buff")
|
||||
span.small-text.character-level {{ characterLevel }}
|
||||
.progress-container.d-flex
|
||||
.svg-icon(v-html="icons.health")
|
||||
.progress
|
||||
.progress-bar.bg-health(:style="{width: `${percent(member.stats.hp, MAX_HEALTH)}%`}")
|
||||
span.small-text {{member.stats.hp | round}} / {{MAX_HEALTH}}
|
||||
.progress-container.d-flex
|
||||
.svg-icon(v-html="icons.experience")
|
||||
.progress
|
||||
.progress-bar.bg-experience(:style="{width: `${percent(member.stats.exp, toNextLevel)}%`}")
|
||||
span.small-text {{member.stats.exp | round}} / {{toNextLevel}}
|
||||
.progress-container.d-flex(v-if="hasClass")
|
||||
.svg-icon(v-html="icons.mana")
|
||||
.progress
|
||||
.progress-bar.bg-mana(:style="{width: `${percent(member.stats.mp, maxMP)}%`}")
|
||||
span.small-text {{member.stats.mp | round}} / {{maxMP}}
|
||||
div
|
||||
profile
|
||||
.d-flex.member-details(:class="{ condensed, expanded }", @click='showMemberModal()')
|
||||
avatar(:member="member",
|
||||
@click.native="$emit('click')",
|
||||
@mouseover.native="$emit('onHover')",
|
||||
@mouseout.native="$emit('onHover')",
|
||||
)
|
||||
.member-stats
|
||||
h3.character-name
|
||||
| {{member.profile.name}}
|
||||
.is-buffed(v-if="isBuffed")
|
||||
.svg-icon(v-html="icons.buff")
|
||||
span.small-text.character-level {{ characterLevel }}
|
||||
.progress-container.d-flex
|
||||
.svg-icon(v-html="icons.health")
|
||||
.progress
|
||||
.progress-bar.bg-health(:style="{width: `${percent(member.stats.hp, MAX_HEALTH)}%`}")
|
||||
span.small-text {{member.stats.hp | round}} / {{MAX_HEALTH}}
|
||||
.progress-container.d-flex
|
||||
.svg-icon(v-html="icons.experience")
|
||||
.progress
|
||||
.progress-bar.bg-experience(:style="{width: `${percent(member.stats.exp, toNextLevel)}%`}")
|
||||
span.small-text {{member.stats.exp | round}} / {{toNextLevel}}
|
||||
.progress-container.d-flex(v-if="hasClass")
|
||||
.svg-icon(v-html="icons.mana")
|
||||
.progress
|
||||
.progress-bar.bg-mana(:style="{width: `${percent(member.stats.mp, maxMP)}%`}")
|
||||
span.small-text {{member.stats.mp | round}} / {{maxMP}}
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
@ -170,7 +171,7 @@
|
|||
<script>
|
||||
import Avatar from './avatar';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import memberModal from './members/memberModal';
|
||||
import profile from './userMenu/profile';
|
||||
|
||||
import { toNextLevel } from '../../common/script/statHelpers';
|
||||
import statsComputed from '../../common/script/libs/statsComputed';
|
||||
|
|
@ -184,7 +185,7 @@ import manaIcon from 'assets/svg/mana.svg';
|
|||
export default {
|
||||
components: {
|
||||
Avatar,
|
||||
memberModal,
|
||||
profile,
|
||||
},
|
||||
props: {
|
||||
member: {
|
||||
|
|
@ -212,6 +213,10 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
percent,
|
||||
showMemberModal () {
|
||||
// @TODO: set viewing users in $store?
|
||||
this.$root.$emit('show::modal', 'profile');
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
|
|
@ -234,10 +239,6 @@ export default {
|
|||
hasClass () {
|
||||
return this.$store.getters['members:hasClass'](this.member);
|
||||
},
|
||||
showMemberModal () {
|
||||
// @TODO: set viewing users in $store?
|
||||
this.$root.$emit('show::modal', 'member-detail-modal');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,143 +0,0 @@
|
|||
<template lang="pug">
|
||||
b-modal#member-detail-modal(title="Empty", size='lg')
|
||||
.modal-header
|
||||
h4
|
||||
span {{profile.profile.name}}
|
||||
// @TODO span(v-if='contribText && profile.contributor.level') - {{contribText(profile.contributor, profile.backer)}}
|
||||
.modal-body
|
||||
.container-fluid
|
||||
.row
|
||||
.col-md-6
|
||||
img.img-renderiv-auto(v-if='profile.profile.imageUrl', :src='profile.profile.imageUrl')
|
||||
markdown(v-if='profile.profile.blurb', text='profile.profile.blurb')
|
||||
ul.muted.list-unstyled(v-if='profile.auth.timestamps')
|
||||
li {{profile._id}}
|
||||
li(v-if='profile.auth.timestamps.created')
|
||||
|
|
||||
| {{ $t('memberSince') }}
|
||||
|
|
||||
// @TODO | {{profile.auth.timestamps.created | date:user.preferences.dateFormat}} -
|
||||
li(v-if='profile.auth.timestamps.loggedin')
|
||||
|
|
||||
| {{ $t('lastLoggedIn') }}
|
||||
|
|
||||
// @TODO | {{profile.auth.timestamps.loggedin | date:user.preferences.dateFormat}} -
|
||||
h3 {{ $t('stats') }}
|
||||
// @TODO: Figure out why this isn't showing up in front page
|
||||
// @TODO .label.label-info {{ {warrior:env.t("warrior"), wizard:env.t("mage"), rogue:env.t("rogue"), healer:env.t("healer")}[profile.stats.class] }}
|
||||
// include ../profiles/stats_all
|
||||
.col-md-6
|
||||
.row
|
||||
//@TODO: +herobox()
|
||||
.row
|
||||
h3 {{ $t('achievements') }}
|
||||
//include ../profiles/achievements
|
||||
.modal-footer
|
||||
.btn-group.pull-left(v-if='user')
|
||||
button.btn.btn-md.btn-default(v-if='user.inbox.blocks.indexOf(profile._id) !== -1', :tooltip="$t('unblock')", @click="User.blockUser({params:{uuid:profile._id}})", tooltip-placement='right')
|
||||
span.glyphicon.glyphicon-plus
|
||||
button.btn.btn-md.btn-default(v-if='profile._id != user._id && !profile.contributor.admin && !(user.inbox.blocks | contains:profile._id)', tooltip {{ $t('block') }}, @click="User.blockUser({params:{uuid:profile._id}})", tooltip-placement='right')
|
||||
span.glyphicon.glyphicon-ban-circle
|
||||
button.btn.btn-md.btn-default(:tooltip="$t('sendPM')", @click="openModal('private-message',{controller:'MemberModalCtrl'})", tooltip-placement='right')
|
||||
span.glyphicon.glyphicon-envelope
|
||||
button.btn.btn-md.btn-default(:tooltip="$t('sendGift')", @click="openModal('send-gift',{controller:'MemberModalCtrl'})", tooltip-placement='right')
|
||||
span.glyphicon.glyphicon-gift
|
||||
button.btn.btn-default(@click='close()') {{ $t('close') }}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
import moment from 'moment';
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
// @TODO: We should probably use a store. Only view one member at a time?
|
||||
props: ['profile'],
|
||||
data () {
|
||||
return {
|
||||
// @TODO: We don't send subscriptions so the structure has changed in the back. Update this when we update the views.
|
||||
gift: {
|
||||
type: 'gems',
|
||||
gems: {amount: 0, fromBalance: true},
|
||||
subscription: {key: ''},
|
||||
message: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
mounted () {
|
||||
// @TODO: This.$store.selectmember
|
||||
// if (member) {
|
||||
// this.profile = member;
|
||||
//
|
||||
// this.achievements = Shared.achievements.getAchievementsForProfile(this.profile);
|
||||
// this.achievPopoverPlacement = 'left';
|
||||
// this.achievAppendToBody = 'false'; // append-to-body breaks popovers in modal windows
|
||||
// }
|
||||
},
|
||||
methods: {
|
||||
timestamp (timestamp) {
|
||||
return moment(timestamp).format(this.user.preferences.dateFormat.toUpperCase());
|
||||
},
|
||||
// @TODO: create mixin for stats: this.statCalc = Stats;
|
||||
// @TODO: create mixin or library for constume functions this.costume = Costume;
|
||||
keyDownListener (e) {
|
||||
if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
|
||||
this.sendPrivateMessage(this.profile._id, this._message);
|
||||
}
|
||||
},
|
||||
// @TODO: Inbox?
|
||||
sendPrivateMessage (uuid, message) {
|
||||
if (!message) return;
|
||||
|
||||
// Members.sendPrivateMessage(message, uuid)
|
||||
// .then(function (response) {
|
||||
// Notification.text(window.env.t('messageSentAlert'));
|
||||
// $rootScope.User.sync();
|
||||
// this.$close();
|
||||
// });
|
||||
},
|
||||
async sendGift (uuid) {
|
||||
await this.$store.dispatch('members:transferGems', {
|
||||
message: this.gift.message,
|
||||
toUserId: uuid,
|
||||
gemAmount: this.gift.gems.amount,
|
||||
});
|
||||
|
||||
// @TODO: Notification.text(this.$t('sentGems'));
|
||||
// @TODO: What needs to be synced? $rootScope.User.sync();
|
||||
this.close();
|
||||
},
|
||||
async reportAbuse (reporter, message, groupId) {
|
||||
let response = await this.$store.dispatch('chat:flag', {
|
||||
groupId,
|
||||
chatId: message.id,
|
||||
});
|
||||
|
||||
message.flags = response.flags;
|
||||
message.flagCount = response.flagCount;
|
||||
// @TODO: Notification.text(this.$t('abuseReported'));
|
||||
this.close();
|
||||
},
|
||||
async clearFlagCount (message, groupId) {
|
||||
await this.$store.dispatch('chat:clearFlagCount', {
|
||||
groupId,
|
||||
chatId: message.id,
|
||||
});
|
||||
|
||||
message.flagCount = 0;
|
||||
// @TODO: Notification.text("Flags cleared");
|
||||
this.close();
|
||||
},
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'member-detail-modal');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -6,27 +6,29 @@
|
|||
.dropdown-menu.dropdown-menu-right.user-dropdown
|
||||
h4.dropdown-item(v-if='!hasNoNotifications()') {{ $t('notifications') }}
|
||||
h4.dropdown-item.toolbar-notifs-no-messages(v-if='hasNoNotifications()') {{ $t('noNotifications') }}
|
||||
a.dropdown-item(v-if='user.purchased.plan.mysteryItems.length', @click='$state.go("options.inventory.drops"); ')
|
||||
a.dropdown-item(v-if='user.purchased.plan.mysteryItems.length', @click='go("/inventory/items")')
|
||||
span.glyphicon.glyphicon-gift
|
||||
span {{ $t('newSubscriberItem') }}
|
||||
a.dropdown-item(v-for='party in user.invitations.parties', ui-sref='options.social.party')
|
||||
a.dropdown-item(v-for='party in user.invitations.parties', @click='go("/party")')
|
||||
span.glyphicon.glyphicon-user
|
||||
span {{ $t('invitedTo', {name: party.name}) }}
|
||||
a.dropdown-item(v-if='user.flags.cardReceived', @click='$state.go("options.inventory.drops"); ')
|
||||
a.dropdown-item(v-if='user.flags.cardReceived', @click='go("/inventory/items")')
|
||||
span.glyphicon.glyphicon-envelope
|
||||
span {{ $t('cardReceived') }}
|
||||
a.dropdown-item(@click='clearCards()', :popover="$t('clear')", popover-placement='right', popover-trigger='mouseenter',popover-append-to-body='true')
|
||||
a.dropdown-item(v-for='guild in user.invitations.guilds', ui-sref='options.social.guilds.public')
|
||||
a.dropdown-item(@click='clearCards()', :popover="$t('clear')",
|
||||
popover-placement='right', popover-trigger='mouseenter', popover-append-to-body='true')
|
||||
a.dropdown-item(v-for='guild in user.invitations.guilds', @click='go("/groups/discovery")')
|
||||
span.glyphicon.glyphicon-user
|
||||
span {{ $t('invitedTo', {name: guild.name}) }}
|
||||
a.dropdown-item(v-if='user.flags.classSelected && !user.preferences.disableClasses && user.stats.points', ui-sref='options.profile.stats')
|
||||
a.dropdown-item(v-if='user.flags.classSelected && !user.preferences.disableClasses && user.stats.points',
|
||||
@click='go("/user/profile")')
|
||||
span.glyphicon.glyphicon-plus-sign
|
||||
span {{ $t('haveUnallocated', {points: user.stats.points}) }}
|
||||
a.dropdown-item(v-for='(k,v) in user.newMessages', v-if='v.value', @click='(k === party._id || k === user.party._id) ? $state.go("options.social.party") : $state.go("options.social.guilds.detail",{gid:k}); ')
|
||||
a.dropdown-item(v-for='(k,v) in user.newMessages', v-if='v.value', @click='navigateToGroup(k)')
|
||||
span.glyphicon.glyphicon-comment
|
||||
span {{v.name}}
|
||||
a.dropdown-item(@click='clearMessages(k)', :popover="$t('clear')", popover-placement='right', popover-trigger='mouseenter',popover-append-to-body='true')
|
||||
a.dropdown-item(v-for='notification in user.groupNotifications', @click='viewGroupApprovalNotification(notification, $index, true)')
|
||||
a.dropdown-item(@click='clearMessages(k)', :popover="$t('clear')", popover-placement='right', popover-trigger='mouseenter',popover-append-to-body='true')
|
||||
a.dropdown-item(v-for='(notification, index) in user.groupNotifications', @click='viewGroupApprovalNotification(notification, index, true)')
|
||||
span(:class="groupApprovalNotificationIcon(notification)")
|
||||
span
|
||||
| {{notification.data.message}}
|
||||
|
|
@ -225,7 +227,7 @@ export default {
|
|||
// @TODO: USe notifications: User.readNotification(notification.id);
|
||||
this.user.groupNotifications.splice(index, 1);
|
||||
return navigate; // @TODO: remove
|
||||
// @TODO: this.$route.go if (navigate) $state.go('options.social.guilds.detail', {gid: notification.data.groupId});
|
||||
// @TODO: this.$route.go if (navigate) go('options.social.guilds.detail', {gid: notification.data.groupId});
|
||||
},
|
||||
groupApprovalNotificationIcon (notification) {
|
||||
if (notification.type === 'GROUP_TASK_APPROVAL') {
|
||||
|
|
@ -234,6 +236,16 @@ export default {
|
|||
return 'glyphicon glyphicon-ok-sign';
|
||||
}
|
||||
},
|
||||
go (path) {
|
||||
this.$route.push(path);
|
||||
},
|
||||
navigateToGroup (key) {
|
||||
if (key === this.party._id || key === this.user.party._id) {
|
||||
this.go('/party');
|
||||
return;
|
||||
}
|
||||
this.go(`/groups/guild/${key}`);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,77 @@
|
|||
<template lang="pug">
|
||||
div
|
||||
welcome-modal
|
||||
new-stuff
|
||||
death
|
||||
low-health
|
||||
level-up
|
||||
choose-class
|
||||
testing
|
||||
testingletiant
|
||||
rebirth-enabled
|
||||
drops-enabled
|
||||
contributor
|
||||
won-challenge
|
||||
ultimate-gear
|
||||
streak
|
||||
rebirth
|
||||
joined-guild
|
||||
joined-challenge
|
||||
invited-friend
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import moment from 'moment';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
import notifications from 'client/mixins/notifications';
|
||||
|
||||
import welcomeModal from './achievements/welcome';
|
||||
import newStuff from './achievements/newStuff';
|
||||
import death from './achievements/death';
|
||||
import lowHealth from './achievements/lowHealth';
|
||||
import levelUp from './achievements/levelUp';
|
||||
import chooseClass from './achievements/chooseClass';
|
||||
import armoireEmpty from './achievements/armoireEmpty';
|
||||
import questCompleted from './achievements/questCompleted';
|
||||
import questInvitation from './achievements/questInvitation';
|
||||
import testing from './achievements/testing';
|
||||
import testingletiant from './achievements/testingletiant';
|
||||
import rebirthEnabled from './achievements/rebirthEnabled';
|
||||
import dropsEnabled from './achievements/dropsEnabled';
|
||||
import contributor from './achievements/contributor';
|
||||
import invitedFriend from './achievements/invitedFriend';
|
||||
import joinedChallenge from './achievements/joinedChallenge';
|
||||
import joinedGuild from './achievements/joinedGuild';
|
||||
import rebirth from './achievements/rebirth';
|
||||
import streak from './achievements/streak';
|
||||
import ultimateGear from './achievements/ultimateGear';
|
||||
import wonChallenge from './achievements/wonChallenge';
|
||||
|
||||
export default {
|
||||
mixins: [notifications],
|
||||
components: {
|
||||
wonChallenge,
|
||||
ultimateGear,
|
||||
streak,
|
||||
rebirth,
|
||||
joinedGuild,
|
||||
joinedChallenge,
|
||||
invitedFriend,
|
||||
welcomeModal,
|
||||
newStuff,
|
||||
death,
|
||||
lowHealth,
|
||||
levelUp,
|
||||
chooseClass,
|
||||
armoireEmpty,
|
||||
questCompleted,
|
||||
questInvitation,
|
||||
testing,
|
||||
testingletiant,
|
||||
rebirthEnabled,
|
||||
dropsEnabled,
|
||||
contributor,
|
||||
},
|
||||
data () {
|
||||
// Levels that already display modals and should not trigger generic Level Up
|
||||
|
|
@ -71,21 +132,26 @@ export default {
|
|||
invitedToQuest () {
|
||||
return this.user.party.quest.RSVPNeeded && !this.user.party.quest.completed;
|
||||
},
|
||||
userDailies () {
|
||||
return this.$store.state.tasks.data.dailys;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
baileyShouldShow () {
|
||||
// @TODO: this.openModal('newStuff', {size:'lg'});
|
||||
this.$root.$emit('show:modal', 'new-stuff');
|
||||
},
|
||||
userHp (after, before) {
|
||||
if (after <= 0) {
|
||||
this.playSound('Death');
|
||||
// @TODO: this.openModal('death', {keyboard:false, backdrop:'static'});
|
||||
this.$root.$emit('show:modal', 'death');
|
||||
// @TODO: {keyboard:false, backdrop:'static'}
|
||||
} else if (after <= 30 && !this.user.flags.warnedLowHealth) {
|
||||
// @TODO: this.openModal('lowHealth', {keyboard:false, backdrop:'static', controller:'UserCtrl', track:'Health Warning'});
|
||||
this.$root.$emit('show:modal', 'low-health');
|
||||
// @TODO: {keyboard:false, backdrop:'static', controller:'UserCtrl', track:'Health Warning'}
|
||||
}
|
||||
if (after === before) return;
|
||||
if (this.user.stats.lvl === 0) return;
|
||||
// @TODO: Notification.hp(after - before, 'hp');
|
||||
this.hp(after - before, 'hp');
|
||||
|
||||
// @TODO: I am pretty sure we no long need this with $store
|
||||
// this.$broadcast('syncPartyRequest', {
|
||||
|
|
@ -98,7 +164,7 @@ export default {
|
|||
userExp (after, before) {
|
||||
if (after === before) return;
|
||||
if (this.user.stats.lvl === 0) return;
|
||||
// @TODO: Notification.exp(after - before);
|
||||
this.exp(after - before);
|
||||
},
|
||||
userGp (after, before) {
|
||||
if (after === before) return;
|
||||
|
|
@ -109,32 +175,33 @@ export default {
|
|||
if (this.user._tmp) {
|
||||
bonus = this.user._tmp.streakBonus || 0;
|
||||
}
|
||||
// @TODO: Notification.gp(money, bonus || 0);
|
||||
this.gp(money, bonus || 0);
|
||||
|
||||
// Append Bonus
|
||||
if (money > 0 && Boolean(bonus)) {
|
||||
if (bonus < 0.01) bonus = 0.01;
|
||||
// @TODO: Notification.text("+ " + Notification.coins(bonus) + ' ' + window.env.t('streakCoins'));
|
||||
this.text(`+ ${Notification.coins(bonus)} ${this.$t('streakCoins')}`);
|
||||
delete this.user._tmp.streakBonus;
|
||||
}
|
||||
},
|
||||
userMp (after, before) {
|
||||
if (after === before) return;
|
||||
if (!this.user.flags.classSelected || this.user.preferences.disableClasses) return;
|
||||
// let mana = after - before;
|
||||
// @TODO: Notification.mp(mana);
|
||||
let mana = after - before;
|
||||
this.mp(mana);
|
||||
},
|
||||
userLvl (after, before) {
|
||||
if (after <= before) return;
|
||||
// @TODO: Notification.lvl();
|
||||
this.lvl();
|
||||
this.playSound('Level_Up');
|
||||
if (this.user._tmp && this.user._tmp.drop && this.user._tmp.drop.type === 'Quest') return;
|
||||
if (this.unlockLevels[`${after}`]) return;
|
||||
// @TODO: if (!this.user.preferences.suppressModals.levelUp) this.openModal('levelUp', {controller:'UserCtrl', size:'sm'});
|
||||
if (!this.user.preferences.suppressModals.levelUp) this.$root.$emit('show:modal', 'level-up');
|
||||
},
|
||||
userClassSelect (after) {
|
||||
if (!after) return;
|
||||
// @TODO: this.openModal('chooseClass', {controller:'UserCtrl', keyboard:false, backdrop:'static'});
|
||||
this.$root.$emit('show::modal', 'choose-class');
|
||||
// @TODO: {controller:'UserCtrl', keyboard:false, backdrop:'static'}
|
||||
},
|
||||
userNotifications (after) {
|
||||
if (!this.user._wrapped) return;
|
||||
|
|
@ -146,15 +213,18 @@ export default {
|
|||
},
|
||||
armoireEmpty (after, before) {
|
||||
if (after === before || after === false) return;
|
||||
// @TODO: this.openModal('armoireEmpty');
|
||||
this.$root.$emit('show::modal', 'armoire-empty');
|
||||
},
|
||||
questCompleted (after) {
|
||||
if (!after) return;
|
||||
// @TODO: this.openModal('questCompleted', {controller:'InventoryCtrl'});
|
||||
this.$root.$emit('show::modal', 'quest-completed');
|
||||
},
|
||||
invitedToQuest (after) {
|
||||
if (after !== true) return;
|
||||
// @TODO: this.openModal('questInvitation', {controller:'PartyCtrl'});
|
||||
this.$root.$emit('show::modal', 'quest-invitation');
|
||||
},
|
||||
userDailies () {
|
||||
this.runYesterDailies();
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
|
|
@ -174,9 +244,10 @@ export default {
|
|||
// let userDayStart = moment().startOf('day').add({ hours: this.user.preferences.dayStart });
|
||||
|
||||
if (!this.user.needsCron) return;
|
||||
let dailys = this.user.dailys;
|
||||
|
||||
if (!this.appLoaded) return;
|
||||
let dailys = this.$store.state.tasks.data.dailys;
|
||||
|
||||
// @TODO: How do we check this now? if (!this.appLoaded) return;
|
||||
|
||||
this.isRunningYesterdailies = true;
|
||||
|
||||
|
|
@ -267,59 +338,57 @@ export default {
|
|||
// @TODO: Use factory function instead
|
||||
switch (notification.type) {
|
||||
case 'GUILD_PROMPT':
|
||||
// @TODO: I'm pretty sure we can find better names for these
|
||||
if (notification.data.textletiant === -1) {
|
||||
// @TODO: this.openModal('testing');
|
||||
this.$root.$emit('show::modal', 'testing');
|
||||
} else {
|
||||
// @TODO: this.openModal('testingletiant');
|
||||
this.$root.$emit('show::modal', 'testingletiant');
|
||||
}
|
||||
break;
|
||||
case 'DROPS_ENABLED':
|
||||
// @TODO: this.openModal('dropsEnabled');
|
||||
this.$root.$emit('show::modal', 'drops-enabled');
|
||||
break;
|
||||
case 'REBIRTH_ENABLED':
|
||||
// @TODO: this.openModal('rebirthEnabled');
|
||||
this.$root.$emit('show::modal', 'rebirth-enabled');
|
||||
break;
|
||||
case 'WON_CHALLENGE':
|
||||
// @TODO:
|
||||
// User.sync().then( function() {
|
||||
// Achievement.displayAchievement('wonChallenge');
|
||||
// });
|
||||
this.$root.$emit('show::modal', 'won-challenge');
|
||||
break;
|
||||
case 'STREAK_ACHIEVEMENT':
|
||||
// @TODO: Notification.streak(this.user.achievements.streak);
|
||||
this.streak(this.user.achievements.streak);
|
||||
this.playSound('Achievement_Unlocked');
|
||||
if (!this.user.preferences.suppressModals.streak) {
|
||||
// @TODO: Achievement.displayAchievement('streak', {size: 'md'});
|
||||
this.$root.$emit('show::modal', 'streak');
|
||||
}
|
||||
break;
|
||||
case 'ULTIMATE_GEAR_ACHIEVEMENT':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('ultimateGear', {size: 'md'});
|
||||
this.$root.$emit('show::modal', 'ultimate-gear');
|
||||
break;
|
||||
case 'REBIRTH_ACHIEVEMENT':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('rebirth');
|
||||
this.$root.$emit('show::modal', 'rebirth');
|
||||
break;
|
||||
case 'GUILD_JOINED_ACHIEVEMENT':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('joinedGuild', {size: 'md'});
|
||||
this.$root.$emit('show::modal', 'joined-guild');
|
||||
break;
|
||||
case 'CHALLENGE_JOINED_ACHIEVEMENT':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('joinedChallenge', {size: 'md'});
|
||||
this.$root.$emit('show::modal', 'joined-challenge');
|
||||
break;
|
||||
case 'INVITED_FRIEND_ACHIEVEMENT':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('invitedFriend', {size: 'md'});
|
||||
this.$root.$emit('show::modal', 'invited-friend');
|
||||
break;
|
||||
case 'NEW_CONTRIBUTOR_LEVEL':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('contributor', {size: 'md'});
|
||||
this.$root.$emit('show::modal', 'contributor');
|
||||
break;
|
||||
case 'CRON':
|
||||
if (notification.data) {
|
||||
// @TODO: if (notification.data.hp) Notification.hp(notification.data.hp, 'hp');
|
||||
// @TODO: if (notification.data.mp) Notification.mp(notification.data.mp);
|
||||
if (notification.data.hp) this.hp(notification.data.hp, 'hp');
|
||||
if (notification.data.mp) this.mp(notification.data.mp);
|
||||
}
|
||||
break;
|
||||
case 'GROUP_TASK_APPROVAL':
|
||||
|
|
@ -383,7 +452,7 @@ export default {
|
|||
});
|
||||
|
||||
// Show notification of task approved
|
||||
// @TODO: Notification.markdown(scoreTaskNotification[i].data.message);
|
||||
this.markdown(scoreTaskNotification[i].data.message);
|
||||
}
|
||||
|
||||
// Score approved tasks
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ b-modal#profile(title="Profile", size='lg', :hide-footer="true")
|
|||
.row
|
||||
.col-6.offset-3.text-center.nav
|
||||
.nav-item(@click='selectedPage = "profile"', :class="{active: selectedPage === 'profile'}") Profile
|
||||
.nav-item(@click='selectedPage = "achievements"', :class="{active: selectedPage === 'achievements'}") Achievements
|
||||
.nav-item(@click='selectedPage = "stats"', :class="{active: selectedPage === 'stats'}") Stats
|
||||
.nav-item(@click='selectedPage = "achievements"', :class="{active: selectedPage === 'achievements'}") Achievements
|
||||
.standard-page(v-show='selectedPage === "profile"')
|
||||
.row
|
||||
.col-8
|
||||
|
|
@ -94,19 +94,92 @@ b-modal#profile(title="Profile", size='lg', :hide-footer="true")
|
|||
span {{ content.quests[k].text() }}
|
||||
span {{ value }}
|
||||
.standard-page(v-show='selectedPage === "stats"')
|
||||
h1 Stats
|
||||
.row
|
||||
.col-6
|
||||
h2.text-center Equipment
|
||||
.well.row
|
||||
.col-4
|
||||
// user.items.gear.equipped
|
||||
.well
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Eyewear
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Head Gear
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Head Access.
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Back Access.
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Armor
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Body Access.
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Main-Hand
|
||||
.col-4.item-wrapper
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Off-Hand
|
||||
.col-6
|
||||
h2.text-center Costume
|
||||
// user.items.gear.costume
|
||||
.well
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Eyewear
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Head Gear
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Head Access.
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Back Access.
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Armor
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Body Access.
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Main-Hand
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Background {{ user.preferences.background }}
|
||||
.col-4.item-wrapper
|
||||
.box
|
||||
h3 Off-Hand
|
||||
.row
|
||||
.col-6
|
||||
h2.text-center Pet
|
||||
h2.text-center(v-once) {{ $t('pets') }}
|
||||
ul
|
||||
li(ng-if='user.items.currentPet')
|
||||
| {{ $t('activePet') }}:
|
||||
| {{ formatAnimal(user.items.currentPet, 'pet') }}
|
||||
li
|
||||
| {{ $t('petsFound') }}:
|
||||
| {{ totalCount(user.items.pets) }}
|
||||
li
|
||||
| {{ $t('beastMasterProgress') }}:
|
||||
| {{ beastMasterProgress(user.items.pets) }}
|
||||
.col-6
|
||||
h2.text-center Mount
|
||||
h2.text-center(v-once) {{ $t('mounts') }}
|
||||
ul
|
||||
li(v-if='user.items.currentMount')
|
||||
| {{ $t('activeMount') }}:
|
||||
| {{ formatAnimal(user.items.currentMount, 'mount') }}
|
||||
li
|
||||
| {{ $t('mountsTamed') }}:
|
||||
| {{ totalCount(user.items.mounts) }}
|
||||
li
|
||||
| {{ $t('mountMasterProgress') }}:
|
||||
| {{ mountMasterProgress(user.items.mounts) }}
|
||||
.row#attributes
|
||||
hr.col-12
|
||||
h2.col-12 Attributes
|
||||
|
|
@ -133,64 +206,7 @@ b-modal#profile(title="Profile", size='lg', :hide-footer="true")
|
|||
li
|
||||
strong Buffs:
|
||||
| {{user.stats.buffs[stat]}}
|
||||
|
||||
.row
|
||||
.col-4
|
||||
div
|
||||
h3 Basics
|
||||
ul
|
||||
li Health: {{user.stats.hp}}/{{user.stats.maxHealth}}
|
||||
li Mana: {{user.stats.mp}}/{{user.stats.maxMP}}
|
||||
li Gold: {{user.stats.gp}}
|
||||
li Level: {{user.stats.lvl}}
|
||||
li Experience: {{user.stats.exp}}
|
||||
|
||||
div(v-if='user.flags.itemsEnabled')
|
||||
h3 Battle Gear
|
||||
ul
|
||||
li(v-for='(key, itemType) in user.items.gear.equipped', v-if='flatGear[key]')
|
||||
strong {{ flatGear[key].text() }}
|
||||
strong(v-if='flatGear[key].str || flatGear[key].con || flatGear[key].per || flatGear[key].int') :
|
||||
span(v-for='stat in ["str","con","per","int"]', v-if='flatGear[key][stat]') {{flatGear[key][stat]}} {{ $t(stat) }}
|
||||
|
||||
div(v-if='user.preferences.costume')
|
||||
h4(v-once) {{ $t('costume') }}
|
||||
div
|
||||
div(ng-repeat='(key, itemType) in user.items.gear.costume')
|
||||
strong {{flatGear[key].text()}}
|
||||
|
||||
div
|
||||
h3 Background
|
||||
ul
|
||||
li(v-if='!user.preferences.background') None
|
||||
li(v-if='user.preferences.background') {{ user.preferences.background }}
|
||||
|
||||
div(ng-if='user.flags.dropsEnabled')
|
||||
h3(v-once) {{ $t('pets') }}
|
||||
ul
|
||||
li(ng-if='user.items.currentPet')
|
||||
| {{ $t('activePet') }}:
|
||||
| {{ formatAnimal(user.items.currentPet, 'pet') }}
|
||||
li
|
||||
| {{ $t('petsFound') }}:
|
||||
| {{ totalCount(user.items.pets) }}
|
||||
li
|
||||
| {{ $t('beastMasterProgress') }}:
|
||||
| {{ beastMasterProgress(user.items.pets) }}
|
||||
|
||||
h3(v-once) {{ $t('mounts') }}
|
||||
ul
|
||||
li(v-if='user.items.currentMount')
|
||||
| {{ $t('activeMount') }}:
|
||||
| {{ formatAnimal(user.items.currentMount, 'mount') }}
|
||||
li
|
||||
| {{ $t('mountsTamed') }}:
|
||||
| {{ totalCount(user.items.mounts) }}
|
||||
li
|
||||
| {{ $t('mountMasterProgress') }}:
|
||||
| {{ mountMasterProgress(user.items.mounts) }}
|
||||
|
||||
.col-4(v-if='user.flags.classSelected && !user.preferences.disableClasses')
|
||||
// @TODO: Implement .col-4(v-if='user.flags.classSelected && !user.preferences.disableClasses')
|
||||
h3(v-once) {{ $t('characterBuild') }}
|
||||
h4(v-once) {{ $t('class') + ': ' }}
|
||||
span {{ classText }}
|
||||
|
|
@ -284,6 +300,26 @@ b-modal#profile(title="Profile", size='lg', :hide-footer="true")
|
|||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.well {
|
||||
background-color: #edecee;
|
||||
border-radius: 2px;
|
||||
padding: 0.4em;
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
.item-wrapper {
|
||||
.box {
|
||||
width: 94px;
|
||||
height: 92px;
|
||||
border-radius: 2px;
|
||||
border: dotted 1px #c3c0c7;
|
||||
}
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
|
@ -353,7 +389,6 @@ export default {
|
|||
this.editingProfile.name = this.user.profile.name;
|
||||
this.editingProfile.imageUrl = this.user.profile.imageUrl;
|
||||
this.achievements = achievementsLib.getAchievementsForProfile(this.user);
|
||||
this.$root.$emit('show::modal', 'profile');
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
|
|
|
|||
17
website/client/components/userMenu/profilePage.vue
Normal file
17
website/client/components/userMenu/profilePage.vue
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<template lang="pug">
|
||||
div
|
||||
// @TODO: profile modal is pulled in on the header. So.. seems a little odd to depend on it that way, but for now let's depend
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import profile from './profile';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
profile,
|
||||
},
|
||||
mounted () {
|
||||
this.$root.$emit('show::modal', 'profile');
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -10,6 +10,7 @@ import StoreModule from './libs/store';
|
|||
import './filters/registerGlobals';
|
||||
import i18n from './libs/i18n';
|
||||
import axios from 'axios';
|
||||
import Notifications from 'vue-notification';
|
||||
|
||||
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ axios.interceptors.response.use((response) => {
|
|||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
Vue.use(Notifications);
|
||||
Vue.use(i18n);
|
||||
Vue.use(StoreModule);
|
||||
|
||||
|
|
|
|||
|
|
@ -98,8 +98,12 @@ export default {
|
|||
round (number) {
|
||||
return Math.abs(number.toFixed(1));
|
||||
},
|
||||
// @TODO: Implement when we have a notify library
|
||||
//notify (html, type, icon, canHide, onClick) {
|
||||
notify (html) {
|
||||
// @TODO: try these params type, icon, canHide, onClick
|
||||
this.$notify({
|
||||
title: 'Habitica',
|
||||
text: html,
|
||||
});
|
||||
// let stack_topright = {"dir1": "down", "dir2": "left", "spacing1": 15, "spacing2": 15, "firstpos1": 60};
|
||||
// let notice = $.pnotify({
|
||||
// type: type || 'warning', //('info', 'text', 'warning', 'success', 'gp', 'xp', 'hp', 'lvl', 'death', 'mp', 'crit')
|
||||
|
|
@ -119,6 +123,6 @@ export default {
|
|||
// onClick();
|
||||
// }
|
||||
// });
|
||||
//},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,11 +29,10 @@ const VideosPage = () => import(/* webpackChunkName: "static" */'./components/st
|
|||
const RegisterLogin = () => import(/* webpackChunkName: "auth" */'./components/auth/registerLogin');
|
||||
|
||||
// User Pages
|
||||
const CreatorIntro = () => import(/* webpackChunkName: "creator" */'./components/creatorIntro');
|
||||
const BackgroundsPage = () => import(/* webpackChunkName: "user" */'./components/userMenu/backgrounds');
|
||||
// const StatsPage = () => import(/* webpackChunkName: "user" */'./components/userMenu/stats');
|
||||
// const AchievementsPage = () => import(/* webpackChunkName: "user" */'./components/userMenu/achievements');
|
||||
const ProfilePage = () => import(/* webpackChunkName: "user" */'./components/userMenu/profile');
|
||||
const ProfilePage = () => import(/* webpackChunkName: "user" */'./components/userMenu/profilePage');
|
||||
|
||||
// Settings
|
||||
const Settings = () => import(/* webpackChunkName: "settings" */'./components/settings/index');
|
||||
|
|
@ -98,7 +97,6 @@ const router = new VueRouter({
|
|||
},
|
||||
// requiresLogin is true by default, isStatic false
|
||||
routes: [
|
||||
{ name: 'avatar', path: '/avatar', component: CreatorIntro },
|
||||
{ name: 'home', path: '/home', component: FrontPage, meta: {requiresLogin: false} },
|
||||
{ name: 'register', path: '/register', component: RegisterLogin, meta: {requiresLogin: false} },
|
||||
{ name: 'login', path: '/login', component: RegisterLogin, meta: {requiresLogin: false} },
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@ export default function () {
|
|||
publicGuilds: [],
|
||||
groupFormOptions: {
|
||||
creatingParty: false,
|
||||
groupId: '',
|
||||
},
|
||||
avatarEditorOptions: {
|
||||
editingUser: false,
|
||||
},
|
||||
editingGroup: {}, // TODO move to local state
|
||||
// content data, frozen to prevent Vue from modifying it since it's static and never changes
|
||||
|
|
|
|||
Loading…
Reference in a new issue