mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Oct 5 fixes (#9163)
* Added removing invites * Addeed messages for empty gems to icon * Added member for challenge members * Fixed task cloning ending * Fixed group task assignment * Added small hack to prevent scrolling issues * Fixed lint
This commit is contained in:
@@ -142,4 +142,22 @@ describe('GET /challenges/:challengeId/members', () => {
|
||||
let resIds = res.concat(res2).map(member => member._id);
|
||||
expect(resIds).to.eql(expectedIds.sort());
|
||||
});
|
||||
|
||||
it('supports using req.query.search to get search members', async () => {
|
||||
let group = await generateGroup(user, {type: 'party', name: generateUUID()});
|
||||
let challenge = await generateChallenge(user, group);
|
||||
|
||||
let usersToGenerate = [];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
usersToGenerate.push(generateUser({challenges: [challenge._id]}));
|
||||
}
|
||||
let generatedUsers = await Promise.all(usersToGenerate);
|
||||
let profileNames = generatedUsers.map(generatedUser => generatedUser.profile.name);
|
||||
|
||||
let firstProfileName = profileNames[0];
|
||||
let nameToSearch = firstProfileName.substring(0, 4);
|
||||
|
||||
let response = await user.get(`/challenges/${challenge._id}/members?search=${nameToSearch}`);
|
||||
expect(response[0].profile.name).to.eql(firstProfileName);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,7 +56,8 @@
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.modal {
|
||||
/* @TODO: The modal-open class is not being removed. Let's try this for now */
|
||||
.modal, .modal-open {
|
||||
overflow-y: scroll !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -301,6 +301,9 @@ export default {
|
||||
challengeId: this.searchId,
|
||||
tasks: clonedTasks,
|
||||
});
|
||||
|
||||
this.$store.state.challengeOptions.cloning = false;
|
||||
this.$store.state.challengeOptions.tasksToClone = [];
|
||||
},
|
||||
async loadChallenge () {
|
||||
this.challenge = await this.$store.dispatch('challenges:getChallenge', {challengeId: this.searchId});
|
||||
|
||||
@@ -10,8 +10,13 @@ div
|
||||
.col-12
|
||||
strong(v-once) {{$t('selectChallengeWinnersDescription')}}
|
||||
.col-12
|
||||
select.form-control(v-model='winnerId')
|
||||
option(v-for='member in members', :value='member._id') {{member.profile.name}}
|
||||
input.form-control(type='text', v-model='searchTerm')
|
||||
.col-12
|
||||
div(v-for='member in memberResults', @click='selectMember(member._id)')
|
||||
strong {{member.profile.name}}
|
||||
span(v-if='winnerId === member._id') Selected
|
||||
//- select.form-control(v-model='winnerId')
|
||||
//- option(v-for='member in members', :value='member._id') {{member.profile.name}}
|
||||
.col-12
|
||||
button.btn.btn-primary(v-once, @click='closeChallenge') {{$t('awardWinners')}}
|
||||
.col-12
|
||||
@@ -72,6 +77,7 @@ div
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce';
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
import bDropdown from 'bootstrap-vue/lib/components/dropdown';
|
||||
import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
|
||||
@@ -86,9 +92,25 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
winnerId: '',
|
||||
searchTerm: '',
|
||||
memberResults: [],
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
searchTerm: debounce(function searchTerm (newSearch) {
|
||||
this.searchChallengeMember(newSearch);
|
||||
}, 500),
|
||||
},
|
||||
methods: {
|
||||
async searchChallengeMember (search) {
|
||||
this.memberResults = await this.$store.dispatch('members:getChallengeMembers', {
|
||||
challengeId: this.challengeId,
|
||||
searchTerm: search,
|
||||
});
|
||||
},
|
||||
selectMember (memberId) {
|
||||
this.winnerId = memberId;
|
||||
},
|
||||
async closeChallenge () {
|
||||
this.challenge = await this.$store.dispatch('challenges:selectChallengeWinner', {
|
||||
challengeId: this.challengeId,
|
||||
|
||||
@@ -53,9 +53,16 @@ div
|
||||
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')
|
||||
.row(v-for='(member, index) in invites')
|
||||
.col-11.no-padding-left
|
||||
member-details(:member='member')
|
||||
.col-1.actions
|
||||
b-dropdown(right=true)
|
||||
.svg-icon.inline.dots(slot='button-content', v-html="icons.dots")
|
||||
b-dropdown-item(@click='removeInvite(member, index)', v-if='isLeader')
|
||||
span.dropdown-icon-item
|
||||
.svg-icon.inline(v-html="icons.removeIcon", v-if='isLeader')
|
||||
span.text {{$t('removeInvite')}}
|
||||
.modal-footer
|
||||
button.btn.btn-primary(@click='close()') {{ $t('close') }}
|
||||
</template>
|
||||
@@ -375,6 +382,14 @@ export default {
|
||||
viewInvites () {
|
||||
this.selectedPage = 'invites';
|
||||
},
|
||||
async removeInvite (member, index) {
|
||||
this.invites.splice(index, 1);
|
||||
await this.$store.dispatch('members:removeMember', {
|
||||
memberId: member._id,
|
||||
groupId: this.groupId,
|
||||
});
|
||||
this.viewMembers();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
@click="itemSelected(item)"
|
||||
)
|
||||
span(slot="popoverContent")
|
||||
strong(v-if='item.key === "gem" && gemsLeft === 0') {{ $t('maxBuyGems') }}
|
||||
h4.popover-content-title {{ item.text }}
|
||||
|
||||
template(slot="itemBadge", scope="ctx")
|
||||
@@ -156,6 +157,8 @@
|
||||
:show="userItems[item.purchaseType][item.key] != 0",
|
||||
:count="userItems[item.purchaseType][item.key] || 0"
|
||||
)
|
||||
.gems-left(v-if='item.key === "gem"')
|
||||
| {{ gemsLeft }}
|
||||
|
||||
span.badge.badge-pill.badge-item.badge-svg(
|
||||
:class="{'item-selected-badge': ctx.item.pinned, 'hide': !ctx.item.pinned}",
|
||||
@@ -163,6 +166,7 @@
|
||||
)
|
||||
span.svg-icon.inline.icon-12.color(v-html="icons.pin")
|
||||
|
||||
|
||||
div.fill-height
|
||||
|
||||
drawer(
|
||||
@@ -339,6 +343,19 @@
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.gems-left {
|
||||
position: absolute;
|
||||
right: -.5em;
|
||||
top: -.5em;
|
||||
color: $white;
|
||||
background: $purple-200;
|
||||
padding: .15em .55em;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 1px 1px 0 rgba($black, 0.12);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -374,6 +391,7 @@
|
||||
import getItemInfo from 'common/script/libs/getItemInfo';
|
||||
import isPinned from 'common/script/libs/isPinned';
|
||||
import shops from 'common/script/libs/shops';
|
||||
import planGemLimits from 'common/script/libs/planGemLimits';
|
||||
|
||||
import _filter from 'lodash/filter';
|
||||
import _sortBy from 'lodash/sortBy';
|
||||
@@ -553,6 +571,10 @@ export default {
|
||||
},
|
||||
];
|
||||
},
|
||||
gemsLeft () {
|
||||
if (!this.user.purchased.plan) return 0;
|
||||
return planGemLimits.convCap + this.user.purchased.plan.consecutive.gemCapExtra - this.user.purchased.plan.gemsBought;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getClassName (classType) {
|
||||
|
||||
@@ -34,8 +34,6 @@
|
||||
div.clearfix(slot="modal-footer")
|
||||
span.balance.float-left {{ $t('yourBalance') }}
|
||||
balanceInfo.float-right
|
||||
|
||||
|
||||
</template>
|
||||
<style lang="scss">
|
||||
|
||||
|
||||
@@ -767,7 +767,7 @@ export default {
|
||||
|
||||
await this.$store.dispatch('tasks:unassignTask', {
|
||||
taskId: this.task._id,
|
||||
userId: this.user._id,
|
||||
userId: memberId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -778,7 +778,7 @@ export default {
|
||||
|
||||
await this.$store.dispatch('tasks:assignTask', {
|
||||
taskId: this.task._id,
|
||||
userId: this.user._id,
|
||||
userId: memberId,
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -35,6 +35,10 @@ export async function getChallengeMembers (store, payload) {
|
||||
url += `&lastId=${payload.lastMemberId}`;
|
||||
}
|
||||
|
||||
if (payload.searchTerm) {
|
||||
url += `&search=${payload.searchTerm}`;
|
||||
}
|
||||
|
||||
let response = await axios.get(url);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
@@ -226,6 +226,10 @@ function _getMembersForItem (type) {
|
||||
fields = memberFields;
|
||||
addComputedStats = true;
|
||||
}
|
||||
|
||||
if (req.query.search) {
|
||||
query['profile.name'] = {$regex: req.query.search};
|
||||
}
|
||||
} else if (type === 'group-members') {
|
||||
if (group.type === 'guild') {
|
||||
query.guilds = group._id;
|
||||
|
||||
Reference in New Issue
Block a user