Challenges plus misc fixes (#8961)

* Forced full refresh after deletE

* Fixed styles on firefox

* Removed instagram link

* Added information to modal

* Fixed deleteing and task keeping

* Added redirect to challenge detail after created

* Updated challenge item styles

* Added new limit option to challenges
This commit is contained in:
Keith Holliday
2017-08-17 11:03:32 -06:00
committed by GitHub
parent f5cf27a79e
commit de63622cdd
13 changed files with 60 additions and 33 deletions

View File

@@ -119,6 +119,16 @@ describe('GET challenges/user', () => {
});
});
it('should return not return challenges in user groups if we send member true param', async () => {
let challenges = await member.get(`/challenges/user?member=${true}`);
let foundChallenge1 = _.find(challenges, { _id: challenge._id });
expect(foundChallenge1).to.not.exist;
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
expect(foundChallenge2).to.not.exist;
});
it('should return newest challenges first', async () => {
let challenges = await user.get('/challenges/user');

View File

@@ -65,7 +65,7 @@
.social-circle
a(href='https://twitter.com/habitica', target='_blank')
.social-icon.svg-icon(v-html='icons.twitter')
.social-circle
// @TODO: Not ready yet .social-circle
a(href='https://www.instagram.com/habitica/', target='_blank')
.social-icon.svg-icon.instagram(v-html='icons.instagram')
.social-circle

View File

@@ -257,11 +257,18 @@ export default {
await this.$store.dispatch('challenges:joinChallenge', {challengeId: this.challengeId});
},
async leaveChallenge () {
let keepChallenge = confirm('Do you want to keep challenge tasks?');
let keep = 'keep-all';
if (!keepChallenge) keep = 'remove-all';
let index = findIndex(this.user.challenges, (challengeId) => {
return challengeId === this.challengeId;
});
this.user.challenges.splice(index, 1);
await this.$store.dispatch('challenges:leaveChallenge', {challengeId: this.challengeId});
await this.$store.dispatch('challenges:leaveChallenge', {
challengeId: this.challengeId,
keep,
});
},
closeChallenge () {
this.$root.$emit('show::modal', 'close-challenge-modal');

View File

@@ -1,7 +1,8 @@
<template lang="pug">
.card
router-link(:to="{ name: 'challenge', params: { challengeId: challenge._id } }")
h3 {{challenge.name}}
.row
router-link.col-12(:to="{ name: 'challenge', params: { challengeId: challenge._id } }")
h3 {{challenge.name}}
.row
.col-6
div.details
@@ -24,7 +25,6 @@
.row.description
.col-12
| {{challenge.description}}
.container.well-wrapper
.well.row
.col-3
.count-details
@@ -48,7 +48,7 @@
div {{$t('reward')}}
</template>
<style lang='scss' scoped>
<style lang="scss" scoped>
@import '~client/assets/scss/colors.scss';
.card {
@@ -104,7 +104,6 @@
.description {
color: $gray-200;
margin-top: 2em;
margin-bottom: 2em;
overflow: hidden;
}
@@ -142,8 +141,8 @@
width: 26px;
}
.count-details {
padding-left: 1em;
.count-details span {
margin-right: .5em;
}
.count {

View File

@@ -14,11 +14,12 @@
strong(v-once) {{$t('description')}}*
div.description-count.float-right {{charactersRemaining}} {{ $t('charactersRemaining') }}
b-form-input.description-textarea(type="text", textarea, :placeholder="$t('challengeDescriptionPlaceHolder')", v-model="workingChallenge.description")
// @TODO: Implemenet in V2 .form-group
.form-group
label
strong(v-once) {{$t('guildInformation')}}*
strong(v-once) Challenge Information*
a.float-right {{ $t('markdownFormattingHelp') }}
b-form-input.information-textarea(type="text", textarea, :placeholder="$t('challengeInformationPlaceHolder')", v-model="workingChallenge.information")
b-form-input.information-textarea(type="text", textarea,
:placeholder="$t('challengeInformationPlaceHolder')", v-model="workingChallenge.description")
.form-group(v-if='creating')
label
strong(v-once) {{$t('where')}}
@@ -296,6 +297,7 @@ export default {
this.$emit('createChallenge', challenge);
this.ressetWorkingChallenge();
this.$root.$emit('hide::modal', 'challenge-modal');
this.$router.push(`/challenges/${challenge._id}`);
},
updateChallenge () {
this.$emit('updatedChallenge', {

View File

@@ -20,7 +20,7 @@ div
.col-12
strong(v-once) {{$t('doYouWantedToDeleteChallenge')}}
.col-12
button.btn.btn-danger(v-once) {{$t('deleteChallenge')}}
button.btn.btn-danger(v-once, @click='deleteChallenge()') {{$t('deleteChallenge')}}
.footer-wrap(slot="modal-footer")
</template>

View File

@@ -11,7 +11,7 @@
// @TODO: implement sorting span.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
button.btn.btn-secondary.create-challenge-button(@click='createChallenge()')
button.btn.btn-secondary.create-challenge-button.float-right(@click='createChallenge()')
.svg-icon.positive-icon(v-html="icons.positiveIcon")
span(v-once) {{$t('createChallenge')}}
.row

View File

@@ -11,7 +11,7 @@
// @TODO: implement sorting span.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
button.btn.btn-secondary.create-challenge-button(@click='createChallenge()')
button.btn.btn-secondary.create-challenge-button.float-right(@click='createChallenge()')
.svg-icon.positive-icon(v-html="icons.positiveIcon")
span(v-once) {{$t('createChallenge')}}
@@ -153,7 +153,9 @@ export default {
this.$root.$emit('show::modal', 'challenge-modal');
},
async loadchallanges () {
this.challenges = await this.$store.dispatch('challenges:getUserChallenges');
this.challenges = await this.$store.dispatch('challenges:getUserChallenges', {
member: true,
});
},
challengeCreated (challenge) {
this.challenges.push(challenge);

View File

@@ -59,7 +59,7 @@ export default {
},
});
localStorage.clear();
this.$router.push('/home');
window.location.href = '/home';
this.$root.$emit('hide::modal', 'reset');
},
},

View File

@@ -146,27 +146,27 @@
.form(v-if='user.auth.local', name='changeUsername', novalidate)
//-.alert.alert-danger(ng-messages='changeUsername.$error && changeUsername.submitted') {{ $t('fillAll') }}
.form-group
input.form-control(type='text', :placeholder="$t('newUsername')", v-model='usernameUpdates.username', required)
input.form-control(type='text', :placeholder="$t('newUsername')", v-model='usernameUpdates.username')
.form-group
input.form-control(type='password', :placeholder="$t('password')", v-model='usernameUpdates.password', required)
input.form-control(type='password', :placeholder="$t('password')", v-model='usernameUpdates.password')
button.btn.btn-primary(type='submit', @click='changeUser("username", usernameUpdates)') {{ $t('submit') }}
h5 {{ $t('changeEmail') }}
.form(v-if='user.auth.local', name='changeEmail', novalidate)
.form-group
input.form-control(type='text', :placeholder="$t('newEmail')", v-model='emailUpdates.newEmail', required)
input.form-control(type='text', :placeholder="$t('newEmail')", v-model='emailUpdates.newEmail')
.form-group
input.form-control(type='password', :placeholder="$t('password')", v-model='emailUpdates.password', required)
input.form-control(type='password', :placeholder="$t('password')", v-model='emailUpdates.password')
button.btn.btn-primary(type='submit', @click='changeUser("email", emailUpdates)') {{ $t('submit') }}
h5 {{ $t('changePass') }}
.form(v-if='user.auth.local', name='changePassword', novalidate)
.form-group
input.form-control(type='password', :placeholder="$t('oldPass')", v-model='passwordUpdates.password', required)
input.form-control(type='password', :placeholder="$t('oldPass')", v-model='passwordUpdates.password')
.form-group
input.form-control(type='password', :placeholder="$t('newPass')", v-model='passwordUpdates.newPassword', required)
input.form-control(type='password', :placeholder="$t('newPass')", v-model='passwordUpdates.newPassword')
.form-group
input.form-control(type='password', :placeholder="$t('confirmPass')", v-model='passwordUpdates.confirmPassword', required)
input.form-control(type='password', :placeholder="$t('confirmPass')", v-model='passwordUpdates.confirmPassword')
button.btn.btn-primary(type='submit', @click='changeUser("password", passwordUpdates)') {{ $t('submit') }}
div

View File

@@ -186,7 +186,7 @@ const router = new VueRouter({
},
{
name: 'challenge',
path: 'challenges/:challengeId',
path: ':challengeId',
component: ChallengeDetail,
props: true,
},

View File

@@ -26,9 +26,10 @@ export async function leaveChallenge (store, payload) {
return response.data.data;
}
export async function getUserChallenges () {
let response = await axios.get('/api/v3/challenges/user');
export async function getUserChallenges (store, payload) {
let url = '/api/v3/challenges/user';
if (payload && payload.member) url += '?member=true';
let response = await axios.get(url);
return response.data.data;
}

View File

@@ -371,13 +371,19 @@ api.getUserChallenges = {
middlewares: [authWithHeaders()],
async handler (req, res) {
let user = res.locals.user;
let orOptions = [
{_id: {$in: user.challenges}}, // Challenges where the user is participating
{leader: user._id}, // Challenges where I'm the leader
];
if (!req.query.member) {
orOptions.push({
group: {$in: user.getGroups()},
}); // Challenges in groups where I'm a member
}
let challenges = await Challenge.find({
$or: [
{_id: {$in: user.challenges}}, // Challenges where the user is participating
{group: {$in: user.getGroups()}}, // Challenges in groups where I'm a member
{leader: user._id}, // Challenges where I'm the leader
],
$or: orOptions,
})
.sort('-official -createdAt')
// see below why we're not using populate