mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-09 10:50:24 +00:00
18
frontend/package-lock.json
generated
18
frontend/package-lock.json
generated
@@ -765,7 +765,7 @@
|
|||||||
},
|
},
|
||||||
"axios": {
|
"axios": {
|
||||||
"version": "0.18.0",
|
"version": "0.18.0",
|
||||||
"resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
|
||||||
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
|
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"follow-redirects": "^1.3.0",
|
"follow-redirects": "^1.3.0",
|
||||||
@@ -6796,7 +6796,7 @@
|
|||||||
},
|
},
|
||||||
"git-up": {
|
"git-up": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "http://registry.npmjs.org/git-up/-/git-up-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/git-up/-/git-up-1.2.1.tgz",
|
||||||
"integrity": "sha1-JkSAoAax2EJhrB/gmjpRacV+oZ0=",
|
"integrity": "sha1-JkSAoAax2EJhrB/gmjpRacV+oZ0=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-ssh": "^1.0.0",
|
"is-ssh": "^1.0.0",
|
||||||
@@ -6805,7 +6805,7 @@
|
|||||||
},
|
},
|
||||||
"git-url-parse": {
|
"git-url-parse": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "http://registry.npmjs.org/git-url-parse/-/git-url-parse-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-5.0.1.tgz",
|
||||||
"integrity": "sha1-/j15xnRq4FBIz6UIyB553du6OEM=",
|
"integrity": "sha1-/j15xnRq4FBIz6UIyB553du6OEM=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"git-up": "^1.0.0"
|
"git-up": "^1.0.0"
|
||||||
@@ -9766,7 +9766,7 @@
|
|||||||
},
|
},
|
||||||
"node-status-codes": {
|
"node-status-codes": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz",
|
||||||
"integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8="
|
"integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8="
|
||||||
},
|
},
|
||||||
"noop6": {
|
"noop6": {
|
||||||
@@ -10137,7 +10137,7 @@
|
|||||||
},
|
},
|
||||||
"package.json": {
|
"package.json": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "http://registry.npmjs.org/package.json/-/package.json-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/package.json/-/package.json-2.0.1.tgz",
|
||||||
"integrity": "sha1-+IYFnSpJ7QduZIg2ldc7K0bSHW0=",
|
"integrity": "sha1-+IYFnSpJ7QduZIg2ldc7K0bSHW0=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"git-package-json": "^1.4.0",
|
"git-package-json": "^1.4.0",
|
||||||
@@ -10147,7 +10147,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"got": {
|
"got": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.1",
|
||||||
"resolved": "http://registry.npmjs.org/got/-/got-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz",
|
||||||
"integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=",
|
"integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"create-error-class": "^3.0.1",
|
"create-error-class": "^3.0.1",
|
||||||
@@ -10169,7 +10169,7 @@
|
|||||||
},
|
},
|
||||||
"package-json": {
|
"package-json": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.0",
|
||||||
"resolved": "http://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz",
|
||||||
"integrity": "sha1-DRW9Z9HLvduyyiIv8u24a8sxqLs=",
|
"integrity": "sha1-DRW9Z9HLvduyyiIv8u24a8sxqLs=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"got": "^5.0.0",
|
"got": "^5.0.0",
|
||||||
@@ -15306,13 +15306,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz",
|
"resolved": "http://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz",
|
||||||
"integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=",
|
"integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz",
|
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz",
|
||||||
"integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=",
|
"integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
91
frontend/src/components/toolbar/cdoc-editor-topbar.js
Normal file
91
frontend/src/components/toolbar/cdoc-editor-topbar.js
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { gettext } from '../../utils/constants';
|
||||||
|
import { IconButton, ButtonGroup, CollabUsersButton } from '@seafile/seafile-editor/dist/components/topbarcomponent/editorToolBar';
|
||||||
|
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem, Tooltip } from 'reactstrap';
|
||||||
|
import FileInfo from '@seafile/seafile-editor/dist/components/topbarcomponent/file-info';
|
||||||
|
|
||||||
|
|
||||||
|
class MoreMenu extends React.PureComponent {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
tooltipOpen: false,
|
||||||
|
dropdownOpen:false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltipToggle = () => {
|
||||||
|
this.setState({ tooltipOpen: !this.state.tooltipOpen });
|
||||||
|
}
|
||||||
|
|
||||||
|
dropdownToggle = () => {
|
||||||
|
this.setState({ dropdownOpen:!this.state.dropdownOpen });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Dropdown isOpen={this.state.dropdownOpen} toggle={this.dropdownToggle} direction="down" className="mx-lg-1">
|
||||||
|
<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}>
|
||||||
|
<DropdownItem onMouseDown={this.props.openDialogs.bind(this, 'help')}>{gettext('Help')}</DropdownItem>
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CDOCTopbar extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let { contentChanged, saving } = this.props;
|
||||||
|
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}
|
||||||
|
showDraftSaved={this.props.showDraftSaved}
|
||||||
|
/>
|
||||||
|
<div className="topbar-btn-container">
|
||||||
|
{this.props.collabUsers.length > 0 && <CollabUsersButton className={'collab-users-dropdown'}
|
||||||
|
users={this.props.collabUsers} id={'usersButton'} />}
|
||||||
|
<ButtonGroup>
|
||||||
|
<IconButton id={'shareBtn'} text={gettext('Share')} icon={'fa fa-share-alt'}
|
||||||
|
onMouseDown={this.props.toggleShareLinkDialog}/>
|
||||||
|
<IconButton text={gettext('Back to parent directory')} id={'parentDirectory'}
|
||||||
|
icon={'fa fa-folder-open'} onMouseDown={this.props.backToParentDirectory}/>
|
||||||
|
{
|
||||||
|
this.props.showFileHistory && <IconButton id={'historyButton'}
|
||||||
|
text={gettext('File History')} onMouseDown={this.props.toggleHistory} icon={'fa fa-history'}/>
|
||||||
|
}
|
||||||
|
{ 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={this.props.onSave} isActive={contentChanged}/>
|
||||||
|
}
|
||||||
|
</ButtonGroup>
|
||||||
|
<MoreMenu
|
||||||
|
openDialogs={this.props.openDialogs}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CDOCTopbar;
|
@@ -5,14 +5,25 @@ import i18n from './i18n';
|
|||||||
import { seafileAPI } from './utils/seafile-api';
|
import { seafileAPI } from './utils/seafile-api';
|
||||||
import io from 'socket.io-client';
|
import io from 'socket.io-client';
|
||||||
import { gettext } from './utils/constants';
|
import { gettext } from './utils/constants';
|
||||||
|
import ModalPortal from './components/modal-portal';
|
||||||
import { RichEditor } from '@seafile/seafile-editor';
|
import { RichEditor } from '@seafile/seafile-editor';
|
||||||
|
import CDOCTypeChooser from '@seafile/seafile-editor/dist/components/codc-type-chooser';
|
||||||
|
import { Value } from 'slate';
|
||||||
|
import CDOCTopbar from './components/toolbar/cdoc-editor-topbar';
|
||||||
|
import ShareDialog from './components/dialog/share-dialog';
|
||||||
|
import { Utils } from './utils/utils';
|
||||||
|
import { translate } from 'react-i18next';
|
||||||
|
|
||||||
import { EditorUtilities } from '@seafile/seafile-editor/dist/editorUtilities';
|
import { EditorUtilities } from '@seafile/seafile-editor/dist/editorUtilities';
|
||||||
import toaster from './components/toast';
|
import toaster from './components/toast';
|
||||||
|
import { RichEditorUtils } from '@seafile/seafile-editor/dist/rich-editor-utils';
|
||||||
|
|
||||||
|
import './css/markdown-viewer/markdown-editor.css';
|
||||||
import './assets/css/fa-solid.css';
|
import './assets/css/fa-solid.css';
|
||||||
import './assets/css/fa-regular.css';
|
import './assets/css/fa-regular.css';
|
||||||
import './assets/css/fontawesome.css';
|
import './assets/css/fontawesome.css';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
const CryptoJS = require('crypto-js');
|
const CryptoJS = require('crypto-js');
|
||||||
|
|
||||||
const lang = window.app.config.lang;
|
const lang = window.app.config.lang;
|
||||||
@@ -28,8 +39,10 @@ class CDOCEditor extends React.Component {
|
|||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.collabServer = seafileCollabServer ? seafileCollabServer : null
|
this.collabServer = seafileCollabServer ? seafileCollabServer : null;
|
||||||
|
this.richEditorUtils = new RichEditorUtils(editorUtilities, this)
|
||||||
this.state = {
|
this.state = {
|
||||||
|
value: Value.create({}),
|
||||||
collabUsers: userInfo ?
|
collabUsers: userInfo ?
|
||||||
[{ user: userInfo, is_editing: false }] : [],
|
[{ user: userInfo, is_editing: false }] : [],
|
||||||
fileInfo: {
|
fileInfo: {
|
||||||
@@ -39,6 +52,11 @@ class CDOCEditor extends React.Component {
|
|||||||
lastModifier: '',
|
lastModifier: '',
|
||||||
id: '',
|
id: '',
|
||||||
},
|
},
|
||||||
|
isShowTypeChooser: false,
|
||||||
|
isSaving: false,
|
||||||
|
contentChanged: false,
|
||||||
|
showShareLinkDialog: false,
|
||||||
|
isShowHistory: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.collabServer) {
|
if (this.state.collabServer) {
|
||||||
@@ -53,22 +71,6 @@ class CDOCEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
editorUtilities.getFileInfo(repoID, filePath).then((res) => {
|
|
||||||
let { mtime, size, starred, permission, last_modifier_name, id } = res.data;
|
|
||||||
let lastModifier = last_modifier_name;
|
|
||||||
this.setState((prevState, props) => ({
|
|
||||||
fileInfo: {
|
|
||||||
...prevState.fileInfo,
|
|
||||||
mtime,
|
|
||||||
size,
|
|
||||||
starred,
|
|
||||||
permission,
|
|
||||||
lastModifier,
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
})
|
|
||||||
|
|
||||||
if (userInfo && this.socket) {
|
if (userInfo && this.socket) {
|
||||||
const { repoID, path } = this.state.fileInfo;
|
const { repoID, path } = this.state.fileInfo;
|
||||||
this.socket.emit('presence', {
|
this.socket.emit('presence', {
|
||||||
@@ -141,20 +143,135 @@ class CDOCEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleStar = () => {
|
||||||
|
let starrd = this.state.fileInfo.starred;
|
||||||
|
if (starrd) {
|
||||||
|
editorUtilities.unStarItem().then((response) => {
|
||||||
|
this.setState({
|
||||||
|
fileInfo: Object.assign({}, this.state.fileInfo, { starred: !starrd })
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if (!starrd) {
|
||||||
|
editorUtilities.starItem().then((response) => {
|
||||||
|
this.setState({
|
||||||
|
fileInfo: Object.assign({}, this.state.fileInfo, { starred: !starrd })
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleHistory = () => {
|
||||||
|
window.location.href = siteRoot + 'repo/file_revisions/' + repoID + '/?p=' + Utils.encodePath(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
backToParentDirectory = () => {
|
||||||
|
window.location.href = editorUtilities.getParentDectionaryUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleShareLinkDialog = () => {
|
||||||
|
this.openDialogs('share_link');
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleCancel = () => {
|
||||||
|
this.setState({
|
||||||
|
showShareLinkDialog: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
openDialogs = (option) => {
|
||||||
|
switch (option) {
|
||||||
|
case 'help':
|
||||||
|
window.richEditor.showHelpDialog();
|
||||||
|
break;
|
||||||
|
case 'share_link':
|
||||||
|
this.setState({
|
||||||
|
showMarkdownEditorDialog: true,
|
||||||
|
showShareLinkDialog: true,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'insert_file':
|
||||||
|
this.setState({
|
||||||
|
showMarkdownEditorDialog: true,
|
||||||
|
showInsertFileDialog: true,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.richEditorUtils.initialContent();
|
||||||
|
editorUtilities.getFileInfo().then((response) => {
|
||||||
|
this.setState({
|
||||||
|
fileInfo: Object.assign({}, this.state.fileInfo, {
|
||||||
|
mtime: response.data.mtime,
|
||||||
|
size: response.data.size,
|
||||||
|
name: response.data.name,
|
||||||
|
starred: response.data.starred,
|
||||||
|
lastModifier: response.data.last_modifier_name,
|
||||||
|
permission: response.data.permission,
|
||||||
|
id: response.data.id,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<I18nextProvider i18n={ i18n } initialLanguage={ lang } >
|
<React.Fragment>
|
||||||
<RichEditor
|
<CDOCTopbar
|
||||||
|
fileInfo={this.state.fileInfo}
|
||||||
collabUsers={this.state.collabUsers}
|
collabUsers={this.state.collabUsers}
|
||||||
|
toggleStar={this.toggleStar}
|
||||||
|
editorUtilities={editorUtilities}
|
||||||
|
backToParentDirectory={this.backToParentDirectory}
|
||||||
|
toggleShareLinkDialog={this.toggleShareLinkDialog}
|
||||||
|
openDialogs={this.openDialogs}
|
||||||
|
showFileHistory={this.state.isShowHistory ? false : true}
|
||||||
|
toggleHistory={this.toggleHistory}
|
||||||
|
saving={this.state.isSaving}
|
||||||
|
onSave={this.richEditorUtils.onSave}
|
||||||
|
contentChanged={this.state.contentChanged}
|
||||||
|
/>
|
||||||
|
<RichEditor
|
||||||
|
onSave={this.richEditorUtils.onSave}
|
||||||
|
resetContentChange={this.richEditorUtils.resetContentChange}
|
||||||
|
value={this.state.value}
|
||||||
|
onChange={this.richEditorUtils.onChange}
|
||||||
editorUtilities={editorUtilities}
|
editorUtilities={editorUtilities}
|
||||||
/>
|
/>
|
||||||
</I18nextProvider>
|
{this.state.showShareLinkDialog &&
|
||||||
|
<ModalPortal>
|
||||||
|
<ShareDialog
|
||||||
|
itemType="file"
|
||||||
|
itemName={this.state.fileInfo.name}
|
||||||
|
itemPath={filePath}
|
||||||
|
repoID={repoID}
|
||||||
|
toggleDialog={this.toggleCancel}
|
||||||
|
isGroupOwnedRepo={false}
|
||||||
|
repoEncrypted={false}
|
||||||
|
/>
|
||||||
|
</ModalPortal>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.state.isShowTypeChooser &&
|
||||||
|
<CDOCTypeChooser
|
||||||
|
showTypeChooser={this.state.isShowTypeChooser}
|
||||||
|
setDocument={this.richEditorUtils.setDocument}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TranslatedCDOCEditor = translate('translations')(CDOCEditor)
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<CDOCEditor/>,
|
<I18nextProvider i18n={i18n} initialLanguage={lang} >
|
||||||
|
<TranslatedCDOCEditor />
|
||||||
|
</I18nextProvider>
|
||||||
|
,
|
||||||
document.getElementById('wrapper')
|
document.getElementById('wrapper')
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user