1- from abc import ABC , ABCMeta , abstractmethod
1+ from abc import ABC , ABCMeta
22
3+ from django .contrib .contenttypes .models import ContentType
34from django .template .loader import render_to_string
45from django .utils .translation import gettext_lazy as _
56
6- from netbox .ui import attrs
7+ from netbox .ui import actions , attrs
78from netbox .ui .attrs import Attr
89from utilities .querydict import dict_to_querydict
910from utilities .string import title
2425
2526
2627class Panel (ABC ):
28+ template_name = None
29+ title = None
30+ actions = []
2731
28- def __init__ (self , title = None ):
32+ def __init__ (self , title = None , actions = None ):
2933 if title is not None :
3034 self .title = title
35+ if actions is not None :
36+ self .actions = actions
37+
38+ def get_context (self , obj ):
39+ return {}
3140
32- @abstractmethod
33- def render (self , obj ):
34- pass
41+ def render (self , context ):
42+ obj = context .get ('object' )
43+ return render_to_string (self .template_name , {
44+ 'request' : context .get ('request' ),
45+ 'object' : obj ,
46+ 'title' : self .title ,
47+ 'actions' : [action .get_context (obj ) for action in self .actions ],
48+ ** self .get_context (obj ),
49+ })
3550
3651
3752class ObjectPanelMeta (ABCMeta ):
@@ -64,20 +79,16 @@ def __new__(mcls, name, bases, namespace, **kwargs):
6479class ObjectPanel (Panel , metaclass = ObjectPanelMeta ):
6580 template_name = 'ui/panels/object.html'
6681
67- def get_attributes (self , obj ):
68- return [
82+ def get_context (self , obj ):
83+ attrs = [
6984 {
7085 'label' : attr .label or title (name ),
7186 'value' : attr .render (obj , {'name' : name }),
7287 } for name , attr in self ._attrs .items ()
7388 ]
74-
75- def render (self , context ):
76- obj = context .get ('object' )
77- return render_to_string (self .template_name , {
78- 'title' : self .title ,
79- 'attrs' : self .get_attributes (obj ),
80- })
89+ return {
90+ 'attrs' : attrs ,
91+ }
8192
8293
8394class NestedGroupObjectPanel (ObjectPanel , metaclass = ObjectPanelMeta ):
@@ -90,44 +101,27 @@ class CustomFieldsPanel(Panel):
90101 template_name = 'ui/panels/custom_fields.html'
91102 title = _ ('Custom Fields' )
92103
93- def render (self , context ):
94- obj = context .get ('object' )
95- custom_fields = obj .get_custom_fields_by_group ()
96- if not custom_fields :
97- return ''
98- return render_to_string (self .template_name , {
99- 'title' : self .title ,
100- 'custom_fields' : custom_fields ,
101- })
104+ def get_context (self , obj ):
105+ return {
106+ 'custom_fields' : obj .get_custom_fields_by_group (),
107+ }
102108
103109
104110class TagsPanel (Panel ):
105111 template_name = 'ui/panels/tags.html'
106112 title = _ ('Tags' )
107113
108- def render (self , context ):
109- return render_to_string (self .template_name , {
110- 'title' : self .title ,
111- 'object' : context .get ('object' ),
112- })
113-
114114
115115class CommentsPanel (Panel ):
116116 template_name = 'ui/panels/comments.html'
117117 title = _ ('Comments' )
118118
119- def render (self , context ):
120- obj = context .get ('object' )
121- return render_to_string (self .template_name , {
122- 'title' : self .title ,
123- 'comments' : obj .comments ,
124- })
125-
126119
127120class RelatedObjectsPanel (Panel ):
128121 template_name = 'ui/panels/related_objects.html'
129122 title = _ ('Related Objects' )
130123
124+ # TODO: Handle related_models from context
131125 def render (self , context ):
132126 return render_to_string (self .template_name , {
133127 'title' : self .title ,
@@ -139,35 +133,37 @@ def render(self, context):
139133class ImageAttachmentsPanel (Panel ):
140134 template_name = 'ui/panels/image_attachments.html'
141135 title = _ ('Image Attachments' )
142-
143- def render (self , context ):
144- return render_to_string (self .template_name , {
145- 'title' : self .title ,
146- 'request' : context .get ('request' ),
147- 'object' : context .get ('object' ),
148- })
136+ actions = [
137+ actions .AddObject (
138+ 'extras.imageattachment' ,
139+ url_params = {
140+ 'object_type' : lambda obj : ContentType .objects .get_for_model (obj ).pk ,
141+ 'object_id' : lambda obj : obj .pk ,
142+ 'return_url' : lambda obj : obj .get_absolute_url (),
143+ },
144+ label = _ ('Attach an image' ),
145+ ),
146+ ]
149147
150148
151149class EmbeddedTablePanel (Panel ):
152150 template_name = 'ui/panels/embedded_table.html'
153151 title = None
154152
155- def __init__ (self , viewname , url_params = None , ** kwargs ):
153+ def __init__ (self , view_name , url_params = None , ** kwargs ):
156154 super ().__init__ (** kwargs )
157- self .viewname = viewname
155+ self .view_name = view_name
158156 self .url_params = url_params or {}
159157
160- def render (self , context ):
161- obj = context .get ('object' )
158+ def get_context (self , obj ):
162159 url_params = {
163160 k : v (obj ) if callable (v ) else v for k , v in self .url_params .items ()
164161 }
165162 # url_params['return_url'] = return_url or context['request'].path
166- return render_to_string (self .template_name , {
167- 'title' : self .title ,
168- 'viewname' : self .viewname ,
163+ return {
164+ 'viewname' : self .view_name ,
169165 'url_params' : dict_to_querydict (url_params ),
170- })
166+ }
171167
172168
173169class PluginContentPanel (Panel ):
0 commit comments