mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-14 14:21:23 +00:00
avatar-tips (#2541)
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import { Tooltip } from 'reactstrap';
|
||||||
import { siteRoot, lang } from '../../utils/constants';
|
import { siteRoot, lang } from '../../utils/constants';
|
||||||
|
|
||||||
moment.locale(lang);
|
moment.locale(lang);
|
||||||
@@ -9,14 +10,51 @@ const propTypes = {
|
|||||||
item: PropTypes.object.isRequired,
|
item: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
function Reviewers(props) {
|
|
||||||
return (
|
class Reviewers extends React.Component {
|
||||||
<div>
|
constructor(props) {
|
||||||
{props.reviewers.map((item, index) => (
|
super(props);
|
||||||
<img key={index} className="avatar avatar-sm" alt={item.username} src={item.avatar_url} />
|
this.state = {
|
||||||
))}
|
reviewerTipOpen: false,
|
||||||
</div>
|
reviewerList:''
|
||||||
);
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle = () => {
|
||||||
|
this.reviewerListItem();
|
||||||
|
this.setState({
|
||||||
|
reviewerTipOpen: !this.state.reviewerTipOpen
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
reviewerListItem = () => {
|
||||||
|
let reviewers = '';
|
||||||
|
|
||||||
|
this.props.item.reviewers.map(item => {
|
||||||
|
reviewers = reviewers + ' and ' + item.user_name
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
reviewerList: reviewers.substr(5,)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let items = this.props.item;
|
||||||
|
let { reviewerList } = this.state;
|
||||||
|
return (
|
||||||
|
<div className='position-relative reviewer-list'>
|
||||||
|
<span id={'reviewers' + items.id}>
|
||||||
|
{items.reviewers.map((item, index) => (
|
||||||
|
<img key={index} id={'reviewer-tip' + '-' + items.id + '-' + index} className="avatar avatar-sm reviewer-avatar" src={item.avatar_url} />
|
||||||
|
))}
|
||||||
|
</span>
|
||||||
|
<Tooltip placement="bottom-end" isOpen={this.state.reviewerTipOpen} target={'reviewers' + items.id} toggle={this.toggle}>
|
||||||
|
{reviewerList}
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReviewListItem extends React.Component {
|
class ReviewListItem extends React.Component {
|
||||||
@@ -25,6 +63,7 @@ class ReviewListItem extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
highlight: '',
|
highlight: '',
|
||||||
|
authorTipOpen: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +83,12 @@ class ReviewListItem extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggle = () => {
|
||||||
|
this.setState({
|
||||||
|
authorTipOpen: !this.state.authorTipOpen
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onReviewsClick = () => {
|
onReviewsClick = () => {
|
||||||
let item = this.props.item;
|
let item = this.props.item;
|
||||||
let itemID = item.id;
|
let itemID = item.id;
|
||||||
@@ -67,8 +112,11 @@ class ReviewListItem extends React.Component {
|
|||||||
<td className="name a-simulate" style={{width: '26%'}} onClick={this.onReviewsClick}>{fileName}</td>
|
<td className="name a-simulate" style={{width: '26%'}} onClick={this.onReviewsClick}>{fileName}</td>
|
||||||
<td className='library' style={{width: '25%'}}>{item.draft_origin_repo_name}</td>
|
<td className='library' style={{width: '25%'}}>{item.draft_origin_repo_name}</td>
|
||||||
<td className="update" style={{width: '20%'}}>{localTime}</td>
|
<td className="update" style={{width: '20%'}}>{localTime}</td>
|
||||||
<td className="author" style={{width: '10%'}}><img className="avatar avatar-sm" src={item.author.avatar_url} /></td>
|
<td className="author" style={{width: '10%'}}><img className="avatar avatar-sm avatar-with-tooltip" id={'tip-' + item.id} src={item.author.avatar_url} /></td>
|
||||||
<td className="reviewer" style={{width: '15%'}}><Reviewers reviewers={item.reviewers}/></td>
|
<td className="reviewer" style={{width: '15%'}}><Reviewers item={item}/></td>
|
||||||
|
<Tooltip placement="bottom-end" isOpen={this.state.authorTipOpen} target={'tip-' + item.id} toggle={this.toggle}>
|
||||||
|
{item.author.user_name}
|
||||||
|
</Tooltip>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
10
frontend/src/css/review-content.css
Normal file
10
frontend/src/css/review-content.css
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.reviewer-list .reviewer-avatar:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reviewer-list .reviewer-avatar {
|
||||||
|
margin-left: -0.5rem;
|
||||||
|
box-shadow: 0 0 0 2px #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
@@ -3,6 +3,7 @@ import { gettext } from '../../utils/constants';
|
|||||||
import { seafileAPI } from '../../utils/seafile-api';
|
import { seafileAPI } from '../../utils/seafile-api';
|
||||||
import Loading from '../../components/loading';
|
import Loading from '../../components/loading';
|
||||||
import ReviewListView from '../../components/review-list-view/review-list-view';
|
import ReviewListView from '../../components/review-list-view/review-list-view';
|
||||||
|
import '../../css/review-content.css';
|
||||||
|
|
||||||
class ReviewContent extends React.Component {
|
class ReviewContent extends React.Component {
|
||||||
|
|
||||||
|
@@ -145,6 +145,10 @@ ul,ol,li {
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.avatar-with-tooltip {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
/* UI Widget */
|
/* UI Widget */
|
||||||
|
|
||||||
/**** caret ****/
|
/**** caret ****/
|
||||||
|
Reference in New Issue
Block a user