added attribute types: TextMultilingual, multiselect
This commit is contained in:
parent
d009f93dba
commit
72f5fbde46
4 changed files with 84 additions and 15 deletions
|
|
@ -5,6 +5,7 @@ from typing import Optional, Dict
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
from modules.shared.attributeUtils import registerModelLabels
|
from modules.shared.attributeUtils import registerModelLabels
|
||||||
|
from modules.datamodels.datamodelUtils import TextMultilingual
|
||||||
from modules.datamodels.datamodelUam import AccessLevel
|
from modules.datamodels.datamodelUam import AccessLevel
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -26,9 +27,9 @@ class Role(BaseModel):
|
||||||
description="Unique role label identifier (e.g., 'admin', 'user', 'viewer')",
|
description="Unique role label identifier (e.g., 'admin', 'user', 'viewer')",
|
||||||
json_schema_extra={"frontend_type": "text", "frontend_readonly": False, "frontend_required": True}
|
json_schema_extra={"frontend_type": "text", "frontend_readonly": False, "frontend_required": True}
|
||||||
)
|
)
|
||||||
description: Dict[str, str] = Field(
|
description: TextMultilingual = Field(
|
||||||
description="Role description in multiple languages",
|
description="Role description in multiple languages",
|
||||||
json_schema_extra={"frontend_type": "object", "frontend_readonly": False, "frontend_required": True}
|
json_schema_extra={"frontend_type": "multilingual", "frontend_readonly": False, "frontend_required": True}
|
||||||
)
|
)
|
||||||
isSystemRole: bool = Field(
|
isSystemRole: bool = Field(
|
||||||
False,
|
False,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
"""Utility datamodels: Prompt."""
|
"""Utility datamodels: Prompt, TextMultilingual."""
|
||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from typing import Dict, Optional
|
||||||
|
from pydantic import BaseModel, Field, field_validator
|
||||||
from modules.shared.attributeUtils import registerModelLabels
|
from modules.shared.attributeUtils import registerModelLabels
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
|
@ -22,3 +23,49 @@ registerModelLabels(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TextMultilingual(BaseModel):
|
||||||
|
"""
|
||||||
|
Multilingual text field supporting multiple languages.
|
||||||
|
Default languages: en (English), ge (German), fr (French), it (Italian)
|
||||||
|
English (en) is the default/required language.
|
||||||
|
"""
|
||||||
|
en: str = Field(description="English text (default language, required)")
|
||||||
|
ge: Optional[str] = Field(None, description="German text")
|
||||||
|
fr: Optional[str] = Field(None, description="French text")
|
||||||
|
it: Optional[str] = Field(None, description="Italian text")
|
||||||
|
|
||||||
|
@field_validator('en')
|
||||||
|
@classmethod
|
||||||
|
def validate_en_required(cls, v):
|
||||||
|
"""Ensure English text is not empty"""
|
||||||
|
if not v or not v.strip():
|
||||||
|
raise ValueError("English text (en) is required and cannot be empty")
|
||||||
|
return v
|
||||||
|
|
||||||
|
def model_dump(self, **kwargs) -> Dict[str, str]:
|
||||||
|
"""Return as dictionary, filtering out None values"""
|
||||||
|
result = {}
|
||||||
|
for lang in ['en', 'ge', 'fr', 'it']:
|
||||||
|
value = getattr(self, lang, None)
|
||||||
|
if value is not None:
|
||||||
|
result[lang] = value
|
||||||
|
return result
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: Dict[str, str]) -> 'TextMultilingual':
|
||||||
|
"""Create TextMultilingual from dictionary"""
|
||||||
|
return cls(
|
||||||
|
en=data.get('en', ''),
|
||||||
|
ge=data.get('ge'),
|
||||||
|
fr=data.get('fr'),
|
||||||
|
it=data.get('it')
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_text(self, lang: str = 'en') -> str:
|
||||||
|
"""Get text for a specific language, fallback to English if not available"""
|
||||||
|
value = getattr(self, lang, None)
|
||||||
|
if value:
|
||||||
|
return value
|
||||||
|
return self.en # Fallback to English
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,17 @@ def getOptions(optionsName: str, currentUser: Optional[User] = None) -> List[Dic
|
||||||
options = []
|
options = []
|
||||||
for role in roles:
|
for role in roles:
|
||||||
# Use English description as label, fallback to roleLabel
|
# Use English description as label, fallback to roleLabel
|
||||||
label = role.description.get("en", role.roleLabel) if isinstance(role.description, dict) else role.roleLabel
|
# Handle TextMultilingual object
|
||||||
|
if hasattr(role.description, 'get_text'):
|
||||||
|
# TextMultilingual object
|
||||||
|
label = role.description.get_text('en')
|
||||||
|
elif isinstance(role.description, dict):
|
||||||
|
# Dict format (backward compatibility)
|
||||||
|
label = role.description.get("en", role.roleLabel)
|
||||||
|
else:
|
||||||
|
# Fallback to roleLabel
|
||||||
|
label = role.roleLabel
|
||||||
|
|
||||||
options.append({
|
options.append({
|
||||||
"value": role.roleLabel,
|
"value": role.roleLabel,
|
||||||
"label": label
|
"label": label
|
||||||
|
|
|
||||||
|
|
@ -166,16 +166,27 @@ def getModelAttributeDefinitions(modelClass: Type[BaseModel] = None, userLanguag
|
||||||
if frontend_options is None and "frontend_options" in json_extra:
|
if frontend_options is None and "frontend_options" in json_extra:
|
||||||
frontend_options = json_extra.get("frontend_options")
|
frontend_options = json_extra.get("frontend_options")
|
||||||
|
|
||||||
# Use frontend type if available, otherwise fall back to Python type
|
# Use frontend type if available, otherwise detect from Python type
|
||||||
field_type = (
|
if frontend_type:
|
||||||
frontend_type
|
field_type = frontend_type
|
||||||
if frontend_type
|
else:
|
||||||
else (
|
# Check if it's TextMultilingual type
|
||||||
field.annotation.__name__
|
annotation_str = str(field.annotation)
|
||||||
if hasattr(field.annotation, "__name__")
|
# Check both the module path and class name for TextMultilingual
|
||||||
else str(field.annotation)
|
if ('TextMultilingual' in annotation_str or
|
||||||
)
|
(hasattr(field.annotation, '__name__') and field.annotation.__name__ == 'TextMultilingual') or
|
||||||
)
|
'datamodelUtils.TextMultilingual' in annotation_str or
|
||||||
|
'datamodels.datamodelUtils.TextMultilingual' in annotation_str):
|
||||||
|
field_type = 'multilingual'
|
||||||
|
elif hasattr(field.annotation, "__name__"):
|
||||||
|
annotation_name = field.annotation.__name__
|
||||||
|
# Check if it's a Dict type (for JSON/object fields)
|
||||||
|
if annotation_name == 'Dict' or annotation_str.startswith('typing.Dict') or annotation_str.startswith('Dict['):
|
||||||
|
field_type = 'object' # Will be rendered as textarea for JSON editing
|
||||||
|
else:
|
||||||
|
field_type = annotation_name
|
||||||
|
else:
|
||||||
|
field_type = str(field.annotation)
|
||||||
|
|
||||||
# Extract default value from field
|
# Extract default value from field
|
||||||
# In Pydantic v2, FieldInfo has a 'default' attribute
|
# In Pydantic v2, FieldInfo has a 'default' attribute
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue