mirror of
https://github.com/discourse/discourse.git
synced 2025-01-31 05:29:30 +08:00
FIX: keep files in order when adding multiple uploads (#6306)
* FIX: keep files in order when adding multiple uploads * use filename in the placeholder when uploading files * add tests * add consecutive nr to the placeholder when multiple uploads with the same filename
This commit is contained in:
parent
a6f0436a29
commit
73443d889c
|
@ -53,10 +53,15 @@ export default Ember.Component.extend({
|
||||||
_xhr: null,
|
_xhr: null,
|
||||||
shouldBuildScrollMap: true,
|
shouldBuildScrollMap: true,
|
||||||
scrollMap: null,
|
scrollMap: null,
|
||||||
|
uploadFilenamePlaceholder: null,
|
||||||
|
|
||||||
@computed
|
@computed("uploadFilenamePlaceholder")
|
||||||
uploadPlaceholder() {
|
uploadPlaceholder(uploadFilenamePlaceholder) {
|
||||||
return `[${I18n.t("uploading")}]() `;
|
const clipboard = I18n.t("clipboard");
|
||||||
|
const filename = uploadFilenamePlaceholder
|
||||||
|
? uploadFilenamePlaceholder
|
||||||
|
: clipboard;
|
||||||
|
return `[${I18n.t("uploading_filename", { filename })}]() `;
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("composer.requiredCategoryMissing")
|
@computed("composer.requiredCategoryMissing")
|
||||||
|
@ -218,6 +223,53 @@ export default Ember.Component.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_setUploadPlaceholderSend(data) {
|
||||||
|
const filename = this._filenamePlaceholder(data);
|
||||||
|
this.set("uploadFilenamePlaceholder", filename);
|
||||||
|
|
||||||
|
// when adding two separate files with the same filename search for matching
|
||||||
|
// placeholder already existing in the editor ie [Uploading: test.png...]
|
||||||
|
// and add order nr to the next one: [Uplodading: test.png(1)...]
|
||||||
|
const regexString = `\\[${I18n.t("uploading_filename", {
|
||||||
|
filename: filename + "(?:\\()?([0-9])?(?:\\))?"
|
||||||
|
})}\\]\\(\\)`;
|
||||||
|
const globalRegex = new RegExp(regexString, "g");
|
||||||
|
const matchingPlaceholder = this.get("composer.reply").match(globalRegex);
|
||||||
|
if (matchingPlaceholder) {
|
||||||
|
// get last matching placeholder and its consecutive nr in regex
|
||||||
|
// capturing group and apply +1 to the placeholder
|
||||||
|
const lastMatch = matchingPlaceholder[matchingPlaceholder.length - 1];
|
||||||
|
const regex = new RegExp(regexString);
|
||||||
|
const orderNr = regex.exec(lastMatch)[1]
|
||||||
|
? parseInt(regex.exec(lastMatch)[1]) + 1
|
||||||
|
: 1;
|
||||||
|
data.orderNr = orderNr;
|
||||||
|
const filenameWithOrderNr = `${filename}(${orderNr})`;
|
||||||
|
this.set("uploadFilenamePlaceholder", filenameWithOrderNr);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_setUploadPlaceholderDone(data) {
|
||||||
|
const filename = this._filenamePlaceholder(data);
|
||||||
|
const filenameWithSize = `${filename} (${data.total})`;
|
||||||
|
this.set("uploadFilenamePlaceholder", filenameWithSize);
|
||||||
|
|
||||||
|
if (data.orderNr) {
|
||||||
|
const filenameWithOrderNr = `${filename}(${data.orderNr})`;
|
||||||
|
this.set("uploadFilenamePlaceholder", filenameWithOrderNr);
|
||||||
|
} else {
|
||||||
|
this.set("uploadFilenamePlaceholder", filename);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_filenamePlaceholder(data) {
|
||||||
|
return data.files[0].name.replace(/\u200B-\u200D\uFEFF]/g, "");
|
||||||
|
},
|
||||||
|
|
||||||
|
_resetUploadFilenamePlaceholder() {
|
||||||
|
this.set("uploadFilenamePlaceholder", null);
|
||||||
|
},
|
||||||
|
|
||||||
_enableAdvancedEditorPreviewSync() {
|
_enableAdvancedEditorPreviewSync() {
|
||||||
return this.siteSettings.enable_advanced_editor_preview_sync;
|
return this.siteSettings.enable_advanced_editor_preview_sync;
|
||||||
},
|
},
|
||||||
|
@ -542,6 +594,7 @@ export default Ember.Component.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
_resetUpload(removePlaceholder) {
|
_resetUpload(removePlaceholder) {
|
||||||
|
Ember.run.next(() => {
|
||||||
if (this._validUploads > 0) {
|
if (this._validUploads > 0) {
|
||||||
this._validUploads--;
|
this._validUploads--;
|
||||||
}
|
}
|
||||||
|
@ -559,6 +612,8 @@ export default Ember.Component.extend({
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
this._resetUploadFilenamePlaceholder();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_bindUploadTarget() {
|
_bindUploadTarget() {
|
||||||
|
@ -568,7 +623,6 @@ export default Ember.Component.extend({
|
||||||
|
|
||||||
const $element = this.$();
|
const $element = this.$();
|
||||||
const csrf = this.session.get("csrfToken");
|
const csrf = this.session.get("csrfToken");
|
||||||
const uploadPlaceholder = this.get("uploadPlaceholder");
|
|
||||||
|
|
||||||
$element.fileupload({
|
$element.fileupload({
|
||||||
url: Discourse.getURL(
|
url: Discourse.getURL(
|
||||||
|
@ -637,7 +691,13 @@ export default Ember.Component.extend({
|
||||||
$element.on("fileuploadsend", (e, data) => {
|
$element.on("fileuploadsend", (e, data) => {
|
||||||
this._pasted = false;
|
this._pasted = false;
|
||||||
this._validUploads++;
|
this._validUploads++;
|
||||||
this.appEvents.trigger("composer:insert-text", uploadPlaceholder);
|
|
||||||
|
this._setUploadPlaceholderSend(data);
|
||||||
|
|
||||||
|
this.appEvents.trigger(
|
||||||
|
"composer:insert-text",
|
||||||
|
this.get("uploadPlaceholder")
|
||||||
|
);
|
||||||
|
|
||||||
if (data.xhr && data.originalFiles.length === 1) {
|
if (data.xhr && data.originalFiles.length === 1) {
|
||||||
this.set("isCancellable", true);
|
this.set("isCancellable", true);
|
||||||
|
@ -647,13 +707,13 @@ export default Ember.Component.extend({
|
||||||
|
|
||||||
$element.on("fileuploaddone", (e, data) => {
|
$element.on("fileuploaddone", (e, data) => {
|
||||||
let upload = data.result;
|
let upload = data.result;
|
||||||
|
this._setUploadPlaceholderDone(data);
|
||||||
if (!this._xhr || !this._xhr._userCancelled) {
|
if (!this._xhr || !this._xhr._userCancelled) {
|
||||||
const markdown = getUploadMarkdown(upload);
|
const markdown = getUploadMarkdown(upload);
|
||||||
cacheShortUploadUrl(upload.short_url, upload.url);
|
cacheShortUploadUrl(upload.short_url, upload.url);
|
||||||
this.appEvents.trigger(
|
this.appEvents.trigger(
|
||||||
"composer:replace-text",
|
"composer:replace-text",
|
||||||
uploadPlaceholder.trim(),
|
this.get("uploadPlaceholder").trim(),
|
||||||
markdown
|
markdown
|
||||||
);
|
);
|
||||||
this._resetUpload(false);
|
this._resetUpload(false);
|
||||||
|
@ -663,6 +723,7 @@ export default Ember.Component.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
$element.on("fileuploadfail", (e, data) => {
|
$element.on("fileuploadfail", (e, data) => {
|
||||||
|
this._setUploadPlaceholderDone(data);
|
||||||
this._resetUpload(true);
|
this._resetUpload(true);
|
||||||
|
|
||||||
const userCancelled = this._xhr && this._xhr._userCancelled;
|
const userCancelled = this._xhr && this._xhr._userCancelled;
|
||||||
|
|
|
@ -317,7 +317,8 @@ en:
|
||||||
|
|
||||||
upload: "Upload"
|
upload: "Upload"
|
||||||
uploading: "Uploading..."
|
uploading: "Uploading..."
|
||||||
uploading_filename: "Uploading {{filename}}..."
|
uploading_filename: "Uploading: {{filename}}..."
|
||||||
|
clipboard: "clipboard"
|
||||||
uploaded: "Uploaded!"
|
uploaded: "Uploaded!"
|
||||||
|
|
||||||
pasting: "Pasting..."
|
pasting: "Pasting..."
|
||||||
|
|
|
@ -89,6 +89,80 @@ QUnit.test("Tests the Composer controls", async assert => {
|
||||||
assert.ok(!exists(".bootbox.modal"), "the confirmation can be cancelled");
|
assert.ok(!exists(".bootbox.modal"), "the confirmation can be cancelled");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QUnit.test("Composer upload placeholder", async assert => {
|
||||||
|
await visit("/");
|
||||||
|
await click("#create-topic");
|
||||||
|
|
||||||
|
const file1 = new Blob([""], { type: "image/png" });
|
||||||
|
file1.name = "test.png";
|
||||||
|
const data1 = {
|
||||||
|
files: [file1],
|
||||||
|
result: {
|
||||||
|
original_filename: "test.png",
|
||||||
|
thumbnail_width: 200,
|
||||||
|
thumbnail_height: 300,
|
||||||
|
url: "/uploads/test1.ext"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const file2 = new Blob([""], { type: "image/png" });
|
||||||
|
file2.name = "test.png";
|
||||||
|
const data2 = {
|
||||||
|
files: [file2],
|
||||||
|
result: {
|
||||||
|
original_filename: "test.png",
|
||||||
|
thumbnail_width: 100,
|
||||||
|
thumbnail_height: 200,
|
||||||
|
url: "/uploads/test2.ext"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const file3 = new Blob([""], { type: "image/png" });
|
||||||
|
file3.name = "image.png";
|
||||||
|
const data3 = {
|
||||||
|
files: [file3],
|
||||||
|
result: {
|
||||||
|
original_filename: "image.png",
|
||||||
|
thumbnail_width: 300,
|
||||||
|
thumbnail_height: 400,
|
||||||
|
url: "/uploads/test3.ext"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await find(".wmd-controls").trigger("fileuploadsend", data1);
|
||||||
|
assert.equal(find(".d-editor-input").val(), "[Uploading: test.png...]() ");
|
||||||
|
|
||||||
|
await find(".wmd-controls").trigger("fileuploadsend", data2);
|
||||||
|
assert.equal(
|
||||||
|
find(".d-editor-input").val(),
|
||||||
|
"[Uploading: test.png...]() [Uploading: test.png(1)...]() "
|
||||||
|
);
|
||||||
|
|
||||||
|
await find(".wmd-controls").trigger("fileuploadsend", data3);
|
||||||
|
assert.equal(
|
||||||
|
find(".d-editor-input").val(),
|
||||||
|
"[Uploading: test.png...]() [Uploading: test.png(1)...]() [Uploading: image.png...]() "
|
||||||
|
);
|
||||||
|
|
||||||
|
await find(".wmd-controls").trigger("fileuploaddone", data2);
|
||||||
|
assert.equal(
|
||||||
|
find(".d-editor-input").val(),
|
||||||
|
"[Uploading: test.png...]() ![test|100x200](/uploads/test2.ext) [Uploading: image.png...]() "
|
||||||
|
);
|
||||||
|
|
||||||
|
await find(".wmd-controls").trigger("fileuploaddone", data3);
|
||||||
|
assert.equal(
|
||||||
|
find(".d-editor-input").val(),
|
||||||
|
"[Uploading: test.png...]() ![test|100x200](/uploads/test2.ext) ![image|300x400](/uploads/test3.ext) "
|
||||||
|
);
|
||||||
|
|
||||||
|
await find(".wmd-controls").trigger("fileuploaddone", data1);
|
||||||
|
assert.equal(
|
||||||
|
find(".d-editor-input").val(),
|
||||||
|
"![test|200x300](/uploads/test1.ext) ![test|100x200](/uploads/test2.ext) ![image|300x400](/uploads/test3.ext) "
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
QUnit.test("Create a topic with server side errors", async assert => {
|
QUnit.test("Create a topic with server side errors", async assert => {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click("#create-topic");
|
await click("#create-topic");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user