mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-25 06:33:48 +00:00
Merge branch '7.0'
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Select from 'react-select';
|
||||
import { Button, Modal, ModalHeader, Input, ModalBody, ModalFooter, Form, FormGroup, Label, Alert } from 'reactstrap';
|
||||
import { gettext, enableEncryptedLibrary, repoPasswordMinLength } from '../../utils/constants';
|
||||
import { gettext, enableEncryptedLibrary, repoPasswordMinLength, storages } from '../../utils/constants';
|
||||
|
||||
const propTypes = {
|
||||
libraryType: PropTypes.string.isRequired,
|
||||
@@ -20,6 +21,7 @@ class CreateRepoDialog extends React.Component {
|
||||
password2: '',
|
||||
errMessage: '',
|
||||
permission: 'rw',
|
||||
storage_id: storages.length ? storages[0].id : '',
|
||||
isSubmitBtnActive: false,
|
||||
};
|
||||
this.newInput = React.createRef();
|
||||
@@ -44,17 +46,14 @@ class CreateRepoDialog extends React.Component {
|
||||
}
|
||||
|
||||
handleSubmit = () => {
|
||||
let isValid= this.validateInputParams();
|
||||
let isValid = this.validateInputParams();
|
||||
if (isValid) {
|
||||
let repoName = this.state.repoName.trim();
|
||||
let password = this.state.encrypt ? this.state.password1 : '';
|
||||
let permission= this.state.permission;
|
||||
let repo = this.createRepo(repoName, password, permission);
|
||||
let repoData = this.prepareRepoData();
|
||||
if (this.props.libraryType === 'department') {
|
||||
this.props.onCreateRepo(repo, 'department');
|
||||
this.props.onCreateRepo(repoData, 'department');
|
||||
return;
|
||||
}
|
||||
this.props.onCreateRepo(repo);
|
||||
this.props.onCreateRepo(repoData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +117,10 @@ class CreateRepoDialog extends React.Component {
|
||||
this.setState({permission: permission});
|
||||
}
|
||||
|
||||
handleStorageInputChange = (selectedItem) => {
|
||||
this.setState({storage_id: selectedItem.value});
|
||||
}
|
||||
|
||||
onEncrypted = (e) => {
|
||||
let isChecked = e.target.checked;
|
||||
this.setState({
|
||||
@@ -126,25 +129,18 @@ class CreateRepoDialog extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
createRepo = (repoName, password, permission) => {
|
||||
prepareRepoData = () => {
|
||||
let libraryType = this.props.libraryType;
|
||||
let encrypt = password ? true : false;
|
||||
|
||||
let repoName = this.state.repoName.trim();
|
||||
let password = this.state.encrypt ? this.state.password1 : '';
|
||||
let permission = this.state.permission;
|
||||
|
||||
let repo = null;
|
||||
if (libraryType === 'mine' || libraryType === 'public') {
|
||||
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: '-',
|
||||
passwd: password
|
||||
};
|
||||
}
|
||||
if (libraryType === 'group') {
|
||||
@@ -160,6 +156,12 @@ class CreateRepoDialog extends React.Component {
|
||||
passwd: password,
|
||||
};
|
||||
}
|
||||
|
||||
const storage_id = this.state.storage_id;
|
||||
if (storage_id) {
|
||||
repo.storage_id = storage_id;
|
||||
}
|
||||
|
||||
return repo;
|
||||
}
|
||||
|
||||
@@ -179,6 +181,17 @@ class CreateRepoDialog extends React.Component {
|
||||
onChange={this.handleRepoNameChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
{storages.length > 0 && (
|
||||
<FormGroup>
|
||||
<Label for="storage-backend">{gettext('Storage Backend')}</Label>
|
||||
<Select
|
||||
id="storage-backend"
|
||||
defaultValue={{value: storages[0].id, label: storages[0].name}}
|
||||
options={storages.map((item, index) => { return {value: item.id, label: item.name}; })}
|
||||
onChange={this.handleStorageInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
{this.props.libraryType === 'group' && (
|
||||
<FormGroup>
|
||||
<Label for="exampleSelect">{gettext('Permission')}</Label>
|
||||
@@ -191,7 +204,7 @@ class CreateRepoDialog extends React.Component {
|
||||
{enableEncryptedLibrary &&
|
||||
<div>
|
||||
<FormGroup check>
|
||||
<Input type="checkbox" id="encrypt" onChange={this.onEncrypted}/>
|
||||
<Input type="checkbox" id="encrypt" onChange={this.onEncrypted} />
|
||||
<Label for="encrypt">{gettext('Encrypt')}</Label>
|
||||
</FormGroup>
|
||||
{!this.state.disabled &&
|
||||
|
@@ -6,6 +6,7 @@ import copy from '@seafile/seafile-editor/dist/utils/copy-to-clipboard';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import Loading from '../loading';
|
||||
|
||||
const propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
@@ -18,6 +19,7 @@ class InternalLink extends React.Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
smartLink: '',
|
||||
isInternalLoding: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -25,7 +27,8 @@ class InternalLink extends React.Component {
|
||||
let { repoID, path, direntType } = this.props;
|
||||
seafileAPI.getInternalLink(repoID, path, direntType).then(res => {
|
||||
this.setState({
|
||||
smartLink: res.data.smart_link
|
||||
smartLink: res.data.smart_link,
|
||||
isInternalLoding: false
|
||||
});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
@@ -42,6 +45,9 @@ class InternalLink extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.isInternalLoding) {
|
||||
return(<Loading />);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<p className="tip mb-1">
|
||||
|
@@ -34,7 +34,7 @@ class AddOrgAdminDialog extends React.Component {
|
||||
addOrgAdmin = () => {
|
||||
if (!this.state.selectedOption) return;
|
||||
const userEmail = this.state.selectedOption.email;
|
||||
seafileAPI.setOrgAdmin(orgID, userEmail, true).then(res => {
|
||||
seafileAPI.orgAdminSetOrgAdmin(orgID, userEmail, true).then(res => {
|
||||
let userInfo = new OrgUserInfo(res.data);
|
||||
this.props.onAddedOrgAdmin(userInfo);
|
||||
}).catch(error => {
|
||||
|
@@ -37,7 +37,7 @@ class SetOrgUserContactEmail extends React.Component {
|
||||
submitBtnDisabled: true
|
||||
});
|
||||
|
||||
seafileAPI.setOrgUserContactEmail(orgID, email, contactEmail).then((res) => {
|
||||
seafileAPI.orgAdminSetOrgUserContactEmail(orgID, email, contactEmail).then((res) => {
|
||||
const newContactEmail = contactEmail ? res.data.contact_email : '';
|
||||
this.props.updateContactEmail(newContactEmail);
|
||||
this.props.toggleDialog();
|
||||
|
@@ -39,7 +39,7 @@ class SetOrgUserName extends React.Component {
|
||||
|
||||
// when name is '', api returns the previous name
|
||||
// but newName needs to be ''
|
||||
seafileAPI.setOrgUserName(orgID, email, name).then((res) => {
|
||||
seafileAPI.orgAdminSetOrgUserName(orgID, email, name).then((res) => {
|
||||
const newName = name ? res.data.name : '';
|
||||
this.props.updateName(newName);
|
||||
this.props.toggleDialog();
|
||||
|
@@ -46,7 +46,7 @@ class SetOrgUserQuota extends React.Component {
|
||||
submitBtnDisabled: true
|
||||
});
|
||||
|
||||
seafileAPI.setOrgUserQuota(orgID, email, quota).then((res) => {
|
||||
seafileAPI.orgAdminSetOrgUserQuota(orgID, email, quota).then((res) => {
|
||||
this.props.updateQuota(res.data.quota_total);
|
||||
this.props.toggleDialog();
|
||||
}).catch((error) => {
|
||||
|
@@ -98,11 +98,13 @@ class ShareDialog extends React.Component {
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
}
|
||||
<NavItem>
|
||||
<NavLink className={activeTab === 'internalLink' ? 'active' : ''} onClick={this.toggle.bind(this, 'internalLink')}>
|
||||
{gettext('Internal Link')}
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
{itemType === 'dir' &&
|
||||
<NavItem>
|
||||
<NavLink className={activeTab === 'internalLink' ? 'active' : ''} onClick={this.toggle.bind(this, 'internalLink')}>
|
||||
{gettext('Internal Link')}
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
}
|
||||
{enableDirPrivateShare &&
|
||||
<Fragment>
|
||||
<NavItem>
|
||||
@@ -139,13 +141,13 @@ class ShareDialog extends React.Component {
|
||||
/>
|
||||
</TabPane>
|
||||
}
|
||||
<TabPane tabId="internalLink">
|
||||
{itemType === 'dir' && activeTab === 'internalLink' &&
|
||||
<InternalLink
|
||||
path={this.props.itemPath}
|
||||
repoID={this.props.repoID}
|
||||
direntType={itemType}
|
||||
/>
|
||||
</TabPane>
|
||||
}
|
||||
{enableDirPrivateShare &&
|
||||
<Fragment>
|
||||
<TabPane tabId="shareToUser">
|
||||
@@ -190,12 +192,12 @@ class ShareDialog extends React.Component {
|
||||
closeShareDialog={this.props.toggleDialog}
|
||||
/>
|
||||
</TabPane>
|
||||
<TabPane tabId="internalLink">
|
||||
{activeTab === 'internalLink' &&
|
||||
<InternalLink
|
||||
repoID={this.props.repoID}
|
||||
path={this.props.itemPath}
|
||||
repoID={this.props.repoID}
|
||||
/>
|
||||
</TabPane>
|
||||
}
|
||||
</TabContent>
|
||||
</div>
|
||||
</Fragment>
|
||||
|
@@ -403,6 +403,9 @@ class DirentListItem extends React.Component {
|
||||
if (Utils.isIEBrower()) {
|
||||
return false;
|
||||
}
|
||||
if (e.dataTransfer.dropEffect === 'copy') {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
}
|
||||
|
@@ -580,6 +580,9 @@ class DirentListView extends React.Component {
|
||||
if (Utils.isIEBrower()) {
|
||||
return false;
|
||||
}
|
||||
if (e.dataTransfer.dropEffect === 'copy') {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ class Repo {
|
||||
this.type = object.type;
|
||||
this.starred = object.starred;
|
||||
this.status = object.status;
|
||||
this.storage_name = object.storage_name;
|
||||
if (object.is_admin != undefined) {
|
||||
this.is_admin = object.is_admin;
|
||||
}
|
||||
|
@@ -13,10 +13,6 @@ import EmptyTip from '../../components/empty-tip';
|
||||
|
||||
import '../../css/invitations.css';
|
||||
|
||||
if (!canInvitePeople) {
|
||||
location.href = siteRoot;
|
||||
}
|
||||
|
||||
class Item extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
@@ -192,7 +188,7 @@ class InvitationsView extends React.Component {
|
||||
this.setState({
|
||||
loading: false,
|
||||
errorMsg: gettext('Permission denied')
|
||||
});
|
||||
});
|
||||
location.href = `${loginUrl}?next=${encodeURIComponent(location.href)}`;
|
||||
} else {
|
||||
this.setState({
|
||||
|
@@ -80,18 +80,18 @@ class MyLibraries extends Component {
|
||||
}
|
||||
|
||||
onCreateRepo = (repo) => {
|
||||
let permission = repo.permission;
|
||||
seafileAPI.createMineRepo(repo).then((res) => {
|
||||
let repo = {
|
||||
const newRepo = new Repo({
|
||||
repo_id: res.data.repo_id,
|
||||
repo_name: res.data.repo_name,
|
||||
size: res.data.repo_size,
|
||||
mtime: res.data.mtime,
|
||||
owner_email: res.data.email,
|
||||
encrypted: res.data.encrypted,
|
||||
permission: permission,
|
||||
};
|
||||
this.state.repoList.unshift(repo);
|
||||
permission: res.data.permission,
|
||||
storage_name: res.data.storage_name
|
||||
});
|
||||
this.state.repoList.unshift(newRepo);
|
||||
this.setState({repoList: this.state.repoList});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
|
@@ -85,10 +85,10 @@ class MylibRepoListView extends React.Component {
|
||||
<tr>
|
||||
<th width="4%"></th>
|
||||
<th width="4%"><span className="sr-only">{gettext('Library Type')}</span></th>
|
||||
<th width="38%"><a className="d-block table-sort-op" href="#" onClick={this.sortByName}>{gettext('Name')} {this.props.sortBy === 'name' && sortIcon}</a></th>
|
||||
<th width={showStorageBackend ? '33%' : '38%'}><a className="d-block table-sort-op" href="#" onClick={this.sortByName}>{gettext('Name')} {this.props.sortBy === 'name' && sortIcon}</a></th>
|
||||
<th width="14%"><span className="sr-only">{gettext('Actions')}</span></th>
|
||||
<th width={showStorageBackend ? '15%' : '20%'}><a className="d-block table-sort-op" href="#" onClick={this.sortBySize}>{gettext('Size')} {this.props.sortBy === 'size' && sortIcon}</a></th>
|
||||
{showStorageBackend ? <th width="10%">{gettext('Storage backend')}</th> : null}
|
||||
{showStorageBackend ? <th width="15%">{gettext('Storage Backend')}</th> : null}
|
||||
<th width={showStorageBackend ? '15%' : '20%'}><a className="d-block table-sort-op" href="#" onClick={this.sortByTime}>{gettext('Last Update')} {this.props.sortBy === 'time' && sortIcon}</a></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@@ -147,7 +147,7 @@ class Item extends Component {
|
||||
|
||||
deleteRepo = () => {
|
||||
const repo = this.props.data;
|
||||
seafileAPI.deleteOrgRepo(orgID, repo.repo_id).then((res) => {
|
||||
seafileAPI.orgAdminDeleteOrgRepo(orgID, repo.repo_id).then((res) => {
|
||||
this.setState({
|
||||
deleted: true
|
||||
});
|
||||
|
@@ -26,7 +26,7 @@ class OrgGroups extends Component {
|
||||
}
|
||||
|
||||
initData = (page) => {
|
||||
seafileAPI.listOrgGroups(orgID, page).then(res => {
|
||||
seafileAPI.orgAdminListOrgGroups(orgID, page).then(res => {
|
||||
let orgGroups = res.data.groups.map(item => {
|
||||
return new OrgGroupInfo(item);
|
||||
});
|
||||
@@ -64,7 +64,7 @@ class OrgGroups extends Component {
|
||||
}
|
||||
|
||||
deleteGroupItem = (group) => {
|
||||
seafileAPI.deleteOrgGroup(orgID, group.id).then(res => {
|
||||
seafileAPI.orgAdminDeleteOrgGroup(orgID, group.id).then(res => {
|
||||
this.setState({
|
||||
orgGroups: this.state.orgGroups.filter(item => item.id != group.id)
|
||||
});
|
||||
|
@@ -28,7 +28,7 @@ class OrgLibraries extends Component {
|
||||
}
|
||||
|
||||
initData = (page) => {
|
||||
seafileAPI.listOrgRepos(orgID, page).then(res => {
|
||||
seafileAPI.orgAdminListOrgRepos(orgID, page).then(res => {
|
||||
let orgRepos = res.data.repo_list.map(item => {
|
||||
return new OrgAdminRepo(item);
|
||||
});
|
||||
@@ -66,7 +66,7 @@ class OrgLibraries extends Component {
|
||||
}
|
||||
|
||||
deleteRepoItem = (repo) => {
|
||||
seafileAPI.deleteOrgRepo(orgID, repo.repoID).then(res => {
|
||||
seafileAPI.orgAdminDeleteOrgRepo(orgID, repo.repoID).then(res => {
|
||||
this.setState({
|
||||
orgRepos: this.state.orgRepos.filter(item => item.repoID != repo.repoID)
|
||||
});
|
||||
@@ -239,7 +239,7 @@ class RepoItem extends React.Component {
|
||||
|
||||
onTransferRepo = (user) => {
|
||||
let repo = this.props.repo;
|
||||
seafileAPI.transferOrgRepo(orgID, repo.repoID, user.email).then(res => {
|
||||
seafileAPI.orgAdminTransferOrgRepo(orgID, repo.repoID, user.email).then(res => {
|
||||
this.props.transferRepoItem(repo.repoID, user);
|
||||
let msg = gettext('Successfully transferred the library.');
|
||||
toaster.success(msg);
|
||||
|
@@ -57,7 +57,7 @@ class UserItem extends React.Component {
|
||||
toggleResetPW = () => {
|
||||
const email = this.props.user.email;
|
||||
toaster.success(gettext('Resetting user\'s password, please wait for a moment.'));
|
||||
seafileAPI.resetOrgUserPassword(orgID, email).then(res => {
|
||||
seafileAPI.orgAdminResetOrgUserPassword(orgID, email).then(res => {
|
||||
let msg;
|
||||
msg = gettext('Successfully reset password to %(passwd)s for user %(user)s.');
|
||||
msg = msg.replace('%(passwd)s', res.data.new_password);
|
||||
@@ -84,7 +84,7 @@ class UserItem extends React.Component {
|
||||
statusCode = 0;
|
||||
}
|
||||
|
||||
seafileAPI.changeOrgUserStatus(this.props.user.id, statusCode).then(res => {
|
||||
seafileAPI.orgAdminChangeOrgUserStatus(this.props.user.id, statusCode).then(res => {
|
||||
this.setState({
|
||||
currentStatus: statusCode == 1 ? 'active' : 'inactive',
|
||||
highlight: false,
|
||||
|
@@ -24,7 +24,7 @@ class OrgUserProfile extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
seafileAPI.getOrgUserInfo(orgID, this.props.email).then((res) => {
|
||||
seafileAPI.orgAdminGetOrgUserInfo(orgID, this.props.email).then((res) => {
|
||||
this.setState(Object.assign({
|
||||
loading: false
|
||||
}, res.data));
|
||||
|
@@ -24,7 +24,7 @@ class OrgUserOwnedRepos extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
seafileAPI.getOrgUserOwnedRepos(orgID, this.props.email).then((res) => {
|
||||
seafileAPI.orgAdminGetOrgUserOwnedRepos(orgID, this.props.email).then((res) => {
|
||||
this.setState(Object.assign({
|
||||
loading: false
|
||||
}, res.data));
|
||||
@@ -147,7 +147,7 @@ class Item extends Component {
|
||||
|
||||
deleteRepo = () => {
|
||||
const repo = this.props.data;
|
||||
seafileAPI.deleteOrgRepo(orgID, repo.repo_id).then((res) => {
|
||||
seafileAPI.orgAdminDeleteOrgRepo(orgID, repo.repo_id).then((res) => {
|
||||
this.setState({
|
||||
deleted: true
|
||||
});
|
||||
|
@@ -22,7 +22,7 @@ class OrgUserSharedRepos extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
seafileAPI.getOrgUserBesharedRepos(orgID, this.props.email).then((res) => {
|
||||
seafileAPI.orgAdminGetOrgUserBesharedRepos(orgID, this.props.email).then((res) => {
|
||||
this.setState(Object.assign({
|
||||
loading: false
|
||||
}, res.data));
|
||||
|
@@ -45,7 +45,7 @@ class OrgUsers extends Component {
|
||||
}
|
||||
|
||||
initOrgUsersData = (page) => {
|
||||
seafileAPI.listOrgUsers(orgID, '', page).then(res => {
|
||||
seafileAPI.orgAdminListOrgUsers(orgID, '', page).then(res => {
|
||||
let userList = res.data.user_list.map(item => {
|
||||
return new OrgUserInfo(item);
|
||||
});
|
||||
@@ -61,7 +61,7 @@ class OrgUsers extends Component {
|
||||
}
|
||||
|
||||
addOrgUser = (email, name, password) => {
|
||||
seafileAPI.addOrgUser(orgID, email, name, password).then(res => {
|
||||
seafileAPI.orgAdminAddOrgUser(orgID, email, name, password).then(res => {
|
||||
let userInfo = new OrgUserInfo(res.data);
|
||||
this.state.orgUsers.unshift(userInfo);
|
||||
this.setState({
|
||||
@@ -79,7 +79,7 @@ class OrgUsers extends Component {
|
||||
}
|
||||
|
||||
toggleOrgUsersDelete = (email) => {
|
||||
seafileAPI.deleteOrgUser(orgID, email).then(res => {
|
||||
seafileAPI.orgAdminDeleteOrgUser(orgID, email).then(res => {
|
||||
let users = this.state.orgUsers.filter(item => item.email != email);
|
||||
this.setState({orgUsers: users});
|
||||
let msg = gettext('Successfully deleted %s');
|
||||
@@ -92,7 +92,7 @@ class OrgUsers extends Component {
|
||||
}
|
||||
|
||||
initOrgAdmin = () => {
|
||||
seafileAPI.listOrgUsers(orgID, true).then(res => {
|
||||
seafileAPI.orgAdminListOrgUsers(orgID, true).then(res => {
|
||||
let userList = res.data.user_list.map(item => {
|
||||
return new OrgUserInfo(item);
|
||||
});
|
||||
@@ -104,7 +104,7 @@ class OrgUsers extends Component {
|
||||
}
|
||||
|
||||
toggleOrgAdminDelete = (email) => {
|
||||
seafileAPI.deleteOrgUser(orgID, email).then(res => {
|
||||
seafileAPI.orgAdminDeleteOrgUser(orgID, email).then(res => {
|
||||
this.setState({
|
||||
orgAdminUsers: this.state.orgAdminUsers.filter(item => item.email != email)
|
||||
});
|
||||
@@ -118,7 +118,7 @@ class OrgUsers extends Component {
|
||||
}
|
||||
|
||||
toggleRevokeAdmin = (email) => {
|
||||
seafileAPI.setOrgAdmin(orgID, email, false).then(res => {
|
||||
seafileAPI.orgAdminSetOrgAdmin(orgID, email, false).then(res => {
|
||||
this.setState({
|
||||
orgAdminUsers: this.state.orgAdminUsers.filter(item => item.email != email)
|
||||
});
|
||||
|
Reference in New Issue
Block a user