This repository has been archived by the owner on May 5, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add checktable widget
- Loading branch information
Showing
6 changed files
with
176 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
from typing import Any, Dict, List, Optional, TypeVar, Generic, Union | ||
|
||
from botx import Bot, Message, MessageMarkup | ||
from pydantic import root_validator, BaseModel | ||
|
||
from pybotx_widgets.resources import strings | ||
from pybotx_widgets.service import merge_markup, send_or_update_message | ||
from pybotx_widgets.undefined import Undefined, undefined | ||
|
||
T = TypeVar("T") # noqa: WPS111 | ||
|
||
|
||
class CheckboxContent(BaseModel, Generic[T]): | ||
"""Checkbox content.""" | ||
|
||
#: text that will be shown on the element. | ||
label: str | ||
#: command that will be triggered by click on the element. | ||
command: str | ||
#: value which will be displayed on the button associated with this checkbox. | ||
checkbox_value: Optional[Union[T, Undefined]] = undefined | ||
#: list of available values. | ||
mapping: Optional[Dict[T, str]] = None | ||
#: extra payload that will be stored in button and then received in new message. | ||
data: Optional[Dict[str, Any]] = None | ||
|
||
class Config: | ||
arbitrary_types_allowed = True | ||
|
||
@root_validator(pre=True) | ||
def is_checkbox_value_exist_in_mapping(cls, values): | ||
mapping = values.get("mapping") | ||
checkbox_value = values.get("checkbox_value") | ||
if ( | ||
mapping | ||
and not isinstance(checkbox_value, Undefined) | ||
and checkbox_value not in mapping | ||
): | ||
raise ValueError( | ||
f"'mapping' should contains 'checkbox_value' - '{checkbox_value}'" | ||
) | ||
|
||
return values | ||
|
||
|
||
def get_value_text(checkbox: CheckboxContent) -> str: | ||
"""Get value text for button.""" | ||
if checkbox.checkbox_value is None: | ||
return strings.EMPTY | ||
|
||
is_undefined = isinstance(checkbox.checkbox_value, Undefined) | ||
|
||
if checkbox.mapping: | ||
if is_undefined: | ||
return strings.CHOOSE_LABEL | ||
return checkbox.mapping[checkbox.checkbox_value] | ||
|
||
if is_undefined: | ||
return strings.FILL_LABEL | ||
|
||
return checkbox.checkbox_value | ||
|
||
|
||
def add_checkboxes(checkboxes: List[CheckboxContent], uncheck_command: str) -> MessageMarkup: | ||
"""Add checkbox.""" | ||
markup = MessageMarkup() | ||
|
||
for checkbox in checkboxes: | ||
checkbox.data = checkbox.data or {} | ||
|
||
if isinstance(checkbox.checkbox_value, Undefined): | ||
checkbox_status = strings.CHECKBOX_UNCHECKED | ||
else: | ||
checkbox_status = strings.CHECKBOX_CHECKED | ||
|
||
checkbox_text = f"{checkbox_status} {checkbox.label}" | ||
|
||
value_text = get_value_text(checkbox) | ||
|
||
markup.add_bubble(uncheck_command, checkbox_text, data=checkbox.data) | ||
markup.add_bubble( | ||
checkbox.command, value_text, new_row=False, data=checkbox.data | ||
) | ||
|
||
return markup | ||
|
||
|
||
async def checktable( | ||
message: Message, | ||
bot: Bot, | ||
checkboxes: List[CheckboxContent], | ||
label: str, | ||
uncheck_command: str, | ||
additional_markup: MessageMarkup = None, | ||
) -> None: | ||
"""Create checktable widget. | ||
:param message - botx Message | ||
:param bot - botx Bot | ||
:param checkboxes - All content to be displayed | ||
:param label - Text of message | ||
:param uncheck_command - Command for handler which uncheck value | ||
:param additional_markup - Additional markup for attaching to widget | ||
""" | ||
|
||
markup = add_checkboxes(checkboxes, uncheck_command) | ||
|
||
if additional_markup: | ||
markup = merge_markup(markup, additional_markup) | ||
|
||
await send_or_update_message(message, bot, label, markup) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
"""Singleton for `undefined` value.""" | ||
from functools import lru_cache | ||
|
||
|
||
class Undefined: | ||
@lru_cache() | ||
def __new__(cls) -> "Undefined": | ||
return super().__new__(cls) | ||
|
||
|
||
undefined = Undefined() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters