Merge branch 'develop' into new-ui-for-api-key
This commit is contained in:
commit
d4a2fe36d3
30 changed files with 453 additions and 175 deletions
|
|
@ -487,7 +487,10 @@ def validate_ip_address(user):
|
|||
if bypass_restrict_ip_check:
|
||||
return
|
||||
|
||||
frappe.throw(_("Access not allowed from this IP Address"), frappe.AuthenticationError)
|
||||
frappe.throw(
|
||||
_("Access not allowed from this IP Address") + f": {frappe.local.request_ip}",
|
||||
frappe.AuthenticationError,
|
||||
)
|
||||
|
||||
|
||||
def get_login_attempt_tracker(key: str, raise_locked_exception: bool = True):
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import hashlib
|
||||
import json
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import click
|
||||
from croniter import CroniterBadCronError, croniter
|
||||
|
|
@ -105,8 +105,7 @@ class ScheduledJobType(Document):
|
|||
# Maintenance jobs run at random time, the time is specific to the site though.
|
||||
# This is done to avoid scheduling all maintenance task on all sites at the same time in
|
||||
# multitenant deployments.
|
||||
hourly_site_offset = int(hashlib.sha1(frappe.local.site.encode()).hexdigest(), 16) % 60
|
||||
daily_site_offset = (hourly_site_offset + 30) % 60
|
||||
maintenance_offset = int(hashlib.sha1(frappe.local.site.encode()).hexdigest(), 16) % 60
|
||||
|
||||
CRON_MAP = {
|
||||
"Yearly": "0 0 1 1 *",
|
||||
|
|
@ -117,10 +116,10 @@ class ScheduledJobType(Document):
|
|||
"Weekly Long": "0 0 * * 0",
|
||||
"Daily": "0 0 * * *",
|
||||
"Daily Long": "0 0 * * *",
|
||||
"Daily Maintenance": f"{daily_site_offset} 0 * * *",
|
||||
"Daily Maintenance": "0 0 * * *",
|
||||
"Hourly": "0 * * * *",
|
||||
"Hourly Long": "0 * * * *",
|
||||
"Hourly Maintenance": f"{hourly_site_offset} * * * *",
|
||||
"Hourly Maintenance": "0 * * * *",
|
||||
"All": f"*/{(frappe.get_conf().scheduler_interval or 240) // 60} * * * *",
|
||||
}
|
||||
|
||||
|
|
@ -133,6 +132,9 @@ class ScheduledJobType(Document):
|
|||
# A dynamic fallback like current time might miss the scheduler interval and job will never start.
|
||||
last_execution = get_datetime(self.last_execution or self.creation)
|
||||
|
||||
next_execution = croniter(self.cron_format, last_execution).get_next(datetime)
|
||||
if self.frequency in ("Hourly Maintenance", "Daily Maintenance"):
|
||||
next_execution += timedelta(minutes=maintenance_offset)
|
||||
return croniter(self.cron_format, last_execution).get_next(datetime)
|
||||
|
||||
def execute(self):
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ class TestScheduledJobType(IntegrationTestCase):
|
|||
sjt = frappe.new_doc(
|
||||
"Scheduled Job Type",
|
||||
frequency="Hourly Maintenance",
|
||||
last_execution=get_datetime("2019-01-01 00:00:00"),
|
||||
last_execution=get_datetime("2019-01-01 23:59:00"),
|
||||
)
|
||||
# Should be within one hour
|
||||
self.assertGreaterEqual(sjt.next_execution, sjt.last_execution)
|
||||
|
|
|
|||
|
|
@ -1447,7 +1447,7 @@ class Database:
|
|||
values: Iterable[Sequence[Any]],
|
||||
ignore_duplicates=False,
|
||||
*,
|
||||
chunk_size=10_000,
|
||||
chunk_size=1000,
|
||||
):
|
||||
"""
|
||||
Insert multiple records at a time
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@ frappe.ui.form.on("System Console", {
|
|||
frm.set_value("type", "Python"); // defaults don't work on singles on old sites.
|
||||
}
|
||||
frm.trigger("load_completions");
|
||||
|
||||
frm.page.add_inner_message(
|
||||
`${__("Tip: Try the new dropdown console using")} <kbd>⇧+T</kbd>`
|
||||
);
|
||||
},
|
||||
|
||||
type: function (frm) {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@
|
|||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-23 16:03:39.355553",
|
||||
"modified": "2025-05-28 09:26:57.614890",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "System Console",
|
||||
|
|
@ -96,14 +96,15 @@
|
|||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"role": "System Manager",
|
||||
"role": "Administrator",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,13 @@ class SystemConsole(Document):
|
|||
# end: auto-generated types
|
||||
|
||||
def run(self):
|
||||
frappe.only_for("System Manager")
|
||||
frappe.only_for(["System Manager", "Administrator"])
|
||||
try:
|
||||
frappe.local.debug_log = []
|
||||
if self.type == "Python":
|
||||
safe_exec(self.console, script_filename="System Console")
|
||||
safe_exec(
|
||||
self.console, script_filename="System Console", restrict_commit_rollback=not self.commit
|
||||
)
|
||||
self.output = "\n".join(frappe.debug_log)
|
||||
elif self.type == "SQL":
|
||||
self.output = frappe.as_json(read_sql(self.console, as_dict=1))
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from frappe.desk.reportview import clean_params, parse_json
|
|||
from frappe.model.utils import render_include
|
||||
from frappe.modules import get_module_path, scrub
|
||||
from frappe.monitor import add_data_to_monitor
|
||||
from frappe.permissions import get_role_permissions, has_permission
|
||||
from frappe.permissions import get_role_permissions, get_valid_perms, has_permission
|
||||
from frappe.utils import cint, cstr, flt, format_duration, get_html_format, sbool
|
||||
|
||||
|
||||
|
|
@ -710,10 +710,8 @@ def has_match(
|
|||
# so that even if one of the sets allows a match, it is true
|
||||
|
||||
if match:
|
||||
if not frappe.has_permission(
|
||||
doctype=ref_doctype, ptype="read", throw=False, ignore_share_permissions=True
|
||||
):
|
||||
match = False
|
||||
valid_perms = get_valid_perms(doctype=ref_doctype)
|
||||
match = any(perm.get("read") and not perm.get("if_owner") for perm in valid_perms)
|
||||
|
||||
matched_for_doctype = matched_for_doctype or match
|
||||
|
||||
|
|
|
|||
|
|
@ -731,7 +731,8 @@ class QueueBuilder:
|
|||
if self.read_receipt:
|
||||
mail.msg_root["Disposition-Notification-To"] = self.sender
|
||||
if self.in_reply_to:
|
||||
mail.set_in_reply_to(self.in_reply_to)
|
||||
if message_id := frappe.db.get_value("Communication", self.in_reply_to, "message_id"):
|
||||
mail.set_in_reply_to(get_string_between("<", message_id, ">"))
|
||||
return mail
|
||||
|
||||
def process(self, send_now=False) -> EmailQueue | None:
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ scheduler_events = {
|
|||
"frappe.utils.global_search.sync_global_search",
|
||||
"frappe.deferred_insert.save_to_db",
|
||||
"frappe.automation.doctype.reminder.reminder.send_reminders",
|
||||
"frappe.model.utils.link_count.update_link_count",
|
||||
],
|
||||
# 10 minutes
|
||||
"0/10 * * * *": [
|
||||
|
|
@ -231,7 +232,6 @@ scheduler_events = {
|
|||
# Use these for when you don't care about when the job runs but just need some guarantee for
|
||||
# frequency.
|
||||
"hourly_maintenance": [
|
||||
"frappe.model.utils.link_count.update_link_count",
|
||||
"frappe.model.utils.user_settings.sync_user_settings",
|
||||
"frappe.desk.page.backups.backups.delete_downloadable_backups",
|
||||
"frappe.desk.form.document_follow.send_hourly_updates",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: developers@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-05-18 09:33+0000\n"
|
||||
"PO-Revision-Date: 2025-05-19 07:02\n"
|
||||
"PO-Revision-Date: 2025-05-26 10:24\n"
|
||||
"Last-Translator: developers@frappe.io\n"
|
||||
"Language-Team: Persian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -115,7 +115,7 @@ msgstr "+ افزودن / حذف فیلدها"
|
|||
#. State'
|
||||
#: frappe/workflow/doctype/workflow_document_state/workflow_document_state.json
|
||||
msgid "0 - Draft; 1 - Submitted; 2 - Cancelled"
|
||||
msgstr "0 - پیشنویس؛ 1 - ارسال شده 2 - لغو شد"
|
||||
msgstr "0 - پیشنویس؛ 1 - ارسال شده؛ 2 - لغو شده"
|
||||
|
||||
#. Description of the 'Priority' (Int) field in DocType 'Web Page'
|
||||
#: frappe/website/doctype/web_page/web_page.json
|
||||
|
|
@ -584,7 +584,7 @@ msgstr "یک {0} {1} تکرارشونده از طریق تکرار خودکار
|
|||
#. Description of the 'Symbol' (Data) field in DocType 'Currency'
|
||||
#: frappe/geo/doctype/currency/currency.json
|
||||
msgid "A symbol for this currency. For e.g. $"
|
||||
msgstr "ن برای این ارز. به عنوان مثال $"
|
||||
msgstr "نمادی برای این ارز. مثلاً $"
|
||||
|
||||
#: frappe/printing/doctype/print_format_field_template/print_format_field_template.py:49
|
||||
msgid "A template already exists for field {0} of {1}"
|
||||
|
|
@ -1153,7 +1153,7 @@ msgstr "افزودن یک نقش جدید"
|
|||
|
||||
#: frappe/public/js/frappe/form/form_tour.js:211
|
||||
msgid "Add a Row"
|
||||
msgstr ""
|
||||
msgstr "افزودن یک ردیف"
|
||||
|
||||
#: frappe/templates/includes/comments/comments.html:30
|
||||
#: frappe/templates/includes/comments/comments.html:47
|
||||
|
|
@ -2138,7 +2138,7 @@ msgstr "افزودن به میتواند یکی از {0} باشد"
|
|||
#. Description of the 'Append To' (Link) field in DocType 'Email Account'
|
||||
#: frappe/email/doctype/email_account/email_account.json
|
||||
msgid "Append as communication against this DocType (must have fields: \"Sender\" and \"Subject\"). These fields can be defined in the email settings section of the appended doctype."
|
||||
msgstr "به عنوان ارتباط در مقابل این DocType اضافه شود (باید دارای فیلدهای: \"فرستنده\" و \"موضوع\"). این فیلدها را میتوان در قسمت تنظیمات ایمیل از doctype ضمیمه شده تعریف کرد."
|
||||
msgstr "به عنوان ارتباط در مقابل این DocType اضافه شود (باید دارای فیلدهای: \"فرستنده\" و \"موضوع\"). این فیلدها را میتوان در قسمت تنظیمات ایمیل از doctype پیوست شده تعریف کرد."
|
||||
|
||||
#: frappe/core/doctype/user_permission/user_permission_list.js:105
|
||||
msgid "Applicable Document Types"
|
||||
|
|
@ -2524,7 +2524,7 @@ msgstr "پیوست"
|
|||
|
||||
#: frappe/public/js/frappe/views/communication.js:152
|
||||
msgid "Attach Document Print"
|
||||
msgstr "ضمیمه چاپ سند"
|
||||
msgstr "پیوست چاپ سند"
|
||||
|
||||
#. Option for the 'Type' (Select) field in DocType 'DocField'
|
||||
#. Option for the 'Field Type' (Select) field in DocType 'Custom Field'
|
||||
|
|
@ -2560,7 +2560,7 @@ msgstr "فایل ها / آدرس ها را پیوست کنید و در جدول
|
|||
#. Label of the attached_file (Code) field in DocType 'Notification Log'
|
||||
#: frappe/desk/doctype/notification_log/notification_log.json
|
||||
msgid "Attached File"
|
||||
msgstr "فایل ضمیمه شده"
|
||||
msgstr "فایل پیوست شده"
|
||||
|
||||
#. Label of the attached_to_doctype (Link) field in DocType 'File'
|
||||
#: frappe/core/doctype/file/file.json
|
||||
|
|
@ -3509,7 +3509,7 @@ msgstr "پرش کرد"
|
|||
#. Label of the brand (Section Break) field in DocType 'Website Settings'
|
||||
#: frappe/website/doctype/website_settings/website_settings.json
|
||||
msgid "Brand"
|
||||
msgstr "نام تجاری"
|
||||
msgstr "برند"
|
||||
|
||||
#. Label of the brand_html (Code) field in DocType 'Website Settings'
|
||||
#: frappe/website/doctype/website_settings/website_settings.json
|
||||
|
|
@ -3519,7 +3519,7 @@ msgstr "HTML برند"
|
|||
#. Label of the banner_image (Attach Image) field in DocType 'Website Settings'
|
||||
#: frappe/website/doctype/website_settings/website_settings.json
|
||||
msgid "Brand Image"
|
||||
msgstr "تصویر نام تجاری"
|
||||
msgstr "تصویر برند"
|
||||
|
||||
#. Label of the brand_logo (Attach Image) field in DocType 'Email Account'
|
||||
#: frappe/email/doctype/email_account/email_account.json
|
||||
|
|
@ -3530,7 +3530,7 @@ msgstr "لوگوی برند"
|
|||
#: frappe/website/doctype/website_settings/website_settings.json
|
||||
msgid "Brand is what appears on the top-left of the toolbar. If it is an image, make sure it\n"
|
||||
"has a transparent background and use the <img /> tag. Keep size as 200px x 30px"
|
||||
msgstr "نام تجاری همان چیزی است که در سمت چپ بالای نوار ابزار ظاهر میشود. اگر تصویر است، مطمئن شوید که\n"
|
||||
msgstr "برند همان چیزی است که در سمت چپ بالای نوار ابزار ظاهر میشود. اگر تصویر است، مطمئن شوید که\n"
|
||||
"دارای پسزمینه شفاف است و از تگ <img /> استفاده کنید. اندازه را 200×30 پیکسل نگه دارید"
|
||||
|
||||
#. Label of the breadcrumbs (Code) field in DocType 'Web Form'
|
||||
|
|
@ -13912,7 +13912,7 @@ msgstr "LDAP فعال نیست."
|
|||
#. Label of the ldap_search_path_group (Data) field in DocType 'LDAP Settings'
|
||||
#: frappe/integrations/doctype/ldap_settings/ldap_settings.json
|
||||
msgid "LDAP search path for Groups"
|
||||
msgstr "مسیر جستجوی LDAP برای گروه ها"
|
||||
msgstr "مسیر جستجوی LDAP برای گروهها"
|
||||
|
||||
#. Label of the ldap_search_path_user (Data) field in DocType 'LDAP Settings'
|
||||
#: frappe/integrations/doctype/ldap_settings/ldap_settings.json
|
||||
|
|
@ -16231,7 +16231,7 @@ msgstr "نظر جدید در مورد {0}: {1}"
|
|||
|
||||
#: frappe/public/js/frappe/form/templates/contact_list.html:3
|
||||
msgid "New Contact"
|
||||
msgstr "تماس جدید"
|
||||
msgstr "مخاطب جدید"
|
||||
|
||||
#: frappe/public/js/frappe/widgets/widget_dialog.js:70
|
||||
msgid "New Custom Block"
|
||||
|
|
@ -17384,7 +17384,7 @@ msgstr "تعداد بک آپ های DB نمیتواند کمتر از 1 با
|
|||
#. Label of the number_of_groups (Int) field in DocType 'Dashboard Chart'
|
||||
#: frappe/desk/doctype/dashboard_chart/dashboard_chart.json
|
||||
msgid "Number of Groups"
|
||||
msgstr "تعداد گروه ها"
|
||||
msgstr "تعداد گروهها"
|
||||
|
||||
#. Label of the number_of_queries (Int) field in DocType 'Recorder'
|
||||
#: frappe/core/doctype/recorder/recorder.json
|
||||
|
|
@ -20425,11 +20425,11 @@ msgstr "دلیل"
|
|||
|
||||
#: frappe/public/js/frappe/views/reports/query_report.js:889
|
||||
msgid "Rebuild"
|
||||
msgstr "بازسازی کنید"
|
||||
msgstr "بازسازی"
|
||||
|
||||
#: frappe/public/js/frappe/views/treeview.js:509
|
||||
msgid "Rebuild Tree"
|
||||
msgstr "درخت را بازسازی کنید"
|
||||
msgstr "بازسازی درخت"
|
||||
|
||||
#: frappe/utils/nestedset.py:177
|
||||
msgid "Rebuilding of tree is not supported for {}"
|
||||
|
|
@ -21021,7 +21021,7 @@ msgstr ""
|
|||
#: frappe/core/doctype/communication/communication.js:43
|
||||
#: frappe/desk/doctype/todo/todo.js:36
|
||||
msgid "Reopen"
|
||||
msgstr "دوباره باز کنید"
|
||||
msgstr "باز کردن دوباره"
|
||||
|
||||
#: frappe/public/js/frappe/form/toolbar.js:544
|
||||
msgid "Repeat"
|
||||
|
|
@ -21402,7 +21402,7 @@ msgstr "نیاز به گواهی مورد اعتماد"
|
|||
#. 'LDAP Settings'
|
||||
#: frappe/integrations/doctype/ldap_settings/ldap_settings.json
|
||||
msgid "Requires any valid fdn path. i.e. ou=groups,dc=example,dc=com"
|
||||
msgstr "به هر مسیر fdn معتبر نیاز دارد. یعنی ou=گروه ها،dc=example,dc=com"
|
||||
msgstr "به هر مسیر fdn معتبر نیاز دارد. یعنی ou=گروهها،dc=example,dc=com"
|
||||
|
||||
#. Description of the 'LDAP search path for Users' (Data) field in DocType
|
||||
#. 'LDAP Settings'
|
||||
|
|
@ -27774,7 +27774,7 @@ msgstr "استفاده از POST"
|
|||
#. Label of the use_report_chart (Check) field in DocType 'Dashboard Chart'
|
||||
#: frappe/desk/doctype/dashboard_chart/dashboard_chart.json
|
||||
msgid "Use Report Chart"
|
||||
msgstr "از نمودار گزارش استفاده کنید"
|
||||
msgstr "استفاده از نمودار گزارش"
|
||||
|
||||
#. Label of the use_ssl (Check) field in DocType 'Email Account'
|
||||
#. Label of the use_ssl_for_outgoing (Check) field in DocType 'Email Account'
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: developers@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-05-18 09:33+0000\n"
|
||||
"PO-Revision-Date: 2025-05-19 07:02\n"
|
||||
"PO-Revision-Date: 2025-05-25 10:26\n"
|
||||
"Last-Translator: developers@frappe.io\n"
|
||||
"Language-Team: Serbian (Latin)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -46,7 +46,7 @@ msgstr "\"Članovi tima\" ili \"Menadžment\""
|
|||
|
||||
#: frappe/public/js/frappe/form/form.js:1090
|
||||
msgid "\"amended_from\" field must be present to do an amendment."
|
||||
msgstr "Polje \"amended_from\" mora postojati da bi se izvršila promena."
|
||||
msgstr "Polje \"Izmenjeno iz\" mora postojati da bi se izvršila promena."
|
||||
|
||||
#: frappe/utils/csvutils.py:246
|
||||
msgid "\"{0}\" is not a valid Google Sheets URL"
|
||||
|
|
@ -1736,7 +1736,7 @@ msgstr "Svi zapisi"
|
|||
|
||||
#: frappe/public/js/frappe/form/form.js:2222
|
||||
msgid "All Submissions"
|
||||
msgstr "Svi podneti podaci"
|
||||
msgstr "Sve podneseno"
|
||||
|
||||
#: frappe/custom/doctype/customize_form/customize_form.js:452
|
||||
msgid "All customizations will be removed. Please confirm."
|
||||
|
|
@ -1823,7 +1823,7 @@ msgstr "Dozvoli gosta"
|
|||
#. Label of the allow_guest_to_view (Check) field in DocType 'DocType'
|
||||
#: frappe/core/doctype/doctype/doctype.json
|
||||
msgid "Allow Guest to View"
|
||||
msgstr "Dozvola gostu da pregleda"
|
||||
msgstr "Dozvoli gostu da pregleda"
|
||||
|
||||
#. Label of the allow_guest_to_comment (Check) field in DocType 'Blog Settings'
|
||||
#: frappe/website/doctype/blog_settings/blog_settings.json
|
||||
|
|
@ -2143,7 +2143,7 @@ msgstr "Izmenjeni dokumenti"
|
|||
#: frappe/core/doctype/transaction_log/transaction_log.json
|
||||
#: frappe/website/doctype/personal_data_download_request/personal_data_download_request.json
|
||||
msgid "Amended From"
|
||||
msgstr "Izmenjeno od"
|
||||
msgstr "Izmenjeno iz"
|
||||
|
||||
#: frappe/public/js/frappe/form/save.js:12
|
||||
msgctxt "Freeze message while amending a document"
|
||||
|
|
@ -3614,7 +3614,7 @@ msgstr "Podešavanje bloga"
|
|||
#. Label of the blog_title (Data) field in DocType 'Blog Settings'
|
||||
#: frappe/website/doctype/blog_settings/blog_settings.json
|
||||
msgid "Blog Title"
|
||||
msgstr "Naziv bloga"
|
||||
msgstr "Naslov bloga"
|
||||
|
||||
#. Name of a role
|
||||
#. Label of the blogger (Link) field in DocType 'Blog Post'
|
||||
|
|
@ -4043,7 +4043,7 @@ msgstr "Callback poruka"
|
|||
#. Label of the callback_title (Data) field in DocType 'Onboarding Step'
|
||||
#: frappe/desk/doctype/onboarding_step/onboarding_step.json
|
||||
msgid "Callback Title"
|
||||
msgstr "Callback naziv"
|
||||
msgstr "Callback naslov"
|
||||
|
||||
#: frappe/public/js/frappe/file_uploader/FileUploader.vue:150
|
||||
#: frappe/public/js/frappe/ui/capture.js:334
|
||||
|
|
@ -4743,7 +4743,7 @@ msgstr "Očisti filtere"
|
|||
#. Label of the days (Int) field in DocType 'Logs To Clear'
|
||||
#: frappe/core/doctype/logs_to_clear/logs_to_clear.json
|
||||
msgid "Clear Logs After (days)"
|
||||
msgstr "Očisti dnevnike nakon (dana)"
|
||||
msgstr "Očisti evidencije nakon (dana)"
|
||||
|
||||
#: frappe/core/doctype/user_permission/user_permission_list.js:144
|
||||
msgid "Clear User Permissions"
|
||||
|
|
@ -5610,7 +5610,7 @@ msgstr "Sadržaj (Markdown)"
|
|||
#. Label of the content_hash (Data) field in DocType 'File'
|
||||
#: frappe/core/doctype/file/file.json
|
||||
msgid "Content Hash"
|
||||
msgstr "Heš sadržaja"
|
||||
msgstr "Heš sadržaj"
|
||||
|
||||
#. Label of the content_type (Select) field in DocType 'Newsletter'
|
||||
#. Label of the content_type (Select) field in DocType 'Blog Post'
|
||||
|
|
@ -6220,7 +6220,7 @@ msgstr "Prilagođene opcije"
|
|||
#. Label of the custom_overrides (Code) field in DocType 'Website Theme'
|
||||
#: frappe/website/doctype/website_theme/website_theme.json
|
||||
msgid "Custom Overrides"
|
||||
msgstr "Prilagodi izmene"
|
||||
msgstr "Prilagođene izmene"
|
||||
|
||||
#. Option for the 'Report Type' (Select) field in DocType 'Report'
|
||||
#: frappe/core/doctype/report/report.json
|
||||
|
|
@ -6413,7 +6413,7 @@ msgstr "Celodnevno"
|
|||
#. Option for the 'Frequency' (Select) field in DocType 'Scheduled Job Type'
|
||||
#: frappe/core/doctype/scheduled_job_type/scheduled_job_type.json
|
||||
msgid "Daily Maintenance"
|
||||
msgstr ""
|
||||
msgstr "Dnevno održavanje"
|
||||
|
||||
#. Option for the 'Style' (Select) field in DocType 'Workflow State'
|
||||
#: frappe/workflow/doctype/workflow_state/workflow_state.json
|
||||
|
|
@ -7141,7 +7141,7 @@ msgstr "Zavisnosti i licence"
|
|||
#: frappe/custom/doctype/custom_field/custom_field.json
|
||||
#: frappe/custom/doctype/customize_form_field/customize_form_field.json
|
||||
msgid "Depends On"
|
||||
msgstr "Zavisni od"
|
||||
msgstr "Zavisi od"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:32
|
||||
msgid "Descendants Of"
|
||||
|
|
@ -7385,7 +7385,7 @@ msgstr "Onemogući SMTP server autentifikaciju"
|
|||
#. Settings'
|
||||
#: frappe/desk/doctype/list_view_settings/list_view_settings.json
|
||||
msgid "Disable Sidebar Stats"
|
||||
msgstr "Onemogući bočnu traku"
|
||||
msgstr "Onemogući statistiku u bočnoj traci"
|
||||
|
||||
#: frappe/website/doctype/website_settings/website_settings.js:146
|
||||
msgid "Disable Signup for your site"
|
||||
|
|
@ -8755,7 +8755,7 @@ msgstr "Član imejl grupe"
|
|||
#. Label of the email_header (Data) field in DocType 'Notification Log'
|
||||
#: frappe/desk/doctype/notification_log/notification_log.json
|
||||
msgid "Email Header"
|
||||
msgstr ""
|
||||
msgstr "Zaglavlje imejla"
|
||||
|
||||
#. Label of the email_id (Data) field in DocType 'Contact Email'
|
||||
#. Label of the email_id (Data) field in DocType 'User Email'
|
||||
|
|
@ -8845,7 +8845,7 @@ msgstr "Imejl podešavanja"
|
|||
#. Label of the email_signature (Text Editor) field in DocType 'User'
|
||||
#: frappe/core/doctype/user/user.json
|
||||
msgid "Email Signature"
|
||||
msgstr "Imejl potpi"
|
||||
msgstr "Imejl potpis"
|
||||
|
||||
#. Label of the email_status (Select) field in DocType 'Communication'
|
||||
#: frappe/core/doctype/communication/communication.json
|
||||
|
|
@ -9106,7 +9106,7 @@ msgstr "Omogući kreiranje standardnog veb-šablona u razvojnom režimu"
|
|||
#. 'Blog Post'
|
||||
#: frappe/website/doctype/blog_post/blog_post.json
|
||||
msgid "Enable email notification for any comment or likes received on your Blog Post."
|
||||
msgstr "Omogući obaveštenje putem imejla za svaki komentar illi lajk na Vašoj objavi na blogu."
|
||||
msgstr "Omogući obaveštenje putem imejla za svaki komentar ili lajk na Vašoj objavi na blogu."
|
||||
|
||||
#. Description of the 'Modal Trigger' (Check) field in DocType 'Form Tour Step'
|
||||
#: frappe/desk/doctype/form_tour_step/form_tour_step.json
|
||||
|
|
@ -9257,7 +9257,7 @@ msgstr "Energetski poen"
|
|||
#. Label of the enqueued_by (Data) field in DocType 'Submission Queue'
|
||||
#: frappe/core/doctype/submission_queue/submission_queue.json
|
||||
msgid "Enqueued By"
|
||||
msgstr "Stavljeno u redu od strane"
|
||||
msgstr "Stavljeno u red od strane"
|
||||
|
||||
#: frappe/core/doctype/recorder/recorder.py:125
|
||||
msgid "Enqueued creation of indexes"
|
||||
|
|
@ -9508,7 +9508,7 @@ msgstr "Primer: \"boje\": [\"#d1d8dd\", \"#ff5858\"]"
|
|||
#. Label of the exact_copies (Int) field in DocType 'Recorder Query'
|
||||
#: frappe/core/doctype/recorder_query/recorder_query.json
|
||||
msgid "Exact Copies"
|
||||
msgstr "Identične kompije"
|
||||
msgstr "Identične kopije"
|
||||
|
||||
#. Label of the example (HTML) field in DocType 'Workflow Transition'
|
||||
#: frappe/workflow/doctype/workflow_transition/workflow_transition.json
|
||||
|
|
@ -9696,7 +9696,7 @@ msgstr "Izvoz redova koji sadrže grešku"
|
|||
#. Label of the export_from (Data) field in DocType 'Access Log'
|
||||
#: frappe/core/doctype/access_log/access_log.json
|
||||
msgid "Export From"
|
||||
msgstr "Izvoz od"
|
||||
msgstr "Izvoz iz"
|
||||
|
||||
#: frappe/core/doctype/data_import/data_import.js:518
|
||||
msgid "Export Import Log"
|
||||
|
|
@ -9901,7 +9901,7 @@ msgstr "Neuspešno dobijanje informacija o sajtu"
|
|||
|
||||
#: frappe/model/virtual_doctype.py:63
|
||||
msgid "Failed to import virtual doctype {}, is controller file present?"
|
||||
msgstr "Neuspešan pokušaj uvoza virtuelnog doctype {}, da lije fajl kontrolera prisutan?"
|
||||
msgstr "Neuspešan pokušaj uvoza virtuelnog doctype {}, da li je fajl kontrolera prisutan?"
|
||||
|
||||
#: frappe/utils/image.py:75
|
||||
msgid "Failed to optimize image: {0}"
|
||||
|
|
@ -10522,7 +10522,7 @@ msgstr "Prilagodi"
|
|||
#. Label of the flag (Data) field in DocType 'Language'
|
||||
#: frappe/core/doctype/language/language.json
|
||||
msgid "Flag"
|
||||
msgstr "Zastavica"
|
||||
msgstr "Zastava"
|
||||
|
||||
#. Option for the 'Type' (Select) field in DocType 'DocField'
|
||||
#. Option for the 'Fieldtype' (Select) field in DocType 'Report Column'
|
||||
|
|
@ -12186,7 +12186,7 @@ msgstr "Tokom svakog časa"
|
|||
#. Option for the 'Frequency' (Select) field in DocType 'Scheduled Job Type'
|
||||
#: frappe/core/doctype/scheduled_job_type/scheduled_job_type.json
|
||||
msgid "Hourly Maintenance"
|
||||
msgstr ""
|
||||
msgstr "Održavanje na svakih sat vremena"
|
||||
|
||||
#. Description of the 'Password Reset Link Generation Limit' (Int) field in
|
||||
#. DocType 'System Settings'
|
||||
|
|
@ -14221,23 +14221,23 @@ msgstr "Poslednjih 10 aktivnih korisnika"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:627
|
||||
msgid "Last 14 Days"
|
||||
msgstr ""
|
||||
msgstr "Poslednjih 14 dana"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:631
|
||||
msgid "Last 30 Days"
|
||||
msgstr ""
|
||||
msgstr "Poslednjih 30 dana"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:651
|
||||
msgid "Last 6 Months"
|
||||
msgstr ""
|
||||
msgstr "Poslednjih 6 meseci"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:623
|
||||
msgid "Last 7 Days"
|
||||
msgstr ""
|
||||
msgstr "Poslednjih 7 dana"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:635
|
||||
msgid "Last 90 Days"
|
||||
msgstr ""
|
||||
msgstr "Poslednjih 90 dana"
|
||||
|
||||
#. Label of the last_active (Datetime) field in DocType 'User'
|
||||
#: frappe/core/doctype/user/user.json
|
||||
|
|
@ -15187,7 +15187,7 @@ msgstr "MIT licenca"
|
|||
|
||||
#: frappe/desk/page/setup_wizard/install_fixtures.py:48
|
||||
msgid "Madam"
|
||||
msgstr "Gospođo"
|
||||
msgstr "Gospođa"
|
||||
|
||||
#. Label of the main_section (Text Editor) field in DocType 'Web Page'
|
||||
#: frappe/website/doctype/web_page/web_page.json
|
||||
|
|
@ -15863,7 +15863,7 @@ msgstr "Mobilni"
|
|||
#: frappe/tests/test_translate.py:89 frappe/tests/test_translate.py:91
|
||||
#: frappe/tests/test_translate.py:94
|
||||
msgid "Mobile No"
|
||||
msgstr ""
|
||||
msgstr "Broj mobilnog telefona"
|
||||
|
||||
#. Label of the modal_trigger (Check) field in DocType 'Form Tour Step'
|
||||
#: frappe/desk/doctype/form_tour_step/form_tour_step.json
|
||||
|
|
@ -16089,7 +16089,7 @@ msgstr "Više članaka o {0}"
|
|||
#. Settings'
|
||||
#: frappe/website/doctype/about_us_settings/about_us_settings.json
|
||||
msgid "More content for the bottom of the page."
|
||||
msgstr "Više sadržaja za dno stranice."
|
||||
msgstr "Dodatni sadržaj za dno stranice."
|
||||
|
||||
#: frappe/public/js/frappe/ui/sort_selector.js:193
|
||||
msgid "Most Used"
|
||||
|
|
@ -16667,19 +16667,19 @@ msgstr "Sledeće"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:683
|
||||
msgid "Next 14 Days"
|
||||
msgstr ""
|
||||
msgstr "Narednih 14 dana"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:687
|
||||
msgid "Next 30 Days"
|
||||
msgstr ""
|
||||
msgstr "Narednih 30 dana"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:703
|
||||
msgid "Next 6 Months"
|
||||
msgstr ""
|
||||
msgstr "Narednih 6 meseci"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:679
|
||||
msgid "Next 7 Days"
|
||||
msgstr ""
|
||||
msgstr "Narednih 7 dana"
|
||||
|
||||
#. Label of the next_action_email_template (Link) field in DocType 'Workflow
|
||||
#. Document State'
|
||||
|
|
@ -16704,11 +16704,11 @@ msgstr "Naredni korak obilaska obrasca"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:695
|
||||
msgid "Next Month"
|
||||
msgstr ""
|
||||
msgstr "Sledeći mesec"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:699
|
||||
msgid "Next Quarter"
|
||||
msgstr ""
|
||||
msgstr "Sledeći kvartal"
|
||||
|
||||
#. Label of the next_schedule_date (Date) field in DocType 'Auto Repeat'
|
||||
#: frappe/automation/doctype/auto_repeat/auto_repeat.json
|
||||
|
|
@ -16738,11 +16738,11 @@ msgstr "Sledeći token za sinhronizaciju"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:691
|
||||
msgid "Next Week"
|
||||
msgstr ""
|
||||
msgstr "Sledeće nedelje"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:707
|
||||
msgid "Next Year"
|
||||
msgstr ""
|
||||
msgstr "Sledeće godine"
|
||||
|
||||
#: frappe/public/js/frappe/form/workflow.js:45
|
||||
msgid "Next actions"
|
||||
|
|
@ -20369,7 +20369,7 @@ msgstr "U redu stavljen"
|
|||
#. Label of the queued_by (Data) field in DocType 'Prepared Report'
|
||||
#: frappe/core/doctype/prepared_report/prepared_report.json
|
||||
msgid "Queued By"
|
||||
msgstr "U redu od strane"
|
||||
msgstr "Stavljeno u red od strane"
|
||||
|
||||
#: frappe/core/doctype/submission_queue/submission_queue.py:174
|
||||
msgid "Queued for Submission. You can track the progress over {0}."
|
||||
|
|
@ -22110,7 +22110,7 @@ msgstr "Indeks reda"
|
|||
#. Label of the row_indexes (Code) field in DocType 'Data Import Log'
|
||||
#: frappe/core/doctype/data_import_log/data_import_log.json
|
||||
msgid "Row Indexes"
|
||||
msgstr "Indeksi redova"
|
||||
msgstr "Indeksi reda"
|
||||
|
||||
#. Label of the row_name (Data) field in DocType 'Property Setter'
|
||||
#: frappe/custom/doctype/property_setter/property_setter.json
|
||||
|
|
@ -23525,7 +23525,7 @@ msgstr "Funkcionalnost serverskih skripti nije dostupna na ovom sajtu."
|
|||
|
||||
#: frappe/public/js/frappe/request.js:254
|
||||
msgid "Server failed to process this request because of a concurrent conflicting request. Please try again."
|
||||
msgstr ""
|
||||
msgstr "Server nije uspeo da obradi zahtev zbog istovremenog konfliktnog zahteva. Molimo Vas da pokušate ponovo."
|
||||
|
||||
#: frappe/public/js/frappe/request.js:246
|
||||
msgid "Server was too busy to process this request. Please try again."
|
||||
|
|
@ -25382,7 +25382,7 @@ msgstr "Simbol"
|
|||
#: frappe/integrations/doctype/google_calendar/google_calendar.json
|
||||
#: frappe/integrations/doctype/google_contacts/google_contacts.json
|
||||
msgid "Sync"
|
||||
msgstr "SInhronizuj"
|
||||
msgstr "Sinhronizuj"
|
||||
|
||||
#: frappe/integrations/doctype/google_calendar/google_calendar.js:28
|
||||
msgid "Sync Calendar"
|
||||
|
|
@ -25648,7 +25648,7 @@ msgstr "Neophodno se privilegije sistem menadžera."
|
|||
#. Option for the 'Channel' (Select) field in DocType 'Notification'
|
||||
#: frappe/email/doctype/notification/notification.json
|
||||
msgid "System Notification"
|
||||
msgstr "Sistemsko obaveštenja"
|
||||
msgstr "Sistemsko obaveštenje"
|
||||
|
||||
#. Label of the system_page (Check) field in DocType 'Page'
|
||||
#: frappe/core/doctype/page/page.json
|
||||
|
|
@ -26060,7 +26060,7 @@ msgstr "Dokument je dodeljen korisniku {0}"
|
|||
#: frappe/desk/doctype/dashboard_chart/dashboard_chart.json
|
||||
#: frappe/desk/doctype/number_card/number_card.json
|
||||
msgid "The document type selected is a child table, so the parent document type is required."
|
||||
msgstr "Izabrana vrsta dokumenta je podtabela, stoga je potrebna matična vrsta dokumenta."
|
||||
msgstr "Izabrana vrsta dokumenta je zavisna tabela, stoga je potrebna matična vrsta dokumenta."
|
||||
|
||||
#: frappe/core/doctype/user_type/user_type.py:110
|
||||
msgid "The field {0} is mandatory"
|
||||
|
|
@ -26317,19 +26317,19 @@ msgstr "Ova Kanban tabla će biti privatna"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:665
|
||||
msgid "This Month"
|
||||
msgstr ""
|
||||
msgstr "Ovaj mesec"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:669
|
||||
msgid "This Quarter"
|
||||
msgstr ""
|
||||
msgstr "Ovaj kvartal"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:661
|
||||
msgid "This Week"
|
||||
msgstr ""
|
||||
msgstr "Ove nedelje"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:673
|
||||
msgid "This Year"
|
||||
msgstr ""
|
||||
msgstr "Ove godine"
|
||||
|
||||
#: frappe/custom/doctype/customize_form/customize_form.js:220
|
||||
msgid "This action is irreversible. Do you wish to continue?"
|
||||
|
|
@ -26663,7 +26663,7 @@ msgstr "Vremenska zona"
|
|||
#. Label of the time_zones (Text) field in DocType 'Country'
|
||||
#: frappe/geo/doctype/country/country.json
|
||||
msgid "Time Zones"
|
||||
msgstr "Vremenske zona"
|
||||
msgstr "Vremenske zone"
|
||||
|
||||
#. Label of the time_format (Data) field in DocType 'Country'
|
||||
#: frappe/geo/doctype/country/country.json
|
||||
|
|
@ -26926,7 +26926,7 @@ msgstr "Da biste izvršili izvoz ovog koraka kao JSON, povežite ga u dokumentu
|
|||
|
||||
#: frappe/email/doctype/email_account/email_account.js:126
|
||||
msgid "To generate password click {0}"
|
||||
msgstr ""
|
||||
msgstr "Za generisanje lozinke kliknite {0}"
|
||||
|
||||
#: frappe/public/js/frappe/views/reports/query_report.js:857
|
||||
msgid "To get the updated report, click on {0}."
|
||||
|
|
@ -26934,7 +26934,7 @@ msgstr "Za ažurirani izveštaj kliknite na {0}."
|
|||
|
||||
#: frappe/email/doctype/email_account/email_account.js:139
|
||||
msgid "To know more click {0}"
|
||||
msgstr ""
|
||||
msgstr "Za više informacija kliknite {0}"
|
||||
|
||||
#. Description of the 'Console' (Code) field in DocType 'System Console'
|
||||
#: frappe/desk/doctype/system_console/system_console.json
|
||||
|
|
@ -27044,7 +27044,7 @@ msgstr "Token nedostaje"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:738
|
||||
msgid "Tomorrow"
|
||||
msgstr ""
|
||||
msgstr "Sutra"
|
||||
|
||||
#: frappe/desk/doctype/bulk_update/bulk_update.py:68
|
||||
#: frappe/model/workflow.py:254
|
||||
|
|
@ -27110,7 +27110,7 @@ msgstr "Najčešće greške"
|
|||
#: frappe/printing/doctype/print_format/print_format.json
|
||||
#: frappe/public/js/print_format_builder/PrintFormatControls.vue:244
|
||||
msgid "Top Left"
|
||||
msgstr "Gore desno"
|
||||
msgstr "Gore levo"
|
||||
|
||||
#. Option for the 'Position' (Select) field in DocType 'Form Tour Step'
|
||||
#. Option for the 'Page Number' (Select) field in DocType 'Print Format'
|
||||
|
|
@ -27643,7 +27643,7 @@ msgstr "Ukloni dodeljivanje uslova"
|
|||
|
||||
#: frappe/app.py:383
|
||||
msgid "Uncaught Exception"
|
||||
msgstr "Neočekivani izuzetak"
|
||||
msgstr "Neuhvaćeni izuzetak"
|
||||
|
||||
#: frappe/public/js/frappe/form/toolbar.js:103
|
||||
msgid "Unchanged"
|
||||
|
|
@ -27973,7 +27973,7 @@ msgstr "Otpremanje na Google Drive"
|
|||
#: frappe/desk/doctype/onboarding_step/onboarding_step.json
|
||||
#, python-format
|
||||
msgid "Use % for any non empty value."
|
||||
msgstr "Koristite % fza bilo koju vrednost koja nije prazna."
|
||||
msgstr "Koristite % za bilo koju vrednost koja nije prazna."
|
||||
|
||||
#. Label of the ascii_encode_password (Check) field in DocType 'Email Account'
|
||||
#: frappe/email/doctype/email_account/email_account.json
|
||||
|
|
@ -28802,7 +28802,7 @@ msgstr "Prikaži {0}"
|
|||
#. Label of the viewed_by (Data) field in DocType 'View Log'
|
||||
#: frappe/core/doctype/view_log/view_log.json
|
||||
msgid "Viewed By"
|
||||
msgstr "Pogledano od strane"
|
||||
msgstr "Uvid od strane"
|
||||
|
||||
#. Group in DocType's connections
|
||||
#. Label of a Card Break in the Build Workspace
|
||||
|
|
@ -29706,7 +29706,7 @@ msgstr "Da"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:726
|
||||
msgid "Yesterday"
|
||||
msgstr ""
|
||||
msgstr "Juče"
|
||||
|
||||
#: frappe/public/js/frappe/utils/user.js:33
|
||||
msgctxt "Name of the current user. For example: You edited this 5 hours ago."
|
||||
|
|
@ -30646,7 +30646,7 @@ msgstr "nonce"
|
|||
#. Label of the notified (Check) field in DocType 'Reminder'
|
||||
#: frappe/automation/doctype/reminder/reminder.json
|
||||
msgid "notified"
|
||||
msgstr "obvešten"
|
||||
msgstr "obavešten"
|
||||
|
||||
#: frappe/public/js/frappe/utils/pretty_date.js:25
|
||||
msgid "now"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: developers@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-05-18 09:33+0000\n"
|
||||
"PO-Revision-Date: 2025-05-19 07:02\n"
|
||||
"PO-Revision-Date: 2025-05-26 10:24\n"
|
||||
"Last-Translator: developers@frappe.io\n"
|
||||
"Language-Team: Swedish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -8299,12 +8299,12 @@ msgstr "Rullgardin Meny"
|
|||
#. Label of the date (Date) field in DocType 'ToDo'
|
||||
#: frappe/desk/doctype/todo/todo.json
|
||||
msgid "Due Date"
|
||||
msgstr "Förfallodatum"
|
||||
msgstr "Förfallo Datum"
|
||||
|
||||
#. Label of the due_date_based_on (Select) field in DocType 'Assignment Rule'
|
||||
#: frappe/automation/doctype/assignment_rule/assignment_rule.json
|
||||
msgid "Due Date Based On"
|
||||
msgstr "Förfallodatum Baserad På"
|
||||
msgstr "Förfallo Datum Baserad På"
|
||||
|
||||
#: frappe/public/js/frappe/form/grid_row_form.js:42
|
||||
#: frappe/public/js/frappe/form/toolbar.js:419
|
||||
|
|
@ -9631,7 +9631,7 @@ msgstr "Förfallo Avisering Aktiverad"
|
|||
#. Option for the 'Delivery Status' (Select) field in DocType 'Communication'
|
||||
#: frappe/core/doctype/communication/communication.json
|
||||
msgid "Expired"
|
||||
msgstr "Utgången"
|
||||
msgstr "Utgått"
|
||||
|
||||
#. Label of the expires_in (Int) field in DocType 'OAuth Bearer Token'
|
||||
#. Label of the expires_in (Int) field in DocType 'Token Cache'
|
||||
|
|
@ -18262,7 +18262,7 @@ msgstr "Outlook.com"
|
|||
#: frappe/desk/doctype/system_console/system_console.json
|
||||
#: frappe/integrations/doctype/integration_request/integration_request.json
|
||||
msgid "Output"
|
||||
msgstr "Utgång"
|
||||
msgstr "Utdata"
|
||||
|
||||
#: frappe/public/js/frappe/form/templates/form_dashboard.html:5
|
||||
msgid "Overview"
|
||||
|
|
@ -30299,7 +30299,7 @@ msgstr "Roll "
|
|||
#. Label of the profile (Code) field in DocType 'Recorder'
|
||||
#: frappe/core/doctype/recorder/recorder.json
|
||||
msgid "cProfile Output"
|
||||
msgstr "cProfil Utgång"
|
||||
msgstr "cProfil Utdata"
|
||||
|
||||
#: frappe/public/js/frappe/ui/toolbar/search_utils.js:286
|
||||
msgid "calendar"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: developers@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-05-18 09:33+0000\n"
|
||||
"PO-Revision-Date: 2025-05-19 07:02\n"
|
||||
"PO-Revision-Date: 2025-05-25 10:26\n"
|
||||
"Last-Translator: developers@frappe.io\n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -5169,7 +5169,7 @@ msgstr "每小时评论限制"
|
|||
|
||||
#: frappe/desk/form/utils.py:75
|
||||
msgid "Comment publicity can only be updated by the original author or a System Manager."
|
||||
msgstr ""
|
||||
msgstr "评论公开状态仅可由原作者或系统管理员修改。"
|
||||
|
||||
#: frappe/model/meta.py:57 frappe/public/js/frappe/form/controls/comment.js:9
|
||||
#: frappe/public/js/frappe/model/meta.js:209
|
||||
|
|
@ -6413,7 +6413,7 @@ msgstr "每日长格式"
|
|||
#. Option for the 'Frequency' (Select) field in DocType 'Scheduled Job Type'
|
||||
#: frappe/core/doctype/scheduled_job_type/scheduled_job_type.json
|
||||
msgid "Daily Maintenance"
|
||||
msgstr ""
|
||||
msgstr "日常维护"
|
||||
|
||||
#. Option for the 'Style' (Select) field in DocType 'Workflow State'
|
||||
#: frappe/workflow/doctype/workflow_state/workflow_state.json
|
||||
|
|
@ -8755,7 +8755,7 @@ msgstr "电子邮件组成员"
|
|||
#. Label of the email_header (Data) field in DocType 'Notification Log'
|
||||
#: frappe/desk/doctype/notification_log/notification_log.json
|
||||
msgid "Email Header"
|
||||
msgstr ""
|
||||
msgstr "邮件标头"
|
||||
|
||||
#. Label of the email_id (Data) field in DocType 'Contact Email'
|
||||
#. Label of the email_id (Data) field in DocType 'User Email'
|
||||
|
|
@ -8905,7 +8905,7 @@ msgstr "未通过{0}验证的电子邮件"
|
|||
|
||||
#: frappe/email/doctype/email_queue/email_queue.js:19
|
||||
msgid "Email queue is currently suspended. Resume to automatically send other emails."
|
||||
msgstr ""
|
||||
msgstr "邮件队列已暂停。恢复后系统将自动发送其他邮件。"
|
||||
|
||||
#. Label of the section_break_udjs (Section Break) field in DocType 'System
|
||||
#. Health Report'
|
||||
|
|
@ -12186,7 +12186,7 @@ msgstr "每小时长格式"
|
|||
#. Option for the 'Frequency' (Select) field in DocType 'Scheduled Job Type'
|
||||
#: frappe/core/doctype/scheduled_job_type/scheduled_job_type.json
|
||||
msgid "Hourly Maintenance"
|
||||
msgstr ""
|
||||
msgstr "按小时维护"
|
||||
|
||||
#. Description of the 'Password Reset Link Generation Limit' (Int) field in
|
||||
#. DocType 'System Settings'
|
||||
|
|
@ -14221,11 +14221,11 @@ msgstr "最近10个活跃用户"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:627
|
||||
msgid "Last 14 Days"
|
||||
msgstr ""
|
||||
msgstr "过去14天"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:631
|
||||
msgid "Last 30 Days"
|
||||
msgstr ""
|
||||
msgstr "过去30天"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:651
|
||||
msgid "Last 6 Months"
|
||||
|
|
@ -14233,11 +14233,11 @@ msgstr "过去6个月"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:623
|
||||
msgid "Last 7 Days"
|
||||
msgstr ""
|
||||
msgstr "过去7天"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:635
|
||||
msgid "Last 90 Days"
|
||||
msgstr ""
|
||||
msgstr "过去90天"
|
||||
|
||||
#. Label of the last_active (Datetime) field in DocType 'User'
|
||||
#: frappe/core/doctype/user/user.json
|
||||
|
|
@ -16667,11 +16667,11 @@ msgstr "下一步"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:683
|
||||
msgid "Next 14 Days"
|
||||
msgstr ""
|
||||
msgstr "未来 14 天"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:687
|
||||
msgid "Next 30 Days"
|
||||
msgstr ""
|
||||
msgstr "未来30天"
|
||||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:703
|
||||
msgid "Next 6 Months"
|
||||
|
|
@ -16679,7 +16679,7 @@ msgstr "未来6个月"
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:679
|
||||
msgid "Next 7 Days"
|
||||
msgstr ""
|
||||
msgstr "未来 7 天"
|
||||
|
||||
#. Label of the next_action_email_template (Link) field in DocType 'Workflow
|
||||
#. Document State'
|
||||
|
|
@ -18580,7 +18580,7 @@ msgstr "父项是数据将被添加到的文档名称"
|
|||
|
||||
#: frappe/public/js/frappe/ui/group_by/group_by.js:251
|
||||
msgid "Parent-to-child or child-to-parent grouping is not allowed."
|
||||
msgstr ""
|
||||
msgstr "禁止父子层级互相嵌套的分组方式。"
|
||||
|
||||
#: frappe/permissions.py:798
|
||||
msgid "Parentfield not specified in {0}: {1}"
|
||||
|
|
@ -23525,7 +23525,7 @@ msgstr "此站点未启用服务器脚本功能"
|
|||
|
||||
#: frappe/public/js/frappe/request.js:254
|
||||
msgid "Server failed to process this request because of a concurrent conflicting request. Please try again."
|
||||
msgstr ""
|
||||
msgstr "因并发请求冲突,服务器未能处理本请求。请稍后重试。"
|
||||
|
||||
#: frappe/public/js/frappe/request.js:246
|
||||
msgid "Server was too busy to process this request. Please try again."
|
||||
|
|
@ -26414,7 +26414,7 @@ msgstr "该文件已关联至受保护文档,不可删除。"
|
|||
|
||||
#: frappe/public/js/frappe/file_uploader/FilePreview.vue:76
|
||||
msgid "This file is public and can be accessed by anyone, even without logging in. Mark it private to limit access."
|
||||
msgstr ""
|
||||
msgstr "本文件为公开文件,无需登录即可访问。请设为私有以限制访问权限。"
|
||||
|
||||
#: frappe/core/doctype/file/file.js:20
|
||||
msgid "This file is public. It can be accessed without authentication."
|
||||
|
|
@ -26926,7 +26926,7 @@ msgstr "导出此步骤为JSON需关联到入职文档并保存"
|
|||
|
||||
#: frappe/email/doctype/email_account/email_account.js:126
|
||||
msgid "To generate password click {0}"
|
||||
msgstr ""
|
||||
msgstr "生成密码请点击{0}"
|
||||
|
||||
#: frappe/public/js/frappe/views/reports/query_report.js:857
|
||||
msgid "To get the updated report, click on {0}."
|
||||
|
|
@ -26934,7 +26934,7 @@ msgstr "获取更新后的报表请点击{0}"
|
|||
|
||||
#: frappe/email/doctype/email_account/email_account.js:139
|
||||
msgid "To know more click {0}"
|
||||
msgstr ""
|
||||
msgstr "了解更多请点击{0}"
|
||||
|
||||
#. Description of the 'Console' (Code) field in DocType 'System Console'
|
||||
#: frappe/desk/doctype/system_console/system_console.json
|
||||
|
|
@ -28831,7 +28831,7 @@ msgstr "可见性"
|
|||
|
||||
#: frappe/public/js/frappe/form/templates/timeline_message_box.html:40
|
||||
msgid "Visible to website/portal users."
|
||||
msgstr ""
|
||||
msgstr "对网站/门户用户可见。"
|
||||
|
||||
#. Option for the 'Type' (Select) field in DocType 'Communication'
|
||||
#: frappe/core/doctype/communication/communication.json
|
||||
|
|
@ -29578,11 +29578,11 @@ msgstr "工作区"
|
|||
|
||||
#: frappe/public/js/frappe/form/footer/form_timeline.js:731
|
||||
msgid "Would you like to publish this comment? This means it will become visible to website/portal users."
|
||||
msgstr ""
|
||||
msgstr "是否确认发布本评论?发布后网站/门户用户可见。"
|
||||
|
||||
#: frappe/public/js/frappe/form/footer/form_timeline.js:735
|
||||
msgid "Would you like to unpublish this comment? This means it will no longer be visible to website/portal users."
|
||||
msgstr ""
|
||||
msgstr "是否确认取消发布本评论?取消后网站/门户用户将不可见。"
|
||||
|
||||
#: frappe/desk/page/setup_wizard/setup_wizard.py:35
|
||||
msgid "Wrapping up"
|
||||
|
|
|
|||
|
|
@ -825,6 +825,8 @@ class BaseDocument:
|
|||
return True
|
||||
elif df.fieldtype == "Code" and df.options == "HTML" and has_text_or_img_tag:
|
||||
return True
|
||||
elif df.fieldtype == "Check":
|
||||
return True # Checkboxes can't be mandatory, they're 0 by default
|
||||
else:
|
||||
return has_text_content
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: MIT. See LICENSE
|
||||
import hashlib
|
||||
import itertools
|
||||
import json
|
||||
import time
|
||||
from collections.abc import Generator, Iterable
|
||||
|
|
@ -1320,7 +1321,8 @@ class Document(BaseDocument, DocRef):
|
|||
elif self._action == "update_after_submit":
|
||||
self.run_method("on_update_after_submit")
|
||||
|
||||
self.clear_cache()
|
||||
if not (frappe.flags.in_import and self.is_new()):
|
||||
self.clear_cache()
|
||||
|
||||
if self.flags.get("notify_update", True):
|
||||
self.notify_update()
|
||||
|
|
@ -1350,7 +1352,12 @@ class Document(BaseDocument, DocRef):
|
|||
|
||||
def notify_update(self):
|
||||
"""Publish realtime that the current document is modified"""
|
||||
if frappe.flags.in_patch:
|
||||
if (
|
||||
frappe.flags.in_import
|
||||
or frappe.flags.in_patch
|
||||
or frappe.flags.in_migrate
|
||||
or frappe.flags.in_install
|
||||
):
|
||||
return
|
||||
|
||||
frappe.publish_realtime(
|
||||
|
|
@ -1456,14 +1463,13 @@ class Document(BaseDocument, DocRef):
|
|||
doc_to_compare = frappe.get_doc(self.doctype, amended_from)
|
||||
|
||||
version = frappe.new_doc("Version")
|
||||
|
||||
if not doc_to_compare and not self.flags.updater_reference:
|
||||
return
|
||||
|
||||
if version.update_version_info(doc_to_compare, self):
|
||||
version.insert(ignore_permissions=True)
|
||||
|
||||
if not frappe.flags.in_migrate:
|
||||
# follow since you made a change?
|
||||
if frappe.get_cached_value("User", frappe.session.user, "follow_created_documents"):
|
||||
follow_document(self.doctype, self.name, frappe.session.user)
|
||||
|
||||
@staticmethod
|
||||
def hook(f):
|
||||
"""Decorator: Make method `hookable` (i.e. extensible by another app).
|
||||
|
|
@ -1871,7 +1877,8 @@ def bulk_insert(
|
|||
doctype: str,
|
||||
documents: Iterable["Document"],
|
||||
ignore_duplicates: bool = False,
|
||||
chunk_size=10_000,
|
||||
chunk_size=1000,
|
||||
commit_chunks=False,
|
||||
):
|
||||
"""Insert simple Documents objects to database in bulk.
|
||||
|
||||
|
|
@ -1882,31 +1889,37 @@ def bulk_insert(
|
|||
"""
|
||||
|
||||
doctype_meta = frappe.get_meta(doctype)
|
||||
documents = list(documents)
|
||||
|
||||
valid_column_map = {
|
||||
doctype: doctype_meta.get_valid_columns(),
|
||||
}
|
||||
values_map = {
|
||||
doctype: _document_values_generator(documents, valid_column_map[doctype]),
|
||||
}
|
||||
|
||||
for child_table in doctype_meta.get_table_fields():
|
||||
child_table_fields = doctype_meta.get_table_fields()
|
||||
for child_table in child_table_fields:
|
||||
valid_column_map[child_table.options] = frappe.get_meta(child_table.options).get_valid_columns()
|
||||
values_map[child_table.options] = _document_values_generator(
|
||||
[
|
||||
ch_doc
|
||||
for ch_doc in (
|
||||
child_docs for doc in documents for child_docs in doc.get(child_table.fieldname)
|
||||
)
|
||||
],
|
||||
valid_column_map[child_table.options],
|
||||
)
|
||||
|
||||
for dt, docs in values_map.items():
|
||||
frappe.db.bulk_insert(
|
||||
dt, valid_column_map[dt], docs, ignore_duplicates=ignore_duplicates, chunk_size=chunk_size
|
||||
)
|
||||
documents = iter(documents)
|
||||
while document_batch := list(itertools.islice(documents, chunk_size)):
|
||||
values_map = {
|
||||
doctype: _document_values_generator(document_batch, valid_column_map[doctype]),
|
||||
}
|
||||
|
||||
for child_table in child_table_fields:
|
||||
values_map[child_table.options] = _document_values_generator(
|
||||
[
|
||||
ch_doc
|
||||
for ch_doc in (
|
||||
child_docs for doc in document_batch for child_docs in doc.get(child_table.fieldname)
|
||||
)
|
||||
],
|
||||
valid_column_map[child_table.options],
|
||||
)
|
||||
|
||||
for dt, docs in values_map.items():
|
||||
frappe.db.bulk_insert(dt, valid_column_map[dt], docs, ignore_duplicates=ignore_duplicates)
|
||||
|
||||
if commit_chunks:
|
||||
frappe.db.commit()
|
||||
|
||||
|
||||
def _document_values_generator(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
# License: MIT. See LICENSE
|
||||
|
||||
from collections import defaultdict
|
||||
from random import random
|
||||
|
||||
import frappe
|
||||
|
||||
|
|
@ -29,10 +30,13 @@ ignore_doctypes = {
|
|||
}
|
||||
|
||||
|
||||
LINK_COUNT_BUFFER_SIZE = 256
|
||||
|
||||
|
||||
def notify_link_count(doctype, name):
|
||||
"""updates link count for given document"""
|
||||
|
||||
if doctype in ignore_doctypes or not frappe.request:
|
||||
if doctype in ignore_doctypes or not frappe.request or random() < 0.9: # Sample 10%
|
||||
return
|
||||
|
||||
if not hasattr(frappe.local, "_link_count"):
|
||||
|
|
@ -50,13 +54,18 @@ def flush_local_link_count():
|
|||
|
||||
link_count = frappe.cache.get_value("_link_count") or {}
|
||||
|
||||
flush = False
|
||||
for key, value in new_links.items():
|
||||
if key in link_count:
|
||||
link_count[key] += value
|
||||
else:
|
||||
elif len(link_count) < LINK_COUNT_BUFFER_SIZE:
|
||||
link_count[key] = value
|
||||
else:
|
||||
continue
|
||||
flush = True
|
||||
|
||||
frappe.cache.set_value("_link_count", link_count)
|
||||
if flush:
|
||||
frappe.cache.set_value("_link_count", link_count)
|
||||
new_links.clear()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ frappe.ui.form.ControlCode = class ControlCode extends frappe.ui.form.ControlTex
|
|||
style="position: absolute; top: 32px; right: 5px;"
|
||||
onmouseover="this.classList.add('btn-default')"
|
||||
onmouseout="this.classList.remove('btn-default')"
|
||||
title="${__("Copy to Clipboard")}"
|
||||
>
|
||||
<svg class="es-icon es-line icon-sm" style="" aria-hidden="true">
|
||||
<use class="" href="#es-line-copy-light"></use>
|
||||
|
|
@ -241,6 +242,10 @@ frappe.ui.form.ControlCode = class ControlCode extends frappe.ui.form.ControlTex
|
|||
return this.editor ? this.editor.session.getValue() : "";
|
||||
}
|
||||
|
||||
set_focus() {
|
||||
this.editor?.focus();
|
||||
}
|
||||
|
||||
load_lib() {
|
||||
if (this.library_loaded) return this.library_loaded;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import Quill from "quill";
|
||||
import ImageResize from "quill-image-resize";
|
||||
import ImageResize from "frappe-quill-image-resize";
|
||||
import MagicUrl from "quill-magic-url";
|
||||
|
||||
Quill.register("modules/imageResize", ImageResize);
|
||||
|
|
@ -7,6 +7,14 @@ Quill.register("modules/magicUrl", MagicUrl);
|
|||
const CodeBlockContainer = Quill.import("formats/code-block-container");
|
||||
CodeBlockContainer.tagName = "PRE";
|
||||
Quill.register(CodeBlockContainer, true);
|
||||
const Embed = Quill.import("blots/embed");
|
||||
const Delta = Quill.import("delta");
|
||||
|
||||
class BreakBlot extends Embed {}
|
||||
BreakBlot.blotName = "Break";
|
||||
BreakBlot.tagName = "br";
|
||||
|
||||
Quill.register(BreakBlot);
|
||||
|
||||
// font size
|
||||
let font_sizes = [
|
||||
|
|
@ -146,6 +154,7 @@ frappe.ui.form.ControlTextEditor = class ControlTextEditor extends frappe.ui.for
|
|||
const toolbar = this.quill.getModule("toolbar");
|
||||
toolbar.addHandler("table", this.handle_table_actions);
|
||||
}
|
||||
|
||||
handle_table_actions(value) {
|
||||
const table = this.quill.getModule("table");
|
||||
|
||||
|
|
@ -219,6 +228,9 @@ frappe.ui.form.ControlTextEditor = class ControlTextEditor extends frappe.ui.for
|
|||
imageResize: {},
|
||||
magicUrl: true,
|
||||
mention: this.get_mention_options(),
|
||||
keyboard: {
|
||||
bindings: this.get_keyboard_bindings(),
|
||||
},
|
||||
},
|
||||
theme: this.df.theme || "snow",
|
||||
readOnly: this.disabled,
|
||||
|
|
@ -375,4 +387,35 @@ frappe.ui.form.ControlTextEditor = class ControlTextEditor extends frappe.ui.for
|
|||
set_focus() {
|
||||
this.quill.focus();
|
||||
}
|
||||
|
||||
get_keyboard_bindings() {
|
||||
let bindings = {
|
||||
"table enter": {
|
||||
key: "Enter",
|
||||
formats: ["table"],
|
||||
handler: function (range) {
|
||||
this.quill.updateContents(
|
||||
new Delta()
|
||||
.retain(range.index)
|
||||
.delete(range.length)
|
||||
.insert({ Break: true })
|
||||
);
|
||||
|
||||
if (!this.quill.getLeaf(range.index + 1)[0].next) {
|
||||
this.quill.updateContents(
|
||||
new Delta()
|
||||
.retain(range.index + 1)
|
||||
.delete(0)
|
||||
.insert({ Break: true }),
|
||||
"user"
|
||||
);
|
||||
}
|
||||
|
||||
this.quill.setSelection(range.index + 1, Quill.sources.SILENT);
|
||||
return false; // dont call other handlers
|
||||
},
|
||||
},
|
||||
};
|
||||
return bindings;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -87,6 +87,10 @@ export default class Grid {
|
|||
data-action="delete_rows">
|
||||
${__("Delete")}
|
||||
</button>
|
||||
<button type="button" class="btn btn-xs btn-secondary grid-remove-rows hidden"
|
||||
data-action="duplicate_rows">
|
||||
${__("Duplicate Row")}
|
||||
</button>
|
||||
<button type="button" class="btn btn-xs btn-danger grid-remove-all-rows hidden"
|
||||
data-action="delete_all_rows">
|
||||
${__("Delete All")}
|
||||
|
|
@ -234,6 +238,14 @@ export default class Grid {
|
|||
}
|
||||
}
|
||||
|
||||
duplicate_rows() {
|
||||
let selected_children = this.get_selected_children();
|
||||
selected_children.forEach((doc) => {
|
||||
this.add_new_row(null, null, false, doc, false);
|
||||
this.check_range(doc.name, doc.name, false);
|
||||
});
|
||||
}
|
||||
|
||||
delete_rows() {
|
||||
var dirty = false;
|
||||
|
||||
|
|
|
|||
157
frappe/public/js/frappe/ui/dropdown_console.js
Normal file
157
frappe/public/js/frappe/ui/dropdown_console.js
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
export class DropdownConsole {
|
||||
constructor() {
|
||||
this.dialog = new frappe.ui.Dialog({
|
||||
title: __("System Console"),
|
||||
minimizable: true,
|
||||
static: true,
|
||||
no_cancel_flag: true, // hack: global escape handler kills the dialog
|
||||
size: "large",
|
||||
fields: [
|
||||
{
|
||||
description: `
|
||||
${frappe.utils.icon("solid-warning", "xs")}
|
||||
WARNING: Executing random untested code here is dangerous, use with extreme caution. <br>
|
||||
Usage: To execute press ctrl/cmd+enter.
|
||||
To minimize this window press Escape.
|
||||
Press shift+t to bring the window back.
|
||||
`,
|
||||
fieldname: "console",
|
||||
fieldtype: "Code",
|
||||
label: "Console",
|
||||
options: "Python",
|
||||
min_lines: 20,
|
||||
max_lines: 20,
|
||||
wrap: true,
|
||||
},
|
||||
{
|
||||
fieldname: "output",
|
||||
fieldtype: "Code",
|
||||
label: "Output",
|
||||
read_only: 1,
|
||||
},
|
||||
],
|
||||
});
|
||||
this.dialog.get_close_btn().show(); // framework hides it on static dialogs
|
||||
this.editor = null;
|
||||
|
||||
let me = this;
|
||||
this.dialog.$wrapper.on("keydown", function (e) {
|
||||
if (e.key === "Escape") {
|
||||
e.preventDefault();
|
||||
if (!me.dialog.is_minimized) {
|
||||
me.dialog.toggle_minimize();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sleep(duration) {
|
||||
return new Promise((r) => setTimeout(r, duration));
|
||||
}
|
||||
|
||||
async wait_for_ace() {
|
||||
// I can't find any other way to ensure that ace is loaded and ready
|
||||
// This small delay shouldn't be noticable.
|
||||
let retry_count = 0;
|
||||
|
||||
while (retry_count++ < 10 && !this.editor) {
|
||||
await this.sleep(25);
|
||||
this.editor = this.dialog.get_field("console").editor;
|
||||
}
|
||||
|
||||
if (!this.editor) {
|
||||
throw Error("Code editor not found");
|
||||
}
|
||||
}
|
||||
|
||||
async show() {
|
||||
this.dialog.show();
|
||||
await this.wait_for_ace();
|
||||
this.bind_executer();
|
||||
this.load_completions();
|
||||
this.load_contextual_boilerplate();
|
||||
}
|
||||
|
||||
async load_contextual_boilerplate() {
|
||||
if (cur_frm && !cur_frm.is_new()) {
|
||||
let current_code = this.dialog.get_value("console");
|
||||
if (!current_code) {
|
||||
this.dialog
|
||||
.get_field("console")
|
||||
.editor?.insert(
|
||||
`doc = frappe.get_doc("${cur_frm.doc.doctype}", "${cur_frm.doc.name}")\n`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async bind_executer() {
|
||||
let me = this;
|
||||
const field = this.dialog.get_field("console");
|
||||
let editor = field.editor;
|
||||
editor.setKeyboardHandler(null); // sorry emacs/vim users
|
||||
editor.commands.addCommand({
|
||||
name: "execute_code",
|
||||
bindKey: {
|
||||
// Shortcut keys
|
||||
win: "Ctrl-Enter",
|
||||
mac: "Command-Enter",
|
||||
},
|
||||
exec: function (editor) {
|
||||
me.execute_code();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async execute_code() {
|
||||
await this.sleep(50); // ace often takes time to push changes
|
||||
this.dialog.set_value("output", "");
|
||||
const output_field = this.dialog.get_field("output");
|
||||
output_field.set_description("");
|
||||
const start = frappe.datetime.now_datetime(true);
|
||||
let { output } = await frappe.xcall(
|
||||
"frappe.desk.doctype.system_console.system_console.execute_code",
|
||||
{
|
||||
doc: {
|
||||
console: this.dialog.get_value("console"),
|
||||
doctype: "System Console",
|
||||
type: "Python",
|
||||
},
|
||||
},
|
||||
"POST",
|
||||
{
|
||||
freeze: true,
|
||||
freeze_message: __("Executing Code"),
|
||||
}
|
||||
);
|
||||
const end = frappe.datetime.now_datetime(true);
|
||||
this.dialog.set_value("output", output);
|
||||
const time_taken = moment(end).diff(start, "milliseconds");
|
||||
output_field.set_description(`Executed in ${time_taken} milliseconds.
|
||||
<a target="_blank" href="/app/console-log?owner=${frappe.session.user}" >View Logs</a>`);
|
||||
}
|
||||
|
||||
async load_completions() {
|
||||
let me = this;
|
||||
let items = await frappe.xcall(
|
||||
"frappe.core.doctype.server_script.server_script.get_autocompletion_items",
|
||||
null,
|
||||
"GET",
|
||||
{ cache: true }
|
||||
);
|
||||
const field = me.dialog.get_field("console");
|
||||
const custom_completions = [];
|
||||
if (cur_frm && !cur_frm.is_new()) {
|
||||
frappe.meta
|
||||
.get_fieldnames(cur_frm.doc.doctype, cur_frm.doc.parent, {
|
||||
fieldtype: ["not in", frappe.model.no_value_type],
|
||||
})
|
||||
.forEach((fieldname) => {
|
||||
custom_completions.push(`doc.${fieldname}`);
|
||||
});
|
||||
}
|
||||
|
||||
field.df.autocompletions = [...items, ...custom_completions];
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ frappe.ui.Filter = class {
|
|||
Date: ["like", "not like"],
|
||||
Datetime: ["like", "not like", "in", "not in", "=", "!="],
|
||||
Data: ["Between", "Timespan"],
|
||||
Time: ["Between", "Timespan"],
|
||||
Select: ["like", "not like", "Between", "Timespan"],
|
||||
Link: ["Between", "Timespan", ">", "<", ">=", "<="],
|
||||
Currency: ["Between", "Timespan"],
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import "./alt_keyboard_shortcuts";
|
||||
import { DropdownConsole } from "./dropdown_console";
|
||||
|
||||
frappe.provide("frappe.ui.keys.handlers");
|
||||
|
||||
|
|
@ -347,3 +348,20 @@ function close_grid_and_dialog() {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
frappe.ui.keys.add_shortcut({
|
||||
shortcut: "shift+t",
|
||||
action: function (e) {
|
||||
if (!frappe.model.can_write("System Console")) {
|
||||
return;
|
||||
}
|
||||
if (cur_dialog?.is_minimized) {
|
||||
cur_dialog.toggle_minimize();
|
||||
cur_dialog.focus_on_first_input();
|
||||
} else {
|
||||
let dropdown_console = new DropdownConsole();
|
||||
dropdown_console.show();
|
||||
}
|
||||
},
|
||||
description: __("Open console"),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -230,16 +230,14 @@ export default class NumberCardWidget extends Widget {
|
|||
const shortened_number = frappe.utils.shorten_number(this.number, default_country, 5);
|
||||
number_parts = shortened_number.split(" ");
|
||||
}
|
||||
|
||||
const symbol = number_parts[1] || "";
|
||||
// done to add multicurrency support in number card
|
||||
if (this.card_doc.currency) {
|
||||
this.formatted_number =
|
||||
format_currency(number_parts[0], this.card_doc.currency) +
|
||||
" " +
|
||||
__(number_parts[1]);
|
||||
format_currency(number_parts[0], this.card_doc.currency) + " " + symbol;
|
||||
return;
|
||||
}
|
||||
const symbol = number_parts[1] || "";
|
||||
|
||||
number_parts[0] = window.convert_old_to_new_number_format(number_parts[0]);
|
||||
const formatted_number = frappe.format(number_parts[0], df, null, doc);
|
||||
this.formatted_number =
|
||||
|
|
|
|||
|
|
@ -431,6 +431,7 @@ input.list-header-checkbox {
|
|||
background-color: var(--control-bg);
|
||||
min-width: 21px;
|
||||
border-radius: 22px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -640,12 +640,17 @@ def get_time(
|
|||
return time_str
|
||||
elif isinstance(time_str, datetime.timedelta):
|
||||
return (datetime.datetime.min + time_str).time()
|
||||
|
||||
try:
|
||||
return parser.parse(time_str).time()
|
||||
except ParserError as e:
|
||||
if "day" in e.args[1] or "hour must be in" in e.args[0]:
|
||||
return (datetime.datetime.min + parse_timedelta(time_str)).time()
|
||||
raise e
|
||||
# PERF: Our DATE_FORMAT is same as ISO format.
|
||||
return datetime.time.fromisoformat(time_str)
|
||||
except ValueError:
|
||||
try:
|
||||
return parser.parse(time_str).time()
|
||||
except ParserError as e:
|
||||
if "day" in e.args[1] or "hour must be in" in e.args[0]:
|
||||
return (datetime.datetime.min + parse_timedelta(time_str)).time()
|
||||
raise e
|
||||
|
||||
|
||||
def get_datetime_str(datetime_obj: DateTimeLikeObject) -> str:
|
||||
|
|
|
|||
|
|
@ -376,7 +376,7 @@ def sync_global_search():
|
|||
yield value
|
||||
|
||||
item_generator = get_search_queue_item_generator()
|
||||
while search_items := tuple(islice(item_generator, 10_000)):
|
||||
while search_items := tuple(islice(item_generator, 1000)):
|
||||
values = _get_deduped_search_item_values(search_items)
|
||||
sync_values(values)
|
||||
|
||||
|
|
|
|||
|
|
@ -155,8 +155,11 @@ def prepare_filters(doctype, controller, kwargs):
|
|||
filters[key] = val
|
||||
|
||||
# filter the filters to include valid fields only
|
||||
from frappe.model.meta import DEFAULT_FIELD_LABELS
|
||||
|
||||
for fieldname in list(filters.keys()):
|
||||
if not meta.has_field(fieldname):
|
||||
# add a check for default fields, as they are not present in meta.fields
|
||||
if not meta.has_field(fieldname) and fieldname not in DEFAULT_FIELD_LABELS.keys():
|
||||
del filters[fieldname]
|
||||
|
||||
return filters
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
"popper.js": "^1.16.0",
|
||||
"postcss": "8",
|
||||
"quill": "2.0.3",
|
||||
"quill-image-resize": "^3.0.9",
|
||||
"frappe-quill-image-resize": "^3.0.9",
|
||||
"quill-magic-url": "^3.0.0",
|
||||
"qz-tray": "^2.0.8",
|
||||
"rtlcss": "^4.0.0",
|
||||
|
|
|
|||
18
yarn.lock
18
yarn.lock
|
|
@ -1445,6 +1445,15 @@ frappe-gantt@^0.6.0:
|
|||
resolved "https://registry.yarnpkg.com/frappe-gantt/-/frappe-gantt-0.6.1.tgz#57ae0b5f024101fc7cd5ba92f605de97dba9c9a1"
|
||||
integrity sha512-1cSU9vLbwypjzaxnCfnEE03Xr3HlAV2S8dRtjxw62o+amkx1A8bBIFd2jp84mcDdTCM77Ij4LzZBslAKZB8oMg==
|
||||
|
||||
frappe-quill-image-resize@^3.0.9:
|
||||
version "3.0.9"
|
||||
resolved "https://registry.yarnpkg.com/frappe-quill-image-resize/-/frappe-quill-image-resize-3.0.9.tgz#35e1d94aca458328be0db03ac25b58171af8c194"
|
||||
integrity sha512-2g38/Z/jbi3gbkCgHRgDe9MVskcjJrUioB3RXhQGhjpGKRgBznyVOLmHAZ1a8sBKAHBfuVz9BRdQulkJUrKg0g==
|
||||
dependencies:
|
||||
lodash "^4.17.4"
|
||||
quill "^1.2.2"
|
||||
raw-loader "^0.5.1"
|
||||
|
||||
fs-exists-sync@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add"
|
||||
|
|
@ -2730,15 +2739,6 @@ quill-delta@^5.1.0:
|
|||
lodash.clonedeep "^4.5.0"
|
||||
lodash.isequal "^4.5.0"
|
||||
|
||||
quill-image-resize@^3.0.9:
|
||||
version "3.0.9"
|
||||
resolved "https://registry.yarnpkg.com/quill-image-resize/-/quill-image-resize-3.0.9.tgz#5677fb6257560bff951153ddbdb836758e49f804"
|
||||
integrity sha512-5Dk0nixhbFsCwSWtPU9qqqtfM2gURfaP+pbBhQvAoMJoF4p99xbAibfAI3gsZJkbWUodoK2iAPf1V5oTSpv9ww==
|
||||
dependencies:
|
||||
lodash "^4.17.4"
|
||||
quill "^1.2.2"
|
||||
raw-loader "^0.5.1"
|
||||
|
||||
quill-magic-url@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/quill-magic-url/-/quill-magic-url-3.0.2.tgz#84654c749650e006250cbaf905295cb87796f3a7"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue