|
|
@@ -74,11 +74,11 @@ export function initRepoCommentForm() { |
|
|
|
} |
|
|
|
|
|
|
|
if (editMode === 'true') { |
|
|
|
const $form = $('#update_issueref_form'); |
|
|
|
const form = document.getElementById('update_issueref_form'); |
|
|
|
const params = new URLSearchParams(); |
|
|
|
params.append('ref', selectedValue); |
|
|
|
try { |
|
|
|
await POST($form.attr('action'), {data: params}); |
|
|
|
await POST(form.getAttribute('action'), {data: params}); |
|
|
|
window.location.reload(); |
|
|
|
} catch (error) { |
|
|
|
console.error(error); |
|
|
@@ -138,12 +138,12 @@ export function initRepoCommentForm() { |
|
|
|
hasUpdateAction = $listMenu.data('action') === 'update'; // Update the var |
|
|
|
|
|
|
|
const clickedItem = this; // eslint-disable-line unicorn/no-this-assignment |
|
|
|
const scope = $(this).attr('data-scope'); |
|
|
|
const scope = this.getAttribute('data-scope'); |
|
|
|
|
|
|
|
$(this).parent().find('.item').each(function () { |
|
|
|
if (scope) { |
|
|
|
// Enable only clicked item for scoped labels |
|
|
|
if ($(this).attr('data-scope') !== scope) { |
|
|
|
if (this.getAttribute('data-scope') !== scope) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
if (this !== clickedItem && !$(this).hasClass('checked')) { |
|
|
@@ -319,29 +319,32 @@ export function initRepoCommentForm() { |
|
|
|
async function onEditContent(event) { |
|
|
|
event.preventDefault(); |
|
|
|
|
|
|
|
const $segment = $(this).closest('.header').next(); |
|
|
|
const $editContentZone = $segment.find('.edit-content-zone'); |
|
|
|
const $renderContent = $segment.find('.render-content'); |
|
|
|
const $rawContent = $segment.find('.raw-content'); |
|
|
|
const segment = this.closest('.header').nextElementSibling; |
|
|
|
const editContentZone = segment.querySelector('.edit-content-zone'); |
|
|
|
const renderContent = segment.querySelector('.render-content'); |
|
|
|
const rawContent = segment.querySelector('.raw-content'); |
|
|
|
|
|
|
|
let comboMarkdownEditor; |
|
|
|
|
|
|
|
const setupDropzone = async ($dropzone) => { |
|
|
|
if (!$dropzone.length) return null; |
|
|
|
/** |
|
|
|
* @param {HTMLElement} dropzone |
|
|
|
*/ |
|
|
|
const setupDropzone = async (dropzone) => { |
|
|
|
if (!dropzone) return null; |
|
|
|
|
|
|
|
let disableRemovedfileEvent = false; // when resetting the dropzone (removeAllFiles), disable the "removedfile" event |
|
|
|
let fileUuidDict = {}; // to record: if a comment has been saved, then the uploaded files won't be deleted from server when clicking the Remove in the dropzone |
|
|
|
const dz = await createDropzone($dropzone[0], { |
|
|
|
url: $dropzone.attr('data-upload-url'), |
|
|
|
const dz = await createDropzone(dropzone, { |
|
|
|
url: dropzone.getAttribute('data-upload-url'), |
|
|
|
headers: {'X-Csrf-Token': csrfToken}, |
|
|
|
maxFiles: $dropzone.attr('data-max-file'), |
|
|
|
maxFilesize: $dropzone.attr('data-max-size'), |
|
|
|
acceptedFiles: (['*/*', ''].includes($dropzone.attr('data-accepts'))) ? null : $dropzone.attr('data-accepts'), |
|
|
|
maxFiles: dropzone.getAttribute('data-max-file'), |
|
|
|
maxFilesize: dropzone.getAttribute('data-max-size'), |
|
|
|
acceptedFiles: ['*/*', ''].includes(dropzone.getAttribute('data-accepts')) ? null : dropzone.getAttribute('data-accepts'), |
|
|
|
addRemoveLinks: true, |
|
|
|
dictDefaultMessage: $dropzone.attr('data-default-message'), |
|
|
|
dictInvalidFileType: $dropzone.attr('data-invalid-input-type'), |
|
|
|
dictFileTooBig: $dropzone.attr('data-file-too-big'), |
|
|
|
dictRemoveFile: $dropzone.attr('data-remove-file'), |
|
|
|
dictDefaultMessage: dropzone.getAttribute('data-default-message'), |
|
|
|
dictInvalidFileType: dropzone.getAttribute('data-invalid-input-type'), |
|
|
|
dictFileTooBig: dropzone.getAttribute('data-file-too-big'), |
|
|
|
dictRemoveFile: dropzone.getAttribute('data-remove-file'), |
|
|
|
timeout: 0, |
|
|
|
thumbnailMethod: 'contain', |
|
|
|
thumbnailWidth: 480, |
|
|
@@ -350,46 +353,54 @@ async function onEditContent(event) { |
|
|
|
this.on('success', (file, data) => { |
|
|
|
file.uuid = data.uuid; |
|
|
|
fileUuidDict[file.uuid] = {submitted: false}; |
|
|
|
const $input = $(`<input id="${data.uuid}" name="files" type="hidden">`).val(data.uuid); |
|
|
|
$dropzone.find('.files').append($input); |
|
|
|
const input = document.createElement('input'); |
|
|
|
input.id = data.uuid; |
|
|
|
input.name = 'files'; |
|
|
|
input.type = 'hidden'; |
|
|
|
input.value = data.uuid; |
|
|
|
dropzone.querySelector('.files').insertAdjacentHTML('beforeend', input.outerHTML); |
|
|
|
}); |
|
|
|
this.on('removedfile', async (file) => { |
|
|
|
if (disableRemovedfileEvent) return; |
|
|
|
$(`#${file.uuid}`).remove(); |
|
|
|
if ($dropzone.attr('data-remove-url') && !fileUuidDict[file.uuid].submitted) { |
|
|
|
document.getElementById(file.uuid)?.remove(); |
|
|
|
if (dropzone.getAttribute('data-remove-url') && !fileUuidDict[file.uuid].submitted) { |
|
|
|
try { |
|
|
|
await POST($dropzone.attr('data-remove-url'), {data: new URLSearchParams({file: file.uuid})}); |
|
|
|
await POST(dropzone.getAttribute('data-remove-url'), {data: new URLSearchParams({file: file.uuid})}); |
|
|
|
} catch (error) { |
|
|
|
console.error(error); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
this.on('submit', () => { |
|
|
|
$.each(fileUuidDict, (fileUuid) => { |
|
|
|
for (const fileUuid of Object.keys(fileUuidDict)) { |
|
|
|
fileUuidDict[fileUuid].submitted = true; |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
this.on('reload', async () => { |
|
|
|
try { |
|
|
|
const response = await GET($editContentZone.attr('data-attachment-url')); |
|
|
|
const response = await GET(editContentZone.getAttribute('data-attachment-url')); |
|
|
|
const data = await response.json(); |
|
|
|
// do not trigger the "removedfile" event, otherwise the attachments would be deleted from server |
|
|
|
disableRemovedfileEvent = true; |
|
|
|
dz.removeAllFiles(true); |
|
|
|
$dropzone.find('.files').empty(); |
|
|
|
dropzone.querySelector('.files').innerHTML = ''; |
|
|
|
fileUuidDict = {}; |
|
|
|
disableRemovedfileEvent = false; |
|
|
|
|
|
|
|
for (const attachment of data) { |
|
|
|
const imgSrc = `${$dropzone.attr('data-link-url')}/${attachment.uuid}`; |
|
|
|
const imgSrc = `${dropzone.getAttribute('data-link-url')}/${attachment.uuid}`; |
|
|
|
dz.emit('addedfile', attachment); |
|
|
|
dz.emit('thumbnail', attachment, imgSrc); |
|
|
|
dz.emit('complete', attachment); |
|
|
|
dz.files.push(attachment); |
|
|
|
fileUuidDict[attachment.uuid] = {submitted: true}; |
|
|
|
$dropzone.find(`img[src='${imgSrc}']`)[0].style.maxWidth = '100%'; |
|
|
|
const $input = $(`<input id="${attachment.uuid}" name="files" type="hidden">`).val(attachment.uuid); |
|
|
|
$dropzone.find('.files').append($input); |
|
|
|
dropzone.querySelector(`img[src='${imgSrc}']`).style.maxWidth = '100%'; |
|
|
|
const input = document.createElement('input'); |
|
|
|
input.id = attachment.uuid; |
|
|
|
input.name = 'files'; |
|
|
|
input.type = 'hidden'; |
|
|
|
input.value = attachment.uuid; |
|
|
|
dropzone.querySelector('.files').insertAdjacentHTML('beforeend', input.outerHTML); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error(error); |
|
|
@@ -402,44 +413,44 @@ async function onEditContent(event) { |
|
|
|
}; |
|
|
|
|
|
|
|
const cancelAndReset = (dz) => { |
|
|
|
showElem($renderContent); |
|
|
|
hideElem($editContentZone); |
|
|
|
showElem(renderContent); |
|
|
|
hideElem(editContentZone); |
|
|
|
if (dz) { |
|
|
|
dz.emit('reload'); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const saveAndRefresh = async (dz) => { |
|
|
|
showElem($renderContent); |
|
|
|
hideElem($editContentZone); |
|
|
|
showElem(renderContent); |
|
|
|
hideElem(editContentZone); |
|
|
|
|
|
|
|
try { |
|
|
|
const params = new URLSearchParams({ |
|
|
|
content: comboMarkdownEditor.value(), |
|
|
|
context: $editContentZone.attr('data-context'), |
|
|
|
context: editContentZone.getAttribute('data-context'), |
|
|
|
}); |
|
|
|
for (const file of dz.files) params.append('files[]', file.uuid); |
|
|
|
|
|
|
|
const response = await POST($editContentZone.attr('data-update-url'), {data: params}); |
|
|
|
const response = await POST(editContentZone.getAttribute('data-update-url'), {data: params}); |
|
|
|
const data = await response.json(); |
|
|
|
if (!data.content) { |
|
|
|
$renderContent.html($('#no-content').html()); |
|
|
|
$rawContent.text(''); |
|
|
|
renderContent.innerHTML = document.getElementById('no-content').innerHTML; |
|
|
|
rawContent.textContent = ''; |
|
|
|
} else { |
|
|
|
$renderContent.html(data.content); |
|
|
|
$rawContent.text(comboMarkdownEditor.value()); |
|
|
|
const $refIssues = $renderContent.find('p .ref-issue'); |
|
|
|
attachRefIssueContextPopup($refIssues); |
|
|
|
renderContent.innerHTML = data.content; |
|
|
|
rawContent.textContent = comboMarkdownEditor.value(); |
|
|
|
const refIssues = renderContent.querySelectorAll('p .ref-issue'); |
|
|
|
attachRefIssueContextPopup(refIssues); |
|
|
|
} |
|
|
|
const $content = $segment; |
|
|
|
if (!$content.find('.dropzone-attachments').length) { |
|
|
|
const content = segment; |
|
|
|
if (!content.querySelector('.dropzone-attachments')) { |
|
|
|
if (data.attachments !== '') { |
|
|
|
$content[0].insertAdjacentHTML('beforeend', data.attachments); |
|
|
|
content.insertAdjacentHTML('beforeend', data.attachments); |
|
|
|
} |
|
|
|
} else if (data.attachments === '') { |
|
|
|
$content.find('.dropzone-attachments').remove(); |
|
|
|
content.querySelector('.dropzone-attachments').remove(); |
|
|
|
} else { |
|
|
|
$content.find('.dropzone-attachments')[0].outerHTML = data.attachments; |
|
|
|
content.querySelector('.dropzone-attachments').outerHTML = data.attachments; |
|
|
|
} |
|
|
|
if (dz) { |
|
|
|
dz.emit('submit'); |
|
|
@@ -452,29 +463,29 @@ async function onEditContent(event) { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
if (!$editContentZone.html()) { |
|
|
|
$editContentZone.html($('#issue-comment-editor-template').html()); |
|
|
|
comboMarkdownEditor = await initComboMarkdownEditor($editContentZone.find('.combo-markdown-editor')); |
|
|
|
if (!editContentZone.innerHTML) { |
|
|
|
editContentZone.innerHTML = document.getElementById('issue-comment-editor-template').innerHTML; |
|
|
|
comboMarkdownEditor = await initComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor')); |
|
|
|
|
|
|
|
const $dropzone = $editContentZone.find('.dropzone'); |
|
|
|
const dz = await setupDropzone($dropzone); |
|
|
|
$editContentZone.find('.cancel.button').on('click', (e) => { |
|
|
|
const dropzone = editContentZone.querySelector('.dropzone'); |
|
|
|
const dz = await setupDropzone(dropzone); |
|
|
|
editContentZone.querySelector('.cancel.button').addEventListener('click', (e) => { |
|
|
|
e.preventDefault(); |
|
|
|
cancelAndReset(dz); |
|
|
|
}); |
|
|
|
$editContentZone.find('.save.button').on('click', (e) => { |
|
|
|
editContentZone.querySelector('.save.button').addEventListener('click', (e) => { |
|
|
|
e.preventDefault(); |
|
|
|
saveAndRefresh(dz); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
comboMarkdownEditor = getComboMarkdownEditor($editContentZone.find('.combo-markdown-editor')); |
|
|
|
comboMarkdownEditor = getComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor')); |
|
|
|
} |
|
|
|
|
|
|
|
// Show write/preview tab and copy raw content as needed |
|
|
|
showElem($editContentZone); |
|
|
|
hideElem($renderContent); |
|
|
|
showElem(editContentZone); |
|
|
|
hideElem(renderContent); |
|
|
|
if (!comboMarkdownEditor.value()) { |
|
|
|
comboMarkdownEditor.value($rawContent.text()); |
|
|
|
comboMarkdownEditor.value(rawContent.textContent); |
|
|
|
} |
|
|
|
comboMarkdownEditor.focus(); |
|
|
|
} |