feat(community): basic "report profile"
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
<creator-intro />
|
<creator-intro />
|
||||||
<profileModal />
|
<profileModal />
|
||||||
<report-flag-modal />
|
<report-flag-modal />
|
||||||
|
<report-member-modal />
|
||||||
<send-gift-modal />
|
<send-gift-modal />
|
||||||
<select-user-modal />
|
<select-user-modal />
|
||||||
<b-navbar
|
<b-navbar
|
||||||
@@ -732,6 +733,7 @@ import creatorIntro from '../creatorIntro';
|
|||||||
import notificationMenu from './notificationsDropdown';
|
import notificationMenu from './notificationsDropdown';
|
||||||
import profileModal from '../userMenu/profileModal';
|
import profileModal from '../userMenu/profileModal';
|
||||||
import reportFlagModal from '../chat/reportFlagModal';
|
import reportFlagModal from '../chat/reportFlagModal';
|
||||||
|
import reportMemberModal from '../members/reportMemberModal';
|
||||||
import sendGiftModal from '@/components/payments/sendGiftModal';
|
import sendGiftModal from '@/components/payments/sendGiftModal';
|
||||||
import selectUserModal from '@/components/payments/selectUserModal';
|
import selectUserModal from '@/components/payments/selectUserModal';
|
||||||
import sync from '@/mixins/sync';
|
import sync from '@/mixins/sync';
|
||||||
@@ -744,6 +746,7 @@ export default {
|
|||||||
notificationMenu,
|
notificationMenu,
|
||||||
profileModal,
|
profileModal,
|
||||||
reportFlagModal,
|
reportFlagModal,
|
||||||
|
reportMemberModal,
|
||||||
sendGiftModal,
|
sendGiftModal,
|
||||||
selectUserModal,
|
selectUserModal,
|
||||||
userDropdown,
|
userDropdown,
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
<template>
|
||||||
|
<b-modal
|
||||||
|
id="report-profile"
|
||||||
|
:title="$t('reportPlayer')"
|
||||||
|
size="md"
|
||||||
|
:hide-footer="true"
|
||||||
|
>
|
||||||
|
<div slot="modal-header">
|
||||||
|
<h2 class="mt-2 mb-0"> {{ $t('reportPlayer') }} </h2>
|
||||||
|
<close-x
|
||||||
|
@close="close()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<blockquote>
|
||||||
|
<strong> {{ displayName }} </strong>
|
||||||
|
<p class="mb-0"> {{ username }} </p>
|
||||||
|
</blockquote>
|
||||||
|
<div>
|
||||||
|
<strong>{{ $t('whyReportingPlayer') }}</strong>
|
||||||
|
<textarea
|
||||||
|
v-model="reportComment"
|
||||||
|
class="form-control"
|
||||||
|
:placeholder="$t('whyReportingPlayerPlaceholder')"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
class="mb-2"
|
||||||
|
v-html="$t('playerReportModalBody', abuseFlagModalBody)">
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="footer text-center d-flex flex-column">
|
||||||
|
<button
|
||||||
|
class="btn btn-danger mx-auto px-3 mb-4"
|
||||||
|
@click="reportAbuse()"
|
||||||
|
>
|
||||||
|
{{ $t('report') }}
|
||||||
|
</button>
|
||||||
|
<a
|
||||||
|
class="cancel-link"
|
||||||
|
@click.prevent="close()"
|
||||||
|
>{{ $t('cancel') }}</a>
|
||||||
|
</div>
|
||||||
|
</b-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
#report-profile {
|
||||||
|
.modal-header {
|
||||||
|
padding: 24px;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.modal-body {
|
||||||
|
padding: 0px 24px 24px 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '~@/assets/scss/colors.scss';
|
||||||
|
strong, p {
|
||||||
|
line-height: 1.71;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: $maroon-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-radius: 2px;
|
||||||
|
background-color: $gray-700;
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: solid 1px $gray-400;
|
||||||
|
min-height: 106px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding: 1rem 1rem 0rem 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import closeX from '@/components/ui/closeX';
|
||||||
|
import notifications from '@/mixins/notifications';
|
||||||
|
import markdownDirective from '@/directives/markdown';
|
||||||
|
import { userStateMixin } from '../../mixins/userState';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
closeX,
|
||||||
|
},
|
||||||
|
directives: {
|
||||||
|
markdown: markdownDirective,
|
||||||
|
},
|
||||||
|
mixins: [notifications, userStateMixin],
|
||||||
|
data () {
|
||||||
|
const abuseFlagModalBody = {
|
||||||
|
firstLinkStart: '<a href="/static/community-guidelines" target="_blank">',
|
||||||
|
secondLinkStart: '<a href="/static/terms" target="_blank">',
|
||||||
|
linkEnd: '</a>',
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
abuseFlagModalBody,
|
||||||
|
displayName: '',
|
||||||
|
username: '',
|
||||||
|
reportComment: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.$root.$on('habitica::report-profile', this.handleReport);
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
this.$root.$off('habitica::report-profile', this.handleReport);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
close () {
|
||||||
|
this.$root.$emit('bv::hide::modal', 'report-profile');
|
||||||
|
},
|
||||||
|
async reportAbuse () {
|
||||||
|
this.text(this.$t('abuseReported'));
|
||||||
|
|
||||||
|
const result = await this.$store.dispatch('members:reportMember', {
|
||||||
|
memberId: this.memberId,
|
||||||
|
source: this.$route.fullPath,
|
||||||
|
comment: this.reportComment,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$root.$emit('habitica:report-profile-result', result);
|
||||||
|
|
||||||
|
this.close();
|
||||||
|
},
|
||||||
|
handleReport (data) {
|
||||||
|
if (!data.memberId) return;
|
||||||
|
this.displayName = data.displayName;
|
||||||
|
this.username = `@${data.username}`;
|
||||||
|
this.memberId = data.memberId;
|
||||||
|
this.reportComment = '';
|
||||||
|
this.$root.$emit('bv::show::modal', 'report-profile');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -58,6 +58,18 @@
|
|||||||
v-html="icons.positive"
|
v-html="icons.positive"
|
||||||
></div>
|
></div>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="user._id !== userLoggedIn._id"
|
||||||
|
v-b-tooltip.hover.right="$t('reportPlayer')"
|
||||||
|
class="btn d-flex justify-content-center align-items-center"
|
||||||
|
@click="reportUser()"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-once
|
||||||
|
class="svg-icon block-icon color"
|
||||||
|
v-html="icons.report"
|
||||||
|
></div>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="hasPermission(userLoggedIn, 'moderator')"
|
v-if="hasPermission(userLoggedIn, 'moderator')"
|
||||||
v-b-tooltip.hover.right="'Admin - Toggle Tools'"
|
v-b-tooltip.hover.right="'Admin - Toggle Tools'"
|
||||||
@@ -523,6 +535,11 @@
|
|||||||
color: $gray-100;
|
color: $gray-100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.report-icon {
|
||||||
|
width: 16px;
|
||||||
|
color: $gray-100;
|
||||||
|
}
|
||||||
|
|
||||||
.photo img {
|
.photo img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
@@ -697,7 +714,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.info-item-value {
|
.info-item-value {
|
||||||
display: inline-block;
|
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -758,6 +774,7 @@ import lock from '@/assets/svg/lock.svg';
|
|||||||
import challenge from '@/assets/svg/challenge.svg';
|
import challenge from '@/assets/svg/challenge.svg';
|
||||||
import member from '@/assets/svg/member-icon.svg';
|
import member from '@/assets/svg/member-icon.svg';
|
||||||
import staff from '@/assets/svg/tier-staff.svg';
|
import staff from '@/assets/svg/tier-staff.svg';
|
||||||
|
import report from '@/assets/svg/report.svg';
|
||||||
import error404 from '../404';
|
import error404 from '../404';
|
||||||
import externalLinks from '../../mixins/externalLinks';
|
import externalLinks from '../../mixins/externalLinks';
|
||||||
import { userCustomStateMixin } from '../../mixins/userState';
|
import { userCustomStateMixin } from '../../mixins/userState';
|
||||||
@@ -788,6 +805,7 @@ export default {
|
|||||||
lock,
|
lock,
|
||||||
member,
|
member,
|
||||||
staff,
|
staff,
|
||||||
|
report,
|
||||||
}),
|
}),
|
||||||
adminToolsLoaded: false,
|
adminToolsLoaded: false,
|
||||||
userIdToMessage: '',
|
userIdToMessage: '',
|
||||||
@@ -1071,6 +1089,13 @@ export default {
|
|||||||
const status = this.achievementsCategories[categoryKey].open;
|
const status = this.achievementsCategories[categoryKey].open;
|
||||||
this.achievementsCategories[categoryKey].open = !status;
|
this.achievementsCategories[categoryKey].open = !status;
|
||||||
},
|
},
|
||||||
|
reportUser () {
|
||||||
|
this.$root.$emit('habitica::report-profile', {
|
||||||
|
memberId: this.user._id,
|
||||||
|
displayName: this.user.profile.name,
|
||||||
|
username: this.user.auth.local.username,
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -114,3 +114,13 @@ export async function getPurchaseHistory (store, payload) {
|
|||||||
const response = await axios.get(`${apiv4Prefix}/members/${payload.memberId}/purchase-history`);
|
const response = await axios.get(`${apiv4Prefix}/members/${payload.memberId}/purchase-history`);
|
||||||
return response.data.data;
|
return response.data.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function reportMember (store, payload) {
|
||||||
|
const url = `${apiv4Prefix}/members/${payload.memberId}/flag`;
|
||||||
|
const data = {
|
||||||
|
comment: payload.comment,
|
||||||
|
source: payload.source,
|
||||||
|
};
|
||||||
|
const response = await axios.post(url, data);
|
||||||
|
return response.data.data;
|
||||||
|
}
|
||||||
|
|||||||
@@ -222,5 +222,9 @@
|
|||||||
"question": "Question",
|
"question": "Question",
|
||||||
"questionDescriptionText": "It's okay to ask your questions in your primary language if you aren't comfortable speaking in English.",
|
"questionDescriptionText": "It's okay to ask your questions in your primary language if you aren't comfortable speaking in English.",
|
||||||
"questionPlaceholder": "Ask your question here",
|
"questionPlaceholder": "Ask your question here",
|
||||||
"submitQuestion": "Submit Question"
|
"submitQuestion": "Submit Question",
|
||||||
|
"reportPlayer": "Report Player",
|
||||||
|
"whyReportingPlayer": "Why are you reporting this player?",
|
||||||
|
"whyReportingPlayerPlaceholder": "Reason for report",
|
||||||
|
"playerReportModalBody": "You should only report a player who violates the <%= firstLinkStart %>Community Guidelines<%= linkEnd %> and/or <%= secondLinkStart %>Terms of Service<%= linkEnd %>. Submitting a false report is a violation of Habitica’s Community Guidelines."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export default class ProfileReporter extends ChatReporter {
|
|||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
notify (flaggedUser, comment) {
|
notify (flaggedUser, comment, source) {
|
||||||
let emailVariables = this.getEmailVariables(flaggedUser);
|
let emailVariables = this.getEmailVariables(flaggedUser);
|
||||||
emailVariables = emailVariables.concat([
|
emailVariables = emailVariables.concat([
|
||||||
{ name: 'REPORTER_COMMENT', content: comment || '' },
|
{ name: 'REPORTER_COMMENT', content: comment || '' },
|
||||||
@@ -93,7 +93,8 @@ export default class ProfileReporter extends ChatReporter {
|
|||||||
slack.sendProfileFlagNotification({
|
slack.sendProfileFlagNotification({
|
||||||
reporter: this.user,
|
reporter: this.user,
|
||||||
flaggedUser,
|
flaggedUser,
|
||||||
comment,
|
userComment: comment,
|
||||||
|
source,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -180,10 +180,11 @@ function sendProfileFlagNotification ({
|
|||||||
reporter,
|
reporter,
|
||||||
flaggedUser,
|
flaggedUser,
|
||||||
userComment,
|
userComment,
|
||||||
|
source,
|
||||||
}) {
|
}) {
|
||||||
const title = 'User Profile Report';
|
const title = 'User Profile Report';
|
||||||
const titleLink = `${BASE_URL}/static/front/#?memberId=${flaggedUser._id}`;
|
const titleLink = `${BASE_URL}/profile/${flaggedUser._id}`;
|
||||||
let text = `@${reporter.auth.local.username} (${reporter._id}; language: ${reporter.preferences.language}) flagged @${flaggedUser.auth.local.username}'s profile`;
|
let text = `@${reporter.auth.local.username} (${reporter._id}; language: ${reporter.preferences.language}) flagged @${flaggedUser.auth.local.username}'s profile from ${source}`;
|
||||||
if (userComment) {
|
if (userComment) {
|
||||||
text += ` and commented: ${userComment}`;
|
text += ` and commented: ${userComment}`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user