diff --git a/frontend/src/components/dir-view-mode/dir-column-file.js b/frontend/src/components/dir-view-mode/dir-column-file.js index 0666aabeea..a417ecfa56 100644 --- a/frontend/src/components/dir-view-mode/dir-column-file.js +++ b/frontend/src/components/dir-view-mode/dir-column-file.js @@ -73,6 +73,8 @@ class DirColumnFile extends React.Component { lastModified = {this.props.lastModified} latestContributor={this.props.latestContributor} onLinkClick={this.props.onLinkClick} + repoID={this.props.repoID} + path={this.props.path} > diff --git a/frontend/src/components/wiki-markdown-viewer.js b/frontend/src/components/wiki-markdown-viewer.js index 0824a7c4b3..90f1c7a942 100644 --- a/frontend/src/components/wiki-markdown-viewer.js +++ b/frontend/src/components/wiki-markdown-viewer.js @@ -1,9 +1,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import MarkdownViewer from '@seafile/seafile-editor/dist/viewer/markdown-viewer'; -import { gettext, repoID, slug, serviceURL, isPublicWiki } from '../utils/constants'; +import { gettext, repoID, slug, serviceURL, isPublicWiki, siteRoot } from '../utils/constants'; +import { Card, CardTitle, CardText } from 'reactstrap'; import Loading from './loading'; import { Utils } from '../utils/utils'; +import { seafileAPI } from '../utils/seafile-api'; +import '../css/related-files-list.css'; const propTypes = { children: PropTypes.object, @@ -14,6 +17,9 @@ const propTypes = { onLinkClick: PropTypes.func.isRequired, isWiki: PropTypes.bool, isTOCShow: PropTypes.bool, + // for dir-column-file component(import repoID is undefined) + repoID: PropTypes.string, + path: PropTypes.string, }; const contentClass = 'wiki-page-content'; @@ -23,7 +29,8 @@ class WikiMarkdownViewer extends React.Component { constructor(props) { super(props); this.state = { - activeTitleIndex: 0 + activeTitleIndex: 0, + relatedFiles: [], }; this.markdownContainer = React.createRef(); this.links = []; @@ -36,6 +43,7 @@ class WikiMarkdownViewer extends React.Component { this.links.forEach(link => { link.addEventListener('click', this.onLinkClick); }); + this.listRelatedFiles(); } componentWillReceiveProps() { @@ -43,6 +51,7 @@ class WikiMarkdownViewer extends React.Component { this.links.forEach(link => { link.removeEventListener('click', this.onLinkClick); }); + this.listRelatedFiles(); } componentDidUpdate() { @@ -64,6 +73,17 @@ class WikiMarkdownViewer extends React.Component { this.titlesInfo = markdownViewer.titlesInfo; } + listRelatedFiles = () => { + // for dir-column-file component(import repoID is undefined) + if (this.props.repoID && this.props.path) { + seafileAPI.listRelatedFiles(this.props.repoID, this.props.path).then(res => { + this.setState({ + relatedFiles: res.data.related_files + }); + }); + } + } + onLinkClick = (event) => { event.preventDefault(); event.stopPropagation(); @@ -179,6 +199,37 @@ class WikiMarkdownViewer extends React.Component { ); } + renderRelatedFiles = () => { + const relatedFiles = this.state.relatedFiles; + if (relatedFiles.length > 0) { + return ( +
+
+

{gettext('related files')}

+
+ { + relatedFiles.map((relatedFile, index) => { + let href = siteRoot + 'lib/' + relatedFile.repo_id + '/file' + Utils.encodePath(relatedFile.path); + return( +
+ + + {relatedFile.name} + {relatedFile.repo_name} + + + +
+ ); + }) + } +
+ ); + } else { + return null; + } + } + render() { if (this.props.isFileLoading) { return ; @@ -188,6 +239,7 @@ class WikiMarkdownViewer extends React.Component {
{this.props.children} {this.renderMarkdown()} + {this.props.isWiki && this.renderRelatedFiles()}

{gettext('Last modified by')} {this.props.latestContributor}, {this.props.lastModified}

diff --git a/frontend/src/css/related-files-list.css b/frontend/src/css/related-files-list.css new file mode 100644 index 0000000000..f24af66e4a --- /dev/null +++ b/frontend/src/css/related-files-list.css @@ -0,0 +1,56 @@ +.sf-releted-files { + margin-top: 80px; +} + +.sf-releted-files-header { + border-top: 2px dashed #E6E6EB; +} + +.sf-releted-files-header h4 { + font-weight: 400; + margin-top: 40px; +} + +.sf-releted-files .sf-releted-file { + margin: 20px 0; +} + +.sf-releted-files .sf-releted-files h4, +.sf-releted-files .sf-releted-files p { + margin: 0; +} + +.sf-releted-files .sf-releted-file a { + text-decoration: none; +} + +.sf-releted-files .sf-releted-file .card-body { + padding: 0.5rem 1.5rem; +} + +.sf-releted-files .sf-releted-file .card { + border-radius: 10px; + background-color: #e5e5ea; + border-color: #e5e5ea; +} + +.sf-releted-files .sf-releted-file .card-title { + margin: 0 0 2px; + color: #333; +} + +.sf-releted-files .sf-releted-file .card-text { + color: #888; +} + +.sf-releted-file-arrow { + position: absolute; + right: 30px; + top: 50%; + margin-top: -8px; + border-top: 2px solid #aaa; + border-right: 2px solid #aaa; + transform: rotate(45deg); + width: 16px; + height: 16px; +} \ No newline at end of file