1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-07-15 16:04:01 +00:00

Merge branch '7.0'

This commit is contained in:
plt 2019-06-28 17:49:04 +08:00
commit 0e661f43a3
23 changed files with 120 additions and 13 deletions

View File

@ -15905,9 +15905,9 @@
} }
}, },
"seafile-js": { "seafile-js": {
"version": "0.2.96", "version": "0.2.97",
"resolved": "https://registry.npmjs.org/seafile-js/-/seafile-js-0.2.96.tgz", "resolved": "https://registry.npmjs.org/seafile-js/-/seafile-js-0.2.97.tgz",
"integrity": "sha512-SCZGVo+e8usxrzV6nWX3Qe3LKtpcuxFA78AY9KRbPic5V2ET2c0xmATIpKa2bT7Ji54t8MvVG0mt2D2AiCZ2Sw==", "integrity": "sha512-a7nlJ4FadqPrsF83GkrKZQem6lQLwm/eDhQc5Ovl5UYw3b1VWz/RARhEO70WKVPtwfmShwKTeRyEZCYVW51edg==",
"requires": { "requires": {
"axios": "^0.18.0", "axios": "^0.18.0",
"form-data": "^2.3.2", "form-data": "^2.3.2",

View File

@ -37,7 +37,7 @@
"react-responsive": "^6.1.1", "react-responsive": "^6.1.1",
"react-select": "^2.4.1", "react-select": "^2.4.1",
"reactstrap": "^6.4.0", "reactstrap": "^6.4.0",
"seafile-js": "^0.2.96", "seafile-js": "^0.2.97",
"socket.io-client": "^2.2.0", "socket.io-client": "^2.2.0",
"sw-precache-webpack-plugin": "0.11.4", "sw-precache-webpack-plugin": "0.11.4",
"unified": "^7.0.0", "unified": "^7.0.0",

View File

@ -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() { 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/ // e.g. from http://127.0.0.1:8000/drafts/reviews/
// get reviews // get reviews
// TODO: need refactor later // TODO: need refactor later

View File

@ -86,7 +86,7 @@ class DirPath extends React.Component {
<span className="path-split">/</span> <span className="path-split">/</span>
</Fragment> </Fragment>
)} )}
{currentPath === '/' ? {(currentPath === '/' || currentPath === '') ?
<span>{repoName}</span>: <span>{repoName}</span>:
<a className="path-link" data-path="/" onClick={this.onPathClick}>{repoName}</a> <a className="path-link" data-path="/" onClick={this.onPathClick}>{repoName}</a>
} }

View File

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { gettext, siteRoot } from '../../utils/constants'; import { gettext, siteRoot } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api';
import toaster from '../toast'; import toaster from '../toast';
const { avatarURL, csrfToken } = window.app.pageOptions; const { avatarURL, csrfToken } = window.app.pageOptions;
@ -50,7 +51,25 @@ class UserAvatarForm extends React.Component {
return false; 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 = () => { openFileInput = () => {
@ -75,7 +94,7 @@ class UserAvatarForm extends React.Component {
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} /> <input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
<label className="col-sm-1 col-form-label">{gettext('Avatar:')}</label> <label className="col-sm-1 col-form-label">{gettext('Avatar:')}</label>
<div className="col-auto position-relative" onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}> <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} /> <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> <span className={`avatar-edit fas fa-edit ${!this.state.isEditShown && 'd-none'}`} onClick={this.openFileInput}></span>
</div> </div>

View File

@ -86,6 +86,30 @@
background: #ff0; background: #ff0;
box-shadow: 0px 2px 10px #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 */ /* annotationLayer ends */
#fileInput { #fileInput {
display:none; display:none;

View File

@ -9,6 +9,8 @@ class Group {
this.parent_group_id = object.parent_group_id; this.parent_group_id = object.parent_group_id;
this.wiki_enabled = object.wiki_enabled; this.wiki_enabled = object.wiki_enabled;
this.repos = object.repos || []; this.repos = object.repos || [];
this.group_quota = object.group_quota;
this.group_quota_usage = object.group_quota_usage;
} }
} }

View File

@ -388,7 +388,10 @@ class GroupView extends React.Component {
<span className="path-split">/</span> <span className="path-split">/</span>
<span>{currentGroup.name}</span> <span>{currentGroup.name}</span>
{currentGroup.parent_group_id !== 0 && ( {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>
<div className="path-tool"> <div className="path-tool">

View File

@ -9,7 +9,7 @@ import './css/image-file-view.css';
const { const {
repoID, filePath, err, repoID, filePath, err,
fileName, previousImage, nextImage, rawPath fileName, previousImage, nextImage, rawPath, thumbnailSizeForOriginal,
} = window.app.pageOptions; } = window.app.pageOptions;
let previousImageUrl, nextImageUrl; let previousImageUrl, nextImageUrl;
@ -30,6 +30,14 @@ class ViewFileImage extends React.Component {
class FileContent extends React.Component { class FileContent extends React.Component {
constructor(props) {
super(props);
this.state = {
thumbnailError: false,
};
this.thumbnailSuffixList = ['tiff', 'eps', 'psd'];
}
componentDidMount() { componentDidMount() {
document.addEventListener('keydown', (e) => { document.addEventListener('keydown', (e) => {
if (previousImage && e.keyCode == 37) { // press '<-' if (previousImage && e.keyCode == 37) { // press '<-'
@ -41,10 +49,20 @@ class FileContent extends React.Component {
}); });
} }
handleError = () => {
this.setState({
thumbnailError: true
});
};
render() { render() {
if (err) { if (err || this.state.thumbnailError) {
return <FileViewTip />; return <FileViewTip />;
} }
let thumbnailUrl = `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${Utils.encodePath(filePath)}`;
let imageSuffix = fileName.split('.').pop();
let isPreviewThumbnail = this.thumbnailSuffixList.includes(imageSuffix);
return ( return (
<div className="file-view-content flex-1 image-file-view"> <div className="file-view-content flex-1 image-file-view">
{previousImage && ( {previousImage && (
@ -53,7 +71,10 @@ class FileContent extends React.Component {
{nextImage && ( {nextImage && (
<a href={nextImageUrl} id="img-next" title={gettext('you can also press →')}><span className="fas fa-chevron-right"></span></a> <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> </div>
); );
} }

View 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

View File

@ -4395,7 +4395,7 @@ var defaultOptions = {
kind: OptionKind.VIEWER kind: OptionKind.VIEWER
}, },
imageResourcesPath: { imageResourcesPath: {
value: './images/', value: sf_pdf_images_path,
kind: OptionKind.VIEWER kind: OptionKind.VIEWER
}, },
maxCanvasPixels: { maxCanvasPixels: {

View File

@ -68,6 +68,12 @@ def get_group_info(request, group_id, avatar_size=GROUP_AVATAR_DEFAULT_SIZE):
"admins": get_group_admins(group.id), "admins": get_group_admins(group.id),
"wiki_enabled": is_wiki_mod_enabled_for_group(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 return group_info

View File

@ -2,6 +2,7 @@
import os import os
import logging import logging
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
@ -23,7 +24,7 @@ from seahub.avatar.templatetags.avatar_tags import api_avatar_url
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class UserAvatarView(APIView): class UserAvatarView(APIView):
authentication_classes = (TokenAuthentication,) authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,) throttle_classes = (UserRateThrottle,)

View File

@ -17,6 +17,7 @@
var commit_id = '{{ current_commit.id }}' || '{{ repo.head_cmmt_id }}'; 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_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_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
</script> </script>
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script> <script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script>
{% endblock %} {% endblock %}

View File

@ -16,6 +16,7 @@ window.app.pageOptions = {
shareLinkExpireDaysDefault: {{ share_link_expire_days_default }}, shareLinkExpireDaysDefault: {{ share_link_expire_days_default }},
shareLinkExpireDaysMin: {{ share_link_expire_days_min }}, shareLinkExpireDaysMin: {{ share_link_expire_days_min }},
shareLinkExpireDaysMax: {{ share_link_expire_days_max }}, shareLinkExpireDaysMax: {{ share_link_expire_days_max }},
thumbnailSizeForOriginal: {{ thumbnail_size_for_original }},
// for all types of files // for all types of files
fileName: '{{ filename|escapejs }}', fileName: '{{ filename|escapejs }}',

View File

@ -40,6 +40,7 @@ window.app.pageOptions = {
<script type="text/javascript"> <script type="text/javascript">
var sf_file_url = '{{ raw_path|escapejs }}'; var sf_file_url = '{{ raw_path|escapejs }}';
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js'; var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
</script> </script>
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></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> <script type="text/javascript" src="{{MEDIA_URL}}js/pdf/viewer.js"></script>

View File

@ -16,6 +16,7 @@
<script type="text/javascript"> <script type="text/javascript">
var sf_file_url = '{{ raw_path|escapejs }}'; var sf_file_url = '{{ raw_path|escapejs }}';
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js'; var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
</script> </script>
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></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> <script type="text/javascript" src="{{MEDIA_URL}}js/pdf/viewer.js"></script>

View File

@ -93,6 +93,7 @@
<script type="text/javascript"> <script type="text/javascript">
var sf_file_url = '{{ raw_path|escapejs }}'; var sf_file_url = '{{ raw_path|escapejs }}';
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js'; var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
</script> </script>
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></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> <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 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_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_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
</script> </script>
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script> <script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></script>
{% elif filetype == 'SpreadSheet' %} {% elif filetype == 'SpreadSheet' %}

View File

@ -62,6 +62,7 @@ OfficePreviewer.prototype.check_status = function() {
var commit_id = '{{ current_commit.id }}' || '{{ repo.head_cmmt_id }}'; 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_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_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() { OfficePreviewer.prototype.load_page = function() {
$.getScript('{{MEDIA_URL}}js/pdf/viewer.js'); $.getScript('{{MEDIA_URL}}js/pdf/viewer.js');
}; };

View File

@ -10,6 +10,7 @@
<script type="text/javascript"> <script type="text/javascript">
var sf_file_url = "{{ raw_path|escapejs }}"; var sf_file_url = "{{ raw_path|escapejs }}";
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js'; var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
</script> </script>
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></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> <script type="text/javascript" src="{{MEDIA_URL}}js/pdf/viewer.js"></script>

View File

@ -18,6 +18,7 @@
<script type="text/javascript"> <script type="text/javascript">
var sf_file_url = "{{ raw_path|escapejs }}"; var sf_file_url = "{{ raw_path|escapejs }}";
var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js'; var sf_pdfworkerjs_url = '{{MEDIA_URL}}js/pdf/pdf.worker.min.js';
var sf_pdf_images_path = '{{MEDIA_URL}}js/pdf/images/';
</script> </script>
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf/pdf.min.js"></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> <script type="text/javascript" src="{{MEDIA_URL}}js/pdf/viewer.js"></script>

View File

@ -226,6 +226,7 @@ urlpatterns = [
url(r'^my-libs/$', react_fake_view, name="my_libs"), url(r'^my-libs/$', react_fake_view, name="my_libs"),
url(r'^groups/$', react_fake_view, name="groups"), url(r'^groups/$', react_fake_view, name="groups"),
url(r'^group/(?P<group_id>\d+)/$', react_fake_view, name="group"), 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'^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'^my-libs/deleted/$', react_fake_view, name="my_libs_deleted"),
url(r'^org/$', react_fake_view, name="org"), url(r'^org/$', react_fake_view, name="org"),

View File

@ -531,6 +531,7 @@ def view_lib_file(request, repo_id, path):
'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX, 'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX,
'can_download_file': parse_repo_perm(permission).can_download, 'can_download_file': parse_repo_perm(permission).can_download,
'seafile_collab_server': SEAFILE_COLLAB_SERVER, 'seafile_collab_server': SEAFILE_COLLAB_SERVER,
'thumbnail_size_for_original': settings.THUMBNAIL_SIZE_FOR_ORIGINAL,
} }
# check whether file is starred # check whether file is starred