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