summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
diff options
context:
space:
mode:
authorMichael Wood <michael.g.wood@intel.com>2015-01-14 12:46:52 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-01-16 08:25:31 +0000
commit025533d90b694ed37278c8f5be85afbd05857971 (patch)
tree51bb70fa2873285e1e6d716cf637d78ccb538317 /bitbake/lib/toaster/toastergui/static/js/layerdetails.js
parent2a6f739f1d3a0383d849cb2944c69797b4b3e437 (diff)
downloadpoky-025533d90b694ed37278c8f5be85afbd05857971.tar.gz
bitbake: toaster: Add layer details page feature
This commit adds the layer details page which shows the metadata for the layer such as layer description, machines associated with the layer as well as the targets provided. If the layer is an imported layer this page also allows you to update the layer's configuration. >From this page you can add/remove the layer from the current project (Bitbake rev: c1442bc68ad8ba20c37b1a7cde1400297f4be811) Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/toastergui/static/js/layerdetails.js')
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/layerdetails.js404
1 files changed, 404 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/js/layerdetails.js b/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
new file mode 100644
index 0000000000..a5a6330630
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
@@ -0,0 +1,404 @@
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
11 /* setup the dependencies typeahead */
12 libtoaster.makeTypeahead(layerDepInput, ctx.xhrDataTypeaheadUrl, { type : "layers", project_id: ctx.projectId, include_added: "true" }, function(item){
13 currentLayerDepSelection = item;
14
15 layerDepBtn.removeAttr("disabled");
16 });
17
18 function addRemoveDep(depLayerId, add, doneCb) {
19 var data = { layer_version_id : ctx.layerVersion.id };
20 if (add)
21 data.add_dep = depLayerId;
22 else
23 data.rm_dep = depLayerId;
24
25 $.ajax({
26 type: "POST",
27 url: ctx.xhrUpdateLayerUrl,
28 data: data,
29 headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
30 success: function (data) {
31 if (data.error != "ok") {
32 console.warn(data.error);
33 } else {
34 doneCb();
35 }
36 },
37 error: function (data) {
38 console.warn("Call failed");
39 console.warn(data);
40 }
41 });
42 }
43
44 function layerRemoveClick() {
45 var toRemove = $(this).parent().data('layer-id');
46 var layerDepItem = $(this);
47
48 addRemoveDep(toRemove, false, function(){
49 layerDepItem.parent().fadeOut(function (){
50 layerDepItem.remove();
51 });
52 });
53 }
54
55 /* Add dependency layer button click handler */
56 layerDepBtn.click(function(){
57 if (currentLayerDepSelection == undefined)
58 return;
59
60 addRemoveDep(currentLayerDepSelection.id, true, function(){
61 /* Make a list item for the new layer dependency */
62 var newLayerDep = $("<li><a></a><span class=\"icon-trash\" data-toggle=\"tooltip\" title=\"Delete\"></span></li>");
63
64 newLayerDep.data('layer-id', currentLayerDepSelection.id);
65 newLayerDep.children("span").tooltip();
66
67 var link = newLayerDep.children("a");
68 link.attr("href", ctx.layerDetailsUrl+String(currentLayerDepSelection.id));
69 link.text(currentLayerDepSelection.name);
70 link.tooltip({title: currentLayerDepSelection.tooltip, placement: "right"});
71
72 /* Connect up the tash icon */
73 var trashItem = newLayerDep.children("span");
74 trashItem.click(layerRemoveClick);
75
76 layerDepsList.append(newLayerDep);
77 /* Clear the current selection */
78 layerDepInput.val("");
79 currentLayerDepSelection = undefined;
80 layerDepBtn.attr("disabled","disabled");
81 });
82 });
83
84 $(".icon-pencil").click(function (){
85 var mParent = $(this).parent("dd");
86 mParent.prev().css("margin-top", "10px");
87 mParent.children("form").slideDown();
88 var currentVal = mParent.children(".current-value");
89 currentVal.hide();
90 /* Set the current value to the input field */
91 mParent.find("textarea,input").val(currentVal.text());
92 /* Hides the "Not set" text */
93 mParent.children(".muted").hide();
94 /* We're editing so hide the delete icon */
95 mParent.children(".delete-current-value").hide();
96 mParent.find(".cancel").show();
97 $(this).hide();
98 });
99
100 $(".delete-current-value").click(function(){
101 var mParent = $(this).parent("dd");
102 mParent.find("input").val("");
103 mParent.find("textarea").val("");
104 mParent.find(".change-btn").click();
105 });
106
107 $(".cancel").click(function(){
108 var mParent = $(this).parents("dd");
109 $(this).hide();
110 mParent.children("form").slideUp(function(){
111 mParent.children(".current-value").show();
112 /* Show the "Not set" text if we ended up with no value */
113 if (!mParent.children(".current-value").html()){
114 mParent.children(".muted").fadeIn();
115 mParent.children(".delete-current-value").hide();
116 } else {
117 mParent.children(".delete-current-value").show();
118 }
119
120 mParent.children(".icon-pencil").show();
121 mParent.prev().css("margin-top", "0px");
122 });
123 });
124
125 $(".build-target-btn").click(function(){
126 /* fire a build */
127 var target = $(this).data('target-name');
128 libtoaster.startABuild(ctx.projectBuildUrl, ctx.projectId, target, null, null);
129 window.location.replace(ctx.projectPageUrl);
130 });
131
132 $(".select-machine-btn").click(function(){
133 var data = { machineName : $(this).data('machine-name') };
134 libtoaster.editProject(ctx.xhrEditProjectUrl, ctx.projectId, data,
135 function (){
136 window.location.replace(ctx.projectPageUrl);
137 }, null);
138 });
139
140 function defaultAddBtnText(){
141 var text = " Add the "+ctx.layerVersion.name+" layer to your project";
142 addRmLayerBtn.text(text);
143 addRmLayerBtn.prepend("<span class=\"icon-plus\"></span>");
144 addRmLayerBtn.removeClass("btn-danger");
145 }
146
147 $("#details-tab").on('show', function(){
148 if (!ctx.layerVersion.inCurrentPrj)
149 defaultAddBtnText();
150
151 window.location.hash = "details";
152 });
153
154 function targetsTabShow(){
155 if (!ctx.layerVersion.inCurrentPrj){
156 if (ctx.numTargets > 0) {
157 var text = " Add the "+ctx.layerVersion.name+" layer to your project "+
158 "to enable these targets";
159 addRmLayerBtn.text(text);
160 addRmLayerBtn.prepend("<span class=\"icon-plus\"></span>");
161 } else {
162 defaultAddBtnText();
163 }
164 }
165
166 window.location.hash = "targets";
167 }
168
169 $("#targets-tab").on('show', targetsTabShow);
170
171 function machinesTabShow(){
172 if (!ctx.layerVersion.inCurrentPrj) {
173 if (ctx.numMachines > 0){
174 var text = " Add the "+ctx.layerVersion.name+" layer to your project " +
175 "to enable these machines";
176 addRmLayerBtn.text(text);
177 addRmLayerBtn.prepend("<span class=\"icon-plus\"></span>");
178 } else {
179 defaultAddBtnText();
180 }
181 }
182
183 window.location.hash = "machines";
184 }
185
186 $("#machines-tab").on('show', machinesTabShow);
187
188 $(".pagesize").change(function(){
189 var search = libtoaster.parseUrlParams();
190 search.limit = this.value;
191
192 window.location.search = libtoaster.dumpsUrlParams(search);
193 });
194
195 /* Enables the Build target and Select Machine buttons and switches the
196 * add/remove button
197 */
198 function setLayerInCurrentPrj(added, depsList) {
199 ctx.layerVersion.inCurrentPrj = added;
200 var alertMsg = $("#alert-msg");
201 /* Reset alert message */
202 alertMsg.text("");
203
204 if (added){
205 /* enable and switch all the button states */
206 $(".build-target-btn").removeAttr("disabled");
207 $(".select-machine-btn").removeAttr("disabled");
208 addRmLayerBtn.addClass("btn-danger");
209 addRmLayerBtn.data('directive', "remove");
210 addRmLayerBtn.text(" Delete the "+ctx.layerVersion.name+" layer from your project");
211 addRmLayerBtn.prepend("<span class=\"icon-trash\"></span>");
212
213 if (depsList) {
214 alertMsg.append("You have added <strong>"+(depsList.length+1)+"</strong> layers: <span id=\"layer-affected-name\"></span> and its dependencies ");
215
216 /* Build the layer deps list */
217 depsList.map(function(layer, i){
218 var link = $("<a></a>");
219
220 link.attr("href", layer.layerdetailurl);
221 link.text(layer.name);
222 link.tooltip({title: layer.tooltip});
223
224 if (i != 0)
225 alertMsg.append(", ");
226
227 alertMsg.append(link);
228 });
229 } else {
230 alertMsg.append("You have added <strong>1</strong> layer: <span id=\"layer-affected-name\"></span>");
231 }
232 } else {
233 /* disable and switch all the button states */
234 $(".build-target-btn").attr("disabled","disabled");
235 $(".select-machine-btn").attr("disabled", "disabled");
236 addRmLayerBtn.removeClass("btn-danger");
237 addRmLayerBtn.data('directive', "add");
238
239 /* "special" handler so that we get the correct button text which depends
240 * on which tab is currently visible. Unfortunately we can't just call
241 * tab('show') as if it's already visible it doesn't run the event.
242 */
243 switch ($(".nav-pills .active a").prop('id')){
244 case 'machines-tab':
245 machinesTabShow();
246 break;
247 case 'targets-tab':
248 targetsTabShow();
249 break;
250 default:
251 defaultAddBtnText();
252 break;
253 }
254
255 alertMsg.append("You have deleted <strong>1</strong> layer: <span id=\"layer-affected-name\"></span>");
256 }
257
258 alertMsg.children("#layer-affected-name").text(ctx.layerVersion.name);
259 $("#alert-area").show();
260 }
261
262 /* Add or remove this layer from the project */
263 addRmLayerBtn.click(function() {
264 var directive = $(this).data('directive');
265
266 if (directive == 'add') {
267 /* If adding get the deps for this layer */
268 libtoaster.getLayerDepsForProject(ctx.xhrDataTypeaheadUrl, ctx.projectId, ctx.layerVersion.id, function (data) {
269 /* got result for dependencies */
270 if (data.list.length == 0){
271 var editData = { layerAdd : ctx.layerVersion.id };
272 libtoaster.editProject(ctx.xhrEditProjectUrl, ctx.projectId, editData,
273 function() {
274 setLayerInCurrentPrj(true);
275 });
276 return;
277 } else {
278 /* The add deps will include this layer so no need to add it
279 * separately.
280 */
281 show_layer_deps_modal(ctx.projectId, ctx.layerVersion, data.list, null, null, true, function () {
282 /* Success add deps and layer */
283 setLayerInCurrentPrj(true, data.list);
284 });
285 }
286 }, null);
287 } else if (directive == 'remove') {
288 var editData = { layerDel : ctx.layerVersion.id };
289
290 libtoaster.editProject(ctx.xhrEditProjectUrl, ctx.projectId, editData,
291 function () {
292 /* Success removed layer */
293 //window.location.reload();
294 setLayerInCurrentPrj(false);
295 }, function () {
296 console.warn ("Removing layer from project failed");
297 });
298 }
299 });
300
301 /* Handler for all of the Change buttons */
302 $(".change-btn").click(function(){
303 var mParent = $(this).parent();
304 var prop = $(this).data('layer-prop');
305
306 /* We have inputs, select and textareas to potentially grab the value
307 * from.
308 */
309 var entryElement = mParent.find("input");
310 if (entryElement.length == 0)
311 entryElement = mParent.find("textarea");
312 if (entryElement.length == 0)
313 entryElement = mParent.find("select");
314 if (entryElement.length == 0) {
315 console.warn("Could not find element to get data from for this change");
316 return;
317 }
318
319 var data = { layer_version_id: ctx.layerVersion.id };
320 data[prop] = entryElement.val();
321
322 $.ajax({
323 type: "POST",
324 url: ctx.xhrUpdateLayerUrl,
325 data: data,
326 headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
327 success: function (data) {
328 if (data.error != "ok") {
329 console.warn(data.error);
330 } else {
331 /* success layer property changed */
332 var inputArea = mParent.parents("dd");
333 var text;
334 /* We don't actually want the value from the select option we want
335 * the text that represents the value to display
336 */
337 text = entryElement.children("option:selected").text();
338 if (!text)
339 text = entryElement.val();
340
341 /* Hide the "Not set" text if it's visible */
342 inputArea.find(".muted").hide();
343 inputArea.find(".current-value").text(text);
344 /* Same behaviour as cancel in that we hide the form/show current
345 * value.
346 */
347 inputArea.find(".cancel").click();
348 }
349 },
350 error: function (data) {
351 console.warn("Call failed");
352 console.warn(data);
353 }
354 });
355 });
356
357 /* Disable the change button when we have no data in the input */
358 $("dl input, dl textarea").keyup(function() {
359 if ($(this).val().length == 0)
360 $(this).parent().children(".change-btn").attr("disabled", "disabled");
361 else
362 $(this).parent().children(".change-btn").removeAttr("disabled");
363 });
364
365 /* This checks to see if the dt's dd has data in it or if the change data
366 * form is visible, otherwise hide it
367 */
368 $("dl").children().each(function (){
369 if ($(this).is("dt")) {
370 var dd = $(this).next("dd");
371 if (!dd.children("form:visible")|| !dd.find(".current-value").html()){
372 if (ctx.layerVersion.sourceId == 3){
373 /* There's no current value and the layer is editable
374 * so show the "Not set" and hide the delete icon
375 */
376 dd.find(".muted").show();
377 dd.find(".delete-current-value").hide();
378 } else {
379 /* We're not viewing an editable layer so hide the empty dd/dl pair */
380 $(this).hide();
381 dd.hide();
382 }
383 }
384 }
385 });
386
387 /* Clear the current search selection and reload the results */
388 $("#target-search-clear").click(function(){
389 $("#target-search").val("");
390 $(this).parents("form").submit();
391 });
392
393 $("#machine-search-clear").click(function(){
394 $("#machine-search").val("");
395 $(this).parents("form").submit();
396 });
397
398
399 layerDepsList.find(".icon-trash").click(layerRemoveClick);
400 layerDepsList.find("a").tooltip();
401 $(".icon-trash").tooltip();
402 $(".commit").tooltip();
403
404}