1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-26 15:26:19 +00:00

renameSdocHistory (#5500)

* renameSdocHistory

* sdoc NewFileHistoryView

* add SeadocHistoryName
This commit is contained in:
欢乐马
2023-06-19 17:35:30 +08:00
committed by GitHub
parent 25e942eed3
commit 757497bd5a
8 changed files with 316 additions and 73 deletions

View File

@@ -1,11 +1,15 @@
import moment from 'moment';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem} from 'reactstrap'; import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem} from 'reactstrap';
import { gettext, filePath } from '../../utils/constants'; import { gettext, filePath } from '../../utils/constants';
import URLDecorator from '../../utils/url-decorator'; import URLDecorator from '../../utils/url-decorator';
import Rename from '../../components/rename';
import '../../css/history-record-item.css'; import '../../css/history-record-item.css';
moment.locale(window.app.config.lang);
class HistoryVersion extends React.Component { class HistoryVersion extends React.Component {
constructor(props) { constructor(props) {
@@ -13,18 +17,19 @@ class HistoryVersion extends React.Component {
this.state = { this.state = {
isShowOperationIcon: false, isShowOperationIcon: false,
isMenuShow: false, isMenuShow: false,
isRenameShow: false,
}; };
} }
onMouseEnter = () => { onMouseEnter = () => {
const { currentVersion, historyVersion } = this.props; const { currentVersion, historyVersion } = this.props;
if (currentVersion.commitId === historyVersion.commitId) return; if (currentVersion.commit_id === historyVersion.commit_id) return;
this.setState({ isShowOperationIcon: true }); this.setState({ isShowOperationIcon: true });
} }
onMouseLeave = () => { onMouseLeave = () => {
const { currentVersion, historyVersion } = this.props; const { currentVersion, historyVersion } = this.props;
if (currentVersion.commitId === historyVersion.commitId) return; if (currentVersion.commit_id === historyVersion.commit_id) return;
this.setState({ isShowOperationIcon: false }); this.setState({ isShowOperationIcon: false });
} }
@@ -35,7 +40,7 @@ class HistoryVersion extends React.Component {
onClick = () => { onClick = () => {
this.setState({ isShowOperationIcon: false }); this.setState({ isShowOperationIcon: false });
const { currentVersion, historyVersion } = this.props; const { currentVersion, historyVersion } = this.props;
if (currentVersion.commitId === historyVersion.commitId) return; if (currentVersion.commit_id === historyVersion.commit_id) return;
this.props.onSelectHistoryVersion(historyVersion); this.props.onSelectHistoryVersion(historyVersion);
} }
@@ -50,15 +55,30 @@ class HistoryVersion extends React.Component {
onItemCopy = () => { onItemCopy = () => {
const { historyVersion } = this.props; const { historyVersion } = this.props;
historyVersion.ctime_format = moment(historyVersion.ctime).format('YYYY-MM-DD HH:mm');
this.props.onCopy(historyVersion); this.props.onCopy(historyVersion);
} }
toggleRename = () => {
this.setState({isRenameShow: !this.state.isRenameShow});
}
onRenameConfirm = (newName) => {
const { obj_id } = this.props.historyVersion;
this.props.renameHistoryVersion(obj_id, newName);
this.toggleRename();
}
onRenameCancel = () => {
this.toggleRename();
}
render() { render() {
const { currentVersion, historyVersion } = this.props; const { currentVersion, historyVersion } = this.props;
if (!currentVersion || !historyVersion) return null; if (!currentVersion || !historyVersion) return null;
const { ctime, commitId, creatorName, revFileId } = historyVersion; const { ctime, commit_id, creator_name, obj_id, name} = historyVersion;
const isHighlightItem = commitId === currentVersion.commitId; const isHighlightItem = commit_id === currentVersion.commit_id;
const url = URLDecorator.getUrl({ type: 'download_historic_file', filePath: filePath, objID: revFileId }); const url = URLDecorator.getUrl({ type: 'download_historic_file', filePath: filePath, objID: obj_id });
return ( return (
<li <li
className={`history-list-item ${isHighlightItem ? 'item-active' : ''}`} className={`history-list-item ${isHighlightItem ? 'item-active' : ''}`}
@@ -67,10 +87,14 @@ class HistoryVersion extends React.Component {
onClick={this.onClick} onClick={this.onClick}
> >
<div className="history-info"> <div className="history-info">
<div className="time">{ctime}</div> {this.state.isRenameShow ?
<Rename name={name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel}/>
:<div className="name">{name}</div>
}
<div className="time">{moment(ctime).format('YYYY-MM-DD HH:mm')}</div>
<div className="owner"> <div className="owner">
<span className="squire-icon"></span> <span className="squire-icon"></span>
<span>{creatorName}</span> <span>{creator_name}</span>
</div> </div>
</div> </div>
<div className="history-operation"> <div className="history-operation">
@@ -86,6 +110,7 @@ class HistoryVersion extends React.Component {
{(this.props.index !== 0) && <DropdownItem onClick={this.onItemRestore}>{gettext('Restore')}</DropdownItem>} {(this.props.index !== 0) && <DropdownItem onClick={this.onItemRestore}>{gettext('Restore')}</DropdownItem>}
<DropdownItem tag='a' href={url} onClick={this.onItemDownLoad}>{gettext('Download')}</DropdownItem> <DropdownItem tag='a' href={url} onClick={this.onItemDownLoad}>{gettext('Download')}</DropdownItem>
{(this.props.index !== 0) && <DropdownItem onClick={this.onItemCopy}>{gettext('Copy')}</DropdownItem>} {(this.props.index !== 0) && <DropdownItem onClick={this.onItemCopy}>{gettext('Copy')}</DropdownItem>}
<DropdownItem onClick={this.toggleRename}>{gettext('Rename')}</DropdownItem>
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>
</div> </div>
@@ -101,6 +126,7 @@ HistoryVersion.propTypes = {
onSelectHistoryVersion: PropTypes.func.isRequired, onSelectHistoryVersion: PropTypes.func.isRequired,
onRestore: PropTypes.func.isRequired, onRestore: PropTypes.func.isRequired,
onCopy: PropTypes.func.isRequired, onCopy: PropTypes.func.isRequired,
renameHistoryVersion: PropTypes.func.isRequired,
}; };
export default HistoryVersion; export default HistoryVersion;

View File

@@ -50,12 +50,12 @@ class SdocFileHistory extends React.Component {
onSelectHistoryVersion = (currentVersion, lastVersion) => { onSelectHistoryVersion = (currentVersion, lastVersion) => {
this.setState({ isLoading: true, currentVersion }); this.setState({ isLoading: true, currentVersion });
seafileAPI.getFileRevision(historyRepoID, currentVersion.commitId, currentVersion.path).then(res => { seafileAPI.getFileRevision(historyRepoID, currentVersion.commit_id, currentVersion.path).then(res => {
return seafileAPI.getFileContent(res.data); return seafileAPI.getFileContent(res.data);
}).then(res => { }).then(res => {
const currentVersionContent = res.data; const currentVersionContent = res.data;
if (lastVersion) { if (lastVersion) {
seafileAPI.getFileRevision(historyRepoID, lastVersion.commitId, lastVersion.path).then(res => { seafileAPI.getFileRevision(historyRepoID, lastVersion.commit_id, lastVersion.path).then(res => {
return seafileAPI.getFileContent(res.data); return seafileAPI.getFileContent(res.data);
}).then(res => { }).then(res => {
const lastVersionContent = res.data; const lastVersionContent = res.data;
@@ -84,7 +84,7 @@ class SdocFileHistory extends React.Component {
const { currentVersionContent } = this.state; const { currentVersionContent } = this.state;
this.setState({ isLoading: true }, () => { this.setState({ isLoading: true }, () => {
localStorage.setItem('seahub-sdoc-history-show-changes', isShowChanges + ''); localStorage.setItem('seahub-sdoc-history-show-changes', isShowChanges + '');
seafileAPI.getFileRevision(historyRepoID, lastVersion.commitId, lastVersion.path).then(res => { seafileAPI.getFileRevision(historyRepoID, lastVersion.commit_id, lastVersion.path).then(res => {
return seafileAPI.getFileContent(res.data); return seafileAPI.getFileContent(res.data);
}).then(res => { }).then(res => {
const lastVersionContent = res.data; const lastVersionContent = res.data;

View File

@@ -2,15 +2,16 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import Loading from '../../components/loading'; import Loading from '../../components/loading';
import { gettext, filePath, historyRepoID } from '../../utils/constants'; import { gettext, historyRepoID, PER_PAGE } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import FileHistory from '../../models/file-history';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import editUtilities from '../../utils/editor-utilities'; import editUtilities from '../../utils/editor-utilities';
import toaster from '../../components/toast'; import toaster from '../../components/toast';
import HistoryVersion from './history-version'; import HistoryVersion from './history-version';
import Switch from '../../components/common/switch'; import Switch from '../../components/common/switch';
const { docUuid } = window.fileHistory.pageOptions;
class SidePanel extends Component { class SidePanel extends Component {
constructor(props) { constructor(props) {
@@ -19,85 +20,104 @@ class SidePanel extends Component {
isLoading: true, isLoading: true,
historyVersions: [], historyVersions: [],
errorMessage: '', errorMessage: '',
currentPage: 1,
hasMore: false,
fileOwner: '',
isReloadingData: false,
}; };
this.init();
} }
componentDidMount() { componentDidMount() {
this.listHistoryVersions(historyRepoID, filePath, this.nextCommit, (historyVersion, lastHistoryVersion) => { seafileAPI.listSdocHistory(docUuid, 1, PER_PAGE).then(res => {
this.props.onSelectHistoryVersion(historyVersion, lastHistoryVersion); let historyList = res.data;
if (historyList.length === 0) {
this.setState({isLoading: false});
throw Error('there has an error in server');
}
this.initResultState(res.data);
}); });
} }
init = () => { refershFileList() {
this.hasMore = true; seafileAPI.listSdocHistory(docUuid, 1, PER_PAGE).then(res => {
this.nextCommit = ''; this.initResultState(res.data);
this.filePath = ''; });
this.oldFilePath = '';
} }
listHistoryVersions = (repoID, filePath, commit, callback) => { initResultState(result) {
seafileAPI.listOldFileHistoryRecords(repoID, filePath, commit).then((res) => { if (result.histories.length) {
let historyData = res.data; this.setState({
if (!historyData) { historyVersions: result.histories,
this.setState({ isLoading: false, errorMessage: 'There is an error in server.' }); currentPage: result.page,
return; hasMore: result.total_count > (PER_PAGE * this.state.currentPage),
} isLoading: false,
this.updateHistoryVersions(historyData, callback); fileOwner: result.histories[0].creator_email,
});
this.props.onSelectHistoryVersion(result.histories[0], result.histories[1]);
}
}
updateResultState(result) {
if (result.histories.length) {
this.setState({
historyVersions: [...this.state.historyVersions, ...result.histories],
currentPage: result.page,
hasMore: result.total_count > (PER_PAGE * this.state.currentPage),
isLoading: false,
fileOwner: result.histories[0].creator_email
});
}
}
loadMore = () => {
if (!this.state.isReloadingData) {
let currentPage = this.state.currentPage + 1;
this.setState({
currentPage: currentPage,
isReloadingData: true,
});
seafileAPI.listSdocHistory(docUuid, currentPage, PER_PAGE).then(res => {
this.updateResultState(res.data);
this.setState({isReloadingData: false});
});
}
}
renameHistoryVersion = (objID, newName) => {
seafileAPI.renameSdocHistory(docUuid, objID, newName).then((res) => {
this.setState({
historyVersions: this.state.historyVersions.map(item => {
if (item.obj_id == objID) {
item.name = newName;
}
return item;
})
});
}).catch(error => { }).catch(error => {
const errorMessage = Utils.getErrorMsg(error, true); const errorMessage = Utils.getErrorMsg(error, true);
this.setState({ isLoading: false, errorMessage: errorMessage }); this.setState({ isLoading: false, errorMessage: errorMessage });
}); });
} }
updateHistoryVersions(result, callback) {
const dataCount = result.data ? result.data.length : 0;
this.nextCommit = result.next_start_commit || '';
if (dataCount) {
const addedHistoryVersions = result.data.map(item => new FileHistory(item));
this.filePath = addedHistoryVersions[dataCount - 1].path;
this.oldFilePath = addedHistoryVersions[dataCount - 1].revRenamedOldPath;
const historyVersions = [ ...this.state.historyVersions, ...addedHistoryVersions ];
this.setState({ historyVersions: historyVersions, isLoading: false, errorMessage: '' }, () => {
callback && callback(historyVersions[0], historyVersions[1]);
});
return;
}
if (this.nextCommit) {
this.listHistoryVersions(historyRepoID, filePath, this.nextCommit);
return;
}
this.hasMore = false;
this.setState({ isLoading: false, errorMessage: '' });
}
onScrollHandler = (event) => { onScrollHandler = (event) => {
const clientHeight = event.target.clientHeight; const clientHeight = event.target.clientHeight;
const scrollHeight = event.target.scrollHeight; const scrollHeight = event.target.scrollHeight;
const scrollTop = event.target.scrollTop; const scrollTop = event.target.scrollTop;
const isBottom = (clientHeight + scrollTop + 1 >= scrollHeight); const isBottom = (clientHeight + scrollTop + 1 >= scrollHeight);
if (isBottom && this.hasMore && this.nextCommit) { if (isBottom && this.state.hasMore) {
this.loadMore(); this.loadMore();
} }
} }
loadMore = () => { restoreVersion = (currentItem) => {
if (this.state.isLoading) return; const { commit_id, path } = currentItem;
this.setState({ isLoading: true }, () => { editUtilities.revertFile(path, commit_id).then(res => {
const currentFilePath = this.oldFilePath || this.filePath;
this.listHistoryVersions(historyRepoID, currentFilePath, this.nextCommit);
});
}
restoreVersion = (historyVersion) => {
const { commitId, path } = historyVersion;
editUtilities.revertFile(path, commitId).then(res => {
if (res.data.success) { if (res.data.success) {
this.init(); this.setState({isLoading: true});
this.setState({ isLoading: true, historyVersions: [], errorMessage: '' } , () => { this.refershFileList();
this.listHistoryVersions(historyRepoID, filePath);
});
} }
let message = gettext('Successfully restored.');
toaster.success(message);
}).catch(error => { }).catch(error => {
const errorMessage = Utils.getErrorMsg(error, true); const errorMessage = Utils.getErrorMsg(error, true);
toaster.danger(gettext(errorMessage)); toaster.danger(gettext(errorMessage));
@@ -111,13 +131,13 @@ class SidePanel extends Component {
return; return;
} }
const { historyVersions } = this.state; const { historyVersions } = this.state;
const historyVersionIndex = historyVersions.findIndex(item => item.commitId === historyVersion.commitId); const historyVersionIndex = historyVersions.findIndex(item => item.commit_id === historyVersion.commit_id);
this.props.onSelectHistoryVersion(historyVersion, historyVersions[historyVersionIndex + 1]); this.props.onSelectHistoryVersion(historyVersion, historyVersions[historyVersionIndex + 1]);
} }
copyHistoryFile = (historyVersion) => { copyHistoryFile = (historyVersion) => {
const { path, revFileId, ctime } = historyVersion; const { path, obj_id, ctime_format } = historyVersion;
seafileAPI.sdocCopyHistoryFile(historyRepoID, path, revFileId, ctime).then(res => { seafileAPI.sdocCopyHistoryFile(historyRepoID, path, obj_id, ctime_format).then(res => {
let message = gettext('Successfully copied %(name)s.'); let message = gettext('Successfully copied %(name)s.');
let filename = res.data.file_name; let filename = res.data.file_name;
message = message.replace('%(name)s', filename); message = message.replace('%(name)s', filename);
@@ -157,13 +177,14 @@ class SidePanel extends Component {
{historyVersions.map((historyVersion, index) => { {historyVersions.map((historyVersion, index) => {
return ( return (
<HistoryVersion <HistoryVersion
key={historyVersion.commitId} key={historyVersion.commit_id}
index={index} index={index}
currentVersion={this.props.currentVersion} currentVersion={this.props.currentVersion}
historyVersion={historyVersion} historyVersion={historyVersion}
onSelectHistoryVersion={this.onSelectHistoryVersion} onSelectHistoryVersion={this.onSelectHistoryVersion}
onRestore={this.restoreVersion} onRestore={this.restoreVersion}
onCopy={this.copyHistoryFile} onCopy={this.copyHistoryFile}
renameHistoryVersion={this.renameHistoryVersion}
/> />
); );
})} })}
@@ -179,7 +200,7 @@ class SidePanel extends Component {
onShowChanges = () => { onShowChanges = () => {
const { isShowChanges, currentVersion } = this.props; const { isShowChanges, currentVersion } = this.props;
const { historyVersions } = this.state; const { historyVersions } = this.state;
const historyVersionIndex = historyVersions.findIndex(item => item.commitId === currentVersion.commitId); const historyVersionIndex = historyVersions.findIndex(item => item.commit_id === currentVersion.commit_id);
const lastVersion = historyVersions[historyVersionIndex + 1]; const lastVersion = historyVersions[historyVersionIndex + 1];
this.props.onShowChanges(!isShowChanges, lastVersion); this.props.onShowChanges(!isShowChanges, lastVersion);
} }

View File

@@ -3,6 +3,7 @@ import json
import logging import logging
import requests import requests
import posixpath import posixpath
from datetime import datetime
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
@@ -24,11 +25,17 @@ from seahub.seadoc.utils import is_valid_seadoc_access_token, get_seadoc_upload_
gen_seadoc_image_parent_path, get_seadoc_asset_upload_link, get_seadoc_asset_download_link, \ gen_seadoc_image_parent_path, get_seadoc_asset_upload_link, get_seadoc_asset_download_link, \
can_access_seadoc_asset can_access_seadoc_asset
from seahub.utils.file_types import SEADOC, IMAGE from seahub.utils.file_types import SEADOC, IMAGE
from seahub.utils import get_file_type_and_ext, normalize_file_path, PREVIEW_FILEEXT, \ from seahub.utils import get_file_type_and_ext, normalize_file_path, PREVIEW_FILEEXT, get_file_history, \
gen_inner_file_get_url, gen_inner_file_upload_url gen_inner_file_get_url, gen_inner_file_upload_url
from seahub.tags.models import FileUUIDMap from seahub.tags.models import FileUUIDMap
from seahub.utils.error_msg import file_type_error_msg from seahub.utils.error_msg import file_type_error_msg
from seahub.utils.repo import parse_repo_perm from seahub.utils.repo import parse_repo_perm
from seahub.utils.file_revisions import get_file_revisions_within_limit
from seahub.seadoc.models import SeadocHistoryName
from seahub.avatar.templatetags.avatar_tags import api_avatar_url
from seahub.base.templatetags.seahub_tags import email2nickname, \
email2contact_email
from seahub.utils.timeutils import utc_datetime_to_isoformat_timestr, timestamp_to_isoformat_timestr
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -353,3 +360,147 @@ class SeadocCopyHistoryFile(APIView):
'file_name': new_file_name, 'file_name': new_file_name,
'file_path': new_file_path, 'file_path': new_file_path,
}) })
class SeadocHistory(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle, )
def _get_new_file_history_info(self, ent, avatar_size, name_dict):
info = {}
creator_name = ent.op_user
url, is_default, date_uploaded = api_avatar_url(creator_name, avatar_size)
info['creator_avatar_url'] = url
info['creator_email'] = creator_name
info['creator_name'] = email2nickname(creator_name)
info['creator_contact_email'] = email2contact_email(creator_name)
info['ctime'] = utc_datetime_to_isoformat_timestr(ent.timestamp)
info['size'] = ent.size
info['obj_id'] = ent.file_id
info['commit_id'] = ent.commit_id
info['old_path'] = ent.old_path if hasattr(ent, 'old_path') else ''
info['path'] = ent.path
info['name'] = name_dict.get(ent.file_id, '')
return info
def get(self, request, file_uuid):
"""list history, same as NewFileHistoryView
"""
uuid_map = FileUUIDMap.objects.get_fileuuidmap_by_uuid(file_uuid)
if not uuid_map:
error_msg = 'seadoc uuid %s not found.' % file_uuid
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo_id = uuid_map.repo_id
username = request.user.username
path = posixpath.join(uuid_map.parent_path, uuid_map.filename)
# permission check
if not check_folder_permission(request, repo_id, path):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
commit_id = repo.head_cmmt_id
try:
avatar_size = int(request.GET.get('avatar_size', 32))
page = int(request.GET.get('page', 1))
per_page = int(request.GET.get('per_page', 25))
except ValueError:
avatar_size = 32
page = 1
per_page = 25
# Don't use seafile_api.get_file_id_by_path()
# if path parameter is `rev_renamed_old_path`.
# seafile_api.get_file_id_by_path() will return None.
file_id = seafile_api.get_file_id_by_commit_and_path(repo_id,
commit_id, path)
if not file_id:
error_msg = 'File %s not found.' % path
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# get repo history limit
try:
history_limit = seafile_api.get_repo_history_limit(repo_id)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
start = (page - 1) * per_page
count = per_page
try:
file_revisions, total_count = get_file_history(repo_id, path, start, count, history_limit)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
name_dict = {}
obj_id_list = [commit.file_id for commit in file_revisions]
if obj_id_list:
name_queryset = SeadocHistoryName.objects.list_by_obj_ids(
doc_uuid=file_uuid, obj_id_list=obj_id_list)
name_dict = {item.obj_id: item.name for item in name_queryset}
data = [self._get_new_file_history_info(ent, avatar_size, name_dict) for ent in file_revisions]
result = {
"histories": data,
"page": page,
"total_count": total_count
}
return Response(result)
def post(self, request, file_uuid):
"""rename history
"""
username = request.user.username
obj_id = request.data.get('obj_id', '')
new_name = request.data.get('new_name', '')
if not obj_id:
error_msg = 'obj_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not new_name:
error_msg = 'new_name invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
uuid_map = FileUUIDMap.objects.get_fileuuidmap_by_uuid(file_uuid)
if not uuid_map:
error_msg = 'seadoc uuid %s not found.' % file_uuid
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo_id = uuid_map.repo_id
username = request.user.username
path = posixpath.join(uuid_map.parent_path, uuid_map.filename)
# permission check
if not check_folder_permission(request, repo_id, path):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
token = seafile_api.get_fileserver_access_token(repo_id,
obj_id, 'download', username)
if not token:
error_msg = 'history %s not found.' % obj_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# main
SeadocHistoryName.objects.update_name(file_uuid, obj_id, new_name)
return Response({
'obj_id': obj_id,
'name': new_name,
})

33
seahub/seadoc/models.py Normal file
View File

@@ -0,0 +1,33 @@
from django.db import models
class SeadocHistoryNameManager(models.Manager):
def update_name(self, doc_uuid, obj_id, name):
if self.filter(doc_uuid=doc_uuid, obj_id=obj_id).exists():
obj = self.filter(doc_uuid=doc_uuid, obj_id=obj_id).update(name=name)
else:
obj = self.create(doc_uuid=doc_uuid, obj_id=obj_id, name=name)
return obj
def list_by_obj_ids(self, doc_uuid, obj_id_list):
return self.filter(doc_uuid=doc_uuid, obj_id__in=obj_id_list)
class SeadocHistoryName(models.Model):
doc_uuid = models.CharField(max_length=36, db_index=True)
obj_id = models.CharField(max_length=40)
name = models.CharField(max_length=255)
objects = SeadocHistoryNameManager()
class Meta:
db_table = 'history_name'
unique_together = ('doc_uuid', 'obj_id')
def to_dict(self):
return {
'id': self.pk,
'doc_uuid': self.doc_uuid,
'obj_id': self.obj_id,
'name': self.name,
}

View File

@@ -1,6 +1,6 @@
from django.urls import re_path from django.urls import re_path
from .apis import SeadocAccessToken, SeadocUploadLink, SeadocDownloadLink, SeadocUploadFile, \ from .apis import SeadocAccessToken, SeadocUploadLink, SeadocDownloadLink, SeadocUploadFile, \
SeadocUploadImage, SeadocDownloadImage, SeadocCopyHistoryFile SeadocUploadImage, SeadocDownloadImage, SeadocCopyHistoryFile, SeadocHistory
urlpatterns = [ urlpatterns = [
re_path(r'^access-token/(?P<repo_id>[-0-9a-f]{36})/$', SeadocAccessToken.as_view(), name='seadoc_access_token'), re_path(r'^access-token/(?P<repo_id>[-0-9a-f]{36})/$', SeadocAccessToken.as_view(), name='seadoc_access_token'),
@@ -10,4 +10,5 @@ urlpatterns = [
re_path(r'^upload-image/(?P<file_uuid>[-0-9a-f]{36})/$', SeadocUploadImage.as_view(), name='seadoc_upload_image'), re_path(r'^upload-image/(?P<file_uuid>[-0-9a-f]{36})/$', SeadocUploadImage.as_view(), name='seadoc_upload_image'),
re_path(r'^download-image/(?P<file_uuid>[-0-9a-f]{36})/(?P<filename>.*)$', SeadocDownloadImage.as_view(), name='seadoc_download_image'), re_path(r'^download-image/(?P<file_uuid>[-0-9a-f]{36})/(?P<filename>.*)$', SeadocDownloadImage.as_view(), name='seadoc_download_image'),
re_path(r'^copy-history-file/(?P<repo_id>[-0-9a-f]{36})/$', SeadocCopyHistoryFile.as_view(), name='seadoc_copy_history_file'), re_path(r'^copy-history-file/(?P<repo_id>[-0-9a-f]{36})/$', SeadocCopyHistoryFile.as_view(), name='seadoc_copy_history_file'),
re_path(r'^history/(?P<file_uuid>[-0-9a-f]{36})/$', SeadocHistory.as_view(), name='seadoc_history'),
] ]

View File

@@ -275,6 +275,7 @@ INSTALLED_APPS = [
'seahub.organizations', 'seahub.organizations',
'seahub.krb5_auth', 'seahub.krb5_auth',
'seahub.django_cas_ng', 'seahub.django_cas_ng',
'seahub.seadoc',
] ]

View File

@@ -1375,3 +1375,13 @@ CREATE TABLE `organizations_orgadminsettings` (
UNIQUE KEY `organizations_orgadminsettings_org_id_key_a01cc7de_uniq` (`org_id`,`key`), UNIQUE KEY `organizations_orgadminsettings_org_id_key_a01cc7de_uniq` (`org_id`,`key`),
KEY `organizations_orgadminsettings_org_id_4f70d186` (`org_id`) KEY `organizations_orgadminsettings_org_id_4f70d186` (`org_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `history_name` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`doc_uuid` varchar(36) NOT NULL,
`obj_id` varchar(40) NOT NULL,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `history_name_doc_uuid` (`doc_uuid`),
UNIQUE KEY `history_name_doc_uuid_obj_id` (`doc_uuid`, `obj_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;