mirror of https://github.com/zulip/zulip.git
refactor: Extract upload mechanics to new JS module.
Tweaked by tabbott to move changes from the next commit that are required for this to pass tests into this commit. Note that this exports a few items that were not previously exported.
This commit is contained in:
parent
0445322625
commit
ddaff4cd2a
|
@ -150,6 +150,7 @@
|
|||
"recent_senders": false,
|
||||
"unread_ui": false,
|
||||
"unread_ops": false,
|
||||
"upload": false,
|
||||
"user_events": false,
|
||||
"Plotly": false,
|
||||
"emoji_codes": false,
|
||||
|
|
|
@ -52,6 +52,7 @@ zrequire('stream_data');
|
|||
zrequire('compose_state');
|
||||
zrequire('people');
|
||||
zrequire('compose');
|
||||
zrequire('upload');
|
||||
page_params.use_websockets = false;
|
||||
|
||||
var me = {
|
||||
|
@ -1296,7 +1297,7 @@ function test_with_mock_socket(test_params) {
|
|||
return 'fake-html';
|
||||
};
|
||||
|
||||
compose.uploadStarted();
|
||||
upload.uploadStarted();
|
||||
|
||||
assert.equal($("#compose-send-button").attr("disabled"), '');
|
||||
assert($("#send-status").hasClass("alert-info"));
|
||||
|
@ -1311,7 +1312,7 @@ function test_with_mock_socket(test_params) {
|
|||
assert.equal(width_percent, '39%');
|
||||
width_update_checked = true;
|
||||
};
|
||||
compose.progressUpdated(1, '', 39);
|
||||
upload.progressUpdated(1, '', 39);
|
||||
assert(width_update_checked);
|
||||
}());
|
||||
|
||||
|
@ -1336,7 +1337,7 @@ function test_with_mock_socket(test_params) {
|
|||
|
||||
function test(err, file, msg) {
|
||||
setup_test();
|
||||
compose.uploadError(err, file);
|
||||
upload.uploadError(err, file);
|
||||
// The text function and html function in zjquery is not in sync
|
||||
// with each other. QuotaExceeded changes html while all other errors
|
||||
// changes body.
|
||||
|
@ -1420,7 +1421,7 @@ function test_with_mock_socket(test_params) {
|
|||
}
|
||||
|
||||
setup();
|
||||
compose.uploadFinished(i, {}, response);
|
||||
upload.uploadFinished(i, {}, response);
|
||||
assert_side_effects();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,113 +19,11 @@ exports.uploads_path = '/user_uploads';
|
|||
exports.uploads_re = new RegExp("\\]\\(" + exports.uploads_domain + "(" + exports.uploads_path + "[^\\)]+)\\)", 'g');
|
||||
exports.clone_file_input = undefined;
|
||||
|
||||
function make_upload_absolute(uri) {
|
||||
if (uri.indexOf(exports.uploads_path) === 0) {
|
||||
// Rewrite the URI to a usable link
|
||||
return exports.uploads_domain + uri;
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
function make_uploads_relative(content) {
|
||||
// Rewrite uploads in markdown links back to domain-relative form
|
||||
return content.replace(exports.uploads_re, "]($1)");
|
||||
}
|
||||
|
||||
// This function resets an input type="file". Pass in the
|
||||
// jquery object.
|
||||
function clear_out_file_list(jq_file_list) {
|
||||
if (exports.clone_file_input !== undefined) {
|
||||
jq_file_list.replaceWith(exports.clone_file_input.clone(true));
|
||||
}
|
||||
// Hack explanation:
|
||||
// IE won't let you do this (untested, but so says StackOverflow):
|
||||
// $("#file_input").val("");
|
||||
}
|
||||
|
||||
exports.uploadStarted = function () {
|
||||
$("#compose-send-button").attr("disabled", "");
|
||||
$("#send-status").addClass("alert-info")
|
||||
.show();
|
||||
$(".send-status-close").one('click', exports.abort_xhr);
|
||||
$("#error-msg").html(
|
||||
$("<p>").text(i18n.t("Uploading…"))
|
||||
.after('<div class="progress progress-striped active">' +
|
||||
'<div class="bar" id="upload-bar" style="width: 00%;"></div>' +
|
||||
'</div>'));
|
||||
};
|
||||
|
||||
exports.progressUpdated = function (i, file, progress) {
|
||||
$("#upload-bar").width(progress + "%");
|
||||
};
|
||||
|
||||
exports.uploadError = function (err, file) {
|
||||
var msg;
|
||||
$("#send-status").addClass("alert-error")
|
||||
.removeClass("alert-info");
|
||||
$("#compose-send-button").prop("disabled", false);
|
||||
switch (err) {
|
||||
case 'BrowserNotSupported':
|
||||
msg = i18n.t("File upload is not yet available for your browser.");
|
||||
break;
|
||||
case 'TooManyFiles':
|
||||
msg = i18n.t("Unable to upload that many files at once.");
|
||||
break;
|
||||
case 'FileTooLarge':
|
||||
// sanitization not needed as the file name is not potentially parsed as HTML, etc.
|
||||
var context = { file_name: file.name };
|
||||
msg = i18n.t('"__file_name__" was too large; the maximum file size is 25MiB.', context);
|
||||
break;
|
||||
case 'REQUEST ENTITY TOO LARGE':
|
||||
msg = i18n.t("Sorry, the file was too large.");
|
||||
break;
|
||||
case 'QuotaExceeded':
|
||||
var translation_part1 = i18n.t('Upload would exceed your maximum quota. You can delete old attachments to free up space.');
|
||||
var translation_part2 = i18n.t('Click here');
|
||||
msg = translation_part1 + ' <a href="#settings/uploaded-files">' + translation_part2 + '</a>';
|
||||
$("#error-msg").html(msg);
|
||||
return;
|
||||
default:
|
||||
msg = i18n.t("An unknown error occurred.");
|
||||
break;
|
||||
}
|
||||
$("#error-msg").text(msg);
|
||||
};
|
||||
|
||||
exports.uploadFinished = function (i, file, response) {
|
||||
if (response.uri === undefined) {
|
||||
return;
|
||||
}
|
||||
var textbox = $("#new_message_content");
|
||||
var split_uri = response.uri.split("/");
|
||||
var filename = split_uri[split_uri.length - 1];
|
||||
// Urgh, yet another hack to make sure we're "composing"
|
||||
// when text gets added into the composebox.
|
||||
if (!compose_state.composing()) {
|
||||
compose_actions.start('stream');
|
||||
}
|
||||
|
||||
var uri = make_upload_absolute(response.uri);
|
||||
|
||||
if (i === -1) {
|
||||
// This is a paste, so there's no filename. Show the image directly
|
||||
textbox.val(textbox.val() + "[pasted image](" + uri + ") ");
|
||||
} else {
|
||||
// This is a dropped file, so make the filename a link to the image
|
||||
textbox.val(textbox.val() + "[" + filename + "](" + uri + ")" + " ");
|
||||
}
|
||||
compose_ui.autosize_textarea();
|
||||
$("#compose-send-button").prop("disabled", false);
|
||||
$("#send-status").removeClass("alert-info")
|
||||
.hide();
|
||||
|
||||
// In order to upload the same file twice in a row, we need to clear out
|
||||
// the #file_input element, so that the next time we use the file dialog,
|
||||
// an actual change event is fired. This is extracted to a function
|
||||
// to abstract away some IE hacks.
|
||||
clear_out_file_list($("#file_input"));
|
||||
};
|
||||
|
||||
function show_all_everyone_warnings() {
|
||||
var stream_count = stream_data.get_subscriber_count(compose_state.stream_name()) || 0;
|
||||
|
||||
|
@ -872,29 +770,7 @@ exports.initialize = function () {
|
|||
Dropbox.choose(options);
|
||||
});
|
||||
|
||||
$("#compose").filedrop({
|
||||
url: "/json/user_uploads",
|
||||
fallback_id: "file_input",
|
||||
paramname: "file",
|
||||
maxfilesize: page_params.maxfilesize,
|
||||
data: {
|
||||
// the token isn't automatically included in filedrop's post
|
||||
csrfmiddlewaretoken: csrf_token,
|
||||
},
|
||||
raw_droppable: ['text/uri-list', 'text/plain'],
|
||||
drop: exports.uploadStarted,
|
||||
progressUpdated: exports.progressUpdated,
|
||||
error: exports.uploadError,
|
||||
uploadFinished: exports.uploadFinished,
|
||||
rawDrop: function (contents) {
|
||||
var textbox = $("#new_message_content");
|
||||
if (!compose_state.composing()) {
|
||||
compose_actions.start('stream');
|
||||
}
|
||||
textbox.val(textbox.val() + contents);
|
||||
compose_ui.autosize_textarea();
|
||||
},
|
||||
});
|
||||
upload.initialize();
|
||||
|
||||
if (page_params.narrow !== undefined) {
|
||||
if (page_params.narrow_topic !== undefined) {
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
var upload = (function () {
|
||||
|
||||
var exports = {};
|
||||
|
||||
function make_upload_absolute(uri) {
|
||||
if (uri.indexOf(compose.uploads_path) === 0) {
|
||||
// Rewrite the URI to a usable link
|
||||
return compose.uploads_domain + uri;
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
// This function resets an input type="file". Pass in the
|
||||
// jquery object.
|
||||
function clear_out_file_list(jq_file_list) {
|
||||
if (compose.clone_file_input !== undefined) {
|
||||
jq_file_list.replaceWith(compose.clone_file_input.clone(true));
|
||||
}
|
||||
// Hack explanation:
|
||||
// IE won't let you do this (untested, but so says StackOverflow):
|
||||
// $("#file_input").val("");
|
||||
}
|
||||
|
||||
exports.uploadStarted = function () {
|
||||
$("#compose-send-button").attr("disabled", "");
|
||||
$("#send-status").addClass("alert-info").show();
|
||||
$(".send-status-close").one('click', compose.abort_xhr);
|
||||
$("#error-msg").html($("<p>").text(i18n.t("Uploading…"))
|
||||
.after('<div class="progress progress-striped active">' +
|
||||
'<div class="bar" id="upload-bar" style="width: 00%;"></div>' +
|
||||
'</div>'));
|
||||
};
|
||||
|
||||
exports.progressUpdated = function (i, file, progress) {
|
||||
$("#upload-bar").width(progress + "%");
|
||||
};
|
||||
|
||||
exports.uploadError = function (err, file) {
|
||||
var msg;
|
||||
$("#send-status").addClass("alert-error")
|
||||
.removeClass("alert-info");
|
||||
$("#compose-send-button").prop("disabled", false);
|
||||
switch (err) {
|
||||
case 'BrowserNotSupported':
|
||||
msg = i18n.t("File upload is not yet available for your browser.");
|
||||
break;
|
||||
case 'TooManyFiles':
|
||||
msg = i18n.t("Unable to upload that many files at once.");
|
||||
break;
|
||||
case 'FileTooLarge':
|
||||
// sanitization not needed as the file name is not potentially parsed as HTML, etc.
|
||||
var context = {
|
||||
file_name: file.name,
|
||||
};
|
||||
msg = i18n.t('"__file_name__" was too large; the maximum file size is 25MiB.', context);
|
||||
break;
|
||||
case 'REQUEST ENTITY TOO LARGE':
|
||||
msg = i18n.t("Sorry, the file was too large.");
|
||||
break;
|
||||
case 'QuotaExceeded':
|
||||
var translation_part1 = i18n.t('Upload would exceed your maximum quota. You can delete old attachments to free up space.');
|
||||
var translation_part2 = i18n.t('Click here');
|
||||
msg = translation_part1 + ' <a href="#settings/uploaded-files">' + translation_part2 + '</a>';
|
||||
$("#error-msg").html(msg);
|
||||
return;
|
||||
default:
|
||||
msg = i18n.t("An unknown error occurred.");
|
||||
break;
|
||||
}
|
||||
$("#error-msg").text(msg);
|
||||
};
|
||||
|
||||
exports.uploadFinished = function (i, file, response) {
|
||||
if (response.uri === undefined) {
|
||||
return;
|
||||
}
|
||||
var textbox = $("#new_message_content");
|
||||
var split_uri = response.uri.split("/");
|
||||
var filename = split_uri[split_uri.length - 1];
|
||||
// Urgh, yet another hack to make sure we're "composing"
|
||||
// when text gets added into the composebox.
|
||||
if (!compose_state.composing()) {
|
||||
compose_actions.start('stream');
|
||||
}
|
||||
|
||||
var uri = make_upload_absolute(response.uri);
|
||||
|
||||
if (i === -1) {
|
||||
// This is a paste, so there's no filename. Show the image directly
|
||||
textbox.val(textbox.val() + "[pasted image](" + uri + ") ");
|
||||
} else {
|
||||
// This is a dropped file, so make the filename a link to the image
|
||||
textbox.val(textbox.val() + "[" + filename + "](" + uri + ")" + " ");
|
||||
}
|
||||
compose_ui.autosize_textarea();
|
||||
$("#compose-send-button").prop("disabled", false);
|
||||
$("#send-status").removeClass("alert-info")
|
||||
.hide();
|
||||
|
||||
// In order to upload the same file twice in a row, we need to clear out
|
||||
// the #file_input element, so that the next time we use the file dialog,
|
||||
// an actual change event is fired. This is extracted to a function
|
||||
// to abstract away some IE hacks.
|
||||
clear_out_file_list($("#file_input"));
|
||||
};
|
||||
|
||||
exports.initialize = function () {
|
||||
$("#compose").filedrop({
|
||||
url: "/json/user_uploads",
|
||||
fallback_id: "file_input",
|
||||
paramname: "file",
|
||||
maxfilesize: page_params.maxfilesize,
|
||||
data: {
|
||||
// the token isn't automatically included in filedrop's post
|
||||
csrfmiddlewaretoken: csrf_token,
|
||||
},
|
||||
raw_droppable: ['text/uri-list', 'text/plain'],
|
||||
drop: exports.uploadStarted,
|
||||
progressUpdated: exports.progressUpdated,
|
||||
error: exports.uploadError,
|
||||
uploadFinished: exports.uploadFinished,
|
||||
rawDrop: function (contents) {
|
||||
var textbox = $("#new_message_content");
|
||||
if (!compose_state.composing()) {
|
||||
compose_actions.start('stream');
|
||||
}
|
||||
textbox.val(textbox.val() + contents);
|
||||
compose_ui.autosize_textarea();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return exports;
|
||||
}());
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = upload;
|
||||
}
|
|
@ -236,7 +236,7 @@ def build_custom_checkers(by_lang):
|
|||
'frontend_tests/node_tests/compose.js',
|
||||
'frontend_tests/node_tests/copy_and_paste.js',
|
||||
'frontend_tests/node_tests/templates.js',
|
||||
'static/js/compose.js',
|
||||
'static/js/upload.js',
|
||||
'static/js/dynamic_text.js',
|
||||
'static/js/stream_color.js',
|
||||
]),
|
||||
|
|
|
@ -977,6 +977,7 @@ JS_SPECS = {
|
|||
'js/compose_state.js',
|
||||
'js/compose_actions.js',
|
||||
'js/compose.js',
|
||||
'js/upload.js',
|
||||
'js/stream_color.js',
|
||||
'js/stream_data.js',
|
||||
'js/topic_data.js',
|
||||
|
|
Loading…
Reference in New Issue