mirror of
https://github.com/haiwen/seahub.git
synced 2025-07-31 22:57:47 +00:00
convert markdown and sdoc (#5636)
This commit is contained in:
parent
34a7318725
commit
e7d32fd4d6
@ -57,6 +57,7 @@ const propTypes = {
|
||||
onItemRename: PropTypes.func.isRequired,
|
||||
onItemMove: PropTypes.func.isRequired,
|
||||
onItemCopy: PropTypes.func.isRequired,
|
||||
onItemConvert: PropTypes.func.isRequired,
|
||||
onDirentClick: PropTypes.func.isRequired,
|
||||
isAllItemSelected: PropTypes.bool.isRequired,
|
||||
onAllItemSelected: PropTypes.func.isRequired,
|
||||
@ -217,6 +218,7 @@ class DirColumnView extends React.Component {
|
||||
onItemRename={this.props.onItemRename}
|
||||
onItemMove={this.props.onItemMove}
|
||||
onItemCopy={this.props.onItemCopy}
|
||||
onItemConvert={this.props.onItemConvert}
|
||||
onDirentClick={this.props.onDirentClick}
|
||||
updateDirent={this.props.updateDirent}
|
||||
isAllItemSelected={this.props.isAllItemSelected}
|
||||
|
@ -19,6 +19,7 @@ const propTypes = {
|
||||
onItemDelete: PropTypes.func.isRequired,
|
||||
onItemMove: PropTypes.func.isRequired,
|
||||
onItemCopy: PropTypes.func.isRequired,
|
||||
onItemConvert: PropTypes.func.isRequired,
|
||||
onRenameNode: PropTypes.func.isRequired,
|
||||
isGroupOwnedRepo: PropTypes.bool.isRequired,
|
||||
userPerm: PropTypes.string,
|
||||
@ -73,6 +74,7 @@ class DirGridView extends React.Component {
|
||||
onItemDelete={this.props.onItemDelete}
|
||||
onItemMove={this.props.onItemMove}
|
||||
onItemCopy={this.props.onItemCopy}
|
||||
onItemConvert={this.props.onItemConvert}
|
||||
isDirentListLoading={this.props.isDirentListLoading}
|
||||
updateDirent={this.props.updateDirent}
|
||||
onRenameNode={this.props.onRenameNode}
|
||||
|
@ -36,6 +36,7 @@ const propTypes = {
|
||||
selectedDirentList: PropTypes.array.isRequired,
|
||||
onItemsMove: PropTypes.func.isRequired,
|
||||
onItemsCopy: PropTypes.func.isRequired,
|
||||
onItemConvert: PropTypes.func.isRequired,
|
||||
onItemsDelete: PropTypes.func.isRequired,
|
||||
onFileTagChanged: PropTypes.func,
|
||||
showDirentDetail: PropTypes.func.isRequired,
|
||||
@ -96,6 +97,7 @@ class DirListView extends React.Component {
|
||||
selectedDirentList={this.props.selectedDirentList}
|
||||
onItemsMove={this.props.onItemsMove}
|
||||
onItemsCopy={this.props.onItemsCopy}
|
||||
onItemConvert={this.props.onItemConvert}
|
||||
onItemsDelete={this.props.onItemsDelete}
|
||||
onAddFile={this.props.onAddFile}
|
||||
onAddFolder={this.props.onAddFolder}
|
||||
|
@ -33,6 +33,7 @@ const propTypes = {
|
||||
onAddFile: PropTypes.func,
|
||||
onItemDelete: PropTypes.func,
|
||||
onItemCopy: PropTypes.func.isRequired,
|
||||
onItemConvert: PropTypes.func.isRequired,
|
||||
onItemMove: PropTypes.func.isRequired,
|
||||
onRenameNode: PropTypes.func.isRequired,
|
||||
onItemClick: PropTypes.func.isRequired,
|
||||
@ -115,6 +116,11 @@ class DirentGridView extends React.Component {
|
||||
this.props.onItemDelete(currentObject);
|
||||
};
|
||||
|
||||
onItemConvert = (currentObject, e, dstType) => {
|
||||
e.nativeEvent.stopImmediatePropagation(); //for document event
|
||||
this.props.onItemConvert(currentObject, dstType);
|
||||
}
|
||||
|
||||
onMenuItemClick = (operation, currentObject, event) => {
|
||||
hideMenu();
|
||||
switch(operation) {
|
||||
@ -136,6 +142,12 @@ class DirentGridView extends React.Component {
|
||||
case 'Copy':
|
||||
this.onItemCopyToggle();
|
||||
break;
|
||||
case 'Convert to Markdown':
|
||||
this.onItemConvert(currentObject, event, 'markdown');
|
||||
break;
|
||||
case 'Convert to sdoc':
|
||||
this.onItemConvert(currentObject, event, 'sdoc');
|
||||
break;
|
||||
case 'Tags':
|
||||
this.onEditFileTagToggle();
|
||||
break;
|
||||
|
@ -35,6 +35,7 @@ const propTypes = {
|
||||
onItemRename: PropTypes.func.isRequired,
|
||||
onItemMove: PropTypes.func.isRequired,
|
||||
onItemCopy: PropTypes.func.isRequired,
|
||||
onItemConvert: PropTypes.func.isRequired,
|
||||
onDirentClick: PropTypes.func.isRequired,
|
||||
updateDirent: PropTypes.func.isRequired,
|
||||
showImagePopup: PropTypes.func.isRequired,
|
||||
@ -268,6 +269,12 @@ class DirentListItem extends React.Component {
|
||||
case 'Lock':
|
||||
this.onLockItem();
|
||||
break;
|
||||
case 'Convert to Markdown':
|
||||
this.onItemConvert(event, 'markdown');
|
||||
break;
|
||||
case 'Convert to sdoc':
|
||||
this.onItemConvert(event, 'sdoc');
|
||||
break;
|
||||
case 'Mark as draft':
|
||||
this.onMarkAsDraft();
|
||||
break;
|
||||
@ -299,6 +306,12 @@ class DirentListItem extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
onItemConvert = (e, dstType)=> {
|
||||
e.preventDefault();
|
||||
e.nativeEvent.stopImmediatePropagation(); //for document event
|
||||
this.props.onItemConvert(this.props.dirent, dstType);
|
||||
}
|
||||
|
||||
onEditFileTagToggle = () => {
|
||||
this.setState({
|
||||
isEditFileTagShow: !this.state.isEditFileTagShow
|
||||
|
@ -42,6 +42,7 @@ const propTypes = {
|
||||
selectedDirentList: PropTypes.array.isRequired,
|
||||
onItemsMove: PropTypes.func.isRequired,
|
||||
onItemsCopy: PropTypes.func.isRequired,
|
||||
onItemConvert: PropTypes.func.isRequired,
|
||||
onItemsDelete: PropTypes.func.isRequired,
|
||||
onFileTagChanged: PropTypes.func,
|
||||
enableDirPrivateShare: PropTypes.bool.isRequired,
|
||||
@ -620,6 +621,7 @@ class DirentListView extends React.Component {
|
||||
onItemRename={this.onItemRename}
|
||||
onItemMove={this.props.onItemMove}
|
||||
onItemCopy={this.props.onItemCopy}
|
||||
onItemConvert={this.props.onItemConvert}
|
||||
updateDirent={this.props.updateDirent}
|
||||
isItemFreezed={this.state.isItemFreezed}
|
||||
freezeItem={this.freezeItem}
|
||||
|
@ -69,6 +69,7 @@ const propTypes = {
|
||||
onItemCopy: PropTypes.func.isRequired,
|
||||
onAddFolder: PropTypes.func.isRequired,
|
||||
onAddFile: PropTypes.func.isRequired,
|
||||
onItemConvert: PropTypes.func.isRequired,
|
||||
onFileTagChanged: PropTypes.func.isRequired,
|
||||
isDirentSelected: PropTypes.bool.isRequired,
|
||||
isAllDirentSelected: PropTypes.bool.isRequired,
|
||||
@ -229,6 +230,7 @@ class LibContentContainer extends React.Component {
|
||||
onItemRename={this.props.onItemRename}
|
||||
onItemMove={this.onItemMove}
|
||||
onItemCopy={this.props.onItemCopy}
|
||||
onItemConvert={this.props.onItemConvert}
|
||||
onDirentClick={this.onDirentClick}
|
||||
updateDirent={this.props.updateDirent}
|
||||
isAllItemSelected={this.props.isAllDirentSelected}
|
||||
@ -264,6 +266,7 @@ class LibContentContainer extends React.Component {
|
||||
onItemDelete={this.props.onItemDelete}
|
||||
onItemMove={this.onItemMove}
|
||||
onItemCopy={this.props.onItemCopy}
|
||||
onItemConvert={this.props.onItemConvert}
|
||||
updateDirent={this.props.updateDirent}
|
||||
onAddFolder={this.props.onAddFolder}
|
||||
showDirentDetail={this.props.showDirentDetail}
|
||||
@ -322,6 +325,7 @@ class LibContentContainer extends React.Component {
|
||||
onItemRename={this.props.onItemRename}
|
||||
onItemMove={this.onItemMove}
|
||||
onItemCopy={this.props.onItemCopy}
|
||||
onItemConvert={this.props.onItemConvert}
|
||||
onDirentClick={this.onDirentClick}
|
||||
updateDirent={this.props.updateDirent}
|
||||
isAllItemSelected={this.props.isAllDirentSelected}
|
||||
|
@ -1236,6 +1236,32 @@ class LibContentView extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
onConvertItem = (dirent, dstType) => {
|
||||
let path = Utils.joinPath(this.state.path, dirent.name);
|
||||
let repoID = this.props.repoID;
|
||||
seafileAPI.convertFile(repoID, path, dstType).then((res) => {
|
||||
let objName = res.data.obj_name;
|
||||
let parentDir = res.data.parent_dir;
|
||||
let file_size = res.data.size;
|
||||
path = parentDir + '/' + objName;
|
||||
let name = Utils.getFileName(path);
|
||||
let parentPath = Utils.getDirName(path);
|
||||
|
||||
if (this.state.currentMode === 'column') {
|
||||
this.updateMoveCopyTreeNode(parentPath);
|
||||
}
|
||||
this.loadDirentList(this.state.path);
|
||||
|
||||
}).catch((error) => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
if (errMessage === gettext('Error')) {
|
||||
let name = Utils.getFileName(path);
|
||||
errMessage = gettext('Renaming {name} failed').replace('{name}', name);
|
||||
}
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
onDirentClick = (dirent) => {
|
||||
let direntList = this.state.direntList.map(dirent => {
|
||||
dirent.isSelected = false;
|
||||
@ -2025,6 +2051,7 @@ class LibContentView extends React.Component {
|
||||
onItemRename={this.onMainPanelItemRename}
|
||||
onItemMove={this.onMoveItem}
|
||||
onItemCopy={this.onCopyItem}
|
||||
onItemConvert={this.onConvertItem}
|
||||
onAddFolder={this.onAddFolder}
|
||||
onAddFile={this.onAddFile}
|
||||
onFileTagChanged={this.onFileTagChanged}
|
||||
|
@ -16,6 +16,8 @@ const TextTranslation = {
|
||||
'OPEN_VIA_CLIENT' : {key : 'Open via Client', value : gettext('Open via Client')},
|
||||
'LOCK' : {key : 'Lock', value : gettext('Lock')},
|
||||
'UNLOCK' : {key : 'Unlock', value : gettext('Unlock')},
|
||||
'CONVERT_TO_MARKDOWN' : {key : 'Convert to Markdown', value : gettext('Convert to Markdown')},
|
||||
'CONVERT_TO_SDOC' : {key : 'Convert to sdoc', value : gettext('Convert to sdoc')},
|
||||
'MARK_AS_DRAFT' : {key : 'Mark as draft', value : gettext('Mark as draft')},
|
||||
'UNMARK_AS_DRAFT' : {key : 'Unmark as draft', value : gettext('Unmark as draft')},
|
||||
'COMMENT' : {key : 'Comment', value : gettext('Comment')},
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { mediaUrl, gettext, serviceURL, siteRoot, isPro, fileAuditEnabled, canGenerateShareLink, canGenerateUploadLink, shareLinkPasswordMinLength, username, folderPermEnabled, onlyofficeConverterExtensions, enableOnlyoffice } from './constants';
|
||||
import { mediaUrl, gettext, serviceURL, siteRoot, isPro, fileAuditEnabled, canGenerateShareLink, canGenerateUploadLink, shareLinkPasswordMinLength, username, folderPermEnabled, onlyofficeConverterExtensions, enableOnlyoffice, enableSeadoc } from './constants';
|
||||
import TextTranslation from './text-translation';
|
||||
import React from 'react';
|
||||
import toaster from '../components/toast';
|
||||
@ -528,7 +528,7 @@ export const Utils = {
|
||||
getFileOperationList: function(isRepoOwner, currentRepoInfo, dirent, isContextmenu) {
|
||||
let list = [];
|
||||
const { SHARE, DOWNLOAD, DELETE, RENAME, MOVE, COPY, TAGS, UNLOCK, LOCK, MARK_AS_DRAFT, UNMARK_AS_DRAFT,
|
||||
HISTORY, ACCESS_LOG, PROPERTIES, OPEN_VIA_CLIENT, ONLYOFFICE_CONVERT } = TextTranslation;
|
||||
HISTORY, ACCESS_LOG, PROPERTIES, OPEN_VIA_CLIENT, ONLYOFFICE_CONVERT, CONVERT_TO_MARKDOWN, CONVERT_TO_SDOC } = TextTranslation;
|
||||
const permission = dirent.permission;
|
||||
const { isCustomPermission, customPermission } = Utils.getUserPermission(permission);
|
||||
|
||||
@ -595,6 +595,19 @@ export const Utils = {
|
||||
}
|
||||
|
||||
list.push('Divider');
|
||||
}
|
||||
|
||||
if ((permission == 'rw' || permission == 'cloud-edit') && enableSeadoc) {
|
||||
if (dirent.name.endsWith('.md')) {
|
||||
list.push(CONVERT_TO_SDOC);
|
||||
}
|
||||
|
||||
if (dirent.name.endsWith('.sdoc')) {
|
||||
list.push(CONVERT_TO_MARKDOWN);
|
||||
}
|
||||
}
|
||||
|
||||
if (permission == 'rw') {
|
||||
if (Utils.isSdocFile(dirent.name)) {
|
||||
if (dirent.is_sdoc_draft) {
|
||||
list.push(UNMARK_AS_DRAFT);
|
||||
@ -602,6 +615,7 @@ export const Utils = {
|
||||
list.push(MARK_AS_DRAFT);
|
||||
}
|
||||
}
|
||||
list.push('Divider');
|
||||
/*
|
||||
if (enableFileComment) {
|
||||
list.push(COMMENT);
|
||||
|
@ -5,6 +5,7 @@ import json
|
||||
import logging
|
||||
import posixpath
|
||||
import requests
|
||||
from pathlib import Path
|
||||
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
@ -20,18 +21,20 @@ from seahub.api2.utils import api_error
|
||||
|
||||
from seahub.utils import check_filename_with_rename, is_pro_version, \
|
||||
gen_inner_file_upload_url, is_valid_dirent_name, normalize_file_path, \
|
||||
normalize_dir_path, get_file_type_and_ext
|
||||
normalize_dir_path, get_file_type_and_ext, check_filename_or_rename
|
||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr
|
||||
from seahub.views import check_folder_permission
|
||||
from seahub.utils.file_op import check_file_lock, if_locked_by_online_office
|
||||
from seahub.views.file import can_preview_file, can_edit_file
|
||||
from seahub.constants import PERMISSION_READ_WRITE
|
||||
from seahub.utils.repo import parse_repo_perm, is_repo_admin, is_repo_owner
|
||||
from seahub.utils.file_types import MARKDOWN, TEXT, SEADOC
|
||||
from seahub.utils.file_types import MARKDOWN, TEXT, SEADOC, MARKDOWN_SUPPORT_CONVERT_TYPES, SDOC_SUPPORT_CONVERT_TYPES
|
||||
from seahub.tags.models import FileUUIDMap
|
||||
from seahub.seadoc.models import SeadocHistoryName, SeadocDraft, SeadocCommentReply
|
||||
from seahub.base.models import FileComment
|
||||
from seahub.settings import MAX_UPLOAD_FILE_NAME_LEN, OFFICE_TEMPLATE_ROOT
|
||||
from seahub.api2.endpoints.utils import convert_file
|
||||
from seahub.seadoc.utils import get_seadoc_file_uuid
|
||||
|
||||
from seahub.drafts.models import Draft
|
||||
from seahub.drafts.utils import is_draft_file, get_file_draft
|
||||
@ -152,8 +155,8 @@ class FileView(APIView):
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
operation = operation.lower()
|
||||
if operation not in ('create', 'rename', 'move', 'copy', 'revert'):
|
||||
error_msg = "operation can only be 'create', 'rename', 'move', 'copy' or 'revert'."
|
||||
if operation not in ('create', 'rename', 'move', 'copy', 'revert', 'convert'):
|
||||
error_msg = "operation can only be 'create', 'rename', 'move', 'copy', 'convert' or 'revert'."
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
# resource check
|
||||
@ -523,6 +526,80 @@ class FileView(APIView):
|
||||
|
||||
return Response({'success': True})
|
||||
|
||||
if operation == 'convert':
|
||||
dst_type = request.data.get('dst_type')
|
||||
|
||||
extension = Path(path).suffix
|
||||
if extension not in ['.md', '.sdoc']:
|
||||
error_msg = 'path invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
if (extension == '.md' and dst_type not in MARKDOWN_SUPPORT_CONVERT_TYPES) or \
|
||||
(extension == '.sdoc' and dst_type not in SDOC_SUPPORT_CONVERT_TYPES):
|
||||
error_msg = 'dst_type invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
# resource check
|
||||
try:
|
||||
file_id = seafile_api.get_file_id_by_path(repo_id, path)
|
||||
except SearpcError as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
if not file_id:
|
||||
error_msg = 'File %s not found.' % path
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# permission check
|
||||
if parse_repo_perm(check_folder_permission(request, repo_id, parent_dir)).can_edit_on_web is False:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
# check file lock
|
||||
try:
|
||||
is_locked, locked_by_me = check_file_lock(repo_id, path, username)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
if is_locked and not locked_by_me:
|
||||
error_msg = _("File is locked")
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
filename = os.path.basename(path)
|
||||
|
||||
if extension == '.md':
|
||||
src_type = 'markdown'
|
||||
filename = filename[:-2] + 'sdoc'
|
||||
elif extension == '.sdoc':
|
||||
src_type = 'sdoc'
|
||||
filename = filename[:-4] + 'md'
|
||||
|
||||
new_file_name = check_filename_or_rename(repo_id, parent_dir, filename)
|
||||
new_file_path = posixpath.join(parent_dir, new_file_name)
|
||||
|
||||
download_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username)
|
||||
|
||||
obj_id = json.dumps({'parent_dir': parent_dir})
|
||||
upload_token = seafile_api.get_fileserver_access_token(repo_id, obj_id, 'upload-link', username,
|
||||
use_onetime=True)
|
||||
doc_uuid = get_seadoc_file_uuid(repo, path)
|
||||
|
||||
try:
|
||||
resp = convert_file(path, username, doc_uuid, download_token, upload_token, src_type, dst_type)
|
||||
if resp.status_code == 500:
|
||||
logger.error('convert file error status: %s body: %s', resp.status_code, resp.text)
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
file_info = self.get_file_info(username, repo_id, new_file_path)
|
||||
return Response(file_info)
|
||||
|
||||
def put(self, request, repo_id, format=None):
|
||||
""" Currently only support lock, unlock, refresh-lock file.
|
||||
|
||||
|
@ -4,6 +4,9 @@ import datetime
|
||||
import time
|
||||
import urllib.request, urllib.parse, urllib.error
|
||||
import logging
|
||||
import requests
|
||||
import jwt
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from rest_framework import status
|
||||
|
||||
@ -11,9 +14,9 @@ from seaserv import ccnet_api, seafile_api
|
||||
from pysearpc import SearpcError
|
||||
|
||||
from seahub.api2.utils import api_error
|
||||
from seahub.base.templatetags.seahub_tags import email2nickname, \
|
||||
email2contact_email
|
||||
from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email
|
||||
from seahub.utils import get_log_events_by_time, is_pro_version, is_org_context
|
||||
from seahub.settings import SECRET_KEY, FILE_CONVERTER_SERVER_URL
|
||||
|
||||
try:
|
||||
from seahub.settings import MULTI_TENANCY
|
||||
@ -210,3 +213,26 @@ def get_user_quota_usage_and_total(email, org_id=''):
|
||||
quota_usage = -1
|
||||
quota_total = -1
|
||||
return quota_usage, quota_total
|
||||
|
||||
|
||||
def gen_headers():
|
||||
payload = {'exp': int(time.time()) + 300, }
|
||||
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
|
||||
return {"Authorization": "Token %s" % token}
|
||||
|
||||
|
||||
def convert_file(path, username, doc_uuid, download_token, upload_token, src_type, dst_type):
|
||||
headers = gen_headers()
|
||||
params = {
|
||||
'path': path,
|
||||
'username': username,
|
||||
'doc_uuid': doc_uuid,
|
||||
'download_token': download_token,
|
||||
'upload_token': upload_token,
|
||||
'src_type': src_type,
|
||||
'dst_type': dst_type,
|
||||
}
|
||||
url = urljoin(FILE_CONVERTER_SERVER_URL, '/api/v1/file-convert/')
|
||||
resp = requests.post(url, json=params, headers=headers, timeout=30)
|
||||
|
||||
return resp
|
||||
|
@ -623,6 +623,8 @@ SHOW_LOGOUT_ICON = False
|
||||
PRIVACY_POLICY_LINK = ''
|
||||
TERMS_OF_SERVICE_LINK = ''
|
||||
|
||||
FILE_CONVERTER_SERVER_URL = 'http://127.0.0.1:8888'
|
||||
|
||||
# For security consideration, please set to match the host/domain of your site, e.g., ALLOWED_HOSTS = ['.example.com'].
|
||||
# Please refer https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts for details.
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
@ -334,6 +334,10 @@ def get_no_duplicate_obj_name(obj_name, exist_obj_names):
|
||||
i += 1
|
||||
|
||||
def check_filename_with_rename(repo_id, parent_dir, obj_name):
|
||||
exist_obj_names = list_obj_names_in_dir(repo_id, parent_dir)
|
||||
return get_no_duplicate_obj_name(obj_name, exist_obj_names)
|
||||
|
||||
def list_obj_names_in_dir(repo_id, parent_dir):
|
||||
cmmts = seafile_api.get_commit_list(repo_id, 0, 1)
|
||||
latest_commit = cmmts[0] if cmmts else None
|
||||
if not latest_commit:
|
||||
@ -343,6 +347,13 @@ def check_filename_with_rename(repo_id, parent_dir, obj_name):
|
||||
latest_commit.id, parent_dir)
|
||||
|
||||
exist_obj_names = [dirent.obj_name for dirent in dirents]
|
||||
return exist_obj_names
|
||||
|
||||
def check_filename_or_rename(repo_id, parent_dir, obj_name):
|
||||
exist_obj_names = list_obj_names_in_dir(repo_id, parent_dir)
|
||||
|
||||
if obj_name not in exist_obj_names:
|
||||
return obj_name
|
||||
return get_no_duplicate_obj_name(obj_name, exist_obj_names)
|
||||
|
||||
def get_user_repos(username, org_id=None):
|
||||
|
@ -10,3 +10,7 @@ AUDIO = 'Audio'
|
||||
SPREADSHEET = 'SpreadSheet'
|
||||
XMIND = 'XMind'
|
||||
SEADOC = 'SDoc'
|
||||
|
||||
|
||||
MARKDOWN_SUPPORT_CONVERT_TYPES = ['sdoc']
|
||||
SDOC_SUPPORT_CONVERT_TYPES = ['markdown']
|
||||
|
Loading…
Reference in New Issue
Block a user