@@ -89,16 +89,35 @@ django.jQuery(function ($) {
8989 }
9090 }
9191 } ,
92+ getRelevantTemplateUrl = function ( orgID , backend ) {
93+ // Returns the URL to fetch relevant templates
94+ var baseUrl = window . _relevantTemplateUrl . replace ( "org_id" , orgID ) ;
95+ var url = new URL ( baseUrl , window . location . origin ) ;
96+
97+ // Get relevant templates of selected org and backend
98+ if ( backend ) {
99+ url . searchParams . set ( "backend" , backend ) ;
100+ }
101+ if ( isDeviceGroup ( ) && ! $ ( ".add-form" ) . length ) {
102+ // Get the group id from the URL
103+ // TODO: This is fragile, consider using a more robust way to get the group id.
104+ var pathParts = window . location . pathname . split ( "/" ) ;
105+ url . searchParams . set ( "group_id" , pathParts [ pathParts . length - 3 ] ) ;
106+ } else if ( $ ( 'input[name="config-0-device"]' ) . length ) {
107+ url . searchParams . set (
108+ "device_id" ,
109+ $ ( 'input[name="config-0-device"]' ) . val ( ) ,
110+ ) ;
111+ }
112+ return url . toString ( ) ;
113+ } ,
92114 showRelevantTemplates = function ( ) {
93115 var orgID = $ ( orgFieldSelector ) . val ( ) ,
94116 backend = isDeviceGroup ( ) ? "" : $ ( backendFieldSelector ) . val ( ) ,
95117 selectedTemplates ;
96118
97119 // Hide templates if no organization or backend is selected
98- if (
99- ( orgID && orgID . length === 0 ) ||
100- ( ! isDeviceGroup ( ) && backend . length === 0 )
101- ) {
120+ if ( ! orgID || ( ! isDeviceGroup ( ) && backend . length === 0 ) ) {
102121 resetTemplateOptions ( ) ;
103122 updateTemplateHelpText ( ) ;
104123 return ;
@@ -109,77 +128,24 @@ django.jQuery(function ($) {
109128 // when the user has changed any of organization or backend field.
110129 // selectedTemplates will be an empty string if no template is selected
111130 // ''.split(',') returns [''] hence, this case requires special handling
112- selectedTemplates = isDeviceGroup ( )
113- ? parseSelectedTemplates ( $ ( "#id_templates" ) . val ( ) )
114- : parseSelectedTemplates (
115- django . _owcInitialValues [ templatesFieldName ( ) ] ,
116- ) ;
117- }
118-
119- var url = window . _relevantTemplateUrl . replace ( "org_id" , orgID ) ;
120- // Get relevant templates of selected org and backend
121- url = url + "?backend=" + backend ;
122- if ( ! isDeviceGroup ( ) ) {
123- var deviceID = $ ( 'input[name="config-0-device"]' ) . val ( ) ;
124- url = url + "&device=" + deviceID ;
125- } else {
126- // Get the group id from the URL
127- var pathParts = window . location . pathname . split ( "/" ) ;
128- url = url + "&group=" + pathParts [ pathParts . length - 3 ] ;
131+ selectedTemplates = parseSelectedTemplates (
132+ $ ( 'input[name="' + templatesFieldName ( ) + '"]' ) . val ( ) ,
133+ ) ;
129134 }
135+ var url = getRelevantTemplateUrl ( orgID , backend ) ;
130136 $ . get ( url ) . done ( function ( data ) {
131137 resetTemplateOptions ( ) ;
132138 var enabledTemplates = [ ] ,
133139 sortedm2mUl = $ ( "ul.sortedm2m-items:first" ) ,
134140 sortedm2mPrefixUl = $ ( "ul.sortedm2m-items:last" ) ;
135141
136- // Adds "li" elements for templates that are already selected
137- // in the database. Select these templates and remove their key from "data"
138- // This maintains the order of the templates and keep
139- // enabled templates on the top
140- if ( selectedTemplates !== undefined ) {
141- selectedTemplates . forEach ( function ( templateId , index ) {
142- // corner case in which backend of template does not match
143- if ( ! data [ templateId ] ) {
144- return ;
145- }
146- var element = getTemplateOptionElement (
147- index ,
148- templateId ,
149- data [ templateId ] ,
150- true ,
151- false ,
152- ) ,
153- prefixElement = getTemplateOptionElement (
154- index ,
155- templateId ,
156- data [ templateId ] ,
157- true ,
158- true ,
159- ) ;
160- sortedm2mUl . append ( element ) ;
161- if ( ! isDeviceGroup ( ) ) {
162- sortedm2mPrefixUl . append ( prefixElement ) ;
163- }
164- delete data [ templateId ] ;
165- } ) ;
166- }
167-
168- // Adds "li" elements for templates that are not selected
169- // in the database.
170- var counter =
171- selectedTemplates !== undefined ? selectedTemplates . length : 0 ,
172- deviceTemplates = [ ] ;
142+ // Adds "li" elements for templates
173143 Object . keys ( data ) . forEach ( function ( templateId , index ) {
174- // corner case in which backend of template does not match
175- if ( ! data [ templateId ] ) {
176- return ;
177- }
178- index = index + counter ;
179144 var isSelected =
180- data [ templateId ] . default &&
181- selectedTemplates === undefined &&
182- ! data [ templateId ] . required ,
145+ data [ templateId ] . selected ||
146+ ( data [ templateId ] . default &&
147+ selectedTemplates === undefined &&
148+ ! data [ templateId ] . required ) ,
183149 element = getTemplateOptionElement (
184150 index ,
185151 templateId ,
@@ -199,9 +165,6 @@ django.jQuery(function ($) {
199165 if ( isSelected === true ) {
200166 enabledTemplates . push ( templateId ) ;
201167 }
202- if ( element . children ( ) . children ( "input" ) . prop ( "checked" ) === true ) {
203- deviceTemplates . push ( templateId ) ;
204- }
205168 sortedm2mUl . append ( element ) ;
206169 if ( ! isDeviceGroup ( ) ) {
207170 sortedm2mPrefixUl . append ( prefixElement ) ;
@@ -210,30 +173,20 @@ django.jQuery(function ($) {
210173 if ( firstRun === true && selectedTemplates !== undefined ) {
211174 updateTemplateSelection ( selectedTemplates ) ;
212175 }
213- // this runs on first load and sets the name of hidden input field which tracks
214- // the selected templates.
215- if ( selectedTemplates === undefined ) {
216- if ( ! isDeviceGroup ( ) ) {
217- $ (
218- `#config-0 .field-templates .sortedm2m-container input[type="hidden"]` ,
219- )
220- . first ( )
221- . attr ( "name" , templatesFieldName ( ) ) ;
222- // set the initial value of the hidden input field
223- // to the selected templates
224- django . _owcInitialValues [ templatesFieldName ( ) ] =
225- deviceTemplates . join ( "," ) ;
226- } else {
227- $ (
228- `.field-templates .sortedm2m-container input[type="hidden"]` ,
229- ) . attr ( "name" , templatesFieldName ( ) ) ;
230- }
231- }
232176 updateTemplateHelpText ( ) ;
233177 updateConfigTemplateField ( enabledTemplates ) ;
234178 } ) ;
235179 } ,
180+ initTemplateField = function ( ) {
181+ // sortedm2m generates a hidden input dynamically using rendered input checkbox elements,
182+ // but because the queryset is set to None in the Django admin, the input is created
183+ // without a name attribute. This workaround assigns the correct name to the hidden input.
184+ $ ( '.sortedm2m-container input[type="hidden"][id="undefined"]' )
185+ . first ( )
186+ . attr ( "name" , templatesFieldName ( ) ) ;
187+ } ,
236188 bindDefaultTemplateLoading = function ( ) {
189+ initTemplateField ( ) ;
237190 var backendField = $ ( backendFieldSelector ) ;
238191 $ ( orgFieldSelector ) . change ( function ( ) {
239192 // Only fetch templates when backend field is present
@@ -246,11 +199,13 @@ django.jQuery(function ($) {
246199 addChangeEventHandlerToBackendField ( ) ;
247200 } else if ( isDeviceGroup ( ) ) {
248201 // Initially request data to get templates
202+ initTemplateField ( ) ;
249203 showRelevantTemplates ( ) ;
250204 } else {
251205 // Add view: backendField is added when user adds configuration
252206 $ ( "#config-group > fieldset.module" ) . ready ( function ( ) {
253207 $ ( "div.add-row > a" ) . one ( "click" , function ( ) {
208+ initTemplateField ( ) ;
254209 addChangeEventHandlerToBackendField ( ) ;
255210 } ) ;
256211 } ) ;
0 commit comments