1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-26 07:22:34 +00:00
* update

* update

* Update utils.py

* Update utils.py

* add fontend code

* Update utils.py

* update

---------

Co-authored-by: 小强 <shuntian@Mac.lan>
This commit is contained in:
Ranjiwei
2025-08-28 17:14:22 +08:00
committed by GitHub
parent 32d0de784a
commit 1c58b515db
8 changed files with 104 additions and 11 deletions

View File

@@ -32,6 +32,12 @@ class CommentPanel extends React.Component {
this.toBeAddedParticipant = [];
}
forceUpdate = () => {
this.listComments();
this.getParticipants();
this.listRepoRelatedUsers();
};
listComments = () => {
seafileAPI.listComments(repoID, fileUuid).then((res) => {
this.setState({

View File

@@ -22,7 +22,8 @@ const propTypes = {
toggleCommentPanel: PropTypes.func.isRequired,
toggleDetailsPanel: PropTypes.func.isRequired,
setImageScale: PropTypes.func,
rotateImage: PropTypes.func
rotateImage: PropTypes.func,
isCommentUpdated: PropTypes.bool,
};
const {
@@ -103,7 +104,7 @@ class FileToolbar extends React.Component {
const { moreDropdownOpen } = this.state;
const { isLocked, lockedByMe } = this.props;
const { isLocked, lockedByMe, isCommentUpdated } = this.props;
let showLockUnlockBtn = false;
let lockUnlockText; let lockUnlockIcon;
if (canLockUnlockFile) {
@@ -214,6 +215,7 @@ class FileToolbar extends React.Component {
aria-label={gettext('Comment')}
>
<i className="sdocfont sdoc-comments"></i>
{isCommentUpdated && <span className='comment-tip'></span>}
</div>
{showShareBtn && (
<IconButton

View File

@@ -15,6 +15,7 @@ import OnlyofficeFileToolbar from './onlyoffice-file-toolbar';
import EmbeddedFileDetails from '../dirent-detail/embedded-file-details';
import { MetadataMiddlewareProvider, MetadataStatusProvider } from '../../hooks';
import Loading from '../loading';
import WebSocketClient from '../../utils/websocket-service';
import '../../css/file-view.css';
@@ -29,7 +30,7 @@ const propTypes = {
};
const { isStarred, isLocked, lockedByMe,
repoID, filePath, filePerm, enableWatermark, userNickName,
repoID, fileUuid, filePath, filePerm, enableWatermark, userNickName,
fileName, repoEncrypted, isRepoAdmin, fileType
} = window.app.pageOptions;
@@ -44,8 +45,11 @@ class FileView extends React.Component {
lockedByMe: lockedByMe,
isCommentPanelOpen: false,
isHeaderShown: (storedIsHeaderShown === null) || (storedIsHeaderShown == 'true'),
isDetailsPanelOpen: false
isDetailsPanelOpen: false,
isCommentUpdated: false,
};
this.socketManager = new WebSocketClient(this.onMessageCallback, repoID);
}
componentDidMount() {
@@ -53,10 +57,25 @@ class FileView extends React.Component {
document.getElementById('favicon').href = fileIcon;
}
onMessageCallback = (data) => {
const { type, content } = data;
if (type === 'comment-update') {
const { repo_id, file_uuid } = content;
if (repoID === repo_id && file_uuid === fileUuid) {
if (!this.state.isCommentPanelOpen) {
this.setState({ isCommentUpdated: true });
} else {
this.commentPanelRef.forceUpdate();
}
}
}
};
toggleCommentPanel = () => {
this.setState({
isCommentPanelOpen: !this.state.isCommentPanelOpen,
isDetailsPanelOpen: false,
isCommentUpdated: false,
});
};
@@ -121,6 +140,10 @@ class FileView extends React.Component {
});
};
setCommentPanelRef = (ref) => {
this.commentPanelRef = ref;
};
render() {
const { isOnlyofficeFile = false } = this.props;
const { isDetailsPanelOpen, isHeaderShown } = this.state;
@@ -142,6 +165,7 @@ class FileView extends React.Component {
/>
{isOnlyofficeFile ?
<OnlyofficeFileToolbar
isCommentUpdated={this.state.isCommentUpdated}
toggleDetailsPanel={this.toggleDetailsPanel}
toggleHeader={this.toggleHeader}
toggleCommentPanel={this.toggleCommentPanel}
@@ -149,6 +173,7 @@ class FileView extends React.Component {
<FileToolbar
isLocked={this.state.isLocked}
lockedByMe={this.state.lockedByMe}
isCommentUpdated={this.state.isCommentUpdated}
onSave={this.props.onSave}
isSaving={this.props.isSaving}
needSave={this.props.needSave}
@@ -175,6 +200,7 @@ class FileView extends React.Component {
{this.props.content}
{this.state.isCommentPanelOpen &&
<CommentPanel
ref={this.setCommentPanelRef}
toggleCommentPanel={this.toggleCommentPanel}
participants={this.props.participants}
onParticipantsChange={this.props.onParticipantsChange}

View File

@@ -7,8 +7,9 @@ import Icon from '../../components/icon';
import IconButton from '../icon-button';
const propTypes = {
isCommentUpdated: PropTypes.bool,
toggleDetailsPanel: PropTypes.func.isRequired,
toggleHeader: PropTypes.func.isRequired
toggleHeader: PropTypes.func.isRequired,
};
const {
@@ -38,6 +39,7 @@ class OnlyofficeFileToolbar extends React.Component {
};
render() {
const { isCommentUpdated } = this.props;
const { moreDropdownOpen } = this.state;
return (
<Fragment>
@@ -54,6 +56,7 @@ class OnlyofficeFileToolbar extends React.Component {
aria-label={gettext('Comment')}
>
<i className="sdocfont sdoc-comments"></i>
{isCommentUpdated && <span className='comment-tip'></span>}
</div>
<Dropdown isOpen={moreDropdownOpen} toggle={this.toggleMoreOpMenu}>
<DropdownToggle

View File

@@ -20,7 +20,7 @@ body {
.onlyoffice-file-view-header-hidden {
transition: all .3s ease-in-out;
display: none!important;
display: none !important;
}
#unfold-onlyoffice-file-view-header {
@@ -32,17 +32,18 @@ body {
display: flex;
justify-content: center;
align-items: center;
background: rgba(255,255,255, 0.6);
background: rgba(255, 255, 255, 0.6);
border-radius: 0 0 14px 14px;
box-shadow: 0 0 8px rgba(0,0,0, 0.4);
box-shadow: 0 0 8px rgba(0, 0, 0, 0.4);
cursor: pointer;
}
#unfold-onlyoffice-file-view-header:hover {
background: rgba(255,255,255, 1);
background: rgba(255, 255, 255, 1);
}
.file-view-header .file-toolbar-btn {
position: relative;
width: 28px;
height: 28px;
margin-left: 10px;
@@ -78,6 +79,17 @@ body {
color: #ED7109;
}
.file-view-header .file-toolbar-btn .comment-tip {
position: absolute;
left: 4px;
top: 4px;
border-radius: 50%;
width: 6px;
height: 6px;
z-index: 100;
background: red;
}
.file-view-header .file-toolbar-more-operations {
height: 38px;
padding: 0;
@@ -140,6 +152,7 @@ body {
right: -500px;
opacity: 0.5;
}
to {
right: 0px;
opacity: 1;

View File

@@ -14,7 +14,7 @@ from django.utils import timezone
from seahub.api2.authentication import TokenAuthentication
from seahub.api2.permissions import IsRepoAccessible
from seahub.api2.throttling import UserRateThrottle
from seahub.api2.utils import api_error, user_to_dict, to_python_boolean
from seahub.api2.utils import api_error, user_to_dict, to_python_boolean, send_comment_update_event
from seahub.avatar.settings import AVATAR_DEFAULT_SIZE
from seahub.base.models import FileComment
from seahub.utils.repo import get_repo_owner
@@ -132,6 +132,7 @@ class FileCommentsView(APIView):
notification = detail
notification['to_users'] = to_users
comment['notification'] = notification
send_comment_update_event(file_uuid)
return Response(comment)
@@ -166,6 +167,7 @@ class FileCommentView(APIView):
file_comment.delete()
SeadocCommentReply.objects.filter(comment_id=comment_id).delete()
send_comment_update_event(file_uuid)
return Response({'success': True})
def put(self, request, repo_id, file_uuid, comment_id):
@@ -204,6 +206,7 @@ class FileCommentView(APIView):
comment = file_comment.to_dict()
comment.update(user_to_dict(file_comment.author, request=request))
send_comment_update_event(file_uuid)
return Response(comment)
@@ -313,6 +316,7 @@ class FileCommentRepliesView(APIView):
notification = detail
notification['to_users'] = to_users
data['notification'] = notification
send_comment_update_event(file_uuid)
return Response(data)
@@ -353,6 +357,7 @@ class FileCommentReplyView(APIView):
if not reply:
return api_error(status.HTTP_404_NOT_FOUND, 'reply not found.')
reply.delete()
send_comment_update_event(file_uuid)
return Response({'success': True})
def put(self, request, repo_id, file_uuid, comment_id, reply_id):
@@ -380,4 +385,5 @@ class FileCommentReplyView(APIView):
data = reply.to_dict()
data.update(
user_to_dict(reply.author, request=request))
send_comment_update_event(file_uuid)
return Response(data)

View File

@@ -8,7 +8,7 @@ import json
import re
import logging
import jwt
import requests
from collections import defaultdict
from functools import wraps
from django.core.cache import cache
@@ -34,9 +34,11 @@ from seahub.utils import get_user_repos
from seahub.utils.mail import send_html_email_with_dj_template
from django.utils.translation import gettext as _
import seahub.settings as settings
from seahub.tags.models import FileUUIDMap
JWT_PRIVATE_KEY = getattr(settings, 'JWT_PRIVATE_KEY', '')
logger = logging.getLogger(__name__)
def api_error(code, msg):
@@ -361,3 +363,37 @@ def is_valid_internal_jwt(auth):
return True
return False
def send_comment_update_event(file_uuid):
if not settings.ENABLE_NOTIFICATION_SERVER:
return
uuid_map = FileUUIDMap.objects.get_fileuuidmap_by_uuid(file_uuid)
if not uuid_map:
return
repo_id = uuid_map.repo_id
event_data = {
"type": "comment-update",
"content": {
"repo_id": repo_id,
"type": "comment_updated",
"file_uuid": file_uuid,
"file_path": ""
}
}
notification_server_event_url = "%s/events" % settings.INNER_NOTIFICATION_SERVER_URL.rstrip('/')
payload = {
'exp': int(time.time()) + 500
}
jwt_token = jwt.encode(payload, JWT_PRIVATE_KEY, algorithm='HS256')
headers = {
'Authorization': 'Token %s' % jwt_token,
}
try:
resp = requests.post(notification_server_event_url, json=event_data, headers=headers)
if not resp.ok:
logger.error(f'Send comment update event failed: {resp.content}')
except Exception as e:
logger.error(f'Send comment update event error. ERROR: {e}')

View File

@@ -982,6 +982,7 @@ ENABLE_WHITEBOARD = False
ENABLE_NOTIFICATION_SERVER = os.environ.get('ENABLE_NOTIFICATION_SERVER', 'false') == 'true'
NOTIFICATION_SERVER_URL = os.environ.get('NOTIFICATION_SERVER_URL', '')
INNER_NOTIFICATION_SERVER_URL = os.environ.get('INNER_NOTIFICATION_SERVER_URL', 'http://127.0.0.1:8083' )
############################
# Settings for Seahub Priv #