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

[lib] modified file/dir mv/cp and other improvement & bugfix

This commit is contained in:
llj
2015-02-06 14:25:36 +08:00
committed by Daniel Pan
parent 86fc129add
commit 11779c91bc
7 changed files with 235 additions and 72 deletions

View File

@@ -32,12 +32,35 @@ define([
// initialize common js behavior // initialize common js behavior
$('th .checkbox-orig').unbind(); $('th .checkbox-orig').unbind();
// get 'more'
var _this = this; var _this = this;
$(window).scroll(function() { $(window).scroll(function() {
if ($(_this.el).is(':visible')) { if ($(_this.el).is(':visible')) {
_this.onWindowScroll(); _this.onWindowScroll();
} }
}); });
// hide 'hidden-op' popup
app.globalState.noFileOpPopup = true;
$(document).click(function(e) {
var target = e.target || event.srcElement;
var popup = $('.hidden-op');
if (!app.globalState.noFileOpPopup &&
!$('.more-op-icon, .hidden-op').is(target) &&
!popup.find('*').is(target)) {
popup.addClass('hide');
app.globalState.noFileOpPopup = true;
if (!app.globalState.popup_tr.find('*').is(target)) {
app.globalState.popup_tr.removeClass('hl').find('.repo-file-op').addClass('vh'); // clicked place: the first tr, place out of the table
$('.repo-file-list tr:gt(0)').each(function() { // when other tr is clicked
if ($(this).find('*').is(target)) {
$(this).addClass('hl').find('.repo-file-op').removeClass('vh');
}
});
}
}
});
}, },
showDir: function(repo_id, path) { showDir: function(repo_id, path) {

View File

@@ -18,28 +18,23 @@ define([
shareTemplate: _.template($("#share-dialog-template").html()), shareTemplate: _.template($("#share-dialog-template").html()),
renameTemplate: _.template($("#rename-form-template").html()), renameTemplate: _.template($("#rename-form-template").html()),
mvcpTemplate: _.template($("#mvcp-form-template").html()), mvcpTemplate: _.template($("#mvcp-form-template").html()),
mvProgressTemplate: _.template($("#mv-progress-popup-template").html()),
initialize: function(options) { initialize: function(options) {
this.options = options || {};
this.model = options.model;
this.dirView = options.dirView; this.dirView = options.dirView;
this.dir = this.dirView.dir;
app.globalState.noFileOpPopup = true;
this.listenTo(this.model, "change", this.render); this.listenTo(this.model, "change", this.render);
//Backbone.View.prototype.initialize.apply(this, arguments);
}, },
render: function() { render: function() {
var dirent_path = Common.pathJoin([this.dirView.dir.path, var dir = this.dir;
this.model.attributes.obj_name]);
//console.log(Common.pathJointhis.dirView.dir.path + "/" + this.model.attributes.obj_name);
this.$el.html(this.template({ this.$el.html(this.template({
dirent: this.model.attributes, dirent: this.model.attributes,
repo_id: this.dirView.dir.repo_id, dirent_path: Common.pathJoin([dir.path, this.model.get('obj_name')]),
// dir_path: this.dirView.dir.path, repo_id: dir.repo_id,
dirent_path: dirent_path, user_perm: dir.user_perm,
user_perm: this.dirView.dir.user_perm, repo_encrypted: dir.encrypted
repo_encrypted: this.dirView.dir.encrypted
})); }));
return this; return this;
}, },
@@ -107,10 +102,10 @@ define([
}); });
}, },
visitDir: function () { visitDir: function () { // todo
// show 'loading' // show 'loading'
this.$('.dirent-icon img').attr({ this.$('.dirent-icon img').attr({
'src': app.config.mediaURL + 'img/loading-icon.gif', 'src': app.config.mediaUrl + 'img/loading-icon.gif',
'alt':'' 'alt':''
}); });
// empty all models // empty all models
@@ -123,7 +118,7 @@ define([
togglePopup: function () { togglePopup: function () {
var icon = this.$('.more-op-icon'), var icon = this.$('.more-op-icon'),
popup = this.$('.hidden-op'); popup = this.$('.hidden-op');
if (popup.hasClass('hide')) { // the popup is not shown if (popup.hasClass('hide')) { // the popup is not shown
if (icon.position().left + icon.width() + popup.outerWidth() < icon.parent().width()) { if (icon.position().left + icon.width() + popup.outerWidth() < icon.parent().width()) {
@@ -136,7 +131,7 @@ define([
} else { } else {
popup.css({'right':0}); popup.css({'right':0});
if (icon.offset().top + popup.height() <= $('#main').offset().top + $('#main').height()) { if (icon.offset().top + popup.height() <= $('#main').offset().top + $('#main').height()) {
popup.css('top', icon.position().top + icon.height() + 3); popup.css('top', icon.position().top + icon.height() + 6);
} else { } else {
popup.css('bottom', icon.position().top + icon.height() + 3); popup.css('bottom', icon.position().top + icon.height() + 3);
} }
@@ -191,17 +186,18 @@ define([
delete: function() { delete: function() {
var dirent_name = this.model.get('obj_name'); var dirent_name = this.model.get('obj_name');
var options = {repo_id: this.dirView.dir.repo_id}; var options = {
options.name = this.model.get('is_dir') ? 'del_dir' : 'del_file'; repo_id: this.dirView.dir.repo_id,
var url_main = Common.getUrl(options); name: this.model.get('is_dir') ? 'del_dir' : 'del_file'
};
var el = this.$el; var el = this.$el;
$.ajax({ $.ajax({
url: url_main + '?parent_dir=' + encodeURIComponent(this.dirView.dir.path) url: Common.getUrl(options) + '?parent_dir=' + encodeURIComponent(this.dirView.dir.path)
+ '&name=' + encodeURIComponent(dirent_name), + '&name=' + encodeURIComponent(dirent_name),
dataType: 'json', dataType: 'json',
success: function(data) { success: function(data) {
el.remove(); el.remove();
app.globalState.noFileOpPopup = true;// make other items can work normally when hover app.globalState.noFileOpPopup = true; // make other items can work normally when hover
var msg = gettext("Successfully deleted %(name)s"); var msg = gettext("Successfully deleted %(name)s");
msg = msg.replace('%(name)s', dirent_name); msg = msg.replace('%(name)s', dirent_name);
Common.feedback(msg, 'success'); Common.feedback(msg, 'success');
@@ -213,20 +209,20 @@ define([
rename: function() { rename: function() {
var is_dir = this.model.get('is_dir'); var is_dir = this.model.get('is_dir');
//var hd_text = is_dir ? "{% trans "Rename Directory" %}" : "{% trans "Rename File" %}";
var title = is_dir ? gettext("Rename Directory") : gettext("Rename File"); var title = is_dir ? gettext("Rename Directory") : gettext("Rename File");
//var op_detail = $('.detail', form);
//op_detail.html(op_detail.html().replace('%(name)s', '<span class="op-target">' + dirent_name + '</span>'));
var dirent_name = this.model.get('obj_name'); var dirent_name = this.model.get('obj_name');
var form = $(this.renameTemplate({ var form = $(this.renameTemplate({
form_title: title, form_title: title,
dirent_name: dirent_name, dirent_name: dirent_name
})); }));
form.modal(); form.modal({focus:false}); // For 'newname' input: if use the default 'focus:true', text in it will be selected.
var form_id = form.attr('id');
$('#simplemodal-container').css({'width':'auto', 'height':'auto'}); $('#simplemodal-container').css({'width':'auto', 'height':'auto'});
var op_detail = $('.detail', form);
op_detail.html(op_detail.html().replace('%(name)s', '<span class="op-target">' + dirent_name + '</span>'));
var form_id = form.attr('id');
var _this = this; var _this = this;
var dir = this.dirView.dir; var dir = this.dirView.dir;
form.submit(function() { form.submit(function() {
@@ -239,29 +235,35 @@ define([
Common.showFormError(form_id, gettext("You have not renamed it.")); Common.showFormError(form_id, gettext("You have not renamed it."));
return false; return false;
} }
var post_data = {'oldname': dirent_name, 'newname':new_name}; var post_data = {
var options = { repo_id: dir.repo_id }; 'oldname': dirent_name,
options.name = is_dir ? 'rename_dir' : 'rename_file'; 'newname': new_name
var post_url = Common.getUrl(options) + '?parent_dir=' + encodeURIComponent(dir.path); };
var post_url = Common.getUrl({
name: is_dir ? 'rename_dir' : 'rename_file',
repo_id: dir.repo_id
}) + '?parent_dir=' + encodeURIComponent(dir.path);
var after_op_success = function (data) { var after_op_success = function (data) {
new_name = data['newname']; var renamed_dirent_data = {
var now = new Date().getTime()/1000; 'obj_name': data['newname'],
$.modal.close(); 'last_modified': new Date().getTime()/1000,
_this.model.set({ // it will trigger 'change' event 'last_update': gettext("Just now"),
'obj_name': new_name,
'last_modified': now,
//'last_update': "{% trans "Just now" %}",
'last_update': "Just now",
'sharelink': '', 'sharelink': '',
'sharetoken': '' 'sharetoken': ''
}); };
if (is_dir) { if (is_dir) {
/*
$.extend(renamed_dirent_data, {
'p_dpath': data['p_dpath']
});
*/
} else { } else {
_this.model.set({ $.extend(renamed_dirent_data, {
'starred': false 'starred': false
}); });
} }
$.modal.close();
_this.model.set(renamed_dirent_data); // it will trigger 'change' event
}; };
Common.ajaxPost({ Common.ajaxPost({
'form': form, 'form': form,
@@ -276,39 +278,182 @@ define([
}, },
mvcp: function() { mvcp: function() {
var dir = this.dir;
var el = event.target || event.srcElement, var el = event.target || event.srcElement,
op_type = $(el).hasClass('mv') ? 'mv':'cp', op_type = $(el).hasClass('mv') ? 'mv' : 'cp',
obj_name = this.model.get('obj_name'), obj_name = this.model.get('obj_name'),
obj_type = this.model.get('is_dir') ? 'dir':'file'; obj_type = this.model.get('is_dir') ? 'dir' : 'file';
var title; var title;
if (op_type == 'mv') if (op_type == 'mv') {
title = gettext("Move {placeholder} to:") title = gettext("Move {placeholder} to:")
.replace('{placeholder}', '<span class="op-target">' + obj_name + '</span>'); .replace('{placeholder}', '<span class="op-target">' + obj_name + '</span>');
else } else {
title = gettext("Copy {placeholder} to:") title = gettext("Copy {placeholder} to:")
.replace('{placeholder}', '<span class="op-target">' + obj_name + '</span>'); .replace('{placeholder}', '<span class="op-target">' + obj_name + '</span>');
}
var form = $(this.mvcpTemplate({ var form = $(this.mvcpTemplate({
form_title: title, form_title: title,
op_type: op_type, op_type: op_type,
obj_type: obj_type, obj_type: obj_type,
obj_name: obj_name, obj_name: obj_name,
show_other_repos: !this.dirView.dir.encrypted, show_other_repos: !dir.encrypted,
})); }));
form.modal({appendTo:'#main', autoResize:true, focus:false}); form.modal({appendTo:'#main', autoResize:true, focus:false});
$('#simplemodal-container').css({'width':'auto', 'height':'auto'}); $('#simplemodal-container').css({'width':'auto', 'height':'auto'});
FileTree.renderTreeForPath({ FileTree.renderTreeForPath({
repo_name: this.dirView.dir.repo_name, repo_name: dir.repo_name,
repo_id: this.dirView.dir.repo_id, repo_id: dir.repo_id,
path: this.dirView.dir.path, path: dir.path
}); });
if (!this.dirView.dir.encrypted) { if (!dir.encrypted) {
FileTree.prepareOtherReposTree({cur_repo_id: this.dirView.dir.repo_id}); FileTree.prepareOtherReposTree({cur_repo_id: dir.repo_id});
} }
var dirent = this.$el;
var _this = this;
form.submit(function() {
var form = $(this),
form_id = form.attr('id'),
path = dir.path,
repo_id = dir.repo_id;
var dst_repo = $('[name="dst_repo"]', form).val(),
dst_path = $('[name="dst_path"]', form).val(),
op = $('[name="op"]', form).val(),
obj_name = $('[name="obj_name"]', form).val(),
obj_type = $('[name="obj_type"]', form).val();
if (!$.trim(dst_repo) || !$.trim(dst_path)) {
$('.error', form).removeClass('hide');
return false;
}
if (dst_repo == repo_id && (dst_path == path || (obj_type == 'dir' && dst_path == path + obj_name + '/'))) {
$('.error', form).html(gettext("Invalid destination path")).removeClass('hide');
return false;
}
var options = { repo_id: repo_id };
if (obj_type == 'dir') {
options.name = op == 'mv' ? 'mv_dir' : 'cp_dir';
} else {
options.name = op == 'mv' ? 'mv_file' : 'cp_file';
}
var post_url = Common.getUrl(options) + '?path=' + encodeURIComponent(path) + '&obj_name=' + encodeURIComponent(obj_name);
var post_data = {
'dst_repo': dst_repo,
'dst_path': dst_path
};
var after_op_success = function(data) {
$.modal.close();
var msg = data['msg'];
if (!data['task_id']) { // no progress
if (op == 'mv') {
dirent.remove();
}
Common.feedback(msg, 'success');
} else {
var mv_progress_popup = $(_this.mvProgressTemplate());
var details = $('#mv-details'),
cancel_btn = $('#cancel-mv'),
other_info = $('#mv-other-info');
cancel_btn.removeClass('hide');
setTimeout(function () {
mv_progress_popup.modal({containerCss: {
width: 300,
height: 150,
paddingTop: 50
}, focus:false});
var det_text = op == 'mv' ? gettext("Moving %(name)s") : gettext("Copying %(name)s");
details.html(det_text.replace('%(name)s', obj_name));
$('#mv-progress').progressbar();
req_progress();
}, 100);
var req_progress = function () {
$.ajax({
url: Common.getUrl({name: 'get_cp_progress'}) + '?task_id=' + encodeURIComponent(data['task_id']),
dataType: 'json',
success: function(data) {
var bar = $('.ui-progressbar-value', $('#mv-progress'));
if (!data['failed'] && !data['canceled'] && !data['successful']) {
if (data['done'] == data['total']) {
bar.css('width', '100%'); // 'done' and 'total' can be both 0
details.addClass('vh');
cancel_btn.addClass('hide');
other_info.html(gettext("Saving...")).removeClass('hide');
} else {
bar.css('width', parseInt(data['done']/data['total']*100, 10) + '%');
}
bar.show();
setTimeout(req_progress, 1000);
} else if (data['successful']) {
$.modal.close();
if (op == 'mv') {
dirent.remove();
}
Common.feedback(msg, 'success');
} else { // failed or canceled
details.addClass('vh');
var other_msg = data['failed'] ? gettext("Failed.") : gettext("Canceled.");
other_info.html(other_msg).removeClass('hide');
cancel_btn.addClass('hide');
setTimeout(function () { $.modal.close(); }, 1000);
}
},
error: function(xhr, textStatus, errorThrown) {
var error;
if (xhr.responseText) {
error = $.parseJSON(xhr.responseText).error;
} else {
error = gettext("Failed. Please check the network.");
}
details.addClass('vh')
other_info.html(error).removeClass('hide');
cancel_btn.addClass('hide');
setTimeout(function () { $.modal.close(); }, 1000);
}
});
};
cancel_btn.click(function() {
Common.disableButton(cancel_btn);
$.ajax({
url: Common.getUrl({name: 'cancel_cp'}) + '?task_id=' + encodeURIComponent(data['task_id']),
dataType: 'json',
success: function(data) {
details.addClass('vh')
other_info.html(gettext("Canceled.")).removeClass('hide');
cancel_btn.addClass('hide');
setTimeout(function () {$.modal.close();}, 1000);
},
error: function(xhr, textStatus, errorThrown) {
var error;
if (xhr.responseText) {
error = $.parseJSON(xhr.responseText).error;
} else {
error = gettext("Failed. Please check the network.");
}
other_info.html(error).removeClass('hide');
Common.enableButton(cancel_btn);
}
});
});
}
}
Common.ajaxPost({
'form': form,
'post_url': post_url,
'post_data': post_data,
'after_op_success': after_op_success,
'form_id': form_id
});
return false;
});
return false; return false;
}, },
updateFile: function () {
}
}); });
return DirentView; return DirentView;

View File

@@ -61,8 +61,8 @@ define([
case 'get_dirents': return siteRoot + 'ajax/repo/' + options.repo_id + '/dirents/'; case 'get_dirents': return siteRoot + 'ajax/repo/' + options.repo_id + '/dirents/';
case 'thumbnail_create': return siteRoot + 'thumbnail/' + options.repo_id + '/create/'; case 'thumbnail_create': return siteRoot + 'thumbnail/' + options.repo_id + '/create/';
case 'unenc_rw_repos': return siteRoot + 'ajax/unenc-rw-repos/'; case 'unenc_rw_repos': return siteRoot + 'ajax/unenc-rw-repos/';
case 'get_cp_progress': return ''; case 'get_cp_progress': return siteRoot + 'ajax/cp_progress/';
case 'cancel_cp': return ''; case 'cancel_cp': return siteRoot + 'ajax/cancel_cp/';
case 'get_shared_link': return ''; case 'get_shared_link': return '';
case 'get_shared_upload_link': return ''; case 'get_shared_upload_link': return '';
} }

View File

@@ -6,7 +6,7 @@ define([
], function($, _, Backbone, Common) { ], function($, _, Backbone, Common) {
'use strict'; 'use strict';
$.jstree._themes = app.config.mediaURL + 'js/themes/'; $.jstree._themes = app.config.mediaUrl + 'js/themes/';
var FileTree = { var FileTree = {
@@ -195,7 +195,7 @@ define([
loading_tip = container.prev(); loading_tip = container.prev();
var repo_name = options.repo_name, var repo_name = options.repo_name,
repo_id = options.repo_id; repo_id = options.repo_id;
var cur_path = options.path; var cur_path = options.path;
if (cur_path != '/') { if (cur_path != '/') {
cur_path += '/'; cur_path += '/';

View File

@@ -8,7 +8,7 @@
<%= groups[i].avatar %> <%= groups[i].avatar %>
<span class="name ellipsis vam"><%= groups[i].name %></span> <span class="name ellipsis vam"><%= groups[i].name %></span>
<a href="<%= app.config.siteRoot %>group/<%= groups[i].id %>/discuss/" title="Discussion" class="a fright vh"> <a href="<%= app.config.siteRoot %>group/<%= groups[i].id %>/discuss/" title="Discussion" class="a fright vh">
<img src="<%= app.config.mediaURL %>img/msgs.png" alt=""> <img src="<%= app.config.mediaUrl %>img/msgs.png" alt="" />
</a> </a>
</li> </li>
<% } %> <% } %>

View File

@@ -42,7 +42,7 @@
<h3><%= form_title %></h3> <h3><%= form_title %></h3>
<p class="detail">{% trans "Rename %(name)s as:" %}</p> <p class="detail">{% trans "Rename %(name)s as:" %}</p>
<input type="hidden" name="oldname" value="<%= dirent_name %>" /> <input type="hidden" name="oldname" value="<%= dirent_name %>" />
<input type="text" name="newname" value="" class="input" maxlength="{{max_file_name}}"/><br /> <input type="text" name="newname" value="<%= dirent_name %>" class="input" maxlength="{{max_file_name}}" /><br />
<p class="error hide"></p> <p class="error hide"></p>
<button type="submit" class="submit">{% trans "Submit" %}</button> <button type="submit" class="submit">{% trans "Submit" %}</button>
<button class="simplemodal-close">{% trans "Cancel" %}</button> <button class="simplemodal-close">{% trans "Cancel" %}</button>
@@ -73,8 +73,11 @@
<button type="submit" class="submit">{% trans "Submit" %}</button> <button type="submit" class="submit">{% trans "Submit" %}</button>
<button class="simplemodal-close">{% trans "Cancel"%}</button> <button class="simplemodal-close">{% trans "Cancel"%}</button>
</form> </form>
</script>
<script type="text/template" id="mv-progress-popup-template">
<div id="mv-progress-popup" class="alc hide"> <div id="mv-progress-popup" class="alc hide">
<p id="mv-details"></p> <p id="mv-details" class="ellipsis"></p>
<div id="mv-progress"></div> <div id="mv-progress"></div>
<p id="mv-other-info" class="hide"></p> <p id="mv-other-info" class="hide"></p>
<button id="cancel-mv">{% trans "Cancel" %}</button> <button id="cancel-mv">{% trans "Cancel" %}</button>

View File

@@ -836,9 +836,7 @@ def mv_file(src_repo_id, src_path, dst_repo_id, dst_path, obj_name, username):
content_type=content_type) content_type=content_type)
result['success'] = True result['success'] = True
msg_url = reverse('repo', args=[dst_repo_id]) + '?p=' + urlquote(dst_path) msg = _(u'Successfully moved %(name)s') % {"name": escape(obj_name)}
msg = _(u'Successfully moved %(name)s <a href="%(url)s">view</a>') % \
{"name":escape(obj_name), "url":msg_url}
result['msg'] = msg result['msg'] = msg
if res.background: if res.background:
result['task_id'] = res.task_id result['task_id'] = res.task_id
@@ -865,9 +863,7 @@ def cp_file(src_repo_id, src_path, dst_repo_id, dst_path, obj_name, username):
content_type=content_type) content_type=content_type)
result['success'] = True result['success'] = True
msg_url = reverse('repo', args=[dst_repo_id]) + '?p=' + urlquote(dst_path) msg = _(u'Successfully copied %(name)s') % {"name":escape(obj_name)}
msg = _(u'Successfully copied %(name)s <a href="%(url)s">view</a>') % \
{"name":escape(obj_name), "url":msg_url}
result['msg'] = msg result['msg'] = msg
if res.background: if res.background:
@@ -912,9 +908,7 @@ def mv_dir(src_repo_id, src_path, dst_repo_id, dst_path, obj_name, username):
content_type=content_type) content_type=content_type)
result['success'] = True result['success'] = True
msg_url = reverse('repo', args=[dst_repo_id]) + '?p=' + urlquote(dst_path) msg = _(u'Successfully moved %(name)s') % {"name":escape(obj_name)}
msg = _(u'Successfully moved %(name)s <a href="%(url)s">view</a>') % \
{"name":escape(obj_name), "url":msg_url}
result['msg'] = msg result['msg'] = msg
if res.background: if res.background:
result['task_id'] = res.task_id result['task_id'] = res.task_id
@@ -957,9 +951,7 @@ def cp_dir(src_repo_id, src_path, dst_repo_id, dst_path, obj_name, username):
content_type=content_type) content_type=content_type)
result['success'] = True result['success'] = True
msg_url = reverse('repo', args=[dst_repo_id]) + '?p=' + urlquote(dst_path) msg = _(u'Successfully copied %(name)s') % {"name":escape(obj_name)}
msg = _(u'Successfully copied %(name)s <a href="%(url)s">view</a>') % \
{"name":escape(obj_name), "url":msg_url}
result['msg'] = msg result['msg'] = msg
if res.background: if res.background:
result['task_id'] = res.task_id result['task_id'] = res.task_id
@@ -2209,7 +2201,7 @@ def ajax_repo_change_passwd(request, repo_id):
}), status=400, content_type=content_type) }), status=400, content_type=content_type)
messages.success(request, _(u'Successfully updated the password of Library %(repo_name)s.') % messages.success(request, _(u'Successfully updated the password of Library %(repo_name)s.') %
{'repo_name': repo.name}) {'repo_name': escape(repo.name)})
return HttpResponse(json.dumps({'success': True}), return HttpResponse(json.dumps({'success': True}),
content_type=content_type) content_type=content_type)