import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import moment from 'moment'; import { seafileAPI } from '../../utils/seafile-api'; import { gettext, siteRoot } from '../../utils/constants'; import { Utils } from '../../utils/utils'; import Loading from '../../components/loading'; import Activity from '../../models/activity'; moment.locale(window.app.config.lang); const contentPropTypes = { isLoadingMore: PropTypes.bool.isRequired, items: PropTypes.array.isRequired, }; class FileActivitiesContent extends Component { render() { let {items, isLoadingMore} = this.props; return (
{isLoadingMore ? : ''}
); } } FileActivitiesContent.propTypes = contentPropTypes; const tablePropTypes = { items: PropTypes.array.isRequired, }; class TableBody extends Component { render() { let listFilesActivities = this.props.items.map(function(item, index) { let op, details; let userProfileURL = `${siteRoot}profile/${encodeURIComponent(item.author_email)}/`; let libURL = siteRoot + 'library/' + item.repo_id + '/' + encodeURIComponent(item.repo_name) + '/'; let libLink = {item.repo_name}; let smallLibLink = {item.repo_name}; if (item.obj_type == 'repo') { switch(item.op_type) { case 'create': op = gettext('Created library'); details = {libLink}; break; case 'rename': op = gettext('Renamed library'); details = {item.old_repo_name} => {libLink}; break; case 'delete': op = gettext('Deleted library'); details = {item.repo_name}; break; case 'recover': op = gettext('Restored library'); details = {libLink}; break; case 'clean-up-trash': if (item.days == 0) { op = gettext('Removed all items from trash.'); } else { op = gettext('Removed items older than {n} days from trash.').replace('{n}', item.days); } details = {libLink}; break; } } else if (item.obj_type == 'review') { let fileURL = `${siteRoot}drafts/review/${item.review_id}`; let fileLink = {item.name}; switch(item.op_type) { case 'open': op = gettext('Open review'); details = {fileLink}
{smallLibLink}; break; case 'closed': op = gettext('Close review'); details = {fileLink}
{smallLibLink}; break; case 'finished': op = gettext('Publish draft'); details = {fileLink}
{smallLibLink}; break; } } else if (item.obj_type == 'file') { let fileURL = `${siteRoot}lib/${item.repo_id}/file${Utils.encodePath(item.path)}`; let fileLink = {item.name}; switch(item.op_type) { case 'create': if (item.name.endsWith('(draft).md')) { op = gettext('Created draft'); details = {fileLink}
{smallLibLink}; break; } op = gettext('Created file'); details = {fileLink}
{smallLibLink}; break; case 'delete': if (item.name.endsWith('(draft).md')) { op = gettext('Deleted draft'); details = {item.name}
{smallLibLink}; break; } op = gettext('Deleted file'); details = {item.name}
{smallLibLink}; break; case 'recover': op = gettext('Restored file'); details = {fileLink}
{smallLibLink}; break; case 'rename': op = gettext('Renamed file'); details = {item.old_name} => {fileLink}
{smallLibLink}; break; case 'move': var filePathLink = {item.path}; op = gettext('Moved file'); details = {item.old_path} => {filePathLink}
{smallLibLink}; break; case 'edit': // update if (item.name.endsWith('(draft).md')) { op = gettext('Updated draft'); details = {fileLink}
{smallLibLink}; break; } op = gettext('Updated file'); details = {fileLink}
{smallLibLink}; break; } } else { // dir let dirURL = siteRoot + 'library/' + item.repo_id + '/' + encodeURIComponent(item.repo_name) + Utils.encodePath(item.path); let dirLink = {item.name}; switch(item.op_type) { case 'create': op = gettext('Created folder'); details = {dirLink}
{smallLibLink}; break; case 'delete': op = gettext('Deleted folder'); details = {item.name}
{smallLibLink}; break; case 'recover': op = gettext('Restored folder'); details = {dirLink}
{smallLibLink}; break; case 'rename': op = gettext('Renamed folder'); details = {item.old_name} => {dirLink}
{smallLibLink}; break; case 'move': var dirPathLink = {item.path}; op = gettext('Moved folder'); details = {item.old_path} => {dirPathLink}
{smallLibLink}; break; } } let isShowDate = true; if (index > 0) { let lastEventTime = this.props.items[index - 1].time; isShowDate = moment(item.time).isSame(lastEventTime, 'day') ? false : true; } return ( { isShowDate && {moment(item.time).format('YYYY-MM-DD')} } {item.author_name} {op} {details} ); }, this); return ( {listFilesActivities} ); } } TableBody.propTypes = tablePropTypes; class FilesActivities extends Component { constructor(props) { super(props); this.state = { errorMsg: '', isFirstLoading: true, isLoadingMore: false, currentPage: 1, hasMore: true, items: [], }; this.avatarSize = 72; this.curPathList = []; this.oldPathList = []; } componentDidMount() { let currentPage = this.state.currentPage; seafileAPI.listActivities(currentPage, this.avatarSize).then(res => { // {"events":[...]} this.setState({ items: this.filterSuperfluousEvents(res.data.events), currentPage: currentPage + 1, isFirstLoading: false, hasMore: true, }); }).catch(error => { if (error.response.status == 403) { this.setState({ isFirstLoading: false, errorMsg: gettext('Permission denied') }); } }); } filterSuperfluousEvents = (events) => { events.map((item) => { if (item.op_type === 'finished') { this.curPathList.push(item.path); this.oldPathList.push(item.old_path); } }); let actuallyEvents = []; for (var i = 0; i < events.length; i++) { if (events[i].obj_type === 'file') { if (events[i].op_type === 'delete' && this.oldPathList.includes(events[i].path)) { this.oldPathList.splice(this.oldPathList.indexOf(events[i].path), 1); continue; } else if (events[i].op_type === 'edit' && this.curPathList.includes(events[i].path)) { this.curPathList.splice(this.curPathList.indexOf(events[i].path), 1); continue; } else if (events[i].op_type === 'rename' && this.oldPathList.includes(events[i].old_path)) { this.oldPathList.splice(this.oldPathList.indexOf(events[i].old_path), 1); continue; } else { let event = new Activity(events[i]); actuallyEvents.push(event); } } else { let event = new Activity(events[i]); actuallyEvents.push(event); } } return actuallyEvents; } getMore() { let currentPage = this.state.currentPage; seafileAPI.listActivities(currentPage, this.avatarSize).then(res => { // {"events":[...]} this.setState({ isLoadingMore: false, items: [...this.state.items, ...this.filterSuperfluousEvents(res.data.events)], currentPage: currentPage + 1, hasMore: res.data.events.length === 0 ? false : true }); }).catch(error => { if (error.response.status == 403) { this.setState({ isLoadingMore: false, errorMsg: gettext('Permission denied') }); } }); } handleScroll = (event) => { if (!this.state.isLoadingMore && this.state.hasMore) { const clientHeight = event.target.clientHeight; const scrollHeight = event.target.scrollHeight; const scrollTop = event.target.scrollTop; const isBottom = (clientHeight + scrollTop + 1 >= scrollHeight); if (isBottom) { // scroll to the bottom this.setState({isLoadingMore: true}, () => { this.getMore(); }); } } } render() { return (

{gettext('Activities')}

{this.state.isFirstLoading && } {(!this.state.isFirstLoading && this.state.errorMsg) &&

{this.state.errorMsg}

} {!this.state.isFirstLoading && }
); } } export default FilesActivities;