Merge branch 'develop' into feature/show-full-number-option
This commit is contained in:
commit
868a019e4b
11 changed files with 73 additions and 32 deletions
|
|
@ -666,7 +666,7 @@ def is_whitelisted(method):
|
|||
|
||||
is_guest = session["user"] == "Guest"
|
||||
if method not in whitelisted or (is_guest and method not in guest_methods):
|
||||
summary = _("You are not permitted to access this resource.")
|
||||
summary = _("You are not permitted to access this resource. Login to access")
|
||||
detail = _("Function {0} is not whitelisted.").format(bold(f"{method.__module__}.{method.__name__}"))
|
||||
msg = f"<details><summary>{summary}</summary>{detail}</details>"
|
||||
throw(msg, PermissionError, title=_("Method Not Allowed"))
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
"editable_grid",
|
||||
"quick_entry",
|
||||
"grid_page_length",
|
||||
"rows_threshold_for_grid_search",
|
||||
"cb01",
|
||||
"track_changes",
|
||||
"track_seen",
|
||||
|
|
@ -697,6 +698,14 @@
|
|||
"fieldname": "protect_attached_files",
|
||||
"fieldtype": "Check",
|
||||
"label": "Protect Attached Files"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "istable",
|
||||
"fieldname": "rows_threshold_for_grid_search",
|
||||
"fieldtype": "Int",
|
||||
"label": "Rows Threshold for Grid Search",
|
||||
"non_negative": 1
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
|
|
@ -775,7 +784,7 @@
|
|||
"link_fieldname": "document_type"
|
||||
}
|
||||
],
|
||||
"modified": "2025-03-27 18:16:53.286909",
|
||||
"modified": "2025-05-21 21:58:59.947374",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "DocType",
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ class DocType(Document):
|
|||
restrict_to_domain: DF.Link | None
|
||||
route: DF.Data | None
|
||||
row_format: DF.Literal["Dynamic", "Compressed"]
|
||||
rows_threshold_for_grid_search: DF.Int
|
||||
search_fields: DF.Data | None
|
||||
sender_field: DF.Data | None
|
||||
sender_name_field: DF.Data | None
|
||||
|
|
|
|||
|
|
@ -71,30 +71,37 @@ def has_permission(doc, user):
|
|||
|
||||
|
||||
def get_unseen_notes():
|
||||
from frappe.query_builder.terms import ParameterizedValueWrapper, SubQuery
|
||||
|
||||
def _get_unseen_notes():
|
||||
note = frappe.qb.DocType("Note")
|
||||
nsb = frappe.qb.DocType("Note Seen By").as_("nsb")
|
||||
|
||||
return (
|
||||
frappe.qb.from_(note)
|
||||
.select(note.name, note.title, note.content, note.notify_on_every_login)
|
||||
.where(
|
||||
(note.notify_on_login == 1)
|
||||
& (note.expire_notification_on > frappe.utils.now())
|
||||
& (
|
||||
ParameterizedValueWrapper(frappe.session.user).notin(
|
||||
SubQuery(frappe.qb.from_(nsb).select(nsb.user).where(nsb.parent == note.name))
|
||||
)
|
||||
)
|
||||
)
|
||||
).run(as_dict=1)
|
||||
|
||||
return (
|
||||
frappe.cache.get_value(
|
||||
f"{UNSEEN_NOTES_KEY}{frappe.session.user}",
|
||||
generator=_get_unseen_notes,
|
||||
)
|
||||
or []
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def reset_notes():
|
||||
frappe.cache.set_value(f"{UNSEEN_NOTES_KEY}{frappe.session.user}", [])
|
||||
return frappe.cache.get_value(f"{UNSEEN_NOTES_KEY}{frappe.session.user}")
|
||||
|
||||
|
||||
def _get_unseen_notes():
|
||||
from frappe.query_builder.terms import ParameterizedValueWrapper, SubQuery
|
||||
|
||||
note = frappe.qb.DocType("Note")
|
||||
nsb = frappe.qb.DocType("Note Seen By").as_("nsb")
|
||||
|
||||
results = (
|
||||
frappe.qb.from_(note)
|
||||
.select(note.name, note.title, note.content, note.notify_on_every_login)
|
||||
.where(
|
||||
(note.notify_on_login == 1)
|
||||
& (note.expire_notification_on > frappe.utils.now())
|
||||
& (
|
||||
ParameterizedValueWrapper(frappe.session.user).notin(
|
||||
SubQuery(frappe.qb.from_(nsb).select(nsb.user).where(nsb.parent == note.name))
|
||||
)
|
||||
)
|
||||
)
|
||||
).run(as_dict=1)
|
||||
frappe.cache.set_value(f"{UNSEEN_NOTES_KEY}{frappe.session.user}", results)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@
|
|||
"dynamic_filters_section",
|
||||
"dynamic_filters_json",
|
||||
"section_break_16",
|
||||
"color"
|
||||
"color",
|
||||
"column_break_xtre",
|
||||
"background_color"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
|
|
@ -209,6 +211,15 @@
|
|||
"label": "Currency",
|
||||
"options": "Currency"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_xtre",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "background_color",
|
||||
"fieldtype": "Color",
|
||||
"label": "Background Color"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Check to display the full numeric value (e.g., 1,234,567 instead of 1.2M).",
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class NumberCard(Document):
|
|||
from frappe.types import DF
|
||||
|
||||
aggregate_function_based_on: DF.Literal[None]
|
||||
background_color: DF.Color | None
|
||||
color: DF.Color | None
|
||||
currency: DF.Link | None
|
||||
document_type: DF.Link | None
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ on_session_creation = [
|
|||
"frappe.core.doctype.user.user.notify_admin_access_to_system_manager",
|
||||
]
|
||||
|
||||
on_login = "frappe.desk.doctype.note.note._get_unseen_notes"
|
||||
on_logout = "frappe.core.doctype.session_default_settings.session_default_settings.clear_session_defaults"
|
||||
|
||||
# PDF
|
||||
|
|
|
|||
|
|
@ -469,11 +469,12 @@ frappe.Application = class Application {
|
|||
if (frappe.boot.notes.length) {
|
||||
frappe.boot.notes.forEach(function (note) {
|
||||
if (!note.seen || note.notify_on_every_login) {
|
||||
var d = frappe.msgprint({ message: note.content, title: note.title });
|
||||
var d = new frappe.ui.Dialog({ content: note.content, title: note.title });
|
||||
d.keep_open = true;
|
||||
d.custom_onhide = function () {
|
||||
d.msg_area = $('<div class="msgprint">').appendTo(d.body);
|
||||
d.msg_area.append(note.content);
|
||||
d.onhide = function () {
|
||||
note.seen = true;
|
||||
|
||||
// Mark note as read if the Notify On Every Login flag is not set
|
||||
if (!note.notify_on_every_login) {
|
||||
frappe.call({
|
||||
|
|
@ -482,11 +483,13 @@ frappe.Application = class Application {
|
|||
note: note.name,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
frappe.call({
|
||||
method: "frappe.desk.doctype.note.note.reset_notes",
|
||||
});
|
||||
}
|
||||
|
||||
// next note
|
||||
me.show_notes();
|
||||
};
|
||||
d.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -852,8 +852,13 @@ export default class GridRow {
|
|||
|
||||
show_search_row() {
|
||||
// show or remove search columns based on grid rows
|
||||
let show_length =
|
||||
this.grid?.meta?.rows_threshold_for_grid_search > 0
|
||||
? this.grid.meta.rows_threshold_for_grid_search
|
||||
: 20;
|
||||
this.show_search =
|
||||
this.show_search && (this.grid?.data?.length >= 20 || this.grid.filter_applied);
|
||||
this.show_search &&
|
||||
(this.grid?.data?.length >= show_length || this.grid.filter_applied);
|
||||
!this.show_search && this.wrapper.remove();
|
||||
return this.show_search;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@ export default class NumberCardWidget extends Widget {
|
|||
async render_card() {
|
||||
this.prepare_actions();
|
||||
this.set_title();
|
||||
this.card_doc?.background_color &&
|
||||
this.widget.css("background-color", this.card_doc.background_color);
|
||||
this.set_loading_state();
|
||||
|
||||
if (!this.card_doc.type) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import frappe
|
||||
from frappe.boot import get_user_pages_or_reports
|
||||
from frappe.desk.doctype.note.note import get_unseen_notes, mark_as_seen
|
||||
from frappe.desk.doctype.note.note import _get_unseen_notes, get_unseen_notes, mark_as_seen
|
||||
from frappe.tests import IntegrationTestCase
|
||||
|
||||
|
||||
|
|
@ -20,6 +20,7 @@ class TestBootData(IntegrationTestCase):
|
|||
note.insert()
|
||||
|
||||
frappe.set_user("test@example.com")
|
||||
_get_unseen_notes()
|
||||
unseen_notes = [d.title for d in get_unseen_notes()]
|
||||
self.assertListEqual(unseen_notes, ["Test Note"])
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue