pug to html

This commit is contained in:
Matteo Pagliazzi 2019-10-12 16:33:05 +02:00
parent 88243a32fa
commit 07349c70bc
236 changed files with 16708 additions and 9648 deletions

View file

@ -10,6 +10,16 @@ module.exports = {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'import/no-unresolved': 'off',
'vue/no-v-html': 'off',
'vue/html-self-closing': ['error', {
html: {
void: 'never',
normal: 'never',
component: 'always',
},
svg: 'never',
math: 'never',
}],
},
parserOptions: {
parser: 'babel-eslint',

File diff suppressed because it is too large Load diff

View file

@ -43,7 +43,6 @@
"eslint-plugin-vue": "^5.0.0",
"inspectpack": "^4.2.2",
"pug": "^2.0.4",
"pug-plain-loader": "^1.0.0",
"sass": "^1.19.0",
"sass-loader": "^8.0.0",
"svg-inline-loader": "^0.8.0",

View file

@ -1,52 +1,70 @@
<template lang="pug">
div
#loading-screen-inapp(v-if='loading')
.row
.col-12.text-center
svg#melior(xmlns='http://www.w3.org/2000/svg', viewbox='0 0 61.91 64')
path(d='M61.82,64H51.59c-3.08,0-3.72.37-3.67-1,0.07-1.87.67-1.94,2.63-2.49,1.63-.45,1-3.35-0.8-5.88-1.28-1.76-3.89-3.81-7.31-2.22a10.75,10.75,0,0,0-4.56,3.52c-1.68,2.33-1.59,4.54,1,4.54s5.39-1.5,6.23.64c1,2.64.33,2.89-.18,2.89H28.55v0C19.77,64,11,63.93,9,58.38c-2.82-7.68,7.43-10.64,7.75-15.46,0.13-2-1-2.85-2.34-2.85h-6V36.41H4.7v-11H8.36V29.1H12v3.65h3.65v5.08a5.76,5.76,0,0,1,3.07,5.05c-0.17,5.51-9.5,8.57-7.79,14.35,1.56,5.29,13.37,4,13,.74L23.7,56.1c-0.06-2.62-.47-6.12.08-9.22C24.64,42,27.67,37.78,33,37.74c1,0,1.78-.21,1.78-1s-1.55-.84-2.64-0.95a23.35,23.35,0,0,1-12.56-5c-2.43-2-6.21-8.3-3.74-7.83a21.74,21.74,0,0,0,4.06.4c1.24,0,4.44-.35,4.44-1.11,0-1-1.85-.42-4.57-0.68C16.48,21.22,9.6,19.83,6,9.35,4.71,5.43,3.83-1.91,6,.46c12.46,13.7,16.69,11.47,23.84,16.16,3.15,2.06,5.19,7,7,6.58,1.2-.27.46-1.37,0.64-3.93C37.66,17,38.75,16.48,36,15.79c-3.26-.81-6.52-4.38-4.39-4.33a11.89,11.89,0,0,0,5.53-.76c1.87-.81,6.43-4.28,9.18-2.89s5.08-.6,6.94-0.25c2.71,0.51,3.41,4.24,3.05,6.42-0.22,1.38-.22,1.38-2,1.28-3.61-.21-4.53,2.67-2,4.25,3.87,2.42,5.51,4.23,6.56,9.58,0.51,2.6.1,3.2-.76,2.72s-2.34-.72-0.29,4-1.29,10.28-2.39,10.9a1.3,1.3,0,0,0-.91,1.34c0,11.42,0,12.27,1.92,12.48,2.9,0.31,4.14-1.44,5.27.06C63.29,62.73,63.41,64,61.82,64ZM4.7,21.28H1v3.65H4.7V21.28Z', transform='translate(-1.05)', fill='#fff')
.col-12.text-center
h2 {{$t('tipTitle', {tipNumber: currentTipNumber})}}
p {{currentTip}}
#app(:class='{"casting-spell": castingSpell}')
banned-account-modal
amazon-payments-modal(v-if='!isStaticPage')
payments-success-modal
sub-cancel-modal-confirm(v-if='isUserLoaded')
sub-canceled-modal(v-if='isUserLoaded')
snackbars
router-view(v-if="!isUserLoggedIn || isStaticPage")
template(v-else)
template(v-if="isUserLoaded")
.resting-banner(v-show="showRestingBanner", ref="restingBanner")
span.content
span.label.d-inline.d-sm-none {{ $t('innCheckOutBannerShort') }}
span.label.d-none.d-sm-inline {{ $t('innCheckOutBanner') }}
span.separator |
span.resume(@click="resumeDamage()") {{ $t('resumeDamage') }}
.closepadding(@click="hideBanner()")
span.svg-icon.inline.icon-10(aria-hidden="true", v-html="icons.close")
notifications-display
app-menu
.container-fluid
app-header
buyModal(
:item="selectedItemToBuy || {}",
:withPin="true",
@buyPressed="customPurchase($event)",
:genericPurchase="genericPurchase(selectedItemToBuy)",
)
selectMembersModal(
:item="selectedSpellToBuy || {}",
:group="user.party",
@memberSelected="memberSelected($event)",
)
div(:class='{sticky: user.preferences.stickyHeader}')
router-view
app-footer
audio#sound(autoplay, ref="sound")
<template>
<div>
<div
v-if="loading"
id="loading-screen-inapp"
>
<div class="row">
<div class="col-12 text-center">
<svg
id="melior"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 61.91 64"
><path
d="M61.82,64H51.59c-3.08,0-3.72.37-3.67-1,0.07-1.87.67-1.94,2.63-2.49,1.63-.45,1-3.35-0.8-5.88-1.28-1.76-3.89-3.81-7.31-2.22a10.75,10.75,0,0,0-4.56,3.52c-1.68,2.33-1.59,4.54,1,4.54s5.39-1.5,6.23.64c1,2.64.33,2.89-.18,2.89H28.55v0C19.77,64,11,63.93,9,58.38c-2.82-7.68,7.43-10.64,7.75-15.46,0.13-2-1-2.85-2.34-2.85h-6V36.41H4.7v-11H8.36V29.1H12v3.65h3.65v5.08a5.76,5.76,0,0,1,3.07,5.05c-0.17,5.51-9.5,8.57-7.79,14.35,1.56,5.29,13.37,4,13,.74L23.7,56.1c-0.06-2.62-.47-6.12.08-9.22C24.64,42,27.67,37.78,33,37.74c1,0,1.78-.21,1.78-1s-1.55-.84-2.64-0.95a23.35,23.35,0,0,1-12.56-5c-2.43-2-6.21-8.3-3.74-7.83a21.74,21.74,0,0,0,4.06.4c1.24,0,4.44-.35,4.44-1.11,0-1-1.85-.42-4.57-0.68C16.48,21.22,9.6,19.83,6,9.35,4.71,5.43,3.83-1.91,6,.46c12.46,13.7,16.69,11.47,23.84,16.16,3.15,2.06,5.19,7,7,6.58,1.2-.27.46-1.37,0.64-3.93C37.66,17,38.75,16.48,36,15.79c-3.26-.81-6.52-4.38-4.39-4.33a11.89,11.89,0,0,0,5.53-.76c1.87-.81,6.43-4.28,9.18-2.89s5.08-.6,6.94-0.25c2.71,0.51,3.41,4.24,3.05,6.42-0.22,1.38-.22,1.38-2,1.28-3.61-.21-4.53,2.67-2,4.25,3.87,2.42,5.51,4.23,6.56,9.58,0.51,2.6.1,3.2-.76,2.72s-2.34-.72-0.29,4-1.29,10.28-2.39,10.9a1.3,1.3,0,0,0-.91,1.34c0,11.42,0,12.27,1.92,12.48,2.9,0.31,4.14-1.44,5.27.06C63.29,62.73,63.41,64,61.82,64ZM4.7,21.28H1v3.65H4.7V21.28Z"
transform="translate(-1.05)"
fill="#fff"
></path></svg>
</div><div class="col-12 text-center">
<h2>{{ $t('tipTitle', {tipNumber: currentTipNumber}) }}</h2><p>{{ currentTip }}</p>
</div>
</div>
</div><div
id="app"
:class="{'casting-spell': castingSpell}"
>
<banned-account-modal /><amazon-payments-modal v-if="!isStaticPage" /><payments-success-modal /><sub-cancel-modal-confirm v-if="isUserLoaded" /><sub-canceled-modal v-if="isUserLoaded" /><snackbars /><router-view v-if="!isUserLoggedIn || isStaticPage" /><template v-else>
<template v-if="isUserLoaded">
<div
v-show="showRestingBanner"
ref="restingBanner"
class="resting-banner"
>
<span class="content"><span class="label d-inline d-sm-none">{{ $t('innCheckOutBannerShort') }}</span><span class="label d-none d-sm-inline">{{ $t('innCheckOutBanner') }}</span><span class="separator"> |</span><span
class="resume"
@click="resumeDamage()"
>{{ $t('resumeDamage') }}</span></span><div
class="closepadding"
@click="hideBanner()"
>
<span
class="svg-icon inline icon-10"
aria-hidden="true"
v-html="icons.close"
></span>
</div>
</div><notifications-display /><app-menu /><div class="container-fluid">
<app-header /><buyModal
:item="selectedItemToBuy || {}"
:with-pin="true"
:generic-purchase="genericPurchase(selectedItemToBuy)"
@buyPressed="customPurchase($event)"
/><selectMembersModal
:item="selectedSpellToBuy || {}"
:group="user.party"
@memberSelected="memberSelected($event)"
/><div :class="{sticky: user.preferences.stickyHeader}">
<router-view />
</div>
</div><app-footer /><audio
id="sound"
ref="sound"
autoplay="autoplay"
></audio>
</template>
</template>
</div>
</div>
</template>
<style lang='scss' scoped>

View file

@ -1,16 +1,22 @@
<template lang="pug">
.row
.col-12.text-center
// @TODO i18n. How to setup the strings with the router-link inside?
img.not-found-img(src='~@/assets/images/404.png')
h1.not-found Sometimes even the bravest adventurer gets lost.
h2.not-found Looks like this link is broken or the page may have moved, sorry!
h2.not-found
| Head back to the
<router-link to="/">Homepage</router-link>
| or
<router-link :to="contactUsLink">Contact Us</router-link>
| about the issue.
<template>
<div class="row">
<div class="col-12 text-center">
<!-- @TODO i18n. How to setup the strings with the router-link inside?--><img
class="not-found-img"
src="~@/assets/images/404.png"
><h1 class="not-found">
Sometimes even the bravest adventurer gets lost.
</h1><h2 class="not-found">
Looks like this link is broken or the page may have moved, sorry!
</h2><h2 class="not-found">
Head back to the<router-link to="/">
Homepage
</router-link>or<router-link :to="contactUsLink">
Contact Us
</router-link>about the issue.
</h2>
</div>
</div>
</template>
<script>

View file

@ -1,7 +1,11 @@
<template lang="pug">
div(:class='achievementClass')
//- +generatedAvatar({sleep: false})
avatar(:member='user', :avatarOnly='true', :withBackground='true')
<template>
<div :class="achievementClass">
<avatar
:member="user"
:avatar-only="true"
:with-background="true"
/>
</div>
</template>
<script>

View file

@ -1,16 +1,31 @@
<template lang="pug">
.modal-footer(style='margin-top:0', ng-init='loadWidgets()')
.container-fluid.share-buttons
.row
.col-12.text-center
a.twitter-share-button.share-button(:href='twitterLink', target='_blank')
.social-icon.twitter.svg-icon(v-html='icons.twitter')
| {{ $t('tweet') }}
a.fb-share-button.share-button(:href='facebookLink', target='_blank')
.social-icon.facebook.svg-icon(v-html='icons.facebook')
| {{ $t('share') }}
// @TODO: Still want this? .col-4
a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')
<template>
<div
class="modal-footer"
style="margin-top:0"
ng-init="loadWidgets()"
>
<div class="container-fluid share-buttons">
<div class="row">
<div class="col-12 text-center">
<a
class="twitter-share-button share-button"
:href="twitterLink"
target="_blank"
><div
class="social-icon twitter svg-icon"
v-html="icons.twitter"
></div>{{ $t('tweet') }}</a><a
class="fb-share-button share-button"
:href="facebookLink"
target="_blank"
><div
class="social-icon facebook svg-icon"
v-html="icons.facebook"
></div>{{ $t('share') }}</a><!-- @TODO: Still want this? .col-4a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')-->
</div>
</div>
</div>
</div>
</template>
<style scoped>

View file

@ -1,14 +1,27 @@
<template lang="pug">
b-modal#armoire-empty(:title="$t('armoireText')", size='lg', :hide-footer="true")
.modal-body
.row
.col-6.offset-3
.shop_armoire
p {{$t('armoireLastItem')}}
p {{$t('armoireNotesEmpty')}}
.modal-footer
.col-12.text-center
button.btn.btn-primary(@click='close()') {{$t('close')}}
<template>
<b-modal
id="armoire-empty"
:title="$t('armoireText')"
size="lg"
:hide-footer="true"
>
<div class="modal-body">
<div class="row">
<div class="col-6 offset-3">
<div class="shop_armoire"></div><p>{{ $t('armoireLastItem') }}</p><p>{{ $t('armoireNotesEmpty') }}</p>
</div>
</div>
</div><div class="modal-footer">
<div class="col-12 text-center">
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('close') }}
</button>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,54 +1,89 @@
<template lang="pug">
b-modal#choose-class(
size='lg',
:hide-header='true',
:hide-footer='true',
:no-close-on-esc='true',
:no-close-on-backdrop='true',
)
.modal-body.select-class
h1.header-purple.text-center {{ $t('chooseClass') }}
.container-fluid
br
.row
.col-md-3(v-for='heroClass in classes')
div(@click='selectedClass = heroClass')
avatar(
:member='user',
:avatarOnly='true',
:withBackground='false',
:overrideAvatarGear='classGear(heroClass)',
:hideClassBadge='true',
:spritesMargin='"1.8em 1.5em"',
:overrideTopPadding='"0px"',
:showVisualBuffs='false',
:class='selectionBox(selectedClass, heroClass)',
)
br
.d-flex.justify-content-center(v-for='heroClass in classes')
.d-inline-flex(v-if='selectedClass === heroClass')
.class-badge.d-flex.justify-content-center
.svg-icon.align-self-center(v-html='icons[heroClass]')
.class-name(:class='`${heroClass}-color`') {{ $t(heroClass) }}
div(v-for='heroClass in classes')
.class-explanation.text-center(
v-if='selectedClass === heroClass'
) {{ $t(`${heroClass}Text`) }}
.text-center(v-markdown='$t("chooseClassLearnMarkdown")')
.modal-actions.text-center
button.btn.btn-primary.d-inline-block(
v-if='!selectedClass',
:disabled='true'
) {{ $t('select') }}
button.btn.btn-primary.d-inline-block(
v-else,
@click='clickSelectClass(selectedClass); close();'
) {{ $t('selectClass', {heroClass: $t(selectedClass)}) }}
.opt-out-wrapper
span#classOptOutBtn.danger(
@click='clickDisableClasses(); close();'
) {{ $t('optOutOfClasses') }}
span.opt-out-description {{ $t('optOutOfClassesText') }}
<template>
<b-modal
id="choose-class"
size="lg"
:hide-header="true"
:hide-footer="true"
:no-close-on-esc="true"
:no-close-on-backdrop="true"
>
<div class="modal-body select-class">
<h1 class="header-purple text-center">
{{ $t('chooseClass') }}
</h1><div class="container-fluid">
<br><div class="row">
<div
v-for="heroClass in classes"
class="col-md-3"
>
<div @click="selectedClass = heroClass">
<avatar
:member="user"
:avatar-only="true"
:with-background="false"
:override-avatar-gear="classGear(heroClass)"
:hide-class-badge="true"
:sprites-margin="'1.8em 1.5em'"
:override-top-padding="'0px'"
:show-visual-buffs="false"
:class="selectionBox(selectedClass, heroClass)"
/>
</div>
</div>
</div><br><div
v-for="heroClass in classes"
class="d-flex justify-content-center"
>
<div
v-if="selectedClass === heroClass"
class="d-inline-flex"
>
<div class="class-badge d-flex justify-content-center">
<div
class="svg-icon align-self-center"
v-html="icons[heroClass]"
></div>
</div><div
class="class-name"
:class="`${heroClass}-color`"
>
{{ $t(heroClass) }}
</div>
</div>
</div><div v-for="heroClass in classes">
<div
v-if="selectedClass === heroClass"
class="class-explanation text-center"
>
{{ $t(`${heroClass}Text`) }}
</div>
</div><div
v-markdown="$t('chooseClassLearnMarkdown')"
class="text-center"
></div><div class="modal-actions text-center">
<button
v-if="!selectedClass"
class="btn btn-primary d-inline-block"
:disabled="true"
>
{{ $t('select') }}
</button><button
v-else
class="btn btn-primary d-inline-block"
@click="clickSelectClass(selectedClass); close();"
>
{{ $t('selectClass', {heroClass: $t(selectedClass)}) }}
</button><div class="opt-out-wrapper">
<span
id="classOptOutBtn"
class="danger"
@click="clickDisableClasses(); close();"
>{{ $t('optOutOfClasses') }}</span>
</div><span class="opt-out-description">{{ $t('optOutOfClassesText') }}</span>
</div>
</div>
</div>
</b-modal>
</template>
<style lang="scss" scoped>

View file

@ -1,16 +1,27 @@
<template lang="pug">
b-modal#contributor(:title="$t('modalContribAchievement')", size='md', :hide-footer="true")
.modal-body
.col-12
achievement-avatar.avatar
.col-6.offset-3.text-center
| {{ $t('contribModal', {name: user.profile.name, level: user.contributor.level}) }}
br
a(:href="$t('conRewardsURL')", target='_blank') {{ $t('contribLink') }}
br
button.btn.btn-primary(style='margin-top:1em' @click='close()') {{ $t('huzzah') }}
br
achievement-footer
<template>
<b-modal
id="contributor"
:title="$t('modalContribAchievement')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
{{ $t('contribModal', {name: user.profile.name, level: user.contributor.level}) }}<br><a
:href="$t('conRewardsURL')"
target="_blank"
>{{ $t('contribLink') }}</a><br><button
class="btn btn-primary"
style="margin-top:1em"
@click="close()"
>
{{ $t('huzzah') }}
</button><br>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,30 +1,56 @@
<template lang="pug">
b-modal#death(
:title="$t('lostAllHealth')",
size='md',
:hide-footer="true",
no-close-on-esc,
no-close-on-backdrop,
)
.row
.col-12
.hero-stats
.meter-label(:tooltip="$t('health')")
span.glyphicon.glyphicon-heart
.meter.health(:tooltip='Math.round(user.stats.hp * 100) / 100')
.bar(:style='barStyle')
// span.meter-text.value
| {{Math.ceil(user.stats.hp)}} / {{maxHealth}}
avatar(:member='user', :sleep='true', :avatarOnly='true', :withBackground='true')
// @TOOD: Sleep +generatedAvatar({sleep:true})
span(class='knockout')
.col-6.offset-3
h4.dont-despair {{ $t('dontDespair') }}
p.death-penalty {{ $t('deathPenaltyDetails') }}
.modal-footer
.col-12.text-center
button.btn.btn-danger(@click='revive()') {{ $t('refillHealthTryAgain') }}
h4.text-center(v-html="$t('dyingOftenTips')")
<template>
<b-modal
id="death"
:title="$t('lostAllHealth')"
size="md"
:hide-footer="true"
no-close-on-esc="no-close-on-esc"
no-close-on-backdrop="no-close-on-backdrop"
>
<div class="row">
<div class="col-12">
<div class="hero-stats">
<div
class="meter-label"
:tooltip="$t('health')"
>
<span class="glyphicon glyphicon-heart"></span>
</div><div
class="meter health"
:tooltip="Math.round(user.stats.hp * 100) / 100"
>
<div
class="bar"
:style="barStyle"
></div>
</div><!-- span.meter-text.value| {{Math.ceil(user.stats.hp)}} / {{maxHealth}}--><avatar
:member="user"
:sleep="true"
:avatar-only="true"
:with-background="true"
/><!-- @TOOD: Sleep +generatedAvatar({sleep:true})--><span class="knockout"></span>
</div>
</div><div class="col-6 offset-3">
<h4 class="dont-despair">
{{ $t('dontDespair') }}
</h4><p class="death-penalty">
{{ $t('deathPenaltyDetails') }}
</p>
</div>
</div><div class="modal-footer">
<div class="col-12 text-center">
<button
class="btn btn-danger"
@click="revive()"
>
{{ $t('refillHealthTryAgain') }}
</button><h4
class="text-center"
v-html="$t('dyingOftenTips')"
></h4>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,16 +1,25 @@
<template lang="pug">
b-modal#drops-enabled(:title="$t('dropsEnabled')", size='lg', :hide-footer="true")
.modal-body
.col-6.offset-3.text-center
p
.item-drop-icon(class='Pet_Egg_Wolf')
span(v-html='firstDropText')
p
.item-drop-icon(class='Pet_Currency_Gem')
span(v-html="$t('useGems')")
.modal-footer
.col-12.text-center
button.btn.btn-primary(@click='close()') {{ $t('close') }}
<template>
<b-modal
id="drops-enabled"
:title="$t('dropsEnabled')"
size="lg"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-6 offset-3 text-center">
<p></p><div class="item-drop-icon Pet_Egg_Wolf"></div><span v-html="firstDropText"></span></p><p></p><div class="item-drop-icon Pet_Currency_Gem"></div><span v-html="$t('useGems')"></span></p>
</div>
</div><div class="modal-footer">
<div class="col-12 text-center">
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('close') }}
</button>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,12 +1,23 @@
<template lang="pug">
b-modal#generic-achievement(:title='data.message', size='md', :hide-footer='true')
.modal-body
.col-12
achievement-avatar.avatar
.col-6.offset-3.text-center
p(v-html='data.modalText')
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
achievement-footer
<template>
<b-modal
id="generic-achievement"
:title="data.message"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
<p v-html="data.modalText"></p><button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,14 +1,23 @@
<template lang="pug">
b-modal#invited-friend(:title="$t('modalAchievement')", size='md', :hide-footer="true")
.modal-body
.col-12
// @TODO: +achievementAvatar('friends',0)
achievement-avatar.avatar
.col-6.offset-3.text-center
p {{ $t('invitedFriendText') }}
br
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
achievement-footer
<template>
<b-modal
id="invited-friend"
:title="$t('modalAchievement')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<!-- @TODO: +achievementAvatar('friends',0)--><achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
<p>{{ $t('invitedFriendText') }}</p><br><button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,14 +1,23 @@
<template lang="pug">
b-modal#joined-challenge(:title="$t('modalAchievement')", size='md', :hide-footer="true")
.modal-body
.col-12
// @TODO: +achievementAvatar('challenge',0)
achievement-avatar.avatar
.col-6.offset-3.text-center
p {{ $t('joinedChallengeText') }}
br
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
achievement-footer
<template>
<b-modal
id="joined-challenge"
:title="$t('modalAchievement')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<!-- @TODO: +achievementAvatar('challenge',0)--><achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
<p>{{ $t('joinedChallengeText') }}</p><br><button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,14 +1,23 @@
<template lang="pug">
b-modal#joined-guild(:title="$t('modalAchievement')", size='md', :hide-footer="true")
.modal-body
.col-12
// @TODO: +achievementAvatar('guild',0)
achievement-avatar.avatar
.col-6.offset-3.text-center
p {{ $t('joinedGuildText') }}
br
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
achievement-footer
<template>
<b-modal
id="joined-guild"
:title="$t('modalAchievement')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<!-- @TODO: +achievementAvatar('guild',0)--><achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
<p>{{ $t('joinedGuildText') }}</p><br><button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,12 +1,23 @@
<template lang="pug">
b-modal#just-add-water(:title='title', size='md', :hide-footer='true')
.modal-body
.col-12
achievement-avatar.avatar
.col-6.offset-3.text-center
p {{ $t('achievementJustAddWaterModalText') }}
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
achievement-footer
<template>
<b-modal
id="just-add-water"
:title="title"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
<p>{{ $t('achievementJustAddWaterModalText') }}</p><button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,30 +1,48 @@
<template lang="pug">
b-modal#level-up(:title="$t('levelUpShare')", size='sm', :hide-footer="true", :hide-header="true")
.modal-body.text-center
h2 {{ $t('reachedLevel', {level: user.stats.lvl}) }}
avatar.avatar(:member='user')
p.text {{ $t('levelup') }}
button.btn.btn-primary(@click='close()') {{ $t('onwards') }}
br
// @TODO: Keep this? .checkbox
input(type='checkbox', v-model=
'user.preferences.suppressModals.levelUp', @change='changeLevelupSuppress()')
label(style='display:inline-block') {{ $t('dontShowAgain') }}
.container-fluid.share-buttons
.row
.col-12.text-center
a.twitter-share-button.share-button(:href='twitterLink', target='_blank')
.social-icon.twitter.svg-icon(v-html='icons.twitter')
| {{ $t('tweet') }}
a.fb-share-button.share-button(:href='facebookLink', target='_blank')
.social-icon.facebook.svg-icon(v-html='icons.facebook')
| {{ $t('share') }}
// @TODO: Still want this? .col-4
a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')
<template>
<b-modal
id="level-up"
:title="$t('levelUpShare')"
size="sm"
:hide-footer="true"
:hide-header="true"
>
<div class="modal-body text-center">
<h2>{{ $t('reachedLevel', {level: user.stats.lvl}) }}</h2><avatar
class="avatar"
:member="user"
/><p class="text">
{{ $t('levelup') }}
</p><button
class="btn btn-primary"
@click="close()"
>
{{ $t('onwards') }}
</button><br><!-- @TODO: Keep this? .checkboxinput(type='checkbox', v-model=
'user.preferences.suppressModals.levelUp', @change='changeLevelupSuppress()')
label(style='display:inline-block') {{ $t('dontShowAgain') }}
-->
</div><div class="container-fluid share-buttons">
<div class="row">
<div class="col-12 text-center">
<a
class="twitter-share-button share-button"
:href="twitterLink"
target="_blank"
><div
class="social-icon twitter svg-icon"
v-html="icons.twitter"
></div>{{ $t('tweet') }}</a><a
class="fb-share-button share-button"
:href="facebookLink"
target="_blank"
><div
class="social-icon facebook svg-icon"
v-html="icons.facebook"
></div>{{ $t('share') }}</a>
</div><!-- @TODO: Still want this? .col-4a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')-->
</div>
</div>
</b-modal>
</template>
<style lang="scss">

View file

@ -1,40 +1,89 @@
<template lang="pug">
b-modal#login-incentives(:title="data.message", size='md', :hide-footer="true")
.modal-body
.row
h3.col-12.text-center(
v-if='data.rewardText'
) {{ $t('unlockedReward', {reward: data.rewardText}) }}
.row.reward-row
.col-12
avatar.avatar(:member='user', :avatarOnly='true', :withBackground='true')
.text-center.col-12(v-if='nextReward')
.reward-wrap(v-if="!data.rewardText")
div(v-if="nextReward.rewardKey.length === 1", :class="nextReward.rewardKey[0]")
.reward(
v-for="reward in nextReward.rewardKey",
v-if="nextReward.rewardKey.length > 1",
:class='reward'
)
.reward-wrap(v-if="data.rewardText")
div(v-if="data.rewardKey.length === 1", :class="data.rewardKey[0]")
.reward(
v-for="reward in data.rewardKey",
v-if="data.rewardKey.length > 1",
:class='reward'
)
.col-12.text-center(v-if="data && data.nextRewardAt")
h4 {{ $t('countLeft', {count: data.nextRewardAt - user.loginIncentives}) }}
.row
.col-12.text-center(v-if='data.rewardText')
p {{ $t('earnedRewardForDevotion', {reward: data.rewardText}) }}
.col-12.text-center
p {{ $t('incentivesDescription') }}
.col-12.text-center(v-if="data && data.nextRewardAt")
h3 {{ $t('nextRewardUnlocksIn', {numberOfCheckinsLeft: data.nextRewardAt - user.loginIncentives}) }}
.modal-footer
.col-12.text-center
button.btn.btn-primary(@click='close()') {{ $t('awesome') }}
<template>
<b-modal
id="login-incentives"
:title="data.message"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="row">
<h3
v-if="data.rewardText"
class="col-12 text-center"
>
{{ $t('unlockedReward', {reward: data.rewardText}) }}
</h3>
</div><div class="row reward-row">
<div class="col-12">
<avatar
class="avatar"
:member="user"
:avatar-only="true"
:with-background="true"
/>
</div><div
v-if="nextReward"
class="text-center col-12"
>
<div
v-if="!data.rewardText"
class="reward-wrap"
>
<div
v-if="nextReward.rewardKey.length === 1"
:class="nextReward.rewardKey[0]"
></div><div
v-for="reward in nextReward.rewardKey"
v-if="nextReward.rewardKey.length > 1"
class="reward"
:class="reward"
></div>
</div><div
v-if="data.rewardText"
class="reward-wrap"
>
<div
v-if="data.rewardKey.length === 1"
:class="data.rewardKey[0]"
></div><div
v-for="reward in data.rewardKey"
v-if="data.rewardKey.length > 1"
class="reward"
:class="reward"
></div>
</div>
</div><div
v-if="data && data.nextRewardAt"
class="col-12 text-center"
>
<h4>{{ $t('countLeft', {count: data.nextRewardAt - user.loginIncentives}) }}</h4>
</div>
</div><div class="row">
<div
v-if="data.rewardText"
class="col-12 text-center"
>
<p>{{ $t('earnedRewardForDevotion', {reward: data.rewardText}) }}</p>
</div><div class="col-12 text-center">
<p>{{ $t('incentivesDescription') }}</p>
</div><div
v-if="data && data.nextRewardAt"
class="col-12 text-center"
>
<h3>{{ $t('nextRewardUnlocksIn', {numberOfCheckinsLeft: data.nextRewardAt - user.loginIncentives}) }}</h3>
</div>
</div>
</div><div class="modal-footer">
<div class="col-12 text-center">
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('awesome') }}
</button>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,12 +1,23 @@
<template lang="pug">
b-modal#lost-masterclasser(:title='title', size='md', :hide-footer='true')
.modal-body
.col-12
achievement-avatar.avatar
.col-6.offset-3.text-center
p {{ $t('achievementLostMasterclasserModalText') }}
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
achievement-footer
<template>
<b-modal
id="lost-masterclasser"
:title="title"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
<p>{{ $t('achievementLostMasterclasserModalText') }}</p><button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,29 +1,58 @@
<template lang="pug">
b-modal#low-health(:title="$t('losingHealthWarning')", size='md', :hide-footer="true")
.modal-body
.col-12.text-center
.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}}
.col-12
avatar(:member='user', :avatarOnly='true', :withBackground='true')
.col-12
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
.col-12.text-center
button.btn.btn-primary(@click='acknowledgeHealthWarning()') {{ $t('ok') }}
<template>
<b-modal
id="low-health"
:title="$t('losingHealthWarning')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12 text-center">
<div
class="meter-label"
:tooltip="$t('health')"
>
<span class="glyphicon glyphicon-heart"></span>
</div><div
class="meter health"
:tooltip="Math.round(user.stats.hp * 100) / 100"
>
<div
class="bar"
:style="barStyle"
></div><span class="meter-text value">{{ healthLeft }}</span>
</div>
</div><div class="col-12">
<avatar
:member="user"
:avatar-only="true"
:with-background="true"
/>
</div><div class="col-12">
<p>{{ $t('losingHealthWarning2') }}</p><h4>{{ $t('toRegainHealth') }}</h4><ul>
<li class="spaced">
{{ $t('lowHealthTips1') }}
</li><li class="spaced">
{{ $t('lowHealthTips2') }}
</li>
</ul><h4>{{ $t('losingHealthQuickly') }}</h4><ul>
<li class="spaced">
{{ $t('lowHealthTips3') }}
</li><li class="spaced">
{{ $t('lowHealthTips4') }}
</li>
</ul><h4>{{ $t('goodLuck') }}</h4>
</div>
</div><div class="modal-footer">
<div class="col-12 text-center">
<button
class="btn btn-primary"
@click="acknowledgeHealthWarning()"
>
{{ $t('ok') }}
</button>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,12 +1,23 @@
<template lang="pug">
b-modal#mind-over-matter(:title='title', size='md', :hide-footer='true')
.modal-body
.col-12
achievement-avatar.avatar
.col-6.offset-3.text-center
p {{ $t('achievementMindOverMatterModalText') }}
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
achievement-footer
<template>
<b-modal
id="mind-over-matter"
:title="title"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
<p>{{ $t('achievementMindOverMatterModalText') }}</p><button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,17 +1,35 @@
<template lang="pug">
b-modal#new-stuff(
size='lg',
:hide-header='true',
:hide-footer='true',
no-close-on-esc,
no-close-on-backdrop
)
.modal-body
.static-view(v-html='html')
.modal-footer
a.btn.btn-info(href='http://habitica.fandom.com/wiki/Whats_New', target='_blank') {{ this.$t('newsArchive') }}
button.btn.btn-secondary(@click='tellMeLater()') {{ this.$t('tellMeLater') }}
button.btn.btn-warning(@click='dismissAlert();') {{ this.$t('dismissAlert') }}
<template>
<b-modal
id="new-stuff"
size="lg"
:hide-header="true"
:hide-footer="true"
no-close-on-esc="no-close-on-esc"
no-close-on-backdrop="no-close-on-backdrop"
>
<div class="modal-body">
<div
class="static-view"
v-html="html"
></div>
</div><div class="modal-footer">
<a
class="btn btn-info"
href="http://habitica.fandom.com/wiki/Whats_New"
target="_blank"
>{{ this.$t('newsArchive') }}</a><button
class="btn btn-secondary"
@click="tellMeLater()"
>
{{ this.$t('tellMeLater') }}
</button><button
class="btn btn-warning"
@click="dismissAlert();"
>
{{ this.$t('dismissAlert') }}
</button>
</div>
</b-modal>
</template>
<style lang='scss'>

View file

@ -1,18 +1,35 @@
<template lang="pug">
b-modal#quest-completed(v-if='user.party.quest.completed', :title="title",
size='md', :hide-footer="true", :no-close-on-esc="true", :no-close-on-backdrop="true",
@hide='hide')
.modal-body.text-center
.quest(:class='`quest_${user.party.quest.completed}`')
p(
v-if='questData.completion && typeof questData.completion === "function"',
v-html='questData.completion()'
)
.quest-rewards.text-center
h3(v-once) {{ $t('paymentYouReceived') }}
questDialogDrops(:item="questData")
.modal-footer
button.btn.btn-primary(@click='setQuestCompleted()') {{ $t('ok') }}
<template>
<b-modal
v-if="user.party.quest.completed"
id="quest-completed"
:title="title"
size="md"
:hide-footer="true"
:no-close-on-esc="true"
:no-close-on-backdrop="true"
@hide="hide"
>
<div class="modal-body text-center">
<div
class="quest"
:class="`quest_${user.party.quest.completed}`"
></div><p
v-if="questData.completion && typeof questData.completion === 'function'"
v-html="questData.completion()"
></p><div class="quest-rewards text-center">
<h3 v-once>
{{ $t('paymentYouReceived') }}
</h3><questDialogDrops :item="questData" />
</div>
</div><div class="modal-footer">
<button
class="btn btn-primary"
@click="setQuestCompleted()"
>
{{ $t('ok') }}
</button>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,47 +1,66 @@
<template lang="pug">
b-modal#quest-invitation(v-if='user.party.quest.key && quests[user.party.quest.key]', :title="$t('questInvitation')", size='lg', :hide-footer="true")
.modal-header
h4 {{ $t('questInvitation') }}
|&nbsp;{{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}}&nbsp;
| {{ $t('experience') }}
tr(ng-if='quest.drop.gp > 0')
td {{quest.drop.gp}}&nbsp;
| {{ $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-secondary(ng-click='questHold = true; $close()') {{ $t('askLater') }}
button.btn.btn-secondary(ng-click='questReject(); $close()') {{ $t('reject') }}
button.btn.btn-primary(ng-click='questAccept(); $close()') {{ $t('accept') }}
<template>
<b-modal
v-if="user.party.quest.key && quests[user.party.quest.key]"
id="quest-invitation"
:title="$t('questInvitation')"
size="lg"
:hide-footer="true"
>
<div class="modal-header">
<h4>{{ $t('questInvitation') }}&nbsp;{{ quests[user.party.quest.key].text() }}</h4>
</div><div class="modal-body">
<div class="pull-right-sm text-center">
<div
class="col-centered"
:class="`quest_${quests[user.party.quest.key].key}`"
></div><div ng-if="quests[user.party.quest.key].boss">
<h4>{{ quests[user.party.quest.key].boss.name() }}</h4><p><strong>{{ $t('bossHP') }} + ': '</strong>{{ quests[user.party.quest.key].boss.hp }}</p><p><strong>{{ $t('bossStrength') }} + ': '</strong>{{ quests[user.party.quest.key].boss.str }}</p>
</div><div ng-if="quests[user.party.quest.key].collect">
<p ng-repeat="(k,v) in quests[user.party.quest.key].collect">
<strong>{{ $t('collect') }} + ': '</strong>{{ quests[user.party.quest.key].collect[k].count }} {{ quests[user.party.quest.key].collect[k].text() }}
</p>
</div>
</div><div ng-bind-html="quests[user.party.quest.key].notes()"></div><div
:key="user.party.quest.key"
class="quest-rewards"
header-participant="$t('rewardsAllParticipants')"
header-quest-owner="$t('rewardsQuestOwner')"
></div><hr><h5>{{ headerParticipant }}</h5><table class="table table-striped">
<tr ng-repeat="drop in _.reject(quest.drop.items, 'onlyOwner')">
<td>{{ drop.text() }}</td>
</tr><tr ng-if="quest.drop.exp > 0">
<td>{{ quest.drop.exp }}&nbsp;{{ $t('experience') }}</td>
</tr><tr ng-if="quest.drop.gp > 0">
<td>{{ quest.drop.gp }}&nbsp;{{ $t('gold') }}</td>
</tr><tr ng-if="quest.drop.unlock()">
<td>{{ quest.drop.unlock() }}</td>
</tr>
</table><div ng-if="getQuestOwnerRewards(quest).length > 0">
<h5>{{ headerQuestOwner }}</h5><table class="table table-striped">
<tr ng-repeat="drop in getQuestOwnerRewards(quest)">
<td>{{ drop.text() }}</td>
</tr>
</table>
</div>
</div><div class="modal-footer">
<button
class="btn btn-secondary"
ng-click="questHold = true; $close()"
>
{{ $t('askLater') }}
</button><button
class="btn btn-secondary"
ng-click="questReject(); $close()"
>
{{ $t('reject') }}
</button><button
class="btn btn-primary"
ng-click="questAccept(); $close()"
>
{{ $t('accept') }}
</button>
</div>
</b-modal>
</template>
<script>

View file

@ -1,17 +1,27 @@
<template lang="pug">
b-modal#rebirth(:title="$t('modalAchievement')", size='md', :hide-footer="true")
.modal-body
.col-12
// @TODO: +achievementAvatar('sun',0)
achievement-avatar.avatar
.col-6.offset-3.text-center
div(v-if='user.achievements.rebirthLevel < 100')
| {{ $t('rebirthAchievement', {number: user.achievements.rebirths, level: user.achievements.rebirthLevel}) }}
div(v-if='user.achievements.rebirthLevel >= 100')
| {{ $t('rebirthAchievement100', {number: user.achievements.rebirths}) }}
br
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
achievement-footer
<template>
<b-modal
id="rebirth"
:title="$t('modalAchievement')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<!-- @TODO: +achievementAvatar('sun',0)--><achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
<div v-if="user.achievements.rebirthLevel < 100">
{{ $t('rebirthAchievement', {number: user.achievements.rebirths, level: user.achievements.rebirthLevel}) }}
</div><div v-if="user.achievements.rebirthLevel >= 100">
{{ $t('rebirthAchievement100', {number: user.achievements.rebirths}) }}
</div><br><button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,13 +1,25 @@
<template lang="pug">
b-modal#rebirth-enabled(:title="$t('rebirthNew')", size='md', :hide-footer="true")
.modal-body
.col-12
.rebirth_orb
p
span {{ $t('rebirthUnlock') }}
.modal-footer
.col-12.text-center
button.btn.btn-primary(@click='close()') {{ $t('close') }}
<template>
<b-modal
id="rebirth-enabled"
:title="$t('rebirthNew')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<div class="rebirth_orb"></div><p><span>{{ $t('rebirthUnlock') }}</span></p>
</div>
</div><div class="modal-footer">
<div class="col-12 text-center">
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('close') }}
</button>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,20 +1,33 @@
<template lang="pug">
b-modal#streak(:title="$t('streakAchievement')", size='md', :hide-footer="true")
.modal-body
.col-12
// @TODO: +achievementAvatar('thermometer',2.5)
achievement-avatar.avatar
.col-6.offset-3.text-center
h3(v-if='user.achievements.streak === 1') {{ $t('firstStreakAchievement') }}
h3(v-if='user.achievements.streak > 1') {{ $t('streakAchievementCount', {streaks: user.achievements.streak}) }}
p {{ $t('twentyOneDays') }}
p {{ $t('dontBreakStreak') }}
br
button.btn.btn-primary(@click='close()') {{ $t('dontStop') }}
.checkbox
input(type='checkbox', v-model='user.preferences.suppressModals.streak', @change='suppressModals')
label {{ $t('dontShowAgain') }}
achievement-footer
<template>
<b-modal
id="streak"
:title="$t('streakAchievement')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<!-- @TODO: +achievementAvatar('thermometer',2.5)--><achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
<h3 v-if="user.achievements.streak === 1">
{{ $t('firstStreakAchievement') }}
</h3><h3 v-if="user.achievements.streak > 1">
{{ $t('streakAchievementCount', {streaks: user.achievements.streak}) }}
</h3><p>{{ $t('twentyOneDays') }}</p><p>{{ $t('dontBreakStreak') }}</p><br><button
class="btn btn-primary"
@click="close()"
>
{{ $t('dontStop') }}
</button><div class="checkbox">
<input
v-model="user.preferences.suppressModals.streak"
type="checkbox"
@change="suppressModals"
><label>{{ $t('dontShowAgain') }}</label>
</div>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,17 +1,37 @@
<template lang="pug">
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-body.text-center
br
.scene_guilds
br
h4 {{ $t('guildReminderText1') }}
.modal-footer
.container-fluid
.row
.col-6.text-center
button.btn.btn-secondary(@click='close()') {{ $t('guildReminderDismiss') }}
.col-6.text-center(@click='close()')
.btn.btn-primary(@click='takeMethere()') {{ $t('guildReminderCTA') }}
<template>
<b-modal
id="testing"
:title="$t('guildReminderTitle')"
size="lg"
:hide-footer="true"
>
<div class="modal-body text-center">
<br><div class="scene_guilds"></div><br><h4>{{ $t('guildReminderText1') }}</h4>
</div><div class="modal-footer">
<div class="container-fluid">
<div class="row">
<div class="col-6 text-center">
<button
class="btn btn-secondary"
@click="close()"
>
{{ $t('guildReminderDismiss') }}
</button>
</div><div
class="col-6 text-center"
@click="close()"
>
<div
class="btn btn-primary"
@click="takeMethere()"
>
{{ $t('guildReminderCTA') }}
</div>
</div>
</div>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,18 +1,34 @@
<template lang="pug">
b-modal#testingletiant(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-content
.modal-body.text-center
br
.scene_guilds
br
h4 {{ $t('guildReminderText2') }}
.modal-footer
.container-fluid
.row
.col-6.text-center
button.btn.btn-secondary(@click='close()') {{ $t('guildReminderDismiss') }}
.col-6.text-center
.btn.btn-primary(@click='takeMethere()') {{ $t('guildReminderCTA') }}
<template>
<b-modal
id="testingletiant"
:title="$t('guildReminderTitle')"
size="lg"
:hide-footer="true"
>
<div class="modal-content"></div><div class="modal-body text-center">
<br><div class="scene_guilds"></div><br><h4>{{ $t('guildReminderText2') }}</h4>
</div><div class="modal-footer">
<div class="container-fluid">
<div class="row">
<div class="col-6 text-center">
<button
class="btn btn-secondary"
@click="close()"
>
{{ $t('guildReminderDismiss') }}
</button>
</div><div class="col-6 text-center">
<div
class="btn btn-primary"
@click="takeMethere()"
>
{{ $t('guildReminderCTA') }}
</div>
</div>
</div>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,35 +1,49 @@
<template lang="pug">
b-modal#ultimate-gear(:title="$t('modalAchievement')", size='md', :hide-footer="true")
.modal-body
.col-12
// @TODO: +achievementAvatar('armor',2.5)
achievement-avatar.avatar
.col-12.text-center
p {{ $t('gearAchievement') }}
br
table.multi-achievement
tr
td(v-if='user.achievements.ultimateGearSets.healer').multi-achievement
.achievement-ultimate-healer2x.multi-achievement
| {{ $t('healer') }}
td(v-if='user.achievements.ultimateGearSets.wizard').multi-achievement
.achievement-ultimate-mage2x.multi-achievement
| {{ $t('mage') }}
td(v-if='user.achievements.ultimateGearSets.rogue').multi-achievement
.achievement-ultimate-rogue2x.multi-achievement
| {{ $t('rogue') }}
td(v-if='user.achievements.ultimateGearSets.warrior').multi-achievement
.achievement-ultimate-warrior2x.multi-achievement
| {{ $t('warrior') }}
br
div(v-if='!(user.achievements.ultimateGearSets.healer && user.achievements.ultimateGearSets.wizard && user.achievements.ultimateGearSets.rogue && user.achievements.ultimateGearSets.warrior)')
p(v-html="$t('moreGearAchievements')")
br
.shop_armoire
p(v-html='$t("armoireUnlocked")')
br
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
achievement-footer
<template>
<b-modal
id="ultimate-gear"
:title="$t('modalAchievement')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<!-- @TODO: +achievementAvatar('armor',2.5)--><achievement-avatar class="avatar" />
</div><div class="col-12 text-center">
<p>{{ $t('gearAchievement') }}</p><br><table class="multi-achievement">
<tr>
<td
v-if="user.achievements.ultimateGearSets.healer"
class="multi-achievement"
>
<div class="achievement-ultimate-healer2x multi-achievement"></div>{{ $t('healer') }}
</td><td
v-if="user.achievements.ultimateGearSets.wizard"
class="multi-achievement"
>
<div class="achievement-ultimate-mage2x multi-achievement"></div>{{ $t('mage') }}
</td><td
v-if="user.achievements.ultimateGearSets.rogue"
class="multi-achievement"
>
<div class="achievement-ultimate-rogue2x multi-achievement"></div>{{ $t('rogue') }}
</td><td
v-if="user.achievements.ultimateGearSets.warrior"
class="multi-achievement"
>
<div class="achievement-ultimate-warrior2x multi-achievement"></div>{{ $t('warrior') }}
</td>
</tr>
</table><br><div v-if="!(user.achievements.ultimateGearSets.healer && user.achievements.ultimateGearSets.wizard && user.achievements.ultimateGearSets.rogue && user.achievements.ultimateGearSets.warrior)">
<p v-html="$t('moreGearAchievements')"></p><br>
</div><div class="shop_armoire"></div><p v-html="$t('armoireUnlocked')"></p><br><button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div><achievement-footer />
</b-modal>
</template>
<style scoped>

View file

@ -1,33 +1,43 @@
<template lang="pug">
b-modal#welcome(:title="$t('welcomeToHabit')", size='lg', :hide-footer="true")
.modal-body.container-fluid
.row
.col-4.col-centered
span(style='display:flex')
h1
| &#9312;
h3(style='margin:auto auto auto .5em') {{ $t('welcome1') }}
.welcome_basic_avatars(style='margin: 1.5em auto 1.5em')
h4 {{ $t('welcome1notes') }}
.col-4.col-centered
span(style='display:flex')
h1
| &#9313;
h3(style='margin:.3em auto auto .5em') {{ $t('welcome2') }}
.welcome_sample_tasks(style='margin: 2.5em auto 1.5em')
h4 {{ $t('welcome2notes') }}
.col-4.col-centered
span(style='display:flex')
h1
| &#9314;
h3(style='margin:auto auto auto .5em') {{ $t('welcome3') }}
.welcome_promo_party(style='margin: 1em auto 1em')
h4 {{ $t('welcome3notes') }}
.modal-footer.text-center(style='margin-top:0')
.col-3
.col-6
button.btn.btn-primary.btn-lg.flex-column(@click='ready()') {{ $t('imReady') }}
.col-3
<template>
<b-modal
id="welcome"
:title="$t('welcomeToHabit')"
size="lg"
:hide-footer="true"
>
<div class="modal-body container-fluid">
<div class="row">
<div class="col-4 col-centered">
<span style="display:flex"><h1>&#9312;</h1><h3 style="margin:auto auto auto .5em">{{ $t('welcome1') }}</h3></span><div
class="welcome_basic_avatars"
style="margin: 1.5em auto 1.5em"
></div><h4>{{ $t('welcome1notes') }}</h4>
</div><div class="col-4 col-centered">
<span style="display:flex"><h1>&#9313;</h1><h3 style="margin:.3em auto auto .5em">{{ $t('welcome2') }}</h3></span><div
class="welcome_sample_tasks"
style="margin: 2.5em auto 1.5em"
></div><h4>{{ $t('welcome2notes') }}</h4>
</div><div class="col-4 col-centered">
<span style="display:flex"><h1>&#9314;</h1><h3 style="margin:auto auto auto .5em">{{ $t('welcome3') }}</h3></span><div
class="welcome_promo_party"
style="margin: 1em auto 1em"
></div><h4>{{ $t('welcome3notes') }}</h4>
</div>
</div>
</div><div
class="modal-footer text-center"
style="margin-top:0"
>
<div class="col-3"></div><div class="col-6">
<button
class="btn btn-primary btn-lg flex-column"
@click="ready()"
>
{{ $t('imReady') }}
</button>
</div><div class="col-3"></div>
</div>
</b-modal>
</template>
<script>

View file

@ -1,25 +1,56 @@
<template lang="pug">
b-modal#won-challenge(:title="$t('wonChallenge')", size='md', :hide-footer="true")
.modal-body.text-center
h4(v-markdown='user.achievements.challenges[user.achievements.challenges.length - 1]')
.row
.col-4
.achievement-karaoke-2x
.col-4
// @TODO: +generatedAvatar({sleep: false})
avatar.avatar(:member='user', :avatar-only='true')
.col-4
.achievement-karaoke-2x
p {{ $t('congratulations') }}
br
button.btn.btn-primary(@click='close()') {{ $t('hurray') }}
.modal-footer
.col-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-4(style='margin-left:.8em')
.fb-share-button(data-href='#{env.BASE_URL}/social/won-challenge', data-layout='button')
.col-4(style='margin-left:.8em')
a.tumblr-share-button(data-href='#{env.BASE_URL}/social/won-challenge', data-notes='none')
<template>
<b-modal
id="won-challenge"
:title="$t('wonChallenge')"
size="md"
:hide-footer="true"
>
<div class="modal-body text-center">
<h4 v-markdown="user.achievements.challenges[user.achievements.challenges.length - 1]"></h4><div class="row">
<div class="col-4">
<div class="achievement-karaoke-2x"></div>
</div><div class="col-4">
<!-- @TODO: +generatedAvatar({sleep: false})--><avatar
class="avatar"
:member="user"
:avatar-only="true"
/>
</div><div class="col-4">
<div class="achievement-karaoke-2x"></div>
</div>
</div><p>{{ $t('congratulations') }}</p><br><button
class="btn btn-primary"
@click="close()"
>
{{ $t('hurray') }}
</button>
</div><div class="modal-footer">
<div class="col-3">
<a
class="twitter-share-button"
href="https://twitter.com/intent/tweet?text=#{tweet}&via=habitica&url=#{env.BASE_URL}/social/won-challenge&count=none"
>{{ $t('tweet') }}</a>
</div><div
class="col-4"
style="margin-left:.8em"
>
<div
class="fb-share-button"
data-href="#{env.BASE_URL}/social/won-challenge"
data-layout="button"
></div>
</div><div
class="col-4"
style="margin-left:.8em"
>
<a
class="tumblr-share-button"
data-href="#{env.BASE_URL}/social/won-challenge"
data-notes="none"
></a>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,117 +1,255 @@
<template lang="pug">
.row.footer-row
buy-gems-modal(v-if='user')
//modify-inventory(v-if="isUserLoaded")
footer.col-12.expanded
.row
.col-12.col-md-2
h3
a(href='https://itunes.apple.com/us/app/habitica/id994882113?ls=1&mt=8', target='_blank') {{ $t('mobileIOS') }}
h3
a(href='https://play.google.com/store/apps/details?id=com.habitrpg.android.habitica', target='_blank') {{ $t('mobileAndroid') }}
.col-12.col-md-2
h3 {{ $t('footerCompany') }}
ul
li
router-link(to='/static/features') {{ $t('companyAbout') }}
li
a(href='https://habitica.wordpress.com/', target='_blank') {{ $t('companyBlog') }}
li
a(href='http://blog.habitrpg.com/', target='_blank') {{ $t('tumblr') }}
li
router-link(to='/static/faq') {{ $t('FAQ') }}
li
a(href='http://habitica.fandom.com/wiki/Whats_New', target='_blank') {{ $t('oldNews') }}
li
router-link(to='/static/merch') {{ $t('merch') }}
li
router-link(to='/static/press-kit') {{ $t('presskit') }}
li
router-link(to='/static/contact') {{ $t('contactUs') }}
.col-12.col-md-2
h3 {{ $t('footerCommunity') }}
ul
li
a(target="_blanck", href="/static/community-guidelines") {{ $t('communityGuidelines') }}
li
router-link(to='/hall/contributors') {{ $t('hall') }}
li
router-link(
to='/groups/guild/a29da26b-37de-4a71-b0c6-48e72a900dac'
) {{ $t('reportBug') }}
li
a(href='https://trello.com/c/odmhIqyW/440-read-first-table-of-contents', target='_blank') {{ $t('requestFeature') }}
li(v-html='$t("communityExtensions")')
li(v-html='$t("communityForum")')
li
a(href='https://www.facebook.com/Habitica', target='_blank') {{ $t('communityFacebook') }}
li
a(href='https://www.instagram.com/habitica', target='_blank') {{ $t('communityInstagram') }}
.col-12.col-md-6
.row
.col-6
h3 {{ $t('footerDevs') }}
ul
li
a(href='/apidoc', target='_blank') {{ $t('APIv3') }}
li
a(:href="getDataDisplayToolUrl", target='_blank') {{ $t('dataDisplayTool') }}
li
a(href='http://habitica.fandom.com/wiki/Guidance_for_Blacksmiths', target='_blank') {{ $t('guidanceForBlacksmiths') }}
.col-6.social
h3 {{ $t('footerSocial') }}
.icons
a.social-circle(href='https://twitter.com/habitica', target='_blank')
.social-icon.svg-icon(v-html='icons.twitter')
a.social-circle(href='https://www.instagram.com/habitica/', target='_blank')
.social-icon.svg-icon.instagram(v-html='icons.instagram')
a.social-circle(href='https://www.facebook.com/Habitica', target='_blank')
.social-icon.facebook.svg-icon(v-html='icons.facebook')
.row
.col-12.col-md-8 {{ $t('donateText3') }}
.col-12.col-md-4
button.btn.btn-contribute.btn-flat(@click="donate()", v-if="user")
.svg-icon.heart(v-html="icons.heart")
.text {{ $t('companyDonate') }}
.btn.btn-contribute.btn-flat(v-else)
a(href='http://habitica.fandom.com/wiki/Contributing_to_Habitica', target='_blank')
.svg-icon.heart(v-html="icons.heart")
.text {{ $t('companyContribute') }}
.row
.col-12
hr
.row
.col-12.col-md-5
| © 2019 Habitica. All rights reserved.
.debug.float-left(v-if="!IS_PRODUCTION && isUserLoaded")
button.btn.btn-primary(@click="debugMenuShown = !debugMenuShown") Toggle Debug Menu
.debug-group(v-if="debugMenuShown")
a.btn.btn-secondary(@click="setHealthLow()") Health = 1
a.btn.btn-secondary(@click="addMissedDay(1)") +1 Missed Day
a.btn.btn-secondary(@click="addMissedDay(2)") +2 Missed Days
a.btn.btn-secondary(@click="addMissedDay(8)") +8 Missed Days
a.btn.btn-secondary(@click="addMissedDay(32)") +32 Missed Days
a.btn.btn-secondary(@click="addTenGems()") +10 Gems
a.btn.btn-secondary(@click="addHourglass()") +1 Mystic Hourglass
a.btn.btn-secondary(@click="addGold()") +500GP
a.btn.btn-secondary(@click="plusTenHealth()") + 10HP
a.btn.btn-secondary(@click="addMana()") +MP
a.btn.btn-secondary(@click="addLevelsAndGold()") +Exp +GP +MP
a.btn.btn-secondary(@click="addExp()") +Exp
a.btn.btn-secondary(@click="addOneLevel()") +1 Level
a.btn.btn-secondary(
@click="addQuestProgress()",
tooltip="+1000 to boss quests. 300 items to collection quests"
) Quest Progress Up
a.btn.btn-secondary(@click="makeAdmin()") Make Admin
a.btn.btn-secondary(@click="openModifyInventoryModal()") Modify Inventory
.col-12.col-md-2.text-center
.logo.svg-icon(v-html='icons.gryphon')
.col-12.col-md-5.text-right
span.ml-4
a(target="_blanck", href="/static/privacy") {{ $t('privacy') }}
span.ml-4
a(target="_blanck", href="/static/terms") {{ $t('terms') }}
<template>
<div class="row footer-row">
<buy-gems-modal v-if="user" /><!--modify-inventory(v-if="isUserLoaded")--><footer class="col-12 expanded">
<div class="row">
<div class="col-12 col-md-2">
<h3>
<a
href="https://itunes.apple.com/us/app/habitica/id994882113?ls=1&mt=8"
target="_blank"
>{{ $t('mobileIOS') }}</a>
</h3><h3>
<a
href="https://play.google.com/store/apps/details?id=com.habitrpg.android.habitica"
target="_blank"
>{{ $t('mobileAndroid') }}</a>
</h3>
</div><div class="col-12 col-md-2">
<h3>{{ $t('footerCompany') }}</h3><ul>
<li>
<router-link to="/static/features">
{{ $t('companyAbout') }}
</router-link>
</li><li>
<a
href="https://habitica.wordpress.com/"
target="_blank"
>{{ $t('companyBlog') }}</a>
</li><li>
<a
href="http://blog.habitrpg.com/"
target="_blank"
>{{ $t('tumblr') }}</a>
</li><li>
<router-link to="/static/faq">
{{ $t('FAQ') }}
</router-link>
</li><li>
<a
href="http://habitica.fandom.com/wiki/Whats_New"
target="_blank"
>{{ $t('oldNews') }}</a>
</li><li>
<router-link to="/static/merch">
{{ $t('merch') }}
</router-link>
</li><li>
<router-link to="/static/press-kit">
{{ $t('presskit') }}
</router-link>
</li><li>
<router-link to="/static/contact">
{{ $t('contactUs') }}
</router-link>
</li>
</ul>
</div><div class="col-12 col-md-2">
<h3>{{ $t('footerCommunity') }}</h3><ul>
<li>
<a
target="_blanck"
href="/static/community-guidelines"
>{{ $t('communityGuidelines') }}</a>
</li><li>
<router-link to="/hall/contributors">
{{ $t('hall') }}
</router-link>
</li><li>
<router-link to="/groups/guild/a29da26b-37de-4a71-b0c6-48e72a900dac">
{{ $t('reportBug') }}
</router-link>
</li><li>
<a
href="https://trello.com/c/odmhIqyW/440-read-first-table-of-contents"
target="_blank"
>{{ $t('requestFeature') }}</a>
</li><li v-html="$t('communityExtensions')"></li><li v-html="$t('communityForum')"></li><li>
<a
href="https://www.facebook.com/Habitica"
target="_blank"
>{{ $t('communityFacebook') }}</a>
</li><li>
<a
href="https://www.instagram.com/habitica"
target="_blank"
>{{ $t('communityInstagram') }}</a>
</li>
</ul>
</div><div class="col-12 col-md-6">
<div class="row">
<div class="col-6">
<h3>{{ $t('footerDevs') }}</h3><ul>
<li>
<a
href="/apidoc"
target="_blank"
>{{ $t('APIv3') }}</a>
</li><li>
<a
:href="getDataDisplayToolUrl"
target="_blank"
>{{ $t('dataDisplayTool') }}</a>
</li><li>
<a
href="http://habitica.fandom.com/wiki/Guidance_for_Blacksmiths"
target="_blank"
>{{ $t('guidanceForBlacksmiths') }}</a>
</li>
</ul>
</div><div class="col-6 social">
<h3>{{ $t('footerSocial') }}</h3><div class="icons">
<a
class="social-circle"
href="https://twitter.com/habitica"
target="_blank"
><div
class="social-icon svg-icon"
v-html="icons.twitter"
></div></a><a
class="social-circle"
href="https://www.instagram.com/habitica/"
target="_blank"
><div
class="social-icon svg-icon instagram"
v-html="icons.instagram"
></div></a><a
class="social-circle"
href="https://www.facebook.com/Habitica"
target="_blank"
><div
class="social-icon facebook svg-icon"
v-html="icons.facebook"
></div></a>
</div>
</div>
</div><div class="row">
<div class="col-12 col-md-8">
{{ $t('donateText3') }}
</div><div class="col-12 col-md-4">
<button
v-if="user"
class="btn btn-contribute btn-flat"
@click="donate()"
>
<div
class="svg-icon heart"
v-html="icons.heart"
></div><div class="text">
{{ $t('companyDonate') }}
</div>
</button><div
v-else
class="btn btn-contribute btn-flat"
>
<a
href="http://habitica.fandom.com/wiki/Contributing_to_Habitica"
target="_blank"
><div
class="svg-icon heart"
v-html="icons.heart"
></div><div class="text">{{ $t('companyContribute') }}</div></a>
</div>
</div>
</div>
</div>
</div><div class="row">
<div class="col-12">
<hr>
</div>
</div><div class="row">
<div class="col-12 col-md-5">
© 2019 Habitica. All rights reserved.<div
v-if="!IS_PRODUCTION && isUserLoaded"
class="debug float-left"
>
<button
class="btn btn-primary"
@click="debugMenuShown = !debugMenuShown"
>
Toggle Debug Menu
</button><div
v-if="debugMenuShown"
class="debug-group"
>
<a
class="btn btn-secondary"
@click="setHealthLow()"
>Health = 1</a><a
class="btn btn-secondary"
@click="addMissedDay(1)"
>+1 Missed Day</a><a
class="btn btn-secondary"
@click="addMissedDay(2)"
>+2 Missed Days</a><a
class="btn btn-secondary"
@click="addMissedDay(8)"
>+8 Missed Days</a><a
class="btn btn-secondary"
@click="addMissedDay(32)"
>+32 Missed Days</a><a
class="btn btn-secondary"
@click="addTenGems()"
>+10 Gems</a><a
class="btn btn-secondary"
@click="addHourglass()"
>+1 Mystic Hourglass</a><a
class="btn btn-secondary"
@click="addGold()"
>+500GP</a><a
class="btn btn-secondary"
@click="plusTenHealth()"
>+ 10HP</a><a
class="btn btn-secondary"
@click="addMana()"
>+MP</a><a
class="btn btn-secondary"
@click="addLevelsAndGold()"
>+Exp +GP +MP</a><a
class="btn btn-secondary"
@click="addExp()"
>+Exp</a><a
class="btn btn-secondary"
@click="addOneLevel()"
>+1 Level</a><a
class="btn btn-secondary"
tooltip="+1000 to boss quests. 300 items to collection quests"
@click="addQuestProgress()"
>Quest Progress Up</a><a
class="btn btn-secondary"
@click="makeAdmin()"
>Make Admin</a><a
class="btn btn-secondary"
@click="openModifyInventoryModal()"
>Modify Inventory</a>
</div>
</div>
</div><div class="col-12 col-md-2 text-center">
<div
class="logo svg-icon"
v-html="icons.gryphon"
></div>
</div><div class="col-12 col-md-5 text-right">
<span class="ml-4"><a
target="_blanck"
href="/static/privacy"
>{{ $t('privacy') }}</a></span><span class="ml-4"><a
target="_blanck"
href="/static/terms"
>{{ $t('terms') }}</a></span>
</div>
</div>
</footer>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,34 +1,124 @@
<template lang="pug">
.form
.form-group.row.text-center
.col-12.col-md-6
.btn.btn-secondary.social-button(@click='socialAuth("facebook")')
.svg-icon.social-icon(v-html="icons.facebookIcon")
span {{registering ? $t('signUpWithSocial', {social: 'Facebook'}) : $t('loginWithSocial', {social: 'Facebook'})}}
.col-12.col-md-6
.btn.btn-secondary.social-button(@click='socialAuth("google")')
.svg-icon.social-icon(v-html="icons.googleIcon")
span {{registering ? $t('signUpWithSocial', {social: 'Google'}) : $t('loginWithSocial', {social: 'Google'})}}
.form-group(v-if='registering')
label(for='usernameInput', v-once) {{$t('username')}}
input#usernameInput.form-control(type='text', :placeholder='$t("usernamePlaceholder")', v-model='username', :class='{"input-valid": usernameValid, "input-invalid": usernameInvalid}')
.form-group(v-if='!registering')
label(for='usernameInput', v-once) {{$t('emailOrUsername')}}
input#usernameInput.form-control(type='text', :placeholder='$t("emailOrUsername")', v-model='username')
.form-group(v-if='registering')
label(for='emailInput', v-once) {{$t('email')}}
input#emailInput.form-control(type='email', :placeholder='$t("emailPlaceholder")', v-model='email', :class='{"input-invalid": emailInvalid, "input-valid": emailValid}')
.form-group
label(for='passwordInput', v-once) {{$t('password')}}
a.float-right.forgot-password(v-once, v-if='!registering', @click='forgotPassword = true') {{$t('forgotPassword')}}
input#passwordInput.form-control(type='password', :placeholder='$t(registering ? "passwordPlaceholder" : "password")', v-model='password')
.form-group(v-if='registering')
label(for='confirmPasswordInput', v-once) {{$t('confirmPassword')}}
input#confirmPasswordInput.form-control(type='password', :placeholder='$t("confirmPasswordPlaceholder")', v-model='passwordConfirm', :class='{"input-invalid": passwordConfirmInvalid, "input-valid": passwordConfirmValid}')
small.form-text(v-once, v-html="$t('termsAndAgreement')")
.text-center
.btn.btn-info(@click='register()', v-if='registering', v-once) {{$t('joinHabitica')}}
.btn.btn-info(@click='login()', v-if='!registering', v-once) {{$t('login')}}
<template>
<div class="form">
<div class="form-group row text-center">
<div class="col-12 col-md-6">
<div
class="btn btn-secondary social-button"
@click="socialAuth('facebook')"
>
<div
class="svg-icon social-icon"
v-html="icons.facebookIcon"
></div><span>{{ registering ? $t('signUpWithSocial', {social: 'Facebook'}) : $t('loginWithSocial', {social: 'Facebook'}) }}</span>
</div>
</div><div class="col-12 col-md-6">
<div
class="btn btn-secondary social-button"
@click="socialAuth('google')"
>
<div
class="svg-icon social-icon"
v-html="icons.googleIcon"
></div><span>{{ registering ? $t('signUpWithSocial', {social: 'Google'}) : $t('loginWithSocial', {social: 'Google'}) }}</span>
</div>
</div>
</div><div
v-if="registering"
class="form-group"
>
<label
v-once
for="usernameInput"
>{{ $t('username') }}</label><input
id="usernameInput"
v-model="username"
class="form-control"
type="text"
:placeholder="$t('usernamePlaceholder')"
:class="{'input-valid': usernameValid, 'input-invalid': usernameInvalid}"
>
</div><div
v-if="!registering"
class="form-group"
>
<label
v-once
for="usernameInput"
>{{ $t('emailOrUsername') }}</label><input
id="usernameInput"
v-model="username"
class="form-control"
type="text"
:placeholder="$t('emailOrUsername')"
>
</div><div
v-if="registering"
class="form-group"
>
<label
v-once
for="emailInput"
>{{ $t('email') }}</label><input
id="emailInput"
v-model="email"
class="form-control"
type="email"
:placeholder="$t('emailPlaceholder')"
:class="{'input-invalid': emailInvalid, 'input-valid': emailValid}"
>
</div><div class="form-group">
<label
v-once
for="passwordInput"
>{{ $t('password') }}</label><a
v-if="!registering"
v-once
class="float-right forgot-password"
@click="forgotPassword = true"
>{{ $t('forgotPassword') }}</a><input
id="passwordInput"
v-model="password"
class="form-control"
type="password"
:placeholder="$t(registering ? 'passwordPlaceholder' : 'password')"
>
</div><div
v-if="registering"
class="form-group"
>
<label
v-once
for="confirmPasswordInput"
>{{ $t('confirmPassword') }}</label><input
id="confirmPasswordInput"
v-model="passwordConfirm"
class="form-control"
type="password"
:placeholder="$t('confirmPasswordPlaceholder')"
:class="{'input-invalid': passwordConfirmInvalid, 'input-valid': passwordConfirmValid}"
><small
v-once
class="form-text"
v-html="$t('termsAndAgreement')"
></small>
</div><div class="text-center">
<div
v-if="registering"
v-once
class="btn btn-info"
@click="register()"
>
{{ $t('joinHabitica') }}
</div><div
v-if="!registering"
v-once
class="btn btn-info"
@click="login()"
>
{{ $t('login') }}
</div>
</div>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,93 +1,263 @@
<template lang="pug">
.form-wrapper
#top-background
.seamless_stars_varied_opacity_repeat
form#login-form(
@submit.prevent='handleSubmit',
@keyup.enter="handleSubmit",
v-if="!forgotPassword && !resetPasswordSetNewOne",
)
.text-center
div
.svg-icon.gryphon
div
.svg-icon.habitica-logo(v-html="icons.habiticaIcon")
.form-group.row.text-center
.col-12.col-md-6
.btn.btn-secondary.social-button(@click='socialAuth("facebook")')
.svg-icon.social-icon(v-html="icons.facebookIcon")
.text {{registering ? $t('signUpWithSocial', {social: 'Facebook'}) : $t('loginWithSocial', {social: 'Facebook'})}}
.col-12.col-md-6
.btn.btn-secondary.social-button(@click='socialAuth("google")')
.svg-icon.social-icon(v-html="icons.googleIcon")
.text {{registering ? $t('signUpWithSocial', {social: 'Google'}) : $t('loginWithSocial', {social: 'Google'})}}
.form-group(v-if='registering')
label(for='usernameInput', v-once) {{$t('username')}}
input#usernameInput.form-control(type='text', :placeholder='$t("usernamePlaceholder")', v-model='username', :class='{"input-valid": usernameValid, "input-invalid": usernameInvalid}')
.input-error(v-for="issue in usernameIssues") {{ issue }}
.form-group(v-if='!registering')
label(for='usernameInput', v-once) {{$t('emailOrUsername')}}
input#usernameInput.form-control(type='text', :placeholder='$t("emailOrUsername")', v-model='username')
.form-group(v-if='registering')
label(for='emailInput', v-once) {{$t('email')}}
input#emailInput.form-control(type='email', :placeholder='$t("emailPlaceholder")', v-model='email', :class='{"input-invalid": emailInvalid, "input-valid": emailValid}')
.form-group
label(for='passwordInput', v-once) {{$t('password')}}
a.float-right.forgot-password(v-once, v-if='!registering', @click='forgotPassword = true') {{$t('forgotPassword')}}
input#passwordInput.form-control(type='password', :placeholder='$t(registering ? "passwordPlaceholder" : "password")', v-model='password')
.form-group(v-if='registering')
label(for='confirmPasswordInput', v-once) {{$t('confirmPassword')}}
input#confirmPasswordInput.form-control(type='password', :placeholder='$t("confirmPasswordPlaceholder")', v-model='passwordConfirm', :class='{"input-invalid": passwordConfirmInvalid, "input-valid": passwordConfirmValid}')
small.form-text(v-once, v-html="$t('termsAndAgreement')")
.text-center
.btn.btn-info(@click='register()', v-if='registering', v-once) {{$t('joinHabitica')}}
.btn.btn-info(@click='login()', v-if='!registering', v-once) {{$t('login')}}
.toggle-links
router-link(:to="{name: 'login'}", v-if='registering', exact)
a.toggle-link(v-once, v-html="$t('alreadyHaveAccountLogin')")
router-link(:to="{name: 'register'}", v-if='!registering', exact)
a.toggle-link(v-once, v-html="$t('dontHaveAccountSignup')")
form#forgot-form(v-on:submit.prevent='handleSubmit', @keyup.enter="handleSubmit", v-if='forgotPassword')
.text-center
div
.svg-icon.gryphon
div
.svg-icon.habitica-logo(v-html="icons.habiticaIcon")
.header
h2(v-once) {{ $t('emailNewPass') }}
p(v-once) {{ $t('forgotPasswordSteps') }}
.form-group.row.text-center
label(for='usernameInput', v-once) {{$t('email')}}
input#usernameInput.form-control(type='text', :placeholder='$t("emailPlaceholder")', v-model='username')
.text-center
.btn.btn-info(@click='forgotPasswordLink()', v-once) {{$t('sendLink')}}
form#reset-password-set-new-one-form(v-on:submit.prevent='handleSubmit', @keyup.enter="handleSubmit", v-if='resetPasswordSetNewOne')
.text-center
div
.svg-icon.gryphon
div
.svg-icon.habitica-logo(v-html="icons.habiticaIcon")
.header
h2 {{ $t('passwordResetPage') }}
.form-group
label(for='passwordInput', v-once) {{$t('newPass')}}
input#passwordInput.form-control(type='password', :placeholder="$t('password')", v-model='password')
.form-group
label(for='confirmPasswordInput', v-once) {{$t('confirmPass')}}
input#confirmPasswordInput.form-control(type='password', :placeholder='$t("confirmPasswordPlaceholder")', v-model='passwordConfirm')
.text-center
.btn.btn-info(
@click='resetPasswordSetNewOneLink()',
:enabled="!resetPasswordSetNewOneData.hasError"
) {{$t('setNewPass')}}
#bottom-wrap(:class="`bottom-wrap-${!registering ? 'login' : 'register'}`")
#bottom-background
.seamless_mountains_demo_repeat
.midground_foreground_extended2
<template>
<div class="form-wrapper">
<div id="top-background">
<div class="seamless_stars_varied_opacity_repeat"></div>
</div><form
v-if="!forgotPassword && !resetPasswordSetNewOne"
id="login-form"
@submit.prevent="handleSubmit"
@keyup.enter="handleSubmit"
>
<div class="text-center">
<div><div class="svg-icon gryphon"></div></div><div>
<div
class="svg-icon habitica-logo"
v-html="icons.habiticaIcon"
></div>
</div>
</div><div class="form-group row text-center">
<div class="col-12 col-md-6">
<div
class="btn btn-secondary social-button"
@click="socialAuth('facebook')"
>
<div
class="svg-icon social-icon"
v-html="icons.facebookIcon"
></div><div class="text">
{{ registering ? $t('signUpWithSocial', {social: 'Facebook'}) : $t('loginWithSocial', {social: 'Facebook'}) }}
</div>
</div>
</div><div class="col-12 col-md-6">
<div
class="btn btn-secondary social-button"
@click="socialAuth('google')"
>
<div
class="svg-icon social-icon"
v-html="icons.googleIcon"
></div><div class="text">
{{ registering ? $t('signUpWithSocial', {social: 'Google'}) : $t('loginWithSocial', {social: 'Google'}) }}
</div>
</div>
</div>
</div><div
v-if="registering"
class="form-group"
>
<label
v-once
for="usernameInput"
>{{ $t('username') }}</label><input
id="usernameInput"
v-model="username"
class="form-control"
type="text"
:placeholder="$t('usernamePlaceholder')"
:class="{'input-valid': usernameValid, 'input-invalid': usernameInvalid}"
><div
v-for="issue in usernameIssues"
class="input-error"
>
{{ issue }}
</div>
</div><div
v-if="!registering"
class="form-group"
>
<label
v-once
for="usernameInput"
>{{ $t('emailOrUsername') }}</label><input
id="usernameInput"
v-model="username"
class="form-control"
type="text"
:placeholder="$t('emailOrUsername')"
>
</div><div
v-if="registering"
class="form-group"
>
<label
v-once
for="emailInput"
>{{ $t('email') }}</label><input
id="emailInput"
v-model="email"
class="form-control"
type="email"
:placeholder="$t('emailPlaceholder')"
:class="{'input-invalid': emailInvalid, 'input-valid': emailValid}"
>
</div><div class="form-group">
<label
v-once
for="passwordInput"
>{{ $t('password') }}</label><a
v-if="!registering"
v-once
class="float-right forgot-password"
@click="forgotPassword = true"
>{{ $t('forgotPassword') }}</a><input
id="passwordInput"
v-model="password"
class="form-control"
type="password"
:placeholder="$t(registering ? 'passwordPlaceholder' : 'password')"
>
</div><div
v-if="registering"
class="form-group"
>
<label
v-once
for="confirmPasswordInput"
>{{ $t('confirmPassword') }}</label><input
id="confirmPasswordInput"
v-model="passwordConfirm"
class="form-control"
type="password"
:placeholder="$t('confirmPasswordPlaceholder')"
:class="{'input-invalid': passwordConfirmInvalid, 'input-valid': passwordConfirmValid}"
><small
v-once
class="form-text"
v-html="$t('termsAndAgreement')"
></small>
</div><div class="text-center">
<div
v-if="registering"
v-once
class="btn btn-info"
@click="register()"
>
{{ $t('joinHabitica') }}
</div><div
v-if="!registering"
v-once
class="btn btn-info"
@click="login()"
>
{{ $t('login') }}
</div><div class="toggle-links">
<router-link
v-if="registering"
:to="{name: 'login'}"
exact="exact"
>
<a
v-once
class="toggle-link"
v-html="$t('alreadyHaveAccountLogin')"
></a>
</router-link><router-link
v-if="!registering"
:to="{name: 'register'}"
exact="exact"
>
<a
v-once
class="toggle-link"
v-html="$t('dontHaveAccountSignup')"
></a>
</router-link>
</div>
</div>
</form><form
v-if="forgotPassword"
id="forgot-form"
@submit.prevent="handleSubmit"
@keyup.enter="handleSubmit"
>
<div class="text-center">
<div><div class="svg-icon gryphon"></div></div><div>
<div
class="svg-icon habitica-logo"
v-html="icons.habiticaIcon"
></div>
</div><div class="header">
<h2 v-once>
{{ $t('emailNewPass') }}
</h2><p v-once>
{{ $t('forgotPasswordSteps') }}
</p>
</div>
</div><div class="form-group row text-center">
<label
v-once
for="usernameInput"
>{{ $t('email') }}</label><input
id="usernameInput"
v-model="username"
class="form-control"
type="text"
:placeholder="$t('emailPlaceholder')"
>
</div><div class="text-center">
<div
v-once
class="btn btn-info"
@click="forgotPasswordLink()"
>
{{ $t('sendLink') }}
</div>
</div>
</form><form
v-if="resetPasswordSetNewOne"
id="reset-password-set-new-one-form"
@submit.prevent="handleSubmit"
@keyup.enter="handleSubmit"
>
<div class="text-center">
<div><div class="svg-icon gryphon"></div></div><div>
<div
class="svg-icon habitica-logo"
v-html="icons.habiticaIcon"
></div>
</div><div class="header">
<h2>{{ $t('passwordResetPage') }}</h2>
</div>
</div><div class="form-group">
<label
v-once
for="passwordInput"
>{{ $t('newPass') }}</label><input
id="passwordInput"
v-model="password"
class="form-control"
type="password"
:placeholder="$t('password')"
>
</div><div class="form-group">
<label
v-once
for="confirmPasswordInput"
>{{ $t('confirmPass') }}</label><input
id="confirmPasswordInput"
v-model="passwordConfirm"
class="form-control"
type="password"
:placeholder="$t('confirmPasswordPlaceholder')"
>
</div><div class="text-center">
<div
class="btn btn-info"
:enabled="!resetPasswordSetNewOneData.hasError"
@click="resetPasswordSetNewOneLink()"
>
{{ $t('setNewPass') }}
</div>
</div>
</form><div
id="bottom-wrap"
:class="`bottom-wrap-${!registering ? 'login' : 'register'}`"
>
<div id="bottom-background">
<div class="seamless_mountains_demo_repeat"></div><div class="midground_foreground_extended2"></div>
</div>
</div>
</div>
</template>
<style>

View file

@ -1,49 +1,53 @@
<template lang="pug">
.avatar(:style="{width, height, paddingTop}", :class="backgroundClass", @click.prevent='castEnd()')
.character-sprites(:style='{margin: spritesMargin}')
template(v-if="!avatarOnly")
// Mount Body
span(v-if="member.items.currentMount", :class="'Mount_Body_' + member.items.currentMount")
// Buffs that cause visual changes to avatar: Snowman, Ghost, Flower, etc
template(v-for="(klass, item) in visualBuffs")
span(v-if="member.stats.buffs[item] && showVisualBuffs", :class="klass")
// Show flower ALL THE TIME!!!
// See https://github.com/HabitRPG/habitica/issues/7133
span(:class="'hair_flower_' + member.preferences.hair.flower")
// Show avatar only if not currently affected by visual buff
template(v-if="showAvatar()")
span(:class="['chair_' + member.preferences.chair, specialMountClass]")
span(:class="[getGearClass('back'), specialMountClass]")
span(:class="[skinClass, specialMountClass]")
span(
:class="[member.preferences.size + '_shirt_' + member.preferences.shirt, specialMountClass]"
)
span(:class="['head_0', specialMountClass]")
span(:class="[member.preferences.size + '_' + getGearClass('armor'), specialMountClass]")
span(:class="[getGearClass('back_collar'), specialMountClass]")
template(v-for="type in ['bangs', 'base', 'mustache', 'beard']")
// eslint-disable-next-line max-len
span(:class="['hair_' + type + '_' + member.preferences.hair[type] + '_' + member.preferences.hair.color, specialMountClass]")
span(:class="[getGearClass('body'), specialMountClass]")
span(:class="[getGearClass('eyewear'), specialMountClass]")
span(:class="[getGearClass('head'), specialMountClass]")
span(:class="[getGearClass('headAccessory'), specialMountClass]")
span(:class="['hair_flower_' + member.preferences.hair.flower, specialMountClass]")
span(v-if="!hideGear('shield')", :class="[getGearClass('shield'), specialMountClass]")
span(v-if="!hideGear('weapon')", :class="[getGearClass('weapon'), specialMountClass]")
// Resting
span.zzz(v-if="member.preferences.sleep")
template(v-if="!avatarOnly")
// Mount Head
span(v-if="member.items.currentMount", :class="'Mount_Head_' + member.items.currentMount")
// Pet
span.current-pet(v-if="member.items.currentPet", :class="'Pet-' + member.items.currentPet")
class-badge.under-avatar(v-if="hasClass && !hideClassBadge", :member-class="member.stats.class")
<template>
<div
class="avatar"
:style="{width, height, paddingTop}"
:class="backgroundClass"
@click.prevent="castEnd()"
>
<div
class="character-sprites"
:style="{margin: spritesMargin}"
>
<template v-if="!avatarOnly">
<!-- Mount Body--><span
v-if="member.items.currentMount"
:class="'Mount_Body_' + member.items.currentMount"
></span>
</template><!-- Buffs that cause visual changes to avatar: Snowman, Ghost, Flower, etc--><template v-for="(klass, item) in visualBuffs">
<span
v-if="member.stats.buffs[item] && showVisualBuffs"
:class="klass"
></span>
</template><!-- Show flower ALL THE TIME!!!--><!-- See https://github.com/HabitRPG/habitica/issues/7133--><span :class="'hair_flower_' + member.preferences.hair.flower"></span><!-- Show avatar only if not currently affected by visual buff--><template v-if="showAvatar()">
<span :class="['chair_' + member.preferences.chair, specialMountClass]"></span><span :class="[getGearClass('back'), specialMountClass]"></span><span :class="[skinClass, specialMountClass]"></span><span :class="[member.preferences.size + '_shirt_' + member.preferences.shirt, specialMountClass]"></span><span :class="['head_0', specialMountClass]"></span><span :class="[member.preferences.size + '_' + getGearClass('armor'), specialMountClass]"></span><span :class="[getGearClass('back_collar'), specialMountClass]"></span><template v-for="type in ['bangs', 'base', 'mustache', 'beard']">
<!-- eslint-disable-next-line max-len--><span :class="['hair_' + type + '_' + member.preferences.hair[type] + '_' + member.preferences.hair.color, specialMountClass]"></span>
</template><span :class="[getGearClass('body'), specialMountClass]"></span><span :class="[getGearClass('eyewear'), specialMountClass]"></span><span :class="[getGearClass('head'), specialMountClass]"></span><span :class="[getGearClass('headAccessory'), specialMountClass]"></span><span :class="['hair_flower_' + member.preferences.hair.flower, specialMountClass]"></span><span
v-if="!hideGear('shield')"
:class="[getGearClass('shield'), specialMountClass]"
></span><span
v-if="!hideGear('weapon')"
:class="[getGearClass('weapon'), specialMountClass]"
></span>
</template><!-- Resting--><span
v-if="member.preferences.sleep"
class="zzz"
></span><template v-if="!avatarOnly">
<!-- Mount Head--><span
v-if="member.items.currentMount"
:class="'Mount_Head_' + member.items.currentMount"
></span><!-- Pet--><span
v-if="member.items.currentPet"
class="current-pet"
:class="'Pet-' + member.items.currentPet"
></span>
</template>
</div><class-badge
v-if="hasClass && !hideClassBadge"
class="under-avatar"
:member-class="member.stats.class"
/>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,23 +1,31 @@
<template lang="pug">
#body.section.customize-section
sub-menu.text-center(:items="items", :activeSubPage="activeSubPage", @changeSubPage="changeSubPage($event)")
div(v-if='activeSubPage === "size"')
customize-options(
:items="sizes",
:currentValue="user.preferences.size"
)
div(v-if='activeSubPage === "shirt"')
customize-options(
:items="freeShirts",
:currentValue="user.preferences.shirt"
)
customize-options(
v-if='editing',
:items='specialShirts',
:currentValue="user.preferences.shirt",
:fullSet='!userOwnsSet("shirt", specialShirtKeys)',
@unlock='unlock(`shirt.${specialShirtKeys.join(",shirt.")}`)'
)
<template>
<div
id="body"
class="section customize-section"
>
<sub-menu
class="text-center"
:items="items"
:active-sub-page="activeSubPage"
@changeSubPage="changeSubPage($event)"
/><div v-if="activeSubPage === 'size'">
<customize-options
:items="sizes"
:current-value="user.preferences.size"
/>
</div><div v-if="activeSubPage === 'shirt'">
<customize-options
:items="freeShirts"
:current-value="user.preferences.shirt"
/><customize-options
v-if="editing"
:items="specialShirts"
:current-value="user.preferences.shirt"
:full-set="!userOwnsSet('shirt', specialShirtKeys)"
@unlock="unlock(`shirt.${specialShirtKeys.join(',shirt.')}`)"
/>
</div>
</div>
</template>
<script>

View file

@ -1,25 +1,55 @@
<template lang="pug">
.customize-options(:class="{'background-set': fullSet}")
.outer-option-background(
v-for='option in items',
:key='option.key',
@click='option.click(option)',
:class='{locked: option.gemLocked || option.goldLocked, premium: Boolean(option.gem), active: option.active || currentValue === option.key, none: option.none, hide: option.hide }'
)
.option
.sprite.customize-option(:class='option.class')
.redline-outer(v-if="option.none")
.redline
.gem-lock(v-if='option.gemLocked')
.svg-icon.gem(v-html='icons.gem')
span {{ option.gem }}
.gold-lock(v-if='option.goldLocked')
.svg-icon.gold(v-html='icons.gold')
span {{ option.gold }}
.purchase-set(v-if='fullSet', @click='unlock()')
span.label {{ $t('purchaseAll') }}
.svg-icon.gem(v-html='icons.gem')
span.price 5
<template>
<div
class="customize-options"
:class="{'background-set': fullSet}"
>
<div
v-for="option in items"
:key="option.key"
class="outer-option-background"
:class="{locked: option.gemLocked || option.goldLocked, premium: Boolean(option.gem), active: option.active || currentValue === option.key, none: option.none, hide: option.hide }"
@click="option.click(option)"
>
<div class="option">
<div
class="sprite customize-option"
:class="option.class"
>
<div
v-if="option.none"
class="redline-outer"
>
<div class="redline"></div>
</div>
</div>
</div><div
v-if="option.gemLocked"
class="gem-lock"
>
<div
class="svg-icon gem"
v-html="icons.gem"
></div><span>{{ option.gem }}</span>
</div><div
v-if="option.goldLocked"
class="gold-lock"
>
<div
class="svg-icon gold"
v-html="icons.gold"
></div><span>{{ option.gold }}</span>
</div>
</div><div
v-if="fullSet"
class="purchase-set"
@click="unlock()"
>
<span class="label">{{ $t('purchaseAll') }}</span><div
class="svg-icon gem"
v-html="icons.gem"
></div><span class="price">5</span>
</div>
</div>
</template>
<script>

View file

@ -1,38 +1,53 @@
<template lang="pug">
#extra.section.container.customize-section
sub-menu.text-center(:items="extraSubMenuItems", :activeSubPage="activeSubPage", @changeSubPage="changeSubPage($event)")
#hair-color(v-if='activeSubPage === "glasses"')
customize-options(
:items="eyewear"
)
#animal-ears(v-if='activeSubPage === "ears"')
customize-options(
:items="animalItems('headAccessory')",
:fullSet='!animalItemsOwned("headAccessory")',
@unlock='unlock(animalItemsUnlockString("headAccessory"))'
)
#animal-tails(v-if='activeSubPage === "tails"')
customize-options(
:items="animalItems('back')",
:fullSet='!animalItemsOwned("back")',
@unlock='unlock(animalItemsUnlockString("back"))'
)
#headband(v-if='activeSubPage === "headband"')
customize-options(
:items="headbands",
)
#wheelchairs(v-if='activeSubPage === "wheelchair"')
customize-options(
:items="chairs",
)
#flowers(v-if='activeSubPage === "flower"')
customize-options(
:items="flowers",
)
<template>
<div
id="extra"
class="section container customize-section"
>
<sub-menu
class="text-center"
:items="extraSubMenuItems"
:active-sub-page="activeSubPage"
@changeSubPage="changeSubPage($event)"
/><div
v-if="activeSubPage === 'glasses'"
id="hair-color"
>
<customize-options :items="eyewear" />
</div><div
v-if="activeSubPage === 'ears'"
id="animal-ears"
>
<customize-options
:items="animalItems('headAccessory')"
:full-set="!animalItemsOwned('headAccessory')"
@unlock="unlock(animalItemsUnlockString('headAccessory'))"
/>
</div><div
v-if="activeSubPage === 'tails'"
id="animal-tails"
>
<customize-options
:items="animalItems('back')"
:full-set="!animalItemsOwned('back')"
@unlock="unlock(animalItemsUnlockString('back'))"
/>
</div><div
v-if="activeSubPage === 'headband'"
id="headband"
>
<customize-options :items="headbands" />
</div><div
v-if="activeSubPage === 'wheelchair'"
id="wheelchairs"
>
<customize-options :items="chairs" />
</div><div
v-if="activeSubPage === 'flower'"
id="flowers"
>
<customize-options :items="flowers" />
</div>
</div>
</template>
<script>

View file

@ -1,44 +1,65 @@
<template lang="pug">
#hair.section.customize-section
sub-menu.text-center(:items="hairSubMenuItems", :activeSubPage="activeSubPage", @changeSubPage="changeSubPage($event)")
#hair-color(v-if='activeSubPage === "color"')
customize-options(
:items="freeHairColors",
:currentValue="user.preferences.hair.color"
)
div(v-if='editing && set.key !== "undefined"', v-for='set in seasonalHairColors')
customize-options(
:items='set.options',
:currentValue="user.preferences.skin",
:fullSet='!hideSet(set) && !userOwnsSet("hair", set.keys, "color")',
@unlock='unlock(`hair.color.${set.keys.join(",hair.color.")}`)'
)
#style(v-if='activeSubPage === "style"')
div(v-for='set in styleSets')
customize-options(
:items='set.options',
:fullSet='set.fullSet',
@unlock='set.unlock()'
)
#bangs(v-if='activeSubPage === "bangs"')
customize-options(
:items='hairBangs',
:currentValue="user.preferences.hair.bangs"
)
#facialhair(v-if='activeSubPage === "facialhair"')
customize-options(
v-if='editing',
:items='mustacheList'
)
customize-options(
v-if='editing',
:items='beardList',
:fullSet='isPurchaseAllNeeded("hair", ["baseHair5", "baseHair6"], ["mustache", "beard"])',
@unlock='unlock(`hair.mustache.${baseHair5Keys.join(",hair.mustache.")},hair.beard.${baseHair6Keys.join(",hair.beard.")}`)'
)
<template>
<div
id="hair"
class="section customize-section"
>
<sub-menu
class="text-center"
:items="hairSubMenuItems"
:active-sub-page="activeSubPage"
@changeSubPage="changeSubPage($event)"
/><div
v-if="activeSubPage === 'color'"
id="hair-color"
>
<customize-options
:items="freeHairColors"
:current-value="user.preferences.hair.color"
/><div
v-for="set in seasonalHairColors"
v-if="editing && set.key !== 'undefined'"
>
<customize-options
:items="set.options"
:current-value="user.preferences.skin"
:full-set="!hideSet(set) && !userOwnsSet('hair', set.keys, 'color')"
@unlock="unlock(`hair.color.${set.keys.join(',hair.color.')}`)"
/>
</div>
</div><div
v-if="activeSubPage === 'style'"
id="style"
>
<div v-for="set in styleSets">
<customize-options
:items="set.options"
:full-set="set.fullSet"
@unlock="set.unlock()"
/>
</div>
</div><div
v-if="activeSubPage === 'bangs'"
id="bangs"
>
<customize-options
:items="hairBangs"
:current-value="user.preferences.hair.bangs"
/>
</div><div
v-if="activeSubPage === 'facialhair'"
id="facialhair"
>
<customize-options
v-if="editing"
:items="mustacheList"
/><customize-options
v-if="editing"
:items="beardList"
:full-set="isPurchaseAllNeeded('hair', ['baseHair5', 'baseHair6'], ['mustache', 'beard'])"
@unlock="unlock(`hair.mustache.${baseHair5Keys.join(',hair.mustache.')},hair.beard.${baseHair6Keys.join(',hair.beard.')}`)"
/>
</div>
</div>
</template>
<script>

View file

@ -1,18 +1,28 @@
<template lang="pug">
#skin.section.customize-section
sub-menu.text-center(:items="skinSubMenuItems", :activeSubPage="activeSubPage", @changeSubPage="changeSubPage($event)")
customize-options(
:items="freeSkins",
:currentValue="user.preferences.skin"
)
div(v-if='editing && set.key !== "undefined"', v-for='set in seasonalSkins')
customize-options(
:items='set.options',
:currentValue="user.preferences.skin",
:fullSet='!hideSet(set) && !userOwnsSet("skin", set.keys)',
@unlock='unlock(`skin.${set.keys.join(",skin.")}`)'
)
<template>
<div
id="skin"
class="section customize-section"
>
<sub-menu
class="text-center"
:items="skinSubMenuItems"
:active-sub-page="activeSubPage"
@changeSubPage="changeSubPage($event)"
/><customize-options
:items="freeSkins"
:current-value="user.preferences.skin"
/><div
v-for="set in seasonalSkins"
v-if="editing && set.key !== 'undefined'"
>
<customize-options
:items="set.options"
:current-value="user.preferences.skin"
:full-set="!hideSet(set) && !userOwnsSet('skin', set.keys)"
@unlock="unlock(`skin.${set.keys.join(',skin.')}`)"
/>
</div>
</div>
</template>
<script>

View file

@ -1,12 +1,15 @@
<template lang="pug">
.sub-menu.text-center
.sub-menu-item(
v-for="item of items",
:key="item.id",
@click='$emit("changeSubPage", item.id)',
:class='{active: activeSubPage === item.id}'
)
strong(v-once) {{ item.label }}
<template>
<div class="sub-menu text-center">
<div
v-for="item of items"
:key="item.id"
class="sub-menu-item"
:class="{active: activeSubPage === item.id}"
@click="$emit('changeSubPage', item.id)"
>
<strong v-once>{{ item.label }}</strong>
</div>
</div>
</template>
<script>

View file

@ -1,12 +1,27 @@
<template lang="pug">
b-modal#banned-account(:title="$t('accountSuspendedTitle')", size='md', :hide-footer="true")
.modal-body
.row
.col-12
p(v-markdown='bannedMessage')
.modal-footer
.col-12.text-center
button.btn.btn-primary(@click='close()') {{$t('close')}}
<template>
<b-modal
id="banned-account"
:title="$t('accountSuspendedTitle')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="row">
<div class="col-12">
<p v-markdown="bannedMessage"></p>
</div>
</div>
</div><div class="modal-footer">
<div class="col-12 text-center">
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('close') }}
</button>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,15 +1,17 @@
<template lang="pug">
.categories
span.category-label.category-label-blue(v-if='owner')
| {{ $t('owned') }}
span.category-label.category-label-green(v-if='member')
| {{ $t('joined') }}
span.category-label(
v-for='category in categories',
<template>
<div class="categories">
<span
v-if="owner"
class="category-label category-label-blue"
>{{ $t('owned') }}</span><span
v-if="member"
class="category-label category-label-green"
>{{ $t('joined') }}</span><span
v-for="category in categories"
class="category-label"
:class="{'category-label-purple':isOfficial(category)}"
)
| {{ $t(category.name) }}
slot
>{{ $t(category.name) }}</span><slot></slot>
</div>
</template>
<script>

View file

@ -1,84 +1,174 @@
<template lang="pug">
.row
challenge-modal(@updatedChallenge='updatedChallenge')
leave-challenge-modal(:challengeId='challenge._id')
close-challenge-modal(:members='members', :challengeId='challenge._id', :prize='challenge.prize')
challenge-member-progress-modal(:challengeId='challenge._id')
.col-12.col-md-8.standard-page
.row
.col-12.col-md-6
h1(v-markdown='challenge.name')
div
span.mr-1.ml-0.d-block
strong(v-once) {{ $t('createdBy') }}:
user-link.mx-1(:user="challenge.leader")
span.mr-1.ml-0.d-block(v-if="challenge.group && challenge.group.name !== 'Tavern'")
strong(v-once) {{ $t(challenge.group.type) }}:
group-link.mx-1(:group="challenge.group")
// @TODO: make challenge.author a variable inside the createdBy string (helps with RTL languages)
// @TODO: Implement in V2 strong.margin-left(v-once)
.svg-icon.calendar-icon(v-html="icons.calendarIcon")
| {{$t('endDate')}}
// "endDate": "End Date: <% endDate %>",
// span {{challenge.endDate}}
.tags
span.tag(v-for='tag in challenge.tags') {{tag}}
.col-12.col-md-6.text-right
.box(@click="showMemberModal()")
.svg-icon.member-icon(v-html="icons.memberIcon")
| {{challenge.memberCount}}
.details(v-once) {{$t('participantsTitle')}}
.box
.svg-icon.gem-icon(v-html="icons.gemIcon")
| {{challenge.prize}}
.details(v-once) {{$t('prize')}}
.row.challenge-actions
.col-12.col-md-6
strong.view-progress {{ $t('viewProgressOf') }}
member-search-dropdown(:text="$t('selectParticipant')", :members='members', :challengeId='challengeId', @member-selected='openMemberProgressModal')
.col-12.col-md-6.text-right
span(v-if='isLeader || isAdmin')
b-dropdown.create-dropdown(:text="$t('addTaskToChallenge')", :variant="'success'")
b-dropdown-item(v-for="type in columns", :key="type", @click="createTask(type)")
| {{$t(type)}}
task-modal(
:task="workingTask",
:purpose="taskFormPurpose",
@cancel="cancelTaskModal()",
ref="taskModal",
:challengeId="challengeId",
@taskCreated='taskCreated',
@taskEdited='taskEdited',
@taskDestroyed='taskDestroyed'
)
.row
task-column.col-12.col-sm-6(
v-for="column in columns",
:type="column",
:key="column",
:taskListOverride='tasksByType[column]',
:showOptions="showOptions",
@editTask="editTask",
@taskDestroyed="taskDestroyed",
v-if='tasksByType[column].length > 0')
.col-12.col-md-4.sidebar.standard-page
.button-container(v-if='canJoin')
button.btn.btn-success(v-once, @click='joinChallenge()') {{$t('joinChallenge')}}
.button-container(v-if='isLeader || isAdmin')
button.btn.btn-primary(v-once, @click='edit()') {{$t('editChallenge')}}
.button-container(v-if='isLeader || isAdmin')
button.btn.btn-primary(v-once, @click='cloneChallenge()') {{$t('clone')}}
.button-container(v-if='isLeader || isAdmin')
button.btn.btn-primary(v-once, @click='exportChallengeCsv()') {{$t('exportChallengeCsv')}}
.button-container(v-if='isLeader || isAdmin')
button.btn.btn-danger(v-once, @click='closeChallenge()') {{$t('endChallenge')}}
div
sidebar-section(:title="$t('challengeSummary')")
p(v-markdown='challenge.summary')
sidebar-section(:title="$t('challengeDescription')")
p(v-markdown='challenge.description')
.text-center(v-if='isMember')
button.btn.btn-danger(v-once, @click='leaveChallenge()') {{$t('leaveChallenge')}}
<template>
<div class="row">
<challenge-modal @updatedChallenge="updatedChallenge" /><leave-challenge-modal :challenge-id="challenge._id" /><close-challenge-modal
:members="members"
:challenge-id="challenge._id"
:prize="challenge.prize"
/><challenge-member-progress-modal :challenge-id="challenge._id" /><div class="col-12 col-md-8 standard-page">
<div class="row">
<div class="col-12 col-md-6">
<h1 v-markdown="challenge.name"></h1><div>
<span class="mr-1 ml-0 d-block"><strong v-once>{{ $t('createdBy') }}:</strong><user-link
class="mx-1"
:user="challenge.leader"
/></span><span
v-if="challenge.group && challenge.group.name !== 'Tavern'"
class="mr-1 ml-0 d-block"
><strong v-once>{{ $t(challenge.group.type) }}:</strong><group-link
class="mx-1"
:group="challenge.group"
/></span><!-- @TODO: make challenge.author a variable inside the createdBy string (helps with RTL languages)--><!-- @TODO: Implement in V2 strong.margin-left(v-once).svg-icon.calendar-icon(v-html="icons.calendarIcon")
| {{$t('endDate')}}
// "endDate": "End Date: <% endDate %>",--><!-- span {{challenge.endDate}}-->
</div><div class="tags">
<span
v-for="tag in challenge.tags"
class="tag"
>{{ tag }}</span>
</div>
</div><div class="col-12 col-md-6 text-right">
<div
class="box"
@click="showMemberModal()"
>
<div
class="svg-icon member-icon"
v-html="icons.memberIcon"
></div>{{ challenge.memberCount }}<div
v-once
class="details"
>
{{ $t('participantsTitle') }}
</div>
</div><div class="box">
<div
class="svg-icon gem-icon"
v-html="icons.gemIcon"
></div>{{ challenge.prize }}<div
v-once
class="details"
>
{{ $t('prize') }}
</div>
</div>
</div>
</div><div class="row challenge-actions">
<div class="col-12 col-md-6">
<strong class="view-progress">{{ $t('viewProgressOf') }}</strong><member-search-dropdown
:text="$t('selectParticipant')"
:members="members"
:challenge-id="challengeId"
@member-selected="openMemberProgressModal"
/>
</div><div class="col-12 col-md-6 text-right">
<span v-if="isLeader || isAdmin"><b-dropdown
class="create-dropdown"
:text="$t('addTaskToChallenge')"
:variant="'success'"
><b-dropdown-item
v-for="type in columns"
:key="type"
@click="createTask(type)"
>{{ $t(type) }}</b-dropdown-item></b-dropdown><task-modal
ref="taskModal"
:task="workingTask"
:purpose="taskFormPurpose"
:challenge-id="challengeId"
@cancel="cancelTaskModal()"
@taskCreated="taskCreated"
@taskEdited="taskEdited"
@taskDestroyed="taskDestroyed"
/></span>
</div>
</div><div class="row">
<task-column
v-for="column in columns"
v-if="tasksByType[column].length > 0"
:key="column"
class="col-12 col-sm-6"
:type="column"
:task-list-override="tasksByType[column]"
:show-options="showOptions"
@editTask="editTask"
@taskDestroyed="taskDestroyed"
/>
</div>
</div><div class="col-12 col-md-4 sidebar standard-page">
<div
v-if="canJoin"
class="button-container"
>
<button
v-once
class="btn btn-success"
@click="joinChallenge()"
>
{{ $t('joinChallenge') }}
</button>
</div><div
v-if="isLeader || isAdmin"
class="button-container"
>
<button
v-once
class="btn btn-primary"
@click="edit()"
>
{{ $t('editChallenge') }}
</button>
</div><div
v-if="isLeader || isAdmin"
class="button-container"
>
<button
v-once
class="btn btn-primary"
@click="cloneChallenge()"
>
{{ $t('clone') }}
</button>
</div><div
v-if="isLeader || isAdmin"
class="button-container"
>
<button
v-once
class="btn btn-primary"
@click="exportChallengeCsv()"
>
{{ $t('exportChallengeCsv') }}
</button>
</div><div
v-if="isLeader || isAdmin"
class="button-container"
>
<button
v-once
class="btn btn-danger"
@click="closeChallenge()"
>
{{ $t('endChallenge') }}
</button>
</div><div>
<sidebar-section :title="$t('challengeSummary')">
<p v-markdown="challenge.summary"></p>
</sidebar-section><sidebar-section :title="$t('challengeDescription')">
<p v-markdown="challenge.description"></p>
</sidebar-section>
</div><div
v-if="isMember"
class="text-center"
>
<button
v-once
class="btn btn-danger"
@click="leaveChallenge()"
>
{{ $t('leaveChallenge') }}
</button>
</div>
</div>
</div>
</template>
<style lang='scss' scoped>

View file

@ -1,42 +1,84 @@
<template lang="pug">
.challenge
.challenge-prize
.number
span.svg-icon(v-html="icons.gemIcon")
span.value {{challenge.prize}}
.label {{ $t('prize') }}
.challenge-header
router-link(
:to="{ name: 'challenge', params: { challengeId: challenge._id } }"
)
h3.challenge-title(v-markdown='challenge.name')
.meta-info
.member-count
.svg-icon.user-icon(v-html="icons.memberIcon")
span.count-label {{challenge.memberCount}}
.divider
.official(v-if="isOfficial")
.svg-icon.user-icon(v-html="icons.officialIcon")
.owner(v-if="fullLayout")
.owner-item
strong {{ $t('createdBy') }}:
user-link.mx-1(:user="challenge.leader")
.owner-item(v-if="challenge.group && !isTavern(challenge.group)")
strong {{ $t(challenge.group.type) }}:
group-link.mx-1(:group="challenge.group")
category-tags.challenge-categories(
:categories="challenge.categories",
:owner="isOwner",
:member="isMember",
)
.challenge-description(v-markdown='challenge.summary')
.well-wrapper(v-if="fullLayout")
.well
div(v-for="task in tasksData", :class="{'muted': task.value === 0}")
.number
.svg-icon(v-html="task.icon", :class="task.label + '-icon'")
span.value {{ task.value }}
.label {{$t(task.label)}}
<template>
<div class="challenge">
<div class="challenge-prize">
<div class="number">
<span
class="svg-icon"
v-html="icons.gemIcon"
></span><span class="value">{{ challenge.prize }}</span>
</div><div class="label">
{{ $t('prize') }}
</div>
</div><div class="challenge-header">
<router-link :to="{ name: 'challenge', params: { challengeId: challenge._id } }">
<h3
v-markdown="challenge.name"
class="challenge-title"
></h3>
</router-link><div class="meta-info">
<div class="member-count">
<div
class="svg-icon user-icon"
v-html="icons.memberIcon"
></div><span class="count-label">{{ challenge.memberCount }}</span>
</div><div class="divider"></div><div
v-if="isOfficial"
class="official"
>
<div
class="svg-icon user-icon"
v-html="icons.officialIcon"
></div>
</div><div
v-if="fullLayout"
class="owner"
>
<div class="owner-item">
<strong>{{ $t('createdBy') }}:</strong><user-link
class="mx-1"
:user="challenge.leader"
/>
</div><div
v-if="challenge.group && !isTavern(challenge.group)"
class="owner-item"
>
<strong>{{ $t(challenge.group.type) }}:</strong><group-link
class="mx-1"
:group="challenge.group"
/>
</div>
</div>
</div>
</div><category-tags
class="challenge-categories"
:categories="challenge.categories"
:owner="isOwner"
:member="isMember"
/><div
v-markdown="challenge.summary"
class="challenge-description"
></div><div
v-if="fullLayout"
class="well-wrapper"
>
<div class="well">
<div
v-for="task in tasksData"
:class="{'muted': task.value === 0}"
>
<div class="number">
<div
class="svg-icon"
:class="task.label + '-icon'"
v-html="task.icon"
></div><span class="value">{{ task.value }}</span>
</div><div class="label">
{{ $t(task.label) }}
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss">

View file

@ -1,14 +1,32 @@
<template lang="pug">
b-modal#challenge-member-modal(title="User Progress", size='lg')
.row.award-row(v-if='isLeader || isAdmin')
.col-12.text-center
button.btn.btn-primary(v-once, @click='closeChallenge()') {{ $t('awardWinners') }}
.row
task-column.col-6(
v-for="column in columns",
:type="column",
:key="column",
:taskListOverride='tasksByType[column]')
<template>
<b-modal
id="challenge-member-modal"
title="User Progress"
size="lg"
>
<div
v-if="isLeader || isAdmin"
class="row award-row"
>
<div class="col-12 text-center">
<button
v-once
class="btn btn-primary"
@click="closeChallenge()"
>
{{ $t('awardWinners') }}
</button>
</div>
</div><div class="row">
<task-column
v-for="column in columns"
:key="column"
class="col-6"
:type="column"
:task-list-override="tasksByType[column]"
/>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,66 +1,152 @@
<template lang="pug">
b-modal#challenge-modal(:title="title", size='lg', @shown="shown")
.form
.form-group
label
strong(v-once) {{$t('name')}} *
b-form-input(type="text", :placeholder="$t('challengeNamePlaceholder')", v-model="workingChallenge.name")
.form-group
label
strong(v-once) {{$t('shortName')}} *
b-form-input(type="text", :placeholder="$t('shortNamePlaceholder')", v-model="workingChallenge.shortName")
.form-group
label
strong(v-once) {{$t('challengeSummary')}} *
div.summary-count {{ $t('charactersRemaining', {characters: charactersRemaining}) }}
textarea.summary-textarea.form-control(:placeholder="$t('challengeSummaryPlaceholder')", v-model="workingChallenge.summary")
.form-group
label
strong(v-once) {{$t('challengeDescription')}} *
a.float-right(v-markdown='$t("markdownFormattingHelp")')
textarea.description-textarea.form-control(:placeholder="$t('challengeDescriptionPlaceholder')", v-model="workingChallenge.description")
.form-group(v-if='creating')
label
strong(v-once) {{$t('challengeGuild')}} *
select.form-control(v-model='workingChallenge.group')
option(v-for='group in groups', :value='group._id') {{group.name}}
.form-group(v-if='workingChallenge.categories')
label
strong(v-once) {{$t('categories')}} *
div.category-wrap(@click.prevent="toggleCategorySelect")
span.category-select(v-if='workingChallenge.categories.length === 0') {{$t('none')}}
.category-label(v-for='category in workingChallenge.categories') {{$t(categoriesHashByKey[category])}}
.category-box(v-if="showCategorySelect && creating")
.form-check(
v-for="group in categoryOptions",
:key="group.key",
v-if='group.key !== "habitica_official" || user.contributor.admin'
)
.custom-control.custom-checkbox
input.custom-control-input(type="checkbox",
:value="group.key",
:id="`challenge-modal-cat-${group.key}`",
v-model="workingChallenge.categories")
label.custom-control-label(v-once, :for="`challenge-modal-cat-${group.key}`") {{ $t(group.label) }}
button.btn.btn-primary(@click.prevent="toggleCategorySelect") {{$t('close')}}
// @TODO: Implement in V2 .form-group
label
strong(v-once) {{$t('endDate')}}
b-form-input.end-date-input
.form-group(v-if='creating')
label
strong(v-once) {{$t('prize')}}
input(type='number', :min='minPrize', :max='maxPrize', v-model="workingChallenge.prize")
.row.footer-wrap
.col-12.text-center.submit-button-wrapper
.alert.alert-warning(v-if='insufficientGemsForTavernChallenge') You do not have enough gems to create a Tavern challenge
// @TODO if buy gems button is added, add analytics tracking to it
// see https://github.com/HabitRPG/habitica/blob/develop/website/views/options/social/challenges.jade#L134
button.btn.btn-primary(v-if='creating && !cloning', @click='createChallenge()', :disabled='loading') {{$t('createChallengeAddTasks')}}
button.btn.btn-primary(v-once, v-if='cloning', @click='createChallenge()', :disabled='loading') {{$t('createChallengeCloneTasks')}}
button.btn.btn-primary(v-once, v-if='!creating && !cloning', @click='updateChallenge()') {{$t('updateChallenge')}}
.col-12.text-center
p(v-once) {{$t('challengeMinimum')}}
<template>
<b-modal
id="challenge-modal"
:title="title"
size="lg"
@shown="shown"
>
<div class="form">
<div class="form-group">
<label><strong v-once>{{ $t('name') }} *</strong></label><b-form-input
v-model="workingChallenge.name"
type="text"
:placeholder="$t('challengeNamePlaceholder')"
/>
</div><div class="form-group">
<label><strong v-once>{{ $t('shortName') }} *</strong></label><b-form-input
v-model="workingChallenge.shortName"
type="text"
:placeholder="$t('shortNamePlaceholder')"
/>
</div><div class="form-group">
<label><strong v-once>{{ $t('challengeSummary') }} *</strong></label><div class="summary-count">
{{ $t('charactersRemaining', {characters: charactersRemaining}) }}
</div><textarea
v-model="workingChallenge.summary"
class="summary-textarea form-control"
:placeholder="$t('challengeSummaryPlaceholder')"
></textarea>
</div><div class="form-group">
<label><strong v-once>{{ $t('challengeDescription') }} *</strong></label><a
v-markdown="$t('markdownFormattingHelp')"
class="float-right"
></a><textarea
v-model="workingChallenge.description"
class="description-textarea form-control"
:placeholder="$t('challengeDescriptionPlaceholder')"
></textarea>
</div><div
v-if="creating"
class="form-group"
>
<label><strong v-once>{{ $t('challengeGuild') }} *</strong></label><select
v-model="workingChallenge.group"
class="form-control"
>
<option
v-for="group in groups"
:value="group._id"
>
{{ group.name }}
</option>
</select>
</div><div
v-if="workingChallenge.categories"
class="form-group"
>
<label><strong v-once>{{ $t('categories') }} *</strong></label><div
class="category-wrap"
@click.prevent="toggleCategorySelect"
>
<span
v-if="workingChallenge.categories.length === 0"
class="category-select"
>{{ $t('none') }}</span><div
v-for="category in workingChallenge.categories"
class="category-label"
>
{{ $t(categoriesHashByKey[category]) }}
</div>
</div><div
v-if="showCategorySelect && creating"
class="category-box"
>
<div
v-for="group in categoryOptions"
v-if="group.key !== 'habitica_official' || user.contributor.admin"
:key="group.key"
class="form-check"
>
<div class="custom-control custom-checkbox">
<input
:id="`challenge-modal-cat-${group.key}`"
v-model="workingChallenge.categories"
class="custom-control-input"
type="checkbox"
:value="group.key"
><label
v-once
class="custom-control-label"
:for="`challenge-modal-cat-${group.key}`"
>{{ $t(group.label) }}</label>
</div>
</div><button
class="btn btn-primary"
@click.prevent="toggleCategorySelect"
>
{{ $t('close') }}
</button>
</div>
</div><!-- @TODO: Implement in V2 .form-grouplabel
strong(v-once) {{$t('endDate')}}
b-form-input.end-date-input--><div
v-if="creating"
class="form-group"
>
<label><strong v-once>{{ $t('prize') }}</strong></label><input
v-model="workingChallenge.prize"
type="number"
:min="minPrize"
:max="maxPrize"
>
</div><div class="row footer-wrap">
<div class="col-12 text-center submit-button-wrapper">
<div
v-if="insufficientGemsForTavernChallenge"
class="alert alert-warning"
>
You do not have enough gems to create a Tavern challenge
</div><!-- @TODO if buy gems button is added, add analytics tracking to it--><!-- see https://github.com/HabitRPG/habitica/blob/develop/website/views/options/social/challenges.jade#L134--><button
v-if="creating && !cloning"
class="btn btn-primary"
:disabled="loading"
@click="createChallenge()"
>
{{ $t('createChallengeAddTasks') }}
</button><button
v-if="cloning"
v-once
class="btn btn-primary"
:disabled="loading"
@click="createChallenge()"
>
{{ $t('createChallengeCloneTasks') }}
</button><button
v-if="!creating && !cloning"
v-once
class="btn btn-primary"
@click="updateChallenge()"
>
{{ $t('updateChallenge') }}
</button>
</div><div class="col-12 text-center">
<p v-once>
{{ $t('challengeMinimum') }}
</p>
</div>
</div>
</div>
</b-modal>
</template>
<style lang='scss'>
@ -245,8 +331,8 @@ export default {
return this.$t('editingChallenge');
},
charactersRemaining () {
const currentLength = this.workingChallenge.summary
? this.workingChallenge.summary.length
const currentLength = this.workingChallenge.summary
? this.workingChallenge.summary.length
: 0;
return MAX_SUMMARY_SIZE_FOR_CHALLENGES - currentLength;
},

View file

@ -1,26 +1,63 @@
<template lang="pug">
div
b-modal#close-challenge-modal(:title="$t('createGuild')", size='md')
.header-wrap(slot="modal-header")
h2.text-center(v-once) {{$t('endChallenge')}}
.row.text-center
.col-12
.support-habitica
// @TODO: Add challenge achievement badge here
.col-12
strong(v-once) {{$t('selectChallengeWinnersDescription')}}
.col-12
member-search-dropdown(:text='winnerText', :members='members', :challengeId='challengeId', @member-selected='selectMember')
.col-12
button.btn.btn-primary(v-once, @click='closeChallenge') {{$t('awardWinners')}}
.col-12
hr
.or {{$t('or')}}
.col-12
strong(v-once) {{$t('doYouWantedToDeleteChallenge')}}
.col-12
button.btn.btn-danger(v-once, @click='deleteChallenge()') {{$t('deleteChallenge')}}
.footer-wrap(slot="modal-footer")
<template>
<div>
<b-modal
id="close-challenge-modal"
:title="$t('createGuild')"
size="md"
>
<div
slot="modal-header"
class="header-wrap"
>
<h2
v-once
class="text-center"
>
{{ $t('endChallenge') }}
</h2>
</div><div class="row text-center">
<div class="col-12">
<div class="support-habitica">
<!-- @TODO: Add challenge achievement badge here-->
</div>
</div><div class="col-12">
<strong v-once>{{ $t('selectChallengeWinnersDescription') }}</strong>
</div><div class="col-12">
<member-search-dropdown
:text="winnerText"
:members="members"
:challenge-id="challengeId"
@member-selected="selectMember"
/>
</div><div class="col-12">
<button
v-once
class="btn btn-primary"
@click="closeChallenge"
>
{{ $t('awardWinners') }}
</button>
</div><div class="col-12">
<hr><div class="or">
{{ $t('or') }}
</div>
</div><div class="col-12">
<strong v-once>{{ $t('doYouWantedToDeleteChallenge') }}</strong>
</div><div class="col-12">
<button
v-once
class="btn btn-danger"
@click="deleteChallenge()"
>
{{ $t('deleteChallenge') }}
</button>
</div>
</div><div
slot="modal-footer"
class="footer-wrap"
></div>
</b-modal>
</div>
</template>
<style lang='scss'>

View file

@ -1,33 +1,57 @@
<template lang="pug">
.row
challenge-modal(v-on:createChallenge='challengeCreated')
sidebar(v-on:search="updateSearch", v-on:filter="updateFilters")
.col-12.col-md-10.standard-page
.row.header-row
.col-md-8.text-left
h1(v-once) {{$t('findChallenges')}}
.col-md-4
// @TODO: implement sorting span.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
button.btn.btn-secondary.create-challenge-button.float-right(@click='createChallenge()')
.svg-icon.positive-icon(v-html="icons.positiveIcon")
span(v-once) {{$t('createChallenge')}}
.row
.no-challenges.text-center.col-md-6.offset-3(v-if='!loading && filteredChallenges.length === 0')
h2(v-once) {{$t('noChallengeMatchFilters')}}
.row
.col-12.col-md-6(v-for='challenge in filteredChallenges')
challenge-item(:challenge='challenge')
mugen-scroll(
:handler="infiniteScrollTrigger",
:should-handle="!loading && canLoadMore",
:threshold="1",
v-show="loading",
)
h2.col-12.loading(v-once) {{ $t('loading') }}
<template>
<div class="row">
<challenge-modal @createChallenge="challengeCreated" /><sidebar
@search="updateSearch"
@filter="updateFilters"
/><div class="col-12 col-md-10 standard-page">
<div class="row header-row">
<div class="col-md-8 text-left">
<h1 v-once>
{{ $t('findChallenges') }}
</h1>
</div><div class="col-md-4">
<!-- @TODO: implement sorting span.dropdown-label {{ $t('sortBy') }}b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}--><button
class="btn btn-secondary create-challenge-button float-right"
@click="createChallenge()"
>
<div
class="svg-icon positive-icon"
v-html="icons.positiveIcon"
></div><span v-once>{{ $t('createChallenge') }}</span>
</button>
</div>
</div><div class="row">
<div
v-if="!loading && filteredChallenges.length === 0"
class="no-challenges text-center col-md-6 offset-3"
>
<h2 v-once>
{{ $t('noChallengeMatchFilters') }}
</h2>
</div>
</div><div class="row">
<div
v-for="challenge in filteredChallenges"
class="col-12 col-md-6"
>
<challenge-item :challenge="challenge" />
</div><mugen-scroll
v-show="loading"
:handler="infiniteScrollTrigger"
:should-handle="!loading && canLoadMore"
:threshold="1"
>
<h2
v-once
class="col-12 loading"
>
{{ $t('loading') }}
</h2>
</mugen-scroll>
</div>
</div>
</div>
</template>
<style lang='scss' scoped>

View file

@ -1,16 +1,43 @@
<template lang="pug">
div
challenge-modal(:groupId='groupId', v-on:createChallenge='challengeCreated')
.row.no-quest-section(v-if='challenges.length === 0')
.col-12.text-center
.svg-icon.challenge-icon(v-html="icons.challengeIcon")
h4(v-once) {{ $t('haveNoChallenges') }}
p(v-once) {{ $t('challengeDetails') }}
button.btn.btn-secondary(@click='createChallenge()') {{ $t('createChallenge') }}
template(v-else)
challenge-item(v-for='challenge in challenges',:challenge='challenge',:key='challenge._id',:fullLayout='false')
.col-12.text-center
button.btn.btn-secondary(@click='createChallenge()') {{ $t('createChallenge') }}
<template>
<div>
<challenge-modal
:group-id="groupId"
@createChallenge="challengeCreated"
/><div
v-if="challenges.length === 0"
class="row no-quest-section"
>
<div class="col-12 text-center">
<div
class="svg-icon challenge-icon"
v-html="icons.challengeIcon"
></div><h4 v-once>
{{ $t('haveNoChallenges') }}
</h4><p v-once>
{{ $t('challengeDetails') }}
</p><button
class="btn btn-secondary"
@click="createChallenge()"
>
{{ $t('createChallenge') }}
</button>
</div>
</div><template v-else>
<challenge-item
v-for="challenge in challenges"
:key="challenge._id"
:challenge="challenge"
:full-layout="false"
/><div class="col-12 text-center">
<button
class="btn btn-secondary"
@click="createChallenge()"
>
{{ $t('createChallenge') }}
</button>
</div>
</template>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,11 +1,23 @@
<template lang="pug">
.row
secondary-menu.col-12
router-link.nav-link(:to="{name: 'myChallenges'}", :class="{'active': $route.name === 'myChallenges'}") {{ $t('myChallenges') }}
router-link.nav-link(:to="{name: 'findChallenges'}", :class="{'active': $route.name === 'findChallenges'}") {{ $t('findChallenges') }}
.col-12
router-view
<template>
<div class="row">
<secondary-menu class="col-12">
<router-link
class="nav-link"
:to="{name: 'myChallenges'}"
:class="{'active': $route.name === 'myChallenges'}"
>
{{ $t('myChallenges') }}
</router-link><router-link
class="nav-link"
:to="{name: 'findChallenges'}"
:class="{'active': $route.name === 'findChallenges'}"
>
{{ $t('findChallenges') }}
</router-link>
</secondary-menu><div class="col-12">
<router-view />
</div>
</div>
</template>
<script>

View file

@ -1,10 +1,26 @@
<template lang="pug">
b-modal#leave-challenge-modal(:title="$t('leaveChallenge')", size='sm', :hide-footer="true")
.modal-body
h2 {{ $t('confirmKeepChallengeTasks') }}
div
button.btn.btn-primary(@click='leaveChallenge("keep")') {{ $t('keepThem') }}
button.btn.btn-danger(@click='leaveChallenge("remove-all")') {{ $t('removeThem') }}
<template>
<b-modal
id="leave-challenge-modal"
:title="$t('leaveChallenge')"
size="sm"
:hide-footer="true"
>
<div class="modal-body">
<h2>{{ $t('confirmKeepChallengeTasks') }}</h2><div>
<button
class="btn btn-primary"
@click="leaveChallenge('keep')"
>
{{ $t('keepThem') }}
</button><button
class="btn btn-danger"
@click="leaveChallenge('remove-all')"
>
{{ $t('removeThem') }}
</button>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,41 +1,73 @@
<template lang="pug">
.row
challenge-modal(v-on:createChallenge='challengeCreated')
sidebar(v-on:search="updateSearch", v-on:filter="updateFilters")
.col-10.standard-page
.row.header-row
.col-md-8.text-left
h1(v-once) {{$t('myChallenges')}}
.col-md-4
// @TODO: implement sorting span.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
button.btn.btn-secondary.create-challenge-button.float-right(@click='createChallenge()')
.svg-icon.positive-icon(v-html="icons.positiveIcon")
span(v-once) {{$t('createChallenge')}}
.row
.no-challenges.text-center.col-md-6.offset-3(v-if='!loading && challenges.length === 0')
.svg-icon(v-html="icons.challengeIcon")
h2(v-once) {{$t('noChallengeTitle')}}
p(v-once) {{$t('challengeDescription1')}}
p(v-once) {{$t('challengeDescription2')}}
.row
.no-challenges.text-center.col-md-6.offset-3(v-if='!loading && challenges.length > 0 && filteredChallenges.length === 0')
h2(v-once) {{$t('noChallengeMatchFilters')}}
.row
.col-12.col-md-6(v-for='challenge in filteredChallenges')
challenge-item(:challenge='challenge')
mugen-scroll(
:handler="infiniteScrollTrigger",
:should-handle="!loading && canLoadMore",
:threshold="1",
v-show="loading",
)
h2.col-12.loading(v-once) {{ $t('loading') }}
<template>
<div class="row">
<challenge-modal @createChallenge="challengeCreated" /><sidebar
@search="updateSearch"
@filter="updateFilters"
/><div class="col-10 standard-page">
<div class="row header-row">
<div class="col-md-8 text-left">
<h1 v-once>
{{ $t('myChallenges') }}
</h1>
</div><div class="col-md-4">
<!-- @TODO: implement sorting span.dropdown-label {{ $t('sortBy') }}b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}--><button
class="btn btn-secondary create-challenge-button float-right"
@click="createChallenge()"
>
<div
class="svg-icon positive-icon"
v-html="icons.positiveIcon"
></div><span v-once>{{ $t('createChallenge') }}</span>
</button>
</div>
</div><div class="row">
<div
v-if="!loading && challenges.length === 0"
class="no-challenges text-center col-md-6 offset-3"
>
<div
class="svg-icon"
v-html="icons.challengeIcon"
></div><h2 v-once>
{{ $t('noChallengeTitle') }}
</h2><p v-once>
{{ $t('challengeDescription1') }}
</p><p v-once>
{{ $t('challengeDescription2') }}
</p>
</div>
</div><div class="row">
<div
v-if="!loading && challenges.length > 0 && filteredChallenges.length === 0"
class="no-challenges text-center col-md-6 offset-3"
>
<h2 v-once>
{{ $t('noChallengeMatchFilters') }}
</h2>
</div>
</div><div class="row">
<div
v-for="challenge in filteredChallenges"
class="col-12 col-md-6"
>
<challenge-item :challenge="challenge" />
</div><mugen-scroll
v-show="loading"
:handler="infiniteScrollTrigger"
:should-handle="!loading && canLoadMore"
:threshold="1"
>
<h2
v-once
class="col-12 loading"
>
{{ $t('loading') }}
</h2>
</mugen-scroll>
</div>
</div>
</div>
</template>
<style lang='scss' scoped>

View file

@ -1,36 +1,81 @@
<template lang="pug">
.standard-sidebar.d-none.d-sm-block
.form-group
input.form-control.search(type="text", :placeholder="$t('search')", v-model='searchTerm')
form
h2(v-once) {{ $t('filter') }}
.form-group
h3 {{ $t('category') }}
.form-check(
v-for="group in categoryOptions",
:key="group.key",
)
.custom-control.custom-checkbox
input.custom-control-input(type="checkbox", :value='group.key' v-model="categoryFilters", :id="group.key")
label.custom-control-label(v-once, :for="group.key") {{ $t(group.label) }}
.form-group(v-if='$route.name !== "findChallenges"')
h3 {{ $t('membership') }}
.form-check(
v-for="group in roleOptions",
:key="group.key",
)
.custom-control.custom-checkbox
input.custom-control-input(type="checkbox", :value='group.key' v-model="roleFilters", :id="group.key")
label.custom-control-label(v-once, :for="group.key") {{ $t(group.label) }}
.form-group
h3 {{ $t('ownership') }}
.form-check(
v-for="group in ownershipOptions",
:key="group.key",
)
.custom-control.custom-checkbox
input.custom-control-input(type="checkbox", :value='group.key' v-model="ownershipFilters", :id="group.key")
label.custom-control-label(v-once, :for="group.key") {{ $t(group.label) }}
<template>
<div class="standard-sidebar d-none d-sm-block">
<div class="form-group">
<input
v-model="searchTerm"
class="form-control search"
type="text"
:placeholder="$t('search')"
>
</div><form>
<h2 v-once>
{{ $t('filter') }}
</h2><div class="form-group">
<h3>{{ $t('category') }}</h3><div
v-for="group in categoryOptions"
:key="group.key"
class="form-check"
>
<div class="custom-control custom-checkbox">
<input
:id="group.key"
v-model="categoryFilters"
class="custom-control-input"
type="checkbox"
:value="group.key"
><label
v-once
class="custom-control-label"
:for="group.key"
>{{ $t(group.label) }}</label>
</div>
</div>
</div><div
v-if="$route.name !== 'findChallenges'"
class="form-group"
>
<h3>{{ $t('membership') }}</h3><div
v-for="group in roleOptions"
:key="group.key"
class="form-check"
>
<div class="custom-control custom-checkbox">
<input
:id="group.key"
v-model="roleFilters"
class="custom-control-input"
type="checkbox"
:value="group.key"
><label
v-once
class="custom-control-label"
:for="group.key"
>{{ $t(group.label) }}</label>
</div>
</div>
</div><div class="form-group">
<h3>{{ $t('ownership') }}</h3><div
v-for="group in ownershipOptions"
:key="group.key"
class="form-check"
>
<div class="custom-control custom-checkbox">
<input
:id="group.key"
v-model="ownershipFilters"
class="custom-control-input"
type="checkbox"
:value="group.key"
><label
v-once
class="custom-control-label"
:for="group.key"
>{{ $t(group.label) }}</label>
</div>
</div>
</div>
</form>
</div>
</template>
<script>

View file

@ -1,16 +1,31 @@
<template lang="pug">
.autocomplete-selection(v-if='searchResults.length > 0', :style='autocompleteStyle')
.autocomplete-results.d-flex.align-items-center(
v-for='result in searchResults',
@click='select(result)',
@mouseenter='setHover(result)',
@mouseleave='resetSelection()',
:class='{"hover-background": result.hover}',
)
span
h3.profile-name(:class='userLevelStyle(result.msg)') {{ result.displayName }}
.svg-icon(v-html="tierIcon(result.msg)", v-if='showTierStyle(result.msg)')
span.username.ml-2(v-if='result.username', :class='{"hover-foreground": result.hover}') @{{ result.username }}
<template>
<div
v-if="searchResults.length > 0"
class="autocomplete-selection"
:style="autocompleteStyle"
>
<div
v-for="result in searchResults"
class="autocomplete-results d-flex align-items-center"
:class="{'hover-background': result.hover}"
@click="select(result)"
@mouseenter="setHover(result)"
@mouseleave="resetSelection()"
>
<span><h3
class="profile-name"
:class="userLevelStyle(result.msg)"
>{{ result.displayName }}</h3><div
v-if="showTierStyle(result.msg)"
class="svg-icon"
v-html="tierIcon(result.msg)"
></div></span><span
v-if="result.username"
class="username ml-2"
:class="{'hover-foreground': result.hover}"
>@{{ result.username }}</span>
</div>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,37 +1,107 @@
<template lang="pug">
div
.mentioned-icon(v-if='isUserMentioned')
.message-hidden(v-if='!inbox && user.contributor.admin && msg.flagCount') {{flagCountDescription}}
.card-body
user-link(:userId="msg.uuid", :name="msg.user", :backer="msg.backer", :contributor="msg.contributor")
p.time
span.mr-1(v-if="msg.username") @{{ msg.username }}
span.mr-1(v-if="msg.username")
span(v-b-tooltip="", :title="msg.timestamp | date") {{ msg.timestamp | timeAgo }}&nbsp;
span(v-if="msg.client && user.contributor.level >= 4") ({{ msg.client }})
.text(v-html='atHighlight(parseMarkdown(msg.text))')
.reported(v-if="isMessageReported && (inbox === true)")
span(v-once) {{ $t('reportedMessage')}}
br
span(v-once) {{ $t('canDeleteNow') }}
hr
.d-flex(v-if='msg.id')
.action.d-flex.align-items-center(v-if='!inbox', @click='copyAsTodo(msg)')
.svg-icon(v-html="icons.copy")
div {{$t('copyAsTodo')}}
.action.d-flex.align-items-center(v-if='(inbox || (user.flags.communityGuidelinesAccepted && msg.uuid !== "system")) && (!isMessageReported || user.contributor.admin)', @click='report(msg)')
.svg-icon(v-html="icons.report", v-once)
div(v-once) {{$t('report')}}
.action.d-flex.align-items-center(v-if='msg.uuid === user._id || inbox || user.contributor.admin', @click='remove()')
.svg-icon(v-html="icons.delete", v-once)
div(v-once) {{$t('delete')}}
.ml-auto.d-flex(v-b-tooltip="{title: likeTooltip(msg.likes[user._id])}", v-if='!inbox')
.action.d-flex.align-items-center.mr-0(@click='like()', v-if='likeCount > 0', :class='{activeLike: msg.likes[user._id]}')
.svg-icon(v-html="icons.liked", :title='$t("liked")')
| +{{ likeCount }}
.action.d-flex.align-items-center.mr-0(@click='like()', v-if='likeCount === 0', :class='{activeLike: msg.likes[user._id]}')
.svg-icon(v-html="icons.like", :title='$t("like")')
span(v-if='!msg.likes[user._id] && !inbox') {{ $t('like') }}
<template>
<div>
<div
v-if="isUserMentioned"
class="mentioned-icon"
></div><div
v-if="!inbox && user.contributor.admin && msg.flagCount"
class="message-hidden"
>
{{ flagCountDescription }}
</div><div class="card-body">
<user-link
:user-id="msg.uuid"
:name="msg.user"
:backer="msg.backer"
:contributor="msg.contributor"
/><p class="time">
<span
v-if="msg.username"
class="mr-1"
>@{{ msg.username }}</span><span
v-if="msg.username"
class="mr-1"
></span><span
v-b-tooltip=""
:title="msg.timestamp | date"
>{{ msg.timestamp | timeAgo }}&nbsp;</span><span v-if="msg.client && user.contributor.level >= 4"> ({{ msg.client }})</span>
</p><div
class="text"
v-html="atHighlight(parseMarkdown(msg.text))"
></div><div
v-if="isMessageReported && (inbox === true)"
class="reported"
>
<span v-once>{{ $t('reportedMessage') }}</span><br><span v-once>{{ $t('canDeleteNow') }}</span>
</div><hr><div
v-if="msg.id"
class="d-flex"
>
<div
v-if="!inbox"
class="action d-flex align-items-center"
@click="copyAsTodo(msg)"
>
<div
class="svg-icon"
v-html="icons.copy"
></div><div>{{ $t('copyAsTodo') }}</div>
</div><div
v-if="(inbox || (user.flags.communityGuidelinesAccepted && msg.uuid !== 'system')) && (!isMessageReported || user.contributor.admin)"
class="action d-flex align-items-center"
@click="report(msg)"
>
<div
v-once
class="svg-icon"
v-html="icons.report"
></div><div v-once>
{{ $t('report') }}
</div>
</div><div
v-if="msg.uuid === user._id || inbox || user.contributor.admin"
class="action d-flex align-items-center"
@click="remove()"
>
<div
v-once
class="svg-icon"
v-html="icons.delete"
></div><div v-once>
{{ $t('delete') }}
</div>
</div><div
v-if="!inbox"
v-b-tooltip="{title: likeTooltip(msg.likes[user._id])}"
class="ml-auto d-flex"
>
<div
v-if="likeCount > 0"
class="action d-flex align-items-center mr-0"
:class="{activeLike: msg.likes[user._id]}"
@click="like()"
>
<div
class="svg-icon"
:title="$t('liked')"
v-html="icons.liked"
></div>+{{ likeCount }}
</div><div
v-if="likeCount === 0"
class="action d-flex align-items-center mr-0"
:class="{activeLike: msg.likes[user._id]}"
@click="like()"
>
<div
class="svg-icon"
:title="$t('like')"
v-html="icons.like"
></div>
</div>
</div><span v-if="!msg.likes[user._id] && !inbox">{{ $t('like') }}</span>
</div>
</div>
</div>
</template>
<style lang="scss">

View file

@ -1,53 +1,93 @@
<template lang="pug">
.container-fluid(ref="container")
.row
.col-12
copy-as-todo-modal(:group-type='groupType', :group-name='groupName', :group-id='groupId')
.row.loadmore
div(v-if="canLoadMore")
.loadmore-divider
button.btn.btn-secondary(@click='triggerLoad()') {{ $t('loadEarlierMessages') }}
.loadmore-divider
h2.col-12.loading(v-show="isLoading") {{ $t('loading') }}
div(v-for="(msg, index) in messages", v-if='chat && canViewFlag(msg)', :class='{row: inbox}')
.d-flex(v-if='user._id !== msg.uuid', :class='{"flex-grow-1": inbox}')
avatar.avatar-left(
v-if='msg.userStyles || (cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected)',
:member="msg.userStyles || cachedProfileData[msg.uuid]",
:avatarOnly="true",
:overrideTopPadding='"14px"',
:hideClassBadge='true',
@click.native="showMemberModal(msg.uuid)",
:class='{"inbox-avatar-left": inbox}'
)
.card(:class='{"col-10": inbox}')
chat-card(
:msg='msg',
:inbox='inbox',
:groupId='groupId',
@message-liked='messageLiked',
@message-removed='messageRemoved',
@show-member-modal='showMemberModal',
@chat-card-mounted='itemWasMounted')
.d-flex(v-if='user._id === msg.uuid', :class='{"flex-grow-1": inbox}')
.card(:class='{"col-10": inbox}')
chat-card(
:msg='msg',
:inbox='inbox',
:groupId='groupId',
@message-liked='messageLiked',
@message-removed='messageRemoved',
@show-member-modal='showMemberModal',
@chat-card-mounted='itemWasMounted')
avatar(
v-if='msg.userStyles || (cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected)',
:member="msg.userStyles || cachedProfileData[msg.uuid]",
:avatarOnly="true",
:hideClassBadge='true',
:overrideTopPadding='"14px"',
@click.native="showMemberModal(msg.uuid)",
:class='{"inbox-avatar-right": inbox}'
)
<template>
<div
ref="container"
class="container-fluid"
>
<div class="row">
<div class="col-12">
<copy-as-todo-modal
:group-type="groupType"
:group-name="groupName"
:group-id="groupId"
/>
</div>
</div><div class="row loadmore">
<div v-if="canLoadMore">
<div class="loadmore-divider"></div><button
class="btn btn-secondary"
@click="triggerLoad()"
>
{{ $t('loadEarlierMessages') }}
</button><div class="loadmore-divider"></div>
</div><h2
v-show="isLoading"
class="col-12 loading"
>
{{ $t('loading') }}
</h2>
</div><div
v-for="(msg, index) in messages"
v-if="chat && canViewFlag(msg)"
:class="{row: inbox}"
>
<div
v-if="user._id !== msg.uuid"
class="d-flex"
:class="{'flex-grow-1': inbox}"
>
<avatar
v-if="msg.userStyles || (cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected)"
class="avatar-left"
:member="msg.userStyles || cachedProfileData[msg.uuid]"
:avatar-only="true"
:override-top-padding="'14px'"
:hide-class-badge="true"
:class="{'inbox-avatar-left': inbox}"
@click.native="showMemberModal(msg.uuid)"
/><div
class="card"
:class="{'col-10': inbox}"
>
<chat-card
:msg="msg"
:inbox="inbox"
:group-id="groupId"
@message-liked="messageLiked"
@message-removed="messageRemoved"
@show-member-modal="showMemberModal"
@chat-card-mounted="itemWasMounted"
/>
</div>
</div><div
v-if="user._id === msg.uuid"
class="d-flex"
:class="{'flex-grow-1': inbox}"
>
<div
class="card"
:class="{'col-10': inbox}"
>
<chat-card
:msg="msg"
:inbox="inbox"
:group-id="groupId"
@message-liked="messageLiked"
@message-removed="messageRemoved"
@show-member-modal="showMemberModal"
@chat-card-mounted="itemWasMounted"
/>
</div><avatar
v-if="msg.userStyles || (cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected)"
:member="msg.userStyles || cachedProfileData[msg.uuid]"
:avatar-only="true"
:hide-class-badge="true"
:override-top-padding="'14px'"
:class="{'inbox-avatar-right': inbox}"
@click.native="showMemberModal(msg.uuid)"
/>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,14 +1,41 @@
<template lang="pug">
b-modal#copyAsTodo(:title="$t('copyMessageAsToDo')", :hide-footer="true", size='md')
.form-group
input.form-control(type='text', v-model='task.text')
.form-group
textarea.form-control(rows='5', v-model='task.notes' focus-element='true')
hr
task(v-if='task._id', :isUser="isUser", :task="task")
.modal-footer
button.btn.btn-secondary(@click='close()') {{ $t('close') }}
button.btn.btn-primary(@click='saveTodo()') {{ $t('submit') }}
<template>
<b-modal
id="copyAsTodo"
:title="$t('copyMessageAsToDo')"
:hide-footer="true"
size="md"
>
<div class="form-group">
<input
v-model="task.text"
class="form-control"
type="text"
>
</div><div class="form-group">
<textarea
v-model="task.notes"
class="form-control"
rows="5"
focus-element="true"
></textarea>
</div><hr><task
v-if="task._id"
:is-user="isUser"
:task="task"
/><div class="modal-footer">
<button
class="btn btn-secondary"
@click="close()"
>
{{ $t('close') }}
</button><button
class="btn btn-primary"
@click="saveTodo()"
>
{{ $t('submit') }}
</button>
</div>
</b-modal>
</template>
<script>

View file

@ -1,19 +1,36 @@
<template lang="pug">
b-modal#report-flag(:title='$t("abuseFlagModalHeading")', size='md', :hide-footer='true')
.modal-body
strong(v-html="$t('abuseFlagModalHeading', reportData)")
blockquote
div(v-markdown='abuseObject.text')
div
strong {{$t('whyReportingPost')}}
span.optional {{$t('optional')}}
textarea.form-control(v-model='reportComment', :placeholder='$t("whyReportingPostPlaceholder")')
small(v-html="$t('abuseFlagModalBody', abuseFlagModalBody)")
.footer.text-center
button.pull-left.btn.btn-danger(@click='clearFlagCount()', v-if='user.contributor.admin && abuseObject.flagCount > 0')
| Reset Flag Count
a.cancel-link(@click.prevent='close()') {{ $t('cancel') }}
button.btn.btn-danger(@click='reportAbuse()') {{ $t('report') }}
<template>
<b-modal
id="report-flag"
:title="$t('abuseFlagModalHeading')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<strong v-html="$t('abuseFlagModalHeading', reportData)"></strong><blockquote><div v-markdown="abuseObject.text"></div></blockquote><div>
<strong>{{ $t('whyReportingPost') }}</strong><span class="optional">{{ $t('optional') }}</span><textarea
v-model="reportComment"
class="form-control"
:placeholder="$t('whyReportingPostPlaceholder')"
></textarea>
</div><small v-html="$t('abuseFlagModalBody', abuseFlagModalBody)"></small>
</div><div class="footer text-center">
<button
v-if="user.contributor.admin && abuseObject.flagCount > 0"
class="pull-left btn btn-danger"
@click="clearFlagCount()"
>
Reset Flag Count
</button><a
class="cancel-link"
@click.prevent="close()"
>{{ $t('cancel') }}</a><button
class="btn btn-danger"
@click="reportAbuse()"
>
{{ $t('report') }}
</button>
</div>
</b-modal>
</template>
<style>

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,3 @@
<template lang="pug">
// Container component used when you only need an empty view to support children routes
router-view
<template>
<!-- Container component used when you only need an empty view to support children routes--><router-view />
</template>

View file

@ -1,35 +1,52 @@
<template lang="pug">
.row.standard-page(v-if='groupIsSubscribed && isLeader')
.col-12.col-md-6.offset-md-3
table.table.alert.alert-info
tr(v-if='group.purchased.plan.dateTerminated')
td.alert.alert-warning
span.noninteractive-button.btn-danger {{ $t('canceledGroupPlan') }}
i.glyphicon.glyphicon-time {{ $t('groupPlanCanceled') }}
strong {{dateTerminated}}
tr(v-if='!group.purchased.plan.dateTerminated')
td
h3 {{ $t('paymentDetails') }}
p(v-if='group.purchased.plan.planId') {{ $t('groupSubscriptionPrice') }}
tr(v-if='group.purchased.plan.extraMonths')
td
span.glyphicon.glyphicon-credit-card
| {{ $t('purchasedGroupPlanPlanExtraMonths', purchasedGroupPlanPlanExtraMonths) }}
tr(v-if='group.purchased.plan.consecutive.count || group.purchased.plan.consecutive.offset')
td
span.glyphicon.glyphicon-forward
| {{ $t('consecutiveSubscription') }}
ul.list-unstyled
li {{ $t('consecutiveMonths') }} {{group.purchased.plan.consecutive.count + group.purchased.plan.consecutive.offset}}
li {{ $t('gemCapExtra') }} {{group.purchased.plan.consecutive.gemCapExtra}}
li {{ $t('mysticHourglasses') }} {{group.purchased.plan.consecutive.trinkets}}
.col-12.col-md-6.offset-md-3
button.btn.btn-success(class='btn-success', v-if='group.purchased.plan.dateTerminated', @click='upgradeGroup()')
| {{ $t('upgrade') }}
.btn.btn-primary(v-if='!group.purchased.plan.dateTerminated && group.purchased.plan.paymentMethod === "Stripe"',
@click='showStripeEdit({groupId: group.id})') {{ $t('subUpdateCard') }}
.btn.btn-sm.btn-danger(v-if='!group.purchased.plan.dateTerminated',
@click='cancelSubscriptionConfirm({group: group})') {{ $t('cancelGroupSub') }}
<template>
<div
v-if="groupIsSubscribed && isLeader"
class="row standard-page"
>
<div class="col-12 col-md-6 offset-md-3">
<table class="table alert alert-info">
<tr v-if="group.purchased.plan.dateTerminated">
<td class="alert alert-warning">
<span class="noninteractive-button btn-danger">{{ $t('canceledGroupPlan') }}</span><i class="glyphicon glyphicon-time">{{ $t('groupPlanCanceled') }}</i><strong>{{ dateTerminated }}</strong>
</td>
</tr><tr v-if="!group.purchased.plan.dateTerminated">
<td>
<h3>{{ $t('paymentDetails') }}</h3><p v-if="group.purchased.plan.planId">
{{ $t('groupSubscriptionPrice') }}
</p>
</td>
</tr><tr v-if="group.purchased.plan.extraMonths">
<td><span class="glyphicon glyphicon-credit-card"></span>{{ $t('purchasedGroupPlanPlanExtraMonths', purchasedGroupPlanPlanExtraMonths) }}</td>
</tr><tr v-if="group.purchased.plan.consecutive.count || group.purchased.plan.consecutive.offset">
<td>
<span class="glyphicon glyphicon-forward"></span>{{ $t('consecutiveSubscription') }}<ul class="list-unstyled">
<li>{{ $t('consecutiveMonths') }} {{ group.purchased.plan.consecutive.count + group.purchased.plan.consecutive.offset }}</li><li>{{ $t('gemCapExtra') }} {{ group.purchased.plan.consecutive.gemCapExtra }}</li><li>{{ $t('mysticHourglasses') }} {{ group.purchased.plan.consecutive.trinkets }}</li></li>
</ul>
</td>
</tr>
</table>
</div><div class="col-12 col-md-6 offset-md-3">
<button
v-if="group.purchased.plan.dateTerminated"
class="btn btn-success btn-success"
@click="upgradeGroup()"
>
{{ $t('upgrade') }}
</button><div
v-if="!group.purchased.plan.dateTerminated && group.purchased.plan.paymentMethod === 'Stripe'"
class="btn btn-primary"
@click="showStripeEdit({groupId: group.id})"
>
{{ $t('subUpdateCard') }}
</div><div
v-if="!group.purchased.plan.dateTerminated"
class="btn btn-sm btn-danger"
@click="cancelSubscriptionConfirm({group: group})"
>
{{ $t('cancelGroupSub') }}
</div>
</div>
</div>
</template>
<script>
@ -52,7 +69,7 @@ export default {
return this.user._id === this.group.leader._id;
},
groupIsSubscribed () {
return this.group.purchased && this.group.purchased.plan
return this.group.purchased && this.group.purchased.plan
&& this.group.purchased.plan.customerId;
},
dateTerminated () {

View file

@ -1,32 +1,92 @@
<template lang="pug">
.create-group-modal-pages
.col-12(v-if='activePage === PAGES.CREATE_GROUP')
h2 {{ $t('nameYourGroup') }}
.form-group
label.control-label(for='new-group-name') {{ $t('name') }}
input.form-control#new-group-name.input-medium.option-content(required, type='text', :placeholder="$t('exampleGroupName')", v-model='newGroup.name')
.form-group
label(for='new-group-description') {{ $t('description') }}
textarea.form-control#new-group-description.option-content(cols='3', :placeholder="$t('exampleGroupDesc')", v-model='newGroup.description')
.form-group.text-left(v-if='newGroup.type === "guild"')
.custom-control.custom-radio
input.custom-control-input(type='radio', name='new-group-privacy', value='private', v-model='newGroup.privacy')
label.custom-control-label {{ $t('thisGroupInviteOnly') }}
.form-group.text-left
.custom-control.custom-checkbox
input.custom-control-input(type='checkbox', v-model='newGroup.leaderOnly.challenges' id='create-group-leaderOnlyChallenges-checkbox')
label.custom-control-label(for='create-group-leaderOnlyChallenges-checkbox') {{ $t('leaderOnlyChallenges') }}
.form-group(v-if='newGroup.type === "party"')
button.btn.btn-secondary.form-control(@click='createGroup()', :value="$t('createGroupPlan')")
.form-group
button.btn.btn-primary.btn-lg.btn-block(@click="createGroup()", :disabled="!newGroupIsReady") {{ $t('createGroupPlan') }}
.col-12(v-if='activePage === PAGES.PAY')
h2 {{ $t('choosePaymentMethod') }}
.payments-column
button.purchase.btn.btn-primary.payment-button.payment-item(@click='pay(PAYMENTS.STRIPE)')
.svg-icon.credit-card-icon(v-html="icons.creditCardIcon")
| {{ $t('card') }}
amazon-button.payment-item(:amazon-data="pay(PAYMENTS.AMAZON)")
<template>
<div class="create-group-modal-pages">
<div
v-if="activePage === PAGES.CREATE_GROUP"
class="col-12"
>
<h2>{{ $t('nameYourGroup') }}</h2><div class="form-group">
<label
class="control-label"
for="new-group-name"
>{{ $t('name') }}</label><input
id="new-group-name"
v-model="newGroup.name"
class="form-control input-medium option-content"
required="required"
type="text"
:placeholder="$t('exampleGroupName')"
>
</div><div class="form-group">
<label for="new-group-description">{{ $t('description') }}</label><textarea
id="new-group-description"
v-model="newGroup.description"
class="form-control option-content"
cols="3"
:placeholder="$t('exampleGroupDesc')"
></textarea>
</div><div
v-if="newGroup.type === 'guild'"
class="form-group text-left"
>
<div class="custom-control custom-radio">
<input
v-model="newGroup.privacy"
class="custom-control-input"
type="radio"
name="new-group-privacy"
value="private"
><label class="custom-control-label">{{ $t('thisGroupInviteOnly') }}</label>
</div>
</div><div class="form-group text-left">
<div class="custom-control custom-checkbox">
<input
id="create-group-leaderOnlyChallenges-checkbox"
v-model="newGroup.leaderOnly.challenges"
class="custom-control-input"
type="checkbox"
><label
class="custom-control-label"
for="create-group-leaderOnlyChallenges-checkbox"
>{{ $t('leaderOnlyChallenges') }}</label>
</div>
</div><div
v-if="newGroup.type === 'party'"
class="form-group"
>
<button
class="btn btn-secondary form-control"
:value="$t('createGroupPlan')"
@click="createGroup()"
></button>
</div><div class="form-group">
<button
class="btn btn-primary btn-lg btn-block"
:disabled="!newGroupIsReady"
@click="createGroup()"
>
{{ $t('createGroupPlan') }}
</button>
</div>
</div><div
v-if="activePage === PAGES.PAY"
class="col-12"
>
<h2>{{ $t('choosePaymentMethod') }}</h2><div class="payments-column">
<button
class="purchase btn btn-primary payment-button payment-item"
@click="pay(PAYMENTS.STRIPE)"
>
<div
class="svg-icon credit-card-icon"
v-html="icons.creditCardIcon"
></div>{{ $t('card') }}
</button><amazon-button
class="payment-item"
:amazon-data="pay(PAYMENTS.AMAZON)"
/>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,66 +1,186 @@
<template lang="pug">
b-modal#group-plan-overview(title="Empty", size='lg', hide-footer=true, @shown='shown()')
.header-wrap.text-center(slot="modal-header")
h2(v-once) {{ $t('gettingStarted') }}
p(v-once) {{ $t('congratsOnGroupPlan') }}
.row
.col-12
.card(:class='{expanded: expandedQuestions.question1}')
.question-head
.q Q.
.title {{ $t('whatsIncludedGroup') }}
.arrow.float-right(@click='toggle("question1")')
.svg-icon(v-html="icons.upIcon", v-if='expandedQuestions.question1')
.svg-icon(v-html="icons.downIcon", v-else)
.question-body(v-if='expandedQuestions.question1')
p {{ $t('whatsIncludedGroupDesc') }}
.col-12
.card(:class='{expanded: expandedQuestions.question2}')
.question-head
.q Q.
.title {{ $t('howDoesBillingWork') }}
.arrow.float-right(@click='toggle("question2")')
.svg-icon(v-html="icons.upIcon", v-if='expandedQuestions.question2')
.svg-icon(v-html="icons.downIcon", v-else)
.question-body(v-if='expandedQuestions.question2')
p {{ $t('howDoesBillingWorkDesc') }}
.col-12
.card(:class='{expanded: expandedQuestions.question3}')
.question-head
.q Q.
.title {{ $t('howToAssignTask') }}
.arrow.float-right(@click='toggle("question3")')
.svg-icon(v-html="icons.upIcon", v-if='expandedQuestions.question3')
.svg-icon(v-html="icons.downIcon", v-else)
.question-body(v-if='expandedQuestions.question3')
p {{ $t('howToAssignTaskDesc') }}
.assign-tasks.image-example
.col-12
.card(:class='{expanded: expandedQuestions.question4}')
.question-head
.q Q.
.title {{ $t('howToRequireApproval') }}
.arrow.float-right(@click='toggle("question4")')
.svg-icon(v-html="icons.upIcon", v-if='expandedQuestions.question4')
.svg-icon(v-html="icons.downIcon", v-else)
.question-body(v-if='expandedQuestions.question4')
p {{ $t('howToRequireApprovalDesc') }}
.requires-approval.image-example
p {{ $t('howToRequireApprovalDesc2') }}
.approval-requested.image-example
.col-12
.card(:class='{expanded: expandedQuestions.question5}')
.question-head
.q Q.
.title {{ $t('whatIsGroupManager') }}
.arrow.float-right(@click='toggle("question5")')
.svg-icon(v-html="icons.upIcon", v-if='expandedQuestions.question5')
.svg-icon(v-html="icons.downIcon", v-else)
.question-body(v-if='expandedQuestions.question5')
p {{ $t('whatIsGroupManagerDesc') }}
.promote-leader.image-example
.col-12.text-center
button.btn.btn-primary.close-button(@click='close()') {{ $t('goToTaskBoard') }}
<template>
<b-modal
id="group-plan-overview"
title="Empty"
size="lg"
hide-footer="hide-footer"
@shown="shown()"
>
<div
slot="modal-header"
class="header-wrap text-center"
>
<h2 v-once>
{{ $t('gettingStarted') }}
</h2><p v-once>
{{ $t('congratsOnGroupPlan') }}
</p>
</div><div class="row">
<div class="col-12">
<div
class="card"
:class="{expanded: expandedQuestions.question1}"
>
<div class="question-head">
<div class="q">
Q.
</div><div class="title">
{{ $t('whatsIncludedGroup') }}
</div><div
class="arrow float-right"
@click="toggle('question1')"
>
<div
v-if="expandedQuestions.question1"
class="svg-icon"
v-html="icons.upIcon"
></div><div
v-else
class="svg-icon"
v-html="icons.downIcon"
></div>
</div>
</div><div
v-if="expandedQuestions.question1"
class="question-body"
>
<p>{{ $t('whatsIncludedGroupDesc') }}</p>
</div>
</div>
</div><div class="col-12">
<div
class="card"
:class="{expanded: expandedQuestions.question2}"
>
<div class="question-head">
<div class="q">
Q.
</div><div class="title">
{{ $t('howDoesBillingWork') }}
</div><div
class="arrow float-right"
@click="toggle('question2')"
>
<div
v-if="expandedQuestions.question2"
class="svg-icon"
v-html="icons.upIcon"
></div><div
v-else
class="svg-icon"
v-html="icons.downIcon"
></div>
</div>
</div><div
v-if="expandedQuestions.question2"
class="question-body"
>
<p>{{ $t('howDoesBillingWorkDesc') }}</p>
</div>
</div>
</div><div class="col-12">
<div
class="card"
:class="{expanded: expandedQuestions.question3}"
>
<div class="question-head">
<div class="q">
Q.
</div><div class="title">
{{ $t('howToAssignTask') }}
</div><div
class="arrow float-right"
@click="toggle('question3')"
>
<div
v-if="expandedQuestions.question3"
class="svg-icon"
v-html="icons.upIcon"
></div><div
v-else
class="svg-icon"
v-html="icons.downIcon"
></div>
</div>
</div><div
v-if="expandedQuestions.question3"
class="question-body"
>
<p>{{ $t('howToAssignTaskDesc') }}</p><div class="assign-tasks image-example"></div>
</div>
</div>
</div><div class="col-12">
<div
class="card"
:class="{expanded: expandedQuestions.question4}"
>
<div class="question-head">
<div class="q">
Q.
</div><div class="title">
{{ $t('howToRequireApproval') }}
</div><div
class="arrow float-right"
@click="toggle('question4')"
>
<div
v-if="expandedQuestions.question4"
class="svg-icon"
v-html="icons.upIcon"
></div><div
v-else
class="svg-icon"
v-html="icons.downIcon"
></div>
</div>
</div><div
v-if="expandedQuestions.question4"
class="question-body"
>
<p>{{ $t('howToRequireApprovalDesc') }}</p><div class="requires-approval image-example"></div><p>{{ $t('howToRequireApprovalDesc2') }}</p><div class="approval-requested image-example"></div>
</div>
</div>
</div><div class="col-12">
<div
class="card"
:class="{expanded: expandedQuestions.question5}"
>
<div class="question-head">
<div class="q">
Q.
</div><div class="title">
{{ $t('whatIsGroupManager') }}
</div><div
class="arrow float-right"
@click="toggle('question5')"
>
<div
v-if="expandedQuestions.question5"
class="svg-icon"
v-html="icons.upIcon"
></div><div
v-else
class="svg-icon"
v-html="icons.downIcon"
></div>
</div>
</div><div
v-if="expandedQuestions.question5"
class="question-body"
>
<p>{{ $t('whatIsGroupManagerDesc') }}</p><div class="promote-leader image-example"></div>
</div>
</div>
</div><div class="col-12 text-center">
<button
class="btn btn-primary close-button"
@click="close()"
>
{{ $t('goToTaskBoard') }}
</button>
</div>
</div>
</b-modal>
</template>
<style>

View file

@ -1,19 +1,33 @@
<template lang="pug">
.row
group-form-modal
secondary-menu.col-12
router-link.nav-link(:to="{name: 'groupPlanDetailTaskInformation', params: {groupId}}",
exact, :class="{'active': $route.name === 'groupPlanDetailTaskInformation'}") {{ $t('groupTaskBoard') }}
router-link.nav-link(:to="{name: 'groupPlanDetailInformation', params: {groupId}}",
exact, :class="{'active': $route.name === 'groupPlanDetailInformation'}") {{ $t('groupInformation') }}
router-link.nav-link(
v-if='isLeader',
:to="{name: 'groupPlanBilling', params: {groupId}}",
exact,
:class="{'active': $route.name === 'groupPlanBilling'}") {{ $t('groupBilling') }}
.col-12
router-view
<template>
<div class="row">
<group-form-modal /><secondary-menu class="col-12">
<router-link
class="nav-link"
:to="{name: 'groupPlanDetailTaskInformation', params: {groupId}}"
exact="exact"
:class="{'active': $route.name === 'groupPlanDetailTaskInformation'}"
>
{{ $t('groupTaskBoard') }}
</router-link><router-link
class="nav-link"
:to="{name: 'groupPlanDetailInformation', params: {groupId}}"
exact="exact"
:class="{'active': $route.name === 'groupPlanDetailInformation'}"
>
{{ $t('groupInformation') }}
</router-link><router-link
v-if="isLeader"
class="nav-link"
:to="{name: 'groupPlanBilling', params: {groupId}}"
exact="exact"
:class="{'active': $route.name === 'groupPlanBilling'}"
>
{{ $t('groupBilling') }}
</router-link>
</secondary-menu><div class="col-12">
<router-view />
</div>
</div>
</template>
<script>

View file

@ -1,52 +1,80 @@
<template lang="pug">
.standard-page
group-plan-overview-modal
task-modal(
:task="workingTask",
:purpose="taskFormPurpose",
@cancel="cancelTaskModal()",
ref="taskModal",
:groupId="groupId",
v-on:taskCreated='taskCreated',
v-on:taskEdited='taskEdited',
v-on:taskDestroyed='taskDestroyed'
)
.row.tasks-navigation
.col-12.col-md-4
h1 {{ $t('groupTasksTitle') }}
// @TODO: Abstract to component!
.col-12.col-md-4
input.form-control.input-search(type="text", :placeholder="$t('search')", v-model="searchText")
.create-task-area.d-flex(v-if='canCreateTasks')
transition(name="slide-tasks-btns")
.d-flex(v-if="openCreateBtn")
.create-task-btn.diamond-btn(
v-for="type in columns",
:key="type",
@click="createTask(type)",
v-b-tooltip.hover.bottom="$t(type)",
)
.svg-icon(v-html="icons[type]", :class='`icon-${type}`')
#create-task-btn.create-btn.diamond-btn.btn.btn-success(
@click="openCreateBtn = !openCreateBtn",
:class="{open: openCreateBtn}",
)
.svg-icon(v-html="icons.positive")
b-tooltip(target="create-task-btn", placement="bottom", v-if="!openCreateBtn") {{ $t('addTaskToGroupPlan') }}
.row
task-column.col-12.col-md-3(
v-for="column in columns",
:type="column",
:key="column",
:taskListOverride='tasksByType[column]',
:showOptions="showOptions"
v-on:editTask="editTask",
v-on:loadGroupCompletedTodos="loadGroupCompletedTodos",
v-on:taskDestroyed="taskDestroyed",
:group='group',
:searchText="searchText")
<template>
<div class="standard-page">
<group-plan-overview-modal /><task-modal
ref="taskModal"
:task="workingTask"
:purpose="taskFormPurpose"
:group-id="groupId"
@cancel="cancelTaskModal()"
@taskCreated="taskCreated"
@taskEdited="taskEdited"
@taskDestroyed="taskDestroyed"
/><div class="row tasks-navigation">
<div class="col-12 col-md-4">
<h1>{{ $t('groupTasksTitle') }}</h1>
</div><!-- @TODO: Abstract to component!--><div class="col-12 col-md-4">
<input
v-model="searchText"
class="form-control input-search"
type="text"
:placeholder="$t('search')"
>
</div><div
v-if="canCreateTasks"
class="create-task-area d-flex"
>
<transition name="slide-tasks-btns">
<div
v-if="openCreateBtn"
class="d-flex"
>
<div
v-for="type in columns"
:key="type"
v-b-tooltip.hover.bottom="$t(type)"
class="create-task-btn diamond-btn"
@click="createTask(type)"
>
<div
class="svg-icon"
:class="`icon-${type}`"
v-html="icons[type]"
></div>
</div>
</div>
</transition><div
id="create-task-btn"
class="create-btn diamond-btn btn btn-success"
:class="{open: openCreateBtn}"
@click="openCreateBtn = !openCreateBtn"
>
<div
class="svg-icon"
v-html="icons.positive"
></div>
</div><b-tooltip
v-if="!openCreateBtn"
target="create-task-btn"
placement="bottom"
>
{{ $t('addTaskToGroupPlan') }}
</b-tooltip>
</div>
</div><div class="row">
<task-column
v-for="column in columns"
:key="column"
class="col-12 col-md-3"
:type="column"
:task-list-override="tasksByType[column]"
:show-options="showOptions"
:group="group"
:search-text="searchText"
@editTask="editTask"
@loadGroupCompletedTodos="loadGroupCompletedTodos" @taskDestroyed="taskDestroyed"
/>
</div>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,8 +1,10 @@
<template lang="pug">
b-link(
v-if='group',
@click.prevent='goToGroup'
) {{group.name}}
<template>
<b-link
v-if="group"
@click.prevent="goToGroup"
>
{{ group.name }}
</b-link>
</template>
<script>

View file

@ -1,50 +1,71 @@
<template lang="pug">
.row.chat-row
.col-12
h3.float-left.label(:class="{accepted: communityGuidelinesAccepted }") {{ label }}
div.float-right(v-markdown='$t("markdownFormattingHelp")')
.row(v-if="communityGuidelinesAccepted")
textarea(:placeholder='placeholder',
v-model='newMessage',
ref='user-entry',
:class='{"user-entry": newMessage}',
@keydown='updateCarretPosition',
@keyup.ctrl.enter='sendMessageShortcut()',
@keydown.tab='handleTab($event)',
@keydown.up='selectPreviousAutocomplete($event)',
@keydown.down='selectNextAutocomplete($event)',
@keydown.enter='selectAutocomplete($event)',
@keydown.esc='handleEscape($event)',
@paste='disableMessageSendShortcut()',
maxlength='3000'
)
span {{ currentLength }} / 3000
autocomplete(
ref='autocomplete',
:text='newMessage',
v-on:select="selectedAutocomplete",
:textbox='textbox',
:coords='coords',
:caretPosition = 'caretPosition',
:chat='group.chat')
community-guidelines
.row.chat-actions
.col-6.chat-receive-actions
button.btn.btn-secondary.float-left.fetch(v-once, @click='fetchRecentMessages()') {{ $t('fetchRecentMessages') }}
button.btn.btn-secondary.float-left(v-once, @click='reverseChat()') {{ $t('reverseChat') }}
.col-6.chat-send-actions
button.btn.btn-primary.send-chat.float-right(:disabled="!communityGuidelinesAccepted", @click='sendMessage()') {{ $t('send') }}
slot(
name="additionRow",
)
.row
.hr.col-12
chat-message(:chat.sync='group.chat', :group-type='group.type', :group-id='group._id', :group-name='group.name')
<template>
<div class="row chat-row">
<div class="col-12">
<h3
class="float-left label"
:class="{accepted: communityGuidelinesAccepted }"
>
{{ label }}
</h3><div
v-markdown="$t('markdownFormattingHelp')"
class="float-right"
></div><div
v-if="communityGuidelinesAccepted"
class="row"
>
<textarea
ref="user-entry"
v-model="newMessage"
:placeholder="placeholder"
:class="{'user-entry': newMessage}"
maxlength="3000"
@keydown="updateCarretPosition"
@keyup.ctrl.enter="sendMessageShortcut()"
@keydown.tab="handleTab($event)"
@keydown.up="selectPreviousAutocomplete($event)" @keydown.down="selectNextAutocomplete($event)" @keydown.enter="selectAutocomplete($event)" @keydown.esc="handleEscape($event)" @paste="disableMessageSendShortcut()"
></textarea><span>{{ currentLength }} / 3000</span><autocomplete
ref="autocomplete"
:text="newMessage"
:textbox="textbox"
:coords="coords"
:caret-position="caretPosition"
:chat="group.chat"
@select="selectedAutocomplete"
/>
</div><community-guidelines /><div class="row chat-actions">
<div class="col-6 chat-receive-actions">
<button
v-once
class="btn btn-secondary float-left fetch"
@click="fetchRecentMessages()"
>
{{ $t('fetchRecentMessages') }}
</button><button
v-once
class="btn btn-secondary float-left"
@click="reverseChat()"
>
{{ $t('reverseChat') }}
</button>
</div><div class="col-6 chat-send-actions">
<button
class="btn btn-primary send-chat float-right"
:disabled="!communityGuidelinesAccepted"
@click="sendMessage()"
>
{{ $t('send') }}
</button>
</div>
</div><slot name="additionRow"></slot><div class="row">
<div class="hr col-12"></div><chat-message
:chat.sync="group.chat"
:group-type="group.type"
:group-id="group._id"
:group-name="group.name"
/>
</div>
</div>
</div>
</template>
<script>

View file

@ -1,9 +1,22 @@
<template lang="pug">
.row.community-guidelines(v-if='!communityGuidelinesAccepted')
div.col.col-sm-12.col-xl-8(v-once, v-html="$t('communityGuidelinesIntro')")
div.col-md-auto.col-md-12.col-xl-4
button.btn.btn-info.btn-follow-guidelines(@click='acceptCommunityGuidelines()', v-once) {{ $t('acceptCommunityGuidelines') }}
<template>
<div
v-if="!communityGuidelinesAccepted"
class="row community-guidelines"
>
<div
v-once
class="col col-sm-12 col-xl-8"
v-html="$t('communityGuidelinesIntro')"
></div><div class="col-md-auto col-md-12 col-xl-4">
<button
v-once
class="btn btn-info btn-follow-guidelines"
@click="acceptCommunityGuidelines()"
>
{{ $t('acceptCommunityGuidelines') }}
</button>
</div>
</div>
</template>
<style lang="scss">

View file

@ -1,25 +1,63 @@
<template lang="pug">
b-modal#create-party-modal(size='lg', hide-footer=true)
.header-wrap(slot="modal-header")
.quest_screen
.row.heading
.col-12.text-center.pr-5.pl-5
h2(v-once) {{ $t('playInPartyTitle') }}
p.mb-4(v-once) {{ $t('playInPartyDescription') }}
button.btn.btn-primary(v-once, @click='createParty()') {{ $t('createParty') }}
.row.grey-row
.col-12.text-center
.join-party
h2(v-once) {{ $t('wantToJoinPartyTitle') }}
p(v-html='$t("wantToJoinPartyDescription")')
.form-group(@click='copyUsername')
.d-flex.align-items-center
label.mr-3(v-once) {{ $t('username') }}
.flex-grow-1
.input-group-prepend.input-group-text @
.text {{ user.auth.local.username }}
.svg-icon.copy-icon(v-html='icons.copy')
.small(v-once) {{ $t('copy') }}
<template>
<b-modal
id="create-party-modal"
size="lg"
hide-footer="hide-footer"
>
<div
slot="modal-header"
class="header-wrap"
>
<div class="quest_screen"></div><div class="row heading">
<div class="col-12 text-center pr-5 pl-5">
<h2 v-once>
{{ $t('playInPartyTitle') }}
</h2><p
v-once
class="mb-4"
>
{{ $t('playInPartyDescription') }}
</p><button
v-once
class="btn btn-primary"
@click="createParty()"
>
{{ $t('createParty') }}
</button>
</div>
</div>
</div><div class="row grey-row">
<div class="col-12 text-center">
<div class="join-party"></div><h2 v-once>
{{ $t('wantToJoinPartyTitle') }}
</h2><p v-html="$t('wantToJoinPartyDescription')"></p><div
class="form-group"
@click="copyUsername"
>
<div class="d-flex align-items-center">
<label
v-once
class="mr-3"
>{{ $t('username') }}</label><div class="flex-grow-1">
<div class="input-group-prepend input-group-text">
@<div class="text">
{{ user.auth.local.username }}
</div><div
class="svg-icon copy-icon"
v-html="icons.copy"
></div><div
v-once
class="small"
>
{{ $t('copy') }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</b-modal>
</template>
<style>

View file

@ -1,34 +1,58 @@
<template lang="pug">
.row
sidebar(@search="updateSearch", @filter="updateFilters")
.standard-page
.header.row
.col-8
h1.page-header.float-left(v-once) {{ $t('publicGuilds') }}
.col-4
// @TODO: Add when we implement recent activity .float-right
span.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
button.btn.btn-secondary.create-group-button.float-right(@click='createGroup()')
.svg-icon.positive-icon(v-html="icons.positiveIcon")
span(v-once) {{$t('createGuild2')}}
.row
.no-guilds.text-center.col-md-6.offset-md-3(v-if='!loading && filteredGuilds.length === 0')
h2(v-once) {{$t('noGuildsMatchFilters')}}
.row
.col-md-12
public-guild-item(v-for="guild in filteredGuilds", :key='guild._id', :guild="guild", :display-leave='true')
mugen-scroll(
:handler="fetchGuilds",
:should-handle="!loading && !this.hasLoadedAllGuilds",
:handle-on-mount="true",
v-show="loading",
)
span(v-once) {{ $t('loading') }}
<template>
<div class="row">
<sidebar
@search="updateSearch"
@filter="updateFilters"
/><div class="standard-page">
<div class="header row">
<div class="col-8">
<h1
v-once
class="page-header float-left"
>
{{ $t('publicGuilds') }}
</h1>
</div><div class="col-4">
<!-- @TODO: Add when we implement recent activity .float-rightspan.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}--><button
class="btn btn-secondary create-group-button float-right"
@click="createGroup()"
>
<div
class="svg-icon positive-icon"
v-html="icons.positiveIcon"
></div><span v-once>{{ $t('createGuild2') }}</span>
</button>
</div>
</div><div class="row">
<div
v-if="!loading && filteredGuilds.length === 0"
class="no-guilds text-center col-md-6 offset-md-3"
>
<h2 v-once>
{{ $t('noGuildsMatchFilters') }}
</h2>
</div>
</div><div class="row">
<div class="col-md-12">
<public-guild-item
v-for="guild in filteredGuilds"
:key="guild._id"
:guild="guild"
:display-leave="true"
/><mugen-scroll
v-show="loading"
:handler="fetchGuilds"
:should-handle="!loading && !this.hasLoadedAllGuilds"
:handle-on-mount="true"
>
<span v-once>{{ $t('loading') }}</span>
</mugen-scroll>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,72 +1,158 @@
<template lang="pug">
.row(v-if="group._id")
group-form-modal(v-if='isParty')
start-quest-modal(:group='this.group')
quest-details-modal(:group='this.group')
participant-list-modal(:group='this.group')
group-gems-modal
.col-12.col-sm-8.standard-page
.row
.col-12.col-md-6.title-details
h1 {{group.name}}
div
span.mr-1.ml-0
strong(v-once) {{$t('groupLeader')}}:
user-link.mx-1(:user="group.leader")
.col-12.col-md-6
.row.icon-row
.col-4.offset-4(v-bind:class="{ 'offset-8': isParty }")
.item-with-icon(@click="showMemberModal()")
.svg-icon.shield(v-html="icons.goldGuildBadgeIcon", v-if='group.memberCount > 1000')
.svg-icon.shield(v-html="icons.silverGuildBadgeIcon", v-if='group.memberCount > 100 && group.memberCount < 999')
.svg-icon.shield(v-html="icons.bronzeGuildBadgeIcon", v-if='group.memberCount < 100')
span.number {{ group.memberCount | abbrNum }}
div.member-list.label(v-once) {{ $t('memberList') }}
.col-4(v-if='!isParty')
.item-with-icon(@click='showGroupGems()')
.svg-icon.gem(v-html="icons.gem")
span.number {{group.balance * 4}}
div.label(v-once) {{ $t('guildBank') }}
chat(
:label="$t('chat')",
:group="group",
:placeholder="!isParty ? $t('chatPlaceholder') : $t('partyChatPlaceholder')",
@fetchRecentMessages="fetchRecentMessages()"
)
template(slot="additionRow")
.row(v-if='showNoNotificationsMessage')
.col-12.no-notifications
| {{$t('groupNoNotifications')}}
.col-12.col-sm-4.sidebar
.row(:class='{"guild-background": !isParty}')
.col-12.buttons-wrapper
.button-container
button.btn.btn-success(class='btn-success', v-if='isLeader && !group.purchased.active', @click='upgradeGroup()')
| {{ $t('upgrade') }}
.button-container
button.btn.btn-primary(b-btn, @click="updateGuild", v-once, v-if='isLeader || isAdmin') {{ $t('edit') }}
.button-container
button.btn.btn-success(class='btn-success', v-if='!isMember', @click='join()') {{ $t('join') }}
.button-container
button.btn.btn-primary(v-once, @click='showInviteModal()') {{$t('invite')}}
// @TODO: hide the invitation button if there's an active group plan and the player is not the leader
.button-container
// @TODO: V2 button.btn.btn-primary(v-once, v-if='!isLeader') {{$t('messageGuildLeader')}} // Suggest making the button visible to the leader too - useful for them to test how the feature works or to send a note to themself. -- Alys
.button-container
// @TODO: V2 button.btn.btn-primary(v-once, v-if='isMember && !isParty') {{$t('donateGems')}} // Suggest removing the isMember restriction - it's okay if non-members donate to a public guild. Also probably allow it for parties if parties can buy imagery. -- Alys
div
quest-sidebar-section(:group='group', v-if='isParty')
sidebar-section(:title="$t('guildSummary')", v-if='!isParty')
p(v-markdown='group.summary')
sidebar-section(:title="$t('groupDescription')")
p(v-markdown='group.description')
sidebar-section(
:title="$t('challenges')",
:tooltip="$t('challengeDetails')"
)
group-challenges(:groupId='searchId')
div.text-center
button.btn.btn-danger(v-if='isMember', @click='clickLeave()') {{ isParty ? $t('leaveParty') : $t('leaveGroup') }}
<template>
<div
v-if="group._id"
class="row"
>
<group-form-modal v-if="isParty" /><start-quest-modal :group="this.group" /><quest-details-modal :group="this.group" /><participant-list-modal :group="this.group" /><group-gems-modal /><div class="col-12 col-sm-8 standard-page">
<div class="row">
<div class="col-12 col-md-6 title-details">
<h1>{{ group.name }}</h1><div>
<span class="mr-1 ml-0"><strong v-once>{{ $t('groupLeader') }}:</strong><user-link
class="mx-1"
:user="group.leader"
/></span>
</div>
</div><div class="col-12 col-md-6">
<div class="row icon-row">
<div
class="col-4 offset-4"
:class="{ 'offset-8': isParty }"
>
<div
class="item-with-icon"
@click="showMemberModal()"
>
<div
v-if="group.memberCount > 1000"
class="svg-icon shield"
v-html="icons.goldGuildBadgeIcon"
></div><div
v-if="group.memberCount > 100 && group.memberCount < 999"
class="svg-icon shield"
v-html="icons.silverGuildBadgeIcon"
></div><div
v-if="group.memberCount < 100"
class="svg-icon shield"
v-html="icons.bronzeGuildBadgeIcon"
></div><span class="number">{{ group.memberCount | abbrNum }}</span><div
v-once
class="member-list label"
>
{{ $t('memberList') }}
</div>
</div>
</div><div
v-if="!isParty"
class="col-4"
>
<div
class="item-with-icon"
@click="showGroupGems()"
>
<div
class="svg-icon gem"
v-html="icons.gem"
></div><span class="number">{{ group.balance * 4 }}</span><div
v-once
class="label"
>
{{ $t('guildBank') }}
</div>
</div>
</div>
</div>
</div>
</div><chat
:label="$t('chat')"
:group="group"
:placeholder="!isParty ? $t('chatPlaceholder') : $t('partyChatPlaceholder')"
@fetchRecentMessages="fetchRecentMessages()"
>
<template slot="additionRow">
<div
v-if="showNoNotificationsMessage"
class="row"
>
<div class="col-12 no-notifications">
{{ $t('groupNoNotifications') }}
</div>
</div>
</template>
</chat>
</div><div class="col-12 col-sm-4 sidebar">
<div
class="row"
:class="{'guild-background': !isParty}"
>
<div class="col-12 buttons-wrapper">
<div class="button-container">
<button
v-if="isLeader && !group.purchased.active"
class="btn btn-success btn-success"
@click="upgradeGroup()"
>
{{ $t('upgrade') }}
</button>
</div><div class="button-container">
<button
v-if="isLeader || isAdmin"
v-once
class="btn btn-primary"
b-btn="b-btn"
@click="updateGuild"
>
{{ $t('edit') }}
</button>
</div><div class="button-container">
<button
v-if="!isMember"
class="btn btn-success btn-success"
@click="join()"
>
{{ $t('join') }}
</button>
</div><div class="button-container">
<button
v-once
class="btn btn-primary"
@click="showInviteModal()"
>
{{ $t('invite') }}
</button><!-- @TODO: hide the invitation button if there's an active group plan and the player is not the leader-->
</div><div class="button-container">
<!-- @TODO: V2 button.btn.btn-primary(v-once, v-if='!isLeader') {{$t('messageGuildLeader')}} // Suggest making the button visible to the leader too - useful for them to test how the feature works or to send a note to themself. -- Alys-->
</div><div class="button-container">
<!-- @TODO: V2 button.btn.btn-primary(v-once, v-if='isMember && !isParty') {{$t('donateGems')}} // Suggest removing the isMember restriction - it's okay if non-members donate to a public guild. Also probably allow it for parties if parties can buy imagery. -- Alys-->
</div>
</div>
</div><div>
<quest-sidebar-section
v-if="isParty"
:group="group"
/><sidebar-section
v-if="!isParty"
:title="$t('guildSummary')"
>
<p v-markdown="group.summary"></p>
</sidebar-section><sidebar-section :title="$t('groupDescription')">
<p v-markdown="group.description"></p>
</sidebar-section><sidebar-section
:title="$t('challenges')"
:tooltip="$t('challengeDetails')"
>
<group-challenges :group-id="searchId" />
</sidebar-section>
</div><div class="text-center">
<button
v-if="isMember"
class="btn btn-danger"
@click="clickLeave()"
>
{{ isParty ? $t('leaveParty') : $t('leaveGroup') }}
</button>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,103 +1,206 @@
<template lang="pug">
b-modal#guild-form(:title="title", :hide-footer="true", size='lg')
form(@submit.stop.prevent="submit")
.form-group
label
strong(v-once) {{$t('name')}} *
b-form-input(type="text", :placeholder="$t('newGuildPlaceholder')", v-model="workingGroup.name")
.form-group
label
strong(v-once) {{$t('privacySettings')}} *
br
.custom-control.custom-checkbox
input.custom-control-input#onlyLeaderCreatesChallenges(type="checkbox", v-model="workingGroup.onlyLeaderCreatesChallenges")
label.custom-control-label(v-once, for="onlyLeaderCreatesChallenges") {{ $t('onlyLeaderCreatesChallenges') }}
#groupPrivateDescription1.icon(:title="$t('privateDescription')")
.svg-icon(v-html='icons.information')
b-tooltip(
:title="$t('onlyLeaderCreatesChallengesDetail')",
target="groupPrivateDescription1",
)
// br
// @TODO Implement in V2 .custom-control.custom-checkbox
input.custom-control-input(type="checkbox", v-model="workingGroup.guildLeaderCantBeMessaged")
label.custom-control-label(v-once) {{ $t('guildLeaderCantBeMessaged') }}
// "guildLeaderCantBeMessaged": "Leader can not be messaged directly",
// @TODO discuss the impact of this with moderators before implementing
br
.custom-control.custom-checkbox(v-if='!isParty && !this.workingGroup.id')
input.custom-control-input#privateGuild(type="checkbox", v-model="workingGroup.privateGuild")
label.custom-control-label(v-once, for="privateGuild") {{ $t('privateGuild') }}
#groupPrivateDescription2.icon(:title="$t('privateDescription')")
.svg-icon(v-html='icons.information')
b-tooltip(
:title="$t('privateDescription')",
target="groupPrivateDescription2",
)
// br
// @TODO: Implement in v2 .custom-control.custom-checkbox(v-if='!creatingParty')
input.custom-control-input(type="checkbox", v-model="workingGroup.allowGuildInvitationsFromNonMembers")
label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers') }}
// "allowGuildInvitationsFromNonMembers": "Allow Guild invitations from non-members",
.form-group(v-if='!isParty')
label
strong(v-once) {{$t('guildSummary')}} *
div.summary-count {{ $t('charactersRemaining', {characters: charactersRemaining}) }}
textarea.form-control.summary-textarea(:placeholder="isParty ? $t('partyDescriptionPlaceholder') : $t('guildSummaryPlaceholder')", v-model="workingGroup.summary")
// @TODO: need summary only for PUBLIC GUILDS, not for tavern, private guilds, or party
.form-group
label
strong(v-once) {{$t('groupDescription')}} *
a.float-right(v-markdown='$t("markdownFormattingHelp")')
textarea.form-control.description-textarea(type="text", textarea, :placeholder="isParty ? $t('partyDescriptionPlaceholder') : $t('guildDescriptionPlaceholder')", v-model="workingGroup.description")
.form-group(v-if='creatingParty && !workingGroup.id')
span
toggleSwitch(:label="$t('inviteMembersNow')", v-model='inviteMembers')
.form-group(style='position: relative;', v-if='!creatingParty && !isParty')
label
strong(v-once) {{$t('categories')}} *
div.category-wrap(@click.prevent="toggleCategorySelect")
span.category-select(v-if='workingGroup.categories.length === 0') {{$t('none')}}
.category-label(v-for='category in workingGroup.categories') {{$t(categoriesHashByKey[category])}}
.category-box(v-if="showCategorySelect")
.form-check(
v-for="group in categoryOptions",
:key="group.key",
v-if='group.key !== "habitica_official" || user.contributor.admin'
)
.custom-control.custom-checkbox
input.custom-control-input(:id="`category-${group.key}`", type="checkbox", :value="group.key", v-model="workingGroup.categories")
label.custom-control-label(v-once, :for="`category-${group.key}`") {{ $t(group.label) }}
button.btn.btn-primary(@click.prevent="toggleCategorySelect") {{$t('close')}}
// @TODO: need categories only for PUBLIC GUILDS, not for tavern, private guilds, or party
.form-group(v-if='inviteMembers && !workingGroup.id')
label
strong(v-once) Invite via Email or User ID
p(v-once) {{$t('inviteMembersHowTo')}} *
div
div(v-for='(member, index) in membersToInvite')
input(type='text', v-model='member.value')
button(@click.prevent='removeMemberToInvite(index)') Remove
div
input(type='text', placeholder='Email address or User ID', v-model='newMemberToInvite.value')
button(@click.prevent='addMemberToInvite()') Add
.form-group.text-center
div.item-with-icon(v-if='!this.workingGroup.id')
.svg-icon(v-html="icons.gem")
span.count 4
button.btn.btn-primary.btn-md(v-if='!workingGroup.id', :disabled='!workingGroup.name || !workingGroup.description') {{ creatingParty ? $t('createParty') : $t('createGuild') }}
button.btn.btn-primary.btn-md(v-if='workingGroup.id', :disabled='!workingGroup.name || !workingGroup.description') {{ isParty ? $t('updateParty') : $t('updateGuild') }}
.gem-description(v-once, v-if='!this.workingGroup.id') {{ $t('guildGemCostInfo') }}
<template>
<b-modal
id="guild-form"
:title="title"
:hide-footer="true"
size="lg"
>
<form @submit.stop.prevent="submit">
<div class="form-group">
<label><strong v-once>{{ $t('name') }} *</strong></label><b-form-input
v-model="workingGroup.name"
type="text"
:placeholder="$t('newGuildPlaceholder')"
/>
</div><div class="form-group">
<label><strong v-once>{{ $t('privacySettings') }} *</strong></label><br><div class="custom-control custom-checkbox">
<input
id="onlyLeaderCreatesChallenges"
v-model="workingGroup.onlyLeaderCreatesChallenges"
class="custom-control-input"
type="checkbox"
><label
v-once
class="custom-control-label"
for="onlyLeaderCreatesChallenges"
>{{ $t('onlyLeaderCreatesChallenges') }}</label><div
id="groupPrivateDescription1"
class="icon"
:title="$t('privateDescription')"
>
<div
class="svg-icon"
v-html="icons.information"
></div>
</div><b-tooltip
:title="$t('onlyLeaderCreatesChallengesDetail')"
target="groupPrivateDescription1"
/>
</div><!-- br--><!-- @TODO Implement in V2 .custom-control.custom-checkboxinput.custom-control-input(type="checkbox", v-model="workingGroup.guildLeaderCantBeMessaged")
label.custom-control-label(v-once) {{ $t('guildLeaderCantBeMessaged') }}
// "guildLeaderCantBeMessaged": "Leader can not be messaged directly",
// @TODO discuss the impact of this with moderators before implementing
--><br><div
v-if="!isParty && !this.workingGroup.id"
class="custom-control custom-checkbox"
>
<input
id="privateGuild"
v-model="workingGroup.privateGuild"
class="custom-control-input"
type="checkbox"
><label
v-once
class="custom-control-label"
for="privateGuild"
>{{ $t('privateGuild') }}</label><div
id="groupPrivateDescription2"
class="icon"
:title="$t('privateDescription')"
>
<div
class="svg-icon"
v-html="icons.information"
></div>
</div><b-tooltip
:title="$t('privateDescription')"
target="groupPrivateDescription2"
/>
</div><!-- br--><!-- @TODO: Implement in v2 .custom-control.custom-checkbox(v-if='!creatingParty')input.custom-control-input(type="checkbox", v-model="workingGroup.allowGuildInvitationsFromNonMembers")
label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers') }}
// "allowGuildInvitationsFromNonMembers": "Allow Guild invitations from non-members",
-->
</div><div
v-if="!isParty"
class="form-group"
>
<label><strong v-once>{{ $t('guildSummary') }} *</strong></label><div class="summary-count">
{{ $t('charactersRemaining', {characters: charactersRemaining}) }}
</div><textarea
v-model="workingGroup.summary"
class="form-control summary-textarea"
:placeholder="isParty ? $t('partyDescriptionPlaceholder') : $t('guildSummaryPlaceholder')"
></textarea><!-- @TODO: need summary only for PUBLIC GUILDS, not for tavern, private guilds, or party-->
</div><div class="form-group">
<label><strong v-once>{{ $t('groupDescription') }} *</strong></label><a
v-markdown="$t('markdownFormattingHelp')"
class="float-right"
></a><textarea
v-model="workingGroup.description"
class="form-control description-textarea"
type="text"
textarea="textarea"
:placeholder="isParty ? $t('partyDescriptionPlaceholder') : $t('guildDescriptionPlaceholder')"
></textarea>
</div><div
v-if="creatingParty && !workingGroup.id"
class="form-group"
>
<span><toggleSwitch
v-model="inviteMembers"
:label="$t('inviteMembersNow')"
/></span>
</div><div
v-if="!creatingParty && !isParty"
class="form-group"
style="position: relative;"
>
<label><strong v-once>{{ $t('categories') }} *</strong></label><div
class="category-wrap"
@click.prevent="toggleCategorySelect"
>
<span
v-if="workingGroup.categories.length === 0"
class="category-select"
>{{ $t('none') }}</span><div
v-for="category in workingGroup.categories"
class="category-label"
>
{{ $t(categoriesHashByKey[category]) }}
</div>
</div><div
v-if="showCategorySelect"
class="category-box"
>
<div
v-for="group in categoryOptions"
v-if="group.key !== 'habitica_official' || user.contributor.admin"
:key="group.key"
class="form-check"
>
<div class="custom-control custom-checkbox">
<input
:id="`category-${group.key}`"
v-model="workingGroup.categories"
class="custom-control-input"
type="checkbox"
:value="group.key"
><label
v-once
class="custom-control-label"
:for="`category-${group.key}`"
>{{ $t(group.label) }}</label>
</div>
</div><button
class="btn btn-primary"
@click.prevent="toggleCategorySelect"
>
{{ $t('close') }}
</button>
</div><!-- @TODO: need categories only for PUBLIC GUILDS, not for tavern, private guilds, or party-->
</div><div
v-if="inviteMembers && !workingGroup.id"
class="form-group"
>
<label><strong v-once>Invite via Email or User ID</strong><p v-once>{{ $t('inviteMembersHowTo') }} *</p></label><div>
<div v-for="(member, index) in membersToInvite">
<input
v-model="member.value"
type="text"
><button @click.prevent="removeMemberToInvite(index)">
Remove
</button>
</div><div>
<input
v-model="newMemberToInvite.value"
type="text"
placeholder="Email address or User ID"
><button @click.prevent="addMemberToInvite()">
Add
</button>
</div>
</div>
</div><div class="form-group text-center">
<div
v-if="!this.workingGroup.id"
class="item-with-icon"
>
<div
class="svg-icon"
v-html="icons.gem"
></div><span class="count">4</span>
</div><button
v-if="!workingGroup.id"
class="btn btn-primary btn-md"
:disabled="!workingGroup.name || !workingGroup.description"
>
{{ creatingParty ? $t('createParty') : $t('createGuild') }}
</button><button
v-if="workingGroup.id"
class="btn btn-primary btn-md"
:disabled="!workingGroup.name || !workingGroup.description"
>
{{ isParty ? $t('updateParty') : $t('updateGuild') }}
</button><div
v-if="!this.workingGroup.id"
v-once
class="gem-description"
>
{{ $t('guildGemCostInfo') }}
</div>
</div>
</form>
</b-modal>
</template>
<style lang="scss" scoped>

View file

@ -1,12 +1,27 @@
<template lang="pug">
b-modal#group-gems-modal(:title="$t('groupGems')", size='md', :hide-footer="true")
.modal-body
.row
.col-6.offset-3
h3 {{ $t('groupGemsDesc') }}
.modal-footer
.col-12.text-center
button.btn.btn-primary(@click='close()') {{$t('close')}}
<template>
<b-modal
id="group-gems-modal"
:title="$t('groupGems')"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="row">
<div class="col-6 offset-3">
<h3>{{ $t('groupGemsDesc') }}</h3>
</div>
</div>
</div><div class="modal-footer">
<div class="col-12 text-center">
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('close') }}
</button>
</div>
</div>
</b-modal>
</template>
<style scoped>

View file

@ -1,108 +1,228 @@
<template lang="pug">
// @TODO: Move to group plans folder
div
div
.header
h1.text-center Need more for your Group?
.row
.col-8.offset-2.text-center
h2.sub-text {{ $t('groupBenefitsDescription') }}
.container.benefits
.row
.col-4
.box
img.box1(src='~@/assets/images/group-plans/group-14@3x.png')
hr
h2 {{ $t('teamBasedTasks') }}
p Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!
.col-4
.box
img.box2(src='~@/assets/images/group-plans/group-12@3x.png')
hr
h2 Group Management Controls
p Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.
.col-4
.box
img.box3(src='~@/assets/images/group-plans/group-13@3x.png')
hr
h2 In-Game Benefits
p Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.
#upgrading-group.container.payment-options(v-if='upgradingGroup._id')
h1.text-center.purple-header Are you ready to upgrade?
.row
.col-12.text-center
.purple-box
.amount-section
.dollar $
.number 9
.name Group Owner Subscription
.plus
.svg-icon(v-html="icons.positiveIcon")
.amount-section
.dollar $
.number 3
.name Each Individual Group Member
.box.payment-providers
h3 Choose your payment method
.payments-column
button.purchase.btn.btn-primary.payment-button.payment-item(@click='pay(PAYMENTS.STRIPE)')
.svg-icon.credit-card-icon(v-html="icons.creditCardIcon")
| {{ $t('card') }}
amazon-button.payment-item(:amazon-data="pay(PAYMENTS.AMAZON)")
.container.col-6.offset-3.create-option(v-if='!upgradingGroup._id')
.row
h1.col-12.text-center.purple-header Create your Group today!
.row
.col-12.text-center
button.btn.btn-primary.create-group(@click='launchModal("create")') Create Your New Group
.row.pricing
.col-5
.dollar $
.number 9
.name
div Group Owner
div Subscription
.col-1
.plus +
.col-6
.dollar $
.number 3
.name
div Each Additional
div Member
b-modal#group-plan-modal(title="Select Payment", size='md', hide-footer=true)
.col-12(v-if='activePage === PAGES.CREATE_GROUP')
.form-group
label.control-label(for='new-group-name') Name
input.form-control#new-group-name.input-medium.option-content(required, type='text', placeholder="Name", v-model='newGroup.name')
.form-group
label(for='new-group-description') {{ $t('description') }}
textarea.form-control#new-group-description.option-content(cols='3', :placeholder="$t('description')", v-model='newGroup.description')
.form-group(v-if='type === "guild"')
.custom-control.custom-radio
input.custom-control-input(type='radio', name='new-group-privacy', value='private', v-model='newGroup.privacy')
label.custom-control-label {{ $t('inviteOnly') }}
.form-group
.custom-control.custom-checkbox
input.custom-control-input(type='checkbox', v-model='newGroup.leaderOnly.challenges' id='create-group-leaderOnlyChallenges-checkbox')
label.custom-control-label(for='create-group-leaderOnlyChallenges-checkbox') {{ $t('leaderOnlyChallenges') }}
.form-group(v-if='type === "party"')
button.btn.btn-secondary.form-control(@click='createGroup()', :value="$t('createGroupPlan')")
.form-group
button.btn.btn-primary.btn-lg.btn-block(@click="createGroup()", :disabled="!newGroupIsReady") {{ $t('createGroupPlan') }}
.col-12(v-if='activePage === PAGES.PAY')
.text-center
h3 Choose your payment method
.payments-column.mx-auto
button.purchase.btn.btn-primary.payment-button.payment-item(@click='pay(PAYMENTS.STRIPE)')
.svg-icon.credit-card-icon(v-html="icons.creditCardIcon")
| {{ $t('card') }}
amazon-button.payment-item(:amazon-data="pay(PAYMENTS.AMAZON)")
<template>
<!-- @TODO: Move to group plans folder--><div>
<div>
<div class="header">
<h1 class="text-center">
Need more for your Group?
</h1><div class="row">
<div class="col-8 offset-2 text-center">
<h2 class="sub-text">
{{ $t('groupBenefitsDescription') }}
</h2>
</div>
</div>
</div><div class="container benefits">
<div class="row">
<div class="col-4">
<div class="box">
<img
class="box1"
src="~@/assets/images/group-plans/group-14@3x.png"
><hr><h2>{{ $t('teamBasedTasks') }}</h2><p>Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!</p>
</div>
</div><div class="col-4">
<div class="box">
<img
class="box2"
src="~@/assets/images/group-plans/group-12@3x.png"
><hr><h2>Group Management Controls</h2><p>Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.</p>
</div>
</div><div class="col-4">
<div class="box">
<img
class="box3"
src="~@/assets/images/group-plans/group-13@3x.png"
><hr><h2>In-Game Benefits</h2><p>Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.</p>
</div>
</div>
</div>
</div><div
v-if="upgradingGroup._id"
id="upgrading-group"
class="container payment-options"
>
<h1 class="text-center purple-header">
Are you ready to upgrade?
</h1><div class="row">
<div class="col-12 text-center">
<div class="purple-box">
<div class="amount-section">
<div class="dollar">
$
</div><div class="number">
9
</div><div class="name">
Group Owner Subscription
</div>
</div><div class="plus">
<div
class="svg-icon"
v-html="icons.positiveIcon"
></div>
</div><div class="amount-section">
<div class="dollar">
$
</div><div class="number">
3
</div><div class="name">
Each Individual Group Member
</div>
</div>
</div><div class="box payment-providers">
<h3>Choose your payment method</h3><div class="payments-column">
<button
class="purchase btn btn-primary payment-button payment-item"
@click="pay(PAYMENTS.STRIPE)"
>
<div
class="svg-icon credit-card-icon"
v-html="icons.creditCardIcon"
></div>{{ $t('card') }}
</button><amazon-button
class="payment-item"
:amazon-data="pay(PAYMENTS.AMAZON)"
/>
</div>
</div>
</div>
</div>
</div><div
v-if="!upgradingGroup._id"
class="container col-6 offset-3 create-option"
>
<div class="row">
<h1 class="col-12 text-center purple-header">
Create your Group today!
</h1>
</div><div class="row">
<div class="col-12 text-center">
<button
class="btn btn-primary create-group"
@click="launchModal('create')"
>
Create Your New Group
</button>
</div>
</div><div class="row pricing">
<div class="col-5">
<div class="dollar">
$
</div><div class="number">
9
</div><div class="name">
<div>Group Owner</div><div>Subscription</div>
</div>
</div><div class="col-1">
<div class="plus">
+
</div>
</div><div class="col-6">
<div class="dollar">
$
</div><div class="number">
3
</div><div class="name">
<div>Each Additional</div><div>Member</div>
</div>
</div>
</div>
</div>
</div><b-modal
id="group-plan-modal"
title="Select Payment"
size="md"
hide-footer="hide-footer"
>
<div
v-if="activePage === PAGES.CREATE_GROUP"
class="col-12"
>
<div class="form-group">
<label
class="control-label"
for="new-group-name"
>Name</label><input
id="new-group-name"
v-model="newGroup.name"
class="form-control input-medium option-content"
required="required"
type="text"
placeholder="Name"
>
</div><div class="form-group">
<label for="new-group-description">{{ $t('description') }}</label><textarea
id="new-group-description"
v-model="newGroup.description"
class="form-control option-content"
cols="3"
:placeholder="$t('description')"
></textarea>
</div><div
v-if="type === 'guild'"
class="form-group"
>
<div class="custom-control custom-radio">
<input
v-model="newGroup.privacy"
class="custom-control-input"
type="radio"
name="new-group-privacy"
value="private"
><label class="custom-control-label">{{ $t('inviteOnly') }}</label>
</div>
</div><div class="form-group">
<div class="custom-control custom-checkbox">
<input
id="create-group-leaderOnlyChallenges-checkbox"
v-model="newGroup.leaderOnly.challenges"
class="custom-control-input"
type="checkbox"
><label
class="custom-control-label"
for="create-group-leaderOnlyChallenges-checkbox"
>{{ $t('leaderOnlyChallenges') }}</label>
</div>
</div><div
v-if="type === 'party'"
class="form-group"
>
<button
class="btn btn-secondary form-control"
:value="$t('createGroupPlan')"
@click="createGroup()"
></button>
</div><div class="form-group">
<button
class="btn btn-primary btn-lg btn-block"
:disabled="!newGroupIsReady"
@click="createGroup()"
>
{{ $t('createGroupPlan') }}
</button>
</div>
</div><div
v-if="activePage === PAGES.PAY"
class="col-12"
>
<div class="text-center">
<h3>Choose your payment method</h3><div class="payments-column mx-auto">
<button
class="purchase btn btn-primary payment-button payment-item"
@click="pay(PAYMENTS.STRIPE)"
>
<div
class="svg-icon credit-card-icon"
v-html="icons.creditCardIcon"
></div>{{ $t('card') }}
</button><amazon-button
class="payment-item"
:amazon-data="pay(PAYMENTS.AMAZON)"
/>
</div>
</div>
</div>
</b-modal>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,14 +1,30 @@
<template lang="pug">
.row
secondary-menu.col-12
router-link.nav-link(:to="{name: 'tavern'}", exact, :class="{'active': $route.name === 'tavern'}") {{ $t('tavern') }}
router-link.nav-link(:to="{name: 'myGuilds'}", :class="{'active': $route.name === 'myGuilds'}") {{ $t('myGuilds') }}
router-link.nav-link(:to="{name: 'guildsDiscovery'}", :class="{'active': $route.name === 'guildsDiscovery'}") {{ $t('guildsDiscovery') }}
.col-12
router-view
group-form-modal
<template>
<div class="row">
<secondary-menu class="col-12">
<router-link
class="nav-link"
:to="{name: 'tavern'}"
exact="exact"
:class="{'active': $route.name === 'tavern'}"
>
{{ $t('tavern') }}
</router-link><router-link
class="nav-link"
:to="{name: 'myGuilds'}"
:class="{'active': $route.name === 'myGuilds'}"
>
{{ $t('myGuilds') }}
</router-link><router-link
class="nav-link"
:to="{name: 'guildsDiscovery'}"
:class="{'active': $route.name === 'guildsDiscovery'}"
>
{{ $t('guildsDiscovery') }}
</router-link>
</secondary-menu><div class="col-12">
<router-view />
</div><group-form-modal />
</div>
</template>
<script>

View file

@ -1,24 +1,52 @@
<template lang="pug">
b-modal#invite-modal(:title='$t(`inviteTo${groupType}`)', :hide-footer='true')
div
strong {{ $t('inviteEmailUsername') }}
.small {{ $t('inviteEmailUsernameInfo') }}
div(v-for='(invite, index) in invites')
.input-group
.d-flex.align-items-center.justify-content-center(v-if='index === invites.length - 1 && invite.text.length === 0')
.svg-icon.positive-icon(v-html='icons.positiveIcon')
input.form-control(
type='text',
:placeholder='$t("emailOrUsernameInvite")',
v-model='invite.text',
v-on:keyup='expandInviteList',
v-on:change='checkInviteList',
:class='{"input-valid": invite.valid, "is-invalid input-invalid": invite.valid === false}',
)
.input-error.text-center.mt-2(v-if="invite.error") {{ invite.error }}
.modal-footer.d-flex.justify-content-center
a.mr-3(@click='close()') {{ $t('cancel') }}
button.btn.btn-primary(@click='sendInvites()', :class='{disabled: cannotSubmit}', :disabled='cannotSubmit') {{ $t('sendInvitations') }}
<template>
<b-modal
id="invite-modal"
:title="$t(`inviteTo${groupType}`)"
:hide-footer="true"
>
<div>
<strong>{{ $t('inviteEmailUsername') }}</strong><div class="small">
{{ $t('inviteEmailUsernameInfo') }}
</div><div v-for="(invite, index) in invites">
<div class="input-group">
<div
v-if="index === invites.length - 1 && invite.text.length === 0"
class="d-flex align-items-center justify-content-center"
>
<div
class="svg-icon positive-icon"
v-html="icons.positiveIcon"
></div>
</div><input
v-model="invite.text"
class="form-control"
type="text"
:placeholder="$t('emailOrUsernameInvite')"
:class="{'input-valid': invite.valid, 'is-invalid input-invalid': invite.valid === false}"
@keyup="expandInviteList"
@change="checkInviteList"
>
</div><div
v-if="invite.error"
class="input-error text-center mt-2"
>
{{ invite.error }}
</div>
</div>
</div><div class="modal-footer d-flex justify-content-center">
<a
class="mr-3"
@click="close()"
>{{ $t('cancel') }}</a><button
class="btn btn-primary"
:class="{disabled: cannotSubmit}"
:disabled="cannotSubmit"
@click="sendInvites()"
>
{{ $t('sendInvitations') }}
</button>
</div>
</b-modal>
</template>
<style lang="scss">

View file

@ -1,78 +1,202 @@
<template lang="pug">
// @TODO: Move this to a member directory
div
remove-member-modal(:member-to-remove='memberToRemove', :group-id='this.groupId' @member-removed='memberRemoved')
b-modal#members-modal(:title="$t('createGuild')", size='md', :hide-footer='true')
.header-wrap(slot="modal-header")
.row
.col-6
h1(v-once) {{$t('members')}}
.col-6
button(type="button" aria-label="Close" class="close", @click='close()')
span(aria-hidden="true") ×
.row.d-flex.align-items-center
.col-4
input.form-control.input-search(type="text", :placeholder="$t('search')", v-model='searchTerm')
.col
select.form-control(@change='changeSortOption($event)')
option(v-for='sortOption in sortOptions', :value='sortOption.value') {{sortOption.text}}
.col-3
select.form-control(@change='changeSortDirection($event)')
option(v-for='sortDirection in sortDirections', :value='sortDirection.value') {{sortDirection.text}}
.row.apply-options.d-flex.justify-content-center(v-if='sortDirty && group.type === "party"')
a(@click='applySortOptions()') {{ $t('applySortToHeader') }}
.row(v-if='invites.length > 0')
.col-6.offset-3.nav
.nav-item(@click='viewMembers()', :class="{active: selectedPage === 'members'}") {{ $t('members') }}
.nav-item(@click='viewInvites()', :class="{active: selectedPage === 'invites'}") {{ $t('invites') }}
div(v-if='selectedPage === "members"')
.row(v-for='(member, index) in sortedMembers')
.col-11.no-padding-left
member-details(:member='member')
.col-1.actions
b-dropdown(right=true)
.svg-icon.inline.dots(slot='button-content', v-html="icons.dots")
b-dropdown-item(@click='sendMessage(member)')
span.dropdown-icon-item
.svg-icon.inline(v-html="icons.messageIcon")
span.text {{$t('sendMessage')}}
b-dropdown-item(@click='promoteToLeader(member)', v-if='shouldShowLeaderFunctions(member._id)')
span.dropdown-icon-item
.svg-icon.inline(v-html="icons.starIcon")
span.text {{$t('promoteToLeader')}}
b-dropdown-item(@click='addManager(member._id)', v-if='shouldShowAddManager(member._id)')
span.dropdown-icon-item
.svg-icon.inline(v-html="icons.starIcon")
span.text {{$t('addManager')}}
b-dropdown-item(@click='removeManager(member._id)', v-if='shouldShowRemoveManager(member._id)')
span.dropdown-icon-item
.svg-icon.inline(v-html="icons.removeIcon")
span.text {{$t('removeManager2')}}
b-dropdown-item(@click='viewProgress(member)', v-if='challengeId')
span.dropdown-icon-item
span.text {{ $t('viewProgress') }}
b-dropdown-item(@click='removeMember(member, index)', v-if='shouldShowLeaderFunctions(member._id)')
span.dropdown-icon-item
.svg-icon.inline(v-html="icons.removeIcon")
span.text {{$t('removeMember')}}
.row(v-if='isLoadMoreAvailable')
.col-12.text-center
button.btn.btn-secondary(@click='loadMoreMembers()') {{ $t('loadMore') }}
.row.gradient(v-if='members.length > 3')
div(v-if='selectedPage === "invites"')
.row(v-for='(member, index) in invites')
.col-11.no-padding-left
member-details(:member='member')
.col-1.actions
b-dropdown(right=true)
.svg-icon.inline.dots(slot='button-content', v-html="icons.dots")
b-dropdown-item(@click='removeInvite(member, index)', v-if='isLeader')
span.dropdown-icon-item
.svg-icon.inline(v-html="icons.removeIcon", v-if='isLeader')
span.text {{$t('removeInvite')}}
.modal-footer
button.btn.btn-primary(@click='close()') {{ $t('close') }}
<template>
<!-- @TODO: Move this to a member directory--><div>
<remove-member-modal
:member-to-remove="memberToRemove"
:group-id="this.groupId"
@member-removed="memberRemoved"
/><b-modal
id="members-modal"
:title="$t('createGuild')"
size="md"
:hide-footer="true"
>
<div
slot="modal-header"
class="header-wrap"
>
<div class="row">
<div class="col-6">
<h1 v-once>
{{ $t('members') }}
</h1>
</div><div class="col-6">
<button
class="close"
type="button"
aria-label="Close"
@click="close()"
>
<span aria-hidden="true">×</span>
</button>
</div>
</div><div class="row d-flex align-items-center">
<div class="col-4">
<input
v-model="searchTerm"
class="form-control input-search"
type="text"
:placeholder="$t('search')"
>
</div><div class="col">
<select
class="form-control"
@change="changeSortOption($event)"
>
<option
v-for="sortOption in sortOptions"
:value="sortOption.value"
>
{{ sortOption.text }}
</option>
</select>
</div><div class="col-3">
<select
class="form-control"
@change="changeSortDirection($event)"
>
<option
v-for="sortDirection in sortDirections"
:value="sortDirection.value"
>
{{ sortDirection.text }}
</option>
</select>
</div>
</div>
</div><div
v-if="sortDirty && group.type === 'party'"
class="row apply-options d-flex justify-content-center"
>
<a @click="applySortOptions()">{{ $t('applySortToHeader') }}</a>
</div><div
v-if="invites.length > 0"
class="row"
>
<div class="col-6 offset-3 nav">
<div
class="nav-item"
:class="{active: selectedPage === 'members'}"
@click="viewMembers()"
>
{{ $t('members') }}
</div><div
class="nav-item"
:class="{active: selectedPage === 'invites'}"
@click="viewInvites()"
>
{{ $t('invites') }}
</div>
</div>
</div><div v-if="selectedPage === 'members'">
<div
v-for="(member, index) in sortedMembers"
class="row"
>
<div class="col-11 no-padding-left">
<member-details :member="member" />
</div><div class="col-1 actions">
<b-dropdown right="right">
<div
slot="button-content"
class="svg-icon inline dots"
v-html="icons.dots"
></div><b-dropdown-item @click="sendMessage(member)">
<span class="dropdown-icon-item"><div
class="svg-icon inline"
v-html="icons.messageIcon"
></div><span class="text">{{ $t('sendMessage') }}</span></span>
</b-dropdown-item><b-dropdown-item
v-if="shouldShowLeaderFunctions(member._id)"
@click="promoteToLeader(member)"
>
<span class="dropdown-icon-item"><div
class="svg-icon inline"
v-html="icons.starIcon"
></div><span class="text">{{ $t('promoteToLeader') }}</span></span>
</b-dropdown-item><b-dropdown-item
v-if="shouldShowAddManager(member._id)"
@click="addManager(member._id)"
>
<span class="dropdown-icon-item"><div
class="svg-icon inline"
v-html="icons.starIcon"
></div><span class="text">{{ $t('addManager') }}</span></span>
</b-dropdown-item><b-dropdown-item
v-if="shouldShowRemoveManager(member._id)"
@click="removeManager(member._id)"
>
<span class="dropdown-icon-item"><div
class="svg-icon inline"
v-html="icons.removeIcon"
></div><span class="text">{{ $t('removeManager2') }}</span></span>
</b-dropdown-item><b-dropdown-item
v-if="challengeId"
@click="viewProgress(member)"
>
<span class="dropdown-icon-item"><span class="text">{{ $t('viewProgress') }}</span></span>
</b-dropdown-item><b-dropdown-item
v-if="shouldShowLeaderFunctions(member._id)"
@click="removeMember(member, index)"
>
<span class="dropdown-icon-item"><div
class="svg-icon inline"
v-html="icons.removeIcon"
></div><span class="text">{{ $t('removeMember') }}</span></span>
</b-dropdown-item>
</b-dropdown>
</div>
</div><div
v-if="isLoadMoreAvailable"
class="row"
>
<div class="col-12 text-center">
<button
class="btn btn-secondary"
@click="loadMoreMembers()"
>
{{ $t('loadMore') }}
</button>
</div>
</div><div
v-if="members.length > 3"
class="row gradient"
></div>
</div><div v-if="selectedPage === 'invites'">
<div
v-for="(member, index) in invites"
class="row"
>
<div class="col-11 no-padding-left">
<member-details :member="member" />
</div><div class="col-1 actions">
<b-dropdown right="right">
<div
slot="button-content"
class="svg-icon inline dots"
v-html="icons.dots"
></div><b-dropdown-item
v-if="isLeader"
@click="removeInvite(member, index)"
>
<span class="dropdown-icon-item"><div
v-if="isLeader"
class="svg-icon inline"
v-html="icons.removeIcon"
></div><span class="text">{{ $t('removeInvite') }}</span></span>
</b-dropdown-item>
</b-dropdown>
</div>
</div>
</div><div class="modal-footer">
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('close') }}
</button>
</div>
</b-modal>
</div>
</template>
<style lang='scss'>

View file

@ -1,35 +1,70 @@
<template lang="pug">
.row
sidebar(v-on:search="updateSearch", v-on:filter="updateFilters")
.standard-page
.row
.col-md-8.text-left
h1.page-header(v-once) {{ $t('myGuilds') }}
h2(v-if='loading && guilds.length === 0') {{ $t('loading') }}
.col-4
button.btn.btn-secondary.create-group-button.float-right(@click='createGroup()')
.svg-icon.positive-icon(v-html="icons.positiveIcon")
span(v-once) {{$t('createGuild2')}}
// @TODO: Add when we implement recent activity .float-right
span.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
.row
.no-guilds.text-center.col-md-6.offset-md-3(v-if='!loading && guilds.length === 0')
.svg-icon(v-html='icons.greyBadge')
h2(v-once) {{$t('noGuildsTitle')}}
p(v-once) {{$t('noGuildsParagraph1')}}
p(v-once) {{$t('noGuildsParagraph2')}}
.row
.no-guilds.text-center.col-md-6.offset-md-3(v-if='!loading && guilds.length > 0 && filteredGuilds.length === 0')
h2(v-once) {{$t('noGuildsMatchFilters')}}
.row
.col-md-12
public-guild-item(v-for="guild in filteredGuilds", :key='guild._id', :guild="guild", :display-gem-bank='true')
<template>
<div class="row">
<sidebar
@search="updateSearch"
@filter="updateFilters"
/><div class="standard-page">
<div class="row">
<div class="col-md-8 text-left">
<h1
v-once
class="page-header"
>
{{ $t('myGuilds') }}
</h1><h2 v-if="loading && guilds.length === 0">
{{ $t('loading') }}
</h2>
</div><div class="col-4">
<button
class="btn btn-secondary create-group-button float-right"
@click="createGroup()"
>
<div
class="svg-icon positive-icon"
v-html="icons.positiveIcon"
></div><span v-once>{{ $t('createGuild2') }}</span>
</button><!-- @TODO: Add when we implement recent activity .float-rightspan.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
-->
</div>
</div><div class="row">
<div
v-if="!loading && guilds.length === 0"
class="no-guilds text-center col-md-6 offset-md-3"
>
<div
class="svg-icon"
v-html="icons.greyBadge"
></div><h2 v-once>
{{ $t('noGuildsTitle') }}
</h2><p v-once>
{{ $t('noGuildsParagraph1') }}
</p><p v-once>
{{ $t('noGuildsParagraph2') }}
</p>
</div>
</div><div class="row">
<div
v-if="!loading && guilds.length > 0 && filteredGuilds.length === 0"
class="no-guilds text-center col-md-6 offset-md-3"
>
<h2 v-once>
{{ $t('noGuildsMatchFilters') }}
</h2>
</div>
</div><div class="row">
<div class="col-md-12">
<public-guild-item
v-for="guild in filteredGuilds"
:key="guild._id"
:guild="guild"
:display-gem-bank="true"
/>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,20 +0,0 @@
<template lang="pug">
div
button.btn.btn-primary(b-btn, @click="$root.$emit('bv::show::modal','new-party-modal')") {{ $t('viewMembers') }}
b-modal#new-party-modal(:title="$t('createGuild')", size='lg')
.header-wrap(slot="modal-header")
.row
.col-6
h1(v-once) {{$t('members')}}
.col-6
button(type="button" aria-label="Close" class="close")
span(aria-hidden="true") ×
.row
.form-group.col-6
input.form-control.search(type="text", :placeholder="$t('search')", v-model='searchTerm')
.col-4.offset-2
span.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', @click='sort(sortOption.value)', :key='sortOption.value') {{sortOption.text}}
</template>

View file

@ -1,17 +1,45 @@
<template lang="pug">
b-modal#participant-list(size='md', :hide-footer='true')
.header-wrap(slot="modal-header")
.row
.col-6
h1(v-once) {{ $t('participantsTitle') }}
.col-6
button(type="button" aria-label="Close" class="close", @click='close()')
span(aria-hidden="true") ×
.row(v-for='member in participants')
.col-12.no-padding-left
member-details(:member='member')
.modal-footer
button.btn.btn-primary(@click='close()') {{ $t('close') }}
<template>
<b-modal
id="participant-list"
size="md"
:hide-footer="true"
>
<div
slot="modal-header"
class="header-wrap"
>
<div class="row">
<div class="col-6">
<h1 v-once>
{{ $t('participantsTitle') }}
</h1>
</div><div class="col-6">
<button
class="close"
type="button"
aria-label="Close"
@click="close()"
>
<span aria-hidden="true">×</span>
</button>
</div>
</div>
</div><div
v-for="member in participants"
class="row"
>
<div class="col-12 no-padding-left">
<member-details :member="member" />
</div>
</div><div class="modal-footer">
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('close') }}
</button>
</div>
</b-modal>
</template>
<style lang='scss'>

View file

@ -1,31 +1,97 @@
<template lang="pug">
router-link.card-link(:to="{ name: 'guild', params: { groupId: guild._id } }")
.card
.card-body
.row
.col-md-2.badge-column
.shield-wrap(:class="{gold: guild.memberCount >= 1000, silver: guild.memberCount >= 100 && guild.memberCount < 1000}")
.svg-icon.shield(v-html="icons.goldGuildBadge", v-if='guild.memberCount >= 1000')
.svg-icon.shield(v-html="icons.silverGuildBadgeIcon", v-if='guild.memberCount >= 100 && guild.memberCount < 1000')
.svg-icon.shield(v-html="icons.bronzeGuildBadgeIcon", v-if='guild.memberCount < 100')
.member-count {{ guild.memberCount | abbrNum }}
.col-md-10
.row
.col-md-8
router-link(:to="{ name: 'guild', params: { groupId: guild._id } }")
h3 {{ guild.name }}
p.summary(v-if='guild.summary') {{guild.summary.substr(0, MAX_SUMMARY_SIZE_FOR_GUILDS)}}
p.summary(v-else) {{ guild.name }}
.col-md-2.cta-container
button.btn.btn-danger(v-if='isMember && displayLeave' @click.prevent='leave()', v-once) {{ $t('leave') }}
button.btn.btn-success(v-if='!isMember' @click='join()', v-once) {{ $t('join') }}
div.item-with-icon.gem-bank(v-if='displayGemBank')
.svg-icon.gem(v-html="icons.gem")
span.count {{ guild.balance * 4 }}
div.guild-bank(v-if='displayGemBank', v-once) {{$t('guildBank')}}
.row
category-tags.col-md-12(:categories="guild.categories", :owner="isOwner", v-once)
span.recommend-text(v-if='showSuggested(guild._id)') {{$t('suggestedGroup')}}
<template>
<router-link
class="card-link"
:to="{ name: 'guild', params: { groupId: guild._id } }"
>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-2 badge-column">
<div
class="shield-wrap"
:class="{gold: guild.memberCount >= 1000, silver: guild.memberCount >= 100 && guild.memberCount < 1000}"
>
<div
v-if="guild.memberCount >= 1000"
class="svg-icon shield"
v-html="icons.goldGuildBadge"
></div><div
v-if="guild.memberCount >= 100 && guild.memberCount < 1000"
class="svg-icon shield"
v-html="icons.silverGuildBadgeIcon"
></div><div
v-if="guild.memberCount < 100"
class="svg-icon shield"
v-html="icons.bronzeGuildBadgeIcon"
></div><div class="member-count">
{{ guild.memberCount | abbrNum }}
</div>
</div>
</div><div class="col-md-10">
<div class="row">
<div class="col-md-8">
<router-link :to="{ name: 'guild', params: { groupId: guild._id } }">
<h3>{{ guild.name }}</h3>
</router-link><p
v-if="guild.summary"
class="summary"
>
{{ guild.summary.substr(0, MAX_SUMMARY_SIZE_FOR_GUILDS) }}
</p><p
v-else
class="summary"
>
{{ guild.name }}
</p>
</div><div class="col-md-2 cta-container">
<button
v-if="isMember && displayLeave"
v-once
class="btn btn-danger"
@click.prevent="leave()"
>
{{ $t('leave') }}
</button><button
v-if="!isMember"
v-once
class="btn btn-success"
@click="join()"
>
{{ $t('join') }}
</button><div
v-if="displayGemBank"
class="item-with-icon gem-bank"
>
<div
class="svg-icon gem"
v-html="icons.gem"
></div><span class="count">{{ guild.balance * 4 }}</span>
</div><div
v-if="displayGemBank"
v-once
class="guild-bank"
>
{{ $t('guildBank') }}
</div>
</div>
</div><div class="row">
<category-tags
v-once
class="col-md-12"
:categories="guild.categories"
:owner="isOwner"
>
<span
v-if="showSuggested(guild._id)"
class="recommend-text"
> {{ $t('suggestedGroup') }}</span>
</category-tags>
</div>
</div>
</div>
</div>
</div>
</router-link>
</template>
<style lang="scss" scoped>

View file

@ -1,26 +1,74 @@
<template lang="pug">
b-modal#quest-details(title="Empty", size='md', :hide-footer="true", :hide-header="true")
.left-panel.content
h3.text-center {{ $t('participantsTitle') }}
.row
.col-10.offset-1.text-center
span.description(v-once) {{ $t('participantDesc') }}
.row
.col-12.member(v-for='member in members')
strong(:class="{'declined-name': member.accepted === false}") {{member.name}}
.accepted.float-right(v-if='member.accepted === true') {{ $t('accepted') }}
.declined.float-right(v-if='member.accepted === false') {{ $t('declined') }}
.pending.float-right(v-if='member.accepted === null') {{ $t('pending') }}
div(v-if='questData')
questDialogContent(:item="questData")
div.text-center.actions(v-if='canEditQuest')
div
button.btn.btn-secondary(v-once, @click="questConfirm()") {{ $t('begin') }}
// @TODO don't allow the party leader to start the quest until the leader has accepted or rejected the invitation (users get confused and think "begin" means "join quest")
div
.cancel(v-once, @click="questCancel()") {{ $t('cancel') }}
.side-panel(v-if='questData')
questDialogDrops(:item="questData")
<template>
<b-modal
id="quest-details"
title="Empty"
size="md"
:hide-footer="true"
:hide-header="true"
>
<div class="left-panel content">
<h3 class="text-center">
{{ $t('participantsTitle') }}
</h3><div class="row">
<div class="col-10 offset-1 text-center">
<span
v-once
class="description"
>{{ $t('participantDesc') }}</span>
</div>
</div><div class="row">
<div
v-for="member in members"
class="col-12 member"
>
<strong :class="{'declined-name': member.accepted === false}">{{ member.name }}</strong><div
v-if="member.accepted === true"
class="accepted float-right"
>
{{ $t('accepted') }}
</div><div
v-if="member.accepted === false"
class="declined float-right"
>
{{ $t('declined') }}
</div><div
v-if="member.accepted === null"
class="pending float-right"
>
{{ $t('pending') }}
</div>
</div>
</div>
</div><div v-if="questData">
<questDialogContent :item="questData" />
</div><div
v-if="canEditQuest"
class="text-center actions"
>
<div>
<button
v-once
class="btn btn-secondary"
@click="questConfirm()"
>
{{ $t('begin') }}
</button><!-- @TODO don't allow the party leader to start the quest until the leader has accepted or rejected the invitation (users get confused and think "begin" means "join quest")-->
</div><div>
<div
v-once
class="cancel"
@click="questCancel()"
>
{{ $t('cancel') }}
</div>
</div>
</div><div
v-if="questData"
class="side-panel"
>
<questDialogDrops :item="questData" />
</div>
</b-modal>
</template>
<style lang='scss' scoped>

View file

@ -1,68 +1,169 @@
<template lang="pug">
sidebar-section(:title="$t('questDetailsTitle')")
.row.no-quest-section(v-if='!onPendingQuest && !onActiveQuest')
.col-12.text-center
.svg-icon(v-html="icons.questIcon")
h4(v-once) {{ $t('youAreNotOnQuest') }}
p(v-once) {{ $t('questDescription') }}
button.btn.btn-secondary(v-once, @click="openStartQuestModal()") {{ $t('startAQuest') }}
.row.quest-active-section(v-if='onPendingQuest && !onActiveQuest')
.col-2
.quest(:class='`inventory_quest_scroll_${questData.key}`')
.col-6.titles
strong {{ questData.text() }}
p {{acceptedCount}} / {{group.memberCount}}
.col-4
button.btn.btn-secondary(@click="openQuestDetails()") {{ $t('details') }}
.row.quest-active-section.quest-invite(v-if='user.party.quest && user.party.quest.RSVPNeeded')
span {{ $t('wouldYouParticipate') }}
button.btn.btn-primary.accept(@click='questAccept(group._id)') {{$t('accept')}}
button.btn.btn-primary.reject(@click='questReject(group._id)') {{$t('reject')}}
.row.quest-active-section(v-if='!onPendingQuest && onActiveQuest')
.col-12.text-center
.quest-boss(:class="'quest_' + questData.key")
h3(v-once) {{ questData.text() }}
.quest-box
.collect-info(v-if='questData.collect')
.row
.col-12
a.float-right(@click="openParticipantList()") {{ $t('participantsTitle') }}
.row(v-for='(value, key) in questData.collect')
.col-2
div(:class="'quest_' + questData.key + '_' + key")
.col-10
strong {{value.text()}}
.grey-progress-bar
.collect-progress-bar(:style="{width: (group.quest.progress.collect[key] / value.count) * 100 + '%'}")
strong {{group.quest.progress.collect[key]}} / {{value.count}}
div.text-right(v-if='userIsOnQuest') {{parseFloat(user.party.quest.progress.collectedItems) || 0}} items found
.boss-info(v-if='questData.boss')
.row
.col-6
h4.float-left(v-once) {{ questData.boss.name() }}
.col-6
a.float-right(@click="openParticipantList()") {{ $t('participantsTitle') }}
.row
.col-12
.grey-progress-bar
.boss-health-bar(:style="{width: bossHpPercent + '%'}")
.row.boss-details
.col-6
span.float-left
| {{ Math.ceil(parseFloat(group.quest.progress.hp) * 100) / 100 }} / {{ parseFloat(questData.boss.hp).toFixed(2) }}
// current boss hp uses ceil so you don't underestimate damage needed to end quest
.col-6(v-if='userIsOnQuest')
// @TODO: Why do we not sync quest progress on the group doc? Each user could have different progress.
span.float-right {{ user.party.quest.progress.up | floor(10) }} {{ $t('pendingDamageLabel') }}
// player's pending damage uses floor so you don't overestimate damage you've already done
.row.rage-bar-row(v-if='questData.boss.rage')
.col-12
.grey-progress-bar
.boss-health-bar.rage-bar(:style="{width: (group.quest.progress.rage / questData.boss.rage.value) * 100 + '%'}")
.row.boss-details.rage-details(v-if='questData.boss.rage')
.col-6
span.float-left {{ $t('rage') }} {{ parseFloat(group.quest.progress.rage).toFixed(2) }} / {{ questData.boss.rage.value }}
button.btn.btn-secondary(v-once, @click="questAbort()", v-if='canEditQuest') {{ $t('abort') }}
<template>
<sidebar-section :title="$t('questDetailsTitle')">
<div
v-if="!onPendingQuest && !onActiveQuest"
class="row no-quest-section"
>
<div class="col-12 text-center">
<div
class="svg-icon"
v-html="icons.questIcon"
></div><h4 v-once>
{{ $t('youAreNotOnQuest') }}
</h4><p v-once>
{{ $t('questDescription') }}
</p><button
v-once
class="btn btn-secondary"
@click="openStartQuestModal()"
>
{{ $t('startAQuest') }}
</button>
</div>
</div><div
v-if="onPendingQuest && !onActiveQuest"
class="row quest-active-section"
>
<div class="col-2">
<div
class="quest"
:class="`inventory_quest_scroll_${questData.key}`"
></div>
</div><div class="col-6 titles">
<strong>{{ questData.text() }}</strong><p>{{ acceptedCount }} / {{ group.memberCount }}</p>
</div><div class="col-4">
<button
class="btn btn-secondary"
@click="openQuestDetails()"
>
{{ $t('details') }}
</button>
</div>
</div><div
v-if="user.party.quest && user.party.quest.RSVPNeeded"
class="row quest-active-section quest-invite"
>
<span>{{ $t('wouldYouParticipate') }}</span><button
class="btn btn-primary accept"
@click="questAccept(group._id)"
>
{{ $t('accept') }}
</button><button
class="btn btn-primary reject"
@click="questReject(group._id)"
>
{{ $t('reject') }}
</button>
</div><div
v-if="!onPendingQuest && onActiveQuest"
class="row quest-active-section"
>
<div class="col-12 text-center">
<div
class="quest-boss"
:class="'quest_' + questData.key"
></div><h3 v-once>
{{ questData.text() }}
</h3><div class="quest-box">
<div
v-if="questData.collect"
class="collect-info"
>
<div class="row">
<div class="col-12">
<a
class="float-right"
@click="openParticipantList()"
>{{ $t('participantsTitle') }}</a>
</div>
</div><div
v-for="(value, key) in questData.collect"
class="row"
>
<div class="col-2">
<div :class="'quest_' + questData.key + '_' + key"></div>
</div><div class="col-10">
<strong>{{ value.text() }}</strong><div class="grey-progress-bar">
<div
class="collect-progress-bar"
:style="{width: (group.quest.progress.collect[key] / value.count) * 100 + '%'}"
></div>
</div><strong>{{ group.quest.progress.collect[key] }} / {{ value.count }}</strong>
</div>
</div><div
v-if="userIsOnQuest"
class="text-right"
>
{{ parseFloat(user.party.quest.progress.collectedItems) || 0 }} items found
</div>
</div><div
v-if="questData.boss"
class="boss-info"
>
<div class="row">
<div class="col-6">
<h4
v-once
class="float-left"
>
{{ questData.boss.name() }}
</h4>
</div><div class="col-6">
<a
class="float-right"
@click="openParticipantList()"
>{{ $t('participantsTitle') }}</a>
</div>
</div><div class="row">
<div class="col-12">
<div class="grey-progress-bar">
<div
class="boss-health-bar"
:style="{width: bossHpPercent + '%'}"
></div>
</div>
</div>
</div><div class="row boss-details">
<div class="col-6">
<span class="float-left">{{ Math.ceil(parseFloat(group.quest.progress.hp) * 100) / 100 }} / {{ parseFloat(questData.boss.hp).toFixed(2) }}<!-- current boss hp uses ceil so you don't underestimate damage needed to end quest--></span>
</div><div
v-if="userIsOnQuest"
class="col-6"
>
<!-- @TODO: Why do we not sync quest progress on the group doc? Each user could have different progress.--><span class="float-right">{{ user.party.quest.progress.up | floor(10) }} {{ $t('pendingDamageLabel') }}</span><!-- player's pending damage uses floor so you don't overestimate damage you've already done-->
</div>
</div><div
v-if="questData.boss.rage"
class="row rage-bar-row"
>
<div class="col-12">
<div class="grey-progress-bar">
<div
class="boss-health-bar rage-bar"
:style="{width: (group.quest.progress.rage / questData.boss.rage.value) * 100 + '%'}"
></div>
</div>
</div>
</div><div
v-if="questData.boss.rage"
class="row boss-details rage-details"
>
<div class="col-6">
<span class="float-left">{{ $t('rage') }} {{ parseFloat(group.quest.progress.rage).toFixed(2) }} / {{ questData.boss.rage.value }}</span>
</div>
</div>
</div>
</div><button
v-if="canEditQuest"
v-once
class="btn btn-secondary"
@click="questAbort()"
>
{{ $t('abort') }}
</button>
</div>
</div>
</sidebar-section>
</template>
<style lang="scss" scoped>

View file

@ -1,37 +1,78 @@
<template lang="pug">
.standard-sidebar.d-none.d-sm-block
.form-group
input.form-control.search(type="text", :placeholder="$t('search')", v-model='searchTerm')
form
h2(v-once) {{ $t('filter') }}
.form-group
h3 {{ $t('category') }}
.form-check(
v-for="group in categoryOptions",
:key="group.key",
)
.custom-control.custom-checkbox
input.custom-control-input(type="checkbox", :value='group.key' v-model="categoryFilters", :id="group.key")
label.custom-control-label(v-once, :for="group.key") {{ $t(group.label) }}
.form-group
h3 {{ $t('role') }}
.form-check(
v-for="group in roleOptions",
:key="group.key",
)
.custom-control.custom-checkbox
input.custom-control-input(type="checkbox", :value='group.key' v-model="roleFilters", :id="group.key")
label.custom-control-label(v-once, :for="group.key") {{ $t(group.label) }}
.form-group
h3 {{ $t('guildSize') }}
.form-check(
v-for="group in guildSizeOptions",
:key="group.key",
)
.custom-control.custom-checkbox
input.custom-control-input(type="checkbox", :value='group.key' v-model="guildSizeFilters", :id="group.key")
label.custom-control-label(v-once, :for="group.key") {{ $t(group.label) }}
<template>
<div class="standard-sidebar d-none d-sm-block">
<div class="form-group">
<input
v-model="searchTerm"
class="form-control search"
type="text"
:placeholder="$t('search')"
>
</div><form>
<h2 v-once>
{{ $t('filter') }}
</h2><div class="form-group">
<h3>{{ $t('category') }}</h3><div
v-for="group in categoryOptions"
:key="group.key"
class="form-check"
>
<div class="custom-control custom-checkbox">
<input
:id="group.key"
v-model="categoryFilters"
class="custom-control-input"
type="checkbox"
:value="group.key"
><label
v-once
class="custom-control-label"
:for="group.key"
>{{ $t(group.label) }}</label>
</div>
</div>
</div><div class="form-group">
<h3>{{ $t('role') }}</h3><div
v-for="group in roleOptions"
:key="group.key"
class="form-check"
>
<div class="custom-control custom-checkbox">
<input
:id="group.key"
v-model="roleFilters"
class="custom-control-input"
type="checkbox"
:value="group.key"
><label
v-once
class="custom-control-label"
:for="group.key"
>{{ $t(group.label) }}</label>
</div>
</div>
</div><div class="form-group">
<h3>{{ $t('guildSize') }}</h3><div
v-for="group in guildSizeOptions"
:key="group.key"
class="form-check"
>
<div class="custom-control custom-checkbox">
<input
:id="group.key"
v-model="guildSizeFilters"
class="custom-control-input"
type="checkbox"
:value="group.key"
><label
v-once
class="custom-control-label"
:for="group.key"
>{{ $t(group.label) }}</label>
</div>
</div>
</div>
</form>
</div>
</template>
<script>

View file

@ -1,31 +1,65 @@
<template lang="pug">
b-modal#start-quest-modal(title="Empty", size='md', :hide-footer="true", :hide-header="true")
.left-panel.content
h3.text-center Quests
.row
.col-4.quest-col(
v-for='(value, key, index) in user.items.quests',
@click='selectQuest({key})',
:class="{selected: key === selectedQuest}", v-if='value > 0')
.quest-wrapper
b-popover(
<template>
<b-modal
id="start-quest-modal"
title="Empty"
size="md"
:hide-footer="true"
:hide-header="true"
>
<div class="left-panel content">
<h3 class="text-center">
Quests
</h3><div class="row">
<div
v-for="(value, key, index) in user.items.quests"
v-if="value > 0"
class="col-4 quest-col"
:class="{selected: key === selectedQuest}"
@click="selectQuest({key})"
>
<div class="quest-wrapper">
<b-popover
:target="`inventory_quest_scroll_${key}`"
placement="top"
triggers="hover")
h4.popover-content-title {{ quests.quests[key].text() }}
questInfo(:quest="quests.quests[key]")
.quest(:class="`inventory_quest_scroll_${key}`", :id="`inventory_quest_scroll_${key}`")
.row
.col-10.offset-1.text-center
span.description(v-once) {{ $t('noQuestToStart') }}
div(v-if='questData')
questDialogContent(:item="questData")
div.text-center
button.btn.btn-primary(@click='questInit()', :disabled="!Boolean(selectedQuest) || loading") {{$t('inviteToPartyOrQuest')}}
div.text-center
p {{$t('inviteInformation')}}
.side-panel(v-if='questData')
questDialogDrops(:item="questData")
placement="top"
triggers="hover"
>
<h4 class="popover-content-title">
{{ quests.quests[key].text() }}
</h4><questInfo :quest="quests.quests[key]" />
</b-popover><div
:id="`inventory_quest_scroll_${key}`"
class="quest"
:class="`inventory_quest_scroll_${key}`"
></div>
</div>
</div>
</div><div class="row">
<div class="col-10 offset-1 text-center">
<span
v-once
class="description"
>{{ $t('noQuestToStart') }}</span>
</div>
</div>
</div><div v-if="questData">
<questDialogContent :item="questData" />
</div><div class="text-center">
<button
class="btn btn-primary"
:disabled="!Boolean(selectedQuest) || loading"
@click="questInit()"
>
{{ $t('inviteToPartyOrQuest') }}
</button>
</div><div class="text-center">
<p>{{ $t('inviteInformation') }}</p>
</div><div
v-if="questData"
class="side-panel"
>
<questDialogDrops :item="questData" />
</div>
</b-modal>
</template>
<style lang='scss' scoped>

View file

@ -1,164 +1,392 @@
<template lang="pug">
.row
world-boss-info-modal
world-boss-rage-modal
.col-12.col-sm-8.clearfix.standard-page
.row
.col-6.title-details
h1(v-once) {{ $t('welcomeToTavern') }}
chat(
:label="$t('tavernChat')",
:group="group",
:placeholder="$t('tavernCommunityGuidelinesPlaceholder')",
@fetchRecentMessages="fetchRecentMessages()"
)
.col-12.col-sm-4.sidebar
.section
.grassy-meadow-backdrop
.daniel_front
.boss-section
.world-boss(v-if='group && group.quest && group.quest.active', :style="{background: questData.colors.dark, 'border-color': questData.colors.extralight, 'outline-color': questData.colors.light}")
.corner-decoration(:style="{top: '-2px', right: '-2px'}")
.corner-decoration(:style="{top: '-2px', left: '-2px'}")
.corner-decoration(:style="{bottom: '-2px', right: '-2px'}")
.corner-decoration(:style="{bottom: '-2px', left: '-2px'}")
.text-center.float-bar.d-flex.align-items-center
span.diamond
span.strong.reduce(:style="{background: questData.colors.dark}") {{ $t('worldBossEvent') }}
span.diamond
.boss-gradient.pb-3.pt-3
p.text-center.reduce(:style="{color: questData.colors.extralight}") {{ $t(`${questData.key}ArtCredit`) }}
.quest-boss(:class="'background_' + questData.key")
.quest-boss(:class="'quest_' + questData.key")
.quest-boss(:class="'phobia_' + questData.key", :style="{display: 'none'}")
.p-3
.row.d-flex.align-items-center.mb-2
.col-sm-6
strong.float-left {{ questData.boss.name() }}
.col-sm-6
span.d-flex.float-right
.svg-icon.boss-icon(v-html="icons.swordIcon")
span.ml-1.reduce(:style="{color: questData.colors.extralight}") {{ $t('pendingDamage', {damage: pendingDamage()}) }}
.grey-progress-bar.mb-1
.boss-health-bar(:style="{width: (group.quest.progress.hp / questData.boss.hp) * 100 + '%'}")
span.d-flex.align-items-center
.svg-icon.boss-icon(v-html="icons.healthIcon")
span.reduce.ml-1.pt-1 {{ $t('bossHealth', {currentHealth: bossCurrentHealth(), maxHealth: questData.boss.hp.toLocaleString()}) }}
.mt-3.mb-2
strong.mr-1 {{ $t('rageAttack') }}
span {{ questData.boss.rage.title() }}
.grey-progress-bar.mb-1
.boss-health-bar.rage-bar(:style="{width: (group.quest.progress.rage / questData.boss.rage.value) * 100 + '%'}")
span.d-flex.align-items-center
.svg-icon.boss-icon(v-html="icons.rageIcon")
span.reduce.ml-1.pt-1 {{ $t('bossRage', {currentRage: bossCurrentRage(), maxRage: questData.boss.rage.value.toLocaleString()}) }}
.row.d-flex.align-items-center.mb-2.mt-2
.col-sm-4.d-flex
strong.mr-2 {{ $t('rageStrikes') }}
.svg-icon.boss-icon.information-icon.m-auto(v-html="icons.informationIcon", v-b-tooltip.hover.top="questData.boss.rage.description()")
.col-sm-8.d-flex.align-items-center.justify-content-center
.m-auto(@click="showWorldBossRage('seasonalShop')")
img.rage-strike(src="~@/assets/images/world-boss/rage_strike@2x.png", v-if="!group.quest.extra.worldDmg.seasonalShop")
img.rage-strike-active(src="~@/assets/images/world-boss/rage_strike-seasonalShop@2x.png", v-if="group.quest.extra.worldDmg.seasonalShop")
.m-auto(@click="showWorldBossRage('market')")
img.rage-strike(src="~@/assets/images/world-boss/rage_strike@2x.png", v-if="!group.quest.extra.worldDmg.market")
img.rage-strike-active(src="~@/assets/images/world-boss/rage_strike-market@2x.png", v-if="group.quest.extra.worldDmg.market")
.m-auto(@click="showWorldBossRage('quests')")
img.rage-strike(src="~@/assets/images/world-boss/rage_strike@2x.png", v-if="!group.quest.extra.worldDmg.quests")
img.rage-strike-active(src="~@/assets/images/world-boss/rage_strike-quests@2x.png", v-if="group.quest.extra.worldDmg.quests")
.boss-description.p-3(:style="{'border-color': questData.colors.extralight}", @click="sections.worldBoss = !sections.worldBoss")
strong.float-left {{ $t('worldBossDescription') }}
.float-right
.toggle-down(v-if="!sections.worldBoss")
.svg-icon.boss-icon(v-html="icons.chevronIcon")
.toggle-up(v-if="sections.worldBoss")
.svg-icon.boss-icon.reverse(v-html="icons.chevronIcon")
.mt-3(v-if="sections.worldBoss", v-html="questData.notes()")
// .text-center.mt-4
.world-boss-info-button(@click="showWorldBossInfo()") {{$t('whatIsWorldBoss') }}
.sleep.below-header-sections
strong(v-once) {{ $t('sleepDescription') }}
ul
li(v-once) {{ $t('sleepBullet1') }}
li(v-once) {{ $t('sleepBullet2') }}
li(v-once) {{ $t('sleepBullet3') }}
li(v-once) {{ $t('sleepBullet4') }}
button.btn.btn-secondary.pause-button(v-if='!user.preferences.sleep', @click='toggleSleep()', v-once) {{ $t('pauseDailies') }}
button.btn.btn-secondary.pause-button(v-if='user.preferences.sleep', @click='toggleSleep()', v-once) {{ $t('unpauseDailies') }}
.px-3
sidebar-section(:title="$t('staffAndModerators')")
.row
.col-4.staff(v-for='user in staff', :class='{staff: user.type === "Staff", moderator: user.type === "Moderator", bailey: user.name === "It\'s Bailey"}')
div
router-link.title(:to="{'name': 'userProfile', 'params': {'userId': user.uuid}}") {{user.name}}
.svg-icon.staff-icon(v-html="icons.tierStaff", v-if='user.type === "Staff"')
.svg-icon.mod-icon(v-html="icons.tierMod", v-if='user.type === "Moderator" && user.name !== "It\'s Bailey"')
.svg-icon.npc-icon(v-html="icons.tierNPC", v-if='user.name === "It\'s Bailey"')
.type {{user.type}}
sidebar-section(:title="$t('helpfulLinks')")
ul
li
a(href='', @click.prevent='modForm()') {{ $t('contactForm') }}
li
router-link(to='/static/community-guidelines', v-once) {{ $t('communityGuidelinesLink') }}
li
router-link(to="/groups/guild/f2db2a7f-13c5-454d-b3ee-ea1f5089e601") {{ $t('lookingForGroup') }}
li
router-link(to='/static/faq', v-once) {{ $t('faq') }}
li
a(href='', v-html="$t('glossary')")
li
a(href='http://habitica.fandom.com/wiki/Habitica_Wiki' target='_blank', v-once) {{ $t('wiki') }}
li
a(href='https://oldgods.net/habitrpg/habitrpg_user_data_display.html', target='_blank', v-once) {{ $t('dataDisplayTool') }}
li
router-link(to="/groups/guild/a29da26b-37de-4a71-b0c6-48e72a900dac") {{ $t('reportProblem') }}
li
a(href='https://trello.com/c/odmhIqyW/440-read-first-table-of-contents', target='_blank', v-once) {{ $t('requestFeature') }}
li
a(href='', v-html="$t('communityForum')")
li
router-link(to="/groups/guild/5481ccf3-5d2d-48a9-a871-70a7380cee5a") {{ $t('askQuestionGuild') }}
sidebar-section(:title="$t('playerTiers')")
.row
.col-12
p(v-once) {{ $t('playerTiersDesc') }}
ul.tier-list
li.tier1(v-once)
| {{ $t('tier1') }}
.svg-icon.tier1-icon(v-html="icons.tier1")
li.tier2(v-once)
| {{ $t('tier2') }}
.svg-icon.tier2-icon(v-html="icons.tier2")
li.tier3(v-once)
| {{ $t('tier3') }}
.svg-icon.tier3-icon(v-html="icons.tier3")
li.tier4(v-once)
| {{ $t('tier4') }}
.svg-icon.tier4-icon(v-html="icons.tier4")
li.tier5(v-once)
| {{ $t('tier5') }}
.svg-icon.tier5-icon(v-html="icons.tier5")
li.tier6(v-once)
| {{ $t('tier6') }}
.svg-icon.tier6-icon(v-html="icons.tier6")
li.tier7(v-once)
| {{ $t('tier7') }}
.svg-icon.tier7-icon(v-html="icons.tier7")
li.moderator(v-once)
| {{ $t('tierModerator') }}
.svg-icon.mod-icon(v-html="icons.tierMod")
li.staff(v-once)
| {{ $t('tierStaff') }}
.svg-icon.staff-icon(v-html="icons.tierStaff")
li.npc(v-once)
| {{ $t('tierNPC') }}
.svg-icon.npc-icon(v-html="icons.tierNPC")
<template>
<div class="row">
<world-boss-info-modal /><world-boss-rage-modal /><div class="col-12 col-sm-8 clearfix standard-page">
<div class="row">
<div class="col-6 title-details">
<h1 v-once>
{{ $t('welcomeToTavern') }}
</h1>
</div>
</div><chat
:label="$t('tavernChat')"
:group="group"
:placeholder="$t('tavernCommunityGuidelinesPlaceholder')"
@fetchRecentMessages="fetchRecentMessages()"
/>
</div><div class="col-12 col-sm-4 sidebar">
<div class="section">
<div class="grassy-meadow-backdrop">
<div class="daniel_front"></div>
</div><div class="boss-section">
<div
v-if="group && group.quest && group.quest.active"
class="world-boss"
:style="{background: questData.colors.dark, 'border-color': questData.colors.extralight, 'outline-color': questData.colors.light}"
>
<div
class="corner-decoration"
:style="{top: '-2px', right: '-2px'}"
></div><div
class="corner-decoration"
:style="{top: '-2px', left: '-2px'}"
></div><div
class="corner-decoration"
:style="{bottom: '-2px', right: '-2px'}"
></div><div
class="corner-decoration"
:style="{bottom: '-2px', left: '-2px'}"
></div><div class="text-center float-bar d-flex align-items-center">
<span class="diamond"></span><span
class="strong reduce"
:style="{background: questData.colors.dark}"
>{{ $t('worldBossEvent') }}</span><span class="diamond"></span>
</div><div class="boss-gradient pb-3 pt-3">
<p
class="text-center reduce"
:style="{color: questData.colors.extralight}"
>
{{ $t(`${questData.key}ArtCredit`) }}
</p><div
class="quest-boss"
:class="'background_' + questData.key"
>
<div
class="quest-boss"
:class="'quest_' + questData.key"
></div><div
class="quest-boss"
:class="'phobia_' + questData.key"
:style="{display: 'none'}"
></div>
</div>
</div><div class="p-3">
<div class="row d-flex align-items-center mb-2">
<div class="col-sm-6">
<strong class="float-left">{{ questData.boss.name() }}</strong>
</div><div class="col-sm-6">
<span class="d-flex float-right"><div
class="svg-icon boss-icon"
v-html="icons.swordIcon"
></div><span
class="ml-1 reduce"
:style="{color: questData.colors.extralight}"
>{{ $t('pendingDamage', {damage: pendingDamage()}) }}</span></span>
</div>
</div><div class="grey-progress-bar mb-1">
<div
class="boss-health-bar"
:style="{width: (group.quest.progress.hp / questData.boss.hp) * 100 + '%'}"
></div>
</div><span class="d-flex align-items-center"><div
class="svg-icon boss-icon"
v-html="icons.healthIcon"
></div><span class="reduce ml-1 pt-1">{{ $t('bossHealth', {currentHealth: bossCurrentHealth(), maxHealth: questData.boss.hp.toLocaleString()}) }}</span></span><div class="mt-3 mb-2">
<strong class="mr-1">{{ $t('rageAttack') }}</strong><span>{{ questData.boss.rage.title() }}</span>
</div><div class="grey-progress-bar mb-1">
<div
class="boss-health-bar rage-bar"
:style="{width: (group.quest.progress.rage / questData.boss.rage.value) * 100 + '%'}"
></div>
</div><span class="d-flex align-items-center"><div
class="svg-icon boss-icon"
v-html="icons.rageIcon"
></div><span class="reduce ml-1 pt-1">{{ $t('bossRage', {currentRage: bossCurrentRage(), maxRage: questData.boss.rage.value.toLocaleString()}) }}</span></span><div class="row d-flex align-items-center mb-2 mt-2">
<div class="col-sm-4 d-flex">
<strong class="mr-2">{{ $t('rageStrikes') }}</strong><div
v-b-tooltip.hover.top="questData.boss.rage.description()"
class="svg-icon boss-icon information-icon m-auto"
v-html="icons.informationIcon"
></div>
</div><div class="col-sm-8 d-flex align-items-center justify-content-center">
<div
class="m-auto"
@click="showWorldBossRage('seasonalShop')"
>
<img
v-if="!group.quest.extra.worldDmg.seasonalShop"
class="rage-strike"
src="~@/assets/images/world-boss/rage_strike@2x.png"
><img
v-if="group.quest.extra.worldDmg.seasonalShop"
class="rage-strike-active"
src="~@/assets/images/world-boss/rage_strike-seasonalShop@2x.png"
>
</div><div
class="m-auto"
@click="showWorldBossRage('market')"
>
<img
v-if="!group.quest.extra.worldDmg.market"
class="rage-strike"
src="~@/assets/images/world-boss/rage_strike@2x.png"
><img
v-if="group.quest.extra.worldDmg.market"
class="rage-strike-active"
src="~@/assets/images/world-boss/rage_strike-market@2x.png"
>
</div><div
class="m-auto"
@click="showWorldBossRage('quests')"
>
<img
v-if="!group.quest.extra.worldDmg.quests"
class="rage-strike"
src="~@/assets/images/world-boss/rage_strike@2x.png"
><img
v-if="group.quest.extra.worldDmg.quests"
class="rage-strike-active"
src="~@/assets/images/world-boss/rage_strike-quests@2x.png"
>
</div>
</div>
</div><div
class="boss-description p-3"
:style="{'border-color': questData.colors.extralight}"
@click="sections.worldBoss = !sections.worldBoss"
>
<strong class="float-left">{{ $t('worldBossDescription') }}</strong><div class="float-right">
<div
v-if="!sections.worldBoss"
class="toggle-down"
>
<div
class="svg-icon boss-icon"
v-html="icons.chevronIcon"
></div>
</div><div
v-if="sections.worldBoss"
class="toggle-up"
>
<div
class="svg-icon boss-icon reverse"
v-html="icons.chevronIcon"
></div>
</div>
</div>
</div><div
v-if="sections.worldBoss"
class="mt-3"
v-html="questData.notes()"
></div>
</div>
</div><!-- .text-center.mt-4.world-boss-info-button(@click="showWorldBossInfo()") {{$t('whatIsWorldBoss') }}
-->
</div><div class="sleep below-header-sections">
<strong v-once>{{ $t('sleepDescription') }}</strong><ul>
<li v-once>
{{ $t('sleepBullet1') }}
</li><li v-once>
{{ $t('sleepBullet2') }}
</li><li v-once>
{{ $t('sleepBullet3') }}
</li><li v-once>
{{ $t('sleepBullet4') }}
</li>
</ul><button
v-if="!user.preferences.sleep"
v-once
class="btn btn-secondary pause-button"
@click="toggleSleep()"
>
{{ $t('pauseDailies') }}
</button><button
v-if="user.preferences.sleep"
v-once
class="btn btn-secondary pause-button"
@click="toggleSleep()"
>
{{ $t('unpauseDailies') }}
</button>
</div>
</div><div class="px-3">
<sidebar-section :title="$t('staffAndModerators')">
<div class="row">
<div
v-for="user in staff"
class="col-4 staff"
:class="{staff: user.type === 'Staff', moderator: user.type === 'Moderator', bailey: user.name === 'It's Bailey'}"
>
<div>
<router-link
class="title"
:to="{'name': 'userProfile', 'params': {'userId': user.uuid}}"
>
{{ user.name }}
</router-link><div
v-if="user.type === 'Staff'"
class="svg-icon staff-icon"
v-html="icons.tierStaff"
></div><div
v-if="user.type === 'Moderator' && user.name !== 'It's Bailey'"
class="svg-icon mod-icon"
v-html="icons.tierMod"
></div><div
v-if="user.name === 'It's Bailey'"
class="svg-icon npc-icon"
v-html="icons.tierNPC"
></div>
</div><div class="type">
{{ user.type }}
</div>
</div>
</div>
</sidebar-section><sidebar-section :title="$t('helpfulLinks')">
<ul>
<li>
<a
href=""
@click.prevent="modForm()"
>{{ $t('contactForm') }}</a>
</li><li>
<router-link
v-once
to="/static/community-guidelines"
>
{{ $t('communityGuidelinesLink') }}
</router-link>
</li><li>
<router-link to="/groups/guild/f2db2a7f-13c5-454d-b3ee-ea1f5089e601">
{{ $t('lookingForGroup') }}
</router-link>
</li><li>
<router-link
v-once
to="/static/faq"
>
{{ $t('faq') }}
</router-link>
</li><li>
<a
href=""
v-html="$t('glossary')"
></a>
</li><li>
<a
v-once
href="http://habitica.fandom.com/wiki/Habitica_Wiki"
target="_blank"
>{{ $t('wiki') }}</a>
</li><li>
<a
v-once
href="https://oldgods.net/habitrpg/habitrpg_user_data_display.html"
target="_blank"
>{{ $t('dataDisplayTool') }}</a>
</li><li>
<router-link to="/groups/guild/a29da26b-37de-4a71-b0c6-48e72a900dac">
{{ $t('reportProblem') }}
</router-link>
</li><li>
<a
v-once
href="https://trello.com/c/odmhIqyW/440-read-first-table-of-contents"
target="_blank"
>{{ $t('requestFeature') }}</a>
</li><li>
<a
href=""
v-html="$t('communityForum')"
></a>
</li><li>
<router-link to="/groups/guild/5481ccf3-5d2d-48a9-a871-70a7380cee5a">
{{ $t('askQuestionGuild') }}
</router-link>
</li>
</ul>
</sidebar-section><sidebar-section :title="$t('playerTiers')">
<div class="row">
<div class="col-12">
<p v-once>
{{ $t('playerTiersDesc') }}
</p><ul class="tier-list">
<li
v-once
class="tier1"
>
{{ $t('tier1') }}<div
class="svg-icon tier1-icon"
v-html="icons.tier1"
></div>
</li><li
v-once
class="tier2"
>
{{ $t('tier2') }}<div
class="svg-icon tier2-icon"
v-html="icons.tier2"
></div>
</li><li
v-once
class="tier3"
>
{{ $t('tier3') }}<div
class="svg-icon tier3-icon"
v-html="icons.tier3"
></div>
</li><li
v-once
class="tier4"
>
{{ $t('tier4') }}<div
class="svg-icon tier4-icon"
v-html="icons.tier4"
></div>
</li><li
v-once
class="tier5"
>
{{ $t('tier5') }}<div
class="svg-icon tier5-icon"
v-html="icons.tier5"
></div>
</li><li
v-once
class="tier6"
>
{{ $t('tier6') }}<div
class="svg-icon tier6-icon"
v-html="icons.tier6"
></div>
</li><li
v-once
class="tier7"
>
{{ $t('tier7') }}<div
class="svg-icon tier7-icon"
v-html="icons.tier7"
></div>
</li><li
v-once
class="moderator"
>
{{ $t('tierModerator') }}<div
class="svg-icon mod-icon"
v-html="icons.tierMod"
></div>
</li><li
v-once
class="staff"
>
{{ $t('tierStaff') }}<div
class="svg-icon staff-icon"
v-html="icons.tierStaff"
></div>
</li><li
v-once
class="npc"
>
{{ $t('tierNPC') }}<div
class="svg-icon npc-icon"
v-html="icons.tierNPC"
></div>
</li>
</ul>
</div>
</div>
</sidebar-section>
</div>
</div>
</div>
</template>
<style lang='scss' scoped>

View file

@ -1,102 +1,195 @@
<template lang="pug">
.row.standard-page
small.muted(v-html="$t('blurbHallContributors')")
.well
div(v-if='user.contributor.admin')
h2 Reward User
.row
.form.col-6(v-if='!hero.profile')
.form-group
input.form-control(type='text', v-model='heroID', :placeholder="'User ID or Username'")
.form-group
button.btn.btn-secondary(@click='loadHero(heroID)')
| Load User
.row
.form.col-6(v-if='hero && hero.profile', submit='saveHero(hero)')
router-link(:to="{'name': 'userProfile', 'params': {'userId': hero._id}}")
h3 @{{hero.auth.local.username}} &nbsp; / &nbsp; {{hero.profile.name}}
.form-group
label Contributor Title
input.form-control(type='text', v-model='hero.contributor.text')
small Common titles: <strong>Ambassador, Artisan, Bard, Blacksmith, Challenger, Comrade, Fletcher, Linguist, Linguistic Scribe, Scribe, Socialite, Storyteller</strong>. Rare titles: Advisor, Chamberlain, Designer, Mathematician, Shirtster, Spokesperson, Statistician, Tinker, Transcriber, Troubadour.
.form-group
label Contributor Tier
input.form-control(type='number', v-model='hero.contributor.level')
small 1-7 for normal contributors, 8 for moderators, 9 for staff. This determines which items, pets, and mounts are available, and name-tag coloring. Tiers 8 and 9 are automatically given admin status.
|&nbsp;
a(target='_blank', href='https://trello.com/c/wkFzONhE/277-contributor-gear') More details (1-7)
|,&nbsp;
a(target='_blank', href='https://github.com/HabitRPG/habitica/issues/3801') more details (8-9)
.form-group
label Contributions
textarea.form-control(cols=5, v-model='hero.contributor.contributions')
.form-group
label Balance
input.form-control(type='number', step="any", v-model='hero.balance')
small
span '{{ hero.balance }}' is in USD, <em>not</em> in Gems. E.g., if this number is 1, it means 4 Gems. Only use this option when manually granting Gems to players, don't use it when granting contributor tiers. Contrib tiers will automatically add Gems.
.accordion
.accordion-group(heading='Items')
h4.expand-toggle(:class="{'open': expandItems}", @click="expandItems = !expandItems") Update Item
.form-group.well(v-if="expandItems")
input.form-control(type='text',placeholder='Path (eg, items.pets.BearCub-Base)',v-model='hero.itemPath')
small.muted Enter the <strong>item path</strong>. E.g., <code>items.pets.BearCub-Zombie</code> or <code>items.gear.owned.head_special_0</code> or <code>items.gear.equipped.head</code>. You can find all the item paths below.
br
input.form-control(type='text',placeholder='Value (eg, 5)',v-model='hero.itemVal')
small.muted Enter the <strong>item value</strong>. E.g., <code>5</code> or <code>false</code> or <code>head_warrior_3</code>. All values are listed in the All Item Paths section below.
.accordion
.accordion-group(heading='All Item Paths')
pre {{allItemPaths}}
.accordion-group(heading='Current Items')
pre {{hero.items}}
.accordion-group(heading='Auth')
h4.expand-toggle(:class="{'open': expandAuth}", @click="expandAuth = !expandAuth") Auth
div(v-if="expandAuth")
pre {{hero.auth}}
.form-group
.checkbox
label
input(type='checkbox', v-if='hero.flags', v-model='hero.flags.chatShadowMuted')
strong Chat Shadow Muting On
.form-group
.checkbox
label
input(type='checkbox', v-if='hero.flags', v-model='hero.flags.chatRevoked')
strong Chat Privileges Revoked
.form-group
.checkbox
label
input(type='checkbox', v-model='hero.auth.blocked')
| Blocked
// h4 Backer Status
// Add backer stuff like tier, disable adds, etcs
.form-group
button.form-control.btn.btn-primary(@click='saveHero()')
| Save
.table-responsive
table.table.table-striped
thead
tr
th {{ $t('name') }}
th(v-if='user.contributor && user.contributor.admin') {{ $t('UUID') }}
th {{ $t('contribLevel') }}
th {{ $t('title') }}
th {{ $t('contributions') }}
tbody
tr(v-for='(hero, index) in heroes')
td
user-link(v-if='hero.contributor && hero.contributor.admin', :user='hero', :popover="$t('gamemaster')", popover-trigger='mouseenter', popover-placement='right')
user-link(v-if='!hero.contributor || !hero.contributor.admin', :user='hero')
td(v-if='user.contributor.admin', @click='populateContributorInput(hero._id, index)').btn-link {{hero._id}}
td {{hero.contributor.level}}
td {{hero.contributor.text}}
td
div(v-markdown='hero.contributor.contributions', target='_blank')
<template>
<div class="row standard-page">
<small
class="muted"
v-html="$t('blurbHallContributors')"
></small><div class="well">
<div v-if="user.contributor.admin">
<h2>Reward User</h2><div class="row">
<div
v-if="!hero.profile"
class="form col-6"
>
<div class="form-group">
<input
v-model="heroID"
class="form-control"
type="text"
:placeholder="'User ID or Username'"
>
</div><div class="form-group">
<button
class="btn btn-secondary"
@click="loadHero(heroID)"
>
Load User
</button>
</div>
</div>
</div><div class="row">
<div
v-if="hero && hero.profile"
class="form col-6"
submit="saveHero(hero)"
>
<router-link :to="{'name': 'userProfile', 'params': {'userId': hero._id}}">
<h3>@{{ hero.auth.local.username }} &nbsp; / &nbsp; {{ hero.profile.name }}</h3>
</router-link><div class="form-group">
<label>Contributor Title</label><input
v-model="hero.contributor.text"
class="form-control"
type="text"
><small>Common titles: <strong>Ambassador, Artisan, Bard, Blacksmith, Challenger, Comrade, Fletcher, Linguist, Linguistic Scribe, Scribe, Socialite, Storyteller</strong>. Rare titles: Advisor, Chamberlain, Designer, Mathematician, Shirtster, Spokesperson, Statistician, Tinker, Transcriber, Troubadour.</small>
</div><div class="form-group">
<label>Contributor Tier</label><input
v-model="hero.contributor.level"
class="form-control"
type="number"
><small>1-7 for normal contributors, 8 for moderators, 9 for staff. This determines which items, pets, and mounts are available, and name-tag coloring. Tiers 8 and 9 are automatically given admin status.&nbsp;<a
target="_blank"
href="https://trello.com/c/wkFzONhE/277-contributor-gear"
>More details (1-7)</a>,&nbsp;<a
target="_blank"
href="https://github.com/HabitRPG/habitica/issues/3801"
>more details (8-9)</a></small>
</div><div class="form-group">
<label>Contributions</label><textarea
v-model="hero.contributor.contributions"
class="form-control"
cols="5"
></textarea>
</div><div class="form-group">
<label>Balance</label><input
v-model="hero.balance"
class="form-control"
type="number"
step="any"
><small><span>'{{ hero.balance }}' is in USD, <em>not</em> in Gems. E.g., if this number is 1, it means 4 Gems. Only use this option when manually granting Gems to players, don't use it when granting contributor tiers. Contrib tiers will automatically add Gems.</span></small>
</div><div class="accordion">
<div
class="accordion-group"
heading="Items"
>
<h4
class="expand-toggle"
:class="{'open': expandItems}"
@click="expandItems = !expandItems"
>
Update Item
</h4><div
v-if="expandItems"
class="form-group well"
>
<input
v-model="hero.itemPath"
class="form-control"
type="text"
placeholder="Path (eg, items.pets.BearCub-Base)"
><small class="muted">Enter the <strong>item path</strong>. E.g., <code>items.pets.BearCub-Zombie</code> or <code>items.gear.owned.head_special_0</code> or <code>items.gear.equipped.head</code>. You can find all the item paths below.</small><br><input
v-model="hero.itemVal"
class="form-control"
type="text"
placeholder="Value (eg, 5)"
><small class="muted">Enter the <strong>item value</strong>. E.g., <code>5</code> or <code>false</code> or <code>head_warrior_3</code>. All values are listed in the All Item Paths section below.</small><div class="accordion">
<div
class="accordion-group"
heading="All Item Paths"
>
<pre>{{ allItemPaths }}</pre>
</div><div
class="accordion-group"
heading="Current Items"
>
<pre>{{ hero.items }}</pre>
</div>
</div>
</div>
</div><div
class="accordion-group"
heading="Auth"
>
<h4
class="expand-toggle"
:class="{'open': expandAuth}"
@click="expandAuth = !expandAuth"
>
Auth
</h4><div v-if="expandAuth">
<pre>{{ hero.auth }}</pre><div class="form-group">
<div class="checkbox">
<label><input
v-if="hero.flags"
v-model="hero.flags.chatShadowMuted"
type="checkbox"
><strong>Chat Shadow Muting On</strong></label>
</div>
</div><div class="form-group">
<div class="checkbox">
<label><input
v-if="hero.flags"
v-model="hero.flags.chatRevoked"
type="checkbox"
><strong>Chat Privileges Revoked</strong></label>
</div>
</div><div class="form-group">
<div class="checkbox">
<label><input
v-model="hero.auth.blocked"
type="checkbox"
>Blocked</label>
</div>
</div>
</div>
</div>
</div><!-- h4 Backer Status--><!-- Add backer stuff like tier, disable adds, etcs--><div class="form-group">
<button
class="form-control btn btn-primary"
@click="saveHero()"
>
Save
</button>
</div>
</div>
</div>
</div><div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>{{ $t('name') }}</th><th v-if="user.contributor && user.contributor.admin">
{{ $t('UUID') }}
</th><th>{{ $t('contribLevel') }}</th><th>{{ $t('title') }}</th><th>{{ $t('contributions') }}</th>
</tr>
</thead><tbody>
<tr v-for="(hero, index) in heroes">
<td>
<user-link
v-if="hero.contributor && hero.contributor.admin"
:user="hero"
:popover="$t('gamemaster')"
popover-trigger="mouseenter"
popover-placement="right"
/><user-link
v-if="!hero.contributor || !hero.contributor.admin"
:user="hero"
/>
</td><td
v-if="user.contributor.admin"
class="btn-link"
@click="populateContributorInput(hero._id, index)"
>
{{ hero._id }}
</td><td>{{ hero.contributor.level }}</td><td>{{ hero.contributor.text }}</td><td>
<div
v-markdown="hero.contributor.contributions"
target="_blank"
></div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,11 +1,24 @@
<template lang="pug">
.row
secondary-menu.col-12
router-link.nav-link(:to="{name: 'contributors'}", exact, :class="{'active': $route.name === 'contributors'}") {{ $t('hallContributors') }}
router-link.nav-link(:to="{name: 'patrons'}", :class="{'active': $route.name === 'patrons'}") {{ $t('hallPatrons') }}
.col-12
router-view
<template>
<div class="row">
<secondary-menu class="col-12">
<router-link
class="nav-link"
:to="{name: 'contributors'}"
exact="exact"
:class="{'active': $route.name === 'contributors'}"
>
{{ $t('hallContributors') }}
</router-link><router-link
class="nav-link"
:to="{name: 'patrons'}"
:class="{'active': $route.name === 'patrons'}"
>
{{ $t('hallPatrons') }}
</router-link>
</secondary-menu><div class="col-12">
<router-view />
</div>
</div>
</template>
<script>

View file

@ -1,20 +1,32 @@
<template lang="pug">
.row
small.muted {{ $t('blurbHallPatrons') }}
.table-responsive
table.table.table-striped(infinite-scroll="loadMore()")
thead
tr
th {{ $t('name') }}
th(v-if='user.contributor.admin') {{ $t('UUID') }}
th {{ $t('backerTier') }}
tbody
tr(v-for='patron in patrons')
td
a.label.label-default(v-class='userLevelStyle(patron)', @click='clickMember(patron._id, true)')
| {{patron.profile.name}}
td(v-if='user.contributor.admin') {{patron._id}}
td {{patron.backer.tier}}
<template>
<div class="row">
<small class="muted">{{ $t('blurbHallPatrons') }}</small><div class="table-responsive">
<table
class="table table-striped"
infinite-scroll="loadMore()"
>
<thead>
<tr>
<th>{{ $t('name') }}</th><th v-if="user.contributor.admin">
{{ $t('UUID') }}
</th><th>{{ $t('backerTier') }}</th>
</tr>
</thead><tbody>
<tr v-for="patron in patrons">
<td>
<a
v-class="userLevelStyle(patron)"
class="label label-default"
@click="clickMember(patron._id, true)"
></a>{{ patron.profile.name }}
</td><td v-if="user.contributor.admin">
{{ patron._id }}
</td><td>{{ patron.backer.tier }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>

View file

@ -1,40 +1,62 @@
<template lang="pug">
div
invite-modal(:group='inviteModalGroup', :groupType='inviteModalGroupType')
create-party-modal
#app-header.row(:class="{'hide-header': $route.name === 'groupPlan'}")
members-modal(:hide-badge="true")
member-details(
:member="user",
:class-badge-position="'next-to-name'",
:is-header="true",
)
.view-party.d-flex.align-items-center(
v-if="hasParty",
)
button.btn.btn-primary.view-party-button(@click='showPartyMembers()') {{ $t('viewParty') }}
.party-members.d-flex(
v-if="hasParty",
v-resize="1500",
@resized="setPartyMembersWidth($event)"
)
member-details(
v-for="(member, $index) in sortedPartyMembers",
:key="member._id",
v-if="member._id !== user._id && $index < membersToShow",
:member="member",
condensed=true,
@onHover="expandMember(member._id)",
:expanded="member._id === expandedMember",
:is-header="true",
:class-badge-position="'hidden'",
)
.no-party.d-flex.justify-content-center.text-center(v-else)
.align-self-center
h3 {{ $t('battleWithFriends') }}
span.small-text(v-html="$t('inviteFriendsParty')")
br
button.btn.btn-primary(@click='createOrInviteParty()') {{ user.party._id ? $t('inviteFriends') : $t('startAParty') }}
<template>
<div>
<invite-modal
:group="inviteModalGroup"
:group-type="inviteModalGroupType"
/><create-party-modal /><div
id="app-header"
class="row"
:class="{'hide-header': $route.name === 'groupPlan'}"
>
<members-modal :hide-badge="true" /><member-details
:member="user"
:class-badge-position="'next-to-name'"
:is-header="true"
/><div
v-if="hasParty"
class="view-party d-flex align-items-center"
>
<button
class="btn btn-primary view-party-button"
@click="showPartyMembers()"
>
{{ $t('viewParty') }}
</button>
</div><div
v-if="hasParty"
v-resize="1500"
class="party-members d-flex"
@resized="setPartyMembersWidth($event)"
>
<member-details
v-for="(member, $index) in sortedPartyMembers"
v-if="member._id !== user._id && $index < membersToShow"
:key="member._id"
:member="member"
condensed="condensed"
:expanded="member._id === expandedMember"
:is-header="true"
:class-badge-position="'hidden'"
@onHover="expandMember(member._id)"
/>
</div><div
v-else
class="no-party d-flex justify-content-center text-center"
>
<div class="align-self-center">
<h3>{{ $t('battleWithFriends') }}</h3><span
class="small-text"
v-html="$t('inviteFriendsParty')"
></span><br><button
class="btn btn-primary"
@click="createOrInviteParty()"
>
{{ user.party._id ? $t('inviteFriends') : $t('startAParty') }}
</button>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,91 +1,337 @@
<template lang="pug">
div
inbox-modal
creator-intro
profileModal
report-flag-modal
send-gems-modal
b-navbar.topbar.navbar-inverse.static-top(toggleable="lg", type="dark", :class="navbarZIndexClass")
b-navbar-brand.brand(aria-label="Habitica")
.logo.svg-icon.d-none.d-xl-block(v-html="icons.logo")
.svg-icon.gryphon.d-xs-block.d-xl-none
b-navbar-toggle(target='menu_collapse').menu-toggle
.quick-menu.mobile-only.form-inline
a.item-with-icon(@click="sync", v-b-tooltip.hover.bottom="$t('sync')", :aria-label="$t('sync')")
.top-menu-icon.svg-icon(v-html="icons.sync")
notification-menu.item-with-icon
user-dropdown.item-with-icon
b-collapse#menu_collapse(v-model="menuIsOpen").collapse.navbar-collapse
b-navbar-nav.menu-list
b-nav-item.topbar-item(:class="{'active': $route.path === '/'}" tag="li", :to="{name: 'tasks'}", exact) {{ $t('tasks') }}
li.topbar-item(:class="{'active': $route.path.startsWith('/inventory'), 'down': $route.path.startsWith('/inventory') && this.isDesktop()}").droppable
.chevron.rotate(@click='dropdownMobile($event)')
.chevron-icon-down(v-html="icons.chevronDown", v-once)
router-link.nav-link(:to="{name: 'items'}") {{ $t('inventory') }}
.topbar-dropdown
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'items'}", exact) {{ $t('items') }}
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'equipment'}") {{ $t('equipment') }}
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'stable'}") {{ $t('stable') }}
li.topbar-item(:class="{'active': $route.path.startsWith('/shop'), 'down': $route.path.startsWith('/shop') && this.isDesktop()}").droppable
.chevron.rotate(@click='dropdownMobile($event)')
.chevron-icon-down(v-html="icons.chevronDown", v-once)
router-link.nav-link(:to="{name: 'market'}") {{ $t('shops') }}
.topbar-dropdown
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'market'}", exact) {{ $t('market') }}
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'quests'}") {{ $t('quests') }}
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'seasonal'}") {{ $t('titleSeasonalShop') }}
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'time'}") {{ $t('titleTimeTravelers') }}
b-nav-item.topbar-item(:class="{'active': $route.path.startsWith('/party')}" tag="li", :to="{name: 'party'}", v-if='this.user.party._id') {{ $t('party') }}
b-nav-item.topbar-item(:class="{'active': $route.path.startsWith('/party')}" @click='openPartyModal()', v-if='!this.user.party._id') {{ $t('party') }}
li.topbar-item(:class="{'active': $route.path.startsWith('/groups'), 'down': $route.path.startsWith('/groups') && this.isDesktop()}").droppable
.chevron.rotate(@click='dropdownMobile($event)')
.chevron-icon-down(v-html="icons.chevronDown", v-once)
router-link.nav-link(:to="{name: 'tavern'}") {{ $t('guilds') }}
.topbar-dropdown
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'tavern'}") {{ $t('tavern') }}
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'myGuilds'}") {{ $t('myGuilds') }}
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'guildsDiscovery'}") {{ $t('guildsDiscovery') }}
li.topbar-item(:class="{'active': $route.path.startsWith('/group-plans'), 'down': $route.path.startsWith('/group-plans') && this.isDesktop()}").droppable
.chevron.rotate(v-if="groupPlans.length > 0", @click='dropdownMobile($event)')
.chevron-icon-down(v-html="icons.chevronDown", v-once)
router-link.nav-link(:to="{name: 'groupPlan'}") {{ $t('group') }}
.topbar-dropdown
router-link.topbar-dropdown-item.dropdown-item(v-for='group in groupPlans', :key='group._id', :to="{name: 'groupPlanDetailTaskInformation', params: {groupId: group._id}}") {{ group.name }}
li.topbar-item(:class="{'active': $route.path.startsWith('/challenges'), 'down': $route.path.startsWith('/challenges') && this.isDesktop()}").droppable
.chevron.rotate(@click='dropdownMobile($event)')
.chevron-icon-down(v-html="icons.chevronDown", v-once)
router-link.nav-link(:to="{name: 'myChallenges'}") {{ $t('challenges') }}
.topbar-dropdown
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'myChallenges'}") {{ $t('myChallenges') }}
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'findChallenges'}") {{ $t('findChallenges') }}
li.topbar-item(:class="{'active': $route.path.startsWith('/help'), 'down': $route.path.startsWith('/help') && this.isDesktop()}").droppable
.chevron.rotate(@click='dropdownMobile($event)')
.chevron-icon-down(v-html="icons.chevronDown", v-once)
router-link.nav-link(:to="{name: 'faq'}") {{ $t('help') }}
.topbar-dropdown
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'faq'}") {{ $t('faq') }}
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'overview'}") {{ $t('overview') }}
router-link.topbar-dropdown-item.dropdown-item(to="/groups/guild/a29da26b-37de-4a71-b0c6-48e72a900dac") {{ $t('reportBug') }}
router-link.topbar-dropdown-item.dropdown-item(to="/groups/guild/5481ccf3-5d2d-48a9-a871-70a7380cee5a") {{ $t('askAQuestion') }}
a.topbar-dropdown-item.dropdown-item(href="https://trello.com/c/odmhIqyW/440-read-first-table-of-contents", target='_blank') {{ $t('requestAF') }}
a.topbar-dropdown-item.dropdown-item(href="http://habitica.fandom.com/wiki/Contributing_to_Habitica", target='_blank') {{ $t('contributing') }}
a.topbar-dropdown-item.dropdown-item(href="http://habitica.fandom.com/wiki/Habitica_Wiki", target='_blank') {{ $t('wiki') }}
a.topbar-dropdown-item.dropdown-item(@click='modForm()') {{ $t('contactForm') }}
.currency-tray.form-inline
.item-with-icon(v-if="userHourglasses > 0")
.top-menu-icon.svg-icon(v-html="icons.hourglasses", v-b-tooltip.hover.bottom="$t('mysticHourglassesTooltip')")
span {{ userHourglasses }}
.item-with-icon
a.top-menu-icon.svg-icon.gem(:aria-label="$t('gems')", href="#buy-gems" v-html="icons.gem", @click.prevent='showBuyGemsModal("gems")', v-b-tooltip.hover.bottom="$t('gems')")
span {{userGems}}
.item-with-icon.gold
.top-menu-icon.svg-icon(:aria-label="$t('gold')", v-html="icons.gold", v-b-tooltip.hover.bottom="$t('gold')")
span {{Math.floor(user.stats.gp * 100) / 100}}
.form-inline.desktop-only
a.item-with-icon(@click="sync", @keyup.enter="sync", role="link", :aria-label="$t('sync')", tabindex="0", v-b-tooltip.hover.bottom="$t('sync')")
.top-menu-icon.svg-icon(v-html="icons.sync")
notification-menu.item-with-icon
user-dropdown.item-with-icon
<template>
<div>
<inbox-modal /><creator-intro /><profileModal /><report-flag-modal /><send-gems-modal /><b-navbar
class="topbar navbar-inverse static-top"
toggleable="lg"
type="dark"
:class="navbarZIndexClass"
>
<b-navbar-brand
class="brand"
aria-label="Habitica"
>
<div
class="logo svg-icon d-none d-xl-block"
v-html="icons.logo"
></div><div class="svg-icon gryphon d-xs-block d-xl-none"></div>
</b-navbar-brand><b-navbar-toggle
class="menu-toggle"
target="menu_collapse"
/><div class="quick-menu mobile-only form-inline">
<a
v-b-tooltip.hover.bottom="$t('sync')"
class="item-with-icon"
:aria-label="$t('sync')"
@click="sync"
><div
class="top-menu-icon svg-icon"
v-html="icons.sync"
></div></a><notification-menu class="item-with-icon" /><user-dropdown class="item-with-icon" />
</div><b-collapse
id="menu_collapse"
v-model="menuIsOpen"
class="collapse navbar-collapse"
>
<b-navbar-nav class="menu-list">
<b-nav-item
class="topbar-item"
:class="{'active': $route.path === '/'}"
tag="li"
:to="{name: 'tasks'}"
exact="exact"
>
{{ $t('tasks') }}
</b-nav-item><li
class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/inventory'), 'down': $route.path.startsWith('/inventory') && this.isDesktop()}"
>
<div
class="chevron rotate"
@click="dropdownMobile($event)"
>
<div
v-once
class="chevron-icon-down"
v-html="icons.chevronDown"
></div>
</div><router-link
class="nav-link"
:to="{name: 'items'}"
>
{{ $t('inventory') }}
</router-link><div class="topbar-dropdown">
<router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'items'}"
exact="exact"
>
{{ $t('items') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'equipment'}"
>
{{ $t('equipment') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'stable'}"
>
{{ $t('stable') }}
</router-link>
</div>
</li><li
class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/shop'), 'down': $route.path.startsWith('/shop') && this.isDesktop()}"
>
<div
class="chevron rotate"
@click="dropdownMobile($event)"
>
<div
v-once
class="chevron-icon-down"
v-html="icons.chevronDown"
></div>
</div><router-link
class="nav-link"
:to="{name: 'market'}"
>
{{ $t('shops') }}
</router-link><div class="topbar-dropdown">
<router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'market'}"
exact="exact"
>
{{ $t('market') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'quests'}"
>
{{ $t('quests') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'seasonal'}"
>
{{ $t('titleSeasonalShop') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'time'}"
>
{{ $t('titleTimeTravelers') }}
</router-link>
</div>
</li><b-nav-item
v-if="this.user.party._id"
class="topbar-item"
:class="{'active': $route.path.startsWith('/party')}"
tag="li"
:to="{name: 'party'}"
>
{{ $t('party') }}
</b-nav-item><b-nav-item
v-if="!this.user.party._id"
class="topbar-item"
:class="{'active': $route.path.startsWith('/party')}"
@click="openPartyModal()"
>
{{ $t('party') }}
</b-nav-item><li
class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/groups'), 'down': $route.path.startsWith('/groups') && this.isDesktop()}"
>
<div
class="chevron rotate"
@click="dropdownMobile($event)"
>
<div
v-once
class="chevron-icon-down"
v-html="icons.chevronDown"
></div>
</div><router-link
class="nav-link"
:to="{name: 'tavern'}"
>
{{ $t('guilds') }}
</router-link><div class="topbar-dropdown">
<router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'tavern'}"
>
{{ $t('tavern') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'myGuilds'}"
>
{{ $t('myGuilds') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'guildsDiscovery'}"
>
{{ $t('guildsDiscovery') }}
</router-link>
</div>
</li><li
class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/group-plans'), 'down': $route.path.startsWith('/group-plans') && this.isDesktop()}"
>
<div
v-if="groupPlans.length > 0"
class="chevron rotate"
@click="dropdownMobile($event)"
>
<div
v-once
class="chevron-icon-down"
v-html="icons.chevronDown"
></div>
</div><router-link
class="nav-link"
:to="{name: 'groupPlan'}"
>
{{ $t('group') }}
</router-link><div class="topbar-dropdown">
<router-link
v-for="group in groupPlans"
:key="group._id"
class="topbar-dropdown-item dropdown-item"
:to="{name: 'groupPlanDetailTaskInformation', params: {groupId: group._id}}"
>
{{ group.name }}
</router-link>
</div>
</li><li
class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/challenges'), 'down': $route.path.startsWith('/challenges') && this.isDesktop()}"
>
<div
class="chevron rotate"
@click="dropdownMobile($event)"
>
<div
v-once
class="chevron-icon-down"
v-html="icons.chevronDown"
></div>
</div><router-link
class="nav-link"
:to="{name: 'myChallenges'}"
>
{{ $t('challenges') }}
</router-link><div class="topbar-dropdown">
<router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'myChallenges'}"
>
{{ $t('myChallenges') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'findChallenges'}"
>
{{ $t('findChallenges') }}
</router-link>
</div>
</li><li
class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/help'), 'down': $route.path.startsWith('/help') && this.isDesktop()}"
>
<div
class="chevron rotate"
@click="dropdownMobile($event)"
>
<div
v-once
class="chevron-icon-down"
v-html="icons.chevronDown"
></div>
</div><router-link
class="nav-link"
:to="{name: 'faq'}"
>
{{ $t('help') }}
</router-link><div class="topbar-dropdown">
<router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'faq'}"
>
{{ $t('faq') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
:to="{name: 'overview'}"
>
{{ $t('overview') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
to="/groups/guild/a29da26b-37de-4a71-b0c6-48e72a900dac"
>
{{ $t('reportBug') }}
</router-link><router-link
class="topbar-dropdown-item dropdown-item"
to="/groups/guild/5481ccf3-5d2d-48a9-a871-70a7380cee5a"
>
{{ $t('askAQuestion') }}
</router-link><a
class="topbar-dropdown-item dropdown-item"
href="https://trello.com/c/odmhIqyW/440-read-first-table-of-contents"
target="_blank"
>{{ $t('requestAF') }}</a><a
class="topbar-dropdown-item dropdown-item"
href="http://habitica.fandom.com/wiki/Contributing_to_Habitica"
target="_blank"
>{{ $t('contributing') }}</a><a
class="topbar-dropdown-item dropdown-item"
href="http://habitica.fandom.com/wiki/Habitica_Wiki"
target="_blank"
>{{ $t('wiki') }}</a><a
class="topbar-dropdown-item dropdown-item"
@click="modForm()"
>{{ $t('contactForm') }}</a>
</div>
</li>
</b-navbar-nav><div class="currency-tray form-inline">
<div
v-if="userHourglasses > 0"
class="item-with-icon"
>
<div
v-b-tooltip.hover.bottom="$t('mysticHourglassesTooltip')"
class="top-menu-icon svg-icon"
v-html="icons.hourglasses"
></div><span>{{ userHourglasses }}</span>
</div><div class="item-with-icon">
<a
v-b-tooltip.hover.bottom="$t('gems')"
class="top-menu-icon svg-icon gem"
:aria-label="$t('gems')"
href="#buy-gems"
@click.prevent="showBuyGemsModal('gems')"
v-html="icons.gem"
></a><span>{{ userGems }}</span>
</div><div class="item-with-icon gold">
<div
v-b-tooltip.hover.bottom="$t('gold')"
class="top-menu-icon svg-icon"
:aria-label="$t('gold')"
v-html="icons.gold"
></div><span>{{ Math.floor(user.stats.gp * 100) / 100 }}</span>
</div>
</div><div class="form-inline desktop-only">
<a
class="item-with-icon"
v-b-tooltip.hover.bottom="$t('sync')"
role="link"
:aria-label="$t('sync')"
tabindex="0"
@click="sync"
@keyup.enter="sync"
><div
class="top-menu-icon svg-icon"
v-html="icons.sync"
></div></a><notification-menu class="item-with-icon" /><user-dropdown class="item-with-icon" />
</div>
</b-collapse>
</b-navbar>
</div>
</template>
<style lang="scss" scoped>

View file

@ -1,19 +1,27 @@
<template lang="pug">
.notification.dropdown-item.dropdown-separated.d-flex.justify-content-between(
@click="clicked"
)
.notification-icon.d-flex.justify-content-center.align-items-center(
v-if="hasIcon",
:class="{'is-not-bailey': isNotBailey}",
)
slot(name="icon")
.notification-content
slot(name="content")
.notification-remove(@click.stop="canRemove ? remove() : null",)
.svg-icon(
v-if="canRemove",
v-html="icons.close",
)
<template>
<div
class="notification dropdown-item dropdown-separated d-flex justify-content-between"
@click="clicked"
>
<div
v-if="hasIcon"
class="notification-icon d-flex justify-content-center align-items-center"
:class="{'is-not-bailey': isNotBailey}"
>
<slot name="icon"></slot>
</div><div class="notification-content">
<slot name="content"></slot>
</div><div
class="notification-remove"
@click.stop="canRemove ? remove() : null"
>
<div
v-if="canRemove"
class="svg-icon"
v-html="icons.close"
></div>
</div>
</div>
</template>
<style lang="scss"> // Not scoped because the classes could be used in i18n strings

View file

@ -1,13 +1,19 @@
<template lang="pug">
base-notification(
:can-remove="canRemove",
:has-icon="true",
:notification="notification",
:read-after-click="true",
@click="action"
)
div(slot="content", v-html="$t('cardReceived', {card: cardString})")
div(slot="icon", :class="cardClass")
<template>
<base-notification
:can-remove="canRemove"
:has-icon="true"
:notification="notification"
:read-after-click="true"
@click="action"
>
<div
slot="content"
v-html="$t('cardReceived', {card: cardString})"
></div><div
slot="icon"
:class="cardClass"
></div>
</base-notification>
</template>
<script>

View file

@ -1,15 +1,26 @@
<template lang="pug">
base-notification(
:can-remove="canRemove",
:has-icon="false",
:notification="notification",
@click="action",
)
div(slot="content")
div(v-html="notification.data.message")
.notifications-buttons
.btn.btn-small.btn-success(@click.stop="approve()") {{ $t('approve') }}
.btn.btn-small.btn-warning(@click.stop="needsWork()") {{ $t('needsWork') }}
<template>
<base-notification
:can-remove="canRemove"
:has-icon="false"
:notification="notification"
@click="action"
>
<div slot="content">
<div v-html="notification.data.message"></div><div class="notifications-buttons">
<div
class="btn btn-small btn-success"
@click.stop="approve()"
>
{{ $t('approve') }}
</div><div
class="btn btn-small btn-warning"
@click.stop="needsWork()"
>
{{ $t('needsWork') }}
</div>
</div>
</div>
</base-notification>
</template>
<script>

View file

@ -1,12 +1,17 @@
<template lang="pug">
base-notification(
:can-remove="canRemove",
:has-icon="false",
:notification="notification",
:read-after-click="true",
@click="action",
)
.notification-green(slot="content", v-html="notification.data.message")
<template>
<base-notification
:can-remove="canRemove"
:has-icon="false"
:notification="notification"
:read-after-click="true"
@click="action"
>
<div
slot="content"
class="notification-green"
v-html="notification.data.message"
></div>
</base-notification>
</template>
<script>

View file

@ -1,12 +1,16 @@
<template lang="pug">
base-notification(
:can-remove="canRemove",
:has-icon="false",
:notification="notification",
:read-after-click="true",
@click="action",
)
div(slot="content", v-html="notification.data.message")
<template>
<base-notification
:can-remove="canRemove"
:has-icon="false"
:notification="notification"
:read-after-click="true"
@click="action"
>
<div
slot="content"
v-html="notification.data.message"
></div>
</base-notification>
</template>
<script>

View file

@ -1,12 +1,16 @@
<template lang="pug">
base-notification(
:can-remove="canRemove",
:has-icon="false",
:notification="notification",
:read-after-click="true",
@click="action",
)
div(slot="content", v-html="notification.data.message")
<template>
<base-notification
:can-remove="canRemove"
:has-icon="false"
:notification="notification"
:read-after-click="true"
@click="action"
>
<div
slot="content"
v-html="notification.data.message"
></div>
</base-notification>
</template>
<script>

Some files were not shown because too many files have changed in this diff Show more