mirror of
https://github.com/discourse/discourse.git
synced 2025-01-30 02:36:15 +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,
|
||||
shouldBuildScrollMap: true,
|
||||
scrollMap: null,
|
||||
uploadFilenamePlaceholder: null,
|
||||
|
||||
@computed
|
||||
uploadPlaceholder() {
|
||||
return `[${I18n.t("uploading")}]() `;
|
||||
@computed("uploadFilenamePlaceholder")
|
||||
uploadPlaceholder(uploadFilenamePlaceholder) {
|
||||
const clipboard = I18n.t("clipboard");
|
||||
const filename = uploadFilenamePlaceholder
|
||||
? uploadFilenamePlaceholder
|
||||
: clipboard;
|
||||
return `[${I18n.t("uploading_filename", { filename })}]() `;
|
||||
},
|
||||
|
||||
@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() {
|
||||
return this.siteSettings.enable_advanced_editor_preview_sync;
|
||||
},
|
||||
|
@ -542,23 +594,26 @@ export default Ember.Component.extend({
|
|||
},
|
||||
|
||||
_resetUpload(removePlaceholder) {
|
||||
if (this._validUploads > 0) {
|
||||
this._validUploads--;
|
||||
}
|
||||
if (this._validUploads === 0) {
|
||||
this.setProperties({
|
||||
uploadProgress: 0,
|
||||
isUploading: false,
|
||||
isCancellable: false
|
||||
});
|
||||
}
|
||||
if (removePlaceholder) {
|
||||
this.appEvents.trigger(
|
||||
"composer:replace-text",
|
||||
this.get("uploadPlaceholder"),
|
||||
""
|
||||
);
|
||||
}
|
||||
Ember.run.next(() => {
|
||||
if (this._validUploads > 0) {
|
||||
this._validUploads--;
|
||||
}
|
||||
if (this._validUploads === 0) {
|
||||
this.setProperties({
|
||||
uploadProgress: 0,
|
||||
isUploading: false,
|
||||
isCancellable: false
|
||||
});
|
||||
}
|
||||
if (removePlaceholder) {
|
||||
this.appEvents.trigger(
|
||||
"composer:replace-text",
|
||||
this.get("uploadPlaceholder"),
|
||||
""
|
||||
);
|
||||
}
|
||||
this._resetUploadFilenamePlaceholder();
|
||||
});
|
||||
},
|
||||
|
||||
_bindUploadTarget() {
|
||||
|
@ -568,7 +623,6 @@ export default Ember.Component.extend({
|
|||
|
||||
const $element = this.$();
|
||||
const csrf = this.session.get("csrfToken");
|
||||
const uploadPlaceholder = this.get("uploadPlaceholder");
|
||||
|
||||
$element.fileupload({
|
||||
url: Discourse.getURL(
|
||||
|
@ -637,7 +691,13 @@ export default Ember.Component.extend({
|
|||
$element.on("fileuploadsend", (e, data) => {
|
||||
this._pasted = false;
|
||||
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) {
|
||||
this.set("isCancellable", true);
|
||||
|
@ -647,13 +707,13 @@ export default Ember.Component.extend({
|
|||
|
||||
$element.on("fileuploaddone", (e, data) => {
|
||||
let upload = data.result;
|
||||
|
||||
this._setUploadPlaceholderDone(data);
|
||||
if (!this._xhr || !this._xhr._userCancelled) {
|
||||
const markdown = getUploadMarkdown(upload);
|
||||
cacheShortUploadUrl(upload.short_url, upload.url);
|
||||
this.appEvents.trigger(
|
||||
"composer:replace-text",
|
||||
uploadPlaceholder.trim(),
|
||||
this.get("uploadPlaceholder").trim(),
|
||||
markdown
|
||||
);
|
||||
this._resetUpload(false);
|
||||
|
@ -663,6 +723,7 @@ export default Ember.Component.extend({
|
|||
});
|
||||
|
||||
$element.on("fileuploadfail", (e, data) => {
|
||||
this._setUploadPlaceholderDone(data);
|
||||
this._resetUpload(true);
|
||||
|
||||
const userCancelled = this._xhr && this._xhr._userCancelled;
|
||||
|
|
|
@ -317,7 +317,8 @@ en:
|
|||
|
||||
upload: "Upload"
|
||||
uploading: "Uploading..."
|
||||
uploading_filename: "Uploading {{filename}}..."
|
||||
uploading_filename: "Uploading: {{filename}}..."
|
||||
clipboard: "clipboard"
|
||||
uploaded: "Uploaded!"
|
||||
|
||||
pasting: "Pasting..."
|
||||
|
|
|
@ -89,6 +89,80 @@ QUnit.test("Tests the Composer controls", async assert => {
|
|||
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 => {
|
||||
await visit("/");
|
||||
await click("#create-topic");
|
||||
|
|
Loading…
Reference in New Issue
Block a user