diff options
7 files changed, 1038 insertions, 150 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/css/default.css b/bitbake/lib/toaster/toastergui/static/css/default.css index 199c7531dc..a3fa0ddf6a 100644 --- a/bitbake/lib/toaster/toastergui/static/css/default.css +++ b/bitbake/lib/toaster/toastergui/static/css/default.css | |||
@@ -232,3 +232,4 @@ dd > span { line-height: 20px; } | |||
232 | .animate-repeat.ng-enter.ng-enter-active { | 232 | .animate-repeat.ng-enter.ng-enter-active { |
233 | opacity:1; | 233 | opacity:1; |
234 | } | 234 | } |
235 | .tab-pane table { margin-top: 10px; } | ||
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 | |||
3 | function 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 | } | ||
diff --git a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js index a2a0abd45b..04264cd8ba 100644 --- a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js +++ b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js | |||
@@ -161,6 +161,39 @@ var libtoaster = (function (){ | |||
161 | }); | 161 | }); |
162 | }; | 162 | }; |
163 | 163 | ||
164 | /* parses the query string of the current window.location to an object */ | ||
165 | function _parseUrlParams() { | ||
166 | string = window.location.search | ||
167 | string = string.substr(1); | ||
168 | stringArray = string.split ("&"); | ||
169 | obj = {}; | ||
170 | |||
171 | for (i in stringArray) { | ||
172 | keyVal = stringArray[i].split ("="); | ||
173 | obj[keyVal[0]] = keyVal[1]; | ||
174 | } | ||
175 | |||
176 | return obj; | ||
177 | }; | ||
178 | |||
179 | /* takes a flat object and outputs it as a query string | ||
180 | * e.g. the output of dumpsUrlParams | ||
181 | */ | ||
182 | function _dumpsUrlParams(obj) { | ||
183 | var str = "?"; | ||
184 | |||
185 | for (key in obj){ | ||
186 | if (!obj[key]) | ||
187 | continue; | ||
188 | |||
189 | str += key+ "="+obj[key].toString(); | ||
190 | str += "&"; | ||
191 | } | ||
192 | |||
193 | return str; | ||
194 | }; | ||
195 | |||
196 | |||
164 | return { | 197 | return { |
165 | reload_params : reload_params, | 198 | reload_params : reload_params, |
166 | startABuild : _startABuild, | 199 | startABuild : _startABuild, |
@@ -169,6 +202,8 @@ var libtoaster = (function (){ | |||
169 | getLayerDepsForProject : _getLayerDepsForProject, | 202 | getLayerDepsForProject : _getLayerDepsForProject, |
170 | editProject : _editProject, | 203 | editProject : _editProject, |
171 | debug: false, | 204 | debug: false, |
205 | parseUrlParams : _parseUrlParams, | ||
206 | dumpsUrlParams : _dumpsUrlParams, | ||
172 | } | 207 | } |
173 | })(); | 208 | })(); |
174 | 209 | ||
diff --git a/bitbake/lib/toaster/toastergui/templates/layerdetails.html b/bitbake/lib/toaster/toastergui/templates/layerdetails.html index 78dc54bfd1..c69f9e945a 100644 --- a/bitbake/lib/toaster/toastergui/templates/layerdetails.html +++ b/bitbake/lib/toaster/toastergui/templates/layerdetails.html | |||
@@ -1,159 +1,505 @@ | |||
1 | {% extends "baseprojectpage.html" %} | 1 | {% extends "baseprojectpage.html" %} |
2 | {% load projecttags %} | 2 | {% load projecttags %} |
3 | {% load humanize %} | 3 | {% load humanize %} |
4 | 4 | {% load static %} | |
5 | {% block localbreadcrumb %} | 5 | {% block localbreadcrumb %} |
6 | <li>Layer Details</li> | 6 | <li><a href="{% url 'layers' %}">All Layers</a></li> |
7 | <li> | ||
8 | {{layerversion.layer.name}} ({{layerversion.commit|truncatechars:13}}) | ||
9 | </li> | ||
7 | {% endblock %} | 10 | {% endblock %} |
8 | |||
9 | {% block projectinfomain %} | 11 | {% block projectinfomain %} |
10 | <div class="page-header"> | 12 | |
11 | <h1>Layer Details</h1> | 13 | |
12 | </div> | 14 | <script src="{% static 'js/layerdetails.js' %}"></script> |
13 | 15 | <script> | |
14 | <div class="row-fluid span7 tabbable"> | 16 | |
15 | <ul class="nav nav-pills"> | 17 | $(document).ready(function (){ |
16 | <li class="active"> | 18 | var ctx = { |
17 | <a data-toggle="tab" href="#information">Layer details</a> | 19 | projectBuildUrl : "{% url 'xhr_build' %}", |
18 | </li> | 20 | layerDetailsUrl : "{% url 'layerdetails' %}", |
19 | <li> | 21 | projectPageUrl : "{% url 'project' project.id %}", |
20 | <a data-toggle="tab" href="#targets">Targets (0)</a> | 22 | xhrEditProjectUrl : "{% url 'xhr_projectedit' project.id %}", |
21 | </li> | 23 | xhrDataTypeaheadUrl : "{% url 'xhr_datatypeahead' %}", |
22 | <li> | 24 | xhrUpdateLayerUrl : "{% url 'xhr_updatelayer' %}", |
23 | <a data-toggle="tab" href="#machines">Machines (0)</a> | 25 | projectId : {{project.id}}, |
24 | </li> | 26 | numTargets : {{total_targets}}, |
25 | <li> | 27 | numMachines: {{machines|length}}, |
26 | <a data-toggle="tab" href="#classes">Classes (0)</a> | 28 | layerVersion : { |
27 | </li> | 29 | name : "{{layerversion.layer.name}}", |
28 | <li> | 30 | id : {{layerversion.id}}, |
29 | <a data-toggle="tab" href="#bbappends">bbappends (0)</a> | 31 | commit: "{{layerversion.commit}}", |
30 | </li> | 32 | inCurrentPrj : {{layer_in_project}}, |
31 | </ul> | 33 | url : "{% url 'layerdetails' layerversion.id %}", |
32 | <div class="tab-content"> | 34 | sourceId: {{layerversion.layer_source_id}}, |
33 | <div name="information" id="information" class="tab-pane active"> | 35 | } |
34 | <dl class="dl-horizontal"> | 36 | }; |
35 | <dt class=""> | 37 | |
36 | <i class="icon-question-sign get-help" title="Fetch/clone URL of the repository"></i> | 38 | try { |
37 | Repository URL | 39 | layerDetailsPageInit(ctx); |
38 | </dt> | 40 | } catch (e) { |
39 | <dd> | 41 | document.write("Sorry, An error has occurred loading this page"); |
40 | <form id="change-repo-form" class="control-group"> | 42 | console.warn(e); |
41 | <div class="input-append"> | 43 | } |
42 | <input type="text" class="input-xlarge" id="type-repo" value="{{layerversion.layer.vcs_url}}"> | 44 | }); |
43 | <button id="apply-change-repo" class="btn" type="button">Change</button> | 45 | </script> |
44 | <!--a href="#" id="cancel-change-repo" class="btn btn-link">Cancel</a--> | 46 | |
45 | </div> | 47 | {# If this is not an imported layer then hide the edit ui #} |
46 | <span class="help-block">Cloning this Git repository failed</span> | 48 | {% if layerversion.layer_source_id != 3 %} |
47 | </form> | 49 | <style> |
48 | </dd> | 50 | .icon-pencil { |
49 | <dt> | 51 | display:none; |
50 | <i class="icon-question-sign get-help" title="Subdirectory within the repository where the layer is located, if not in the root (usually only used if the repository contains more than one layer)"></i> | 52 | } |
51 | Repository subdirectory | 53 | .delete-current-value{ |
52 | </dt> | 54 | display: none; |
53 | <dd> | 55 | } |
54 | <span id="subdir">{{layerversion.dirpath}}</span> | 56 | li .icon-trash { |
55 | <i id="change-subdir" class="icon-pencil"></i> | 57 | display:none; |
56 | <i id="delete-subdir" class="icon-trash"></i> | 58 | } |
57 | <form id="change-subdir-form" style="display:none;"> | 59 | .add-deps { |
58 | <div class="input-append"> | 60 | display:none; |
59 | <input type="text" id="type-subdir" value="meta-acer"> | 61 | } |
60 | <button id="apply-change-subdir" class="btn" type="button">Change</button> | 62 | </style> |
61 | <a href="#" id="cancel-change-subdir" class="btn btn-link">Cancel</a> | 63 | {% endif %} |
62 | </div> | 64 | |
63 | </form> | 65 | {% include "layers_dep_modal.html" %} |
64 | </dd> | 66 | <div class="container-fluid top-padded"> |
65 | <dt>Brach, tag or commit</dt> | 67 | <div class="row-fluid"> |
66 | <dd> | 68 | <div class="span11"> |
67 | {{layerversion.up_branch.name}} | 69 | <div class="page-header"> |
68 | <i class="icon-pencil"></i> | 70 | <h1>{{layerversion.layer.name}} <small class="commit" data-toggle="tooltip" title="{{layerversion.commit}}">({{layerversion.commit|truncatechars:13}})</small></h1> |
69 | </dd> | 71 | </div> |
70 | <dt> | ||
71 | <i class="icon-question-sign get-help" title="The Yocto Project versions with which this layer is compatible. Currently Toaster supports Yocto Project 1.6 and 1.7"></i> | ||
72 | Yocto Project compatibility | ||
73 | </dt> | ||
74 | <dd> | ||
75 | <i class="icon-pencil"></i> | ||
76 | </dd> | ||
77 | <dt> | ||
78 | <i class="icon-question-sign get-help" title="Other layers this layer depends upon"></i> | ||
79 | Layer dependencies | ||
80 | </dt> | ||
81 | <dd> | ||
82 | <ul class="unstyled"> | ||
83 | {% for ld in layer.dependencies.all %} | ||
84 | <li> | ||
85 | <a href="#">openembedded core (meta)</a> | ||
86 | <i class="icon-trash"></i> | ||
87 | </li> | ||
88 | {% endfor %} | ||
89 | </ul> | ||
90 | <div class="input-append"> | ||
91 | <input type="text" autocomplete="off" data-minLength="1" data-autocomplete="off" | ||
92 | data-provide="typeahead" data-source=' | ||
93 | ' | ||
94 | placeholder="Type a layer name" id="layer-dependency"> | ||
95 | <a class="btn" type="button" id="add-layer-dependency" disabled> | ||
96 | Add layer | ||
97 | </a> | ||
98 | </div> | ||
99 | <span class="help-block">You can only add layers Toaster knows about</span> | ||
100 | </dd> | ||
101 | </dl> | ||
102 | </div> | ||
103 | <div name="targets" id="targets" class="tab-pane"> | ||
104 | <div class="alert alert-info"> | ||
105 | <strong>There is no target data for {{layerversion.layer.name}} ... yet</strong> <br /> | ||
106 | Toaster learns about layers as they are built. Once you have used {{layerversion.layer.name}} in a build, Toaster will show you | ||
107 | here the targets it provides. | ||
108 | </div> | ||
109 | </div> | ||
110 | <div name="machines" id="machines" class="tab-pane"> | ||
111 | <div class="alert alert-info"> | ||
112 | <strong>There is no machine data for {{layerversion.layer.name}} ... yet</strong> <br /> | ||
113 | Toaster learns about layers as they are built. Once you have used {{layerversion.layer.name}} in a build, Toaster will show you | ||
114 | here the machines it provides. | ||
115 | </div> | ||
116 | </div> | ||
117 | </div> | 72 | </div> |
118 | </div> | 73 | </div> |
119 | <div class="row span4 well"> | 74 | |
120 | <h2>About {{layerversion.layer.name}}</h2> | 75 | <div class="row-fluid"> |
121 | <dl> | 76 | <div class="span7"> |
122 | 77 | <div class="tabbable"> | |
123 | <dt> | 78 | <div class="alert alert-info lead" id="alert-area" style="display:none"> |
124 | Summary | 79 | <button type="button" class="close" id="dismiss-alert" data-dismiss="alert">×</button> |
125 | <i class="icon-question-sign get-help" title="One-line description of the layer"></i> | 80 | <span id="alert-msg"></span> |
126 | </dt> | 81 | <p style="margin-top:10px;"><a href="{% url 'project' project.id %}">Go to project configuration</a></p> |
127 | <dd> | 82 | </div> |
128 | <span >{{layerversion.layer.summary}}</span> | 83 | <ul class="nav nav-pills"> |
129 | <i class="icon-pencil"></i> | 84 | <li class="active"> |
130 | </dd> | 85 | <a data-toggle="tab" href="#information" id="details-tab">Layer details</a> |
131 | <!--form> | 86 | </li> |
132 | <textarea class="span12" rows="2"></textarea> | 87 | <li> |
133 | <button class="btn" type="button">Change</button> | 88 | <a data-toggle="tab" href="#targets" id="targets-tab">Targets ({{total_targets}})</a> |
134 | <a href="#" class="btn btn-link">Cancel</a> | 89 | </li> |
135 | </form--> | 90 | <li> |
136 | <dt> | 91 | <a data-toggle="tab" href="#machines" id="machines-tab">Machines ({{total_machines}})</a> |
137 | Description | 92 | </li> |
138 | </dt> | 93 | </ul> |
139 | <dd> | 94 | </div> |
140 | <span >{{layerversion.layer.description}}</span> | 95 | <div class="tab-content"> |
141 | <i class="icon-pencil"></i> | 96 | <span class="button-place"> |
142 | </dd> | 97 | {% if layer_in_project == 0 %} |
143 | <!--form> | 98 | <button id="add-remove-layer-btn" data-directive="add" class="btn btn-large btn-block"> |
144 | <textarea class="span12" rows="6"></textarea> | 99 | <span class="icon-plus"></span> |
145 | <button class="btn" type="button">Change</button> | 100 | Add the {{layerversion.layer.name}} layer to your project |
146 | <a href="#" class="btn btn-link">Cancel</a> | 101 | </button> |
147 | </form--> | 102 | {% else %} |
148 | <dt> | 103 | <button id="add-remove-layer-btn" data-directive="remove" class="btn btn-block btn-large btn-danger"> |
149 | Maintainer(s) | 104 | <span class="icon-trash"></span> |
150 | </dt> | 105 | Delete the {{layerversion.layer.name}} layer from your project |
151 | <dd> | 106 | </button> |
152 | <span class="muted">Not set</span> | 107 | {% endif %} |
153 | <i class="icon-pencil"></i> | 108 | </span> |
154 | </dd> | 109 | |
155 | </dl> | 110 | <!-- layer details pane --> |
156 | </div> | 111 | <div name="information" id="information" class="tab-pane active"> |
112 | <dl class="dl-horizontal"> | ||
113 | <dt class=""> | ||
114 | <i class="icon-question-sign get-help" title="Fetch/clone URL of the repository"></i> | ||
115 | Repository URL | ||
116 | </dt> | ||
117 | <dd> | ||
118 | <span class="current-value">{{layerversion.layer.vcs_url}}</span> | ||
119 | {% if layerversion.get_vcs_link_url %} | ||
120 | <a href="{{layerversion.get_vcs_link_url}}/" class="icon-share get-info"></a> | ||
121 | {% endif %} | ||
122 | <form id="change-repo-form" class="control-group" style="display:none"> | ||
123 | <div class="input-append"> | ||
124 | <input type="text" class="input-xlarge" value="{{layerversion.layer.vcs_url}}"> | ||
125 | <button data-layer-prop="vcs_url" class="btn change-btn" type="button">Save</button> | ||
126 | <a href="#" style="display:none" class="btn btn-link cancel">Cancel</a> | ||
127 | </div> | ||
128 | </form> | ||
129 | <i class="icon-pencil" ></i> | ||
130 | </dd> | ||
131 | <dt> | ||
132 | <i class="icon-question-sign get-help" title="Subdirectory within the repository where the layer is located, if not in the root (usually only used if the repository contains more than one layer)"></i> | ||
133 | Repository subdirectory | ||
134 | </dt> | ||
135 | <dd> | ||
136 | <span class="muted" style="display:none">Not set</span> | ||
137 | <span class="current-value">{{layerversion.dirpath}}</span> | ||
138 | {% if layerversion.get_vcs_dirpath_link_url %} | ||
139 | <a href="{{layerversion.get_vcs_dirpath_link_url}}" class="icon-share get-info"></a> | ||
140 | {% endif %} | ||
141 | <form id="change-subdir-form" style="display:none;"> | ||
142 | <div class="input-append"> | ||
143 | <input type="text" value="{{layerversion.dirpath}}"> | ||
144 | <button data-layer-prop="dirpath" class="btn change-btn" type="button">Save</button> | ||
145 | <a href="#" style="display:none" class="btn btn-link cancel">Cancel</a> | ||
146 | </div> | ||
147 | </form> | ||
148 | <i id="change-subdir" class="icon-pencil"></i> | ||
149 | <span class="icon-trash delete-current-value" data-toggle="tooltip" title="Delete"></span> | ||
150 | </dd> | ||
151 | <dt>Brach, tag or commit</dt> | ||
152 | <dd> | ||
153 | <span class="current-value">{{layerversion.commit}}</span> | ||
154 | <form style="display:none;"> | ||
155 | <div class="input-append"> | ||
156 | <input type="text" value="{{layerversion.commit}}"> | ||
157 | <button data-layer-prop="commit" class="btn change-btn" type="button">Save</button> | ||
158 | <a href="#" style="display:none" class="btn btn-link cancel">Cancel</a> | ||
159 | </div> | ||
160 | </form> | ||
161 | <i class="icon-pencil"></i> | ||
162 | </dd> | ||
163 | <dt> | ||
164 | <i class="icon-question-sign get-help" title="The Yocto Project versions with which this layer is compatible. Currently Toaster supports Yocto Project 1.6 and 1.7"></i> | ||
165 | Yocto Project compatibility | ||
166 | </dt> | ||
167 | <dd> | ||
168 | <span class="current-value">{{layerversion.up_branch.name}}</span> | ||
169 | <form style="display:none"> | ||
170 | <div class="input-append"> | ||
171 | <select name="projectversion" id="projectversion"> | ||
172 | {% for compat in yocto_compat %} | ||
173 | <option value="{{compat.id}}" {%if layerversion.up_branch.id == compat.id %} selected{%endif%}>{{compat.name}}</option> | ||
174 | {% endfor %} | ||
175 | </select> | ||
176 | <button data-layer-prop="up_branch" class="btn change-btn" type="button">Save</button> | ||
177 | <a href="#" style="display:none" class="btn btn-link cancel">Cancel</a> | ||
178 | </div> | ||
179 | </form> | ||
180 | <i class="icon-pencil"></i> | ||
181 | </dd> | ||
182 | <dt> | ||
183 | <i class="icon-question-sign get-help" title="Other layers this layer depends upon"></i> | ||
184 | Layer dependencies | ||
185 | </dt> | ||
186 | <dd> | ||
187 | <ul class="unstyled" id="layer-deps-list"> | ||
188 | {% for ld in layerversion.dependencies.all %} | ||
189 | <span class="current-value"> | ||
190 | <li data-layer-id="{{ld.depends_on.id}}"> | ||
191 | <!-- TODO use ld.depends_on.get_vcs_reference instead of commit --> | ||
192 | <a data-toggle="tooltip" title="{{ld.depends_on.layer.vcs_url}} | {{ld.depends_on.commit}}" href="{% url 'layerdetails' ld.depends_on.id %}">{{ld.depends_on.layer.name}}</a> | ||
193 | <span class="icon-trash " data-toggle="tooltip" title="Delete"></span> | ||
194 | </li> | ||
195 | </span> | ||
196 | {% endfor %} | ||
197 | </ul> | ||
198 | <div class="input-append add-deps"> | ||
199 | <input type="text" autocomplete="off" data-minLength="1" data-autocomplete="off" placeholder="Type a layer name" id="layer-dep-input"> | ||
200 | <a class="btn" type="button" id="add-layer-dependency-btn" disabled> | ||
201 | Add layer | ||
202 | </a> | ||
203 | </div> | ||
204 | <span class="help-block add-deps">You can only add layers Toaster knows about</span> | ||
205 | </dd> | ||
206 | </dl> | ||
207 | </div> | ||
208 | <!-- targets tab --> | ||
209 | <div name="targets" id="targets" class="tab-pane"> | ||
210 | {% if total_targets == 0 %} | ||
211 | <div class="alert alert-info"> | ||
212 | <strong>There is no target data for {{layerversion.layer.name}} ... yet</strong> <br /> | ||
213 | Toaster learns about layers as they are built. Once you have used {{layerversion.layer.name}} in a build, Toaster will show you | ||
214 | here the targets it provides. | ||
215 | </div> | ||
216 | {% else %} | ||
217 | |||
218 | <div class="row-fluid"> | ||
219 | |||
220 | {% if targets.paginator.count == 0 %} | ||
221 | <div class="alert"> | ||
222 | <h3>No targets found</h3> | ||
223 | {% endif %} | ||
224 | |||
225 | {# only show the search form if we have more than 10 results #} | ||
226 | {% if targets.paginator.count > 10 or request.GET.targets_search %} | ||
227 | {% if targets.paginator.count == 0 %} | ||
228 | <form class="input-append"> | ||
229 | {% else %} | ||
230 | <form class="navbar-search input-append pull-left"> | ||
231 | {% endif %} | ||
232 | |||
233 | <input type="text" id="target-search" name="targets_search" placeholder="Search targets" class="input-xlarge" value="{{request.GET.targets_search}}"> | ||
234 | {% if request.GET.targets_search %} | ||
235 | <a class="add-on btn" id="target-search-clear"> | ||
236 | <i class="icon-remove"></i> | ||
237 | </a> | ||
238 | {% endif %} | ||
239 | <button type="submit" class="btn">Search</button> | ||
240 | </form> | ||
241 | {% endif %} | ||
242 | |||
243 | {% if targets.paginator.count == 0 %} | ||
244 | <!-- end alert --> | ||
245 | </div> | ||
246 | <!-- end row-fluid --> | ||
247 | </div> | ||
248 | {% else %} | ||
249 | |||
250 | <div class="pull-right"> | ||
251 | <span class="help-inline" style="padding-top:5px;">Show rows:</span> | ||
252 | <select style="margin-top:5px;margin-bottom:0px;" class="pagesize"> | ||
253 | {% with "10 25 50 100 150" as list%} | ||
254 | {% for i in list.split %} | ||
255 | {% if request.session.limit == i %} | ||
256 | <option value="{{i}}" selected>{{i}}</option> | ||
257 | {% else %} | ||
258 | <option value="{{i}}">{{i}}</option> | ||
259 | {% endif %} | ||
260 | {% endfor %} | ||
261 | {% endwith %} | ||
262 | </select> | ||
263 | </div> | ||
264 | </div> | ||
265 | |||
266 | <table class="table table-bordered table-hover"> | ||
267 | <thead> | ||
268 | <tr> | ||
269 | <th> | ||
270 | <i class="icon-question-sign get-help" title="Information about a single piece of software, including where to download the source, configuration options, how to compile the source files and how to package the compiled output"></i> | ||
271 | Target | ||
272 | {% if request.GET.targets_search %} | ||
273 | <span class="badge badge-info">{{targets.paginator.count}}</span> | ||
274 | {% endif %} | ||
275 | </th> | ||
276 | <th> | ||
277 | <i class="icon-question-sign get-help" title="The recipe version and revision"></i> | ||
278 | Target version | ||
279 | </th> | ||
280 | <th class="span4">Description</th> | ||
281 | <th>Build target</th> | ||
282 | </tr> | ||
283 | </thead> | ||
284 | <tbody> | ||
285 | {% for target in targets %} | ||
286 | <tr> | ||
287 | <td> | ||
288 | {{target.name}} | ||
289 | {% if target.up_id %} | ||
290 | <a href="http://layers.openembedded.org/layerindex/recipe/{{target.up_id}}/" class="icon-share get-info"></a> | ||
291 | {% endif %} | ||
292 | </td> | ||
293 | <td>{{target.version}}</td> | ||
294 | <td>{{target.summary}}</td> | ||
295 | <td><button class="btn btn-block build-target-btn" data-target-name="{{target.name}}" {% if layer_in_project == 0 %}disabled="disabled"{% endif %} >Build Target</button></td> | ||
296 | </tr> | ||
297 | {% endfor %} | ||
298 | </tbody> | ||
299 | </table> | ||
300 | |||
301 | <!-- Show pagination controls --> | ||
302 | <div class="pagination"> | ||
303 | <ul> | ||
304 | {%if targets.has_previous %} | ||
305 | <li><a href="?tpage={{targets.previous_page_number}}{{request.GET.limit}}#targets">«</a></li> | ||
306 | {%else%} | ||
307 | <li class="disabled"><a href="#">«</a></li> | ||
308 | {%endif%} | ||
309 | {% for i in targets.paginator.page_range %} | ||
310 | <li {%if i == targets.number %} class="active" {%endif%}><a href="?tpage={{i}}#targets">{{i}}</a></li> | ||
311 | {% endfor %} | ||
312 | {%if targets.has_next%} | ||
313 | <li><a href="?tpage={{targets.next_page_number}}#targets">»</a></li> | ||
314 | {%else%} | ||
315 | <li class="disabled"><a href="#">»</a></li> | ||
316 | {%endif%} | ||
317 | </ul> | ||
318 | <div class="pull-right"> | ||
319 | <span class="help-inline" style="padding-top:5px;">Show rows:</span> | ||
320 | <select style="margin-top:5px;margin-bottom:0px;" class="pagesize"> | ||
321 | {% with "10 25 50 100 150" as list%} | ||
322 | {% for i in list.split %} | ||
323 | {% if request.session.limit == i %} | ||
324 | <option value="{{i}}" selected>{{i}}</option> | ||
325 | {% else %} | ||
326 | <option value="{{i}}">{{i}}</option> | ||
327 | {% endif %} | ||
328 | {% endfor %} | ||
329 | {% endwith %} | ||
330 | </select> | ||
331 | </div> | ||
332 | </div> | ||
333 | {% endif %} | ||
334 | {% endif %} | ||
335 | </div> | ||
336 | |||
337 | |||
338 | <div name="machines" id="machines" class="tab-pane"> | ||
339 | {% if total_machines == 0 %} | ||
340 | <div class="alert alert-info"> | ||
341 | <strong>There is no machine data for {{layerversion.layer.name}} ... yet</strong> <br /> | ||
342 | Toaster learns about layers as they are built. Once you have used {{layerversion.layer.name}} in a build, Toaster will show you | ||
343 | here the machines it provides. | ||
344 | </div> | ||
345 | {% else %} | ||
346 | |||
347 | <div class="row-fluid"> | ||
348 | |||
349 | {% if machines.paginator.count == 0 %} | ||
350 | <div class="alert"> | ||
351 | <h3>No machines found</h3> | ||
352 | {% endif %} | ||
353 | |||
354 | {# only show the search form if we have more than 10 results #} | ||
355 | {% if machines.paginator.count > 10 or request.GET.machines_search %} | ||
356 | {% if machines.paginator.count == 0 %} | ||
357 | <form class="input-append"> | ||
358 | {% else %} | ||
359 | <form class="navbar-search input-append pull-left"> | ||
360 | {% endif %} | ||
361 | |||
362 | <input type="text" id="machine-search" name="machines_search" placeholder="Search machines" class="input-xlarge" value="{{request.GET.machines_search}}"> | ||
363 | {% if request.GET.machines_search %} | ||
364 | <a class="add-on btn" id="machine-search-clear"> | ||
365 | <i class="icon-remove"></i> | ||
366 | </a> | ||
367 | {% endif %} | ||
368 | <button type="submit" class="btn">Search</button> | ||
369 | </form> | ||
370 | {% endif %} | ||
371 | |||
372 | {% if machines.paginator.count == 0 %} | ||
373 | <!-- end alert --> | ||
374 | </div> | ||
375 | <!-- end row-fluid --> | ||
376 | </div> | ||
377 | {% else %} | ||
378 | |||
379 | <div class="pull-right"> | ||
380 | <span class="help-inline" style="padding-top:5px;">Show rows:</span> | ||
381 | <select style="margin-top:5px;margin-bottom:0px;" class="pagesize"> | ||
382 | {% with "10 25 50 100 150" as list%} | ||
383 | {% for i in list.split %} | ||
384 | {% if request.session.limit == i %} | ||
385 | <option value="{{i}}" selected>{{i}}</option> | ||
386 | {% else %} | ||
387 | <option value="{{i}}">{{i}}</option> | ||
388 | {% endif %} | ||
389 | {% endfor %} | ||
390 | {% endwith %} | ||
391 | </select> | ||
392 | </div> | ||
393 | </div> | ||
394 | |||
395 | <table class="table table-bordered table-hover"> | ||
396 | <thead> | ||
397 | <tr> | ||
398 | <th> | ||
399 | <i class="icon-question-sign get-help" title="The machine is the hardware for which you are building"></i> | ||
400 | Machine | ||
401 | {% if request.GET.machines_search %} | ||
402 | <span class="badge badge-info">{{machines.paginator.count}}</span> | ||
403 | {% endif %} | ||
404 | </th> | ||
405 | <th>Description</th> | ||
406 | <th>Select machine</th> | ||
407 | </tr> | ||
408 | </thead> | ||
409 | <tbody> | ||
410 | {% for machine in machines %} | ||
411 | <tr> | ||
412 | <td>{{machine.name}}</td> | ||
413 | <td>{{machine.description}}</td> | ||
414 | <td><button class="btn btn-block select-machine-btn" data-machine-name="{{machine.name}}" {% if layer_in_project == 0 %}disabled="disabled"{% endif %}}>Select machine</button></td> | ||
415 | </tr> | ||
416 | {% endfor %} | ||
417 | </tbody> | ||
418 | </table> | ||
419 | |||
420 | <!-- Show pagination controls --> | ||
421 | <div class="pagination"> | ||
422 | <ul> | ||
423 | {%if machines.has_previous %} | ||
424 | <li><a href="?mpage={{machines.previous_page_number}}{{request.GET.limit}}#machines">«</a></li> | ||
425 | {%else%} | ||
426 | <li class="disabled"><a href="#">«</a></li> | ||
427 | {%endif%} | ||
428 | {% for i in machines.paginator.page_range %} | ||
429 | <li {%if i == machines.number %} class="active" {%endif%}><a href="?mpage={{i}}#machines">{{i}}</a></li> | ||
430 | {% endfor %} | ||
431 | {%if machines.has_next%} | ||
432 | <li><a href="?mpage={{machines.next_page_number}}#machines">»</a></li> | ||
433 | {%else%} | ||
434 | <li class="disabled"><a href="#">»</a></li> | ||
435 | {%endif%} | ||
436 | </ul> | ||
437 | <div class="pull-right"> | ||
438 | <span class="help-inline" style="padding-top:5px;">Show rows:</span> | ||
439 | <select style="margin-top:5px;margin-bottom:0px;" class="pagesize"> | ||
440 | {% with "10 25 50 100 150" as list%} | ||
441 | {% for i in list.split %} | ||
442 | {% if request.session.limit == i %} | ||
443 | <option value="{{i}}" selected>{{i}}</option> | ||
444 | {% else %} | ||
445 | <option value="{{i}}">{{i}}</option> | ||
446 | {% endif %} | ||
447 | {% endfor %} | ||
448 | {% endwith %} | ||
449 | </select> | ||
450 | </div> | ||
451 | </div> | ||
452 | {% endif %} | ||
453 | {% endif %} | ||
454 | </div> | ||
455 | </div> | ||
456 | </div> | ||
457 | <div class="row span4 well"> | ||
458 | <h2>About {{layerversion.layer.name}}</h2> | ||
459 | <dl> | ||
460 | |||
461 | <dt> | ||
462 | Summary | ||
463 | <i class="icon-question-sign get-help" title="One-line description of the layer"></i> | ||
464 | </dt> | ||
465 | <dd> | ||
466 | <span class="muted" style="display:none">Not set</span> | ||
467 | <span class="current-value">{{layerversion.layer.summary}}</span> | ||
468 | <form style="display:none; margin-bottom:20px"> | ||
469 | <textarea class="span12" rows="2">{% if layerversion.layer.summary %}{{layerversion.layer.summary}}{% endif %}</textarea> | ||
470 | <button class="btn change-btn" data-layer-prop="summary" type="button">Save</button> | ||
471 | <a href="#" class="btn btn-link cancel">Cancel</a> | ||
472 | </form> | ||
473 | <i class="icon-pencil"></i> | ||
474 | <span class="icon-trash delete-current-value" data-toggle="tooltip" title="Delete"></span> | ||
475 | </dd> | ||
476 | <dt> | ||
477 | Description | ||
478 | </dt> | ||
479 | <dd> | ||
480 | <span class="muted" style="display:none">Not set</span> | ||
481 | <span class="current-value">{{layerversion.layer.description}}</span> | ||
482 | <form style="display:none; margin-bottom:20px"> | ||
483 | <textarea class="span12" rows="6">{% if layerversion.layer.description %}{{layerversion.layer.description}}{% endif %}</textarea> | ||
484 | <button class="btn change-btn" data-layer-prop="description" type="button" >Save</button> | ||
485 | <a href="#" class="btn btn-link cancel">Cancel</a> | ||
486 | </form> | ||
487 | <i class="icon-pencil"></i> | ||
488 | <span class="icon-trash delete-current-value" data-toggle="tooltip" title="Delete"></span> | ||
489 | </dd> | ||
490 | </dd> | ||
491 | {% if layerversion.layer.up_id %} | ||
492 | <dt>Layer index</dt> | ||
493 | <dd> | ||
494 | <a href="http://layers.openembedded.org/layerindex/branch/{{layerversion.up_branch.name}}/layer/{{layerversion.layer.name}}"/>layer index link</a> | ||
495 | |||
496 | </dd> | ||
497 | {% endif %} | ||
157 | 498 | ||
499 | </dl> | ||
500 | </div> | ||
158 | 501 | ||
502 | </div> | ||
503 | </div> | ||
504 | </div> | ||
159 | {% endblock %} | 505 | {% endblock %} |
diff --git a/bitbake/lib/toaster/toastergui/templates/layers_dep_modal.html b/bitbake/lib/toaster/toastergui/templates/layers_dep_modal.html index b03fd0b218..8222027d4f 100644 --- a/bitbake/lib/toaster/toastergui/templates/layers_dep_modal.html +++ b/bitbake/lib/toaster/toastergui/templates/layers_dep_modal.html | |||
@@ -18,7 +18,16 @@ | |||
18 | </div> | 18 | </div> |
19 | 19 | ||
20 | <script> | 20 | <script> |
21 | /* projectId: current project | ||
22 | * layer: Object representing the parent layer { id: .. name: ... url } | ||
23 | * dependencies: array of dependency layer objects { id: .. name: ..} | ||
24 | * title: optional override for title | ||
25 | * body: optional override for body | ||
26 | * addToProject: Whether to add layers to project on accept | ||
27 | * successAdd: function to run on success | ||
28 | */ | ||
21 | function show_layer_deps_modal(projectId, layer, dependencies, title, body, addToProject, successAdd) { | 29 | function show_layer_deps_modal(projectId, layer, dependencies, title, body, addToProject, successAdd) { |
30 | |||
22 | // update layer name | 31 | // update layer name |
23 | if (title) { | 32 | if (title) { |
24 | $('#dependencies_modal #title').text(title); | 33 | $('#dependencies_modal #title').text(title); |
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py index 6e1b0ab913..5c969f814c 100644 --- a/bitbake/lib/toaster/toastergui/urls.py +++ b/bitbake/lib/toaster/toastergui/urls.py | |||
@@ -94,6 +94,7 @@ urlpatterns = patterns('toastergui.views', | |||
94 | 94 | ||
95 | url(r'^xhr_datatypeahead/$', 'xhr_datatypeahead', name='xhr_datatypeahead'), | 95 | url(r'^xhr_datatypeahead/$', 'xhr_datatypeahead', name='xhr_datatypeahead'), |
96 | url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'), | 96 | url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'), |
97 | url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'), | ||
97 | 98 | ||
98 | 99 | ||
99 | # default redirection | 100 | # default redirection |
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 8c21ca48e0..7a9d662b31 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
@@ -2336,6 +2336,50 @@ if toastermain.settings.MANAGED: | |||
2336 | 2336 | ||
2337 | return HttpResponse(jsonfilter({"error": "ok", "imported_layer" : { "name" : layer.name, "id": layer_version.id }, "deps_added": layers_added }), content_type = "application/json") | 2337 | return HttpResponse(jsonfilter({"error": "ok", "imported_layer" : { "name" : layer.name, "id": layer_version.id }, "deps_added": layers_added }), content_type = "application/json") |
2338 | 2338 | ||
2339 | def xhr_updatelayer(request): | ||
2340 | |||
2341 | def error_response(error): | ||
2342 | return HttpResponse(jsonfilter({"error": error}), content_type = "application/json") | ||
2343 | |||
2344 | if not request.POST.has_key("layer_version_id"): | ||
2345 | return error_response("Please specify a layer version id") | ||
2346 | try: | ||
2347 | layer_version_id = request.POST["layer_version_id"] | ||
2348 | layer_version = Layer_Version.objects.get(id=layer_version_id) | ||
2349 | except: | ||
2350 | return error_response("Cannot find layer to update") | ||
2351 | |||
2352 | |||
2353 | if request.POST.has_key("vcs_url"): | ||
2354 | layer_version.layer.vcs_url = request.POST["vcs_url"] | ||
2355 | if request.POST.has_key("dirpath"): | ||
2356 | layer_version.dirpath = request.POST["dirpath"] | ||
2357 | if request.POST.has_key("commit"): | ||
2358 | layer_version.commit = request.POST["commit"] | ||
2359 | if request.POST.has_key("up_branch"): | ||
2360 | layer_version.up_branch_id = int(request.POST["up_branch"]) | ||
2361 | |||
2362 | if request.POST.has_key("add_dep"): | ||
2363 | lvd = LayerVersionDependency(layer_version=layer_version, depends_on_id=request.POST["add_dep"]) | ||
2364 | lvd.save() | ||
2365 | |||
2366 | if request.POST.has_key("rm_dep"): | ||
2367 | rm_dep = LayerVersionDependency.objects.get(layer_version=layer_version, depends_on_id=request.POST["rm_dep"]) | ||
2368 | rm_dep.delete() | ||
2369 | |||
2370 | if request.POST.has_key("summary"): | ||
2371 | layer_version.layer.summary = request.POST["summary"] | ||
2372 | if request.POST.has_key("description"): | ||
2373 | layer_version.layer.description = request.POST["description"] | ||
2374 | |||
2375 | try: | ||
2376 | layer_version.layer.save() | ||
2377 | layer_version.save() | ||
2378 | except: | ||
2379 | return error_response("Could not update layer version entry") | ||
2380 | |||
2381 | return HttpResponse(jsonfilter({"error": "ok",}), content_type = "application/json") | ||
2382 | |||
2339 | 2383 | ||
2340 | 2384 | ||
2341 | def importlayer(request): | 2385 | def importlayer(request): |
@@ -2439,8 +2483,53 @@ if toastermain.settings.MANAGED: | |||
2439 | 2483 | ||
2440 | def layerdetails(request, layerid): | 2484 | def layerdetails(request, layerid): |
2441 | template = "layerdetails.html" | 2485 | template = "layerdetails.html" |
2486 | limit = 10 | ||
2487 | |||
2488 | if request.GET.has_key("limit"): | ||
2489 | request.session['limit'] = request.GET['limit'] | ||
2490 | |||
2491 | if request.session.has_key('limit'): | ||
2492 | limit = request.session['limit'] | ||
2493 | |||
2494 | layer_version = Layer_Version.objects.get(pk = layerid) | ||
2495 | |||
2496 | # Targets tab query functionality | ||
2497 | if request.GET.has_key('targets_search'): | ||
2498 | targets = Paginator(Recipe.objects.filter(layer_version=layer_version,name__icontains=request.GET['targets_search']).order_by("name"), limit) | ||
2499 | else: | ||
2500 | targets = Paginator(Recipe.objects.filter(layer_version=layer_version).order_by("name"), limit) | ||
2501 | |||
2502 | if request.GET.has_key("tpage"): | ||
2503 | try: | ||
2504 | targets = targets.page(request.GET['tpage']) | ||
2505 | except EmptyPage: | ||
2506 | targets = targets.page(targets.num_pages) | ||
2507 | else: | ||
2508 | targets = targets.page(1) | ||
2509 | |||
2510 | # Machines tab query functionality | ||
2511 | if request.GET.has_key('machines_search'): | ||
2512 | machines = Paginator(Machine.objects.filter(layer_version=layer_version,name__icontains=request.GET['machines_search']).order_by("name"), limit) | ||
2513 | else: | ||
2514 | machines = Paginator(Machine.objects.filter(layer_version=layer_version).order_by("name"), limit) | ||
2515 | |||
2516 | if request.GET.has_key("mpage"): | ||
2517 | try: | ||
2518 | machines = machines.page(request.GET['mpage']) | ||
2519 | except EmptyPage: | ||
2520 | machines = machines.page(machines.num_pages) | ||
2521 | else: | ||
2522 | machines = machines.page(1) | ||
2523 | |||
2442 | context = { | 2524 | context = { |
2443 | 'layerversion': Layer_Version.objects.get(pk = layerid), | 2525 | 'layerversion': layer_version, |
2526 | 'layer_in_project' : ProjectLayer.objects.filter(project_id=request.session['project_id'],layercommit=layerid).count(), | ||
2527 | 'yocto_compat': Branch.objects.filter(layer_source=layer_version.layer_source), | ||
2528 | 'machines': machines, | ||
2529 | 'targets': targets, | ||
2530 | 'total_targets': Recipe.objects.filter(layer_version=layer_version).count(), | ||
2531 | |||
2532 | 'total_machines': Machine.objects.filter(layer_version=layer_version).count(), | ||
2444 | } | 2533 | } |
2445 | return render(request, template, context) | 2534 | return render(request, template, context) |
2446 | 2535 | ||
@@ -2972,3 +3061,6 @@ else: | |||
2972 | 3061 | ||
2973 | def xhr_importlayer(request): | 3062 | def xhr_importlayer(request): |
2974 | raise Exception("page not available in interactive mode") | 3063 | raise Exception("page not available in interactive mode") |
3064 | |||
3065 | def xhr_updatelayer(request): | ||
3066 | raise Exception("page not available in interactive mode") | ||