From b42b2cd1ad448ff0bc861dae54e446163e97b12e Mon Sep 17 00:00:00 2001 From: Vassili Minaev Date: Tue, 24 Mar 2026 22:09:41 -0600 Subject: [PATCH] User field adjustments --- frappe/contacts/doctype/pronouns/__init__.py | 0 frappe/contacts/doctype/pronouns/pronouns.js | 8 +++ .../contacts/doctype/pronouns/pronouns.json | 57 +++++++++++++++++++ frappe/contacts/doctype/pronouns/pronouns.py | 20 +++++++ .../doctype/pronouns/test_pronouns.py | 22 +++++++ frappe/core/doctype/user/user.js | 5 ++ frappe/core/doctype/user/user.json | 45 ++++++++++----- frappe/core/doctype/user/user.py | 4 +- 8 files changed, 147 insertions(+), 14 deletions(-) create mode 100644 frappe/contacts/doctype/pronouns/__init__.py create mode 100644 frappe/contacts/doctype/pronouns/pronouns.js create mode 100644 frappe/contacts/doctype/pronouns/pronouns.json create mode 100644 frappe/contacts/doctype/pronouns/pronouns.py create mode 100644 frappe/contacts/doctype/pronouns/test_pronouns.py diff --git a/frappe/contacts/doctype/pronouns/__init__.py b/frappe/contacts/doctype/pronouns/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/contacts/doctype/pronouns/pronouns.js b/frappe/contacts/doctype/pronouns/pronouns.js new file mode 100644 index 0000000000..6f9188d96d --- /dev/null +++ b/frappe/contacts/doctype/pronouns/pronouns.js @@ -0,0 +1,8 @@ +// Copyright (c) 2026, Frappe Technologies and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Pronouns", { +// refresh(frm) { + +// }, +// }); diff --git a/frappe/contacts/doctype/pronouns/pronouns.json b/frappe/contacts/doctype/pronouns/pronouns.json new file mode 100644 index 0000000000..557fbebe15 --- /dev/null +++ b/frappe/contacts/doctype/pronouns/pronouns.json @@ -0,0 +1,57 @@ +{ + "actions": [], + "allow_rename": 1, + "autoname": "field:pronouns", + "creation": "2026-03-24 20:39:16.401720", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "pronouns" + ], + "fields": [ + { + "fieldname": "pronouns", + "fieldtype": "Data", + "label": "Pronouns", + "unique": 1 + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "links": [], + "modified": "2026-03-24 20:58:54.860631", + "modified_by": "admin@seitimegames.com", + "module": "Contacts", + "name": "Pronouns", + "naming_rule": "By fieldname", + "owner": "admin@seitimegames.com", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Guest", + "share": 1 + } + ], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "creation", + "sort_order": "DESC", + "states": [] +} diff --git a/frappe/contacts/doctype/pronouns/pronouns.py b/frappe/contacts/doctype/pronouns/pronouns.py new file mode 100644 index 0000000000..a352f5d606 --- /dev/null +++ b/frappe/contacts/doctype/pronouns/pronouns.py @@ -0,0 +1,20 @@ +# Copyright (c) 2026, Frappe Technologies and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class Pronouns(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + pronouns: DF.Data | None + # end: auto-generated types + + pass diff --git a/frappe/contacts/doctype/pronouns/test_pronouns.py b/frappe/contacts/doctype/pronouns/test_pronouns.py new file mode 100644 index 0000000000..90f8f9836f --- /dev/null +++ b/frappe/contacts/doctype/pronouns/test_pronouns.py @@ -0,0 +1,22 @@ +# Copyright (c) 2026, Frappe Technologies and Contributors +# See license.txt + +# import frappe +from frappe.tests import IntegrationTestCase + + +# On IntegrationTestCase, the doctype test records and all +# link-field test record dependencies are recursively loaded +# Use these module variables to add/remove to/from that list +EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"] +IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"] + + + +class IntegrationTestPronouns(IntegrationTestCase): + """ + Integration tests for Pronouns. + Use this class for testing interactions between multiple components. + """ + + pass diff --git a/frappe/core/doctype/user/user.js b/frappe/core/doctype/user/user.js index 3e9ff32d5e..dba430d214 100644 --- a/frappe/core/doctype/user/user.js +++ b/frappe/core/doctype/user/user.js @@ -97,6 +97,11 @@ frappe.ui.form.on("User", { frm.roles_editor.show(); } } + + if (!frappe.user.has_role("System Manager") && frm.doc.birth_date == null) { + var df = frappe.meta.get_docfield("User", "birth_date", cur_frm.doc.name); + df.read_only = 1; + } }, refresh: function (frm) { let doc = frm.doc; diff --git a/frappe/core/doctype/user/user.json b/frappe/core/doctype/user/user.json index bdc97b4993..ffba2e037d 100644 --- a/frappe/core/doctype/user/user.json +++ b/frappe/core/doctype/user/user.json @@ -35,15 +35,16 @@ "block_modules", "home_settings", "short_bio", - "gender", + "pronouns", "birth_date", + "discord_username", "interest", + "gender", "column_break_26", - "phone", - "location", "bio", - "column_break_22", + "phone", "mobile_no", + "location", "settings_tab", "desk_settings_section", "mute_sounds", @@ -144,7 +145,7 @@ { "fieldname": "first_name", "fieldtype": "Data", - "label": "First Name", + "label": "Preferred Name", "oldfieldname": "first_name", "oldfieldtype": "Data", "reqd": 1 @@ -152,6 +153,7 @@ { "fieldname": "middle_name", "fieldtype": "Data", + "hidden": 1, "label": "Middle Name", "oldfieldname": "middle_name", "oldfieldtype": "Data" @@ -160,6 +162,7 @@ "bold": 1, "fieldname": "last_name", "fieldtype": "Data", + "hidden": 1, "label": "Last Name", "oldfieldname": "last_name", "oldfieldtype": "Data" @@ -167,6 +170,7 @@ { "fieldname": "full_name", "fieldtype": "Data", + "hidden": 1, "in_global_search": 1, "in_standard_filter": 1, "label": "Full Name", @@ -206,6 +210,7 @@ { "fieldname": "language", "fieldtype": "Link", + "hidden": 1, "label": "Language", "options": "Language" }, @@ -265,6 +270,7 @@ { "fieldname": "gender", "fieldtype": "Link", + "hidden": 1, "label": "Gender", "oldfieldname": "gender", "oldfieldtype": "Select", @@ -273,12 +279,14 @@ { "fieldname": "phone", "fieldtype": "Data", + "hidden": 1, "label": "Phone", "options": "Phone" }, { "fieldname": "mobile_no", "fieldtype": "Data", + "hidden": 1, "label": "Mobile No", "options": "Phone", "unique": 1 @@ -286,24 +294,23 @@ { "fieldname": "birth_date", "fieldtype": "Date", - "label": "Birth Date", + "label": "Special Day", "no_copy": 1, "oldfieldname": "birth_date", - "oldfieldtype": "Date" + "oldfieldtype": "Date", + "reqd": 1 }, { "fieldname": "location", "fieldtype": "Data", + "hidden": 1, "label": "Location", "no_copy": 1 }, - { - "fieldname": "column_break_22", - "fieldtype": "Column Break" - }, { "fieldname": "interest", "fieldtype": "Small Text", + "hidden": 1, "label": "Interests" }, { @@ -852,6 +859,18 @@ "fieldname": "form_navigation_buttons", "fieldtype": "Check", "label": "Show navigation buttons" + }, + { + "fieldname": "pronouns", + "fieldtype": "Link", + "label": "Pronouns", + "options": "Pronouns" + }, + { + "fieldname": "discord_username", + "fieldtype": "Data", + "label": "Discord Username", + "reqd": 1 } ], "icon": "fa fa-user", @@ -905,8 +924,8 @@ } ], "make_attachments_public": 1, - "modified": "2026-02-22 13:44:36.317890", - "modified_by": "Administrator", + "modified": "2026-03-24 21:30:57.199337", + "modified_by": "admin@seitimegames.com", "module": "Core", "name": "User", "owner": "Administrator", diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 5f4b1d3fae..50d48ae1e4 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -76,7 +76,7 @@ class User(Document): api_key: DF.Data | None api_secret: DF.Password | None bio: DF.SmallText | None - birth_date: DF.Date | None + birth_date: DF.Date block_modules: DF.Table[BlockModule] bulk_actions: DF.Check bypass_restrict_ip_check_if_2fa_enabled: DF.Check @@ -86,6 +86,7 @@ class User(Document): default_workspace: DF.Link | None defaults: DF.Table[DefaultValue] desk_theme: DF.Literal["Light", "Dark", "Automatic"] + discord_username: DF.Data document_follow_frequency: DF.Literal["Hourly", "Daily", "Weekly"] document_follow_notify: DF.Check email: DF.Data @@ -124,6 +125,7 @@ class User(Document): notifications: DF.Check onboarding_status: DF.SmallText | None phone: DF.Data | None + pronouns: DF.Link | None redirect_url: DF.SmallText | None reset_password_key: DF.Data | None restrict_ip: DF.SmallText | None