2019-03-11 13:08:25 +00:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
2019-05-08 08:11:36 +00:00
|
|
|
import { gettext, canGenerateShareLink, isPro, mediaUrl, canLockUnlockFile } from '../../utils/constants';
|
2019-03-11 13:08:25 +00:00
|
|
|
import { IconButton, ButtonGroup, CollabUsersButton } from '@seafile/seafile-editor/dist/components/topbarcomponent/editorToolBar';
|
2019-04-13 03:54:14 +00:00
|
|
|
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem, Tooltip } from 'reactstrap';
|
2019-03-11 13:08:25 +00:00
|
|
|
import FileInfo from '@seafile/seafile-editor/dist/components/topbarcomponent/file-info';
|
|
|
|
|
2019-04-23 05:55:07 +00:00
|
|
|
const { seafileCollabServer } = window.app.config;
|
|
|
|
|
2019-03-11 13:08:25 +00:00
|
|
|
const propTypes = {
|
2019-03-29 10:15:39 +00:00
|
|
|
isDocs: PropTypes.bool.isRequired,
|
2019-03-11 13:08:25 +00:00
|
|
|
hasDraft: PropTypes.bool.isRequired,
|
|
|
|
isDraft: PropTypes.bool.isRequired,
|
|
|
|
editorUtilities: PropTypes.object.isRequired,
|
|
|
|
collabUsers: PropTypes.array.isRequired,
|
|
|
|
fileInfo: PropTypes.object.isRequired,
|
|
|
|
toggleShareLinkDialog: PropTypes.func.isRequired,
|
|
|
|
onEdit: PropTypes.func.isRequired,
|
|
|
|
toggleNewDraft: PropTypes.func.isRequired,
|
|
|
|
toggleStar: PropTypes.func.isRequired,
|
|
|
|
backToParentDirectory: PropTypes.func.isRequired,
|
|
|
|
openDialogs: PropTypes.func.isRequired,
|
2019-03-15 04:11:32 +00:00
|
|
|
showFileHistory: PropTypes.bool.isRequired,
|
|
|
|
toggleHistory: PropTypes.func.isRequired,
|
2019-04-13 03:54:14 +00:00
|
|
|
editorMode: PropTypes.string.isRequired,
|
|
|
|
readOnly: PropTypes.bool.isRequired,
|
2019-04-13 06:51:41 +00:00
|
|
|
contentChanged: PropTypes.bool.isRequired,
|
|
|
|
saving: PropTypes.bool.isRequired,
|
2019-04-15 04:09:58 +00:00
|
|
|
showDraftSaved: PropTypes.bool.isRequired,
|
2019-05-05 04:05:29 +00:00
|
|
|
isLocked: PropTypes.bool.isRequired,
|
|
|
|
lockedByMe: PropTypes.bool.isRequired,
|
|
|
|
toggleLockFile: PropTypes.func.isRequired,
|
2019-03-11 13:08:25 +00:00
|
|
|
};
|
|
|
|
|
2019-04-13 03:54:14 +00:00
|
|
|
const MoreMenuPropTypes = {
|
|
|
|
readOnly: PropTypes.bool.isRequired,
|
|
|
|
openDialogs: PropTypes.func.isRequired,
|
|
|
|
onEdit: PropTypes.func.isRequired,
|
2019-04-23 05:55:07 +00:00
|
|
|
editorMode: PropTypes.string.isRequired,
|
|
|
|
isSmallScreen: PropTypes.bool,
|
|
|
|
toggleShareLinkDialog: PropTypes.func,
|
|
|
|
backToParentDirectory: PropTypes.func,
|
2019-04-24 08:37:42 +00:00
|
|
|
showFileHistory: PropTypes.bool,
|
2019-04-23 05:55:07 +00:00
|
|
|
toggleHistory: PropTypes.func,
|
2019-04-17 02:31:17 +00:00
|
|
|
};
|
2019-04-13 03:54:14 +00:00
|
|
|
|
|
|
|
class MoreMenu extends React.PureComponent {
|
2019-03-11 13:08:25 +00:00
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2019-04-13 03:54:14 +00:00
|
|
|
this.state = {
|
|
|
|
tooltipOpen: false,
|
|
|
|
dropdownOpen:false
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
tooltipToggle = () => {
|
|
|
|
this.setState({ tooltipOpen: !this.state.tooltipOpen });
|
|
|
|
}
|
|
|
|
|
|
|
|
dropdownToggle = () => {
|
|
|
|
this.setState({ dropdownOpen:!this.state.dropdownOpen });
|
2019-03-11 13:08:25 +00:00
|
|
|
}
|
|
|
|
|
2019-04-13 03:54:14 +00:00
|
|
|
render() {
|
|
|
|
const editorMode = this.props.editorMode;
|
2019-04-19 07:58:11 +00:00
|
|
|
const isSmall = this.props.isSmallScreen;
|
2019-03-11 13:08:25 +00:00
|
|
|
return (
|
2019-04-19 06:36:58 +00:00
|
|
|
<Dropdown isOpen={this.state.dropdownOpen} toggle={this.dropdownToggle} direction="down" className="mx-1">
|
2019-04-13 03:54:14 +00:00
|
|
|
<DropdownToggle id="moreButton">
|
|
|
|
<i className="fa fa-ellipsis-v"/>
|
|
|
|
<Tooltip toggle={this.tooltipToggle} delay={{show: 0, hide: 0}} target="moreButton" placement='bottom' isOpen={this.state.tooltipOpen}>{gettext('More')}
|
|
|
|
</Tooltip>
|
|
|
|
</DropdownToggle>
|
|
|
|
<DropdownMenu className="drop-list" right={true}>
|
|
|
|
{(!this.props.readOnly && editorMode === 'rich') &&
|
|
|
|
<DropdownItem onMouseDown={this.props.onEdit.bind(this, 'plain')}>{gettext('Switch to plain text editor')}</DropdownItem>}
|
|
|
|
{(!this.props.readOnly && editorMode === 'plain') &&
|
|
|
|
<DropdownItem onMouseDown={this.props.onEdit.bind(this, 'rich')}>{gettext('Switch to rich text editor')}</DropdownItem>}
|
|
|
|
{(this.props.openDialogs && editorMode === 'rich') &&
|
|
|
|
<DropdownItem onMouseDown={this.props.openDialogs.bind(this, 'help')}>{gettext('Help')}</DropdownItem>
|
2019-03-11 13:08:25 +00:00
|
|
|
}
|
2019-04-25 08:29:41 +00:00
|
|
|
{isSmall && canGenerateShareLink && <DropdownItem onMouseDown={this.props.toggleShareLinkDialog}>{gettext('Share')}</DropdownItem>}
|
2019-04-19 07:58:11 +00:00
|
|
|
{isSmall && <DropdownItem onMouseDown={this.props.backToParentDirectory}>{gettext('Back to parent directory')}</DropdownItem>}
|
|
|
|
{(isSmall && this.props.showFileHistory) &&
|
|
|
|
<DropdownItem onMouseDown={this.props.toggleHistory}>{gettext('File History')}</DropdownItem>
|
|
|
|
}
|
2019-04-13 03:54:14 +00:00
|
|
|
</DropdownMenu>
|
|
|
|
</Dropdown>
|
2019-03-11 13:08:25 +00:00
|
|
|
);
|
|
|
|
}
|
2019-04-13 03:54:14 +00:00
|
|
|
}
|
2019-03-11 13:08:25 +00:00
|
|
|
|
2019-04-13 03:54:14 +00:00
|
|
|
MoreMenu.propTypes = MoreMenuPropTypes;
|
|
|
|
|
|
|
|
|
|
|
|
class MarkdownViewerToolbar extends React.Component {
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2019-03-11 13:08:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2019-05-05 04:05:29 +00:00
|
|
|
let { contentChanged, saving, isLocked, lockedByMe } = this.props;
|
2019-04-19 07:15:20 +00:00
|
|
|
let canPublishDraft = this.props.fileInfo.permission == 'rw';
|
|
|
|
let canCreateDraft = canPublishDraft && (!this.props.hasDraft && !this.props.isDraft && this.props.isDocs);
|
2019-04-13 03:54:14 +00:00
|
|
|
|
|
|
|
if (this.props.editorMode === 'rich') {
|
|
|
|
return (
|
|
|
|
<div className="sf-md-viewer-topbar">
|
|
|
|
<div className="sf-md-viewer-topbar-first d-flex justify-content-between">
|
2019-04-15 04:09:58 +00:00
|
|
|
<FileInfo
|
|
|
|
toggleStar={this.props.toggleStar}
|
|
|
|
editorUtilities={this.props.editorUtilities}
|
|
|
|
fileInfo={this.props.fileInfo}
|
|
|
|
showDraftSaved={this.props.showDraftSaved}
|
2019-05-08 09:59:26 +00:00
|
|
|
isLocked={isLocked}
|
|
|
|
isPro={isPro}
|
|
|
|
mediaUrl={mediaUrl}
|
2019-05-05 04:05:29 +00:00
|
|
|
isStarred={this.props.fileInfo.isStarred}
|
2019-04-15 04:09:58 +00:00
|
|
|
/>
|
2019-04-13 03:54:14 +00:00
|
|
|
{(this.props.hasDraft && !this.props.isDraft) &&
|
|
|
|
<div className='seafile-btn-view-review'>
|
|
|
|
<div className='tag tag-green'>{gettext('This file is in draft stage.')}
|
|
|
|
<a className="ml-2" onMouseDown={this.props.editorUtilities.goDraftPage}>{gettext('View Draft')}</a></div>
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
<div className="topbar-btn-container">
|
2019-04-19 07:15:20 +00:00
|
|
|
{canCreateDraft &&
|
2019-04-13 03:54:14 +00:00
|
|
|
<button onMouseDown={this.props.toggleNewDraft} className="btn btn-success btn-new-draft">
|
|
|
|
{gettext('New Draft')}</button>
|
|
|
|
}
|
2019-04-17 02:31:17 +00:00
|
|
|
{this.props.isDraft &&
|
|
|
|
<div>
|
|
|
|
<button type="button" className="btn btn-success seafile-btn-add-review"
|
|
|
|
onMouseDown={this.props.editorUtilities.goDraftPage}>{gettext('Start review')}</button>
|
2019-04-19 07:15:20 +00:00
|
|
|
{canPublishDraft &&
|
|
|
|
<button type="button" className="btn btn-success seafile-btn-add-review"
|
|
|
|
onMouseDown={this.props.editorUtilities.publishDraftFile}>{gettext('Publish')}</button>
|
|
|
|
}
|
2019-04-17 02:31:17 +00:00
|
|
|
</div>
|
|
|
|
}
|
2019-04-23 05:55:07 +00:00
|
|
|
{(seafileCollabServer && this.props.collabUsers.length > 0) &&
|
|
|
|
<CollabUsersButton
|
|
|
|
className="collab-users-dropdown"
|
|
|
|
users={this.props.collabUsers}
|
|
|
|
id="usersButton"
|
|
|
|
/>
|
|
|
|
}
|
2019-04-13 03:54:14 +00:00
|
|
|
<ButtonGroup>
|
2019-05-05 04:05:29 +00:00
|
|
|
<IconButton text={gettext('Back to parent directory')} id={'parentDirectory'}
|
|
|
|
icon={'fa fa-folder-open'} onMouseDown={this.props.backToParentDirectory}/>
|
|
|
|
{(canLockUnlockFile && !isLocked) &&
|
|
|
|
<IconButton id="lock-unlock-file" icon='fa fa-lock' text={gettext('Lock')} onMouseDown={this.props.toggleLockFile}/>
|
|
|
|
}
|
|
|
|
{(canLockUnlockFile && lockedByMe) &&
|
|
|
|
<IconButton id="lock-unlock-file" icon='fa fa-unlock' text={gettext('Unlock')} onMouseDown={this.props.toggleLockFile}/>
|
|
|
|
}
|
2019-04-25 07:09:28 +00:00
|
|
|
{canGenerateShareLink &&
|
|
|
|
<IconButton id={'shareBtn'} text={gettext('Share')} icon={'fa fa-share-alt'}
|
2019-05-14 02:15:09 +00:00
|
|
|
onMouseDown={this.props.toggleShareLinkDialog}/>
|
2019-04-25 07:09:28 +00:00
|
|
|
}
|
2019-04-13 03:54:14 +00:00
|
|
|
{
|
|
|
|
this.props.showFileHistory && <IconButton id={'historyButton'}
|
|
|
|
text={gettext('File History')} onMouseDown={this.props.toggleHistory} icon={'fa fa-history'}/>
|
|
|
|
}
|
2019-04-13 06:51:41 +00:00
|
|
|
{ saving ?
|
|
|
|
<button type={'button'} className={'btn btn-icon btn-secondary btn-active'}>
|
|
|
|
<i className={'fa fa-spin fa-spinner'}/></button>
|
|
|
|
:
|
|
|
|
<IconButton text={gettext('Save')} id={'saveButton'} icon={'fa fa-save'} disabled={!contentChanged}
|
2019-04-13 13:47:01 +00:00
|
|
|
onMouseDown={window.seafileEditor && window.seafileEditor.onRichEditorSave} isActive={contentChanged}/>
|
2019-04-13 06:51:41 +00:00
|
|
|
}
|
2019-04-13 03:54:14 +00:00
|
|
|
</ButtonGroup>
|
|
|
|
<MoreMenu
|
|
|
|
readOnly={this.props.readOnly}
|
|
|
|
openDialogs={this.props.openDialogs}
|
|
|
|
editorMode={this.props.editorMode}
|
|
|
|
onEdit={this.props.onEdit}
|
2019-04-19 07:58:11 +00:00
|
|
|
isSmallScreen={false}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="sf-md-viewer-topbar-first-narrow d-flex justify-content-between">
|
|
|
|
<FileInfo
|
|
|
|
toggleStar={this.props.toggleStar}
|
|
|
|
editorUtilities={this.props.editorUtilities}
|
|
|
|
fileInfo={this.props.fileInfo}
|
|
|
|
showDraftSaved={this.props.showDraftSaved}
|
|
|
|
/>
|
|
|
|
<div className="topbar-btn-container">
|
|
|
|
<ButtonGroup>
|
|
|
|
{saving ?
|
|
|
|
<button type={'button'} className={'btn btn-icon btn-secondary btn-active'}>
|
|
|
|
<i className={'fa fa-spin fa-spinner'}/></button>
|
|
|
|
:
|
|
|
|
<IconButton text={gettext('Save')} id={'saveButton'} icon={'fa fa-save'} disabled={!contentChanged}
|
|
|
|
onMouseDown={window.seafileEditor && window.seafileEditor.onRichEditorSave} isActive={contentChanged}/>
|
|
|
|
}
|
|
|
|
</ButtonGroup>
|
|
|
|
<MoreMenu
|
|
|
|
readOnly={this.props.readOnly}
|
|
|
|
openDialogs={this.props.openDialogs}
|
|
|
|
editorMode={this.props.editorMode}
|
|
|
|
onEdit={this.props.onEdit}
|
|
|
|
toggleShareLinkDialog={this.props.toggleShareLinkDialog}
|
|
|
|
backToParentDirectory={this.props.backToParentDirectory}
|
|
|
|
showFileHistory={this.props.showFileHistory}
|
|
|
|
toggleHistory={this.props.toggleHistory}
|
|
|
|
isSmallScreen={true}
|
2019-04-13 03:54:14 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
} else if (this.props.editorMode === 'plain') {
|
|
|
|
return (
|
|
|
|
<div className="sf-md-viewer-topbar">
|
|
|
|
<div className="sf-md-viewer-topbar-first d-flex justify-content-between">
|
|
|
|
<FileInfo toggleStar={this.props.toggleStar} editorUtilities={this.props.editorUtilities}
|
|
|
|
fileInfo={this.props.fileInfo}/>
|
|
|
|
<div className="topbar-btn-container">
|
2019-04-23 05:55:07 +00:00
|
|
|
{(seafileCollabServer && this.props.collabUsers.length > 0) &&
|
|
|
|
<CollabUsersButton
|
|
|
|
className="collab-users-dropdown"
|
|
|
|
users={this.props.collabUsers}
|
|
|
|
id="usersButton"
|
|
|
|
/>
|
|
|
|
}
|
2019-04-13 06:51:41 +00:00
|
|
|
<ButtonGroup>
|
|
|
|
{ saving ?
|
|
|
|
<button type={'button'} className={'btn btn-icon btn-secondary btn-active'}>
|
|
|
|
<i className={'fa fa-spin fa-spinner'}/></button>
|
|
|
|
:
|
|
|
|
<IconButton id={'saveButton'} text={gettext('Save')} icon={'fa fa-save'} onMouseDown={window.seafileEditor && window.seafileEditor.onPlainEditorSave} disabled={!contentChanged} isActive={contentChanged} />
|
|
|
|
}
|
|
|
|
</ButtonGroup>
|
2019-04-13 03:54:14 +00:00
|
|
|
<MoreMenu
|
|
|
|
readOnly={this.props.readOnly}
|
|
|
|
openDialogs={this.props.openDialogs}
|
|
|
|
editorMode={this.props.editorMode}
|
|
|
|
onEdit={this.props.onEdit}
|
2019-04-19 07:58:11 +00:00
|
|
|
isSmallScreen={false}
|
2019-04-13 03:54:14 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-04-19 07:58:11 +00:00
|
|
|
<div className="sf-md-viewer-topbar-first-narrow d-flex justify-content-between">
|
|
|
|
<FileInfo toggleStar={this.props.toggleStar} editorUtilities={this.props.editorUtilities}
|
|
|
|
fileInfo={this.props.fileInfo}/>
|
|
|
|
<div className="topbar-btn-container">
|
|
|
|
<ButtonGroup>
|
|
|
|
{saving ?
|
|
|
|
<button type={'button'} className={'btn btn-icon btn-secondary btn-active'}>
|
|
|
|
<i className={'fa fa-spin fa-spinner'}/></button>
|
|
|
|
:
|
|
|
|
<IconButton
|
|
|
|
id={'saveButton'}
|
|
|
|
text={gettext('Save')}
|
|
|
|
icon={'fa fa-save'}
|
|
|
|
onMouseDown={window.seafileEditor && window.seafileEditor.onPlainEditorSave}
|
|
|
|
disabled={!contentChanged}
|
|
|
|
isActive={contentChanged}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
</ButtonGroup>
|
|
|
|
<MoreMenu
|
|
|
|
readOnly={this.props.readOnly}
|
|
|
|
openDialogs={this.props.openDialogs}
|
|
|
|
editorMode={this.props.editorMode}
|
|
|
|
onEdit={this.props.onEdit}
|
|
|
|
isSmallScreen={false}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2019-04-13 03:54:14 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2019-03-11 13:08:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MarkdownViewerToolbar.propTypes = propTypes;
|
|
|
|
|
|
|
|
export default MarkdownViewerToolbar;
|