mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 06:37:23 +01:00
Sept 7 fixes (#9022)
* Fixed login incentives header * Added achievement hover * Removed grassy background from editing modal * Fixed loading of other user equipment * Prevented non admins from using habitica official * Fixed challenge loading and leader changing on group reload * Added community guidlines link * Added challenge cloning * Fixed heroes editing
This commit is contained in:
@@ -8,7 +8,7 @@ b-modal#login-incentives(:title="data.message", size='md', :hide-footer="true")
|
|||||||
.reward-wrap
|
.reward-wrap
|
||||||
div(v-if="nextReward.rewardKey.length === 1", :class="nextReward.rewardKey[0]")
|
div(v-if="nextReward.rewardKey.length === 1", :class="nextReward.rewardKey[0]")
|
||||||
.reward(v-for="reward in nextReward.rewardKey", v-if="nextReward.rewardKey.length > 1", :class='reward')
|
.reward(v-for="reward in nextReward.rewardKey", v-if="nextReward.rewardKey.length > 1", :class='reward')
|
||||||
div(v-if="data.nextRewardAt")
|
.col-12.text-center(v-if="data.nextRewardAt")
|
||||||
h4 {{ $t('countLeft', {count: data.nextRewardAt - user.loginIncentives}) }}
|
h4 {{ $t('countLeft', {count: data.nextRewardAt - user.loginIncentives}) }}
|
||||||
.row
|
.row
|
||||||
.col-8.offset-2.text-center
|
.col-8.offset-2.text-center
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
.row
|
.row
|
||||||
challenge-modal(:challenge='challenge', v-on:updatedChallenge='updatedChallenge')
|
challenge-modal(:challenge='challenge', :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')
|
||||||
|
|
||||||
@@ -68,6 +68,8 @@
|
|||||||
button.btn.btn-danger(v-once, @click='closeChallenge()') {{$t('endChallenge')}}
|
button.btn.btn-danger(v-once, @click='closeChallenge()') {{$t('endChallenge')}}
|
||||||
div(v-if='isLeader')
|
div(v-if='isLeader')
|
||||||
button.btn.btn-secondary(v-once, @click='exportChallengeCsv()') {{$t('exportChallengeCsv')}}
|
button.btn.btn-secondary(v-once, @click='exportChallengeCsv()') {{$t('exportChallengeCsv')}}
|
||||||
|
div(v-if='isLeader')
|
||||||
|
button.btn.btn-secondary(v-once, @click='cloneChallenge()') {{$t('clone')}}
|
||||||
.description-section
|
.description-section
|
||||||
h2 {{$t('challengeSummary')}}
|
h2 {{$t('challengeSummary')}}
|
||||||
p {{challenge.summary}}
|
p {{challenge.summary}}
|
||||||
@@ -162,11 +164,15 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
const TASK_KEYS_TO_REMOVE = ['_id', 'completed', 'date', 'dateCompleted', 'history', 'id', 'streak', 'createdAt', 'challenge'];
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
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';
|
||||||
import findIndex from 'lodash/findIndex';
|
import findIndex from 'lodash/findIndex';
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import uuid from 'uuid';
|
||||||
|
|
||||||
import { mapState } from 'client/libs/store';
|
import { mapState } from 'client/libs/store';
|
||||||
import closeChallengeModal from './closeChallengeModal';
|
import closeChallengeModal from './closeChallengeModal';
|
||||||
@@ -194,12 +200,14 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
searchId: '',
|
||||||
columns: ['habit', 'daily', 'todo', 'reward'],
|
columns: ['habit', 'daily', 'todo', 'reward'],
|
||||||
icons: Object.freeze({
|
icons: Object.freeze({
|
||||||
gemIcon,
|
gemIcon,
|
||||||
memberIcon,
|
memberIcon,
|
||||||
calendarIcon,
|
calendarIcon,
|
||||||
}),
|
}),
|
||||||
|
cloning: false,
|
||||||
challenge: {},
|
challenge: {},
|
||||||
members: [],
|
members: [],
|
||||||
tasksByType: {
|
tasksByType: {
|
||||||
@@ -225,15 +233,69 @@ export default {
|
|||||||
return this.user._id === this.challenge.leader._id;
|
return this.user._id === this.challenge.leader._id;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
async mounted () {
|
mounted () {
|
||||||
this.challenge = await this.$store.dispatch('challenges:getChallenge', {challengeId: this.challengeId});
|
if (!this.searchId) this.searchId = this.challengeId;
|
||||||
this.members = await this.$store.dispatch('members:getChallengeMembers', {challengeId: this.challengeId});
|
if (!this.challenge._id) this.loadChallenge();
|
||||||
let tasks = await this.$store.dispatch('tasks:getChallengeTasks', {challengeId: this.challengeId});
|
},
|
||||||
|
async beforeRouteUpdate (to, from, next) {
|
||||||
|
this.searchId = to.params.challengeId;
|
||||||
|
await this.loadChallenge();
|
||||||
|
|
||||||
|
if (this.$store.state.challengeOptions.cloning) {
|
||||||
|
this.cloneTasks(this.$store.state.challengeOptions.tasksToClone);
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
cleanUpTask (task) {
|
||||||
|
let cleansedTask = omit(task, TASK_KEYS_TO_REMOVE);
|
||||||
|
|
||||||
|
// Copy checklists but reset to uncomplete and assign new id
|
||||||
|
if (!cleansedTask.checklist) cleansedTask.checklist = [];
|
||||||
|
cleansedTask.checklist.forEach((item) => {
|
||||||
|
item.completed = false;
|
||||||
|
item.id = uuid();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cleansedTask.type !== 'reward') {
|
||||||
|
delete cleansedTask.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cleansedTask;
|
||||||
|
},
|
||||||
|
cloneTasks (tasksToClone) {
|
||||||
|
let clonedTasks = [];
|
||||||
|
|
||||||
|
for (let key in tasksToClone) {
|
||||||
|
let tasksSection = tasksToClone[key];
|
||||||
|
tasksSection.forEach(task => {
|
||||||
|
let clonedTask = cloneDeep(task);
|
||||||
|
clonedTask = this.cleanUpTask(clonedTask);
|
||||||
|
clonedTask = taskDefaults(clonedTask);
|
||||||
|
this.tasksByType[task.type].push(clonedTask);
|
||||||
|
clonedTasks.push(clonedTask);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$store.dispatch('tasks:createChallengeTasks', {
|
||||||
|
challengeId: this.searchId,
|
||||||
|
tasks: clonedTasks,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async loadChallenge () {
|
||||||
|
this.challenge = await this.$store.dispatch('challenges:getChallenge', {challengeId: this.searchId});
|
||||||
|
this.members = await this.$store.dispatch('members:getChallengeMembers', {challengeId: this.searchId});
|
||||||
|
let tasks = await this.$store.dispatch('tasks:getChallengeTasks', {challengeId: this.searchId});
|
||||||
|
this.tasksByType = {
|
||||||
|
habit: [],
|
||||||
|
daily: [],
|
||||||
|
todo: [],
|
||||||
|
reward: [],
|
||||||
|
};
|
||||||
tasks.forEach((task) => {
|
tasks.forEach((task) => {
|
||||||
this.tasksByType[task.type].push(task);
|
this.tasksByType[task.type].push(task);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
editTask (task) {
|
editTask (task) {
|
||||||
this.taskFormPurpose = 'edit';
|
this.taskFormPurpose = 'edit';
|
||||||
this.editingTask = cloneDeep(task);
|
this.editingTask = cloneDeep(task);
|
||||||
@@ -272,8 +334,8 @@ export default {
|
|||||||
this.$root.$emit('show::modal', 'members-modal');
|
this.$root.$emit('show::modal', 'members-modal');
|
||||||
},
|
},
|
||||||
async joinChallenge () {
|
async joinChallenge () {
|
||||||
this.user.challenges.push(this.challengeId);
|
this.user.challenges.push(this.searchId);
|
||||||
await this.$store.dispatch('challenges:joinChallenge', {challengeId: this.challengeId});
|
await this.$store.dispatch('challenges:joinChallenge', {challengeId: this.searchId});
|
||||||
// @TODO: this doesn't work because of asyncresource
|
// @TODO: this doesn't work because of asyncresource
|
||||||
let tasks = await this.$store.dispatch('tasks:fetchUserTasks');
|
let tasks = await this.$store.dispatch('tasks:fetchUserTasks');
|
||||||
this.$store.state.tasks.data = tasks.data;
|
this.$store.state.tasks.data = tasks.data;
|
||||||
@@ -284,11 +346,11 @@ export default {
|
|||||||
if (!keepChallenge) keep = 'remove-all';
|
if (!keepChallenge) keep = 'remove-all';
|
||||||
|
|
||||||
let index = findIndex(this.user.challenges, (challengeId) => {
|
let index = findIndex(this.user.challenges, (challengeId) => {
|
||||||
return challengeId === this.challengeId;
|
return challengeId === this.searchId;
|
||||||
});
|
});
|
||||||
this.user.challenges.splice(index, 1);
|
this.user.challenges.splice(index, 1);
|
||||||
await this.$store.dispatch('challenges:leaveChallenge', {
|
await this.$store.dispatch('challenges:leaveChallenge', {
|
||||||
challengeId: this.challengeId,
|
challengeId: this.searchId,
|
||||||
keep,
|
keep,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -297,6 +359,7 @@ export default {
|
|||||||
},
|
},
|
||||||
edit () {
|
edit () {
|
||||||
// @TODO: set working challenge
|
// @TODO: set working challenge
|
||||||
|
this.cloning = false;
|
||||||
this.$root.$emit('show::modal', 'challenge-modal');
|
this.$root.$emit('show::modal', 'challenge-modal');
|
||||||
},
|
},
|
||||||
// @TODO: view members
|
// @TODO: view members
|
||||||
@@ -309,9 +372,14 @@ export default {
|
|||||||
},
|
},
|
||||||
async exportChallengeCsv () {
|
async exportChallengeCsv () {
|
||||||
// let response = await this.$store.dispatch('challenges:exportChallengeCsv', {
|
// let response = await this.$store.dispatch('challenges:exportChallengeCsv', {
|
||||||
// challengeId: this.challengeId,
|
// challengeId: this.searchId,
|
||||||
// });
|
// });
|
||||||
window.location = `/api/v3/challenges/${this.challengeId}/export/csv`;
|
window.location = `/api/v3/challenges/${this.searchId}/export/csv`;
|
||||||
|
},
|
||||||
|
cloneChallenge () {
|
||||||
|
this.cloning = true;
|
||||||
|
this.$store.state.challengeOptions.tasksToClone = this.tasksByType;
|
||||||
|
this.$root.$emit('show::modal', 'challenge-modal');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
b-modal#challenge-modal(:title="$t('createChallenge')", size='lg')
|
b-modal#challenge-modal(:title="title", size='lg')
|
||||||
.form
|
.form
|
||||||
.form-group
|
.form-group
|
||||||
label
|
label
|
||||||
@@ -137,7 +137,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'],
|
props: ['challenge', 'groupId', 'cloning'],
|
||||||
components: {
|
components: {
|
||||||
bModal,
|
bModal,
|
||||||
bDropdown,
|
bDropdown,
|
||||||
@@ -210,7 +210,6 @@ export default {
|
|||||||
let categoriesHashByKey = hashedCategories;
|
let categoriesHashByKey = hashedCategories;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
creating: true,
|
|
||||||
workingChallenge: {
|
workingChallenge: {
|
||||||
name: '',
|
name: '',
|
||||||
summary: '',
|
summary: '',
|
||||||
@@ -234,21 +233,6 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
async mounted () {
|
async mounted () {
|
||||||
this.$root.$on('shown::modal', () => {
|
|
||||||
if (this.challenge) {
|
|
||||||
this.workingChallenge = Object.assign(this.workingChallenge, this.challenge);
|
|
||||||
this.workingChallenge.categories = [];
|
|
||||||
|
|
||||||
if (this.challenge.categories) {
|
|
||||||
this.challenge.categories.forEach(category => {
|
|
||||||
this.workingChallenge.categories.push(category.slug);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.creating = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.groups = await this.$store.dispatch('guilds:getMyGuilds');
|
this.groups = await this.$store.dispatch('guilds:getMyGuilds');
|
||||||
if (this.user.party._id) {
|
if (this.user.party._id) {
|
||||||
let party = await this.$store.dispatch('guilds:getGroup', {groupId: 'party'});
|
let party = await this.$store.dispatch('guilds:getGroup', {groupId: 'party'});
|
||||||
@@ -265,14 +249,31 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.resetWorkingChallenge();
|
this.resetWorkingChallenge();
|
||||||
|
this.setUpWorkingChallenge();
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
user () {
|
user () {
|
||||||
if (!this.challenge) this.workingChallenge.leader = this.user._id;
|
if (!this.challenge) this.workingChallenge.leader = this.user._id;
|
||||||
},
|
},
|
||||||
|
challenge () {
|
||||||
|
this.setUpWorkingChallenge();
|
||||||
|
},
|
||||||
|
cloning () {
|
||||||
|
this.setUpWorkingChallenge();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({user: 'user.data'}),
|
...mapState({user: 'user.data'}),
|
||||||
|
creating () {
|
||||||
|
return !this.workingChallenge.id;
|
||||||
|
},
|
||||||
|
title () {
|
||||||
|
if (this.creating) {
|
||||||
|
return this.$t('createChallenge');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.$t('editingChallenge');
|
||||||
|
},
|
||||||
charactersRemaining () {
|
charactersRemaining () {
|
||||||
let currentLength = this.workingChallenge.summary ? this.workingChallenge.summary.length : 0;
|
let currentLength = this.workingChallenge.summary ? this.workingChallenge.summary.length : 0;
|
||||||
return MAX_SUMMARY_SIZE_FOR_CHALLENGES - currentLength;
|
return MAX_SUMMARY_SIZE_FOR_CHALLENGES - currentLength;
|
||||||
@@ -320,6 +321,23 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setUpWorkingChallenge () {
|
||||||
|
if (!this.challenge) return;
|
||||||
|
|
||||||
|
this.workingChallenge = Object.assign({}, this.workingChallenge, this.challenge);
|
||||||
|
this.workingChallenge.categories = [];
|
||||||
|
|
||||||
|
if (this.challenge.categories) {
|
||||||
|
this.challenge.categories.forEach(category => {
|
||||||
|
this.workingChallenge.categories.push(category.slug);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.cloning) {
|
||||||
|
this.$delete(this.workingChallenge, '_id');
|
||||||
|
this.$delete(this.workingChallenge, 'id');
|
||||||
|
}
|
||||||
|
},
|
||||||
resetWorkingChallenge () {
|
resetWorkingChallenge () {
|
||||||
this.workingChallenge = {
|
this.workingChallenge = {
|
||||||
name: '',
|
name: '',
|
||||||
@@ -369,6 +387,9 @@ export default {
|
|||||||
|
|
||||||
this.$emit('createChallenge', challenge);
|
this.$emit('createChallenge', challenge);
|
||||||
this.resetWorkingChallenge();
|
this.resetWorkingChallenge();
|
||||||
|
|
||||||
|
if (this.cloning) this.$store.state.challengeOptions.cloning = true;
|
||||||
|
|
||||||
this.$root.$emit('hide::modal', 'challenge-modal');
|
this.$root.$emit('hide::modal', 'challenge-modal');
|
||||||
this.$router.push(`/challenges/${challenge._id}`);
|
this.$router.push(`/challenges/${challenge._id}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,11 +95,6 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
...mapState({user: 'user.data'}),
|
...mapState({user: 'user.data'}),
|
||||||
},
|
},
|
||||||
async mounted () {
|
|
||||||
this.groupIdForChallenges = this.groupId;
|
|
||||||
if (this.groupId === 'party' && this.user.party._id) this.groupIdForChallenges = this.user.party._id;
|
|
||||||
this.challenges = await this.$store.dispatch('challenges:getGroupChallenges', {groupId: this.groupIdForChallenges});
|
|
||||||
},
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
challenges: [],
|
challenges: [],
|
||||||
@@ -111,6 +106,13 @@ export default {
|
|||||||
groupIdForChallenges: '',
|
groupIdForChallenges: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
async groupId () {
|
||||||
|
this.groupIdForChallenges = this.groupId;
|
||||||
|
if (this.groupId === 'party' && this.user.party._id) this.groupIdForChallenges = this.user.party._id;
|
||||||
|
this.challenges = await this.$store.dispatch('challenges:getGroupChallenges', {groupId: this.groupIdForChallenges});
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
createChallenge () {
|
createChallenge () {
|
||||||
this.$root.$emit('show::modal', 'challenge-modal');
|
this.$root.$emit('show::modal', 'challenge-modal');
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
|
|||||||
|
|
||||||
.section.avatar-section.row(:class='{"page-2": modalPage === 2}')
|
.section.avatar-section.row(:class='{"page-2": modalPage === 2}')
|
||||||
.col-6.offset-3
|
.col-6.offset-3
|
||||||
.user-creation-bg
|
.user-creation-bg(v-if='!editing')
|
||||||
avatar(:member='user', :avatarOnly='!editing')
|
avatar(:member='user', :avatarOnly='!editing')
|
||||||
|
|
||||||
.section(v-if='modalPage === 2')
|
.section(v-if='modalPage === 2')
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
.row(v-if="group")
|
.row(v-if="group._id")
|
||||||
group-form-modal(v-if='isParty')
|
group-form-modal(v-if='isParty')
|
||||||
invite-modal(:group='this.group')
|
invite-modal(:group='this.group')
|
||||||
start-quest-modal(:group='this.group')
|
start-quest-modal(:group='this.group')
|
||||||
@@ -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-once, v-if='group.leader.profile') : {{group.leader.profile.name}}
|
span.float-left(v-if='group.leader.profile') : {{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 }")
|
||||||
@@ -461,8 +461,8 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
searchId: null,
|
searchId: '',
|
||||||
group: null,
|
group: {},
|
||||||
icons: Object.freeze({
|
icons: Object.freeze({
|
||||||
like: likeIcon,
|
like: likeIcon,
|
||||||
copy: copyIcon,
|
copy: copyIcon,
|
||||||
@@ -568,7 +568,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeRouteUpdate (to, from, next) {
|
beforeRouteUpdate (to, from, next) {
|
||||||
this.searchId = to.params.groupId;
|
this.$set(this, 'searchId', to.params.groupId);
|
||||||
next();
|
next();
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -665,7 +665,8 @@ export default {
|
|||||||
this.checkForAchievements();
|
this.checkForAchievements();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.group = group;
|
|
||||||
|
this.$set(this, 'group', group);
|
||||||
},
|
},
|
||||||
deleteAllMessages () {
|
deleteAllMessages () {
|
||||||
if (confirm(this.$t('confirmDeleteAllMessages'))) {
|
if (confirm(this.$t('confirmDeleteAllMessages'))) {
|
||||||
|
|||||||
@@ -80,6 +80,7 @@
|
|||||||
.form-check(
|
.form-check(
|
||||||
v-for="group in categoryOptions",
|
v-for="group in categoryOptions",
|
||||||
:key="group.key",
|
:key="group.key",
|
||||||
|
v-if='group.key !== "habitica_official" || user.contributor.admin'
|
||||||
)
|
)
|
||||||
label.custom-control.custom-checkbox
|
label.custom-control.custom-checkbox
|
||||||
input.custom-control-input(type="checkbox", :value="group.key", v-model="workingGroup.categories")
|
input.custom-control-input(type="checkbox", :value="group.key", v-model="workingGroup.categories")
|
||||||
@@ -174,6 +175,7 @@ import bFormCheckbox from 'bootstrap-vue/lib/components/form-checkbox';
|
|||||||
import bFormSelect from 'bootstrap-vue/lib/components/form-select';
|
import bFormSelect from 'bootstrap-vue/lib/components/form-select';
|
||||||
import bTooltip from 'bootstrap-vue/lib/components/tooltip';
|
import bTooltip from 'bootstrap-vue/lib/components/tooltip';
|
||||||
|
|
||||||
|
import { mapState } from 'client/libs/store';
|
||||||
import toggleSwitch from 'client/components/ui/toggleSwitch';
|
import toggleSwitch from 'client/components/ui/toggleSwitch';
|
||||||
import gemIcon from 'assets/svg/gem.svg';
|
import gemIcon from 'assets/svg/gem.svg';
|
||||||
import informationIcon from 'assets/svg/information.svg';
|
import informationIcon from 'assets/svg/information.svg';
|
||||||
@@ -294,6 +296,7 @@ export default {
|
|||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapState({user: 'user.data'}),
|
||||||
editingGroup () {
|
editingGroup () {
|
||||||
return this.$store.state.editingGroup;
|
return this.$store.state.editingGroup;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -119,9 +119,11 @@ export default {
|
|||||||
let user = this.$store.state.user.data;
|
let user = this.$store.state.user.data;
|
||||||
let filterGuild = this.filterGuild;
|
let filterGuild = this.filterGuild;
|
||||||
return this.guilds.filter((guild) => {
|
return this.guilds.filter((guild) => {
|
||||||
|
if (guild.categories) {
|
||||||
guild.categorySlugs = guild.categories.map(cat => {
|
guild.categorySlugs = guild.categories.map(cat => {
|
||||||
return cat.slug;
|
return cat.slug;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return filterGuild(guild, filters, search, user);
|
return filterGuild(guild, filters, search, user);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
button.btn.btn-secondary.send-chat.float-right(v-once, @click='sendMessage()') {{ $t('send') }}
|
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') }}
|
button.btn.btn-secondary.float-left(v-once, @click='fetchRecentMessages()') {{ $t('fetchRecentMessages') }}
|
||||||
|
|
||||||
.row.community-guidelines(v-if='!communityGuidelinesAccepted')
|
.row.community-guidelines(v-if='true || !communityGuidelinesAccepted')
|
||||||
div.col-8(v-once) {{ $t('communityGuidelinesIntro') }}
|
div.col-8(v-once, v-html="$t('communityGuidelinesIntro')")
|
||||||
div.col-4
|
div.col-4
|
||||||
button.btn.btn-info(@click='acceptCommunityGuidelines()', v-once) {{ $t('acceptCommunityGuidelines') }}
|
button.btn.btn-info(@click='acceptCommunityGuidelines()', v-once) {{ $t('acceptCommunityGuidelines') }}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
// h4 Backer Status
|
// h4 Backer Status
|
||||||
// Add backer stuff like tier, disable adds, etcs
|
// Add backer stuff like tier, disable adds, etcs
|
||||||
.form-group
|
.form-group
|
||||||
button.form-control.btn.btn-primary
|
button.form-control.btn.btn-primary(@click='saveHero()')
|
||||||
| {{ $t('save') }}
|
| {{ $t('save') }}
|
||||||
|
|
||||||
.table-responsive
|
.table-responsive
|
||||||
@@ -104,8 +104,10 @@ import quests from 'common/script/content/quests';
|
|||||||
import { mountInfo, petInfo } from 'common/script/content/stable';
|
import { mountInfo, petInfo } from 'common/script/content/stable';
|
||||||
import { food, hatchingPotions, special } from 'common/script/content';
|
import { food, hatchingPotions, special } from 'common/script/content';
|
||||||
import gear from 'common/script/content/gear';
|
import gear from 'common/script/content/gear';
|
||||||
|
import notifications from 'client/mixins/notifications';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [notifications],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
heroes: [],
|
heroes: [],
|
||||||
@@ -162,13 +164,17 @@ export default {
|
|||||||
async loadHero (uuid, heroIndex) {
|
async loadHero (uuid, heroIndex) {
|
||||||
this.currentHeroIndex = heroIndex;
|
this.currentHeroIndex = heroIndex;
|
||||||
let hero = await this.$store.dispatch('hall:getHero', { uuid });
|
let hero = await this.$store.dispatch('hall:getHero', { uuid });
|
||||||
this.hero = hero;
|
this.hero = Object.assign({}, this.hero, hero);
|
||||||
|
if (!this.hero.flags) {
|
||||||
|
this.hero.flags = {
|
||||||
|
chatRevoked: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async saveHero (hero) {
|
async saveHero () {
|
||||||
this.hero.contributor.admin = this.hero.contributor.level > 7 ? true : false;
|
this.hero.contributor.admin = this.hero.contributor.level > 7 ? true : false;
|
||||||
let heroUpdated = await this.$store.dispatch('hall:updateHero', { heroDetails: hero });
|
let heroUpdated = await this.$store.dispatch('hall:updateHero', { heroDetails: this.hero });
|
||||||
// @TODO: Import
|
this.text('User updated');
|
||||||
// Notification.text("User updated");
|
|
||||||
this.hero = {};
|
this.hero = {};
|
||||||
this.heroID = -1;
|
this.heroID = -1;
|
||||||
this.heroes[this.currentHeroIndex] = heroUpdated;
|
this.heroes[this.currentHeroIndex] = heroUpdated;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ div
|
|||||||
.nav-item(@click='selectedPage = "profile"', :class="{active: selectedPage === 'profile'}") Profile
|
.nav-item(@click='selectedPage = "profile"', :class="{active: selectedPage === 'profile'}") Profile
|
||||||
.nav-item(@click='selectedPage = "stats"', :class="{active: selectedPage === 'stats'}") Stats
|
.nav-item(@click='selectedPage = "stats"', :class="{active: selectedPage === 'stats'}") Stats
|
||||||
.nav-item(@click='selectedPage = "achievements"', :class="{active: selectedPage === 'achievements'}") Achievements
|
.nav-item(@click='selectedPage = "achievements"', :class="{active: selectedPage === 'achievements'}") Achievements
|
||||||
.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
|
||||||
.header
|
.header
|
||||||
@@ -91,14 +91,9 @@ div
|
|||||||
#achievements.standard-page.container(v-show='selectedPage === "achievements"', v-if='user.achievements')
|
#achievements.standard-page.container(v-show='selectedPage === "achievements"', v-if='user.achievements')
|
||||||
.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='achievment in category.achievements')
|
.col-3.text-center(v-for='(achievment, key) in category.achievements')
|
||||||
.box.achievement-container(:class='{"achievement-unearned": !achievment.earned}', :data-popover-html='achievment.title + achievment.text',
|
.box.achievement-container(:id='key', :class='{"achievement-unearned": !achievment.earned}')
|
||||||
popover-placement='achievPopoverPlacement',
|
b-popover(:target="'#' + key", triggers="hover", placement="top", :content="achievment.title + achievment.text")
|
||||||
popover-append-to-body='achievAppendToBody')
|
|
||||||
div(popover-trigger='mouseenter',
|
|
||||||
:data-popover-html='achievment.title + achievment.text',
|
|
||||||
popover-placement='achievPopoverPlacement',
|
|
||||||
popover-append-to-body='achievAppendToBody')
|
|
||||||
.achievement(:class='achievment.icon + "2x"', v-if='achievment.earned')
|
.achievement(:class='achievment.icon + "2x"', v-if='achievment.earned')
|
||||||
.counter.badge.badge-info.stack-count(v-if='achievment.optionalCount') {{achievment.optionalCount}}
|
.counter.badge.badge-info.stack-count(v-if='achievment.optionalCount') {{achievment.optionalCount}}
|
||||||
.achievement.achievement-unearned(class='achievement-unearned2x', v-if='!achievment.earned')
|
.achievement.achievement-unearned(class='achievement-unearned2x', v-if='!achievment.earned')
|
||||||
@@ -548,6 +543,7 @@ import autoAllocate from '../../../common/script/fns/autoAllocate';
|
|||||||
import allocate from '../../../common/script/ops/allocate';
|
import allocate from '../../../common/script/ops/allocate';
|
||||||
|
|
||||||
import MemberDetails from '../memberDetails';
|
import MemberDetails from '../memberDetails';
|
||||||
|
import bPopover from 'bootstrap-vue/lib/components/popover';
|
||||||
import privateMessageModal from 'client/components/private-message-modal';
|
import privateMessageModal from 'client/components/private-message-modal';
|
||||||
import sendGemsModal from 'client/components/payments/sendGemsModal';
|
import sendGemsModal from 'client/components/payments/sendGemsModal';
|
||||||
import markdown from 'client/directives/markdown';
|
import markdown from 'client/directives/markdown';
|
||||||
@@ -573,6 +569,7 @@ export default {
|
|||||||
sendGemsModal,
|
sendGemsModal,
|
||||||
MemberDetails,
|
MemberDetails,
|
||||||
toggleSwitch,
|
toggleSwitch,
|
||||||
|
bPopover,
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
@@ -625,9 +622,13 @@ export default {
|
|||||||
...mapState({
|
...mapState({
|
||||||
userLoggedIn: 'user.data',
|
userLoggedIn: 'user.data',
|
||||||
flatGear: 'content.gear.flat',
|
flatGear: 'content.gear.flat',
|
||||||
equippedItems: 'user.data.items.gear.equipped',
|
|
||||||
costumeItems: 'user.data.items.gear.costume',
|
|
||||||
}),
|
}),
|
||||||
|
equippedItems () {
|
||||||
|
return this.user.items.gear.equipped;
|
||||||
|
},
|
||||||
|
costumeItems () {
|
||||||
|
return this.user.items.gear.costume;
|
||||||
|
},
|
||||||
user () {
|
user () {
|
||||||
let user = this.userLoggedIn;
|
let user = this.userLoggedIn;
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ export async function getHero (store, payload) {
|
|||||||
|
|
||||||
export async function updateHero (store, payload) {
|
export async function updateHero (store, payload) {
|
||||||
let url = `/api/v3/hall/heroes/${payload.heroDetails._id}`;
|
let url = `/api/v3/hall/heroes/${payload.heroDetails._id}`;
|
||||||
let response = await axios.put(url, {
|
let response = await axios.put(url, payload.heroDetails);
|
||||||
heroDetails: payload.heroDetails,
|
|
||||||
});
|
|
||||||
return response.data.data;
|
return response.data.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,10 @@ export default function () {
|
|||||||
message: {},
|
message: {},
|
||||||
groupId: '',
|
groupId: '',
|
||||||
},
|
},
|
||||||
|
challengeOptions: {
|
||||||
|
cloning: false,
|
||||||
|
tasksToClone: {},
|
||||||
|
},
|
||||||
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
|
||||||
// TODO apply freezing to the entire codebase (the server) and not only to the client side?
|
// TODO apply freezing to the entire codebase (the server) and not only to the client side?
|
||||||
|
|||||||
@@ -115,5 +115,6 @@
|
|||||||
"updateChallenge": "Update Challenge",
|
"updateChallenge": "Update Challenge",
|
||||||
"haveNoChallenges": "You don't have any Challenges",
|
"haveNoChallenges": "You don't have any Challenges",
|
||||||
"loadMore": "Load More",
|
"loadMore": "Load More",
|
||||||
"exportChallengeCsv": "Export Challenge"
|
"exportChallengeCsv": "Export Challenge",
|
||||||
|
"editingChallenge": "Editing Challenge"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
"pauseDailies": "Pause Damage",
|
"pauseDailies": "Pause Damage",
|
||||||
"unpauseDailies": "Unpause Damage",
|
"unpauseDailies": "Unpause Damage",
|
||||||
"staffAndModerators": "Staff and Moderators",
|
"staffAndModerators": "Staff and Moderators",
|
||||||
"communityGuidelinesIntro": "Habitica tries to create a welcoming environment for users of all ages and backgrounds, especially in public spaces like the Tavern. If you have any questions, please consult our Community Guidelines.",
|
"communityGuidelinesIntro": "Habitica tries to create a welcoming environment for users of all ages and backgrounds, especially in public spaces like the Tavern. If you have any questions, please consult our <a href='/static/community-guidelines' target='_blank'>Community Guidelines</a>.",
|
||||||
"acceptCommunityGuidelines": "I agree to follow the Community Guidelines",
|
"acceptCommunityGuidelines": "I agree to follow the Community Guidelines",
|
||||||
"daniel": "Daniel",
|
"daniel": "Daniel",
|
||||||
"danielText": "Welcome to the Tavern! Stay a while and meet the locals. If you need to rest (vacation? illness?), I'll set you up at the Inn. While checked-in, your Dailies won't hurt you at the day's end, but you can still check them off.",
|
"danielText": "Welcome to the Tavern! Stay a while and meet the locals. If you need to rest (vacation? illness?), I'll set you up at the Inn. While checked-in, your Dailies won't hurt you at the day's end, but you can still check them off.",
|
||||||
|
|||||||
Reference in New Issue
Block a user