mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 06:07:21 +01:00
Sept 23 fixes (#9074)
* Discover challenges * Fixed hero loading * Moved add task button * Fixed bailey showing * Added logs for bad sub data * Fixed blurb editing * Added confirmation for deleteing message * Reset invite modals on invite * fixed group member sorting * Fixed chat time styles * Fixed hover on liked * Fixed like count * Added reverse * Fixed editing party * Added leader conditions * Added search * Added loading * Reset members when leaving party * Rounded pending * Fixed overflow on collecting quests * Added to invite friends * Hid summary from party * Fixed button styles * Fixed button class * Removed okay button * Fixed renav for profile modal * Added subscription back to menu * Fixed static link * Added daily due setting * Added local auth adding * Fixed centering of text * Removed message locally * Added count for new message * Added style fix for profile pet * Fixed achievement popovers * Fixed white boxes * Added plain color backgrounds * fixed challenge mutability * Fixed challenge editing * Added notation for large numbers * Add color text to guild sizes * Removed membership filters from discover challenges * Added invites to group * Cmd + enter send message * Made leader clickable * Updated group validation * Added cancelling autocomplete * Added mention icon * Added removing member * Removed extra string
This commit is contained in:
@@ -27,7 +27,7 @@ div
|
|||||||
span.small-text(v-html="$t('inviteFriendsParty')")
|
span.small-text(v-html="$t('inviteFriendsParty')")
|
||||||
br
|
br
|
||||||
// TODO link to party creation or party page if partying solo
|
// TODO link to party creation or party page if partying solo
|
||||||
button.btn.btn-primary(@click='openPartyModal()') {{ $t('startAParty') }}
|
button.btn.btn-primary(@click='openPartyModal()') {{ partyMembers && partyMembers.length > 1 ? $t('startAParty') : $t('inviteFriends') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ div
|
|||||||
span {{Math.floor(user.stats.gp * 100) / 100}}
|
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
|
||||||
|
span.message-count.top-count(v-if='user.inbox.newMessages > 0') {{user.inbox.newMessages}}
|
||||||
.svg-icon.user(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()')
|
||||||
@@ -75,7 +76,8 @@ div
|
|||||||
a.dropdown-item(@click='showProfile("stats")') {{ $t('stats') }}
|
a.dropdown-item(@click='showProfile("stats")') {{ $t('stats') }}
|
||||||
a.dropdown-item(@click='showProfile("achievements")') {{ $t('achievements') }}
|
a.dropdown-item(@click='showProfile("achievements")') {{ $t('achievements') }}
|
||||||
a.dropdown-item.dropdown-separated(@click='showProfile("profile")') {{ $t('profile') }}
|
a.dropdown-item.dropdown-separated(@click='showProfile("profile")') {{ $t('profile') }}
|
||||||
router-link.dropdown-item.dropdown-separated(:to="{name: 'site'}") {{ $t('settings') }}
|
router-link.dropdown-item(:to="{name: 'site'}") {{ $t('settings') }}
|
||||||
|
router-link.dropdown-item.dropdown-separated(:to="{name: 'subscription'}") {{ $t('subscription') }}
|
||||||
a.nav-link.dropdown-item.dropdown-separated(to="/", @click.prevent='logout()') {{ $t('logout') }}
|
a.nav-link.dropdown-item.dropdown-separated(to="/", @click.prevent='logout()') {{ $t('logout') }}
|
||||||
li(v-if='!this.user.purchased.plan.customerId', @click='showBuyGemsModal("subscribe")')
|
li(v-if='!this.user.purchased.plan.customerId', @click='showBuyGemsModal("subscribe")')
|
||||||
.dropdown-item.text-center
|
.dropdown-item.text-center
|
||||||
@@ -295,6 +297,13 @@ div
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-count.top-count {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: .5em;
|
||||||
|
padding: .2em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
.row
|
.row
|
||||||
challenge-modal(:challenge='challenge', :cloning='cloning' v-on:updatedChallenge='updatedChallenge')
|
challenge-modal(:cloning='cloning' v-on:updatedChallenge='updatedChallenge')
|
||||||
close-challenge-modal(:members='members', :challengeId='challenge._id')
|
close-challenge-modal(:members='members', :challengeId='challenge._id')
|
||||||
challenge-member-progress-modal(:memberId='progressMemberId', :challengeId='challenge._id')
|
challenge-member-progress-modal(:memberId='progressMemberId', :challengeId='challenge._id')
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
.svg-icon.calendar-icon(v-html="icons.calendarIcon")
|
.svg-icon.calendar-icon(v-html="icons.calendarIcon")
|
||||||
| {{$t('endDate')}}
|
| {{$t('endDate')}}
|
||||||
// "endDate": "End Date: <% endDate %>",
|
// "endDate": "End Date: <% endDate %>",
|
||||||
span {{challenge.endDate}}
|
// span {{challenge.endDate}}
|
||||||
.tags
|
.tags
|
||||||
span.tag(v-for='tag in challenge.tags') {{tag}}
|
span.tag(v-for='tag in challenge.tags') {{tag}}
|
||||||
.col-4
|
.col-4
|
||||||
@@ -28,13 +28,27 @@
|
|||||||
.svg-icon.gem-icon(v-html="icons.gemIcon")
|
.svg-icon.gem-icon(v-html="icons.gemIcon")
|
||||||
| {{challenge.prize}}
|
| {{challenge.prize}}
|
||||||
.details(v-once) {{$t('prize')}}
|
.details(v-once) {{$t('prize')}}
|
||||||
.row(v-if='isLeader')
|
.row.leader-actions(v-if='isLeader')
|
||||||
.col-6.offset-6
|
.col-7.offset-5
|
||||||
span
|
span.view-progress
|
||||||
strong View Progress Of
|
strong {{ $t('viewProgressOf') }}
|
||||||
b-dropdown.create-dropdown(text="Select a Participant")
|
b-dropdown.create-dropdown(text="Select a Participant")
|
||||||
b-dropdown-item(v-for="member in members", :key="member._id", @click="openMemberProgressModal(member._id)")
|
b-dropdown-item(v-for="member in members", :key="member._id", @click="openMemberProgressModal(member._id)")
|
||||||
| {{ member.profile.name }}
|
| {{ member.profile.name }}
|
||||||
|
span(v-if='isLeader')
|
||||||
|
b-dropdown.create-dropdown(:text="$t('create')", :variant="'success'")
|
||||||
|
b-dropdown-item(v-for="type in columns", :key="type", @click="createTask(type)")
|
||||||
|
| {{$t(type)}}
|
||||||
|
task-modal(
|
||||||
|
:task="workingTask",
|
||||||
|
:purpose="taskFormPurpose",
|
||||||
|
@cancel="cancelTaskModal()",
|
||||||
|
ref="taskModal",
|
||||||
|
:challengeId="challengeId",
|
||||||
|
v-on:taskCreated='taskCreated',
|
||||||
|
v-on:taskEdited='taskEdited',
|
||||||
|
@taskDestroyed='taskDestroyed'
|
||||||
|
)
|
||||||
|
|
||||||
.row
|
.row
|
||||||
task-column.col-6(
|
task-column.col-6(
|
||||||
@@ -50,20 +64,6 @@
|
|||||||
button.btn.btn-success(v-once, @click='joinChallenge()') {{$t('joinChallenge')}}
|
button.btn.btn-success(v-once, @click='joinChallenge()') {{$t('joinChallenge')}}
|
||||||
div(v-if='isMember')
|
div(v-if='isMember')
|
||||||
button.btn.btn-danger(v-once, @click='leaveChallenge()') {{$t('leaveChallenge')}}
|
button.btn.btn-danger(v-once, @click='leaveChallenge()') {{$t('leaveChallenge')}}
|
||||||
div(v-if='isLeader')
|
|
||||||
b-dropdown.create-dropdown(:text="$t('create')")
|
|
||||||
b-dropdown-item(v-for="type in columns", :key="type", @click="createTask(type)")
|
|
||||||
| {{$t(type)}}
|
|
||||||
task-modal(
|
|
||||||
:task="workingTask",
|
|
||||||
:purpose="taskFormPurpose",
|
|
||||||
@cancel="cancelTaskModal()",
|
|
||||||
ref="taskModal",
|
|
||||||
:challengeId="challengeId",
|
|
||||||
v-on:taskCreated='taskCreated',
|
|
||||||
v-on:taskEdited='taskEdited',
|
|
||||||
@taskDestroyed='taskDestroyed'
|
|
||||||
)
|
|
||||||
div(v-if='isLeader')
|
div(v-if='isLeader')
|
||||||
button.btn.btn-secondary(v-once, @click='edit()') {{$t('editChallenge')}}
|
button.btn.btn-secondary(v-once, @click='edit()') {{$t('editChallenge')}}
|
||||||
div(v-if='isLeader')
|
div(v-if='isLeader')
|
||||||
@@ -155,6 +155,14 @@
|
|||||||
.description-section {
|
.description-section {
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.leader-actions {
|
||||||
|
margin-top: 1em;
|
||||||
|
|
||||||
|
.view-progress {
|
||||||
|
margin-right: .5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -375,6 +383,7 @@ export default {
|
|||||||
edit () {
|
edit () {
|
||||||
// @TODO: set working challenge
|
// @TODO: set working challenge
|
||||||
this.cloning = false;
|
this.cloning = false;
|
||||||
|
this.$store.state.challengeOptions.workingChallenge = Object.assign({}, this.$store.state.challengeOptions.workingChallenge, this.challenge);
|
||||||
this.$root.$emit('show::modal', 'challenge-modal');
|
this.$root.$emit('show::modal', 'challenge-modal');
|
||||||
},
|
},
|
||||||
// @TODO: view members
|
// @TODO: view members
|
||||||
|
|||||||
@@ -130,6 +130,7 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import clone from 'lodash/clone';
|
||||||
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';
|
||||||
@@ -139,7 +140,7 @@ import { TAVERN_ID, MIN_SHORTNAME_SIZE_FOR_CHALLENGES, MAX_SUMMARY_SIZE_FOR_CHAL
|
|||||||
import { mapState } from 'client/libs/store';
|
import { mapState } from 'client/libs/store';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['challenge', 'groupId', 'cloning'],
|
props: ['groupId', 'cloning'],
|
||||||
components: {
|
components: {
|
||||||
bModal,
|
bModal,
|
||||||
bDropdown,
|
bDropdown,
|
||||||
@@ -186,19 +187,19 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'mental_health',
|
label: 'mental_health',
|
||||||
key: 'mental_health ',
|
key: 'mental_health',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'getting_organized',
|
label: 'getting_organized',
|
||||||
key: 'getting_organized ',
|
key: 'getting_organized',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'self_improvement',
|
label: 'self_improvement',
|
||||||
key: 'self_improvement ',
|
key: 'self_improvement',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'spirituality',
|
label: 'spirituality',
|
||||||
key: 'spirituality ',
|
key: 'spirituality',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'time_management',
|
label: 'time_management',
|
||||||
@@ -250,7 +251,6 @@ export default {
|
|||||||
_id: TAVERN_ID,
|
_id: TAVERN_ID,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.resetWorkingChallenge();
|
|
||||||
this.setUpWorkingChallenge();
|
this.setUpWorkingChallenge();
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -321,9 +321,14 @@ export default {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
challenge () {
|
||||||
|
return this.$store.state.challengeOptions.workingChallenge;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setUpWorkingChallenge () {
|
setUpWorkingChallenge () {
|
||||||
|
this.resetWorkingChallenge();
|
||||||
|
|
||||||
if (!this.challenge) return;
|
if (!this.challenge) return;
|
||||||
|
|
||||||
this.workingChallenge = Object.assign({}, this.workingChallenge, this.challenge);
|
this.workingChallenge = Object.assign({}, this.workingChallenge, this.challenge);
|
||||||
@@ -357,6 +362,8 @@ export default {
|
|||||||
shortName: '',
|
shortName: '',
|
||||||
todos: [],
|
todos: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.$store.state.workingChallenge = {};
|
||||||
},
|
},
|
||||||
async createChallenge () {
|
async createChallenge () {
|
||||||
// @TODO: improve error handling, add it to updateChallenge, make errors translatable. Suggestion: `<% fieldName %> is required` where possible, where `fieldName` is inserted as the translatable string that's used for the field header.
|
// @TODO: improve error handling, add it to updateChallenge, make errors translatable. Suggestion: `<% fieldName %> is required` where possible, where `fieldName` is inserted as the translatable string that's used for the field header.
|
||||||
@@ -385,9 +392,11 @@ export default {
|
|||||||
name: catName,
|
name: catName,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.workingChallenge.categories = serverCategories;
|
|
||||||
|
|
||||||
let challenge = await this.$store.dispatch('challenges:createChallenge', {challenge: this.workingChallenge});
|
let challengeDetails = clone(this.workingChallenge);
|
||||||
|
challengeDetails.categories = serverCategories;
|
||||||
|
|
||||||
|
let challenge = await this.$store.dispatch('challenges:createChallenge', {challenge: challengeDetails});
|
||||||
// @TODO: When to remove from guild instead?
|
// @TODO: When to remove from guild instead?
|
||||||
this.user.balance -= this.workingChallenge.prize / 4;
|
this.user.balance -= this.workingChallenge.prize / 4;
|
||||||
|
|
||||||
@@ -403,18 +412,21 @@ export default {
|
|||||||
let categoryKeys = this.workingChallenge.categories;
|
let categoryKeys = this.workingChallenge.categories;
|
||||||
let serverCategories = [];
|
let serverCategories = [];
|
||||||
categoryKeys.forEach(key => {
|
categoryKeys.forEach(key => {
|
||||||
let catName = this.categoriesHashByKey[key];
|
let newKey = key.trim();
|
||||||
|
let catName = this.categoriesHashByKey[newKey];
|
||||||
serverCategories.push({
|
serverCategories.push({
|
||||||
slug: key,
|
slug: newKey,
|
||||||
name: catName,
|
name: catName,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.workingChallenge.categories = serverCategories;
|
|
||||||
|
let challengeDetails = clone(this.workingChallenge);
|
||||||
|
challengeDetails.categories = serverCategories;
|
||||||
|
|
||||||
this.$emit('updatedChallenge', {
|
this.$emit('updatedChallenge', {
|
||||||
challenge: this.workingChallenge,
|
challenge: challengeDetails,
|
||||||
});
|
});
|
||||||
this.$store.dispatch('challenges:updateChallenge', {challenge: this.workingChallenge});
|
this.$store.dispatch('challenges:updateChallenge', {challenge: challengeDetails});
|
||||||
this.resetWorkingChallenge();
|
this.resetWorkingChallenge();
|
||||||
this.$root.$emit('hide::modal', 'challenge-modal');
|
this.$root.$emit('hide::modal', 'challenge-modal');
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
input.custom-control-input(type="checkbox", :value='group.key' v-model="categoryFilters")
|
input.custom-control-input(type="checkbox", :value='group.key' v-model="categoryFilters")
|
||||||
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) }}
|
||||||
.form-group
|
.form-group(v-if='$route.name !== "findChallenges"')
|
||||||
h3 Membership
|
h3 Membership
|
||||||
.form-check(
|
.form-check(
|
||||||
v-for="group in roleOptions",
|
v-for="group in roleOptions",
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ export default {
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
text (newText) {
|
text (newText) {
|
||||||
|
if (!newText[newText.length - 1] || newText[newText.length - 1] === ' ') {
|
||||||
|
this.searchActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (newText[newText.length - 1] !== '@') return;
|
if (newText[newText.length - 1] !== '@') return;
|
||||||
this.searchActive = true;
|
this.searchActive = true;
|
||||||
this.currentSearchPosition = newText.length - 1;
|
this.currentSearchPosition = newText.length - 1;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
//.hr(v-if='displayDivider(msg)')
|
//.hr(v-if='displayDivider(msg)')
|
||||||
.hr-middle(v-once) {{ msg.timestamp }}
|
.hr-middle(v-once) {{ msg.timestamp }}
|
||||||
.row(v-if='user._id !== msg.uuid')
|
.row(v-if='user._id !== msg.uuid')
|
||||||
.col-2
|
div(:class='inbox ? "col-4" : "col-2"')
|
||||||
avatar(
|
avatar(
|
||||||
v-if='cachedProfileData[msg.uuid]',
|
v-if='cachedProfileData[msg.uuid]',
|
||||||
:member="cachedProfileData[msg.uuid]",
|
:member="cachedProfileData[msg.uuid]",
|
||||||
@@ -18,8 +18,9 @@
|
|||||||
:hideClassBadge='true',
|
:hideClassBadge='true',
|
||||||
@click.native="showMemberModal(msg.uuid)",
|
@click.native="showMemberModal(msg.uuid)",
|
||||||
)
|
)
|
||||||
.card.col-10
|
.card(:class='inbox ? "col-8" : "col-10"')
|
||||||
.message-hidden(v-if='msg.flagCount > 0 && user.contributor.admin') Message Hidden
|
.mentioned-icon(v-if='isUserMentioned(msg)')
|
||||||
|
.message-hidden(v-if='msg.flagCount > 0 && user.contributor.admin') Message Hidden - {{ msg.flagCount }} Flags
|
||||||
.card-block
|
.card-block
|
||||||
h3.leader(
|
h3.leader(
|
||||||
:class='userLevelStyle(cachedProfileData[msg.uuid])'
|
:class='userLevelStyle(cachedProfileData[msg.uuid])'
|
||||||
@@ -27,7 +28,7 @@
|
|||||||
)
|
)
|
||||||
| {{msg.user}}
|
| {{msg.user}}
|
||||||
.svg-icon(v-html="icons[`tier${cachedProfileData[msg.uuid].contributor.level}`]", v-if='cachedProfileData[msg.uuid] && cachedProfileData[msg.uuid].contributor && cachedProfileData[msg.uuid].contributor.level')
|
.svg-icon(v-html="icons[`tier${cachedProfileData[msg.uuid].contributor.level}`]", v-if='cachedProfileData[msg.uuid] && cachedProfileData[msg.uuid].contributor && cachedProfileData[msg.uuid].contributor.level')
|
||||||
p {{msg.timestamp | timeAgo}}
|
p.time {{msg.timestamp | timeAgo}}
|
||||||
.text(v-markdown='msg.text')
|
.text(v-markdown='msg.text')
|
||||||
hr
|
hr
|
||||||
.action(@click='like(msg, index)', v-if='msg.likes', :class='{active: msg.likes[user._id]}')
|
.action(@click='like(msg, index)', v-if='msg.likes', :class='{active: msg.likes[user._id]}')
|
||||||
@@ -43,13 +44,15 @@
|
|||||||
span.action(v-if='msg.uuid === user._id || inbox', @click='remove(msg, index)')
|
span.action(v-if='msg.uuid === user._id || inbox', @click='remove(msg, index)')
|
||||||
.svg-icon(v-html="icons.delete")
|
.svg-icon(v-html="icons.delete")
|
||||||
| {{$t('delete')}}
|
| {{$t('delete')}}
|
||||||
span.action.float-right(v-if='likeCount(msg) > 0')
|
span.action.float-right.liked(v-if='likeCount(msg) > 0')
|
||||||
.svg-icon(v-html="icons.liked")
|
.svg-icon(v-html="icons.liked")
|
||||||
| + {{ likeCount(msg) }}
|
| + {{ likeCount(msg) }}
|
||||||
// @TODO can we avoid duplicating all this code? Cannot we just push everything
|
// @TODO can we avoid duplicating all this code? Cannot we just push everything
|
||||||
// to the right if the user is the author?
|
// to the right if the user is the author?
|
||||||
|
// Maybe we just create two sub components instead
|
||||||
.row(v-if='user._id === msg.uuid')
|
.row(v-if='user._id === msg.uuid')
|
||||||
.card.col-10
|
.card(:class='inbox ? "col-8" : "col-10"')
|
||||||
|
.mentioned-icon(v-if='isUserMentioned(msg)')
|
||||||
.message-hidden(v-if='msg.flagCount > 0 && user.contributor.admin') Message Hidden - {{ msg.flagCount }} Flags
|
.message-hidden(v-if='msg.flagCount > 0 && user.contributor.admin') Message Hidden - {{ msg.flagCount }} Flags
|
||||||
.card-block
|
.card-block
|
||||||
h3.leader(
|
h3.leader(
|
||||||
@@ -58,7 +61,7 @@
|
|||||||
)
|
)
|
||||||
| {{msg.user}}
|
| {{msg.user}}
|
||||||
.svg-icon(v-html="icons[`tier${cachedProfileData[msg.uuid].contributor.level}`]", v-if='cachedProfileData[msg.uuid] && cachedProfileData[msg.uuid].contributor && cachedProfileData[msg.uuid].contributor.level')
|
.svg-icon(v-html="icons[`tier${cachedProfileData[msg.uuid].contributor.level}`]", v-if='cachedProfileData[msg.uuid] && cachedProfileData[msg.uuid].contributor && cachedProfileData[msg.uuid].contributor.level')
|
||||||
p {{msg.timestamp | timeAgo}}
|
p.time {{msg.timestamp | timeAgo}}
|
||||||
.text(v-markdown='msg.text')
|
.text(v-markdown='msg.text')
|
||||||
hr
|
hr
|
||||||
.action(@click='like(msg, index)', v-if='msg.likes', :class='{active: msg.likes[user._id]}')
|
.action(@click='like(msg, index)', v-if='msg.likes', :class='{active: msg.likes[user._id]}')
|
||||||
@@ -74,10 +77,10 @@
|
|||||||
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(v-if='likeCount(msg) > 0')
|
span.action.float-right.liked(v-if='likeCount(msg) > 0')
|
||||||
.svg-icon(v-html="icons.liked")
|
.svg-icon(v-html="icons.liked")
|
||||||
| + {{ likeCount(msg) }}
|
| + {{ likeCount(msg) }}
|
||||||
.col-2
|
div(:class='inbox ? "col-4" : "col-2"')
|
||||||
avatar(
|
avatar(
|
||||||
v-if='cachedProfileData[msg.uuid]',
|
v-if='cachedProfileData[msg.uuid]',
|
||||||
:member="cachedProfileData[msg.uuid]",
|
:member="cachedProfileData[msg.uuid]",
|
||||||
@@ -134,6 +137,26 @@
|
|||||||
}
|
}
|
||||||
// End of tier colors
|
// End of tier colors
|
||||||
|
|
||||||
|
.leader {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #878190;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mentioned-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #bda8ff;
|
||||||
|
box-shadow: 0 1px 1px 0 rgba(26, 24, 29, 0.12);
|
||||||
|
position: absolute;
|
||||||
|
right: -.5em;
|
||||||
|
top: -.5em;
|
||||||
|
}
|
||||||
|
|
||||||
h3 { // this is the user name
|
h3 { // this is the user name
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
@@ -173,6 +196,7 @@
|
|||||||
.text {
|
.text {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #4e4a57;
|
color: #4e4a57;
|
||||||
|
text-align: left !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action {
|
.action {
|
||||||
@@ -185,6 +209,10 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.liked:hover {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
.action .svg-icon {
|
.action .svg-icon {
|
||||||
margin-right: .2em;
|
margin-right: .2em;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
@@ -302,6 +330,27 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
isUserMentioned (message) {
|
||||||
|
let user = this.user;
|
||||||
|
|
||||||
|
if (message.hasOwnProperty('highlight')) return message.highlight;
|
||||||
|
|
||||||
|
message.highlight = false;
|
||||||
|
let messagetext = message.text.toLowerCase();
|
||||||
|
let username = user.profile.name;
|
||||||
|
let mentioned = messagetext.indexOf(username.toLowerCase());
|
||||||
|
let pattern = `${username}([^\w]|$){1}`;
|
||||||
|
|
||||||
|
if (mentioned === -1) return message.highlight;
|
||||||
|
|
||||||
|
let preceedingchar = messagetext.substring(mentioned - 1, mentioned);
|
||||||
|
if (mentioned === 0 || preceedingchar.trim() === '' || preceedingchar === '@') {
|
||||||
|
let regex = new RegExp(pattern, 'i');
|
||||||
|
message.highlight = regex.test(messagetext);
|
||||||
|
}
|
||||||
|
|
||||||
|
return message.highlight;
|
||||||
|
},
|
||||||
canViewFlag (message) {
|
canViewFlag (message) {
|
||||||
if (message.uuid === this.user._id) return true;
|
if (message.uuid === this.user._id) return true;
|
||||||
if (!message.flagCount || message.flagCount === 0) return true;
|
if (!message.flagCount || message.flagCount === 0) return true;
|
||||||
@@ -345,7 +394,13 @@ export default {
|
|||||||
},
|
},
|
||||||
likeCount (message) {
|
likeCount (message) {
|
||||||
if (!message.likes) return 0;
|
if (!message.likes) return 0;
|
||||||
return Object.keys(message.likes).length;
|
|
||||||
|
let likeCount = 0;
|
||||||
|
for (let key in message.likes) {
|
||||||
|
let like = message.likes[key];
|
||||||
|
if (like) likeCount += 1;
|
||||||
|
}
|
||||||
|
return likeCount;
|
||||||
},
|
},
|
||||||
async like (messageToLike, index) {
|
async like (messageToLike, index) {
|
||||||
let message = cloneDeep(messageToLike);
|
let message = cloneDeep(messageToLike);
|
||||||
@@ -374,10 +429,13 @@ export default {
|
|||||||
this.$root.$emit('show::modal', 'report-flag');
|
this.$root.$emit('show::modal', 'report-flag');
|
||||||
},
|
},
|
||||||
async remove (message, index) {
|
async remove (message, index) {
|
||||||
|
if (!confirm(this.$t('areYouSureDeleteMessage'))) return;
|
||||||
|
|
||||||
this.chat.splice(index, 1);
|
this.chat.splice(index, 1);
|
||||||
|
|
||||||
if (this.inbox) {
|
if (this.inbox) {
|
||||||
axios.delete(`/api/v3/user/messages/${message.id}`);
|
axios.delete(`/api/v3/user/messages/${message.id}`);
|
||||||
|
this.$delete(this.user.inbox.messages, message.id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -228,8 +228,9 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
|
|||||||
.row.text-center.set-title
|
.row.text-center.set-title
|
||||||
strong {{backgroundShopSets[0].text}}
|
strong {{backgroundShopSets[0].text}}
|
||||||
.row.incentive-background-row
|
.row.incentive-background-row
|
||||||
|
.col-12(v-if='showPlainBackgroundBlurb(backgroundShopSets[0].identifier, backgroundShopSets[0].items)') {{ $t('incentiveBackgroundsUnlockedWithCheckins') }}
|
||||||
.col-2(v-for='bg in backgroundShopSets[0].items',
|
.col-2(v-for='bg in backgroundShopSets[0].items',
|
||||||
@click='buy("background." + bg.key)',
|
@click='unlock("background." + bg.key)',
|
||||||
:popover-title='bg.text',
|
:popover-title='bg.text',
|
||||||
:popover='bg.notes',
|
:popover='bg.notes',
|
||||||
popover-trigger='mouseenter')
|
popover-trigger='mouseenter')
|
||||||
@@ -248,7 +249,6 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
|
|||||||
.row(v-for='set in sets', v-if='activeSubPage === key')
|
.row(v-for='set in sets', v-if='activeSubPage === key')
|
||||||
.col-8.offset-2.text-center.set-title
|
.col-8.offset-2.text-center.set-title
|
||||||
strong {{set.text}}
|
strong {{set.text}}
|
||||||
.col-12(v-if='showPlainBackgroundBlurb(set.identifier, set.items)') {{ $t('incentiveBackgroundsUnlockedWithCheckins') }}
|
|
||||||
.col-4.text-center.customize-option.background-button(v-for='bg in set.items',
|
.col-4.text-center.customize-option.background-button(v-for='bg in set.items',
|
||||||
@click='!user.purchased.background[bg.key] ? backgroundSelected(bg) : unlock("background." + bg.key)',
|
@click='!user.purchased.background[bg.key] ? backgroundSelected(bg) : unlock("background." + bg.key)',
|
||||||
:popover-title='bg.text',
|
:popover-title='bg.text',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
.col-6.title-details
|
.col-6.title-details
|
||||||
h1 {{group.name}}
|
h1 {{group.name}}
|
||||||
strong.float-left(v-once) {{$t('groupLeader')}}
|
strong.float-left(v-once) {{$t('groupLeader')}}
|
||||||
span.float-left(v-if='group.leader.profile') : {{group.leader.profile.name}}
|
span.leader.float-left(v-if='group.leader.profile', @click='showMemberProfile(group.leader)') : {{group.leader.profile.name}}
|
||||||
.col-6
|
.col-6
|
||||||
.row.icon-row
|
.row.icon-row
|
||||||
.col-4.offset-4(v-bind:class="{ 'offset-8': isParty }")
|
.col-4.offset-4(v-bind:class="{ 'offset-8': isParty }")
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
.svg-icon.shield(v-html="icons.goldGuildBadgeIcon", v-if='group.memberCount > 1000')
|
.svg-icon.shield(v-html="icons.goldGuildBadgeIcon", v-if='group.memberCount > 1000')
|
||||||
.svg-icon.shield(v-html="icons.silverGuildBadgeIcon", v-if='group.memberCount > 100 && group.memberCount < 999')
|
.svg-icon.shield(v-html="icons.silverGuildBadgeIcon", v-if='group.memberCount > 100 && group.memberCount < 999')
|
||||||
.svg-icon.shield(v-html="icons.bronzeGuildBadgeIcon", v-if='group.memberCount < 100')
|
.svg-icon.shield(v-html="icons.bronzeGuildBadgeIcon", v-if='group.memberCount < 100')
|
||||||
span.number {{group.memberCount}}
|
span.number {{ group.memberCount | abbrNum }}
|
||||||
div(v-once) {{ $t('members') }}
|
div(v-once) {{ $t('members') }}
|
||||||
.col-4(v-if='!isParty')
|
.col-4(v-if='!isParty')
|
||||||
.item-with-icon
|
.item-with-icon
|
||||||
@@ -30,8 +30,11 @@
|
|||||||
.row.new-message-row
|
.row.new-message-row
|
||||||
textarea(:placeholder="!isParty ? $t('chatPlaceholder') : $t('partyChatPlaceholder')", v-model='newMessage', @keydown='updateCarretPosition')
|
textarea(:placeholder="!isParty ? $t('chatPlaceholder') : $t('partyChatPlaceholder')", v-model='newMessage', @keydown='updateCarretPosition')
|
||||||
autocomplete(:text='newMessage', v-on:select="selectedAutocomplete", :coords='coords', :chat='group.chat')
|
autocomplete(:text='newMessage', v-on:select="selectedAutocomplete", :coords='coords', :chat='group.chat')
|
||||||
button.btn.btn-secondary.send-chat.float-right(v-once, @click='sendMessage()') {{ $t('send') }}
|
button.btn.btn-secondary.send-chat.float-left(v-once, @click='sendMessage()') {{ $t('send') }}
|
||||||
button.btn.btn-secondary.float-left(v-once, @click='fetchRecentMessages()') {{ $t('fetchRecentMessages') }}
|
.row
|
||||||
|
.col-6
|
||||||
|
button.btn.btn-secondary.float-left.fetch(v-once, @click='fetchRecentMessages()') {{ $t('fetchRecentMessages') }}
|
||||||
|
button.btn.btn-secondary.float-left(v-once, @click='reverseChat()') {{ $t('reverseChat') }}
|
||||||
|
|
||||||
.row.community-guidelines(v-if='!communityGuidelinesAccepted')
|
.row.community-guidelines(v-if='!communityGuidelinesAccepted')
|
||||||
div.col-8(v-once, v-html="$t('communityGuidelinesIntro')")
|
div.col-8(v-once, v-html="$t('communityGuidelinesIntro')")
|
||||||
@@ -75,7 +78,7 @@
|
|||||||
.svg-icon(v-html="icons.questIcon")
|
.svg-icon(v-html="icons.questIcon")
|
||||||
h4(v-once) {{ $t('youAreNotOnQuest') }}
|
h4(v-once) {{ $t('youAreNotOnQuest') }}
|
||||||
p(v-once) {{ $t('questDescription') }}
|
p(v-once) {{ $t('questDescription') }}
|
||||||
button.btn.btn-secondary(v-once, @click="openStartQuestModal()") {{ $t('startAQuest') }}
|
button.btn.btn-secondary(v-once, @click="openStartQuestModal()", v-if='isLeader') {{ $t('startAQuest') }}
|
||||||
.row.quest-active-section(v-if='isParty && onPendingQuest && !onActiveQuest')
|
.row.quest-active-section(v-if='isParty && onPendingQuest && !onActiveQuest')
|
||||||
h2 Pending quest
|
h2 Pending quest
|
||||||
button.btn.btn-secondary(v-once, @click="questForceStart()") {{ $t('begin') }}
|
button.btn.btn-secondary(v-once, @click="questForceStart()") {{ $t('begin') }}
|
||||||
@@ -110,7 +113,7 @@
|
|||||||
| {{parseFloat(group.quest.progress.hp).toFixed(2)}} / {{parseFloat(questData.boss.hp).toFixed(2)}}
|
| {{parseFloat(group.quest.progress.hp).toFixed(2)}} / {{parseFloat(questData.boss.hp).toFixed(2)}}
|
||||||
.col-6
|
.col-6
|
||||||
// @TODO: Why do we not sync quset progress on the group doc? Each user could have different progress
|
// @TODO: Why do we not sync quset progress on the group doc? Each user could have different progress
|
||||||
span.float-right {{user.party.quest.progress.up || 0}} pending damage
|
span.float-right {{parseFloat(user.party.quest.progress.up).toFixed(1) || 0}} pending damage
|
||||||
.row.rage-bar-row(v-if='questData.boss.rage')
|
.row.rage-bar-row(v-if='questData.boss.rage')
|
||||||
.col-12
|
.col-12
|
||||||
.grey-progress-bar
|
.grey-progress-bar
|
||||||
@@ -119,9 +122,9 @@
|
|||||||
.col-6
|
.col-6
|
||||||
span.float-left
|
span.float-left
|
||||||
| Rage {{questData.boss.rage.value}}
|
| Rage {{questData.boss.rage.value}}
|
||||||
button.btn.btn-secondary(v-once, @click="questAbort()") {{ $t('abort') }}
|
button.btn.btn-secondary(v-once, @click="questAbort()", v-if='isLeader') {{ $t('abort') }}
|
||||||
|
|
||||||
.section-header
|
.section-header(v-if='!isParty')
|
||||||
.row
|
.row
|
||||||
.col-10
|
.col-10
|
||||||
h3(v-once) {{ $t('guildSummary') }}
|
h3(v-once) {{ $t('guildSummary') }}
|
||||||
@@ -164,7 +167,7 @@
|
|||||||
.section(v-if="sections.challenges")
|
.section(v-if="sections.challenges")
|
||||||
group-challenges(:groupId='searchId')
|
group-challenges(:groupId='searchId')
|
||||||
div.text-center
|
div.text-center
|
||||||
button.btn.btn-primary(class='btn-danger', v-if='isMember', @click='clickLeave()') {{ $t('leave') }}
|
button.btn.btn-danger(v-if='isMember', @click='clickLeave()') {{ $t('leave') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -174,6 +177,10 @@
|
|||||||
color: $purple-200;
|
color: $purple-200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.leader:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.button-container {
|
.button-container {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
|
||||||
@@ -294,7 +301,7 @@
|
|||||||
z-index: 10;
|
z-index: 10;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 1em;
|
right: 1em;
|
||||||
bottom: 3em;
|
bottom: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,7 +418,7 @@
|
|||||||
.collect-progress-bar {
|
.collect-progress-bar {
|
||||||
background-color: #24cc8f;
|
background-color: #24cc8f;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hr {
|
.hr {
|
||||||
@@ -649,6 +656,11 @@ export default {
|
|||||||
document.body.removeChild(div);
|
document.body.removeChild(div);
|
||||||
},
|
},
|
||||||
updateCarretPosition (eventUpdate) {
|
updateCarretPosition (eventUpdate) {
|
||||||
|
if (eventUpdate.metaKey && eventUpdate.keyCode === 13) {
|
||||||
|
this.sendMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let text = eventUpdate.target;
|
let text = eventUpdate.target;
|
||||||
this.getCoord(eventUpdate, text);
|
this.getCoord(eventUpdate, text);
|
||||||
},
|
},
|
||||||
@@ -661,6 +673,8 @@ export default {
|
|||||||
this.$root.$emit('show::modal', 'members-modal');
|
this.$root.$emit('show::modal', 'members-modal');
|
||||||
},
|
},
|
||||||
async sendMessage () {
|
async sendMessage () {
|
||||||
|
if (!this.newMessage) return;
|
||||||
|
|
||||||
let response = await this.$store.dispatch('chat:postChat', {
|
let response = await this.$store.dispatch('chat:postChat', {
|
||||||
group: this.group,
|
group: this.group,
|
||||||
message: this.newMessage,
|
message: this.newMessage,
|
||||||
@@ -685,6 +699,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let group = await this.$store.dispatch('guilds:getGroup', {groupId: this.searchId});
|
let group = await this.$store.dispatch('guilds:getGroup', {groupId: this.searchId});
|
||||||
|
|
||||||
if (this.isParty) {
|
if (this.isParty) {
|
||||||
this.$store.state.party.data = group;
|
this.$store.state.party.data = group;
|
||||||
this.group = this.$store.state.party.data;
|
this.group = this.$store.state.party.data;
|
||||||
@@ -749,14 +764,10 @@ export default {
|
|||||||
if (this.isParty) {
|
if (this.isParty) {
|
||||||
data.type = 'party';
|
data.type = 'party';
|
||||||
Analytics.updateUser({partySize: null, partyID: null});
|
Analytics.updateUser({partySize: null, partyID: null});
|
||||||
|
this.$store.state.party.members = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.$store.dispatch('guilds:leave', data);
|
await this.$store.dispatch('guilds:leave', data);
|
||||||
|
|
||||||
// @TODO: Implement
|
|
||||||
// User.sync().then(function () {
|
|
||||||
// $rootScope.hardRedirect('/party');
|
|
||||||
// });
|
|
||||||
},
|
},
|
||||||
upgradeGroup () {
|
upgradeGroup () {
|
||||||
this.$store.state.upgradingGroup = this.group;
|
this.$store.state.upgradingGroup = this.group;
|
||||||
@@ -794,6 +805,12 @@ export default {
|
|||||||
}
|
}
|
||||||
// $rootScope.$state.go('options.inventory.quests');
|
// $rootScope.$state.go('options.inventory.quests');
|
||||||
},
|
},
|
||||||
|
async showMemberProfile (leader) {
|
||||||
|
let heroDetails = await this.$store.dispatch('members:fetchMember', { memberId: leader._id });
|
||||||
|
this.$store.state.profileUser = heroDetails.data.data;
|
||||||
|
this.$store.state.profileOptions.startingPage = 'profile';
|
||||||
|
this.$root.$emit('show::modal', 'profile');
|
||||||
|
},
|
||||||
async questCancel () {
|
async questCancel () {
|
||||||
if (!confirm(this.$t('sureCancel'))) return;
|
if (!confirm(this.$t('sureCancel'))) return;
|
||||||
let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/cancel'});
|
let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/cancel'});
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ export default {
|
|||||||
async submit () {
|
async submit () {
|
||||||
if (this.$store.state.user.data.balance < 1 && !this.workingGroup.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(this.$t('notEnoughGems'));
|
||||||
return;
|
return;
|
||||||
// @TODO return $rootScope.openModal('buyGems', {track:"Gems > Gems > Create Group"});
|
// @TODO return $rootScope.openModal('buyGems', {track:"Gems > Gems > Create Group"});
|
||||||
// @TODO when modal is implemented, enable analytics
|
// @TODO when modal is implemented, enable analytics
|
||||||
@@ -385,27 +385,16 @@ export default {
|
|||||||
}); */
|
}); */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.workingGroup.name || !this.workingGroup.description) {
|
let errors = [];
|
||||||
// @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');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.workingGroup.summary) {
|
if (!this.workingGroup.name) errors.push(this.$t('nameRequired'));
|
||||||
// @TODO: Add proper notifications. Summary is mandatory for only public guilds (not tavern, private guilds, parties)
|
if (!this.workingGroup.summary) errors.push(this.$t('summaryRequired'));
|
||||||
alert('Enter a summary');
|
if (this.workingGroup.summary.length > MAX_SUMMARY_SIZE_FOR_GUILDS) errors.push(this.$t('summaryTooLong'));
|
||||||
return;
|
if (!this.workingGroup.description) errors.push(this.$t('descriptionRequired'));
|
||||||
}
|
if (!this.isParty && (!this.workingGroup.categories || this.workingGroup.categories.length === 0)) errors.push(this.$t('categoiresRequired'));
|
||||||
|
|
||||||
if (this.workingGroup.summary.length > MAX_SUMMARY_SIZE_FOR_GUILDS) {
|
if (errors.length > 0) {
|
||||||
// @TODO: Add proper notifications. Summary is mandatory for only public guilds (not tavern, private guilds, parties)
|
alert(errors.join('\n'));
|
||||||
alert('Summary is too long');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.workingGroup.categories || this.workingGroup.categories.length === 0) {
|
|
||||||
// @TODO: Add proper notifications
|
|
||||||
alert('One or more categories must be selected');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ b-modal#invite-modal(:title="$t('inviteFriends')", size='lg')
|
|||||||
input.form-control(type='text', v-model='user.uuid')
|
input.form-control(type='text', v-model='user.uuid')
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
button.btn.btn-xs.pull-right(@click='addUuid()')
|
button.btn.btn-primary.pull-right(@click='addUuid()')
|
||||||
i.glyphicon.glyphicon-plus
|
i.glyphicon.glyphicon-plus
|
||||||
| +
|
| +
|
||||||
tr
|
tr
|
||||||
@@ -36,7 +36,7 @@ b-modal#invite-modal(:title="$t('inviteFriends')", size='lg')
|
|||||||
input.form-control(type='email', v-model='email.email')
|
input.form-control(type='email', v-model='email.email')
|
||||||
tr
|
tr
|
||||||
td(colspan=2)
|
td(colspan=2)
|
||||||
a.btn.btn-xs.pull-right(@click='addEmail()')
|
button.btn.btn-primary.pull-right(@click='addEmail()')
|
||||||
i.glyphicon.glyphicon-plus
|
i.glyphicon.glyphicon-plus
|
||||||
| +
|
| +
|
||||||
tr
|
tr
|
||||||
@@ -132,6 +132,9 @@ export default {
|
|||||||
|
|
||||||
this.text(this.$t(invitationString));
|
this.text(this.$t(invitationString));
|
||||||
|
|
||||||
|
this.invitees = [];
|
||||||
|
this.emails = [];
|
||||||
|
|
||||||
// @TODO: This function didn't make it over this.resetInvitees();
|
// @TODO: This function didn't make it over this.resetInvitees();
|
||||||
|
|
||||||
// @TODO: Sync group invites?
|
// @TODO: Sync group invites?
|
||||||
@@ -140,7 +143,7 @@ export default {
|
|||||||
// } else {
|
// } else {
|
||||||
// this.$router.push(`/groups/guilds/${this.group._id}`);
|
// this.$router.push(`/groups/guilds/${this.group._id}`);
|
||||||
// }
|
// }
|
||||||
this.$root.$emit('hide:modal', 'invite-modal');
|
this.$root.$emit('hide::modal', 'invite-modal');
|
||||||
// @TODO: error?
|
// @TODO: error?
|
||||||
// _resetInvitees();
|
// _resetInvitees();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
// @TODO: Move this to a member directory
|
// @TODO: Move this to a member directory
|
||||||
div
|
div
|
||||||
b-modal#members-modal(:title="$t('createGuild')", size='md')
|
remove-member-modal(:member-to-remove='memberToRemove', :group-id='this.groupId' @member-removed='memberRemoved')
|
||||||
|
b-modal#members-modal(:title="$t('createGuild')", size='md', :hide-footer='true')
|
||||||
.header-wrap(slot="modal-header")
|
.header-wrap(slot="modal-header")
|
||||||
.row
|
.row
|
||||||
.col-6
|
.col-6
|
||||||
@@ -16,36 +17,47 @@ div
|
|||||||
span.dropdown-label {{ $t('sortBy') }}
|
span.dropdown-label {{ $t('sortBy') }}
|
||||||
b-dropdown(:text="$t('sort')", right=true)
|
b-dropdown(:text="$t('sort')", right=true)
|
||||||
b-dropdown-item(v-for='sortOption in sortOptions', @click='sort(sortOption.value)', :key='sortOption.value') {{sortOption.text}}
|
b-dropdown-item(v-for='sortOption in sortOptions', @click='sort(sortOption.value)', :key='sortOption.value') {{sortOption.text}}
|
||||||
.row(v-for='member in sortedMembers')
|
.row(v-if='invites.length > 0')
|
||||||
.col-11.no-padding-left
|
.col-6.offset-3.nav
|
||||||
member-details(:member='member')
|
.nav-item(@click='viewMembers()', :class="{active: selectedPage === 'members'}") {{ $t('members') }}
|
||||||
.col-1.actions
|
.nav-item(@click='viewInvites()', :class="{active: selectedPage === 'invites'}") {{ $t('invites') }}
|
||||||
b-dropdown(right=true)
|
div(v-if='selectedPage === "members"')
|
||||||
.svg-icon.inline.dots(slot='button-content', v-html="icons.dots")
|
.row(v-for='(member, index) in sortedMembers')
|
||||||
b-dropdown-item(@click='sort(option.value)', v-if='isLeader')
|
.col-11.no-padding-left
|
||||||
span.dropdown-icon-item
|
member-details(:member='member')
|
||||||
.svg-icon.inline(v-html="icons.removeIcon", v-if='isLeader')
|
.col-1.actions
|
||||||
span.text {{$t('removeMember')}}
|
b-dropdown(right=true)
|
||||||
b-dropdown-item(@click='sendMessage(member._id)')
|
.svg-icon.inline.dots(slot='button-content', v-html="icons.dots")
|
||||||
span.dropdown-icon-item
|
b-dropdown-item(@click='removeMember(member, index)', v-if='isLeader')
|
||||||
.svg-icon.inline(v-html="icons.messageIcon")
|
span.dropdown-icon-item
|
||||||
span.text {{$t('sendMessage')}}
|
.svg-icon.inline(v-html="icons.removeIcon", v-if='isLeader')
|
||||||
b-dropdown-item(@click='sort(option.value)', v-if='isLeader')
|
span.text {{$t('removeMember')}}
|
||||||
span.dropdown-icon-item
|
b-dropdown-item(@click='sendMessage(member._id)')
|
||||||
.svg-icon.inline(v-html="icons.starIcon")
|
span.dropdown-icon-item
|
||||||
span.text {{$t('promoteToLeader')}}
|
.svg-icon.inline(v-html="icons.messageIcon")
|
||||||
b-dropdown-item(@click='sort(option.value)', v-if='isLeader && groupIsSubscribed')
|
span.text {{$t('sendMessage')}}
|
||||||
span.dropdown-icon-item
|
b-dropdown-item(@click='sort(option.value)', v-if='isLeader')
|
||||||
.svg-icon.inline(v-html="icons.starIcon")
|
span.dropdown-icon-item
|
||||||
span.text {{$t('addManager')}}
|
.svg-icon.inline(v-html="icons.starIcon")
|
||||||
b-dropdown-item(@click='sort(option.value)', v-if='isLeader && groupIsSubscribed')
|
span.text {{$t('promoteToLeader')}}
|
||||||
span.dropdown-icon-item
|
b-dropdown-item(@click='sort(option.value)', v-if='isLeader && groupIsSubscribed')
|
||||||
.svg-icon.inline(v-html="icons.removeIcon")
|
span.dropdown-icon-item
|
||||||
span.text {{$t('removeManager2')}}
|
.svg-icon.inline(v-html="icons.starIcon")
|
||||||
.row(v-if='groupId === "challenge"')
|
span.text {{$t('addManager')}}
|
||||||
.col-12.text-center
|
b-dropdown-item(@click='sort(option.value)', v-if='isLeader && groupIsSubscribed')
|
||||||
button.btn.btn-secondary(@click='loadMoreMembers()') {{ $t('loadMore') }}
|
span.dropdown-icon-item
|
||||||
.row.gradient(v-if='members.length > 3')
|
.svg-icon.inline(v-html="icons.removeIcon")
|
||||||
|
span.text {{$t('removeManager2')}}
|
||||||
|
.row(v-if='groupId === "challenge"')
|
||||||
|
.col-12.text-center
|
||||||
|
button.btn.btn-secondary(@click='loadMoreMembers()') {{ $t('loadMore') }}
|
||||||
|
.row.gradient(v-if='members.length > 3')
|
||||||
|
div(v-if='selectedPage === "invites"')
|
||||||
|
.row(v-for='member in invites')
|
||||||
|
.col-11.no-padding-left
|
||||||
|
member-details(:member='member')
|
||||||
|
.modal-footer
|
||||||
|
button.btn.btn-primary(@click='close()') {{ $t('close') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang='scss'>
|
<style lang='scss'>
|
||||||
@@ -130,10 +142,29 @@ div
|
|||||||
.dropdown-icon-item .svg-icon {
|
.dropdown-icon-item .svg-icon {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: .5em;
|
||||||
|
margin-top: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: .5em;
|
||||||
|
color: #878190;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item:hover, .nav-item.active {
|
||||||
|
color: #4f2a93;
|
||||||
|
border-bottom: 2px solid #4f2a93;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// @TODO: Move this under members directory
|
|
||||||
import sortBy from 'lodash/sortBy';
|
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';
|
||||||
@@ -141,6 +172,7 @@ import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
|
|||||||
import { mapState } from 'client/libs/store';
|
import { mapState } from 'client/libs/store';
|
||||||
|
|
||||||
import privateMessageModal from 'client/components/private-message-modal';
|
import privateMessageModal from 'client/components/private-message-modal';
|
||||||
|
import removeMemberModal from 'client/components/members/removeMemberModal';
|
||||||
import MemberDetails from '../memberDetails';
|
import MemberDetails from '../memberDetails';
|
||||||
import removeIcon from 'assets/members/remove.svg';
|
import removeIcon from 'assets/members/remove.svg';
|
||||||
import messageIcon from 'assets/members/message.svg';
|
import messageIcon from 'assets/members/message.svg';
|
||||||
@@ -155,12 +187,15 @@ export default {
|
|||||||
bDropdownItem,
|
bDropdownItem,
|
||||||
MemberDetails,
|
MemberDetails,
|
||||||
privateMessageModal,
|
privateMessageModal,
|
||||||
|
removeMemberModal,
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
sortOption: '',
|
sortOption: '',
|
||||||
|
selectedPage: 'members',
|
||||||
members: [],
|
members: [],
|
||||||
memberToRemove: '',
|
invites: [],
|
||||||
|
memberToRemove: {},
|
||||||
sortOptions: [
|
sortOptions: [
|
||||||
{
|
{
|
||||||
value: 'level',
|
value: 'level',
|
||||||
@@ -212,6 +247,13 @@ export default {
|
|||||||
},
|
},
|
||||||
sortedMembers () {
|
sortedMembers () {
|
||||||
let sortedMembers = this.members;
|
let sortedMembers = this.members;
|
||||||
|
|
||||||
|
if (this.searchTerm) {
|
||||||
|
sortedMembers = sortedMembers.filter(member => {
|
||||||
|
return member.profile.name.toLowerCase().indexOf(this.searchTerm.toLowerCase) !== -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.sortOption) return sortedMembers;
|
if (!this.sortOption) return sortedMembers;
|
||||||
|
|
||||||
sortedMembers = sortBy(this.members, [(member) => {
|
sortedMembers = sortBy(this.members, [(member) => {
|
||||||
@@ -227,7 +269,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
return this.members;
|
return sortedMembers;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -252,6 +294,12 @@ export default {
|
|||||||
includeAllPublicFields: true,
|
includeAllPublicFields: true,
|
||||||
});
|
});
|
||||||
this.members = members;
|
this.members = members;
|
||||||
|
|
||||||
|
let invites = await this.$store.dispatch('members:getGroupInvites', {
|
||||||
|
groupId,
|
||||||
|
includeAllPublicFields: true,
|
||||||
|
});
|
||||||
|
this.invites = invites;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.$store.state.memberModalOptions.viewingMembers.length > 0) {
|
if (this.$store.state.memberModalOptions.viewingMembers.length > 0) {
|
||||||
@@ -277,24 +325,15 @@ export default {
|
|||||||
|
|
||||||
this.$root.$emit('show::modal', 'members-modal');
|
this.$root.$emit('show::modal', 'members-modal');
|
||||||
},
|
},
|
||||||
async removeMember (member) {
|
async removeMember (member, index) {
|
||||||
this.memberToRemove = member;
|
this.memberToRemove = member;
|
||||||
|
this.memberToRemove.index = index;
|
||||||
this.$root.$emit('show::modal', 'remove-member');
|
this.$root.$emit('show::modal', 'remove-member');
|
||||||
},
|
},
|
||||||
async confirmRemoveMember (confirmation) {
|
memberRemoved () {
|
||||||
if (!confirmation) {
|
this.members.splice(this.memberToRemove.index, 1);
|
||||||
this.memberToRemove = '';
|
this.group.memberCount -= 1;
|
||||||
return;
|
this.memberToRemove = {};
|
||||||
}
|
|
||||||
|
|
||||||
await this.$store.dispatch('members:removeMember', {
|
|
||||||
memberId: this.memberToRemove._id,
|
|
||||||
groupId: this.group._id,
|
|
||||||
message: this.removeMessage,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.memberToRemove = '';
|
|
||||||
this.removeMessage = '';
|
|
||||||
},
|
},
|
||||||
async quickReply (uid) {
|
async quickReply (uid) {
|
||||||
this.memberToReply = uid;
|
this.memberToReply = uid;
|
||||||
@@ -330,6 +369,12 @@ export default {
|
|||||||
|
|
||||||
this.members = this.members.concat(newMembers);
|
this.members = this.members.concat(newMembers);
|
||||||
},
|
},
|
||||||
|
viewMembers () {
|
||||||
|
this.selectedPage = 'members';
|
||||||
|
},
|
||||||
|
viewInvites () {
|
||||||
|
this.selectedPage = 'invites';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ router-link.card-link(:to="{ name: 'guild', params: { groupId: guild._id } }")
|
|||||||
.card-block
|
.card-block
|
||||||
.row
|
.row
|
||||||
.col-md-2.badge-column
|
.col-md-2.badge-column
|
||||||
.shield-wrap
|
.shield-wrap(:class="{gold: guild.memberCount > 1000, silver: guild.memberCount > 100 && guild.memberCount < 999}")
|
||||||
.svg-icon.shield(v-html="icons.goldGuildBadge", v-if='guild.memberCount > 1000')
|
.svg-icon.shield(v-html="icons.goldGuildBadge", v-if='guild.memberCount > 1000')
|
||||||
.svg-icon.shield(v-html="icons.silverGuildBadgeIcon", v-if='guild.memberCount > 100 && guild.memberCount < 999')
|
.svg-icon.shield(v-html="icons.silverGuildBadgeIcon", v-if='guild.memberCount > 100 && guild.memberCount < 999')
|
||||||
.svg-icon.shield(v-html="icons.bronzeGuildBadgeIcon", v-if='guild.memberCount < 100')
|
.svg-icon.shield(v-html="icons.bronzeGuildBadgeIcon", v-if='guild.memberCount < 100')
|
||||||
.member-count {{guild.memberCount}}
|
.member-count {{ guild.memberCount | abbrNum }}
|
||||||
.col-md-10
|
.col-md-10
|
||||||
.row
|
.row
|
||||||
.col-md-8
|
.col-md-8
|
||||||
@@ -76,6 +76,14 @@ router-link.card-link(:to="{ name: 'guild', params: { groupId: guild._id } }")
|
|||||||
width: 70px;
|
width: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gold {
|
||||||
|
color: #fdbb5a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.silver {
|
||||||
|
color: #c2c2c2;
|
||||||
|
}
|
||||||
|
|
||||||
.badge-column {
|
.badge-column {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
div(v-if='questData')
|
div(v-if='questData')
|
||||||
questDialogContent(:item="questData")
|
questDialogContent(:item="questData")
|
||||||
div.text-center
|
div.text-center
|
||||||
button.btn.btn-primary(@click='questInit()', :disabled="!Boolean(selectedQuest)") {{$t('inviteToPartyOrQuest')}}
|
button.btn.btn-primary(@click='questInit()', :disabled="!Boolean(selectedQuest) || loading") {{$t('inviteToPartyOrQuest')}}
|
||||||
div.text-center
|
div.text-center
|
||||||
p {{$t('inviteInformation')}}
|
p {{$t('inviteInformation')}}
|
||||||
.side-panel(v-if='questData')
|
.side-panel(v-if='questData')
|
||||||
@@ -122,6 +122,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
loading: false,
|
||||||
selectedQuest: {},
|
selectedQuest: {},
|
||||||
icons: Object.freeze({
|
icons: Object.freeze({
|
||||||
copy: copyIcon,
|
copy: copyIcon,
|
||||||
@@ -157,6 +158,8 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async questInit () {
|
async questInit () {
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
Analytics.updateUser({
|
Analytics.updateUser({
|
||||||
partyID: this.group._id,
|
partyID: this.group._id,
|
||||||
partySize: this.group.memberCount,
|
partySize: this.group.memberCount,
|
||||||
@@ -170,6 +173,8 @@ export default {
|
|||||||
|
|
||||||
if (this.$store.state.party.data) this.$store.state.party.data.quest = quest;
|
if (this.$store.state.party.data) this.$store.state.party.data.quest = quest;
|
||||||
|
|
||||||
|
this.loading = false;
|
||||||
|
|
||||||
this.$root.$emit('hide::modal', 'start-quest-modal');
|
this.$root.$emit('hide::modal', 'start-quest-modal');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,8 +12,13 @@
|
|||||||
.row
|
.row
|
||||||
textarea(:placeholder="$t('tavernCommunityGuidelinesPlaceholder')", v-model='newMessage', :class='{"user-entry": newMessage}', @keydown='updateCarretPosition')
|
textarea(:placeholder="$t('tavernCommunityGuidelinesPlaceholder')", v-model='newMessage', :class='{"user-entry": newMessage}', @keydown='updateCarretPosition')
|
||||||
autocomplete(:text='newMessage', v-on:select="selectedAutocomplete", :coords='coords', :chat='group.chat')
|
autocomplete(:text='newMessage', v-on:select="selectedAutocomplete", :coords='coords', :chat='group.chat')
|
||||||
button.btn.btn-secondary.send-chat.float-right(v-once, @click='sendMessage()') {{ $t('send') }}
|
|
||||||
button.btn.btn-secondary.float-left(v-once, @click='fetchRecentMessages()') {{ $t('fetchRecentMessages') }}
|
.row
|
||||||
|
.col-6
|
||||||
|
button.btn.btn-secondary.send-chat.float-left(v-once, @click='sendMessage()') {{ $t('send') }}
|
||||||
|
.col-6
|
||||||
|
button.btn.btn-secondary.float-right.fetch(v-once, @click='fetchRecentMessages()') {{ $t('fetchRecentMessages') }}
|
||||||
|
button.btn.btn-secondary.float-right(v-once, @click='reverseChat()') {{ $t('reverseChat') }}
|
||||||
|
|
||||||
.row.community-guidelines(v-if='!communityGuidelinesAccepted')
|
.row.community-guidelines(v-if='!communityGuidelinesAccepted')
|
||||||
div.col-8(v-once, v-html="$t('communityGuidelinesIntro')")
|
div.col-8(v-once, v-html="$t('communityGuidelinesIntro')")
|
||||||
@@ -523,6 +528,11 @@ export default {
|
|||||||
document.body.removeChild(div);
|
document.body.removeChild(div);
|
||||||
},
|
},
|
||||||
updateCarretPosition (eventUpdate) {
|
updateCarretPosition (eventUpdate) {
|
||||||
|
if (eventUpdate.metaKey && eventUpdate.keyCode === 13) {
|
||||||
|
this.sendMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let text = eventUpdate.target;
|
let text = eventUpdate.target;
|
||||||
this.getCoord(eventUpdate, text);
|
this.getCoord(eventUpdate, text);
|
||||||
},
|
},
|
||||||
@@ -551,6 +561,9 @@ export default {
|
|||||||
async fetchRecentMessages () {
|
async fetchRecentMessages () {
|
||||||
this.group = await this.$store.dispatch('guilds:getGroup', {groupId: TAVERN_ID});
|
this.group = await this.$store.dispatch('guilds:getGroup', {groupId: TAVERN_ID});
|
||||||
},
|
},
|
||||||
|
reverseChat () {
|
||||||
|
this.group.chat.reverse();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -186,8 +186,9 @@ export default {
|
|||||||
window.scrollTo(0, 200);
|
window.scrollTo(0, 200);
|
||||||
this.loadHero(id, index);
|
this.loadHero(id, index);
|
||||||
},
|
},
|
||||||
clickMember (hero) {
|
async clickMember (hero) {
|
||||||
this.$store.state.profileUser = hero;
|
let heroDetails = await this.$store.dispatch('members:fetchMember', { memberId: hero._id });
|
||||||
|
this.$store.state.profileUser = heroDetails.data.data;
|
||||||
this.$store.state.profileOptions.startingPage = 'profile';
|
this.$store.state.profileOptions.startingPage = 'profile';
|
||||||
this.$root.$emit('show::modal', 'profile');
|
this.$root.$emit('show::modal', 'profile');
|
||||||
},
|
},
|
||||||
|
|||||||
53
website/client/components/members/removeMemberModal.vue
Normal file
53
website/client/components/members/removeMemberModal.vue
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
b-modal#remove-member(:title="$t('removeMember')", size='md', :hide-footer="true")
|
||||||
|
.text-center
|
||||||
|
h2.col-12 {{ $t('sureKick') }}
|
||||||
|
.col-12.removing-member(v-if='memberToRemove.profile') {{memberToRemove.profile.name}}
|
||||||
|
.modal-body
|
||||||
|
textarea.form-control(type='text',
|
||||||
|
rows='5',
|
||||||
|
:placeholder="$t('optionalMessage')",
|
||||||
|
v-model='removeMessage')
|
||||||
|
.modal-footer
|
||||||
|
button.pull-left.btn.btn-danger(@click='confirmRemoveMember()') {{ $t('yesRemove') }}
|
||||||
|
button.btn.btn-default(@click='close()') {{ $t('cancel') }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.removing-member {
|
||||||
|
color: #878190;
|
||||||
|
margin-bottom: .5em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['memberToRemove', 'groupId'],
|
||||||
|
components: {
|
||||||
|
bModal,
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
removeMessage: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async confirmRemoveMember () {
|
||||||
|
await this.$store.dispatch('members:removeMember', {
|
||||||
|
memberId: this.memberToRemove._id,
|
||||||
|
groupId: this.groupId,
|
||||||
|
message: this.removeMessage,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.removeMessage = '';
|
||||||
|
this.$emit('member-removed', this.memberToRemove);
|
||||||
|
this.close();
|
||||||
|
},
|
||||||
|
close () {
|
||||||
|
this.$root.$emit('hide::modal', 'remove-member');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -34,7 +34,8 @@
|
|||||||
.form-horizontal(v-if='user.flags.classSelected && !user.preferences.disableClasses')
|
.form-horizontal(v-if='user.flags.classSelected && !user.preferences.disableClasses')
|
||||||
h5 {{ $t('characterBuild') }}
|
h5 {{ $t('characterBuild') }}
|
||||||
h6(v-once) {{ $t('class') + ': ' }}
|
h6(v-once) {{ $t('class') + ': ' }}
|
||||||
span {{ classText }}
|
// @TODO: what is classText
|
||||||
|
span(v-if='classText') {{ classText }}
|
||||||
button.btn.btn-danger.btn-xs(@click='changeClass(null)', v-once) {{ $t('changeClass') }}
|
button.btn.btn-danger.btn-xs(@click='changeClass(null)', v-once) {{ $t('changeClass') }}
|
||||||
small.cost 3
|
small.cost 3
|
||||||
span.Pet_Currency_Gem1x.inline-gems
|
span.Pet_Currency_Gem1x.inline-gems
|
||||||
@@ -117,21 +118,20 @@
|
|||||||
button.btn.btn-primary(v-if='!user.auth[network.key].id', @click='socialLogin(network.key, user)') {{ $t('registerWithSocial', {network: network.name}) }}
|
button.btn.btn-primary(v-if='!user.auth[network.key].id', @click='socialLogin(network.key, user)') {{ $t('registerWithSocial', {network: network.name}) }}
|
||||||
button.btn.btn-primary(disabled='disabled', v-if='!hasBackupAuthOption(network.key) && user.auth[network.key].id') {{ $t('registeredWithSocial', {network: network.name}) }}
|
button.btn.btn-primary(disabled='disabled', v-if='!hasBackupAuthOption(network.key) && user.auth[network.key].id') {{ $t('registeredWithSocial', {network: network.name}) }}
|
||||||
button.btn.btn-danger(@click='deleteSocialAuth(network.key)', v-if='hasBackupAuthOption(network.key) && user.auth[network.key].id') {{ $t('detachSocial', {network: network.name}) }}
|
button.btn.btn-danger(@click='deleteSocialAuth(network.key)', v-if='hasBackupAuthOption(network.key) && user.auth[network.key].id') {{ $t('detachSocial', {network: network.name}) }}
|
||||||
// hr
|
hr
|
||||||
// TODO
|
div(v-if='!user.auth.local.username')
|
||||||
// div(v-if='!user.auth.local.username')
|
|
||||||
p {{ $t('addLocalAuth') }}
|
p {{ $t('addLocalAuth') }}
|
||||||
form(ng-submit='http("post", "/api/v3/user/auth/local/register", localAuth, "addedLocalAuth")', name='localAuth', novalidate)
|
.form(name='localAuth', novalidate)
|
||||||
//-.alert.alert-danger(ng-messages='changeUsername.$error && changeUsername.submitted') {{ $t('fillAll') }}
|
//-.alert.alert-danger(ng-messages='changeUsername.$error && changeUsername.submitted') {{ $t('fillAll') }}
|
||||||
.form-group
|
.form-group
|
||||||
input.form-control(type='text', placeholder="$t('username')", v-model='localAuth.username', required)
|
input.form-control(type='text', :placeholder="$t('username')", v-model='localAuth.username', required)
|
||||||
.form-group
|
.form-group
|
||||||
input.form-control(type='text', placeholder="$t('email')", v-model='localAuth.email', required)
|
input.form-control(type='text', :placeholder="$t('email')", v-model='localAuth.email', required)
|
||||||
.form-group
|
.form-group
|
||||||
input.form-control(type='password', placeholder="$t('password')", v-model='localAuth.password', required)
|
input.form-control(type='password', :placeholder="$t('password')", v-model='localAuth.password', required)
|
||||||
.form-group
|
.form-group
|
||||||
input.form-control(type='password', placeholder="$t('confirmPass')", v-model='localAuth.confirmPassword', required)
|
input.form-control(type='password', :placeholder="$t('confirmPass')", v-model='localAuth.confirmPassword', required)
|
||||||
button.btn.btn-primary(type='submit', ng-disabled='localAuth.$invalid', value="$t('submit')")
|
button.btn.btn-primary(type='submit', @click='addLocalAuth()') {{ $t('submit') }}
|
||||||
|
|
||||||
.usersettings(v-if='user.auth.local.username')
|
.usersettings(v-if='user.auth.local.username')
|
||||||
p {{ $t('username') }}
|
p {{ $t('username') }}
|
||||||
@@ -231,6 +231,12 @@ export default {
|
|||||||
usernameUpdates: {},
|
usernameUpdates: {},
|
||||||
emailUpdates: {},
|
emailUpdates: {},
|
||||||
passwordUpdates: {},
|
passwordUpdates: {},
|
||||||
|
localAuth: {
|
||||||
|
username: '',
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
@@ -290,6 +296,7 @@ export default {
|
|||||||
// Guide.goto('intro', 0, true);
|
// Guide.goto('intro', 0, true);
|
||||||
},
|
},
|
||||||
showBailey () {
|
showBailey () {
|
||||||
|
this.user.flags.newStuff = true;
|
||||||
this.$root.$emit('show::modal', 'new-stuff');
|
this.$root.$emit('show::modal', 'new-stuff');
|
||||||
},
|
},
|
||||||
hasBackupAuthOption (networkKeyToCheck) {
|
hasBackupAuthOption (networkKeyToCheck) {
|
||||||
@@ -380,6 +387,9 @@ export default {
|
|||||||
alert(e.message);
|
alert(e.message);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
addLocalAuth () {
|
||||||
|
axios.post('/api/v3/user/auth/local/register', this.localAuth, 'addedLocalAuth');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -163,6 +163,16 @@ export default {
|
|||||||
}]);
|
}]);
|
||||||
},
|
},
|
||||||
purchasedPlanIdInfo () {
|
purchasedPlanIdInfo () {
|
||||||
|
if (!this.subscriptionBlocks[this.user.purchased.plan.planId]) {
|
||||||
|
// @TODO: find which subs are in the common
|
||||||
|
console.log(this.subscriptionBlocks[this.user.purchased.plan.planId]); // eslint-disable-line
|
||||||
|
return {
|
||||||
|
price: 0,
|
||||||
|
months: 0,
|
||||||
|
plan: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
price: this.subscriptionBlocks[this.user.purchased.plan.planId].price,
|
price: this.subscriptionBlocks[this.user.purchased.plan.planId].price,
|
||||||
months: this.subscriptionBlocks[this.user.purchased.plan.planId].months,
|
months: this.subscriptionBlocks[this.user.purchased.plan.planId].months,
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
nav.navbar.navbar-inverse.fixed-top.navbar-toggleable-sm
|
nav.navbar.navbar-inverse.fixed-top.navbar-toggleable-sm
|
||||||
.navbar-header
|
.navbar-header
|
||||||
router-link.nav-item(
|
router-link.nav-item(:to='!isUserLoggedIn ? "/static/home" : "/"')
|
||||||
to='/static/home',
|
|
||||||
)
|
|
||||||
.logo.svg-icon(v-html='icons.logo')
|
.logo.svg-icon(v-html='icons.logo')
|
||||||
.collapse.navbar-collapse
|
.collapse.navbar-collapse
|
||||||
ul.navbar-nav.mr-auto(v-if='$route.name !== "home"')
|
ul.navbar-nav.mr-auto(v-if='$route.name !== "home"')
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
.filters.d-flex.justify-content-end
|
.filters.d-flex.justify-content-end
|
||||||
.filter.small-text(
|
.filter.small-text(
|
||||||
v-for="filter in types[type].filters",
|
v-for="filter in types[type].filters",
|
||||||
:class="{active: activeFilter.label === filter.label}",
|
:class="{active: activeFilters[type].label === filter.label}",
|
||||||
@click="activateFilter(type, filter)",
|
@click="activateFilter(type, filter)",
|
||||||
) {{ $t(filter.label) }}
|
) {{ $t(filter.label) }}
|
||||||
.tasks-list(ref="taskList", v-sortable='', @onsort='sorted')
|
.tasks-list(ref="taskList", v-sortable='', @onsort='sorted')
|
||||||
@@ -226,9 +226,14 @@ export default {
|
|||||||
reward: rewardIcon,
|
reward: rewardIcon,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let activeFilters = {};
|
||||||
|
for (let type in types) {
|
||||||
|
activeFilters[type] = types[type].filters.find(f => f.default === true);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
types,
|
types,
|
||||||
activeFilter: types[this.type].filters.find(f => f.default === true),
|
activeFilters,
|
||||||
icons,
|
icons,
|
||||||
openedCompletedTodos: false,
|
openedCompletedTodos: false,
|
||||||
|
|
||||||
@@ -252,7 +257,7 @@ export default {
|
|||||||
return inAppRewards(this.user);
|
return inAppRewards(this.user);
|
||||||
},
|
},
|
||||||
hasRewardsList () {
|
hasRewardsList () {
|
||||||
return this.isUser === true && this.type === 'reward' && this.activeFilter.label !== 'custom';
|
return this.isUser === true && this.type === 'reward' && this.activeFilters[this.type].label !== 'custom';
|
||||||
},
|
},
|
||||||
initialColumnDescription () {
|
initialColumnDescription () {
|
||||||
// Show the column description in the middle only if there are no elements (tasks or in app items)
|
// Show the column description in the middle only if there are no elements (tasks or in app items)
|
||||||
@@ -262,6 +267,12 @@ export default {
|
|||||||
|
|
||||||
return this.tasks[`${this.type}s`].length === 0;
|
return this.tasks[`${this.type}s`].length === 0;
|
||||||
},
|
},
|
||||||
|
dailyDueDefaultView () {
|
||||||
|
if (this.user.preferences.dailyDueDefaultView) {
|
||||||
|
this.activateFilter('daily', this.types.daily.filters[1]);
|
||||||
|
}
|
||||||
|
return this.user.preferences.dailyDueDefaultView;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
taskList: {
|
taskList: {
|
||||||
@@ -270,6 +281,11 @@ export default {
|
|||||||
}, 250),
|
}, 250),
|
||||||
deep: true,
|
deep: true,
|
||||||
},
|
},
|
||||||
|
dailyDueDefaultView () {
|
||||||
|
if (this.user.preferences.dailyDueDefaultView) {
|
||||||
|
this.activateFilter('daily', this.types.daily.filters[1]);
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.setColumnBackgroundVisibility();
|
this.setColumnBackgroundVisibility();
|
||||||
@@ -301,7 +317,7 @@ export default {
|
|||||||
if (type === 'todo' && filter.label === 'complete2') {
|
if (type === 'todo' && filter.label === 'complete2') {
|
||||||
this.loadCompletedTodos();
|
this.loadCompletedTodos();
|
||||||
}
|
}
|
||||||
this.activeFilter = filter;
|
this.activeFilters[type] = filter;
|
||||||
},
|
},
|
||||||
setColumnBackgroundVisibility () {
|
setColumnBackgroundVisibility () {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
@@ -330,7 +346,7 @@ export default {
|
|||||||
},
|
},
|
||||||
filterTask (task) {
|
filterTask (task) {
|
||||||
// View
|
// View
|
||||||
if (!this.activeFilter.filter(task)) return false;
|
if (!this.activeFilters[task.type].filter(task)) return false;
|
||||||
|
|
||||||
// Tags
|
// Tags
|
||||||
const selectedTags = this.selectedTags;
|
const selectedTags = this.selectedTags;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
.svg-icon.envelope(v-html="icons.messageIcon")
|
.svg-icon.envelope(v-html="icons.messageIcon")
|
||||||
h4(v-once) Nothing Here Yet
|
h4(v-once) Nothing Here Yet
|
||||||
p(v-once) Select a conversation on the left
|
p(v-once) Select a conversation on the left
|
||||||
chat-message.container-fluid.message-scroll(:chat.sync='activeChat', :inbox='true', ref="chatscroll")
|
chat-message.message-scroll(:chat.sync='activeChat', :inbox='true', ref="chatscroll")
|
||||||
|
|
||||||
// @TODO: Implement new message header here when we fix the above
|
// @TODO: Implement new message header here when we fix the above
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ div
|
|||||||
member-details(:member="user")
|
member-details(:member="user")
|
||||||
.row
|
.row
|
||||||
.col-6.offset-3.text-center.nav
|
.col-6.offset-3.text-center.nav
|
||||||
.nav-item(@click='selectedPage = "profile"', :class="{active: selectedPage === 'profile'}") {{ $t('profile') }}
|
.nav-item(@click='selectPage("profile")', :class="{active: selectedPage === 'profile'}") {{ $t('profile') }}
|
||||||
.nav-item(@click='selectedPage = "stats"', :class="{active: selectedPage === 'stats'}") {{ $t('stats') }}
|
.nav-item(@click='selectPage("stats")', :class="{active: selectedPage === 'stats'}") {{ $t('stats') }}
|
||||||
.nav-item(@click='selectedPage = "achievements"', :class="{active: selectedPage === 'achievements'}") {{ $t('achievements') }}
|
.nav-item(@click='selectPage("achievements")', :class="{active: selectedPage === 'achievements'}") {{ $t('achievements') }}
|
||||||
#userProfile.standard-page(v-show='selectedPage === "profile"', v-if='user.profile')
|
#userProfile.standard-page(v-show='selectedPage === "profile"', v-if='user.profile')
|
||||||
.row
|
.row
|
||||||
.col-8
|
.col-8
|
||||||
@@ -94,9 +94,9 @@ div
|
|||||||
.row(v-for='(category, key) in achievements')
|
.row(v-for='(category, key) in achievements')
|
||||||
h2.col-12.text-center {{ $t(key+'Achievs') }}
|
h2.col-12.text-center {{ $t(key+'Achievs') }}
|
||||||
.col-3.text-center(v-for='(achievement, key) in category.achievements')
|
.col-3.text-center(v-for='(achievement, key) in category.achievements')
|
||||||
.box.achievement-container(:id='key', :class='{"achievement-unearned": !achievement.earned}')
|
.box.achievement-container(:id='key + "-achievement"', :class='{"achievement-unearned": !achievement.earned}')
|
||||||
b-popover(
|
b-popover(
|
||||||
:target="'#' + key",
|
:target="'#' + key + '-achievement'",
|
||||||
triggers="hover",
|
triggers="hover",
|
||||||
placement="top",
|
placement="top",
|
||||||
)
|
)
|
||||||
@@ -121,11 +121,11 @@ div
|
|||||||
span {{ value }}
|
span {{ value }}
|
||||||
#stats.standard-page(v-show='selectedPage === "stats"', v-if='user.preferences')
|
#stats.standard-page(v-show='selectedPage === "stats"', v-if='user.preferences')
|
||||||
.row
|
.row
|
||||||
.col-6 {{$t('equipment')}}
|
.col-6
|
||||||
h2.text-center
|
h2.text-center {{$t('equipment')}}
|
||||||
.well
|
.well
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
.box(:class='{white: equippedItems.eyewear}')
|
.box(:class='{white: equippedItems.eyewear && equippedItems.eyewear.indexOf("base_0") === -1}')
|
||||||
div(:class="`shop_${equippedItems.eyewear}`")
|
div(:class="`shop_${equippedItems.eyewear}`")
|
||||||
h3 {{$t('eyewear')}}
|
h3 {{$t('eyewear')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
@@ -133,11 +133,11 @@ div
|
|||||||
div(:class="`shop_${equippedItems.head}`")
|
div(:class="`shop_${equippedItems.head}`")
|
||||||
h3 {{$t('headGear')}}
|
h3 {{$t('headGear')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
.box(:class='{white: equippedItems.headAccessory}')
|
.box(:class='{white: equippedItems.headAccessory && equippedItems.headAccessory.indexOf("base_0") === -1}')
|
||||||
div(:class="`shop_${equippedItems.headAccessory}`")
|
div(:class="`shop_${equippedItems.headAccessory}`")
|
||||||
h3 {{$t('headAccess')}}
|
h3 {{$t('headAccess')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
.box(:class='{white: equippedItems.backAccessory}')
|
.box(:class='{white: equippedItems.backAccessory && equippedItems.backAccessory.indexOf("base_0") === -1}')
|
||||||
div(:class="`shop_${equippedItems.backAccessory}`")
|
div(:class="`shop_${equippedItems.backAccessory}`")
|
||||||
h3 {{$t('backAccess')}}
|
h3 {{$t('backAccess')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
@@ -145,7 +145,7 @@ div
|
|||||||
div(:class="`shop_${equippedItems.armor}`")
|
div(:class="`shop_${equippedItems.armor}`")
|
||||||
h3 {{$t('armor')}}
|
h3 {{$t('armor')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
.box(:class='{white: equippedItems.bodyAccessory}')
|
.box(:class='{white: equippedItems.bodyAccessory && equippedItems.bodyAccessory.indexOf("base_0") === -1}')
|
||||||
div(:class="`shop_${equippedItems.bodyAccessory}`")
|
div(:class="`shop_${equippedItems.bodyAccessory}`")
|
||||||
h3 {{$t('bodyAccess')}}
|
h3 {{$t('bodyAccess')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
@@ -161,7 +161,7 @@ div
|
|||||||
h2.text-center {{$t('costume')}}
|
h2.text-center {{$t('costume')}}
|
||||||
.well
|
.well
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
.box(:class='{white: costumeItems.eyewear}')
|
.box(:class='{white: costumeItems.eyewear && costumeItems.eyewear.indexOf("base_0") === -1}')
|
||||||
div(:class="`shop_${costumeItems.eyewear}`")
|
div(:class="`shop_${costumeItems.eyewear}`")
|
||||||
h3 {{$t('eyewear')}}
|
h3 {{$t('eyewear')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
@@ -169,11 +169,11 @@ div
|
|||||||
div(:class="`shop_${costumeItems.head}`")
|
div(:class="`shop_${costumeItems.head}`")
|
||||||
h3 {{$t('headGear')}}
|
h3 {{$t('headGear')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
.box(:class='{white: costumeItems.headAccessory}')
|
.box(:class='{white: costumeItems.headAccessory && costumeItems.headAccessory.indexOf("base_0") === -1}')
|
||||||
div(:class="`shop_${costumeItems.headAccessory}`")
|
div(:class="`shop_${costumeItems.headAccessory}`")
|
||||||
h3 {{$t('headAccess')}}
|
h3 {{$t('headAccess')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
.box(:class='{white: costumeItems.backAccessory}')
|
.box(:class='{white: costumeItems.backAccessory && costumeItems.backAccessory.indexOf("base_0") === -1}')
|
||||||
div(:class="`shop_${costumeItems.backAccessory}`")
|
div(:class="`shop_${costumeItems.backAccessory}`")
|
||||||
h3 {{$t('backAccess')}}
|
h3 {{$t('backAccess')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
@@ -181,7 +181,7 @@ div
|
|||||||
div(:class="`shop_${costumeItems.armor}`")
|
div(:class="`shop_${costumeItems.armor}`")
|
||||||
h3 {{$t('armor')}}
|
h3 {{$t('armor')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
.box(:class='{white: costumeItems.bodyAccessory}')
|
.box(:class='{white: costumeItems.bodyAccessory && costumeItems.bodyAccessory.indexOf("base_0") === -1}')
|
||||||
div(:class="`shop_${costumeItems.bodyAccessory}`")
|
div(:class="`shop_${costumeItems.bodyAccessory}`")
|
||||||
h3 {{$t('bodyAccess')}}
|
h3 {{$t('bodyAccess')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
@@ -189,8 +189,8 @@ div
|
|||||||
div(:class="`shop_${costumeItems.weapon}`")
|
div(:class="`shop_${costumeItems.weapon}`")
|
||||||
h3 {{$t('mainHand')}}
|
h3 {{$t('mainHand')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
.box(:class='{white: user.preferences.background}')
|
.box(:class='{white: user.preferences.background}', style="overflow:hidden")
|
||||||
div(:class="user.preferences.background")
|
div(:class="'background_' + user.preferences.background")
|
||||||
h3 {{$t('background')}}
|
h3 {{$t('background')}}
|
||||||
.col-4.item-wrapper
|
.col-4.item-wrapper
|
||||||
.box(:class='{white: costumeItems.shield && costumeItems.shield.indexOf("base_0") === -1}')
|
.box(:class='{white: costumeItems.shield && costumeItems.shield.indexOf("base_0") === -1}')
|
||||||
@@ -326,7 +326,7 @@ div
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pet, .mount {
|
.pet, .mount {
|
||||||
margin-top: -1.6em;
|
margin-top: -1.8em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
@@ -660,6 +660,7 @@ export default {
|
|||||||
|
|
||||||
this.editingProfile.name = user.profile.name;
|
this.editingProfile.name = user.profile.name;
|
||||||
this.editingProfile.imageUrl = user.profile.imageUrl;
|
this.editingProfile.imageUrl = user.profile.imageUrl;
|
||||||
|
this.editingProfile.blurb = user.profile.blurb;
|
||||||
|
|
||||||
if (!user.achievements.quests) user.achievements.quests = {};
|
if (!user.achievements.quests) user.achievements.quests = {};
|
||||||
if (!user.achievements.challenges) user.achievements.challenges = {};
|
if (!user.achievements.challenges) user.achievements.challenges = {};
|
||||||
@@ -700,6 +701,11 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
selectPage (page) {
|
||||||
|
this.selectedPage = page;
|
||||||
|
// @TODO: rename this property?
|
||||||
|
this.$store.state.profileOptions.startingPage = page;
|
||||||
|
},
|
||||||
sendMessage () {
|
sendMessage () {
|
||||||
this.$store.state.userIdToMessage = this.user._id;
|
this.$store.state.userIdToMessage = this.user._id;
|
||||||
this.$root.$emit('show::modal', 'private-message');
|
this.$root.$emit('show::modal', 'private-message');
|
||||||
|
|||||||
@@ -1,6 +1,32 @@
|
|||||||
import intersection from 'lodash/intersection';
|
import intersection from 'lodash/intersection';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
filters: {
|
||||||
|
// https://stackoverflow.com/questions/2685911/is-there-a-way-to-round-numbers-into-a-reader-friendly-format-e-g-1-1k
|
||||||
|
abbrNum: (number) => {
|
||||||
|
let decPlaces = 2;
|
||||||
|
decPlaces = Math.pow(10, decPlaces);
|
||||||
|
|
||||||
|
let abbrev = ['k', 'm', 'b', 't'];
|
||||||
|
for (let i = abbrev.length - 1; i >= 0; i--) {
|
||||||
|
let size = Math.pow(10, (i + 1) * 3);
|
||||||
|
|
||||||
|
if (size <= number) {
|
||||||
|
number = Math.round(number * decPlaces / size) / decPlaces;
|
||||||
|
|
||||||
|
if (number === 1000 && i < abbrev.length - 1) {
|
||||||
|
number = 1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
number += abbrev[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return number;
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isMemberOfGroup (user, group) {
|
isMemberOfGroup (user, group) {
|
||||||
if (group._id === this.$store.state.constants.TAVERN_ID) return true;
|
if (group._id === this.$store.state.constants.TAVERN_ID) return true;
|
||||||
|
|||||||
@@ -21,8 +21,11 @@ export async function fetchMember (store, payload) {
|
|||||||
|
|
||||||
export async function getGroupInvites (store, payload) {
|
export async function getGroupInvites (store, payload) {
|
||||||
let url = `${apiV3Prefix}/groups/${payload.groupId}/invites`;
|
let url = `${apiV3Prefix}/groups/${payload.groupId}/invites`;
|
||||||
|
if (payload.includeAllPublicFields) {
|
||||||
|
url += '?includeAllPublicFields=true';
|
||||||
|
}
|
||||||
let response = await axios.get(url);
|
let response = await axios.get(url);
|
||||||
return response;
|
return response.data.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getChallengeMembers (store, payload) {
|
export async function getChallengeMembers (store, payload) {
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ export default function () {
|
|||||||
challengeOptions: {
|
challengeOptions: {
|
||||||
cloning: false,
|
cloning: false,
|
||||||
tasksToClone: {},
|
tasksToClone: {},
|
||||||
|
workingChallenge: {},
|
||||||
},
|
},
|
||||||
editingGroup: {}, // @TODO move to local state
|
editingGroup: {}, // @TODO move to local state
|
||||||
// content data, frozen to prevent Vue from modifying it since it's static and never changes
|
// content data, frozen to prevent Vue from modifying it since it's static and never changes
|
||||||
|
|||||||
@@ -89,7 +89,7 @@
|
|||||||
"joinedChallenge": "Joined a Challenge",
|
"joinedChallenge": "Joined a Challenge",
|
||||||
"joinedChallengeText": "This user put themselves to the test by joining a Challenge!",
|
"joinedChallengeText": "This user put themselves to the test by joining a Challenge!",
|
||||||
"myChallenges": "My Challenges",
|
"myChallenges": "My Challenges",
|
||||||
"findChallenges": "Find Challenges",
|
"findChallenges": "Discover Challenges",
|
||||||
"noChallengeTitle": "You don't have any Challenges.",
|
"noChallengeTitle": "You don't have any Challenges.",
|
||||||
"challengeDescription1": "Challenges are community events in which players compete and earn prizes by completing a group of related tasks.",
|
"challengeDescription1": "Challenges are community events in which players compete and earn prizes by completing a group of related tasks.",
|
||||||
"challengeDescription2": "Find recommended Challenges based on your interests, browse Habitica's public Challenges, or create your own Challenges.",
|
"challengeDescription2": "Find recommended Challenges based on your interests, browse Habitica's public Challenges, or create your own Challenges.",
|
||||||
@@ -123,5 +123,6 @@
|
|||||||
"summaryTooLong": "Summary is too long",
|
"summaryTooLong": "Summary is too long",
|
||||||
"descriptionRequired": "Description is required",
|
"descriptionRequired": "Description is required",
|
||||||
"locationRequired": "Location of challenge is required ('Add to')",
|
"locationRequired": "Location of challenge is required ('Add to')",
|
||||||
"categoiresRequired": "One or more categories must be selected"
|
"categoiresRequired": "One or more categories must be selected",
|
||||||
|
"viewProgressOf": "View Progress Of"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -382,5 +382,8 @@
|
|||||||
"questOwnerRewards": "Quest Owner Rewards",
|
"questOwnerRewards": "Quest Owner Rewards",
|
||||||
"updateParty": "Update Party",
|
"updateParty": "Update Party",
|
||||||
"upgrade": "Upgrade",
|
"upgrade": "Upgrade",
|
||||||
"selectPartyMember": "Select a Party Member"
|
"selectPartyMember": "Select a Party Member",
|
||||||
|
"areYouSureDeleteMessage": "Are you sure you want to delete this message?",
|
||||||
|
"reverseChat": "Reverse Chat",
|
||||||
|
"invites": "Invites"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,6 +170,8 @@ api.getMemberAchievements = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Return a request handler for getMembersForGroup / getInvitesForGroup / getMembersForChallenge
|
// Return a request handler for getMembersForGroup / getInvitesForGroup / getMembersForChallenge
|
||||||
|
|
||||||
|
// @TODO: This violates the Liskov substitution principle. We should create factory functions. See Webhooks for a good example
|
||||||
function _getMembersForItem (type) {
|
function _getMembersForItem (type) {
|
||||||
// check for allowed `type`
|
// check for allowed `type`
|
||||||
if (['group-members', 'group-invites', 'challenge-members'].indexOf(type) === -1) {
|
if (['group-members', 'group-invites', 'challenge-members'].indexOf(type) === -1) {
|
||||||
@@ -243,9 +245,18 @@ function _getMembersForItem (type) {
|
|||||||
} else if (type === 'group-invites') {
|
} else if (type === 'group-invites') {
|
||||||
if (group.type === 'guild') { // eslint-disable-line no-lonely-if
|
if (group.type === 'guild') { // eslint-disable-line no-lonely-if
|
||||||
query['invitations.guilds.id'] = group._id;
|
query['invitations.guilds.id'] = group._id;
|
||||||
|
|
||||||
|
if (req.query.includeAllPublicFields === 'true') {
|
||||||
|
fields = memberFields;
|
||||||
|
addComputedStats = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
query['invitations.party.id'] = group._id; // group._id and not groupId because groupId could be === 'party'
|
query['invitations.party.id'] = group._id; // group._id and not groupId because groupId could be === 'party'
|
||||||
// @TODO invitations are now stored like this: `'invitations.parties': []` Probably need a database index for it.
|
// @TODO invitations are now stored like this: `'invitations.parties': []` Probably need a database index for it.
|
||||||
|
if (req.query.includeAllPublicFields === 'true') {
|
||||||
|
fields = memberFields;
|
||||||
|
addComputedStats = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user