5
5
"""
6
6
7
7
from django import forms
8
- from django .shortcuts import redirect
8
+ from django .shortcuts import redirect , render
9
9
from django .urls import reverse
10
+ from django .views .decorators .http import require_GET
10
11
from django .views .generic import CreateView , DeleteView , DetailView , ListView , UpdateView
11
12
13
+ from argus .htmx .request import HtmxHttpRequest
14
+ from argus .htmx .widgets import DropdownMultiSelect
15
+ from argus .notificationprofile .media import MEDIA_CLASSES_DICT
12
16
from argus .notificationprofile .models import NotificationProfile , Timeslot , Filter , DestinationConfig
13
17
14
18
@@ -18,7 +22,52 @@ def __init__(self, *args, **kwargs):
18
22
super ().__init__ (* args , ** kwargs )
19
23
20
24
21
- class NotificationProfileForm (NoColonMixin , forms .ModelForm ):
25
+ class DestinationFieldMixin :
26
+ def _get_destination_choices (self , user ):
27
+ choices = []
28
+ for dc in DestinationConfig .objects .filter (user = user ):
29
+ MediaPlugin = MEDIA_CLASSES_DICT [dc .media .slug ]
30
+ label = MediaPlugin .get_label (dc )
31
+ choices .append ((dc .id , f"{ dc .media .name } : { label } " ))
32
+ return choices
33
+
34
+ def _init_destinations (self , user ):
35
+ qs = DestinationConfig .objects .filter (user = user )
36
+ self .fields ["destinations" ].queryset = qs
37
+ if self .instance .id :
38
+ partial_get = reverse (
39
+ "htmx:notificationprofile-destinations-field-update" ,
40
+ kwargs = {"pk" : self .instance .pk },
41
+ )
42
+ else :
43
+ partial_get = reverse ("htmx:notificationprofile-destinations-field-create" )
44
+ self .fields ["destinations" ].widget = DropdownMultiSelect (
45
+ partial_get = partial_get ,
46
+ attrs = {"placeholder" : "select destination..." },
47
+ )
48
+ self .fields ["destinations" ].choices = self ._get_destination_choices (user )
49
+
50
+
51
+ class FilterFieldMixin :
52
+ def _init_filters (self , user ):
53
+ qs = Filter .objects .filter (user = user )
54
+ self .fields ["filters" ].queryset = qs
55
+
56
+ if self .instance .id :
57
+ partial_get = reverse (
58
+ "htmx:notificationprofile-filters-field-update" ,
59
+ kwargs = {"pk" : self .instance .pk },
60
+ )
61
+ else :
62
+ partial_get = reverse ("htmx:notificationprofile-filters-field-create" )
63
+ self .fields ["filters" ].widget = DropdownMultiSelect (
64
+ partial_get = partial_get ,
65
+ attrs = {"placeholder" : "select filter..." },
66
+ )
67
+ self .fields ["filters" ].choices = tuple (qs .values_list ("id" , "name" ))
68
+
69
+
70
+ class NotificationProfileForm (DestinationFieldMixin , FilterFieldMixin , NoColonMixin , forms .ModelForm ):
22
71
class Meta :
23
72
model = NotificationProfile
24
73
fields = ["name" , "timeslot" , "filters" , "active" , "destinations" ]
@@ -29,12 +78,74 @@ class Meta:
29
78
def __init__ (self , * args , ** kwargs ):
30
79
user = kwargs .pop ("user" )
31
80
super ().__init__ (* args , ** kwargs )
81
+
32
82
self .fields ["timeslot" ].queryset = Timeslot .objects .filter (user = user )
33
- self .fields ["filters" ].queryset = Filter .objects .filter (user = user )
34
- self .fields ["destinations" ].queryset = DestinationConfig .objects .filter (user = user )
35
83
self .fields ["active" ].widget .attrs ["class" ] = "checkbox checkbox-sm checkbox-accent border"
84
+ self .fields ["active" ].widget .attrs ["autocomplete" ] = "off"
36
85
self .fields ["name" ].widget .attrs ["class" ] = "input input-bordered"
37
86
87
+ self .action = self .get_action ()
88
+
89
+ self ._init_filters (user )
90
+ self ._init_destinations (user )
91
+
92
+ def get_action (self ):
93
+ if self .instance and self .instance .pk :
94
+ return reverse ("htmx:notificationprofile-update" , kwargs = {"pk" : self .instance .pk })
95
+ else :
96
+ return reverse ("htmx:notificationprofile-create" )
97
+
98
+
99
+ class NotificationProfileFilterForm (FilterFieldMixin , NoColonMixin , forms .ModelForm ):
100
+ class Meta :
101
+ model = NotificationProfile
102
+ fields = ["filters" ]
103
+
104
+ def __init__ (self , * args , ** kwargs ):
105
+ user = kwargs .pop ("user" )
106
+ super ().__init__ (* args , ** kwargs )
107
+ self ._init_filters (user )
108
+
109
+
110
+ class NotificationProfileDestinationForm (DestinationFieldMixin , NoColonMixin , forms .ModelForm ):
111
+ class Meta :
112
+ model = NotificationProfile
113
+ fields = ["destinations" ]
114
+
115
+ def __init__ (self , * args , ** kwargs ):
116
+ user = kwargs .pop ("user" )
117
+ super ().__init__ (* args , ** kwargs )
118
+ self ._init_destinations (user )
119
+
120
+
121
+ def _render_form_field (request : HtmxHttpRequest , form , partial_template_name , prefix = None ):
122
+ # Not a view!
123
+ form = form (request .GET or None , user = request .user , prefix = prefix )
124
+ context = {"form" : form }
125
+ return render (request , partial_template_name , context = context )
126
+
127
+
128
+ @require_GET
129
+ def filters_form_view (request : HtmxHttpRequest , pk : int = None ):
130
+ prefix = f"npf{ pk } " if pk else None
131
+ return _render_form_field (
132
+ request ,
133
+ NotificationProfileFilterForm ,
134
+ "htmx/notificationprofile/_notificationprofile_form.html" ,
135
+ prefix = prefix ,
136
+ )
137
+
138
+
139
+ @require_GET
140
+ def destinations_form_view (request : HtmxHttpRequest , pk : int = None ):
141
+ prefix = f"npf{ pk } " if pk else None
142
+ return _render_form_field (
143
+ request ,
144
+ NotificationProfileDestinationForm ,
145
+ "htmx/notificationprofile/_notificationprofile_form.html" ,
146
+ prefix = prefix ,
147
+ )
148
+
38
149
39
150
class NotificationProfileMixin :
40
151
"Common functionality for all views"
@@ -54,6 +165,8 @@ def get_queryset(self):
54
165
return qs .filter (user_id = self .request .user .id )
55
166
56
167
def get_template_names (self ):
168
+ if self .request .htmx and self .partial_template_name :
169
+ return [self .partial_template_name ]
57
170
orig_app_label = self .model ._meta .app_label
58
171
orig_model_name = self .model ._meta .model_name
59
172
self .model ._meta .app_label = "htmx/notificationprofile"
@@ -76,6 +189,7 @@ class ChangeMixin:
76
189
"Common functionality for create and update views"
77
190
78
191
form_class = NotificationProfileForm
192
+ partial_template_name = "htmx/notificationprofile/_notificationprofile_form.html"
79
193
80
194
def get_form_kwargs (self ):
81
195
kwargs = super ().get_form_kwargs ()
@@ -85,16 +199,21 @@ def get_form_kwargs(self):
85
199
def form_valid (self , form ):
86
200
self .object = form .save (commit = False )
87
201
self .object .user = self .request .user
88
- self .object .save ()
89
202
return super ().form_valid (form )
90
203
204
+ def get_prefix (self ):
205
+ if self .object and self .object .pk :
206
+ prefix = f"npf{ self .object .pk } "
207
+ return prefix
208
+ return self .prefix
209
+
91
210
92
211
class NotificationProfileListView (NotificationProfileMixin , ListView ):
93
212
def get_context_data (self , ** kwargs ):
94
213
context = super ().get_context_data (** kwargs )
95
214
forms = []
96
215
for obj in self .get_queryset ():
97
- form = NotificationProfileForm (None , user = self .request .user , instance = obj )
216
+ form = NotificationProfileForm (None , prefix = f"npf { obj . pk } " , user = self .request .user , instance = obj )
98
217
forms .append (form )
99
218
context ["form_list" ] = forms
100
219
return context
0 commit comments