Coverage for src/lexigram/admin/actions/row_manager/types.py: 0%

73 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-24 23:18 +0800

1""" 

2Types and data structures for row action management. 

3 

4Provides enums, dataclasses, and protocols for row actions. 

5""" 

6 

7from __future__ import annotations 

8 

9from collections.abc import Callable 

10from dataclasses import dataclass, field 

11from enum import StrEnum 

12from typing import Any, Protocol, TypeVar 

13 

14T = TypeVar("T") 

15 

16 

17class ActionStyle(StrEnum): 

18 """Visual style for actions.""" 

19 

20 PRIMARY = "primary" 

21 SECONDARY = "secondary" 

22 SUCCESS = "success" 

23 DANGER = "danger" 

24 WARNING = "warning" 

25 INFO = "info" 

26 

27 

28class ActionPosition(StrEnum): 

29 """Where to display the action.""" 

30 

31 ROW_START = "row_start" # Before row content 

32 ROW_END = "row_end" # After row content (default) 

33 DROPDOWN = "dropdown" # In overflow menu 

34 

35 

36@dataclass(slots=True) 

37class RowAction: 

38 """Configuration for a row action.""" 

39 

40 name: str 

41 """Action identifier.""" 

42 

43 label: str 

44 """Display label.""" 

45 

46 handler: Callable[[Any], Any] | None = None 

47 """Async function to execute the action.""" 

48 

49 icon: str | None = None 

50 """Icon name (e.g., 'eye', 'edit', 'trash').""" 

51 

52 style: ActionStyle = ActionStyle.SECONDARY 

53 """Visual style.""" 

54 

55 position: ActionPosition = ActionPosition.ROW_END 

56 """Where to display the action.""" 

57 

58 confirm: bool = False 

59 """Whether to show confirmation dialog.""" 

60 

61 confirm_message: str | None = None 

62 """Custom confirmation message.""" 

63 

64 url: str | None = None 

65 """URL for link-based actions (alternative to handler).""" 

66 

67 method: str = "GET" 

68 """HTTP method for URL-based actions.""" 

69 

70 open_in_modal: bool = False 

71 """Whether to open URL in a modal.""" 

72 

73 keyboard_shortcut: str | None = None 

74 """Keyboard shortcut (e.g., 'e', 'Ctrl+D').""" 

75 

76 visible: Callable[[Any], bool] = lambda _: True 

77 """Function to determine if action is visible for a record.""" 

78 

79 disabled: Callable[[Any], bool] = lambda _: False 

80 """Function to determine if action is disabled for a record.""" 

81 

82 tooltip: str | None = None 

83 """Tooltip text.""" 

84 

85 badge: str | None = None 

86 """Badge text (e.g., "New", "Beta").""" 

87 

88 group: str | None = None 

89 """Group name for organizing actions in dropdown.""" 

90 

91 metadata: dict[str, Any] = field(default_factory=dict) 

92 """Additional metadata.""" 

93 

94 

95@dataclass(slots=True) 

96class ActionGroup: 

97 """Group of related actions shown in a dropdown menu.""" 

98 

99 name: str 

100 """Group identifier.""" 

101 

102 label: str 

103 """Display label for the dropdown button.""" 

104 

105 icon: str | None = "menu" 

106 """Icon for dropdown button.""" 

107 

108 actions: list[RowAction] = field(default_factory=list) 

109 """Actions in this group.""" 

110 

111 style: ActionStyle = ActionStyle.SECONDARY 

112 """Visual style.""" 

113 

114 visible: Callable[[Any], bool] = lambda _: True 

115 """Function to determine if group is visible.""" 

116 

117 

118class IRowDataSource(Protocol[T]): # type: ignore[misc] 

119 """Protocol for data sources that support row operations.""" 

120 

121 async def get_by_id(self, record_id: Any) -> T | None: 

122 """Get a single record by ID.""" 

123 ... 

124 

125 async def delete(self, record_id: Any) -> bool: 

126 """Delete a record.""" 

127 ... 

128 

129 async def duplicate(self, record_id: Any) -> T: 

130 """Duplicate a record.""" 

131 ...