mirror of
https://github.com/haiwen/seahub.git
synced 2025-04-27 11:01:14 +00:00
Add excl draw module 2 (#7658)
* init exceldraw module * excalidraw demo * i18n fixed bug * exceldraw change to excalidraw * lang setting --------- Co-authored-by: 杨顺强 <978987373@qq.com> Co-authored-by: First <first@FirstdeMacBook-Pro.local>
This commit is contained in:
parent
ef9be3fed1
commit
ff7fd0f0d5
@ -627,6 +627,12 @@ module.exports = function (webpackEnv) {
|
||||
// Make sure to add the new loader(s) before the "file" loader.
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.m?js$/,
|
||||
resolve: {
|
||||
fullySpecified: false
|
||||
}
|
||||
}
|
||||
].filter(Boolean),
|
||||
},
|
||||
plugins: [
|
||||
|
@ -2,6 +2,7 @@ const paths = require('./paths');
|
||||
|
||||
const entryFiles = {
|
||||
tldrawEditor: '/tldrawEditor.js',
|
||||
excalidrawEditor: '/excalidraw-editor.js',
|
||||
markdownEditor: '/index.js',
|
||||
plainMarkdownEditor: '/pages/plain-markdown-editor/index.js',
|
||||
TCAccept: '/tc-accept.js',
|
||||
|
1294
frontend/package-lock.json
generated
1294
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,7 @@
|
||||
"@codemirror/view": "^6.34.1",
|
||||
"@emoji-mart/data": "^1.2.1",
|
||||
"@emoji-mart/react": "^1.1.1",
|
||||
"@excalidraw/excalidraw": "^0.18.0",
|
||||
"@gatsbyjs/reach-router": "2.0.1",
|
||||
"@seafile/react-image-lightbox": "4.0.2",
|
||||
"@seafile/resumablejs": "1.1.16",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { siteRoot, username, enableSeadoc, thumbnailDefaultSize, thumbnailSizeForOriginal, gettext, fileServerRoot, enableWhiteboard, useGoFileserver } from '../../utils/constants';
|
||||
import { siteRoot, username, enableSeadoc, thumbnailDefaultSize, thumbnailSizeForOriginal, gettext, fileServerRoot, enableWhiteboard, useGoFileserver, enableExcalidraw } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import URLDecorator from '../../utils/url-decorator';
|
||||
@ -412,6 +412,9 @@ class DirentGridView extends React.Component {
|
||||
case 'New Whiteboard File':
|
||||
this.onCreateFileToggle('.draw');
|
||||
break;
|
||||
case 'New Excalidraw File':
|
||||
this.onCreateFileToggle('.exdraw');
|
||||
break;
|
||||
case 'New SeaDoc File':
|
||||
this.onCreateFileToggle('.sdoc');
|
||||
break;
|
||||
@ -734,13 +737,15 @@ class DirentGridView extends React.Component {
|
||||
if (!['admin', 'rw'].includes(this.props.userPerm)) return;
|
||||
|
||||
const {
|
||||
NEW_FOLDER, NEW_FILE,
|
||||
NEW_FOLDER,
|
||||
NEW_FILE,
|
||||
NEW_MARKDOWN_FILE,
|
||||
NEW_EXCEL_FILE,
|
||||
NEW_POWERPOINT_FILE,
|
||||
NEW_WORD_FILE,
|
||||
NEW_SEADOC_FILE,
|
||||
NEW_TLDRAW_FILE
|
||||
NEW_TLDRAW_FILE,
|
||||
NEW_EXCALIDRAW_FILE
|
||||
} = TextTranslation;
|
||||
|
||||
let direntsContainerMenuList = [
|
||||
@ -763,6 +768,10 @@ class DirentGridView extends React.Component {
|
||||
direntsContainerMenuList.push(NEW_TLDRAW_FILE);
|
||||
}
|
||||
|
||||
if (enableExcalidraw) {
|
||||
direntsContainerMenuList.push(NEW_EXCALIDRAW_FILE);
|
||||
}
|
||||
|
||||
if (selectedDirentList.length === 0) {
|
||||
if (!hasCustomPermission('create')) return;
|
||||
this.handleContextClick(event, DIRENT_GRID_CONTAINER_MENU_ID, direntsContainerMenuList);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { siteRoot, gettext, username, enableSeadoc, thumbnailSizeForOriginal, thumbnailDefaultSize, fileServerRoot, enableWhiteboard, useGoFileserver } from '../../utils/constants';
|
||||
import { siteRoot, gettext, username, enableSeadoc, thumbnailSizeForOriginal, thumbnailDefaultSize, fileServerRoot, enableWhiteboard, useGoFileserver, enableExcalidraw } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import TextTranslation from '../../utils/text-translation';
|
||||
import URLDecorator from '../../utils/url-decorator';
|
||||
@ -431,7 +431,8 @@ class DirentListView extends React.Component {
|
||||
NEW_POWERPOINT_FILE,
|
||||
NEW_WORD_FILE,
|
||||
NEW_SEADOC_FILE,
|
||||
NEW_TLDRAW_FILE
|
||||
NEW_TLDRAW_FILE,
|
||||
NEW_EXCALIDRAW_FILE,
|
||||
} = TextTranslation;
|
||||
|
||||
const direntsContainerMenuList = [
|
||||
@ -452,6 +453,10 @@ class DirentListView extends React.Component {
|
||||
direntsContainerMenuList.push(NEW_TLDRAW_FILE);
|
||||
}
|
||||
|
||||
if (enableExcalidraw) {
|
||||
direntsContainerMenuList.push(NEW_EXCALIDRAW_FILE);
|
||||
}
|
||||
|
||||
if (this.props.selectedDirentList.length === 0) {
|
||||
let id = 'dirent-container-menu';
|
||||
|
||||
@ -529,6 +534,9 @@ class DirentListView extends React.Component {
|
||||
case 'New Whiteboard File':
|
||||
this.onCreateFileToggle('.draw');
|
||||
break;
|
||||
case 'New Excalidraw File':
|
||||
this.onCreateFileToggle('.exdraw');
|
||||
break;
|
||||
case 'New SeaDoc File':
|
||||
this.onCreateFileToggle('.sdoc');
|
||||
break;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { enableSeadoc, gettext, enableWhiteboard } from '../../utils/constants';
|
||||
import { enableSeadoc, gettext, enableWhiteboard, enableExcalidraw } from '../../utils/constants';
|
||||
import Loading from '../loading';
|
||||
import ModalPortal from '../modal-portal';
|
||||
import CreateFile from '../../components/dialog/create-file-dialog';
|
||||
@ -74,7 +74,8 @@ class DirentNoneView extends React.Component {
|
||||
NEW_POWERPOINT_FILE,
|
||||
NEW_WORD_FILE,
|
||||
NEW_SEADOC_FILE,
|
||||
NEW_TLDRAW_FILE
|
||||
NEW_TLDRAW_FILE,
|
||||
NEW_EXCALIDRAW_FILE
|
||||
} = TextTranslation;
|
||||
const direntsContainerMenuList = [
|
||||
NEW_FOLDER, NEW_FILE, 'Divider',
|
||||
@ -92,6 +93,9 @@ class DirentNoneView extends React.Component {
|
||||
if (enableWhiteboard) {
|
||||
direntsContainerMenuList.push(NEW_TLDRAW_FILE);
|
||||
}
|
||||
if (enableExcalidraw) {
|
||||
direntsContainerMenuList.push(NEW_EXCALIDRAW_FILE);
|
||||
}
|
||||
let id = 'dirent-container-menu';
|
||||
if (isCustomPermission) {
|
||||
const { create: canCreate } = customPermission.permission;
|
||||
|
@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { enableSeadoc, enableWhiteboard, gettext } from '../../utils/constants';
|
||||
import { enableExcalidraw, enableSeadoc, enableWhiteboard, gettext } from '../../utils/constants';
|
||||
import ModalPortal from '../modal-portal';
|
||||
import CreateFolder from '../../components/dialog/create-folder-dialog';
|
||||
import CreateFile from '../../components/dialog/create-file-dialog';
|
||||
@ -115,6 +115,13 @@ class DirOperationToolbar extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
onCreateExcalidrawToggle = () => {
|
||||
this.setState({
|
||||
isCreateFileDialogShow: !this.state.isCreateFileDialogShow,
|
||||
fileType: '.exdraw'
|
||||
});
|
||||
};
|
||||
|
||||
onCreateSeaDocToggle = () => {
|
||||
this.setState({
|
||||
isCreateFileDialogShow: !this.state.isCreateFileDialogShow,
|
||||
@ -266,6 +273,9 @@ class DirOperationToolbar extends React.Component {
|
||||
if (enableWhiteboard) {
|
||||
newSubOpList.push({ 'text': gettext('New Whiteboard File'), 'onClick': this.onCreateTldrawToggle });
|
||||
}
|
||||
if (enableExcalidraw) {
|
||||
newSubOpList.push({ 'text': gettext('New Excalidraw File'), 'onClick': this.onCreateExcalidrawToggle });
|
||||
}
|
||||
opList.push({
|
||||
'icon': 'new',
|
||||
'text': gettext('New'),
|
||||
|
11
frontend/src/excalidraw-editor.js
Normal file
11
frontend/src/excalidraw-editor.js
Normal file
@ -0,0 +1,11 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import Loading from './components/loading';
|
||||
import ExcaliEditor from './pages/excalidraw-editor';
|
||||
|
||||
const root = createRoot(document.getElementById('wrapper'));
|
||||
root.render(
|
||||
<Suspense fallback={<Loading />}>
|
||||
<ExcaliEditor />
|
||||
</Suspense>
|
||||
);
|
15
frontend/src/pages/excalidraw-editor/constants.js
Normal file
15
frontend/src/pages/excalidraw-editor/constants.js
Normal file
@ -0,0 +1,15 @@
|
||||
export const SAVE_INTERVAL_TIME = 3 * 60 * 1000;
|
||||
|
||||
export const langList = {
|
||||
'zh-cn': 'zh-CN',
|
||||
'en': 'en',
|
||||
'zh-tw': 'zh-TW',
|
||||
'ru': 'ru-RU',
|
||||
'it': 'it-IT',
|
||||
'fr': 'fr-FR',
|
||||
'es-ms': 'en',
|
||||
'es-ar': 'en',
|
||||
'es': 'es-ES',
|
||||
'de': 'de-DE',
|
||||
'cs': 'cs-CZ',
|
||||
};
|
26
frontend/src/pages/excalidraw-editor/editor-api.js
Normal file
26
frontend/src/pages/excalidraw-editor/editor-api.js
Normal file
@ -0,0 +1,26 @@
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
|
||||
const { repoID, filePath, fileName } = window.app.pageOptions;
|
||||
let dirPath = Utils.getDirName(filePath);
|
||||
|
||||
class EditorApi {
|
||||
|
||||
saveContent(content) {
|
||||
return seafileAPI.getUpdateLink(repoID, dirPath).then((res) => {
|
||||
const uploadLink = res.data;
|
||||
return seafileAPI.updateFile(uploadLink, filePath, fileName, content);
|
||||
});
|
||||
}
|
||||
|
||||
getFileContent = () => {
|
||||
return seafileAPI.getFileDownloadLink(repoID, filePath).then(res => {
|
||||
const downLoadUrl = res.data;
|
||||
return seafileAPI.getFileContent(downLoadUrl);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const editorApi = new EditorApi();
|
||||
|
||||
export default editorApi;
|
8
frontend/src/pages/excalidraw-editor/index.css
Normal file
8
frontend/src/pages/excalidraw-editor/index.css
Normal file
@ -0,0 +1,8 @@
|
||||
.dropdown-menu {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.excalidraw .dropdown-menu {
|
||||
--bs-dropdown-padding-x: auto;
|
||||
border: unset;
|
||||
}
|
86
frontend/src/pages/excalidraw-editor/index.js
Normal file
86
frontend/src/pages/excalidraw-editor/index.js
Normal file
@ -0,0 +1,86 @@
|
||||
import React, { useCallback, useState, useEffect, useRef } from 'react';
|
||||
import SimpleEditor from './simple-editor';
|
||||
import editorApi from './editor-api';
|
||||
import isHotkey from 'is-hotkey';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import toaster from '../../components/toast';
|
||||
import { SAVE_INTERVAL_TIME } from './constants';
|
||||
|
||||
import './index.css';
|
||||
|
||||
const ExcaliEditor = () => {
|
||||
const [fileContent, setFileContent] = useState(null);
|
||||
const editorRef = useRef(null);
|
||||
const isChangedRef = useRef(false);
|
||||
const [isFetching, setIsFetching] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
editorApi.getFileContent().then(res => {
|
||||
if (res.data?.appState?.collaborators && !Array.isArray(res.data.appState.collaborators)) {
|
||||
// collaborators.forEach is not a function
|
||||
res.data['appState']['collaborators'] = [];
|
||||
}
|
||||
setFileContent(res.data);
|
||||
setIsFetching(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const saveSceneContent = useCallback(async () => {
|
||||
if (isChangedRef.current) {
|
||||
try {
|
||||
await editorApi.saveContent(JSON.stringify(editorRef.current));
|
||||
isChangedRef.current = false;
|
||||
toaster.success(gettext('Successfully saved'), { duration: 2 });
|
||||
} catch {
|
||||
toaster.danger(gettext('Failed to save'), { duration: 2 });
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handleHotkeySave = (event) => {
|
||||
if (isHotkey('mod+s', event)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', handleHotkeySave, true);
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleHotkeySave, true);
|
||||
};
|
||||
}, [saveSceneContent]);
|
||||
|
||||
useEffect(() => {
|
||||
const saveInterval = setInterval(() => {
|
||||
if (isChangedRef.current) {
|
||||
editorApi.saveContent(JSON.stringify(editorRef.current)).then(res => {
|
||||
isChangedRef.current = false;
|
||||
});
|
||||
}
|
||||
}, SAVE_INTERVAL_TIME);
|
||||
|
||||
return () => {
|
||||
clearInterval(saveInterval);
|
||||
};
|
||||
}, [saveSceneContent]);
|
||||
|
||||
const onSaveContent = useCallback(() => {
|
||||
saveSceneContent();
|
||||
}, [saveSceneContent]);
|
||||
|
||||
const onChangeContent = useCallback((elements) => {
|
||||
editorRef.current = { elements };
|
||||
isChangedRef.current = true;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<SimpleEditor
|
||||
isFetching={isFetching}
|
||||
sceneContent={fileContent}
|
||||
onSaveContent={onSaveContent}
|
||||
onChangeContent={onChangeContent}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExcaliEditor;
|
75
frontend/src/pages/excalidraw-editor/simple-editor.js
Normal file
75
frontend/src/pages/excalidraw-editor/simple-editor.js
Normal file
@ -0,0 +1,75 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Excalidraw, MainMenu } from '@excalidraw/excalidraw';
|
||||
import isHotkey from 'is-hotkey';
|
||||
import CodeMirrorLoading from '../../components/code-mirror-loading';
|
||||
import { langList } from './constants';
|
||||
|
||||
import '@excalidraw/excalidraw/index.css';
|
||||
|
||||
const SimpleEditor = ({
|
||||
sceneContent = null,
|
||||
onChangeContent,
|
||||
onSaveContent,
|
||||
isFetching
|
||||
}) => {
|
||||
const [excalidrawAPI, setExcalidrawAPI] = useState(null);
|
||||
const UIOptions = {
|
||||
canvasActions: {
|
||||
saveToActiveFile: false,
|
||||
LoadScene: false
|
||||
},
|
||||
tools: { image: false },
|
||||
};
|
||||
|
||||
const handleChange = () => {
|
||||
const elements = excalidrawAPI.getSceneElements();
|
||||
onChangeContent(elements);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleHotkeySave = (event) => {
|
||||
if (isHotkey('mod+s', event)) {
|
||||
event.preventDefault();
|
||||
onSaveContent(excalidrawAPI.getSceneElements());
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', handleHotkeySave, true);
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleHotkeySave, true);
|
||||
};
|
||||
}, [excalidrawAPI, onSaveContent]);
|
||||
|
||||
if (isFetching) {
|
||||
return (
|
||||
<div className='excali-container'>
|
||||
<CodeMirrorLoading />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='excali-container' style={{ height: '100vh', width: '100vw' }}>
|
||||
<Excalidraw
|
||||
initialData={sceneContent}
|
||||
excalidrawAPI={(api) => setExcalidrawAPI(api)}
|
||||
onChange={handleChange}
|
||||
UIOptions={UIOptions}
|
||||
langCode={langList[window.app.config.lang] || 'en'}
|
||||
>
|
||||
<MainMenu>
|
||||
<MainMenu.DefaultItems.Export />
|
||||
<MainMenu.DefaultItems.SaveAsImage />
|
||||
<MainMenu.DefaultItems.Help />
|
||||
<MainMenu.DefaultItems.ClearCanvas />
|
||||
<MainMenu.DefaultItems.ToggleTheme />
|
||||
<MainMenu.DefaultItems.ChangeCanvasBackground />
|
||||
</MainMenu>
|
||||
</Excalidraw>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SimpleEditor;
|
@ -99,6 +99,7 @@ export const enableSSOToThirdpartWebsite = window.app.pageOptions.enableSSOToThi
|
||||
export const enableSeadoc = window.app.pageOptions.enableSeadoc;
|
||||
export const enableSeafileAI = window.app.pageOptions.enableSeafileAI;
|
||||
export const enableWhiteboard = window.app.pageOptions.enableWhiteboard;
|
||||
export const enableExcalidraw = window.app.pageOptions.enableExcalidraw;
|
||||
export const enableMultipleOfficeSuite = window.app.pageOptions.enableMultipleOfficeSuite;
|
||||
|
||||
export const curNoteMsg = window.app.pageOptions.curNoteMsg;
|
||||
|
@ -31,6 +31,10 @@ const TextTranslation = {
|
||||
key: 'New Whiteboard File',
|
||||
value: gettext('New Whiteboard File')
|
||||
},
|
||||
NEW_EXCALIDRAW_FILE: {
|
||||
key: 'New Excalidraw File',
|
||||
value: gettext('New Excalidraw File')
|
||||
},
|
||||
NEW_SEADOC_FILE: {
|
||||
key: 'New SeaDoc File',
|
||||
value: gettext('New SeaDoc File')
|
||||
|
@ -25,7 +25,7 @@ from seahub.settings import SEAFILE_VERSION, SITE_DESCRIPTION, \
|
||||
LOGIN_BG_IMAGE_PATH, THUMBNAIL_DEFAULT_SIZE, \
|
||||
CUSTOM_LOGIN_BG_PATH, ENABLE_SHARE_LINK_REPORT_ABUSE, \
|
||||
PRIVACY_POLICY_LINK, TERMS_OF_SERVICE_LINK, ENABLE_SEADOC, THUMBNAIL_SIZE_FOR_GRID, \
|
||||
FILE_SERVER_ROOT, ENABLE_WHITEBOARD, ENABLE_SEAFILE_AI
|
||||
FILE_SERVER_ROOT, ENABLE_WHITEBOARD, ENABLE_SEAFILE_AI, ENABLE_EXCALIDRAW
|
||||
|
||||
from seahub.organizations.models import OrgAdminSettings
|
||||
from seahub.organizations.settings import ORG_ENABLE_ADMIN_CUSTOM_LOGO
|
||||
@ -181,6 +181,7 @@ def base(request):
|
||||
'enable_seadoc': ENABLE_SEADOC,
|
||||
'enable_seafile_ai': ENABLE_SEAFILE_AI,
|
||||
'enable_whiteboard': ENABLE_WHITEBOARD,
|
||||
'enable_excalidraw': ENABLE_EXCALIDRAW,
|
||||
}
|
||||
|
||||
if request.user.is_staff:
|
||||
|
@ -961,6 +961,12 @@ FILE_CONVERTER_SERVER_URL = 'http://127.0.0.1:8888'
|
||||
|
||||
ENABLE_WHITEBOARD = False
|
||||
|
||||
##########################
|
||||
# Settings for excalidraw #
|
||||
##########################
|
||||
|
||||
ENABLE_EXCALIDRAW = False
|
||||
|
||||
############################
|
||||
# Settings for Seahub Priv #
|
||||
############################
|
||||
|
@ -159,6 +159,7 @@
|
||||
officeWebAppEditFileExtension: {% if office_web_app_edit_file_extension %} {{office_web_app_edit_file_extension|safe}} {% else %} [] {% endif %},
|
||||
enableSeadoc: {% if enable_seadoc %} true {% else %} false {% endif %},
|
||||
enableWhiteboard: {% if enable_whiteboard %} true {% else %} false {% endif %},
|
||||
enableExcalidraw: {% if enable_excalidraw %} true {% else %} false {% endif %},
|
||||
isOrgContext: {% if org is not None %} true {% else %} false {% endif %},
|
||||
enableMetadataManagement: {% if enable_metadata_management %} true {% else %} false {% endif %},
|
||||
isMultiTenacy: {% if multi_tenancy %} true {% else %} false {% endif %},
|
||||
|
19
seahub/templates/excalidraw_file_view_react.html
Normal file
19
seahub/templates/excalidraw_file_view_react.html
Normal file
@ -0,0 +1,19 @@
|
||||
{% extends 'file_view_react.html' %}
|
||||
{% load render_bundle from webpack_loader %}
|
||||
|
||||
|
||||
{% block extra_style %}
|
||||
{% render_bundle 'excalidrawEditor' 'css' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_data %}
|
||||
docPath: '{{ path|escapejs }}',
|
||||
docName: '{{ filename|escapejs }}',
|
||||
docUuid: '{{ file_uuid }}',
|
||||
lang: '{{ lang }}',
|
||||
rawPath: '{{ raw_path|escapejs }}',
|
||||
{% endblock %}
|
||||
|
||||
{% block render_bundle %}
|
||||
{% render_bundle 'excalidrawEditor' 'js' %}
|
||||
{% endblock %}
|
@ -144,6 +144,7 @@ PREVIEW_FILEEXT = {
|
||||
XMIND: ('xmind',),
|
||||
SEADOC: ('sdoc',),
|
||||
TLDRAW: ('draw',),
|
||||
EXCALIDRAW: ('exdraw',),
|
||||
}
|
||||
|
||||
def get_non_sdoc_file_exts():
|
||||
|
@ -11,6 +11,7 @@ SPREADSHEET = 'SpreadSheet'
|
||||
XMIND = 'XMind'
|
||||
SEADOC = 'SDoc'
|
||||
TLDRAW = 'Tldraw'
|
||||
EXCALIDRAW = 'Excalidraw'
|
||||
|
||||
|
||||
MARKDOWN_SUPPORT_CONVERT_TYPES = ['sdoc']
|
||||
|
@ -61,7 +61,7 @@ from seahub.utils import render_error, is_org_context, \
|
||||
from seahub.utils.ip import get_remote_ip
|
||||
from seahub.utils.file_types import (IMAGE, PDF, SVG,
|
||||
DOCUMENT, SPREADSHEET, AUDIO,
|
||||
MARKDOWN, TEXT, VIDEO, XMIND, SEADOC, TLDRAW)
|
||||
MARKDOWN, TEXT, VIDEO, XMIND, SEADOC, TLDRAW, EXCALIDRAW)
|
||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr
|
||||
from seahub.utils.star import is_file_starred
|
||||
from seahub.utils.http import json_response, \
|
||||
@ -850,6 +850,27 @@ def view_lib_file(request, repo_id, path):
|
||||
return_dict['raw_path'] = raw_path
|
||||
|
||||
|
||||
can_edit_file = True
|
||||
if parse_repo_perm(permission).can_edit_on_web is False:
|
||||
can_edit_file = False
|
||||
elif is_locked and not locked_by_me:
|
||||
can_edit_file = False
|
||||
return_dict['can_edit_file'] = can_edit_file
|
||||
|
||||
return render(request, template, return_dict)
|
||||
|
||||
if filetype == EXCALIDRAW:
|
||||
|
||||
return_dict['protocol'] = request.is_secure() and 'https' or 'http'
|
||||
return_dict['domain'] = get_current_site(request).domain
|
||||
return_dict['serviceUrl'] = get_service_url().rstrip('/')
|
||||
return_dict['language_code'] = get_language()
|
||||
return_dict['share_link_expire_days_Default'] = SHARE_LINK_EXPIRE_DAYS_DEFAULT
|
||||
return_dict['share_link_expire_days_min'] = SHARE_LINK_EXPIRE_DAYS_MIN
|
||||
return_dict['share_link_expire_days_max'] = SHARE_LINK_EXPIRE_DAYS_MAX
|
||||
return_dict['raw_path'] = raw_path
|
||||
|
||||
|
||||
can_edit_file = True
|
||||
if parse_repo_perm(permission).can_edit_on_web is False:
|
||||
can_edit_file = False
|
||||
|
Loading…
Reference in New Issue
Block a user