From 207d55fb244a50b2e5116a54f5f5320985496ec0 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Fri, 2 Jan 2026 17:37:44 +0530 Subject: [PATCH 01/12] feat(Navbar): show title when available --- frappe/public/js/frappe/ui/page.js | 3 ++- frappe/public/js/frappe/views/breadcrumbs.js | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/ui/page.js b/frappe/public/js/frappe/ui/page.js index 857bbcb4dd..95b6046f4b 100644 --- a/frappe/public/js/frappe/ui/page.js +++ b/frappe/public/js/frappe/ui/page.js @@ -770,7 +770,8 @@ frappe.ui.Page = class Page { if (icon) { title = `${frappe.utils.icon(icon)} ${title}`; } - let title_wrapper = this.$title_area.find(".title-text"); + + let title_wrapper = this.$title_area.find(".title-text-form"); title_wrapper.html(title); title_wrapper.attr("title", __(tooltip_label) || this.title); diff --git a/frappe/public/js/frappe/views/breadcrumbs.js b/frappe/public/js/frappe/views/breadcrumbs.js index abe1f60922..af4345e5f4 100644 --- a/frappe/public/js/frappe/views/breadcrumbs.js +++ b/frappe/public/js/frappe/views/breadcrumbs.js @@ -224,7 +224,8 @@ frappe.breadcrumbs = { if (docname.startsWith("new-" + doctype.toLowerCase().replace(/ /g, "-"))) { docname_title = __("New {0}", [__(doctype)]); } else { - docname_title = doc.name; + let title = frappe.model.get_doc_title(doc); + docname_title = title || doc.name; } this.append_breadcrumb_element(form_route, docname_title, "title-text-form"); @@ -238,7 +239,12 @@ frappe.breadcrumbs = { last_crumb.css("cursor", "copy"); last_crumb.click((event) => { event.stopImmediatePropagation(); - frappe.utils.copy_to_clipboard(last_crumb.text()); + frappe.utils.copy_to_clipboard(doc.name); + }); + last_crumb.attr("title", __("Click to copy name")); + last_crumb.tooltip({ + delay: { show: 100, hide: 100 }, + trigger: "hover", }); } }, From a8b615b278d851775d0761e494251c10b642e21f Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Fri, 2 Jan 2026 18:15:55 +0530 Subject: [PATCH 02/12] fix: allow setting cutom list title --- frappe/public/js/frappe/ui/page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/ui/page.js b/frappe/public/js/frappe/ui/page.js index 95b6046f4b..b2ab3dc581 100644 --- a/frappe/public/js/frappe/ui/page.js +++ b/frappe/public/js/frappe/ui/page.js @@ -771,7 +771,7 @@ frappe.ui.Page = class Page { title = `${frappe.utils.icon(icon)} ${title}`; } - let title_wrapper = this.$title_area.find(".title-text-form"); + let title_wrapper = this.$title_area.find(".title-text"); title_wrapper.html(title); title_wrapper.attr("title", __(tooltip_label) || this.title); From ffa2a6bfa59e3bf5adbefc725a011e48f683a0d4 Mon Sep 17 00:00:00 2001 From: trustedcomputer Date: Fri, 2 Jan 2026 16:05:46 -0800 Subject: [PATCH 03/12] fix(ui): add navigation buttons back --- frappe/core/doctype/user/user.json | 9 ++++++++- frappe/core/doctype/user/user.py | 2 ++ frappe/public/js/frappe/form/toolbar.js | 5 ++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/user/user.json b/frappe/core/doctype/user/user.json index 9a13ccb3a5..5454f5ac62 100644 --- a/frappe/core/doctype/user/user.json +++ b/frappe/core/doctype/user/user.json @@ -59,6 +59,7 @@ "view_switcher", "form_settings_section", "form_sidebar", + "form_navigation_buttons", "timeline", "dashboard", "show_absolute_datetime_in_timeline", @@ -850,6 +851,12 @@ "is_virtual": 1, "label": "Active Sessions", "options": "User Session Display" + }, + { + "default": "1", + "fieldname": "form_navigation_buttons", + "fieldtype": "Check", + "label": "Navigation Buttons" } ], "icon": "fa fa-user", @@ -903,7 +910,7 @@ } ], "make_attachments_public": 1, - "modified": "2025-12-13 12:53:46.486021", + "modified": "2026-01-02 16:00:51.406511", "modified_by": "Administrator", "module": "Core", "name": "User", diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 4fbc28a96a..1557b90ce8 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -48,6 +48,7 @@ desk_properties = ( "bulk_actions", "view_switcher", "form_sidebar", + "form_navigation_buttons", "timeline", "dashboard", ) @@ -96,6 +97,7 @@ class User(Document): follow_created_documents: DF.Check follow_liked_documents: DF.Check follow_shared_documents: DF.Check + form_navigation_buttons: DF.Check form_sidebar: DF.Check full_name: DF.Data | None gender: DF.Link | None diff --git a/frappe/public/js/frappe/form/toolbar.js b/frappe/public/js/frappe/form/toolbar.js index bf527655fd..1f65c44f30 100644 --- a/frappe/public/js/frappe/form/toolbar.js +++ b/frappe/public/js/frappe/form/toolbar.js @@ -318,9 +318,12 @@ frappe.ui.form.Toolbar = class Toolbar { this.page.clear_menu(); if (frappe.boot.desk_settings.form_sidebar) { - // this.make_navigation(); this.make_menu_items(); } + + if (frappe.boot.desk_settings.form_navigation_buttons) { + this.make_navigation(); + } } make_navigation() { From 8d99bed738703e712e11c9fac2285326ef7cc1bf Mon Sep 17 00:00:00 2001 From: AarDG10 Date: Sat, 3 Jan 2026 13:54:27 +0530 Subject: [PATCH 04/12] fix(test): maintain sanity to avoid unexpected test failures in postgres --- frappe/tests/test_sqlite_search.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/tests/test_sqlite_search.py b/frappe/tests/test_sqlite_search.py index c4c528e294..8f6bfcee99 100644 --- a/frappe/tests/test_sqlite_search.py +++ b/frappe/tests/test_sqlite_search.py @@ -47,6 +47,8 @@ class TestSQLiteSearchAPI(IntegrationTestCase): @classmethod def setUpClass(cls): super().setUpClass() + frappe.db.delete("Note") + frappe.db.delete("ToDo") cls.search = TestSQLiteSearch() # Clean up any existing test database cls.search.drop_index() From 21f6fbadba0506686292e9fdfe5caab11db20338 Mon Sep 17 00:00:00 2001 From: Kerolles Fathy Date: Sat, 3 Jan 2026 18:05:55 +0200 Subject: [PATCH 05/12] fix: share doc with everyone (#35634) * fix: handle shared with everyone case * chore: remove comment * fix: remove unrelated change --- frappe/public/js/frappe/form/sidebar/share.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/form/sidebar/share.js b/frappe/public/js/frappe/form/sidebar/share.js index b771929a64..56a9af08bc 100644 --- a/frappe/public/js/frappe/form/sidebar/share.js +++ b/frappe/public/js/frappe/form/sidebar/share.js @@ -11,7 +11,8 @@ frappe.ui.form.Share = class Share { } render_sidebar() { const shared = this.shared || this.frm.get_docinfo().shared; - const shared_users = shared.filter(Boolean).map((s) => s.user); + const has_everyone = shared.some((s) => s && s.everyone); + const shared_users = shared.filter((s) => s && s.user && !s.everyone).map((s) => s.user); if (this.frm.is_new()) { this.parent.find(".share-doc-btn").hide(); @@ -26,7 +27,7 @@ frappe.ui.form.Share = class Share { this.shares.empty(); - if (!shared_users.length) { + if (!shared_users.length && !has_everyone) { this.shares.hide(); return; } @@ -36,7 +37,12 @@ frappe.ui.form.Share = class Share { avatar_group.on("click", () => { this.frm.share_doc(); }); - // REDESIGN-TODO: handle "shared with everyone" + + if (has_everyone) { + avatar_group.prepend( + frappe.avatar_group(["Everyone"], 1, { align: "left", overlap: true }) + ); + } this.shares.append(avatar_group); } show() { From 2f62168654af021af7664f41dbd1a1e5f8efcae5 Mon Sep 17 00:00:00 2001 From: Packeting <127834955+Packeting1@users.noreply.github.com> Date: Sun, 4 Jan 2026 11:17:30 +0800 Subject: [PATCH 06/12] fix: show form button in mobile print view --- frappe/printing/page/print/print.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/frappe/printing/page/print/print.js b/frappe/printing/page/print/print.js index e20859348a..a3b8fba88b 100644 --- a/frappe/printing/page/print/print.js +++ b/frappe/printing/page/print/print.js @@ -88,14 +88,16 @@ frappe.ui.form.PrintView = class { icon: "refresh", }); - this.page.add_action_icon( - "es-line-filetype", - () => { - this.go_to_form_view(); - }, - "", - __("Form") - ); + if (frappe.is_mobile()) { + this.page.add_button(__("Form"), () => this.go_to_form_view(), { icon: "small-file" }); + } else { + this.page.add_action_icon( + "es-line-filetype", + () => this.go_to_form_view(), + "", + __("Form") + ); + } } setup_sidebar() { From 8d8fa78bee65825ce5033b1d21fd67b09f12baca Mon Sep 17 00:00:00 2001 From: Aarol D'Souza <98270103+AarDG10@users.noreply.github.com> Date: Sun, 4 Jan 2026 10:18:53 +0530 Subject: [PATCH 07/12] fix(postgres): add pg compatible query for copying comm_date from comm to comm_link (#35488) --- .../copy_communication_date_to_link.py | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/frappe/core/doctype/communication_link/patches/copy_communication_date_to_link.py b/frappe/core/doctype/communication_link/patches/copy_communication_date_to_link.py index 0a6cd1ee5e..563acd8f8d 100644 --- a/frappe/core/doctype/communication_link/patches/copy_communication_date_to_link.py +++ b/frappe/core/doctype/communication_link/patches/copy_communication_date_to_link.py @@ -6,18 +6,32 @@ def execute(): batch_size = 10_000 while True: - frappe.db.sql( - """ - update `tabCommunication Link` cl - inner join `tabCommunication` c on cl.parent = c.name - set cl.communication_date = c.communication_date - where cl.communication_date is null - and c.communication_date is not null - limit %s - """, + frappe.db.multisql( + { + "mariadb": """ + update `tabCommunication Link` cl + inner join `tabCommunication` c on cl.parent = c.name + set cl.communication_date = c.communication_date + where cl.communication_date is null + and c.communication_date is not null + limit %s + """, + "postgres": """ + UPDATE "tabCommunication Link" + SET communication_date = sub.communication_date + FROM ( + SELECT cl.name, c.communication_date + FROM "tabCommunication Link" cl + JOIN "tabCommunication" c ON cl.parent = c.name + WHERE cl.communication_date IS NULL + AND c.communication_date IS NOT NULL + LIMIT %s + ) AS sub + WHERE "tabCommunication Link".name = sub.name + """, + }, (batch_size,), ) - frappe.db.commit() if not frappe.db.sql( From 9bd495e0ed003d9ca27b7d45abae0bc83f7ac616 Mon Sep 17 00:00:00 2001 From: Kerolles Fathy Date: Sun, 4 Jan 2026 10:45:33 +0200 Subject: [PATCH 08/12] fix(sidebar): correct indentation for sidebar child items (#35513) --- frappe/workspace_sidebar/integrations.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/workspace_sidebar/integrations.json b/frappe/workspace_sidebar/integrations.json index c3a279c87d..aa53fcd538 100644 --- a/frappe/workspace_sidebar/integrations.json +++ b/frappe/workspace_sidebar/integrations.json @@ -113,7 +113,7 @@ "type": "Link" }, { - "child": 0, + "child": 1, "collapsible": 1, "icon": "settings", "indent": 0, @@ -125,7 +125,7 @@ "type": "Link" }, { - "child": 0, + "child": 1, "collapsible": 1, "icon": "list", "indent": 0, @@ -137,7 +137,7 @@ "type": "Link" }, { - "child": 0, + "child": 1, "collapsible": 1, "icon": "list", "indent": 0, @@ -149,7 +149,7 @@ "type": "Link" } ], - "modified": "2025-12-18 17:22:26.558605", + "modified": "2025-12-29 23:46:47.024937", "modified_by": "Administrator", "module": "Integrations", "name": "Integrations", From 4db80d8fe25080b18f9926a585ff4c2231d8732e Mon Sep 17 00:00:00 2001 From: MochaMind Date: Sun, 4 Jan 2026 15:42:46 +0530 Subject: [PATCH 09/12] fix: Russian translations (#35637) --- frappe/locale/ru.po | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/frappe/locale/ru.po b/frappe/locale/ru.po index dd2a0151b8..7bed58bfa8 100644 --- a/frappe/locale/ru.po +++ b/frappe/locale/ru.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" "POT-Creation-Date: 2025-12-21 09:35+0000\n" -"PO-Revision-Date: 2025-12-24 20:23\n" +"PO-Revision-Date: 2026-01-03 23:05\n" "Last-Translator: developers@frappe.io\n" "Language-Team: Russian\n" "MIME-Version: 1.0\n" @@ -133,7 +133,15 @@ msgid "0 - too guessable: risky password.\n" "3 - safely unguessable: moderate protection from offline slow-hash scenario.\n" "
\n" "4 - very unguessable: strong protection from offline slow-hash scenario." -msgstr "" +msgstr "0 - слишком легко угадывается: рискованный пароль.\n" +"
\n" +"1 - очень легко угадывается: защита от атак с ограничением скорости. \n" +"
\n" +"2 - относительно легко угадывается: защита от атак без ограничения скорости.\n" +"
\n" +"3 - практически невозможно угадать: умеренная защита от сценариев с медленным хешированием в офлайн-режиме.\n" +"
\n" +"4 - очень трудно угадать: надежная защита от сценариев с медленным хешированием в офлайн-режиме." #. Description of the 'Priority' (Int) field in DocType 'Web Page' #: frappe/website/doctype/web_page/web_page.json @@ -1466,7 +1474,7 @@ msgstr "Добавить новую вкладку" #: frappe/utils/password_strength.py:191 msgid "Add numbers or special characters." -msgstr "" +msgstr "Добавьте цифры или специальные символы." #: frappe/public/js/print_format_builder/PrintFormatSection.vue:125 msgid "Add page break" @@ -5217,7 +5225,7 @@ msgstr "Распространенные имена и фамилии легко #: frappe/utils/password_strength.py:190 msgid "Common words are easy to guess." -msgstr "" +msgstr "Общие слова легко угадать." #. Name of a DocType #. Option for the 'Communication Type' (Select) field in DocType @@ -5912,7 +5920,7 @@ msgstr "Создать новую Канбан доску" #: frappe/public/js/frappe/list/list_filter.js:101 msgid "Create Saved Filter" -msgstr "" +msgstr "Создать сохраненный фильтр" #: frappe/core/doctype/user/user.js:271 msgid "Create User Email" @@ -12025,7 +12033,7 @@ msgstr "Помощь HTML" #. Description of the 'Content' (Text Editor) field in DocType 'Note' #: frappe/desk/doctype/note/note.json msgid "Help: To link to another record in the system, use \"/desk/note/[Note Name]\" as the Link URL. (don't use \"http://\")" -msgstr "" +msgstr "Помощь: Для ссылки на другую запись в системе используйте \"/desk/note/[Имя заметки]\" в качестве ссылки (не используйте \"http://\")" #. Label of the helpful (Int) field in DocType 'Help Article' #: frappe/website/doctype/help_article/help_article.json @@ -17498,7 +17506,7 @@ msgstr "Не найден шаблон по пути: {0}" #: frappe/core/page/permission_manager/permission_manager.js:362 msgid "No user has the role {0}" -msgstr "" +msgstr "Нет пользователя с ролью {0}" #: frappe/public/js/frappe/form/controls/multiselect_list.js:276 msgid "No values to show" @@ -19124,7 +19132,7 @@ msgstr "Пароль не найден для {0} {1} {2}" #: frappe/core/doctype/user/user.py:1307 msgid "Password requirements not met" -msgstr "" +msgstr "Пароль не соответствует требованиям" #: frappe/core/doctype/user/user.py:1140 msgid "Password reset instructions have been sent to {}'s email" @@ -28580,7 +28588,7 @@ msgstr "Используйте TLS" #: frappe/utils/password_strength.py:191 msgid "Use a few uncommon words together." -msgstr "" +msgstr "Используйте несколько редких слов вместе." #: frappe/utils/password_strength.py:44 msgid "Use a few words, avoid common phrases." @@ -29334,7 +29342,7 @@ msgstr "Посмотреть веб-сайт" #: frappe/core/page/permission_manager/permission_manager.js:395 msgid "View all {0} users" -msgstr "" +msgstr "Просмотреть всех {0} пользователей" #: frappe/www/confirm_workflow_action.html:12 msgid "View document" @@ -29456,7 +29464,7 @@ msgstr "Предупреждение: Обновление счетчика мо #: frappe/core/doctype/doctype/doctype.py:458 msgid "Warning: Usage of 'format:' is discouraged." -msgstr "" +msgstr "Внимание: использование конструкции 'format:' не рекомендуется." #: frappe/website/doctype/help_article/templates/help_article.html:24 msgid "Was this article helpful?" @@ -30472,7 +30480,7 @@ msgstr "Вы можете задать только 3 пользовательс #: frappe/handler.py:184 msgid "You can only upload JPG, PNG, GIF, PDF, TXT, CSV or Microsoft documents." -msgstr "" +msgstr "Вы можете загружать только документы в форматах JPG, PNG, GIF, PDF, TXT, CSV или Microsoft." #: frappe/core/doctype/data_export/exporter.py:199 msgid "You can only upload upto 5000 records in one go. (may be less in some cases)" @@ -32285,7 +32293,7 @@ msgstr "{0} недель назад" #: frappe/core/page/permission_manager/permission_manager.js:378 msgid "{0} with the role {1}" -msgstr "" +msgstr "{0} с ролью {1}" #: frappe/public/js/frappe/utils/pretty_date.js:39 msgid "{0} y" From 1ddeb4041145046d4082a74ab73eaa2c3b363f04 Mon Sep 17 00:00:00 2001 From: KerollesFathy Date: Sun, 4 Jan 2026 16:09:21 +0000 Subject: [PATCH 10/12] fix(sidebar): prevent user avatar shift on collapse/expand --- frappe/public/scss/desk/sidebar.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/scss/desk/sidebar.scss b/frappe/public/scss/desk/sidebar.scss index 65d6dcedc1..3a8c64e283 100644 --- a/frappe/public/scss/desk/sidebar.scss +++ b/frappe/public/scss/desk/sidebar.scss @@ -166,7 +166,7 @@ } .nav-item { - margin-left: 0px; + margin-left: -5px; } } From 084caa89324ae9804fc76982549154db77ceb834 Mon Sep 17 00:00:00 2001 From: KerollesFathy Date: Sun, 4 Jan 2026 17:53:15 +0000 Subject: [PATCH 11/12] fix(desktop): improve edit button visibility and dark theme styles --- frappe/desk/page/desktop/desktop.css | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/frappe/desk/page/desktop/desktop.css b/frappe/desk/page/desktop/desktop.css index 9749e9af25..7ae5c0818b 100644 --- a/frappe/desk/page/desktop/desktop.css +++ b/frappe/desk/page/desktop/desktop.css @@ -446,9 +446,20 @@ bottom: 4%; right: 4%; z-index: 100; - opacity: 0.1; + opacity: 0.5; } + .desktop-edit:hover{ opacity: 1; transition: opacity 0.3s; +} + +[data-theme="dark"] .desktop-edit{ + background-color: var(--surface-gray-3); + opacity: 1; +} + +[data-theme="dark"] .desktop-edit:hover{ + opacity: 0.8; + transition: opacity 0.3s; } \ No newline at end of file From f8443020ca8e314c718f3003e9ebe4ee9f5b948d Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Mon, 5 Jan 2026 12:11:16 +0530 Subject: [PATCH 12/12] fix(error): don't return in a finally block (PEP-765) (#35610) https://docs.python.org/3/whatsnew/3.14.html#pep-765-control-flow-in-finally-blocks Signed-off-by: Akhil Narang --- frappe/utils/error.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frappe/utils/error.py b/frappe/utils/error.py index deed1deb34..3a424eff5d 100644 --- a/frappe/utils/error.py +++ b/frappe/utils/error.py @@ -109,9 +109,10 @@ def get_error_metadata() -> str: metadata["form_dict"] = sanitized_dict(frappe.form_dict) metadata["user"] = getattr(frappe.session, "user", "Unidentified") - finally: + except Exception: # We don't want to bother with exception handling *while* gathering some error's metadata - return frappe.as_json(metadata) # noqa: B012 + pass + return frappe.as_json(metadata) def log_error_snapshot(exception: Exception):