diff --git a/frontend/src/components/constants.js b/frontend/src/components/constants.js index 88dc36b69a..375033cb22 100644 --- a/frontend/src/components/constants.js +++ b/frontend/src/components/constants.js @@ -16,8 +16,7 @@ export const slug = window.wiki ? window.wiki.config.slug : ''; export const repoID = window.wiki ? window.wiki.config.repoId : ''; export const serviceUrl = window.wiki ? window.wiki.config.serviceUrl : ''; export const initialFilePath = window.wiki ? window.wiki.config.initial_file_path : ''; -export const permission = window.wiki ? window.wiki.config.permission : ''; - +export const permission = window.wiki ? window.wiki.config.permission === 'True' : ''; // file history export const PER_PAGE = 25; diff --git a/frontend/src/components/search-result-item.js b/frontend/src/components/search/search-result-item.js similarity index 93% rename from frontend/src/components/search-result-item.js rename to frontend/src/components/search/search-result-item.js index b08f158d4e..1492526d9a 100644 --- a/frontend/src/components/search-result-item.js +++ b/frontend/src/components/search/search-result-item.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; class SearchResultItem extends React.Component { diff --git a/frontend/src/components/search.js b/frontend/src/components/search/search.js similarity index 92% rename from frontend/src/components/search.js rename to frontend/src/components/search/search.js index 92df6cb61f..18d99ab00c 100644 --- a/frontend/src/components/search.js +++ b/frontend/src/components/search/search.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; -import { gettext, repoID } from './constants'; +import { gettext, repoID } from '../constants'; import SearchResultItem from './search-result-item'; -import editorUtilities from '../utils/editor-utilties'; +import editorUtilities from '../../utils/editor-utilties'; class Search extends Component { @@ -192,10 +192,11 @@ class Search extends Component {
-
+
+ - - +
{this.renderSearchResult()} diff --git a/frontend/src/components/toolbar/path-toolbar.js b/frontend/src/components/toolbar/path-toolbar.js new file mode 100644 index 0000000000..1dfafc72a5 --- /dev/null +++ b/frontend/src/components/toolbar/path-toolbar.js @@ -0,0 +1,29 @@ +import React from 'react'; +import { gettext, repoID, permission, siteRoot, initialFilePath } from '../constants'; + +function PathToolbar() { + + let trashUrl = ''; + let historyUrl = ''; + if (initialFilePath === '/' && permission) { + trashUrl = siteRoot + 'repo/recycle/' + repoID + '/?referer=' + encodeURIComponent(location.href); + historyUrl = siteRoot + 'repo/history/' + repoID + '/?referer=' + encodeURIComponent(location.href); + return ( +
    +
  • +
  • +
+ ); + } else if (permission) { + trashUrl = siteRoot + 'dir/recycle/' + repoID + '/?dir_path=' + encodeURIComponent(initialFilePath); + return ( +
    +
  • +
+ ); + } + return ''; + +} + +export default PathToolbar; diff --git a/frontend/src/components/tree-dir-view/tree-dir-list.js b/frontend/src/components/tree-dir-view/tree-dir-list.js index 687c5d5591..00a31051f2 100644 --- a/frontend/src/components/tree-dir-view/tree-dir-list.js +++ b/frontend/src/components/tree-dir-view/tree-dir-list.js @@ -5,10 +5,23 @@ class TreeDirList extends React.Component { constructor(props) { super(props); this.state = { - isMourseEnter: false + isMourseEnter: false, + highlight: '', } } + onMouseEnter = () => { + this.setState({ + highlight: 'tr-highlight' + }); + } + + onMouseLeave = () => { + this.setState({ + highlight: '', + }); + } + onMainNodeClick = () => { this.props.onMainNodeClick(this.props.node); } @@ -16,14 +29,12 @@ class TreeDirList extends React.Component { render() { let node = this.props.node; return ( - - + + - - {node.name} - - {node.size} + {node.name} + {node.size} {node.last_update_time} ) diff --git a/frontend/src/components/tree-dir-view/tree-dir-view.js b/frontend/src/components/tree-dir-view/tree-dir-view.js index 91dc0114a4..d7f473d1a1 100644 --- a/frontend/src/components/tree-dir-view/tree-dir-view.js +++ b/frontend/src/components/tree-dir-view/tree-dir-view.js @@ -1,6 +1,6 @@ import React, { Component } from "react"; import TreeDirList from './tree-dir-list' -import "../../css/tree-dir-view.css"; +import "../../css/common.css"; const gettext = window.gettext; class TreeDirView extends React.Component { @@ -9,16 +9,16 @@ class TreeDirView extends React.Component { let children = node.hasChildren() ? node.children : null; return ( - - - - +
+ + + - + - + {children && children.map((node, index) => { return ( diff --git a/frontend/src/components/tree-view/tree-node-view.js b/frontend/src/components/tree-view/tree-node-view.js index 8487f047cb..0997eebbeb 100644 --- a/frontend/src/components/tree-view/tree-node-view.js +++ b/frontend/src/components/tree-view/tree-node-view.js @@ -124,7 +124,7 @@ class TreeNodeView extends React.Component { } renderMenuController() { - if (permission === "True") { + if (permission) { let isShow = (this.props.node.path === this.props.currentFilePath); return (
diff --git a/frontend/src/css/common.css b/frontend/src/css/common.css index f406855083..38055aa6c8 100644 --- a/frontend/src/css/common.css +++ b/frontend/src/css/common.css @@ -32,6 +32,30 @@ .flex-right { justify-content: flex-end; } + +/* begin path navigation */ +.path-containter { /* for the real path */ + font-size:16px; + word-break: break-all; +} + +.path-split { + display: inline-block; + padding: 0 5px; + color: #818a91; +} + +.path-link { + color: #eb8205 !important; + text-decoration: none; +} + +.path-link:hover { + cursor: pointer; + text-decoration: underline !important; +} +/* end path navigation */ + /* begin main table list style */ .table-container { @@ -47,6 +71,8 @@ .table-container table th { text-align: left; font-weight: normal; + font-size: 13px; + line-height: 1.6; color: #9c9c9c; } @@ -57,15 +83,26 @@ } .table-container table th, .table-container table td { - padding-top: 5px; - padding-bottom: 5px; + padding: 5px 3px; border-bottom: 1px solid #eee; } -.table-container table tr img { +.table-container table th { + padding-top: 1rem; +} + +.table-container table .icon { + position: relative; +} + +.table-container table .icon img { + position: absolute; display: block; width: 24px; height: 24px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); } /* specific handler */ .table-container table .menu-toggle { diff --git a/frontend/src/css/file-history.css b/frontend/src/css/file-history.css index 90aebef9a0..4ddaac6330 100644 --- a/frontend/src/css/file-history.css +++ b/frontend/src/css/file-history.css @@ -8,8 +8,6 @@ } .history-heading { - height: 3.1875rem; - line-height: 3.1875rem; font-size: 25px; } diff --git a/frontend/src/css/search.css b/frontend/src/css/search.css index c989d7ffa7..436c32b7b9 100644 --- a/frontend/src/css/search.css +++ b/frontend/src/css/search.css @@ -13,32 +13,18 @@ z-index: 2; } -.search-input-container { - position: relative; +.search-container .search-icon-left { + display: flex; +} + +.search-container .search-icon-right { + cursor: pointer; + pointer-events: all; + font-style: normal; } .search-input { - padding: 0 2rem; - height: 2rem; -} - -.search-icon { - position: absolute; - top: 0; - width: 2rem; - height: 2rem; - display: flex; - justify-content:center; - align-items:center; - color: #999 !important; -} - -.icon-search{ - left: 0; -} - -.sf2-icon-x3{ - right: 0; + height: 1.875rem; } .search-result-container { diff --git a/frontend/src/css/toolbar.css b/frontend/src/css/toolbar.css new file mode 100644 index 0000000000..72aff25857 --- /dev/null +++ b/frontend/src/css/toolbar.css @@ -0,0 +1,83 @@ + +/* begin current-module-toobar */ +.cur-view-toolbar { + position: relative; + display: flex; + flex: 1; +} + +.cur-view-toolbar:before { + position: absolute; + top: 3px; + bottom: 3px; + left: -16px; + border-left: 1px solid #ddd; + content: ''; +} + +.top-toolbar-btn { + padding: 0 0.25rem; + margin-right: 0.25rem; + height: 30px; + min-width: 55px; + background-color: #fff !important; + line-height: 29px; + font-weight: normal; + font-size: 13px; + color: #333; + border: 1px solid #ccc; + border-radius: 2px; +} + +.sf-view-mode-change-btn { + padding: 0; + height: 30px; + min-width: 2rem; + color: #aaa; + background-color: #fff !important; + border: 1px solid #ccc; + line-height: 29px; + font-size: 18px; + border-radius: 0 !important; +} + +.sf-view-mode-change-btn.current-mode { + background-color: #ccc !important; + color: #fff !important; +} + +/* end current-module-toobar */ + +/* begin common-toolbar */ +.common-toolbar { + display: flex; + margin-left: auto; +} + +.common-toolbar div{ + margin-left: .5rem; +} +/* end common-toolbar */ + +/* begin path toolbar */ +.path-toolbar { + list-style: none; +} + +.path-toolbar .toolbar-item { + display: inline-block; + text-align: center; + margin-left: 0.75rem; +} + +.path-toolbar .toolbar-item a { + color:#8a8a8a; + font-size:22px; +} + + +.path-toolbar .toolbar-item a:hover { + color:#eb8205; + text-decoration:none; +} +/* end path toolbar */ diff --git a/frontend/src/css/tree-dir-view.css b/frontend/src/css/tree-dir-view.css deleted file mode 100644 index 36dd37323c..0000000000 --- a/frontend/src/css/tree-dir-view.css +++ /dev/null @@ -1,50 +0,0 @@ -.doc-view-container { - width: 100%; - height: 100%; - margin: 10px 16px; -} - -.doc-view-header .row, -.doc-view-body .row { - margin: 0; -} - -.doc-view-body { - width: 100%; - height: 100%; -} - -.doc-view-body tr:hover{ - background-color: #f8f8f8; -} - -.doc-view-header tr .dirent-icon, -.doc-view-body tr .dirent-icon { - display: flex; - align-items: center; - justify-content: center; -} - -.doc-view-container td { - color: #333; - font-size: 14px; - word-break: break-all; -} - -.doc-view-container th { - text-align: left; - font-weight: normal; - color: #9c9c9c; -} - -.doc-view-container th, td { - padding-top: 5px; - padding-bottom: 5px; - border-bottom: 1px solid #eee; -} -.doc-view-container .img-placeholder, -.doc-view-container tr img { - display: block; - width: 24px; - height: 24px; -} diff --git a/frontend/src/css/wiki.css b/frontend/src/css/wiki.css index 50c89ee744..53ec91d87d 100644 --- a/frontend/src/css/wiki.css +++ b/frontend/src/css/wiki.css @@ -41,7 +41,8 @@ .wiki-main .cur-view-path { border-bottom: 1px solid #e8e8e8; - margin-bottom: 8px; + display: flex; + justify-content: space-between; } .wiki-main .cur-view-path::after { display:none; @@ -191,12 +192,3 @@ img[src=""] { .wiki-md-viewer-rendered-content.article h1 { margin-top: 0; } - -.custom-link { - color: #eb8205 !important; - cursor: pointer; -} - -.custom-link:hover { - text-decoration: underline !important; -} \ No newline at end of file diff --git a/frontend/src/dashboard.js b/frontend/src/dashboard.js index b8c9a970da..0a14f0f2d1 100644 --- a/frontend/src/dashboard.js +++ b/frontend/src/dashboard.js @@ -3,7 +3,7 @@ import ReactDOM from 'react-dom'; import SidePanel from './pages/dashboard/side-panel'; import MainPanel from './pages/dashboard/main-panel'; import Account from './components/account'; -import Search from './components/search'; +import Search from './components/search/search'; import Notification from './components/notification'; import cookie from 'react-cookies'; import { isPro, gettext, siteRoot } from './components/constants'; @@ -12,6 +12,7 @@ import './assets/css/fa-solid.css'; import './assets/css/fa-regular.css'; import './assets/css/fontawesome.css'; import './css/dashboard.css'; +import './css/toolbar.css'; import './css/search.css'; diff --git a/frontend/src/drafts.js b/frontend/src/drafts.js index 02fdea4dc5..611c0840c3 100644 --- a/frontend/src/drafts.js +++ b/frontend/src/drafts.js @@ -10,6 +10,7 @@ import './assets/css/fa-regular.css'; import './assets/css/fontawesome.css'; import './css/layout.css'; import './css/common.css'; +import './css/toolbar.css'; class Drafts extends Component { diff --git a/frontend/src/file-history.js b/frontend/src/file-history.js index 89751ef5ce..9614acc07a 100644 --- a/frontend/src/file-history.js +++ b/frontend/src/file-history.js @@ -12,6 +12,7 @@ import './assets/css/fa-regular.css'; import './assets/css/fontawesome.css'; import './css/layout.css'; import './css/file-history.css'; +import './css/toolbar.css'; class FileHistory extends React.Component { diff --git a/frontend/src/pages/drafts/main-panel.js b/frontend/src/pages/drafts/main-panel.js index 24d7625326..98ba59d49d 100644 --- a/frontend/src/pages/drafts/main-panel.js +++ b/frontend/src/pages/drafts/main-panel.js @@ -72,8 +72,10 @@ class MainPanel extends React.Component { return (
+
+
{gettext('Drafts')}
diff --git a/frontend/src/pages/file-history/main-panel.js b/frontend/src/pages/file-history/main-panel.js index 6b3a123b55..33ac0266da 100644 --- a/frontend/src/pages/file-history/main-panel.js +++ b/frontend/src/pages/file-history/main-panel.js @@ -23,7 +23,7 @@ class MainPanel extends React.Component { return (
-
+
diff --git a/frontend/src/pages/repo-wiki-mode/main-panel.js b/frontend/src/pages/repo-wiki-mode/main-panel.js index 9b874706d3..880070b656 100644 --- a/frontend/src/pages/repo-wiki-mode/main-panel.js +++ b/frontend/src/pages/repo-wiki-mode/main-panel.js @@ -1,13 +1,21 @@ import React, { Component } from 'react'; -import { gettext, repoID, serviceUrl, slug, siteRoot, isPro, permission } from '../../components/constants'; -import Search from '../../components/search'; +import { gettext, repoID, serviceUrl, slug, siteRoot, isPro } from '../../components/constants'; +import Search from '../../components/search/search'; import Account from '../../components/account'; import Notification from '../../components/notification'; +import PathToolbar from '../../components/toolbar/path-toolbar'; import MarkdownViewer from '../../components/markdown-viewer'; import TreeDirView from '../../components/tree-dir-view/tree-dir-view'; class MainPanel extends Component { + constructor(props) { + super(props); + this.state = { + isWikiMode: true + } + } + onMenuClick = () => { this.props.onMenuClick(); } @@ -24,6 +32,10 @@ class MainPanel extends Component { switchViewMode = (e) => { e.preventDefault(); + if (e.target.id === 'wiki') { + return; + } + this.setState({isWikiMode: false}); this.props.switchViewMode(e.target.id); } @@ -42,7 +54,15 @@ class MainPanel extends Component { } else { nodePath += "/" + item; return ( - /{item} + + / + + {item} + + ) } }); @@ -50,18 +70,24 @@ class MainPanel extends Component { return (
- -
- { permission && - {gettext("Edit")} - } - - +
+ +
+ { + this.props.permission === 'rw' && + + } +
+
+ + + +
- {isPro && + { + isPro && + } @@ -75,8 +101,9 @@ class MainPanel extends Component { {slug} {pathElem}
+
-
+
{ this.props.isViewFileState && /{item} + + / + + {item} + + ) } }); @@ -45,14 +53,17 @@ class MainPanel extends Component { return (
- - +
+ + { + this.props.permission === 'rw' && + + } +
- {isPro && + { + isPro && + } @@ -67,7 +78,7 @@ class MainPanel extends Component { {pathElem}
-
+
{ this.props.isViewFileState && { const downLoadUrl = res.data; @@ -70,20 +71,20 @@ class Wiki extends Component { this.setState({ content: res.data, isFileLoading: false - }) - }) + }); + }); }); - }) + }); let fileUrl = serviceUrl + '/wiki/lib/' + repoID + filePath; window.history.pushState({urlPath: fileUrl, filePath: filePath}, filePath, fileUrl); } }, () => { - console.log("failed to load files"); + console.log('failed to load files'); this.setState({ isLoadFailed: true - }) - }) + }); + }); } initMainPanelData(filePath) { @@ -97,7 +98,7 @@ class Wiki extends Component { lastModified: moment.unix(mtime).fromNow(), permission: permission, filePath: filePath, - }) + }); seafileAPI.getFileDownloadLink(repoID, filePath).then((res) => { const downLoadUrl = res.data; @@ -105,29 +106,29 @@ class Wiki extends Component { this.setState({ content: res.data, isFileLoading: false - }) + }); }); - }) - }) + }); + }); - let fileUrl = serviceUrl + '/wiki/lib/' + repoID + filePath; - window.history.pushState({urlPath: fileUrl, filePath: filePath}, filePath, fileUrl); + let fileUrl = serviceUrl + '/wiki/lib/' + repoID + filePath; + window.history.pushState({urlPath: fileUrl, filePath: filePath}, filePath, fileUrl); } switchViewMode = (mode) => { let dirPath; - let tree = this.state.tree_data - let node = tree.getNodeByPath(this.state.filePath) + let tree = this.state.tree_data; + let node = tree.getNodeByPath(this.state.filePath); if (node.isDir()) { - dirPath = this.state.filePath + dirPath = this.state.filePath; } else { const index = this.state.filePath.lastIndexOf('/'); dirPath = this.state.filePath.substring(0, index); } - cookie.save("view_mode", mode, { path: '/' }) + cookie.save('view_mode', mode, { path: '/' }); - window.location.href = serviceUrl + "/#common/lib/" + repoID + dirPath; + window.location.href = serviceUrl + '/#common/lib/' + repoID + dirPath; } onLinkClick = (event) => { @@ -220,25 +221,25 @@ class Wiki extends Component { onMenuClick = () => { this.setState({ closeSideBar: !this.state.closeSideBar, - }) + }); } onCloseSide = () => { this.setState({ closeSideBar: !this.state.closeSideBar, - }) + }); } onAddFolderNode = (dirPath) => { editorUtilities.createDir(dirPath).then(res => { let tree = this.state.tree_data.clone(); let name = this.getFileNameByPath(dirPath); - let index = dirPath.lastIndexOf("/"); + let index = dirPath.lastIndexOf('/'); let parentPath = dirPath.substring(0, index); if (!parentPath) { - parentPath = "/"; + parentPath = '/'; } - let node = this.buildNewNode(name, "dir"); + let node = this.buildNewNode(name, 'dir'); let parentNode = tree.getNodeByPath(parentPath); tree.addNodeToParent(node, parentNode); if (this.state.isViewFileState) { @@ -246,23 +247,23 @@ class Wiki extends Component { this.setState({ tree_data: tree, changedNode: node - }) + }); } else { this.exitViewFileState(tree, parentNode); } - }) + }); } onAddFileNode = (filePath) => { editorUtilities.createFile(filePath).then(res => { let tree = this.state.tree_data.clone(); let name = this.getFileNameByPath(filePath); - let index = filePath.lastIndexOf("/"); + let index = filePath.lastIndexOf('/'); let parentPath = filePath.substring(0, index); if (!parentPath) { - parentPath = "/"; + parentPath = '/'; } - let node = this.buildNewNode(name, "file"); + let node = this.buildNewNode(name, 'file'); let parentNode = tree.getNodeByPath(parentPath); tree.addNodeToParent(node, parentNode); if (this.state.isViewFileState) { @@ -270,11 +271,11 @@ class Wiki extends Component { this.setState({ tree_data: tree, changedNode: node - }) + }); } else { this.exitViewFileState(tree, parentNode); } - }) + }); } onRenameNode = (node, newName) => { @@ -284,10 +285,10 @@ class Wiki extends Component { editorUtilities.renameFile(filePath, newName).then(res => { let cloneNode = node.clone(); - tree.updateNodeParam(node, "name", newName); + tree.updateNodeParam(node, 'name', newName); node.name = newName; let date = new Date().getTime()/1000; - tree.updateNodeParam(node, "last_update_time", moment.unix(date).fromNow()); + tree.updateNodeParam(node, 'last_update_time', moment.unix(date).fromNow()); node.last_update_time = moment.unix(date).fromNow(); if (this.state.isViewFileState) { @@ -308,7 +309,7 @@ class Wiki extends Component { changedNode: parentNode }); } - }) + }); } else if (node.isDir()) { editorUtilities.renameDir(filePath, newName).then(res => { @@ -316,10 +317,10 @@ class Wiki extends Component { let currentFileNode = tree.getNodeByPath(currentFilePath); let nodePath = node.path; - tree.updateNodeParam(node, "name", newName); + tree.updateNodeParam(node, 'name', newName); node.name = newName; let date = new Date().getTime()/1000; - tree.updateNodeParam(node, "last_update_time", moment.unix(date).fromNow()); + tree.updateNodeParam(node, 'last_update_time', moment.unix(date).fromNow()); node.last_update_time = moment.unix(date).fromNow(); if (this.state.isViewFileState) { @@ -344,7 +345,7 @@ class Wiki extends Component { this.setState({tree_data: tree}); } } - }) + }); } } @@ -374,10 +375,10 @@ class Wiki extends Component { this.setState({ tree_data: tree, changedNode: homeNode - }) + }); this.initMainPanelData(homeNode.path); } else { - this.setState({tree_data: tree}) + this.setState({tree_data: tree}); } } else { let parentNode = tree.getNodeByPath(this.state.filePath); @@ -413,26 +414,26 @@ class Wiki extends Component { } getFileNameByPath(path) { - let index = path.lastIndexOf("/"); + let index = path.lastIndexOf('/'); if (index === -1) { - return ""; + return ''; } return path.slice(index+1); } getHomeNode(treeData) { - return treeData.getNodeByPath("/home.md"); + return treeData.getNodeByPath('/home.md'); } buildNewNode(name, type) { let date = new Date().getTime()/1000; let node = new Node({ - name : name, - type: type, - size: '0', - last_update_time: moment.unix(date).fromNow(), - isExpanded: false, - children: [] + name : name, + type: type, + size: '0', + last_update_time: moment.unix(date).fromNow(), + isExpanded: false, + children: [] }); return node; } @@ -454,12 +455,12 @@ class Wiki extends Component { } isMarkdownFile(filePath) { - let index = filePath.lastIndexOf("."); + let index = filePath.lastIndexOf('.'); if (index === -1) { return false; } else { let type = filePath.substring(index).toLowerCase(); - if (type === ".md" || type === ".markdown") { + if (type === '.md' || type === '.markdown') { return true; } else { return false; @@ -478,23 +479,23 @@ class Wiki extends Component { } getPathFromInternalMarkdownLink(url) { - var re = new RegExp(serviceUrl + '/lib/' + repoID + '/file' + "(.*\.md)"); + var re = new RegExp(serviceUrl + '/lib/' + repoID + '/file' + '(.*\.md)'); var array = re.exec(url); var path = decodeURIComponent(array[1]); return path; } getPathFromInternalDirLink(url) { - var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + repoID + "(/.*)"); + var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + repoID + '(/.*)'); var array = re.exec(url); var path = decodeURIComponent(array[1]); var dirPath = path.substring(1); - var re = new RegExp("(^/.*)"); + re = new RegExp('(^/.*)'); if (re.test(dirPath)) { path = dirPath; } else { - path = '/' + dirPath + path = '/' + dirPath; } return path; diff --git a/frontend/src/wiki.js b/frontend/src/wiki.js index aa1ad77b3f..e25b82ca2e 100644 --- a/frontend/src/wiki.js +++ b/frontend/src/wiki.js @@ -5,14 +5,15 @@ import MainPanel from './pages/wiki/main-panel'; import moment from 'moment'; import { slug, repoID, serviceUrl, initialFilePath } from './components/constants'; import editorUtilities from './utils/editor-utilties'; -import Node from './components/tree-view/node' -import Tree from './components/tree-view/tree' +import Node from './components/tree-view/node'; +import Tree from './components/tree-view/tree'; import 'seafile-ui'; import './assets/css/fa-solid.css'; import './assets/css/fa-regular.css'; import './assets/css/fontawesome.css'; import './css/side-panel.css'; import './css/wiki.css'; +import './css/toolbar.css'; import './css/search.css'; class Wiki extends Component { @@ -60,18 +61,17 @@ class Wiki extends Component { permission: res.data.permission, filePath: filePath, isFileLoading: false - }) + }); }); const hash = window.location.hash; let fileUrl = serviceUrl + '/wikis/' + slug + filePath + hash; window.history.pushState({urlPath: fileUrl, filePath: filePath}, filePath, fileUrl); } }, () => { - console.log("failed to load files"); this.setState({ isLoadFailed: true - }) - }) + }); + }); } initMainPanelData(filePath){ @@ -85,12 +85,12 @@ class Wiki extends Component { permission: res.data.permission, filePath: filePath, isFileLoading: false - }) - }) + }); + }); - const hash = window.location.hash; - let fileUrl = serviceUrl + '/wikis/' + slug + filePath + hash; - window.history.pushState({urlPath: fileUrl, filePath: filePath}, filePath, fileUrl); + const hash = window.location.hash; + let fileUrl = serviceUrl + '/wikis/' + slug + filePath + hash; + window.history.pushState({urlPath: fileUrl, filePath: filePath}, filePath, fileUrl); } onLinkClick = (event) => { @@ -183,25 +183,25 @@ class Wiki extends Component { onMenuClick = () => { this.setState({ closeSideBar: !this.state.closeSideBar, - }) + }); } onCloseSide = () => { this.setState({ closeSideBar: !this.state.closeSideBar, - }) + }); } onAddFolderNode = (dirPath) => { editorUtilities.createDir(dirPath).then(res => { let tree = this.state.tree_data.clone(); let name = this.getFileNameByPath(dirPath); - let index = dirPath.lastIndexOf("/"); + let index = dirPath.lastIndexOf('/'); let parentPath = dirPath.substring(0, index); if (!parentPath) { - parentPath = "/"; + parentPath = '/'; } - let node = this.buildNewNode(name, "dir"); + let node = this.buildNewNode(name, 'dir'); let parentNode = tree.getNodeByPath(parentPath); tree.addNodeToParent(node, parentNode); if (this.state.isViewFileState) { @@ -209,23 +209,23 @@ class Wiki extends Component { this.setState({ tree_data: tree, changedNode: node - }) + }); } else { this.exitViewFileState(tree, parentNode); } - }) + }); } onAddFileNode = (filePath) => { editorUtilities.createFile(filePath).then(res => { let tree = this.state.tree_data.clone(); let name = this.getFileNameByPath(filePath); - let index = filePath.lastIndexOf("/"); + let index = filePath.lastIndexOf('/'); let parentPath = filePath.substring(0, index); if (!parentPath) { - parentPath = "/"; + parentPath = '/'; } - let node = this.buildNewNode(name, "file"); + let node = this.buildNewNode(name, 'file'); let parentNode = tree.getNodeByPath(parentPath); tree.addNodeToParent(node, parentNode); if (this.state.isViewFileState) { @@ -233,11 +233,11 @@ class Wiki extends Component { this.setState({ tree_data: tree, changedNode: node - }) + }); } else { this.exitViewFileState(tree, parentNode); } - }) + }); } onRenameNode = (node, newName) => { @@ -247,10 +247,10 @@ class Wiki extends Component { editorUtilities.renameFile(filePath, newName).then(res => { let cloneNode = node.clone(); - tree.updateNodeParam(node, "name", newName); + tree.updateNodeParam(node, 'name', newName); node.name = newName; let date = new Date().getTime()/1000; - tree.updateNodeParam(node, "last_update_time", moment.unix(date).fromNow()); + tree.updateNodeParam(node, 'last_update_time', moment.unix(date).fromNow()); node.last_update_time = moment.unix(date).fromNow(); if (this.state.isViewFileState) { @@ -271,7 +271,7 @@ class Wiki extends Component { changedNode: parentNode }); } - }) + }); } else if (node.isDir()) { editorUtilities.renameDir(filePath, newName).then(res => { @@ -279,10 +279,10 @@ class Wiki extends Component { let currentFileNode = tree.getNodeByPath(currentFilePath); let nodePath = node.path; - tree.updateNodeParam(node, "name", newName); + tree.updateNodeParam(node, 'name', newName); node.name = newName; let date = new Date().getTime()/1000; - tree.updateNodeParam(node, "last_update_time", moment.unix(date).fromNow()); + tree.updateNodeParam(node, 'last_update_time', moment.unix(date).fromNow()); node.last_update_time = moment.unix(date).fromNow(); if (this.state.isViewFileState) { @@ -307,7 +307,7 @@ class Wiki extends Component { this.setState({tree_data: tree}); } } - }) + }); } } @@ -337,10 +337,10 @@ class Wiki extends Component { this.setState({ tree_data: tree, changedNode: homeNode - }) + }); this.initMainPanelData(homeNode.path); } else { - this.setState({tree_data: tree}) + this.setState({tree_data: tree}); } } else { let parentNode = tree.getNodeByPath(this.state.filePath); @@ -376,26 +376,26 @@ class Wiki extends Component { } getFileNameByPath(path) { - let index = path.lastIndexOf("/"); + let index = path.lastIndexOf('/'); if (index === -1) { - return ""; + return ''; } return path.slice(index+1); } getHomeNode(treeData) { - return treeData.getNodeByPath("/home.md"); + return treeData.getNodeByPath('/home.md'); } buildNewNode(name, type) { let date = new Date().getTime()/1000; let node = new Node({ - name : name, - type: type, - size: '0', - last_update_time: moment.unix(date).fromNow(), - isExpanded: false, - children: [] + name : name, + type: type, + size: '0', + last_update_time: moment.unix(date).fromNow(), + isExpanded: false, + children: [] }); return node; } @@ -417,12 +417,12 @@ class Wiki extends Component { } isMarkdownFile(filePath) { - let index = filePath.lastIndexOf("."); + let index = filePath.lastIndexOf('.'); if (index === -1) { return false; } else { let type = filePath.substring(index).toLowerCase(); - if (type === ".md" || type === ".markdown") { + if (type === '.md' || type === '.markdown') { return true; } else { return false; @@ -441,23 +441,23 @@ class Wiki extends Component { } getPathFromInternalMarkdownLink(url) { - var re = new RegExp(serviceUrl + '/lib/' + repoID + '/file' + "(.*\.md)"); + var re = new RegExp(serviceUrl + '/lib/' + repoID + '/file' + '(.*\.md)'); var array = re.exec(url); var path = decodeURIComponent(array[1]); return path; } getPathFromInternalDirLink(url) { - var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + repoID + "(/.*)"); + var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + repoID + '(/.*)'); var array = re.exec(url); var path = decodeURIComponent(array[1]); var dirPath = path.substring(1); - var re = new RegExp("(^/.*)"); + re = new RegExp('(^/.*)'); if (re.test(dirPath)) { path = dirPath; } else { - path = '/' + dirPath + path = '/' + dirPath; } return path; @@ -495,11 +495,11 @@ class Wiki extends Component { onMainNodeClick={this.onMainNodeClick} />
- ) + ); } } ReactDOM.render ( , document.getElementById('wrapper') -) +); diff --git a/media/css/seahub.css b/media/css/seahub.css index c7005e29f8..9a21e39e27 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -162,7 +162,6 @@ .sf2-icon-organization:before { content:"\e010"; } .sf2-icon-share:before { content:"\e011"; } .sf2-icon-star:before { content:"\e012"; } -.sf2-icon-wiki:before { content:"\e013"; } .sf2-icon-history:before { content:"\e014"; } .sf2-icon-cog1:before { content:"\e015"; } .sf2-icon-trash:before { content:"\e016"; } @@ -180,9 +179,11 @@ .sf2-icon-msgs2:before { content:"\e021"; } /*.sf2-icon-group-settings:before { content:"\e022"; }*/ .sf2-icon-comment:before { content:"\e023"; } +.sf2-icon-wiki:before { content:"\e013"; } .sf2-icon-wiki2:before { content:"\e024"; } .sf2-icon-grid-view:before { content:"\e025"; } .sf2-icon-list-view:before { content:"\e026"; } +.sf2-icon-wiki-view:before { content:"\e013"; } .sf2-icon-plus:before { content: "\e027"; } .sf2-icon-copy:before { content: "\e028"; } .sf2-icon-move:before { content: "\e029"; } @@ -1856,7 +1857,7 @@ button.sf-dropdown-toggle:focus { } /**** custom magnificPopup ****/ .mfp-bottom-bar { - position:relative; + position:relative; } .mfp-title { min-width:230px; @@ -2067,6 +2068,9 @@ button.sf-dropdown-toggle:focus { background:#fff; line-height:17px; } +.btn-white { + height: 30px; +} .cur-view-toolbar .btn-white { min-width: 55px; } @@ -4167,6 +4171,7 @@ img.thumbnail { /* view mode */ .switch-mode { margin-left:15px; + font-size: 0; } .wiki-view-icon-btn, .grid-view-icon-btn, @@ -4180,14 +4185,27 @@ img.thumbnail { color:#aaa; cursor:pointer; border-radius:0; + margin-left: -1px; } +.list-view-icon-btn { + margin-left: 0; +} + +.wiki-view-icon-btn.active, .grid-view-icon-btn.active, .list-view-icon-btn.active { color:#fff; background:#ccc; cursor:default; } + +.view-btn:hover, +.view-btn:focus, +.view-btn:active { + position: relative; + z-index: 1; +} /* grid view */ .grid-item { display:inline-block; diff --git a/media/css/seahub_react.css b/media/css/seahub_react.css index e7c21ec715..64e5b0df43 100644 --- a/media/css/seahub_react.css +++ b/media/css/seahub_react.css @@ -14,7 +14,6 @@ * loading * popover * op-icon - * path * account * quota * side-tabnav @@ -59,10 +58,13 @@ .sf2-icon-monitor:before { content:"\e007"; } .sf2-icon-wrench:before { content:"\e001"; } .sf2-icon-bell:before { content:"\e003"; } -.sf2-icon-x3:before { content:"\e035"; } +.sf2-icon-close:before { content:"\e035"; } .sf2-icon-grid-view:before { content:"\e025"; } .sf2-icon-list-view:before { content:"\e026"; } +.sf2-icon-wiki-view:before { content:"\e013"; } .sf2-icon-edit:before { content:"\e018"; } +.sf2-icon-history:before { content:"\e014"; } +.sf2-icon-trash:before { content:"\e016"; } /* common class and element style*/ a { color:#eb8205; } @@ -98,13 +100,6 @@ ul,ol,li { /* UI Widget */ -/**** topbar button ****/ -.btn-topbar { - padding: 0.25rem 0.5rem; - line-height: 1.6; - font-weight: normal; -} - /**** caret ****/ .outer-caret, .inner-caret { @@ -197,24 +192,9 @@ ul,ol,li { vertical-align:middle; } - -/**** path ****/ -.path-containter { /* for the real path */ - font-size:16px; - word-break: break-all; -} -.path-split { - display:inline-block; - padding:0 5px; - color:#818a91; -} - -/* specific elements */ - /** Account info **/ #account { position:relative; - margin-left:32px; } #my-info { @@ -527,10 +507,6 @@ a.op-icon:focus { user-select: none; } -.common-toolbar { - margin-left:auto; - display:flex; -} #notifications { position:relative; width: 32px; diff --git a/seahub/templates/home_base.html b/seahub/templates/home_base.html index 8018b98fee..c6b7fd7570 100644 --- a/seahub/templates/home_base.html +++ b/seahub/templates/home_base.html @@ -76,6 +76,7 @@ {% endif %} +
  • {% trans "Drafts" %}
  • {% endblock %}
    diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index 9c768c0497..94eaa642ba 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -495,9 +495,10 @@
    - + + <% if (app.pageOptions.enable_repo_wiki_mode) { %> - + <% } %>
    diff --git a/static/scripts/app/views/dir.js b/static/scripts/app/views/dir.js index e75dbd3146..635c57a92b 100644 --- a/static/scripts/app/views/dir.js +++ b/static/scripts/app/views/dir.js @@ -46,8 +46,10 @@ define([ var view_mode = Cookies.get('view_mode'); if (view_mode == 'grid') { this.view_mode = 'grid'; - } else { + } else if (view_mode == 'list'){ this.view_mode = 'list'; + } else { + this.view_mode = 'wiki'; } this.contextOptions = {}; @@ -142,8 +144,22 @@ define([ this.dir.setPath(category, repo_id, path); this.dir.dirent_more = false; + // goto wiki + if ( this.view_mode === "wiki") { + this.$('.grid-view-icon-btn').removeClass('active'); + this.$('.list-view-icon-btn').removeClass('active'); + this.$('.wiki-view-icon-btn').addClass('active'); + var siteRoot = app.pageOptions.site_root; + var repoId = this.dir.repo_id; + var path = this.dir.path; + var url = siteRoot + 'wiki/lib/' + repoId + path; + + window.location = url; + return; + } this.renderDir(); + }, // public function @@ -616,6 +632,7 @@ define([ 'click #share-cur-dir': 'share', 'click #js-switch-grid-view': 'switchToGridView', 'click #js-switch-list-view': 'switchToListView', + 'click #js-switch-wiki-view': 'switchdToWikiView', 'click #mv-dirents': 'mv', 'click #cp-dirents': 'cp', @@ -888,6 +905,7 @@ define([ this.view_mode = 'grid'; Cookies.set('view_mode', 'grid'); this.$('.list-view-icon-btn').removeClass('active'); + this.$('.wiki-view-icon-btn').removeClass('active'); this.$('.grid-view-icon-btn').addClass('active'); this.renderDir(); } @@ -900,11 +918,30 @@ define([ this.view_mode = 'list'; Cookies.set('view_mode', 'list'); this.$('.grid-view-icon-btn').removeClass('active'); + this.$('.wiki-view-icon-btn').removeClass('active'); this.$('.list-view-icon-btn').addClass('active'); this.renderDir(); } }, + switchdToWikiView: function() { + if (this.view_mode == 'wiki') { + return; + } else { + this.view_mode = 'wiki'; + Cookies.set('view_mode', 'wiki'); + this.$('.grid-view-icon-btn').removeClass('active'); + this.$('.list-view-icon-btn').removeClass('active'); + this.$('.wiki-view-icon-btn').addClass('active'); + var siteRoot = app.pageOptions.site_root; + var repoId = this.dir.repo_id; + var path = this.dir.path; + var url = siteRoot + 'wiki/lib/' + repoId + path; + + window.location = url; + } + }, + sortDirents: function() { var sort_mode = app.pageOptions.sort_mode; switch(sort_mode) {
    {gettext('Name')}{gettext('Size')}{gettext('Size')} {gettext('Last Update')}