1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-12 04:12:16 +00:00

add repo create dialog

This commit is contained in:
shanshuirenjia 2018-12-07 10:36:59 +08:00
parent 6a3fed0382
commit 0efff439e9
8 changed files with 205 additions and 61 deletions

View File

@ -140,8 +140,8 @@ class App extends Component {
<SharedLibrariesWrapper path={siteRoot + 'shared-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <SharedLibrariesWrapper path={siteRoot + 'shared-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
<MyLibraries path={siteRoot + 'my-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <MyLibraries path={siteRoot + 'my-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
<DirView path={siteRoot + 'library/:repoID/*'} onMenuClick={this.onShowSidePanel} updateCurrentTab={this.updateCurrentTab}/> <DirView path={siteRoot + 'library/:repoID/*'} onMenuClick={this.onShowSidePanel} updateCurrentTab={this.updateCurrentTab}/>
<Groups path={siteRoot + 'groups'} /> <Groups path={siteRoot + 'groups'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick}/>
<Group path={siteRoot + 'group/:groupID'} /> <Group path={siteRoot + 'group/:groupID'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick}/>
</Router> </Router>
</MainPanel> </MainPanel>
</div> </div>

View File

@ -1,10 +1,11 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, Modal, ModalHeader, Input, ModalBody, ModalFooter, Form, FormGroup, Label, Check } from 'reactstrap'; import { Button, Modal, ModalHeader, Input, CustomInput, ModalBody, ModalFooter, Form, FormGroup, Label } from 'reactstrap';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
const propTypes = { const propTypes = {
onCreateRepo: PropTypes.func.isRequired,
onCreateToggle: PropTypes.func.isRequired,
}; };
class CreateRepoDialog extends React.Component { class CreateRepoDialog extends React.Component {
@ -12,21 +13,35 @@ class CreateRepoDialog extends React.Component {
super(props); super(props);
this.state = { this.state = {
repoName: '', repoName: '',
password: '', disabled: true,
encrypt: false,
password1: '',
password2: '', password2: '',
errMessage: '',
}; };
this.newInput = React.createRef(); this.newInput = React.createRef();
} }
handleChange = (e) => { handleRepoNameChange = (e) => {
this.setState({ this.setState({repoName: e.target.value});
childName: e.target.value, }
});
handlePassword1Change = (e) => {
this.setState({password1: e.target.value});
}
handlePassword2Change = (e) => {
this.setState({password2: e.target.value});
} }
handleSubmit = () => { handleSubmit = () => {
let path = this.state.parentPath + this.state.childName; let isValidate = this.validateInputParams();
this.props.onAddFolder(path); if (isValidate) {
let repoName = this.state.repoName.trim();
let password = this.state.encrypt ? this.state.password1 : '';
let repo = this.createRepo(repoName, password);
this.props.onCreateRepo(repo);
}
} }
handleKeyPress = (e) => { handleKeyPress = (e) => {
@ -36,17 +51,86 @@ class CreateRepoDialog extends React.Component {
} }
toggle = () => { toggle = () => {
this.props.addFolderCancel(); this.props.onCreateToggle();
} }
componentDidMount() { componentDidMount() {
this.newInput.focus(); this.newInput.focus();
} }
validateInputParams() {
let errMessage = '';
let repoName = this.state.repoName.trim();
if (!repoName.length) {
errMessage = 'Name is required';
this.setState({errMessage: errMessage});
return false;
}
if (repoName.indexOf('/') > -1) {
errMessage = 'Name should not include '/'.';
this.setState({errMessage: errMessage});
return;
}
if (this.state.encrypt) {
let password1 = this.state.password1.trim();
let password2 = this.state.password2.trim();
if (!password1.length) {
errMessage = 'Please enter password';
this.setState({errMessage: errMessage});
return false;
}
if (!password2.length) {
errMessage = 'Please enter the password again';
this.setState({errMessage: errMessage});
return false;
}
if (password1.length < 8) {
errMessage = 'Password is too short';
this.setState({errMessage: errMessage});
return false;
}
if (password1 !== password2) {
errMessage = 'Passwords don\'t match';
this.setState({errMessage: errMessage});
return false;
}
}
return true;
}
onEncrypted = (e) => {
let isChecked = e.target.checked;
this.setState({
encrypt: isChecked,
disabled: !isChecked
});
}
createRepo = (repoName, password) => {
let encrypt = password ? true : false;
let repo = {
id: null,
name: repoName,
desc: "",
encrypted: encrypt,
passwd: password,
passwd1: password,
passwd2: password,
mtime: 0,
mtime_relative: "",
owner: "-",
owner_nickname: "-",
permission: "rw",
storage_name: "-",
};
return repo;
}
render() { render() {
return ( return (
<Modal isOpen={true} toggle={this.toggle}> <Modal isOpen={true} toggle={this.toggle}>
<ModalHeader toggle={this.toggle}>{gettext('New Folder')}</ModalHeader> <ModalHeader toggle={this.toggle}>{gettext('New Library')}</ModalHeader>
<ModalBody> <ModalBody>
<Form> <Form>
<FormGroup> <FormGroup>
@ -55,33 +139,36 @@ class CreateRepoDialog extends React.Component {
onKeyPress={this.handleKeyPress} onKeyPress={this.handleKeyPress}
innerRef={input => {this.newInput = input;}} innerRef={input => {this.newInput = input;}}
id="fileName" placeholder={gettext('newName')} id="fileName" placeholder={gettext('newName')}
value={this.state.childName} value={this.state.repoName}
onChange={this.handleNameChange} onChange={this.handleRepoNameChange}
/>
</FormGroup>
<FormGroup check>
<Input type="checkbox" id="encrypt" onChange={this.onEncrypted}/>
<Label for="encrypt">{gettext('Encrypt')}</Label>
</FormGroup>
<FormGroup>
<Label for="passwd1">{gettext('Password')} ({gettext('at least 8 characters')})</Label>
<Input
id="passwd1"
type="password"
disabled={this.state.disabled}
value={this.state.password1}
onChange={this.handlePassword1Change}
/> />
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<Input type="checkbox" id="encrypt"/>{gettext('Encrypt')} <Label for="passwd2">{gettext('Password again')}: </Label>
</FormGroup>
<FormGroup>
<Label for="fileName">{gettext('Password(at least 8 characters)')}</Label>
<Input <Input
id="fileName" id="passwd2"
placeholder={gettext('password')} type="password"
value={this.state.childName} disabled={this.state.disabled}
onChange={this.handlePasswordChange} value={this.state.password2}
/>
</FormGroup>
<FormGroup>
<Label for="fileName">{gettext('Password again')}: </Label>
<Input
id="fileName"
placeholder={gettext('password2')}
value={this.state.childName}
onChange={this.handlePassword2Change} onChange={this.handlePassword2Change}
/> />
</FormGroup> </FormGroup>
</Form> </Form>
<div className="err-message"></div> <Label className="err-message">{gettext(this.state.errMessage)}</Label>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button color="primary" onClick={this.handleSubmit}>{gettext('Submit')}</Button> <Button color="primary" onClick={this.handleSubmit}>{gettext('Submit')}</Button>

View File

@ -7,7 +7,7 @@ import More from '../more';
const propTypes = { const propTypes = {
placeholder: PropTypes.string, placeholder: PropTypes.string,
repoID: PropTypes.string.isRequired, repoID: PropTypes.string,
onSearchedClick: PropTypes.func.isRequired, onSearchedClick: PropTypes.func.isRequired,
}; };

View File

@ -6,7 +6,7 @@ import Notification from '../common/notification';
import Account from '../common/account'; import Account from '../common/account';
const propTypes = { const propTypes = {
repoID: PropTypes.string.isRequired, repoID: PropTypes.string,
onSearchedClick: PropTypes.func.isRequired, onSearchedClick: PropTypes.func.isRequired,
searchPlaceholder: PropTypes.string searchPlaceholder: PropTypes.string
}; };

View File

@ -1,23 +1,55 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
import ModalPortal from '../modal-portal';
import CreateRepoDialog from '../dialog/create-repo-dialog';
const propTypes = { const propTypes = {
isOwnLibrary: PropTypes.bool.isRequired, // isOwnLibrary: PropTypes.bool.isRequired,
libraryType: PropTypes.string.isRequired, // libraryType: PropTypes.string.isRequired,
onCreateRepo: PropTypes.func.isRequired,
}; };
class RepoViewToolbar extends React.Component { class RepoViewToolbar extends React.Component {
constructor(props) {
super(props);
this.state = {
isCreateRepoDialogShow: false,
};
}
onCreateRepo = (repo) => {
this.props.onCreateRepo(repo);
this.onCreateToggle();
}
onCreateToggle = () => {
this.setState({isCreateRepoDialogShow: !this.state.isCreateRepoDialogShow});
}
render() { render() {
return ( return (
<Fragment>
<div className="cur-view-toolbar border-left-show"> <div className="cur-view-toolbar border-left-show">
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.props.onShowSidePanel}></span> <span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.props.onShowSidePanel}></span>
<div className="operation"> <div className="operation">
<button className="btn btn-secondary operation-item" title={gettext('New Library')} onClick={this.onCreateClick}>{gettext('New Library')}</button> <button className="btn btn-secondary operation-item" title={gettext('New Library')} onClick={this.onCreateToggle}>
<i className="fas fa-plus-square op-icon"></i>
{gettext('New Library')}
</button>
<button className="btn btn-secondary operation-item" title={gettext('More')} onClick={this.onShareClick}>{gettext('More')}</button> <button className="btn btn-secondary operation-item" title={gettext('More')} onClick={this.onShareClick}>{gettext('More')}</button>
</div> </div>
</div> </div>
{this.state.isCreateRepoDialogShow && (
<ModalPortal>
<CreateRepoDialog
onCreateRepo={this.onCreateRepo}
onCreateToggle={this.onCreateToggle}
/>
</ModalPortal>
)}
</Fragment>
); );
} }
} }

View File

@ -1,9 +1,11 @@
import React, { Component } from 'react'; import React, { Component, Fragment } from 'react';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import { gettext, siteRoot, loginUrl, username } from '../../utils/constants'; import { gettext, siteRoot, loginUrl, username } from '../../utils/constants';
import Loading from '../../components/loading'; import Loading from '../../components/loading';
import GroupRepoItem from './group-repo-item'; import GroupRepoItem from './group-repo-item';
import CommonToolbar from '../../components/toolbar/common-toolbar';
import RepoViewToolbar from '../../components/toolbar/repo-view-toobar';
import '../../css/groups.css'; import '../../css/groups.css';
@ -271,8 +273,20 @@ class Group extends Component {
}); });
} }
onCreateRepo = (repo) => {
let groupId = this.props.groupID;
seafileAPI.createGroupRepo(groupId, repo).then(() => {
//todo update group list
});
}
render() { render() {
return ( return (
<Fragment>
<div className="main-panel-north">
<RepoViewToolbar onShowSidePanel={this.props.onShowSidePanel} onCreateRepo={this.onCreateRepo} />
<CommonToolbar onSearchedClick={this.props.onSearchedClick} />
</div>
<div className="main-panel-center"> <div className="main-panel-center">
<div className="cur-view-container"> <div className="cur-view-container">
<div className="cur-view-path"> <div className="cur-view-path">
@ -283,6 +297,7 @@ class Group extends Component {
</div> </div>
</div> </div>
</div> </div>
</Fragment>
); );
} }
} }

View File

@ -1,8 +1,9 @@
import React, { Component } from 'react'; import React, { Component, Fragment } from 'react';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { gettext, siteRoot, loginUrl, username } from '../../utils/constants'; import { gettext, siteRoot, loginUrl, username } from '../../utils/constants';
import Loading from '../../components/loading'; import Loading from '../../components/loading';
import GroupRepoItem from './group-repo-item'; import GroupRepoItem from './group-repo-item';
import GeneralToolbar from '../../components/toolbar/general-toolbar';
import '../../css/groups.css'; import '../../css/groups.css';
@ -157,6 +158,8 @@ class Groups extends Component {
render() { render() {
return ( return (
<Fragment>
<GeneralToolbar onShowSidePanel={this.props.onShowSidePanel} onSearchedClick={this.props.onSearchedClick}/>
<div className="main-panel-center"> <div className="main-panel-center">
<div className="cur-view-container"> <div className="cur-view-container">
<div className="cur-view-path"> <div className="cur-view-path">
@ -167,6 +170,7 @@ class Groups extends Component {
</div> </div>
</div> </div>
</div> </div>
</Fragment>
); );
} }
} }

View File

@ -393,11 +393,17 @@ class MyLibraries extends Component {
}); });
} }
onCreateRepo = (repo) => {
seafileAPI.createMineRepo(repo).then((res) => {
});
}
render() { render() {
return ( return (
<Fragment> <Fragment>
<div className="main-panel-north"> <div className="main-panel-north">
<RepoViewToolbar onShowSidePanel={this.props.onShowSidePanel}/> <RepoViewToolbar onShowSidePanel={this.props.onShowSidePanel} onCreateRepo={this.onCreateRepo} />
<CommonToolbar onSearchedClick={this.props.onSearchedClick} /> <CommonToolbar onSearchedClick={this.props.onSearchedClick} />
</div> </div>
<div className="main-panel-center"> <div className="main-panel-center">