mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-20 10:58:33 +00:00
Merge branch 'master' into 12.0
This commit is contained in:
@@ -1,19 +1,34 @@
|
||||
import React from 'react';
|
||||
import React, {Fragment} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
Nav,
|
||||
NavItem,
|
||||
NavLink,
|
||||
TabContent,
|
||||
TabPane
|
||||
} from 'reactstrap';
|
||||
import makeAnimated from 'react-select/animated';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { gettext, isPro } from '../../utils/constants';
|
||||
import {gettext, isPro, orgID} from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../toast';
|
||||
import UserSelect from '../user-select';
|
||||
import { SeahubSelect } from '../common/select';
|
||||
import '../../css/transfer-dialog.css';
|
||||
|
||||
const propTypes = {
|
||||
itemName: PropTypes.string.isRequired,
|
||||
toggleDialog: PropTypes.func.isRequired,
|
||||
submit: PropTypes.func.isRequired,
|
||||
canTransferToDept: PropTypes.bool
|
||||
canTransferToDept: PropTypes.bool,
|
||||
isOrgAdmin: PropTypes.bool,
|
||||
isSysAdmin: PropTypes.bool,
|
||||
|
||||
};
|
||||
|
||||
class TransferDialog extends React.Component {
|
||||
@@ -23,23 +38,54 @@ class TransferDialog extends React.Component {
|
||||
selectedOption: null,
|
||||
errorMsg: [],
|
||||
transferToUser: true,
|
||||
transferToGroup: false,
|
||||
activeTab: 'transUser'
|
||||
};
|
||||
this.options = [];
|
||||
}
|
||||
|
||||
handleSelectChange = (option) => {
|
||||
this.setState({selectedOption: option});
|
||||
this.setState({ selectedOption: option });
|
||||
};
|
||||
|
||||
submit = () => {
|
||||
let user = this.state.selectedOption;
|
||||
this.props.submit(user);
|
||||
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
if (isPro) {
|
||||
if (this.props.isOrgAdmin) {
|
||||
seafileAPI.orgAdminListDepartments(orgID).then((res) => {
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
let obj = {};
|
||||
obj.value = res.data[i].name;
|
||||
obj.email = res.data[i].email;
|
||||
obj.label = res.data[i].name;
|
||||
this.options.push(obj);
|
||||
}
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
else if (this.props.isSysAdmin) {
|
||||
seafileAPI.sysAdminListDepartments().then((res) => {
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
let obj = {};
|
||||
obj.value = res.data[i].name;
|
||||
obj.email = res.data[i].email;
|
||||
obj.label = res.data[i].name;
|
||||
this.options.push(obj);
|
||||
}
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
else{
|
||||
seafileAPI.listDepartments().then((res) => {
|
||||
for (let i = 0 ; i < res.data.length; i++) {
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
let obj = {};
|
||||
obj.value = res.data[i].name;
|
||||
obj.email = res.data[i].email;
|
||||
@@ -56,49 +102,85 @@ class TransferDialog extends React.Component {
|
||||
onClick = () => {
|
||||
this.setState({
|
||||
transferToUser: !this.state.transferToUser,
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
toggle = (tab) => {
|
||||
if (this.state.activeTab !== tab) {
|
||||
this.setState({ activeTab: tab });
|
||||
}
|
||||
};
|
||||
|
||||
renderTransContent = () => {
|
||||
let activeTab = this.state.activeTab;
|
||||
let canTransferToDept = true;
|
||||
if (this.props.canTransferToDept != undefined) {
|
||||
canTransferToDept = this.props.canTransferToDept;
|
||||
}
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="transfer-dialog-side">
|
||||
<Nav pills>
|
||||
<NavItem role="tab" aria-selected={activeTab === 'transUser'} aria-controls="transfer-user-panel">
|
||||
<NavLink className={activeTab === 'transUser' ? 'active' : ''} onClick={(this.toggle.bind(this, 'transUser'))} tabIndex="0" onKeyDown={this.onTabKeyDown}>
|
||||
{gettext('Transfer to user')}
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
{isPro &&
|
||||
<NavItem role="tab" aria-selected={activeTab === 'transDepart'} aria-controls="transfer-depart-panel">
|
||||
<NavLink className={activeTab === 'transDepart' ? 'active' : ''} onClick={this.toggle.bind(this, 'transDepart')} tabIndex="0" onKeyDown={this.onTabKeyDown}>
|
||||
{gettext('Transfer to department')}
|
||||
</NavLink>
|
||||
</NavItem>}
|
||||
</Nav>
|
||||
</div>
|
||||
<div className="transfer-dialog-main">
|
||||
<TabContent activeTab={this.state.activeTab}>
|
||||
<Fragment>
|
||||
<TabPane tabId="transUser" role="tabpanel" id="transfer-user-panel">
|
||||
<UserSelect
|
||||
ref="userSelect"
|
||||
isMulti={false}
|
||||
className="reviewer-select"
|
||||
placeholder={gettext('Select a user')}
|
||||
onSelectChange={this.handleSelectChange}
|
||||
/>
|
||||
</TabPane>
|
||||
{isPro && canTransferToDept &&
|
||||
<TabPane tabId="transDepart" role="tabpanel" id="transfer-depart-panel">
|
||||
<SeahubSelect
|
||||
isClearable
|
||||
maxMenuHeight={200}
|
||||
hideSelectedOptions={true}
|
||||
components={makeAnimated()}
|
||||
placeholder={gettext('Select a department')}
|
||||
options={this.options}
|
||||
onChange={this.handleSelectChange}
|
||||
value={this.state.selectedOption}
|
||||
/>
|
||||
</TabPane>}
|
||||
</Fragment>
|
||||
</TabContent>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
render() {
|
||||
|
||||
|
||||
const { itemName: repoName } = this.props;
|
||||
let title = gettext('Transfer Library {library_name}');
|
||||
title = title.replace('{library_name}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoName) + '</span>');
|
||||
|
||||
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.props.toggleDialog}>
|
||||
<Modal isOpen={true} style={{maxWidth: '720px'}} toggle={this.props.toggleDialog} className="transfer-dialog">
|
||||
<ModalHeader toggle={this.props.toggleDialog}>
|
||||
<span dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></span>
|
||||
<span dangerouslySetInnerHTML={{ __html: title }} className="d-flex mw-100"></span>
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
{this.state.transferToUser ?
|
||||
<UserSelect
|
||||
ref="userSelect"
|
||||
isMulti={false}
|
||||
className="reviewer-select"
|
||||
placeholder={gettext('Select a user')}
|
||||
onSelectChange={this.handleSelectChange}
|
||||
/> :
|
||||
<SeahubSelect
|
||||
isClearable
|
||||
maxMenuHeight={200}
|
||||
hideSelectedOptions={true}
|
||||
components={makeAnimated()}
|
||||
placeholder={gettext('Select a department')}
|
||||
options={this.options}
|
||||
onChange={this.handleSelectChange}
|
||||
value={this.state.selectedOption}
|
||||
/>
|
||||
}
|
||||
{isPro && canTransferToDept &&
|
||||
<span role="button" tabIndex="0" className="action-link" onClick={this.onClick} onKeyDown={Utils.onKeyDown}>{this.state.transferToUser ?
|
||||
gettext('Transfer to department'): gettext('Transfer to user')}
|
||||
</span>
|
||||
}
|
||||
<ModalBody className="transfer-dialog-content" role="tablist">
|
||||
{this.renderTransContent()}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="secondary" onClick={this.props.toggleDialog}>{gettext('Cancel')}</Button>
|
||||
|
@@ -43,6 +43,7 @@ class DirGridView extends React.Component {
|
||||
path={this.props.path}
|
||||
isDirentListLoading={this.props.isDirentListLoading}
|
||||
onAddFile={this.props.onAddFile}
|
||||
currentRepoInfo={this.props.currentRepoInfo}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -53,6 +53,7 @@ class DirListView extends React.Component {
|
||||
path={this.props.path}
|
||||
isDirentListLoading={this.props.isDirentListLoading}
|
||||
onAddFile={this.props.onAddFile}
|
||||
currentRepoInfo={this.props.currentRepoInfo}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -449,7 +449,8 @@ class DirentGridView extends React.Component {
|
||||
NEW_POWERPOINT_FILE,
|
||||
NEW_WORD_FILE
|
||||
];
|
||||
if (enableSeadoc) {
|
||||
const { currentRepoInfo } = this.props;
|
||||
if (enableSeadoc && !currentRepoInfo.encrypted) {
|
||||
menuList.push(NEW_SEADOC_FILE);
|
||||
}
|
||||
this.handleContextClick(event, id, menuList);
|
||||
|
@@ -727,7 +727,7 @@ class DirentListItem extends React.Component {
|
||||
onContextMenu={this.onItemContextMenu}
|
||||
>
|
||||
<td className={`pl10 ${this.state.isDragTipShow ? 'tr-drag-effect' : ''}`}>
|
||||
<input type="checkbox" className="vam" onChange={this.onItemSelected} checked={dirent.isSelected}/>
|
||||
<input type="checkbox" className="vam" onChange={this.onItemSelected} checked={dirent.isSelected} aria-label={dirent.isSelected ?gettext('Unselect this item') : gettext('Select this item')} />
|
||||
</td>
|
||||
<td className="pl10">
|
||||
{dirent.starred !== undefined &&
|
||||
|
@@ -340,7 +340,8 @@ class DirentListView extends React.Component {
|
||||
NEW_POWERPOINT_FILE,
|
||||
NEW_WORD_FILE
|
||||
];
|
||||
if (enableSeadoc) {
|
||||
const { currentRepoInfo } = this.props;
|
||||
if (enableSeadoc && !currentRepoInfo.encrypted) {
|
||||
direntsContainerMenuList.push(NEW_SEADOC_FILE);
|
||||
}
|
||||
|
||||
@@ -619,7 +620,7 @@ class DirentListView extends React.Component {
|
||||
<thead onMouseDown={this.onThreadMouseDown} onContextMenu={this.onThreadContextMenu}>
|
||||
<tr>
|
||||
<th width="3%" className="pl10">
|
||||
<input type="checkbox" className="vam" onChange={this.props.onAllItemSelected} checked={this.props.isAllItemSelected} />
|
||||
<input type="checkbox" className="vam" onChange={this.props.onAllItemSelected} checked={this.props.isAllItemSelected} aria-label={this.props.isAllItemSelected ? gettext('Unselect all items') : gettext('Select all items')} />
|
||||
</th>
|
||||
<th width="3%" className="pl10">{/*icon */}</th>
|
||||
<th width="5%" className="pl10">{/*star */}</th>
|
||||
|
@@ -10,6 +10,7 @@ import '../../css/tip-for-new-file.css';
|
||||
const propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
isDirentListLoading: PropTypes.bool.isRequired,
|
||||
currentRepoInfo: PropTypes.object.isRequired,
|
||||
onAddFile: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
@@ -45,6 +46,7 @@ class DirentNodeView extends React.Component {
|
||||
if (this.props.isDirentListLoading) {
|
||||
return (<Loading />);
|
||||
}
|
||||
const { currentRepoInfo } = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
@@ -61,7 +63,7 @@ class DirentNodeView extends React.Component {
|
||||
<button className="big-new-file-button" onClick={this.onCreateNewFile.bind(this, '.xlsx')}>
|
||||
{'+ Excel'}</button>
|
||||
<br />
|
||||
{enableSeadoc && <button className="big-new-file-button" onClick={this.onCreateNewFile.bind(this, '.sdoc')}>
|
||||
{enableSeadoc && !currentRepoInfo.encrypted && <button className="big-new-file-button" onClick={this.onCreateNewFile.bind(this, '.sdoc')}>
|
||||
{'+ SeaDoc'}</button>}
|
||||
</div>
|
||||
{this.state.isCreateFileDialogShow && (
|
||||
|
@@ -681,7 +681,7 @@ class FileUploader extends React.Component {
|
||||
<Fragment>
|
||||
<div className="file-uploader-container">
|
||||
<div className="file-uploader">
|
||||
<input className="upload-input" type="file" ref={this.uploadInput} onClick={this.onClick}/>
|
||||
<input className="upload-input" type="file" ref={this.uploadInput} onClick={this.onClick} aria-label={gettext('Upload')} />
|
||||
</div>
|
||||
</div>
|
||||
{this.state.isUploadRemindDialogShow &&
|
||||
|
@@ -1,7 +1,9 @@
|
||||
import React from 'react';
|
||||
import React, { Suspense } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { WikiViewer } from '@seafile/sdoc-editor';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import { appAvatarURL, assetsUrl, gettext, name, repoID, serviceURL, sharedToken, siteRoot, slug, username } from '../../utils/constants';
|
||||
import i18n from '../../_i18n/i18n-sdoc-editor';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import Loading from '../loading';
|
||||
|
||||
@@ -104,7 +106,13 @@ class SdocWikiPageViewer extends React.Component {
|
||||
scrollRef: this.scrollRef,
|
||||
};
|
||||
|
||||
return <WikiViewer {...props} />;
|
||||
return (
|
||||
<I18nextProvider i18n={ i18n }>
|
||||
<Suspense fallback={<Loading />}>
|
||||
<WikiViewer {...props} />
|
||||
</Suspense>
|
||||
</I18nextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@@ -664,7 +664,7 @@ class FileUploader extends React.Component {
|
||||
<Fragment>
|
||||
<div className="file-uploader-container">
|
||||
<div className="file-uploader">
|
||||
<input className="upload-input" type="file" ref={this.uploadInput} onClick={this.onClick}/>
|
||||
<input className="upload-input" type="file" ref={this.uploadInput} onClick={this.onClick} aria-label={gettext('Upload')} />
|
||||
</div>
|
||||
</div>
|
||||
{this.state.isUploadProgressDialogShow &&
|
||||
|
@@ -8,6 +8,7 @@ const propTypes = {
|
||||
currentSelectedOption: PropTypes.object.isRequired,
|
||||
options: PropTypes.array.isRequired,
|
||||
selectOption: PropTypes.func.isRequired,
|
||||
operationBeforeSelect: PropTypes.func,
|
||||
toggleItemFreezed: PropTypes.func
|
||||
};
|
||||
|
||||
@@ -52,7 +53,11 @@ class Selector extends Component {
|
||||
|
||||
selectItem = (e, targetItem) => {
|
||||
e.stopPropagation();
|
||||
this.props.selectOption(targetItem);
|
||||
if (this.props.operationBeforeSelect) {
|
||||
this.props.operationBeforeSelect();
|
||||
} else {
|
||||
this.props.selectOption(targetItem);
|
||||
}
|
||||
this.togglePopover();
|
||||
};
|
||||
|
||||
|
@@ -179,7 +179,7 @@ class DirOperationToolbar extends React.Component {
|
||||
|
||||
let content = null;
|
||||
if (Utils.isDesktop()) {
|
||||
let { showShareBtn } = this.props;
|
||||
const { showShareBtn, repoEncrypted } = this.props;
|
||||
content = (
|
||||
<Fragment>
|
||||
{canUpload && (
|
||||
@@ -210,7 +210,7 @@ class DirOperationToolbar extends React.Component {
|
||||
<button className="dropdown-item" onClick={this.onCreateExcelToggle} role="menuitem">{gettext('New Excel File')}</button>
|
||||
<button className="dropdown-item" onClick={this.onCreatePPTToggle} role="menuitem">{gettext('New PowerPoint File')}</button>
|
||||
<button className="dropdown-item" onClick={this.onCreateWordToggle} role="menuitem">{gettext('New Word File')}</button>
|
||||
{enableSeadoc && <button className="dropdown-item" onClick={this.onCreateSeaDocToggle} role="menuitem">{gettext('New SeaDoc File')} (beta)</button>}
|
||||
{enableSeadoc && !repoEncrypted && <button className="dropdown-item" onClick={this.onCreateSeaDocToggle} role="menuitem">{gettext('New SeaDoc File')} (beta)</button>}
|
||||
</div>
|
||||
)}
|
||||
</Fragment>
|
||||
|
Reference in New Issue
Block a user