184 lines
4.8 KiB
Python
184 lines
4.8 KiB
Python
import sys
|
|
from collections.abc import Sequence
|
|
from typing import Literal
|
|
|
|
import frappe
|
|
from frappe import _
|
|
from frappe.utils import strip_html_tags
|
|
from frappe.utils.data import safe_decode
|
|
|
|
|
|
def msgprint(
|
|
msg: str | Sequence[str] | Sequence[Sequence[str]],
|
|
title: str | None = None,
|
|
raise_exception: bool | type[Exception] | Exception = False,
|
|
as_table: bool = False,
|
|
as_list: bool = False,
|
|
indicator: Literal["blue", "green", "orange", "red", "yellow"] | None = None,
|
|
alert: bool = False,
|
|
primary_action: dict | None = None,
|
|
is_minimizable: bool = False,
|
|
wide: bool = False,
|
|
*,
|
|
realtime=False,
|
|
allow_dangerous_html=False,
|
|
) -> None:
|
|
"""Print a message to the user (via HTTP response).
|
|
Messages are sent in the `__server_messages` property in the
|
|
response JSON and shown in a pop-up / modal.
|
|
|
|
:param msg: Message.
|
|
:param title: [optional] Message title. Default: "Message".
|
|
:param raise_exception: [optional] Raise given exception and show message.
|
|
:param as_table: [optional] If `msg` is a list of lists, render as HTML table.
|
|
:param as_list: [optional] If `msg` is a list, render as un-ordered list.
|
|
:param primary_action: [optional] Bind a primary server/client side action.
|
|
:param is_minimizable: [optional] Allow users to minimize the modal
|
|
:param wide: [optional] Show wide modal
|
|
:param realtime: Publish message immediately using websocket.
|
|
:param allow_dangerous_html: Allow arbitrary HTML in message.
|
|
"""
|
|
import inspect
|
|
|
|
from frappe.utils.html_utils import clean_html
|
|
|
|
msg = safe_decode(msg)
|
|
out = frappe._dict(message=msg)
|
|
|
|
def _raise_exception():
|
|
if raise_exception:
|
|
if inspect.isclass(raise_exception) and issubclass(raise_exception, Exception):
|
|
exc = raise_exception(msg)
|
|
elif isinstance(raise_exception, Exception):
|
|
exc = raise_exception
|
|
exc.args = (msg,)
|
|
else:
|
|
exc = frappe.ValidationError(msg)
|
|
if out.__frappe_exc_id:
|
|
exc.__frappe_exc_id = out.__frappe_exc_id
|
|
raise exc
|
|
|
|
if frappe.flags.mute_messages:
|
|
_raise_exception()
|
|
return
|
|
|
|
if isinstance(msg, Sequence):
|
|
if as_list:
|
|
out.as_list = as_list
|
|
else:
|
|
out.as_table = as_table
|
|
|
|
if not allow_dangerous_html:
|
|
if out.as_list:
|
|
out.message = [clean_html(cell) for cell in msg]
|
|
elif out.as_table:
|
|
out.message = [[clean_html(cell) for cell in row] for row in msg]
|
|
else:
|
|
out.message = clean_html(msg)
|
|
|
|
if sys.stdin and sys.stdin.isatty():
|
|
if out.as_list:
|
|
msg = [strip_html_tags(cell) for cell in msg]
|
|
elif out.as_table:
|
|
msg = [[strip_html_tags(cell) for cell in row] for row in msg]
|
|
else:
|
|
msg = strip_html_tags(msg)
|
|
|
|
if frappe.flags.print_messages and out.message:
|
|
print(f"Message: {msg}")
|
|
|
|
out.title = title or _("Message", context="Default title of the message dialog")
|
|
|
|
if not indicator and raise_exception:
|
|
indicator = "red"
|
|
|
|
if indicator:
|
|
out.indicator = indicator
|
|
|
|
if is_minimizable:
|
|
out.is_minimizable = is_minimizable
|
|
|
|
if alert:
|
|
out.alert = 1
|
|
|
|
if raise_exception:
|
|
out.raise_exception = 1
|
|
out.__frappe_exc_id = frappe.generate_hash()
|
|
|
|
if primary_action:
|
|
out.primary_action = primary_action
|
|
|
|
if wide:
|
|
out.wide = wide
|
|
|
|
if realtime:
|
|
frappe.publish_realtime(event="msgprint", message=out)
|
|
else:
|
|
frappe.message_log.append(out)
|
|
_raise_exception()
|
|
|
|
|
|
def toast(message: str, indicator: Literal["blue", "green", "orange", "red", "yellow"] | None = None):
|
|
msgprint(message, indicator=indicator, alert=True)
|
|
|
|
|
|
def clear_messages():
|
|
frappe.local.message_log = []
|
|
|
|
|
|
def get_message_log() -> list[dict]:
|
|
return [msg_out for msg_out in frappe.local.message_log]
|
|
|
|
|
|
def clear_last_message():
|
|
if len(frappe.local.message_log) > 0:
|
|
frappe.local.message_log = frappe.local.message_log[:-1]
|
|
|
|
|
|
def throw(
|
|
msg: str | Sequence[str],
|
|
exc: type[Exception] | Exception = frappe.ValidationError,
|
|
title: str | None = None,
|
|
is_minimizable: bool = False,
|
|
wide: bool = False,
|
|
as_list: bool = False,
|
|
primary_action=None,
|
|
*,
|
|
allow_dangerous_html=False,
|
|
) -> None:
|
|
"""Throw execption and show message (`msgprint`).
|
|
|
|
:param msg: Message.
|
|
:param exc: Exception class. Default `frappe.ValidationError`
|
|
:param title: [optional] Message title. Default: "Message".
|
|
:param is_minimizable: [optional] Allow users to minimize the modal
|
|
:param wide: [optional] Show wide modal
|
|
:param as_list: [optional] If `msg` is a list, render as un-ordered list.
|
|
:param primary_action: [optional] Bind a primary server/client side action.
|
|
"""
|
|
msgprint(
|
|
msg,
|
|
raise_exception=exc,
|
|
title=title,
|
|
indicator="red",
|
|
is_minimizable=is_minimizable,
|
|
wide=wide,
|
|
as_list=as_list,
|
|
primary_action=primary_action,
|
|
allow_dangerous_html=allow_dangerous_html,
|
|
)
|
|
|
|
|
|
def throw_permission_error():
|
|
throw(_("Not permitted"), frappe.PermissionError)
|
|
|
|
|
|
__all__ = [
|
|
"clear_last_message",
|
|
"clear_messages",
|
|
"get_message_log",
|
|
"msgprint",
|
|
"throw",
|
|
"throw_permission_error",
|
|
"toast",
|
|
]
|