diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index dda7d58057..c0166f04e3 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -180,7 +180,7 @@
"dependencies": {
"reactstrap": {
"version": "5.0.0",
- "resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-5.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/reactstrap/-/reactstrap-5.0.0.tgz",
"integrity": "sha512-y0eju/LAK7gbEaTFfq2iW92MF7/5Qh0tc1LgYr2mg92IX8NodGc03a+I+cp7bJ0VXHAiLy0bFL9UP89oSm4cBg==",
"requires": {
"classnames": "^2.2.3",
@@ -640,7 +640,7 @@
},
"axios": {
"version": "0.18.0",
- "resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
"requires": {
"follow-redirects": "^1.3.0",
@@ -2507,9 +2507,9 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"codemirror": {
- "version": "5.42.0",
- "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.42.0.tgz",
- "integrity": "sha512-pbApC8zDzItP3HRphD6kQVwS976qB5Qi0hU3MZMixLk+AyugOW1RF+8XJEjeyl5yWsHNe88tDUxzeRh5AOxPRw=="
+ "version": "5.42.2",
+ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.42.2.tgz",
+ "integrity": "sha512-Tkv6im39VuhduFMsDA3MlXcC/kKas3Z0PI1/8N88QvFQbtOeiiwnfFJE4juGyC8/a4sb1BSxQlzsil8XLQdxRw=="
},
"collapse-white-space": {
"version": "1.0.4",
@@ -9964,7 +9964,7 @@
},
"react-popper": {
"version": "0.8.3",
- "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-0.8.3.tgz",
+ "resolved": "http://registry.npmjs.org/react-popper/-/react-popper-0.8.3.tgz",
"integrity": "sha1-D3MzMTfJ+wr27EB00tBYWgoEYeE=",
"requires": {
"popper.js": "^1.12.9",
diff --git a/frontend/src/components/history-list-view/history-list-item.js b/frontend/src/components/history-list-view/history-list-item.js
index 4173d7989a..49b7415b0c 100644
--- a/frontend/src/components/history-list-view/history-list-item.js
+++ b/frontend/src/components/history-list-view/history-list-item.js
@@ -1,17 +1,20 @@
import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
-import MenuControl from '../menu-control';
+import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem} from 'reactstrap';
+import { gettext, filePath } from '../../utils/constants';
+import URLDecorator from '../../utils/url-decorator';
moment.locale(window.app.config.lang);
+
const propTypes = {
- isItemFrezeed: PropTypes.bool.isRequired,
- isFirstItem: PropTypes.bool.isRequired,
- preCommitID: PropTypes.string.isRequired,
+ index: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
- currentItem: PropTypes.object.isRequired,
- onMenuControlClick: PropTypes.func.isRequired,
- onHistoryItemClick: PropTypes.func.isRequired,
+ currentItem: PropTypes.object,
+ isItemFreezed: PropTypes.bool.isRequired,
+ onItemClick: PropTypes.func.isRequired,
+ onItemRestore: PropTypes.func.isRequired,
+ onFreezedItemToggle: PropTypes.func.isRequired,
};
class HistoryListItem extends React.Component {
@@ -19,42 +22,57 @@ class HistoryListItem extends React.Component {
constructor(props) {
super(props);
this.state = {
- isShowOperationIcon: false
+ isShowOperationIcon: false,
+ isMenuShow: false,
};
}
onMouseEnter = () => {
- if (!this.props.isItemFrezeed) {
+ if (!this.props.isItemFreezed) {
this.setState({isShowOperationIcon: true});
}
}
onMouseLeave = () => {
- if (!this.props.isItemFrezeed) {
+ if (!this.props.isItemFreezed) {
this.setState({isShowOperationIcon: false});
}
}
+ onToggleClick = (e) => {
+ this.setState({isMenuShow: !this.state.isMenuShow});
+ this.props.onFreezedItemToggle();
+ }
+
onItemClick = () => {
+ this.setState({isShowOperationIcon: false}); //restore to default state
if (this.props.item.commit_id === this.props.currentItem.commit_id) {
return;
}
- this.setState({isShowOperationIcon: false}); //restore to default state
- this.props.onHistoryItemClick(this.props.item, this.props.preCommitID);
+ let currentIndex = this.props.index;
+ this.props.onItemClick(this.props.item, currentIndex);
}
- onMenuControlClick = (e) => {
- e.nativeEvent.stopImmediatePropagation();
- this.props.onMenuControlClick(e, this.props.item , this.props.isFirstItem);
+ onItemRestore = () => {
+ this.props.onItemRestore(this.props.currentItem);
+ }
+
+ onItemDownload = () => {
+ // nothing todo
}
render() {
+ if (!this.props.currentItem) {
+ return '';
+ }
let item = this.props.item;
- let time = moment.parseZone(item.ctime).format('YYYY-MM-DD HH:mm');
+ let time = moment(item.ctime).format('YYYY-MM-DD HH:mm');
let isHigtlightItem = false;
if (this.props.item && this.props.currentItem) {
isHigtlightItem = this.props.item.commit_id === this.props.currentItem.commit_id;
}
+ let objID = this.props.currentItem.rev_file_id;
+ let url = URLDecorator.getUrl({type: 'download_historic_file', filePath: filePath, objID: objID});
return (
-
+
+
+
+ {(this.props.index !== 0) && {gettext('Restore')}}
+ {gettext('Download')}
+
+
);
diff --git a/frontend/src/components/history-list-view/history-list-menu.js b/frontend/src/components/history-list-view/history-list-menu.js
deleted file mode 100644
index 493a568ba5..0000000000
--- a/frontend/src/components/history-list-view/history-list-menu.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { gettext, filePath } from '../../utils/constants';
-import URLDecorator from '../../utils/url-decorator';
-
-const propTypes = {
- isFirstItem: PropTypes.bool.isRequired,
- isListMenuShow: PropTypes.bool.isRequired,
- menuPosition: PropTypes.object.isRequired,
- currentItem: PropTypes.object,
- onDownloadFile: PropTypes.func.isRequired,
- onRestoreFile: PropTypes.func.isRequired,
-};
-
-class HistoryListMenu extends React.Component {
-
- onDownloadFile = () => {
- this.props.onDownloadFile();
- }
-
- onRestoreFile = () => {
- this.props.onRestoreFile();
- }
-
- render() {
- let style = {};
- let position = this.props.menuPosition;
- if (this.props.isListMenuShow) {
- style = {position: 'fixed',left: position.left + 'px',top: position.top + 'px',display: 'block'};
- }
-
- if (!this.props.currentItem) {
- return '';
- }
-
- let objID = this.props.currentItem.rev_file_id;
- let url = URLDecorator.getUrl({type: 'download_historic_file', filePath: filePath, objID: objID});
-
- if (this.props.isFirstItem) {
- return (
-
- );
- }
-
- return (
-
- );
- }
-
-}
-
-HistoryListMenu.propTypes = propTypes;
-
-export default HistoryListMenu;
diff --git a/frontend/src/components/history-list-view/history-list-view.js b/frontend/src/components/history-list-view/history-list-view.js
index e96927c3be..fce29cff68 100644
--- a/frontend/src/components/history-list-view/history-list-view.js
+++ b/frontend/src/components/history-list-view/history-list-view.js
@@ -2,25 +2,41 @@ import React from 'react';
import PropTypes from 'prop-types';
import HisotyListItem from './history-list-item';
import Loading from '../loading';
-import axios from 'axios';
-import editUtilties from '../../utils/editor-utilties';
-import URLDecorator from '../../utils/url-decorator';
-import { filePath } from '../../utils/constants';
const propTypes = {
hasMore: PropTypes.bool.isRequired,
isReloadingData: PropTypes.bool.isRequired,
- isItemFrezeed: PropTypes.bool.isRequired,
historyList: PropTypes.array.isRequired,
- currentItem: PropTypes.object,
reloadMore: PropTypes.func.isRequired,
- onMenuControlClick: PropTypes.func.isRequired,
- onHistoryItemClick: PropTypes.func.isRequired,
- setDiffContent: PropTypes.func.isRequired,
+ onItemClick: PropTypes.func.isRequired,
};
class HistoryListView extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ isItemFreezed: false,
+ currentItem: null,
+ };
+ }
+
+ componentDidMount = () => {
+ let historyList = this.props.historyList;
+ if (historyList.length > 0) {
+ this.setState({currentItem: historyList[0]});
+ if (historyList === 1) {
+ this.props.onItemClick(historyList[0]);
+ } else {
+ this.props.onItemClick(historyList[0], historyList[1]);
+ }
+ }
+ }
+
+ onFreezedItemToggle = () => {
+ this.setState({isItemFreezed: !this.state.isItemFreezed});
+ }
+
onScrollHandler = (event) => {
const clientHeight = event.target.clientHeight;
const scrollHeight = event.target.scrollHeight;
@@ -32,46 +48,30 @@ class HistoryListView extends React.Component {
}
}
- componentDidMount() {
- let historyList = this.props.historyList;
- if (historyList.length > 1) {
- let downLoadURL = URLDecorator.getUrl({type: 'download_historic_file', filePath: filePath, objID: historyList[0].rev_file_id});
- let downLoadURL1 = URLDecorator.getUrl({type: 'download_historic_file', filePath: filePath, objID: historyList[1].rev_file_id});
- axios.all([
- editUtilties.getFileContent(downLoadURL),
- editUtilties.getFileContent(downLoadURL1)
- ]).then(axios.spread((res1, res2) => {
- this.props.setDiffContent(res1.data, res2.data);
- }));
+ onItemClick = (item, currentIndex) => {
+ this.setState({currentItem: item});
+ if (currentIndex !== this.props.historyList.length) {
+ let preItem = this.props.historyList[currentIndex + 1];
+ this.props.onItemClick(item, preItem);
} else {
- let downLoadURL = URLDecorator.getUrl({type: 'download_historic_file', filePath: filePath, objID: historyList[0].rev_file_id});
- axios.all([
- editUtilties.getFileContent(downLoadURL),
- ]).then(axios.spread((res1) => {
- this.props.setDiffContent(res1.data, '');
- }));
+ this.props.onItemClick(item);
}
-
}
render() {
return (
- {this.props.historyList.map((item, index, historyList) => {
- let preItemIndex = index + 1;
- if (preItemIndex === historyList.length) {
- preItemIndex = index;
- }
+ {this.props.historyList.map((item, index) => {
return (
);
})}
diff --git a/frontend/src/css/file-history.css b/frontend/src/css/file-history.css
index 9789f5f561..58638923e5 100644
--- a/frontend/src/css/file-history.css
+++ b/frontend/src/css/file-history.css
@@ -1,38 +1,54 @@
-.history-main {
+.history-header .title {
+ font-size: 1.5rem;
+ line-height: 1rem;
+}
+
+.history-header .title .go-back {
+ margin-right: 0.75rem;
+ color: #c0c0c0;
+}
+
+.history-header .title .go-back:hover {
+ color:#ff9933;
+ text-decoration: none;
+}
+
+.content-viewer {
background-color: #fafaf9;
border-radius: 10px;
+ overflow: auto;
}
-.history, .markdown-viewer-render-content {
+.markdown-viewer-render-content {
background-color: #fff;
word-break: break-word;
+ margin: 20px 40px;
+ border: 1px solid #e6e6dd;
}
-.history-heading {
- font-size: 25px;
-}
-
-.panel-heading {
+.panel-header {
position: relative;
- padding: .5rem 0rem;
+ padding: .5rem 0;
width: 100%;
border-bottom: 1px solid #e8e8e8;
font-size: 1rem;
- font-weight: normal;
+ font-weight: 400;
line-height: 1.5;
height: 36px;
text-align: center;
}
-.history .history-body {
- flex: 1;
+.history-body {
display: flex;
+ flex: 1;
+ overflow: hidden;
min-height: 0;
}
.history-list-container {
flex: 1;
flex-direction: column;
+ min-height: 0;
overflow: auto;
}
@@ -93,14 +109,3 @@
text-decoration: none;
color: #6e7687;
}
-
-.history-viewer-contanier {
- flex: 1;
- overflow: auto;
-}
-
-.markdown-viewer-render-content {
- margin: 20px 40px;
- border: 1px solid #e6e6dd;
-}
-
diff --git a/frontend/src/css/layout.css b/frontend/src/css/layout.css
index 8ef77fe3d6..ca465be238 100644
--- a/frontend/src/css/layout.css
+++ b/frontend/src/css/layout.css
@@ -8,6 +8,12 @@
/* for top bottom layout*/
#header {
display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.5rem 1rem;
+ border-bottom: 1px solid #e8e8e8;
+ background-color: #f4f4f7;
+ font-size: 1rem;
}
/* for left right layout */
diff --git a/frontend/src/file-history.js b/frontend/src/file-history.js
index 29d5e35e62..3f069194c3 100644
--- a/frontend/src/file-history.js
+++ b/frontend/src/file-history.js
@@ -1,11 +1,14 @@
-import React from 'react';
+import React, { Fragment } from 'react';
import ReactDOM from 'react-dom';
+import axios from 'axios';
import editUtilties from './utils/editor-utilties';
-import { filePath } from './utils/constants';
+import { siteRoot, filePath, fileName } from './utils/constants';
+import { Utils } from './utils/utils';
import URLDecorator from './utils/url-decorator';
+import CommonToolbar from './components/toolbar/common-toolbar';
import SidePanel from './pages/file-history/side-panel';
import MainPanel from './pages/file-history/main-panel';
-import axios from 'axios';
+
import './assets/css/fa-solid.css';
import './assets/css/fa-regular.css';
import './assets/css/fontawesome.css';
@@ -19,52 +22,80 @@ class FileHistory extends React.Component {
constructor(props) {
super(props);
this.state = {
- content: '',
renderingContent: true,
- fileOwner: '',
- markdownContent: '',
- markdownContentOld: ''
+ newMarkdownContent: '',
+ oldMarkdownContent: ''
};
}
+ onSearchedClick = (selectedItem) => {
+ if (selectedItem.is_dir === true) {
+ let url = siteRoot + 'library/' + selectedItem.repo_id + '/' + selectedItem.repo_name + selectedItem.path;
+ let newWindow = window.open('about:blank');
+ newWindow.location.href = url;
+ } else {
+ let url = siteRoot + 'lib/' + selectedItem.repo_id + '/file' + Utils.encodePath(selectedItem.path);
+ let newWindow = window.open('about:blank');
+ newWindow.location.href = url;
+ }
+ }
- setDiffContent = (markdownContent, markdownContentOld)=> {
+ setDiffContent = (newmarkdownContent, oldMarkdownContent)=> {
this.setState({
renderingContent: false,
- markdownContent: markdownContent,
- markdownContentOld: markdownContentOld
+ newmarkdownContent: newmarkdownContent,
+ oldMarkdownContent: oldMarkdownContent,
});
}
- onHistoryItemClick = (item, preCommitID)=> {
- let objID = item.rev_file_id;
- let downLoadURL = URLDecorator.getUrl({type: 'download_historic_file', filePath: filePath, objID: objID});
- let downLoadURL1 = URLDecorator.getUrl({type: 'download_historic_file', filePath: filePath, objID: preCommitID});
+ onHistoryItemClick = (item, preItem)=> {
this.setState({renderingContent: true});
- axios.all([
- editUtilties.getFileContent(downLoadURL),
- editUtilties.getFileContent(downLoadURL1)
- ]).then(axios.spread((res1, res2) => {
- this.setDiffContent(res1.data, res2.data);
- }));
+ if (preItem) {
+ let currID = item.rev_file_id;
+ let preID = preItem.rev_file_id;
+ let downLoadURL = URLDecorator.getUrl({type: 'download_historic_file', filePath: filePath, objID: currID});
+ let downLoadURL1 = URLDecorator.getUrl({type: 'download_historic_file', filePath: filePath, objID: preID});
+ axios.all([
+ editUtilties.getFileContent(downLoadURL),
+ editUtilties.getFileContent(downLoadURL1)
+ ]).then(axios.spread((res1, res2) => {
+ this.setDiffContent(res1.data, res2.data);
+ }));
+ } else {
+ let currID = item.rev_file_id;
+ let downLoadURL = URLDecorator.getUrl({type: 'download_historic_file', filePath: filePath, objID: currID});
+ axios.all([
+ editUtilties.getFileContent(downLoadURL),
+ ]).then(axios.spread((res1) => {
+ this.setDiffContent(res1.data, '');
+ }));
+ }
}
render() {
return(
-
-
-
-
-
+
+
+
+
+
+
+
);
}
}
diff --git a/frontend/src/pages/file-history/main-panel.js b/frontend/src/pages/file-history/main-panel.js
index fbce83a083..32c43ff470 100644
--- a/frontend/src/pages/file-history/main-panel.js
+++ b/frontend/src/pages/file-history/main-panel.js
@@ -2,7 +2,6 @@ import React from 'react';
import PropTypes from 'prop-types';
import Prism from 'prismjs';
import Loading from '../../components/loading';
-import CommonToolbar from '../../components/toolbar/common-toolbar';
import DiffViewer from '@seafile/seafile-editor/dist/viewer/diff-viewer';
import '../../css/initial-style.css';
@@ -12,8 +11,8 @@ const contentClass = 'markdown-viewer-render-content';
const propTypes = {
renderingContent: PropTypes.bool.isRequired,
content: PropTypes.string,
- markdownContent: PropTypes.string.isRequired,
- markdownContentOld: PropTypes.string.isRequired,
+ newMarkdownContent: PropTypes.string.isRequired,
+ oldMarkdownContent: PropTypes.string.isRequired,
};
class MainPanel extends React.Component {
@@ -28,18 +27,18 @@ class MainPanel extends React.Component {
render() {
return (
-
-
-
-
-
-
- {
- this.props.renderingContent ?
- (
) :
- (
)
- }
-
+
+
+ {
+ this.props.renderingContent ?
+ (
) :
+ (
+
+
)
+ }
);
diff --git a/frontend/src/pages/file-history/side-panel.js b/frontend/src/pages/file-history/side-panel.js
index 21cf073eec..084ab81fba 100644
--- a/frontend/src/pages/file-history/side-panel.js
+++ b/frontend/src/pages/file-history/side-panel.js
@@ -1,14 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { gettext, PER_PAGE, filePath, fileName } from '../../utils/constants';
+import { gettext, PER_PAGE, filePath } from '../../utils/constants';
import editUtilties from '../../utils/editor-utilties';
import Loading from '../../components/loading';
import HistoryListView from '../../components/history-list-view/history-list-view';
-import HistoryListMenu from '../../components/history-list-view/history-list-menu';
const propTypes = {
- onHistoryItemClick: PropTypes.func.isRequired,
- setDiffContent: PropTypes.func.isRequired,
+ onItemClick: PropTypes.func.isRequired,
};
class SidePanel extends React.Component {
@@ -22,26 +20,21 @@ class SidePanel extends React.Component {
isLoading: true,
isError: false,
fileOwner: '',
- isListMenuShow: false,
- isFirstItem: false,
- currentItem: null,
- menuPosition: {top: '', left: ''},
- isItemFrezeed: false,
isReloadingData: false,
};
}
componentDidMount() {
editUtilties.listFileHistoryRecords(filePath, 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);
- document.addEventListener('click', this.onHideContextMenu);
});
}
- componentWillUnmount() {
- document.removeEventListener('click', this.onHideContextMenu);
- }
-
refershFileList() {
editUtilties.listFileHistoryRecords(filePath, 1, PER_PAGE).then(res => {
this.initResultState(res.data);
@@ -57,7 +50,6 @@ class SidePanel extends React.Component {
isLoading: false,
isError: false,
fileOwner: result.data[0].creator_email,
- currentItem: result.data[0],
});
}
}
@@ -75,25 +67,6 @@ class SidePanel extends React.Component {
}
}
- onShowContenxtMenu = (e, item, isFirstItem) => {
- let left = e.clientX - 8*16;
- let top = e.clientY + 10;
- this.setState({
- currentItem: item,
- isFirstItem: isFirstItem,
- isListMenuShow: !this.state.isListMenuShow,
- menuPosition: {top: top, left: left},
- isItemFrezeed: !this.state.isItemFrezeed,
- });
- }
-
- onHideContextMenu = (e) => {
- this.setState({
- isListMenuShow: false,
- isItemFrezeed: false
- });
- }
-
reloadMore = () => {
if (!this.state.isReloadingData) {
let currentPage = this.state.currentPage + 1;
@@ -103,16 +76,13 @@ class SidePanel extends React.Component {
});
editUtilties.listFileHistoryRecords(filePath, currentPage, PER_PAGE).then(res => {
this.updateResultState(res.data);
- this.setState({
- isReloadingData: false
- });
+ this.setState({isReloadingData: false});
});
}
}
- onRestoreFile = () => {
- this.onHideContextMenu();
- let commitId = this.state.currentItem.commit_id;
+ onItemRestore = (currentItem) => {
+ let commitId = currentItem.commit_id;
editUtilties.revertFile(filePath, commitId).then(res => {
if (res.data.success) {
this.setState({isLoading: true});
@@ -121,28 +91,15 @@ class SidePanel extends React.Component {
});
}
- onDownloadFile = () => {
- this.onHideContextMenu();
- }
-
- onHistoryItemClick =(item, preCommitID) => {
- this.setState({currentItem: item});
- this.props.onHistoryItemClick(item, preCommitID);
+ onItemClick =(item, preItem) => {
+ this.props.onItemClick(item, preItem);
}
render() {
return (
-
-
-
{gettext('History Versions')}
+
+
{gettext('History Versions')}
{this.state.isLoading && }
{this.state.historyInfo &&
@@ -150,22 +107,11 @@ class SidePanel extends React.Component {
hasMore={this.state.hasMore}
isReloadingData={this.state.isReloadingData}
historyList={this.state.historyInfo}
- onMenuControlClick={this.onShowContenxtMenu}
- isItemFrezeed={this.state.isItemFrezeed}
reloadMore={this.reloadMore}
- currentItem={this.state.currentItem}
- onHistoryItemClick={this.onHistoryItemClick}
- setDiffContent={this.props.setDiffContent}
+ onItemClick={this.onItemClick}
+ onItemRestore={this.onItemRestore}
/>
}
-
diff --git a/media/css/seahub_react.css b/media/css/seahub_react.css
index 660bdda4c9..5b3b96c508 100644
--- a/media/css/seahub_react.css
+++ b/media/css/seahub_react.css
@@ -732,18 +732,6 @@ a.sf-popover-item:hover {
background-color: #f8f8f8;
}
-/* for go-back */
-.go-back {
- font-size: 25px;
- padding-right: 0.75rem;
- color:#ccc;
-}
-
-.go-back:hover {
- color:#ff9933;
- text-decoration: none;
-}
-
/* basic layout */
.side-panel-top {
padding: .5rem 1rem;