enhanced strings and elements visibility delegates
This commit is contained in:
@@ -15,7 +15,7 @@ from .model.descriptors import (
|
|||||||
Filter as Filter,
|
Filter as Filter,
|
||||||
EntityPermission as EntityPermission,
|
EntityPermission as EntityPermission,
|
||||||
CommandCallbackContext as CommandCallbackContext,
|
CommandCallbackContext as CommandCallbackContext,
|
||||||
EntityEventContext as EntityEventContext,
|
BotContext as BotContext,
|
||||||
CommandButton as CommandButton,
|
CommandButton as CommandButton,
|
||||||
FieldEditButton as FieldEditButton,
|
FieldEditButton as FieldEditButton,
|
||||||
InlineButton as InlineButton,
|
InlineButton as InlineButton,
|
||||||
|
|||||||
@@ -30,14 +30,12 @@ async def telegram_webhook(
|
|||||||
logger.error("Invalid request", exc_info=True)
|
logger.error("Invalid request", exc_info=True)
|
||||||
return Response(status_code=400)
|
return Response(status_code=400)
|
||||||
try:
|
try:
|
||||||
state_kw = request.state._state # TODO: avoid accessing private attribute
|
|
||||||
|
|
||||||
await app.dp.feed_webhook_update(
|
await app.dp.feed_webhook_update(
|
||||||
app.bot,
|
app.bot,
|
||||||
update,
|
update,
|
||||||
db_session=db_session,
|
db_session=db_session,
|
||||||
app=app,
|
app=app,
|
||||||
**(state_kw or {}),
|
app_state=request.state,
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error("Error processing update", exc_info=True)
|
logger.error("Error processing update", exc_info=True)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from aiogram.types import InlineKeyboardButton
|
from aiogram.types import InlineKeyboardButton
|
||||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||||
|
|
||||||
from ....model.descriptors import EntityDescriptor
|
from ....model.descriptors import BotContext, EntityDescriptor
|
||||||
from ....utils.main import get_callable_str
|
from ....utils.main import get_callable_str
|
||||||
from ..context import ContextData, CallbackCommand
|
from ..context import ContextData, CallbackCommand
|
||||||
|
|
||||||
@@ -9,6 +9,7 @@ from ..context import ContextData, CallbackCommand
|
|||||||
async def add_filter_controls(
|
async def add_filter_controls(
|
||||||
keyboard_builder: InlineKeyboardBuilder,
|
keyboard_builder: InlineKeyboardBuilder,
|
||||||
entity_descriptor: EntityDescriptor,
|
entity_descriptor: EntityDescriptor,
|
||||||
|
context: BotContext,
|
||||||
filter: str = None,
|
filter: str = None,
|
||||||
filtering_fields: list[str] = None,
|
filtering_fields: list[str] = None,
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
@@ -16,8 +17,9 @@ async def add_filter_controls(
|
|||||||
caption = ", ".join(
|
caption = ", ".join(
|
||||||
[
|
[
|
||||||
await get_callable_str(
|
await get_callable_str(
|
||||||
entity_descriptor.fields_descriptors[field_name].caption,
|
callable_str=entity_descriptor.fields_descriptors[field_name].caption,
|
||||||
entity_descriptor,
|
context=context,
|
||||||
|
descriptor=entity_descriptor.fields_descriptors[field_name],
|
||||||
)
|
)
|
||||||
if entity_descriptor.fields_descriptors[field_name].caption
|
if entity_descriptor.fields_descriptors[field_name].caption
|
||||||
else field_name
|
else field_name
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ from aiogram.types import Message, CallbackQuery
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from datetime import datetime, time
|
from datetime import datetime, time
|
||||||
|
|
||||||
|
from quickbot.main import QBotApp
|
||||||
|
from quickbot.utils.serialization import deserialize
|
||||||
|
|
||||||
from ....model.bot_entity import BotEntity
|
from ....model.bot_entity import BotEntity
|
||||||
from ....model.bot_enum import BotEnum
|
from ....model.bot_enum import BotEnum
|
||||||
from ....model.descriptors import FieldDescriptor
|
from ....model.descriptors import BotContext, FieldDescriptor
|
||||||
from ....model.settings import Settings
|
from ....model.settings import Settings
|
||||||
from ....model.user import UserBase
|
from ....model.user import UserBase
|
||||||
from ....utils.main import get_callable_str, get_value_repr
|
from ....utils.main import get_callable_str, get_value_repr
|
||||||
@@ -21,38 +24,87 @@ async def show_editor(message: Message | CallbackQuery, **kwargs):
|
|||||||
user: UserBase = kwargs["user"]
|
user: UserBase = kwargs["user"]
|
||||||
callback_data: ContextData = kwargs.get("callback_data", None)
|
callback_data: ContextData = kwargs.get("callback_data", None)
|
||||||
state_data: dict = kwargs["state_data"]
|
state_data: dict = kwargs["state_data"]
|
||||||
|
db_session = kwargs["db_session"]
|
||||||
|
app: QBotApp = kwargs["app"]
|
||||||
|
|
||||||
value_type = field_descriptor.type_base
|
value_type = field_descriptor.type_base
|
||||||
|
|
||||||
|
entity_data_dict: dict = state_data.get("entity_data")
|
||||||
|
entity_data = None
|
||||||
|
|
||||||
|
if callback_data.context == CommandContext.COMMAND_FORM:
|
||||||
|
cmd = app.bot_commands.get(callback_data.user_command.split("&")[0])
|
||||||
|
|
||||||
|
entity_data = (
|
||||||
|
{
|
||||||
|
key: await deserialize(
|
||||||
|
session=kwargs["db_session"],
|
||||||
|
type_=cmd.param_form[key].type_,
|
||||||
|
value=value,
|
||||||
|
)
|
||||||
|
for key, value in entity_data_dict.items()
|
||||||
|
}
|
||||||
|
if entity_data_dict and cmd.param_form
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
|
elif callback_data.context == CommandContext.ENTITY_CREATE:
|
||||||
|
entity_data = (
|
||||||
|
{
|
||||||
|
key: await deserialize(
|
||||||
|
session=kwargs["db_session"],
|
||||||
|
type_=field_descriptor.entity_descriptor.fields_descriptors[
|
||||||
|
key
|
||||||
|
].type_,
|
||||||
|
value=value,
|
||||||
|
)
|
||||||
|
for key, value in entity_data_dict.items()
|
||||||
|
}
|
||||||
|
if entity_data_dict
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
entity_id = callback_data.entity_id
|
||||||
|
if entity_id:
|
||||||
|
entity_data = await field_descriptor.entity_descriptor.type_.get(
|
||||||
|
session=db_session, id=entity_id
|
||||||
|
)
|
||||||
|
|
||||||
|
context = BotContext(
|
||||||
|
db_session=db_session, app=app, app_state=kwargs["app_state"], message=message
|
||||||
|
)
|
||||||
|
|
||||||
if field_descriptor.edit_prompt:
|
if field_descriptor.edit_prompt:
|
||||||
edit_prompt = await get_callable_str(
|
edit_prompt = await get_callable_str(
|
||||||
field_descriptor.edit_prompt,
|
callable_str=field_descriptor.edit_prompt,
|
||||||
field_descriptor,
|
context=context,
|
||||||
callback_data
|
descriptor=field_descriptor,
|
||||||
if callback_data.context == CommandContext.COMMAND_FORM
|
entity=entity_data,
|
||||||
else None,
|
|
||||||
current_value,
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if field_descriptor.caption:
|
if field_descriptor.caption:
|
||||||
caption_str = await get_callable_str(
|
caption_str = await get_callable_str(
|
||||||
field_descriptor.caption,
|
field_descriptor.caption,
|
||||||
field_descriptor,
|
context=context,
|
||||||
callback_data
|
descriptor=field_descriptor,
|
||||||
if callback_data.context == CommandContext.COMMAND_FORM
|
|
||||||
else None,
|
|
||||||
current_value,
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
caption_str = field_descriptor.name
|
caption_str = field_descriptor.name
|
||||||
if callback_data.context == CommandContext.ENTITY_EDIT:
|
if callback_data.context == CommandContext.ENTITY_EDIT:
|
||||||
|
db_session = kwargs["db_session"]
|
||||||
|
app = kwargs["app"]
|
||||||
edit_prompt = (
|
edit_prompt = (
|
||||||
await Settings.get(
|
await Settings.get(
|
||||||
Settings.APP_STRINGS_FIELD_EDIT_PROMPT_TEMPLATE_P_NAME_VALUE
|
Settings.APP_STRINGS_FIELD_EDIT_PROMPT_TEMPLATE_P_NAME_VALUE
|
||||||
)
|
)
|
||||||
).format(
|
).format(
|
||||||
name=caption_str,
|
name=caption_str,
|
||||||
value=await get_value_repr(current_value, field_descriptor, user.lang),
|
value=await get_value_repr(
|
||||||
|
value=current_value,
|
||||||
|
field_descriptor=field_descriptor,
|
||||||
|
context=context,
|
||||||
|
locale=user.lang,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
edit_prompt = (
|
edit_prompt = (
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from ....model.bot_enum import BotEnum
|
|||||||
from ....model.settings import Settings
|
from ....model.settings import Settings
|
||||||
from ....model.user import UserBase
|
from ....model.user import UserBase
|
||||||
from ....model.view_setting import ViewSetting
|
from ....model.view_setting import ViewSetting
|
||||||
from ....model.descriptors import FieldDescriptor, Filter
|
from ....model.descriptors import BotContext, EntityList, FieldDescriptor, Filter
|
||||||
from ....model import EntityPermission
|
from ....model import EntityPermission
|
||||||
from ....utils.main import (
|
from ....utils.main import (
|
||||||
get_user_permissions,
|
get_user_permissions,
|
||||||
@@ -108,9 +108,8 @@ async def render_entity_picker(
|
|||||||
for item in enum_items
|
for item in enum_items
|
||||||
]
|
]
|
||||||
elif issubclass(type_, BotEntity):
|
elif issubclass(type_, BotEntity):
|
||||||
form_name = field_descriptor.ep_form or "default"
|
form_list: EntityList = type_.bot_entity_descriptor.lists.get(
|
||||||
form_list = type_.bot_entity_descriptor.lists.get(
|
field_descriptor.ep_form, type_.bot_entity_descriptor.default_list
|
||||||
form_name, type_.bot_entity_descriptor.default_list
|
|
||||||
)
|
)
|
||||||
permissions = get_user_permissions(user, type_.bot_entity_descriptor)
|
permissions = get_user_permissions(user, type_.bot_entity_descriptor)
|
||||||
if form_list.filtering:
|
if form_list.filtering:
|
||||||
@@ -196,6 +195,13 @@ async def render_entity_picker(
|
|||||||
page = 1
|
page = 1
|
||||||
entity_items = list[BotEntity]()
|
entity_items = list[BotEntity]()
|
||||||
|
|
||||||
|
context = BotContext(
|
||||||
|
db_session=db_session,
|
||||||
|
app=kwargs["app"],
|
||||||
|
app_state=kwargs["app_state"],
|
||||||
|
message=message,
|
||||||
|
)
|
||||||
|
|
||||||
items = [
|
items = [
|
||||||
{
|
{
|
||||||
"text": f"{
|
"text": f"{
|
||||||
@@ -205,14 +211,16 @@ async def render_entity_picker(
|
|||||||
if item in (current_value or [])
|
if item in (current_value or [])
|
||||||
else '【 】 '
|
else '【 】 '
|
||||||
}{
|
}{
|
||||||
type_.bot_entity_descriptor.item_repr(
|
await get_callable_str(
|
||||||
type_.bot_entity_descriptor, item
|
callable_str=type_.bot_entity_descriptor.item_repr,
|
||||||
|
context=context,
|
||||||
|
entity=item,
|
||||||
)
|
)
|
||||||
if type_.bot_entity_descriptor.item_repr
|
if type_.bot_entity_descriptor.item_repr
|
||||||
else await get_callable_str(
|
else await get_callable_str(
|
||||||
type_.bot_entity_descriptor.full_name,
|
callable_str=type_.bot_entity_descriptor.full_name,
|
||||||
type_.bot_entity_descriptor,
|
context=context,
|
||||||
item,
|
descriptor=type_.bot_entity_descriptor,
|
||||||
)
|
)
|
||||||
if type_.bot_entity_descriptor.full_name
|
if type_.bot_entity_descriptor.full_name
|
||||||
else f'{type_.bot_entity_descriptor.name}: {str(item.id)}'
|
else f'{type_.bot_entity_descriptor.name}: {str(item.id)}'
|
||||||
@@ -262,6 +270,7 @@ async def render_entity_picker(
|
|||||||
await add_filter_controls(
|
await add_filter_controls(
|
||||||
keyboard_builder=keyboard_builder,
|
keyboard_builder=keyboard_builder,
|
||||||
entity_descriptor=type_.bot_entity_descriptor,
|
entity_descriptor=type_.bot_entity_descriptor,
|
||||||
|
context=context,
|
||||||
filter=entity_filter,
|
filter=entity_filter,
|
||||||
filtering_fields=form_list.filtering_fields,
|
filtering_fields=form_list.filtering_fields,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ from aiogram.types import Message, CallbackQuery
|
|||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||||
|
|
||||||
|
from quickbot.model.descriptors import EntityForm
|
||||||
|
|
||||||
from ....model import EntityPermission
|
from ....model import EntityPermission
|
||||||
from ....model.settings import Settings
|
from ....model.settings import Settings
|
||||||
from ....model.user import UserBase
|
from ....model.user import UserBase
|
||||||
@@ -127,14 +129,17 @@ async def field_editor(message: Message | CallbackQuery, **kwargs):
|
|||||||
form_name = (
|
form_name = (
|
||||||
callback_data.form_params.split("&")[0]
|
callback_data.form_params.split("&")[0]
|
||||||
if callback_data.form_params
|
if callback_data.form_params
|
||||||
else "default"
|
else None
|
||||||
)
|
)
|
||||||
form = entity_descriptor.forms.get(
|
form: EntityForm = entity_descriptor.forms.get(
|
||||||
form_name, entity_descriptor.default_form
|
form_name, entity_descriptor.default_form
|
||||||
)
|
)
|
||||||
entity_data = {
|
entity_data = {
|
||||||
key: serialize(
|
key: serialize(
|
||||||
getattr(entity, key),
|
getattr(
|
||||||
|
entity,
|
||||||
|
entity_descriptor.fields_descriptors[key].field_name,
|
||||||
|
),
|
||||||
entity_descriptor.fields_descriptors[key],
|
entity_descriptor.fields_descriptors[key],
|
||||||
)
|
)
|
||||||
for key in (
|
for key in (
|
||||||
|
|||||||
@@ -13,7 +13,12 @@ from ..user_handlers.main import cammand_handler
|
|||||||
from ....model import EntityPermission
|
from ....model import EntityPermission
|
||||||
from ....model.user import UserBase
|
from ....model.user import UserBase
|
||||||
from ....model.settings import Settings
|
from ....model.settings import Settings
|
||||||
from ....model.descriptors import EntityEventContext, FieldDescriptor
|
from ....model.descriptors import (
|
||||||
|
BotContext,
|
||||||
|
EntityForm,
|
||||||
|
EntityList,
|
||||||
|
FieldDescriptor,
|
||||||
|
)
|
||||||
from ....model.language import LanguageBase
|
from ....model.language import LanguageBase
|
||||||
from ....auth import authorize_command
|
from ....auth import authorize_command
|
||||||
from ....utils.main import (
|
from ....utils.main import (
|
||||||
@@ -84,16 +89,6 @@ async def field_editor_callback(message: Message | CallbackQuery, **kwargs):
|
|||||||
value=value,
|
value=value,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
# else:
|
|
||||||
# value = state_data.get("value")
|
|
||||||
# if value:
|
|
||||||
# value = json.loads(value)
|
|
||||||
# else:
|
|
||||||
# value = {}
|
|
||||||
# value[list(LanguageBase.all_members.keys())[locale_index]] = (
|
|
||||||
# message.text
|
|
||||||
# )
|
|
||||||
# value = json.dumps(value, ensure_ascii=False)
|
|
||||||
|
|
||||||
elif type_base in [int, float, Decimal]:
|
elif type_base in [int, float, Decimal]:
|
||||||
try:
|
try:
|
||||||
@@ -163,9 +158,9 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
|||||||
form_name = (
|
form_name = (
|
||||||
callback_data.form_params.split("&")[0]
|
callback_data.form_params.split("&")[0]
|
||||||
if callback_data.form_params
|
if callback_data.form_params
|
||||||
else "default"
|
else None
|
||||||
)
|
)
|
||||||
form = entity_descriptor.forms.get(
|
form: EntityForm = entity_descriptor.forms.get(
|
||||||
form_name, entity_descriptor.default_form
|
form_name, entity_descriptor.default_form
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -176,6 +171,7 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
|||||||
entity_descriptor=entity_descriptor,
|
entity_descriptor=entity_descriptor,
|
||||||
user=user,
|
user=user,
|
||||||
callback_data=callback_data,
|
callback_data=callback_data,
|
||||||
|
state_data=state_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
current_index = (
|
current_index = (
|
||||||
@@ -188,7 +184,7 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
|||||||
|
|
||||||
entity_data = state_data.get("entity_data", {})
|
entity_data = state_data.get("entity_data", {})
|
||||||
|
|
||||||
if callback_data.context == CommandContext.ENTITY_CREATE and not entity_data:
|
if callback_data.context == CommandContext.ENTITY_CREATE:
|
||||||
stack = state_data.get("navigation_stack", [])
|
stack = state_data.get("navigation_stack", [])
|
||||||
prev_callback_data = ContextData.unpack(stack[-1]) if stack else None
|
prev_callback_data = ContextData.unpack(stack[-1]) if stack else None
|
||||||
if (
|
if (
|
||||||
@@ -199,15 +195,15 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
|||||||
prev_form_name = (
|
prev_form_name = (
|
||||||
prev_callback_data.form_params.split("&")[0]
|
prev_callback_data.form_params.split("&")[0]
|
||||||
if prev_callback_data.form_params
|
if prev_callback_data.form_params
|
||||||
else "default"
|
else None
|
||||||
)
|
)
|
||||||
prev_form_params = (
|
prev_form_params = (
|
||||||
prev_callback_data.form_params.split("&")[1:]
|
prev_callback_data.form_params.split("&")[1:]
|
||||||
if prev_callback_data.form_params
|
if prev_callback_data.form_params
|
||||||
else []
|
else []
|
||||||
)
|
)
|
||||||
prev_form_list = entity_descriptor.lists.get(
|
prev_form_list: EntityList = entity_descriptor.lists.get(
|
||||||
prev_form_name or "default", entity_descriptor.default_list
|
prev_form_name, entity_descriptor.default_list
|
||||||
)
|
)
|
||||||
|
|
||||||
if prev_form_list.static_filters:
|
if prev_form_list.static_filters:
|
||||||
@@ -256,7 +252,7 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
|||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
entity_data[field_descriptor.field_name] = value
|
entity_data[field_descriptor.name] = value
|
||||||
|
|
||||||
# What if user has several roles and each role has its own ownership field? Should we allow creation even
|
# 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
|
# if user has no CREATE_ALL permission
|
||||||
@@ -283,6 +279,13 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
|||||||
for key, value in entity_data.items()
|
for key, value in entity_data.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context = BotContext(
|
||||||
|
db_session=db_session,
|
||||||
|
app=app,
|
||||||
|
app_state=kwargs["app_state"],
|
||||||
|
message=message,
|
||||||
|
)
|
||||||
|
|
||||||
if callback_data.context == CommandContext.ENTITY_CREATE:
|
if callback_data.context == CommandContext.ENTITY_CREATE:
|
||||||
entity_type = entity_descriptor.type_
|
entity_type = entity_descriptor.type_
|
||||||
user_permissions = get_user_permissions(user, entity_descriptor)
|
user_permissions = get_user_permissions(user, entity_descriptor)
|
||||||
@@ -304,25 +307,21 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
|||||||
if iscoroutinefunction(entity_descriptor.on_created):
|
if iscoroutinefunction(entity_descriptor.on_created):
|
||||||
await entity_descriptor.on_created(
|
await entity_descriptor.on_created(
|
||||||
new_entity,
|
new_entity,
|
||||||
EntityEventContext(
|
context,
|
||||||
db_session=db_session, app=app, message=message
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
entity_descriptor.on_created(
|
entity_descriptor.on_created(
|
||||||
new_entity,
|
new_entity,
|
||||||
EntityEventContext(
|
context,
|
||||||
db_session=db_session, app=app, message=message
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
form_name = (
|
form_name = (
|
||||||
callback_data.form_params.split("&")[0]
|
callback_data.form_params.split("&")[0]
|
||||||
if callback_data.form_params
|
if callback_data.form_params
|
||||||
else "default"
|
else None
|
||||||
)
|
)
|
||||||
form_list = entity_descriptor.lists.get(
|
form_list = entity_descriptor.lists.get(
|
||||||
form_name or "default", entity_descriptor.default_list
|
form_name, entity_descriptor.default_list
|
||||||
)
|
)
|
||||||
|
|
||||||
state_data["navigation_context"] = ContextData(
|
state_data["navigation_context"] = ContextData(
|
||||||
@@ -357,7 +356,11 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
|||||||
)
|
)
|
||||||
|
|
||||||
for key, value in deser_entity_data.items():
|
for key, value in deser_entity_data.items():
|
||||||
setattr(entity, key, value)
|
setattr(
|
||||||
|
entity,
|
||||||
|
entity.bot_entity_descriptor.fields_descriptors[key].field_name,
|
||||||
|
value,
|
||||||
|
)
|
||||||
|
|
||||||
await db_session.commit()
|
await db_session.commit()
|
||||||
await db_session.refresh(entity)
|
await db_session.refresh(entity)
|
||||||
@@ -366,16 +369,12 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
|||||||
if iscoroutinefunction(entity_descriptor.on_updated):
|
if iscoroutinefunction(entity_descriptor.on_updated):
|
||||||
await entity_descriptor.on_updated(
|
await entity_descriptor.on_updated(
|
||||||
entity,
|
entity,
|
||||||
EntityEventContext(
|
context,
|
||||||
db_session=db_session, app=app, message=message
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
entity_descriptor.on_updated(
|
entity_descriptor.on_updated(
|
||||||
entity,
|
entity,
|
||||||
EntityEventContext(
|
context,
|
||||||
db_session=db_session, app=app, message=message
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
elif callback_data.context == CommandContext.COMMAND_FORM:
|
elif callback_data.context == CommandContext.COMMAND_FORM:
|
||||||
@@ -397,5 +396,4 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
|
|||||||
|
|
||||||
clear_state(state_data=state_data)
|
clear_state(state_data=state_data)
|
||||||
|
|
||||||
# TODO: Try back=False and check if it works to navigate to newly created entity
|
|
||||||
await route_callback(message=message, back=True, **kwargs)
|
await route_callback(message=message, back=True, **kwargs)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from aiogram.types import InlineKeyboardButton
|
|||||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||||
|
|
||||||
from ....model.settings import Settings
|
from ....model.settings import Settings
|
||||||
from ....model.descriptors import FieldDescriptor
|
from ....model.descriptors import EntityForm, FieldDescriptor
|
||||||
from ....model.user import UserBase
|
from ....model.user import UserBase
|
||||||
from ..context import ContextData, CallbackCommand, CommandContext
|
from ..context import ContextData, CallbackCommand, CommandContext
|
||||||
from ....utils.navigation import get_navigation_context, pop_navigation_context
|
from ....utils.navigation import get_navigation_context, pop_navigation_context
|
||||||
@@ -34,9 +34,9 @@ async def wrap_editor(
|
|||||||
form_name = (
|
form_name = (
|
||||||
callback_data.form_params.split("&")[0]
|
callback_data.form_params.split("&")[0]
|
||||||
if callback_data.form_params
|
if callback_data.form_params
|
||||||
else "default"
|
else None
|
||||||
)
|
)
|
||||||
form = field_descriptor.entity_descriptor.forms.get(
|
form: EntityForm = field_descriptor.entity_descriptor.forms.get(
|
||||||
form_name, field_descriptor.entity_descriptor.default_form
|
form_name, field_descriptor.entity_descriptor.default_form
|
||||||
)
|
)
|
||||||
if form.edit_field_sequence:
|
if form.edit_field_sequence:
|
||||||
@@ -46,6 +46,7 @@ async def wrap_editor(
|
|||||||
entity_descriptor=field_descriptor.entity_descriptor,
|
entity_descriptor=field_descriptor.entity_descriptor,
|
||||||
user=user,
|
user=user,
|
||||||
callback_data=callback_data,
|
callback_data=callback_data,
|
||||||
|
state_data=state_data,
|
||||||
)
|
)
|
||||||
field_index = (
|
field_index = (
|
||||||
field_sequence.index(field_descriptor.name)
|
field_sequence.index(field_descriptor.name)
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ from logging import getLogger
|
|||||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||||
|
|
||||||
from ....model.descriptors import (
|
from ....model.descriptors import (
|
||||||
|
EntityForm,
|
||||||
FieldEditButton,
|
FieldEditButton,
|
||||||
CommandButton,
|
CommandButton,
|
||||||
InlineButton,
|
InlineButton,
|
||||||
EntityEventContext,
|
BotContext,
|
||||||
)
|
)
|
||||||
from ....model.settings import Settings
|
from ....model.settings import Settings
|
||||||
from ....model.user import UserBase
|
from ....model.user import UserBase
|
||||||
@@ -92,12 +93,15 @@ async def entity_item(
|
|||||||
entity=entity_item, user=user, permission=EntityPermission.UPDATE
|
entity=entity_item, user=user, permission=EntityPermission.UPDATE
|
||||||
)
|
)
|
||||||
|
|
||||||
form = entity_descriptor.forms.get(
|
form: EntityForm = entity_descriptor.forms.get(
|
||||||
callback_data.form_params or "default", entity_descriptor.default_form
|
callback_data.form_params, entity_descriptor.default_form
|
||||||
|
)
|
||||||
|
|
||||||
|
context = BotContext(
|
||||||
|
db_session=db_session, app=app, app_state=kwargs["app_state"], message=query
|
||||||
)
|
)
|
||||||
|
|
||||||
if form.form_buttons:
|
if form.form_buttons:
|
||||||
context = EntityEventContext(db_session=db_session, app=app, message=query)
|
|
||||||
for edit_buttons_row in form.form_buttons:
|
for edit_buttons_row in form.form_buttons:
|
||||||
btn_row = []
|
btn_row = []
|
||||||
for button in edit_buttons_row:
|
for button in edit_buttons_row:
|
||||||
@@ -114,16 +118,17 @@ async def entity_item(
|
|||||||
field_value = getattr(entity_item, field_descriptor.field_name)
|
field_value = getattr(entity_item, field_descriptor.field_name)
|
||||||
if btn_caption:
|
if btn_caption:
|
||||||
btn_text = await get_callable_str(
|
btn_text = await get_callable_str(
|
||||||
btn_caption, field_descriptor, entity_item, field_value
|
callable_str=btn_caption,
|
||||||
|
context=context,
|
||||||
|
entity=entity_item,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if field_descriptor.type_base is bool:
|
if field_descriptor.type_base is bool:
|
||||||
btn_text = f"{'【✔︎】 ' if field_value else '【 】 '}{
|
btn_text = f"{'【✔︎】 ' if field_value else '【 】 '}{
|
||||||
await get_callable_str(
|
await get_callable_str(
|
||||||
field_descriptor.caption,
|
callable_str=field_descriptor.caption,
|
||||||
field_descriptor,
|
context=context,
|
||||||
entity_item,
|
descriptor=field_descriptor,
|
||||||
field_value,
|
|
||||||
)
|
)
|
||||||
if field_descriptor.caption
|
if field_descriptor.caption
|
||||||
else field_name
|
else field_name
|
||||||
@@ -135,10 +140,9 @@ async def entity_item(
|
|||||||
else '✏️'
|
else '✏️'
|
||||||
} {
|
} {
|
||||||
await get_callable_str(
|
await get_callable_str(
|
||||||
field_descriptor.caption,
|
callable_str=field_descriptor.caption,
|
||||||
field_descriptor,
|
context=context,
|
||||||
entity_item,
|
descriptor=field_descriptor,
|
||||||
field_value,
|
|
||||||
)
|
)
|
||||||
if field_descriptor.caption
|
if field_descriptor.caption
|
||||||
else field_name
|
else field_name
|
||||||
@@ -160,7 +164,9 @@ async def entity_item(
|
|||||||
btn_caption = button.caption
|
btn_caption = button.caption
|
||||||
|
|
||||||
btn_text = await get_callable_str(
|
btn_text = await get_callable_str(
|
||||||
btn_caption, entity_descriptor, entity_item
|
callable_str=btn_caption,
|
||||||
|
context=context,
|
||||||
|
entity=entity_item,
|
||||||
)
|
)
|
||||||
|
|
||||||
if isinstance(button.command, ContextData):
|
if isinstance(button.command, ContextData):
|
||||||
@@ -206,6 +212,7 @@ async def entity_item(
|
|||||||
entity_descriptor=entity_descriptor,
|
entity_descriptor=entity_descriptor,
|
||||||
user=user,
|
user=user,
|
||||||
callback_data=callback_data,
|
callback_data=callback_data,
|
||||||
|
state_data=state_data,
|
||||||
)
|
)
|
||||||
edit_delete_row.append(
|
edit_delete_row.append(
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
@@ -243,11 +250,17 @@ async def entity_item(
|
|||||||
keyboard_builder.row(*edit_delete_row)
|
keyboard_builder.row(*edit_delete_row)
|
||||||
|
|
||||||
if form.item_repr:
|
if form.item_repr:
|
||||||
item_text = form.item_repr(entity_descriptor, entity_item)
|
item_text = await get_callable_str(
|
||||||
|
callable_str=form.item_repr,
|
||||||
|
context=context,
|
||||||
|
entity=entity_item,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
entity_caption = (
|
entity_caption = (
|
||||||
await get_callable_str(
|
await get_callable_str(
|
||||||
entity_descriptor.full_name, entity_descriptor, entity_item
|
callable_str=entity_descriptor.full_name,
|
||||||
|
context=context,
|
||||||
|
descriptor=entity_descriptor,
|
||||||
)
|
)
|
||||||
if entity_descriptor.full_name
|
if entity_descriptor.full_name
|
||||||
else entity_descriptor.name
|
else entity_descriptor.name
|
||||||
@@ -255,7 +268,9 @@ async def entity_item(
|
|||||||
|
|
||||||
entity_item_repr = (
|
entity_item_repr = (
|
||||||
await get_callable_str(
|
await get_callable_str(
|
||||||
entity_descriptor.item_repr, entity_descriptor, entity_item
|
callable_str=entity_descriptor.item_repr,
|
||||||
|
context=context,
|
||||||
|
entity=entity_item,
|
||||||
)
|
)
|
||||||
if entity_descriptor.item_repr
|
if entity_descriptor.item_repr
|
||||||
else str(entity_item.id)
|
else str(entity_item.id)
|
||||||
@@ -267,11 +282,23 @@ async def entity_item(
|
|||||||
|
|
||||||
for field_descriptor in entity_descriptor.fields_descriptors.values():
|
for field_descriptor in entity_descriptor.fields_descriptors.values():
|
||||||
if (
|
if (
|
||||||
field_descriptor.is_visible is not None
|
isinstance(field_descriptor.is_visible, bool)
|
||||||
and not field_descriptor.is_visible
|
and not field_descriptor.is_visible
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if callable(field_descriptor.is_visible):
|
||||||
|
if iscoroutinefunction(field_descriptor.is_visible):
|
||||||
|
field_visible = await field_descriptor.is_visible(
|
||||||
|
field_descriptor, entity_item, context
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
field_visible = field_descriptor.is_visible(
|
||||||
|
field_descriptor, entity_item, context
|
||||||
|
)
|
||||||
|
if not field_visible:
|
||||||
|
continue
|
||||||
|
|
||||||
skip = False
|
skip = False
|
||||||
|
|
||||||
for own_field in entity_descriptor.ownership_fields.items():
|
for own_field in entity_descriptor.ownership_fields.items():
|
||||||
@@ -287,20 +314,27 @@ async def entity_item(
|
|||||||
if skip:
|
if skip:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
field_caption = await get_callable_str(
|
field_caption = (
|
||||||
field_descriptor.caption, field_descriptor, entity_item
|
await get_callable_str(
|
||||||
|
callable_str=field_descriptor.caption,
|
||||||
|
context=context,
|
||||||
|
descriptor=field_descriptor,
|
||||||
|
)
|
||||||
|
if field_descriptor.caption
|
||||||
|
else field_descriptor.field_name
|
||||||
)
|
)
|
||||||
if field_descriptor.caption_value:
|
if field_descriptor.caption_value:
|
||||||
value = await get_callable_str(
|
value = await get_callable_str(
|
||||||
field_descriptor.caption_value,
|
callable_str=field_descriptor.caption_value,
|
||||||
field_descriptor,
|
context=context,
|
||||||
entity_item,
|
descriptor=field_descriptor,
|
||||||
getattr(entity_item, field_descriptor.field_name),
|
entity=entity_item,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
value = await get_value_repr(
|
value = await get_value_repr(
|
||||||
value=getattr(entity_item, field_descriptor.field_name),
|
value=getattr(entity_item, field_descriptor.field_name),
|
||||||
field_descriptor=field_descriptor,
|
field_descriptor=field_descriptor,
|
||||||
|
context=context,
|
||||||
locale=user.lang,
|
locale=user.lang,
|
||||||
)
|
)
|
||||||
item_text += f"\n{field_caption or field_descriptor.name}:{f' <b>{value}</b>' if value else ''}"
|
item_text += f"\n{field_caption or field_descriptor.name}:{f' <b>{value}</b>' if value else ''}"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder
|
|||||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from quickbot.model.descriptors import EntityEventContext
|
from quickbot.model.descriptors import BotContext
|
||||||
|
|
||||||
from ..context import ContextData, CallbackCommand
|
from ..context import ContextData, CallbackCommand
|
||||||
from ....model.user import UserBase
|
from ....model.user import UserBase
|
||||||
@@ -49,6 +49,10 @@ async def entity_delete_callback(query: CallbackQuery, **kwargs):
|
|||||||
text=(await Settings.get(Settings.APP_STRINGS_FORBIDDEN))
|
text=(await Settings.get(Settings.APP_STRINGS_FORBIDDEN))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
context = BotContext(
|
||||||
|
db_session=db_session, app=app, app_state=kwargs["app_state"], message=query
|
||||||
|
)
|
||||||
|
|
||||||
if callback_data.data == "yes":
|
if callback_data.data == "yes":
|
||||||
entity = await entity_descriptor.type_.remove(
|
entity = await entity_descriptor.type_.remove(
|
||||||
session=db_session, id=int(callback_data.entity_id), commit=True
|
session=db_session, id=int(callback_data.entity_id), commit=True
|
||||||
@@ -58,12 +62,12 @@ async def entity_delete_callback(query: CallbackQuery, **kwargs):
|
|||||||
if iscoroutinefunction(entity_descriptor.on_created):
|
if iscoroutinefunction(entity_descriptor.on_created):
|
||||||
await entity_descriptor.on_deleted(
|
await entity_descriptor.on_deleted(
|
||||||
entity,
|
entity,
|
||||||
EntityEventContext(db_session=db_session, app=app, message=query),
|
context,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
entity_descriptor.on_deleted(
|
entity_descriptor.on_deleted(
|
||||||
entity,
|
entity,
|
||||||
EntityEventContext(db_session=db_session, app=app, message=query),
|
context,
|
||||||
)
|
)
|
||||||
|
|
||||||
await route_callback(message=query, **kwargs)
|
await route_callback(message=query, **kwargs)
|
||||||
@@ -76,7 +80,12 @@ async def entity_delete_callback(query: CallbackQuery, **kwargs):
|
|||||||
return await query.message.edit_text(
|
return await query.message.edit_text(
|
||||||
text=(
|
text=(
|
||||||
await Settings.get(Settings.APP_STRINGS_CONFIRM_DELETE_P_NAME)
|
await Settings.get(Settings.APP_STRINGS_CONFIRM_DELETE_P_NAME)
|
||||||
).format(name=await get_entity_item_repr(entity=entity)),
|
).format(
|
||||||
|
name=await get_entity_item_repr(
|
||||||
|
entity=entity,
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
),
|
||||||
reply_markup=InlineKeyboardBuilder()
|
reply_markup=InlineKeyboardBuilder()
|
||||||
.row(
|
.row(
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
|
|||||||
@@ -10,7 +10,13 @@ from ....model.bot_entity import BotEntity
|
|||||||
from ....model.settings import Settings
|
from ....model.settings import Settings
|
||||||
from ....model.user import UserBase
|
from ....model.user import UserBase
|
||||||
from ....model.view_setting import ViewSetting
|
from ....model.view_setting import ViewSetting
|
||||||
from ....model.descriptors import EntityDescriptor, Filter
|
from ....model.descriptors import (
|
||||||
|
BotContext,
|
||||||
|
EntityDescriptor,
|
||||||
|
EntityForm,
|
||||||
|
EntityList,
|
||||||
|
Filter,
|
||||||
|
)
|
||||||
from ....model import EntityPermission
|
from ....model import EntityPermission
|
||||||
from ....utils.main import (
|
from ....utils.main import (
|
||||||
get_user_permissions,
|
get_user_permissions,
|
||||||
@@ -103,12 +109,12 @@ async def entity_list(
|
|||||||
form_params = (
|
form_params = (
|
||||||
callback_data.form_params.split("&") if callback_data.form_params else []
|
callback_data.form_params.split("&") if callback_data.form_params else []
|
||||||
)
|
)
|
||||||
form_name = form_params.pop(0) if form_params else "default"
|
form_name = form_params.pop(0) if form_params else None
|
||||||
form_list = entity_descriptor.lists.get(
|
form_list: EntityList = entity_descriptor.lists.get(
|
||||||
form_name or "default", entity_descriptor.default_list
|
form_name, entity_descriptor.default_list
|
||||||
)
|
)
|
||||||
form_item = entity_descriptor.forms.get(
|
form_item: EntityForm = entity_descriptor.forms.get(
|
||||||
form_list.item_form or "default", entity_descriptor.default_form
|
form_list.item_form, entity_descriptor.default_form
|
||||||
)
|
)
|
||||||
|
|
||||||
keyboard_builder = InlineKeyboardBuilder()
|
keyboard_builder = InlineKeyboardBuilder()
|
||||||
@@ -124,6 +130,7 @@ async def entity_list(
|
|||||||
entity_descriptor=entity_descriptor,
|
entity_descriptor=entity_descriptor,
|
||||||
user=user,
|
user=user,
|
||||||
callback_data=callback_data,
|
callback_data=callback_data,
|
||||||
|
state_data=kwargs["state_data"],
|
||||||
)
|
)
|
||||||
keyboard_builder.row(
|
keyboard_builder.row(
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
@@ -199,20 +206,39 @@ async def entity_list(
|
|||||||
total_pages = 1
|
total_pages = 1
|
||||||
page = 1
|
page = 1
|
||||||
|
|
||||||
|
context = BotContext(
|
||||||
|
db_session=db_session,
|
||||||
|
app=app,
|
||||||
|
app_state=kwargs["app_state"],
|
||||||
|
message=message,
|
||||||
|
)
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
|
caption = None
|
||||||
|
|
||||||
if form_list.item_repr:
|
if form_list.item_repr:
|
||||||
caption = form_list.item_repr(entity_descriptor, item)
|
caption = await get_callable_str(
|
||||||
|
callable_str=form_list.item_repr,
|
||||||
|
context=context,
|
||||||
|
entity=item,
|
||||||
|
)
|
||||||
elif entity_descriptor.item_repr:
|
elif entity_descriptor.item_repr:
|
||||||
caption = entity_descriptor.item_repr(entity_descriptor, item)
|
caption = await get_callable_str(
|
||||||
|
callable_str=entity_descriptor.item_repr,
|
||||||
|
context=context,
|
||||||
|
entity=item,
|
||||||
|
)
|
||||||
elif entity_descriptor.full_name:
|
elif entity_descriptor.full_name:
|
||||||
caption = f"{
|
caption = f"{
|
||||||
await get_callable_str(
|
await get_callable_str(
|
||||||
callable_str=entity_descriptor.full_name,
|
callable_str=entity_descriptor.full_name,
|
||||||
|
context=context,
|
||||||
descriptor=entity_descriptor,
|
descriptor=entity_descriptor,
|
||||||
entity=item,
|
entity=item,
|
||||||
)
|
)
|
||||||
}: {item.id}"
|
}: {item.id}"
|
||||||
else:
|
|
||||||
|
if not caption:
|
||||||
caption = f"{entity_descriptor.name}: {item.id}"
|
caption = f"{entity_descriptor.name}: {item.id}"
|
||||||
|
|
||||||
keyboard_builder.row(
|
keyboard_builder.row(
|
||||||
@@ -240,6 +266,7 @@ async def entity_list(
|
|||||||
await add_filter_controls(
|
await add_filter_controls(
|
||||||
keyboard_builder=keyboard_builder,
|
keyboard_builder=keyboard_builder,
|
||||||
entity_descriptor=entity_descriptor,
|
entity_descriptor=entity_descriptor,
|
||||||
|
context=context,
|
||||||
filter=entity_filter,
|
filter=entity_filter,
|
||||||
filtering_fields=form_list.filtering_fields,
|
filtering_fields=form_list.filtering_fields,
|
||||||
)
|
)
|
||||||
@@ -254,17 +281,29 @@ async def entity_list(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if form_list.caption:
|
if form_list.caption:
|
||||||
entity_text = await get_callable_str(form_list.caption, entity_descriptor)
|
entity_text = await get_callable_str(
|
||||||
|
callable_str=form_list.caption,
|
||||||
|
context=context,
|
||||||
|
descriptor=entity_descriptor,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if entity_descriptor.full_name_plural:
|
if entity_descriptor.full_name_plural:
|
||||||
entity_text = await get_callable_str(
|
entity_text = await get_callable_str(
|
||||||
entity_descriptor.full_name_plural, entity_descriptor
|
callable_str=entity_descriptor.full_name_plural,
|
||||||
|
context=context,
|
||||||
|
descriptor=entity_descriptor,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
entity_text = entity_descriptor.name
|
entity_text = entity_descriptor.name
|
||||||
|
|
||||||
if entity_descriptor.description:
|
if entity_descriptor.description:
|
||||||
entity_text = f"{entity_text} {await get_callable_str(entity_descriptor.description, entity_descriptor)}"
|
entity_text = f"{entity_text} {
|
||||||
|
await get_callable_str(
|
||||||
|
callable_str=entity_descriptor.description,
|
||||||
|
context=context,
|
||||||
|
descriptor=entity_descriptor,
|
||||||
|
)
|
||||||
|
}"
|
||||||
|
|
||||||
state: FSMContext = kwargs["state"]
|
state: FSMContext = kwargs["state"]
|
||||||
state_data = kwargs["state_data"]
|
state_data = kwargs["state_data"]
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ from aiogram import Router, F
|
|||||||
from aiogram.fsm.context import FSMContext
|
from aiogram.fsm.context import FSMContext
|
||||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton
|
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton
|
||||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||||
from babel.support import LazyProxy
|
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from quickbot.model.descriptors import BotContext
|
||||||
from ....model.settings import Settings
|
from ....model.settings import Settings
|
||||||
from ..context import ContextData, CallbackCommand
|
from ..context import ContextData, CallbackCommand
|
||||||
from ....utils.main import get_send_message
|
from ....utils.main import get_send_message, get_callable_str
|
||||||
from ....model.descriptors import EntityCaptionCallable
|
|
||||||
from ....utils.navigation import save_navigation_context, pop_navigation_context
|
from ....utils.navigation import save_navigation_context, pop_navigation_context
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -46,12 +46,21 @@ async def entities_menu(
|
|||||||
|
|
||||||
for entity in entity_metadata.entity_descriptors.values():
|
for entity in entity_metadata.entity_descriptors.values():
|
||||||
if entity.show_in_entities_menu:
|
if entity.show_in_entities_menu:
|
||||||
if entity.full_name_plural.__class__ == EntityCaptionCallable:
|
if entity.full_name_plural:
|
||||||
caption = entity.full_name_plural(entity) or entity.name
|
caption = await get_callable_str(
|
||||||
elif entity.full_name_plural.__class__ == LazyProxy:
|
callable_str=entity.full_name_plural,
|
||||||
caption = f"{f'{entity.icon} ' if entity.icon else ''}{entity.full_name_plural.value or entity.name}"
|
context=BotContext(
|
||||||
|
db_session=kwargs["db_session"],
|
||||||
|
app=app,
|
||||||
|
app_state=kwargs["app_state"],
|
||||||
|
message=message,
|
||||||
|
),
|
||||||
|
descriptor=entity,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
caption = f"{f'{entity.icon} ' if entity.icon else ''}{entity.full_name_plural or entity.name}"
|
caption = entity.name
|
||||||
|
|
||||||
|
caption = f"{f'{entity.icon} ' if entity.icon else ''}{caption}"
|
||||||
|
|
||||||
keyboard_builder.row(
|
keyboard_builder.row(
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ from aiogram.types import Message, CallbackQuery, InlineKeyboardButton
|
|||||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
|
from quickbot.model.descriptors import BotContext
|
||||||
|
|
||||||
from ....model.settings import Settings
|
from ....model.settings import Settings
|
||||||
from ....model.user import UserBase
|
from ....model.user import UserBase
|
||||||
from ..context import ContextData, CallbackCommand, CommandContext
|
from ..context import ContextData, CallbackCommand, CommandContext
|
||||||
@@ -53,14 +55,26 @@ async def parameters_menu(
|
|||||||
if not key.is_visible:
|
if not key.is_visible:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
context = BotContext(
|
||||||
|
db_session=kwargs["db_session"],
|
||||||
|
app=kwargs["app"],
|
||||||
|
app_state=kwargs["app_state"],
|
||||||
|
message=message,
|
||||||
|
)
|
||||||
|
|
||||||
if key.caption_value:
|
if key.caption_value:
|
||||||
caption = await get_callable_str(
|
caption = await get_callable_str(
|
||||||
callable_str=key.caption_value, descriptor=key, entity=None, value=value
|
callable_str=key.caption_value,
|
||||||
|
context=context,
|
||||||
|
descriptor=key,
|
||||||
|
entity={key.field_name: value},
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if key.caption:
|
if key.caption:
|
||||||
caption = await get_callable_str(
|
caption = await get_callable_str(
|
||||||
callable_str=key.caption, descriptor=key, entity=None, value=value
|
callable_str=key.caption,
|
||||||
|
context=context,
|
||||||
|
descriptor=key,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
caption = key.name
|
caption = key.name
|
||||||
@@ -68,7 +82,7 @@ async def parameters_menu(
|
|||||||
if key.type_ is bool:
|
if key.type_ is bool:
|
||||||
caption = f"{'【✔︎】' if value else '【 】'} {caption}"
|
caption = f"{'【✔︎】' if value else '【 】'} {caption}"
|
||||||
else:
|
else:
|
||||||
caption = f"{caption}: {await get_value_repr(value=value, field_descriptor=key, locale=user.lang)}"
|
caption = f"{caption}: {await get_value_repr(value=value, field_descriptor=key, context=context, locale=user.lang)}"
|
||||||
|
|
||||||
keyboard_builder.row(
|
keyboard_builder.row(
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder
|
|||||||
from typing import Any, Callable, TYPE_CHECKING, Literal, Union
|
from typing import Any, Callable, TYPE_CHECKING, Literal, Union
|
||||||
from babel.support import LazyProxy
|
from babel.support import LazyProxy
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
from fastapi.datastructures import State
|
||||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||||
|
|
||||||
from .role import RoleBase
|
from .role import RoleBase
|
||||||
@@ -16,29 +17,32 @@ if TYPE_CHECKING:
|
|||||||
from ..main import QBotApp
|
from ..main import QBotApp
|
||||||
from .user import UserBase
|
from .user import UserBase
|
||||||
|
|
||||||
EntityCaptionCallable = Callable[["EntityDescriptor"], str]
|
# EntityCaptionCallable = Callable[["EntityDescriptor"], str]
|
||||||
EntityItemCaptionCallable = Callable[["EntityDescriptor", Any], str]
|
# EntityItemCaptionCallable = Callable[["EntityDescriptor", Any], str]
|
||||||
EntityFieldCaptionCallable = Callable[["FieldDescriptor", Any, Any], str]
|
# EntityFieldCaptionCallable = Callable[["FieldDescriptor", Any, Any], str]
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class FieldEditButton:
|
class FieldEditButton:
|
||||||
field_name: str
|
field_name: str
|
||||||
caption: str | LazyProxy | EntityFieldCaptionCallable | None = None
|
caption: str | LazyProxy | Callable[["BotEntity", "BotContext"], str] | None = None
|
||||||
visibility: Callable[[Any], bool] | None = None
|
visibility: Callable[["BotEntity", "BotContext"], bool] | None = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class CommandButton:
|
class CommandButton:
|
||||||
command: ContextData | Callable[[ContextData, Any], ContextData] | str
|
command: ContextData | Callable[[ContextData, Any], ContextData] | str
|
||||||
caption: str | LazyProxy | EntityItemCaptionCallable
|
caption: str | LazyProxy | Callable[["BotEntity", "BotContext"], str] | None = None
|
||||||
visibility: Callable[[Any], bool] | None = None
|
visibility: Callable[["BotEntity", "BotContext"], bool] | None = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class InlineButton:
|
class InlineButton:
|
||||||
inline_button: InlineKeyboardButton | Callable[[Any], InlineKeyboardButton]
|
inline_button: (
|
||||||
visibility: Callable[[Any], bool] | None = None
|
InlineKeyboardButton
|
||||||
|
| Callable[["BotEntity", "BotContext"], InlineKeyboardButton]
|
||||||
|
)
|
||||||
|
visibility: Callable[["BotEntity", "BotContext"], bool] | None = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -66,8 +70,10 @@ class Filter:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class EntityList:
|
class EntityList:
|
||||||
caption: str | LazyProxy | EntityCaptionCallable | None = None
|
caption: (
|
||||||
item_repr: EntityItemCaptionCallable | None = None
|
str | LazyProxy | Callable[["EntityDescriptor", "BotContext"], str] | None
|
||||||
|
) = None
|
||||||
|
item_repr: Callable[["BotEntity", "BotContext"], str] | None = None
|
||||||
show_add_new_button: bool = True
|
show_add_new_button: bool = True
|
||||||
item_form: str | None = None
|
item_form: str | None = None
|
||||||
pagination: bool = True
|
pagination: bool = True
|
||||||
@@ -79,7 +85,7 @@ class EntityList:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class EntityForm:
|
class EntityForm:
|
||||||
item_repr: EntityItemCaptionCallable | None = None
|
item_repr: Callable[["BotEntity", "BotContext"], str] | None = None
|
||||||
edit_field_sequence: list[str] = None
|
edit_field_sequence: list[str] = None
|
||||||
form_buttons: list[list[FieldEditButton | CommandButton | InlineButton]] = None
|
form_buttons: list[list[FieldEditButton | CommandButton | InlineButton]] = None
|
||||||
show_edit_button: bool = True
|
show_edit_button: bool = True
|
||||||
@@ -89,11 +95,24 @@ class EntityForm:
|
|||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
class _BaseFieldDescriptor:
|
class _BaseFieldDescriptor:
|
||||||
icon: str = None
|
icon: str = None
|
||||||
caption: str | LazyProxy | EntityFieldCaptionCallable | None = None
|
caption: (
|
||||||
description: str | LazyProxy | EntityFieldCaptionCallable | None = None
|
str | LazyProxy | Callable[["FieldDescriptor", "BotContext"], str] | None
|
||||||
edit_prompt: str | LazyProxy | EntityFieldCaptionCallable | None = None
|
) = None
|
||||||
caption_value: EntityFieldCaptionCallable | None = None
|
description: (
|
||||||
is_visible: bool | None = None
|
str | LazyProxy | Callable[["FieldDescriptor", "BotContext"], str] | None
|
||||||
|
) = None
|
||||||
|
edit_prompt: (
|
||||||
|
str
|
||||||
|
| LazyProxy
|
||||||
|
| Callable[["FieldDescriptor", Union["BotEntity", Any], "BotContext"], str]
|
||||||
|
| None
|
||||||
|
) = None
|
||||||
|
caption_value: (
|
||||||
|
Callable[["FieldDescriptor", Union["BotEntity", Any], "BotContext"], str] | None
|
||||||
|
) = None
|
||||||
|
is_visible: (
|
||||||
|
bool | Callable[["FieldDescriptor", "BotEntity", "BotContext"], bool] | None
|
||||||
|
) = None
|
||||||
localizable: bool = False
|
localizable: bool = False
|
||||||
bool_false_value: str | LazyProxy = "no"
|
bool_false_value: str | LazyProxy = "no"
|
||||||
bool_true_value: str | LazyProxy = "yes"
|
bool_true_value: str | LazyProxy = "yes"
|
||||||
@@ -140,10 +159,16 @@ class FieldDescriptor(_BaseFieldDescriptor):
|
|||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
class _BaseEntityDescriptor:
|
class _BaseEntityDescriptor:
|
||||||
icon: str = "📘"
|
icon: str = "📘"
|
||||||
full_name: str | LazyProxy | EntityCaptionCallable | None = None
|
full_name: (
|
||||||
full_name_plural: str | LazyProxy | EntityCaptionCallable | None = None
|
str | LazyProxy | Callable[["EntityDescriptor", "BotContext"], str] | None
|
||||||
description: str | LazyProxy | EntityCaptionCallable | None = None
|
) = None
|
||||||
item_repr: EntityItemCaptionCallable | None = None
|
full_name_plural: (
|
||||||
|
str | LazyProxy | Callable[["EntityDescriptor", "BotContext"], str] | None
|
||||||
|
) = None
|
||||||
|
description: (
|
||||||
|
str | LazyProxy | Callable[["EntityDescriptor", "BotContext"], str] | None
|
||||||
|
) = None
|
||||||
|
item_repr: Callable[["BotEntity", "BotContext"], str] | None = None
|
||||||
default_list: EntityList = field(default_factory=EntityList)
|
default_list: EntityList = field(default_factory=EntityList)
|
||||||
default_form: EntityForm = field(default_factory=EntityForm)
|
default_form: EntityForm = field(default_factory=EntityForm)
|
||||||
lists: dict[str, EntityList] = field(default_factory=dict[str, EntityList])
|
lists: dict[str, EntityList] = field(default_factory=dict[str, EntityList])
|
||||||
@@ -164,9 +189,9 @@ class _BaseEntityDescriptor:
|
|||||||
EntityPermission.DELETE_ALL: [RoleBase.SUPER_USER],
|
EntityPermission.DELETE_ALL: [RoleBase.SUPER_USER],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
on_created: Callable[["BotEntity", "EntityEventContext"], None] | None = None
|
on_created: Callable[["BotEntity", "BotContext"], None] | None = None
|
||||||
on_deleted: Callable[["BotEntity", "EntityEventContext"], None] | None = None
|
on_deleted: Callable[["BotEntity", "BotContext"], None] | None = None
|
||||||
on_updated: Callable[["BotEntity", "EntityEventContext"], None] | None = None
|
on_updated: Callable[["BotEntity", "BotContext"], None] | None = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
@@ -202,9 +227,10 @@ class CommandCallbackContext[UT: UserBase]:
|
|||||||
|
|
||||||
|
|
||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
class EntityEventContext:
|
class BotContext:
|
||||||
db_session: AsyncSession
|
db_session: AsyncSession
|
||||||
app: "QBotApp"
|
app: "QBotApp"
|
||||||
|
app_state: State
|
||||||
message: Message | CallbackQuery | None = None
|
message: Message | CallbackQuery | None = None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from babel.support import LazyProxy
|
|||||||
from inspect import iscoroutinefunction, signature
|
from inspect import iscoroutinefunction, signature
|
||||||
from aiogram.types import Message, CallbackQuery
|
from aiogram.types import Message, CallbackQuery
|
||||||
from aiogram.utils.i18n import I18n
|
from aiogram.utils.i18n import I18n
|
||||||
from typing import Any, TYPE_CHECKING
|
from typing import Any, TYPE_CHECKING, Callable
|
||||||
import ujson as json
|
import ujson as json
|
||||||
|
|
||||||
from ..model.bot_entity import BotEntity
|
from ..model.bot_entity import BotEntity
|
||||||
@@ -10,15 +10,14 @@ from ..model.bot_enum import BotEnum
|
|||||||
from ..model.settings import Settings
|
from ..model.settings import Settings
|
||||||
|
|
||||||
from ..model.descriptors import (
|
from ..model.descriptors import (
|
||||||
|
BotContext,
|
||||||
|
EntityList,
|
||||||
FieldDescriptor,
|
FieldDescriptor,
|
||||||
EntityDescriptor,
|
EntityDescriptor,
|
||||||
EntityItemCaptionCallable,
|
|
||||||
EntityFieldCaptionCallable,
|
|
||||||
EntityPermission,
|
EntityPermission,
|
||||||
EntityCaptionCallable,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from ..bot.handlers.context import ContextData, CommandContext
|
from ..bot.handlers.context import CallbackCommand, ContextData, CommandContext
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..model.user import UserBase
|
from ..model.user import UserBase
|
||||||
@@ -106,24 +105,38 @@ def clear_state(state_data: dict, clear_nav: bool = False):
|
|||||||
|
|
||||||
|
|
||||||
async def get_entity_item_repr(
|
async def get_entity_item_repr(
|
||||||
entity: BotEntity, item_repr: EntityItemCaptionCallable | None = None
|
entity: BotEntity,
|
||||||
|
context: BotContext,
|
||||||
|
item_repr: Callable[[BotEntity, BotContext], str] | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
descr = entity.bot_entity_descriptor
|
descr = entity.bot_entity_descriptor
|
||||||
|
|
||||||
|
if not item_repr:
|
||||||
|
item_repr = descr.item_repr
|
||||||
|
|
||||||
if item_repr:
|
if item_repr:
|
||||||
return item_repr(descr, entity)
|
if iscoroutinefunction(item_repr):
|
||||||
return (
|
return await item_repr(entity, context)
|
||||||
descr.item_repr(descr, entity)
|
else:
|
||||||
if descr.item_repr
|
return item_repr(entity, context)
|
||||||
else f"{
|
|
||||||
await get_callable_str(descr.full_name, descr, entity)
|
return f"{
|
||||||
|
await get_callable_str(
|
||||||
|
callable_str=descr.full_name,
|
||||||
|
context=context,
|
||||||
|
descriptor=descr,
|
||||||
|
entity=entity,
|
||||||
|
)
|
||||||
if descr.full_name
|
if descr.full_name
|
||||||
else descr.name
|
else descr.name
|
||||||
}: {str(entity.id)}"
|
}: {str(entity.id)}"
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def get_value_repr(
|
async def get_value_repr(
|
||||||
value: Any, field_descriptor: FieldDescriptor, locale: str | None = None
|
value: Any,
|
||||||
|
field_descriptor: FieldDescriptor,
|
||||||
|
context: BotContext,
|
||||||
|
locale: str | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
if value is None:
|
if value is None:
|
||||||
return ""
|
return ""
|
||||||
@@ -133,9 +146,14 @@ async def get_value_repr(
|
|||||||
return "【✔︎】" if value else "【 】"
|
return "【✔︎】" if value else "【 】"
|
||||||
elif field_descriptor.is_list:
|
elif field_descriptor.is_list:
|
||||||
if issubclass(type_, BotEntity):
|
if issubclass(type_, BotEntity):
|
||||||
return (
|
return f"[{
|
||||||
f"[{', '.join([await get_entity_item_repr(item) for item in value])}]"
|
', '.join(
|
||||||
|
[
|
||||||
|
await get_entity_item_repr(entity=item, context=context)
|
||||||
|
for item in value
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
}]"
|
||||||
elif issubclass(type_, BotEnum):
|
elif issubclass(type_, BotEnum):
|
||||||
return f"[{', '.join(item.localized(locale) for item in value)}]"
|
return f"[{', '.join(item.localized(locale) for item in value)}]"
|
||||||
elif type_ is str:
|
elif type_ is str:
|
||||||
@@ -143,7 +161,7 @@ async def get_value_repr(
|
|||||||
else:
|
else:
|
||||||
return f"[{', '.join([str(item) for item in value])}]"
|
return f"[{', '.join([str(item) for item in value])}]"
|
||||||
elif issubclass(type_, BotEntity):
|
elif issubclass(type_, BotEntity):
|
||||||
return await get_entity_item_repr(value)
|
return await get_entity_item_repr(entity=value, context=context)
|
||||||
elif issubclass(type_, BotEnum):
|
elif issubclass(type_, BotEnum):
|
||||||
return value.localized(locale)
|
return value.localized(locale)
|
||||||
elif isinstance(value, str):
|
elif isinstance(value, str):
|
||||||
@@ -162,13 +180,13 @@ async def get_callable_str(
|
|||||||
callable_str: (
|
callable_str: (
|
||||||
str
|
str
|
||||||
| LazyProxy
|
| LazyProxy
|
||||||
| EntityCaptionCallable
|
| Callable[[EntityDescriptor, BotContext], str]
|
||||||
| EntityItemCaptionCallable
|
| Callable[[BotEntity, BotContext], str]
|
||||||
| EntityFieldCaptionCallable
|
| Callable[[FieldDescriptor, BotEntity, BotContext], str]
|
||||||
),
|
),
|
||||||
descriptor: FieldDescriptor | EntityDescriptor,
|
context: BotContext,
|
||||||
entity: Any = None,
|
descriptor: FieldDescriptor | EntityDescriptor | None = None,
|
||||||
value: Any = None,
|
entity: BotEntity | Any = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
if isinstance(callable_str, str):
|
if isinstance(callable_str, str):
|
||||||
return callable_str
|
return callable_str
|
||||||
@@ -177,19 +195,22 @@ async def get_callable_str(
|
|||||||
elif callable(callable_str):
|
elif callable(callable_str):
|
||||||
args = signature(callable_str).parameters
|
args = signature(callable_str).parameters
|
||||||
if iscoroutinefunction(callable_str):
|
if iscoroutinefunction(callable_str):
|
||||||
if len(args) == 1:
|
if len(args) == 3:
|
||||||
return await callable_str(descriptor)
|
return await callable_str(descriptor, entity, context)
|
||||||
elif len(args) == 2:
|
|
||||||
return await callable_str(descriptor, entity)
|
|
||||||
elif len(args) == 3:
|
|
||||||
return await callable_str(descriptor, entity, value)
|
|
||||||
else:
|
else:
|
||||||
if len(args) == 1:
|
if issubclass(args[0].annotation, BotEntity):
|
||||||
return callable_str(descriptor)
|
return await callable_str(entity, context)
|
||||||
elif len(args) == 2:
|
else:
|
||||||
return callable_str(descriptor, entity)
|
return await callable_str(descriptor, context)
|
||||||
elif len(args) == 3:
|
else:
|
||||||
return callable_str(descriptor, entity, value)
|
if len(args) == 3:
|
||||||
|
return callable_str(descriptor, entity, context)
|
||||||
|
else:
|
||||||
|
return callable_str(entity or descriptor, context)
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"Invalid callable type: {type(callable_str)}. Expected str, LazyProxy or callable."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_entity_descriptor(
|
def get_entity_descriptor(
|
||||||
@@ -225,19 +246,45 @@ def get_field_descriptor(
|
|||||||
|
|
||||||
|
|
||||||
def build_field_sequence(
|
def build_field_sequence(
|
||||||
entity_descriptor: EntityDescriptor, user: "UserBase", callback_data: ContextData
|
entity_descriptor: EntityDescriptor,
|
||||||
|
user: "UserBase",
|
||||||
|
callback_data: ContextData,
|
||||||
|
state_data: dict,
|
||||||
):
|
):
|
||||||
|
prev_form_list = None
|
||||||
|
|
||||||
|
stack = state_data.get("navigation_stack", [])
|
||||||
|
prev_callback_data = ContextData.unpack(stack[-1]) if stack else None
|
||||||
|
if (
|
||||||
|
prev_callback_data
|
||||||
|
and prev_callback_data.command == CallbackCommand.ENTITY_LIST
|
||||||
|
and prev_callback_data.entity_name == entity_descriptor.name
|
||||||
|
):
|
||||||
|
prev_form_name = (
|
||||||
|
prev_callback_data.form_params.split("&")[0]
|
||||||
|
if prev_callback_data.form_params
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
prev_form_list: EntityList = entity_descriptor.lists.get(
|
||||||
|
prev_form_name, entity_descriptor.default_list
|
||||||
|
)
|
||||||
|
|
||||||
field_sequence = list[str]()
|
field_sequence = list[str]()
|
||||||
# exclude ownership fields from edit if user has no CREATE_ALL/UPDATE_ALL permission
|
# exclude ownership fields from edit if user has no CREATE_ALL/UPDATE_ALL permission
|
||||||
user_permissions = get_user_permissions(user, entity_descriptor)
|
user_permissions = get_user_permissions(user, entity_descriptor)
|
||||||
for fd in entity_descriptor.fields_descriptors.values():
|
for fd in entity_descriptor.fields_descriptors.values():
|
||||||
if not (
|
skip = False
|
||||||
|
if (
|
||||||
fd.is_optional
|
fd.is_optional
|
||||||
or fd.field_name == "id"
|
or fd.field_name == "id"
|
||||||
or fd.field_name[:-3] == "_id"
|
or (
|
||||||
|
fd.field_name[-3:] == "_id"
|
||||||
|
and fd.field_name[:-3] in entity_descriptor.fields_descriptors
|
||||||
|
)
|
||||||
or fd.default is not None
|
or fd.default is not None
|
||||||
|
or fd.default_factory is not None
|
||||||
):
|
):
|
||||||
skip = False
|
skip = True
|
||||||
for own_field in entity_descriptor.ownership_fields.items():
|
for own_field in entity_descriptor.ownership_fields.items():
|
||||||
if (
|
if (
|
||||||
own_field[1].rstrip("_id") == fd.field_name.rstrip("_id")
|
own_field[1].rstrip("_id") == fd.field_name.rstrip("_id")
|
||||||
@@ -255,6 +302,15 @@ def build_field_sequence(
|
|||||||
):
|
):
|
||||||
skip = True
|
skip = True
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if (
|
||||||
|
prev_form_list
|
||||||
|
and prev_form_list.static_filters
|
||||||
|
and fd.field_name.rstrip("_id")
|
||||||
|
in [f.field_name.rstrip("_id") for f in prev_form_list.static_filters]
|
||||||
|
):
|
||||||
|
skip = True
|
||||||
|
|
||||||
if not skip:
|
if not skip:
|
||||||
field_sequence.append(fd.field_name)
|
field_sequence.append(fd.field_name)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user