1
0
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:
杨顺强
2024-04-25 14:29:17 +08:00
53 changed files with 761 additions and 211 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 && (

View File

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

View File

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

View File

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

View File

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

View File

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