from abc import ABC from dataclasses import dataclass from typing import Any, Generic, TypeVar from velai.nodes.actions.node_action_decorator import register_annotated_actions from velai.nodes.actions.node_action_models import AsyncNodeActionResultIterator, NodeActionArguments from velai.nodes.actions.node_action_registry import NodeActionNotFoundError, NodeActionRegistry from velai.nodes.base_node import BaseNode, logger from velai.nodes.vue_nodes import VueNodeData, VueNodeRenderable T_BASE_NODE = TypeVar("T_BASE_NODE", bound=BaseNode) @dataclass class NodeRenderableConfig: resizable: bool = True min_width: int = 250 min_height: int = 200 max_width: int = 720 max_height: int = 720 class BaseNodeRenderable(VueNodeRenderable[T_BASE_NODE], Generic[T_BASE_NODE], ABC): def __init__(self): super().__init__() self.config = NodeRenderableConfig() # create registry and automatically find registered actions self.action_registry = NodeActionRegistry() register_annotated_actions(self.action_registry, self) async def run_custom_action(self, args: NodeActionArguments) -> AsyncNodeActionResultIterator: try: async for result in self.action_registry.run_action(args): yield result except NodeActionNotFoundError: logger.exception() # todo: create actual renderable fields that correspond to the vue components def get_header_buttons(self, node: T_BASE_NODE) -> list[dict[str, Any]]: return [] def get_fields(self, node: T_BASE_NODE) -> list[dict[str, Any]]: return [] def get_settings(self, node: T_BASE_NODE) -> list[dict[str, Any]]: return [] def to_vue_node_data(self, node: T_BASE_NODE) -> VueNodeData: data = VueNodeData() data.title = node.get_display_title() data.defaultTitle = node.node_type.display_name data.kind = node.node_type.kind.value data.headerButtons += self.get_header_buttons(node) data.fields += self.get_fields(node) data.settings += self.get_settings(node) state = node.get_state() data.values.update(**state) data.resizable = self.config.resizable data.min_width = self.config.min_width data.min_height_px = self.config.min_height data.max_width = self.config.max_width data.max_height = self.config.max_height return data