From a28c5cd72439c5dba66a1967a71a9977468961f4 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:43:16 +0200 Subject: [PATCH 01/23] refactor: receive email --- frappe/email/receive.py | 88 +++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 47 deletions(-) diff --git a/frappe/email/receive.py b/frappe/email/receive.py index a6c6c00d61..f0b49de7eb 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -190,7 +190,7 @@ class EmailServer: if cint(self.settings.use_imap): self.check_imap_uidvalidity(folder) - readonly = False if self.settings.email_sync_rule == "UNSEEN" else True + readonly = self.settings.email_sync_rule != "UNSEEN" self.imap.select(folder, readonly=readonly) response, message = self.imap.uid("search", None, self.settings.email_sync_rule) @@ -213,27 +213,32 @@ class EmailServer: if not uid_validity or uid_validity != current_uid_validity: # uidvalidity changed & all email uids are reindexed by server - Communication = frappe.qb.DocType("Communication") - frappe.qb.update(Communication).set(Communication.uid, -1).where( - Communication.communication_medium == "Email" - ).where(Communication.email_account == self.settings.email_account).run() + frappe.db.set_value( + "Communication", + {"communication_medium": "Email", "email_account": self.settings.email_account}, + "uid", + -1, + update_modified=False, + ) if self.settings.use_imap: # Remove {"} quotes that are added to handle spaces in IMAP Folder names if folder[0] == folder[-1] == '"': folder = folder[1:-1] - # new update for the IMAP Folder DocType - IMAPFolder = frappe.qb.DocType("IMAP Folder") - frappe.qb.update(IMAPFolder).set(IMAPFolder.uidvalidity, current_uid_validity).set( - IMAPFolder.uidnext, uidnext - ).where(IMAPFolder.parent == self.settings.email_account_name).where( - IMAPFolder.folder_name == folder - ).run() + + frappe.db.set_value( + "IMAP Folder", + {"parent": self.settings.email_account_name, "folder_name": folder}, + {"uidvalidity": current_uid_validity, "uidnext": uidnext}, + update_modified=False, + ) else: - EmailAccount = frappe.qb.DocType("Email Account") - frappe.qb.update(EmailAccount).set(EmailAccount.uidvalidity, current_uid_validity).set( - EmailAccount.uidnext, uidnext - ).where(EmailAccount.name == self.settings.email_account_name).run() + frappe.db.set_value( + "Email Account", + self.settings.email_account_name, + {"uidvalidity": current_uid_validity, "uidnext": uidnext}, + update_modified=False, + ) sync_count = 100 if uid_validity else int(self.settings.initial_sync_count) from_uid = 1 if uidnext < (sync_count + 1) or (uidnext - sync_count) < 1 else uidnext - sync_count @@ -245,10 +250,7 @@ class EmailServer: pattern = rf"(?<={cmd} )[0-9]*" match = re.search(pattern, response.decode("utf-8"), re.U | re.I) - if match: - return match.group(0) - else: - return None + return match[0] if match else None def retrieve_message(self, uid, msg_num): try: @@ -267,7 +269,7 @@ class EmailServer: except Exception as e: if self.has_login_limit_exceeded(e): - raise LoginLimitExceeded(e) + raise LoginLimitExceeded(e) from e frappe.log_error("Unable to fetch email", self.make_error_msg(uid, msg_num)) @@ -295,20 +297,18 @@ class EmailServer: with suppress(Exception): if not cint(self.settings.use_imap): self.pop.dele(msg_num) - else: - # mark as seen if email sync rule is UNSEEN (syncing only unseen mails) - if self.settings.email_sync_rule == "UNSEEN": - self.imap.uid("STORE", uid, "+FLAGS", "(\\SEEN)") + elif self.settings.email_sync_rule == "UNSEEN": + self.imap.uid("STORE", uid, "+FLAGS", "(\\SEEN)") def is_temporary_system_problem(self, e): messages = ( "-ERR [SYS/TEMP] Temporary system problem. Please try again later.", "Connection timed out", ) - for message in messages: - if message in strip(cstr(e)) or message in strip(cstr(getattr(e, "strerror", ""))): - return True - return False + return any( + message in strip(cstr(e)) or message in strip(cstr(getattr(e, "strerror", ""))) + for message in messages + ) def make_error_msg(self, uid, msg_num): traceback = frappe.get_traceback(with_context=True) @@ -322,14 +322,16 @@ class EmailServer: partial_mail = Email(headers) if partial_mail: - return ( - "\nDate: {date}\nFrom: {from_email}\nSubject: {subject}\n\n\nTraceback: \n{traceback}".format( - date=partial_mail.date, - from_email=partial_mail.from_email, - subject=partial_mail.subject, - traceback=traceback, - ) - ) + return f""" +Date: {partial_mail.date} +From: {partial_mail.from_email} +Subject: {partial_mail.subject} + + +Traceback: +{traceback} +""" + return traceback def update_flag(self, folder, uid_list=None): @@ -415,10 +417,7 @@ class Email: # Convert non-string (e.g. None) # Truncate to 140 chars (can be used as a document name) - self.subject = str(self.subject).strip()[:140] - - if not self.subject: - self.subject = "No Subject" + self.subject = str(self.subject).strip()[:140] or "No Subject" def set_from(self): # gmail mailing-list compatibility @@ -499,12 +498,7 @@ class Email: self.html_content += markdown(text_content) def get_charset(self, part): - """Detect charset.""" - charset = part.get_content_charset() - if not charset: - charset = chardet.detect(safe_encode(cstr(part)))["encoding"] - - return charset + return part.get_content_charset() or chardet.detect(safe_encode(cstr(part)))["encoding"] def get_payload(self, part): charset = self.get_charset(part) From 306c9239867aef4773870c8fdc30a592c58397c8 Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Wed, 10 Apr 2024 17:22:05 +0530 Subject: [PATCH 02/23] chore: minor code cleanup - Use walrus operator where possible - Drop redundant checks - we anyway can't iterate over an empty list Signed-off-by: Akhil Narang --- frappe/model/db_query.py | 18 +++++++----------- frappe/permissions.py | 3 --- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 25feeef770..8231fc0ea4 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -1034,21 +1034,17 @@ class DatabaseQuery: self._fetch_shared_documents = True self.match_filters.append(match_filters) - def get_permission_query_conditions(self): + def get_permission_query_conditions(self) -> str: conditions = [] hooks = frappe.get_hooks("permission_query_conditions", {}) condition_methods = hooks.get(self.doctype, []) + hooks.get("*", []) - if condition_methods: - for method in condition_methods: - c = frappe.call(frappe.get_attr(method), self.user, doctype=self.doctype) - if c: - conditions.append(c) + for method in condition_methods: + if c := frappe.call(frappe.get_attr(method), self.user, doctype=self.doctype): + conditions.append(c) - permision_script_name = get_server_script_map().get("permission_query", {}).get(self.doctype) - if permision_script_name: - script = frappe.get_doc("Server Script", permision_script_name) - condition = script.get_permission_query_conditions(self.user) - if condition: + if permission_script_name := get_server_script_map().get("permission_query", {}).get(self.doctype): + script = frappe.get_doc("Server Script", permission_script_name) + if condition := script.get_permission_query_conditions(self.user): conditions.append(condition) return " and ".join(conditions) if conditions else "" diff --git a/frappe/permissions.py b/frappe/permissions.py index 13b3a219c7..52f4a66a6b 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -441,9 +441,6 @@ def has_controller_permissions(doc, ptype, user=None, debug=False) -> bool: hooks = frappe.get_hooks("has_permission") methods = hooks.get(doc.doctype, []) + hooks.get("*", []) - if not methods: - return True - for method in reversed(methods): controller_permission = frappe.call(method, doc=doc, ptype=ptype, user=user, debug=debug) debug and _debug_log(f"Controller permission check from {method}: {controller_permission}") From facff87cadf263bf7e0e0a400ae9c4693a03a775 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 10 Apr 2024 18:11:46 +0530 Subject: [PATCH 03/23] refactor: local declaration --- frappe/public/js/frappe/router.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js index 69a2bca04d..8627e21161 100644 --- a/frappe/public/js/frappe/router.js +++ b/frappe/public/js/frappe/router.js @@ -177,13 +177,12 @@ frappe.router = { // /app/user/user-001 = ["Form", "User", "user-001"] // /app/event/view/calendar/default = ["List", "Event", "Calendar", "Default"] - let private_workspace = route[1] && `${route[1]}-${frappe.user.name.toLowerCase()}`; - if (frappe.workspaces[route[0]]) { // public workspace route = ["Workspaces", frappe.workspaces[route[0]].title]; } else if (route[0] == "private") { // private workspace + let private_workspace = route[1] && `${route[1]}-${frappe.user.name.toLowerCase()}`; if (!frappe.workspaces[private_workspace] && localStorage.new_workspace) { let new_workspace = JSON.parse(localStorage.new_workspace); if (frappe.router.slug(new_workspace.title) === route[1]) { From 822679246c8077beba8f44c05877727ef7a62e7b Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 10 Apr 2024 19:29:12 +0530 Subject: [PATCH 04/23] fix: use workspace title instead of name this is how workspaces work :shrug: --- frappe/public/js/frappe/views/workspace/workspace.js | 2 +- frappe/utils/user.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/views/workspace/workspace.js b/frappe/public/js/frappe/views/workspace/workspace.js index 735f8097b5..cdb57b321b 100644 --- a/frappe/public/js/frappe/views/workspace/workspace.js +++ b/frappe/public/js/frappe/views/workspace/workspace.js @@ -353,7 +353,7 @@ frappe.views.Workspace = class Workspace { if (frappe.boot.user.default_workspace) { default_page = { - name: frappe.boot.user.default_workspace.name, + name: frappe.boot.user.default_workspace.title, public: frappe.boot.user.default_workspace.public, }; } else if ( diff --git a/frappe/utils/user.py b/frappe/utils/user.py index 8069f22497..a3562d6d7a 100644 --- a/frappe/utils/user.py +++ b/frappe/utils/user.py @@ -235,8 +235,12 @@ class UserPermissions: self.build_permissions() if d.get("default_workspace"): - public = frappe.get_cached_value("Workspace", d.default_workspace, "public") - d.default_workspace = {"name": d.default_workspace, "public": public} + workspace = frappe.get_cached_doc("Workspace", d.default_workspace) + d.default_workspace = { + "name": workspace.name, + "public": workspace.public, + "title": workspace.title, + } d.name = self.name d.onboarding_status = frappe.parse_json(d.onboarding_status) From 84cbe3dcc53383266a72cb524a68630734db22e9 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 11 Apr 2024 19:58:55 +0530 Subject: [PATCH 05/23] refactor: Simplify workspace resolution no need for if-elses eh --- frappe/public/js/frappe/router.js | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js index 8627e21161..b57827ce1d 100644 --- a/frappe/public/js/frappe/router.js +++ b/frappe/public/js/frappe/router.js @@ -473,26 +473,26 @@ frappe.router = { return "/app/" + path_string; } - // Workspace + // Resolution order + // 1. User's default workspace in user doctype + // 2. Private home + // 3. Public home + // 4. First workspace in list let private_home = `home-${frappe.user.name.toLowerCase()}`; - let default_page = null; - if (frappe.boot.user.default_workspace) { - default_page = frappe.router.slug(frappe.boot.user.default_workspace.name); - } else if (frappe.workspaces[private_home]) { - default_page = private_home; - } else if (frappe.workspaces["home"]) { - default_page = "home"; - } else { - // Fallback to first workspace - default_page = Object.keys(frappe.workspaces)[0]; - } + let default_workspace = frappe.router.slug(frappe.boot.user.default_workspace?.name || ""); - if (frappe.workspaces[default_page]?.public == false) { - default_page = "private/" + default_page; - } + let workspace = + frappe.workspaces[default_workspace] || + frappe.workspaces[private_home] || + frappe.workspaces["home"] || + Object.values(frappe.workspaces)[0]; - if (default_page) { - return "/app/" + default_page; + if (workspace) { + return ( + "/app/" + + (workspace.public ? "" : "private/") + + frappe.router.slug(workspace.title) + ); } return "/app"; From 9238f4649f6a1ef7e9d8ca584ec9346ff0f71e66 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Sat, 30 Mar 2024 10:29:05 +0100 Subject: [PATCH 06/23] feat(Customize Form): add "Trim Table" action --- .../doctype/customize_form/customize_form.js | 31 +++++++++++++++++++ .../doctype/customize_form/customize_form.py | 14 +++++++++ 2 files changed, 45 insertions(+) diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js index 206e736651..317c72ef17 100644 --- a/frappe/custom/doctype/customize_form/customize_form.js +++ b/frappe/custom/doctype/customize_form/customize_form.js @@ -140,6 +140,14 @@ frappe.ui.form.on("Customize Form", { __("Actions") ); + frm.add_custom_button( + __("Trim Table"), + function () { + frm.trigger("trim_table"); + }, + __("Actions") + ); + const is_autoname_autoincrement = frm.doc.autoname === "autoincrement"; frm.set_df_property("naming_rule", "hidden", is_autoname_autoincrement); frm.set_df_property("autoname", "read_only", is_autoname_autoincrement); @@ -194,6 +202,29 @@ frappe.ui.form.on("Customize Form", { ); }, + trim_table(frm) { + frappe.confirm( + __( + "Warning: DATA LOSS IMMINENT! Proceeding will permanently delete the database columns associated with fields that have been removed from this DocType. This action is irreversible. Do you wish to continue?" + ), + () => { + return frm.call({ + doc: frm.doc, + method: "trim_table", + callback: function (r) { + if (!r.exc) { + frappe.show_alert({ + message: __("Table Trimmed"), + indicator: "green", + }); + frappe.customize_form.clear_locals_and_refresh(frm); + } + }, + }); + } + ); + }, + setup_export(frm) { if (frappe.boot.developer_mode) { frm.add_custom_button( diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index c08a36c5dd..b1a5ff8605 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -21,6 +21,7 @@ from frappe.custom.doctype.property_setter.property_setter import delete_propert from frappe.model import core_doctypes_list, no_value_fields from frappe.model.docfield import supports_translation from frappe.model.document import Document +from frappe.model.meta import trim_table from frappe.utils import cint @@ -639,6 +640,19 @@ class CustomizeForm(Document): frappe.clear_cache(doctype=self.doc_type) self.fetch_to_customize() + @frappe.whitelist() + def trim_table(self): + """Removes database fields that don't exist in the doctype. + + This may be needed as maintenance since removing a field in a DocType + doesn't automatically delete the db field. + """ + if not self.doc_type: + return + + trim_table(self.doc_type, dry_run=False) + self.fetch_to_customize() + @classmethod def allow_fieldtype_change(self, old_type: str, new_type: str) -> bool: """allow type change, if both old_type and new_type are in same field group. From 535bc103406ffc107e40f10ccf4d63bf08df7af7 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 12 Apr 2024 10:44:18 +0530 Subject: [PATCH 07/23] fix: make letterhead attachments public by default (#25925) Also does it for web page. Note: This is just default config, users can change while uploading. --- frappe/integrations/doctype/webhook/test_webhook.py | 2 ++ frappe/printing/doctype/letter_head/letter_head.json | 3 ++- frappe/website/doctype/web_page/web_page.json | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/webhook/test_webhook.py b/frappe/integrations/doctype/webhook/test_webhook.py index eae78f3564..36dab48148 100644 --- a/frappe/integrations/doctype/webhook/test_webhook.py +++ b/frappe/integrations/doctype/webhook/test_webhook.py @@ -71,7 +71,9 @@ class TestWebhook(FrappeTestCase): @classmethod def tearDownClass(cls): # delete any existing webhooks + frappe.db.rollback() frappe.db.delete("Webhook") + frappe.db.commit() def setUp(self): # retrieve or create a User webhook for `after_insert` diff --git a/frappe/printing/doctype/letter_head/letter_head.json b/frappe/printing/doctype/letter_head/letter_head.json index ebbf3879f7..9855c0ff32 100644 --- a/frappe/printing/doctype/letter_head/letter_head.json +++ b/frappe/printing/doctype/letter_head/letter_head.json @@ -198,8 +198,9 @@ "icon": "fa fa-font", "idx": 1, "links": [], + "make_attachments_public": 1, "max_attachments": 3, - "modified": "2024-03-23 16:03:28.922006", + "modified": "2024-04-12 10:30:25.793932", "modified_by": "Administrator", "module": "Printing", "name": "Letter Head", diff --git a/frappe/website/doctype/web_page/web_page.json b/frappe/website/doctype/web_page/web_page.json index b9c65acd87..bd03f7d071 100644 --- a/frappe/website/doctype/web_page/web_page.json +++ b/frappe/website/doctype/web_page/web_page.json @@ -338,7 +338,8 @@ "index_web_pages_for_search": 1, "is_published_field": "published", "links": [], - "modified": "2024-03-23 16:04:02.407199", + "make_attachments_public": 1, + "modified": "2024-04-12 10:30:49.022735", "modified_by": "Administrator", "module": "Website", "name": "Web Page", From a0268f126f2758316e09ca2ac6b3ea9521ffab1d Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 12 Apr 2024 10:55:47 +0530 Subject: [PATCH 08/23] fix: Dry run and confirm before trimming tables --- .../doctype/customize_form/customize_form.js | 51 +++++++++++-------- .../doctype/customize_form/customize_form.py | 7 +++ 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js index 317c72ef17..c314dc97af 100644 --- a/frappe/custom/doctype/customize_form/customize_form.js +++ b/frappe/custom/doctype/customize_form/customize_form.js @@ -202,27 +202,38 @@ frappe.ui.form.on("Customize Form", { ); }, - trim_table(frm) { - frappe.confirm( - __( - "Warning: DATA LOSS IMMINENT! Proceeding will permanently delete the database columns associated with fields that have been removed from this DocType. This action is irreversible. Do you wish to continue?" - ), - () => { - return frm.call({ - doc: frm.doc, - method: "trim_table", - callback: function (r) { - if (!r.exc) { - frappe.show_alert({ - message: __("Table Trimmed"), - indicator: "green", - }); - frappe.customize_form.clear_locals_and_refresh(frm); - } - }, - }); - } + async trim_table(frm) { + let dropped_columns = await frappe.xcall( + "frappe.custom.doctype.customize_form.customize_form.get_orphaned_columns", + { doctype: frm.doc.doc_type } ); + + if (!dropped_columns?.length) { + frappe.toast(__("This doctype has no orphan fields to trim")); + return; + } + let msg = __( + "Warning: DATA LOSS IMMINENT! Proceeding will permanently delete following database columns from doctype {0}:", + [frm.doc.doc_type.bold()] + ); + msg += "
    " + dropped_columns.map((col) => `
  1. ${col}
  2. `).join("") + "
"; + msg += __("This action is irreversible. Do you wish to continue?"); + + frappe.confirm(msg, () => { + return frm.call({ + doc: frm.doc, + method: "trim_table", + callback: function (r) { + if (!r.exc) { + frappe.show_alert({ + message: __("Table Trimmed"), + indicator: "green", + }); + frappe.customize_form.clear_locals_and_refresh(frm); + } + }, + }); + }); }, setup_export(frm) { diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index b1a5ff8605..43b3d10c34 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -665,6 +665,13 @@ class CustomizeForm(Document): return any(map(in_field_group, ALLOWED_FIELDTYPE_CHANGE)) +@frappe.whitelist() +def get_orphaned_columns(doctype: str): + frappe.only_for("System Manager") + frappe.db.begin(read_only=True) # Avoid any potential bug from writing to db + return trim_table(doctype, dry_run=True) + + def reset_customization(doctype): setters = frappe.get_all( "Property Setter", From ea61af2cebed536a829d3b3905a9a85ce91de955 Mon Sep 17 00:00:00 2001 From: Fisher Yu <12823863+szufisher@users.noreply.github.com> Date: Fri, 12 Apr 2024 17:09:02 +0800 Subject: [PATCH 09/23] [fix] Add missing translate function call (#25747) * Update Properties.vue * Update store.js * Update Section.vue * Update list_settings.js * Update grid_row.js * Update list_settings.js * chore: add in missing context for some strings Co-authored-by: Corentin Flr <10946971+cogk@users.noreply.github.com> * chore: formatting and lint fixes Signed-off-by: Akhil Narang --------- Signed-off-by: Akhil Narang Co-authored-by: Akhil Narang Co-authored-by: Corentin Flr <10946971+cogk@users.noreply.github.com> --- .../js/form_builder/components/Section.vue | 4 ++-- frappe/public/js/frappe/form/grid_row.js | 4 ++-- frappe/public/js/frappe/list/list_settings.js | 20 +++++++++---------- .../components/Properties.vue | 6 +++--- frappe/public/js/workflow_builder/store.js | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/frappe/public/js/form_builder/components/Section.vue b/frappe/public/js/form_builder/components/Section.vue index cd5edabe06..6f01d5eaed 100644 --- a/frappe/public/js/form_builder/components/Section.vue +++ b/frappe/public/js/form_builder/components/Section.vue @@ -260,14 +260,14 @@ function delete_column(with_children) { const options = computed(() => { let groups = [ { - group: "Section", + group: __("Section"), items: [ { label: __("Add section below"), onClick: add_section_below }, { label: __("Remove section"), onClick: remove_section }, ], }, { - group: "Column", + group: __("Column"), items: [{ label: __("Add column"), onClick: add_column }], }, ]; diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index af06f2bdf8..59940c0d86 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -504,7 +504,7 @@ export default class GridRow { ); if (selectedColumn && !selectedColumn.hidden && show_field(selectedColumn.fieldtype)) { fields.push({ - label: selectedColumn.label, + label: __(selectedColumn.label, null, this.grid.doctype), value: selectedColumn.fieldname, checked: true, }); @@ -519,7 +519,7 @@ export default class GridRow { show_field(column.fieldtype) ) { fields.push({ - label: column.label, + label: __(column.label, null, this.grid.doctype), value: column.fieldname, checked: false, }); diff --git a/frappe/public/js/frappe/list/list_settings.js b/frappe/public/js/frappe/list/list_settings.js index aa1cb31427..45d10517e3 100644 --- a/frappe/public/js/frappe/list/list_settings.js +++ b/frappe/public/js/frappe/list/list_settings.js @@ -118,7 +118,7 @@ export default class ListSettings { ${frappe.utils.icon("drag", "xs", "", "", "sortable-handle " + show_sortable_handle)}
- ${me.fields[idx].label} + ${__(me.fields[idx].label, null, me.doctype)}
@@ -132,14 +132,14 @@ export default class ListSettings { fields_html.html(` @@ -209,7 +209,7 @@ export default class ListSettings { for (let idx = 0; idx < fields_order.length; idx++) { me.fields.push({ fieldname: fields_order.item(idx).getAttribute("data-fieldname"), - label: fields_order.item(idx).getAttribute("data-label"), + label: __(fields_order.item(idx).getAttribute("data-label")), }); } @@ -264,7 +264,7 @@ export default class ListSettings { let field = frappe.meta.get_docfield(me.doctype, value); if (field) { me.fields.push({ - label: field.label, + label: __(field.label, null, me.doctype), fieldname: field.fieldname, }); } @@ -320,7 +320,7 @@ export default class ListSettings { me.subject_field.fieldname != field.fieldname ) { me.fields.push({ - label: field.label, + label: __(field.label, null, me.doctype), fieldname: field.fieldname, }); } @@ -331,7 +331,7 @@ export default class ListSettings { let me = this; me.subject_field = { - label: "ID", + label: __("ID"), fieldname: "name", }; @@ -339,7 +339,7 @@ export default class ListSettings { let field = frappe.meta.get_docfield(me.doctype, meta.title_field.trim()); me.subject_field = { - label: field.label, + label: __(field.label, null, me.doctype), fieldname: field.fieldname, }; } @@ -353,7 +353,7 @@ export default class ListSettings { if (frappe.has_indicator(me.doctype)) { me.fields.push({ type: "Status", - label: "Status", + label: __("Status"), fieldname: "status_field", }); } @@ -365,7 +365,7 @@ export default class ListSettings { meta.fields.forEach((field) => { if (!frappe.model.no_value_type.includes(field.fieldtype)) { multiselect_fields.push({ - label: field.label, + label: __(field.label, null, field.doctype), value: field.fieldname, checked: fields.includes(field.fieldname), }); diff --git a/frappe/public/js/workflow_builder/components/Properties.vue b/frappe/public/js/workflow_builder/components/Properties.vue index 8167ab8299..7c505dee56 100644 --- a/frappe/public/js/workflow_builder/components/Properties.vue +++ b/frappe/public/js/workflow_builder/components/Properties.vue @@ -16,12 +16,12 @@ let properties = computed(() => { if (field.val() === "") field.focus(); }); if (store.workflow.selected && "action" in store.workflow.selected.data) { - title.value = "Transition Properties"; + title.value = __("Transition Properties"); return store.transitionfields.filter((df) => ["action", "allowed", "allow_self_approval", "condition"].includes(df.fieldname) ); } else if (store.workflow.selected && "state" in store.workflow.selected.data) { - title.value = "State Properties"; + title.value = __("State Properties"); let allow_edit = store.statefields.find((df) => df.fieldname == "allow_edit"); store.statefields = store.statefields.filter( (df) => !["allow_edit", "workflow_builder_id"].includes(df.fieldname) @@ -39,7 +39,7 @@ let properties = computed(() => { return true; }); } - title.value = "Workflow Details"; + title.value = __("Workflow Details"); return store.workflowfields.filter( (df) => !["states", "transitions", "workflow_data", "workflow_name"].includes(df.fieldname) ); diff --git a/frappe/public/js/workflow_builder/store.js b/frappe/public/js/workflow_builder/store.js index 46cda01ec9..179150fc32 100644 --- a/frappe/public/js/workflow_builder/store.js +++ b/frappe/public/js/workflow_builder/store.js @@ -80,7 +80,7 @@ export const useStore = defineStore("workflow-builder-store", () => { const workflow_data = clean_workflow_data(); doc.workflow_data = JSON.stringify(workflow_data); await frappe.call("frappe.client.save", { doc }); - frappe.toast("Workflow updated successfully"); + frappe.toast(__("Workflow updated successfully")); fetch(); } catch (e) { console.error(e); From e7cb2c04bcf1675651c4855b88db9eeac41d1fed Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Fri, 12 Apr 2024 15:46:57 +0530 Subject: [PATCH 10/23] fix: tables in markdown editor (#25935) --- frappe/public/js/frappe/utils/tools.js | 2 +- frappe/public/scss/common/controls.scss | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/utils/tools.js b/frappe/public/js/frappe/utils/tools.js index 8820fe17eb..2d3d195ffa 100644 --- a/frappe/public/js/frappe/utils/tools.js +++ b/frappe/public/js/frappe/utils/tools.js @@ -37,7 +37,7 @@ frappe.tools.downloadify = function (data, roles, title) { frappe.markdown = function (txt) { if (!frappe.md2html) { - frappe.md2html = new showdown.Converter(); + frappe.md2html = new showdown.Converter({ tables: true }); } while (txt.substr(0, 1) === "\n") { diff --git a/frappe/public/scss/common/controls.scss b/frappe/public/scss/common/controls.scss index fd75433a36..939ef502a9 100644 --- a/frappe/public/scss/common/controls.scss +++ b/frappe/public/scss/common/controls.scss @@ -381,6 +381,17 @@ textarea.form-control { min-height: 300px; max-height: 600px; overflow: auto; + + table { + width: 100%; + border-collapse: collapse; + + th, + td { + border: 1px solid var(--border-color); + padding: var(--padding-sm); + } + } } .markdown-toggle, From 95ae166e400d1dc7c5cd3209b6565428c00d5c41 Mon Sep 17 00:00:00 2001 From: Safwan Erooth Date: Sat, 13 Apr 2024 04:25:08 +0530 Subject: [PATCH 11/23] fix: enable checkbox clickability in list view by adjusting z-index --- frappe/public/scss/desk/list.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/public/scss/desk/list.scss b/frappe/public/scss/desk/list.scss index 5fcc81e0eb..1a252695b0 100644 --- a/frappe/public/scss/desk/list.scss +++ b/frappe/public/scss/desk/list.scss @@ -257,6 +257,7 @@ input.list-row-checkbox { margin-bottom: 0px; --checkbox-right-margin: calc(var(--checkbox-size) / 2 + #{$level-margin-right}); background-color: var(--card-bg); + z-index: 1; } input.list-check-all { From 37cef2ec86b6224c0ac48856f50094b8248799dd Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Sat, 13 Apr 2024 09:40:37 +0200 Subject: [PATCH 12/23] feat!: simplify admin password prompt for new site (#25937) --- frappe/utils/install.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/frappe/utils/install.py b/frappe/utils/install.py index b408b0c87e..b389259877 100644 --- a/frappe/utils/install.py +++ b/frappe/utils/install.py @@ -143,18 +143,7 @@ def install_basic_docs(): def get_admin_password(): - def ask_admin_password(): - admin_password = getpass.getpass("Set Administrator password: ") - admin_password2 = getpass.getpass("Re-enter Administrator password: ") - if admin_password != admin_password2: - print("\nPasswords do not match") - return ask_admin_password() - return admin_password - - admin_password = frappe.conf.get("admin_password") - if not admin_password: - return ask_admin_password() - return admin_password + return frappe.conf.get("admin_password") or getpass.getpass("Set Administrator password: ") def before_tests(): From bb68908fe9e23d23bff917009202184836525ff1 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 15 Apr 2024 16:23:38 +0530 Subject: [PATCH 13/23] refactor: web form link logic (#25951) --- frappe/website/doctype/web_form/web_form.py | 64 +++++++------------ .../web_form_field/web_form_field.json | 4 +- 2 files changed, 25 insertions(+), 43 deletions(-) diff --git a/frappe/website/doctype/web_form/web_form.py b/frappe/website/doctype/web_form/web_form.py index 906766d0bb..828a432cdc 100644 --- a/frappe/website/doctype/web_form/web_form.py +++ b/frappe/website/doctype/web_form/web_form.py @@ -652,52 +652,34 @@ def get_in_list_view_fields(doctype): return [get_field_df(f) for f in fields] -@frappe.whitelist(allow_guest=True) def get_link_options(web_form_name, doctype, allow_read_on_all_link_options=False): - web_form_doc = frappe.get_doc("Web Form", web_form_name) - doctype_validated = False - limited_to_user = False - if web_form_doc.login_required: - # check if frappe session user is not guest or admin - if frappe.session.user != "Guest": - doctype_validated = True + web_form: WebForm = frappe.get_doc("Web Form", web_form_name) - if not allow_read_on_all_link_options: - limited_to_user = True - else: - frappe.throw(_("You must be logged in to use this form."), frappe.PermissionError) + if web_form.login_required and frappe.session.user == "Guest": + frappe.throw(_("You must be logged in to use this form."), frappe.PermissionError) - else: - for field in web_form_doc.web_form_fields: - if field.options == doctype: - doctype_validated = True - break - - if doctype_validated: - link_options, filters = [], {} - - if limited_to_user: - filters = {"owner": frappe.session.user} - - fields = ["name as value"] - - meta = frappe.get_meta(doctype) - - if meta.title_field and meta.show_title_field_in_link: - fields.append(f"{meta.title_field} as label") - - link_options = frappe.get_all(doctype, filters, fields) - - if meta.title_field and meta.show_title_field_in_link: - return json.dumps(link_options, default=str) - else: - return "\n".join([str(doc.value) for doc in link_options]) - - else: - raise frappe.PermissionError( - _("You don't have permission to access the {0} DocType.").format(doctype) + if not web_form.published or not any(f for f in web_form.web_form_fields if f.options == doctype): + frappe.throw( + _("You don't have permission to access the {0} DocType.").format(doctype), frappe.PermissionError ) + link_options, filters = [], {} + if not allow_read_on_all_link_options: + filters = {"owner": frappe.session.user} + + fields = ["name as value"] + + meta = frappe.get_meta(doctype) + if meta.title_field and meta.show_title_field_in_link: + fields.append(f"{meta.title_field} as label") + + link_options = frappe.get_all(doctype, filters, fields) + + if meta.title_field and meta.show_title_field_in_link: + return json.dumps(link_options, default=str) + else: + return "\n".join([str(doc.value) for doc in link_options]) + @redis_cache(ttl=60 * 60) def get_published_web_forms() -> dict[str, str]: diff --git a/frappe/website/doctype/web_form_field/web_form_field.json b/frappe/website/doctype/web_form_field/web_form_field.json index 665e9e4a9b..02d794e546 100644 --- a/frappe/website/doctype/web_form_field/web_form_field.json +++ b/frappe/website/doctype/web_form_field/web_form_field.json @@ -50,7 +50,7 @@ }, { "default": "0", - "depends_on": "eval:doc.fieldtype === 'Link'", + "depends_on": "eval:doc.fieldtype === 'Link' && parent.login_required", "fieldname": "allow_read_on_all_link_options", "fieldtype": "Check", "label": "Allow Read On All Link Options" @@ -156,7 +156,7 @@ ], "istable": 1, "links": [], - "modified": "2024-03-23 16:04:02.173108", + "modified": "2024-04-15 16:11:58.469820", "modified_by": "Administrator", "module": "Website", "name": "Web Form Field", From a6b040123856480daaacd53c41e10c915bd3a809 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Mon, 15 Apr 2024 17:38:48 +0530 Subject: [PATCH 14/23] chore: update POT file (#25948) --- frappe/locale/main.pot | 511 ++++++++++++++++++++++++----------------- 1 file changed, 298 insertions(+), 213 deletions(-) diff --git a/frappe/locale/main.pot b/frappe/locale/main.pot index 25b5877c59..554a705bd8 100644 --- a/frappe/locale/main.pot +++ b/frappe/locale/main.pot @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Frappe Framework VERSION\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" -"POT-Creation-Date: 2024-04-07 09:33+0000\n" -"PO-Revision-Date: 2024-04-07 09:33+0000\n" +"POT-Creation-Date: 2024-04-14 10:31+0000\n" +"PO-Revision-Date: 2024-04-14 10:31+0000\n" "Last-Translator: developers@frappe.io\n" "Language-Team: developers@frappe.io\n" "MIME-Version: 1.0\n" @@ -72,7 +72,7 @@ msgstr "" msgid "'In Global Search' is not allowed for field {0} of type {1}" msgstr "" -#: core/doctype/doctype/doctype.py:1302 +#: core/doctype/doctype/doctype.py:1321 msgid "'In Global Search' not allowed for type {0} in row {1}" msgstr "" @@ -80,7 +80,7 @@ msgstr "" msgid "'In List View' is not allowed for field {0} of type {1}" msgstr "" -#: custom/doctype/customize_form/customize_form.py:358 +#: custom/doctype/customize_form/customize_form.py:359 msgid "'In List View' not allowed for type {0} in row {1}" msgstr "" @@ -92,7 +92,7 @@ msgstr "" msgid "'{0}' is not a valid URL" msgstr "" -#: core/doctype/doctype/doctype.py:1296 +#: core/doctype/doctype/doctype.py:1315 msgid "'{0}' not allowed for type {1} in row {2}" msgstr "" @@ -104,6 +104,7 @@ msgstr "" msgid "** Failed: {0} to {1}: {2}" msgstr "" +#: public/js/frappe/list/list_settings.js:132 #: public/js/frappe/views/kanban/kanban_settings.js:111 msgid "+ Add / Remove Fields" msgstr "" @@ -611,7 +612,7 @@ msgstr "" msgid "A DocType (Document Type) is used to insert forms in ERPNext. Forms such as Customer, Orders, and Invoices are Doctypes in the backend. You can also create new DocTypes to create new forms in ERPNext as per your business needs." msgstr "" -#: core/doctype/doctype/doctype.py:1014 +#: core/doctype/doctype/doctype.py:1015 msgid "A DocType's name should start with a letter and can only consist of letters, numbers, spaces, underscores and hyphens" msgstr "" @@ -898,7 +899,7 @@ msgctxt "Social Login Key" msgid "Access Token URL" msgstr "" -#: auth.py:451 +#: auth.py:453 msgid "Access not allowed from this IP Address" msgstr "" @@ -978,7 +979,7 @@ msgstr "" msgid "Action Complete" msgstr "" -#: model/document.py:1686 +#: model/document.py:1687 msgid "Action Failed" msgstr "" @@ -1021,7 +1022,8 @@ msgstr "" #: custom/doctype/customize_form/customize_form.js:124 #: custom/doctype/customize_form/customize_form.js:132 #: custom/doctype/customize_form/customize_form.js:140 -#: custom/doctype/customize_form/customize_form.js:238 +#: custom/doctype/customize_form/customize_form.js:148 +#: custom/doctype/customize_form/customize_form.js:283 #: public/js/frappe/ui/page.html:56 #: public/js/frappe/views/reports/query_report.js:190 #: public/js/frappe/views/reports/query_report.js:203 @@ -1687,7 +1689,7 @@ msgstr "" #: contacts/doctype/salutation/salutation.json #: core/doctype/communication/communication.json core/doctype/file/file.json #: core/doctype/language/language.json core/doctype/module_def/module_def.json -#: core/doctype/user/user.json desk/doctype/event/event.json +#: desk/doctype/event/event.json #: desk/doctype/notification_log/notification_log.json #: desk/doctype/notification_settings/notification_settings.json #: desk/doctype/tag/tag.json desk/doctype/tag_link/tag_link.json @@ -1712,7 +1714,7 @@ msgctxt "Server Script" msgid "All" msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:394 +#: public/js/frappe/ui/notifications/notifications.js:401 msgid "All Day" msgstr "" @@ -1740,7 +1742,7 @@ msgstr "" msgid "All Submissions" msgstr "" -#: custom/doctype/customize_form/customize_form.js:384 +#: custom/doctype/customize_form/customize_form.js:429 msgid "All customizations will be removed. Please confirm." msgstr "" @@ -2365,6 +2367,12 @@ msgstr "" msgid "App Name" msgstr "" +#. Label of a Data field in DocType 'Changelog Feed' +#: desk/doctype/changelog_feed/changelog_feed.json +msgctxt "Changelog Feed" +msgid "App Name" +msgstr "" + #. Label of a Select field in DocType 'Module Def' #: core/doctype/module_def/module_def.json msgctxt "Module Def" @@ -2389,7 +2397,7 @@ msgctxt "Dropbox Settings" msgid "App Secret Key" msgstr "" -#: modules/utils.py:262 +#: modules/utils.py:275 msgid "App not found for module: {0}" msgstr "" @@ -3788,6 +3796,12 @@ msgctxt "Server Script" msgid "Before Insert" msgstr "" +#. Option for the 'DocType Event' (Select) field in DocType 'Server Script' +#: core/doctype/server_script/server_script.json +msgctxt "Server Script" +msgid "Before Print" +msgstr "" + #. Option for the 'DocType Event' (Select) field in DocType 'Server Script' #: core/doctype/server_script/server_script.json msgctxt "Server Script" @@ -4575,7 +4589,7 @@ msgstr "" msgid "Can not rename as column {0} is already present on DocType." msgstr "" -#: core/doctype/doctype/doctype.py:1111 +#: core/doctype/doctype/doctype.py:1130 msgid "Can only change to/from Autoincrement naming rule when there is no data in the doctype" msgstr "" @@ -4654,7 +4668,7 @@ msgid "Cancel {0} documents?" msgstr "" #: desk/form/save.py:59 public/js/frappe/model/indicator.js:78 -#: public/js/frappe/ui/filters/filter.js:496 +#: public/js/frappe/ui/filters/filter.js:502 msgid "Cancelled" msgstr "" @@ -4705,7 +4719,7 @@ msgstr "" msgid "Cancelling {0}" msgstr "" -#: core/doctype/prepared_report/prepared_report.py:245 +#: core/doctype/prepared_report/prepared_report.py:252 msgid "Cannot Download Report due to insufficient permissions" msgstr "" @@ -4753,7 +4767,7 @@ msgstr "" msgid "Cannot change state of Cancelled Document. Transition row {0}" msgstr "" -#: core/doctype/doctype/doctype.py:1101 +#: core/doctype/doctype/doctype.py:1120 msgid "Cannot change to/from autoincrement autoname in Customize Form" msgstr "" @@ -4781,23 +4795,23 @@ msgstr "" msgid "Cannot delete public workspace without Workspace Manager role" msgstr "" -#: custom/doctype/customize_form/customize_form.js:313 +#: custom/doctype/customize_form/customize_form.js:358 msgid "Cannot delete standard action. You can hide it if you want" msgstr "" -#: custom/doctype/customize_form/customize_form.js:328 +#: custom/doctype/customize_form/customize_form.js:373 msgid "Cannot delete standard document state." msgstr "" -#: custom/doctype/customize_form/customize_form.js:276 +#: custom/doctype/customize_form/customize_form.js:321 msgid "Cannot delete standard field {0}. You can hide it instead." msgstr "" -#: custom/doctype/customize_form/customize_form.js:298 +#: custom/doctype/customize_form/customize_form.js:343 msgid "Cannot delete standard link. You can hide it if you want" msgstr "" -#: custom/doctype/customize_form/customize_form.js:268 +#: custom/doctype/customize_form/customize_form.js:313 msgid "Cannot delete system generated field {0}. You can hide it instead." msgstr "" @@ -4898,11 +4912,11 @@ msgstr "" msgid "Cannot update {0}" msgstr "" -#: model/db_query.py:1106 +#: model/db_query.py:1103 msgid "Cannot use sub-query in order by" msgstr "" -#: model/db_query.py:1124 +#: model/db_query.py:1121 msgid "Cannot use {0} in order/group by" msgstr "" @@ -5043,6 +5057,11 @@ msgid "" "Warning: Incorrectly updating counters can prevent documents from getting created. " msgstr "" +#. Name of a DocType +#: desk/doctype/changelog_feed/changelog_feed.json +msgid "Changelog Feed" +msgstr "" + #: email/doctype/email_domain/email_domain.js:5 msgid "Changing any setting will reflect on all the email accounts associated with this domain." msgstr "" @@ -5241,7 +5260,7 @@ msgctxt "Form Tour Step" msgid "Child Doctype" msgstr "" -#: core/doctype/doctype/doctype.py:1583 +#: core/doctype/doctype/doctype.py:1602 msgid "Child Table {0} for field {1}" msgstr "" @@ -6054,7 +6073,7 @@ msgstr "" msgid "Compare Versions" msgstr "" -#: core/doctype/server_script/server_script.py:140 +#: core/doctype/server_script/server_script.py:141 msgid "Compilation warning" msgstr "" @@ -6621,7 +6640,7 @@ msgctxt "Website Settings" msgid "Copyright" msgstr "" -#: custom/doctype/customize_form/customize_form.py:118 +#: custom/doctype/customize_form/customize_form.py:119 msgid "Core DocTypes cannot be customized." msgstr "" @@ -7412,7 +7431,7 @@ msgstr "" msgid "Customizations Discarded" msgstr "" -#: custom/doctype/customize_form/customize_form.js:397 +#: custom/doctype/customize_form/customize_form.js:442 msgid "Customizations Reset" msgstr "" @@ -7830,7 +7849,7 @@ msgstr "" msgid "Data Import Template" msgstr "" -#: custom/doctype/customize_form/customize_form.py:610 +#: custom/doctype/customize_form/customize_form.py:611 msgid "Data Too Long" msgstr "" @@ -7859,7 +7878,7 @@ msgstr "" msgid "Database Storage Usage By Tables" msgstr "" -#: custom/doctype/customize_form/customize_form.py:244 +#: custom/doctype/customize_form/customize_form.py:245 msgid "Database Table Row Size Limit" msgstr "" @@ -8273,11 +8292,11 @@ msgctxt "User" msgid "Default Workspace" msgstr "" -#: core/doctype/doctype/doctype.py:1324 +#: core/doctype/doctype/doctype.py:1343 msgid "Default for 'Check' type of field {0} must be either '0' or '1'" msgstr "" -#: core/doctype/doctype/doctype.py:1337 +#: core/doctype/doctype/doctype.py:1356 msgid "Default value for {0} must be in the list of options." msgstr "" @@ -8684,7 +8703,7 @@ msgstr "" #. Name of a role #: automation/doctype/reminder/reminder.json core/doctype/report/report.json #: core/doctype/submission_queue/submission_queue.json -#: core/doctype/user_group/user_group.json +#: core/doctype/user/user.json core/doctype/user_group/user_group.json #: custom/doctype/doctype_layout/doctype_layout.json #: desk/doctype/calendar_view/calendar_view.json #: desk/doctype/custom_html_block/custom_html_block.json @@ -9181,7 +9200,7 @@ msgctxt "Workspace Shortcut" msgid "DocType" msgstr "" -#: core/doctype/doctype/doctype.py:1525 +#: core/doctype/doctype/doctype.py:1544 msgid "DocType {0} provided for the field {1} must have atleast one Link field" msgstr "" @@ -9245,11 +9264,11 @@ msgctxt "Workspace Shortcut" msgid "DocType View" msgstr "" -#: core/doctype/doctype/doctype.py:648 +#: core/doctype/doctype/doctype.py:649 msgid "DocType can not be merged" msgstr "" -#: core/doctype/doctype/doctype.py:642 +#: core/doctype/doctype/doctype.py:643 msgid "DocType can only be renamed by Administrator" msgstr "" @@ -9284,19 +9303,19 @@ msgstr "" msgid "DocType required" msgstr "" -#: modules/utils.py:157 +#: modules/utils.py:170 msgid "DocType {0} does not exist." msgstr "" -#: modules/utils.py:220 +#: modules/utils.py:233 msgid "DocType {} not found" msgstr "" -#: core/doctype/doctype/doctype.py:1008 +#: core/doctype/doctype/doctype.py:1009 msgid "DocType's name should not start or end with whitespace" msgstr "" -#: core/doctype/doctype/doctype.js:70 +#: core/doctype/doctype/doctype.js:71 msgid "DocTypes can not be modified, please use {0} instead" msgstr "" @@ -9310,7 +9329,7 @@ msgctxt "Document Follow" msgid "Doctype" msgstr "" -#: core/doctype/doctype/doctype.py:1002 +#: core/doctype/doctype/doctype.py:1003 msgid "Doctype name is limited to {0} characters ({1})" msgstr "" @@ -9392,19 +9411,19 @@ msgctxt "Customize Form" msgid "Document Links" msgstr "" -#: core/doctype/doctype/doctype.py:1159 +#: core/doctype/doctype/doctype.py:1178 msgid "Document Links Row #{0}: Could not find field {1} in {2} DocType" msgstr "" -#: core/doctype/doctype/doctype.py:1179 +#: core/doctype/doctype/doctype.py:1198 msgid "Document Links Row #{0}: Invalid doctype or fieldname." msgstr "" -#: core/doctype/doctype/doctype.py:1142 +#: core/doctype/doctype/doctype.py:1161 msgid "Document Links Row #{0}: Parent DocType is mandatory for internal links" msgstr "" -#: core/doctype/doctype/doctype.py:1148 +#: core/doctype/doctype/doctype.py:1167 msgid "Document Links Row #{0}: Table Fieldname is mandatory for internal links" msgstr "" @@ -9468,7 +9487,7 @@ msgstr "" msgid "Document Naming Settings" msgstr "" -#: model/document.py:1548 +#: model/document.py:1549 msgid "Document Queued" msgstr "" @@ -9715,7 +9734,7 @@ msgctxt "User Type" msgid "Document Types and Permissions" msgstr "" -#: core/doctype/submission_queue/submission_queue.py:163 model/document.py:1750 +#: core/doctype/submission_queue/submission_queue.py:163 model/document.py:1751 msgid "Document Unlocked" msgstr "" @@ -9943,7 +9962,7 @@ msgid "Download Your Data" msgstr "" #: public/js/frappe/model/indicator.js:73 -#: public/js/frappe/ui/filters/filter.js:494 +#: public/js/frappe/ui/filters/filter.js:500 msgid "Draft" msgstr "" @@ -11131,7 +11150,7 @@ msgstr "" msgid "Enabled email inbox for user {0}" msgstr "" -#: core/doctype/server_script/server_script.py:268 +#: core/doctype/server_script/server_script.py:269 msgid "Enabled scheduled execution for script {0}" msgstr "" @@ -11585,6 +11604,10 @@ msgctxt "Recorder" msgid "Event Type" msgstr "" +#: public/js/frappe/ui/notifications/notifications.js:56 +msgid "Events" +msgstr "" + #: desk/doctype/event/event.py:261 msgid "Events in Today's Calendar" msgstr "" @@ -11821,11 +11844,11 @@ msgstr "" msgid "Export All {0} rows?" msgstr "" -#: custom/doctype/customize_form/customize_form.js:220 +#: custom/doctype/customize_form/customize_form.js:262 msgid "Export Custom Permissions" msgstr "" -#: custom/doctype/customize_form/customize_form.js:200 +#: custom/doctype/customize_form/customize_form.js:242 msgid "Export Customizations" msgstr "" @@ -11888,6 +11911,10 @@ msgstr "" msgid "Export {0} records" msgstr "" +#: custom/doctype/customize_form/customize_form.js:263 +msgid "Exported permissions will be force-synced on every migrate overriding any other customization." +msgstr "" + #. Label of a Data field in DocType 'Email Queue' #: email/doctype/email_queue/email_queue.json msgctxt "Email Queue" @@ -11993,7 +12020,7 @@ msgstr "" msgid "Failed to connect to server" msgstr "" -#: auth.py:654 +#: auth.py:656 msgid "Failed to decode token, please provide a valid base64-encoded token." msgstr "" @@ -12187,11 +12214,11 @@ msgctxt "Web Form List Column" msgid "Field" msgstr "" -#: core/doctype/doctype/doctype.py:417 +#: core/doctype/doctype/doctype.py:418 msgid "Field \"route\" is mandatory for Web Views" msgstr "" -#: core/doctype/doctype/doctype.py:1474 +#: core/doctype/doctype/doctype.py:1493 msgid "Field \"title\" is mandatory if \"Website Search Field\" is set." msgstr "" @@ -12205,7 +12232,7 @@ msgctxt "Custom Field" msgid "Field Description" msgstr "" -#: core/doctype/doctype/doctype.py:1039 +#: core/doctype/doctype/doctype.py:1058 msgid "Field Missing" msgstr "" @@ -12320,11 +12347,11 @@ msgctxt "Webhook Data" msgid "Fieldname" msgstr "" -#: core/doctype/doctype/doctype.py:266 +#: core/doctype/doctype/doctype.py:267 msgid "Fieldname '{0}' conflicting with a {1} of the name {2} in {3}" msgstr "" -#: core/doctype/doctype/doctype.py:1038 +#: core/doctype/doctype/doctype.py:1057 msgid "Fieldname called {0} must exist to enable autonaming" msgstr "" @@ -12348,14 +12375,15 @@ msgstr "" msgid "Fieldname {0} cannot have special characters like {1}" msgstr "" -#: core/doctype/doctype/doctype.py:1845 +#: core/doctype/doctype/doctype.py:1864 msgid "Fieldname {0} conflicting with meta object" msgstr "" -#: core/doctype/doctype/doctype.py:496 public/js/form_builder/utils.js:302 +#: core/doctype/doctype/doctype.py:497 public/js/form_builder/utils.js:302 msgid "Fieldname {0} is restricted" msgstr "" +#: public/js/frappe/list/list_settings.js:132 #: public/js/frappe/views/kanban/kanban_settings.js:111 msgid "Fields" msgstr "" @@ -12465,7 +12493,7 @@ msgstr "" msgid "Fieldtype cannot be changed from {0} to {1}" msgstr "" -#: custom/doctype/customize_form/customize_form.py:584 +#: custom/doctype/customize_form/customize_form.py:585 msgid "Fieldtype cannot be changed from {0} to {1} in row {2}" msgstr "" @@ -12913,11 +12941,11 @@ msgctxt "Report Filter" msgid "Fold" msgstr "" -#: core/doctype/doctype/doctype.py:1398 +#: core/doctype/doctype/doctype.py:1417 msgid "Fold can not be at the end of the form" msgstr "" -#: core/doctype/doctype/doctype.py:1396 +#: core/doctype/doctype/doctype.py:1415 msgid "Fold must come before a Section Break" msgstr "" @@ -13241,7 +13269,7 @@ msgstr "" msgid "For updating, you can update only selective columns." msgstr "" -#: core/doctype/doctype/doctype.py:1689 +#: core/doctype/doctype/doctype.py:1708 msgid "For {0} at level {1} in {2} in row {3}" msgstr "" @@ -13911,13 +13939,13 @@ msgctxt "Web Form" msgid "Go to this URL after completing the form" msgstr "" -#: core/doctype/doctype/doctype.js:54 +#: core/doctype/doctype/doctype.js:55 #: custom/doctype/client_script/client_script.js:10 msgid "Go to {0}" msgstr "" #: core/doctype/data_import/data_import.js:92 -#: core/doctype/doctype/doctype.js:58 +#: core/doctype/doctype/doctype.js:59 #: custom/doctype/customize_form/customize_form.js:104 #: custom/doctype/doctype_layout/doctype_layout.js:42 #: workflow/doctype/workflow/workflow.js:44 @@ -14546,7 +14574,7 @@ msgstr "" #: public/js/frappe/form/templates/form_sidebar.html:40 #: public/js/frappe/form/workflow.js:23 -#: public/js/frappe/ui/toolbar/navbar.html:87 public/js/frappe/utils/help.js:27 +#: public/js/frappe/ui/toolbar/navbar.html:88 public/js/frappe/utils/help.js:27 msgid "Help" msgstr "" @@ -14590,7 +14618,7 @@ msgctxt "Help Category" msgid "Help Category" msgstr "" -#: public/js/frappe/ui/toolbar/navbar.html:84 +#: public/js/frappe/ui/toolbar/navbar.html:85 msgid "Help Dropdown" msgstr "" @@ -14875,7 +14903,7 @@ msgctxt "User Permission" msgid "Hide descendant records of For Value." msgstr "" -#: public/js/frappe/form/layout.js:260 +#: public/js/frappe/form/layout.js:268 msgid "Hide details" msgstr "" @@ -15015,6 +15043,7 @@ msgstr "" #: core/doctype/data_import/importer.py:1201 desk/report/todo/todo.py:36 #: model/meta.py:45 public/js/frappe/data_import/data_exporter.js:329 #: public/js/frappe/data_import/data_exporter.js:344 +#: public/js/frappe/list/list_settings.js:334 #: public/js/frappe/list/list_view.js:357 #: public/js/frappe/list/list_view.js:421 public/js/frappe/model/meta.js:197 #: public/js/frappe/model/model.js:122 @@ -15178,7 +15207,7 @@ msgctxt "Workflow Document State" msgid "If Checked workflow status will not override status in list view" msgstr "" -#: core/doctype/doctype/doctype.py:1701 public/js/frappe/roles_editor.js:66 +#: core/doctype/doctype/doctype.py:1720 public/js/frappe/roles_editor.js:66 msgid "If Owner" msgstr "" @@ -15380,7 +15409,7 @@ msgstr "" msgid "If you have recently restored the site you may need to copy the site config contaning original Encryption Key." msgstr "" -#: core/doctype/doctype/doctype.js:80 +#: core/doctype/doctype/doctype.js:81 msgid "If you just want to customize for your site, use {0} instead." msgstr "" @@ -15464,7 +15493,7 @@ msgstr "" msgid "Illegal Document Status for {0}" msgstr "" -#: model/db_query.py:443 model/db_query.py:446 model/db_query.py:1109 +#: model/db_query.py:443 model/db_query.py:446 model/db_query.py:1106 msgid "Illegal SQL Query" msgstr "" @@ -15559,11 +15588,11 @@ msgctxt "Letter Head" msgid "Image Width" msgstr "" -#: core/doctype/doctype/doctype.py:1454 +#: core/doctype/doctype/doctype.py:1473 msgid "Image field must be a valid fieldname" msgstr "" -#: core/doctype/doctype/doctype.py:1456 +#: core/doctype/doctype/doctype.py:1475 msgid "Image field must be of type Attach Image" msgstr "" @@ -15775,7 +15804,7 @@ msgctxt "DocField" msgid "In Global Search" msgstr "" -#: core/doctype/doctype/doctype.js:95 +#: core/doctype/doctype/doctype.js:96 msgid "In Grid View" msgstr "" @@ -15785,7 +15814,7 @@ msgctxt "DocField" msgid "In List Filter" msgstr "" -#: core/doctype/doctype/doctype.js:96 +#: core/doctype/doctype/doctype.js:97 msgid "In List View" msgstr "" @@ -16167,7 +16196,7 @@ msgstr "" msgid "Instructions Emailed" msgstr "" -#: permissions.py:817 +#: permissions.py:815 msgid "Insufficient Permission Level for {0}" msgstr "" @@ -16183,7 +16212,7 @@ msgstr "" msgid "Insufficient Permissions for editing Report" msgstr "" -#: core/doctype/doctype/doctype.py:445 +#: core/doctype/doctype/doctype.py:446 msgid "Insufficient attachment limit" msgstr "" @@ -16345,7 +16374,7 @@ msgid "Invalid" msgstr "" #: public/js/form_builder/utils.js:221 public/js/frappe/form/grid_row.js:769 -#: public/js/frappe/form/layout.js:774 +#: public/js/frappe/form/layout.js:782 msgid "Invalid \"depends_on\" expression" msgstr "" @@ -16385,7 +16414,7 @@ msgstr "" msgid "Invalid DocType: {0}" msgstr "" -#: core/doctype/doctype/doctype.py:1220 +#: core/doctype/doctype/doctype.py:1239 msgid "Invalid Fieldname" msgstr "" @@ -16429,7 +16458,7 @@ msgstr "" msgid "Invalid Operation" msgstr "" -#: core/doctype/doctype/doctype.py:1577 core/doctype/doctype/doctype.py:1586 +#: core/doctype/doctype/doctype.py:1596 core/doctype/doctype/doctype.py:1605 msgid "Invalid Option" msgstr "" @@ -16463,7 +16492,7 @@ msgstr "" msgid "Invalid Search Field {0}" msgstr "" -#: core/doctype/doctype/doctype.py:1162 +#: core/doctype/doctype/doctype.py:1181 msgid "Invalid Table Fieldname" msgstr "" @@ -16508,7 +16537,7 @@ msgstr "" msgid "Invalid field name {0}" msgstr "" -#: core/doctype/doctype/doctype.py:1047 +#: core/doctype/doctype/doctype.py:1066 msgid "Invalid fieldname '{0}' in autoname" msgstr "" @@ -16567,7 +16596,7 @@ msgctxt "Error message in web form" msgid "Invalid values for fields:" msgstr "" -#: core/doctype/doctype/doctype.py:1512 +#: core/doctype/doctype/doctype.py:1531 msgid "Invalid {0} condition" msgstr "" @@ -16771,7 +16800,7 @@ msgctxt "DocType" msgid "Is Published Field" msgstr "" -#: core/doctype/doctype/doctype.py:1463 +#: core/doctype/doctype/doctype.py:1482 msgid "Is Published Field must be a valid fieldname" msgstr "" @@ -17731,11 +17760,11 @@ msgstr "" msgid "Last synced {0}" msgstr "" -#: custom/doctype/customize_form/customize_form.js:186 +#: custom/doctype/customize_form/customize_form.js:194 msgid "Layout Reset" msgstr "" -#: custom/doctype/customize_form/customize_form.js:178 +#: custom/doctype/customize_form/customize_form.js:186 msgid "Layout will be reset to standard layout, are you sure you want to do this?" msgstr "" @@ -18089,6 +18118,12 @@ msgctxt "Dashboard Chart" msgid "Line" msgstr "" +#. Label of a Long Text field in DocType 'Changelog Feed' +#: desk/doctype/changelog_feed/changelog_feed.json +msgctxt "Changelog Feed" +msgid "Link" +msgstr "" + #. Option for the 'Field Type' (Select) field in DocType 'Custom Field' #: custom/doctype/custom_field/custom_field.json msgctxt "Custom Field" @@ -18769,7 +18804,7 @@ msgstr "" msgid "Looks like you haven’t added any third party apps." msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:308 +#: public/js/frappe/ui/notifications/notifications.js:315 msgid "Looks like you haven’t received any notifications." msgstr "" @@ -19009,7 +19044,7 @@ msgctxt "Print Format" msgid "Margin Top" msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:44 +#: public/js/frappe/ui/notifications/notifications.js:45 msgid "Mark all as read" msgstr "" @@ -19144,7 +19179,7 @@ msgctxt "System Settings" msgid "Max auto email report per user" msgstr "" -#: core/doctype/doctype/doctype.py:1290 +#: core/doctype/doctype/doctype.py:1309 msgid "Max width for type Currency is 100px in row {0}" msgstr "" @@ -19599,7 +19634,7 @@ msgstr "" msgid "Missing DocType" msgstr "" -#: core/doctype/doctype/doctype.py:1474 +#: core/doctype/doctype/doctype.py:1493 msgid "Missing Field" msgstr "" @@ -19878,11 +19913,11 @@ msgstr "" msgid "Module onboarding progress reset" msgstr "" -#: custom/doctype/customize_form/customize_form.js:208 +#: custom/doctype/customize_form/customize_form.js:250 msgid "Module to Export" msgstr "" -#: modules/utils.py:255 +#: modules/utils.py:268 msgid "Module {} not found" msgstr "" @@ -20777,7 +20812,7 @@ msgstr "" msgid "No" msgstr "" -#: public/js/frappe/ui/filters/filter.js:502 +#: public/js/frappe/ui/filters/filter.js:508 msgctxt "Checkbox is not checked" msgid "No" msgstr "" @@ -20904,11 +20939,11 @@ msgstr "" msgid "No Name Specified for {0}" msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:308 +#: public/js/frappe/ui/notifications/notifications.js:315 msgid "No New notifications" msgstr "" -#: core/doctype/doctype/doctype.py:1681 +#: core/doctype/doctype/doctype.py:1700 msgid "No Permissions Specified" msgstr "" @@ -20960,7 +20995,7 @@ msgstr "" msgid "No Tags" msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:428 +#: public/js/frappe/ui/notifications/notifications.js:435 msgid "No Upcoming Events" msgstr "" @@ -21016,7 +21051,7 @@ msgstr "" msgid "No contacts linked to document" msgstr "" -#: desk/query_report.py:331 +#: desk/query_report.py:335 msgid "No data to export" msgstr "" @@ -21262,7 +21297,7 @@ msgstr "" msgid "Not Permitted" msgstr "" -#: desk/query_report.py:506 +#: desk/query_report.py:510 msgid "Not Permitted to read {0}" msgstr "" @@ -21305,7 +21340,7 @@ msgstr "" msgid "Not Set" msgstr "" -#: public/js/frappe/ui/filters/filter.js:564 +#: public/js/frappe/ui/filters/filter.js:570 msgctxt "Field value is not set" msgid "Not Set" msgstr "" @@ -21338,7 +21373,7 @@ msgstr "" msgid "Not allowed to attach {0} document, please enable Allow Print For {0} in Print Settings" msgstr "" -#: core/doctype/doctype/doctype.py:335 +#: core/doctype/doctype/doctype.py:336 msgid "Not allowed to create custom Virtual DocType." msgstr "" @@ -21362,7 +21397,7 @@ msgstr "" msgid "Not in Developer Mode" msgstr "" -#: core/doctype/doctype/doctype.py:330 +#: core/doctype/doctype/doctype.py:331 msgid "Not in Developer Mode! Set in site_config.json or make 'Custom' DocType." msgstr "" @@ -21448,6 +21483,10 @@ msgstr "" msgid "Notes:" msgstr "" +#: public/js/frappe/ui/notifications/notifications.js:485 +msgid "Nothing New" +msgstr "" + #: public/js/frappe/form/undo_manager.js:43 msgid "Nothing left to redo" msgstr "" @@ -21523,7 +21562,7 @@ msgstr "" #. Name of a DocType #: desk/doctype/notification_settings/notification_settings.json -#: public/js/frappe/ui/notifications/notifications.js:36 +#: public/js/frappe/ui/notifications/notifications.js:37 msgid "Notification Settings" msgstr "" @@ -21542,8 +21581,8 @@ msgstr "" msgid "Notification sent to" msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:49 -#: public/js/frappe/ui/notifications/notifications.js:180 +#: public/js/frappe/ui/notifications/notifications.js:50 +#: public/js/frappe/ui/notifications/notifications.js:187 msgid "Notifications" msgstr "" @@ -21553,7 +21592,7 @@ msgctxt "Role" msgid "Notifications" msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:292 +#: public/js/frappe/ui/notifications/notifications.js:299 msgid "Notifications Disabled" msgstr "" @@ -21679,7 +21718,7 @@ msgctxt "Recorder" msgid "Number of Queries" msgstr "" -#: core/doctype/doctype/doctype.py:442 public/js/frappe/doctype/index.js:59 +#: core/doctype/doctype/doctype.py:443 public/js/frappe/doctype/index.js:59 msgid "Number of attachment fields are more than {}, limit updated to {}." msgstr "" @@ -21982,7 +22021,7 @@ msgctxt "Workflow Document State" msgid "Only Allow Edit For" msgstr "" -#: core/doctype/doctype/doctype.py:1556 +#: core/doctype/doctype/doctype.py:1575 msgid "Only Options allowed for Data field are:" msgstr "" @@ -22034,7 +22073,7 @@ msgstr "" msgid "Only reports of type Report Builder can be edited" msgstr "" -#: custom/doctype/customize_form/customize_form.py:124 +#: custom/doctype/customize_form/customize_form.py:125 msgid "Only standard DocTypes are allowed to be customized from Customize Form." msgstr "" @@ -22216,7 +22255,7 @@ msgstr "" msgid "Option 3" msgstr "" -#: core/doctype/doctype/doctype.py:1574 +#: core/doctype/doctype/doctype.py:1593 msgid "Option {0} for field {1} is not a child table" msgstr "" @@ -22278,7 +22317,7 @@ msgctxt "Web Template Field" msgid "Options" msgstr "" -#: core/doctype/doctype/doctype.py:1314 +#: core/doctype/doctype/doctype.py:1333 msgid "Options 'Dynamic Link' type of field must point to another Link Field with options as 'DocType'" msgstr "" @@ -22288,7 +22327,7 @@ msgctxt "Custom Field" msgid "Options Help" msgstr "" -#: core/doctype/doctype/doctype.py:1596 +#: core/doctype/doctype/doctype.py:1615 msgid "Options for Rating field can range from 3 to 10" msgstr "" @@ -22296,7 +22335,7 @@ msgstr "" msgid "Options for select. Each option on a new line." msgstr "" -#: core/doctype/doctype/doctype.py:1331 +#: core/doctype/doctype/doctype.py:1350 msgid "Options for {0} must be set before setting the default value." msgstr "" @@ -22763,7 +22802,7 @@ msgctxt "Form Tour Step" msgid "Parent Field" msgstr "" -#: core/doctype/doctype/doctype.py:913 +#: core/doctype/doctype/doctype.py:914 msgid "Parent Field (Tree)" msgstr "" @@ -22773,7 +22812,7 @@ msgctxt "DocType" msgid "Parent Field (Tree)" msgstr "" -#: core/doctype/doctype/doctype.py:919 +#: core/doctype/doctype/doctype.py:920 msgid "Parent Field must be a valid fieldname" msgstr "" @@ -22783,7 +22822,7 @@ msgctxt "Top Bar Item" msgid "Parent Label" msgstr "" -#: core/doctype/doctype/doctype.py:1145 +#: core/doctype/doctype/doctype.py:1164 msgid "Parent Missing" msgstr "" @@ -22805,7 +22844,7 @@ msgstr "" msgid "Parent is the name of the document to which the data will get added to." msgstr "" -#: permissions.py:797 +#: permissions.py:795 msgid "Parentfield not specified in {0}: {1}" msgstr "" @@ -23227,7 +23266,7 @@ msgctxt "System Settings" msgid "Permissions" msgstr "" -#: core/doctype/doctype/doctype.py:1772 core/doctype/doctype/doctype.py:1782 +#: core/doctype/doctype/doctype.py:1791 core/doctype/doctype/doctype.py:1801 msgid "Permissions Error" msgstr "" @@ -23667,7 +23706,7 @@ msgstr "" msgid "Please select applicable Doctypes" msgstr "" -#: model/db_query.py:1121 +#: model/db_query.py:1118 msgid "Please select atleast 1 column from {0} to sort/group" msgstr "" @@ -23742,7 +23781,7 @@ msgstr "" msgid "Please specify" msgstr "" -#: permissions.py:773 +#: permissions.py:771 msgid "Please specify a valid parent DocType for {0}" msgstr "" @@ -23892,6 +23931,12 @@ msgctxt "Address" msgid "Postal Code" msgstr "" +#. Label of a Datetime field in DocType 'Changelog Feed' +#: desk/doctype/changelog_feed/changelog_feed.json +msgctxt "Changelog Feed" +msgid "Posting Timestamp" +msgstr "" + #. Group in Blog Category's connections #: website/doctype/blog_category/blog_category.json msgctxt "Blog Category" @@ -23930,7 +23975,7 @@ msgctxt "Web Form Field" msgid "Precision" msgstr "" -#: core/doctype/doctype/doctype.py:1348 +#: core/doctype/doctype/doctype.py:1367 msgid "Precision should be between 1 and 6" msgstr "" @@ -23978,7 +24023,7 @@ msgstr "" msgid "Prepared Report User" msgstr "" -#: desk/query_report.py:294 +#: desk/query_report.py:298 msgid "Prepared report render failed" msgstr "" @@ -24511,7 +24556,7 @@ msgstr "" msgid "Proceed Anyway" msgstr "" -#: public/js/frappe/form/controls/table.js:88 +#: public/js/frappe/form/controls/table.js:104 msgid "Processing" msgstr "" @@ -24929,7 +24974,7 @@ msgctxt "DocType" msgid "Queue in Background (BETA)" msgstr "" -#: utils/background_jobs.py:469 +#: utils/background_jobs.py:470 msgid "Queue should be one of {0}" msgstr "" @@ -25478,7 +25523,7 @@ msgctxt "Website Settings" msgid "Redirects" msgstr "" -#: sessions.py:142 +#: sessions.py:143 msgid "Redis cache server not running. Please contact Administrator / Tech support" msgstr "" @@ -26129,7 +26174,7 @@ msgstr "" msgid "Rename {0}" msgstr "" -#: core/doctype/doctype/doctype.py:690 +#: core/doctype/doctype/doctype.py:691 msgid "Renamed files and replaced code in controllers, please check!" msgstr "" @@ -26436,7 +26481,7 @@ msgctxt "Report" msgid "Report Type" msgstr "" -#: core/doctype/doctype/doctype.py:1747 +#: core/doctype/doctype/doctype.py:1766 msgid "Report cannot be set for Single types" msgstr "" @@ -26458,11 +26503,11 @@ msgstr "" msgid "Report limit reached" msgstr "" -#: core/doctype/prepared_report/prepared_report.py:203 +#: core/doctype/prepared_report/prepared_report.py:210 msgid "Report timed out." msgstr "" -#: desk/query_report.py:561 +#: desk/query_report.py:565 msgid "Report updated successfully" msgstr "" @@ -26748,7 +26793,7 @@ msgctxt "OAuth Client" msgid "Response Type" msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:400 +#: public/js/frappe/ui/notifications/notifications.js:407 msgid "Rest of the day" msgstr "" @@ -27390,7 +27435,7 @@ msgstr "" msgid "Row #" msgstr "" -#: core/doctype/doctype/doctype.py:1769 core/doctype/doctype/doctype.py:1779 +#: core/doctype/doctype/doctype.py:1788 core/doctype/doctype/doctype.py:1798 msgid "Row # {0}: Non administrator user can not set the role {1} to the custom doctype" msgstr "" @@ -27398,7 +27443,7 @@ msgstr "" msgid "Row #{0}:" msgstr "" -#: core/doctype/doctype/doctype.py:491 +#: core/doctype/doctype/doctype.py:492 msgid "Row #{}: Fieldname is required" msgstr "" @@ -27432,11 +27477,11 @@ msgstr "" msgid "Row {0}" msgstr "" -#: custom/doctype/customize_form/customize_form.py:348 +#: custom/doctype/customize_form/customize_form.py:349 msgid "Row {0}: Not allowed to disable Mandatory for standard fields" msgstr "" -#: custom/doctype/customize_form/customize_form.py:337 +#: custom/doctype/customize_form/customize_form.py:338 msgid "Row {0}: Not allowed to enable Allow on Submit for standard fields" msgstr "" @@ -27484,7 +27529,7 @@ msgctxt "Energy Point Rule" msgid "Rule Name" msgstr "" -#: permissions.py:653 +#: permissions.py:651 msgid "Rule for this doctype, role, permlevel and if-owner combination already exists." msgstr "" @@ -27824,7 +27869,7 @@ msgctxt "Freeze message while saving a document" msgid "Saving" msgstr "" -#: custom/doctype/customize_form/customize_form.js:343 +#: custom/doctype/customize_form/customize_form.js:388 msgid "Saving Customization..." msgstr "" @@ -27936,7 +27981,7 @@ msgctxt "Newsletter" msgid "Scheduled To Send" msgstr "" -#: core/doctype/server_script/server_script.py:280 +#: core/doctype/server_script/server_script.py:281 msgid "Scheduled execution for script {0} has updated" msgstr "" @@ -28135,7 +28180,7 @@ msgstr "" msgid "Search Results for" msgstr "" -#: core/doctype/doctype/doctype.py:1415 +#: core/doctype/doctype/doctype.py:1434 msgid "Search field {0} is not valid" msgstr "" @@ -28223,7 +28268,7 @@ msgctxt "User" msgid "Security Settings" msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:302 +#: public/js/frappe/ui/notifications/notifications.js:309 msgid "See all Activity" msgstr "" @@ -28491,7 +28536,7 @@ msgstr "" msgid "Select Mandatory" msgstr "" -#: custom/doctype/customize_form/customize_form.js:235 +#: custom/doctype/customize_form/customize_form.js:280 msgid "Select Module" msgstr "" @@ -28564,11 +28609,11 @@ msgstr "" msgid "Select a group node first." msgstr "" -#: core/doctype/doctype/doctype.py:1880 +#: core/doctype/doctype/doctype.py:1899 msgid "Select a valid Sender Field for creating documents from Email" msgstr "" -#: core/doctype/doctype/doctype.py:1864 +#: core/doctype/doctype/doctype.py:1883 msgid "Select a valid Subject field for creating documents from Email" msgstr "" @@ -28919,7 +28964,7 @@ msgctxt "DocType" msgid "Sender Email Field" msgstr "" -#: core/doctype/doctype/doctype.py:1883 +#: core/doctype/doctype/doctype.py:1902 msgid "Sender Field should have Email in options" msgstr "" @@ -29057,7 +29102,7 @@ msgstr "" msgid "Series counter for {} updated to {} successfully" msgstr "" -#: core/doctype/doctype/doctype.py:1071 +#: core/doctype/doctype/doctype.py:1090 #: core/doctype/document_naming_settings/document_naming_settings.py:170 msgid "Series {0} already used in {1}" msgstr "" @@ -29172,7 +29217,7 @@ msgstr "" msgid "Session Expiry must be in format {0}" msgstr "" -#: public/js/frappe/ui/filters/filter.js:563 +#: public/js/frappe/ui/filters/filter.js:569 msgctxt "Field value is set" msgid "Set" msgstr "" @@ -29660,7 +29705,7 @@ msgstr "" msgid "Show Error" msgstr "" -#: public/js/frappe/form/layout.js:545 +#: public/js/frappe/form/layout.js:553 msgid "Show Fieldname (click to copy on clipboard)" msgstr "" @@ -29902,7 +29947,7 @@ msgctxt "Slack Webhook URL" msgid "Show link to document" msgstr "" -#: public/js/frappe/form/layout.js:247 public/js/frappe/form/layout.js:265 +#: public/js/frappe/form/layout.js:255 public/js/frappe/form/layout.js:273 msgid "Show more details" msgstr "" @@ -30042,7 +30087,7 @@ msgctxt "User" msgid "Simultaneous Sessions" msgstr "" -#: custom/doctype/customize_form/customize_form.py:121 +#: custom/doctype/customize_form/customize_form.py:122 msgid "Single DocTypes cannot be customized." msgstr "" @@ -30103,7 +30148,7 @@ msgstr "" msgid "Skipping column {0}" msgstr "" -#: modules/utils.py:158 +#: modules/utils.py:171 msgid "Skipping fixture syncing for doctype {0} from file {1}" msgstr "" @@ -30321,7 +30366,7 @@ msgctxt "Customize Form" msgid "Sort Order" msgstr "" -#: core/doctype/doctype/doctype.py:1498 +#: core/doctype/doctype/doctype.py:1517 msgid "Sort field {0} must be a valid fieldname" msgstr "" @@ -30447,7 +30492,7 @@ msgstr "" msgid "Standard DocType can not be deleted." msgstr "" -#: core/doctype/doctype/doctype.py:224 +#: core/doctype/doctype/doctype.py:225 msgid "Standard DocType cannot have default print format, use Customize Form" msgstr "" @@ -30688,6 +30733,7 @@ msgid "Stats based on last week's performance (from {0} to {1})" msgstr "" #: core/doctype/data_import/data_import.js:489 +#: public/js/frappe/list/list_settings.js:356 #: public/js/frappe/views/reports/report_view.js:908 msgid "Status" msgstr "" @@ -31025,7 +31071,7 @@ msgctxt "DocType" msgid "Subject Field" msgstr "" -#: core/doctype/doctype/doctype.py:1873 +#: core/doctype/doctype/doctype.py:1892 msgid "Subject Field type should be Data, Text, Long Text, Small Text, Text Editor" msgstr "" @@ -31146,7 +31192,7 @@ msgid "Submit {0} documents?" msgstr "" #: public/js/frappe/model/indicator.js:95 -#: public/js/frappe/ui/filters/filter.js:495 +#: public/js/frappe/ui/filters/filter.js:501 #: website/doctype/web_form/templates/web_form.html:133 msgid "Submitted" msgstr "" @@ -31426,7 +31472,7 @@ msgstr "" msgid "Sync Contacts" msgstr "" -#: custom/doctype/customize_form/customize_form.js:214 +#: custom/doctype/customize_form/customize_form.js:256 msgid "Sync on Migrate" msgstr "" @@ -31549,6 +31595,7 @@ msgstr "" #: custom/doctype/property_setter/property_setter.json #: desk/doctype/bulk_update/bulk_update.json #: desk/doctype/calendar_view/calendar_view.json +#: desk/doctype/changelog_feed/changelog_feed.json #: desk/doctype/console_log/console_log.json #: desk/doctype/custom_html_block/custom_html_block.json #: desk/doctype/dashboard/dashboard.json @@ -31727,7 +31774,7 @@ msgctxt "DocType Link" msgid "Table Fieldname" msgstr "" -#: core/doctype/doctype/doctype.py:1151 +#: core/doctype/doctype/doctype.py:1170 msgid "Table Fieldname Missing" msgstr "" @@ -31755,6 +31802,10 @@ msgctxt "DocField" msgid "Table MultiSelect" msgstr "" +#: custom/doctype/customize_form/customize_form.js:229 +msgid "Table Trimmed" +msgstr "" + #: public/js/frappe/form/grid.js:1138 msgid "Table updated" msgstr "" @@ -32283,7 +32334,7 @@ msgstr "" msgid "There are documents which have workflow states that do not exist in this Workflow. It is recommended that you add these states to the Workflow and change their states before removing these states." msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:428 +#: public/js/frappe/ui/notifications/notifications.js:435 msgid "There are no upcoming events for you." msgstr "" @@ -32300,7 +32351,7 @@ msgstr "" msgid "There can be only 9 Page Break fields in a Web Form" msgstr "" -#: core/doctype/doctype/doctype.py:1391 +#: core/doctype/doctype/doctype.py:1410 msgid "There can be only one Fold in a form" msgstr "" @@ -32312,6 +32363,10 @@ msgstr "" msgid "There is no data to be exported" msgstr "" +#: public/js/frappe/ui/notifications/notifications.js:485 +msgid "There is nothing new to show you right now." +msgstr "" + #: core/doctype/file/file.py:571 utils/file_manager.py:372 msgid "There is some problem with the file url: {0}" msgstr "" @@ -32402,6 +32457,10 @@ msgstr "" msgid "This Kanban Board will be private" msgstr "" +#: custom/doctype/customize_form/customize_form.js:220 +msgid "This action is irreversible. Do you wish to continue?" +msgstr "" + #: __init__.py:1016 msgid "This action is only allowed for {}" msgstr "" @@ -32422,6 +32481,14 @@ msgctxt "Dashboard Chart" msgid "This chart will be available to all Users if this is set" msgstr "" +#: custom/doctype/customize_form/customize_form.js:212 +msgid "This doctype has no orphan fields to trim" +msgstr "" + +#: core/doctype/doctype/doctype.py:1035 +msgid "This doctype has pending migrations, run 'bench migrate' before modifying the doctype to avoid losing changes." +msgstr "" + #: desk/doctype/workspace/workspace.js:23 msgid "This document allows you to edit limited fields. For all kinds of workspace customization, use the Edit button located on the workspace page" msgstr "" @@ -32446,7 +32513,7 @@ msgstr "" msgid "This document is already amended, you cannot ammend it again" msgstr "" -#: model/document.py:1545 +#: model/document.py:1546 msgid "This document is currently locked and queued for execution. Please try again after some time." msgstr "" @@ -32586,7 +32653,7 @@ msgstr "" msgid "This site is in read only mode, full functionality will be restored soon." msgstr "" -#: core/doctype/doctype/doctype.js:76 +#: core/doctype/doctype/doctype.js:77 msgid "This site is running in developer mode. Any change made here will be updated in code." msgstr "" @@ -32851,11 +32918,11 @@ msgctxt "Activity Log" msgid "Timeline Name" msgstr "" -#: core/doctype/doctype/doctype.py:1486 +#: core/doctype/doctype/doctype.py:1505 msgid "Timeline field must be a Link or Dynamic Link" msgstr "" -#: core/doctype/doctype/doctype.py:1482 +#: core/doctype/doctype/doctype.py:1501 msgid "Timeline field must be a valid fieldname" msgstr "" @@ -32924,6 +32991,12 @@ msgctxt "Blog Settings" msgid "Title" msgstr "" +#. Label of a Data field in DocType 'Changelog Feed' +#: desk/doctype/changelog_feed/changelog_feed.json +msgctxt "Changelog Feed" +msgid "Title" +msgstr "" + #. Label of a Data field in DocType 'Discussion Topic' #: website/doctype/discussion_topic/discussion_topic.json msgctxt "Discussion Topic" @@ -33044,7 +33117,7 @@ msgctxt "Website Settings" msgid "Title Prefix" msgstr "" -#: core/doctype/doctype/doctype.py:1423 +#: core/doctype/doctype/doctype.py:1442 msgid "Title field must be a valid fieldname" msgstr "" @@ -33232,10 +33305,6 @@ msgstr "" msgid "Today" msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:55 -msgid "Today's Events" -msgstr "" - #: public/js/frappe/views/reports/report_view.js:1493 msgid "Toggle Chart" msgstr "" @@ -33392,7 +33461,7 @@ msgctxt "Discussion Reply" msgid "Topic" msgstr "" -#: desk/query_report.py:497 public/js/frappe/views/reports/print_grid.html:45 +#: desk/query_report.py:501 public/js/frappe/views/reports/print_grid.html:45 #: public/js/frappe/views/reports/report_view.js:1474 msgid "Total" msgstr "" @@ -33650,6 +33719,10 @@ msgctxt "Notification" msgid "Trigger on valid methods like \"before_insert\", \"after_update\", etc (will depend on the DocType selected)" msgstr "" +#: custom/doctype/customize_form/customize_form.js:144 +msgid "Trim Table" +msgstr "" + #: public/js/frappe/widgets/onboarding_widget.js:323 msgid "Try Again" msgstr "" @@ -34162,7 +34235,7 @@ msgstr "" #: core/doctype/data_import/data_import_list.js:36 #: core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.js:23 -#: custom/doctype/customize_form/customize_form.js:370 +#: custom/doctype/customize_form/customize_form.js:415 #: desk/doctype/bulk_update/bulk_update.js:15 #: printing/page/print_format_builder/print_format_builder.js:447 #: printing/page/print_format_builder/print_format_builder.js:501 @@ -34774,7 +34847,7 @@ msgctxt "User" msgid "User Image" msgstr "" -#: public/js/frappe/ui/toolbar/navbar.html:115 +#: public/js/frappe/ui/toolbar/navbar.html:116 msgid "User Menu" msgstr "" @@ -35181,7 +35254,7 @@ msgstr "" msgid "Value for a check field can be either 0 or 1" msgstr "" -#: custom/doctype/customize_form/customize_form.py:607 +#: custom/doctype/customize_form/customize_form.py:608 msgid "Value for field {0} is too long in {1}. Length should be lesser than {2} characters" msgstr "" @@ -35308,7 +35381,7 @@ msgstr "" msgid "View Comment" msgstr "" -#: public/js/frappe/ui/notifications/notifications.js:213 +#: public/js/frappe/ui/notifications/notifications.js:220 msgid "View Full Log" msgstr "" @@ -35463,6 +35536,10 @@ msgctxt "Workflow State" msgid "Warning" msgstr "" +#: custom/doctype/customize_form/customize_form.js:217 +msgid "Warning: DATA LOSS IMMINENT! Proceeding will permanently delete following database columns from doctype {0}:" +msgstr "" + #: public/js/frappe/model/meta.js:179 msgid "Warning: Unable to find {0} in any table related to {1}" msgstr "" @@ -35784,7 +35861,7 @@ msgctxt "DocType" msgid "Website Search Field" msgstr "" -#: core/doctype/doctype/doctype.py:1470 +#: core/doctype/doctype/doctype.py:1489 msgid "Website Search Field must be a valid fieldname" msgstr "" @@ -36053,6 +36130,10 @@ msgstr "" msgid "Welcome to {0}" msgstr "" +#: public/js/frappe/ui/notifications/notifications.js:62 +msgid "What's New" +msgstr "" + #. Description of the 'Allow Guests to Upload Files' (Check) field in DocType #. 'System Settings' #: core/doctype/system_settings/system_settings.json @@ -36320,6 +36401,10 @@ msgstr "" msgid "Workflow state represents the current state of a document." msgstr "" +#: public/js/workflow_builder/store.js:83 +msgid "Workflow updated successfully" +msgstr "" + #. Description of the Onboarding Step 'Setup Approval Workflows' #: custom/onboarding_step/workflows/workflows.json msgid "Workflows allow you to define custom rules for the approval process of a particular document in ERPNext. You can also set complex Workflow Rules and set approval conditions." @@ -36350,7 +36435,7 @@ msgctxt "Workspace" msgid "Workspace" msgstr "" -#: public/js/frappe/router.js:194 +#: public/js/frappe/router.js:193 msgid "Workspace {0} does not exist" msgstr "" @@ -36573,7 +36658,7 @@ msgctxt "Approve confirmation dialog" msgid "Yes" msgstr "" -#: public/js/frappe/ui/filters/filter.js:501 +#: public/js/frappe/ui/filters/filter.js:507 msgctxt "Checkbox is checked" msgid "Yes" msgstr "" @@ -36644,7 +36729,7 @@ msgstr "" msgid "You are not allowed to edit the report." msgstr "" -#: permissions.py:605 +#: permissions.py:603 msgid "You are not allowed to export {} doctype" msgstr "" @@ -36761,7 +36846,7 @@ msgstr "" msgid "You can select one from the following," msgstr "" -#: desk/query_report.py:332 +#: desk/query_report.py:336 msgid "You can try changing the filters of your report." msgstr "" @@ -36773,11 +36858,11 @@ msgstr "" msgid "You can use wildcard %" msgstr "" -#: custom/doctype/customize_form/customize_form.py:385 +#: custom/doctype/customize_form/customize_form.py:386 msgid "You can't set 'Options' for field {0}" msgstr "" -#: custom/doctype/customize_form/customize_form.py:389 +#: custom/doctype/customize_form/customize_form.py:390 msgid "You can't set 'Translatable' for field {0}" msgstr "" @@ -36799,7 +36884,7 @@ msgstr "" msgid "You cannot give review points to yourself" msgstr "" -#: custom/doctype/customize_form/customize_form.py:381 +#: custom/doctype/customize_form/customize_form.py:382 msgid "You cannot unset 'Read Only' for field {0}" msgstr "" @@ -36894,7 +36979,7 @@ msgstr "" msgid "You have been successfully logged out" msgstr "" -#: custom/doctype/customize_form/customize_form.py:240 +#: custom/doctype/customize_form/customize_form.py:241 msgid "You have hit the row size limit on database table: {0}" msgstr "" @@ -37059,7 +37144,7 @@ msgstr "" msgid "Your account has been deleted" msgstr "" -#: auth.py:472 +#: auth.py:474 msgid "Your account has been locked and will resume after {0} seconds" msgstr "" @@ -37775,7 +37860,7 @@ msgctxt "Workspace" msgid "grey" msgstr "" -#: utils/backups.py:375 +#: utils/backups.py:380 msgid "gzip not found in PATH! This is required to take a backup." msgstr "" @@ -37893,7 +37978,7 @@ msgstr "" msgid "just now" msgstr "" -#: desk/desktop.py:255 desk/query_report.py:277 +#: desk/desktop.py:255 desk/query_report.py:281 msgid "label" msgstr "" @@ -39129,7 +39214,7 @@ msgstr "" msgid "{0} in row {1} cannot have both URL and child items" msgstr "" -#: core/doctype/doctype/doctype.py:914 +#: core/doctype/doctype/doctype.py:915 msgid "{0} is a mandatory field" msgstr "" @@ -39137,7 +39222,7 @@ msgstr "" msgid "{0} is a not a valid zip file" msgstr "" -#: core/doctype/doctype/doctype.py:1554 +#: core/doctype/doctype/doctype.py:1573 msgid "{0} is an invalid Data field." msgstr "" @@ -39218,11 +39303,11 @@ msgstr "" msgid "{0} is not a valid Workflow State. Please update your Workflow and try again." msgstr "" -#: permissions.py:786 +#: permissions.py:784 msgid "{0} is not a valid parent DocType for {1}" msgstr "" -#: permissions.py:806 +#: permissions.py:804 msgid "{0} is not a valid parentfield for {1}" msgstr "" @@ -39308,7 +39393,7 @@ msgstr "" msgid "{0} months ago" msgstr "" -#: model/document.py:1602 +#: model/document.py:1603 msgid "{0} must be after {1}" msgstr "" @@ -39411,7 +39496,7 @@ msgstr "" msgid "{0} role does not have permission on any doctype" msgstr "" -#: desk/query_report.py:576 +#: desk/query_report.py:580 msgid "{0} saved successfully" msgstr "" @@ -39431,7 +39516,7 @@ msgstr "" msgid "{0} shared this document with {1}" msgstr "" -#: core/doctype/doctype/doctype.py:316 +#: core/doctype/doctype/doctype.py:317 msgid "{0} should be indexed because it's referred in dashboard connections" msgstr "" @@ -39467,7 +39552,7 @@ msgstr "" msgid "{0} un-shared this document with {1}" msgstr "" -#: custom/doctype/customize_form/customize_form.py:249 +#: custom/doctype/customize_form/customize_form.py:250 msgid "{0} updated" msgstr "" @@ -39523,7 +39608,7 @@ msgstr "" msgid "{0} {1} is linked with the following submitted documents: {2}" msgstr "" -#: model/document.py:175 permissions.py:559 +#: model/document.py:175 permissions.py:557 msgid "{0} {1} not found" msgstr "" @@ -39539,31 +39624,31 @@ msgstr "" msgid "{0}: '{1}' ({3}) will get truncated, as max characters allowed is {2}" msgstr "" -#: core/doctype/doctype/doctype.py:1738 +#: core/doctype/doctype/doctype.py:1757 msgid "{0}: Cannot set Amend without Cancel" msgstr "" -#: core/doctype/doctype/doctype.py:1756 +#: core/doctype/doctype/doctype.py:1775 msgid "{0}: Cannot set Assign Amend if not Submittable" msgstr "" -#: core/doctype/doctype/doctype.py:1754 +#: core/doctype/doctype/doctype.py:1773 msgid "{0}: Cannot set Assign Submit if not Submittable" msgstr "" -#: core/doctype/doctype/doctype.py:1733 +#: core/doctype/doctype/doctype.py:1752 msgid "{0}: Cannot set Cancel without Submit" msgstr "" -#: core/doctype/doctype/doctype.py:1740 +#: core/doctype/doctype/doctype.py:1759 msgid "{0}: Cannot set Import without Create" msgstr "" -#: core/doctype/doctype/doctype.py:1736 +#: core/doctype/doctype/doctype.py:1755 msgid "{0}: Cannot set Submit, Cancel, Amend without Write" msgstr "" -#: core/doctype/doctype/doctype.py:1760 +#: core/doctype/doctype/doctype.py:1779 msgid "{0}: Cannot set import as {1} is not importable" msgstr "" @@ -39571,43 +39656,43 @@ msgstr "" msgid "{0}: Failed to attach new recurring document. To enable attaching document in the auto repeat notification email, enable {1} in Print Settings" msgstr "" -#: core/doctype/doctype/doctype.py:1374 +#: core/doctype/doctype/doctype.py:1393 msgid "{0}: Field '{1}' cannot be set as Unique as it has non-unique values" msgstr "" -#: core/doctype/doctype/doctype.py:1282 +#: core/doctype/doctype/doctype.py:1301 msgid "{0}: Field {1} in row {2} cannot be hidden and mandatory without default" msgstr "" -#: core/doctype/doctype/doctype.py:1241 +#: core/doctype/doctype/doctype.py:1260 msgid "{0}: Field {1} of type {2} cannot be mandatory" msgstr "" -#: core/doctype/doctype/doctype.py:1229 +#: core/doctype/doctype/doctype.py:1248 msgid "{0}: Fieldname {1} appears multiple times in rows {2}" msgstr "" -#: core/doctype/doctype/doctype.py:1361 +#: core/doctype/doctype/doctype.py:1380 msgid "{0}: Fieldtype {1} for {2} cannot be unique" msgstr "" -#: core/doctype/doctype/doctype.py:1693 +#: core/doctype/doctype/doctype.py:1712 msgid "{0}: No basic permissions set" msgstr "" -#: core/doctype/doctype/doctype.py:1707 +#: core/doctype/doctype/doctype.py:1726 msgid "{0}: Only one rule allowed with the same Role, Level and {1}" msgstr "" -#: core/doctype/doctype/doctype.py:1263 +#: core/doctype/doctype/doctype.py:1282 msgid "{0}: Options must be a valid DocType for field {1} in row {2}" msgstr "" -#: core/doctype/doctype/doctype.py:1252 +#: core/doctype/doctype/doctype.py:1271 msgid "{0}: Options required for Link or Table type field {1} in row {2}" msgstr "" -#: core/doctype/doctype/doctype.py:1270 +#: core/doctype/doctype/doctype.py:1289 msgid "{0}: Options {1} must be the same as doctype name {2} for the field {3}" msgstr "" @@ -39615,7 +39700,7 @@ msgstr "" msgid "{0}: Other permission rules may also apply" msgstr "" -#: core/doctype/doctype/doctype.py:1722 +#: core/doctype/doctype/doctype.py:1741 msgid "{0}: Permission at level 0 must be set before higher levels are set" msgstr "" @@ -39623,7 +39708,7 @@ msgstr "" msgid "{0}: You can increase the limit for the field if required via {1}" msgstr "" -#: core/doctype/doctype/doctype.py:1216 +#: core/doctype/doctype/doctype.py:1235 msgid "{0}: fieldname cannot be set to reserved keyword {1}" msgstr "" @@ -39641,7 +39726,7 @@ msgstr "" msgid "{0}: {1} vs {2}" msgstr "" -#: core/doctype/doctype/doctype.py:1382 +#: core/doctype/doctype/doctype.py:1401 msgid "{0}:Fieldtype {1} for {2} cannot be indexed" msgstr "" @@ -39661,7 +39746,7 @@ msgstr "" msgid "{count} rows selected" msgstr "" -#: core/doctype/doctype/doctype.py:1436 +#: core/doctype/doctype/doctype.py:1455 msgid "{{{0}}} is not a valid fieldname pattern. It should be {{field_name}}." msgstr "" @@ -39702,7 +39787,7 @@ msgstr "" msgid "{} not found in PATH! This is required to restore the database." msgstr "" -#: utils/backups.py:442 +#: utils/backups.py:447 msgid "{} not found in PATH! This is required to take a backup." msgstr "" From a99c4ff2b0f0803bd2b625e80f4a8014ee10827f Mon Sep 17 00:00:00 2001 From: David Arnold Date: Mon, 15 Apr 2024 14:09:48 +0200 Subject: [PATCH 15/23] fix: don't sanitize defaults and options (#25939) --- frappe/core/doctype/docfield/docfield.json | 6 ++++-- frappe/custom/doctype/custom_field/custom_field.json | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json index 08820719ca..4943f7a94c 100644 --- a/frappe/core/doctype/docfield/docfield.json +++ b/frappe/core/doctype/docfield/docfield.json @@ -228,6 +228,7 @@ "description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.", "fieldname": "options", "fieldtype": "Small Text", + "ignore_xss_filter": 1, "in_list_view": 1, "label": "Options", "oldfieldname": "options", @@ -236,6 +237,7 @@ { "fieldname": "default", "fieldtype": "Small Text", + "ignore_xss_filter": 1, "label": "Default", "max_height": "3rem", "oldfieldname": "default", @@ -582,7 +584,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2024-03-23 16:02:18.210626", + "modified": "2024-04-12 16:27:34.546314", "modified_by": "Administrator", "module": "Core", "name": "DocField", @@ -592,4 +594,4 @@ "sort_field": "creation", "sort_order": "ASC", "states": [] -} \ No newline at end of file +} diff --git a/frappe/custom/doctype/custom_field/custom_field.json b/frappe/custom/doctype/custom_field/custom_field.json index 09c6fad731..abe50d0444 100644 --- a/frappe/custom/doctype/custom_field/custom_field.json +++ b/frappe/custom/doctype/custom_field/custom_field.json @@ -143,6 +143,7 @@ { "fieldname": "options", "fieldtype": "Small Text", + "ignore_xss_filter": 1, "in_list_view": 1, "label": "Options", "oldfieldname": "options", @@ -186,6 +187,7 @@ { "fieldname": "default", "fieldtype": "Text", + "ignore_xss_filter": 1, "label": "Default Value", "oldfieldname": "default", "oldfieldtype": "Text" @@ -464,7 +466,7 @@ "idx": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2024-03-23 16:02:15.143117", + "modified": "2024-04-12 16:25:50.349736", "modified_by": "Administrator", "module": "Custom", "name": "Custom Field", @@ -498,4 +500,4 @@ "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} From 55b1e4a167d1d5279747220d8ab5aa0733d8b9aa Mon Sep 17 00:00:00 2001 From: avc <94137451+git-avc@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:15:02 +0200 Subject: [PATCH 16/23] fix: filter button translation (#25944) --- frappe/public/js/frappe/ui/filters/filter_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/ui/filters/filter_list.js b/frappe/public/js/frappe/ui/filters/filter_list.js index 880c3ba8d9..100ceecc8e 100644 --- a/frappe/public/js/frappe/ui/filters/filter_list.js +++ b/frappe/public/js/frappe/ui/filters/filter_list.js @@ -130,7 +130,7 @@ frappe.ui.FilterGroup = class { update_filter_button() { const filters_applied = this.filters.length > 0; const button_label = filters_applied - ? __("Filters {0}", [this.filters.length]) + ? __("Filters {0}", [`${this.filters.length}`]) : __("Filter"); this.filter_button From 9feef371ff887b116336cf05244821156bc02d24 Mon Sep 17 00:00:00 2001 From: avc <94137451+git-avc@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:16:24 +0200 Subject: [PATCH 17/23] fix: let's color tag in form view (#25949) * fix: let's color tag in form * fix: linters --- frappe/public/js/frappe/dom.js | 29 +++++++++++++++++++++-------- frappe/public/js/frappe/ui/tags.js | 17 +++++++++++------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/frappe/public/js/frappe/dom.js b/frappe/public/js/frappe/dom.js index 33b9e3e403..c20cb98d88 100644 --- a/frappe/public/js/frappe/dom.js +++ b/frappe/public/js/frappe/dom.js @@ -304,27 +304,40 @@ frappe.unscrub = function (txt) { return frappe.model.unscrub(txt); }; -frappe.get_data_pill = (label, target_id = null, remove_action = null, image = null) => { +frappe.get_data_pill = ( + label, + target_id = null, + remove_action = null, + image = null, + colored = false +) => { + let color = "", + style = ""; + if (colored) { + color = frappe.get_palette(label); + } + style = `background-color: var(${color[0]}); color: var(${color[1]})`; let data_pill_wrapper = $(` - `); - if (remove_action) { let remove_btn = $(` ${frappe.utils.icon("close", "sm")} - `).click(() => { - remove_action(target_id || label, data_pill_wrapper); - }); + `); + if (typeof remove_action === "function") { + remove_btn.click(() => { + remove_action(target_id || label, data_pill_wrapper); + }); + } data_pill_wrapper.append(remove_btn); } - return data_pill_wrapper; }; diff --git a/frappe/public/js/frappe/ui/tags.js b/frappe/public/js/frappe/ui/tags.js index 8dc9ed106c..1db78fc156 100644 --- a/frappe/public/js/frappe/ui/tags.js +++ b/frappe/public/js/frappe/ui/tags.js @@ -100,17 +100,22 @@ frappe.ui.Tags = class { } get_tag(label) { - let $tag = frappe.get_data_pill(label, label, (target, pill_wrapper) => { - this.removeTag(target); - pill_wrapper.closest(".form-tag-row").remove(); - }); - + let colored = true; + let $tag = frappe.get_data_pill( + label, + label, + (target, pill_wrapper) => { + this.removeTag(target); + pill_wrapper.closest(".form-tag-row").remove(); + }, + null, + colored + ); if (this.onTagClick) { $tag.on("click", ".pill-label", () => { this.onTagClick(label); }); } - return $tag; } }; From 7b39a9bbd344a84c4b4dfaa2f3ea9be1679a9ac7 Mon Sep 17 00:00:00 2001 From: Rutwik Hiwalkar Date: Tue, 16 Apr 2024 11:35:58 +0530 Subject: [PATCH 18/23] feat: add vim and emacs mode for ace-editor (#25936) --- frappe/core/doctype/user/user.json | 12 ++++++++++-- frappe/core/doctype/user/user.py | 1 + frappe/public/js/frappe/form/controls/code.js | 4 +++- frappe/utils/user.py | 1 + 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/frappe/core/doctype/user/user.json b/frappe/core/doctype/user/user.json index 206a9ba248..1cdf6c2397 100644 --- a/frappe/core/doctype/user/user.json +++ b/frappe/core/doctype/user/user.json @@ -48,6 +48,7 @@ "desk_settings_section", "mute_sounds", "desk_theme", + "code_editor_type", "banner_image", "change_password", "new_password", @@ -726,6 +727,13 @@ "fieldname": "workspace_section", "fieldtype": "Section Break", "label": "Workspace" + }, + { + "default": "vscode", + "fieldname": "code_editor_type", + "fieldtype": "Select", + "label": "Code Editor Type", + "options": "vscode\nvim\nemacs" } ], "icon": "fa fa-user", @@ -788,7 +796,7 @@ "link_fieldname": "user" } ], - "modified": "2024-03-23 16:03:59.833565", + "modified": "2024-04-12 23:25:04.628007", "modified_by": "Administrator", "module": "Core", "name": "User", @@ -827,4 +835,4 @@ "states": [], "title_field": "full_name", "track_changes": 1 -} +} \ No newline at end of file diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 2d1583a81c..d856fd0c0f 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -63,6 +63,7 @@ class User(Document): birth_date: DF.Date | None block_modules: DF.Table[BlockModule] bypass_restrict_ip_check_if_2fa_enabled: DF.Check + code_editor_type: DF.Literal["vscode", "vim", "emacs"] default_workspace: DF.Link | None defaults: DF.Table[DefaultValue] desk_theme: DF.Literal["Light", "Dark", "Automatic"] diff --git a/frappe/public/js/frappe/form/controls/code.js b/frappe/public/js/frappe/form/controls/code.js index 4efd92bd8d..d57b6728b7 100644 --- a/frappe/public/js/frappe/form/controls/code.js +++ b/frappe/public/js/frappe/form/controls/code.js @@ -177,7 +177,9 @@ frappe.ui.form.ControlCode = class ControlCode extends frappe.ui.form.ControlTex const ace_language_mode = language_map[language] || ""; this.editor.session.setMode(ace_language_mode); - this.editor.setKeyboardHandler("ace/keyboard/vscode"); + this.editor.setKeyboardHandler( + `ace/keyboard/${frappe.boot.user.code_editor_type || "vscode"}` + ); } parse(value) { diff --git a/frappe/utils/user.py b/frappe/utils/user.py index a3562d6d7a..872fa8dca8 100644 --- a/frappe/utils/user.py +++ b/frappe/utils/user.py @@ -216,6 +216,7 @@ class UserPermissions: [ "creation", "desk_theme", + "code_editor_type", "document_follow_notify", "email", "email_signature", From fd02b912de9ddf6c2305f7ba0e954d0c09ec2b63 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 16 Apr 2024 12:48:02 +0530 Subject: [PATCH 19/23] fix: title width for form (#25958) --- frappe/public/scss/desk/mobile.scss | 8 -------- frappe/public/scss/desk/page.scss | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/frappe/public/scss/desk/mobile.scss b/frappe/public/scss/desk/mobile.scss index a965feca65..9136441f87 100644 --- a/frappe/public/scss/desk/mobile.scss +++ b/frappe/public/scss/desk/mobile.scss @@ -9,14 +9,6 @@ body { // overflow-x: hidden; //Prevent scroll on narrow devices // } -@media (max-width: 1024px) { - body[data-route^="Form"] { - .page-title .title-text { - max-width: 35vw; - } - } -} - @media (max-width: 991px) { .intro-area, .footnote-area { diff --git a/frappe/public/scss/desk/page.scss b/frappe/public/scss/desk/page.scss index d2c391ebbb..fd5edd9106 100644 --- a/frappe/public/scss/desk/page.scss +++ b/frappe/public/scss/desk/page.scss @@ -32,7 +32,7 @@ cursor: pointer; margin-bottom: 0px; margin-right: var(--margin-sm); - max-width: 48vw; + max-width: 25vw; } .indicator-pill { margin-top: 2px; From f46c4813caeb8d6f0253f343c730adbb1ea2cde5 Mon Sep 17 00:00:00 2001 From: Corentin Flr <10946971+cogk@users.noreply.github.com> Date: Tue, 16 Apr 2024 10:06:59 +0200 Subject: [PATCH 20/23] fix(ControlLink)!: Fix link selection in tables on iOS (#25472) * fix(ControlLink)!: Fix link selection in tables on iOS * test: use correct selector * test: change selector --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Ankush Menat --- cypress/integration/control_dynamic_link.js | 10 +++---- frappe/public/js/frappe/form/controls/link.js | 7 +++-- frappe/public/scss/common/awesomeplete.scss | 29 ++++++++++--------- frappe/public/scss/common/modal.scss | 3 +- frappe/public/scss/desk/filters.scss | 6 ++-- 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/cypress/integration/control_dynamic_link.js b/cypress/integration/control_dynamic_link.js index 7f34f7ad42..f98e23c57a 100644 --- a/cypress/integration/control_dynamic_link.js +++ b/cypress/integration/control_dynamic_link.js @@ -85,7 +85,7 @@ context("Dynamic Link", () => { //Checking if the listbox have length greater than 0 cy.get('[data-fieldname="doc_id"]') .find(".awesomplete") - .find("li") + .find("div") .its("length") .should("be.gte", 0); cy.get(".btn-modal-close").click({ force: true }); @@ -100,7 +100,7 @@ context("Dynamic Link", () => { //Checking if the listbox have length greater than 0 cy.get('[data-fieldname="doc_id"]') .find(".awesomplete") - .find("li") + .find("div") .its("length") .should("be.gte", 0); cy.get(".btn-modal-close").click({ force: true, multiple: true }); @@ -119,7 +119,7 @@ context("Dynamic Link", () => { //Checking if the listbox have length greater than 0 cy.get('[data-fieldname="doc_id"]') .find(".awesomplete") - .find("li") + .find("div") .its("length") .should("be.gte", 0); @@ -134,7 +134,7 @@ context("Dynamic Link", () => { //Checking if the listbox have length greater than 0 cy.get('[data-fieldname="doc_id"]') .find(".awesomplete") - .find("li") + .find("div") .its("length") .should("be.gte", 0); cy.get_field("doc_type").clear(); @@ -143,7 +143,7 @@ context("Dynamic Link", () => { cy.intercept("/api/method/frappe.desk.search.search_link").as("search_query"); cy.fill_field("doc_type", "System Settings", "Link", { delay: 500 }); cy.wait("@search_query"); - cy.get(`[data-fieldname="doc_type"] ul:visible li:first-child`).click({ + cy.get(`[data-fieldname="doc_type"] ul:visible div:first-child`).click({ scrollBehavior: false, }); diff --git a/frappe/public/js/frappe/form/controls/link.js b/frappe/public/js/frappe/form/controls/link.js index 7cae8684e8..e51fd1251f 100644 --- a/frappe/public/js/frappe/form/controls/link.js +++ b/frappe/public/js/frappe/form/controls/link.js @@ -219,10 +219,13 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat ) { html += '
' + __(d.description) + ""; } - return $("
  • ") + return $(`
    `) + .on("click", (event) => { + me.awesomplete.select(event.currentTarget, event.currentTarget); + }) .data("item.autocomplete", d) .prop("aria-selected", "false") - .html(`

    ${html}

    `) + .html(`

    ${html}

    `) .get(0); }, sort: function () { diff --git a/frappe/public/scss/common/awesomeplete.scss b/frappe/public/scss/common/awesomeplete.scss index 2ec7c62253..471df71675 100644 --- a/frappe/public/scss/common/awesomeplete.scss +++ b/frappe/public/scss/common/awesomeplete.scss @@ -12,11 +12,11 @@ display: block; } - & > ul:empty { - display: none; - } + & > [role="listbox"] { + &:empty { + display: none; + } - & > ul { position: absolute; width: 100%; list-style: none; @@ -33,7 +33,8 @@ z-index: 4; min-width: 250px; - & > li { + & > li, + & > [role="option"] { cursor: pointer; @include get_textstyle("sm", "regular"); padding: var(--padding-sm); @@ -52,17 +53,17 @@ strong { @include get_textstyle("sm", "bold"); } - } - & > li .link-option { - font-weight: normal; - color: var(--text-color); - } + .link-option { + font-weight: normal; + color: var(--text-color); + } - & > li:hover, - & > li[aria-selected="true"] { - background-color: var(--awesomplete-hover-bg); - color: var(--text-color); + &:hover, + &[aria-selected="true"] { + background-color: var(--awesomplete-hover-bg); + color: var(--text-color); + } } a:hover { diff --git a/frappe/public/scss/common/modal.scss b/frappe/public/scss/common/modal.scss index b2e888a41d..8c6d3abd60 100644 --- a/frappe/public/scss/common/modal.scss +++ b/frappe/public/scss/common/modal.scss @@ -85,7 +85,8 @@ body.modal-open[style^="padding-right"] { } } - .awesomplete ul { + .awesomplete ul, + .awesomplete [role="listbox"] { z-index: 2; } diff --git a/frappe/public/scss/desk/filters.scss b/frappe/public/scss/desk/filters.scss index 53e9dfea5a..27f21a087f 100644 --- a/frappe/public/scss/desk/filters.scss +++ b/frappe/public/scss/desk/filters.scss @@ -31,11 +31,13 @@ } .awesomplete { - ul[role="listbox"] { + & > ul, + & > [role="listbox"] { min-width: 100%; width: auto; - li { + & > li, + & > [role="option"] { max-width: 300px; } } From 53bd1a85d16420e903ab5570b4a055592550d4fa Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:53:41 +0200 Subject: [PATCH 21/23] chore: bump pydantic to v2.7.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 491dc504fc..bc8967ab55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,7 @@ dependencies = [ "psutil~=5.9.5", "psycopg2-binary~=2.9.1", "pyOpenSSL~=24.0.0", - "pydantic==2.3.0", + "pydantic~=2.7.0", "pyotp~=2.8.0", "python-dateutil~=2.8.2", "pytz==2023.3", From 733a7fe6f8b0296d835924f7d09632270fb99534 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:56:54 +0200 Subject: [PATCH 22/23] chore: bump sqlparse to v0.5.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bc8967ab55..5718bc64ec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,7 +67,7 @@ dependencies = [ "rsa>=4.1", "semantic-version~=2.10.0", "sentry-sdk~=1.37.1", - "sqlparse~=0.4.4", + "sqlparse~=0.5.0", "sql_metadata~=2.9.0", "tenacity~=8.2.2", "terminaltables~=3.1.10", From 708e10552c08ca2b8ff16eb717bf7004bb430101 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 16 Apr 2024 17:11:03 +0200 Subject: [PATCH 23/23] chore: bump sql_metadata to 2.11.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5718bc64ec..7bf21f9c23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,7 @@ dependencies = [ "semantic-version~=2.10.0", "sentry-sdk~=1.37.1", "sqlparse~=0.5.0", - "sql_metadata~=2.9.0", + "sql_metadata~=2.11.0", "tenacity~=8.2.2", "terminaltables~=3.1.10", "traceback-with-variables~=2.0.4",