mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-07 01:41:39 +00:00
Implement wiki mode menu function (#2461)
This commit is contained in:
100
frontend/src/components/file-chooser/dirent-list-item.js
Normal file
100
frontend/src/components/file-chooser/dirent-list-item.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import Dirent from '../../models/dirent';
|
||||
|
||||
const propTypes = {
|
||||
filePath: PropTypes.string,
|
||||
selectedPath: PropTypes.string,
|
||||
dirent: PropTypes.object.isRequired,
|
||||
repo: PropTypes.object.isRequired,
|
||||
onDirentItemClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DirentListItem extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
let filePath = this.props.filePath ? this.props.filePath + '/' + this.props.dirent.name : '/' + this.props.dirent.name;
|
||||
|
||||
this.state = {
|
||||
isShowChildren: false,
|
||||
hasRequest: false,
|
||||
hasChildren: true,
|
||||
filePath: filePath,
|
||||
direntList: [],
|
||||
};
|
||||
}
|
||||
|
||||
onItemClick = () => {
|
||||
this.props.onDirentItemClick(this.state.filePath);
|
||||
}
|
||||
|
||||
onToggleClick = () => {
|
||||
if (!this.state.hasRequest) {
|
||||
seafileAPI.listDir(this.props.repo.repo_id, this.state.filePath).then(res => {
|
||||
let direntList = [];
|
||||
res.data.forEach(item => {
|
||||
if (item.type === 'dir') {
|
||||
let dirent = new Dirent(item);
|
||||
direntList.push(dirent);
|
||||
}
|
||||
this.setState({
|
||||
hasRequest: true,
|
||||
direntList: direntList,
|
||||
});
|
||||
});
|
||||
if (res.data.length === 0 || direntList.length === 0) {
|
||||
this.setState({
|
||||
hasRequest: true,
|
||||
direntList: [],
|
||||
hasChildren: false
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({isShowChildren: !this.state.isShowChildren});
|
||||
}
|
||||
|
||||
renderChildren = () => {
|
||||
return (
|
||||
<ul className="list-view-content">
|
||||
{this.state.direntList.map((dirent, index) => {
|
||||
return (
|
||||
<DirentListItem
|
||||
key={index}
|
||||
dirent={dirent}
|
||||
repo={this.props.repo}
|
||||
filePath={this.state.filePath}
|
||||
onItemClick={this.onItemClick}
|
||||
selectedPath={this.props.selectedPath}
|
||||
onDirentItemClick={this.props.onDirentItemClick}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<li className="file-chooser-item">
|
||||
{
|
||||
this.state.hasChildren &&
|
||||
<span className={`item-toggle fa ${this.state.isShowChildren ? 'fa-caret-down' : 'fa-caret-right'}`} onClick={this.onToggleClick}></span>
|
||||
}
|
||||
<span className={`item-info ${this.state.filePath === this.props.selectedPath ? 'item-active' : ''}`} onClick={this.onItemClick}>
|
||||
<span className="icon far fa-folder"></span>
|
||||
<span className="name">{this.props.dirent && this.props.dirent.name}</span>
|
||||
</span>
|
||||
{this.state.isShowChildren && this.renderChildren()}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DirentListItem.propTypes = propTypes;
|
||||
|
||||
export default DirentListItem;
|
61
frontend/src/components/file-chooser/dirent-list-view.js
Normal file
61
frontend/src/components/file-chooser/dirent-list-view.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import Dirent from '../../models/dirent';
|
||||
import DirentListItem from './dirent-list-item';
|
||||
|
||||
const propTypes = {
|
||||
selectedPath: PropTypes.string,
|
||||
repo: PropTypes.object.isRequired,
|
||||
isShowChildren: PropTypes.bool.isRequired,
|
||||
onDirentItemClick: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
class DirentListView extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
direntList: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let repo = this.props.repo;
|
||||
seafileAPI.listDir(repo.repo_id, '/').then(res => {
|
||||
let direntList = [];
|
||||
res.data.forEach(item => {
|
||||
if (item.type === 'dir') {
|
||||
let dirent = new Dirent(item);
|
||||
direntList.push(dirent);
|
||||
}
|
||||
this.setState({
|
||||
direntList: direntList,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
let { direntList } = this.state;
|
||||
return (
|
||||
<ul className={`list-view-content ${this.props.isShowChildren ? '' : 'hide'}`}>
|
||||
{ direntList.map((dirent, index) => {
|
||||
return (
|
||||
<DirentListItem
|
||||
key={index}
|
||||
repo={this.props.repo}
|
||||
dirent={dirent}
|
||||
onDirentItemClick={this.props.onDirentItemClick}
|
||||
selectedPath={this.props.selectedPath}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DirentListView.propTypes = propTypes;
|
||||
|
||||
export default DirentListView;
|
125
frontend/src/components/file-chooser/file-chooser.js
Normal file
125
frontend/src/components/file-chooser/file-chooser.js
Normal file
@@ -0,0 +1,125 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import RepoListView from './repo-list-view';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { gettext, repoID } from '../../utils/constants';
|
||||
import Repo from '../../models/repo';
|
||||
|
||||
import '../../css/file-chooser.css';
|
||||
|
||||
const propTypes = {
|
||||
onDirentItemClick: PropTypes.func,
|
||||
onRepoItemClick: PropTypes.func,
|
||||
};
|
||||
|
||||
class FileChooser extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
hasRequest: false,
|
||||
isOtherRepoShow: false,
|
||||
repoList: [],
|
||||
currentRepo: null,
|
||||
selectedRepo: null,
|
||||
selectedPath: '',
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
seafileAPI.getRepoInfo(repoID).then(res => {
|
||||
let repo = new Repo(res.data);
|
||||
this.setState({
|
||||
currentRepo: repo,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onOtherRepoToggle = () => {
|
||||
if (!this.state.hasRequest) {
|
||||
let { currentRepo } = this.state;
|
||||
seafileAPI.listRepos().then(res => {
|
||||
let repos = res.data.repos;
|
||||
let repoList = [];
|
||||
let repoIdList = [];
|
||||
for(let i = 0; i < repos.length; i++) {
|
||||
if (repos[i].repo_name === currentRepo.repo_name || repos[i].permission !== 'rw') {
|
||||
continue;
|
||||
}
|
||||
if (repoIdList.indexOf(repos[i].repo_id) > -1) {
|
||||
continue;
|
||||
}
|
||||
repoList.push(repos[i]);
|
||||
repoIdList.push(repos[i].repo_id);
|
||||
}
|
||||
this.setState({
|
||||
repoList: repoList,
|
||||
isOtherRepoShow: !this.state.isOtherRepoShow,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.setState({isOtherRepoShow: !this.state.isOtherRepoShow});
|
||||
}
|
||||
}
|
||||
|
||||
onDirentItemClick = (repo, filePath) => {
|
||||
this.props.onDirentItemClick(repo, filePath);
|
||||
this.setState({
|
||||
selectedRepo: repo,
|
||||
selectedPath: filePath
|
||||
});
|
||||
}
|
||||
|
||||
onRepoItemClick = (repo) => {
|
||||
this.props.onRepoItemClick(repo);
|
||||
this.setState({
|
||||
selectedRepo: repo,
|
||||
selectedPath: '',
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="file-chooser-container">
|
||||
<div className="list-view">
|
||||
<div className="list-view-header">
|
||||
<span className="item-toggle fa fa-caret-down"></span>
|
||||
<span className="library">{gettext('Current Library')}</span>
|
||||
</div>
|
||||
{
|
||||
this.state.currentRepo &&
|
||||
<RepoListView
|
||||
initToShowChildren={true}
|
||||
repo={this.state.currentRepo}
|
||||
selectedRepo={this.state.selectedRepo}
|
||||
selectedPath={this.state.selectedPath}
|
||||
onRepoItemClick={this.onRepoItemClick}
|
||||
onDirentItemClick={this.onDirentItemClick}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
<div className="list-view">
|
||||
<div className="list-view-header">
|
||||
<span className={`item-toggle fa ${this.state.isOtherRepoShow ? 'fa-caret-down' : 'fa-caret-right'}`} onClick={this.onOtherRepoToggle}></span>
|
||||
<span className="library">{gettext('Other Libraries')}</span>
|
||||
</div>
|
||||
{
|
||||
this.state.isOtherRepoShow &&
|
||||
<RepoListView
|
||||
initToShowChildren={false}
|
||||
repoList={this.state.repoList}
|
||||
selectedRepo={this.state.selectedRepo}
|
||||
selectedPath={this.state.selectedPath}
|
||||
onRepoItemClick={this.onRepoItemClick}
|
||||
onDirentItemClick={this.onDirentItemClick}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FileChooser.propTypes = propTypes;
|
||||
|
||||
export default FileChooser;
|
64
frontend/src/components/file-chooser/repo-list-item.js
Normal file
64
frontend/src/components/file-chooser/repo-list-item.js
Normal file
@@ -0,0 +1,64 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import DirentListView from './dirent-list-view';
|
||||
|
||||
const propTypes = {
|
||||
selectedPath: PropTypes.string,
|
||||
selectedRepo: PropTypes.object,
|
||||
repo: PropTypes.object.isRequired,
|
||||
initToShowChildren: PropTypes.bool.isRequired,
|
||||
onDirentItemClick: PropTypes.func.isRequired,
|
||||
onRepoItemClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class RepoListItem extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isShowChildren: this.props.initToShowChildren,
|
||||
};
|
||||
}
|
||||
|
||||
onToggleClick = () => {
|
||||
this.setState({isShowChildren: !this.state.isShowChildren});
|
||||
}
|
||||
|
||||
onDirentItemClick = (filePath) => {
|
||||
let repo = this.props.repo;
|
||||
this.props.onDirentItemClick(repo, filePath);
|
||||
}
|
||||
|
||||
onRepoItemClick = () => {
|
||||
this.props.onRepoItemClick(this.props.repo);
|
||||
}
|
||||
|
||||
render() {
|
||||
let repoActive = false;
|
||||
let isCurrentRepo = this.props.selectedRepo && (this.props.repo.repo_id === this.props.selectedRepo.repo_id);
|
||||
if (isCurrentRepo && !this.props.selectedPath) {
|
||||
repoActive = true;
|
||||
}
|
||||
return (
|
||||
<li className="file-chooser-item">
|
||||
<span className={`item-toggle fa ${this.state.isShowChildren ? 'fa-caret-down' : 'fa-caret-right'}`} onClick={this.onToggleClick}></span>
|
||||
<span className={`item-info ${repoActive ? 'item-active' : ''}`} onClick={this.onRepoItemClick}>
|
||||
<span className="icon far fa-folder"></span>
|
||||
<span className="name">{this.props.repo.repo_name}</span>
|
||||
</span>
|
||||
{
|
||||
<DirentListView
|
||||
repo={this.props.repo}
|
||||
isShowChildren={this.state.isShowChildren}
|
||||
onDirentItemClick={this.onDirentItemClick}
|
||||
selectedPath={this.props.selectedPath}
|
||||
/>
|
||||
}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
RepoListItem.propTypes = propTypes;
|
||||
|
||||
export default RepoListItem;
|
45
frontend/src/components/file-chooser/repo-list-view.js
Normal file
45
frontend/src/components/file-chooser/repo-list-view.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import RepoListItem from './repo-list-item';
|
||||
|
||||
const propTypes = {
|
||||
repo: PropTypes.object,
|
||||
repoList: PropTypes.array,
|
||||
selectedRepo: PropTypes.object,
|
||||
initToShowChildren: PropTypes.bool.isRequired,
|
||||
selectedPath: PropTypes.string,
|
||||
onDirentItemClick: PropTypes.func.isRequired,
|
||||
onRepoItemClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class RepoListView extends React.Component {
|
||||
|
||||
render() {
|
||||
let { repo, repoList } = this.props;
|
||||
if (repo) {
|
||||
repoList = [];
|
||||
repoList.push(repo);
|
||||
}
|
||||
return (
|
||||
<ul className="list-view-content file-chooser-item">
|
||||
{repoList.length > 0 && repoList.map((repoItem, index) => {
|
||||
return (
|
||||
<RepoListItem
|
||||
key={index}
|
||||
repo={repoItem}
|
||||
initToShowChildren={this.props.initToShowChildren}
|
||||
selectedRepo={this.props.selectedRepo}
|
||||
selectedPath={this.props.selectedPath}
|
||||
onRepoItemClick={this.props.onRepoItemClick}
|
||||
onDirentItemClick={this.props.onDirentItemClick}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
RepoListView.propTypes = propTypes;
|
||||
|
||||
export default RepoListView;
|
Reference in New Issue
Block a user