Coverage for netbox/navigation/__init__.py: 88%

50 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 18:35 +0000

1from collections.abc import Sequence 

2from dataclasses import dataclass 

3 

4from django.urls import reverse_lazy 

5 

6__all__ = ( 

7 'Menu', 

8 'MenuGroup', 

9 'MenuItem', 

10 'MenuItemButton', 

11 'get_model_buttons', 

12 'get_model_item', 

13) 

14 

15 

16# 

17# Navigation menu data classes 

18# 

19 

20@dataclass 

21class MenuItemButton: 

22 

23 link: str 

24 title: str 

25 icon_class: str 

26 _url: str | None = None 

27 permissions: Sequence[str] | None = () 

28 color: str | None = None 

29 

30 def __post_init__(self): 

31 if self.link: 31 ↛ exitline 31 didn't return from function '__post_init__' because the condition on line 31 was always true

32 self._url = reverse_lazy(self.link) 

33 

34 @property 

35 def url(self): 

36 return self._url 

37 

38 @url.setter 

39 def url(self, value): 

40 self._url = value 

41 

42 

43@dataclass 

44class MenuItem: 

45 

46 link: str 

47 link_text: str 

48 _url: str | None = None 

49 permissions: Sequence[str] | None = () 

50 auth_required: bool | None = False 

51 staff_only: bool | None = False 

52 buttons: Sequence[MenuItemButton] | None = () 

53 

54 def __post_init__(self): 

55 if self.link: 55 ↛ exitline 55 didn't return from function '__post_init__' because the condition on line 55 was always true

56 self._url = reverse_lazy(self.link) 

57 

58 @property 

59 def url(self): 

60 return self._url 

61 

62 @url.setter 

63 def url(self, value): 

64 self._url = value 

65 

66 

67@dataclass 

68class MenuGroup: 

69 

70 label: str 

71 items: Sequence[MenuItem] 

72 

73 

74@dataclass 

75class Menu: 

76 

77 label: str 

78 icon_class: str 

79 groups: Sequence[MenuGroup] 

80 

81 @property 

82 def name(self): 

83 return self.label.replace(' ', '_') 

84 

85 

86# 

87# Utility functions 

88# 

89 

90def get_model_item(app_label, model_name, label, actions=('add', 'bulk_import')): 

91 return MenuItem( 

92 link=f'{app_label}:{model_name}_list', 

93 link_text=label, 

94 permissions=[f'{app_label}.view_{model_name}'], 

95 buttons=get_model_buttons(app_label, model_name, actions) 

96 ) 

97 

98 

99def get_model_buttons(app_label, model_name, actions=('add', 'bulk_import')): 

100 buttons = [] 

101 

102 if 'add' in actions: 

103 buttons.append( 

104 MenuItemButton( 

105 link=f'{app_label}:{model_name}_add', 

106 title='Add', 

107 icon_class='mdi mdi-plus-thick', 

108 permissions=[f'{app_label}.add_{model_name}'] 

109 ) 

110 ) 

111 if 'bulk_import' in actions: 

112 buttons.append( 

113 MenuItemButton( 

114 link=f'{app_label}:{model_name}_bulk_import', 

115 title='Import', 

116 icon_class='mdi mdi-upload', 

117 permissions=[f'{app_label}.add_{model_name}'] 

118 ) 

119 ) 

120 

121 return buttons