mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 20:36:07 +01:00 
			
		
		
		
	Make Ctrl+Enter (quick submit) work for issue comment and wiki editor (#19729)
* Make Ctrl+Enter (quick submit) work for issue comment and wiki editor * Remove the required `SubmitReviewForm.Type`, empty type (triggered by quick submit) means "comment" * Merge duplicate code
This commit is contained in:
		@@ -623,7 +623,7 @@ func (f *CodeCommentForm) Validate(req *http.Request, errs binding.Errors) bindi
 | 
			
		||||
// SubmitReviewForm for submitting a finished code review
 | 
			
		||||
type SubmitReviewForm struct {
 | 
			
		||||
	Content  string
 | 
			
		||||
	Type     string `binding:"Required;In(approve,comment,reject)"`
 | 
			
		||||
	Type     string
 | 
			
		||||
	CommitID string
 | 
			
		||||
	Files    []string
 | 
			
		||||
}
 | 
			
		||||
@@ -634,7 +634,7 @@ func (f *SubmitReviewForm) Validate(req *http.Request, errs binding.Errors) bind
 | 
			
		||||
	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReviewType will return the corresponding reviewtype for type
 | 
			
		||||
// ReviewType will return the corresponding ReviewType for type
 | 
			
		||||
func (f SubmitReviewForm) ReviewType() models.ReviewType {
 | 
			
		||||
	switch f.Type {
 | 
			
		||||
	case "approve":
 | 
			
		||||
@@ -643,6 +643,8 @@ func (f SubmitReviewForm) ReviewType() models.ReviewType {
 | 
			
		||||
		return models.ReviewTypeComment
 | 
			
		||||
	case "reject":
 | 
			
		||||
		return models.ReviewTypeReject
 | 
			
		||||
	case "":
 | 
			
		||||
		return models.ReviewTypeComment // default to comment when doing quick-submit (Ctrl+Enter) on the review form
 | 
			
		||||
	default:
 | 
			
		||||
		return models.ReviewTypeUnknown
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -180,7 +180,7 @@
 | 
			
		||||
						<a class="preview item" data-url="{{$.Repository.HTMLURL}}/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div class="ui bottom attached active write tab segment">
 | 
			
		||||
						<textarea class="review-textarea" tabindex="1" name="content"></textarea>
 | 
			
		||||
						<textarea class="review-textarea js-quick-submit" tabindex="1" name="content"></textarea>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div class="ui bottom attached tab preview segment markup">
 | 
			
		||||
					{{$.i18n.Tr "loading"}}
 | 
			
		||||
 
 | 
			
		||||
@@ -202,7 +202,7 @@
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="field">
 | 
			
		||||
			<div class="ui bottom active tab write">
 | 
			
		||||
				<textarea tabindex="1" name="content"></textarea>
 | 
			
		||||
				<textarea tabindex="1" name="content" class="js-quick-submit"></textarea>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="ui bottom tab preview markup">
 | 
			
		||||
				{{$.i18n.Tr "loading"}}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="field {{if .Err_Content}}error{{end}}">
 | 
			
		||||
				<label for="content">{{.i18n.Tr "settings.key_content"}}</label>
 | 
			
		||||
				<textarea id="ssh-key-content" name="content" placeholder="{{.i18n.Tr "settings.key_content_ssh_placeholder"}}" required>{{.content}}</textarea>
 | 
			
		||||
				<textarea id="ssh-key-content" name="content" class="js-quick-submit" placeholder="{{.i18n.Tr "settings.key_content_ssh_placeholder"}}" required>{{.content}}</textarea>
 | 
			
		||||
			</div>
 | 
			
		||||
			<input name="type" type="hidden" value="ssh">
 | 
			
		||||
			<button class="ui green button">
 | 
			
		||||
@@ -81,7 +81,7 @@
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class="field">
 | 
			
		||||
							<label for="signature">{{$.i18n.Tr "settings.ssh_token_signature"}}</label>
 | 
			
		||||
							<textarea id="ssh-key-signature" name="signature" placeholder="{{$.i18n.Tr "settings.key_signature_ssh_placeholder"}}" required>{{$.signature}}</textarea>
 | 
			
		||||
							<textarea id="ssh-key-signature" name="signature" class="js-quick-submit" placeholder="{{$.i18n.Tr "settings.key_signature_ssh_placeholder"}}" required>{{$.signature}}</textarea>
 | 
			
		||||
						</div>
 | 
			
		||||
						<input name="type" type="hidden" value="verify_ssh">
 | 
			
		||||
						<button class="ui green button">
 | 
			
		||||
 
 | 
			
		||||
@@ -44,13 +44,28 @@ export function initFootLanguageMenu() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export function initGlobalEnterQuickSubmit() {
 | 
			
		||||
  $('.js-quick-submit').on('keydown', function (e) {
 | 
			
		||||
    if (((e.ctrlKey && !e.altKey) || e.metaKey) && (e.keyCode === 13 || e.keyCode === 10)) {
 | 
			
		||||
      $(this).closest('form').trigger('submit');
 | 
			
		||||
  $(document).on('keydown', '.js-quick-submit', (e) => {
 | 
			
		||||
    if (((e.ctrlKey && !e.altKey) || e.metaKey) && (e.key === 'Enter')) {
 | 
			
		||||
      handleGlobalEnterQuickSubmit(e.target);
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function handleGlobalEnterQuickSubmit(target) {
 | 
			
		||||
  const $target = $(target);
 | 
			
		||||
  const $form = $(target).closest('form');
 | 
			
		||||
  if ($form.length) {
 | 
			
		||||
    // here use the event to trigger the submit event (instead of calling `submit()` method directly)
 | 
			
		||||
    // otherwise the `areYouSure` handler won't be executed, then there will be an annoying "confirm to leave" dialog
 | 
			
		||||
    $form.trigger('submit');
 | 
			
		||||
  } else {
 | 
			
		||||
    // if no form, then the editor is for an AJAX request, dispatch an event to the target, let the target's event handler to do the AJAX request.
 | 
			
		||||
    // the 'ce-' prefix means this is a CustomEvent
 | 
			
		||||
    $target.trigger('ce-quick-submit');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function initGlobalButtonClickOnEnter() {
 | 
			
		||||
  $(document).on('keypress', '.ui.button', (e) => {
 | 
			
		||||
    if (e.keyCode === 13 || e.keyCode === 32) { // enter key or space bar
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import $ from 'jquery';
 | 
			
		||||
import attachTribute from '../tribute.js';
 | 
			
		||||
import {handleGlobalEnterQuickSubmit} from '../common-global.js';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @returns {EasyMDE}
 | 
			
		||||
@@ -71,9 +72,12 @@ export async function createCommentEasyMDE(textarea, easyMDEOptions = {}) {
 | 
			
		||||
        title: 'Revert to simple textarea',
 | 
			
		||||
      },
 | 
			
		||||
    ], ...easyMDEOptions});
 | 
			
		||||
 | 
			
		||||
  const inputField = easyMDE.codemirror.getInputField();
 | 
			
		||||
  inputField.classList.add('js-quick-submit');
 | 
			
		||||
 | 
			
		||||
  easyMDE.codemirror.setOption('extraKeys', {
 | 
			
		||||
    'Cmd-Enter': codeMirrorQuickSubmit,
 | 
			
		||||
    'Ctrl-Enter': codeMirrorQuickSubmit,
 | 
			
		||||
    Enter: (cm) => {
 | 
			
		||||
      const tributeContainer = document.querySelector('.tribute-container');
 | 
			
		||||
      if (!tributeContainer || tributeContainer.style.display === 'none') {
 | 
			
		||||
@@ -149,3 +153,12 @@ export function validateTextareaNonEmpty($textarea) {
 | 
			
		||||
  $mdeInputField.prop('required', false);
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * there is no guarantee that the CodeMirror object is inside the same form as the textarea,
 | 
			
		||||
 * so can not call handleGlobalEnterQuickSubmit directly.
 | 
			
		||||
 * @param {CodeMirror.EditorFromTextArea} codeMirror
 | 
			
		||||
 */
 | 
			
		||||
export function codeMirrorQuickSubmit(codeMirror) {
 | 
			
		||||
  handleGlobalEnterQuickSubmit(codeMirror.getTextArea());
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -355,6 +355,11 @@ async function onEditContent(event) {
 | 
			
		||||
      initEasyMDEImagePaste(easyMDE, $dropzone[0], $dropzone.find('.files'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const $saveButton = $editContentZone.find('.save.button');
 | 
			
		||||
    $textarea.on('ce-quick-submit', () => {
 | 
			
		||||
      $saveButton.trigger('click');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $editContentZone.find('.cancel.button').on('click', () => {
 | 
			
		||||
      $renderContent.show();
 | 
			
		||||
      $editContentZone.hide();
 | 
			
		||||
@@ -362,7 +367,8 @@ async function onEditContent(event) {
 | 
			
		||||
        dz.emit('reload');
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    $editContentZone.find('.save.button').on('click', () => {
 | 
			
		||||
 | 
			
		||||
    $saveButton.on('click', () => {
 | 
			
		||||
      $renderContent.show();
 | 
			
		||||
      $editContentZone.hide();
 | 
			
		||||
      const $attachments = $dropzone.find('.files').find('[name=files]').map(function () {
 | 
			
		||||
@@ -400,7 +406,7 @@ async function onEditContent(event) {
 | 
			
		||||
        initCommentContent();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  } else {
 | 
			
		||||
  } else { // use existing form
 | 
			
		||||
    $textarea = $segment.find('textarea');
 | 
			
		||||
    easyMDE = getAttachedEasyMDE($textarea);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import $ from 'jquery';
 | 
			
		||||
import {initMarkupContent} from '../markup/content.js';
 | 
			
		||||
import {attachEasyMDEToElements, importEasyMDE, validateTextareaNonEmpty} from './comp/EasyMDE.js';
 | 
			
		||||
import {attachEasyMDEToElements, codeMirrorQuickSubmit, importEasyMDE, validateTextareaNonEmpty} from './comp/EasyMDE.js';
 | 
			
		||||
import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js';
 | 
			
		||||
 | 
			
		||||
const {csrfToken} = window.config;
 | 
			
		||||
@@ -122,10 +122,12 @@ async function initRepoWikiFormEditor() {
 | 
			
		||||
    ]
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  attachEasyMDEToElements(easyMDE);
 | 
			
		||||
  easyMDE.codemirror.setOption('extraKeys', {
 | 
			
		||||
    'Cmd-Enter': codeMirrorQuickSubmit,
 | 
			
		||||
    'Ctrl-Enter': codeMirrorQuickSubmit,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const $mdeInputField = $(easyMDE.codemirror.getInputField());
 | 
			
		||||
  $mdeInputField.addClass('js-quick-submit');
 | 
			
		||||
  attachEasyMDEToElements(easyMDE);
 | 
			
		||||
 | 
			
		||||
  $form.on('submit', () => {
 | 
			
		||||
    if (!validateTextareaNonEmpty($editArea)) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user