New client many fixes (#8981)
* Footer style fixes * Limited string display * Fixed background reload * Began adding more avatar items * Fixed challenge updated cats and official to be seen by admins * Fixed min prize * Fixed required fields * Added my challenges and find challenges to menu * Removed nav to party page when have no party * Updated user and notifications icon * Added accept, reject and messages * Added selfcare * Underline links * Added forgot password * Fixed task adding * Disabled habit options that should be * Added markdown to tags * Added confirm to delete * Fixed cancel/delete style * Fixed rounding * Added gold icon * Fixed task icon styles * Fixed margin botton * Fixed some repeat styles * Fixed custom reward style * Hide like count 0 * Added new tavern images * Redirect to party page after create * Hid leader options from non leaders * Removed manager options from non group plan * Fixed some nav styles * Fixed overlay color * Prevented edit data from being transfered to create * Added hover state for spells * Add performance fixes for chat avatars * Fixed merge conflicts * Updated fron navigation * Fixed reg gryphon logo * Began adding gem modal functionality * Added purchase gems with gold * Fixed restore * Replaced description with summary * Spells that target tasks fix * Added initial challenge task load * Fixed lint issue
@@ -21,6 +21,13 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.modal-backdrop.show {
|
||||||
|
opacity: 1 !important;
|
||||||
|
background-color: rgba(67, 40, 116, 0.9) !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import AppMenu from './components/appMenu';
|
import AppMenu from './components/appMenu';
|
||||||
|
|||||||
BIN
website/client/assets/images/melior.png
Executable file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
website/client/assets/images/melior@2x.png
Executable file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
website/client/assets/images/melior@3x.png
Executable file
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
@@ -1,3 +1,3 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="20" viewBox="0 0 24 20">
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="20" viewBox="0 0 24 20">
|
||||||
<path fill="#C3C0C7" fill-rule="evenodd" d="M13 16h2v-2h-2v2zm-4 0h2v-2H9v2zm-4 0h2v-2H5v2zm12-4h2v-2h-2v2zm-4 0h2v-2h-2v2zm-4 0h2v-2H9v2zm13-4H2v8a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8zm2-2v10a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4h1V0h2v2h10V0h2v2h1a4 4 0 0 1 4 4zM5 12h2v-2H5v2z"/>
|
<path fill-rule="evenodd" d="M13 16h2v-2h-2v2zm-4 0h2v-2H9v2zm-4 0h2v-2H5v2zm12-4h2v-2h-2v2zm-4 0h2v-2h-2v2zm-4 0h2v-2H9v2zm13-4H2v8a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8zm2-2v10a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4h1V0h2v2h10V0h2v2h1a4 4 0 0 1 4 4zM5 12h2v-2H5v2z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 382 B After Width: | Height: | Size: 367 B |
@@ -1,3 +1,3 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="20" viewBox="0 0 30 20">
|
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="20" viewBox="0 0 30 20">
|
||||||
<path fill="#C3C0C7" fill-rule="evenodd" d="M11 11H9v2H7v-2H5V9h2V7h2v2h2v2zm8 0h6V9h-6v2zm9 5c0 1.103-.897 2-2 2H16V2h10c1.103 0 2 .897 2 2v12zM4 18c-1.103 0-2-.897-2-2V4c0-1.103.897-2 2-2h10v16H4zM26 0H4a4 4 0 0 0-4 4v12a4 4 0 0 0 4 4h22a4 4 0 0 0 4-4V4a4 4 0 0 0-4-4z"/>
|
<path fill-rule="evenodd" d="M11 11H9v2H7v-2H5V9h2V7h2v2h2v2zm8 0h6V9h-6v2zm9 5c0 1.103-.897 2-2 2H16V2h10c1.103 0 2 .897 2 2v12zM4 18c-1.103 0-2-.897-2-2V4c0-1.103.897-2 2-2h10v16H4zM26 0H4a4 4 0 0 0-4 4v12a4 4 0 0 0 4 4h22a4 4 0 0 0 4-4V4a4 4 0 0 0-4-4z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 354 B |
5
website/client/assets/svg/notifications.svg
Executable file → Normal file
@@ -1,4 +1,3 @@
|
|||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
<title>notifications</title>
|
<path fill="#D5C8FF" fill-rule="evenodd" d="M21 0H3C1.3 0 0 1.3 0 3v14c0 1.7 1.3 3 3 3h4l2.9 3.1c1.2 1.2 3.1 1.2 4.2 0L17 20h4c1.7 0 3-1.3 3-3V3c0-1.7-1.3-3-3-3zm1 17c0 .6-.4 1-1 1h-4.9l-3.5 3.7c-.2.2-.4.3-.6.3-.2 0-.4-.1-.7-.3L7.9 18H3c-.6 0-1-.4-1-1V3c0-.6.4-1 1-1h18c.6 0 1 .4 1 1v14zM19 7H5V5h14v2zm0 4H5V9h14v2zm0 4H5v-2h14v2z"/>
|
||||||
<path d="M26 4h-20c-1.7 0-3 1.3-3 3v14c0 1.7 1.3 3 3 3h5l2.9 3.1c1.2 1.2 3.1 1.2 4.2 0l2.9-3.1h5c1.7 0 3-1.3 3-3v-14c0-1.7-1.3-3-3-3v0zM27 21c0 0.6-0.4 1-1 1h-5.9l-3.5 3.7c-0.2 0.2-0.4 0.3-0.6 0.3s-0.4-0.1-0.7-0.3l-3.4-3.7h-5.9c-0.6 0-1-0.4-1-1v-14c0-0.6 0.4-1 1-1h20c0.6 0 1 0.4 1 1v14zM24 11h-16v-2h16v2zM24 15h-16v-2h16v2zM24 19h-16v-2h16v2z"></path>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 487 B After Width: | Height: | Size: 430 B |
@@ -1,3 +1,3 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="26" height="20" viewBox="0 0 26 20">
|
<svg xmlns="http://www.w3.org/2000/svg" width="26" height="20" viewBox="0 0 26 20">
|
||||||
<path fill="#C3C0C7" fill-rule="evenodd" d="M24 10h-8V8h4a2 2 0 0 0 2-2V2c1.103 0 2 .897 2 2v6zm0 6a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-4h8v1a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-1h8v4zM2 4c0-1.103.897-2 2-2v4a2 2 0 0 0 2 2h4v2H2V4zm10 9h2V8h-2v5zm8-11v4H6V2h14zm2-2H4a4 4 0 0 0-4 4v12a4 4 0 0 0 4 4h18a4 4 0 0 0 4-4V4a4 4 0 0 0-4-4z"/>
|
<path fill-rule="evenodd" d="M24 10h-8V8h4a2 2 0 0 0 2-2V2c1.103 0 2 .897 2 2v6zm0 6a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-4h8v1a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-1h8v4zM2 4c0-1.103.897-2 2-2v4a2 2 0 0 0 2 2h4v2H2V4zm10 9h2V8h-2v5zm8-11v4H6V2h14zm2-2H4a4 4 0 0 0-4 4v12a4 4 0 0 0 4 4h18a4 4 0 0 0 4-4V4a4 4 0 0 0-4-4z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 421 B After Width: | Height: | Size: 406 B |
@@ -1,3 +1,3 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
|
||||||
<path fill="#C3C0C7" fill-rule="evenodd" d="M8.343 14.916c-.312 0-.61-.123-.831-.344l-3.831-3.831 1.662-1.662 2.934 2.934 5.938-6.929L16 6.613l-6.764 7.893a1.182 1.182 0 0 1-.848.409l-.045.001zM18 16c0 1.103-.897 2-2 2H4c-1.102 0-2-.897-2-2V4c0-1.103.898-2 2-2h12c1.103 0 2 .897 2 2v12zM16 0H4a4 4 0 0 0-4 4v12a4 4 0 0 0 4 4h12a4 4 0 0 0 4-4V4a4 4 0 0 0-4-4z"/>
|
<path fill-rule="evenodd" d="M8.343 14.916c-.312 0-.61-.123-.831-.344l-3.831-3.831 1.662-1.662 2.934 2.934 5.938-6.929L16 6.613l-6.764 7.893a1.182 1.182 0 0 1-.848.409l-.045.001zM18 16c0 1.103-.897 2-2 2H4c-1.102 0-2-.897-2-2V4c0-1.103.898-2 2-2h12c1.103 0 2 .897 2 2v12zM16 0H4a4 4 0 0 0-4 4v12a4 4 0 0 0 4 4h12a4 4 0 0 0 4-4V4a4 4 0 0 0-4-4z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 457 B After Width: | Height: | Size: 442 B |
5
website/client/assets/svg/user.svg
Executable file → Normal file
@@ -1,4 +1,3 @@
|
|||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="24" viewBox="0 0 22 24">
|
||||||
<title>user</title>
|
<path fill-rule="evenodd" d="M15 13h-.4c1.9-1.2 3.3-3.3 3.4-5.8.1-3.8-3.1-7.2-6.9-7.2C7.1 0 4 3.1 4 7c0 2.6 1.3 4.8 3.4 6H7c-3.9 0-7 3.1-7 7v1c0 1.7 1.3 3 3 3h16c1.7 0 3-1.3 3-3v-1c0-3.9-3.1-7-7-7zM6 7c0-2.8 2.2-5 5-5s5 2.2 5 5-2.2 5-5 5-5-2.2-5-5zm13 15H3c-.6 0-1-.4-1-1v-1c0-2.8 2.2-5 5-5h8c2.8 0 5 2.2 5 5v1c0 .6-.4 1-1 1z"/>
|
||||||
<path d="M20 17h-0.4c1.9-1.2 3.3-3.3 3.4-5.8 0.1-3.8-3.1-7.2-6.9-7.2-4 0-7.1 3.1-7.1 7 0 2.6 1.3 4.8 3.4 6h-0.4c-3.9 0-7 3.1-7 7v1c0 1.7 1.3 3 3 3h16c1.7 0 3-1.3 3-3v-1c0-3.9-3.1-7-7-7v0zM11 11c0-2.8 2.2-5 5-5s5 2.2 5 5c0 2.8-2.2 5-5 5s-5-2.2-5-5v0zM24 26h-16c-0.6 0-1-0.4-1-1v-1c0-2.8 2.2-5 5-5h8c2.8 0 5 2.2 5 5v1c0 0.6-0.4 1-1 1v0z"></path>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 469 B After Width: | Height: | Size: 424 B |
@@ -113,7 +113,8 @@
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
footer {
|
footer {
|
||||||
background-color: #e1e0e3;
|
background-color: #e1e0e3;
|
||||||
height: 376px;
|
min-height: 408px;
|
||||||
|
width: 100%;
|
||||||
padding-left: 6em;
|
padding-left: 6em;
|
||||||
padding-right: 6em;
|
padding-right: 6em;
|
||||||
padding-top: 3em;
|
padding-top: 3em;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
#app-header.row
|
#app-header.row
|
||||||
create-party-modal
|
create-party-modal
|
||||||
members-modal(:group='user.party', :hide-badge="true")
|
members-modal(:hide-badge="true")
|
||||||
member-details(:member="user")
|
member-details(:member="user")
|
||||||
.view-party(v-if="user.party && user.party._id && partyMembers && partyMembers.length > 1")
|
.view-party(v-if="user.party && user.party._id && partyMembers && partyMembers.length > 1")
|
||||||
// TODO button should open the party members modal
|
// TODO button should open the party members modal
|
||||||
@@ -124,6 +124,8 @@ export default {
|
|||||||
openPartyModal () {
|
openPartyModal () {
|
||||||
if (this.user.party._id) {
|
if (this.user.party._id) {
|
||||||
this.$store.state.groupId = this.user.party._id;
|
this.$store.state.groupId = this.user.party._id;
|
||||||
|
// @TODO: do we need to fetch party?
|
||||||
|
this.$store.state.memberModalOptions.group = this.$store.state.party;
|
||||||
this.$root.$emit('show::modal', 'members-modal');
|
this.$root.$emit('show::modal', 'members-modal');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ div
|
|||||||
router-link.dropdown-item(:to="{name: 'quests'}") {{ $t('quests') }}
|
router-link.dropdown-item(:to="{name: 'quests'}") {{ $t('quests') }}
|
||||||
router-link.dropdown-item(:to="{name: 'seasonal'}") {{ $t('titleSeasonalShop') }}
|
router-link.dropdown-item(:to="{name: 'seasonal'}") {{ $t('titleSeasonalShop') }}
|
||||||
router-link.dropdown-item(:to="{name: 'time'}") {{ $t('titleTimeTravelers') }}
|
router-link.dropdown-item(:to="{name: 'time'}") {{ $t('titleTimeTravelers') }}
|
||||||
router-link.nav-item(tag="li", :to="{name: 'party'}")
|
router-link.nav-item(tag="li", :to="{name: 'party'}", v-if='this.user.party._id')
|
||||||
|
a.nav-link(v-once) {{ $t('party') }}
|
||||||
|
.nav-item(@click='openPartyModal()', v-if='!this.user.party._id')
|
||||||
a.nav-link(v-once) {{ $t('party') }}
|
a.nav-link(v-once) {{ $t('party') }}
|
||||||
router-link.nav-item.dropdown(tag="li", :to="{name: 'tavern'}", :class="{'active': $route.path.startsWith('/guilds')}")
|
router-link.nav-item.dropdown(tag="li", :to="{name: 'tavern'}", :class="{'active': $route.path.startsWith('/guilds')}")
|
||||||
a.nav-link(v-once) {{ $t('guilds') }}
|
a.nav-link(v-once) {{ $t('guilds') }}
|
||||||
@@ -30,15 +32,15 @@ div
|
|||||||
router-link.dropdown-item(:to="{name: 'tavern'}") {{ $t('tavern') }}
|
router-link.dropdown-item(:to="{name: 'tavern'}") {{ $t('tavern') }}
|
||||||
router-link.dropdown-item(:to="{name: 'myGuilds'}") {{ $t('myGuilds') }}
|
router-link.dropdown-item(:to="{name: 'myGuilds'}") {{ $t('myGuilds') }}
|
||||||
router-link.dropdown-item(:to="{name: 'guildsDiscovery'}") {{ $t('guildsDiscovery') }}
|
router-link.dropdown-item(:to="{name: 'guildsDiscovery'}") {{ $t('guildsDiscovery') }}
|
||||||
router-link.nav-item.dropdown(
|
.nav-item.dropdown(tag="li", :class="{'active': $route.path.startsWith('/group-plans')}")
|
||||||
tag="li",
|
a.nav-link(v-once) {{ $t('group') }}
|
||||||
:to="{name: 'groupPlan'}",
|
.dropdown-menu
|
||||||
:class="{'active': $route.path.startsWith('/group-plan')}")
|
router-link.dropdown-item(v-for='group in groupPlans', :key='group._id', :to="{name: 'groupPlanDetailTaskInformation', params: {groupId: group._id}}") {{ group.name }}
|
||||||
a.nav-link(v-once) {{ $t('group') }}
|
router-link.nav-item.dropdown(tag="li", :to="{name: 'myChallenges'}", :class="{'active': $route.path.startsWith('/challenges')}")
|
||||||
.dropdown-menu
|
|
||||||
router-link.dropdown-item(v-for='group in groupPlans', :key='group._id', :to="{name: 'groupPlanDetailTaskInformation', params: {groupId: group._id}}") {{ group.name }}
|
|
||||||
router-link.nav-item(tag="li", :to="{name: 'myChallenges'}", exact)
|
|
||||||
a.nav-link(v-once) {{ $t('challenges') }}
|
a.nav-link(v-once) {{ $t('challenges') }}
|
||||||
|
.dropdown-menu
|
||||||
|
router-link.dropdown-item(:to="{name: 'myChallenges'}") {{ $t('myChallenges') }}
|
||||||
|
router-link.dropdown-item(:to="{name: 'findChallenges'}") {{ $t('findChallenges') }}
|
||||||
router-link.nav-item.dropdown(tag="li", to="/help", :class="{'active': $route.path.startsWith('/help')}", :to="{name: 'faq'}")
|
router-link.nav-item.dropdown(tag="li", to="/help", :class="{'active': $route.path.startsWith('/help')}", :to="{name: 'faq'}")
|
||||||
a.nav-link(v-once) {{ $t('help') }}
|
a.nav-link(v-once) {{ $t('help') }}
|
||||||
.dropdown-menu
|
.dropdown-menu
|
||||||
@@ -57,10 +59,10 @@ div
|
|||||||
span {{userGems | roundBigNumber}}
|
span {{userGems | roundBigNumber}}
|
||||||
.item-with-icon
|
.item-with-icon
|
||||||
.svg-icon(v-html="icons.gold")
|
.svg-icon(v-html="icons.gold")
|
||||||
span {{user.stats.gp | roundBigNumber}}
|
span {{Math.floor(user.stats.gp * 100) / 100}}
|
||||||
notification-menu
|
notification-menu
|
||||||
a.dropdown.item-with-icon.item-user
|
a.dropdown.item-with-icon.item-user
|
||||||
.svg-icon(v-html="icons.user")
|
.svg-icon.user(v-html="icons.user")
|
||||||
.dropdown-menu.dropdown-menu-right.user-dropdown
|
.dropdown-menu.dropdown-menu-right.user-dropdown
|
||||||
a.dropdown-item.edit-avatar.dropdown-separated(@click='showAvatar()')
|
a.dropdown-item.edit-avatar.dropdown-separated(@click='showAvatar()')
|
||||||
h3 {{ user.profile.name }}
|
h3 {{ user.profile.name }}
|
||||||
@@ -173,11 +175,12 @@ div
|
|||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
|
|
||||||
.svg-icon {
|
.svg-icon {
|
||||||
vertical-align: middle;
|
vertical-align: bottom;
|
||||||
width: 24px;
|
display: inline-block;
|
||||||
height: 24px;
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
float: left;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,13 +190,13 @@ div
|
|||||||
color: $header-color;
|
color: $header-color;
|
||||||
transition: none;
|
transition: none;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.svg-icon {
|
.svg-icon {
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
color: $white;
|
color: $header-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,6 +279,9 @@ export default {
|
|||||||
async getUserGroupPlans () {
|
async getUserGroupPlans () {
|
||||||
this.groupPlans = await this.$store.dispatch('guilds:getGroupPlans');
|
this.groupPlans = await this.$store.dispatch('guilds:getGroupPlans');
|
||||||
},
|
},
|
||||||
|
openPartyModal () {
|
||||||
|
this.$root.$emit('show::modal', 'create-party-modal');
|
||||||
|
},
|
||||||
showBuyGemsModal () {
|
showBuyGemsModal () {
|
||||||
this.$root.$emit('show::modal', 'buy-gems');
|
this.$root.$emit('show::modal', 'buy-gems');
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
#top-background
|
#top-background
|
||||||
.seamless_stars_varied_opacity_repeat
|
.seamless_stars_varied_opacity_repeat
|
||||||
|
|
||||||
form#login-form(v-on:submit.prevent='handleSubmit', @keyup.enter="handleSubmit")
|
form#login-form(v-on:submit.prevent='handleSubmit', @keyup.enter="handleSubmit", v-if='!forgotPassword')
|
||||||
.text-center
|
.text-center
|
||||||
div
|
div
|
||||||
.svg-icon.gryphon(v-html="icons.gryphon")
|
.svg-icon.gryphon
|
||||||
div
|
div
|
||||||
.svg-icon.habitica-logo(v-html="icons.habiticaIcon")
|
.svg-icon.habitica-logo(v-html="icons.habiticaIcon")
|
||||||
.form-group.row.text-center
|
.form-group.row.text-center
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
input#emailInput.form-control(type='email', :placeholder='$t("emailPlaceholder")', v-model='email')
|
input#emailInput.form-control(type='email', :placeholder='$t("emailPlaceholder")', v-model='email')
|
||||||
.form-group
|
.form-group
|
||||||
label(for='passwordInput', v-once) {{$t('password')}}
|
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("passwordPlaceholder")', v-model='password')
|
input#passwordInput.form-control(type='password', :placeholder='$t("passwordPlaceholder")', v-model='password')
|
||||||
.form-group(v-if='registering')
|
.form-group(v-if='registering')
|
||||||
label(for='confirmPasswordInput', v-once) {{$t('confirmPassword')}}
|
label(for='confirmPasswordInput', v-once) {{$t('confirmPassword')}}
|
||||||
@@ -43,6 +44,21 @@
|
|||||||
router-link(:to="{name: 'register'}", v-if='!registering', exact)
|
router-link(:to="{name: 'register'}", v-if='!registering', exact)
|
||||||
a.toggle-link(v-once) Don't have an account? Join Habitica!
|
a.toggle-link(v-once) Don't have an account? Join Habitica!
|
||||||
|
|
||||||
|
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 Email a Password Reset Link
|
||||||
|
p Enter the email address you used to register your Habitica account.
|
||||||
|
.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')}}
|
||||||
|
|
||||||
#bottom-wrap
|
#bottom-wrap
|
||||||
#bottom-background
|
#bottom-background
|
||||||
.seamless_mountains_demo_repeat
|
.seamless_mountains_demo_repeat
|
||||||
@@ -56,6 +72,7 @@
|
|||||||
|
|
||||||
small a {
|
small a {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -85,7 +102,7 @@
|
|||||||
color: $purple-400;
|
color: $purple-400;
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-form {
|
#login-form, #forgot-form {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 40em;
|
width: 40em;
|
||||||
padding-top: 5em;
|
padding-top: 5em;
|
||||||
@@ -93,9 +110,20 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
|
||||||
.gryphon {
|
.gryphon {
|
||||||
|
background-image: url('~assets/images/melior@3x.png');
|
||||||
width: 63.2px;
|
width: 63.2px;
|
||||||
height: 69.4px;
|
height: 69.4px;
|
||||||
|
background-size: cover;
|
||||||
color: $white;
|
color: $white;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
@@ -188,9 +216,14 @@
|
|||||||
.toggle-link {
|
.toggle-link {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.forgot-password {
|
||||||
|
color: #bda8ff !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import axios from 'axios';
|
||||||
import hello from 'hellojs';
|
import hello from 'hellojs';
|
||||||
|
|
||||||
import gryphon from 'assets/svg/gryphon.svg';
|
import gryphon from 'assets/svg/gryphon.svg';
|
||||||
@@ -205,6 +238,7 @@ export default {
|
|||||||
email: '',
|
email: '',
|
||||||
password: '',
|
password: '',
|
||||||
passwordConfirm: '',
|
passwordConfirm: '',
|
||||||
|
forgotPassword: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
data.icons = Object.freeze({
|
data.icons = Object.freeze({
|
||||||
@@ -282,8 +316,25 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.forgotPassword) {
|
||||||
|
this.forgotPasswordLink();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.login();
|
this.login();
|
||||||
},
|
},
|
||||||
|
async forgotPasswordLink () {
|
||||||
|
if (!this.username) {
|
||||||
|
alert('Email is required');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await axios.post('/api/v3/user/reset-password', {
|
||||||
|
email: this.username,
|
||||||
|
});
|
||||||
|
|
||||||
|
alert(this.$t('newPassSent'));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -250,13 +250,17 @@ export default {
|
|||||||
this.tasksByType[task.type].splice(index, 1, task);
|
this.tasksByType[task.type].splice(index, 1, task);
|
||||||
},
|
},
|
||||||
showMemberModal () {
|
showMemberModal () {
|
||||||
this.$store.state.groupId = 'challenge'; // @TODO: change these terrible settings
|
this.$store.state.memberModalOptions.groupId = 'challenge'; // @TODO: change these terrible settings
|
||||||
this.$store.state.viewingMembers = this.members;
|
this.$store.state.memberModalOptions.group = this.group;
|
||||||
|
this.$store.state.memberModalOptions.viewingMembers = this.members;
|
||||||
this.$root.$emit('show::modal', 'members-modal');
|
this.$root.$emit('show::modal', 'members-modal');
|
||||||
},
|
},
|
||||||
async joinChallenge () {
|
async joinChallenge () {
|
||||||
this.user.challenges.push(this.challengeId);
|
this.user.challenges.push(this.challengeId);
|
||||||
await this.$store.dispatch('challenges:joinChallenge', {challengeId: this.challengeId});
|
await this.$store.dispatch('challenges:joinChallenge', {challengeId: this.challengeId});
|
||||||
|
// @TODO: this doesn't work because of asyncresource
|
||||||
|
let tasks = await this.$store.dispatch('tasks:fetchUserTasks');
|
||||||
|
this.$store.state.tasks.data = tasks.data;
|
||||||
},
|
},
|
||||||
async leaveChallenge () {
|
async leaveChallenge () {
|
||||||
let keepChallenge = confirm('Do you want to keep challenge tasks?');
|
let keepChallenge = confirm('Do you want to keep challenge tasks?');
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
div Challenge Prize
|
div Challenge Prize
|
||||||
.row.description
|
.row.description
|
||||||
.col-12
|
.col-12
|
||||||
| {{challenge.description}}
|
| {{challenge.summary}}
|
||||||
.well.row
|
.well.row
|
||||||
.col-3
|
.col-3
|
||||||
.count-details
|
.count-details
|
||||||
@@ -104,7 +104,8 @@
|
|||||||
|
|
||||||
.description {
|
.description {
|
||||||
color: $gray-200;
|
color: $gray-200;
|
||||||
margin-bottom: 2em;
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,12 @@
|
|||||||
.form-check(
|
.form-check(
|
||||||
v-for="group in categoryOptions",
|
v-for="group in categoryOptions",
|
||||||
:key="group.key",
|
:key="group.key",
|
||||||
|
v-if='group.key !== "habitica_official" || user.contributor.admin'
|
||||||
)
|
)
|
||||||
label.custom-control.custom-checkbox
|
label.custom-control.custom-checkbox
|
||||||
input.custom-control-input(type="checkbox", :value="group.key" v-model="workingChallenge.categories")
|
input.custom-control-input(type="checkbox",
|
||||||
|
:value='group.key',
|
||||||
|
v-model="workingChallenge.categories")
|
||||||
span.custom-control-indicator
|
span.custom-control-indicator
|
||||||
span.custom-control-description(v-once) {{ $t(group.label) }}
|
span.custom-control-description(v-once) {{ $t(group.label) }}
|
||||||
button.btn.btn-primary(@click.prevent="toggleCategorySelect") {{$t('close')}}
|
button.btn.btn-primary(@click.prevent="toggleCategorySelect") {{$t('close')}}
|
||||||
@@ -47,7 +50,7 @@
|
|||||||
.form-group
|
.form-group
|
||||||
label
|
label
|
||||||
strong(v-once) {{$t('prize')}}
|
strong(v-once) {{$t('prize')}}
|
||||||
input(type='number', min='1', :max='maxPrize', v-model="workingChallenge.prize")
|
input(type='number', :min='minPrize', :max='maxPrize', v-model="workingChallenge.prize")
|
||||||
.row.footer-wrap
|
.row.footer-wrap
|
||||||
.col-12.text-center.submit-button-wrapper
|
.col-12.text-center.submit-button-wrapper
|
||||||
.alert.alert-warning(v-if='insufficientGemsForTavernChallenge')
|
.alert.alert-warning(v-if='insufficientGemsForTavernChallenge')
|
||||||
@@ -220,6 +223,13 @@ export default {
|
|||||||
if (this.challenge) {
|
if (this.challenge) {
|
||||||
Object.assign(this.workingChallenge, this.challenge);
|
Object.assign(this.workingChallenge, this.challenge);
|
||||||
this.workingChallenge.categories = [];
|
this.workingChallenge.categories = [];
|
||||||
|
|
||||||
|
if (this.challenge.categories) {
|
||||||
|
this.challenge.categories.forEach(category => {
|
||||||
|
this.workingChallenge.categories.push(category.slug);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.creating = false;
|
this.creating = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -230,6 +240,7 @@ export default {
|
|||||||
this.groups.push({
|
this.groups.push({
|
||||||
name: party.name,
|
name: party.name,
|
||||||
_id: party._id,
|
_id: party._id,
|
||||||
|
privacy: 'private',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +267,13 @@ export default {
|
|||||||
userBalance = userBalance * 4;
|
userBalance = userBalance * 4;
|
||||||
|
|
||||||
let groupBalance = 0;
|
let groupBalance = 0;
|
||||||
let group = find(this.groups, { _id: this.workingChallenge.group });
|
let group;
|
||||||
|
this.groups.forEach(item => {
|
||||||
|
if (item._id === this.workingChallenge.group) {
|
||||||
|
group = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (group && group.balance && group.leader === this.user._id) {
|
if (group && group.balance && group.leader === this.user._id) {
|
||||||
groupBalance = group.balance * 4;
|
groupBalance = group.balance * 4;
|
||||||
@@ -264,6 +281,18 @@ export default {
|
|||||||
|
|
||||||
return userBalance + groupBalance;
|
return userBalance + groupBalance;
|
||||||
},
|
},
|
||||||
|
minPrize () {
|
||||||
|
let groupFound;
|
||||||
|
this.groups.forEach(group => {
|
||||||
|
if (group._id === this.workingChallenge.group) {
|
||||||
|
groupFound = group;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (groupFound && groupFound.privacy === 'private') return 0;
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
insufficientGemsForTavernChallenge () {
|
insufficientGemsForTavernChallenge () {
|
||||||
let balance = this.user.balance || 0;
|
let balance = this.user.balance || 0;
|
||||||
let isForTavern = this.workingChallenge.group === TAVERN_ID;
|
let isForTavern = this.workingChallenge.group === TAVERN_ID;
|
||||||
@@ -320,6 +349,17 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateChallenge () {
|
updateChallenge () {
|
||||||
|
let categoryKeys = this.workingChallenge.categories;
|
||||||
|
let serverCategories = [];
|
||||||
|
categoryKeys.forEach(key => {
|
||||||
|
let catName = this.categoriesHashByKey[key];
|
||||||
|
serverCategories.push({
|
||||||
|
slug: key,
|
||||||
|
name: catName,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.workingChallenge.categories = serverCategories;
|
||||||
|
|
||||||
this.$emit('updatedChallenge', {
|
this.$emit('updatedChallenge', {
|
||||||
challenge: this.workingChallenge,
|
challenge: this.workingChallenge,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
span.action(v-if='msg.uuid === user._id', @click='remove(msg, index)')
|
span.action(v-if='msg.uuid === user._id', @click='remove(msg, index)')
|
||||||
.svg-icon(v-html="icons.delete")
|
.svg-icon(v-html="icons.delete")
|
||||||
| {{$t('delete')}}
|
| {{$t('delete')}}
|
||||||
span.action.float-right
|
span.action.float-right(v-if='likeCount(msg) > 0')
|
||||||
.svg-icon(v-html="icons.liked")
|
.svg-icon(v-html="icons.liked")
|
||||||
| + {{ likeCount(msg) }}
|
| + {{ likeCount(msg) }}
|
||||||
.row(v-if='user._id === msg.uuid')
|
.row(v-if='user._id === msg.uuid')
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
span.action(v-if='msg.uuid === user._id', @click='remove(msg, index)')
|
span.action(v-if='msg.uuid === user._id', @click='remove(msg, index)')
|
||||||
.svg-icon(v-html="icons.delete")
|
.svg-icon(v-html="icons.delete")
|
||||||
| {{$t('delete')}}
|
| {{$t('delete')}}
|
||||||
span.action.float-right
|
span.action.float-right(v-if='likeCount(msg) > 0')
|
||||||
.svg-icon(v-html="icons.liked")
|
.svg-icon(v-html="icons.liked")
|
||||||
| + {{ likeCount(msg) }}
|
| + {{ likeCount(msg) }}
|
||||||
.col-2
|
.col-2
|
||||||
@@ -128,6 +128,7 @@ import axios from 'axios';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import { mapState } from 'client/libs/store';
|
import { mapState } from 'client/libs/store';
|
||||||
|
import throttle from 'lodash/throttle';
|
||||||
import markdownDirective from 'client/directives/markdown';
|
import markdownDirective from 'client/directives/markdown';
|
||||||
import Avatar from '../avatar';
|
import Avatar from '../avatar';
|
||||||
import styleHelper from 'client/mixins/styleHelper';
|
import styleHelper from 'client/mixins/styleHelper';
|
||||||
@@ -155,6 +156,14 @@ export default {
|
|||||||
mounted () {
|
mounted () {
|
||||||
this.loadProfileCache();
|
this.loadProfileCache();
|
||||||
},
|
},
|
||||||
|
created () {
|
||||||
|
window.addEventListener('scroll', throttle(() => {
|
||||||
|
this.loadProfileCache(window.scrollY / 1000);
|
||||||
|
}, 1000));
|
||||||
|
},
|
||||||
|
destroyed () {
|
||||||
|
// window.removeEventListener('scroll', this.handleScroll);
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
icons: Object.freeze({
|
icons: Object.freeze({
|
||||||
@@ -167,6 +176,8 @@ export default {
|
|||||||
copyingMessage: {},
|
copyingMessage: {},
|
||||||
currentDayDividerDisplay: moment().day(),
|
currentDayDividerDisplay: moment().day(),
|
||||||
cachedProfileData: {},
|
cachedProfileData: {},
|
||||||
|
currentProfileLoadedCount: 0,
|
||||||
|
currentProfileLoadedEnd: 10,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
@@ -191,14 +202,22 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async loadProfileCache () {
|
async loadProfileCache (screenPosition) {
|
||||||
let promises = [];
|
let promises = [];
|
||||||
|
|
||||||
|
// @TODO: write an explination
|
||||||
|
if (screenPosition && Math.floor(screenPosition) + 1 > this.currentProfileLoadedEnd / 10) {
|
||||||
|
this.currentProfileLoadedEnd = 10 * (Math.floor(screenPosition) + 1);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.messages.forEach(message => {
|
this.messages.forEach(message => {
|
||||||
let uuid = message.uuid;
|
let uuid = message.uuid;
|
||||||
if (uuid && !this.cachedProfileData[uuid]) {
|
if (uuid && !this.cachedProfileData[uuid]) {
|
||||||
if (uuid === 'system') return;
|
if (uuid === 'system' || this.currentProfileLoadedCount === this.currentProfileLoadedEnd) return;
|
||||||
promises.push(axios.get(`/api/v3/members/${uuid}`));
|
promises.push(axios.get(`/api/v3/members/${uuid}`));
|
||||||
|
this.currentProfileLoadedCount += 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -53,8 +53,10 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
|
|||||||
.slim_shirt_pink.option(@click='set({"preferences.shirt":"pink"})', :class='{active: user.preferences.shirt === "pink"}')
|
.slim_shirt_pink.option(@click='set({"preferences.shirt":"pink"})', :class='{active: user.preferences.shirt === "pink"}')
|
||||||
.slim_shirt_white.option(@click='set({"preferences.shirt":"white"})', :class='{active: user.preferences.shirt === "white"}')
|
.slim_shirt_white.option(@click='set({"preferences.shirt":"white"})', :class='{active: user.preferences.shirt === "white"}')
|
||||||
.slim_shirt_yellow.option(@click='set({"preferences.shirt":"yellow"})', :class='{active: user.preferences.shirt === "yellow"}')
|
.slim_shirt_yellow.option(@click='set({"preferences.shirt":"yellow"})', :class='{active: user.preferences.shirt === "yellow"}')
|
||||||
.col-12.premium-shirts(v-if='editing')
|
.col-12.customize-options
|
||||||
.broad_shirt_convict.option(@click='set({"preferences.shirt":"convict"})', :class='{active: user.preferences.shirt === "convict"}')
|
.option(v-for='option in ["convict", "cross", "fire", "horizon", "ocean", "purple", "rainbow", "redblue", "thunder", "tropical", "zombie"]',
|
||||||
|
:class='[`broad_shirt_${option}`, {active: user.preferences.shirt === option}]',
|
||||||
|
@click='set({"preferences.shirt": option})')
|
||||||
|
|
||||||
.section.customize-section(v-if='activeTopPage === "skin"')
|
.section.customize-section(v-if='activeTopPage === "skin"')
|
||||||
.row.sub-menu.col-6.offset-3.text-center
|
.row.sub-menu.col-6.offset-3.text-center
|
||||||
@@ -141,6 +143,13 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
|
|||||||
.hair_flower_4.option(@click='set({"preferences.hair.flower":4})', :class='{active: user.preferences.hair.flower === 4}')
|
.hair_flower_4.option(@click='set({"preferences.hair.flower":4})', :class='{active: user.preferences.hair.flower === 4}')
|
||||||
.hair_flower_5.option(@click='set({"preferences.hair.flower":5})', :class='{active: user.preferences.hair.flower === 5}')
|
.hair_flower_5.option(@click='set({"preferences.hair.flower":5})', :class='{active: user.preferences.hair.flower === 5}')
|
||||||
.hair_flower_6.option(@click='set({"preferences.hair.flower":6})', :class='{active: user.preferences.hair.flower === 6}')
|
.hair_flower_6.option(@click='set({"preferences.hair.flower":6})', :class='{active: user.preferences.hair.flower === 6}')
|
||||||
|
.row(v-if='activeSubPage === "flower"')
|
||||||
|
.col-12.customize-options
|
||||||
|
// button.customize-option(ng-repeat='item in ::getGearArray("animal")', class='{{::item.key}}',
|
||||||
|
ng-class="{locked: user.items.gear.owned[item.key] == undefined, selectableInventory: user.preferences.costume ? user.items.gear.costume.headAccessory == item.key : user.items.gear.equipped.headAccessory == item.key}",
|
||||||
|
popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter',
|
||||||
|
popover-placement='right', popover-append-to-body='true',
|
||||||
|
ng-click='user.items.gear.owned[item.key] ? equip(item.key) : purchase(item.type,item)')
|
||||||
|
|
||||||
#backgrounds.section.container.customize-section(v-if='activeTopPage === "backgrounds"')
|
#backgrounds.section.container.customize-section(v-if='activeTopPage === "backgrounds"')
|
||||||
.row.sub-menu.col-6.offset-3
|
.row.sub-menu.col-6.offset-3
|
||||||
@@ -172,6 +181,7 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
|
|||||||
@click.prevent.stop="togglePinned(bg)"
|
@click.prevent.stop="togglePinned(bg)"
|
||||||
)
|
)
|
||||||
span.svg-icon.inline.icon-12.color(v-html="icons.pin")
|
span.svg-icon.inline.icon-12.color(v-html="icons.pin")
|
||||||
|
|
||||||
.col-12.text-center(v-if='!ownsSet("background", set.items) && set.identifier !== "incentiveBackgrounds"')
|
.col-12.text-center(v-if='!ownsSet("background", set.items) && set.identifier !== "incentiveBackgrounds"')
|
||||||
.gem-amount
|
.gem-amount
|
||||||
.svg-icon.gem(v-html='icons.gem')
|
.svg-icon.gem(v-html='icons.gem')
|
||||||
@@ -215,6 +225,11 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
|
|||||||
input.custom-control-input(type="checkbox")
|
input.custom-control-input(type="checkbox")
|
||||||
span.custom-control-indicator
|
span.custom-control-indicator
|
||||||
span.custom-control-description(v-once) {{ $t('creativity') }}
|
span.custom-control-description(v-once) {{ $t('creativity') }}
|
||||||
|
div
|
||||||
|
label.custom-control.custom-checkbox
|
||||||
|
input.custom-control-input(type="checkbox")
|
||||||
|
span.custom-control-indicator
|
||||||
|
span.custom-control-description(v-once) {{ $t('self_care') }}
|
||||||
|
|
||||||
.section.row.justin-message-section(:class='{top: modalPage > 1}')
|
.section.row.justin-message-section(:class='{top: modalPage > 1}')
|
||||||
.col-9
|
.col-9
|
||||||
@@ -401,6 +416,10 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
|
|||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.background:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.purchase-single {
|
.purchase-single {
|
||||||
width: 141px;
|
width: 141px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -489,7 +508,6 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.badge-svg {
|
.badge-svg {
|
||||||
left: calc((100% - 18px) / 2);
|
left: calc((100% - 18px) / 2);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -559,22 +577,9 @@ export default {
|
|||||||
data () {
|
data () {
|
||||||
let backgroundShopSets = getBackgroundShopSets();
|
let backgroundShopSets = getBackgroundShopSets();
|
||||||
|
|
||||||
// @TODO: add dates to backgrounds
|
|
||||||
let backgroundShopSetsByYear = {
|
|
||||||
2014: [],
|
|
||||||
2015: [],
|
|
||||||
2016: [],
|
|
||||||
2017: [],
|
|
||||||
};
|
|
||||||
backgroundShopSets.forEach((set) => {
|
|
||||||
let year = set.identifier.substr(set.identifier.length - 4);
|
|
||||||
if (!backgroundShopSetsByYear[year]) return;
|
|
||||||
backgroundShopSetsByYear[year].push(set);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
backgroundShopSets,
|
backgroundShopSets,
|
||||||
backgroundShopSetsByYear,
|
backgroundUpdate: new Date(),
|
||||||
icons: Object.freeze({
|
icons: Object.freeze({
|
||||||
logoPurple,
|
logoPurple,
|
||||||
bodyIcon,
|
bodyIcon,
|
||||||
@@ -610,6 +615,32 @@ export default {
|
|||||||
startingPage () {
|
startingPage () {
|
||||||
return this.$store.state.avatarEditorOptions.startingPage;
|
return this.$store.state.avatarEditorOptions.startingPage;
|
||||||
},
|
},
|
||||||
|
backgroundShopSetsByYear () {
|
||||||
|
// @TODO: add dates to backgrounds
|
||||||
|
let backgroundShopSetsByYear = {
|
||||||
|
2014: [],
|
||||||
|
2015: [],
|
||||||
|
2016: [],
|
||||||
|
2017: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hack to force update for now until we restructure the data
|
||||||
|
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||||
|
|
||||||
|
this.backgroundShopSets.forEach((set) => {
|
||||||
|
let year = set.identifier.substr(set.identifier.length - 4);
|
||||||
|
if (!backgroundShopSetsByYear[year]) return;
|
||||||
|
|
||||||
|
let setOwnedByUser = false;
|
||||||
|
for (let key in set.items) {
|
||||||
|
if (this.user.purchased.background[key]) setOwnedByUser = true;
|
||||||
|
}
|
||||||
|
set.userOwns = setOwnedByUser;
|
||||||
|
|
||||||
|
backgroundShopSetsByYear[year].push(set);
|
||||||
|
});
|
||||||
|
return backgroundShopSetsByYear;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
prev () {
|
prev () {
|
||||||
@@ -654,7 +685,6 @@ export default {
|
|||||||
for (let key in set) {
|
for (let key in set) {
|
||||||
let value = set[key];
|
let value = set[key];
|
||||||
if (type === 'background') key = value.key;
|
if (type === 'background') key = value.key;
|
||||||
|
|
||||||
if (this.user.purchased[type][key]) setOwnedByUser = true;
|
if (this.user.purchased[type][key]) setOwnedByUser = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,6 +727,7 @@ export default {
|
|||||||
path,
|
path,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
this.backgroundUpdate = new Date();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert(e.message);
|
alert(e.message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,9 +172,10 @@ export default {
|
|||||||
};
|
};
|
||||||
group.name = this.$t('possessiveParty', {name: this.user.profile.name});
|
group.name = this.$t('possessiveParty', {name: this.user.profile.name});
|
||||||
let party = await this.$store.dispatch('guilds:create', {group});
|
let party = await this.$store.dispatch('guilds:create', {group});
|
||||||
this.$store.state.party = party;
|
this.$store.state.party.data = party;
|
||||||
this.user.party._id = party._id;
|
this.user.party._id = party._id;
|
||||||
this.$root.$emit('hide::modal', 'create-party-modal');
|
this.$root.$emit('hide::modal', 'create-party-modal');
|
||||||
|
this.$router.push('/party');
|
||||||
// @TODO: Analytics.updateUser({'partyID': $scope.group ._id, 'partySize': 1});
|
// @TODO: Analytics.updateUser({'partyID': $scope.group ._id, 'partySize': 1});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ export default {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
createGroup () {
|
createGroup () {
|
||||||
|
this.$store.state.editingGroup = {};
|
||||||
this.$root.$emit('show::modal', 'guild-form');
|
this.$root.$emit('show::modal', 'guild-form');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -578,7 +578,8 @@ export default {
|
|||||||
this.newMessage = newText;
|
this.newMessage = newText;
|
||||||
},
|
},
|
||||||
showMemberModal () {
|
showMemberModal () {
|
||||||
this.$store.state.groupId = this.group._id;
|
this.$store.state.memberModalOptions.groupId = this.group._id;
|
||||||
|
this.$store.state.memberModalOptions.group = this.group;
|
||||||
this.$root.$emit('show::modal', 'members-modal');
|
this.$root.$emit('show::modal', 'members-modal');
|
||||||
},
|
},
|
||||||
async sendMessage () {
|
async sendMessage () {
|
||||||
@@ -638,8 +639,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async join () {
|
async join () {
|
||||||
// @TODO: This needs to be in the notifications where users will now accept invites
|
if (this.group.cancelledPlan && !confirm(this.$t('aboutToJoinCancelledGroupPlan'))) {
|
||||||
if (this.group.cancelledPlan && !confirm(window.env.t('aboutToJoinCancelledGroupPlan'))) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.$store.dispatch('guilds:join', {guildId: this.group._id, type: 'myGuilds'});
|
await this.$store.dispatch('guilds:join', {guildId: this.group._id, type: 'myGuilds'});
|
||||||
@@ -685,11 +685,6 @@ export default {
|
|||||||
|
|
||||||
await this.$store.dispatch('guilds:join', {groupId: this.group._id});
|
await this.$store.dispatch('guilds:join', {groupId: this.group._id});
|
||||||
},
|
},
|
||||||
// @TODO: Move to notificatin component
|
|
||||||
async reject () {
|
|
||||||
await this.$store.dispatch('guilds:rejectInvite', {groupId: this.group._id});
|
|
||||||
// User.sync();
|
|
||||||
},
|
|
||||||
clickStartQuest () {
|
clickStartQuest () {
|
||||||
// Analytics.track({'hitType':'event','eventCategory':'button','eventAction':'click','eventLabel':'Start a Quest'});
|
// Analytics.track({'hitType':'event','eventCategory':'button','eventAction':'click','eventLabel':'Start a Quest'});
|
||||||
let hasQuests = find(this.user.items.quests, (quest) => {
|
let hasQuests = find(this.user.items.quests, (quest) => {
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
.form-group
|
.form-group
|
||||||
label
|
label
|
||||||
strong(v-once) {{$t('name')}} *
|
strong(v-once) {{$t('name')}} *
|
||||||
b-form-input(type="text", :placeholder="$t('newGuildPlaceholder')", v-model="workingGuild.name")
|
b-form-input(type="text", :placeholder="$t('newGuildPlaceholder')", v-model="workingGroup.name")
|
||||||
.form-group(v-if='workingGuild.id && members.length > 0')
|
.form-group(v-if='workingGroup.id && members.length > 0')
|
||||||
label
|
label
|
||||||
strong(v-once) {{$t('guildOrPartyLeader')}} *
|
strong(v-once) {{$t('guildOrPartyLeader')}} *
|
||||||
select.form-control(v-model="workingGuild.newLeader")
|
select.form-control(v-model="workingGroup.newLeader")
|
||||||
option(v-for='member in members', :value="member._id") {{ member.profile.name }}
|
option(v-for='member in members', :value="member._id") {{ member.profile.name }}
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
strong(v-once) {{$t('privacySettings')}} *
|
strong(v-once) {{$t('privacySettings')}} *
|
||||||
br
|
br
|
||||||
label.custom-control.custom-checkbox
|
label.custom-control.custom-checkbox
|
||||||
input.custom-control-input(type="checkbox", v-model="workingGuild.onlyLeaderCreatesChallenges")
|
input.custom-control-input(type="checkbox", v-model="workingGroup.onlyLeaderCreatesChallenges")
|
||||||
span.custom-control-indicator
|
span.custom-control-indicator
|
||||||
span.custom-control-description(v-once) {{ $t('onlyLeaderCreatesChallenges') }}
|
span.custom-control-description(v-once) {{ $t('onlyLeaderCreatesChallenges') }}
|
||||||
b-tooltip.icon(:content="$t('privateDescription')")
|
b-tooltip.icon(:content="$t('privateDescription')")
|
||||||
@@ -24,13 +24,13 @@
|
|||||||
|
|
||||||
// br
|
// br
|
||||||
// @TODO Implement in V2 label.custom-control.custom-checkbox
|
// @TODO Implement in V2 label.custom-control.custom-checkbox
|
||||||
input.custom-control-input(type="checkbox", v-model="workingGuild.guildLeaderCantBeMessaged")
|
input.custom-control-input(type="checkbox", v-model="workingGroup.guildLeaderCantBeMessaged")
|
||||||
span.custom-control-indicator
|
span.custom-control-indicator
|
||||||
span.custom-control-description(v-once) {{ $t('guildLeaderCantBeMessaged') }}
|
span.custom-control-description(v-once) {{ $t('guildLeaderCantBeMessaged') }}
|
||||||
|
|
||||||
br
|
br
|
||||||
label.custom-control.custom-checkbox(v-if='!isParty')
|
label.custom-control.custom-checkbox(v-if='!isParty')
|
||||||
input.custom-control-input(type="checkbox", v-model="workingGuild.privateGuild")
|
input.custom-control-input(type="checkbox", v-model="workingGroup.privateGuild")
|
||||||
span.custom-control-indicator
|
span.custom-control-indicator
|
||||||
span.custom-control-description(v-once) {{ $t('privateGuild') }}
|
span.custom-control-description(v-once) {{ $t('privateGuild') }}
|
||||||
b-tooltip.icon(:content="$t('privateDescription')")
|
b-tooltip.icon(:content="$t('privateDescription')")
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
// br
|
// br
|
||||||
// @TODO: Implement in v2 label.custom-control.custom-checkbox(v-if='!creatingParty')
|
// @TODO: Implement in v2 label.custom-control.custom-checkbox(v-if='!creatingParty')
|
||||||
input.custom-control-input(type="checkbox", v-model="workingGuild.allowGuildInvationsFromNonMembers")
|
input.custom-control-input(type="checkbox", v-model="workingGroup.allowGuildInvationsFromNonMembers")
|
||||||
span.custom-control-indicator
|
span.custom-control-indicator
|
||||||
span.custom-control-description(v-once) {{ $t('allowGuildInvationsFromNonMembers') }}
|
span.custom-control-description(v-once) {{ $t('allowGuildInvationsFromNonMembers') }}
|
||||||
|
|
||||||
@@ -46,16 +46,16 @@
|
|||||||
label
|
label
|
||||||
strong(v-once) {{$t('guildSummary')}} *
|
strong(v-once) {{$t('guildSummary')}} *
|
||||||
div.summary-count {{charactersRemaining}} {{ $t('charactersRemaining') }}
|
div.summary-count {{charactersRemaining}} {{ $t('charactersRemaining') }}
|
||||||
textarea.form-control.summary-textarea(:placeholder="$t('guildSummaryPlaceholder')", v-model="workingGuild.summary")
|
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
|
// @TODO: need summary only for PUBLIC GUILDS, not for tavern, private guilds, or party
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
label
|
label
|
||||||
strong(v-once) {{$t('groupDescription')}} *
|
strong(v-once) {{$t('groupDescription')}} *
|
||||||
a.float-right {{ $t('markdownFormattingHelp') }}
|
a.float-right {{ $t('markdownFormattingHelp') }}
|
||||||
b-form-input.description-textarea(type="text", textarea, :placeholder="creatingParty ? $t('partyDescriptionPlaceholder') : $t('guildDescriptionPlaceholder')", v-model="workingGuild.description")
|
b-form-input.description-textarea(type="text", textarea, :placeholder="isParty ? $t('partyDescriptionPlaceholder') : $t('guildDescriptionPlaceholder')", v-model="workingGroup.description")
|
||||||
|
|
||||||
.form-group(v-if='creatingParty && !workingGuild.id')
|
.form-group(v-if='creatingParty && !workingGroup.id')
|
||||||
span
|
span
|
||||||
toggleSwitch(:label="$t('inviteMembersNow')", v-model='inviteMembers')
|
toggleSwitch(:label="$t('inviteMembersNow')", v-model='inviteMembers')
|
||||||
|
|
||||||
@@ -63,21 +63,21 @@
|
|||||||
label
|
label
|
||||||
strong(v-once) {{$t('categories')}} *
|
strong(v-once) {{$t('categories')}} *
|
||||||
div.category-wrap(@click.prevent="toggleCategorySelect")
|
div.category-wrap(@click.prevent="toggleCategorySelect")
|
||||||
span.category-select(v-if='workingGuild.categories.length === 0') {{$t('none')}}
|
span.category-select(v-if='workingGroup.categories.length === 0') {{$t('none')}}
|
||||||
.category-label(v-for='category in workingGuild.categories') {{$t(categoriesHashByKey[category])}}
|
.category-label(v-for='category in workingGroup.categories') {{$t(categoriesHashByKey[category])}}
|
||||||
.category-box(v-if="showCategorySelect")
|
.category-box(v-if="showCategorySelect")
|
||||||
.form-check(
|
.form-check(
|
||||||
v-for="group in categoryOptions",
|
v-for="group in categoryOptions",
|
||||||
:key="group.key",
|
:key="group.key",
|
||||||
)
|
)
|
||||||
label.custom-control.custom-checkbox
|
label.custom-control.custom-checkbox
|
||||||
input.custom-control-input(type="checkbox", :value="group.key", v-model="workingGuild.categories")
|
input.custom-control-input(type="checkbox", :value="group.key", v-model="workingGroup.categories")
|
||||||
span.custom-control-indicator
|
span.custom-control-indicator
|
||||||
span.custom-control-description(v-once) {{ $t(group.label) }}
|
span.custom-control-description(v-once) {{ $t(group.label) }}
|
||||||
button.btn.btn-primary(@click.prevent="toggleCategorySelect") {{$t('close')}}
|
button.btn.btn-primary(@click.prevent="toggleCategorySelect") {{$t('close')}}
|
||||||
// @TODO: need categories only for PUBLIC GUILDS, not for tavern, private guilds, or party
|
// @TODO: need categories only for PUBLIC GUILDS, not for tavern, private guilds, or party
|
||||||
|
|
||||||
.form-group(v-if='inviteMembers && !workingGuild.id')
|
.form-group(v-if='inviteMembers && !workingGroup.id')
|
||||||
label
|
label
|
||||||
strong(v-once) Invite via Email or User ID
|
strong(v-once) Invite via Email or User ID
|
||||||
p(v-once) {{$t('inviteMembersHowTo')}} *
|
p(v-once) {{$t('inviteMembersHowTo')}} *
|
||||||
@@ -91,12 +91,12 @@
|
|||||||
button(@click.prevent='addMemberToInvite()') Add
|
button(@click.prevent='addMemberToInvite()') Add
|
||||||
|
|
||||||
.form-group.text-center
|
.form-group.text-center
|
||||||
div.item-with-icon(v-if='!this.workingGuild.id')
|
div.item-with-icon(v-if='!this.workingGroup.id')
|
||||||
.svg-icon(v-html="icons.gem")
|
.svg-icon(v-html="icons.gem")
|
||||||
span.count 4
|
span.count 4
|
||||||
button.btn.btn-primary.btn-md(v-if='!workingGuild.id', :disabled='!workingGuild.name || !workingGuild.description') {{ creatingParty ? $t('createParty') : $t('createGuild') }}
|
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='workingGuild.id', :disabled='!workingGuild.name || !workingGuild.description') {{ isParty ? $t('updateParty') : $t('updateGuild') }}
|
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.workingGuild.id') {{ $t('guildGemCostInfo') }}
|
.gem-description(v-once, v-if='!this.workingGroup.id') {{ $t('guildGemCostInfo') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -187,7 +187,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
let data = {
|
let data = {
|
||||||
workingGuild: {
|
workingGroup: {
|
||||||
id: '',
|
id: '',
|
||||||
name: '',
|
name: '',
|
||||||
type: 'guild',
|
type: 'guild',
|
||||||
@@ -286,25 +286,34 @@ export default {
|
|||||||
// @TODO: do we need this? Maybe us computed. If we need, then make it on show a specific modal
|
// @TODO: do we need this? Maybe us computed. If we need, then make it on show a specific modal
|
||||||
this.$root.$on('shown::modal', () => {
|
this.$root.$on('shown::modal', () => {
|
||||||
let editingGroup = this.$store.state.editingGroup;
|
let editingGroup = this.$store.state.editingGroup;
|
||||||
if (!editingGroup._id) return;
|
if (!editingGroup._id) {
|
||||||
this.workingGuild.name = editingGroup.name;
|
this.resetWorkingGroup();
|
||||||
this.workingGuild.type = editingGroup.type;
|
return;
|
||||||
this.workingGuild.privacy = editingGroup.privacy;
|
}
|
||||||
if (editingGroup.summary) this.workingGuild.summary = editingGroup.summary;
|
|
||||||
if (editingGroup.description) this.workingGuild.description = editingGroup.description;
|
this.workingGroup.name = editingGroup.name;
|
||||||
if (editingGroup._id) this.workingGuild.id = editingGroup._id;
|
this.workingGroup.type = editingGroup.type;
|
||||||
if (editingGroup.leader._id) this.workingGuild.newLeader = editingGroup.leader._id;
|
|
||||||
|
this.workingGroup.privateGuild = true;
|
||||||
|
if (editingGroup.privacy === 'public') {
|
||||||
|
this.workingGroup.privateGuild = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editingGroup.summary) this.workingGroup.summary = editingGroup.summary;
|
||||||
|
if (editingGroup.description) this.workingGroup.description = editingGroup.description;
|
||||||
|
if (editingGroup._id) this.workingGroup.id = editingGroup._id;
|
||||||
|
if (editingGroup.leader._id) this.workingGroup.newLeader = editingGroup.leader._id;
|
||||||
if (editingGroup._id) this.getMembers();
|
if (editingGroup._id) this.getMembers();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
charactersRemaining () {
|
charactersRemaining () {
|
||||||
let currentLength = this.workingGuild.summary ? this.workingGuild.summary.length : 0;
|
let currentLength = this.workingGroup.summary ? this.workingGroup.summary.length : 0;
|
||||||
return MAX_SUMMARY_SIZE_FOR_GUILDS - currentLength;
|
return MAX_SUMMARY_SIZE_FOR_GUILDS - currentLength;
|
||||||
},
|
},
|
||||||
title () {
|
title () {
|
||||||
if (this.creatingParty) return this.$t('createParty');
|
if (this.creatingParty) return this.$t('createParty');
|
||||||
if (!this.workingGuild.id) return this.$t('createGuild');
|
if (!this.workingGroup.id) return this.$t('createGuild');
|
||||||
if (this.isParty) return this.$t('updateParty');
|
if (this.isParty) return this.$t('updateParty');
|
||||||
return this.$t('updateGuild');
|
return this.$t('updateGuild');
|
||||||
},
|
},
|
||||||
@@ -312,14 +321,14 @@ export default {
|
|||||||
return this.$store.state.groupFormOptions.createParty;
|
return this.$store.state.groupFormOptions.createParty;
|
||||||
},
|
},
|
||||||
isParty () {
|
isParty () {
|
||||||
return this.workingGuild.type === 'party';
|
return this.workingGroup.type === 'party';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getMembers () {
|
async getMembers () {
|
||||||
if (!this.workingGuild.id) return;
|
if (!this.workingGroup.id) return;
|
||||||
let members = await this.$store.dispatch('members:getGroupMembers', {
|
let members = await this.$store.dispatch('members:getGroupMembers', {
|
||||||
groupId: this.workingGuild.id,
|
groupId: this.workingGroup.id,
|
||||||
includeAllPublicFields: true,
|
includeAllPublicFields: true,
|
||||||
});
|
});
|
||||||
this.members = members;
|
this.members = members;
|
||||||
@@ -339,51 +348,51 @@ export default {
|
|||||||
this.showCategorySelect = !this.showCategorySelect;
|
this.showCategorySelect = !this.showCategorySelect;
|
||||||
},
|
},
|
||||||
async submit () {
|
async submit () {
|
||||||
if (this.$store.state.user.data.balance < 1 && !this.workingGuild.id) {
|
if (this.$store.state.user.data.balance < 1 && !this.workingGroup.id) {
|
||||||
// @TODO: Add proper notifications
|
// @TODO: Add proper notifications
|
||||||
alert('Not enough gems');
|
alert('Not enough gems');
|
||||||
return;
|
return;
|
||||||
// @TODO return $rootScope.openModal('buyGems', {track:"Gems > Create Group"});
|
// @TODO return $rootScope.openModal('buyGems', {track:"Gems > Create Group"});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.workingGuild.name || !this.workingGuild.description) {
|
if (!this.workingGroup.name || !this.workingGroup.description) {
|
||||||
// @TODO: Add proper notifications - split this out into two, make errors translatable. Suggestion: `<% fieldName %> is required` for all errors where possible, where `fieldName` is inserted as the translatable string that's used for the field header.
|
// @TODO: Add proper notifications - split this out into two, make errors translatable. Suggestion: `<% fieldName %> is required` for all errors where possible, where `fieldName` is inserted as the translatable string that's used for the field header.
|
||||||
alert('Enter a name and description');
|
alert('Enter a name and description');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.workingGuild.summary) {
|
if (!this.workingGroup.summary) {
|
||||||
// @TODO: Add proper notifications. Summary is mandatory for only public guilds (not tavern, private guilds, parties)
|
// @TODO: Add proper notifications. Summary is mandatory for only public guilds (not tavern, private guilds, parties)
|
||||||
alert('Enter a summary');
|
alert('Enter a summary');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.workingGuild.summary.length > MAX_SUMMARY_SIZE_FOR_GUILDS) {
|
if (this.workingGroup.summary.length > MAX_SUMMARY_SIZE_FOR_GUILDS) {
|
||||||
// @TODO: Add proper notifications. Summary is mandatory for only public guilds (not tavern, private guilds, parties)
|
// @TODO: Add proper notifications. Summary is mandatory for only public guilds (not tavern, private guilds, parties)
|
||||||
alert('Summary is too long');
|
alert('Summary is too long');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.workingGuild.categories || this.workingGuild.categories.length === 0) {
|
if (!this.workingGroup.categories || this.workingGroup.categories.length === 0) {
|
||||||
// @TODO: Add proper notifications
|
// @TODO: Add proper notifications
|
||||||
alert('One or more categories must be selected');
|
alert('One or more categories must be selected');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO: Add proper notifications
|
// @TODO: Add proper notifications
|
||||||
if (!this.workingGuild.id && !confirm(this.$t('confirmGuild'))) return;
|
if (!this.workingGroup.id && !confirm(this.$t('confirmGuild'))) return;
|
||||||
|
|
||||||
if (!this.workingGuild.privateGuild) {
|
if (!this.workingGroup.privateGuild) {
|
||||||
this.workingGuild.privacy = 'public';
|
this.workingGroup.privacy = 'public';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.workingGuild.onlyLeaderCreatesChallenges) {
|
if (!this.workingGroup.onlyLeaderCreatesChallenges) {
|
||||||
this.workingGuild.leaderOnly = {
|
this.workingGroup.leaderOnly = {
|
||||||
challenges: true,
|
challenges: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let categoryKeys = this.workingGuild.categories;
|
let categoryKeys = this.workingGroup.categories;
|
||||||
let serverCategories = [];
|
let serverCategories = [];
|
||||||
categoryKeys.forEach(key => {
|
categoryKeys.forEach(key => {
|
||||||
let catName = this.categoriesHashByKey[key];
|
let catName = this.categoriesHashByKey[key];
|
||||||
@@ -392,22 +401,22 @@ export default {
|
|||||||
name: catName,
|
name: catName,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.workingGuild.categories = serverCategories;
|
this.workingGroup.categories = serverCategories;
|
||||||
|
|
||||||
let newgroup;
|
let newgroup;
|
||||||
if (this.workingGuild.id) {
|
if (this.workingGroup.id) {
|
||||||
await this.$store.dispatch('guilds:update', {group: this.workingGuild});
|
await this.$store.dispatch('guilds:update', {group: this.workingGroup});
|
||||||
this.$root.$emit('updatedGroup', this.workingGuild);
|
this.$root.$emit('updatedGroup', this.workingGroup);
|
||||||
// @TODO: this doesn't work because of the async resource
|
// @TODO: this doesn't work because of the async resource
|
||||||
// if (updatedGroup.type === 'party') this.$store.state.party = {data: updatedGroup};
|
// if (updatedGroup.type === 'party') this.$store.state.party = {data: updatedGroup};
|
||||||
} else {
|
} else {
|
||||||
newgroup = await this.$store.dispatch('guilds:create', {group: this.workingGuild});
|
newgroup = await this.$store.dispatch('guilds:create', {group: this.workingGroup});
|
||||||
this.$store.state.user.data.balance -= 1;
|
this.$store.state.user.data.balance -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.state.editingGroup = {};
|
this.$store.state.editingGroup = {};
|
||||||
|
|
||||||
this.workingGuild = {
|
this.workingGroup = {
|
||||||
name: '',
|
name: '',
|
||||||
type: 'guild',
|
type: 'guild',
|
||||||
privacy: 'private',
|
privacy: 'private',
|
||||||
@@ -424,6 +433,19 @@ export default {
|
|||||||
}
|
}
|
||||||
this.$root.$emit('hide::modal', 'guild-form');
|
this.$root.$emit('hide::modal', 'guild-form');
|
||||||
},
|
},
|
||||||
|
resetWorkingGroup () {
|
||||||
|
this.workingGroup = {
|
||||||
|
name: '',
|
||||||
|
type: 'guild',
|
||||||
|
privacy: 'private',
|
||||||
|
description: '',
|
||||||
|
categories: [],
|
||||||
|
onlyLeaderCreatesChallenges: true,
|
||||||
|
guildLeaderCantBeMessaged: true,
|
||||||
|
privateGuild: true,
|
||||||
|
allowGuildInvationsFromNonMembers: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -19,24 +19,24 @@ div
|
|||||||
.col-8.offset-1
|
.col-8.offset-1
|
||||||
member-details(:member='member')
|
member-details(:member='member')
|
||||||
.col-3.actions
|
.col-3.actions
|
||||||
b-dropdown(:text="$t('sort')", right=true)
|
b-dropdown(text="...", right=true)
|
||||||
b-dropdown-item(@click='sort(option.value)')
|
b-dropdown-item(@click='sort(option.value)', v-if='isLeader')
|
||||||
span.dropdown-icon-item
|
span.dropdown-icon-item
|
||||||
.svg-icon.inline(v-html="icons.removeIcon")
|
.svg-icon.inline(v-html="icons.removeIcon", v-if='isLeader')
|
||||||
span.text {{$t('removeMember')}}
|
span.text {{$t('removeMember')}}
|
||||||
b-dropdown-item(@click='sort(option.value)')
|
b-dropdown-item(@click='sort(option.value)')
|
||||||
span.dropdown-icon-item
|
span.dropdown-icon-item
|
||||||
.svg-icon.inline(v-html="icons.messageIcon")
|
.svg-icon.inline(v-html="icons.messageIcon")
|
||||||
span.text {{$t('sendMessage')}}
|
span.text {{$t('sendMessage')}}
|
||||||
b-dropdown-item(@click='sort(option.value)')
|
b-dropdown-item(@click='sort(option.value)', v-if='isLeader')
|
||||||
span.dropdown-icon-item
|
span.dropdown-icon-item
|
||||||
.svg-icon.inline(v-html="icons.starIcon")
|
.svg-icon.inline(v-html="icons.starIcon")
|
||||||
span.text {{$t('promoteToLeader')}}
|
span.text {{$t('promoteToLeader')}}
|
||||||
b-dropdown-item(@click='sort(option.value)')
|
b-dropdown-item(@click='sort(option.value)', v-if='isLeader && groupIsSubscribed')
|
||||||
span.dropdown-icon-item
|
span.dropdown-icon-item
|
||||||
.svg-icon.inline(v-html="icons.starIcon")
|
.svg-icon.inline(v-html="icons.starIcon")
|
||||||
span.text {{$t('addManager')}}
|
span.text {{$t('addManager')}}
|
||||||
b-dropdown-item(@click='sort(option.value)')
|
b-dropdown-item(@click='sort(option.value)', v-if='isLeader && groupIsSubscribed')
|
||||||
span.dropdown-icon-item
|
span.dropdown-icon-item
|
||||||
.svg-icon.inline(v-html="icons.removeIcon")
|
.svg-icon.inline(v-html="icons.removeIcon")
|
||||||
span.text {{$t('removeManager2')}}
|
span.text {{$t('removeManager2')}}
|
||||||
@@ -109,6 +109,7 @@ import sortBy from 'lodash/sortBy';
|
|||||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||||
import bDropdown from 'bootstrap-vue/lib/components/dropdown';
|
import bDropdown from 'bootstrap-vue/lib/components/dropdown';
|
||||||
import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
|
import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
|
||||||
|
import { mapState } from 'client/libs/store';
|
||||||
|
|
||||||
import MemberDetails from '../memberDetails';
|
import MemberDetails from '../memberDetails';
|
||||||
import removeIcon from 'assets/members/remove.svg';
|
import removeIcon from 'assets/members/remove.svg';
|
||||||
@@ -116,7 +117,7 @@ import messageIcon from 'assets/members/message.svg';
|
|||||||
import starIcon from 'assets/members/star.svg';
|
import starIcon from 'assets/members/star.svg';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['group', 'hideBadge'],
|
props: ['hideBadge'],
|
||||||
components: {
|
components: {
|
||||||
bModal,
|
bModal,
|
||||||
bDropdown,
|
bDropdown,
|
||||||
@@ -160,6 +161,16 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapState({user: 'user.data'}),
|
||||||
|
isLeader () {
|
||||||
|
return this.user._id === this.group.leader || this.user._id === this.group.leader._id;
|
||||||
|
},
|
||||||
|
groupIsSubscribed () {
|
||||||
|
return this.group.purchased.active;
|
||||||
|
},
|
||||||
|
group () {
|
||||||
|
return this.$store.state.memberModalOptions.group;
|
||||||
|
},
|
||||||
sortedMembers () {
|
sortedMembers () {
|
||||||
let sortedMembers = this.members;
|
let sortedMembers = this.members;
|
||||||
if (!this.sortOption) return sortedMembers;
|
if (!this.sortOption) return sortedMembers;
|
||||||
@@ -182,7 +193,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getMembers () {
|
async getMembers () {
|
||||||
let groupId = this.$store.state.groupId || this.group._id;
|
let groupId = this.$store.state.memberModalOptions.groupId || this.group._id;
|
||||||
if (groupId && groupId !== 'challenge') {
|
if (groupId && groupId !== 'challenge') {
|
||||||
let members = await this.$store.dispatch('members:getGroupMembers', {
|
let members = await this.$store.dispatch('members:getGroupMembers', {
|
||||||
groupId,
|
groupId,
|
||||||
@@ -191,7 +202,7 @@ export default {
|
|||||||
this.members = members;
|
this.members = members;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.$store.state.viewingMembers.length > 0) {
|
if (this.$store.state.memberModalOptions.viewingMembers.length > 0) {
|
||||||
this.members = this.$store.state.viewingMembers;
|
this.members = this.$store.state.viewingMembers;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ export default {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
createGroup () {
|
createGroup () {
|
||||||
|
this.$store.state.editingGroup = {};
|
||||||
this.$root.$emit('show::modal', 'guild-form');
|
this.$root.$emit('show::modal', 'guild-form');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
.col-md-4.sidebar
|
.col-md-4.sidebar
|
||||||
.section
|
.section
|
||||||
.grassy-meadow-backdrop
|
.grassy-meadow-backdrop
|
||||||
|
.daniel_front
|
||||||
|
|
||||||
.sleep.below-header-sections
|
.sleep.below-header-sections
|
||||||
strong(v-once) {{ $t('sleepDescription') }}
|
strong(v-once) {{ $t('sleepDescription') }}
|
||||||
@@ -196,12 +197,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.grassy-meadow-backdrop {
|
.grassy-meadow-backdrop {
|
||||||
background-image: url('~assets/images/tavern_backdrop_web.png');
|
background-image: url('~assets/images/tavern_backdrop_web_backgroundtile.png');
|
||||||
background-size: cover;
|
background-repeat: repeat-x;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 246px;
|
height: 246px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.daniel_front {
|
||||||
|
background-image: url('~assets/images/tavern_backdrop_web_daniel_and_props.png');
|
||||||
|
width: 100%;
|
||||||
|
height: 246px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
.sleep {
|
.sleep {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
.item-with-icon.item-notifications.dropdown
|
div.item-with-icon.item-notifications.dropdown
|
||||||
.svg-icon(v-html="icons.notifications")
|
.svg-icon.notifications(v-html="icons.notifications")
|
||||||
// span.glyphicon(:class='iconClasses()')
|
// span.glyphicon(:class='iconClasses()')
|
||||||
// span.notification-counter(v-if='getNotificationsCount()') {{getNotificationsCount()}}
|
// span.notification-counter(v-if='getNotificationsCount()') {{getNotificationsCount()}}
|
||||||
.dropdown-menu.dropdown-menu-right.user-dropdown
|
.dropdown-menu.dropdown-menu-right.user-dropdown
|
||||||
@@ -9,24 +9,32 @@
|
|||||||
a.dropdown-item(v-if='user.purchased.plan.mysteryItems.length', @click='go("/inventory/items")')
|
a.dropdown-item(v-if='user.purchased.plan.mysteryItems.length', @click='go("/inventory/items")')
|
||||||
span.glyphicon.glyphicon-gift
|
span.glyphicon.glyphicon-gift
|
||||||
span {{ $t('newSubscriberItem') }}
|
span {{ $t('newSubscriberItem') }}
|
||||||
a.dropdown-item(v-for='party in user.invitations.parties', @click='go("/party")')
|
a.dropdown-item(v-for='party in user.invitations.parties')
|
||||||
span.glyphicon.glyphicon-user
|
div
|
||||||
span {{ $t('invitedTo', {name: party.name}) }}
|
span.glyphicon.glyphicon-user
|
||||||
|
span {{ $t('invitedTo', {name: party.name}) }}
|
||||||
|
div
|
||||||
|
span(@click='accept(party)') Accept
|
||||||
|
span(@click='reject(party)') Reject
|
||||||
a.dropdown-item(v-if='user.flags.cardReceived', @click='go("/inventory/items")')
|
a.dropdown-item(v-if='user.flags.cardReceived', @click='go("/inventory/items")')
|
||||||
span.glyphicon.glyphicon-envelope
|
span.glyphicon.glyphicon-envelope
|
||||||
span {{ $t('cardReceived') }}
|
span {{ $t('cardReceived') }}
|
||||||
a.dropdown-item(@click='clearCards()', :popover="$t('clear')",
|
a.dropdown-item(@click='clearCards()', :popover="$t('clear')",
|
||||||
popover-placement='right', popover-trigger='mouseenter', popover-append-to-body='true')
|
popover-placement='right', popover-trigger='mouseenter', popover-append-to-body='true')
|
||||||
a.dropdown-item(v-for='guild in user.invitations.guilds', @click='go("/groups/discovery")')
|
a.dropdown-item(v-for='guild in user.invitations.guilds')
|
||||||
span.glyphicon.glyphicon-user
|
div
|
||||||
span {{ $t('invitedTo', {name: guild.name}) }}
|
span.glyphicon.glyphicon-user
|
||||||
|
span {{ $t('invitedTo', {name: guild.name}) }}
|
||||||
|
div
|
||||||
|
span(@click='accept(guild)') Accept
|
||||||
|
span(@click='reject(guild)') Reject
|
||||||
a.dropdown-item(v-if='user.flags.classSelected && !user.preferences.disableClasses && user.stats.points',
|
a.dropdown-item(v-if='user.flags.classSelected && !user.preferences.disableClasses && user.stats.points',
|
||||||
@click='go("/user/profile")')
|
@click='go("/user/profile")')
|
||||||
span.glyphicon.glyphicon-plus-sign
|
span.glyphicon.glyphicon-plus-sign
|
||||||
span {{ $t('haveUnallocated', {points: user.stats.points}) }}
|
span {{ $t('haveUnallocated', {points: user.stats.points}) }}
|
||||||
a.dropdown-item(v-for='(k,v) in user.newMessages', v-if='v.value', @click='navigateToGroup(k)')
|
a.dropdown-item(v-for='(message, key) in user.newMessages', v-if='message.value', @click='navigateToGroup(key)')
|
||||||
span.glyphicon.glyphicon-comment
|
span.glyphicon.glyphicon-comment
|
||||||
span {{v.name}}
|
span {{message.name}}
|
||||||
a.dropdown-item(@click='clearMessages(k)', :popover="$t('clear')", popover-placement='right', popover-trigger='mouseenter',popover-append-to-body='true')
|
a.dropdown-item(@click='clearMessages(k)', :popover="$t('clear')", popover-placement='right', popover-trigger='mouseenter',popover-append-to-body='true')
|
||||||
a.dropdown-item(v-for='(notification, index) in user.groupNotifications', @click='viewGroupApprovalNotification(notification, index, true)')
|
a.dropdown-item(v-for='(notification, index) in user.groupNotifications', @click='viewGroupApprovalNotification(notification, index, true)')
|
||||||
span(:class="groupApprovalNotificationIcon(notification)")
|
span(:class="groupApprovalNotificationIcon(notification)")
|
||||||
@@ -42,14 +50,25 @@
|
|||||||
|
|
||||||
<style lang='scss' scoped>
|
<style lang='scss' scoped>
|
||||||
@import '~client/assets/scss/colors.scss';
|
@import '~client/assets/scss/colors.scss';
|
||||||
.svg-icon {
|
|
||||||
width: 25px;
|
.item-notifications {
|
||||||
|
width: 44px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-notifications:hover {
|
.item-notifications:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notifications {
|
||||||
|
vertical-align: bottom;
|
||||||
|
display: inline-block;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-top: .2em;
|
||||||
|
}
|
||||||
|
|
||||||
/* @TODO: Move to shared css */
|
/* @TODO: Move to shared css */
|
||||||
.dropdown:hover .dropdown-menu {
|
.dropdown:hover .dropdown-menu {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -231,7 +250,7 @@ export default {
|
|||||||
// @TODO: USe notifications: User.readNotification(notification.id);
|
// @TODO: USe notifications: User.readNotification(notification.id);
|
||||||
this.user.groupNotifications.splice(index, 1);
|
this.user.groupNotifications.splice(index, 1);
|
||||||
return navigate; // @TODO: remove
|
return navigate; // @TODO: remove
|
||||||
// @TODO: this.$route.go if (navigate) go('options.social.guilds.detail', {gid: notification.data.groupId});
|
// @TODO: this.$router.go if (navigate) go('options.social.guilds.detail', {gid: notification.data.groupId});
|
||||||
},
|
},
|
||||||
groupApprovalNotificationIcon (notification) {
|
groupApprovalNotificationIcon (notification) {
|
||||||
if (notification.type === 'GROUP_TASK_APPROVAL') {
|
if (notification.type === 'GROUP_TASK_APPROVAL') {
|
||||||
@@ -241,7 +260,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
go (path) {
|
go (path) {
|
||||||
this.$route.push(path);
|
this.$router.push(path);
|
||||||
},
|
},
|
||||||
navigateToGroup (key) {
|
navigateToGroup (key) {
|
||||||
if (key === this.party._id || key === this.user.party._id) {
|
if (key === this.party._id || key === this.user.party._id) {
|
||||||
@@ -250,6 +269,18 @@ export default {
|
|||||||
}
|
}
|
||||||
this.go(`/groups/guild/${key}`);
|
this.go(`/groups/guild/${key}`);
|
||||||
},
|
},
|
||||||
|
async reject (group) {
|
||||||
|
await this.$store.dispatch('guilds:rejectInvite', {groupId: group.id});
|
||||||
|
// @TODO: User.sync();
|
||||||
|
},
|
||||||
|
async accept (group) {
|
||||||
|
if (group.cancelledPlan && !confirm(this.$t('aboutToJoinCancelledGroupPlan'))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// @TODO: check for party , type: 'myGuilds'
|
||||||
|
await this.$store.dispatch('guilds:join', {guildId: group.id});
|
||||||
|
// this.user.guilds.push(this.group._id);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,112 +1,111 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
b-modal#buy-gems(title="Amazon", :hide-footer="true", size='lg')
|
b-modal#buy-gems(title="Buy Gems", :hide-footer="true", size='lg')
|
||||||
.modal-body
|
.modal-body
|
||||||
.buy-gems
|
div(v-if='userReachedGemCap')
|
||||||
// @TODO: +gemButton(true)
|
h2 {{ $t('buyGemsGold') }}
|
||||||
|
p {{ $t('maxBuyGems') }}
|
||||||
|
|
||||||
div(ng-if='user.purchased.plan.customerId && (user.purchased.plan.gemsBought >= User.user.purchased.plan.consecutive.gemCapExtra + Shared.planGemLimits.convCap)')
|
.row(v-if='!userReachedGemCap')
|
||||||
.panel.panel-default
|
.col-12
|
||||||
.panel-body
|
h2 {{ $t('buyGemsGold') }}
|
||||||
h3 {{ $t('buyGemsGold') }}
|
p {{ $t('subGemPop') }}
|
||||||
p {{ $t('maxBuyGems') }}
|
|
||||||
|
|
||||||
div(ng-if='user.purchased.plan.customerId && (user.purchased.plan.gemsBought < User.user.purchased.plan.consecutive.gemCapExtra + Shared.planGemLimits.convCap)')
|
.col-4
|
||||||
.panel.panel-default
|
button.btn.btn-primary(@click='purchase({ params: {type: "gems", key: "gem"} })')
|
||||||
.panel-body
|
| Buy Gems for 20 Gold each
|
||||||
h3 {{ $t('buyGemsGold') }}
|
span.Pet_Currency_Gem.inline-gems
|
||||||
p {{ $t('subGemPop') }}
|
.badge.badge-success.stack-count {{planGemLimits.convCap + user.purchased.plan.consecutive.gemCapExtra - user.purchased.plan.gemsBought}}
|
||||||
.container-fluid
|
.col-8
|
||||||
.row
|
p {{ $t('buyGemsAllow1') }}
|
||||||
.col-md-3
|
| {{planGemLimits.convCap + user.purchased.plan.consecutive.gemCapExtra - user.purchased.plan.gemsBought}}
|
||||||
button.customize-option(ng-click='User.purchase({params:{type:"gems",key:"gem"}})')
|
| {{ $t('buyGemsAllow2') }}
|
||||||
span.Pet_Currency_Gem.inline-gems
|
.col-12
|
||||||
// @TODO: .badge.badge-success.stack-count {{Shared.planGemLimits.convCap + User.user.purchased.plan.consecutive.gemCapExtra - User.user.purchased.plan.gemsBought}}
|
p(v-html="$t('seeSubscriptionDetails')")
|
||||||
|
|
||||||
|
.row(v-if='user.purchased.plan.customerId')
|
||||||
|
.col-12
|
||||||
|
h2 {{ $t('purchaseGemsSeparately') }}
|
||||||
|
.col-12.alert.alert-info
|
||||||
|
| $5 {{ $t('USD') }} = +20
|
||||||
|
.col-12
|
||||||
|
h3 {{ $t('paymentMethods') }}
|
||||||
|
button.purchase.btn.btn-primary(ng-click='Payments.showStripe({})') {{ $t('card') }}
|
||||||
|
a.purchase(href='/paypal/checkout?_id=${user._id}&apiToken=${User.settings.auth.apiToken}')
|
||||||
|
img(src='https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-small.png',alt='Pay now with Paypal')
|
||||||
|
a.purchase(ng-click="Payments.amazonPayments.init({type: 'single'})")
|
||||||
|
img(src='https://payments.amazon.com/gp/cba/button', alt='Pay now with Amazon Payments')
|
||||||
|
|
||||||
|
.row(v-if='!user.purchased.plan.customerId')
|
||||||
|
.col-12
|
||||||
|
h2 {{ $t('purchaseGems') }}
|
||||||
|
.small
|
||||||
|
span.dashed-underline(popover="$t('donateText3')", popover-trigger='mouseenter', popover-placement='bottom')
|
||||||
|
| $5 {{ $t('USD') }}
|
||||||
|
span#TotalGemPrice.dashed-underline(popover="$t('donateText1')",
|
||||||
|
popover-trigger='mouseenter', ement='bottom')
|
||||||
|
| +20
|
||||||
|
span(class="Pet_Currency_Gem1x inline-gems")
|
||||||
|
.container-fluid
|
||||||
p
|
p
|
||||||
| 20
|
small.muted {{ $t('paymentMethods') }}
|
||||||
span.shop_gold
|
a.purchase.btn.btn-primary(ng-click='Payments.showStripe({})') {{ $t('card') }}
|
||||||
.col-md-8
|
a.purchase(href='/paypal/checkout?_id=${user._id}&apiToken=${User.settings.auth.apiToken}')
|
||||||
.popover.right.gem-count-popover
|
img(src='https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-small.png',
|
||||||
.arrow
|
alt='Pay now with Paypal')
|
||||||
.popover-content
|
a.purchase(ng-click="Payments.amazonPayments.init({type: 'single'})")
|
||||||
p {{ $t('buyGemsAllow1') }}
|
img(src='https://payments.amazon.com/gp/cba/button', alt='Pay now with Amazon Payments')
|
||||||
// @TOOD: | {{Shared.planGemLimits.convCap + User.user.purchased.plan.consecutive.gemCapExtra - User.user.purchased.plan.gemsBought}}
|
|
||||||
| {{ $t('buyGemsAllow2') }}
|
.container-fluid
|
||||||
p {{ $t('seeSubscriptionDetails') }}
|
h2 {{ $t('freeGemsTitle') }}
|
||||||
div(ng-if='user.purchased.plan.customerId')
|
p {{ $t('subFreeGemsHow') }}
|
||||||
|
|
||||||
.well
|
.well
|
||||||
h3 {{ $t('purchaseGemsSeparately') }}
|
h3
|
||||||
.container-fluid
|
.small {{ $t('buyGemsGoldTitle') }}
|
||||||
.row
|
h3 {{ $t('becomeSubscriber') }}
|
||||||
.col-md-4.col-md-offset-4.alert.alert-info $5
|
|
||||||
| {{ $t('USD') }}
|
|
||||||
span#TotalGemPrice.dashed-underline(:popover="$t('donateText1')",
|
|
||||||
popover-trigger='mouseenter',popover-placement='bottom')
|
|
||||||
| +20
|
|
||||||
span(class="Pet_Currency_Gem1x inline-gems")
|
|
||||||
.container-fluid
|
|
||||||
.row
|
|
||||||
.col-md-10.col-md-offset-2
|
|
||||||
p
|
|
||||||
small.muted {{ $t('paymentMethods') }}
|
|
||||||
a.purchase.btn.btn-primary(ng-click='Payments.showStripe({})') {{ $t('card') }}
|
|
||||||
a.purchase(href='/paypal/checkout?_id=${user._id}&apiToken=${User.settings.auth.apiToken}')
|
|
||||||
img(src='https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-small.png',alt='Pay now with Paypal')
|
|
||||||
a.purchase(ng-click="Payments.amazonPayments.init({type: 'single'})")
|
|
||||||
img(src='https://payments.amazon.com/gp/cba/button', alt='Pay now with Amazon Payments')
|
|
||||||
div(ng-if='!user.purchased.plan.customerId')
|
|
||||||
.panel.panel-default
|
|
||||||
.panel-body
|
|
||||||
h3 {{ $t('purchaseGems') }}
|
|
||||||
.small
|
|
||||||
span.dashed-underline(popover="$t('donateText3')", popover-trigger='mouseenter', popover-placement='bottom')
|
|
||||||
| {{ $t('donateText2') }}
|
|
||||||
.container-fluid
|
|
||||||
.row
|
|
||||||
.col-md-4.col-md-offset-4.alert.alert-info $5
|
|
||||||
| {{ $t('USD') }}
|
|
||||||
span#TotalGemPrice.dashed-underline(popover="$t('donateText1')",
|
|
||||||
popover-trigger='mouseenter', ement='bottom')
|
|
||||||
| +20
|
|
||||||
span(class="Pet_Currency_Gem1x inline-gems")
|
|
||||||
.container-fluid
|
|
||||||
.row
|
|
||||||
.col-md-10.col-md-offset-2
|
|
||||||
p
|
|
||||||
small.muted {{ $t('paymentMethods') }}
|
|
||||||
a.purchase.btn.btn-primary(ng-click='Payments.showStripe({})') {{ $t('card') }}
|
|
||||||
a.purchase(href='/paypal/checkout?_id=${user._id}&apiToken=${User.settings.auth.apiToken}')
|
|
||||||
img(src='https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-small.png',
|
|
||||||
alt='Pay now with Paypal')
|
|
||||||
a.purchase(ng-click="Payments.amazonPayments.init({type: 'single'})")
|
|
||||||
img(src='https://payments.amazon.com/gp/cba/button', alt='Pay now with Amazon Payments')
|
|
||||||
|
|
||||||
.container-fluid
|
div(ng-include="'partials/options.settings.subscription.html'", ng-controller='SettingsCtrl')
|
||||||
h3 {{ $t('freeGemsTitle') }}
|
|
||||||
p {{ $t('subFreeGemsHow') }}
|
|
||||||
|
|
||||||
.well
|
.row(v-if='user.purchased.plan.customerId')
|
||||||
h3
|
.col-12
|
||||||
.small {{ $t('buyGemsGoldTitle') }}
|
p(v-html="$t('seeSubscriptionDetails')")
|
||||||
h3 {{ $t('becomeSubscriber') }}
|
.modal-footer
|
||||||
|
.col-12.text-center
|
||||||
div(ng-include="'partials/options.settings.subscription.html'", ng-controller='SettingsCtrl')
|
button.btn.btn-secondary(@click='close()') {{ $t('close') }}
|
||||||
div(ng-if='user.purchased.plan.customerId').pull-left
|
|
||||||
p {{ $t('seeSubscriptionDetails') }}
|
|
||||||
.text-right
|
|
||||||
button.btn.btn-default(ng-click='$close()') {{ $t('close') }}
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||||
|
import { mapState } from 'client/libs/store';
|
||||||
|
import planGemLimits from '../../../common/script/libs/planGemLimits';
|
||||||
|
import purchase from '../../../common/script/ops/purchase';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
bModal,
|
bModal,
|
||||||
},
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
planGemLimits,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({user: 'user.data'}),
|
||||||
|
userReachedGemCap () {
|
||||||
|
return this.user.purchased.plan.customerId && this.user.purchased.plan.gemsBought >= this.user.purchased.plan.consecutive.gemCapExtra + this.planGemLimits.convCap;
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
close () {
|
close () {
|
||||||
this.$root.$emit('hide::modal', 'buy-gems');
|
this.$root.$emit('hide::modal', 'buy-gems');
|
||||||
},
|
},
|
||||||
|
purchase (params) {
|
||||||
|
try {
|
||||||
|
purchase(this.user, params);
|
||||||
|
} catch (e) {
|
||||||
|
alert(e.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -72,8 +72,8 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.restoreValues.stats = this.user.stats;
|
Object.assign(this.restoreValues.stats, this.user.stats);
|
||||||
this.restoreValues.achievements.streak = this.user.achievements.streak;
|
Object.assign(this.restoreValues.achievements.streak, this.user.achievements.streak);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({user: 'user.data'}),
|
...mapState({user: 'user.data'}),
|
||||||
|
|||||||
@@ -7,46 +7,25 @@
|
|||||||
nav.navbar.navbar-toggleable-md.navbar-light.bg-faded
|
nav.navbar.navbar-toggleable-md.navbar-light.bg-faded
|
||||||
button.navbar-toggler.navbar-toggler-right(type='button', data-toggle='collapse', data-target='#navbarNav', aria-controls='navbarNav', aria-expanded='false', aria-label='Toggle navigation')
|
button.navbar-toggler.navbar-toggler-right(type='button', data-toggle='collapse', data-target='#navbarNav', aria-controls='navbarNav', aria-expanded='false', aria-label='Toggle navigation')
|
||||||
span.navbar-toggler-icon
|
span.navbar-toggler-icon
|
||||||
a.navbar-brand(href='#') Navbar
|
a.navbar-brand(href='#')
|
||||||
|
.logo.svg-icon(v-html="icons.logo")
|
||||||
#navbarNav.collapse.navbar-collapse
|
#navbarNav.collapse.navbar-collapse
|
||||||
ul.navbar-nav
|
ul.navbar-nav.float-right
|
||||||
li.nav-item.active
|
|
||||||
a.nav-link(href='#')
|
|
||||||
| Home
|
|
||||||
span.sr-only (current)
|
|
||||||
li.nav-item
|
li.nav-item
|
||||||
a.nav-link(href='#') Features
|
router-link.nav-link(to="/static/features") How it Works
|
||||||
li.nav-item
|
li.nav-item
|
||||||
a.nav-link(href='#') Pricing
|
router-link.nav-link(to="/static/plans") Group Plans
|
||||||
li.nav-item
|
li.nav-item
|
||||||
a.nav-link.disabled(href='#') Disabled
|
a.nav-link(href="https://habitica.wordpress.com/") Blog
|
||||||
|
li.nav-item
|
||||||
|
a.nav-link(href="http://blog.habitrpg.com/") Tumblr
|
||||||
|
li.nav-item
|
||||||
|
router-link.nav-link(to="/static/press-kit") Press Kit
|
||||||
|
li.nav-item
|
||||||
|
router-link.nav-link(to="/static/contact") Contact
|
||||||
|
li.nav-item
|
||||||
|
button#play-btn(class="btn btn-primary btn-lg gamifybutton") Enter Habitica
|
||||||
|
|
||||||
//-
|
|
||||||
//- nav.navbar.navbar-light.bg-faded
|
|
||||||
//- .navbar-header
|
|
||||||
//- button.navbar-toggle.collapsed(type='button', data-toggle='collapse', data-target='#bs-example-navbar-collapse-1')
|
|
||||||
//- span.sr-only Toggle navigation
|
|
||||||
//- span.icon-bar
|
|
||||||
//- span.icon-bar
|
|
||||||
//- span.icon-bar
|
|
||||||
//- a.navbar-brand(href='#')
|
|
||||||
//- img.img-rendering-auto(src='https://d2afqr2xdmyzvu.cloudfront.net/assets/habitica_lockup2_desat.png', alt="$t('altAttrNavLogo')", width='156px')
|
|
||||||
//- #bs-example-navbar-collapse-1.collapse.navbar-collapse
|
|
||||||
//- ul.nav.navbar-nav.navbar-right
|
|
||||||
//- li
|
|
||||||
//- a(href='/static/features') {{ $t('companyAbout') }}
|
|
||||||
//- li
|
|
||||||
//- a(href='/static/plans') {{ $t('groupPlans') }}
|
|
||||||
//- li
|
|
||||||
//- a(href='https://habitica.wordpress.com/') {{ $t('companyBlog') }}
|
|
||||||
//- li
|
|
||||||
//- a(href='http://blog.habitrpg.com/') {{ $t('tumblr') }}
|
|
||||||
//- li
|
|
||||||
//- a(href='/static/press-kit') {{ $t('presskit') }}
|
|
||||||
//- li
|
|
||||||
//- a(href='/static/contact') {{ $t('contactUs') }}
|
|
||||||
//- li
|
|
||||||
//- button#header-play-button.btn.btn-primary.navbar-btn.navbar-right(@click='playButtonClick()') {{ $t('playButtonFull') }}
|
|
||||||
#intro.container-fluid
|
#intro.container-fluid
|
||||||
.row
|
.row
|
||||||
h1.col-12.text-center {{ $t('motivate1') }}
|
h1.col-12.text-center {{ $t('motivate1') }}
|
||||||
@@ -556,6 +535,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.logo {
|
||||||
|
width: 128px;
|
||||||
|
height: 28px;
|
||||||
|
color: purple;
|
||||||
|
}
|
||||||
|
|
||||||
#intro {
|
#intro {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding-top: 1em;
|
padding-top: 1em;
|
||||||
@@ -634,9 +619,14 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import logo from 'assets/svg/logo.svg';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
icons: Object.freeze({
|
||||||
|
logo,
|
||||||
|
}),
|
||||||
userCount: 1000000,
|
userCount: 1000000,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ div(v-if='user.stats.lvl > 10')
|
|||||||
white-space: initial;
|
white-space: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spell:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.spell {
|
.spell {
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
@@ -244,16 +248,16 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO: do we need to fetcht the party everytime? We should probably just check store
|
let party = this.$store.state.party.members;
|
||||||
let party = await this.$store.dispatch('guilds:getGroup', {groupId: 'party'});
|
|
||||||
party = isArray(party) ? party : [];
|
party = isArray(party) ? party : [];
|
||||||
party = party.concat(this.user);
|
party = party.concat(this.user);
|
||||||
this.$store.state.party.data = party;
|
|
||||||
this.castEnd(party, 'party');
|
this.castEnd(party, 'party');
|
||||||
} else if (spell.target === 'tasks') {
|
} else if (spell.target === 'tasks') {
|
||||||
let tasks = this.$store.state.tasks.habits.concat(this.user.dailys)
|
let userTasks = this.$store.state.tasks.data;
|
||||||
.concat(this.$store.state.tasks.rewards)
|
let tasks = userTasks.habits
|
||||||
.concat(this.$store.state.tasks.todos);
|
.concat(userTasks.dailys)
|
||||||
|
.concat(userTasks.rewards)
|
||||||
|
.concat(userTasks.todos);
|
||||||
// exclude challenge tasks
|
// exclude challenge tasks
|
||||||
tasks = tasks.filter((task) => {
|
tasks = tasks.filter((task) => {
|
||||||
if (!task.challenge) return true;
|
if (!task.challenge) return true;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
|
|
||||||
// Habits right side control
|
// Habits right side control
|
||||||
.right-control.d-flex.align-items-center.justify-content-center(v-if="task.type === 'habit'", :class="controlClass.down")
|
.right-control.d-flex.align-items-center.justify-content-center(v-if="task.type === 'habit'", :class="controlClass.down")
|
||||||
.task-control.habit-control(:class="controlClass.down + '-control-habit'", @click="isUser ? score('down') : null")
|
.task-control.habit-control(:class="controlClass.down + '-control-habit'", @click="(isUser && controlClass.down !== 'task-habit-disabled') ? score('down') : null")
|
||||||
.svg-icon.negative(v-html="icons.negative")
|
.svg-icon.negative(v-html="icons.negative")
|
||||||
// Rewards right side control
|
// Rewards right side control
|
||||||
.right-control.d-flex.align-items-center.justify-content-center.reward-control(v-if="task.type === 'reward'", :class="controlClass", @click="isUser ? score('down') : null")
|
.right-control.d-flex.align-items-center.justify-content-center.reward-control(v-if="task.type === 'reward'", :class="controlClass", @click="isUser ? score('down') : null")
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
@import '~client/assets/scss/colors.scss';
|
@import '~client/assets/scss/colors.scss';
|
||||||
|
|
||||||
.task {
|
.task {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 2px;
|
||||||
box-shadow: 0 2px 2px 0 rgba($black, 0.16), 0 1px 4px 0 rgba($black, 0.12);
|
box-shadow: 0 2px 2px 0 rgba($black, 0.16), 0 1px 4px 0 rgba($black, 0.12);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
@@ -78,6 +78,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.task-habit-disabled-control-habit:hover {
|
||||||
|
cursor: initial;
|
||||||
|
}
|
||||||
|
|
||||||
.task-title {
|
.task-title {
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
color: $gray-10;
|
color: $gray-10;
|
||||||
@@ -247,6 +251,7 @@
|
|||||||
.small-text {
|
.small-text {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
color: $yellow-10;
|
color: $yellow-10;
|
||||||
|
font-style: initial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -276,6 +281,11 @@
|
|||||||
color: $gray-300;
|
color: $gray-300;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.task-reward {
|
||||||
|
// @TODO: I'm unsure of where this is defined. Can't find it in search. So, I am using important for now
|
||||||
|
background-color: rgba(255, 217, 160, 0.28) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -11,10 +11,14 @@
|
|||||||
slot="modal-header",
|
slot="modal-header",
|
||||||
:class="[cssClass]",
|
:class="[cssClass]",
|
||||||
)
|
)
|
||||||
h1 {{ title }}
|
.row
|
||||||
|
h1.col-8 {{ title }}
|
||||||
|
.col-4
|
||||||
|
span.cancel-task-btn(v-once, @click="cancel()") {{ $t('cancel') }}
|
||||||
|
button.btn.btn-secondary(type="submit", v-once) {{ $t('save') }}
|
||||||
.form-group
|
.form-group
|
||||||
label(v-once) {{ `${$t('title')}*` }}
|
label(v-once) {{ `${$t('title')}*` }}
|
||||||
input.form-control(type='text', :class="[`${cssClass}-modal-input`]", required, v-model="task.text")
|
input.form-control.title-input(type='text', :class="[`${cssClass}-modal-input`]", required, v-model="task.text", autofocus)
|
||||||
.form-group
|
.form-group
|
||||||
label(v-once) {{ $t('notes') }}
|
label(v-once) {{ $t('notes') }}
|
||||||
textarea.form-control(:class="[`${cssClass}-modal-input`]", v-model="task.notes", rows="3")
|
textarea.form-control(:class="[`${cssClass}-modal-input`]", v-model="task.notes", rows="3")
|
||||||
@@ -22,6 +26,7 @@
|
|||||||
.option(v-if="task.type === 'reward'")
|
.option(v-if="task.type === 'reward'")
|
||||||
label(v-once) {{ $t('cost') }}
|
label(v-once) {{ $t('cost') }}
|
||||||
input(type="number", v-model="task.value", required, min="0")
|
input(type="number", v-model="task.value", required, min="0")
|
||||||
|
.svg-icon.gold(v-html="icons.gold")
|
||||||
.option(v-if="['daily', 'todo'].indexOf(task.type) > -1")
|
.option(v-if="['daily', 'todo'].indexOf(task.type) > -1")
|
||||||
label(v-once) {{ $t('checklist') }}
|
label(v-once) {{ $t('checklist') }}
|
||||||
br
|
br
|
||||||
@@ -69,14 +74,16 @@
|
|||||||
label(v-once) {{ $t('startDate') }}
|
label(v-once) {{ $t('startDate') }}
|
||||||
datepicker(v-model="task.startDate")
|
datepicker(v-model="task.startDate")
|
||||||
.option(v-if="task.type === 'daily'")
|
.option(v-if="task.type === 'daily'")
|
||||||
label(v-once) {{ $t('repeats') }}
|
.form-group
|
||||||
b-dropdown(:text="$t(task.frequency)")
|
label(v-once) {{ $t('repeats') }}
|
||||||
b-dropdown-item(v-for="frequency in ['daily', 'weekly', 'monthly', 'yearly']", :key="frequency", @click="task.frequency = frequency", :class="{active: task.frequency === frequency}")
|
b-dropdown(:text="$t(task.frequency)")
|
||||||
| {{ $t(frequency) }}
|
b-dropdown-item(v-for="frequency in ['daily', 'weekly', 'monthly', 'yearly']", :key="frequency", @click="task.frequency = frequency", :class="{active: task.frequency === frequency}")
|
||||||
label(v-once) {{ $t('repeatEvery') }}
|
| {{ $t(frequency) }}
|
||||||
input.form-control(type="number", v-model="task.everyX", min="0", required)
|
.form-group
|
||||||
| {{ repeatSuffix }}
|
label(v-once) {{ $t('repeatEvery') }}
|
||||||
br
|
input(type="number", v-model="task.everyX", min="0", required)
|
||||||
|
| {{ repeatSuffix }}
|
||||||
|
br
|
||||||
template(v-if="task.frequency === 'weekly'")
|
template(v-if="task.frequency === 'weekly'")
|
||||||
.form-check-inline.weekday-check(
|
.form-check-inline.weekday-check(
|
||||||
v-for="(day, dayNumber) in ['su','m','t','w','th','f','s']",
|
v-for="(day, dayNumber) in ['su','m','t','w','th','f','s']",
|
||||||
@@ -141,7 +148,6 @@
|
|||||||
@change="updateRequiresApproval")
|
@change="updateRequiresApproval")
|
||||||
|
|
||||||
.task-modal-footer(slot="modal-footer")
|
.task-modal-footer(slot="modal-footer")
|
||||||
button.btn.btn-primary(type="submit", v-once) {{ $t('save') }}
|
|
||||||
span.cancel-task-btn(v-once, v-if="purpose === 'create'", @click="cancel()") {{ $t('cancel') }}
|
span.cancel-task-btn(v-once, v-if="purpose === 'create'", @click="cancel()") {{ $t('cancel') }}
|
||||||
span.delete-task-btn(v-once, v-else, @click="destroy()") {{ $t('delete') }}
|
span.delete-task-btn(v-once, v-else, @click="destroy()") {{ $t('delete') }}
|
||||||
</template>
|
</template>
|
||||||
@@ -311,6 +317,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cancel-task-btn {
|
||||||
|
margin-right: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
.task-modal-footer {
|
.task-modal-footer {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding-bottom: 24px;
|
padding-bottom: 24px;
|
||||||
@@ -319,7 +329,6 @@
|
|||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
|
|
||||||
.delete-task-btn, .cancel-task-btn {
|
.delete-task-btn, .cancel-task-btn {
|
||||||
margin-left: 16px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover, &:focus, &:active {
|
&:hover, &:focus, &:active {
|
||||||
@@ -343,6 +352,14 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.gold {
|
||||||
|
width: 24px;
|
||||||
|
margin-left: 5em;
|
||||||
|
margin-top: -2.4em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||||
import { mapGetters, mapActions, mapState } from 'client/libs/store';
|
import { mapGetters, mapActions, mapState } from 'client/libs/store';
|
||||||
@@ -361,6 +378,7 @@ import difficultyNormalIcon from 'assets/svg/difficulty-normal.svg';
|
|||||||
import positiveIcon from 'assets/svg/positive.svg';
|
import positiveIcon from 'assets/svg/positive.svg';
|
||||||
import negativeIcon from 'assets/svg/negative.svg';
|
import negativeIcon from 'assets/svg/negative.svg';
|
||||||
import deleteIcon from 'assets/svg/delete.svg';
|
import deleteIcon from 'assets/svg/delete.svg';
|
||||||
|
import goldIcon from 'assets/svg/gold.svg';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -385,6 +403,7 @@ export default {
|
|||||||
negative: negativeIcon,
|
negative: negativeIcon,
|
||||||
positive: positiveIcon,
|
positive: positiveIcon,
|
||||||
destroy: deleteIcon,
|
destroy: deleteIcon,
|
||||||
|
gold: goldIcon,
|
||||||
}),
|
}),
|
||||||
requiresApproval: false, // We can't set task.group fields so we use this field to toggle
|
requiresApproval: false, // We can't set task.group fields so we use this field to toggle
|
||||||
members: [],
|
members: [],
|
||||||
@@ -527,6 +546,7 @@ export default {
|
|||||||
this.$root.$emit('hide::modal', 'task-modal');
|
this.$root.$emit('hide::modal', 'task-modal');
|
||||||
},
|
},
|
||||||
destroy () {
|
destroy () {
|
||||||
|
if (!confirm('Are you sure you want to delete this task?')) return;
|
||||||
this.destroyTask(this.task);
|
this.destroyTask(this.task);
|
||||||
this.$root.$emit('hide::modal', 'task-modal');
|
this.$root.$emit('hide::modal', 'task-modal');
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
@change="toggleTag(tag)",
|
@change="toggleTag(tag)",
|
||||||
)
|
)
|
||||||
span.custom-control-indicator
|
span.custom-control-indicator
|
||||||
span.custom-control-description {{ tag.name }}
|
span.custom-control-description(v-markdown='tag.name')
|
||||||
|
|
||||||
.filter-panel-footer.clearfix
|
.filter-panel-footer.clearfix
|
||||||
template(v-if="editingTags === true")
|
template(v-if="editingTags === true")
|
||||||
@@ -117,9 +117,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
#create-dropdown .dropdown-toggle::after {
|
#create-dropdown .dropdown-toggle::after {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -142,7 +142,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-icon-item .svg-icon {
|
.dropdown-icon-item .svg-icon {
|
||||||
width: 16px;
|
width: 22px;
|
||||||
|
color: #C3C0C7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-icon-item:hover .svg-icon, .dropdown-item.active .svg-icon {
|
||||||
|
color: $purple-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-icon-item .text {
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.btn.btn-secondary.filter-button {
|
button.btn.btn-secondary.filter-button {
|
||||||
@@ -278,6 +287,7 @@
|
|||||||
import TaskColumn from './column';
|
import TaskColumn from './column';
|
||||||
import TaskModal from './taskModal';
|
import TaskModal from './taskModal';
|
||||||
import spells from './spells';
|
import spells from './spells';
|
||||||
|
import markdown from 'client/directives/markdown';
|
||||||
|
|
||||||
import positiveIcon from 'assets/svg/positive.svg';
|
import positiveIcon from 'assets/svg/positive.svg';
|
||||||
import filterIcon from 'assets/svg/filter.svg';
|
import filterIcon from 'assets/svg/filter.svg';
|
||||||
@@ -315,6 +325,9 @@ export default {
|
|||||||
spells,
|
spells,
|
||||||
SelectMembersModal,
|
SelectMembersModal,
|
||||||
},
|
},
|
||||||
|
directives: {
|
||||||
|
markdown,
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
columns: ['habit', 'daily', 'todo', 'reward'],
|
columns: ['habit', 'daily', 'todo', 'reward'],
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
div
|
div
|
||||||
span(:class="userLevelStyle(conversation)") {{conversation.name}}
|
span(:class="userLevelStyle(conversation)") {{conversation.name}}
|
||||||
span.timeago {{conversation.date}}
|
span.timeago {{conversation.date}}
|
||||||
div {{conversation.lastMessageText}}
|
div {{conversation.lastMessageText.substring(0, 30)}}
|
||||||
.col-8.messages
|
.col-8.messages
|
||||||
chat-message.container-fluid(:chat.sync='activeChat')
|
chat-message.container-fluid(:chat.sync='activeChat')
|
||||||
|
|
||||||
|
|||||||
@@ -256,6 +256,7 @@ const router = new VueRouter({
|
|||||||
{ name: 'merch', path: 'merch', component: MerchPage, meta: {requiresLogin: false}},
|
{ name: 'merch', path: 'merch', component: MerchPage, meta: {requiresLogin: false}},
|
||||||
// { name: 'newStuff', path: 'newStuff', component: NewStuffPage, meta: {requiresLogin: false}},
|
// { name: 'newStuff', path: 'newStuff', component: NewStuffPage, meta: {requiresLogin: false}},
|
||||||
{ name: 'overview', path: 'overview', component: OverviewPage, meta: {requiresLogin: false}},
|
{ name: 'overview', path: 'overview', component: OverviewPage, meta: {requiresLogin: false}},
|
||||||
|
{ name: 'oldNews', path: 'old-news', component: ParentPage, meta: {requiresLogin: false}},
|
||||||
{ name: 'plans', path: 'plans', component: GroupPlansPage, meta: {requiresLogin: false}},
|
{ name: 'plans', path: 'plans', component: GroupPlansPage, meta: {requiresLogin: false}},
|
||||||
{ name: 'pressKit', path: 'press-kit', component: PressKitPage, meta: {requiresLogin: false}},
|
{ name: 'pressKit', path: 'press-kit', component: PressKitPage, meta: {requiresLogin: false}},
|
||||||
{ name: 'privacy', path: 'privacy', component: PrivacyPage, meta: {requiresLogin: false}},
|
{ name: 'privacy', path: 'privacy', component: PrivacyPage, meta: {requiresLogin: false}},
|
||||||
|
|||||||
@@ -98,11 +98,12 @@ export async function create (store, createdTask) {
|
|||||||
|
|
||||||
sanitizeChecklist(createdTask);
|
sanitizeChecklist(createdTask);
|
||||||
|
|
||||||
list.unshift(createdTask);
|
|
||||||
store.state.user.data.tasksOrder[type].unshift(createdTask._id);
|
|
||||||
const response = await axios.post('/api/v3/tasks/user', createdTask);
|
const response = await axios.post('/api/v3/tasks/user', createdTask);
|
||||||
|
|
||||||
Object.assign(list[0], response.data.data);
|
let newTask = response.data.data;
|
||||||
|
list.unshift(newTask);
|
||||||
|
store.state.user.data.tasksOrder[type].unshift(newTask._id);
|
||||||
|
Object.assign(list[0], newTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function save (store, editedTask) {
|
export async function save (store, editedTask) {
|
||||||
|
|||||||
@@ -88,7 +88,11 @@ export default function () {
|
|||||||
selectedLanguage,
|
selectedLanguage,
|
||||||
}),
|
}),
|
||||||
hideHeader: false,
|
hideHeader: false,
|
||||||
viewingMembers: [],
|
memberModalOptions: {
|
||||||
|
viewingMembers: [],
|
||||||
|
groupId: '',
|
||||||
|
group: {},
|
||||||
|
},
|
||||||
openedItemRows: [],
|
openedItemRows: [],
|
||||||
spellOptions: {
|
spellOptions: {
|
||||||
castingSpell: false,
|
castingSpell: false,
|
||||||
|
|||||||
@@ -300,5 +300,8 @@
|
|||||||
"partyInformationPlaceholder": "Write a message to your Party members here!",
|
"partyInformationPlaceholder": "Write a message to your Party members here!",
|
||||||
"selectPartyMember": "Select a Party Member",
|
"selectPartyMember": "Select a Party Member",
|
||||||
"errorNotInParty": "You are not in a Party",
|
"errorNotInParty": "You are not in a Party",
|
||||||
"health_wellness": "Health & Wellness"
|
"health_wellness": "Health & Wellness",
|
||||||
|
"self_care": "Self-Care",
|
||||||
|
"sendLink": "Send Link",
|
||||||
|
"forgotPassword": "Forgot Password"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ let schema = new Schema({
|
|||||||
group: {type: String, ref: 'Group', validate: [validator.isUUID, 'Invalid uuid.'], required: true},
|
group: {type: String, ref: 'Group', validate: [validator.isUUID, 'Invalid uuid.'], required: true},
|
||||||
memberCount: {type: Number, default: 1},
|
memberCount: {type: Number, default: 1},
|
||||||
prize: {type: Number, default: 0, min: 0},
|
prize: {type: Number, default: 0, min: 0},
|
||||||
|
categories: [{
|
||||||
|
slug: {type: String},
|
||||||
|
name: {type: String},
|
||||||
|
}],
|
||||||
}, {
|
}, {
|
||||||
strict: true,
|
strict: true,
|
||||||
minimize: false, // So empty objects are returned
|
minimize: false, // So empty objects are returned
|
||||||
|
|||||||