mirror of
https://github.com/wassname/talk.git
synced 2026-07-12 01:07:03 +08:00
Karma
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
.karmaTooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 16px;
|
||||
color: #0D5B8F;
|
||||
-ms-user-select:none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-touch-callout:none;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color:rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
.icon:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu {
|
||||
background-color: white;
|
||||
border: solid 1px #999;
|
||||
border-radius: 3px;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
-webkit-box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
|
||||
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
|
||||
z-index: 10;
|
||||
top: 32px;
|
||||
left: -100px;
|
||||
width: 150px;
|
||||
text-align: left;
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
.menu::before{
|
||||
content: '';
|
||||
border: 10px solid transparent;
|
||||
border-top-color: #999;
|
||||
position: absolute;
|
||||
left: 96px;
|
||||
top: -20px;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.menu::after{
|
||||
content: '';
|
||||
border: 10px solid transparent;
|
||||
border-top-color: white;
|
||||
position: absolute;
|
||||
left: 96px;
|
||||
top: -19px;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.descriptionList {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.strongItem {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.descriptionItem {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #2B7EB5;
|
||||
text-decoration: underline;
|
||||
display: block;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
import { Icon } from 'coral-ui';
|
||||
import styles from './KarmaTooltip.css';
|
||||
import ClickOutside from 'coral-framework/components/ClickOutside';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
const initialState = { menuVisible: false };
|
||||
|
||||
class KarmaTooltip extends React.Component {
|
||||
state = initialState;
|
||||
|
||||
toogleMenu = () => {
|
||||
this.setState({ menuVisible: !this.state.menuVisible });
|
||||
};
|
||||
|
||||
hideMenu = () => {
|
||||
this.setState({ menuVisible: false });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { menuVisible } = this.state;
|
||||
|
||||
return (
|
||||
<ClickOutside onClickOutside={this.hideMenu}>
|
||||
<div className={cn(styles.karmaTooltip, 'talk-admin-karma-tooltip')}>
|
||||
<span
|
||||
onClick={this.toogleMenu}
|
||||
className={cn(styles.icon, 'talk-admin-karma-tooltip-icon')}
|
||||
>
|
||||
<Icon name="info" />
|
||||
</span>
|
||||
|
||||
{menuVisible && (
|
||||
<div className={cn(styles.menu, 'talk-admin-karma-tooltip-menu')}>
|
||||
<strong>{t('user_detail.user_karma_score')}</strong>
|
||||
<a
|
||||
className={styles.link}
|
||||
href={t('user_detail.karma_docs_link')}
|
||||
target="_blank"
|
||||
>
|
||||
{t('user_detail.learn_more')}
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</ClickOutside>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default KarmaTooltip;
|
||||
@@ -39,17 +39,16 @@
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.statItem,
|
||||
.statReportResult {
|
||||
.statItem, .statReportResult, .statKarmaResult {
|
||||
padding: 3px 5px;
|
||||
background-color: #D8D8D8;
|
||||
border-radius: 3px;
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
font-size: 0.9em;
|
||||
line-height: normal;
|
||||
letter-spacing: 0.4px;
|
||||
min-width: 60px;
|
||||
min-width: 35px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.statResult {
|
||||
@@ -58,21 +57,21 @@
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.statReportResult {
|
||||
.statReportResult, .statKarmaResult {
|
||||
color: white;
|
||||
margin: 5px 0;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.statReportResult.reliable {
|
||||
background-color: #749C48;
|
||||
.statReportResult.reliable, .statKarmaResult.good {
|
||||
background-color: #03AB61;
|
||||
}
|
||||
|
||||
.statReportResult.neutral {
|
||||
.statReportResult.neutral, .statKarmaResult.neutral {
|
||||
background-color: #616161;
|
||||
}
|
||||
|
||||
.statReportResult.unreliable {
|
||||
.statReportResult.unreliable, .statKarmaResult.bad {
|
||||
background-color: #F44336;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
getReliability,
|
||||
isSuspended,
|
||||
isBanned,
|
||||
getKarma,
|
||||
} from 'coral-framework/utils/user';
|
||||
import ButtonCopyToClipboard from './ButtonCopyToClipboard';
|
||||
import ClickOutside from 'coral-framework/components/ClickOutside';
|
||||
@@ -25,6 +26,7 @@ import {
|
||||
import ActionsMenu from 'coral-admin/src/components/ActionsMenu';
|
||||
import ActionsMenuItem from 'coral-admin/src/components/ActionsMenuItem';
|
||||
import UserInfoTooltip from './UserInfoTooltip';
|
||||
import KarmaTooltip from './KarmaTooltip';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
class UserDetail extends React.Component {
|
||||
@@ -203,23 +205,29 @@ class UserDetail extends React.Component {
|
||||
|
||||
<ul className={styles.stats}>
|
||||
<li className={styles.stat}>
|
||||
<span className={styles.statItem}>
|
||||
{t('user_detail.total_comments')}
|
||||
</span>
|
||||
<div>
|
||||
<span className={styles.statItem}>
|
||||
{t('user_detail.total_comments')}
|
||||
</span>
|
||||
</div>
|
||||
<span className={styles.statResult}>{totalComments}</span>
|
||||
</li>
|
||||
<li className={styles.stat}>
|
||||
<span className={styles.statItem}>
|
||||
{t('user_detail.reject_rate')}
|
||||
</span>
|
||||
<div>
|
||||
<span className={styles.statItem}>
|
||||
{t('user_detail.reject_rate')}
|
||||
</span>
|
||||
</div>
|
||||
<span className={styles.statResult}>
|
||||
{rejectedPercent.toFixed(1)}%
|
||||
</span>
|
||||
</li>
|
||||
<li className={styles.stat}>
|
||||
<span className={styles.statItem}>
|
||||
{t('user_detail.reports')}
|
||||
</span>
|
||||
<div>
|
||||
<span className={styles.statItem}>
|
||||
{t('user_detail.reports')}
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
className={cn(
|
||||
styles.statReportResult,
|
||||
@@ -229,6 +237,19 @@ class UserDetail extends React.Component {
|
||||
{capitalize(getReliability(user.reliable.flagger))}
|
||||
</span>
|
||||
</li>
|
||||
<li className={styles.stat}>
|
||||
<div>
|
||||
<span className={styles.statItem}>
|
||||
{t('user_detail.karma')}
|
||||
</span>
|
||||
<KarmaTooltip />
|
||||
</div>
|
||||
<span
|
||||
className={cn(styles.statKarmaResult, styles[getKarma(100)])}
|
||||
>
|
||||
{100}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -49,3 +49,18 @@ export const canUsernameBeUpdated = status => {
|
||||
moment(created_at).isAfter(oldestEditTime)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* getKarma
|
||||
* retrieves karma value as string
|
||||
*/
|
||||
|
||||
export const getKarma = score => {
|
||||
if (score === 0) {
|
||||
return 'neutral';
|
||||
} else if (score) {
|
||||
return 'good';
|
||||
} else {
|
||||
return 'bad';
|
||||
}
|
||||
};
|
||||
|
||||
@@ -470,6 +470,10 @@ en:
|
||||
all: "All"
|
||||
rejected: "Rejected"
|
||||
user_history: "User History"
|
||||
karma: "Karma"
|
||||
learn_more: "Learn More"
|
||||
user_karma_score: "User Karma Score"
|
||||
karma_docs_link: "https://docs.coralproject.net/talk/trust/#user-karma-score"
|
||||
user_history:
|
||||
user_banned: "User banned"
|
||||
ban_removed: "Ban removed"
|
||||
|
||||
Reference in New Issue
Block a user