1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-01 23:38:37 +00:00

Revert "Umind update (#3064)"

This reverts commit b839efe490.
This commit is contained in:
lian 2019-03-21 17:31:01 +08:00
parent 91a520f13e
commit 0d94fcd070
14 changed files with 626 additions and 194 deletions

View File

@ -0,0 +1,71 @@
#wrapper {
width: 100%;
height: 100%;
display: flex;
overflow: hidden;
}
.umind-container {
display: flex;
flex: 1;
flex-direction: column;
}
.umind-container .umind-header {
padding: 8px;
border: 1px solid #E6E9ED;
}
.umind-container .umind-body {
display: flex;
flex: 1;
}
.toolbar-container {
display: flex;
}
.toolbar-container .custom-toolbar {
width: auto;
}
.toolbar-container .common-toolbar {
display: flex;
flex: 1;
}
.umind-body .umind-editor-content,
.umind-body .umind-editor-sidebar {
display: flex;
flex-direction: column;
}
.umind-editor-content .umind-editor {
display: flex;
flex: 1;
background-color: #eee;
}
.umind-editor-sidebar {
background: #FAFAFA;
}
.umind-editor-sidebar:first-child {
border-right: 1px solid #E6E9ED;
}
.umind-editor-sidebar:last-child {
border-left: 1px solid #E6E9ED;
}
.umind-editor-sidebar .detail-panel {
flex: 1;
display: flex;
background: #FAFAFA;
}
.detail-panel .node-detail {
flex: 1;
background: #FAFAFA;
}

View File

@ -0,0 +1,76 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Row, Col } from 'antd';
import GGEditor, { Mind } from 'gg-editor';
import { seafileAPI } from '../utils/seafile-api';
import UMindToolbar from './umind-toolbar/umind-toolbar';
import UMindDetailPanel from './umind-detail-panel';
import UMindEditorMinimap from './umind-editor/umind-editor-minimap';
import UMindContextMenu from './umind-editor/umind-context-menu';
import Loading from '../components/loading';
// import data from './mock.js';
import 'antd/dist/antd.css';
import './theme/iconfont.css'
import '../css/umind.css';
const propTypes = {
};
const { repoID, fileName, filePath } = window.app.pageOptions;
class UMind extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
data: ''
};
this.umindContent = '';
}
componentDidMount() {
seafileAPI.getFileDownloadLink(repoID, filePath).then(res => {
let url = res.data;
seafileAPI.getFileContent(url).then(res => {
let data = res.data;
this.umindContent = data;
this.setState({
isLoading: false,
data: data
});
});
})
}
render() {
return (
<GGEditor className="umind-container">
<Row type="flex" className="umind-header">
<Col span={24} className="toolbar-container">
<UMindToolbar />
</Col>
</Row>
<Row type="flex" className="umind-body">
<Col span={20} className="umind-editor-content">
{this.state.isLoading && <Loading />}
{!this.state.isLoading && (
<Mind data={this.umindContent} className="umind-editor" />
)}
</Col>
<Col span={4} className="umind-editor-sidebar">
<UMindDetailPanel />
<UMindEditorMinimap />
</Col>
</Row>
<UMindContextMenu />
</GGEditor>
);
}
}
UMind.propTypes = propTypes;
export default UMind;

View File

@ -0,0 +1,114 @@
@font-face {
font-family: "iconfont";
src: url('//at.alicdn.com/t/font_598462_3xve1872wizzolxr.eot?t=1522149591264');
src: url('//at.alicdn.com/t/font_598462_3xve1872wizzolxr.eot?t=1522149591264#iefix') format('embedded-opentype'),
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('//at.alicdn.com/t/font_598462_3xve1872wizzolxr.ttf?t=1522149591264') format('truetype'),
url('//at.alicdn.com/t/font_598462_3xve1872wizzolxr.svg?t=1522149591264#iconfont') format('svg');
}
@font-face {
font-family: "bi-icon";
src: url('//at.alicdn.com/t/font_538964_lt8h7c2h3hfo5hfr.eot');
src: url('//at.alicdn.com/t/font_538964_lt8h7c2h3hfo5hfr.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_538964_lt8h7c2h3hfo5hfr.woff') format('woff'),
url('//at.alicdn.com/t/font_538964_lt8h7c2h3hfo5hfr.ttf') format('truetype'),
url('//at.alicdn.com/t/font_538964_lt8h7c2h3hfo5hfr.svg#iconfont') format('svg');
}
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.bi-icon {
font-family:"bi-icon" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-save:before {
content: "\e669";
}
.icon-undo:before {
content: "\e8ab";
}
.icon-redo:before {
content: "\e8a9";
}
.icon-cut:before {
content: "\e8a2";
}
.icon-copy-o:before {
content: "\e8a4";
}
.icon-paster-o:before {
content: "\e8a8";
}
.icon-delete-o:before {
content: "\e8a5";
}
.icon-zoom-in-o:before {
content: "\e8ac";
}
.icon-zoom-out-o:before {
content: "\e8ae";
}
.icon-fit:before {
content: "\e8a6";
}
.icon-actual-size-o:before {
content: "\e8a3";
}
.icon-to-back:before {
content: "\e8b0";
}
.icon-to-front:before {
content: "\e8aa";
}
.icon-select:before {
content: "\e8a7";
}
.icon-group:before {
content: "\e8af";
}
.icon-ungroup:before {
content: "\e8ad";
}
.icon-insert-sibling:before {
content: "\e8af";
}
.icon-insert-child:before {
content: "\e8ae";
}
.icon-collapse-subtree:before {
content: "\e8b3";
}
.icon-expand-subtree:before {
content: "\e8b4";
}

View File

@ -0,0 +1,22 @@
import React from 'react';
import { Card } from 'antd';
import { NodePanel, CanvasPanel, DetailPanel } from 'gg-editor';
import NodeDetail from './node-detail';
class UMindDetails extends React.Component {
render() {
return (
<DetailPanel className="detail-panel">
<NodePanel className="node-detail">
<NodeDetail />
</NodePanel>
<CanvasPanel className="node-detail">
<Card type="inner" title="画布属性" bordered={true} />
</CanvasPanel>
</DetailPanel>
);
}
}
export default UMindDetails;

View File

@ -0,0 +1,74 @@
import React from 'react';
import { Card, Form, Input } from 'antd';
import { withPropsAPI } from 'gg-editor';
const { Item } = Form;
const inlineFormItemLayout = {
labelCol: {
sm: { span: 6 },
},
wrapperCol: {
sm: { span: 18 },
},
};
class NodeDetail extends React.Component {
handleSubmit = (e) => {
e.preventDefault();
const { form, propsAPI } = this.props;
const { getSelected, executeCommand, update } = propsAPI;
form.validateFieldsAndScroll((err, values) => {
if (err) {
return;
}
const item = getSelected()[0];
if (!item) {
return;
}
executeCommand(() => {
update(item, {
...values,
});
});
});
}
render() {
const { form, propsAPI } = this.props;
const { getFieldDecorator } = form;
const { getSelected } = propsAPI;
const item = getSelected()[0];
if (!item) {
return null;
}
const { label } = item.getModel();
return (
<Card type="inner" title="节点属性" bordered={false}>
<Form onSubmit={this.handleSubmit}>
<Item
label="标签"
{...inlineFormItemLayout}
>
{
getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)
}
</Item>
</Form>
</Card>
);
}
}
export default Form.create()(withPropsAPI(NodeDetail));

View File

@ -0,0 +1,33 @@
.context-menu {
display: none;
background: #FFFFFF;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, .15);
overflow: hidden;
}
.context-menu .item {
cursor: pointer;
user-select: none;
display: flex;
align-items: center;
padding: 5px 12px;
transition: all .3s;
}
.context-menu .item:hover {
background: #E6F7FF;
}
.context-menu .item i {
margin-right: 8px;
}
.context-menu .disable .item {
cursor: auto;
color: rgba(0, 0, 0, 0.25);
}
.context-menu .disable .item:hover {
background: #FFFFFF;
}

View File

@ -0,0 +1,61 @@
import React from 'react';
import { Command, NodeMenu, CanvasMenu, ContextMenu } from 'gg-editor';
import './context-menu.css';
class UMindContextMenu extends React.Component {
render() {
return (
<ContextMenu className="context-menu">
<NodeMenu>
<Command name="append">
<div className="item">
<i className="bi-icon icon-insert-sibling" />
<span>插入同级</span>
</div>
</Command>
<Command name="appendChild">
<div className="item">
<i className="bi-icon icon-insert-child" />
<span>插入子级</span>
</div>
</Command>
<Command name="collapse">
<div className="item">
<i className="bi-icon icon-collapse-subtree" />
<span>折叠</span>
</div>
</Command>
<Command name="expand">
<div className="item">
<i className="bi-icon icon-expand-subtree" />
<span>展开</span>
</div>
</Command>
<Command name="delete">
<div className="item">
<i className="iconfont icon-delete-o" />
<span>删除</span>
</div>
</Command>
</NodeMenu>
<CanvasMenu>
<Command name="undo">
<div className="item">
<i className="iconfont icon-undo" />
<span>撤销</span>
</div>
</Command>
<Command name="redo">
<div className="item">
<i className="iconfont icon-redo" />
<span>重做</span>
</div>
</Command>
</CanvasMenu>
</ContextMenu>
);
}
}
export default UMindContextMenu;

View File

@ -0,0 +1,15 @@
import React from 'react';
import { Card } from 'antd';
import { Minimap } from 'gg-editor';
class UMindEditorMinimap extends React.Component {
render() {
return (
<Card type="inner" title="缩略图" bordered={false}>
<Minimap height={200} />
</Card>
);
}
}
export default UMindEditorMinimap;

View File

@ -0,0 +1,38 @@
.common-toolbar {
display: flex;
align-items: center;
}
.common-toolbar .command i {
cursor: pointer;
display: inline-block;
margin: 0 6px;
width: 27px;
height: 27px;
text-align: center;
border: 1px solid #FFFFFF;
}
.common-toolbar .command i:hover {
border: 1px solid #E6E9ED;
}
.common-toolbar .disable i {
cursor: auto;
color: rgba(0, 0, 0, 0.25);
}
.common-toolbar .disable i:hover {
border: 1px solid #FFFFFF;
}
.tooltip .ant-tooltip-inner {
font-size: 12px;
border-radius: 0;
}
.common-toolbar .anticon.custom-save {
display: flex;
justify-content: center;
align-items: center;
}

View File

@ -0,0 +1,102 @@
import React, { Fragment } from 'react';
import { Tooltip, Divider, Icon } from 'antd';
import { Toolbar, Command } from 'gg-editor';
import withGGEditorContext from 'gg-editor/es/common/context/GGEditorContext/withGGEditorContext';
import { gettext } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils';
import toaster from '../../components/toast';
import './toolbar.css';
const { repoID, filePath, fileName } = window.app.pageOptions;
class UMindToolbar extends React.Component {
onSaveClick = (e) => {
e.preventDefault();
let { editor } = this.props;
let page = editor.getCurrentPage();
let { data, defaultData } = page._cfg;
let dirPath = Utils.getDirName(filePath);
seafileAPI.getUpdateLink(repoID, dirPath).then(res => {
let updateLink = res.data;
// need optimized
let updateData = data ? JSON.stringify(data) : JSON.stringify(defaultData);
seafileAPI.updateFile(updateLink, filePath, fileName, updateData).then(res => {
toaster.success(gettext('File saved.'));
}).catch(() => {
toaster.success(gettext('File save failed.'));
});
})
}
render() {
return (
<Fragment>
<div className="custom-toolbar" onClick={this.onSaveClick}>
<Tooltip title="保存" placement="bottom" overlayClassName="tooltip">
<Icon type="save" />
</Tooltip>
</div>
<Toolbar className="common-toolbar">
<Divider type="vertical" />
<Command name="undo">
<Tooltip title="撤销" placement="bottom" overlayClassName="tooltip">
<i className="iconfont icon-undo" />
</Tooltip>
</Command>
<Command name="redo">
<Tooltip title="重做" placement="bottom" overlayClassName="tooltip">
<i className="iconfont icon-redo" />
</Tooltip>
</Command>
<Divider type="vertical" />
<Command name="zoomIn">
<Tooltip title="放大" placement="bottom" overlayClassName="tooltip">
<i className="iconfont icon-zoom-in-o" />
</Tooltip>
</Command>
<Command name="zoomOut">
<Tooltip title="缩小" placement="bottom" overlayClassName="tooltip">
<i className="iconfont icon-zoom-out-o" />
</Tooltip>
</Command>
<Command name="autoZoom">
<Tooltip title="适应画布" placement="bottom" overlayClassName="tooltip">
<i className="iconfont icon-fit" />
</Tooltip>
</Command>
<Command name="resetZoom">
<Tooltip title="实际尺寸" placement="bottom" overlayClassName="tooltip">
<i className="iconfont icon-actual-size-o" />
</Tooltip>
</Command>
<Divider type="vertical" />
<Command name="append">
<Tooltip title="插入同级" placement="bottom" overlayClassName="tooltip">
<i className="bi-icon icon-insert-sibling" />
</Tooltip>
</Command>
<Command name="appendChild">
<Tooltip title="插入子级" placement="bottom" overlayClassName="tooltip">
<i className="bi-icon icon-insert-child" />
</Tooltip>
</Command>
<Divider type="vertical" />
<Command name="collapse">
<Tooltip title="折叠" placement="bottom" overlayClassName="tooltip">
<i className="bi-icon icon-collapse-subtree" />
</Tooltip>
</Command>
<Command name="expand">
<Tooltip title="展开" placement="bottom" overlayClassName="tooltip">
<i className="bi-icon icon-expand-subtree" />
</Tooltip>
</Command>
</Toolbar>
</Fragment>
);
}
}
export default withGGEditorContext(UMindToolbar);

View File

@ -1,90 +1,17 @@
import { seafileAPI } from './utils/seafile-api';
import { Utils } from './utils/utils';
import { gettext, lang } from './utils/constants';
import toaster from './components/toast';
import React from 'react';
import ReactDOM from 'react-dom';
import UMind from './umind';
const { UMind, React, ReactDOM } = window;
const { repoID, filePath, fileName, username } = window.app.pageOptions;
const DEFAULT_DATA = {
roots: [{
label: '中心主题',
children: [{
label: '分支主题 1',
}, {
label: '分支主题 2',
}, {
label: '分支主题 3',
}],
}],
};
class ViewFileUmind extends React.Component {
constructor(props) {
super(props);
this.state = {
data: DEFAULT_DATA,
isDataLoading: true
};
this.locale = 'zh-CN';
this.config = {
file: {
id: repoID + filePath,
},
user: {
id: username,
},
socket: {
url: 'https://umind.alibaba-inc.com',
events: {
user: 'user',
operation: 'operation',
},
onUserListChange: () => {},
},
};
}
componentDidMount() {
seafileAPI.getFileDownloadLink(repoID, filePath).then(res => {
let url = res.data;
seafileAPI.getFileContent(url).then(res => {
if (res.data) {
this.setState({
isDataLoading: false,
data: res.data
});
} else {
this.setState({
isDataLoading: false,
data: DEFAULT_DATA
});
}
}).catch(() => {
// toaster.success(gettext('file loading error'));
});
});
}
handleSave = (data) => {
let dirPath = Utils.getDirName(filePath);
seafileAPI.getUpdateLink(repoID, dirPath).then(res => {
let updateLink = res.data;
let updateData = JSON.stringify(data);
seafileAPI.updateFile(updateLink, filePath, fileName, updateData).then(res => {
// toaster.success(gettext('File saved.'));
}).catch(() => {
// toaster.success(gettext('File saved failed.'));
});
});
}
class ViewFileUMind extends React.Component {
render() {
return (
<UMind.default locale={this.locale} config={this.config} data={this.state.data} save={this.handleSave} />
<UMind />
);
}
}
ReactDOM.render(<ViewFileUmind />, document.getElementById('root'));
ReactDOM.render(
<ViewFileUMind />,
document.getElementById('wrapper')
);

View File

@ -1,111 +0,0 @@
{% load seahub_tags i18n staticfiles %}
{% load render_bundle from webpack_loader %}
<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE }}">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="keywords" content="{% trans "File Collaboration Team Organization" %}" />
{% block viewport %}
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
{% endblock %}
<title>{% block sub_title %}{% endblock %}{{ site_title }}</title>
<link rel="stylesheet" href="https://g.alicdn.com/code/lib/antd/3.10.7/antd.min.css">
</head>
<body>
<div id="root"></div>
<script src="https://g.alicdn.com/code/lib/react/16.6.1/umd/react.production.min.js"></script>
<script src="https://g.alicdn.com/code/lib/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
<script src="https://g.alicdn.com/code/lib/moment.js/2.22.2/moment.min.js"></script>
<script src="https://g.alicdn.com/code/lib/antd/3.10.7/antd.min.js"></script>
<script src="https://g.alicdn.com/code/lib/socket.io/2.1.1/socket.io.js"></script>
<script src="https://g.alicdn.com/UMind/UMind/1.0.0/bundle.js"></script>
<script type="text/javascript">
// overwrite the one in base_for_react.html
window.app = {
config: {
mediaUrl: '{{ MEDIA_URL }}',
logoPath: '{{ logo_path }}',
logoWidth: '{{ logo_width }}',
logoHeight: '{{ logo_height }}',
siteTitle: '{{ site_title }}',
siteName: '{{ site_name }}',
siteRoot: '{{ SITE_ROOT }}',
loginUrl: '{{ LOGIN_URL }}',
isPro: '{{ is_pro }}',
lang: '{{ LANGUAGE_CODE }}',
fileServerRoot: '{{ FILE_SERVER_ROOT }}',
serviceURL: '{{ service_url }}',
seafileVersion: '{{ seafile_version }}',
},
pageOptions: {
seafileCollabServer: '{{seafile_collab_server}}',
name: "{{request.user.username|email2nickname|escapejs}}",
contactEmail: "{{request.user.username|email2contact_email|escapejs}}",
username: "{{request.user.username|escapejs}}",
canAddRepo: {% if user.permissions.can_add_repo %} true {% else %} false {% endif %},
canGenerateShareLink: {% if user.permissions.can_generate_share_link %} true {% else %} false {% endif %},
canGenerateUploadLink: {% if user.permissions.can_generate_upload_link %} true {% else %} false {% endif %},
canViewOrg:'{{ user.permissions.can_view_org }}',
fileAuditEnabled: '{{ file_audit_enabled }}',
enableFileComment: '{{ enable_file_comment }}',
folderPermEnabled: '{{ folder_perm_enabled }}',
enableResetEncryptedRepoPassword: '{{ enable_reset_encrypted_repo_password }}',
isEmailConfigured: '{{ is_email_configured }}',
enableUploadFolder: '{{ enable_upload_folder }}',
enableResumableFileUpload: '{{ enable_resumable_fileupload }}',
// storage backends
storages: (function () {
// for 'create repo' & 'storage backend' column in 'my libs'
var storages = [];
{% for storage in storages %}
storages.push({
'id': '{{storage.storage_id|escapejs}}',
'name': '{{storage.storage_name|escapejs}}'
});
{% endfor %}
return storages;
})(),
enableRepoSnapshotLabel: {% if enable_repo_snapshot_label %} true {% else %} false {% endif %},
shareLinkExpireDaysMin: "{{ share_link_expire_days_min }}",
shareLinkExpireDaysMax: "{{ share_link_expire_days_max }}",
maxFileName: "{{ max_file_name }}",
enableWiki: {% if user.permissions.can_use_wiki %} true {% else %} false {% endif %},
enableEncryptedLibrary: '{{ enable_encrypted_library }}',
enableRepoHistorySetting: '{{ enable_repo_history_setting }}',
isSystemStaff: {% if request.user.is_staff %} true {% else %} false {% endif %},
thumbnailSizeForOriginal: {{ thumbnail_size_for_original }},
repoPasswordMinLength: {{repo_password_min_length}},
}
};
window.app.pageOptions = {
username: '{{ user.username|escapejs }}',
userNickName: '{{request.user.username|email2nickname|escapejs}}',
// for all types of files
fileName: '{{ filename|escapejs }}',
isStarred: {% if is_starred %}true{% else %}false{% endif %},
isLocked: {% if file_locked %}true{% else %}false{% endif %},
latestContributor: '{{ latest_contributor|escapejs }}',
latestContributorName: '{{ latest_contributor|email2nickname|escapejs }}',
lastModificationTime: '{{ last_modified }}',
repoID: '{{ repo.id }}',
repoName: '{{ repo.name|escapejs }}',
filePath: '{{ path|escapejs }}',
filePerm: '{{ file_perm }}',
parentDir: '{{ parent_dir|escapejs }}',
err: '{{ err }}',
lockedByMe: {% if locked_by_me %}true{% else %}false{% endif %},
canLockUnlockFile: {% if can_lock_unlock_file %}true{% else %}false{% endif %},
canEditFile: {% if can_edit_file %}true{% else %}false{% endif %}, // only for some file types
canDownloadFile: {% if can_download_file %}true{% else %}false{% endif %},
enableComment: {% if enable_file_comment %}true{% else %}false{% endif %},
enableWatermark: {% if enable_watermark %}true{% else %}false{% endif %},
};
</script>
{% block render_bundle %}
{% render_bundle 'viewFileUMind' 'js'%}
{% endblock %}
</body>
</html>

View File

@ -0,0 +1,10 @@
{% extends 'file_view_react.html' %}
{% load render_bundle from webpack_loader %}
{% block extra_style %}
{% render_bundle 'viewFileUMind' 'css' %}
{% endblock %}
{% block render_bundle %}
{% render_bundle 'viewFileUMind' 'js'%}
{% endblock %}

View File

@ -728,7 +728,7 @@ def view_lib_file(request, repo_id, path):
return render(request, template, return_dict)
elif filetype == UMIND:
return render(request, 'umind_file_view_react.html', return_dict)
return render(request, 'view_file_umind.html', return_dict)
elif filetype == IMAGE:
template = '%s_file_view_react.html' % filetype.lower()