layerdetails.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. "use strict";
  2. function layerDetailsPageInit (ctx) {
  3. var layerDepInput = $("#layer-dep-input");
  4. var layerDepBtn = $("#add-layer-dependency-btn");
  5. var layerDepsList = $("#layer-deps-list");
  6. var currentLayerDepSelection;
  7. var addRmLayerBtn = $("#add-remove-layer-btn");
  8. var targetTab = $("#targets-tab");
  9. var machineTab = $("#machines-tab");
  10. var detailsTab = $("#details-tab");
  11. /* setup the dependencies typeahead */
  12. libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.layersTypeAheadUrl, { include_added: "true" }, function(item){
  13. currentLayerDepSelection = item;
  14. layerDepBtn.removeAttr("disabled");
  15. });
  16. /* disable the add layer button if its input field is empty */
  17. layerDepInput.on("keyup",function(){
  18. if ($(this).val().length === 0) {
  19. layerDepBtn.attr("disabled", "disabled");
  20. }
  21. });
  22. $(window).on('hashchange', function(e){
  23. switch(window.location.hash){
  24. case '#machines':
  25. machineTab.tab('show');
  26. break;
  27. case '#recipes':
  28. targetTab.tab('show');
  29. break;
  30. default:
  31. detailsTab.tab('show');
  32. break;
  33. }
  34. });
  35. function addRemoveDep(depLayerId, add, doneCb) {
  36. var data = { layer_version_id : ctx.layerVersion.id };
  37. if (add)
  38. data.add_dep = depLayerId;
  39. else
  40. data.rm_dep = depLayerId;
  41. $.ajax({
  42. type: "POST",
  43. url: ctx.xhrUpdateLayerUrl,
  44. data: data,
  45. headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
  46. success: function (data) {
  47. if (data.error != "ok") {
  48. console.warn(data.error);
  49. } else {
  50. doneCb();
  51. }
  52. },
  53. error: function (data) {
  54. console.warn("Call failed");
  55. console.warn(data);
  56. }
  57. });
  58. }
  59. function layerDepRemoveClick() {
  60. var toRemove = $(this).parent().data('layer-id');
  61. var layerDepItem = $(this);
  62. addRemoveDep(toRemove, false, function(){
  63. layerDepItem.parent().fadeOut(function (){
  64. layerDepItem.remove();
  65. });
  66. });
  67. }
  68. /* Add dependency layer button click handler */
  69. layerDepBtn.click(function(){
  70. if (currentLayerDepSelection === undefined)
  71. return;
  72. addRemoveDep(currentLayerDepSelection.id, true, function(){
  73. /* Make a list item for the new layer dependency */
  74. var newLayerDep = $("<li><a></a><span class=\"glyphicon glyphicon-trash\" data-toggle=\"tooltip\" title=\"Delete\"></span></li>");
  75. newLayerDep.data('layer-id', currentLayerDepSelection.id);
  76. newLayerDep.children("span").tooltip();
  77. var link = newLayerDep.children("a");
  78. link.attr("href", currentLayerDepSelection.layerdetailurl);
  79. link.text(currentLayerDepSelection.name);
  80. link.tooltip({title: currentLayerDepSelection.tooltip, placement: "right"});
  81. /* Connect up the tash icon */
  82. var trashItem = newLayerDep.children("span");
  83. trashItem.click(layerDepRemoveClick);
  84. layerDepsList.append(newLayerDep);
  85. /* Clear the current selection */
  86. layerDepInput.val("");
  87. currentLayerDepSelection = undefined;
  88. layerDepBtn.attr("disabled", "disabled");
  89. });
  90. });
  91. $(".glyphicon-edit").click(function (){
  92. var mParent = $(this).parent("dd");
  93. mParent.prev().css("margin-top", "10px");
  94. mParent.children("form").slideDown();
  95. var currentVal = mParent.children(".current-value");
  96. currentVal.hide();
  97. /* Set the current value to the input field */
  98. mParent.find("textarea,input").val(currentVal.text());
  99. /* If the input field is empty, disable the submit button */
  100. if ( mParent.find("textarea,input").val().length == 0 ) {
  101. mParent.find(".change-btn").attr("disabled", "disabled");
  102. }
  103. /* Hides the "Not set" text */
  104. mParent.children(".text-muted").hide();
  105. /* We're editing so hide the delete icon */
  106. mParent.children(".delete-current-value").hide();
  107. mParent.find(".cancel").show();
  108. $(this).hide();
  109. });
  110. $(".delete-current-value").click(function(){
  111. var mParent = $(this).parent("dd");
  112. mParent.find("input").val("");
  113. mParent.find("textarea").val("");
  114. mParent.find(".change-btn").click();
  115. });
  116. $(".cancel").click(function(){
  117. var mParent = $(this).parents("dd");
  118. $(this).hide();
  119. mParent.children("form").slideUp(function(){
  120. mParent.children(".current-value").show();
  121. /* Show the "Not set" text if we ended up with no value */
  122. if (!mParent.children(".current-value").html()){
  123. mParent.children(".text-muted").fadeIn();
  124. mParent.children(".delete-current-value").hide();
  125. } else {
  126. mParent.children(".delete-current-value").show();
  127. }
  128. mParent.children(".glyphicon-edit").show();
  129. mParent.prev().css("margin-top", "0");
  130. });
  131. });
  132. function defaultAddBtnText(){
  133. var text = " Add the "+ctx.layerVersion.name+" layer to your project";
  134. addRmLayerBtn.text(text);
  135. addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-plus\"></span>");
  136. addRmLayerBtn.removeClass("btn-danger");
  137. }
  138. detailsTab.on('show', function(){
  139. if (!ctx.layerVersion.inCurrentPrj)
  140. defaultAddBtnText();
  141. window.location.hash = "details";
  142. });
  143. function targetsTabShow(){
  144. if (!ctx.layerVersion.inCurrentPrj){
  145. if (ctx.numTargets > 0) {
  146. var text = " Add the "+ctx.layerVersion.name+" layer to your project "+
  147. "to enable these recipes";
  148. addRmLayerBtn.text(text);
  149. addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-plus\"></span>");
  150. } else {
  151. defaultAddBtnText();
  152. }
  153. }
  154. window.location.hash = "recipes";
  155. }
  156. $("#recipestable").on('table-done', function(e, total, tableParams){
  157. ctx.numTargets = total;
  158. if (total === 0 && !tableParams.search) {
  159. $("#no-recipes-yet").show();
  160. } else {
  161. $("#no-recipes-yet").hide();
  162. }
  163. targetTab.removeClass("text-muted");
  164. if (window.location.hash === "#recipes"){
  165. /* re run the machinesTabShow to update the text */
  166. targetsTabShow();
  167. }
  168. });
  169. $("#machinestable").on('table-done', function(e, total, tableParams){
  170. ctx.numMachines = total;
  171. if (total === 0 && !tableParams.search)
  172. $("#no-machines-yet").show();
  173. else
  174. $("#no-machines-yet").hide();
  175. machineTab.removeClass("text-muted");
  176. if (window.location.hash === "#machines"){
  177. /* re run the machinesTabShow to update the text */
  178. machinesTabShow();
  179. }
  180. $(".select-machine-btn").click(function(e){
  181. if ($(this).hasClass("disabled"))
  182. e.preventDefault();
  183. });
  184. });
  185. targetTab.on('show.bs.tab', targetsTabShow);
  186. function machinesTabShow(){
  187. if (!ctx.layerVersion.inCurrentPrj) {
  188. if (ctx.numMachines > 0){
  189. var text = " Add the "+ctx.layerVersion.name+" layer to your project " +
  190. "to enable these machines";
  191. addRmLayerBtn.text(text);
  192. addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-plus\"></span>");
  193. } else {
  194. defaultAddBtnText();
  195. }
  196. }
  197. window.location.hash = "machines";
  198. }
  199. machineTab.on('show.bs.tab', machinesTabShow);
  200. $(".pagesize").change(function(){
  201. var search = libtoaster.parseUrlParams();
  202. search.limit = this.value;
  203. window.location.search = libtoaster.dumpsUrlParams(search);
  204. });
  205. /* Enables the Build target and Select Machine buttons and switches the
  206. * add/remove button
  207. */
  208. function setLayerInCurrentPrj(added) {
  209. ctx.layerVersion.inCurrentPrj = added;
  210. if (added){
  211. /* enable and switch all the button states */
  212. $(".build-recipe-btn").removeClass("disabled");
  213. $(".select-machine-btn").removeClass("disabled");
  214. addRmLayerBtn.addClass("btn-danger");
  215. addRmLayerBtn.data('directive', "remove");
  216. addRmLayerBtn.text(" Remove the "+ctx.layerVersion.name+" layer from your project");
  217. addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-trash\"></span>");
  218. } else {
  219. /* disable and switch all the button states */
  220. $(".build-recipe-btn").addClass("disabled");
  221. $(".select-machine-btn").addClass("disabled");
  222. addRmLayerBtn.removeClass("btn-danger");
  223. addRmLayerBtn.data('directive', "add");
  224. /* "special" handler so that we get the correct button text which depends
  225. * on which tab is currently visible. Unfortunately we can't just call
  226. * tab('show') as if it's already visible it doesn't run the event.
  227. */
  228. switch ($(".nav-tabs .active a").prop('id')){
  229. case 'machines-tab':
  230. machinesTabShow();
  231. break;
  232. case 'targets-tab':
  233. targetsTabShow();
  234. break;
  235. default:
  236. defaultAddBtnText();
  237. break;
  238. }
  239. }
  240. }
  241. $("#dismiss-alert").click(function(){
  242. $(this).parent().fadeOut();
  243. });
  244. /* Add or remove this layer from the project */
  245. addRmLayerBtn.click(function() {
  246. var add = ($(this).data('directive') === "add");
  247. libtoaster.addRmLayer(ctx.layerVersion, add, function (layersList){
  248. var alertMsg = $("#alert-msg");
  249. alertMsg.html(libtoaster.makeLayerAddRmAlertMsg(ctx.layerVersion, layersList, add));
  250. setLayerInCurrentPrj(add);
  251. libtoaster.showChangeNotification(alertMsg);
  252. });
  253. });
  254. /* Handler for all of the Change buttons */
  255. $(".change-btn").click(function(){
  256. var mParent = $(this).parent();
  257. var prop = $(this).data('layer-prop');
  258. /* We have inputs, select and textareas to potentially grab the value
  259. * from.
  260. */
  261. var entryElement = mParent.find("input");
  262. if (entryElement.length === 0)
  263. entryElement = mParent.find("textarea");
  264. if (entryElement.length === 0) {
  265. console.warn("Could not find element to get data from for this change");
  266. return;
  267. }
  268. var data = { layer_version_id: ctx.layerVersion.id };
  269. data[prop] = entryElement.val();
  270. $.ajax({
  271. type: "POST",
  272. url: ctx.xhrUpdateLayerUrl,
  273. data: data,
  274. headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
  275. success: function (data) {
  276. if (data.error != "ok") {
  277. console.warn(data.error);
  278. } else {
  279. /* success layer property changed */
  280. var inputArea = mParent.parents("dd");
  281. var text;
  282. text = entryElement.val();
  283. /* Hide the "Not set" text if it's visible */
  284. inputArea.find(".text-muted").hide();
  285. inputArea.find(".current-value").text(text);
  286. /* Same behaviour as cancel in that we hide the form/show current
  287. * value.
  288. */
  289. inputArea.find(".cancel").click();
  290. }
  291. },
  292. error: function (data) {
  293. console.warn("Call failed");
  294. console.warn(data);
  295. }
  296. });
  297. });
  298. /* Disable the change button when we have no data in the input */
  299. $("dl input, dl textarea").on("input",function() {
  300. if ($(this).val().length === 0)
  301. $(this).parent().next(".change-btn").attr("disabled", "disabled");
  302. else
  303. $(this).parent().next(".change-btn").removeAttr("disabled");
  304. });
  305. /* This checks to see if the dt's dd has data in it or if the change data
  306. * form is visible, otherwise hide it
  307. */
  308. $("dl").children().each(function (){
  309. if ($(this).is("dt")) {
  310. var dd = $(this).next("dd");
  311. if (!dd.children("form:visible")|| !dd.find(".current-value").html()){
  312. if (ctx.layerVersion.sourceId == 3){
  313. /* There's no current value and the layer is editable
  314. * so show the "Not set" and hide the delete icon
  315. */
  316. dd.find(".text-muted").show();
  317. dd.find(".delete-current-value").hide();
  318. } else {
  319. /* We're not viewing an editable layer so hide the empty dd/dl pair */
  320. $(this).hide();
  321. dd.hide();
  322. }
  323. }
  324. }
  325. });
  326. /* Hide the right column if it contains no information */
  327. if ($("dl.item-info").children(':visible').length === 0) {
  328. $("dl.item-info").parent().hide();
  329. }
  330. /* Clear the current search selection and reload the results */
  331. $(".target-search-clear").click(function(){
  332. $("#target-search").val("");
  333. $(this).parents("form").submit();
  334. });
  335. $(".machine-search-clear").click(function(){
  336. $("#machine-search").val("");
  337. $(this).parents("form").submit();
  338. });
  339. layerDepsList.find(".glyphicon-trash").click(layerDepRemoveClick);
  340. layerDepsList.find("a").tooltip();
  341. $(".glyphicon-trash").tooltip();
  342. $(".commit").tooltip();
  343. }