view libervia/web/pages/_browser/dialog.py @ 1533:285c49d7aad3

_browser (template): add `media_type_main` and `media_type_sub` filters: this is to follow main template module change, as string slicing is not done the same way in jinja2 and nunjucks.
author Goffi <goffi@goffi.org>
date Thu, 22 Jun 2023 16:36:18 +0200
parents eb00d593801d
children e47c24204449
line wrap: on
line source

"""manage common dialogs"""

from browser import document, window, timer, console as log
from template import Template

log.warning = log.warn


class Confirm:

    def __init__(self, message, ok_label="", cancel_label="", ok_color="success"):
        self._tpl = Template("dialogs/confirm.html")
        self.message = message
        self.ok_label = ok_label
        assert ok_color in ("success", "danger")
        self.ok_color = ok_color
        self.cancel_label = cancel_label

    def cancel_cb(self, evt, notif_elt):
        notif_elt.remove()

    def show(self, ok_cb, cancel_cb=None):
        if cancel_cb is None:
            cancel_cb = self.cancel_cb
        notif_elt = self._tpl.get_elt({
            "message": self.message,
            "ok_label": self.ok_label,
            "ok_color": self.ok_color,
            "cancel_label": self.cancel_label,
        })

        document['notifs_area'] <= notif_elt
        timer.set_timeout(lambda: notif_elt.classList.add('state_appended'), 0)
        for cancel_elt in notif_elt.select(".click_to_cancel"):
            cancel_elt.bind("click", lambda evt: cancel_cb(evt, notif_elt))
        for cancel_elt in notif_elt.select(".click_to_ok"):
            cancel_elt.bind("click", lambda evt: ok_cb(evt, notif_elt))

    def _ashow_cb(self, evt, notif_elt, resolve_cb, confirmed):
        evt.stopPropagation()
        notif_elt.remove()
        resolve_cb(confirmed)

    async def ashow(self):
        return window.Promise.new(
            lambda resolve_cb, reject_cb:
            self.show(
                lambda evt, notif_elt: self._ashow_cb(evt, notif_elt, resolve_cb, True),
                lambda evt, notif_elt: self._ashow_cb(evt, notif_elt, resolve_cb, False)
            )
        )


class Notification:

    def __init__(self):
        self._tpl = Template("dialogs/notification.html")

    def close(self, notif_elt):
        notif_elt.classList.remove('state_appended')
        notif_elt.bind("transitionend", lambda __: notif_elt.remove())

    def show(
        self,
        message: str,
        level: str = "info",
        delay: int = 5
    ) -> None:
        # we log in console error messages, may be useful
        if level in ("warning", "error"):
            print(f"[{level}] {message}")
        notif_elt = self._tpl.get_elt({
            "message": message,
            "level": level,
        })
        document["notifs_area"] <= notif_elt
        timer.set_timeout(lambda: notif_elt.classList.add('state_appended'), 0)
        timer.set_timeout(lambda: self.close(notif_elt), delay * 1000)
        for elt in notif_elt.select('.click_to_close'):
            elt.bind('click', lambda __: self.close(notif_elt))


class RetryNotification:
    def __init__(self, retry_cb):
        self._tpl = Template("dialogs/retry-notification.html")
        self.retry_cb = retry_cb
        self.counter = 0
        self.timer = None

    def retry(self, notif_elt):
        if self.timer is not None:
            timer.clear_interval(self.timer)
            self.timer = None
        notif_elt.classList.remove('state_appended')
        notif_elt.bind("transitionend", lambda __: notif_elt.remove())
        self.retry_cb()

    def update_counter(self, notif_elt):
        counter = notif_elt.select_one(".retry_counter")
        counter.text = str(self.counter)
        self.counter -= 1
        if self.counter < 0:
            self.retry(notif_elt)

    def show(
        self,
        message: str,
        level: str = "warning",
        delay: int = 5
    ) -> None:
        # we log in console error messages, may be useful
        if level == "error":
            log.error(message)
        elif level == "warning":
            log.warning(message)
        self.counter = delay
        notif_elt = self._tpl.get_elt({
            "message": message,
            "level": level,
        })
        self.update_counter(notif_elt)
        document["notifs_area"] <= notif_elt
        timer.set_timeout(lambda: notif_elt.classList.add('state_appended'), 0)
        self.timer = timer.set_interval(self.update_counter, 1000, notif_elt)
        for elt in notif_elt.select('.click_to_retry'):
            elt.bind('click', lambda __: self.retry(notif_elt))




notification = Notification()