1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-07-31 06:40:39 +00:00
seahub/frontend/src/pages/dashboard/files-activities.js

261 lines
8.6 KiB
JavaScript

import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { Link } from '@gatsbyjs/reach-router';
import { seafileAPI } from '../../utils/seafile-api';
import { gettext, siteRoot, username } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import Loading from '../../components/loading';
import Activity from '../../models/activity';
import FileActivitiesContent from './content';
import UserSelector from './user-selector';
import '../../css/files-activities.css';
moment.locale(window.app.config.lang);
const propTypes = {
onlyMine: PropTypes.bool
};
class FilesActivities extends Component {
constructor(props) {
super(props);
this.state = {
errorMsg: '',
isFirstLoading: true,
isLoadingMore: false,
currentPage: 1,
hasMore: true,
allItems: [],
items: [],
availableUsers: [],
targetUsers: []
};
this.avatarSize = 72;
this.curPathList = [];
this.oldPathList = [];
this.availableUserEmails = new Set();
}
componentDidMount() {
let { currentPage, availableUsers } = this.state;
seafileAPI.listActivities(currentPage, this.avatarSize).then(res => {
// {"events":[...]}
let events = this.mergePublishEvents(res.data.events);
events = this.mergeFileCreateEvents(events);
events.forEach(item => {
if (!this.availableUserEmails.has(item.author_email)) {
this.availableUserEmails.add(item.author_email);
availableUsers.push({
email: item.author_email,
name: item.author_name,
avatar_url: item.avatar_url
});
}
});
this.setState({
allItems: events,
items: this.filterEvents(events),
availableUsers: availableUsers,
currentPage: currentPage + 1,
isFirstLoading: false,
hasMore: true,
});
if (this.state.items.length < 25) {
this.getMore();
}
}).catch(error => {
this.setState({
isFirstLoading: false,
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
});
});
}
mergePublishEvents = (events) => {
events.forEach((item) => {
if (item.op_type === 'publish') {
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);
} else if (events[i].op_type === 'edit' && this.curPathList.includes(events[i].path)) {
this.curPathList.splice(this.curPathList.indexOf(events[i].path), 1);
} 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);
} else {
actuallyEvents.push(events[i]);
}
} else {
actuallyEvents.push(events[i]);
}
}
return actuallyEvents;
};
mergeFileCreateEvents = (events) => {
let actuallyEvents = [];
let multiFilesActivity = null;
for (var i = 0; i < events.length; i++) {
let isFulfilCondition = events[i].obj_type === 'file' &&
events[i].op_type === 'create' &&
events[i + 1] &&
events[i + 1].obj_type === 'file' &&
events[i + 1].op_type === 'create' &&
events[i + 1].repo_name === events[i].repo_name &&
events[i + 1].author_email === events[i].author_email;
if (multiFilesActivity != null) {
multiFilesActivity.createdFilesCount++;
multiFilesActivity.createdFilesList.push(events[i]);
if (isFulfilCondition) {
continue;
} else {
actuallyEvents.push(multiFilesActivity);
multiFilesActivity = null;
}
} else {
if (isFulfilCondition) {
multiFilesActivity = new Activity(events[i]);
multiFilesActivity.obj_type = 'files';
multiFilesActivity.createdFilesCount++;
multiFilesActivity.createdFilesList.push(events[i]);
} else {
actuallyEvents.push(events[i]);
}
}
}
return actuallyEvents;
};
getMore() {
const { currentPage, availableUsers, targetUsers } = this.state;
seafileAPI.listActivities(currentPage, this.avatarSize).then(res => {
// {"events":[...]}
let events = this.mergePublishEvents(res.data.events);
events = this.mergeFileCreateEvents(events);
events.forEach(item => {
if (!this.availableUserEmails.has(item.author_email)) {
this.availableUserEmails.add(item.author_email);
availableUsers.push({
email: item.author_email,
name: item.author_name,
avatar_url: item.avatar_url
});
}
});
const filteredEvents = this.filterEvents(events);
this.setState({
allItems: [...this.state.allItems, ...events],
items: [...this.state.items, ...filteredEvents],
availableUsers: availableUsers,
currentPage: currentPage + 1,
isLoadingMore: false,
hasMore: res.data.events.length === 0 ? false : true
});
if (this.state.items.length < 25 && this.state.hasMore) {
if (!(targetUsers.length && currentPage == 100)) {
this.getMore();
}
}
}).catch(error => {
this.setState({
isLoadingMore: false,
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
});
});
}
filterEvents = (events) => {
const { onlyMine } = this.props;
const { targetUsers } = this.state;
if (onlyMine) {
return events.filter(item => item.author_email == username);
} else if (targetUsers.length) {
return events.filter(item => targetUsers.map(item => item.email).indexOf(item.author_email) != -1);
} else {
return events;
}
};
setTargetUsers = (selectedUsers) => {
this.setState({
targetUsers: selectedUsers
}, () => {
const items = this.filterEvents(this.state.allItems);
this.setState({
items: items
}, () => {
if (items.length < 25 && this.state.hasMore) {
this.getMore();
}
});
});
};
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() {
const { onlyMine } = this.props;
const { targetUsers, availableUsers } = this.state;
return (
<div className="main-panel-center">
<div className="cur-view-container" id="activities">
<div className="cur-view-path">
<ul className="nav">
<li className="nav-item">
<Link to={`${siteRoot}dashboard/`} className={`nav-link${onlyMine ? '' : ' active'}`}>{gettext('All Activities')}</Link>
</li>
<li className="nav-item">
<Link to={`${siteRoot}my-activities/`} className={`nav-link${onlyMine ? ' active': ''}`}>{gettext('My Activities')}</Link>
</li>
</ul>
</div>
<div className="cur-view-content d-block" onScroll={this.handleScroll}>
{this.state.isFirstLoading && <Loading />}
{(!this.state.isFirstLoading && this.state.errorMsg) &&
<p className="error text-center">{this.state.errorMsg}</p>
}
{!this.state.isFirstLoading && (
<Fragment>
{!onlyMine && (
<UserSelector
availableUsers={availableUsers}
currentSelectedUsers={targetUsers}
setTargetUsers={this.setTargetUsers}
/>
)}
<FileActivitiesContent items={this.state.items} isLoadingMore={this.state.isLoadingMore} />
</Fragment>
)
}
</div>
</div>
</div>
);
}
}
FilesActivities.propTypes = propTypes;
export default FilesActivities;