@@ -3,6 +3,7 @@ | |||||
from frappe.core.doctype.user_permission.user_permission import add_user_permissions, remove_applicable | from frappe.core.doctype.user_permission.user_permission import add_user_permissions, remove_applicable | ||||
from frappe.permissions import has_user_permission | from frappe.permissions import has_user_permission | ||||
from frappe.core.doctype.doctype.test_doctype import new_doctype | 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 frappe | ||||
import unittest | import unittest | ||||
@@ -31,6 +32,16 @@ class TestUserPermission(unittest.TestCase): | |||||
param = get_params(user, 'User', perm_user.name, is_default=1) | param = get_params(user, 'User', perm_user.name, is_default=1) | ||||
self.assertRaises(frappe.ValidationError, add_user_permissions, param) | 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): | def test_default_user_permission(self): | ||||
frappe.set_user('Administrator') | frappe.set_user('Administrator') | ||||
user = create_user('test_user_perm1@example.com', 'Website Manager') | user = create_user('test_user_perm1@example.com', 'Website Manager') | ||||
@@ -48,7 +48,6 @@ class UserPermission(Document): | |||||
}, or_filters={ | }, or_filters={ | ||||
'applicable_for': cstr(self.applicable_for), | 'applicable_for': cstr(self.applicable_for), | ||||
'apply_to_all_doctypes': 1, | 'apply_to_all_doctypes': 1, | ||||
'hide_descendants': cstr(self.hide_descendants) | |||||
}, limit=1) | }, limit=1) | ||||
if overlap_exists: | if overlap_exists: | ||||
ref_link = frappe.get_desk_link(self.doctype, overlap_exists[0].name) | ref_link = frappe.get_desk_link(self.doctype, overlap_exists[0].name) | ||||
@@ -319,7 +319,7 @@ def export_query(): | |||||
if add_totals_row: | if add_totals_row: | ||||
ret = append_totals_row(ret) | 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): | for i, row in enumerate(ret): | ||||
data.append([i+1] + list(row)) | data.append([i+1] + list(row)) | ||||
@@ -378,7 +378,8 @@ def get_labels(fields, doctype): | |||||
for key in fields: | for key in fields: | ||||
key = key.split(" as ")[0] | key = key.split(" as ")[0] | ||||
if key.startswith(('count(', 'sum(', 'avg(')): continue | |||||
if key.startswith(('count(', 'sum(', 'avg(')): | |||||
continue | |||||
if "." in key: | if "." in key: | ||||
parenttype, fieldname = key.split(".")[0][4:-1], key.split(".")[1].strip("`") | parenttype, fieldname = key.split(".")[0][4:-1], key.split(".")[1].strip("`") | ||||
@@ -386,10 +387,16 @@ def get_labels(fields, doctype): | |||||
parenttype = doctype | parenttype = doctype | ||||
fieldname = fieldname.strip("`") | 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) | labels.append(label) | ||||
return labels | return labels | ||||
@@ -866,7 +866,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView { | |||||
} | } | ||||
doctype_fields = [{ | doctype_fields = [{ | ||||
label: __('ID'), | |||||
label: __('ID', null, 'Label of name column in report'), | |||||
fieldname: 'name', | fieldname: 'name', | ||||
fieldtype: 'Data', | fieldtype: 'Data', | ||||
reqd: 1 | reqd: 1 | ||||
@@ -249,6 +249,7 @@ | |||||
--checkbox-right-margin: var(--margin-xs); | --checkbox-right-margin: var(--margin-xs); | ||||
--checkbox-size: 14px; | --checkbox-size: 14px; | ||||
--checkbox-focus-shadow: 0 0 0 2px var(--gray-300); | --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, <svg width='6' height='8' viewBox='0 0 6 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M1.25 7.5L4.75 4L1.25 0.5' stroke='%231F272E' stroke-linecap='round' stroke-linejoin='round'/></svg>"); | --right-arrow-svg: url("data: image/svg+xml;utf8, <svg width='6' height='8' viewBox='0 0 6 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M1.25 7.5L4.75 4L1.25 0.5' stroke='%231F272E' stroke-linecap='round' stroke-linejoin='round'/></svg>"); | ||||
--left-arrow-svg: url("data: image/svg+xml;utf8, <svg width='6' height='8' viewBox='0 0 6 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M7.5 9.5L4 6l3.5-3.5' stroke='%231F272E' stroke-linecap='round' stroke-linejoin='round'></path></svg>"); | --left-arrow-svg: url("data: image/svg+xml;utf8, <svg width='6' height='8' viewBox='0 0 6 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M7.5 9.5L4 6l3.5-3.5' stroke='%231F272E' stroke-linecap='round' stroke-linejoin='round'></path></svg>"); | ||||
@@ -54,7 +54,7 @@ input[type="radio"] { | |||||
} | } | ||||
&:checked::before { | &:checked::before { | ||||
background-color: var(--blue-500); | |||||
background-color: var(--primary); | |||||
border-radius: 16px; | border-radius: 16px; | ||||
box-shadow: inset 0 0 0 2px white; | box-shadow: inset 0 0 0 2px white; | ||||
} | } | ||||
@@ -85,8 +85,8 @@ input[type="checkbox"] { | |||||
} | } | ||||
&:checked { | &: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%; | background-size: 57%, 100%; | ||||
box-shadow: none; | box-shadow: none; | ||||
border: none; | border: none; | ||||
@@ -54,4 +54,6 @@ $input-height: 28px !default; | |||||
// skeleton | // skeleton | ||||
--skeleton-bg: var(--gray-100); | --skeleton-bg: var(--gray-100); | ||||
// progress bar | |||||
--progress-bar-bg: var(--primary); | |||||
} | } |
@@ -118,6 +118,9 @@ $custom-control-label-color: var(--text-color); | |||||
$custom-switch-indicator-size: 8px; | $custom-switch-indicator-size: 8px; | ||||
$custom-control-indicator-border-width: 2px; | $custom-control-indicator-border-width: 2px; | ||||
// progress bar | |||||
$progress-bar-bg: var(--progress-bar-bg); | |||||
$navbar-nav-link-padding-x: 1rem !default; | $navbar-nav-link-padding-x: 1rem !default; | ||||
$navbar-padding-y: 1rem !default; | $navbar-padding-y: 1rem !default; | ||||
$card-border-radius: 0.75rem !default; | $card-border-radius: 0.75rem !default; | ||||
@@ -3558,9 +3558,9 @@ Skipping column {0},Spalte {0} wird übersprungen, | |||||
Social Home,Soziales Zuhause, | 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.", | 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.", | 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, | Successful Transactions,Erfolgreiche Transaktionen, | ||||
Successfully Submitted!,Erfolgreich eingereicht!, | Successfully Submitted!,Erfolgreich eingereicht!, | ||||
Successfully imported {0} record.,{0} Datensatz erfolgreich importiert., | 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 Calendar,Mit Google Kalender synchronisieren, | ||||
Sync with Google Contacts,Mit Google-Kontakten synchronisieren, | Sync with Google Contacts,Mit Google-Kontakten synchronisieren, | ||||
Synced,Synchronisiert, | Synced,Synchronisiert, | ||||
Syncing,Synchronisierung, | |||||
Syncing,Synchronisiert, | |||||
Syncing {0} of {1},{0} von {1} synchronisieren, | Syncing {0} of {1},{0} von {1} synchronisieren, | ||||
Tag Link,Tag-Link, | |||||
Tag Link,Schlagwortverknüpfung, | |||||
Take Backup,Backup erstellen, | Take Backup,Backup erstellen, | ||||
Template Error,Vorlagenfehler, | Template Error,Vorlagenfehler, | ||||
Template Options,Vorlagenoptionen, | Template Options,Vorlagenoptionen, | ||||
@@ -4,7 +4,7 @@ import json | |||||
import mimetypes | import mimetypes | ||||
import os | import os | ||||
import re | import re | ||||
from functools import cache, wraps | |||||
from functools import lru_cache, wraps | |||||
from typing import Dict, Optional | from typing import Dict, Optional | ||||
import yaml | import yaml | ||||
@@ -512,7 +512,7 @@ def add_preload_headers(response): | |||||
import traceback | import traceback | ||||
traceback.print_exc() | traceback.print_exc() | ||||
@cache | |||||
@lru_cache() | |||||
def is_binary_file(path): | def is_binary_file(path): | ||||
# ref: https://stackoverflow.com/a/7392391/10309266 | # ref: https://stackoverflow.com/a/7392391/10309266 | ||||
textchars = bytearray({7,8,9,10,12,13,27} | set(range(0x20, 0x100)) - {0x7f}) | textchars = bytearray({7,8,9,10,12,13,27} | set(range(0x20, 0x100)) - {0x7f}) | ||||