1"use strict"; 2 3function customRecipePageInit(ctx) { 4 5 var urlParams = libtoaster.parseUrlParams(); 6 var customiseTable = $("#selectpackagestable"); 7 var addPkgDepsModalBtn = $("#add-package-deps-modal-btn"); 8 var rmdPkgReverseDepsModalBtn = $("#rm-package-reverse-deps-modal-btn"); 9 10 if (urlParams.hasOwnProperty('notify') && urlParams.notify === 'new'){ 11 $("#image-created-notification").show(); 12 } 13 14 customiseTable.on('table-done', function(e, total){ 15 /* Table is done so now setup the click handler for the package buttons */ 16 $(".add-rm-package-btn").click(function(e){ 17 e.preventDefault(); 18 var targetPkg = $(this).data(); 19 20 checkPackageDeps(targetPkg, function(pkgData){ 21 if (targetPkg.directive === 'add'){ 22 /* If we're adding a package we may need to show the modal to advise 23 * on dependencies for this package. 24 */ 25 if (pkgData.unsatisfied_dependencies.length === 0){ 26 addRemovePackage(targetPkg); 27 } else { 28 showPackageDepsModal(targetPkg, pkgData); 29 } 30 } else if (targetPkg.directive === 'remove') { 31 if (pkgData.reverse_dependencies.length === 0){ 32 addRemovePackage(targetPkg); 33 } else { 34 showPackageReverseDepsModal(targetPkg, pkgData); 35 } 36 } 37 }); 38 }); 39 }); 40 41 function checkPackageDeps(targetPkg, doneCb){ 42 $.ajax({ 43 type: 'GET', 44 url: targetPkg.packageUrl, 45 headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, 46 success: function(data){ 47 if (data.error !== 'ok'){ 48 console.warn(data.error); 49 return; 50 } 51 doneCb(data); 52 } 53 }); 54 } 55 56 function showPackageDepsModal(targetPkg, pkgData){ 57 var modal = $("#package-deps-modal"); 58 var depsList = modal.find("#package-add-dep-list"); 59 var deps = pkgData.unsatisfied_dependencies; 60 61 modal.find(".package-to-add-name").text(targetPkg.name); 62 63 depsList.text(""); 64 65 for (var i in deps){ 66 var li = $('<li></li>').text(deps[i].name); 67 li.append($('<span></span>').text(" ("+ 68 deps[i].size_formatted+")")); 69 depsList.append(li); 70 } 71 72 modal.find("#package-deps-total-size").text( 73 pkgData.unsatisfied_dependencies_size_formatted); 74 75 targetPkg.depsAdded = deps; 76 77 addPkgDepsModalBtn.data(targetPkg); 78 modal.modal('show'); 79 } 80 81 addPkgDepsModalBtn.click(function(e){ 82 e.preventDefault(); 83 84 addRemovePackage($(this).data(), null); 85 }); 86 87 function showPackageReverseDepsModal(targetPkg, pkgData){ 88 var modal = $("#package-reverse-deps-modal"); 89 var depsList = modal.find("#package-reverse-dep-list"); 90 var deps = pkgData.reverse_dependencies; 91 92 var depsCount = deps.length; 93 var vDepends = "depends"; 94 var vPackage = "package"; 95 var vThis = "this"; 96 if (depsCount > 1) { 97 vDepends = "depend"; 98 vPackage = "packages"; 99 vThis = "these"; 100 } 101 modal.find(".package-to-rm-name").text(targetPkg.name); 102 modal.find(".reverse-deps-count").text(depsCount); 103 modal.find(".reverse-deps-count-plus1").text((depsCount+1) + " packages"); 104 modal.find(".reverse-deps-depends").text(vDepends); 105 modal.find(".reverse-deps-package").text(vPackage); 106 modal.find(".reverse-deps-this").text(vThis); 107 108 depsList.text(""); 109 110 for (var i in deps){ 111 var li = $('<li></li>').text(deps[i].name); 112 li.append($('<span></span>').text(" ("+ 113 deps[i].size_formatted+")")); 114 depsList.append(li); 115 } 116 117 modal.find("#package-reverse-deps-total-size").text( 118 pkgData.reverse_dependencies_size_formatted); 119 120 targetPkg.depsRemoved = deps; 121 122 rmdPkgReverseDepsModalBtn.data(targetPkg); 123 modal.modal('show'); 124 } 125 126 rmdPkgReverseDepsModalBtn.click(function(e){ 127 e.preventDefault(); 128 129 addRemovePackage($(this).data(), null); 130 }); 131 132 133 function addRemovePackage(targetPkg, tableParams){ 134 var method; 135 var msg = "You have "; 136 137 var btnCell = $("#package-btn-cell-" + targetPkg.id); 138 var inlineNotify = btnCell.children(".inline-notification"); 139 140 var i; 141 var dep; 142 var depBtnCell; 143 144 if (targetPkg.directive === 'add') { 145 method = 'PUT'; 146 /* If the package had dependencies also notify that they were added */ 147 if (targetPkg.hasOwnProperty('depsAdded') && 148 targetPkg.depsAdded.length > 0) { 149 150 msg += "added "; 151 msg += "<strong>" + (targetPkg.depsAdded.length + 1) + "</strong>"; 152 msg += " packages to " + ctx.recipe.name + ": "; 153 msg += "<strong>" + targetPkg.name + "</strong> and its dependencies"; 154 155 for (i in targetPkg.depsAdded){ 156 dep = targetPkg.depsAdded[i]; 157 158 msg += " <strong>" + dep.name + "</strong>"; 159 160 /* Add any cells currently in view to the list of cells which get 161 * an list-inline notification inside them and which change add/rm state 162 */ 163 depBtnCell = $("#package-btn-cell-" + dep.pk); 164 btnCell = btnCell.add(depBtnCell); 165 166 inlineNotify = inlineNotify.add( 167 depBtnCell.children(".inline-notification")); 168 } 169 170 inlineNotify.text( 171 (targetPkg.depsAdded.length + 1) + " packages added"); 172 173 } else { 174 msg += "added <strong>1</strong>"; 175 msg += " package to " + ctx.recipe.name + ": "; 176 msg += "<strong>" + targetPkg.name + "</strong>"; 177 inlineNotify.text("1 package added"); 178 } 179 180 } else if (targetPkg.directive === 'remove') { 181 method = 'DELETE'; 182 var numPackageString = "1 package "; 183 var revDepList = ""; 184 if (targetPkg.hasOwnProperty('depsRemoved') && 185 targetPkg.depsRemoved.length > 0) { 186 var depsRemovedLength = targetPkg.depsRemoved.length; 187 var ending = "y: "; 188 var maxRevDepsDisplayed = 5; 189 var d = 0; 190 if (depsRemovedLength > 1) { 191 ending = "ies: "; 192 } 193 numPackageString = (depsRemovedLength + 1) + " packages"; 194 revDepList = " and its " + depsRemovedLength + " reverse dependenc" + ending; 195 for (i in targetPkg.depsRemoved){ 196 /* include up to maxRevDepsDisplayed rev deps on the page notification */ 197 var notShownCount = depsRemovedLength - maxRevDepsDisplayed; 198 dep = targetPkg.depsRemoved[i]; 199 if (d < maxRevDepsDisplayed) { 200 if (d > 0) { 201 revDepList += ", "; 202 } 203 revDepList += dep.name; 204 d++; 205 if ((d === maxRevDepsDisplayed) && (notShownCount > 0)) { 206 revDepList += " and " + notShownCount + " more"; 207 } 208 } 209 210 /* Add any cells currently in view to the list of cells which get 211 * an list-inline notification inside them and which change add/rm state 212 */ 213 depBtnCell = $("#package-btn-cell-" + dep.pk); 214 btnCell = btnCell.add(depBtnCell); 215 216 inlineNotify = inlineNotify.add( 217 depBtnCell.children(".inline-notification")); 218 } 219 } 220 msg+= "removed " + numPackageString + " from " + ctx.recipe.name + ":"; 221 msg += " <strong>" + targetPkg.name + "</strong>"; 222 msg += revDepList; 223 224 inlineNotify.text(numPackageString + " removed"); 225 } else { 226 throw("Unknown package directive: should be add or remove"); 227 } 228 229 $.ajax({ 230 type: method, 231 url: targetPkg.packageUrl, 232 headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, 233 success: function(data){ 234 if (data.error !== 'ok'){ 235 console.warn(data.error); 236 return; 237 } 238 239 libtoaster.showChangeNotification(msg); 240 241 /* do the in-cell/inline notification to swap buttoms from add to 242 * remove 243 */ 244 btnCell.children("button").fadeOut().promise().done(function(){ 245 inlineNotify.fadeIn().delay(500).fadeOut(function(){ 246 if (targetPkg.directive === 'add') 247 btnCell.children("button[data-directive=remove]").fadeIn(); 248 else 249 btnCell.children("button[data-directive=add]").fadeIn(); 250 }); 251 }); 252 253 /* Update the total num packages */ 254 $.ajax({ 255 type: "GET", 256 url: ctx.recipe.xhrPackageListUrl, 257 headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, 258 success: function(data){ 259 console.log(data); 260 $("#total-num-packages").text(data.total); 261 $("#total-size-packages").text(data.total_size_formatted); 262 } 263 }); 264 } 265 }); 266 } 267 268 $("#no-results-show-all-packages").click(function(){ 269 $(".no-results-search-input").val(""); 270 }); 271 272 $("#no-results-remove-search-btn").click(function(){ 273 $(".no-results-search-input").val(""); 274 $(this).hide(); 275 }); 276 277 /* Trigger a build of your custom image */ 278 $(".build-custom-image").click(function(){ 279 libtoaster.startABuild(null, ctx.recipe.name, 280 function(){ 281 window.location.replace(libtoaster.ctx.projectBuildsUrl); 282 }); 283 }); 284 285 $("#delete-custom-recipe-confirmed").click(function(e){ 286 e.preventDefault(); 287 libtoaster.disableAjaxLoadingTimer(); 288 $(this).find('[data-role="submit-state"]').hide(); 289 $(this).find('[data-role="loading-state"]').show(); 290 $(this).attr("disabled", "disabled"); 291 292 $.ajax({ 293 type: 'DELETE', 294 url: ctx.recipe.xhrCustomRecipeUrl, 295 headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, 296 success: function (data) { 297 if (data.error !== "ok") { 298 console.warn(data.error); 299 } else { 300 var msg = $('<span>You have deleted <strong>1</strong> custom image: <strong id="deleted-custom-image-name"></strong></span>'); 301 msg.find("#deleted-custom-image-name").text(ctx.recipe.name); 302 303 libtoaster.setNotification("custom-image-recipe-deleted", 304 msg.html()); 305 306 window.location.replace(data.gotoUrl); 307 } 308 }, 309 error: function (data) { 310 console.warn(data); 311 } 312 }); 313 }); 314 315 /* Stop the download link from working if it is in disabled state 316 * http://getbootstrap.com/css/#forms-disabled-fieldsets 317 */ 318 $("a[disabled=disabled]").click(function(e){ 319 e.preventDefault(); 320 }); 321 322} 323