Merge remote-tracking branch 'upstream/develop' into capture-client-events
This commit is contained in:
commit
f0c6c349e0
27 changed files with 402 additions and 140 deletions
|
|
@ -628,6 +628,9 @@ def add_user_specific_sidebar(sidebar_items):
|
|||
if f"-{frappe.session.user.lower()}" in sidebar:
|
||||
sidebars_to_remove.append(sidebar)
|
||||
for sidebar in sidebars_to_remove:
|
||||
sidebar_name = sidebar.replace(f"-{frappe.session.user.lower()}", "")
|
||||
sidebar_items[sidebar]["label"] = sidebar_items[sidebar_name]["label"]
|
||||
sidebar_items[sidebar_name] = sidebar_items.pop(sidebar)
|
||||
try:
|
||||
sidebar_name = sidebar.replace(f"-{frappe.session.user.lower()}", "")
|
||||
sidebar_items[sidebar]["label"] = sidebar_items[sidebar_name]["label"]
|
||||
sidebar_items[sidebar_name] = sidebar_items.pop(sidebar)
|
||||
except KeyError:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -7,27 +7,31 @@
|
|||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"label",
|
||||
"standard",
|
||||
"icon_type",
|
||||
"link_type",
|
||||
"link_to",
|
||||
"parent_icon",
|
||||
"sidebar",
|
||||
"icon_image",
|
||||
"column_break_3",
|
||||
"standard",
|
||||
"app",
|
||||
"icon",
|
||||
"logo_url",
|
||||
"idx",
|
||||
"link",
|
||||
"hidden",
|
||||
"restrict_removal",
|
||||
"roles_tab",
|
||||
"roles"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"fieldname": "label",
|
||||
"fieldtype": "Data",
|
||||
"label": "Label",
|
||||
"translatable": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
|
|
@ -42,9 +46,12 @@
|
|||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"depends_on": "eval: doc.link_type == \"External\"",
|
||||
"fieldname": "link",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Link"
|
||||
"label": "Link",
|
||||
"max_height": "100px"
|
||||
},
|
||||
{
|
||||
"fieldname": "icon",
|
||||
|
|
@ -62,10 +69,11 @@
|
|||
"label": "Logo URL"
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"fieldname": "icon_type",
|
||||
"fieldtype": "Select",
|
||||
"label": "Icon Type",
|
||||
"options": "Folder\nApp\nLink"
|
||||
"options": "Link\nFolder\nApp"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.standard == 1",
|
||||
|
|
@ -75,6 +83,8 @@
|
|||
"options": "Installed Applications"
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"depends_on": "eval: doc.link_type != \"External\"",
|
||||
"fieldname": "link_to",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"label": "Link To",
|
||||
|
|
@ -93,12 +103,13 @@
|
|||
"label": "Hidden"
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"fieldname": "link_type",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Link Type",
|
||||
"options": "DocType\nWorkspace\nExternal"
|
||||
"options": "Workspace Sidebar\nExternal"
|
||||
},
|
||||
{
|
||||
"fieldname": "roles_tab",
|
||||
|
|
@ -116,10 +127,22 @@
|
|||
"fieldtype": "Link",
|
||||
"label": "Sidebar",
|
||||
"options": "Workspace Sidebar"
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"fieldname": "icon_image",
|
||||
"fieldtype": "Attach",
|
||||
"label": "Icon Image"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "restrict_removal",
|
||||
"fieldtype": "Check",
|
||||
"label": "Restrict Removal"
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2025-11-15 22:10:10.463829",
|
||||
"modified": "2026-01-01 19:41:40.557973",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Desktop Icon",
|
||||
|
|
@ -139,6 +162,7 @@
|
|||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 1,
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
|
|
|
|||
|
|
@ -25,14 +25,16 @@ class DesktopIcon(Document):
|
|||
|
||||
app: DF.Autocomplete | None
|
||||
hidden: DF.Check
|
||||
icon_type: DF.Literal["Folder", "App", "Link"]
|
||||
icon_image: DF.Attach | None
|
||||
icon_type: DF.Literal["Link", "Folder", "App"]
|
||||
idx: DF.Int
|
||||
label: DF.Data | None
|
||||
link: DF.SmallText | None
|
||||
link_to: DF.DynamicLink | None
|
||||
link_type: DF.Literal["DocType", "Workspace", "External"]
|
||||
link_type: DF.Literal["Workspace Sidebar", "External"]
|
||||
logo_url: DF.Data | None
|
||||
parent_icon: DF.Link | None
|
||||
restrict_removal: DF.Check
|
||||
roles: DF.Table[HasRole]
|
||||
sidebar: DF.Link | None
|
||||
standard: DF.Check
|
||||
|
|
@ -72,22 +74,27 @@ class DesktopIcon(Document):
|
|||
os.remove(file_path)
|
||||
|
||||
def is_permitted(self, bootinfo):
|
||||
if frappe.session.user == "Administrator":
|
||||
return True
|
||||
if self.icon_type == "Folder":
|
||||
return True
|
||||
workspaces = get_workspace_names(bootinfo.workspaces)
|
||||
if self.icon_type == "Link":
|
||||
if self.link_type == "DocType":
|
||||
return self.link_to in bootinfo.user.can_read
|
||||
elif self.link_type == "Workspace":
|
||||
return self.link_to in workspaces
|
||||
elif self.icon_type == "App":
|
||||
return self.check_app_permission(self.label)
|
||||
return self.check_app_permission()
|
||||
else:
|
||||
try:
|
||||
items = bootinfo.workspace_sidebar_item[self.label.lower()]["items"]
|
||||
#
|
||||
if len(items) == 0:
|
||||
return False
|
||||
|
||||
def check_app_permission(self, app_name):
|
||||
if len(items) and all(item["type"] == "Section Break" for item in items):
|
||||
return False
|
||||
|
||||
return True
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
def check_app_permission(self):
|
||||
for a in frappe.get_installed_apps():
|
||||
if frappe.get_hooks(app_name=a)["app_title"][0] == app_name or self.app == a:
|
||||
if frappe.get_hooks(app_name=a)["app_title"][0] == self.label or self.app == a:
|
||||
permission_method = frappe.get_hooks(app_name=a)["add_to_apps_screen"][0].get(
|
||||
"has_permission", None
|
||||
)
|
||||
|
|
|
|||
|
|
@ -43,20 +43,53 @@ function get_route(desktop_icon) {
|
|||
if (desktop_icon.link_type == "External" && desktop_icon.link) {
|
||||
route = window.location.origin + desktop_icon.link;
|
||||
} else {
|
||||
if (desktop_icon.link_type == "Workspace") {
|
||||
item = {
|
||||
type: desktop_icon.link_type,
|
||||
link: frappe.router.slug(desktop_icon.link_to),
|
||||
};
|
||||
} else if (desktop_icon.link_type == "DocType" || desktop_icon.link_type == "list") {
|
||||
item = {
|
||||
type: desktop_icon.link_type,
|
||||
name: desktop_icon.link_to,
|
||||
};
|
||||
}
|
||||
route = frappe.utils.generate_route(item);
|
||||
}
|
||||
let sidebar = frappe.boot.workspace_sidebar_item[desktop_icon.label.toLowerCase()];
|
||||
if (desktop_icon.link_type == "Workspace Sidebar" && sidebar) {
|
||||
let first_link = sidebar.items.find((i) => i.type == "Link");
|
||||
if (first_link) {
|
||||
if (first_link.link_type === "Report") {
|
||||
let args = {
|
||||
type: first_link.link_type,
|
||||
name: first_link.link_to,
|
||||
};
|
||||
|
||||
if (first_link.report || !frappe.app.sidebar.editor.edit_mode) {
|
||||
args.is_query_report =
|
||||
first_link.report.report_type === "Query Report" ||
|
||||
first_link.report.report_type == "Script Report";
|
||||
args.report_ref_doctype = first_link.report.ref_doctype;
|
||||
}
|
||||
|
||||
route = frappe.utils.generate_route(args);
|
||||
} else if (first_link.link_type == "Workspace") {
|
||||
let workspaces = frappe.workspaces[frappe.router.slug(first_link.link_to)];
|
||||
if (workspaces.public) {
|
||||
route = "/desk/" + frappe.router.slug(first_link.link_to);
|
||||
} else {
|
||||
route = "/desk/private/" + frappe.router.slug(workspaces.title);
|
||||
}
|
||||
|
||||
if (first_link.route) {
|
||||
route = first_link.route;
|
||||
}
|
||||
} else if (first_link.link_type === "URL") {
|
||||
route = first_link.url;
|
||||
} else if (first_link.link_type == "Page" && first_link.route_options) {
|
||||
route = frappe.utils.generate_route({
|
||||
type: first_link.link_type,
|
||||
name: first_link.link_to,
|
||||
route_options: JSON.parse(first_link.route_options),
|
||||
});
|
||||
} else {
|
||||
route = frappe.utils.generate_route({
|
||||
type: first_link.link_type,
|
||||
name: first_link.link_to,
|
||||
tab: first_link.tab,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
"icon_type": "Link",
|
||||
"idx": 0,
|
||||
"label": "Automation",
|
||||
"link_to": "Assignment Rule",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-25 13:25:38.018090",
|
||||
"link_to": "Automation",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.577056",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Automation",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Framework",
|
||||
"restrict_removal": 0,
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
"icon_type": "Link",
|
||||
"idx": 0,
|
||||
"label": "Build",
|
||||
"link_to": "DocType",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-25 13:26:22.147009",
|
||||
"link_to": "Build",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.609927",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Build",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Framework",
|
||||
"restrict_removal": 0,
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
"icon_type": "Link",
|
||||
"idx": 0,
|
||||
"label": "Data",
|
||||
"link_to": "Data Import",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-25 13:25:18.769875",
|
||||
"link_to": "Data",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.385516",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Data",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Framework",
|
||||
"restrict_removal": 0,
|
||||
"roles": [
|
||||
{
|
||||
"role": "Accounts User"
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
"icon_type": "Link",
|
||||
"idx": 0,
|
||||
"label": "Email",
|
||||
"link_to": "Email Account",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-25 13:25:50.374006",
|
||||
"link_to": "Email",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.584412",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Email",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Framework",
|
||||
"restrict_removal": 0,
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
"icon_type": "Link",
|
||||
"idx": 0,
|
||||
"label": "Integrations",
|
||||
"link_to": "Connected App",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-25 13:26:12.851783",
|
||||
"link_to": "Integrations",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.603540",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Integrations",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Framework",
|
||||
"restrict_removal": 0,
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,13 @@
|
|||
"icon_type": "Link",
|
||||
"idx": 101,
|
||||
"label": "My Workspaces",
|
||||
"link_to": "",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-17 16:04:09.545862",
|
||||
"link_to": "My Workspaces",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.338117",
|
||||
"modified_by": "Administrator",
|
||||
"name": "My Workspaces",
|
||||
"owner": "Administrator",
|
||||
"restrict_removal": 1,
|
||||
"roles": [],
|
||||
"sidebar": "My Workspaces",
|
||||
"standard": 1
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
"icon_type": "Link",
|
||||
"idx": 0,
|
||||
"label": "Printing",
|
||||
"link_to": "Print Format",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-25 13:25:33.114392",
|
||||
"link_to": "Printing",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.569646",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Printing",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Framework",
|
||||
"restrict_removal": 0,
|
||||
"roles": [
|
||||
{
|
||||
"role": "System Manager"
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
"icon_type": "Link",
|
||||
"idx": 0,
|
||||
"label": "Productivity",
|
||||
"link_to": "ToDo",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-25 13:27:47.019742",
|
||||
"link_to": "Productivity",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.152305",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Productivity",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Framework",
|
||||
"restrict_removal": 0,
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@
|
|||
"idx": 0,
|
||||
"label": "System",
|
||||
"link_to": "System",
|
||||
"link_type": "Workspace",
|
||||
"modified": "2025-11-25 13:37:01.223244",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.161174",
|
||||
"modified_by": "Administrator",
|
||||
"name": "System",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Framework",
|
||||
"restrict_removal": 0,
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@
|
|||
"idx": 0,
|
||||
"label": "Users",
|
||||
"link_to": "Users",
|
||||
"link_type": "Workspace",
|
||||
"modified": "2025-11-25 13:26:04.757422",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.597388",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Users",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Framework",
|
||||
"restrict_removal": 0,
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@
|
|||
"idx": 0,
|
||||
"label": "Website",
|
||||
"link_to": "Website",
|
||||
"link_type": "Workspace",
|
||||
"modified": "2025-11-25 13:25:58.604796",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-01-01 20:07:01.591355",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Website",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Framework",
|
||||
"restrict_removal": 0,
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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-02 22:29\n"
|
||||
"Last-Translator: developers@frappe.io\n"
|
||||
"Language-Team: German\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -7784,7 +7784,7 @@ msgstr "DocType ist eine Tabelle / ein Formular in der Anwendung."
|
|||
|
||||
#: frappe/integrations/doctype/webhook/webhook.py:83
|
||||
msgid "DocType must be Submittable for the selected Doc Event"
|
||||
msgstr "DocType muss für das ausgewählte Doc-Ereignis übermittelt werden"
|
||||
msgstr "DocType muss für das ausgewählte Doc-Ereignis buchbar sein"
|
||||
|
||||
#: frappe/client.py:406
|
||||
msgid "DocType must be a string"
|
||||
|
|
@ -8071,7 +8071,7 @@ msgstr "Der Dokumenttyp kann nicht importiert werden"
|
|||
|
||||
#: frappe/permissions.py:148
|
||||
msgid "Document Type is not submittable"
|
||||
msgstr "Der Dokumenttyp kann nicht übermittelt werden"
|
||||
msgstr "Der Dokumenttyp kann nicht gebucht werden"
|
||||
|
||||
#. Label of the document_type (Link) field in DocType 'Milestone Tracker'
|
||||
#: frappe/automation/doctype/milestone_tracker/milestone_tracker.json
|
||||
|
|
@ -14022,7 +14022,7 @@ msgstr "Ist Standard"
|
|||
#: frappe/core/doctype/doctype/doctype.json
|
||||
#: frappe/core/doctype/doctype/doctype_list.js:40
|
||||
msgid "Is Submittable"
|
||||
msgstr "Abschließbar"
|
||||
msgstr "Kann gebucht werden"
|
||||
|
||||
#. Label of the is_system_generated (Check) field in DocType 'Custom Field'
|
||||
#. Label of the is_system_generated (Check) field in DocType 'Customize Form
|
||||
|
|
@ -18253,7 +18253,7 @@ msgstr "Onboarding abgeschlossen"
|
|||
#: frappe/core/doctype/doctype/doctype.json
|
||||
#: frappe/core/doctype/doctype/doctype_list.js:43
|
||||
msgid "Once submitted, submittable documents cannot be changed. They can only be Cancelled and Amended."
|
||||
msgstr "Einmal eingereichte Dokumente können nicht mehr geändert werden. Sie können nur storniert oder berichtigt werden."
|
||||
msgstr "Einmal gebuchte Dokumente können nicht mehr geändert werden. Sie können nur storniert oder berichtigt werden."
|
||||
|
||||
#: frappe/core/page/permission_manager/permission_manager_help.html:35
|
||||
msgid "Once you have set this, the users will only be able access documents (eg. Blog Post) where the link exists (eg. Blogger)."
|
||||
|
|
|
|||
|
|
@ -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-29 21:45\n"
|
||||
"PO-Revision-Date: 2026-01-01 22:27\n"
|
||||
"Last-Translator: developers@frappe.io\n"
|
||||
"Language-Team: Persian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -1017,7 +1017,7 @@ msgstr "اکتیو دایرکتوری"
|
|||
#. Label of the active_domains (Table) field in DocType 'Domain Settings'
|
||||
#: frappe/core/doctype/domain_settings/domain_settings.json
|
||||
msgid "Active Domains"
|
||||
msgstr "دامنه های فعال"
|
||||
msgstr "دامنههای فعال"
|
||||
|
||||
#. Label of the active_sessions (Table) field in DocType 'User'
|
||||
#. Label of the active_sessions (Int) field in DocType 'System Health Report'
|
||||
|
|
@ -1660,7 +1660,7 @@ msgstr "تمامی فیلدها برای ارسال نظر ضروری است."
|
|||
#. Description of the 'Document States' (Table) field in DocType 'Workflow'
|
||||
#: frappe/workflow/doctype/workflow/workflow.json
|
||||
msgid "All possible Workflow States and roles of the workflow. Docstatus Options: 0 is \"Saved\", 1 is \"Submitted\" and 2 is \"Cancelled\""
|
||||
msgstr "همه حالت های گردش کار ممکن و نقشهای گردش کار. گزینههای Docstatus: 0 \"ذخیره شده\"، 1 \"ارسال شده\" و 2 \"لغو شده\" است."
|
||||
msgstr "تمام وضعیتها و نقشهای ممکن گردش کار. گزینههای وضعیت اسناد: ۰ به معنای «ذخیره شده»، ۱ به معنای «ارسال شده» و ۲ به معنای «لغو شده» است"
|
||||
|
||||
#: frappe/utils/password_strength.py:183
|
||||
msgid "All-uppercase is almost as easy to guess as all-lowercase."
|
||||
|
|
@ -5026,7 +5026,7 @@ msgstr "گرد کردن تجاری"
|
|||
#. Label of the commit (Check) field in DocType 'System Console'
|
||||
#: frappe/desk/doctype/system_console/system_console.json
|
||||
msgid "Commit"
|
||||
msgstr "مرتکب شدن"
|
||||
msgstr "کامیت"
|
||||
|
||||
#. Label of the committed (Check) field in DocType 'Console Log'
|
||||
#: frappe/desk/doctype/console_log/console_log.json
|
||||
|
|
@ -5236,7 +5236,7 @@ msgstr "پیکربندی ستونها"
|
|||
|
||||
#: frappe/core/doctype/recorder/recorder_list.js:200
|
||||
msgid "Configure Recorder"
|
||||
msgstr "ضبط کننده را پیکربندی کنید"
|
||||
msgstr "پیکربندی ضبط کننده"
|
||||
|
||||
#: frappe/public/js/print_format_builder/Field.vue:103
|
||||
msgid "Configure columns for {0}"
|
||||
|
|
@ -5905,7 +5905,7 @@ msgstr ""
|
|||
#. Label of the current_job_id (Link) field in DocType 'RQ Worker'
|
||||
#: frappe/core/doctype/rq_worker/rq_worker.json
|
||||
msgid "Current Job ID"
|
||||
msgstr "شناسه شغلی فعلی"
|
||||
msgstr "شناسه کار فعلی"
|
||||
|
||||
#. Label of the current_value (Int) field in DocType 'Document Naming Settings'
|
||||
#: frappe/core/doctype/document_naming_settings/document_naming_settings.json
|
||||
|
|
@ -13988,17 +13988,17 @@ msgstr "شناسه کار"
|
|||
#. Label of the job_info_section (Section Break) field in DocType 'RQ Job'
|
||||
#: frappe/core/doctype/rq_job/rq_job.json
|
||||
msgid "Job Info"
|
||||
msgstr "اطلاعات شغلی"
|
||||
msgstr "اطلاعات کار"
|
||||
|
||||
#. Label of the job_name (Data) field in DocType 'RQ Job'
|
||||
#: frappe/core/doctype/rq_job/rq_job.json
|
||||
msgid "Job Name"
|
||||
msgstr "نام شغل"
|
||||
msgstr "نام کار"
|
||||
|
||||
#. Label of the job_status_section (Section Break) field in DocType 'RQ Job'
|
||||
#: frappe/core/doctype/rq_job/rq_job.json
|
||||
msgid "Job Status"
|
||||
msgstr "وضعیت شغلی"
|
||||
msgstr "وضعیت کار"
|
||||
|
||||
#: frappe/core/doctype/data_import/data_import.js:191
|
||||
#: frappe/core/doctype/rq_job/rq_job.js:24
|
||||
|
|
@ -18977,11 +18977,11 @@ msgstr "پچ"
|
|||
#. Name of a DocType
|
||||
#: frappe/core/doctype/patch_log/patch_log.json
|
||||
msgid "Patch Log"
|
||||
msgstr "ثبت وصله"
|
||||
msgstr "لاگ پچ"
|
||||
|
||||
#: frappe/modules/patch_handler.py:136
|
||||
msgid "Patch type {} not found in patches.txt"
|
||||
msgstr "نوع وصله {} در patches.txt یافت نشد"
|
||||
msgstr "نوع پچ {} در patches.txt یافت نشد"
|
||||
|
||||
#. Label of the path (Data) field in DocType 'API Request Log'
|
||||
#. Label of the path (Small Text) field in DocType 'Package Release'
|
||||
|
|
@ -20322,7 +20322,7 @@ msgstr "ویژگی"
|
|||
#: frappe/custom/doctype/customize_form_field/customize_form_field.json
|
||||
#: frappe/website/doctype/web_form_field/web_form_field.json
|
||||
msgid "Property Depends On"
|
||||
msgstr "اموال بستگی دارد"
|
||||
msgstr "ویژگی بستگی دارد به"
|
||||
|
||||
#. Name of a DocType
|
||||
#: frappe/custom/doctype/property_setter/property_setter.json
|
||||
|
|
@ -20647,7 +20647,7 @@ msgstr "در صف ارسال میتوانید پیشرفت را در {0} دن
|
|||
|
||||
#: frappe/desk/page/backups/backups.py:96
|
||||
msgid "Queued for backup. You will receive an email with the download link"
|
||||
msgstr "در صف پشتیبان گیری یک ایمیل با لینک دانلود دریافت خواهید کرد"
|
||||
msgstr "در صف پشتیبانگیری قرار گرفت. ایمیلی حاوی لینک دانلود دریافت خواهید کرد"
|
||||
|
||||
#. Label of the queues (Data) field in DocType 'System Health Report Workers'
|
||||
#: frappe/desk/doctype/system_health_report_workers/system_health_report_workers.json
|
||||
|
|
@ -20694,7 +20694,7 @@ msgstr "لاگ اطلاعات خام"
|
|||
#. Name of a DocType
|
||||
#: frappe/core/doctype/rq_job/rq_job.json
|
||||
msgid "RQ Job"
|
||||
msgstr "شغل RQ"
|
||||
msgstr "کار RQ"
|
||||
|
||||
#. Name of a DocType
|
||||
#: frappe/core/doctype/rq_worker/rq_worker.json
|
||||
|
|
@ -23192,12 +23192,12 @@ msgstr "انتخاب محدوده تاریخ"
|
|||
#: frappe/public/js/frappe/doctype/index.js:178
|
||||
#: frappe/website/doctype/web_form/web_form.json
|
||||
msgid "Select DocType"
|
||||
msgstr "DocType را انتخاب کنید"
|
||||
msgstr "انتخاب DocType"
|
||||
|
||||
#. Label of the reference_doctype (Link) field in DocType 'Data Export'
|
||||
#: frappe/core/doctype/data_export/data_export.json
|
||||
msgid "Select Doctype"
|
||||
msgstr "Doctype را انتخاب کنید"
|
||||
msgstr "انتخاب DocType"
|
||||
|
||||
#: frappe/printing/page/print_format_builder_beta/print_format_builder_beta.js:50
|
||||
#: frappe/workflow/page/workflow_builder/workflow_builder.js:50
|
||||
|
|
@ -28366,7 +28366,7 @@ msgstr "از شناسه ایمیل متفاوت استفاده کنید"
|
|||
#. Description of the 'Detect CSV type' (Check) field in DocType 'Data Import'
|
||||
#: frappe/core/doctype/data_import/data_import.json
|
||||
msgid "Use if the default settings don't seem to detect your data correctly"
|
||||
msgstr "استفاده کنید اگر تنظیمات پیشفرض به درستی دادههای شما را شناسایی نمیکنند"
|
||||
msgstr "اگر تنظیمات پیشفرض به درستی دادههای شما را شناسایی نمیکنند، از این گزینه استفاده کنید"
|
||||
|
||||
#: frappe/model/db_query.py:509
|
||||
msgid "Use of sub-query or function is restricted"
|
||||
|
|
@ -30761,7 +30761,7 @@ msgstr "نظر داد"
|
|||
#. Inspector'
|
||||
#: frappe/core/doctype/permission_inspector/permission_inspector.json
|
||||
msgid "create"
|
||||
msgstr "ایجاد كردن"
|
||||
msgstr "ایجاد کردن"
|
||||
|
||||
#. Option for the 'Indicator Color' (Select) field in DocType 'Workspace'
|
||||
#: frappe/desk/doctype/workspace/workspace.json
|
||||
|
|
|
|||
|
|
@ -176,6 +176,24 @@ def sync_customizations_for_doctype(data: dict, folder: str, filename: str = "")
|
|||
custom_field.flags.ignore_validate = True
|
||||
custom_field.update(d)
|
||||
custom_field.db_update()
|
||||
case "DocType Link":
|
||||
for d in data[key]:
|
||||
link = frappe.db.get_value(
|
||||
"DocType Link",
|
||||
{
|
||||
"parent": doc_type,
|
||||
"link_doctype": d.get("link_doctype"),
|
||||
"link_fieldname": d.get("link_fieldname"),
|
||||
},
|
||||
)
|
||||
if not link:
|
||||
d["owner"] = "Administrator"
|
||||
_insert(d)
|
||||
else:
|
||||
doc_link = frappe.get_doc("DocType Link", link)
|
||||
doc_link.flags.ignore_validate = True
|
||||
doc_link.update(d)
|
||||
doc_link.db_update()
|
||||
case "Property Setter":
|
||||
# Property setter implement their own deduplication, we can just sync them as is
|
||||
for d in data[key]:
|
||||
|
|
@ -205,6 +223,9 @@ def sync_customizations_for_doctype(data: dict, folder: str, filename: str = "")
|
|||
sync("custom_fields", "Custom Field", "dt")
|
||||
update_schema = True
|
||||
|
||||
if data.get("links", False):
|
||||
sync("links", "DocType Link", "parent")
|
||||
|
||||
if data["property_setters"]:
|
||||
sync("property_setters", "Property Setter", "doc_type")
|
||||
|
||||
|
|
|
|||
|
|
@ -252,3 +252,4 @@ frappe.patches.v16_0.auto_generate_desktop_icon_and_sidebar
|
|||
frappe.patches.v16_0.add_private_workspaces_to_sidebar
|
||||
frappe.core.doctype.communication_link.patches.copy_communication_date_to_link
|
||||
frappe.core.doctype.communication.patches.drop_ref_dt_dn_index
|
||||
frappe.patches.v16_0.change_link_type_to_workspace_sidebar
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
desktop_icons = frappe.get_all(
|
||||
"Desktop Icon",
|
||||
filters={
|
||||
"icon_type": "Link",
|
||||
"link_type": ["in", ["Workspace", "DocType"]],
|
||||
},
|
||||
)
|
||||
|
||||
for icon in desktop_icons:
|
||||
icon_doc = frappe.get_doc("Desktop Icon", icon.name)
|
||||
if frappe.db.exists("Workspace Sidebar", icon.name):
|
||||
icon_doc.link_type = "Workspace Sidebar"
|
||||
icon_doc.link_to = icon.name
|
||||
icon_doc.save()
|
||||
|
||||
frappe.db.commit()
|
||||
|
|
@ -431,7 +431,7 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat
|
|||
no_spinner: true,
|
||||
cache: use_get,
|
||||
args: args,
|
||||
callback: (r) => {
|
||||
callback: async (r) => {
|
||||
if (!window.Cypress && !this.$input.is(":focus")) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -441,7 +441,7 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat
|
|||
let filter_string = this.df.filter_description
|
||||
? this.df.filter_description
|
||||
: args.filters
|
||||
? this.get_filter_description(args.filters)
|
||||
? await this.get_filter_description(args.filters)
|
||||
: null;
|
||||
if (filter_string) {
|
||||
r.message.push({
|
||||
|
|
@ -533,14 +533,9 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat
|
|||
}
|
||||
}
|
||||
|
||||
get_filter_description(filters) {
|
||||
let doctype = this.get_options();
|
||||
async get_filter_description(filters) {
|
||||
const doctype = this.get_options();
|
||||
let filter_array = [];
|
||||
let meta = null;
|
||||
|
||||
frappe.model.with_doctype(doctype, () => {
|
||||
meta = frappe.get_meta(doctype);
|
||||
});
|
||||
|
||||
// convert object style to array
|
||||
if (!Array.isArray(filters)) {
|
||||
|
|
@ -549,50 +544,175 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat
|
|||
if (!Array.isArray(value)) {
|
||||
value = ["=", value];
|
||||
}
|
||||
filter_array.push([fieldname, ...value]); // fieldname, operator, value
|
||||
filter_array.push([doctype, fieldname, ...value]); // [doctype, fieldname, operator, value]
|
||||
}
|
||||
} else {
|
||||
filter_array = filters;
|
||||
filter_array = filters.slice(); // clone
|
||||
}
|
||||
|
||||
// add doctype if missing
|
||||
filter_array = filter_array.map((filter) => {
|
||||
if (filter.length === 3) {
|
||||
return [doctype, ...filter]; // doctype, fieldname, operator, value
|
||||
}
|
||||
return filter;
|
||||
});
|
||||
|
||||
function get_filter_description(filter) {
|
||||
let doctype = filter[0];
|
||||
let fieldname = filter[1];
|
||||
let docfield = frappe.meta.get_docfield(doctype, fieldname);
|
||||
let label = docfield ? docfield.label : frappe.model.unscrub(fieldname);
|
||||
// add doctype if missing: [doctype, fieldname, operator, value]
|
||||
filter_array = filter_array.map((f) => (f.length === 3 ? [doctype, ...f] : f));
|
||||
|
||||
function formatValueForDisplay(docfield, val) {
|
||||
// Check boolean fields -> show Yes/No (localized)
|
||||
// Handles 0/1, true/false values
|
||||
if (docfield && docfield.fieldtype === "Check") {
|
||||
filter[3] = filter[3] ? __("Yes") : __("No");
|
||||
return val == 1 || val === true ? __("Yes") : __("No");
|
||||
}
|
||||
|
||||
if (filter[3] && Array.isArray(filter[3]) && filter[3].length > 5) {
|
||||
filter[3] = filter[3].slice(0, 5);
|
||||
filter[3].push("...");
|
||||
// Array values -> truncate to first 5, append "..."
|
||||
if (Array.isArray(val)) {
|
||||
const filtered = val.filter((v) => v != null && v !== "");
|
||||
const arr = filtered.slice(0, 5).map((v) => {
|
||||
// Strings in quotes, numbers/dates not quoted
|
||||
if (typeof v === "string") {
|
||||
return `"${String(__(v))}"`;
|
||||
}
|
||||
// Numbers, dates, etc. - not translated, not quoted
|
||||
return String(v);
|
||||
});
|
||||
if (filtered.length > 5) arr.push("...");
|
||||
return arr.join(", ");
|
||||
}
|
||||
|
||||
let value;
|
||||
if (filter[3] && Array.isArray(filter[3])) {
|
||||
value = filter[3].map((v) => String(__(v)).bold()).join(", ");
|
||||
} else if (filter[3] == null || filter[3] === "") {
|
||||
value = __("empty").bold();
|
||||
} else {
|
||||
value = String(__(filter[3])).bold();
|
||||
// Null / empty
|
||||
if (val == null || val === "") {
|
||||
return __("empty", null, "Comparison value is empty");
|
||||
}
|
||||
|
||||
return [__(label).bold(), __(filter[2]), value].join(" ");
|
||||
// Format based on type: strings in quotes, numbers/dates not quoted
|
||||
if (typeof val === "string") {
|
||||
return `"${String(__(val))}"`;
|
||||
}
|
||||
|
||||
// Numbers, dates, etc. - not translated, not quoted
|
||||
return frappe.format(val, docfield || {});
|
||||
}
|
||||
|
||||
let filter_string = filter_array.map(get_filter_description).join(", ");
|
||||
async function describe_filter(filter) {
|
||||
// expect [doctype, fieldname, operator, value]
|
||||
const _doctype = filter[0];
|
||||
const fieldname = filter[1];
|
||||
const operator = filter[2];
|
||||
let value = filter[3];
|
||||
|
||||
return __("Filters applied for {0}", [filter_string]);
|
||||
// Ensure metadata is loaded for this doctype before accessing docfield
|
||||
await frappe.model.with_doctype(_doctype, () => {});
|
||||
|
||||
const docfield = frappe.meta.get_docfield(_doctype, fieldname);
|
||||
const label = docfield ? docfield.label : frappe.model.unscrub(fieldname);
|
||||
const fieldtype = docfield ? docfield.fieldtype : null;
|
||||
|
||||
const labelDisplay = `<i>${String(__(label, null, _doctype))}</i>`;
|
||||
const valueDisplay = formatValueForDisplay(docfield, value);
|
||||
const is_time_like = ["Date", "Datetime", "Time"].includes(fieldtype);
|
||||
|
||||
// Handle all operators with translation and interpolation in one call
|
||||
switch (operator) {
|
||||
case "=":
|
||||
if (fieldtype === "Check") {
|
||||
if (fieldname === "enabled") {
|
||||
return value == 1
|
||||
? __("is enabled") // ["enabled", "=", 1]
|
||||
: __("is disabled"); // ["enabled", "=", 0]
|
||||
}
|
||||
|
||||
if (fieldname === "disabled") {
|
||||
return value == 1
|
||||
? __("is disabled") // ["disabled", "=", 1]
|
||||
: __("is enabled"); // ["disabled", "=", 0]
|
||||
}
|
||||
|
||||
return value == 1
|
||||
? __("{0} is enabled", [labelDisplay])
|
||||
: __("{0} is disabled", [labelDisplay]);
|
||||
}
|
||||
return __("{0} equals {1}", [labelDisplay, valueDisplay]);
|
||||
case "!=":
|
||||
if (fieldtype === "Check") {
|
||||
if (fieldname === "enabled") {
|
||||
return value == 1
|
||||
? __("is disabled") // ["enabled", "!=", 1]
|
||||
: __("is enabled"); // ["enabled", "!=", 0]
|
||||
}
|
||||
|
||||
if (fieldname === "disabled") {
|
||||
return value == 1
|
||||
? __("is enabled") // ["disabled", "!=", 1]
|
||||
: __("is disabled"); // ["disabled", "!=", 0]
|
||||
}
|
||||
|
||||
return value == 1
|
||||
? __("{0} is disabled", [labelDisplay])
|
||||
: __("{0} is enabled", [labelDisplay]);
|
||||
}
|
||||
return __("{0} is not equal to {1}", [labelDisplay, valueDisplay]);
|
||||
case "in":
|
||||
return __("{0} is one of {1}", [labelDisplay, valueDisplay]);
|
||||
case "not in":
|
||||
return __("{0} is not one of {1}", [labelDisplay, valueDisplay]);
|
||||
case "like":
|
||||
return __("{0} contains {1}", [labelDisplay, valueDisplay]);
|
||||
case "not like":
|
||||
return __("{0} does not contain {1}", [labelDisplay, valueDisplay]);
|
||||
case ">":
|
||||
if (is_time_like) {
|
||||
return __("{0} is after {1}", [labelDisplay, valueDisplay]);
|
||||
}
|
||||
return __("{0} is greater than {1}", [labelDisplay, valueDisplay]);
|
||||
case "<":
|
||||
if (is_time_like) {
|
||||
return __("{0} is before {1}", [labelDisplay, valueDisplay]);
|
||||
}
|
||||
return __("{0} is less than {1}", [labelDisplay, valueDisplay]);
|
||||
case ">=":
|
||||
if (is_time_like) {
|
||||
return __("{0} is on or after {1}", [labelDisplay, valueDisplay]);
|
||||
}
|
||||
return __("{0} is greater than or equal to {1}", [labelDisplay, valueDisplay]);
|
||||
case "<=":
|
||||
if (is_time_like) {
|
||||
return __("{0} is on or before {1}", [labelDisplay, valueDisplay]);
|
||||
}
|
||||
return __("{0} is less than or equal to {1}", [labelDisplay, valueDisplay]);
|
||||
case "is":
|
||||
if (value == "set") {
|
||||
return __("{0} is set", [labelDisplay]);
|
||||
}
|
||||
if (value == "not set") {
|
||||
return __("{0} is not set", [labelDisplay]);
|
||||
}
|
||||
return __("{0} is {1}", [labelDisplay, valueDisplay]);
|
||||
case "between":
|
||||
if (Array.isArray(value) && value.length === 2) {
|
||||
return __("{0} is between {1} and {2}", [
|
||||
labelDisplay,
|
||||
formatValueForDisplay(docfield, value[0]),
|
||||
formatValueForDisplay(docfield, value[1]),
|
||||
]);
|
||||
}
|
||||
return __("{0} is between {1}", [labelDisplay, valueDisplay]);
|
||||
case "descendants of":
|
||||
return __("{0} is a descendant of {1}", [labelDisplay, valueDisplay]);
|
||||
case "ancestors of":
|
||||
return __("{0} is an ancestor of {1}", [labelDisplay, valueDisplay]);
|
||||
case "not descendants of":
|
||||
return __("{0} is not a descendant of {1}", [labelDisplay, valueDisplay]);
|
||||
case "not ancestors of":
|
||||
return __("{0} is not an ancestor of {1}", [labelDisplay, valueDisplay]);
|
||||
case "timespan":
|
||||
return __("{0} is within {1}", [labelDisplay, valueDisplay]);
|
||||
default:
|
||||
// Fallback for unknown operators (no translatable text here)
|
||||
return [labelDisplay, operator, valueDisplay].join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
const descriptions = await Promise.all(
|
||||
filter_array.map((filter) => describe_filter(filter))
|
||||
);
|
||||
const filter_string = frappe.utils.comma_and(descriptions);
|
||||
return __("Filtered by: {0}.", [filter_string]);
|
||||
}
|
||||
|
||||
set_custom_query(args) {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
<div class="standard-actions flex">
|
||||
<span class="page-icon-group hide hidden-xs hidden-sm"></span>
|
||||
<div class="menu-btn-group hide">
|
||||
<button type="button" class="btn btn-default icon-btn" data-toggle="dropdown" aria-expanded="false" aria-label="{{ __("Menu") }}">
|
||||
<button type="button" class="btn btn-default icon-btn menu-more-button" data-toggle="dropdown" aria-expanded="false" aria-label="{{ __("Menu") }}">
|
||||
<span>
|
||||
<span class="menu-btn-group-label">
|
||||
<svg class="icon icon-sm">
|
||||
|
|
|
|||
|
|
@ -231,6 +231,10 @@ frappe.breadcrumbs = {
|
|||
if (view === "form") {
|
||||
let last_crumb = this.$breadcrumbs.find("li").last();
|
||||
last_crumb.addClass("disabled");
|
||||
if (frappe.is_mobile()) {
|
||||
last_crumb.addClass("ellipsis");
|
||||
last_crumb.find("a").addClass("ellipsis");
|
||||
}
|
||||
last_crumb.css("cursor", "copy");
|
||||
last_crumb.click((event) => {
|
||||
event.stopImmediatePropagation();
|
||||
|
|
|
|||
|
|
@ -108,13 +108,6 @@ frappe.views.CommunicationComposer = class {
|
|||
fieldtype: "Link",
|
||||
options: "Email Template",
|
||||
fieldname: "email_template",
|
||||
get_query: () => {
|
||||
return {
|
||||
filters: {
|
||||
use_html: me.dialog.get_value("use_html"),
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldtype: "HTML",
|
||||
|
|
|
|||
|
|
@ -321,18 +321,28 @@ body {
|
|||
|
||||
@media (max-width: 480px) {
|
||||
body[data-route^="Form"] {
|
||||
.navbar-breadcrumbs {
|
||||
max-width: 165px;
|
||||
}
|
||||
.page-title {
|
||||
width: 100%;
|
||||
.title-area {
|
||||
flex-direction: column;
|
||||
align-items: baseline !important;
|
||||
|
||||
.indicator-pill {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.mobile-no-divider li a {
|
||||
font-size: 14px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.page-actions {
|
||||
.standard-actions {
|
||||
.menu-btn-group .menu-more-button {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
.title-area {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
align-items: baseline;
|
||||
.indicator-pill {
|
||||
margin-left: var(--margin-sm);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class TestUtils(IntegrationTestCase):
|
|||
)
|
||||
def test_export_customizations_with_module_filter(self):
|
||||
# create two customizations, one matching the module, one under a different module
|
||||
with note_customizations() as (custom_field, property_setter):
|
||||
with note_customizations() as (custom_field, property_setter, _doctype_link):
|
||||
custom_field.db_set("module", "Custom")
|
||||
property_setter.db_set("module", "Custom")
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ class TestUtils(IntegrationTestCase):
|
|||
os.access(frappe.get_app_path("frappe"), os.W_OK), "Only run if frappe app paths is writable"
|
||||
)
|
||||
def test_sync_customizations(self):
|
||||
with note_customizations() as (custom_field, property_setter):
|
||||
with note_customizations() as (custom_field, property_setter, doctype_link):
|
||||
file_path = export_customizations(module="Custom", doctype="Note", sync_on_migrate=True)
|
||||
custom_field.db_set("modified", now_datetime())
|
||||
custom_field.reload()
|
||||
|
|
@ -152,6 +152,7 @@ class TestUtils(IntegrationTestCase):
|
|||
sync_customizations(app="frappe")
|
||||
self.assertTrue(property_setter.doctype, property_setter.name)
|
||||
self.assertTrue(custom_prop_setter.doctype, custom_prop_setter.name)
|
||||
self.assertTrue(doctype_link.doctype, doctype_link.name)
|
||||
|
||||
self.assertTrue(file_path.endswith("/custom/custom/note.json"))
|
||||
self.assertTrue(os.path.exists(file_path))
|
||||
|
|
@ -232,9 +233,23 @@ def note_customizations():
|
|||
property_setter = make_property_setter(
|
||||
"Note", fieldname="content", property="bold", value="1", property_type="Check"
|
||||
)
|
||||
yield custom_field, property_setter
|
||||
|
||||
doctype_link = frappe.get_doc(
|
||||
{
|
||||
"doctype": "DocType Link",
|
||||
"parent": "Note",
|
||||
"parenttype": "DocType",
|
||||
"parentfield": "links",
|
||||
"link_doctype": "User",
|
||||
"link_fieldname": "owner",
|
||||
"group": "Test Group",
|
||||
}
|
||||
).insert()
|
||||
|
||||
yield custom_field, property_setter, doctype_link
|
||||
finally:
|
||||
custom_field.delete()
|
||||
property_setter.delete()
|
||||
doctype_link.delete()
|
||||
trim_table("Note", dry_run=False)
|
||||
delete_path(frappe.get_module_path("Desk", "Note"))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue