mirror of
https://github.com/go-gitea/gitea
synced 2024-11-25 11:02:53 +01:00
Prevent from submitting issue/comment on uploading (#32263)
fix #32262 --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
parent
a264c46fb0
commit
620f19610e
7 changed files with 109 additions and 56 deletions
|
@ -3,14 +3,19 @@ import '@github/text-expander-element';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import {attachTribute} from '../tribute.ts';
|
import {attachTribute} from '../tribute.ts';
|
||||||
import {hideElem, showElem, autosize, isElemVisible} from '../../utils/dom.ts';
|
import {hideElem, showElem, autosize, isElemVisible} from '../../utils/dom.ts';
|
||||||
import {initEasyMDEPaste, initTextareaEvents} from './EditorUpload.ts';
|
import {
|
||||||
|
EventUploadStateChanged,
|
||||||
|
initEasyMDEPaste,
|
||||||
|
initTextareaEvents,
|
||||||
|
triggerUploadStateChanged,
|
||||||
|
} from './EditorUpload.ts';
|
||||||
import {handleGlobalEnterQuickSubmit} from './QuickSubmit.ts';
|
import {handleGlobalEnterQuickSubmit} from './QuickSubmit.ts';
|
||||||
import {renderPreviewPanelContent} from '../repo-editor.ts';
|
import {renderPreviewPanelContent} from '../repo-editor.ts';
|
||||||
import {easyMDEToolbarActions} from './EasyMDEToolbarActions.ts';
|
import {easyMDEToolbarActions} from './EasyMDEToolbarActions.ts';
|
||||||
import {initTextExpander} from './TextExpander.ts';
|
import {initTextExpander} from './TextExpander.ts';
|
||||||
import {showErrorToast} from '../../modules/toast.ts';
|
import {showErrorToast} from '../../modules/toast.ts';
|
||||||
import {POST} from '../../modules/fetch.ts';
|
import {POST} from '../../modules/fetch.ts';
|
||||||
import {initTextareaMarkdown} from './EditorMarkdown.ts';
|
import {EventEditorContentChanged, initTextareaMarkdown, triggerEditorContentChanged} from './EditorMarkdown.ts';
|
||||||
import {DropzoneCustomEventReloadFiles, initDropzone} from '../dropzone.ts';
|
import {DropzoneCustomEventReloadFiles, initDropzone} from '../dropzone.ts';
|
||||||
|
|
||||||
let elementIdCounter = 0;
|
let elementIdCounter = 0;
|
||||||
|
@ -37,7 +42,34 @@ export function validateTextareaNonEmpty(textarea) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComboMarkdownEditor {
|
export class ComboMarkdownEditor {
|
||||||
|
static EventEditorContentChanged = EventEditorContentChanged;
|
||||||
|
static EventUploadStateChanged = EventUploadStateChanged;
|
||||||
|
|
||||||
|
public container : HTMLElement;
|
||||||
|
|
||||||
|
// TODO: use correct types to replace these "any" types
|
||||||
|
options: any;
|
||||||
|
|
||||||
|
tabEditor: HTMLElement;
|
||||||
|
tabPreviewer: HTMLElement;
|
||||||
|
|
||||||
|
easyMDE: any;
|
||||||
|
easyMDEToolbarActions: any;
|
||||||
|
easyMDEToolbarDefault: any;
|
||||||
|
|
||||||
|
textarea: HTMLTextAreaElement & {_giteaComboMarkdownEditor: any};
|
||||||
|
textareaMarkdownToolbar: HTMLElement;
|
||||||
|
textareaAutosize: any;
|
||||||
|
|
||||||
|
dropzone: HTMLElement;
|
||||||
|
attachedDropzoneInst: any;
|
||||||
|
|
||||||
|
previewUrl: string;
|
||||||
|
previewContext: string;
|
||||||
|
previewMode: string;
|
||||||
|
previewWiki: boolean;
|
||||||
|
|
||||||
constructor(container, options = {}) {
|
constructor(container, options = {}) {
|
||||||
container._giteaComboMarkdownEditor = this;
|
container._giteaComboMarkdownEditor = this;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
@ -63,14 +95,13 @@ class ComboMarkdownEditor {
|
||||||
|
|
||||||
setupContainer() {
|
setupContainer() {
|
||||||
initTextExpander(this.container.querySelector('text-expander'));
|
initTextExpander(this.container.querySelector('text-expander'));
|
||||||
this.container.addEventListener('ce-editor-content-changed', (e) => this.options?.onContentChanged?.(this, e));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setupTextarea() {
|
setupTextarea() {
|
||||||
this.textarea = this.container.querySelector('.markdown-text-editor');
|
this.textarea = this.container.querySelector('.markdown-text-editor');
|
||||||
this.textarea._giteaComboMarkdownEditor = this;
|
this.textarea._giteaComboMarkdownEditor = this;
|
||||||
this.textarea.id = `_combo_markdown_editor_${String(elementIdCounter++)}`;
|
this.textarea.id = `_combo_markdown_editor_${String(elementIdCounter++)}`;
|
||||||
this.textarea.addEventListener('input', (e) => this.options?.onContentChanged?.(this, e));
|
this.textarea.addEventListener('input', () => triggerEditorContentChanged(this.container));
|
||||||
this.applyEditorHeights(this.textarea, this.options.editorHeights);
|
this.applyEditorHeights(this.textarea, this.options.editorHeights);
|
||||||
|
|
||||||
if (this.textarea.getAttribute('data-disable-autosize') !== 'true') {
|
if (this.textarea.getAttribute('data-disable-autosize') !== 'true') {
|
||||||
|
@ -115,15 +146,21 @@ class ComboMarkdownEditor {
|
||||||
|
|
||||||
async setupDropzone() {
|
async setupDropzone() {
|
||||||
const dropzoneParentContainer = this.container.getAttribute('data-dropzone-parent-container');
|
const dropzoneParentContainer = this.container.getAttribute('data-dropzone-parent-container');
|
||||||
if (dropzoneParentContainer) {
|
if (!dropzoneParentContainer) return;
|
||||||
this.dropzone = this.container.closest(this.container.getAttribute('data-dropzone-parent-container'))?.querySelector('.dropzone');
|
this.dropzone = this.container.closest(this.container.getAttribute('data-dropzone-parent-container'))?.querySelector('.dropzone');
|
||||||
if (this.dropzone) this.attachedDropzoneInst = await initDropzone(this.dropzone);
|
if (!this.dropzone) return;
|
||||||
}
|
|
||||||
|
this.attachedDropzoneInst = await initDropzone(this.dropzone);
|
||||||
|
// dropzone events
|
||||||
|
// * "processing" means a file is being uploaded
|
||||||
|
// * "queuecomplete" means all files have been uploaded
|
||||||
|
this.attachedDropzoneInst.on('processing', () => triggerUploadStateChanged(this.container));
|
||||||
|
this.attachedDropzoneInst.on('queuecomplete', () => triggerUploadStateChanged(this.container));
|
||||||
}
|
}
|
||||||
|
|
||||||
dropzoneGetFiles() {
|
dropzoneGetFiles() {
|
||||||
if (!this.dropzone) return null;
|
if (!this.dropzone) return null;
|
||||||
return Array.from(this.dropzone.querySelectorAll('.files [name=files]'), (el) => el.value);
|
return Array.from(this.dropzone.querySelectorAll<HTMLInputElement>('.files [name=files]'), (el) => el.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
dropzoneReloadFiles() {
|
dropzoneReloadFiles() {
|
||||||
|
@ -137,8 +174,13 @@ class ComboMarkdownEditor {
|
||||||
this.attachedDropzoneInst.emit(DropzoneCustomEventReloadFiles);
|
this.attachedDropzoneInst.emit(DropzoneCustomEventReloadFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isUploading() {
|
||||||
|
if (!this.dropzone) return false;
|
||||||
|
return this.attachedDropzoneInst.getQueuedFiles().length || this.attachedDropzoneInst.getUploadingFiles().length;
|
||||||
|
}
|
||||||
|
|
||||||
setupTab() {
|
setupTab() {
|
||||||
const tabs = this.container.querySelectorAll('.tabular.menu > .item');
|
const tabs = this.container.querySelectorAll<HTMLElement>('.tabular.menu > .item');
|
||||||
|
|
||||||
// Fomantic Tab requires the "data-tab" to be globally unique.
|
// Fomantic Tab requires the "data-tab" to be globally unique.
|
||||||
// So here it uses our defined "data-tab-for" and "data-tab-panel" to generate the "data-tab" attribute for Fomantic.
|
// So here it uses our defined "data-tab-for" and "data-tab-panel" to generate the "data-tab" attribute for Fomantic.
|
||||||
|
@ -170,7 +212,7 @@ class ComboMarkdownEditor {
|
||||||
formData.append('mode', this.previewMode);
|
formData.append('mode', this.previewMode);
|
||||||
formData.append('context', this.previewContext);
|
formData.append('context', this.previewContext);
|
||||||
formData.append('text', this.value());
|
formData.append('text', this.value());
|
||||||
formData.append('wiki', this.previewWiki);
|
formData.append('wiki', String(this.previewWiki));
|
||||||
const response = await POST(this.previewUrl, {data: formData});
|
const response = await POST(this.previewUrl, {data: formData});
|
||||||
const data = await response.text();
|
const data = await response.text();
|
||||||
renderPreviewPanelContent($(panelPreviewer), data);
|
renderPreviewPanelContent($(panelPreviewer), data);
|
||||||
|
@ -237,24 +279,24 @@ class ComboMarkdownEditor {
|
||||||
easyMDEOpt.toolbar = this.parseEasyMDEToolbar(EasyMDE, easyMDEOpt.toolbar ?? this.easyMDEToolbarDefault);
|
easyMDEOpt.toolbar = this.parseEasyMDEToolbar(EasyMDE, easyMDEOpt.toolbar ?? this.easyMDEToolbarDefault);
|
||||||
|
|
||||||
this.easyMDE = new EasyMDE(easyMDEOpt);
|
this.easyMDE = new EasyMDE(easyMDEOpt);
|
||||||
this.easyMDE.codemirror.on('change', (...args) => {this.options?.onContentChanged?.(this, ...args)});
|
this.easyMDE.codemirror.on('change', () => triggerEditorContentChanged(this.container));
|
||||||
this.easyMDE.codemirror.setOption('extraKeys', {
|
this.easyMDE.codemirror.setOption('extraKeys', {
|
||||||
'Cmd-Enter': (cm) => handleGlobalEnterQuickSubmit(cm.getTextArea()),
|
'Cmd-Enter': (cm) => handleGlobalEnterQuickSubmit(cm.getTextArea()),
|
||||||
'Ctrl-Enter': (cm) => handleGlobalEnterQuickSubmit(cm.getTextArea()),
|
'Ctrl-Enter': (cm) => handleGlobalEnterQuickSubmit(cm.getTextArea()),
|
||||||
Enter: (cm) => {
|
Enter: (cm) => {
|
||||||
const tributeContainer = document.querySelector('.tribute-container');
|
const tributeContainer = document.querySelector<HTMLElement>('.tribute-container');
|
||||||
if (!tributeContainer || tributeContainer.style.display === 'none') {
|
if (!tributeContainer || tributeContainer.style.display === 'none') {
|
||||||
cm.execCommand('newlineAndIndent');
|
cm.execCommand('newlineAndIndent');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Up: (cm) => {
|
Up: (cm) => {
|
||||||
const tributeContainer = document.querySelector('.tribute-container');
|
const tributeContainer = document.querySelector<HTMLElement>('.tribute-container');
|
||||||
if (!tributeContainer || tributeContainer.style.display === 'none') {
|
if (!tributeContainer || tributeContainer.style.display === 'none') {
|
||||||
return cm.execCommand('goLineUp');
|
return cm.execCommand('goLineUp');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Down: (cm) => {
|
Down: (cm) => {
|
||||||
const tributeContainer = document.querySelector('.tribute-container');
|
const tributeContainer = document.querySelector<HTMLElement>('.tribute-container');
|
||||||
if (!tributeContainer || tributeContainer.style.display === 'none') {
|
if (!tributeContainer || tributeContainer.style.display === 'none') {
|
||||||
return cm.execCommand('goLineDown');
|
return cm.execCommand('goLineDown');
|
||||||
}
|
}
|
||||||
|
@ -314,13 +356,7 @@ export function getComboMarkdownEditor(el) {
|
||||||
return el?._giteaComboMarkdownEditor;
|
return el?._giteaComboMarkdownEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function initComboMarkdownEditor(container, options = {}) {
|
export async function initComboMarkdownEditor(container: HTMLElement, options = {}) {
|
||||||
if (container instanceof $) {
|
|
||||||
if (container.length !== 1) {
|
|
||||||
throw new Error('initComboMarkdownEditor: container must be a single element');
|
|
||||||
}
|
|
||||||
container = container[0];
|
|
||||||
}
|
|
||||||
if (!container) {
|
if (!container) {
|
||||||
throw new Error('initComboMarkdownEditor: container is null');
|
throw new Error('initComboMarkdownEditor: container is null');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
export const EventEditorContentChanged = 'ce-editor-content-changed';
|
||||||
|
|
||||||
export function triggerEditorContentChanged(target) {
|
export function triggerEditorContentChanged(target) {
|
||||||
target.dispatchEvent(new CustomEvent('ce-editor-content-changed', {bubbles: true}));
|
target.dispatchEvent(new CustomEvent(EventEditorContentChanged, {bubbles: true}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleIndentSelection(textarea, e) {
|
function handleIndentSelection(textarea, e) {
|
||||||
|
|
|
@ -7,9 +7,16 @@ import {
|
||||||
DropzoneCustomEventUploadDone,
|
DropzoneCustomEventUploadDone,
|
||||||
generateMarkdownLinkForAttachment,
|
generateMarkdownLinkForAttachment,
|
||||||
} from '../dropzone.ts';
|
} from '../dropzone.ts';
|
||||||
|
import type CodeMirror from 'codemirror';
|
||||||
|
|
||||||
let uploadIdCounter = 0;
|
let uploadIdCounter = 0;
|
||||||
|
|
||||||
|
export const EventUploadStateChanged = 'ce-upload-state-changed';
|
||||||
|
|
||||||
|
export function triggerUploadStateChanged(target) {
|
||||||
|
target.dispatchEvent(new CustomEvent(EventUploadStateChanged, {bubbles: true}));
|
||||||
|
}
|
||||||
|
|
||||||
function uploadFile(dropzoneEl, file) {
|
function uploadFile(dropzoneEl, file) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const curUploadId = uploadIdCounter++;
|
const curUploadId = uploadIdCounter++;
|
||||||
|
@ -18,7 +25,7 @@ function uploadFile(dropzoneEl, file) {
|
||||||
const onUploadDone = ({file}) => {
|
const onUploadDone = ({file}) => {
|
||||||
if (file._giteaUploadId === curUploadId) {
|
if (file._giteaUploadId === curUploadId) {
|
||||||
dropzoneInst.off(DropzoneCustomEventUploadDone, onUploadDone);
|
dropzoneInst.off(DropzoneCustomEventUploadDone, onUploadDone);
|
||||||
resolve();
|
resolve(file);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
dropzoneInst.on(DropzoneCustomEventUploadDone, onUploadDone);
|
dropzoneInst.on(DropzoneCustomEventUploadDone, onUploadDone);
|
||||||
|
@ -27,6 +34,8 @@ function uploadFile(dropzoneEl, file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextareaEditor {
|
class TextareaEditor {
|
||||||
|
editor : HTMLTextAreaElement;
|
||||||
|
|
||||||
constructor(editor) {
|
constructor(editor) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +70,8 @@ class TextareaEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
class CodeMirrorEditor {
|
class CodeMirrorEditor {
|
||||||
|
editor: CodeMirror.EditorFromTextArea;
|
||||||
|
|
||||||
constructor(editor) {
|
constructor(editor) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import {handleReply} from './repo-issue.ts';
|
import {handleReply} from './repo-issue.ts';
|
||||||
import {getComboMarkdownEditor, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts';
|
import {getComboMarkdownEditor, initComboMarkdownEditor, ComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts';
|
||||||
import {POST} from '../modules/fetch.ts';
|
import {POST} from '../modules/fetch.ts';
|
||||||
import {showErrorToast} from '../modules/toast.ts';
|
import {showErrorToast} from '../modules/toast.ts';
|
||||||
import {hideElem, showElem} from '../utils/dom.ts';
|
import {hideElem, showElem} from '../utils/dom.ts';
|
||||||
import {attachRefIssueContextPopup} from './contextpopup.ts';
|
import {attachRefIssueContextPopup} from './contextpopup.ts';
|
||||||
import {initCommentContent, initMarkupContent} from '../markup/content.ts';
|
import {initCommentContent, initMarkupContent} from '../markup/content.ts';
|
||||||
|
import {triggerUploadStateChanged} from './comp/EditorUpload.ts';
|
||||||
|
|
||||||
async function onEditContent(event) {
|
async function onEditContent(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -15,7 +16,7 @@ async function onEditContent(event) {
|
||||||
const renderContent = segment.querySelector('.render-content');
|
const renderContent = segment.querySelector('.render-content');
|
||||||
const rawContent = segment.querySelector('.raw-content');
|
const rawContent = segment.querySelector('.raw-content');
|
||||||
|
|
||||||
let comboMarkdownEditor;
|
let comboMarkdownEditor : ComboMarkdownEditor;
|
||||||
|
|
||||||
const cancelAndReset = (e) => {
|
const cancelAndReset = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -79,9 +80,12 @@ async function onEditContent(event) {
|
||||||
comboMarkdownEditor = getComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor'));
|
comboMarkdownEditor = getComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor'));
|
||||||
if (!comboMarkdownEditor) {
|
if (!comboMarkdownEditor) {
|
||||||
editContentZone.innerHTML = document.querySelector('#issue-comment-editor-template').innerHTML;
|
editContentZone.innerHTML = document.querySelector('#issue-comment-editor-template').innerHTML;
|
||||||
|
const saveButton = editContentZone.querySelector('.ui.primary.button');
|
||||||
comboMarkdownEditor = await initComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor'));
|
comboMarkdownEditor = await initComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor'));
|
||||||
|
const syncUiState = () => saveButton.disabled = comboMarkdownEditor.isUploading();
|
||||||
|
comboMarkdownEditor.container.addEventListener(ComboMarkdownEditor.EventUploadStateChanged, syncUiState);
|
||||||
editContentZone.querySelector('.ui.cancel.button').addEventListener('click', cancelAndReset);
|
editContentZone.querySelector('.ui.cancel.button').addEventListener('click', cancelAndReset);
|
||||||
editContentZone.querySelector('.ui.primary.button').addEventListener('click', saveAndRefresh);
|
saveButton.addEventListener('click', saveAndRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show write/preview tab and copy raw content as needed
|
// Show write/preview tab and copy raw content as needed
|
||||||
|
@ -93,6 +97,7 @@ async function onEditContent(event) {
|
||||||
}
|
}
|
||||||
comboMarkdownEditor.switchTabToEditor();
|
comboMarkdownEditor.switchTabToEditor();
|
||||||
comboMarkdownEditor.focus();
|
comboMarkdownEditor.focus();
|
||||||
|
triggerUploadStateChanged(comboMarkdownEditor.container);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initRepoIssueCommentEdit() {
|
export function initRepoIssueCommentEdit() {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {htmlEscape} from 'escape-goat';
|
||||||
import {createTippy, showTemporaryTooltip} from '../modules/tippy.ts';
|
import {createTippy, showTemporaryTooltip} from '../modules/tippy.ts';
|
||||||
import {hideElem, showElem, toggleElem} from '../utils/dom.ts';
|
import {hideElem, showElem, toggleElem} from '../utils/dom.ts';
|
||||||
import {setFileFolding} from './file-fold.ts';
|
import {setFileFolding} from './file-fold.ts';
|
||||||
import {getComboMarkdownEditor, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts';
|
import {ComboMarkdownEditor, getComboMarkdownEditor, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts';
|
||||||
import {toAbsoluteUrl} from '../utils.ts';
|
import {toAbsoluteUrl} from '../utils.ts';
|
||||||
import {GET, POST} from '../modules/fetch.ts';
|
import {GET, POST} from '../modules/fetch.ts';
|
||||||
import {showErrorToast} from '../modules/toast.ts';
|
import {showErrorToast} from '../modules/toast.ts';
|
||||||
|
@ -483,9 +483,9 @@ export function initRepoPullRequestReview() {
|
||||||
await handleReply(this);
|
await handleReply(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
const $reviewBox = $('.review-box-panel');
|
const elReviewBox = document.querySelector('.review-box-panel');
|
||||||
if ($reviewBox.length === 1) {
|
if (elReviewBox) {
|
||||||
const _promise = initComboMarkdownEditor($reviewBox.find('.combo-markdown-editor'));
|
initComboMarkdownEditor(elReviewBox.querySelector('.combo-markdown-editor'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following part is only for diff views
|
// The following part is only for diff views
|
||||||
|
@ -548,7 +548,7 @@ export function initRepoPullRequestReview() {
|
||||||
$td.find("input[name='line']").val(idx);
|
$td.find("input[name='line']").val(idx);
|
||||||
$td.find("input[name='side']").val(side === 'left' ? 'previous' : 'proposed');
|
$td.find("input[name='side']").val(side === 'left' ? 'previous' : 'proposed');
|
||||||
$td.find("input[name='path']").val(path);
|
$td.find("input[name='path']").val(path);
|
||||||
const editor = await initComboMarkdownEditor($td.find('.combo-markdown-editor'));
|
const editor = await initComboMarkdownEditor($td[0].querySelector('.combo-markdown-editor'));
|
||||||
editor.focus();
|
editor.focus();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
@ -669,20 +669,22 @@ export async function initSingleCommentEditor($commentForm) {
|
||||||
// pages:
|
// pages:
|
||||||
// * normal new issue/pr page: no status-button, no comment-button (there is only a normal submit button which can submit empty content)
|
// * normal new issue/pr page: no status-button, no comment-button (there is only a normal submit button which can submit empty content)
|
||||||
// * issue/pr view page: with comment form, has status-button and comment-button
|
// * issue/pr view page: with comment form, has status-button and comment-button
|
||||||
const opts = {};
|
const editor = await initComboMarkdownEditor($commentForm[0].querySelector('.combo-markdown-editor'));
|
||||||
const statusButton = document.querySelector('#status-button');
|
const statusButton = document.querySelector<HTMLButtonElement>('#status-button');
|
||||||
const commentButton = document.querySelector('#comment-button');
|
const commentButton = document.querySelector<HTMLButtonElement>('#comment-button');
|
||||||
opts.onContentChanged = (editor) => {
|
const syncUiState = () => {
|
||||||
const editorText = editor.value().trim();
|
const editorText = editor.value().trim(), isUploading = editor.isUploading();
|
||||||
if (statusButton) {
|
if (statusButton) {
|
||||||
statusButton.textContent = statusButton.getAttribute(editorText ? 'data-status-and-comment' : 'data-status');
|
statusButton.textContent = statusButton.getAttribute(editorText ? 'data-status-and-comment' : 'data-status');
|
||||||
|
statusButton.disabled = isUploading;
|
||||||
}
|
}
|
||||||
if (commentButton) {
|
if (commentButton) {
|
||||||
commentButton.disabled = !editorText;
|
commentButton.disabled = !editorText || isUploading;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const editor = await initComboMarkdownEditor($commentForm.find('.combo-markdown-editor'), opts);
|
editor.container.addEventListener(ComboMarkdownEditor.EventUploadStateChanged, syncUiState);
|
||||||
opts.onContentChanged(editor); // sync state of buttons with the initial content
|
editor.container.addEventListener(ComboMarkdownEditor.EventEditorContentChanged, syncUiState);
|
||||||
|
syncUiState();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initIssueTemplateCommentEditors($commentForm) {
|
export function initIssueTemplateCommentEditors($commentForm) {
|
||||||
|
@ -690,16 +692,13 @@ export function initIssueTemplateCommentEditors($commentForm) {
|
||||||
// * new issue with issue template
|
// * new issue with issue template
|
||||||
const $comboFields = $commentForm.find('.combo-editor-dropzone');
|
const $comboFields = $commentForm.find('.combo-editor-dropzone');
|
||||||
|
|
||||||
const initCombo = async ($combo) => {
|
const initCombo = async (elCombo) => {
|
||||||
const $dropzoneContainer = $combo.find('.form-field-dropzone');
|
const $formField = $(elCombo.querySelector('.form-field-real'));
|
||||||
const $formField = $combo.find('.form-field-real');
|
const dropzoneContainer = elCombo.querySelector('.form-field-dropzone');
|
||||||
const $markdownEditor = $combo.find('.combo-markdown-editor');
|
const markdownEditor = elCombo.querySelector('.combo-markdown-editor');
|
||||||
|
|
||||||
const editor = await initComboMarkdownEditor($markdownEditor, {
|
const editor = await initComboMarkdownEditor(markdownEditor);
|
||||||
onContentChanged: (editor) => {
|
editor.container.addEventListener(ComboMarkdownEditor.EventEditorContentChanged, () => $formField.val(editor.value()));
|
||||||
$formField.val(editor.value());
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
$formField.on('focus', async () => {
|
$formField.on('focus', async () => {
|
||||||
// deactivate all markdown editors
|
// deactivate all markdown editors
|
||||||
|
@ -709,8 +708,8 @@ export function initIssueTemplateCommentEditors($commentForm) {
|
||||||
|
|
||||||
// activate this markdown editor
|
// activate this markdown editor
|
||||||
hideElem($formField);
|
hideElem($formField);
|
||||||
showElem($markdownEditor);
|
showElem(markdownEditor);
|
||||||
showElem($dropzoneContainer);
|
showElem(dropzoneContainer);
|
||||||
|
|
||||||
await editor.switchToUserPreference();
|
await editor.switchToUserPreference();
|
||||||
editor.focus();
|
editor.focus();
|
||||||
|
@ -718,7 +717,7 @@ export function initIssueTemplateCommentEditors($commentForm) {
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const el of $comboFields) {
|
for (const el of $comboFields) {
|
||||||
initCombo($(el));
|
initCombo(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ function initTagNameEditor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function initRepoReleaseEditor() {
|
function initRepoReleaseEditor() {
|
||||||
const editor = document.querySelector('.repository.new.release .combo-markdown-editor');
|
const editor = document.querySelector<HTMLElement>('.repository.new.release .combo-markdown-editor');
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,11 @@ import {fomanticMobileScreen} from '../modules/fomantic.ts';
|
||||||
import {POST} from '../modules/fetch.ts';
|
import {POST} from '../modules/fetch.ts';
|
||||||
|
|
||||||
async function initRepoWikiFormEditor() {
|
async function initRepoWikiFormEditor() {
|
||||||
const editArea = document.querySelector('.repository.wiki .combo-markdown-editor textarea');
|
const editArea = document.querySelector<HTMLTextAreaElement>('.repository.wiki .combo-markdown-editor textarea');
|
||||||
if (!editArea) return;
|
if (!editArea) return;
|
||||||
|
|
||||||
const form = document.querySelector('.repository.wiki.new .ui.form');
|
const form = document.querySelector('.repository.wiki.new .ui.form');
|
||||||
const editorContainer = form.querySelector('.combo-markdown-editor');
|
const editorContainer = form.querySelector<HTMLElement>('.combo-markdown-editor');
|
||||||
let editor;
|
let editor;
|
||||||
|
|
||||||
let renderRequesting = false;
|
let renderRequesting = false;
|
||||||
|
|
Loading…
Reference in a new issue