From ebf253b841d56c5cb1e57cb1e5e50c06d315bdee Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Tue, 15 Jun 2021 03:12:33 +0200 Subject: Add attachments for PR reviews (#16075) * First step for multiple dropzones per page. * Allow attachments on review comments. * Lint. * Fixed accidental initialize of the review textarea. * Initialize SimpleMDE textarea. Co-authored-by: techknowlogick --- web_src/js/index.js | 77 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 28 deletions(-) (limited to 'web_src') diff --git a/web_src/js/index.js b/web_src/js/index.js index 8818511e32..e42a664015 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -327,11 +327,11 @@ function getPastedImages(e) { return files; } -async function uploadFile(file) { +async function uploadFile(file, uploadUrl) { const formData = new FormData(); formData.append('file', file, file.name); - const res = await fetch($('#dropzone').data('upload-url'), { + const res = await fetch(uploadUrl, { method: 'POST', headers: {'X-Csrf-Token': csrf}, body: formData, @@ -345,24 +345,33 @@ function reload() { function initImagePaste(target) { target.each(function () { - this.addEventListener('paste', async (e) => { - for (const img of getPastedImages(e)) { - const name = img.name.substr(0, img.name.lastIndexOf('.')); - insertAtCursor(this, `![${name}]()`); - const data = await uploadFile(img); - replaceAndKeepCursor(this, `![${name}]()`, `![${name}](${AppSubUrl}/attachments/${data.uuid})`); - const input = $(``).val(data.uuid); - $('.files').append(input); - } - }, false); + const dropzone = this.querySelector('.dropzone'); + if (!dropzone) { + return; + } + const uploadUrl = dropzone.dataset.uploadUrl; + const dropzoneFiles = dropzone.querySelector('.files'); + for (const textarea of this.querySelectorAll('textarea')) { + textarea.addEventListener('paste', async (e) => { + for (const img of getPastedImages(e)) { + const name = img.name.substr(0, img.name.lastIndexOf('.')); + insertAtCursor(textarea, `![${name}]()`); + const data = await uploadFile(img, uploadUrl); + replaceAndKeepCursor(textarea, `![${name}]()`, `![${name}](${AppSubUrl}/attachments/${data.uuid})`); + const input = $(``).val(data.uuid); + dropzoneFiles.appendChild(input[0]); + } + }, false); + } }); } -function initSimpleMDEImagePaste(simplemde, files) { +function initSimpleMDEImagePaste(simplemde, dropzone, files) { + const uploadUrl = dropzone.dataset.uploadUrl; simplemde.codemirror.on('paste', async (_, e) => { for (const img of getPastedImages(e)) { const name = img.name.substr(0, img.name.lastIndexOf('.')); - const data = await uploadFile(img); + const data = await uploadFile(img, uploadUrl); const pos = simplemde.codemirror.getCursor(); simplemde.codemirror.replaceRange(`![${name}](${AppSubUrl}/attachments/${data.uuid})`, pos); const input = $(``).val(data.uuid); @@ -381,7 +390,7 @@ function initCommentForm() { autoSimpleMDE = setCommentSimpleMDE($('.comment.form textarea:not(.review-textarea)')); initBranchSelector(); initCommentPreviewTab($('.comment.form')); - initImagePaste($('.comment.form textarea')); + initImagePaste($('.comment.form')); // Listsubmit function initListSubmits(selector, outerSelector) { @@ -993,8 +1002,7 @@ async function initRepository() { let dz; const $dropzone = $editContentZone.find('.dropzone'); - const $files = $editContentZone.find('.comment-files'); - if ($dropzone.length > 0) { + if ($dropzone.length === 1) { $dropzone.data('saved', false); const filenameDict = {}; @@ -1020,7 +1028,7 @@ async function initRepository() { submitted: false }; const input = $(``).val(data.uuid); - $files.append(input); + $dropzone.find('.files').append(input); }); this.on('removedfile', (file) => { if (!(file.name in filenameDict)) { @@ -1042,7 +1050,7 @@ async function initRepository() { this.on('reload', () => { $.getJSON($editContentZone.data('attachment-url'), (data) => { dz.removeAllFiles(true); - $files.empty(); + $dropzone.find('.files').empty(); $.each(data, function () { const imgSrc = `${$dropzone.data('link-url')}/${this.uuid}`; dz.emit('addedfile', this); @@ -1055,7 +1063,7 @@ async function initRepository() { }; $dropzone.find(`img[src='${imgSrc}']`).css('max-width', '100%'); const input = $(``).val(this.uuid); - $files.append(input); + $dropzone.find('.files').append(input); }); }); }); @@ -1075,7 +1083,9 @@ async function initRepository() { $simplemde = setCommentSimpleMDE($textarea); commentMDEditors[$editContentZone.data('write')] = $simplemde; initCommentPreviewTab($editContentForm); - initSimpleMDEImagePaste($simplemde, $files); + if ($dropzone.length === 1) { + initSimpleMDEImagePaste($simplemde, $dropzone[0], $dropzone.find('.files')); + } $editContentZone.find('.cancel.button').on('click', () => { $renderContent.show(); @@ -1087,7 +1097,7 @@ async function initRepository() { $editContentZone.find('.save.button').on('click', () => { $renderContent.show(); $editContentZone.hide(); - const $attachments = $files.find('[name=files]').map(function () { + const $attachments = $dropzone.find('.files').find('[name=files]').map(function () { return $(this).val(); }).get(); $.post($editContentZone.data('update-url'), { @@ -1369,6 +1379,13 @@ function initPullRequestReview() { $simplemde.codemirror.focus(); assingMenuAttributes(form.find('.menu')); }); + + const $reviewBox = $('.review-box'); + if ($reviewBox.length === 1) { + setCommentSimpleMDE($reviewBox.find('textarea')); + initImagePaste($reviewBox); + } + // The following part is only for diff views if ($('.repository.pull.diff').length === 0) { return; @@ -1656,6 +1673,10 @@ $.fn.getCursorPosition = function () { }; function setCommentSimpleMDE($editArea) { + if ($editArea.length === 0) { + return null; + } + const simplemde = new SimpleMDE({ autoDownloadFontAwesome: false, element: $editArea[0], @@ -1827,7 +1848,8 @@ function initReleaseEditor() { const $files = $editor.parent().find('.files'); const $simplemde = setCommentSimpleMDE($textarea); initCommentPreviewTab($editor); - initSimpleMDEImagePaste($simplemde, $files); + const dropzone = $editor.parent().find('.dropzone')[0]; + initSimpleMDEImagePaste($simplemde, dropzone, $files); } function initOrganization() { @@ -2610,11 +2632,10 @@ $(document).ready(async () => { initLinkAccountView(); // Dropzone - const $dropzone = $('#dropzone'); - if ($dropzone.length > 0) { + for (const el of document.querySelectorAll('.dropzone')) { const filenameDict = {}; - - await createDropzone('#dropzone', { + const $dropzone = $(el); + await createDropzone(el, { url: $dropzone.data('upload-url'), headers: {'X-Csrf-Token': csrf}, maxFiles: $dropzone.data('max-file'), @@ -2633,7 +2654,7 @@ $(document).ready(async () => { this.on('success', (file, data) => { filenameDict[file.name] = data.uuid; const input = $(``).val(data.uuid); - $('.files').append(input); + $dropzone.find('.files').append(input); }); this.on('removedfile', (file) => { if (file.name in filenameDict) { -- cgit v1.2.3