Replies: 3 comments 3 replies
-
Hi @guvenir18, Looks like you want to create "private" pages: |
Beta Was this translation helpful? Give feedback.
-
My app uses single page. I have a single method defined as @ui.page("/main_page")
async def main_page():
# Other methods that creates cards and other stuff So I would expect it to behave as a private page as you mentioned but the issue I told above still happens. |
Beta Was this translation helpful? Give feedback.
-
I had a similar challenge, not just with sessions but also with different logs in one session. This is what I came up with, maybe it will help. used loguru in my project so thats why it's in it.. could use the normal logger like the examples import asyncio
from nicegui import ui, native
import logging
from loguru import logger as loguru_logger
from nicegui import ui
import re
class LogNotifyHandler(logging.Handler):
"""A logging handler that emits messages to a log element."""
def __init__(
self,
element: ui.log, level: int = logging.NOTSET,
notify: bool = True, notify_include_time: bool = True
) -> None:
super().__init__(level)
self.element: ui.log = element
self.notify: bool = notify
self.notify_time: bool = notify_include_time
def emit(self, record: logging.LogRecord) -> None:
try:
msg = self.format(record)
self.element.push(msg)
if self.notify:
self._notify(record)
except Exception as e:
self.handleError(record)
msg = f"Error: {str(e)}"
self.element.push(msg)
if self.notify:
ui.notify(msg, type='negative', close_button=True, timeout=0)
def get_time_lvl_msg(self, record: logging.LogRecord) -> tuple[str, str, str]:
pattern = r'^(?P<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}) \| (?P<level>[\w\d\s]+?)\s*\| (?P<msg>.*)$'
match = re.match(pattern, record.msg)
if match:
time = match.group('time')
level = match.group('level')
msg = match.group('msg')
return time.strip(), level.strip(), msg.strip()
raise ValueError("log record does not match standard")
def _notify(self, record: logging.LogRecord):
time, level, msg = self.get_time_lvl_msg(record)
if self.notify_time:
msg = f"{time}-{msg}"
notification_params = {
"message": msg,
"type": "default",
"close_button": False,
"timeout": 5000
}
if level in ["TRACE", "DEBUG"]:
pass # No specific action for trace and debug levels
elif level == "INFO":
notification_params["type"] = 'info'
elif level == "WARNING":
notification_params.update({"type": 'warning', "close_button": True, "timeout": 0})
elif level in ["ERROR", "CRITICAL"]:
notification_params.update({"type": 'negative', "close_button": True, "timeout": 0})
elif level == 'Level 25': # Custom level
notification_params.update({"type": 'positive', "close_button": True, "timeout": 10000})
else:
raise NotImplementedError(f"Notification for level '{level}' is not implemented.")
with self.element:
ui.notify(**notification_params)
class LogNotifySessionHandler:
def __init__(self, log: ui.log, ui_client: ui.context.client, name: str, notify: bool = True, log_visible: bool = True):
self.log_element: ui.log = log
self.log_element.visible = log_visible
self.session_name: str = f"logger_{id(ui_client)}_{name}"
self.logger: loguru_logger = self._create_logger()
self.handler: LogNotifyHandler = self._create_handler(notify)
ui.context.client.on_disconnect(lambda: self.logger.remove(self.handler))
def _create_logger(self) -> loguru_logger:
return loguru_logger.bind(task=self.session_name)
def _create_handler(self, notify) -> LogNotifyHandler:
handler = LogNotifyHandler(self.log_element, notify=notify)
self.logger.add(handler, filter=lambda record: record["extra"]["task"] == self.session_name)
return handler
async def get_log_test_ui(log: ui.log, context: ui.context, name: str):
# todo: this wil run for every, find way to stop it when page is shut down
# create session and add session test button
async def log_stuff():
# Example logs to demonstrate functionality
while True:
session_logger.logger.info("This is an info message")
await asyncio.sleep(1)
session_logger.logger.warning("This is a warning message")
await asyncio.sleep(1)
session_logger.logger.error("This is an error message")
await asyncio.sleep(1)
session_logger.logger.critical("This is an error message")
await asyncio.sleep(1)
session_logger.logger.log(25, "This is a custom positive message")
session_logger = LogNotifySessionHandler(log, context.client, name)
ui.button('Log stuff', on_click=lambda: log_stuff())
@ui.page('/')
async def session_log_site():
# log session main
log = ui.log(max_lines=3).classes('w-full h-16')
session_main_logger = LogNotifySessionHandler(log, ui.context, "main", log_visible=False)
session_main_logger.logger.debug("start")
for item in range(3):
session_main_logger.logger.info(f"main {item}")
# log session a
log_a = ui.log().classes('w-full')
log_and_notify_a = get_log_test_ui(log_a, ui.context, "A")
await log_and_notify_a
# log session b
log_b = ui.log(max_lines=20).classes('w-full')
log_and_notify_b = get_log_test_ui(log_b, ui.context, "B")
await log_and_notify_b
ui.run(
title="Log app",
dark=True,
port=native.find_open_port(),
reconnect_timeout=300,
) |
Beta Was this translation helpful? Give feedback.
-
Question
Hello, first of all thanks for this great library.
Is it possible to make ui.log work specific for each user ? Lets say I have two users using app at same time. When user1 clicks a button, log message is shown for both of the users in log window. What I want is logs created from interactions of user1 only shown to user1.
I thought about some solutions like storing each user's log message to app.storage and bind ui.log there but it looks like a lot of work. Maybe there is someting I am missing.
Thanks for help
Beta Was this translation helpful? Give feedback.
All reactions