diff --git a/frappe/core/doctype/user_permission/test_user_permission.py b/frappe/core/doctype/user_permission/test_user_permission.py
index cf905c2ce2..7da62c408f 100644
--- a/frappe/core/doctype/user_permission/test_user_permission.py
+++ b/frappe/core/doctype/user_permission/test_user_permission.py
@@ -3,6 +3,7 @@
from frappe.core.doctype.user_permission.user_permission import add_user_permissions, remove_applicable
from frappe.permissions import has_user_permission
from frappe.core.doctype.doctype.test_doctype import new_doctype
+from frappe.website.doctype.blog_post.test_blog_post import make_test_blog
import frappe
import unittest
@@ -31,6 +32,16 @@ class TestUserPermission(unittest.TestCase):
param = get_params(user, 'User', perm_user.name, is_default=1)
self.assertRaises(frappe.ValidationError, add_user_permissions, param)
+ def test_default_user_permission_corectness(self):
+ user = create_user('test_default_corectness_permission_1@example.com')
+ param = get_params(user, 'User', user.name, is_default=1, hide_descendants= 1)
+ add_user_permissions(param)
+ #create a duplicate entry with default
+ perm_user = create_user('test_default_corectness2@example.com')
+ test_blog = make_test_blog()
+ param = get_params(perm_user, 'Blog Post', test_blog.name, is_default=1, hide_descendants= 1)
+ add_user_permissions(param)
+
def test_default_user_permission(self):
frappe.set_user('Administrator')
user = create_user('test_user_perm1@example.com', 'Website Manager')
diff --git a/frappe/core/doctype/user_permission/user_permission.py b/frappe/core/doctype/user_permission/user_permission.py
index 1366ace115..fb658481b2 100644
--- a/frappe/core/doctype/user_permission/user_permission.py
+++ b/frappe/core/doctype/user_permission/user_permission.py
@@ -48,7 +48,6 @@ class UserPermission(Document):
}, or_filters={
'applicable_for': cstr(self.applicable_for),
'apply_to_all_doctypes': 1,
- 'hide_descendants': cstr(self.hide_descendants)
}, limit=1)
if overlap_exists:
ref_link = frappe.get_desk_link(self.doctype, overlap_exists[0].name)
diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py
index 27ac882016..4001d0b9cf 100644
--- a/frappe/desk/reportview.py
+++ b/frappe/desk/reportview.py
@@ -319,7 +319,7 @@ def export_query():
if add_totals_row:
ret = append_totals_row(ret)
- data = [['Sr'] + get_labels(db_query.fields, doctype)]
+ data = [[_('Sr')] + get_labels(db_query.fields, doctype)]
for i, row in enumerate(ret):
data.append([i+1] + list(row))
@@ -378,7 +378,8 @@ def get_labels(fields, doctype):
for key in fields:
key = key.split(" as ")[0]
- if key.startswith(('count(', 'sum(', 'avg(')): continue
+ if key.startswith(('count(', 'sum(', 'avg(')):
+ continue
if "." in key:
parenttype, fieldname = key.split(".")[0][4:-1], key.split(".")[1].strip("`")
@@ -386,10 +387,16 @@ def get_labels(fields, doctype):
parenttype = doctype
fieldname = fieldname.strip("`")
- df = frappe.get_meta(parenttype).get_field(fieldname)
- label = df.label if df else fieldname.title()
- if label in labels:
- label = doctype + ": " + label
+ if parenttype == doctype and fieldname == "name":
+ label = _("ID", context="Label of name column in report")
+ else:
+ df = frappe.get_meta(parenttype).get_field(fieldname)
+ label = _(df.label if df else fieldname.title())
+ if parenttype != doctype:
+ # If the column is from a child table, append the child doctype.
+ # For example, "Item Code (Sales Invoice Item)".
+ label += f" ({ _(parenttype) })"
+
labels.append(label)
return labels
diff --git a/frappe/public/js/frappe/views/reports/report_view.js b/frappe/public/js/frappe/views/reports/report_view.js
index f5d9f3e110..23e415ed3e 100644
--- a/frappe/public/js/frappe/views/reports/report_view.js
+++ b/frappe/public/js/frappe/views/reports/report_view.js
@@ -866,7 +866,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
}
doctype_fields = [{
- label: __('ID'),
+ label: __('ID', null, 'Label of name column in report'),
fieldname: 'name',
fieldtype: 'Data',
reqd: 1
diff --git a/frappe/public/scss/common/css_variables.scss b/frappe/public/scss/common/css_variables.scss
index f4794362d3..b8b7f869fa 100644
--- a/frappe/public/scss/common/css_variables.scss
+++ b/frappe/public/scss/common/css_variables.scss
@@ -249,6 +249,7 @@
--checkbox-right-margin: var(--margin-xs);
--checkbox-size: 14px;
--checkbox-focus-shadow: 0 0 0 2px var(--gray-300);
+ --checkbox-gradient: linear-gradient(180deg, #4AC3F8 -124.51%, var(--primary) 100%);
--right-arrow-svg: url("data: image/svg+xml;utf8, ");
--left-arrow-svg: url("data: image/svg+xml;utf8, ");
diff --git a/frappe/public/scss/common/global.scss b/frappe/public/scss/common/global.scss
index 0324b75bfb..8a849ab51a 100644
--- a/frappe/public/scss/common/global.scss
+++ b/frappe/public/scss/common/global.scss
@@ -54,7 +54,7 @@ input[type="radio"] {
}
&:checked::before {
- background-color: var(--blue-500);
+ background-color: var(--primary);
border-radius: 16px;
box-shadow: inset 0 0 0 2px white;
}
@@ -85,8 +85,8 @@ input[type="checkbox"] {
}
&:checked {
- background-color: var(--blue-500);
- background-image: $check-icon, linear-gradient(180deg, #4AC3F8 -124.51%, #2490EF 100%);
+ background-color: var(--primary);
+ background-image: $check-icon, var(--checkbox-gradient);
background-size: 57%, 100%;
box-shadow: none;
border: none;
diff --git a/frappe/public/scss/desk/css_variables.scss b/frappe/public/scss/desk/css_variables.scss
index 0912cb278b..a06ba3e9b0 100644
--- a/frappe/public/scss/desk/css_variables.scss
+++ b/frappe/public/scss/desk/css_variables.scss
@@ -54,4 +54,6 @@ $input-height: 28px !default;
// skeleton
--skeleton-bg: var(--gray-100);
+ // progress bar
+ --progress-bar-bg: var(--primary);
}
diff --git a/frappe/public/scss/desk/variables.scss b/frappe/public/scss/desk/variables.scss
index 2855277ccd..abc63cd637 100644
--- a/frappe/public/scss/desk/variables.scss
+++ b/frappe/public/scss/desk/variables.scss
@@ -118,6 +118,9 @@ $custom-control-label-color: var(--text-color);
$custom-switch-indicator-size: 8px;
$custom-control-indicator-border-width: 2px;
+// progress bar
+$progress-bar-bg: var(--progress-bar-bg);
+
$navbar-nav-link-padding-x: 1rem !default;
$navbar-padding-y: 1rem !default;
$card-border-radius: 0.75rem !default;
diff --git a/frappe/translations/de.csv b/frappe/translations/de.csv
index 18ff55e386..9fad17becd 100644
--- a/frappe/translations/de.csv
+++ b/frappe/translations/de.csv
@@ -3558,9 +3558,9 @@ Skipping column {0},Spalte {0} wird übersprungen,
Social Home,Soziales Zuhause,
Some columns might get cut off when printing to PDF. Try to keep number of columns under 10.,"Einige Spalten werden beim Drucken in PDF möglicherweise abgeschnitten. Versuchen Sie, die Anzahl der Spalten unter 10 zu halten.",
Something went wrong during the token generation. Click on {0} to generate a new one.,"Während der Token-Generierung ist ein Fehler aufgetreten. Klicken Sie auf {0}, um eine neue zu erstellen.",
-Submit After Import,Nach dem Import einreichen,
-Submitting...,Einreichen ...,
-Success! You are good to go 👍,Erfolg! Du bist gut zu gehen 👍,
+Submit After Import,Nach dem Import buchen,
+Submitting...,wird verbucht...,
+Success! You are good to go 👍,Erfolg! Du kannst nun durchstarten 👍,
Successful Transactions,Erfolgreiche Transaktionen,
Successfully Submitted!,Erfolgreich eingereicht!,
Successfully imported {0} record.,{0} Datensatz erfolgreich importiert.,
@@ -3572,9 +3572,9 @@ Sync Contacts,Kontakte synchronisieren,
Sync with Google Calendar,Mit Google Kalender synchronisieren,
Sync with Google Contacts,Mit Google-Kontakten synchronisieren,
Synced,Synchronisiert,
-Syncing,Synchronisierung,
+Syncing,Synchronisiert,
Syncing {0} of {1},{0} von {1} synchronisieren,
-Tag Link,Tag-Link,
+Tag Link,Schlagwortverknüpfung,
Take Backup,Backup erstellen,
Template Error,Vorlagenfehler,
Template Options,Vorlagenoptionen,
diff --git a/frappe/website/utils.py b/frappe/website/utils.py
index 1772d8ada1..152d312533 100644
--- a/frappe/website/utils.py
+++ b/frappe/website/utils.py
@@ -4,7 +4,7 @@ import json
import mimetypes
import os
import re
-from functools import cache, wraps
+from functools import lru_cache, wraps
from typing import Dict, Optional
import yaml
@@ -512,7 +512,7 @@ def add_preload_headers(response):
import traceback
traceback.print_exc()
-@cache
+@lru_cache()
def is_binary_file(path):
# ref: https://stackoverflow.com/a/7392391/10309266
textchars = bytearray({7,8,9,10,12,13,27} | set(range(0x20, 0x100)) - {0x7f})