mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 22:27:26 +01:00
Oct 1 fixes (#9121)
* Added default tags to task * Added seasonal gear check and show spooky * Disabled spooky sparkles * Fixed challenge remove tasks modal * Hid checklist * Added group gems modal * Purchase with amazon * Added check for user health
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
h1(v-markdown='challenge.name')
|
||||
div
|
||||
strong(v-once) {{$t('createdBy')}}:
|
||||
span {{challenge.leader.profile.name}}
|
||||
span(v-if='challenge.leader && challenge.leader.profile') {{challenge.leader.profile.name}}
|
||||
// @TODO: make challenge.author a variable inside the createdBy string (helps with RTL languages)
|
||||
// @TODO: Implement in V2 strong.margin-left(v-once)
|
||||
.svg-icon.calendar-icon(v-html="icons.calendarIcon")
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
invite-modal(:group='this.group')
|
||||
start-quest-modal(:group='this.group')
|
||||
quest-details-modal(:group='this.group')
|
||||
group-gems-modal
|
||||
.col-12.col-sm-8.standard-page
|
||||
.row
|
||||
.col-6.title-details
|
||||
@@ -20,7 +21,7 @@
|
||||
span.number {{ group.memberCount | abbrNum }}
|
||||
div(v-once) {{ $t('memberList') }}
|
||||
.col-4(v-if='!isParty')
|
||||
.item-with-icon
|
||||
.item-with-icon(@click='showGroupGems()')
|
||||
.svg-icon.gem(v-html="icons.gem")
|
||||
span.number {{group.balance * 4}}
|
||||
div(v-once) {{ $t('guildBank') }}
|
||||
@@ -47,7 +48,6 @@
|
||||
.row
|
||||
.col-12.hr
|
||||
chat-message(:chat.sync='group.chat', :group-id='group._id', group-name='group.name')
|
||||
|
||||
.col-12.col-sm-4.sidebar
|
||||
.row(:class='{"guild-background": !isParty}')
|
||||
.col-6
|
||||
@@ -453,6 +453,7 @@ import inviteModal from './inviteModal';
|
||||
import chatMessage from '../chat/chatMessages';
|
||||
import autocomplete from '../chat/autoComplete';
|
||||
import groupChallenges from '../challenges/groupChallenges';
|
||||
import groupGemsModal from 'client/components/groups/groupGemsModal';
|
||||
import markdownDirective from 'client/directives/markdown';
|
||||
|
||||
import bCollapse from 'bootstrap-vue/lib/components/collapse';
|
||||
@@ -490,6 +491,7 @@ export default {
|
||||
groupChallenges,
|
||||
autocomplete,
|
||||
questDetailsModal,
|
||||
groupGemsModal,
|
||||
},
|
||||
directives: {
|
||||
bToggle,
|
||||
@@ -857,6 +859,9 @@ export default {
|
||||
let quest = await this.$store.dispatch('quests:sendAction', {groupId: this.group._id, action: 'quests/reject'});
|
||||
this.group.quest = quest;
|
||||
},
|
||||
showGroupGems () {
|
||||
this.$root.$emit('show::modal', 'group-gems-modal');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
32
website/client/components/groups/groupGemsModal.vue
Normal file
32
website/client/components/groups/groupGemsModal.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template lang="pug">
|
||||
b-modal#group-gems-modal(:title="$t('groupGems')", size='md', :hide-footer="true")
|
||||
.modal-body
|
||||
.row
|
||||
.col-6.offset-3
|
||||
h3 {{ $t('groupGemsDesc') }}
|
||||
.modal-footer
|
||||
.col-12.text-center
|
||||
button.btn.btn-primary(@click='close()') {{$t('close')}}
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.modal-body {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'group-gems-modal');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -303,6 +303,11 @@ export default {
|
||||
this.$root.$emit('show::modal', 'avatar-modal');
|
||||
}
|
||||
|
||||
if (this.user.stats.hp <= 0) {
|
||||
this.playSound('Death');
|
||||
this.$root.$emit('show::modal', 'death');
|
||||
}
|
||||
|
||||
if (this.questCompleted) {
|
||||
this.$root.$emit('show::modal', 'quest-completed');
|
||||
}
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
<template lang="pug">
|
||||
b-modal#amazon-payment(title="Amazon", :hide-footer="true", size='lg')
|
||||
b-modal#amazon-payment(title="Amazon", :hide-footer="true", size='md')
|
||||
h2.text-center Continue with Amazon
|
||||
#AmazonPayButton
|
||||
#AmazonPayWallet(v-if="amazonPayments.loggedIn", style="width: 400px; height: 228px;")
|
||||
#AmazonPayRecurring(v-if="amazonPayments.loggedIn && amazonPayments.type === 'subscription'",
|
||||
style="width: 400px; height: 140px;")
|
||||
.modal-footer
|
||||
.btn.btn-primary(:disabled="amazonPaymentsCanCheckout() || !amazonButtonEnabled",
|
||||
.text-center
|
||||
.btn.btn-primary(v-if="amazonPaymentsCanCheckout",
|
||||
@click="amazonCheckOut()") {{ $t('checkout') }}
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
#AmazonPayButton {
|
||||
margin: 0 auto;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#AmazonPayRecurring {
|
||||
height: 200px;
|
||||
width: 500px;
|
||||
@@ -41,6 +48,17 @@ export default {
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
...mapState(['isAmazonReady']),
|
||||
amazonPaymentsCanCheckout () {
|
||||
if (this.amazonPayments.type === 'single') {
|
||||
return this.amazonPaymentspaymentSelected === true;
|
||||
} else if (this.amazonPayments.type === 'subscription') {
|
||||
return this.amazonPaymentspaymentSelected === true &&
|
||||
// Mah.. one is a boolean the other a string...
|
||||
this.amazonPaymentsrecurringConsent === 'true';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
if (this.isAmazonReady) return this.setupAmazon();
|
||||
@@ -79,11 +97,16 @@ export default {
|
||||
billingAgreementId: this.amazonPaymentsbillingAgreementId,
|
||||
});
|
||||
|
||||
// @TODO: Success
|
||||
if (response.status === 200) {
|
||||
this.amazonPayments.loggedIn = true;
|
||||
this.amazonPaymentsorderReferenceId = response.data.orderReferenceId;
|
||||
this.amazonPayments.orderReferenceId = response.data.data.orderReferenceId;
|
||||
|
||||
// @TODO: Clarify the deifference of these functions by renaming
|
||||
this.amazonPaymentsinitWidgets();
|
||||
// @TODO: error
|
||||
this.amazonInitWidgets();
|
||||
return;
|
||||
}
|
||||
|
||||
alert(response.message);
|
||||
}
|
||||
},
|
||||
@@ -106,17 +129,6 @@ export default {
|
||||
onError: this.amazonOnError,
|
||||
});
|
||||
},
|
||||
amazonPaymentsCanCheckout () {
|
||||
if (this.amazonPayments.type === 'single') {
|
||||
return this.amazonPaymentspaymentSelected === true;
|
||||
} else if (this.amazonPayments.type === 'subscription') {
|
||||
return this.amazonPaymentspaymentSelected === true &&
|
||||
// Mah.. one is a boolean the other a string...
|
||||
this.amazonPaymentsrecurringConsent === 'true';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
amazonInitWidgets () {
|
||||
let walletParams = {
|
||||
sellerId: AMAZON_PAYMENTS.SELLER_ID, // @TODO: Import
|
||||
@@ -131,6 +143,7 @@ export default {
|
||||
onError: this.amazonOnError,
|
||||
};
|
||||
|
||||
// @TODO: Check if this is duplicated below
|
||||
if (this.amazonPayments.type === 'subscription') {
|
||||
walletParams.agreementType = 'BillingAgreement';
|
||||
|
||||
@@ -158,7 +171,7 @@ export default {
|
||||
}).bind('AmazonPayRecurring');
|
||||
};
|
||||
} else {
|
||||
walletParams.amazonOrderReferenceId = this.amazonPaymentsorderReferenceId;
|
||||
walletParams.amazonOrderReferenceId = this.amazonPayments.orderReferenceId;
|
||||
}
|
||||
|
||||
new this.OffAmazonPayments.Widgets.Wallet(walletParams).bind('AmazonPayWallet');
|
||||
@@ -166,18 +179,22 @@ export default {
|
||||
async amazonCheckOut () {
|
||||
this.amazonButtonEnabled = false;
|
||||
|
||||
// @TODO: Create factory functions
|
||||
// @TODO: A gift should not read the same as buying gems for yourself.
|
||||
if (this.amazonPayments.type === 'single') {
|
||||
let url = '/amazon/checkout';
|
||||
let response = await axios.post(url, {
|
||||
orderReferenceId: this.amazonPaymentsorderReferenceId,
|
||||
orderReferenceId: this.amazonPayments.orderReferenceId,
|
||||
gift: this.amazonPaymentsgift,
|
||||
});
|
||||
|
||||
// Success
|
||||
this.amazonPaymentsreset();
|
||||
if (response.status < 400) {
|
||||
this.reset();
|
||||
// @TODO: What are we syncing?
|
||||
window.location.reload(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Failure
|
||||
alert(response.message);
|
||||
this.amazonPaymentsreset();
|
||||
} else if (this.amazonPayments.type === 'subscription') {
|
||||
@@ -212,7 +229,7 @@ export default {
|
||||
}
|
||||
|
||||
window.location.reload(true);
|
||||
this.amazonPaymentsreset();
|
||||
this.reset();
|
||||
}
|
||||
},
|
||||
amazonPaymentsinitWidgets () {
|
||||
@@ -263,16 +280,15 @@ export default {
|
||||
},
|
||||
amazonOnError (error) {
|
||||
alert(error.getErrorMessage());
|
||||
// @TODO: this.amazonPaymentsreset();
|
||||
this.reset();
|
||||
},
|
||||
reset () {
|
||||
this.amazonPaymentsmodal.close(); // @TODO: this.$root.$emit('hide::modal', 'guild-form');
|
||||
this.amazonPaymentsmodal = null;
|
||||
this.amazonPayments.type = null;
|
||||
this.amazonPayments.loggedIn = false;
|
||||
this.amazonPaymentsgift = null;
|
||||
this.amazonPaymentsbillingAgreementId = null;
|
||||
this.amazonPaymentsorderReferenceId = null;
|
||||
this.amazonPayments.orderReferenceId = null;
|
||||
this.amazonPaymentspaymentSelected = false;
|
||||
this.amazonPaymentsrecurringConsent = false;
|
||||
this.amazonPaymentssubscription = null;
|
||||
|
||||
@@ -39,14 +39,14 @@
|
||||
.gem-text {{ $t('gems') }}
|
||||
.divider
|
||||
button.btn.btn-primary(@click='gemAmount = 4') {{gemAmount === 4 ? $t('selected') : '$1.00'}}
|
||||
.card.text-center.col-3(:class="{active: gemAmount === 21 }")
|
||||
.card.text-center.col-3(:class="{active: gemAmount === 20 }")
|
||||
.card-img-top
|
||||
.mx-auto(v-html='icons.twentyOneGems', style='"height: 55px; width: 47.5px; margin-top: 1.85em;"')
|
||||
.card-body
|
||||
.gem-count 20
|
||||
.gem-text {{ $t('gems') }}
|
||||
.divider
|
||||
button.btn.btn-primary(@click='gemAmount === 21 ? gemAmount = 0 : gemAmount = 21') {{gemAmount === 21 ? $t('selected') : '$5.00'}}
|
||||
button.btn.btn-primary(@click='gemAmount === 20 ? gemAmount = 0 : gemAmount = 20') {{gemAmount === 20 ? $t('selected') : '$5.00'}}
|
||||
//.card.text-center(:class="{active: gemAmount === 42}")
|
||||
.card-img-top
|
||||
.mx-auto(v-html='icons.fortyTwoGems', style='"height: 49.5px; width: 51px; margin-top: 1.9em;"')
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
span.text(v-once, v-html="seasonal.notes")
|
||||
span.rectangle
|
||||
div.content(v-else-if="seasonal.featured.items.length !== 0")
|
||||
div.featured-label.with-border
|
||||
div.featured-label.with-border(v-if='!featuredGearBought')
|
||||
span.rectangle
|
||||
span.text(v-once) {{ $t('featuredset', { name: seasonal.featured.text }) }}
|
||||
span.rectangle
|
||||
@@ -349,6 +349,7 @@
|
||||
selectedSortItemsBy: 'AZ',
|
||||
|
||||
hidePinned: false,
|
||||
featuredGearBought: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -363,7 +364,22 @@
|
||||
},
|
||||
|
||||
seasonal () {
|
||||
return shops.getSeasonalShop(this.user);
|
||||
let seasonal = shops.getSeasonalShop(this.user);
|
||||
|
||||
let itemsNotOwned = seasonal.featured.items.filter(item => {
|
||||
return !this.user.items.gear.owned[item.key];
|
||||
});
|
||||
seasonal.featured.items = itemsNotOwned;
|
||||
|
||||
// If we are out of gear, show the spells
|
||||
// @TODO: Open this up when they are available.
|
||||
// @TODO: add dates to check instead?
|
||||
// if (seasonal.featured.items.length === 0) {
|
||||
// this.featuredGearBought = true;
|
||||
// seasonal.featured.items = seasonal.featured.items.concat(seasonal.categories[0].items);
|
||||
// }
|
||||
|
||||
return seasonal;
|
||||
},
|
||||
seasonalCategories () {
|
||||
return this.seasonal.categories;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template lang='pug'>
|
||||
b-modal#broken-task-modal(title="Broken Challenge", size='sm', :hide-footer="true", v-if='brokenChallengeTask.challenge')
|
||||
b-modal#broken-task-modal(title="Broken Challenge", size='sm', :hide-footer="true", v-if='brokenChallengeTask && brokenChallengeTask.challenge')
|
||||
.modal-body
|
||||
div(v-if='brokenChallengeTask.challenge.broken === "TASK_DELETED" || brokenChallengeTask.challenge.broken === "CHALLENGE_TASK_NOT_FOUND"')
|
||||
h2 {{ $t('brokenTask') }}
|
||||
@@ -38,10 +38,14 @@ import notifications from 'client/mixins/notifications';
|
||||
|
||||
export default {
|
||||
mixins: [notifications],
|
||||
props: ['brokenChallengeTask'],
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
computed: {
|
||||
brokenChallengeTask () {
|
||||
return this.$store.state.brokenChallengeTask;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
destroyTask: 'tasks:destroy',
|
||||
@@ -70,6 +74,7 @@ export default {
|
||||
this.destroyTask(this.brokenChallengeTask);
|
||||
},
|
||||
close () {
|
||||
this.$store.state.brokenChallengeTask = {};
|
||||
this.$root.$emit('hide::modal', 'broken-task-modal');
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<template lang="pug">
|
||||
.task-wrapper
|
||||
broken-task-modal(:brokenChallengeTask='brokenChallengeTask')
|
||||
.task(@click='castEnd($event, task)')
|
||||
approval-header(:task='task', v-if='this.task.group.id', :group='group')
|
||||
.d-flex(:class="{'task-not-scoreable': isUser !== true}")
|
||||
@@ -17,7 +16,7 @@
|
||||
.task-clickable-area(@click="edit($event, task)")
|
||||
h3.task-title(:class="{ 'has-notes': task.notes }", v-markdown="task.text")
|
||||
.task-notes.small-text(v-markdown="task.notes")
|
||||
.checklist(v-if="task.checklist && task.checklist.length > 0")
|
||||
.checklist(v-if="canViewchecklist")
|
||||
label.custom-control.custom-checkbox.checklist-item(
|
||||
v-for="item in task.checklist", :class="{'checklist-item-done': item.completed}",
|
||||
)
|
||||
@@ -311,7 +310,6 @@ import checkIcon from 'assets/svg/check.svg';
|
||||
import bPopover from 'bootstrap-vue/lib/components/popover';
|
||||
import markdownDirective from 'client/directives/markdown';
|
||||
import notifications from 'client/mixins/notifications';
|
||||
import brokenTaskModal from './brokenTaskModal';
|
||||
import approvalHeader from './approvalHeader';
|
||||
import approvalFooter from './approvalFooter';
|
||||
|
||||
@@ -321,7 +319,6 @@ export default {
|
||||
bPopover,
|
||||
approvalFooter,
|
||||
approvalHeader,
|
||||
brokenTaskModal,
|
||||
},
|
||||
directives: {
|
||||
markdown: markdownDirective,
|
||||
@@ -339,7 +336,6 @@ export default {
|
||||
tags: tagsIcon,
|
||||
check: checkIcon,
|
||||
}),
|
||||
brokenChallengeTask: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -348,6 +344,11 @@ export default {
|
||||
getTagsFor: 'tasks:getTagsFor',
|
||||
getTaskClasses: 'tasks:getTaskClasses',
|
||||
}),
|
||||
canViewchecklist () {
|
||||
let hasChecklist = this.task.checklist && this.task.checklist.length > 0;
|
||||
let userIsTaskUser = this.task.userId ? this.task.userId === this.user._id : true;
|
||||
return hasChecklist && userIsTaskUser;
|
||||
},
|
||||
leftControl () {
|
||||
const task = this.task;
|
||||
if (task.type === 'reward') return false;
|
||||
@@ -505,7 +506,7 @@ export default {
|
||||
}
|
||||
},
|
||||
handleBrokenTask (task) {
|
||||
this.brokenChallengeTask = task;
|
||||
this.$store.state.brokenChallengeTask = task;
|
||||
this.$root.$emit('show::modal', 'broken-task-modal');
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template lang="pug">
|
||||
.row.user-tasks-page
|
||||
broken-task-modal
|
||||
task-modal(
|
||||
:task="editingTask || creatingTask",
|
||||
:purpose="creatingTask !== null ? 'create' : 'edit'",
|
||||
@@ -289,6 +290,7 @@ import throttle from 'lodash/throttle';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import { mapState, mapActions } from 'client/libs/store';
|
||||
import taskDefaults from 'common/script/libs/taskDefaults';
|
||||
import brokenTaskModal from './brokenTaskModal';
|
||||
|
||||
import Item from 'client/components/inventory/item.vue';
|
||||
|
||||
@@ -300,6 +302,7 @@ export default {
|
||||
bDropdownItem,
|
||||
Item,
|
||||
spells,
|
||||
brokenTaskModal,
|
||||
},
|
||||
directives: {
|
||||
markdown,
|
||||
@@ -412,6 +415,8 @@ export default {
|
||||
},
|
||||
createTask (type) {
|
||||
this.creatingTask = taskDefaults({type, text: ''});
|
||||
this.creatingTask.tags = this.selectedTags;
|
||||
|
||||
// Necessary otherwise the first time the modal is not rendered
|
||||
Vue.nextTick(() => {
|
||||
this.$root.$emit('show::modal', 'task-modal');
|
||||
|
||||
@@ -133,6 +133,7 @@ export default function () {
|
||||
notificationStore: [],
|
||||
modalStack: [],
|
||||
userIdToMessage: '',
|
||||
brokenChallengeTask: {},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -391,5 +391,7 @@
|
||||
"reverseChat": "Reverse Chat",
|
||||
"invites": "Invites",
|
||||
"details": "Details",
|
||||
"participantDesc": "Once all members have either accepted or declined, the Quest begins. Only those that clicked 'accept' will be able to participate in the Quest and receive the drops."
|
||||
"participantDesc": "Once all members have either accepted or declined, the Quest begins. Only those that clicked 'accept' will be able to participate in the Quest and receive the drops.",
|
||||
"groupGems": "Group Gems",
|
||||
"groupGemsDesc": "Guild Gems can be spent to make Challenges! In the future, you will be able to add more Guild Gems."
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
availableSpells: [
|
||||
// 'spookySparkles',
|
||||
'spookySparkles',
|
||||
],
|
||||
|
||||
availableQuests: [
|
||||
|
||||
Reference in New Issue
Block a user