1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-17 07:41:26 +00:00

Wiki coding style improve (#2380)

This commit is contained in:
shanshuirenjia
2018-09-18 20:57:17 -05:00
committed by Daniel Pan
parent 3d165ec733
commit db47fb34a7
27 changed files with 437 additions and 275 deletions

View File

@@ -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;

View File

@@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
class SearchResultItem extends React.Component {

View File

@@ -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 {
<div className="search">
<div className={`search-mask ${this.state.isMaskShow ? "" : "hide"}`} onClick={this.onCloseHandler}></div>
<div className="search-container">
<div className="search-input-container">
<div className="input-icon">
<i className="search-icon-left input-icon-addon fas fa-search"></i>
<input
type="text"
className="search-input"
className="form-control search-input"
name="query"
placeholder={this.props.placeholder}
style={style}
@@ -204,8 +205,7 @@ class Search extends Component {
onChange={this.onChangeHandler}
autoComplete="off"
/>
<a className="search-icon fas fa-search"></a>
<a className={`search-icon sf2-icon-x3 ${this.state.isCloseShow ? "" : "hide"}`} onClick={this.onCloseHandler}></a>
<i className={`search-icon-right input-icon-addon sf2-icon-close ${this.state.isCloseShow ? "" : "hide"}`} onClick={this.onCloseHandler}></i>
</div>
<div className="search-result-container">
{this.renderSearchResult()}

View File

@@ -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 (
<ul className="path-toolbar">
<li className="toolbar-item"><a className="op-link sf2-icon-trash" href={trashUrl} title={gettext('Trash')} aria-label={gettext('Trash')}></a></li>
<li className="toolbar-item"><a className="op-link sf2-icon-history" href={historyUrl} title={gettext('History')} aria-label={gettext('History')}></a></li>
</ul>
);
} else if (permission) {
trashUrl = siteRoot + 'dir/recycle/' + repoID + '/?dir_path=' + encodeURIComponent(initialFilePath);
return (
<ul className="path-toolbar">
<li className="toolbar-item"><a className="op-link sf2-icon-trash" href={trashUrl} title={gettext('Trash')} aria-label={gettext('Trash')}></a></li>
</ul>
);
}
return '';
}
export default PathToolbar;

View File

@@ -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 (
<tr className='row' onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<td className="dirent-icon" style={{width: "5%"}}>
<tr className={this.state.highlight} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<td className="icon" style={{width: "4%"}}>
<img src={node.type === "dir" ? serviceUrl + "/media/img/folder-192.png" : serviceUrl + "/media/img/file/192/txt.png"}></img>
</td>
<td style={{width: "60%"}}>
<a className="custom-link" onClick={this.onMainNodeClick}>{node.name}</a>
</td>
<td style={{width: "15%"}}>{node.size}</td>
<td className="name a-simulate" style={{width: "60%"}} onClick={this.onMainNodeClick}>{node.name}</td>
<td style={{width: "16%"}}>{node.size}</td>
<td style={{width: "20%"}} title={node.last_update_time}>{node.last_update_time}</td>
</tr>
)

View File

@@ -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 (
<table className="doc-view-container">
<thead className="doc-view-header">
<tr className="row">
<th style={{width: "5%"}}></th>
<table>
<thead>
<tr>
<th style={{width: "4%"}}></th>
<th style={{width: "60%"}}>{gettext('Name')}</th>
<th style={{width: "15%"}}>{gettext('Size')}</th>
<th style={{width: "16%"}}>{gettext('Size')}</th>
<th style={{width: "20%"}}>{gettext('Last Update')}</th>
</tr>
</thead>
<tbody className="doc-view-body">
<tbody>
{children && children.map((node, index) => {
return (
<TreeDirList key={index} node={node} onMainNodeClick={this.props.onMainNodeClick}></TreeDirList>

View File

@@ -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 (
<div className="right-icon">

View File

@@ -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 {

View File

@@ -8,8 +8,6 @@
}
.history-heading {
height: 3.1875rem;
line-height: 3.1875rem;
font-size: 25px;
}

View File

@@ -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 {

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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';

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -72,8 +72,10 @@ class MainPanel extends React.Component {
return (
<div className="main-panel">
<div className="main-panel-north flex-right">
<div className="common-toolbar">
<Notification seafileAPI={seafileAPI}/>
<Account />
</div>
</div>
<div className="main-panel-center">
<div className="panel-heading text-left">{gettext('Drafts')}</div>

View File

@@ -23,7 +23,7 @@ class MainPanel extends React.Component {
return (
<div className="main-panel viewer">
<div className="main-panel-north">
<div className="history-heading">
<div className="common-toolbar">
<Notification />
<Account />
</div>

View File

@@ -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 (
<a key={index} className="custom-link" data-path={nodePath} onClick={this.onMainNavBarClick}><span className="path-split">/</span>{item}</a>
<span key={index} >
<span className="path-split">/</span>
<a
className="path-link"
data-path={nodePath}
onClick={this.onMainNavBarClick}>
{item}
</a>
</span>
)
}
});
@@ -50,18 +70,24 @@ class MainPanel extends Component {
return (
<div className="wiki-main-panel o-hidden">
<div className="main-panel-top panel-top">
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.onMenuClick}></span>
<div className="wiki-page-ops">
{ permission &&
<a className="btn btn-secondary btn-topbar" title="Edit File" onClick={this.onEditClick}>{gettext("Edit")}</a>
}
<a className="btn btn-secondary btn-topbar sf2-icon-list-view" id='list' title={gettext("List")} onClick={this.switchViewMode}></a>
<a className="btn btn-secondary btn-topbar sf2-icon-grid-view" id='grid' title={gettext("Grid")} onClick={this.switchViewMode}></a>
<div className="cur-view-toolbar">
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.onMenuClick}></span>
<div>
{
this.props.permission === 'rw' &&
<button className="btn btn-secondary top-toolbar-btn" title="Edit File" onClick={this.onEditClick}>{gettext("Edit")}</button>
}
</div>
<div className="btn-group">
<button className="btn btn-secondary btn-icon sf-view-mode-change-btn sf2-icon-list-view" id='list' title={gettext("List")} onClick={this.switchViewMode}></button>
<button className="btn btn-secondary btn-icon sf-view-mode-change-btn sf2-icon-grid-view" id='grid' title={gettext("Grid")} onClick={this.switchViewMode}></button>
<button className={`btn btn-secondary btn-icon sf-view-mode-change-btn sf2-icon-wiki-view ${this.state.isWikiMode ? 'current-mode' : ''}`} id='wiki' title={gettext("wiki")} onClick={this.switchViewMode}></button>
</div>
</div>
<div className="common-toolbar">
{isPro && <Search onSearchedClick={this.props.onSearchedClick}
placeholder={gettext("Search files in this library")}
/>
{
isPro &&
<Search onSearchedClick={this.props.onSearchedClick} placeholder={gettext("Search files in this library")} />
}
<Notification />
<Account />
@@ -75,8 +101,9 @@ class MainPanel extends Component {
<a href={siteRoot + 'wiki/lib/' + repoID + '/'} className="normal">{slug}</a>
{pathElem}
</div>
<PathToolbar />
</div>
<div className="cur-view-container">
<div className="cur-view-container table-container">
{ this.props.isViewFileState && <MarkdownViewer
markdownContent={this.props.content}
latestContributor={this.props.latestContributor}

View File

@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { gettext, repoID, serviceUrl, slug, siteRoot, isPro } from '../../components/constants';
import Search from '../../components/search';
import Search from '../../components/search/search';
import Account from '../../components/account';
import Notification from '../../components/notification';
import MarkdownViewer from '../../components/markdown-viewer';
@@ -37,7 +37,15 @@ class MainPanel extends Component {
} else {
nodePath += "/" + item;
return (
<a key={index} className="custom-link" data-path={nodePath} onClick={this.onMainNavBarClick}><span className="path-split">/</span>{item}</a>
<span key={index} >
<span className="path-split">/</span>
<a
className="path-link"
data-path={nodePath}
onClick={this.onMainNavBarClick}>
{item}
</a>
</span>
)
}
});
@@ -45,14 +53,17 @@ class MainPanel extends Component {
return (
<div className="wiki-main-panel o-hidden">
<div className="main-panel-top panel-top">
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.onMenuClick}></span>
<div className={`wiki-page-ops ${this.props.permission === 'rw' ? '' : 'hide'}`}>
<a className="btn btn-secondary btn-topbar" onClick={this.onEditClick}>{gettext("Edit Page")}</a>
</div>
<div className="cur-view-toolbar">
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.onMenuClick}></span>
{
this.props.permission === 'rw' &&
<button className="btn btn-secondary top-toolbar-btn" title="Edit File" onClick={this.onEditClick}>{gettext("Edit Page")}</button>
}
</div>
<div className="common-toolbar">
{isPro && <Search onSearchedClick={this.props.onSearchedClick}
placeholder={gettext("Search files in this wiki")}
/>
{
isPro &&
<Search onSearchedClick={this.props.onSearchedClick} placeholder={gettext("Search files in this wiki")}/>
}
<Notification />
<Account />
@@ -67,7 +78,7 @@ class MainPanel extends Component {
{pathElem}
</div>
</div>
<div className="cur-view-container">
<div className="cur-view-container table-container">
{ this.props.isViewFileState && <MarkdownViewer
markdownContent={this.props.content}
latestContributor={this.props.latestContributor}

View File

@@ -3,18 +3,19 @@ import ReactDOM from 'react-dom';
import SidePanel from './pages/repo-wiki-mode/side-panel';
import MainPanel from './pages/repo-wiki-mode/main-panel';
import moment from 'moment';
import { slug, repoID, serviceUrl, initialFilePath } from './components/constants';
import { repoID, serviceUrl, initialFilePath } from './components/constants';
import editorUtilities from './utils/editor-utilties';
import { seafileAPI } from './utils/seafile-api';
import Node from './components/tree-view/node';
import Tree from './components/tree-view/tree';
import cookie from 'react-cookies';
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 {
@@ -62,7 +63,7 @@ class Wiki extends Component {
permission: permission,
filePath: filePath,
isFileLoading: false
})
});
seafileAPI.getFileDownloadLink(repoID, filePath).then((res) => {
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;

View File

@@ -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}
/>
</div>
)
);
}
}
ReactDOM.render (
<Wiki />,
document.getElementById('wrapper')
)
);