Skip to content

Commit cc7236e

Browse files
authored
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
1 parent 3b359b1 commit cc7236e

File tree

8 files changed

+54
-16
lines changed

8 files changed

+54
-16
lines changed

services/forms/repo_form.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ func (f *CodeCommentForm) Validate(req *http.Request, errs binding.Errors) bindi
623623
// SubmitReviewForm for submitting a finished code review
624624
type SubmitReviewForm struct {
625625
Content string
626-
Type string `binding:"Required;In(approve,comment,reject)"`
626+
Type string
627627
CommitID string
628628
Files []string
629629
}
@@ -634,7 +634,7 @@ func (f *SubmitReviewForm) Validate(req *http.Request, errs binding.Errors) bind
634634
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
635635
}
636636

637-
// ReviewType will return the corresponding reviewtype for type
637+
// ReviewType will return the corresponding ReviewType for type
638638
func (f SubmitReviewForm) ReviewType() models.ReviewType {
639639
switch f.Type {
640640
case "approve":
@@ -643,6 +643,8 @@ func (f SubmitReviewForm) ReviewType() models.ReviewType {
643643
return models.ReviewTypeComment
644644
case "reject":
645645
return models.ReviewTypeReject
646+
case "":
647+
return models.ReviewTypeComment // default to comment when doing quick-submit (Ctrl+Enter) on the review form
646648
default:
647649
return models.ReviewTypeUnknown
648650
}

templates/repo/diff/box.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@
180180
<a class="preview item" data-url="{{$.Repository.HTMLURL}}/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a>
181181
</div>
182182
<div class="ui bottom attached active write tab segment">
183-
<textarea class="review-textarea" tabindex="1" name="content"></textarea>
183+
<textarea class="review-textarea js-quick-submit" tabindex="1" name="content"></textarea>
184184
</div>
185185
<div class="ui bottom attached tab preview segment markup">
186186
{{$.i18n.Tr "loading"}}

templates/repo/issue/view_content.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@
202202
</div>
203203
<div class="field">
204204
<div class="ui bottom active tab write">
205-
<textarea tabindex="1" name="content"></textarea>
205+
<textarea tabindex="1" name="content" class="js-quick-submit"></textarea>
206206
</div>
207207
<div class="ui bottom tab preview markup">
208208
{{$.i18n.Tr "loading"}}

templates/user/settings/keys_ssh.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
</div>
2121
<div class="field {{if .Err_Content}}error{{end}}">
2222
<label for="content">{{.i18n.Tr "settings.key_content"}}</label>
23-
<textarea id="ssh-key-content" name="content" placeholder="{{.i18n.Tr "settings.key_content_ssh_placeholder"}}" required>{{.content}}</textarea>
23+
<textarea id="ssh-key-content" name="content" class="js-quick-submit" placeholder="{{.i18n.Tr "settings.key_content_ssh_placeholder"}}" required>{{.content}}</textarea>
2424
</div>
2525
<input name="type" type="hidden" value="ssh">
2626
<button class="ui green button">
@@ -81,7 +81,7 @@
8181
</div>
8282
<div class="field">
8383
<label for="signature">{{$.i18n.Tr "settings.ssh_token_signature"}}</label>
84-
<textarea id="ssh-key-signature" name="signature" placeholder="{{$.i18n.Tr "settings.key_signature_ssh_placeholder"}}" required>{{$.signature}}</textarea>
84+
<textarea id="ssh-key-signature" name="signature" class="js-quick-submit" placeholder="{{$.i18n.Tr "settings.key_signature_ssh_placeholder"}}" required>{{$.signature}}</textarea>
8585
</div>
8686
<input name="type" type="hidden" value="verify_ssh">
8787
<button class="ui green button">

web_src/js/features/common-global.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,28 @@ export function initFootLanguageMenu() {
4444

4545

4646
export function initGlobalEnterQuickSubmit() {
47-
$('.js-quick-submit').on('keydown', function (e) {
48-
if (((e.ctrlKey && !e.altKey) || e.metaKey) && (e.keyCode === 13 || e.keyCode === 10)) {
49-
$(this).closest('form').trigger('submit');
47+
$(document).on('keydown', '.js-quick-submit', (e) => {
48+
if (((e.ctrlKey && !e.altKey) || e.metaKey) && (e.key === 'Enter')) {
49+
handleGlobalEnterQuickSubmit(e.target);
50+
return false;
5051
}
5152
});
5253
}
5354

55+
export function handleGlobalEnterQuickSubmit(target) {
56+
const $target = $(target);
57+
const $form = $(target).closest('form');
58+
if ($form.length) {
59+
// here use the event to trigger the submit event (instead of calling `submit()` method directly)
60+
// otherwise the `areYouSure` handler won't be executed, then there will be an annoying "confirm to leave" dialog
61+
$form.trigger('submit');
62+
} else {
63+
// 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.
64+
// the 'ce-' prefix means this is a CustomEvent
65+
$target.trigger('ce-quick-submit');
66+
}
67+
}
68+
5469
export function initGlobalButtonClickOnEnter() {
5570
$(document).on('keypress', '.ui.button', (e) => {
5671
if (e.keyCode === 13 || e.keyCode === 32) { // enter key or space bar

web_src/js/features/comp/EasyMDE.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import $ from 'jquery';
22
import attachTribute from '../tribute.js';
3+
import {handleGlobalEnterQuickSubmit} from '../common-global.js';
34

45
/**
56
* @returns {EasyMDE}
@@ -71,9 +72,12 @@ export async function createCommentEasyMDE(textarea, easyMDEOptions = {}) {
7172
title: 'Revert to simple textarea',
7273
},
7374
], ...easyMDEOptions});
75+
7476
const inputField = easyMDE.codemirror.getInputField();
75-
inputField.classList.add('js-quick-submit');
77+
7678
easyMDE.codemirror.setOption('extraKeys', {
79+
'Cmd-Enter': codeMirrorQuickSubmit,
80+
'Ctrl-Enter': codeMirrorQuickSubmit,
7781
Enter: (cm) => {
7882
const tributeContainer = document.querySelector('.tribute-container');
7983
if (!tributeContainer || tributeContainer.style.display === 'none') {
@@ -149,3 +153,12 @@ export function validateTextareaNonEmpty($textarea) {
149153
$mdeInputField.prop('required', false);
150154
return true;
151155
}
156+
157+
/**
158+
* there is no guarantee that the CodeMirror object is inside the same form as the textarea,
159+
* so can not call handleGlobalEnterQuickSubmit directly.
160+
* @param {CodeMirror.EditorFromTextArea} codeMirror
161+
*/
162+
export function codeMirrorQuickSubmit(codeMirror) {
163+
handleGlobalEnterQuickSubmit(codeMirror.getTextArea());
164+
}

web_src/js/features/repo-legacy.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,14 +355,20 @@ async function onEditContent(event) {
355355
initEasyMDEImagePaste(easyMDE, $dropzone[0], $dropzone.find('.files'));
356356
}
357357

358+
const $saveButton = $editContentZone.find('.save.button');
359+
$textarea.on('ce-quick-submit', () => {
360+
$saveButton.trigger('click');
361+
});
362+
358363
$editContentZone.find('.cancel.button').on('click', () => {
359364
$renderContent.show();
360365
$editContentZone.hide();
361366
if (dz) {
362367
dz.emit('reload');
363368
}
364369
});
365-
$editContentZone.find('.save.button').on('click', () => {
370+
371+
$saveButton.on('click', () => {
366372
$renderContent.show();
367373
$editContentZone.hide();
368374
const $attachments = $dropzone.find('.files').find('[name=files]').map(function () {
@@ -400,7 +406,7 @@ async function onEditContent(event) {
400406
initCommentContent();
401407
});
402408
});
403-
} else {
409+
} else { // use existing form
404410
$textarea = $segment.find('textarea');
405411
easyMDE = getAttachedEasyMDE($textarea);
406412
}

web_src/js/features/repo-wiki.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import $ from 'jquery';
22
import {initMarkupContent} from '../markup/content.js';
3-
import {attachEasyMDEToElements, importEasyMDE, validateTextareaNonEmpty} from './comp/EasyMDE.js';
3+
import {attachEasyMDEToElements, codeMirrorQuickSubmit, importEasyMDE, validateTextareaNonEmpty} from './comp/EasyMDE.js';
44
import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js';
55

66
const {csrfToken} = window.config;
@@ -122,10 +122,12 @@ async function initRepoWikiFormEditor() {
122122
]
123123
});
124124

125-
attachEasyMDEToElements(easyMDE);
125+
easyMDE.codemirror.setOption('extraKeys', {
126+
'Cmd-Enter': codeMirrorQuickSubmit,
127+
'Ctrl-Enter': codeMirrorQuickSubmit,
128+
});
126129

127-
const $mdeInputField = $(easyMDE.codemirror.getInputField());
128-
$mdeInputField.addClass('js-quick-submit');
130+
attachEasyMDEToElements(easyMDE);
129131

130132
$form.on('submit', () => {
131133
if (!validateTextareaNonEmpty($editArea)) {

0 commit comments

Comments
 (0)