Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | "use strict"; |
| 2 | |
| 3 | function projectPageInit(ctx) { |
| 4 | |
| 5 | var layerAddInput = $("#layer-add-input"); |
| 6 | var layersInPrjList = $("#layers-in-project-list"); |
| 7 | var layerAddBtn = $("#add-layer-btn"); |
| 8 | |
| 9 | var machineChangeInput = $("#machine-change-input"); |
| 10 | var machineChangeBtn = $("#machine-change-btn"); |
| 11 | var machineForm = $("#select-machine-form"); |
| 12 | var machineChangeFormToggle = $("#change-machine-toggle"); |
| 13 | var machineNameTitle = $("#project-machine-name"); |
| 14 | var machineChangeCancel = $("#cancel-machine-change"); |
| 15 | |
| 16 | var freqBuildBtn = $("#freq-build-btn"); |
| 17 | var freqBuildList = $("#freq-build-list"); |
| 18 | |
| 19 | var releaseChangeFormToggle = $("#release-change-toggle"); |
| 20 | var releaseTitle = $("#project-release-title"); |
| 21 | var releaseForm = $("#change-release-form"); |
| 22 | var releaseModal = $("#change-release-modal"); |
| 23 | var cancelReleaseChange = $("#cancel-release-change"); |
| 24 | |
| 25 | var currentLayerAddSelection; |
| 26 | var currentMachineAddSelection = {}; |
| 27 | |
| 28 | var urlParams = libtoaster.parseUrlParams(); |
| 29 | |
| 30 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){ |
| 31 | updateProjectLayers(prjInfo.layers); |
| 32 | updateFreqBuildRecipes(prjInfo.freqtargets); |
| 33 | updateProjectRelease(prjInfo.release); |
| 34 | updateProjectReleases(prjInfo.releases, prjInfo.release); |
| 35 | |
| 36 | /* If we're receiving a machine set from the url and it's different from |
| 37 | * our current machine then activate set machine sequence. |
| 38 | */ |
| 39 | if (urlParams.hasOwnProperty('setMachine') && |
| 40 | urlParams.setMachine !== prjInfo.machine.name){ |
| 41 | currentMachineAddSelection.name = urlParams.setMachine; |
| 42 | machineChangeBtn.click(); |
| 43 | } else { |
| 44 | updateMachineName(prjInfo.machine.name); |
| 45 | } |
| 46 | |
| 47 | /* Now we're really ready show the page */ |
| 48 | $("#project-page").show(); |
| 49 | }); |
| 50 | |
| 51 | (function notificationRequest(){ |
| 52 | |
| 53 | if (urlParams.hasOwnProperty('notify')){ |
| 54 | switch (urlParams.notify){ |
| 55 | case 'new-project': |
| 56 | $("#project-created-notification").show(); |
| 57 | break; |
| 58 | case 'layer-imported': |
| 59 | layerImportedNotification(); |
| 60 | break; |
| 61 | default: |
| 62 | break; |
| 63 | } |
| 64 | } |
| 65 | })(); |
| 66 | |
| 67 | /* Layer imported notification */ |
| 68 | function layerImportedNotification(){ |
| 69 | var imported = $.cookie("layer-imported-alert"); |
| 70 | var message = "Layer imported"; |
| 71 | |
| 72 | if (!imported) |
| 73 | return; |
| 74 | else |
| 75 | imported = JSON.parse(imported); |
| 76 | |
| 77 | if (imported.deps_added.length === 0) { |
| 78 | message = "You have imported <strong><a href=\""+imported.imported_layer.layerdetailurl+"\">"+imported.imported_layer.name+"</a></strong> and added it to your project."; |
| 79 | } else { |
| 80 | |
| 81 | var links = "<a href=\""+imported.imported_layer.layerdetailurl+"\">"+imported.imported_layer.name+"</a>, "; |
| 82 | |
| 83 | imported.deps_added.map (function(item, index){ |
| 84 | links +='<a href="'+item.layerdetailurl+'">'+item.name+'</a>'; |
| 85 | /*If we're at the last element we don't want the trailing comma */ |
| 86 | if (imported.deps_added[index+1] !== undefined) |
| 87 | links += ', '; |
| 88 | }); |
| 89 | |
| 90 | /* Length + 1 here to do deps + the imported layer */ |
| 91 | message = 'You have imported <strong><a href="'+imported.imported_layer.layerdetailurl+'">'+imported.imported_layer.name+'</a></strong> and added <strong>'+(imported.deps_added.length+1)+'</strong> layers to your project: <strong>'+links+'</strong>'; |
| 92 | } |
| 93 | |
| 94 | libtoaster.showChangeNotification(message); |
| 95 | |
| 96 | $.removeCookie("layer-imported-alert", { path: "/"}); |
| 97 | } |
| 98 | |
| 99 | /* Add/Rm layer functionality */ |
| 100 | |
| 101 | libtoaster.makeTypeahead(layerAddInput, libtoaster.ctx.layersTypeAheadUrl, { include_added: "false" }, function(item){ |
| 102 | currentLayerAddSelection = item; |
| 103 | layerAddBtn.removeAttr("disabled"); |
| 104 | }); |
| 105 | |
| 106 | layerAddBtn.click(function(e){ |
| 107 | e.preventDefault(); |
| 108 | var layerObj = currentLayerAddSelection; |
| 109 | |
| 110 | addRmLayer(layerObj, true); |
| 111 | /* Reset the text input */ |
| 112 | layerAddInput.val(""); |
| 113 | }); |
| 114 | |
| 115 | function addRmLayer(layerObj, add){ |
| 116 | |
| 117 | libtoaster.addRmLayer(layerObj, add, function(layerDepsList){ |
| 118 | if (add){ |
| 119 | updateProjectLayers([layerObj]); |
| 120 | updateProjectLayers(layerDepsList); |
| 121 | } |
| 122 | |
| 123 | /* Show the alert message */ |
| 124 | var message = libtoaster.makeLayerAddRmAlertMsg(layerObj, layerDepsList, add); |
| 125 | libtoaster.showChangeNotification(message); |
| 126 | }); |
| 127 | } |
| 128 | |
| 129 | function updateProjectLayers(layers){ |
| 130 | |
| 131 | /* No layers to add */ |
| 132 | if (layers.length === 0){ |
| 133 | updateLayersCount(); |
| 134 | return; |
| 135 | } |
| 136 | |
| 137 | for (var i in layers){ |
| 138 | var layerObj = layers[i]; |
| 139 | |
| 140 | var projectLayer = $("<li><a></a><span class=\"icon-trash\" data-toggle=\"tooltip\" title=\"Delete\"></span></li>"); |
| 141 | |
| 142 | projectLayer.data('layer', layerObj); |
| 143 | projectLayer.children("span").tooltip(); |
| 144 | |
| 145 | var link = projectLayer.children("a"); |
| 146 | |
| 147 | link.attr("href", layerObj.layerdetailurl); |
| 148 | link.text(layerObj.name); |
| 149 | /* YOCTO #8024 |
| 150 | link.tooltip({title: layerObj.giturl + " | "+ layerObj.branch.name, placement: "right"}); |
| 151 | branch name not accessible sometimes it is revision instead |
| 152 | */ |
| 153 | |
| 154 | var trashItem = projectLayer.children("span"); |
| 155 | trashItem.click(function (e) { |
| 156 | e.preventDefault(); |
| 157 | var layerObjToRm = $(this).parent().data('layer'); |
| 158 | |
| 159 | addRmLayer(layerObjToRm, false); |
| 160 | |
| 161 | $(this).parent().fadeOut(function (){ |
| 162 | $(this).remove(); |
| 163 | updateLayersCount(); |
| 164 | }); |
| 165 | }); |
| 166 | |
| 167 | layersInPrjList.append(projectLayer); |
| 168 | |
| 169 | updateLayersCount(); |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | function updateLayersCount(){ |
| 174 | var count = $("#layers-in-project-list").children().length; |
| 175 | |
| 176 | if (count === 0) |
| 177 | $("#no-layers-in-project").fadeIn(); |
| 178 | else |
| 179 | $("#no-layers-in-project").hide(); |
| 180 | |
| 181 | $("#project-layers-count").text(count); |
| 182 | |
| 183 | return count; |
| 184 | } |
| 185 | |
| 186 | /* Frequent builds functionality */ |
| 187 | function updateFreqBuildRecipes(recipes) { |
| 188 | var noMostBuilt = $("#no-most-built"); |
| 189 | |
| 190 | if (recipes.length === 0){ |
| 191 | noMostBuilt.show(); |
| 192 | freqBuildBtn.hide(); |
| 193 | } else { |
| 194 | noMostBuilt.hide(); |
| 195 | freqBuildBtn.show(); |
| 196 | } |
| 197 | |
| 198 | for (var i in recipes){ |
| 199 | var freqTargetCheck = $('<li><label class="checkbox"><input type="checkbox" /><span class="freq-target-name"></span></label></li>'); |
| 200 | freqTargetCheck.find(".freq-target-name").text(recipes[i]); |
| 201 | freqTargetCheck.find("input").val(recipes[i]); |
| 202 | freqTargetCheck.click(function(){ |
| 203 | if (freqBuildList.find(":checked").length > 0) |
| 204 | freqBuildBtn.removeAttr("disabled"); |
| 205 | else |
| 206 | freqBuildBtn.attr("disabled", "disabled"); |
| 207 | }); |
| 208 | |
| 209 | freqBuildList.append(freqTargetCheck); |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | freqBuildBtn.click(function(e){ |
| 214 | e.preventDefault(); |
| 215 | |
| 216 | var toBuild = ""; |
| 217 | freqBuildList.find(":checked").each(function(){ |
| 218 | toBuild += $(this).val(); |
| 219 | }); |
| 220 | |
| 221 | libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl, libtoaster.ctx.projectId, toBuild, function(){ |
| 222 | /* Build started */ |
| 223 | window.location.replace(libtoaster.ctx.projectBuildsUrl); |
| 224 | }, |
| 225 | function(){ |
| 226 | /* Build start failed */ |
| 227 | /* [YOCTO #7995] */ |
| 228 | window.location.replace(libtoaster.ctx.projectBuildsUrl); |
| 229 | }); |
| 230 | }); |
| 231 | |
| 232 | |
| 233 | /* Change machine functionality */ |
| 234 | |
| 235 | machineChangeFormToggle.click(function(){ |
| 236 | machineForm.slideDown(); |
| 237 | machineNameTitle.hide(); |
| 238 | $(this).hide(); |
| 239 | }); |
| 240 | |
| 241 | machineChangeCancel.click(function(){ |
| 242 | machineForm.slideUp(function(){ |
| 243 | machineNameTitle.show(); |
| 244 | machineChangeFormToggle.show(); |
| 245 | }); |
| 246 | }); |
| 247 | |
| 248 | function updateMachineName(machineName){ |
| 249 | machineChangeInput.val(machineName); |
| 250 | machineNameTitle.text(machineName); |
| 251 | } |
| 252 | |
| 253 | libtoaster.makeTypeahead(machineChangeInput, libtoaster.ctx.machinesTypeAheadUrl, { }, function(item){ |
| 254 | currentMachineAddSelection = item; |
| 255 | machineChangeBtn.removeAttr("disabled"); |
| 256 | }); |
| 257 | |
| 258 | machineChangeBtn.click(function(e){ |
| 259 | e.preventDefault(); |
| 260 | if (currentMachineAddSelection.name === undefined) |
| 261 | return; |
| 262 | |
| 263 | libtoaster.editCurrentProject({ machineName : currentMachineAddSelection.name }, |
| 264 | function(){ |
| 265 | /* Success machine changed */ |
| 266 | updateMachineName(currentMachineAddSelection.name); |
| 267 | machineChangeCancel.click(); |
| 268 | |
| 269 | /* Show the alert message */ |
| 270 | var message = $('<span class="lead">You have changed the machine to: <strong><span id="notify-machine-name"></span></strong></span>'); |
| 271 | message.find("#notify-machine-name").text(currentMachineAddSelection.name); |
| 272 | libtoaster.showChangeNotification(message); |
| 273 | }, |
| 274 | function(){ |
| 275 | /* Failed machine changed */ |
| 276 | console.log("failed to change machine"); |
| 277 | }); |
| 278 | }); |
| 279 | |
| 280 | |
| 281 | /* Change release functionality */ |
| 282 | function updateProjectRelease(release){ |
| 283 | releaseTitle.text(release.description); |
| 284 | } |
| 285 | |
| 286 | function updateProjectReleases(releases, current){ |
| 287 | for (var i in releases){ |
| 288 | var releaseOption = $("<option></option>"); |
| 289 | |
| 290 | releaseOption.val(releases[i].id); |
| 291 | releaseOption.text(releases[i].description); |
| 292 | releaseOption.data('release', releases[i]); |
| 293 | |
| 294 | if (releases[i].id == current.id) |
| 295 | releaseOption.attr("selected", "selected"); |
| 296 | |
| 297 | releaseForm.children("select").append(releaseOption); |
| 298 | } |
| 299 | } |
| 300 | |
| 301 | releaseChangeFormToggle.click(function(){ |
| 302 | releaseForm.slideDown(); |
| 303 | releaseTitle.hide(); |
| 304 | $(this).hide(); |
| 305 | }); |
| 306 | |
| 307 | cancelReleaseChange.click(function(e){ |
| 308 | e.preventDefault(); |
| 309 | releaseForm.slideUp(function(){ |
| 310 | releaseTitle.show(); |
| 311 | releaseChangeFormToggle.show(); |
| 312 | }); |
| 313 | }); |
| 314 | |
| 315 | function changeProjectRelease(release, layersToRm){ |
| 316 | libtoaster.editCurrentProject({ projectVersion : release.id }, |
| 317 | function(){ |
| 318 | /* Success */ |
| 319 | /* Update layers list with new layers */ |
| 320 | layersInPrjList.addClass('muted'); |
| 321 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, |
| 322 | function(prjInfo){ |
| 323 | layersInPrjList.children().remove(); |
| 324 | updateProjectLayers(prjInfo.layers); |
| 325 | layersInPrjList.removeClass('muted'); |
| 326 | releaseChangedNotification(release, prjInfo.layers, layersToRm); |
| 327 | }); |
| 328 | updateProjectRelease(release); |
| 329 | cancelReleaseChange.click(); |
| 330 | }); |
| 331 | } |
| 332 | |
| 333 | /* Create a notification to show the changes to the layer configuration |
| 334 | * caused by changing a release. |
| 335 | */ |
| 336 | |
| 337 | function releaseChangedNotification(release, layers, layersToRm){ |
| 338 | |
| 339 | var message; |
| 340 | |
| 341 | if (layers.length === 0 && layersToRm.length === 0){ |
| 342 | message = $('<span><span class="lead">You have changed the project release to: <strong><span id="notify-release-name"></span></strong>.'); |
| 343 | message.find("#notify-release-name").text(release.description); |
| 344 | libtoaster.showChangeNotification(message); |
| 345 | return; |
| 346 | } |
| 347 | |
| 348 | /* Create the whitespace separated list of layers removed */ |
| 349 | var layersDelList = ""; |
| 350 | |
| 351 | layersToRm.map(function(layer, i){ |
| 352 | layersDelList += layer.name; |
| 353 | if (layersToRm[i+1] !== undefined) |
| 354 | layersDelList += ', '; |
| 355 | }); |
| 356 | |
| 357 | message = $('<span><span class="lead">You have changed the project release to: <strong><span id="notify-release-name"></span></strong>. This has caused the following changes in your project layers:</span><ul id="notify-layers-changed-list"></ul></span>'); |
| 358 | |
| 359 | var changedList = message.find("#notify-layers-changed-list"); |
| 360 | |
| 361 | message.find("#notify-release-name").text(release.description); |
| 362 | |
| 363 | /* Manually construct the list item for changed layers */ |
| 364 | var li = '<li><strong>'+layers.length+'</strong> layers changed to the <strong>'+release.name+'</strong> release: '; |
| 365 | for (var i in layers){ |
| 366 | li += '<a href='+layers[i].layerdetailurl+'>'+layers[i].name+'</a>'; |
| 367 | if (i !== 0) |
| 368 | li += ', '; |
| 369 | } |
| 370 | |
| 371 | changedList.append($(li)); |
| 372 | |
| 373 | /* Layers removed */ |
| 374 | if (layersToRm && layersToRm.length > 0){ |
| 375 | if (layersToRm.length == 1) |
| 376 | li = '<li><strong>1</strong> layer deleted: '+layersToRm[0].name+'</li>'; |
| 377 | else |
| 378 | li = '<li><strong>'+layersToRm.length+'</strong> layers deleted: '+layersDelList+'</li>'; |
| 379 | |
| 380 | changedList.append($(li)); |
| 381 | } |
| 382 | |
| 383 | libtoaster.showChangeNotification(message); |
| 384 | } |
| 385 | |
| 386 | /* Show the modal dialog which gives the option to remove layers which |
| 387 | * aren't compatible with the proposed release |
| 388 | */ |
| 389 | function showReleaseLayerChangeModal(release, layers){ |
| 390 | var layersToRmList = releaseModal.find("#layers-to-remove-list"); |
| 391 | layersToRmList.text(""); |
| 392 | |
| 393 | releaseModal.find(".proposed-release-change-name").text(release.description); |
| 394 | releaseModal.data("layers", layers); |
| 395 | releaseModal.data("release", release); |
| 396 | |
| 397 | for (var i in layers){ |
| 398 | layersToRmList.append($("<li></li>").text(layers[i].name)); |
| 399 | } |
| 400 | releaseModal.modal('show'); |
| 401 | } |
| 402 | |
| 403 | $("#change-release-btn").click(function(e){ |
| 404 | e.preventDefault(); |
| 405 | |
| 406 | var newRelease = releaseForm.find("option:selected").data('release'); |
| 407 | |
| 408 | $.getJSON(ctx.testReleaseChangeUrl, |
| 409 | { new_release_id: newRelease.id }, |
| 410 | function(layers) { |
| 411 | if (layers.rows.length === 0){ |
| 412 | /* No layers to change for this release */ |
| 413 | changeProjectRelease(newRelease, []); |
| 414 | } else { |
| 415 | showReleaseLayerChangeModal(newRelease, layers.rows); |
| 416 | } |
| 417 | }); |
| 418 | }); |
| 419 | |
| 420 | /* Release change modal accept */ |
| 421 | $("#change-release-and-rm-layers").click(function(){ |
| 422 | var layers = releaseModal.data("layers"); |
| 423 | var release = releaseModal.data("release"); |
| 424 | |
| 425 | changeProjectRelease(release, layers); |
| 426 | }); |
| 427 | |
| 428 | } |