UNPKG

yapi-vendor

Version:
288 lines (265 loc) 8.37 kB
import React, { PureComponent as Component } from 'react'; import { Timeline, Spin, Row, Col, Tag, Avatar, Button, Modal, AutoComplete } from 'antd'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { formatTime } from '../../common.js'; import showDiffMsg from '../../../common/diff-view.js'; import variable from '../../constants/variable'; import { Link } from 'react-router-dom'; import { fetchNewsData, fetchMoreNews } from '../../reducer/modules/news.js'; import { fetchInterfaceList } from '../../reducer/modules/interface.js'; import ErrMsg from '../ErrMsg/ErrMsg.js'; const jsondiffpatch = require('jsondiffpatch/dist/jsondiffpatch.umd.js'); const formattersHtml = jsondiffpatch.formatters.html; import 'jsondiffpatch/dist/formatters-styles/annotated.css'; import 'jsondiffpatch/dist/formatters-styles/html.css'; import './TimeLine.scss'; import { timeago } from '../../../common/utils.js'; // const Option = AutoComplete.Option; const { Option, OptGroup } = AutoComplete; const AddDiffView = props => { const { title, content, className } = props; if (!content) { return null; } return ( <div className={className}> <h3 className="title">{title}</h3> <div dangerouslySetInnerHTML={{ __html: content }} /> </div> ); }; AddDiffView.propTypes = { title: PropTypes.string, content: PropTypes.string, className: PropTypes.string }; // timeago(new Date().getTime() - 40); @connect( state => { return { newsData: state.news.newsData, curpage: state.news.curpage, curUid: state.user.uid }; }, { fetchNewsData, fetchMoreNews, fetchInterfaceList } ) class TimeTree extends Component { static propTypes = { newsData: PropTypes.object, fetchNewsData: PropTypes.func, fetchMoreNews: PropTypes.func, setLoading: PropTypes.func, loading: PropTypes.bool, curpage: PropTypes.number, typeid: PropTypes.number, curUid: PropTypes.number, type: PropTypes.string, fetchInterfaceList: PropTypes.func }; constructor(props) { super(props); this.state = { bidden: '', loading: false, visible: false, curDiffData: {}, apiList: [] }; this.curSelectValue = ''; } getMore() { const that = this; if (this.props.curpage <= this.props.newsData.total) { this.setState({ loading: true }); this.props .fetchMoreNews( this.props.typeid, this.props.type, this.props.curpage + 1, 10, this.curSelectValue ) .then(function() { that.setState({ loading: false }); if (that.props.newsData.total === that.props.curpage) { that.setState({ bidden: 'logbidden' }); } }); } } handleCancel = () => { this.setState({ visible: false }); }; componentWillMount() { this.props.fetchNewsData(this.props.typeid, this.props.type, 1, 10); if (this.props.type === 'project') { this.getApiList(); } } openDiff = data => { this.setState({ curDiffData: data, visible: true }); }; async getApiList() { let result = await this.props.fetchInterfaceList({ project_id: this.props.typeid, limit: 'all' }); this.setState({ apiList: result.payload.data.data.list }); } handleSelectApi = selectValue => { this.curSelectValue = selectValue; this.props.fetchNewsData(this.props.typeid, this.props.type, 1, 10, selectValue); }; render() { let data = this.props.newsData ? this.props.newsData.list : []; const curDiffData = this.state.curDiffData; let logType = { project: '项目', group: '分组', interface: '接口', interface_col: '接口集', user: '用户', other: '其他' }; const children = this.state.apiList.map(item => { let methodColor = variable.METHOD_COLOR[item.method ? item.method.toLowerCase() : 'get']; return ( <Option title={item.title} value={item._id + ''} path={item.path} key={item._id}> {item.title}{' '} <Tag style={{ color: methodColor ? methodColor.color : '#cfefdf', backgroundColor: methodColor ? methodColor.bac : '#00a854', border: 'unset' }} > {item.method} </Tag> </Option> ); }); children.unshift( <Option value="" key="all"> 选择全部 </Option> ); if (data && data.length) { data = data.map((item, i) => { let interfaceDiff = false; // 去掉了 && item.data.interface_id if (item.data && typeof item.data === 'object') { interfaceDiff = true; } return ( <Timeline.Item dot={ <Link to={`/user/profile/${item.uid}`}> <Avatar src={`/api/user/avatar?uid=${item.uid}`} /> </Link> } key={i} > <div className="logMesHeade"> <span className="logoTimeago">{timeago(item.add_time)}</span> {/*<span className="logusername"><Link to={`/user/profile/${item.uid}`}><Icon type="user" />{item.username}</Link></span>*/} <span className="logtype">{logType[item.type]}动态</span> <span className="logtime">{formatTime(item.add_time)}</span> </div> <span className="logcontent" dangerouslySetInnerHTML={{ __html: item.content }} /> <div style={{ padding: '10px 0 0 10px' }}> {interfaceDiff && <Button onClick={() => this.openDiff(item.data)}>改动详情</Button>} </div> </Timeline.Item> ); }); } else { data = ''; } let pending = this.props.newsData.total <= this.props.curpage ? ( <a className="logbidden">以上为全部内容</a> ) : ( <a className="loggetMore" onClick={this.getMore.bind(this)}> 查看更多 </a> ); if (this.state.loading) { pending = <Spin />; } let diffView = showDiffMsg(jsondiffpatch, formattersHtml, curDiffData); return ( <section className="news-timeline"> <Modal style={{ minWidth: '800px' }} title="Api 改动日志" visible={this.state.visible} footer={null} onCancel={this.handleCancel} > <i>注: 绿色代表新增内容,红色代表删除内容</i> <div className="project-interface-change-content"> {diffView.map((item, index) => { return ( <AddDiffView className="item-content" title={item.title} key={index} content={item.content} /> ); })} {diffView.length === 0 && <ErrMsg type="noChange" />} </div> </Modal> {this.props.type === 'project' && ( <Row className="news-search"> <Col span="3">选择查询的 Api:</Col> <Col span="10"> <AutoComplete onSelect={this.handleSelectApi} style={{ width: '100%' }} placeholder="Select Api" optionLabelProp="title" filterOption={(inputValue, options) => { if (options.props.value == '') return true; if ( options.props.path.indexOf(inputValue) !== -1 || options.props.title.indexOf(inputValue) !== -1 ) { return true; } return false; }} > {/* {children} */} <OptGroup label="other"> <Option value="wiki" path="" title="wiki"> wiki </Option> </OptGroup> <OptGroup label="api">{children}</OptGroup> </AutoComplete> </Col> </Row> )} {data ? ( <Timeline className="news-content" pending={pending}> {data} </Timeline> ) : ( <ErrMsg type="noData" /> )} </section> ); } } export default TimeTree;