mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-19 18:29:23 +00:00
feat: sdoc history group
This commit is contained in:
@@ -7,6 +7,7 @@ import URLDecorator from '../../../utils/url-decorator';
|
||||
import Rename from '../../../components/rename';
|
||||
|
||||
import '../../../css/history-record-item.css';
|
||||
import classNames from 'classnames';
|
||||
|
||||
moment.locale(window.app.config.lang);
|
||||
|
||||
@@ -39,9 +40,9 @@ class HistoryVersion extends React.Component {
|
||||
|
||||
onClick = () => {
|
||||
this.setState({ isShowOperationIcon: false });
|
||||
const { currentVersion, historyVersion } = this.props;
|
||||
const { currentVersion, historyVersion, path } = this.props;
|
||||
if (currentVersion.commit_id === historyVersion.commit_id) return;
|
||||
this.props.onSelectHistoryVersion(historyVersion);
|
||||
this.props.onSelectHistoryVersion(path);
|
||||
};
|
||||
|
||||
onRestore = () => {
|
||||
@@ -73,19 +74,36 @@ class HistoryVersion extends React.Component {
|
||||
this.toggleRename();
|
||||
};
|
||||
|
||||
showDailyHistory = (event) => {
|
||||
event.stopPropagation();
|
||||
event.nativeEvent.stopImmediatePropagation();
|
||||
const { path } = this.props;
|
||||
this.props.showDailyHistory(path);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { currentVersion, historyVersion } = this.props;
|
||||
const { currentVersion, historyVersion, path, showDaily } = this.props;
|
||||
if (!currentVersion || !historyVersion) return null;
|
||||
const { ctime, commit_id, creator_name, obj_id, name} = historyVersion;
|
||||
const { ctime, commit_id, creator_name, obj_id, name, count } = historyVersion;
|
||||
const isHighlightItem = commit_id === currentVersion.commit_id;
|
||||
const url = URLDecorator.getUrl({ type: 'download_historic_file', filePath: filePath, objID: obj_id });
|
||||
return (
|
||||
<li
|
||||
className={`history-list-item ${isHighlightItem ? 'item-active' : ''}`}
|
||||
className={`history-list-item ${isHighlightItem ? 'item-active' : ''} ${path[2] > 0 ? 'daily-history-detail' : ''}`}
|
||||
onMouseEnter={this.onMouseEnter}
|
||||
onMouseLeave={this.onMouseLeave}
|
||||
onClick={this.onClick}
|
||||
>
|
||||
{path[2] === 0 && (
|
||||
<div className="daily-history-detail-toggle-container">
|
||||
{count > 1 && (
|
||||
<div className={classNames('daily-history-detail-toggle', { 'daily-history-detail-show': showDaily })} onClick={this.showDailyHistory}>
|
||||
<i className="dropdown-toggle"></i>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{path[2] > 0 && (<div className="daily-history-detail-no-more"></div>)}
|
||||
<div className="history-info">
|
||||
{this.state.isRenameShow ?
|
||||
<Rename name={name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel}/>
|
||||
@@ -109,7 +127,7 @@ class HistoryVersion extends React.Component {
|
||||
<DropdownMenu>
|
||||
{/* {(this.props.index !== 0) && <DropdownItem onClick={this.onItemRestore}>{gettext('Restore')}</DropdownItem>} */}
|
||||
<DropdownItem tag='a' href={url} onClick={this.onItemDownLoad}>{gettext('Download')}</DropdownItem>
|
||||
{(this.props.index !== 0) && <DropdownItem onClick={this.onItemCopy}>{gettext('Copy')}</DropdownItem>}
|
||||
{(path[0] !== 0 && path[1] !== 0 && path[2] !== 0) && <DropdownItem onClick={this.onItemCopy}>{gettext('Copy')}</DropdownItem>}
|
||||
<DropdownItem onClick={this.toggleRename}>{gettext('Rename')}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
@@ -120,13 +138,15 @@ class HistoryVersion extends React.Component {
|
||||
}
|
||||
|
||||
HistoryVersion.propTypes = {
|
||||
index: PropTypes.number,
|
||||
showDaily: PropTypes.bool,
|
||||
path: PropTypes.array,
|
||||
currentVersion: PropTypes.object.isRequired,
|
||||
historyVersion: PropTypes.object,
|
||||
onSelectHistoryVersion: PropTypes.func.isRequired,
|
||||
onRestore: PropTypes.func.isRequired,
|
||||
onCopy: PropTypes.func.isRequired,
|
||||
renameHistoryVersion: PropTypes.func.isRequired,
|
||||
showDailyHistory: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default HistoryVersion;
|
||||
|
@@ -150,6 +150,10 @@
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .history-list-item.history-month-title {
|
||||
padding: 5px 16px;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .history-list-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
@@ -159,6 +163,25 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .history-list-item .history-operation {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .history-list-item .history-info {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .history-list-item .history-info .name {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .history-list-item.item-active .history-info .name{
|
||||
color: #ff8000;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .history-list-item .history-operation:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -210,6 +233,57 @@
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .history-info .rename-container,
|
||||
.sdoc-file-history-versions .history-info .rename-container input {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
min-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .history-info .rename-container input:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .daily-history-detail-toggle-container {
|
||||
width: 20px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .daily-history-detail-toggle-container .daily-history-detail-toggle {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .daily-history-detail-no-more {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 14px;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .daily-history-detail-toggle .dropdown-toggle {
|
||||
font-size: 18px;
|
||||
color: #888;
|
||||
transform: rotate(-90deg);
|
||||
transition: all .1s;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .daily-history-detail-toggle.daily-history-detail-show .dropdown-toggle {
|
||||
transform: unset;
|
||||
}
|
||||
|
||||
.sdoc-file-history-versions .daily-history-detail-toggle .dropdown-toggle:hover {
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (min-width:992px) {
|
||||
|
||||
.history-side-panel {
|
@@ -12,7 +12,7 @@ import { Utils } from '../../../utils/utils';
|
||||
import toaster from '../../../components/toast';
|
||||
|
||||
import '../../../css/layout.css';
|
||||
import '../../../css/sdoc-file-history.css';
|
||||
import './index.css';
|
||||
|
||||
const { serviceURL, avatarURL, siteRoot } = window.app.config;
|
||||
const { username, name } = window.app.pageOptions;
|
||||
@@ -48,15 +48,15 @@ class SdocFileHistory extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
onSelectHistoryVersion = (currentVersion, lastVersion) => {
|
||||
onSelectHistoryVersion = (currentVersion, isShowChanges) => {
|
||||
this.setState({ isLoading: true, currentVersion });
|
||||
seafileAPI.getFileRevision(historyRepoID, currentVersion.commit_id, currentVersion.path).then(res => {
|
||||
return seafileAPI.getFileContent(res.data);
|
||||
}).then(res => {
|
||||
const currentVersionContent = res.data;
|
||||
if (lastVersion) {
|
||||
seafileAPI.getFileRevision(historyRepoID, lastVersion.commit_id, lastVersion.path).then(res => {
|
||||
return seafileAPI.getFileContent(res.data);
|
||||
if (isShowChanges) {
|
||||
seafileAPI.getNextFileRevision(historyRepoID, currentVersion.id, currentVersion.path).then(res => {
|
||||
return res.data ? seafileAPI.getFileContent(res.data) : { data: '' };
|
||||
}).then(res => {
|
||||
const lastVersionContent = res.data;
|
||||
this.setContent(currentVersionContent, lastVersionContent);
|
||||
@@ -79,13 +79,13 @@ class SdocFileHistory extends React.Component {
|
||||
this.setState({ currentVersionContent, lastVersionContent, isLoading: false, changes: [], currentDiffIndex: 0 });
|
||||
};
|
||||
|
||||
onShowChanges = (isShowChanges, lastVersion) => {
|
||||
if (isShowChanges && lastVersion) {
|
||||
const { currentVersionContent } = this.state;
|
||||
onShowChanges = (isShowChanges) => {
|
||||
if (isShowChanges) {
|
||||
const { currentVersionContent, currentVersion } = this.state;
|
||||
this.setState({ isLoading: true }, () => {
|
||||
localStorage.setItem('seahub-sdoc-history-show-changes', isShowChanges + '');
|
||||
seafileAPI.getFileRevision(historyRepoID, lastVersion.commit_id, lastVersion.path).then(res => {
|
||||
return seafileAPI.getFileContent(res.data);
|
||||
seafileAPI.getNextFileRevision(historyRepoID, currentVersion.id, currentVersion.path).then(res => {
|
||||
return res.data ? seafileAPI.getFileContent(res.data) : { data: '' };
|
||||
}).then(res => {
|
||||
const lastVersionContent = res.data;
|
||||
this.setContent(currentVersionContent, lastVersionContent);
|
||||
@@ -175,10 +175,10 @@ class SdocFileHistory extends React.Component {
|
||||
>
|
||||
<span className="fas fa-chevron-down"></span>
|
||||
</div>
|
||||
<UncontrolledTooltip placement="bottom" target="sdoc-file-changes-last">
|
||||
<UncontrolledTooltip placement="bottom" target="sdoc-file-changes-last" delay={0} fade={false}>
|
||||
{gettext('Last modification')}
|
||||
</UncontrolledTooltip>
|
||||
<UncontrolledTooltip placement="bottom" target="sdoc-file-changes-next">
|
||||
<UncontrolledTooltip placement="bottom" target="sdoc-file-changes-next" delay={0} fade={false}>
|
||||
{gettext('Next modification')}
|
||||
</UncontrolledTooltip>
|
||||
</div>
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import moment from 'moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import Loading from '../../../components/loading';
|
||||
@@ -10,6 +11,8 @@ import toaster from '../../../components/toast';
|
||||
import HistoryVersion from './history-version';
|
||||
import Switch from '../../../components/common/switch';
|
||||
|
||||
moment.locale(window.app.config.lang);
|
||||
|
||||
const { docUuid } = window.fileHistory.pageOptions;
|
||||
|
||||
class SidePanel extends Component {
|
||||
@@ -18,67 +21,81 @@ class SidePanel extends Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
isLoading: true,
|
||||
historyVersions: [],
|
||||
historyGroups: [],
|
||||
errorMessage: '',
|
||||
currentPage: 1,
|
||||
hasMore: false,
|
||||
fileOwner: '',
|
||||
isReloadingData: false,
|
||||
};
|
||||
this.currentPage = 1;
|
||||
}
|
||||
|
||||
// listSdocDailyHistoryDetail
|
||||
|
||||
componentDidMount() {
|
||||
seafileAPI.listSdocHistory(docUuid, 1, PER_PAGE).then(res => {
|
||||
let historyList = res.data;
|
||||
if (historyList.length === 0) {
|
||||
this.setState({isLoading: false});
|
||||
throw Error('there has an error in server');
|
||||
}
|
||||
this.initResultState(res.data);
|
||||
});
|
||||
this.firstLoadSdocHistory();
|
||||
}
|
||||
|
||||
refershFileList() {
|
||||
seafileAPI.listSdocHistory(docUuid, 1, PER_PAGE).then(res => {
|
||||
this.initResultState(res.data);
|
||||
});
|
||||
}
|
||||
|
||||
initResultState(result) {
|
||||
if (result.histories.length) {
|
||||
firstLoadSdocHistory() {
|
||||
this.currentPage = 1;
|
||||
seafileAPI.listSdocHistory(docUuid, this.currentPage, PER_PAGE).then(res => {
|
||||
const result = res.data;
|
||||
const resultCount = result.histories.length;
|
||||
this.setState({
|
||||
historyVersions: result.histories,
|
||||
currentPage: result.page,
|
||||
hasMore: result.total_count > (PER_PAGE * this.state.currentPage),
|
||||
historyGroups: this.formatHistories(result.histories),
|
||||
hasMore: resultCount >= PER_PAGE,
|
||||
isLoading: false,
|
||||
fileOwner: result.histories[0].creator_email,
|
||||
});
|
||||
this.props.onSelectHistoryVersion(result.histories[0], result.histories[1]);
|
||||
}
|
||||
if (result.histories[0]) {
|
||||
this.props.onSelectHistoryVersion(result.histories[0], result.histories[1]);
|
||||
}
|
||||
}).catch((error) => {
|
||||
this.setState({isLoading: false});
|
||||
throw Error('there has an error in server');
|
||||
});
|
||||
}
|
||||
|
||||
formatHistories(histories) {
|
||||
const oldHistoryGroups = this.state.historyGroups;
|
||||
if (!Array.isArray(histories) || histories.length === 0) return oldHistoryGroups;
|
||||
const newHistoryGroups = oldHistoryGroups.slice(0);
|
||||
histories.forEach(history => {
|
||||
const { date } = history;
|
||||
const month = moment(date).format('YYYY-MM');
|
||||
const monthItem = newHistoryGroups.find(item => item.month === month);
|
||||
if (monthItem) {
|
||||
monthItem.children.push({ day: moment(date).format('YYYY-MM-DD'), showDaily: false, children: [ history ] });
|
||||
} else {
|
||||
newHistoryGroups.push({
|
||||
month,
|
||||
children: [
|
||||
{ day: moment(date).format('YYYY-MM-DD'), showDaily: false, children: [ history ] }
|
||||
]
|
||||
});
|
||||
}
|
||||
});
|
||||
return newHistoryGroups;
|
||||
}
|
||||
|
||||
updateResultState(result) {
|
||||
if (result.histories.length) {
|
||||
this.setState({
|
||||
historyVersions: [...this.state.historyVersions, ...result.histories],
|
||||
currentPage: result.page,
|
||||
hasMore: result.total_count > (PER_PAGE * this.state.currentPage),
|
||||
isLoading: false,
|
||||
fileOwner: result.histories[0].creator_email
|
||||
});
|
||||
}
|
||||
const resultCount = result.histories.length;
|
||||
this.setState({
|
||||
historyGroups: this.formatHistories(result.histories),
|
||||
hasMore: resultCount >= PER_PAGE,
|
||||
isLoading: false,
|
||||
fileOwner: result.histories[0].creator_email,
|
||||
});
|
||||
}
|
||||
|
||||
loadMore = () => {
|
||||
if (!this.state.isReloadingData) {
|
||||
let currentPage = this.state.currentPage + 1;
|
||||
this.setState({
|
||||
currentPage: currentPage,
|
||||
isReloadingData: true,
|
||||
});
|
||||
seafileAPI.listSdocHistory(docUuid, currentPage, PER_PAGE).then(res => {
|
||||
this.updateResultState(res.data);
|
||||
this.setState({isReloadingData: false});
|
||||
this.currentPage = this.currentPage + 1;
|
||||
this.setState({ isReloadingData: true }, () => {
|
||||
seafileAPI.listSdocHistory(docUuid, this.currentPage, PER_PAGE).then(res => {
|
||||
this.updateResultState(res.data);
|
||||
this.setState({isReloadingData: false});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -86,7 +103,7 @@ class SidePanel extends Component {
|
||||
renameHistoryVersion = (objID, newName) => {
|
||||
seafileAPI.renameSdocHistory(docUuid, objID, newName).then((res) => {
|
||||
this.setState({
|
||||
historyVersions: this.state.historyVersions.map(item => {
|
||||
historyGroups: this.state.historyGroups.map(item => {
|
||||
if (item.obj_id == objID) {
|
||||
item.name = newName;
|
||||
}
|
||||
@@ -113,8 +130,9 @@ class SidePanel extends Component {
|
||||
const { commit_id, path } = currentItem;
|
||||
editUtilities.revertFile(path, commit_id).then(res => {
|
||||
if (res.data.success) {
|
||||
this.setState({isLoading: true});
|
||||
this.refershFileList();
|
||||
this.setState({isLoading: true}, () => {
|
||||
this.firstLoadSdocHistory();
|
||||
});
|
||||
}
|
||||
let message = gettext('Successfully restored.');
|
||||
toaster.success(message);
|
||||
@@ -124,15 +142,11 @@ class SidePanel extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
onSelectHistoryVersion = (historyVersion) => {
|
||||
onSelectHistoryVersion = (path) => {
|
||||
const { isShowChanges } = this.props;
|
||||
if (!isShowChanges) {
|
||||
this.props.onSelectHistoryVersion(historyVersion);
|
||||
return;
|
||||
}
|
||||
const { historyVersions } = this.state;
|
||||
const historyVersionIndex = historyVersions.findIndex(item => item.commit_id === historyVersion.commit_id);
|
||||
this.props.onSelectHistoryVersion(historyVersion, historyVersions[historyVersionIndex + 1]);
|
||||
const { historyGroups } = this.state;
|
||||
const historyVersion = historyGroups[path[0]].children[path[1]].children[path[2]];
|
||||
this.props.onSelectHistoryVersion(historyVersion, isShowChanges);
|
||||
};
|
||||
|
||||
copyHistoryFile = (historyVersion) => {
|
||||
@@ -148,9 +162,41 @@ class SidePanel extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
showDailyHistory = (path, callback) => {
|
||||
const { historyGroups } = this.state;
|
||||
const newHistoryGroups = historyGroups.slice(0);
|
||||
const dayHistoryGroup = newHistoryGroups[path[0]].children[path[1]];
|
||||
if (dayHistoryGroup.showDaily) {
|
||||
dayHistoryGroup.showDaily = false;
|
||||
this.setState({ historyGroups: newHistoryGroups }, () => {
|
||||
callback && callback();
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (dayHistoryGroup.children.length > 1) {
|
||||
dayHistoryGroup.showDaily = true;
|
||||
this.setState({ historyGroups: newHistoryGroups }, () => {
|
||||
callback && callback();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
seafileAPI.listSdocDailyHistoryDetail(docUuid, dayHistoryGroup.children[0].ctime).then(res => {
|
||||
const histories = res.data.histories;
|
||||
dayHistoryGroup.children.push(...histories);
|
||||
dayHistoryGroup.showDaily = true;
|
||||
this.setState({ historyGroups: newHistoryGroups }, () => {
|
||||
callback && callback();
|
||||
});
|
||||
}).catch(error => {
|
||||
const errorMessage = Utils.getErrorMsg(error, true);
|
||||
toaster.danger(gettext(errorMessage));
|
||||
});
|
||||
};
|
||||
|
||||
renderHistoryVersions = () => {
|
||||
const { isLoading, historyVersions, errorMessage } = this.state;
|
||||
if (historyVersions.length === 0) {
|
||||
const { isLoading, historyGroups, errorMessage } = this.state;
|
||||
if (historyGroups.length === 0) {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="h-100 w-100 d-flex align-items-center justify-content-center">
|
||||
@@ -174,18 +220,31 @@ class SidePanel extends Component {
|
||||
|
||||
return (
|
||||
<>
|
||||
{historyVersions.map((historyVersion, index) => {
|
||||
{historyGroups.map((monthHistoryGroup, historyGroupIndex) => {
|
||||
return (
|
||||
<HistoryVersion
|
||||
key={historyVersion.commit_id}
|
||||
index={index}
|
||||
currentVersion={this.props.currentVersion}
|
||||
historyVersion={historyVersion}
|
||||
onSelectHistoryVersion={this.onSelectHistoryVersion}
|
||||
onRestore={this.restoreVersion}
|
||||
onCopy={this.copyHistoryFile}
|
||||
renameHistoryVersion={this.renameHistoryVersion}
|
||||
/>
|
||||
<Fragment key={monthHistoryGroup.month}>
|
||||
<div className="history-list-item history-month-title" key={monthHistoryGroup.month}>{monthHistoryGroup.month}</div>
|
||||
{monthHistoryGroup.children.map((dayHistoryGroup, dayHistoryGroupIndex) => {
|
||||
const { children, showDaily } = dayHistoryGroup;
|
||||
const displayHistories = showDaily ? children : children.slice(0, 1);
|
||||
return displayHistories.map((history, index) => {
|
||||
return (
|
||||
<HistoryVersion
|
||||
key={history.commit_id}
|
||||
path={[historyGroupIndex, dayHistoryGroupIndex, index]}
|
||||
showDaily={index === 0 && showDaily}
|
||||
currentVersion={this.props.currentVersion}
|
||||
historyVersion={history}
|
||||
onSelectHistoryVersion={this.onSelectHistoryVersion}
|
||||
onRestore={this.restoreVersion}
|
||||
onCopy={this.copyHistoryFile}
|
||||
renameHistoryVersion={this.renameHistoryVersion}
|
||||
showDailyHistory={this.showDailyHistory}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}).flat()}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
{isLoading && (
|
||||
@@ -198,15 +257,12 @@ class SidePanel extends Component {
|
||||
};
|
||||
|
||||
onShowChanges = () => {
|
||||
const { isShowChanges, currentVersion } = this.props;
|
||||
const { historyVersions } = this.state;
|
||||
const historyVersionIndex = historyVersions.findIndex(item => item.commit_id === currentVersion.commit_id);
|
||||
const lastVersion = historyVersions[historyVersionIndex + 1];
|
||||
this.props.onShowChanges(!isShowChanges, lastVersion);
|
||||
const { isShowChanges } = this.props;
|
||||
this.props.onShowChanges(!isShowChanges);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { historyVersions } = this.state;
|
||||
const { historyGroups } = this.state;
|
||||
|
||||
return (
|
||||
<div className="sdoc-file-history-panel h-100 o-hidden d-flex flex-column">
|
||||
@@ -216,7 +272,7 @@ class SidePanel extends Component {
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={classnames('sdoc-file-history-versions', { 'o-hidden': historyVersions.length === 0 } )}
|
||||
className={classnames('sdoc-file-history-versions', { 'o-hidden': historyGroups.length === 0 } )}
|
||||
onScroll={this.onScrollHandler}
|
||||
>
|
||||
{this.renderHistoryVersions()}
|
||||
|
Reference in New Issue
Block a user