From f83eb25569bf52e8a2ee742a1960282105889a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20I=C3=9Fbr=C3=BCcker?= Date: Sat, 16 Aug 2025 06:20:07 +0200 Subject: [PATCH] Submit bookmark form with Ctrl/Cmd + Enter (#1158) --- bookmarks/frontend/behaviors/form.js | 23 ++++++++++++++++ bookmarks/templates/bookmarks/edit.html | 2 +- bookmarks/templates/bookmarks/new.html | 2 +- .../tests_e2e/e2e_test_new_bookmark_form.py | 26 ++++++++++++++++++- 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/bookmarks/frontend/behaviors/form.js b/bookmarks/frontend/behaviors/form.js index ca47555..8df61cf 100644 --- a/bookmarks/frontend/behaviors/form.js +++ b/bookmarks/frontend/behaviors/form.js @@ -1,5 +1,27 @@ import { Behavior, registerBehavior } from "./index"; +class FormSubmit extends Behavior { + constructor(element) { + super(element); + + this.onKeyDown = this.onKeyDown.bind(this); + this.element.addEventListener("keydown", this.onKeyDown); + } + + destroy() { + this.element.removeEventListener("keydown", this.onKeyDown); + } + + onKeyDown(event) { + // Check for Ctrl/Cmd + Enter combination + if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) { + event.preventDefault(); + event.stopPropagation(); + this.element.requestSubmit(); + } + } +} + class AutoSubmitBehavior extends Behavior { constructor(element) { super(element); @@ -51,5 +73,6 @@ class UploadButton extends Behavior { } } +registerBehavior("ld-form-submit", FormSubmit); registerBehavior("ld-auto-submit", AutoSubmitBehavior); registerBehavior("ld-upload-button", UploadButton); diff --git a/bookmarks/templates/bookmarks/edit.html b/bookmarks/templates/bookmarks/edit.html index cbf0ddc..4f4dcd4 100644 --- a/bookmarks/templates/bookmarks/edit.html +++ b/bookmarks/templates/bookmarks/edit.html @@ -13,7 +13,7 @@

Edit bookmark

+ novalidate ld-form-submit> {% include 'bookmarks/form.html' %}
diff --git a/bookmarks/templates/bookmarks/new.html b/bookmarks/templates/bookmarks/new.html index 43fa7df..58ccfa9 100644 --- a/bookmarks/templates/bookmarks/new.html +++ b/bookmarks/templates/bookmarks/new.html @@ -12,7 +12,7 @@

New bookmark

-
+ {% include 'bookmarks/form.html' %}
diff --git a/bookmarks/tests_e2e/e2e_test_new_bookmark_form.py b/bookmarks/tests_e2e/e2e_test_new_bookmark_form.py index f7a5ae7..569056c 100644 --- a/bookmarks/tests_e2e/e2e_test_new_bookmark_form.py +++ b/bookmarks/tests_e2e/e2e_test_new_bookmark_form.py @@ -4,8 +4,9 @@ from urllib.parse import quote from django.urls import reverse from playwright.sync_api import sync_playwright, expect -from bookmarks.tests_e2e.helpers import LinkdingE2ETestCase +from bookmarks.models import Bookmark from bookmarks.services import website_loader +from bookmarks.tests_e2e.helpers import LinkdingE2ETestCase mock_website_metadata = website_loader.WebsiteMetadata( url="https://example.com", @@ -311,3 +312,26 @@ class BookmarkFormE2ETestCase(LinkdingE2ETestCase): # Verify that the fields are NOT visually marked as modified expect(title_field).to_have_class("form-input") expect(description_field).to_have_class("form-input") + + def test_ctrl_enter_submits_form_from_description(self): + with sync_playwright() as p: + page = self.open(reverse("linkding:bookmarks.new"), p) + url_field = page.get_by_label("URL") + description_field = page.get_by_label("Description") + + url_field.fill("https://example.com") + description_field.fill("Test description") + description_field.focus() + + # Press Ctrl+Enter to submit form + description_field.press("Control+Enter") + + # Should navigate away from new bookmark page after successful submission + expect(page).not_to_have_url( + self.live_server_url + reverse("linkding:bookmarks.new") + ) + + self.assertEqual(1, Bookmark.objects.count()) + bookmark = Bookmark.objects.first() + self.assertEqual("https://example.com", bookmark.url) + self.assertEqual("Example Domain", bookmark.title)