diff options
Diffstat (limited to 'web_src/js/features/repo-issue-edit.ts')
-rw-r--r-- | web_src/js/features/repo-issue-edit.ts | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/web_src/js/features/repo-issue-edit.ts b/web_src/js/features/repo-issue-edit.ts new file mode 100644 index 0000000000..33a7a10923 --- /dev/null +++ b/web_src/js/features/repo-issue-edit.ts @@ -0,0 +1,127 @@ +import $ from 'jquery'; +import {handleReply} from './repo-issue.ts'; +import {getComboMarkdownEditor, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts'; +import {POST} from '../modules/fetch.ts'; +import {showErrorToast} from '../modules/toast.ts'; +import {hideElem, showElem} from '../utils/dom.ts'; +import {attachRefIssueContextPopup} from './contextpopup.ts'; +import {initCommentContent, initMarkupContent} from '../markup/content.ts'; + +async function onEditContent(event) { + event.preventDefault(); + + 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 cancelAndReset = (e) => { + e.preventDefault(); + showElem(renderContent); + hideElem(editContentZone); + comboMarkdownEditor.dropzoneReloadFiles(); + }; + + const saveAndRefresh = async (e) => { + e.preventDefault(); + renderContent.classList.add('is-loading'); + showElem(renderContent); + hideElem(editContentZone); + try { + const params = new URLSearchParams({ + content: comboMarkdownEditor.value(), + context: editContentZone.getAttribute('data-context'), + content_version: editContentZone.getAttribute('data-content-version'), + }); + for (const file of comboMarkdownEditor.dropzoneGetFiles() ?? []) { + params.append('files[]', file); + } + + const response = await POST(editContentZone.getAttribute('data-update-url'), {data: params}); + const data = await response.json(); + if (response.status === 400) { + showErrorToast(data.errorMessage); + return; + } + editContentZone.setAttribute('data-content-version', data.contentVersion); + if (!data.content) { + renderContent.innerHTML = document.querySelector('#no-content').innerHTML; + rawContent.textContent = ''; + } else { + renderContent.innerHTML = data.content; + rawContent.textContent = comboMarkdownEditor.value(); + const refIssues = renderContent.querySelectorAll('p .ref-issue'); + attachRefIssueContextPopup(refIssues); + } + const content = segment; + if (!content.querySelector('.dropzone-attachments')) { + if (data.attachments !== '') { + content.insertAdjacentHTML('beforeend', data.attachments); + } + } else if (data.attachments === '') { + content.querySelector('.dropzone-attachments').remove(); + } else { + content.querySelector('.dropzone-attachments').outerHTML = data.attachments; + } + comboMarkdownEditor.dropzoneSubmitReload(); + initMarkupContent(); + initCommentContent(); + } catch (error) { + showErrorToast(`Failed to save the content: ${error}`); + console.error(error); + } finally { + renderContent.classList.remove('is-loading'); + } + }; + + comboMarkdownEditor = getComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor')); + if (!comboMarkdownEditor) { + editContentZone.innerHTML = document.querySelector('#issue-comment-editor-template').innerHTML; + comboMarkdownEditor = await initComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor')); + editContentZone.querySelector('.ui.cancel.button').addEventListener('click', cancelAndReset); + editContentZone.querySelector('.ui.primary.button').addEventListener('click', saveAndRefresh); + } + + // Show write/preview tab and copy raw content as needed + showElem(editContentZone); + hideElem(renderContent); + // FIXME: ideally here should reload content and attachment list from backend for existing editor, to avoid losing data + if (!comboMarkdownEditor.value()) { + comboMarkdownEditor.value(rawContent.textContent); + } + comboMarkdownEditor.switchTabToEditor(); + comboMarkdownEditor.focus(); +} + +export function initRepoIssueCommentEdit() { + // Edit issue or comment content + $(document).on('click', '.edit-content', onEditContent); + + // Quote reply + $(document).on('click', '.quote-reply', async function (event) { + event.preventDefault(); + const target = this.getAttribute('data-target'); + const quote = document.querySelector(`#${target}`).textContent.replace(/\n/g, '\n> '); + const content = `> ${quote}\n\n`; + + let editor; + if (this.classList.contains('quote-reply-diff')) { + const replyBtn = this.closest('.comment-code-cloud').querySelector('button.comment-form-reply'); + editor = await handleReply(replyBtn); + } else { + // for normal issue/comment page + editor = getComboMarkdownEditor($('#comment-form .combo-markdown-editor')); + } + if (editor) { + if (editor.value()) { + editor.value(`${editor.value()}\n\n${content}`); + } else { + editor.value(content); + } + editor.focus(); + editor.moveCursorToEnd(); + } + }); +} |