Merge branch 'add_emoji_icon' into dev
This commit is contained in:
commit
33d05a23f3
6 changed files with 47 additions and 14 deletions
|
|
@ -3,9 +3,9 @@ import operator
|
||||||
import warnings
|
import warnings
|
||||||
from typing import Any, ClassVar, Optional
|
from typing import Any, ClassVar, Optional
|
||||||
|
|
||||||
|
import emoji
|
||||||
from cachetools import TTLCache, cachedmethod
|
from cachetools import TTLCache, cachedmethod
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
|
||||||
from langflow.interface.custom.code_parser import CodeParser
|
from langflow.interface.custom.code_parser import CodeParser
|
||||||
from langflow.utils import validate
|
from langflow.utils import validate
|
||||||
|
|
||||||
|
|
@ -35,6 +35,10 @@ class Component:
|
||||||
else:
|
else:
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
# Validate the emoji at the icon field
|
||||||
|
if self.icon:
|
||||||
|
self.icon = self.validate_icon(self.icon)
|
||||||
|
|
||||||
def __setattr__(self, key, value):
|
def __setattr__(self, key, value):
|
||||||
if key == "_user_id" and hasattr(self, "_user_id"):
|
if key == "_user_id" and hasattr(self, "_user_id"):
|
||||||
warnings.warn("user_id is immutable and cannot be changed.")
|
warnings.warn("user_id is immutable and cannot be changed.")
|
||||||
|
|
@ -82,7 +86,22 @@ class Component:
|
||||||
elif "documentation" in item_name:
|
elif "documentation" in item_name:
|
||||||
template_config["documentation"] = ast.literal_eval(item_value)
|
template_config["documentation"] = ast.literal_eval(item_value)
|
||||||
|
|
||||||
|
elif "icon" in item_name:
|
||||||
|
icon_str = ast.literal_eval(item_value)
|
||||||
|
template_config["icon"] = self.validate_icon(icon_str)
|
||||||
|
|
||||||
return template_config
|
return template_config
|
||||||
|
|
||||||
|
def validate_icon(self, value: str):
|
||||||
|
# we are going to use the emoji library to validate the emoji
|
||||||
|
# emojis can be defined using the :emoji_name: syntax
|
||||||
|
if not value.startswith(":") or not value.endswith(":"):
|
||||||
|
raise ValueError("Invalid emoji. Please use the :emoji_name: syntax.")
|
||||||
|
|
||||||
|
emoji_value = emoji.emojize(value, variant="emoji_type")
|
||||||
|
if value == emoji_value:
|
||||||
|
raise ValueError(f"Invalid emoji. {value} is not a valid emoji.")
|
||||||
|
return emoji_value
|
||||||
|
|
||||||
def build(self, *args: Any, **kwargs: Any) -> Any:
|
def build(self, *args: Any, **kwargs: Any) -> Any:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
|
||||||
|
|
@ -10,25 +10,31 @@ from langflow.interface.custom.code_parser.utils import (
|
||||||
extract_inner_type_from_generic_alias,
|
extract_inner_type_from_generic_alias,
|
||||||
extract_union_types_from_generic_alias,
|
extract_union_types_from_generic_alias,
|
||||||
)
|
)
|
||||||
|
from langflow.interface.custom.custom_component.component import Component
|
||||||
from langflow.services.database.models.flow import Flow
|
from langflow.services.database.models.flow import Flow
|
||||||
from langflow.services.database.utils import session_getter
|
from langflow.services.database.utils import session_getter
|
||||||
from langflow.services.deps import get_credential_service, get_db_service
|
from langflow.services.deps import get_credential_service, get_db_service
|
||||||
from langflow.utils import validate
|
from langflow.utils import validate
|
||||||
|
|
||||||
from .component import Component
|
|
||||||
|
|
||||||
|
|
||||||
class CustomComponent(Component):
|
class CustomComponent(Component):
|
||||||
display_name: Optional[str] = None
|
display_name: Optional[str] = None
|
||||||
|
"""The display name of the component. Defaults to None."""
|
||||||
description: Optional[str] = None
|
description: Optional[str] = None
|
||||||
|
"""The description of the component. Defaults to None."""
|
||||||
|
icon: Optional[str] = None
|
||||||
|
"""The icon of the component. It should be an emoji. Defaults to None."""
|
||||||
code: Optional[str] = None
|
code: Optional[str] = None
|
||||||
|
"""The code of the component. Defaults to None."""
|
||||||
field_config: dict = {}
|
field_config: dict = {}
|
||||||
|
"""The field configuration of the component. Defaults to an empty dictionary."""
|
||||||
code_class_base_inheritance: ClassVar[str] = "CustomComponent"
|
code_class_base_inheritance: ClassVar[str] = "CustomComponent"
|
||||||
function_entrypoint_name: ClassVar[str] = "build"
|
function_entrypoint_name: ClassVar[str] = "build"
|
||||||
function: Optional[Callable] = None
|
function: Optional[Callable] = None
|
||||||
repr_value: Optional[Any] = ""
|
repr_value: Optional[Any] = ""
|
||||||
user_id: Optional[Union[UUID, str]] = None
|
user_id: Optional[Union[UUID, str]] = None
|
||||||
status: Optional[Any] = None
|
status: Optional[Any] = None
|
||||||
|
"""The status of the component. This is displayed on the frontend. Defaults to None."""
|
||||||
_tree: Optional[dict] = None
|
_tree: Optional[dict] = None
|
||||||
|
|
||||||
def __init__(self, **data):
|
def __init__(self, **data):
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ from typing import Any, Dict, List, Optional, Union
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
from langflow.field_typing.range_spec import RangeSpec
|
from langflow.field_typing.range_spec import RangeSpec
|
||||||
from langflow.interface.custom.code_parser.utils import extract_inner_type
|
from langflow.interface.custom.code_parser.utils import extract_inner_type
|
||||||
from langflow.interface.custom.custom_component import CustomComponent
|
from langflow.interface.custom.custom_component import CustomComponent
|
||||||
|
|
@ -19,7 +21,6 @@ from langflow.interface.importing.utils import eval_custom_component_code
|
||||||
from langflow.template.field.base import TemplateField
|
from langflow.template.field.base import TemplateField
|
||||||
from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode
|
from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode
|
||||||
from langflow.utils.util import get_base_classes
|
from langflow.utils.util import get_base_classes
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
|
|
||||||
def add_output_types(frontend_node: CustomComponentFrontendNode, return_types: List[str]):
|
def add_output_types(frontend_node: CustomComponentFrontendNode, return_types: List[str]):
|
||||||
|
|
@ -231,6 +232,7 @@ def sanitize_template_config(template_config):
|
||||||
"beta",
|
"beta",
|
||||||
"documentation",
|
"documentation",
|
||||||
"output_types",
|
"output_types",
|
||||||
|
"icon",
|
||||||
}
|
}
|
||||||
for key in template_config.copy():
|
for key in template_config.copy():
|
||||||
if key not in attributes:
|
if key not in attributes:
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,12 @@ import re
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import ClassVar, Dict, List, Optional, Union
|
from typing import ClassVar, Dict, List, Optional, Union
|
||||||
|
|
||||||
from pydantic import BaseModel, Field, field_serializer, model_serializer
|
|
||||||
|
|
||||||
from langflow.template.field.base import TemplateField
|
from langflow.template.field.base import TemplateField
|
||||||
from langflow.template.frontend_node.constants import CLASSES_TO_REMOVE, FORCE_SHOW_FIELDS
|
from langflow.template.frontend_node.constants import CLASSES_TO_REMOVE, FORCE_SHOW_FIELDS
|
||||||
from langflow.template.frontend_node.formatter import field_formatters
|
from langflow.template.frontend_node.formatter import field_formatters
|
||||||
from langflow.template.template.base import Template
|
from langflow.template.template.base import Template
|
||||||
from langflow.utils import constants
|
from langflow.utils import constants
|
||||||
|
from pydantic import BaseModel, Field, field_serializer, model_serializer
|
||||||
|
|
||||||
|
|
||||||
class FieldFormatters(BaseModel):
|
class FieldFormatters(BaseModel):
|
||||||
|
|
@ -43,6 +42,7 @@ class FrontendNode(BaseModel):
|
||||||
_format_template: bool = True
|
_format_template: bool = True
|
||||||
template: Template
|
template: Template
|
||||||
description: Optional[str] = None
|
description: Optional[str] = None
|
||||||
|
icon: Optional[str] = None
|
||||||
base_classes: List[str]
|
base_classes: List[str]
|
||||||
name: str = ""
|
name: str = ""
|
||||||
display_name: Optional[str] = ""
|
display_name: Optional[str] = ""
|
||||||
|
|
|
||||||
|
|
@ -156,14 +156,19 @@ export default function GenericNode({
|
||||||
(!showNode && "justify-center")
|
(!showNode && "justify-center")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<IconComponent
|
{data?.node?.icon ? (
|
||||||
name={data.node?.flow ? "group_components" : name}
|
<span className="text-lg">{data?.node?.icon}</span>
|
||||||
className={
|
) : (
|
||||||
"generic-node-icon " +
|
<IconComponent
|
||||||
(!showNode ? "absolute inset-x-6 h-12 w-12" : "")
|
name={data.node?.flow ? "group_components" : name}
|
||||||
}
|
className={
|
||||||
iconColor={`${nodeColors[types[data.type]]}`}
|
"generic-node-icon " +
|
||||||
/>
|
(!showNode ? "absolute inset-x-6 h-12 w-12" : "")
|
||||||
|
}
|
||||||
|
iconColor={`${nodeColors[types[data.type]]}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{showNode && (
|
{showNode && (
|
||||||
<div className="generic-node-tooltip-div">
|
<div className="generic-node-tooltip-div">
|
||||||
{nameEditable && inputName ? (
|
{nameEditable && inputName ? (
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ export type APIClassType = {
|
||||||
description: string;
|
description: string;
|
||||||
template: APITemplateType;
|
template: APITemplateType;
|
||||||
display_name: string;
|
display_name: string;
|
||||||
|
icon?: string;
|
||||||
input_types?: Array<string>;
|
input_types?: Array<string>;
|
||||||
output_types?: Array<string>;
|
output_types?: Array<string>;
|
||||||
custom_fields?: CustomFieldsType;
|
custom_fields?: CustomFieldsType;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue