add visibility delegates for fields in edit form
This commit is contained in:
@@ -5,7 +5,7 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from babel.support import LazyProxy
|
||||
from logging import getLogger
|
||||
|
||||
from ....model.descriptors import FieldDescriptor
|
||||
from ....model.descriptors import BotContext, FieldDescriptor
|
||||
from ....model.user import UserBase
|
||||
from ..context import ContextData, CallbackCommand
|
||||
from ....utils.main import get_send_message
|
||||
@@ -67,12 +67,20 @@ async def bool_editor(
|
||||
|
||||
state_data = kwargs["state_data"]
|
||||
|
||||
context = BotContext(
|
||||
db_session=kwargs["db_session"],
|
||||
app=kwargs["app"],
|
||||
app_state=kwargs["app_state"],
|
||||
message=message,
|
||||
)
|
||||
|
||||
await wrap_editor(
|
||||
keyboard_builder=keyboard_builder,
|
||||
field_descriptor=field_descriptor,
|
||||
callback_data=callback_data,
|
||||
state_data=state_data,
|
||||
user=user,
|
||||
context=context,
|
||||
)
|
||||
|
||||
state: FSMContext = kwargs["state"]
|
||||
|
||||
@@ -6,7 +6,7 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from logging import getLogger
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ....model.descriptors import FieldDescriptor
|
||||
from ....model.descriptors import BotContext, FieldDescriptor
|
||||
from ....model.settings import Settings
|
||||
from ....model.user import UserBase
|
||||
from ..context import ContextData, CallbackCommand
|
||||
@@ -158,6 +158,12 @@ async def time_picker(
|
||||
)
|
||||
|
||||
state_data = kwargs["state_data"]
|
||||
context = BotContext(
|
||||
db_session=kwargs["db_session"],
|
||||
app=kwargs["app"],
|
||||
app_state=kwargs["app_state"],
|
||||
message=message,
|
||||
)
|
||||
|
||||
await wrap_editor(
|
||||
keyboard_builder=keyboard_builder,
|
||||
@@ -165,6 +171,7 @@ async def time_picker(
|
||||
callback_data=callback_data,
|
||||
state_data=state_data,
|
||||
user=user,
|
||||
context=context,
|
||||
)
|
||||
|
||||
await state.set_data(state_data)
|
||||
@@ -272,12 +279,20 @@ async def date_picker(
|
||||
|
||||
state_data = kwargs["state_data"]
|
||||
|
||||
context = BotContext(
|
||||
db_session=kwargs["db_session"],
|
||||
app=kwargs["app"],
|
||||
app_state=kwargs["app_state"],
|
||||
message=message,
|
||||
)
|
||||
|
||||
await wrap_editor(
|
||||
keyboard_builder=keyboard_builder,
|
||||
field_descriptor=field_descriptor,
|
||||
callback_data=callback_data,
|
||||
state_data=state_data,
|
||||
user=user,
|
||||
context=context,
|
||||
)
|
||||
|
||||
await state.set_data(state_data)
|
||||
@@ -295,11 +310,11 @@ async def date_picker(
|
||||
async def date_picker_year(
|
||||
query: CallbackQuery,
|
||||
callback_data: ContextData,
|
||||
app: "QBotApp",
|
||||
state: FSMContext,
|
||||
user: UserBase,
|
||||
**kwargs,
|
||||
):
|
||||
app: "QBotApp" = kwargs["app"]
|
||||
start_date = datetime.strptime(callback_data.data, "%Y-%m-%d %H-%M")
|
||||
|
||||
state_data = await state.get_data()
|
||||
@@ -366,12 +381,20 @@ async def date_picker_year(
|
||||
|
||||
field_descriptor = get_field_descriptor(app, callback_data)
|
||||
|
||||
context = BotContext(
|
||||
db_session=kwargs["db_session"],
|
||||
app=app,
|
||||
app_state=kwargs["app_state"],
|
||||
message=query,
|
||||
)
|
||||
|
||||
await wrap_editor(
|
||||
keyboard_builder=keyboard_builder,
|
||||
field_descriptor=field_descriptor,
|
||||
callback_data=callback_data,
|
||||
state_data=state_data,
|
||||
user=user,
|
||||
context=context,
|
||||
)
|
||||
|
||||
await query.message.edit_reply_markup(reply_markup=keyboard_builder.as_markup())
|
||||
@@ -380,9 +403,8 @@ async def date_picker_year(
|
||||
@router.callback_query(
|
||||
ContextData.filter(F.command == CallbackCommand.DATE_PICKER_MONTH)
|
||||
)
|
||||
async def date_picker_month(
|
||||
query: CallbackQuery, callback_data: ContextData, app: "QBotApp", **kwargs
|
||||
):
|
||||
async def date_picker_month(query: CallbackQuery, callback_data: ContextData, **kwargs):
|
||||
app: "QBotApp" = kwargs["app"]
|
||||
field_descriptor = get_field_descriptor(app, callback_data)
|
||||
state: FSMContext = kwargs["state"]
|
||||
state_data = await state.get_data()
|
||||
|
||||
@@ -293,12 +293,20 @@ async def render_entity_picker(
|
||||
|
||||
state_data = kwargs["state_data"]
|
||||
|
||||
context = BotContext(
|
||||
db_session=db_session,
|
||||
app=kwargs["app"],
|
||||
app_state=kwargs["app_state"],
|
||||
message=message,
|
||||
)
|
||||
|
||||
await wrap_editor(
|
||||
keyboard_builder=keyboard_builder,
|
||||
field_descriptor=field_descriptor,
|
||||
callback_data=callback_data,
|
||||
state_data=state_data,
|
||||
user=user,
|
||||
context=context,
|
||||
)
|
||||
|
||||
await state.set_data(state_data)
|
||||
|
||||
@@ -5,12 +5,13 @@ from aiogram.types import Message, CallbackQuery
|
||||
from logging import getLogger
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
from quickbot.model.descriptors import EntityForm
|
||||
from quickbot.model.descriptors import BotContext, EntityForm
|
||||
|
||||
from ....model import EntityPermission
|
||||
from ....model.settings import Settings
|
||||
from ....model.user import UserBase
|
||||
from ....utils.main import (
|
||||
build_field_sequence,
|
||||
check_entity_permission,
|
||||
get_field_descriptor,
|
||||
)
|
||||
@@ -134,6 +135,22 @@ async def field_editor(message: Message | CallbackQuery, **kwargs):
|
||||
form: EntityForm = entity_descriptor.forms.get(
|
||||
form_name, entity_descriptor.default_form
|
||||
)
|
||||
if form.edit_field_sequence:
|
||||
field_sequence = form.edit_field_sequence
|
||||
else:
|
||||
context = BotContext(
|
||||
db_session=db_session,
|
||||
app=app,
|
||||
app_state=kwargs["app_state"],
|
||||
message=message,
|
||||
)
|
||||
field_sequence = await build_field_sequence(
|
||||
entity_descriptor=entity_descriptor,
|
||||
user=user,
|
||||
callback_data=callback_data,
|
||||
state_data=state_data,
|
||||
context=context,
|
||||
)
|
||||
entity_data = {
|
||||
key: serialize(
|
||||
getattr(
|
||||
@@ -143,7 +160,7 @@ async def field_editor(message: Message | CallbackQuery, **kwargs):
|
||||
entity_descriptor.fields_descriptors[key],
|
||||
)
|
||||
for key in (
|
||||
form.edit_field_sequence
|
||||
field_sequence
|
||||
if callback_data.context == CommandContext.ENTITY_EDIT
|
||||
else [callback_data.field_name]
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ from aiogram import Router, F
|
||||
from aiogram.types import Message, CallbackQuery
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from decimal import Decimal
|
||||
import json
|
||||
|
||||
@@ -39,6 +39,26 @@ if TYPE_CHECKING:
|
||||
router = Router()
|
||||
|
||||
|
||||
async def _validate_value(
|
||||
field_descriptor: FieldDescriptor,
|
||||
value: Any,
|
||||
message: Message | CallbackQuery,
|
||||
**kwargs: Any,
|
||||
) -> bool | str:
|
||||
if field_descriptor.validator:
|
||||
context = BotContext(
|
||||
db_session=kwargs["db_session"],
|
||||
app=kwargs["app"],
|
||||
app_state=kwargs["app_state"],
|
||||
message=message,
|
||||
)
|
||||
if iscoroutinefunction(field_descriptor.validator):
|
||||
return await field_descriptor.validator(value, context)
|
||||
else:
|
||||
return field_descriptor.validator(value, context)
|
||||
return True
|
||||
|
||||
|
||||
@router.message(CallbackCommandFilter(CallbackCommand.FIELD_EDITOR_CALLBACK))
|
||||
@router.callback_query(
|
||||
ContextData.filter(F.command == CallbackCommand.FIELD_EDITOR_CALLBACK)
|
||||
@@ -59,6 +79,39 @@ async def field_editor_callback(message: Message | CallbackQuery, **kwargs):
|
||||
field_descriptor = get_field_descriptor(app, callback_data)
|
||||
type_base = field_descriptor.type_base
|
||||
|
||||
if type_base in [int, float, Decimal]:
|
||||
try:
|
||||
val = type_base(value) # @IgnoreException
|
||||
except Exception:
|
||||
return await message.answer(
|
||||
text=(await Settings.get(Settings.APP_STRINGS_INVALID_INPUT))
|
||||
)
|
||||
elif type_base is str and field_descriptor.localizable:
|
||||
locale_index = int(state_data.get("locale_index"))
|
||||
val = {
|
||||
list(LanguageBase.all_members.values())[
|
||||
locale_index
|
||||
].value: message.text
|
||||
}
|
||||
else:
|
||||
val = value
|
||||
|
||||
validation_result = await _validate_value(
|
||||
field_descriptor=field_descriptor,
|
||||
value=val,
|
||||
message=message,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
if isinstance(validation_result, str):
|
||||
return await message.answer(
|
||||
text=f"{await Settings.get(Settings.APP_STRINGS_INVALID_INPUT)}\n{validation_result}"
|
||||
)
|
||||
elif not validation_result:
|
||||
return await message.answer(
|
||||
text=(await Settings.get(Settings.APP_STRINGS_INVALID_INPUT))
|
||||
)
|
||||
|
||||
if type_base is str and field_descriptor.localizable:
|
||||
locale_index = int(state_data.get("locale_index"))
|
||||
|
||||
@@ -90,13 +143,6 @@ async def field_editor_callback(message: Message | CallbackQuery, **kwargs):
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
elif type_base in [int, float, Decimal]:
|
||||
try:
|
||||
_ = type_base(value) # @IgnoreException
|
||||
except Exception:
|
||||
return await message.answer(
|
||||
text=(await Settings.get(Settings.APP_STRINGS_INVALID_INPUT))
|
||||
)
|
||||
else:
|
||||
callback_data: ContextData = kwargs["callback_data"]
|
||||
if callback_data.data:
|
||||
@@ -150,6 +196,9 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
||||
app: "QBotApp" = kwargs["app"]
|
||||
entity_descriptor = get_entity_descriptor(app, callback_data)
|
||||
|
||||
entity_data = state_data.get("entity_data", {})
|
||||
entity_data[field_descriptor.field_name] = value
|
||||
|
||||
if callback_data.context == CommandContext.COMMAND_FORM:
|
||||
field_sequence = list(field_descriptor.command.param_form.keys())
|
||||
current_index = field_sequence.index(callback_data.field_name)
|
||||
@@ -167,11 +216,18 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
||||
if form.edit_field_sequence:
|
||||
field_sequence = form.edit_field_sequence
|
||||
else:
|
||||
field_sequence = build_field_sequence(
|
||||
context = BotContext(
|
||||
db_session=kwargs["db_session"],
|
||||
app=kwargs["app"],
|
||||
app_state=kwargs["app_state"],
|
||||
message=message,
|
||||
)
|
||||
field_sequence = await build_field_sequence(
|
||||
entity_descriptor=entity_descriptor,
|
||||
user=user,
|
||||
callback_data=callback_data,
|
||||
state_data=state_data,
|
||||
context=context,
|
||||
)
|
||||
|
||||
current_index = (
|
||||
@@ -182,8 +238,6 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
||||
)
|
||||
field_descriptors = entity_descriptor.fields_descriptors
|
||||
|
||||
entity_data = state_data.get("entity_data", {})
|
||||
|
||||
if callback_data.context == CommandContext.ENTITY_CREATE:
|
||||
stack = state_data.get("navigation_stack", [])
|
||||
prev_callback_data = ContextData.unpack(stack[-1]) if stack else None
|
||||
@@ -224,7 +278,7 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
||||
]
|
||||
and current_index < len(field_sequence) - 1
|
||||
):
|
||||
entity_data[field_descriptor.field_name] = value
|
||||
# entity_data[field_descriptor.field_name] = value
|
||||
state_data.update({"entity_data": entity_data})
|
||||
|
||||
next_field_name = field_sequence[current_index + 1]
|
||||
@@ -252,7 +306,7 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
||||
)
|
||||
|
||||
else:
|
||||
entity_data[field_descriptor.name] = value
|
||||
# entity_data[field_descriptor.field_name] = value
|
||||
|
||||
# What if user has several roles and each role has its own ownership field? Should we allow creation even
|
||||
# if user has no CREATE_ALL permission
|
||||
|
||||
@@ -5,7 +5,7 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from logging import getLogger
|
||||
from typing import Any
|
||||
|
||||
from ....model.descriptors import FieldDescriptor
|
||||
from ....model.descriptors import BotContext, FieldDescriptor
|
||||
from ....model.language import LanguageBase
|
||||
from ....model.settings import Settings
|
||||
from ....model.user import UserBase
|
||||
@@ -87,12 +87,20 @@ async def string_editor(
|
||||
|
||||
state_data = kwargs["state_data"]
|
||||
|
||||
context = BotContext(
|
||||
db_session=kwargs["db_session"],
|
||||
app=kwargs["app"],
|
||||
app_state=kwargs["app_state"],
|
||||
message=message,
|
||||
)
|
||||
|
||||
await wrap_editor(
|
||||
keyboard_builder=keyboard_builder,
|
||||
field_descriptor=field_descriptor,
|
||||
callback_data=callback_data,
|
||||
state_data=state_data,
|
||||
user=user,
|
||||
context=context,
|
||||
)
|
||||
|
||||
await state.set_data(state_data)
|
||||
|
||||
@@ -2,7 +2,7 @@ from aiogram.types import InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from ....model.settings import Settings
|
||||
from ....model.descriptors import EntityForm, FieldDescriptor
|
||||
from ....model.descriptors import BotContext, EntityForm, FieldDescriptor
|
||||
from ....model.user import UserBase
|
||||
from ..context import ContextData, CallbackCommand, CommandContext
|
||||
from ....utils.navigation import get_navigation_context, pop_navigation_context
|
||||
@@ -15,6 +15,7 @@ async def wrap_editor(
|
||||
callback_data: ContextData,
|
||||
state_data: dict,
|
||||
user: UserBase,
|
||||
context: BotContext,
|
||||
):
|
||||
if callback_data.context in [
|
||||
CommandContext.ENTITY_CREATE,
|
||||
@@ -42,11 +43,12 @@ async def wrap_editor(
|
||||
if form.edit_field_sequence:
|
||||
field_sequence = form.edit_field_sequence
|
||||
else:
|
||||
field_sequence = build_field_sequence(
|
||||
field_sequence = await build_field_sequence(
|
||||
entity_descriptor=field_descriptor.entity_descriptor,
|
||||
user=user,
|
||||
callback_data=callback_data,
|
||||
state_data=state_data,
|
||||
context=context,
|
||||
)
|
||||
field_index = (
|
||||
field_sequence.index(field_descriptor.name)
|
||||
|
||||
@@ -208,11 +208,12 @@ async def entity_item(
|
||||
if form.edit_field_sequence:
|
||||
field_sequence = form.edit_field_sequence
|
||||
else:
|
||||
field_sequence = build_field_sequence(
|
||||
field_sequence = await build_field_sequence(
|
||||
entity_descriptor=entity_descriptor,
|
||||
user=user,
|
||||
callback_data=callback_data,
|
||||
state_data=state_data,
|
||||
context=context,
|
||||
)
|
||||
edit_delete_row.append(
|
||||
InlineKeyboardButton(
|
||||
@@ -314,6 +315,16 @@ async def entity_item(
|
||||
if skip:
|
||||
continue
|
||||
|
||||
if field_descriptor.caption_value:
|
||||
item_text += f"\n{
|
||||
await get_callable_str(
|
||||
callable_str=field_descriptor.caption_value,
|
||||
context=context,
|
||||
descriptor=field_descriptor,
|
||||
entity=entity_item,
|
||||
)
|
||||
}"
|
||||
else:
|
||||
field_caption = (
|
||||
await get_callable_str(
|
||||
callable_str=field_descriptor.caption,
|
||||
@@ -323,14 +334,6 @@ async def entity_item(
|
||||
if field_descriptor.caption
|
||||
else field_descriptor.field_name
|
||||
)
|
||||
if field_descriptor.caption_value:
|
||||
value = await get_callable_str(
|
||||
callable_str=field_descriptor.caption_value,
|
||||
context=context,
|
||||
descriptor=field_descriptor,
|
||||
entity=entity_item,
|
||||
)
|
||||
else:
|
||||
value = await get_value_repr(
|
||||
value=getattr(entity_item, field_descriptor.field_name),
|
||||
field_descriptor=field_descriptor,
|
||||
|
||||
@@ -118,6 +118,12 @@ async def entity_list(
|
||||
)
|
||||
|
||||
keyboard_builder = InlineKeyboardBuilder()
|
||||
context = BotContext(
|
||||
db_session=db_session,
|
||||
app=app,
|
||||
app_state=kwargs["app_state"],
|
||||
message=message,
|
||||
)
|
||||
|
||||
if (
|
||||
EntityPermission.CREATE in user_permissions
|
||||
@@ -126,11 +132,12 @@ async def entity_list(
|
||||
if form_item.edit_field_sequence:
|
||||
field_sequence = form_item.edit_field_sequence
|
||||
else:
|
||||
field_sequence = build_field_sequence(
|
||||
field_sequence = await build_field_sequence(
|
||||
entity_descriptor=entity_descriptor,
|
||||
user=user,
|
||||
callback_data=callback_data,
|
||||
state_data=kwargs["state_data"],
|
||||
context=context,
|
||||
)
|
||||
keyboard_builder.row(
|
||||
InlineKeyboardButton(
|
||||
@@ -206,13 +213,6 @@ async def entity_list(
|
||||
total_pages = 1
|
||||
page = 1
|
||||
|
||||
context = BotContext(
|
||||
db_session=db_session,
|
||||
app=app,
|
||||
app_state=kwargs["app_state"],
|
||||
message=message,
|
||||
)
|
||||
|
||||
for item in items:
|
||||
caption = None
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ async def cammand_handler(message: Message | CallbackQuery, cmd: BotCommand, **k
|
||||
db_session=kwargs["db_session"],
|
||||
user=kwargs["user"],
|
||||
app=app,
|
||||
app_state=kwargs["app_state"],
|
||||
state_data=state_data,
|
||||
state=state,
|
||||
i18n=kwargs["i18n"],
|
||||
|
||||
@@ -161,6 +161,7 @@ class QBotApp(Generic[UserType, ConfigType], FastAPI):
|
||||
)
|
||||
else:
|
||||
for locale, description in command.caption.items():
|
||||
locale = "default" if locale == "en" else locale
|
||||
if locale not in commands_captions:
|
||||
commands_captions[locale] = []
|
||||
commands_captions[locale].append((command_name, description))
|
||||
|
||||
@@ -31,7 +31,7 @@ class FieldEditButton:
|
||||
|
||||
@dataclass
|
||||
class CommandButton:
|
||||
command: ContextData | Callable[[ContextData, Any], ContextData] | str
|
||||
command: ContextData | Callable[["BotEntity", "BotContext"], ContextData] | str
|
||||
caption: str | LazyProxy | Callable[["BotEntity", "BotContext"], str] | None = None
|
||||
visibility: Callable[["BotEntity", "BotContext"], bool] | None = None
|
||||
|
||||
@@ -113,6 +113,12 @@ class _BaseFieldDescriptor:
|
||||
is_visible: (
|
||||
bool | Callable[["FieldDescriptor", "BotEntity", "BotContext"], bool] | None
|
||||
) = None
|
||||
is_visible_in_edit_form: (
|
||||
bool
|
||||
| Callable[["FieldDescriptor", Union["BotEntity", Any], "BotContext"], bool]
|
||||
| None
|
||||
) = None
|
||||
validator: Callable[[Any, "BotContext"], Union[bool, str]] | None = None
|
||||
localizable: bool = False
|
||||
bool_false_value: str | LazyProxy = "no"
|
||||
bool_true_value: str | LazyProxy = "yes"
|
||||
@@ -219,6 +225,7 @@ class CommandCallbackContext[UT: UserBase]:
|
||||
db_session: AsyncSession
|
||||
user: UT
|
||||
app: "QBotApp"
|
||||
app_state: State
|
||||
state_data: dict[str, Any]
|
||||
state: FSMContext
|
||||
form_data: dict[str, Any]
|
||||
|
||||
@@ -2,6 +2,7 @@ from types import NoneType, UnionType
|
||||
from aiogram.utils.i18n.context import get_i18n
|
||||
from datetime import datetime
|
||||
from sqlmodel import SQLModel, Field, select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
from typing import Any, get_args, get_origin
|
||||
|
||||
from ..db import async_session
|
||||
@@ -193,11 +194,23 @@ class Settings(metaclass=SettingsMetaclass):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def get[T](cls, param: T, all_locales=False, locale: str = None) -> T:
|
||||
async def get[T](
|
||||
cls,
|
||||
param: T,
|
||||
session: AsyncSession = None,
|
||||
all_locales=False,
|
||||
locale: str = None,
|
||||
) -> T:
|
||||
name = param.field_name
|
||||
|
||||
if name not in cls._cache.keys():
|
||||
cls._cache[name] = await cls.load_param(param)
|
||||
if session is None:
|
||||
async with async_session() as session:
|
||||
cls._cache[name] = await cls.load_param(
|
||||
session=session, param=param
|
||||
)
|
||||
else:
|
||||
cls._cache[name] = await cls.load_param(session=session, param=param)
|
||||
|
||||
ret_val = cls._cache[name]
|
||||
|
||||
@@ -213,8 +226,7 @@ class Settings(metaclass=SettingsMetaclass):
|
||||
return ret_val
|
||||
|
||||
@classmethod
|
||||
async def load_param(cls, param: FieldDescriptor) -> Any:
|
||||
async with async_session() as session:
|
||||
async def load_param(cls, session: AsyncSession, param: FieldDescriptor) -> Any:
|
||||
db_setting = (
|
||||
await session.exec(
|
||||
select(DbSettings).where(DbSettings.name == param.field_name)
|
||||
@@ -240,20 +252,20 @@ class Settings(metaclass=SettingsMetaclass):
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def load_params(cls):
|
||||
async with async_session() as session:
|
||||
db_settings = (await session.exec(select(DbSettings))).all()
|
||||
for db_setting in db_settings:
|
||||
if db_setting.name in cls.__dict__:
|
||||
setting = cls.__dict__[db_setting.name] # type: FieldDescriptor
|
||||
cls._cache[db_setting.name] = await deserialize(
|
||||
session=session,
|
||||
type_=setting.type_,
|
||||
value=db_setting.value,
|
||||
)
|
||||
# @classmethod
|
||||
# async def load_params(cls):
|
||||
# async with async_session() as session:
|
||||
# db_settings = (await session.exec(select(DbSettings))).all()
|
||||
# for db_setting in db_settings:
|
||||
# if db_setting.name in cls.__dict__:
|
||||
# setting = cls.__dict__[db_setting.name] # type: FieldDescriptor
|
||||
# cls._cache[db_setting.name] = await deserialize(
|
||||
# session=session,
|
||||
# type_=setting.type_,
|
||||
# value=db_setting.value,
|
||||
# )
|
||||
|
||||
cls._loaded = True
|
||||
# cls._loaded = True
|
||||
|
||||
@classmethod
|
||||
async def set_param(cls, param: str | FieldDescriptor, value) -> None:
|
||||
|
||||
@@ -15,6 +15,7 @@ from ..model.descriptors import (
|
||||
FieldDescriptor,
|
||||
EntityDescriptor,
|
||||
EntityPermission,
|
||||
_BaseFieldDescriptor,
|
||||
)
|
||||
|
||||
from ..bot.handlers.context import CallbackCommand, ContextData, CommandContext
|
||||
@@ -198,10 +199,13 @@ async def get_callable_str(
|
||||
if len(args) == 3:
|
||||
return await callable_str(descriptor, entity, context)
|
||||
else:
|
||||
if issubclass(args[0].annotation, BotEntity):
|
||||
return await callable_str(entity, context)
|
||||
else:
|
||||
param = args[next(iter(args))]
|
||||
if not isinstance(param.annotation, str) and issubclass(
|
||||
param.annotation, _BaseFieldDescriptor
|
||||
):
|
||||
return await callable_str(descriptor, context)
|
||||
else:
|
||||
return await callable_str(entity, context)
|
||||
else:
|
||||
if len(args) == 3:
|
||||
return callable_str(descriptor, entity, context)
|
||||
@@ -245,11 +249,12 @@ def get_field_descriptor(
|
||||
return None
|
||||
|
||||
|
||||
def build_field_sequence(
|
||||
async def build_field_sequence(
|
||||
entity_descriptor: EntityDescriptor,
|
||||
user: "UserBase",
|
||||
callback_data: ContextData,
|
||||
state_data: dict,
|
||||
context: BotContext,
|
||||
):
|
||||
prev_form_list = None
|
||||
|
||||
@@ -269,10 +274,20 @@ def build_field_sequence(
|
||||
prev_form_name, entity_descriptor.default_list
|
||||
)
|
||||
|
||||
entity_data = state_data.get("entity_data", {})
|
||||
|
||||
field_sequence = list[str]()
|
||||
# exclude ownership fields from edit if user has no CREATE_ALL/UPDATE_ALL permission
|
||||
user_permissions = get_user_permissions(user, entity_descriptor)
|
||||
for fd in entity_descriptor.fields_descriptors.values():
|
||||
if isinstance(fd.is_visible_in_edit_form, bool):
|
||||
skip = not fd.is_visible_in_edit_form
|
||||
elif callable(fd.is_visible_in_edit_form):
|
||||
if iscoroutinefunction(fd.is_visible_in_edit_form):
|
||||
skip = not await fd.is_visible_in_edit_form(fd, entity_data, context)
|
||||
else:
|
||||
skip = not fd.is_visible_in_edit_form(fd, entity_data, context)
|
||||
else:
|
||||
skip = False
|
||||
if (
|
||||
fd.is_optional
|
||||
|
||||
Reference in New Issue
Block a user