diff --git a/media/css/seahub.css b/media/css/seahub.css index 960214edf8..b0ef7f9fcb 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -481,7 +481,7 @@ textarea:-moz-placeholder {/* for FF */ } /* for messages like 'contact added successfully' */ .messages { - position:absolute; + position:fixed; border-radius: 2px; -webkit-border-radius: 2px; -moz-border-radius: 2px; @@ -490,12 +490,12 @@ textarea:-moz-placeholder {/* for FF */ -webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.2); } .messages .info, -.messages .success{ +.messages .success { padding:5px; background:#C4ECA9; margin:0; } -.messages .error{ +.messages .error { padding:5px; background:#FDF; margin:0; @@ -1365,7 +1365,6 @@ textarea:-moz-placeholder {/* for FF */ text-align:right; } #shared-link { - display: inline-block; border:0; } .file-op { diff --git a/media/js/utils.js b/media/js/utils.js index 7227b1fc98..f232545f6f 100644 --- a/media/js/utils.js +++ b/media/js/utils.js @@ -277,17 +277,14 @@ function prepareCSRFToken(xhr, settings) { } function apply_form_error(formid, error_msg) { - var form_err = $("#" + formid + " .error"), - container = $("#simplemodal-container"); - - form_err.html(error_msg).attr('class', 'error').removeClass('hide'); - container.css('height', $('#'+formid).height()); + $("#" + formid + " .error").html(error_msg).removeClass('hide'); + $("#simplemodal-container").css({'height':'auto'}); } // handle messages if ($('.messages')[0]) { - $('#main').append($('.messages')).css('position','relative'); - $('.messages').css({'left':($('#main').width() - $('.messages').width())/2 + 'px', 'top':'-20px'}).removeClass('hide'); + $('#main').append($('.messages')); + $('.messages').css({'left':($(window).width() - $('.messages').width())/2, 'top':10}).removeClass('hide'); setTimeout(function() { $('.messages').addClass('hide'); }, 10000); } @@ -300,14 +297,24 @@ function feedback(con, type, time) { var html = ''; $('#main').append(html); } - $('#main').css('position','relative'); - $('.messages').css({'left':($('#main').width() - $('.messages').width())/2 + 'px', 'top':'-20px'}).removeClass('hide'); + $('.messages').css({'left':($(window).width() - $('.messages').width())/2, 'top':10}).removeClass('hide'); setTimeout(function() { $('.messages').addClass('hide'); }, time); } - function disable(btn) { btn.attr('disabled', 'disabled').addClass('btn-disabled'); } function enable(btn) { btn.removeAttr('disabled').removeClass('btn-disabled'); } + +// get substr according to character numbers +function trimByChar(str, n) { + var len = str.length; + var new_str = ''; + if (len > n) { + new_str = str.substr(0, n) + '...'; + } else { + new_str = str; + } + return new_str; +} diff --git a/share/views.py b/share/views.py index d26b882c25..f7f52f3a3c 100644 --- a/share/views.py +++ b/share/views.py @@ -379,7 +379,6 @@ def get_shared_link(request): content_type = 'application/json; charset=utf-8' repo_id = request.GET.get('repo_id') - obj_id = request.GET.get('obj_id') path = request.GET.get('p', '/') if path[-1] == '/': path = path[:-1] @@ -401,7 +400,7 @@ def get_shared_link(request): try: fs.save() except IntegrityError, e: - err = _('Failed to get shared link, please retry.') + err = _('Failed to get the link, please retry it.') data = json.dumps([{'error': err}]) return HttpResponse(data, status=500, content_type=content_type) @@ -466,11 +465,11 @@ def send_shared_link(request): } try: - send_mail(_(u'Your friend sharing a file to you on Seafile'), + send_mail(_(u'Your friend shared a file to you on Seafile'), t.render(Context(c)), None, [to_email], fail_silently=False) except: - data = json.dumps({'error':_(u'Failed to send mail')}) + data = json.dumps({'error':_(u'Send failed.')}) return HttpResponse(data, status=500, content_type=content_type) data = json.dumps("success") diff --git a/templates/file_view.html b/templates/file_view.html index 2af0f6eb72..d2f570e441 100644 --- a/templates/file_view.html +++ b/templates/file_view.html @@ -25,7 +25,7 @@
- + {% if is_starred %} @@ -82,7 +82,7 @@
{% if user_perm == 'rw' %} @@ -280,6 +281,20 @@ +
+

{% trans 'Share' %}

+

{% trans 'Link: ' %}

+ + +
+ {% with attach_type='dir' %} {% include "snippets/group_recommend_form.html" %} {% endwith %} @@ -704,6 +719,112 @@ $('.file-star').click(function() { } }); }); +//file share +function trimFilename(name, n) { + var len = name.length; + var ext = ''; + var str = ''; + if (len > n) { + if (name.lastIndexOf('.') != -1) { // with extension + ext = name.split('.').reverse()[0]; + str = name.substr(0, n - ext.length - 3) + '...' + name.substr(name.lastIndexOf('.') - 2); + } else { + str = name.substr(0, n) + '...'; + } + } else { + str = name; + } + return str; +} +$('.file-share').click(function() { + var filename = $(this).data('name'); + function showPopup(link) { + $('#file-share .op-target').html(trimFilename(filename, 30)); + $('#shared-link, #link-send-form input[name="file_shared_link"]').val(link); + $('#main').append('

' + link + '

'); + $('#shared-link').css({'width':$('#linkwidth').width() + 2}); + $('#file-share').modal({'focus':false}); // in ff: if 'focus' is true, 'shared-link' gets the focus + $('#linkwidth').remove(); + $('#simplemodal-container').css({'width':'auto', 'height':'auto'}); + } + if ($(this).data('link')) { + showPopup($(this).data('link')); + } else { + $.ajax({ + url: '{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p={{ path|urlencode }}' + e(filename), + dataType: 'json', + cache: false, + contentType: 'application/json; charset=utf-8', + success: function(data) { + if (data.length > 0) { + showPopup('{{ protocol }}://{{ domain }}{{ SITE_ROOT }}f/' + data[0]['token'] + '/'); + } + }, + error: function(xhr, ajaxOptions, thrownError) { + var jsonVal = jQuery.parseJSON(xhr.responseText); + feedback(jsonVal[0]['error'], 'error'); + } + }); + } + return false; +}); + +var share_list = []; +{% for contact in contacts %} +share_list.push({value:'{{ contact.contact_email }}', label:'{{ contact.contact_email }}'}); +{% endfor %} +$('#send-link').click(function() { + $(this).addClass('hide'); + var input = $('#link-send-input'); + input.css({'min-width':input.css('width'), 'width': $('#file-share').width() - parseInt(input.css('padding-left')) - parseInt(input.css('padding-right')) - parseInt(input.css('border-left-width')) - parseInt(input.css('border-right-width'))}); + $('#link-send-form').removeClass('hide'); + addAutocomplete('#link-send-input', '#link-send-form', share_list); +}); +$("#link-send-form").submit(function() { + var form = $(this), + file_shared_link = form.children('input[name="file_shared_link"]').val(), + email = $.trim(form.children('textarea[name="email"]').val()), + submit_btn = form.children('input[type="submit"]'), + err = form.children('.error'); + + if (!email) { + err.html('{% trans "Please input at least an email." %}').removeClass('hide'); + return false; + } + + disable(submit_btn); + err.addClass('hide'); + $('#sending').removeClass('hide'); + + $.ajax({ + type: "POST", + url: "{% url 'send_shared_link' %}", + dataType: 'json', + cache: false, + contentType: 'application/json; charset=utf-8', + beforeSend: prepareCSRFToken, + data: {file_shared_link: file_shared_link, email: email}, + success: function(data) { + $.modal.close(); + feedback('{% trans "Successfully shared." %}', "success"); + }, + error: function(data, textStatus, jqXHR) { + $('#sending').addClass('hide'); + enable(submit_btn); + var errors = $.parseJSON(data.responseText); + $.each(errors, function(index, value) { + if (index == 'error') { + err.html(value); + } else { + err.html(value[0]); + } + err.removeClass('hide'); + }); + } + }); + return false; +}); +$('#shared-link').click(function() { $(this).select(); }); {% include "snippets/list_commit_detail.html" %} {% include "snippets/bottom_bar.html" %} diff --git a/views.py b/views.py index 7089a9899b..53de75cee6 100644 --- a/views.py +++ b/views.py @@ -168,6 +168,10 @@ def get_repo_dirents(request, repo_id, commit, path): org_id = request.user.org['org_id'] starred_files = get_dir_starred_files(request.user.username, repo_id, path, org_id) + fileshares = FileShare.objects.filter(repo_id=repo_id).filter(username=request.user.username) + http_or_https = request.is_secure() and 'https' or 'http' + domain = RequestSite(request).domain + for dirent in dirs: if stat.S_ISDIR(dirent.props.mode): dir_list.append(dirent) @@ -175,9 +179,15 @@ def get_repo_dirents(request, repo_id, commit, path): file_list.append(dirent) dirent.file_size = get_file_size(dirent.obj_id) dirent.starred = False + dirent.sharelink = '' fpath = os.path.join(path, dirent.obj_name) if fpath in starred_files: dirent.starred = True + for share in fileshares: + if fpath == share.path: + dirent.sharelink = '%s://%s%sf/%s/' % (http_or_https, domain, settings.SITE_ROOT, share.token) + dirent.sharetoken = share.token + break dir_list.sort(lambda x, y : cmp(x.obj_name.lower(), y.obj_name.lower())) @@ -254,6 +264,9 @@ class RepoMixin(object): self.file_list, self.dir_list = get_repo_dirents(self.request, self.repo_id, self.current_commit, self.path) self.zipped = self.get_nav_path() self.applet_root = self.get_applet_root() + self.protocol = self.request.is_secure() and 'https' or 'http' + self.domain = RequestSite(self.request).domain + self.contacts = Contact.objects.filter(user_email=self.request.user.username) def get(self, request, *args, **kwargs): self.prepare_property() @@ -359,6 +372,9 @@ class RepoView(LoginRequiredMixin, CtxSwitchRequiredMixin, RepoMixin, kwargs['update_url'] = self.get_update_url() kwargs['httpserver_root'] = self.get_httpserver_root() kwargs['head_id'] = self.repo.head_cmmt_id + kwargs['protocol'] = self.protocol + kwargs['domain'] = self.domain + kwargs['contacts'] = self.contacts return kwargs @@ -1277,9 +1293,7 @@ def repo_view_file(request, repo_id): http_or_https = request.is_secure() and 'https' or 'http' domain = RequestSite(request).domain if fileshare: - file_shared_link = '%s://%s%sf/%s/' % (http_or_https, domain, - settings.SITE_ROOT, - fileshare.token) + file_shared_link = '%s://%s%sf/%s/' % (http_or_https, domain, settings.SITE_ROOT, fileshare.token) else: file_shared_link = ''