mirror of
https://github.com/haiwen/seahub.git
synced 2025-07-15 07:52:14 +00:00
Merge branch '7.0'
This commit is contained in:
commit
0e661f43a3
6
frontend/package-lock.json
generated
6
frontend/package-lock.json
generated
@ -15905,9 +15905,9 @@
|
||||
}
|
||||
},
|
||||
"seafile-js": {
|
||||
"version": "0.2.96",
|
||||
"resolved": "https://registry.npmjs.org/seafile-js/-/seafile-js-0.2.96.tgz",
|
||||
"integrity": "sha512-SCZGVo+e8usxrzV6nWX3Qe3LKtpcuxFA78AY9KRbPic5V2ET2c0xmATIpKa2bT7Ji54t8MvVG0mt2D2AiCZ2Sw==",
|
||||
"version": "0.2.97",
|
||||
"resolved": "https://registry.npmjs.org/seafile-js/-/seafile-js-0.2.97.tgz",
|
||||
"integrity": "sha512-a7nlJ4FadqPrsF83GkrKZQem6lQLwm/eDhQc5Ovl5UYw3b1VWz/RARhEO70WKVPtwfmShwKTeRyEZCYVW51edg==",
|
||||
"requires": {
|
||||
"axios": "^0.18.0",
|
||||
"form-data": "^2.3.2",
|
||||
|
@ -37,7 +37,7 @@
|
||||
"react-responsive": "^6.1.1",
|
||||
"react-select": "^2.4.1",
|
||||
"reactstrap": "^6.4.0",
|
||||
"seafile-js": "^0.2.96",
|
||||
"seafile-js": "^0.2.97",
|
||||
"socket.io-client": "^2.2.0",
|
||||
"sw-precache-webpack-plugin": "0.11.4",
|
||||
"unified": "^7.0.0",
|
||||
|
@ -76,7 +76,20 @@ class App extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
navigateClientUrlToLib = () =>{
|
||||
if(window.location.hash && window.location.hash.indexOf('common/lib') != -1){
|
||||
let splitUrlArray = window.location.hash.split('/');
|
||||
let repoID = splitUrlArray[splitUrlArray.length - 2];
|
||||
let url = siteRoot + 'library/' + repoID + '/';
|
||||
navigate(url, {repalce: true});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// url from client e.g. http://127.0.0.1:8000/#common/lib/34e7fb92-e91d-499d-bcde-c30ea8af9828/
|
||||
// navigate to library page http://127.0.0.1:8000/library/34e7fb92-e91d-499d-bcde-c30ea8af9828/
|
||||
this.navigateClientUrlToLib();
|
||||
|
||||
// e.g. from http://127.0.0.1:8000/drafts/reviews/
|
||||
// get reviews
|
||||
// TODO: need refactor later
|
||||
|
@ -86,7 +86,7 @@ class DirPath extends React.Component {
|
||||
<span className="path-split">/</span>
|
||||
</Fragment>
|
||||
)}
|
||||
{currentPath === '/' ?
|
||||
{(currentPath === '/' || currentPath === '') ?
|
||||
<span>{repoName}</span>:
|
||||
<a className="path-link" data-path="/" onClick={this.onPathClick}>{repoName}</a>
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import toaster from '../toast';
|
||||
|
||||
const { avatarURL, csrfToken } = window.app.pageOptions;
|
||||
@ -50,7 +51,25 @@ class UserAvatarForm extends React.Component {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.form.current.submit();
|
||||
//this.form.current.submit();
|
||||
seafileAPI.updateUserAvatar(file, 160).then((res) => {
|
||||
this.setState({
|
||||
avatarSrc: res.data.avatar_url
|
||||
});
|
||||
toaster.success(gettext('Success'));
|
||||
}).catch((error) => {
|
||||
let errorMsg = '';
|
||||
if (error.response) {
|
||||
if (error.response.data && error.response.data['error_msg']) {
|
||||
errorMsg = error.response.data['error_msg'];
|
||||
} else {
|
||||
errorMsg = gettext('Error');
|
||||
}
|
||||
} else {
|
||||
errorMsg = gettext('Please check the network.');
|
||||
}
|
||||
toaster.danger(errorMsg);
|
||||
});
|
||||
}
|
||||
|
||||
openFileInput = () => {
|
||||
@ -75,7 +94,7 @@ class UserAvatarForm extends React.Component {
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
|
||||
<label className="col-sm-1 col-form-label">{gettext('Avatar:')}</label>
|
||||
<div className="col-auto position-relative" onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
|
||||
<img src={avatarURL} width="80" height="80" alt="" className="user-avatar" />
|
||||
<img src={this.state.avatarSrc} width="80" height="80" alt="" className="user-avatar" />
|
||||
<input type="file" name="avatar" className="d-none" onChange={this.fileInputChange} ref={this.fileInput} />
|
||||
<span className={`avatar-edit fas fa-edit ${!this.state.isEditShown && 'd-none'}`} onClick={this.openFileInput}></span>
|
||||
</div>
|
||||
|
@ -86,6 +86,30 @@
|
||||
background: #ff0;
|
||||
box-shadow: 0px 2px 10px #ff0;
|
||||
}
|
||||
|
||||
.annotationLayer .textAnnotation img {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.annotationLayer .popupWrapper {
|
||||
position: absolute;
|
||||
width: 20em;
|
||||
}
|
||||
|
||||
.annotationLayer .popup {
|
||||
position: absolute;
|
||||
z-index: 200;
|
||||
max-width: 20em;
|
||||
background-color: #FFFF99;
|
||||
box-shadow: 0px 2px 5px #333;
|
||||
border-radius: 2px;
|
||||
padding: 0.6em;
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
font: message-box;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
/* annotationLayer ends */
|
||||
#fileInput {
|
||||
display:none;
|
||||
|
@ -9,6 +9,8 @@ class Group {
|
||||
this.parent_group_id = object.parent_group_id;
|
||||
this.wiki_enabled = object.wiki_enabled;
|
||||
this.repos = object.repos || [];
|
||||
this.group_quota = object.group_quota;
|
||||
this.group_quota_usage = object.group_quota_usage;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,10 @@ class GroupView extends React.Component {
|
||||
<span className="path-split">/</span>
|
||||
<span>{currentGroup.name}</span>
|
||||
{currentGroup.parent_group_id !== 0 && (
|
||||
<span className="department-group-icon fas fa-building" title={gettext('This is a special group representing a department.')}></span>
|
||||
<Fragment>
|
||||
<span className="department-group-icon fas fa-building" title={gettext('This is a special group representing a department.')}></span>
|
||||
<span>{' '}{'('}{gettext('Used:')}{' '}{Utils.bytesToSize(currentGroup.group_quota_usage)}{'/'}{Utils.bytesToSize(currentGroup.group_quota)}{')'}</span>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
<div className="path-tool">
|
||||
|
@ -9,7 +9,7 @@ import './css/image-file-view.css';
|
||||
|
||||
const {
|
||||
repoID, filePath, err,
|
||||
fileName, previousImage, nextImage, rawPath
|
||||
fileName, previousImage, nextImage, rawPath, thumbnailSizeForOriginal,
|
||||
} = window.app.pageOptions;
|
||||
|
||||
let previousImageUrl, nextImageUrl;
|
||||
@ -30,6 +30,14 @@ class ViewFileImage extends React.Component {
|
||||
|
||||
class FileContent extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
thumbnailError: false,
|
||||
};
|
||||
this.thumbnailSuffixList = ['tiff', 'eps', 'psd'];
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (previousImage && e.keyCode == 37) { // press '<-'
|
||||
@ -41,10 +49,20 @@ class FileContent extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
handleError = () => {
|
||||
this.setState({
|
||||
thumbnailError: true
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
if (err) {
|
||||
if (err || this.state.thumbnailError) {
|
||||
return <FileViewTip />;
|
||||
}
|
||||
let thumbnailUrl = `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${Utils.encodePath(filePath)}`;
|
||||
let imageSuffix = fileName.split('.').pop();
|
||||
let isPreviewThumbnail = this.thumbnailSuffixList.includes(imageSuffix);
|
||||
|
||||
return (
|
||||
<div className="file-view-content flex-1 image-file-view">
|
||||
{previousImage && (
|
||||
@ -53,7 +71,10 @@ class FileContent extends React.Component {
|
||||
{nextImage && (
|
||||
<a href={nextImageUrl} id="img-next" title={gettext('you can also press →')}><span className="fas fa-chevron-right"></span></a>
|
||||
)}
|
||||
<img src={rawPath} alt={fileName} id="image-view" />
|
||||
{isPreviewThumbnail ?
|
||||
<img src={thumbnailUrl} alt={fileName} id="image-view" onError={this.handleError}/> :
|
||||
<img src={rawPath} alt={fileName} id="image-view"/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
7
media/js/pdf/images/annotation-noicon.svg
Normal file
7
media/js/pdf/images/annotation-noicon.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 40 40">
|
||||
</svg>
|
After Width: | Height: | Size: 158 B |
@ -4395,7 +4395,7 @@ var defaultOptions = {
|
||||
kind: OptionKind.VIEWER
|
||||
},
|
||||
imageResourcesPath: {
|
||||
value: './images/',
|
||||
value: sf_pdf_images_path,
|
||||
kind: OptionKind.VIEWER
|
||||
},
|
||||
maxCanvasPixels: {
|
||||
|
@ -68,6 +68,12 @@ def get_group_info(request, group_id, avatar_size=GROUP_AVATAR_DEFAULT_SIZE):
|
||||
"admins": get_group_admins(group.id),
|
||||
"wiki_enabled": is_wiki_mod_enabled_for_group(group_id)
|
||||
}
|
||||
# parent_group_id = 0: non department group
|
||||
# parent_group_id = -1: top department group
|
||||
# parent_group_id = n(n > 0): sub department group, n is parent group's id
|
||||
if group.parent_group_id != 0:
|
||||
group_info['group_quota'] = seafile_api.get_group_quota(group_id)
|
||||
group_info['group_quota_usage'] = seafile_api.get_group_quota_usage(group_id)
|
||||
|
||||
return group_info
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
import os
|
||||
import logging
|
||||
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
@ -23,7 +24,7 @@ from seahub.avatar.templatetags.avatar_tags import api_avatar_url
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class UserAvatarView(APIView):
|
||||
authentication_classes = (TokenAuthentication,)
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
throttle_classes = (UserRateThrottle,)
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
var commit_id = '{{ current_commit.id }}' || '{{ repo.head_cmmt_id }}';
|
||||
var sf_file_url = '{{ SITE_ROOT }}office-convert/static/{{ repo.id }}/' + commit_id + '{{ path|urlencode }}/fake.pdf';
|
||||
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
|
||||
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
|
||||
</script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script>
|
||||
{% endblock %}
|
||||
|
@ -16,6 +16,7 @@ window.app.pageOptions = {
|
||||
shareLinkExpireDaysDefault: {{ share_link_expire_days_default }},
|
||||
shareLinkExpireDaysMin: {{ share_link_expire_days_min }},
|
||||
shareLinkExpireDaysMax: {{ share_link_expire_days_max }},
|
||||
thumbnailSizeForOriginal: {{ thumbnail_size_for_original }},
|
||||
|
||||
// for all types of files
|
||||
fileName: '{{ filename|escapejs }}',
|
||||
|
@ -40,6 +40,7 @@ window.app.pageOptions = {
|
||||
<script type="text/javascript">
|
||||
var sf_file_url = '{{ raw_path|escapejs }}';
|
||||
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
|
||||
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
|
||||
</script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/viewer.js"></script>
|
||||
|
@ -16,6 +16,7 @@
|
||||
<script type="text/javascript">
|
||||
var sf_file_url = '{{ raw_path|escapejs }}';
|
||||
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
|
||||
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
|
||||
</script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/viewer.js"></script>
|
||||
|
@ -93,6 +93,7 @@
|
||||
<script type="text/javascript">
|
||||
var sf_file_url = '{{ raw_path|escapejs }}';
|
||||
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
|
||||
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
|
||||
</script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/viewer.js"></script>
|
||||
@ -102,6 +103,7 @@
|
||||
var commit_id = '{{ current_commit.id }}' || '{{ repo.head_cmmt_id }}';
|
||||
var sf_file_url = '{{ SITE_ROOT }}office-convert/static/{{ repo.id }}/' + commit_id + '{{ path|urlencode }}/fake.pdf?token={{shared_token}}';
|
||||
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
|
||||
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
|
||||
</script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script>
|
||||
{% elif filetype == 'SpreadSheet' %}
|
||||
|
@ -62,6 +62,7 @@ OfficePreviewer.prototype.check_status = function() {
|
||||
var commit_id = '{{ current_commit.id }}' || '{{ repo.head_cmmt_id }}';
|
||||
var sf_file_url = '{{ SITE_ROOT }}office-convert/static/{{ repo.id }}/' + commit_id + '{{ path|urlencode }}/fake.pdf?token={{shared_token}}';
|
||||
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
|
||||
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
|
||||
OfficePreviewer.prototype.load_page = function() {
|
||||
$.getScript('{{MEDIA_URL}}js/pdf/viewer.js');
|
||||
};
|
||||
|
@ -10,6 +10,7 @@
|
||||
<script type="text/javascript">
|
||||
var sf_file_url = "{{ raw_path|escapejs }}";
|
||||
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
|
||||
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
|
||||
</script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/viewer.js"></script>
|
||||
|
@ -18,6 +18,7 @@
|
||||
<script type="text/javascript">
|
||||
var sf_file_url = "{{ raw_path|escapejs }}";
|
||||
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
|
||||
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
|
||||
</script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/viewer.js"></script>
|
||||
|
@ -226,6 +226,7 @@ urlpatterns = [
|
||||
url(r'^my-libs/$', react_fake_view, name="my_libs"),
|
||||
url(r'^groups/$', react_fake_view, name="groups"),
|
||||
url(r'^group/(?P<group_id>\d+)/$', react_fake_view, name="group"),
|
||||
url(r'^library/(?P<repo_id>[-0-9a-f]{36})/$', react_fake_view, name="library_view"),
|
||||
url(r'^library/(?P<repo_id>[-0-9a-f]{36})/(?P<repo_name>[^/]+)/(?P<path>.*)$', react_fake_view, name="lib_view"),
|
||||
url(r'^my-libs/deleted/$', react_fake_view, name="my_libs_deleted"),
|
||||
url(r'^org/$', react_fake_view, name="org"),
|
||||
|
@ -531,6 +531,7 @@ def view_lib_file(request, repo_id, path):
|
||||
'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX,
|
||||
'can_download_file': parse_repo_perm(permission).can_download,
|
||||
'seafile_collab_server': SEAFILE_COLLAB_SERVER,
|
||||
'thumbnail_size_for_original': settings.THUMBNAIL_SIZE_FOR_ORIGINAL,
|
||||
}
|
||||
|
||||
# check whether file is starred
|
||||
|
Loading…
Reference in New Issue
Block a user