from dataclasses import dataclass
from typing import Union, List
from enum import Enum
from q2_sdk.tools.utils import linarize_string
[docs]
class ModalType(Enum):
"""Enumeration for TectonModal modal_type"""
ERROR = "error" #: Displays a modal with a red exclamation mark in a triangle
INFO = "info" #: Displays a modal with a "i" in a circle colored with the FI's primary color
SUCCESS = "success" #: Displays a modal with a green check mark in a circle
WARNING = "warning" #: Displays a modal with a yellow exclamation mark in a circle
[docs]
class ModalAction:
"""
Defines Modal Action class if needing to redirect from a modal or supply custom hook that will be executed
where a button on the modal is clicked.
"""
def __init__(
self,
action_label: str,
external_route: str = "",
internal_route: str = "",
custom_action_hook=None,
):
"""
:param action_label: label for action button
:param external_route: redirect to destinations within the Q2 application (e.g. activityCenter);
will not be used if custom_action_hook is defined
:param internal_route: routing key for the desired extension route destination on modal close. will remain on
current route if empty.
Can not be used in conjuction with custom_action_hook.
:param custom_action_hook: custom JS function name to be executed when the action is clicked
function needs to be defined in Q2Form.custom_javascript. If function not available, will default to just
redirecting to the landing page
"""
assert not (
external_route and internal_route
), """Modal action cannot have both external_route and
internal_route parameters. Use internal_route for routing inside your extension, or external_route to for
another location within the q2 application."""
self.name = action_label
self.external_route = external_route
self.internal_route = internal_route
if self.external_route:
self.custom_action = "externalRoute"
self.redirect_target = self.external_route
elif self.internal_route:
self.custom_action = "internalRoute"
self.redirect_target = self.internal_route
else:
self.custom_action = custom_action_hook
[docs]
class Modal:
"""Parent class for displaying Q2 Compliant modals in the Q2 Online interface"""
def __init__(
self,
modal_type: ModalType,
title: str,
message="",
modal_actions: Union[ModalAction, List[ModalAction]] = None,
show_close=True,
**kwargs,
):
"""
:param modal_type: success, error, warning
:param title: modal title to be displayed
:param message: modal message to be displayed
:param modal_actions: Custom buttons for routing to external or internal routes or executing custom JS functions.
:param show_close: show default close button (true/false) when custom buttons are added. this button will always close
modal and remain on current route, and always reads "Close"
"""
if isinstance(modal_type, ModalType):
modal_type = modal_type.value
self.type = modal_type
self.title = title
self.message = linarize_string(message)
self.show_close = "true" if show_close else "false"
self.modal_actions = False
if isinstance(modal_actions, ModalAction):
self.modal_actions = [modal_actions]
elif kwargs.get("modal_action"):
self.modal_actions = [kwargs.get("modal_action")]
else:
self.modal_actions = modal_actions
if self.modal_actions:
msg = f"Modal only supports three actions, {len(self.modal_actions)} were declared."
assert len(self.modal_actions) <= 3, msg
if self.modal_actions:
self.modal_actions = [vars(a) for a in self.modal_actions]
[docs]
@dataclass
class TransRow:
label: str
value: str
[docs]
class TectonModal(Modal):
"""Parent class for displaying Tecton Compliant modals in the Q2 Online interface"""
def __init__(
self,
modal_type: ModalType,
title: str,
message="",
modal_actions: Union[ModalAction, List[ModalAction]] = None,
show_close=True,
is_blocking=False,
trans_info: List[TransRow] = None,
info_list: List[str] = None,
addl_info: str = None,
custom_markup: str = None,
**kwargs,
):
"""
:param modal_type: success, error, warning, info
:param title: modal title to be displayed
:param message: modal message to be displayed
:param modal_actions: Custom buttons for routing to external or internal routes or executing custom JS functions.
:param show_close: show default close button (true/false) when custom buttons are added. this button will always close
modal and remain on current route, and always reads "Close"
:param is_blocking: Disables the X or equivalent that allows the modal to be closed, forcing the user to
make a choice to close the modal.
:param trans_info: List of TransRow items to show in a structured label: value list
:param info_list: List of str to show in a list
:param addl_info: str that is displayed below the message, transInfo, and infoList content.
:param custom_markup: str that is displayed below the message but before transInfo.
"""
self.trans_info = trans_info
self.info_list = info_list
self.addl_info = addl_info
self.custom_markup = custom_markup.replace("'", r"\'") if custom_markup else ""
self.is_blocking = is_blocking
if kwargs.get("close") is not None:
show_close = kwargs["close"]
super().__init__(
modal_type, title, message, modal_actions, show_close=show_close, **kwargs
)
[docs]
class SuccessModal(Modal):
"""Returns a success code to Online with green checkmark to the user"""
def __init__(
self,
title,
message,
modal_actions: Union[ModalAction, List[ModalAction]] = None,
show_close=True,
**kwargs,
):
super().__init__(
ModalType.SUCCESS,
title,
message,
modal_actions=modal_actions,
show_close=show_close,
**kwargs,
)
[docs]
class ErrorModal(Modal):
"""Returns an error code to Online with red error icon to the user"""
def __init__(
self,
title,
message,
modal_actions: Union[ModalAction, List[ModalAction]] = None,
show_close=True,
**kwargs,
):
super().__init__(
ModalType.ERROR,
title,
message,
modal_actions=modal_actions,
show_close=show_close,
**kwargs,
)
[docs]
class WarningModal(Modal):
"""Returns modal with orange warning icon to the user"""
def __init__(
self,
title,
message,
modal_actions: Union[ModalAction, List[ModalAction]] = None,
show_close=True,
**kwargs,
):
super().__init__(
ModalType.WARNING,
title,
message,
modal_actions=modal_actions,
show_close=show_close,
**kwargs,
)
[docs]
class InfoModal(Modal):
"""Returns modal with orange warning icon to the user"""
def __init__(
self,
title,
message,
modal_actions: Union[ModalAction, List[ModalAction]] = None,
show_close=True,
**kwargs,
):
super().__init__(
ModalType.INFO,
title,
message,
modal_actions=modal_actions,
show_close=show_close,
**kwargs,
)