diff --git a/frontend/src/css/umind.css b/frontend/src/css/umind.css
new file mode 100644
index 0000000000..f7e0760005
--- /dev/null
+++ b/frontend/src/css/umind.css
@@ -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;
+}
diff --git a/frontend/src/umind/index.js b/frontend/src/umind/index.js
new file mode 100644
index 0000000000..95290a62af
--- /dev/null
+++ b/frontend/src/umind/index.js
@@ -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 (
+
+
+
+
+
+
+
+
+ {this.state.isLoading && }
+ {!this.state.isLoading && (
+
+ )}
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+UMind.propTypes = propTypes;
+
+export default UMind;
diff --git a/frontend/src/umind/theme/iconfont.css b/frontend/src/umind/theme/iconfont.css
new file mode 100644
index 0000000000..65d8f71574
--- /dev/null
+++ b/frontend/src/umind/theme/iconfont.css
@@ -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";
+}
diff --git a/frontend/src/umind/umind-detail-panel/index.js b/frontend/src/umind/umind-detail-panel/index.js
new file mode 100644
index 0000000000..4e2f84c66d
--- /dev/null
+++ b/frontend/src/umind/umind-detail-panel/index.js
@@ -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 (
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default UMindDetails;
diff --git a/frontend/src/umind/umind-detail-panel/node-detail.js b/frontend/src/umind/umind-detail-panel/node-detail.js
new file mode 100644
index 0000000000..19c33f250f
--- /dev/null
+++ b/frontend/src/umind/umind-detail-panel/node-detail.js
@@ -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 (
+
+
+
+ );
+ }
+}
+
+export default Form.create()(withPropsAPI(NodeDetail));
diff --git a/frontend/src/umind/umind-editor/context-menu.css b/frontend/src/umind/umind-editor/context-menu.css
new file mode 100644
index 0000000000..fefaae9c8d
--- /dev/null
+++ b/frontend/src/umind/umind-editor/context-menu.css
@@ -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;
+}
diff --git a/frontend/src/umind/umind-editor/umind-context-menu.js b/frontend/src/umind/umind-editor/umind-context-menu.js
new file mode 100644
index 0000000000..4b841352f6
--- /dev/null
+++ b/frontend/src/umind/umind-editor/umind-context-menu.js
@@ -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 (
+
+
+
+
+
+ 插入同级
+
+
+
+
+
+ 插入子级
+
+
+
+
+
+ 折叠
+
+
+
+
+
+ 展开
+
+
+
+
+
+ 删除
+
+
+
+
+
+
+
+ 撤销
+
+
+
+
+
+ 重做
+
+
+
+
+ );
+ }
+}
+
+export default UMindContextMenu;
diff --git a/frontend/src/umind/umind-editor/umind-editor-minimap.js b/frontend/src/umind/umind-editor/umind-editor-minimap.js
new file mode 100644
index 0000000000..3fd64f5934
--- /dev/null
+++ b/frontend/src/umind/umind-editor/umind-editor-minimap.js
@@ -0,0 +1,15 @@
+import React from 'react';
+import { Card } from 'antd';
+import { Minimap } from 'gg-editor';
+
+class UMindEditorMinimap extends React.Component {
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+
+export default UMindEditorMinimap;
diff --git a/frontend/src/umind/umind-toolbar/toolbar.css b/frontend/src/umind/umind-toolbar/toolbar.css
new file mode 100644
index 0000000000..1a54e43231
--- /dev/null
+++ b/frontend/src/umind/umind-toolbar/toolbar.css
@@ -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;
+}
\ No newline at end of file
diff --git a/frontend/src/umind/umind-toolbar/umind-toolbar.js b/frontend/src/umind/umind-toolbar/umind-toolbar.js
new file mode 100644
index 0000000000..70d4326562
--- /dev/null
+++ b/frontend/src/umind/umind-toolbar/umind-toolbar.js
@@ -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 (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default withGGEditorContext(UMindToolbar);
diff --git a/frontend/src/view-file-umind.js b/frontend/src/view-file-umind.js
index 46602528ff..a1110416c4 100644
--- a/frontend/src/view-file-umind.js
+++ b/frontend/src/view-file-umind.js
@@ -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 (
-
+
);
}
}
-ReactDOM.render(, document.getElementById('root'));
\ No newline at end of file
+ReactDOM.render(
+ ,
+ document.getElementById('wrapper')
+);
\ No newline at end of file
diff --git a/seahub/templates/umind_file_view_react.html b/seahub/templates/umind_file_view_react.html
deleted file mode 100644
index 8aa7cad0d6..0000000000
--- a/seahub/templates/umind_file_view_react.html
+++ /dev/null
@@ -1,111 +0,0 @@
-{% load seahub_tags i18n staticfiles %}
-{% load render_bundle from webpack_loader %}
-
-
-
-
-
-
-
- {% block viewport %}
-
- {% endblock %}
- {% block sub_title %}{% endblock %}{{ site_title }}
-
-
-
-
-
-
-
-
-
-
-
- {% block render_bundle %}
- {% render_bundle 'viewFileUMind' 'js'%}
- {% endblock %}
-
-
diff --git a/seahub/templates/view_file_umind.html b/seahub/templates/view_file_umind.html
new file mode 100644
index 0000000000..805308c1e1
--- /dev/null
+++ b/seahub/templates/view_file_umind.html
@@ -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 %}
diff --git a/seahub/views/file.py b/seahub/views/file.py
index 3a42101174..9557f7dd52 100644
--- a/seahub/views/file.py
+++ b/seahub/views/file.py
@@ -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()