1"use strict"; 2 3function layerDetailsPageInit (ctx) { 4 5 var layerDepInput = $("#layer-dep-input"); 6 var layerDepBtn = $("#add-layer-dependency-btn"); 7 var layerDepsList = $("#layer-deps-list"); 8 var currentLayerDepSelection; 9 var addRmLayerBtn = $("#add-remove-layer-btn"); 10 var targetTab = $("#targets-tab"); 11 var machineTab = $("#machines-tab"); 12 var detailsTab = $("#details-tab"); 13 var editLayerSource = $("#edit-layer-source"); 14 var saveSourceChangesBtn = $("#save-changes-for-switch"); 15 var layerGitRefInput = $("#layer-git-ref"); 16 var layerSubDirInput = $('#layer-subdir'); 17 18 targetTab.on('show.bs.tab', targetsTabShow); 19 detailsTab.on('show.bs.tab', detailsTabShow); 20 machineTab.on('show.bs.tab', machinesTabShow); 21 22 /* setup the dependencies typeahead */ 23 libtoaster.makeTypeahead(layerDepInput, 24 libtoaster.ctx.layersTypeAheadUrl, 25 { include_added: "true" }, function(item){ 26 currentLayerDepSelection = item; 27 layerDepBtn.removeAttr("disabled"); 28 }); 29 30 /* disable the add layer button if its input field is empty */ 31 layerDepInput.on("keyup",function(){ 32 if ($(this).val().length === 0) { 33 layerDepBtn.attr("disabled", "disabled"); 34 } 35 }); 36 37 function addRemoveDep(depLayerId, add, doneCb) { 38 var data = { layer_version_id : ctx.layerVersion.id }; 39 if (add) 40 data.add_dep = depLayerId; 41 else 42 data.rm_dep = depLayerId; 43 44 $.ajax({ 45 type: "POST", 46 url: ctx.xhrUpdateLayerUrl, 47 data: data, 48 headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, 49 success: function (data) { 50 if (data.error != "ok") { 51 console.warn(data.error); 52 } else { 53 doneCb(); 54 } 55 }, 56 error: function (data) { 57 console.warn("Call failed"); 58 console.warn(data); 59 } 60 }); 61 } 62 63 function layerDepRemoveClick() { 64 var toRemove = $(this).parent().data('layer-id'); 65 var layerDepItem = $(this); 66 67 addRemoveDep(toRemove, false, function(){ 68 layerDepItem.parent().fadeOut(function (){ 69 layerDepItem.remove(); 70 }); 71 }); 72 } 73 74 /* Add dependency layer button click handler */ 75 layerDepBtn.click(function(){ 76 if (currentLayerDepSelection === undefined) 77 return; 78 79 addRemoveDep(currentLayerDepSelection.id, true, function(){ 80 /* Make a list item for the new layer dependency */ 81 var newLayerDep = $("<li><a></a><span class=\"glyphicon glyphicon-trash\" data-toggle=\"tooltip\" title=\"Delete\"></span></li>"); 82 83 newLayerDep.data('layer-id', currentLayerDepSelection.id); 84 newLayerDep.children("span").tooltip(); 85 86 var link = newLayerDep.children("a"); 87 link.attr("href", currentLayerDepSelection.layerdetailurl); 88 link.text(currentLayerDepSelection.name); 89 link.tooltip({title: currentLayerDepSelection.tooltip, placement: "right"}); 90 91 /* Connect up the tash icon */ 92 var trashItem = newLayerDep.children("span"); 93 trashItem.click(layerDepRemoveClick); 94 95 layerDepsList.append(newLayerDep); 96 /* Clear the current selection */ 97 layerDepInput.val(""); 98 currentLayerDepSelection = undefined; 99 layerDepBtn.attr("disabled", "disabled"); 100 }); 101 }); 102 103 $(".glyphicon-edit").click(function (){ 104 var mParent = $(this).parent("dd"); 105 mParent.prev().css("margin-top", "10px"); 106 mParent.children("form").slideDown(); 107 var currentVal = mParent.children(".current-value"); 108 currentVal.hide(); 109 /* Set the current value to the input field */ 110 mParent.find("textarea,input").val(currentVal.text()); 111 /* If the input field is empty, disable the submit button */ 112 if ( mParent.find("textarea,input").val().length == 0 ) { 113 mParent.find(".change-btn").attr("disabled", "disabled"); 114 } 115 /* Hides the "Not set" text */ 116 mParent.children(".text-muted").hide(); 117 /* We're editing so hide the delete icon */ 118 mParent.children(".delete-current-value").hide(); 119 mParent.find(".cancel").show(); 120 $(this).hide(); 121 }); 122 123 $(".delete-current-value").click(function(){ 124 var mParent = $(this).parent("dd"); 125 mParent.find("input").val(""); 126 mParent.find("textarea").val(""); 127 mParent.find(".change-btn").click(); 128 }); 129 130 $(".cancel").click(function(){ 131 var mParent = $(this).parents("dd"); 132 $(this).hide(); 133 mParent.children("form").slideUp(function(){ 134 mParent.children(".current-value").show(); 135 /* Show the "Not set" text if we ended up with no value */ 136 if (!mParent.children(".current-value").html()){ 137 mParent.children(".text-muted").fadeIn(); 138 mParent.children(".delete-current-value").hide(); 139 } else { 140 mParent.children(".delete-current-value").show(); 141 } 142 143 mParent.children(".glyphicon-edit").show(); 144 mParent.prev().css("margin-top", "0"); 145 }); 146 }); 147 148 149 function defaultAddBtnText(){ 150 var text = " Add the "+ctx.layerVersion.name+" layer to your project"; 151 addRmLayerBtn.text(text); 152 addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-plus\"></span>"); 153 addRmLayerBtn.removeClass("btn-danger"); 154 } 155 156 function detailsTabShow(){ 157 if (!ctx.layerVersion.inCurrentPrj) 158 defaultAddBtnText(); 159 160 window.location.hash = "information"; 161 } 162 163 function targetsTabShow(){ 164 if (!ctx.layerVersion.inCurrentPrj){ 165 if (ctx.numTargets > 0) { 166 var text = " Add the "+ctx.layerVersion.name+" layer to your project "+ 167 "to enable these recipes"; 168 addRmLayerBtn.text(text); 169 addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-plus\"></span>"); 170 } else { 171 defaultAddBtnText(); 172 } 173 } 174 175 window.location.hash = "recipes"; 176 } 177 178 $("#recipestable").on('table-done', function(e, total, tableParams){ 179 ctx.numTargets = total; 180 181 if (total === 0 && !tableParams.search) { 182 $("#no-recipes-yet").show(); 183 } else { 184 $("#no-recipes-yet").hide(); 185 } 186 187 targetTab.removeClass("text-muted"); 188 if (window.location.hash === "#recipes"){ 189 /* re run the machinesTabShow to update the text */ 190 targetsTabShow(); 191 } 192 }); 193 194 $("#machinestable").on('table-done', function(e, total, tableParams){ 195 ctx.numMachines = total; 196 197 if (total === 0 && !tableParams.search) 198 $("#no-machines-yet").show(); 199 else 200 $("#no-machines-yet").hide(); 201 202 machineTab.removeClass("text-muted"); 203 if (window.location.hash === "#machines"){ 204 /* re run the machinesTabShow to update the text */ 205 machinesTabShow(); 206 } 207 208 $(".select-machine-btn").click(function(e){ 209 if ($(this).hasClass("disabled")) 210 e.preventDefault(); 211 }); 212 213 }); 214 215 216 function machinesTabShow(){ 217 if (!ctx.layerVersion.inCurrentPrj) { 218 if (ctx.numMachines > 0){ 219 var text = " Add the "+ctx.layerVersion.name+" layer to your project " + 220 "to enable these machines"; 221 addRmLayerBtn.text(text); 222 addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-plus\"></span>"); 223 } else { 224 defaultAddBtnText(); 225 } 226 } 227 228 window.location.hash = "machines"; 229 } 230 231 $(".pagesize").change(function(){ 232 var search = libtoaster.parseUrlParams(); 233 search.limit = this.value; 234 235 window.location.search = libtoaster.dumpsUrlParams(search); 236 }); 237 238 /* Enables the Build target and Select Machine buttons and switches the 239 * add/remove button 240 */ 241 function setLayerInCurrentPrj(added) { 242 ctx.layerVersion.inCurrentPrj = added; 243 244 if (added){ 245 /* enable and switch all the button states */ 246 $(".build-recipe-btn").removeClass("disabled"); 247 $(".select-machine-btn").removeClass("disabled"); 248 addRmLayerBtn.addClass("btn-danger"); 249 addRmLayerBtn.data('directive', "remove"); 250 addRmLayerBtn.text(" Remove the "+ctx.layerVersion.name+" layer from your project"); 251 addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-trash\"></span>"); 252 253 } else { 254 /* disable and switch all the button states */ 255 $(".build-recipe-btn").addClass("disabled"); 256 $(".select-machine-btn").addClass("disabled"); 257 addRmLayerBtn.removeClass("btn-danger"); 258 addRmLayerBtn.data('directive', "add"); 259 260 /* "special" handler so that we get the correct button text which depends 261 * on which tab is currently visible. Unfortunately we can't just call 262 * tab('show') as if it's already visible it doesn't run the event. 263 */ 264 switch ($(".nav-tabs .active a").prop('id')){ 265 case 'machines-tab': 266 machinesTabShow(); 267 break; 268 case 'targets-tab': 269 targetsTabShow(); 270 break; 271 default: 272 defaultAddBtnText(); 273 break; 274 } 275 } 276 } 277 278 $("#dismiss-alert").click(function(){ 279 $(this).parent().fadeOut(); 280 }); 281 282 /* Add or remove this layer from the project */ 283 addRmLayerBtn.click(function() { 284 285 var add = ($(this).data('directive') === "add"); 286 287 libtoaster.addRmLayer(ctx.layerVersion, add, function (layersList){ 288 var alertMsg = $("#alert-msg"); 289 alertMsg.html(libtoaster.makeLayerAddRmAlertMsg(ctx.layerVersion, layersList, add)); 290 291 setLayerInCurrentPrj(add); 292 293 libtoaster.showChangeNotification(alertMsg); 294 }); 295 }); 296 297 /* Handler for all of the Change buttons */ 298 $(".change-btn").click(function(){ 299 var mParent = $(this).parent(); 300 var prop = $(this).data('layer-prop'); 301 302 /* We have inputs, select and textareas to potentially grab the value 303 * from. 304 */ 305 var entryElement = mParent.find("input"); 306 if (entryElement.length === 0) 307 entryElement = mParent.find("textarea"); 308 if (entryElement.length === 0) { 309 console.warn("Could not find element to get data from for this change"); 310 return; 311 } 312 313 var data = { layer_version_id: ctx.layerVersion.id }; 314 data[prop] = entryElement.val(); 315 316 $.ajax({ 317 type: "POST", 318 url: ctx.xhrUpdateLayerUrl, 319 data: data, 320 headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, 321 success: function (data) { 322 if (data.error != "ok") { 323 console.warn(data.error); 324 } else { 325 /* success layer property changed */ 326 var inputArea = mParent.parents("dd"); 327 var text; 328 329 text = entryElement.val(); 330 331 /* Hide the "Not set" text if it's visible */ 332 inputArea.find(".text-muted").hide(); 333 inputArea.find(".current-value").text(text); 334 /* Same behaviour as cancel in that we hide the form/show current 335 * value. 336 */ 337 inputArea.find(".cancel").click(); 338 } 339 }, 340 error: function (data) { 341 console.warn("Call failed"); 342 console.warn(data); 343 } 344 }); 345 }); 346 347 /* Disable the change button when we have no data in the input */ 348 $("dl input, dl textarea").on("input",function() { 349 if ($(this).val().length === 0) 350 $(this).parent().next(".change-btn").attr("disabled", "disabled"); 351 else 352 $(this).parent().next(".change-btn").removeAttr("disabled"); 353 }); 354 355 /* This checks to see if the dt's dd has data in it or if the change data 356 * form is visible, otherwise hide it 357 */ 358 $("dl").children().each(function (){ 359 if ($(this).is("dt")) { 360 var dd = $(this).next("dd"); 361 if (!dd.children("form:visible")|| !dd.find(".current-value").html()){ 362 if (ctx.layerVersion.layer_source == ctx.layerSourceTypes.TYPE_IMPORTED || 363 ctx.layerVersion.layer_source == ctx.layerSourceTypes.TYPE_LOCAL) { 364 /* There's no current value and the layer is editable 365 * so show the "Not set" and hide the delete icon 366 */ 367 dd.find(".text-muted").show(); 368 dd.find(".delete-current-value").hide(); 369 } else { 370 /* We're not viewing an editable layer so hide the empty dd/dl pair */ 371 $(this).hide(); 372 dd.hide(); 373 } 374 } 375 } 376 }); 377 378 /* Hide the right column if it contains no information */ 379 if ($("dl.item-info").children(':visible').length === 0) { 380 $("dl.item-info").parent().hide(); 381 } 382 383 /* Clear the current search selection and reload the results */ 384 $(".target-search-clear").click(function(){ 385 $("#target-search").val(""); 386 $(this).parents("form").submit(); 387 }); 388 389 $(".machine-search-clear").click(function(){ 390 $("#machine-search").val(""); 391 $(this).parents("form").submit(); 392 }); 393 394 $("#layer-delete-confirmed").click(function(){ 395 396 $("#delete-layer-modal button[data-dismiss='modal']").hide(); 397 398 var message = $('<span>You have deleted <strong>1</strong> layer from your project: <strong id="deleted-layer-name"></strong>'); 399 message.find("#deleted-layer-name").text(ctx.layerVersion.name); 400 401 $.ajax({ 402 type: "DELETE", 403 url: ctx.xhrUpdateLayerUrl, 404 headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, 405 success: function(data) { 406 if (data.error != "ok") { 407 console.warn(data.error); 408 } else { 409 libtoaster.setNotification("layer-deleted", message.html()); 410 window.location.replace(data.gotoUrl); 411 } 412 }, 413 error: function(data) { 414 console.warn("Call failed"); 415 console.warn(data); 416 } 417 }); 418 }); 419 420 layerDepsList.find(".glyphicon-trash").click(layerDepRemoveClick); 421 layerDepsList.find("a").tooltip(); 422 $(".glyphicon-trash").tooltip(); 423 $(".commit").tooltip(); 424 425 editLayerSource.click(function() { 426 /* Kindly bring the git layers imported from layerindex to normal page 427 * and not this new page :( 428 */ 429 $(this).hide(); 430 saveSourceChangesBtn.attr("disabled", "disabled"); 431 432 $("#git-repo-info, #directory-info").hide(); 433 $("#edit-layer-source-form").fadeIn(); 434 if ($("#layer-dir-path-in-details").val() == "") { 435 //Local dir path is empty... 436 $("#repo").prop("checked", true); 437 $("#layer-git").fadeIn(); 438 $("#layer-dir").hide(); 439 } else { 440 $("#layer-git").hide(); 441 $("#layer-dir").fadeIn(); 442 } 443 }); 444 445 $('input:radio[name="source-location"]').change(function() { 446 if ($('input[name=source-location]:checked').val() == "repo") { 447 $("#layer-git").fadeIn(); 448 $("#layer-dir").hide(); 449 if ($("#layer-git-repo-url").val().length === 0 && layerGitRefInput.val().length === 0) { 450 saveSourceChangesBtn.attr("disabled", "disabled"); 451 } 452 } else { 453 $("#layer-dir").fadeIn(); 454 $("#layer-git").hide(); 455 } 456 }); 457 458 $("#layer-dir-path-in-details").keyup(function() { 459 saveSourceChangesBtn.removeAttr("disabled"); 460 }); 461 462 $("#layer-git-repo-url").keyup(function() { 463 if ($("#layer-git-repo-url").val().length > 0 && layerGitRefInput.val().length > 0) { 464 saveSourceChangesBtn.removeAttr("disabled"); 465 } 466 }); 467 468 layerGitRefInput.keyup(function() { 469 if ($("#layer-git-repo-url").val().length > 0 && layerGitRefInput.val().length > 0) { 470 saveSourceChangesBtn.removeAttr("disabled"); 471 } 472 }); 473 474 475 layerSubDirInput.keyup(function(){ 476 if ($(this).val().length > 0){ 477 saveSourceChangesBtn.removeAttr("disabled"); 478 } 479 }); 480 481 $('#cancel-changes-for-switch').click(function() { 482 $("#edit-layer-source-form").hide(); 483 $("#directory-info, #git-repo-info").fadeIn(); 484 editLayerSource.show(); 485 }); 486 487 saveSourceChangesBtn.click(function() { 488 489 var layerData = { 490 vcs_url: $('#layer-git-repo-url').val(), 491 commit: layerGitRefInput.val(), 492 dirpath: layerSubDirInput.val(), 493 local_source_dir: $('#layer-dir-path-in-details').val(), 494 }; 495 496 if ($('input[name=source-location]:checked').val() == "repo") { 497 layerData.local_source_dir = ""; 498 } else { 499 layerData.vcs_url = ""; 500 layerData.git_ref = ""; 501 } 502 503 $.ajax({ 504 type: "POST", 505 url: ctx.xhrUpdateLayerUrl, 506 data: layerData, 507 headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, 508 success: function (data) { 509 if (data.error != "ok") { 510 console.warn(data.error); 511 } else { 512 /* success layer property changed */ 513 window.location.reload(); 514 } 515 }, 516 error: function (data) { 517 console.warn("Call failed"); 518 console.warn(data); 519 } 520 }); 521 }); 522} 523