diff --git a/website/client/components/appHeader.vue b/website/client/components/appHeader.vue
index 82ffa4736f..3c1035883d 100644
--- a/website/client/components/appHeader.vue
+++ b/website/client/components/appHeader.vue
@@ -27,7 +27,7 @@ div
span.small-text(v-html="$t('inviteFriendsParty')")
br
// 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') }}
diff --git a/website/client/components/groups/publicGuildItem.vue b/website/client/components/groups/publicGuildItem.vue
index 40dcd7c85f..c27c6f2d11 100644
--- a/website/client/components/groups/publicGuildItem.vue
+++ b/website/client/components/groups/publicGuildItem.vue
@@ -4,11 +4,11 @@ router-link.card-link(:to="{ name: 'guild', params: { groupId: guild._id } }")
.card-block
.row
.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.silverGuildBadgeIcon", v-if='guild.memberCount > 100 && guild.memberCount < 999')
.svg-icon.shield(v-html="icons.bronzeGuildBadgeIcon", v-if='guild.memberCount < 100')
- .member-count {{guild.memberCount}}
+ .member-count {{ guild.memberCount | abbrNum }}
.col-md-10
.row
.col-md-8
@@ -76,6 +76,14 @@ router-link.card-link(:to="{ name: 'guild', params: { groupId: guild._id } }")
width: 70px;
}
+ .gold {
+ color: #fdbb5a;
+ }
+
+ .silver {
+ color: #c2c2c2;
+ }
+
.badge-column {
display: flex;
align-items: center;
diff --git a/website/client/components/groups/startQuestModal.vue b/website/client/components/groups/startQuestModal.vue
index e55844ae21..2f48d519bc 100644
--- a/website/client/components/groups/startQuestModal.vue
+++ b/website/client/components/groups/startQuestModal.vue
@@ -12,7 +12,7 @@
div(v-if='questData')
questDialogContent(:item="questData")
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
p {{$t('inviteInformation')}}
.side-panel(v-if='questData')
@@ -122,6 +122,7 @@ export default {
},
data () {
return {
+ loading: false,
selectedQuest: {},
icons: Object.freeze({
copy: copyIcon,
@@ -157,6 +158,8 @@ export default {
},
async questInit () {
+ this.loading = true;
+
Analytics.updateUser({
partyID: this.group._id,
partySize: this.group.memberCount,
@@ -170,6 +173,8 @@ export default {
if (this.$store.state.party.data) this.$store.state.party.data.quest = quest;
+ this.loading = false;
+
this.$root.$emit('hide::modal', 'start-quest-modal');
},
},
diff --git a/website/client/components/groups/tavern.vue b/website/client/components/groups/tavern.vue
index 5e482d9a3a..213841d546 100644
--- a/website/client/components/groups/tavern.vue
+++ b/website/client/components/groups/tavern.vue
@@ -12,8 +12,13 @@
.row
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')
- 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')
div.col-8(v-once, v-html="$t('communityGuidelinesIntro')")
@@ -523,6 +528,11 @@ export default {
document.body.removeChild(div);
},
updateCarretPosition (eventUpdate) {
+ if (eventUpdate.metaKey && eventUpdate.keyCode === 13) {
+ this.sendMessage();
+ return;
+ }
+
let text = eventUpdate.target;
this.getCoord(eventUpdate, text);
},
@@ -551,6 +561,9 @@ export default {
async fetchRecentMessages () {
this.group = await this.$store.dispatch('guilds:getGroup', {groupId: TAVERN_ID});
},
+ reverseChat () {
+ this.group.chat.reverse();
+ },
},
};
diff --git a/website/client/components/hall/heroes.vue b/website/client/components/hall/heroes.vue
index 0545a90f09..d0054c1d74 100644
--- a/website/client/components/hall/heroes.vue
+++ b/website/client/components/hall/heroes.vue
@@ -186,8 +186,9 @@ export default {
window.scrollTo(0, 200);
this.loadHero(id, index);
},
- clickMember (hero) {
- this.$store.state.profileUser = hero;
+ async clickMember (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.$root.$emit('show::modal', 'profile');
},
diff --git a/website/client/components/members/removeMemberModal.vue b/website/client/components/members/removeMemberModal.vue
new file mode 100644
index 0000000000..fbdaa37206
--- /dev/null
+++ b/website/client/components/members/removeMemberModal.vue
@@ -0,0 +1,53 @@
+
+ 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') }}
+
+
+
+
+
diff --git a/website/client/components/settings/site.vue b/website/client/components/settings/site.vue
index 76f704d9b8..24957203d6 100644
--- a/website/client/components/settings/site.vue
+++ b/website/client/components/settings/site.vue
@@ -34,7 +34,8 @@
.form-horizontal(v-if='user.flags.classSelected && !user.preferences.disableClasses')
h5 {{ $t('characterBuild') }}
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') }}
small.cost 3
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(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}) }}
- // hr
- // TODO
- // div(v-if='!user.auth.local.username')
+ hr
+ div(v-if='!user.auth.local.username')
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') }}
.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
- 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
- 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
- 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')")
+ input.form-control(type='password', :placeholder="$t('confirmPass')", v-model='localAuth.confirmPassword', required)
+ button.btn.btn-primary(type='submit', @click='addLocalAuth()') {{ $t('submit') }}
.usersettings(v-if='user.auth.local.username')
p {{ $t('username') }}
@@ -231,6 +231,12 @@ export default {
usernameUpdates: {},
emailUpdates: {},
passwordUpdates: {},
+ localAuth: {
+ username: '',
+ email: '',
+ password: '',
+ confirmPassword: '',
+ },
};
},
mounted () {
@@ -290,6 +296,7 @@ export default {
// Guide.goto('intro', 0, true);
},
showBailey () {
+ this.user.flags.newStuff = true;
this.$root.$emit('show::modal', 'new-stuff');
},
hasBackupAuthOption (networkKeyToCheck) {
@@ -380,6 +387,9 @@ export default {
alert(e.message);
}
},
+ addLocalAuth () {
+ axios.post('/api/v3/user/auth/local/register', this.localAuth, 'addedLocalAuth');
+ },
},
};
diff --git a/website/client/components/settings/subscription.vue b/website/client/components/settings/subscription.vue
index 1e8db4b84e..538f57dcda 100644
--- a/website/client/components/settings/subscription.vue
+++ b/website/client/components/settings/subscription.vue
@@ -163,6 +163,16 @@ export default {
}]);
},
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 {
price: this.subscriptionBlocks[this.user.purchased.plan.planId].price,
months: this.subscriptionBlocks[this.user.purchased.plan.planId].months,
diff --git a/website/client/components/static/header.vue b/website/client/components/static/header.vue
index d003629a4e..05011d6f90 100644
--- a/website/client/components/static/header.vue
+++ b/website/client/components/static/header.vue
@@ -1,9 +1,7 @@
nav.navbar.navbar-inverse.fixed-top.navbar-toggleable-sm
.navbar-header
- router-link.nav-item(
- to='/static/home',
- )
+ router-link.nav-item(:to='!isUserLoggedIn ? "/static/home" : "/"')
.logo.svg-icon(v-html='icons.logo')
.collapse.navbar-collapse
ul.navbar-nav.mr-auto(v-if='$route.name !== "home"')
diff --git a/website/client/components/tasks/column.vue b/website/client/components/tasks/column.vue
index 89f909b4ed..8e4d1f79c5 100644
--- a/website/client/components/tasks/column.vue
+++ b/website/client/components/tasks/column.vue
@@ -6,7 +6,7 @@
.filters.d-flex.justify-content-end
.filter.small-text(
v-for="filter in types[type].filters",
- :class="{active: activeFilter.label === filter.label}",
+ :class="{active: activeFilters[type].label === filter.label}",
@click="activateFilter(type, filter)",
) {{ $t(filter.label) }}
.tasks-list(ref="taskList", v-sortable='', @onsort='sorted')
@@ -226,9 +226,14 @@ export default {
reward: rewardIcon,
});
+ let activeFilters = {};
+ for (let type in types) {
+ activeFilters[type] = types[type].filters.find(f => f.default === true);
+ }
+
return {
types,
- activeFilter: types[this.type].filters.find(f => f.default === true),
+ activeFilters,
icons,
openedCompletedTodos: false,
@@ -252,7 +257,7 @@ export default {
return inAppRewards(this.user);
},
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 () {
// 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;
},
+ dailyDueDefaultView () {
+ if (this.user.preferences.dailyDueDefaultView) {
+ this.activateFilter('daily', this.types.daily.filters[1]);
+ }
+ return this.user.preferences.dailyDueDefaultView;
+ },
},
watch: {
taskList: {
@@ -270,6 +281,11 @@ export default {
}, 250),
deep: true,
},
+ dailyDueDefaultView () {
+ if (this.user.preferences.dailyDueDefaultView) {
+ this.activateFilter('daily', this.types.daily.filters[1]);
+ }
+ },
},
mounted () {
this.setColumnBackgroundVisibility();
@@ -301,7 +317,7 @@ export default {
if (type === 'todo' && filter.label === 'complete2') {
this.loadCompletedTodos();
}
- this.activeFilter = filter;
+ this.activeFilters[type] = filter;
},
setColumnBackgroundVisibility () {
this.$nextTick(() => {
@@ -330,7 +346,7 @@ export default {
},
filterTask (task) {
// View
- if (!this.activeFilter.filter(task)) return false;
+ if (!this.activeFilters[task.type].filter(task)) return false;
// Tags
const selectedTags = this.selectedTags;
diff --git a/website/client/components/userMenu/inbox.vue b/website/client/components/userMenu/inbox.vue
index 23413994a8..acc31d3f12 100644
--- a/website/client/components/userMenu/inbox.vue
+++ b/website/client/components/userMenu/inbox.vue
@@ -36,7 +36,7 @@
.svg-icon.envelope(v-html="icons.messageIcon")
h4(v-once) Nothing Here Yet
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
diff --git a/website/client/components/userMenu/profile.vue b/website/client/components/userMenu/profile.vue
index 10cf8b61cf..8f1ed84bed 100644
--- a/website/client/components/userMenu/profile.vue
+++ b/website/client/components/userMenu/profile.vue
@@ -20,9 +20,9 @@ div
member-details(:member="user")
.row
.col-6.offset-3.text-center.nav
- .nav-item(@click='selectedPage = "profile"', :class="{active: selectedPage === 'profile'}") {{ $t('profile') }}
- .nav-item(@click='selectedPage = "stats"', :class="{active: selectedPage === 'stats'}") {{ $t('stats') }}
- .nav-item(@click='selectedPage = "achievements"', :class="{active: selectedPage === 'achievements'}") {{ $t('achievements') }}
+ .nav-item(@click='selectPage("profile")', :class="{active: selectedPage === 'profile'}") {{ $t('profile') }}
+ .nav-item(@click='selectPage("stats")', :class="{active: selectedPage === 'stats'}") {{ $t('stats') }}
+ .nav-item(@click='selectPage("achievements")', :class="{active: selectedPage === 'achievements'}") {{ $t('achievements') }}
#userProfile.standard-page(v-show='selectedPage === "profile"', v-if='user.profile')
.row
.col-8
@@ -94,9 +94,9 @@ div
.row(v-for='(category, key) in achievements')
h2.col-12.text-center {{ $t(key+'Achievs') }}
.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(
- :target="'#' + key",
+ :target="'#' + key + '-achievement'",
triggers="hover",
placement="top",
)
@@ -121,11 +121,11 @@ div
span {{ value }}
#stats.standard-page(v-show='selectedPage === "stats"', v-if='user.preferences')
.row
- .col-6 {{$t('equipment')}}
- h2.text-center
+ .col-6
+ h2.text-center {{$t('equipment')}}
.well
.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}`")
h3 {{$t('eyewear')}}
.col-4.item-wrapper
@@ -133,11 +133,11 @@ div
div(:class="`shop_${equippedItems.head}`")
h3 {{$t('headGear')}}
.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}`")
h3 {{$t('headAccess')}}
.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}`")
h3 {{$t('backAccess')}}
.col-4.item-wrapper
@@ -145,7 +145,7 @@ div
div(:class="`shop_${equippedItems.armor}`")
h3 {{$t('armor')}}
.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}`")
h3 {{$t('bodyAccess')}}
.col-4.item-wrapper
@@ -161,7 +161,7 @@ div
h2.text-center {{$t('costume')}}
.well
.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}`")
h3 {{$t('eyewear')}}
.col-4.item-wrapper
@@ -169,11 +169,11 @@ div
div(:class="`shop_${costumeItems.head}`")
h3 {{$t('headGear')}}
.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}`")
h3 {{$t('headAccess')}}
.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}`")
h3 {{$t('backAccess')}}
.col-4.item-wrapper
@@ -181,7 +181,7 @@ div
div(:class="`shop_${costumeItems.armor}`")
h3 {{$t('armor')}}
.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}`")
h3 {{$t('bodyAccess')}}
.col-4.item-wrapper
@@ -189,8 +189,8 @@ div
div(:class="`shop_${costumeItems.weapon}`")
h3 {{$t('mainHand')}}
.col-4.item-wrapper
- .box(:class='{white: user.preferences.background}')
- div(:class="user.preferences.background")
+ .box(:class='{white: user.preferences.background}', style="overflow:hidden")
+ div(:class="'background_' + user.preferences.background")
h3 {{$t('background')}}
.col-4.item-wrapper
.box(:class='{white: costumeItems.shield && costumeItems.shield.indexOf("base_0") === -1}')
@@ -326,7 +326,7 @@ div
}
.pet, .mount {
- margin-top: -1.6em;
+ margin-top: -1.8em !important;
}
.header {
@@ -660,6 +660,7 @@ export default {
this.editingProfile.name = user.profile.name;
this.editingProfile.imageUrl = user.profile.imageUrl;
+ this.editingProfile.blurb = user.profile.blurb;
if (!user.achievements.quests) user.achievements.quests = {};
if (!user.achievements.challenges) user.achievements.challenges = {};
@@ -700,6 +701,11 @@ export default {
},
},
methods: {
+ selectPage (page) {
+ this.selectedPage = page;
+ // @TODO: rename this property?
+ this.$store.state.profileOptions.startingPage = page;
+ },
sendMessage () {
this.$store.state.userIdToMessage = this.user._id;
this.$root.$emit('show::modal', 'private-message');
diff --git a/website/client/mixins/groupsUtilities.js b/website/client/mixins/groupsUtilities.js
index f650a05243..0d13d940d0 100644
--- a/website/client/mixins/groupsUtilities.js
+++ b/website/client/mixins/groupsUtilities.js
@@ -1,6 +1,32 @@
import intersection from 'lodash/intersection';
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: {
isMemberOfGroup (user, group) {
if (group._id === this.$store.state.constants.TAVERN_ID) return true;
diff --git a/website/client/store/actions/members.js b/website/client/store/actions/members.js
index c9cf12bd65..f3734b952c 100644
--- a/website/client/store/actions/members.js
+++ b/website/client/store/actions/members.js
@@ -21,8 +21,11 @@ export async function fetchMember (store, payload) {
export async function getGroupInvites (store, payload) {
let url = `${apiV3Prefix}/groups/${payload.groupId}/invites`;
+ if (payload.includeAllPublicFields) {
+ url += '?includeAllPublicFields=true';
+ }
let response = await axios.get(url);
- return response;
+ return response.data.data;
}
export async function getChallengeMembers (store, payload) {
diff --git a/website/client/store/index.js b/website/client/store/index.js
index 60e16f4bc6..7b5fcdc41c 100644
--- a/website/client/store/index.js
+++ b/website/client/store/index.js
@@ -95,6 +95,7 @@ export default function () {
challengeOptions: {
cloning: false,
tasksToClone: {},
+ workingChallenge: {},
},
editingGroup: {}, // @TODO move to local state
// content data, frozen to prevent Vue from modifying it since it's static and never changes
diff --git a/website/common/locales/en/challenge.json b/website/common/locales/en/challenge.json
index 9e2ddf78fe..705d7d7a3f 100644
--- a/website/common/locales/en/challenge.json
+++ b/website/common/locales/en/challenge.json
@@ -89,7 +89,7 @@
"joinedChallenge": "Joined a Challenge",
"joinedChallengeText": "This user put themselves to the test by joining a Challenge!",
"myChallenges": "My Challenges",
- "findChallenges": "Find Challenges",
+ "findChallenges": "Discover 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.",
"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",
"descriptionRequired": "Description is required",
"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"
}
diff --git a/website/common/locales/en/groups.json b/website/common/locales/en/groups.json
index c086703a81..b6099ab6c1 100644
--- a/website/common/locales/en/groups.json
+++ b/website/common/locales/en/groups.json
@@ -382,5 +382,8 @@
"questOwnerRewards": "Quest Owner Rewards",
"updateParty": "Update Party",
"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"
}
diff --git a/website/server/controllers/api-v3/members.js b/website/server/controllers/api-v3/members.js
index 938019e4c3..8c2129b267 100644
--- a/website/server/controllers/api-v3/members.js
+++ b/website/server/controllers/api-v3/members.js
@@ -170,6 +170,8 @@ api.getMemberAchievements = {
};
// 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) {
// check for allowed `type`
if (['group-members', 'group-invites', 'challenge-members'].indexOf(type) === -1) {
@@ -243,9 +245,18 @@ function _getMembersForItem (type) {
} else if (type === 'group-invites') {
if (group.type === 'guild') { // eslint-disable-line no-lonely-if
query['invitations.guilds.id'] = group._id;
+
+ if (req.query.includeAllPublicFields === 'true') {
+ fields = memberFields;
+ addComputedStats = true;
+ }
} else {
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.
+ if (req.query.includeAllPublicFields === 'true') {
+ fields = memberFields;
+ addComputedStats = true;
+ }
}
}