diff options
Diffstat (limited to 'bitbake')
10 files changed, 119 insertions, 76 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/js/base.js b/bitbake/lib/toaster/toastergui/static/js/base.js index ccc23e0e60..9424b6c328 100644 --- a/bitbake/lib/toaster/toastergui/static/js/base.js +++ b/bitbake/lib/toaster/toastergui/static/js/base.js | |||
@@ -15,20 +15,21 @@ function basePageInit (ctx) { | |||
15 | 15 | ||
16 | /* Hide the change project icon when there is only one project */ | 16 | /* Hide the change project icon when there is only one project */ |
17 | if (ctx.numProjects == 1){ | 17 | if (ctx.numProjects == 1){ |
18 | $('#project .icon-pencil').hide(); | 18 | $('#project .icon-pencil').hide(); |
19 | } | 19 | } |
20 | 20 | ||
21 | newBuildButton.show().removeAttr("disabled"); | 21 | newBuildButton.show().removeAttr("disabled"); |
22 | 22 | ||
23 | |||
23 | _checkProjectBuildable() | 24 | _checkProjectBuildable() |
24 | _setupNewBuildButton(); | 25 | _setupNewBuildButton(); |
25 | 26 | ||
26 | 27 | ||
27 | function _checkProjectBuildable(){ | 28 | function _checkProjectBuildable(){ |
28 | if (currentProjectId == undefined) | 29 | if (libtoaster.ctx.projectId == undefined) |
29 | return; | 30 | return; |
30 | 31 | ||
31 | libtoaster.getProjectInfo(ctx.projectInfoUrl, currentProjectId, | 32 | libtoaster.getProjectInfo(ctx.projectInfoUrl, libtoaster.ctx.projectId, |
32 | function(data){ | 33 | function(data){ |
33 | if (data.machine.name == undefined || data.layers.length == 0) { | 34 | if (data.machine.name == undefined || data.layers.length == 0) { |
34 | /* we can't build anything with out a machine and some layers */ | 35 | /* we can't build anything with out a machine and some layers */ |
@@ -53,18 +54,13 @@ function basePageInit (ctx) { | |||
53 | /* If we don't have a current project then present the set project | 54 | /* If we don't have a current project then present the set project |
54 | * form. | 55 | * form. |
55 | */ | 56 | */ |
56 | if (currentProjectId == undefined) { | 57 | if (libtoaster.ctx.projectId == undefined) { |
57 | $('#change-project-form').show(); | 58 | $('#change-project-form').show(); |
58 | $('#project .icon-pencil').hide(); | 59 | $('#project .icon-pencil').hide(); |
59 | } | 60 | } |
60 | 61 | ||
61 | libtoaster.makeTypeahead(newBuildTargetInput, { type : "targets", project_id: currentProjectId }, function(item){ | ||
62 | /* successfully selected a target */ | ||
63 | selectedTarget = item; | ||
64 | }); | ||
65 | 62 | ||
66 | 63 | libtoaster.makeTypeahead(newBuildProjectInput, libtoaster.ctx.projectsUrl, { format : "json" }, function(item){ | |
67 | libtoaster.makeTypeahead(newBuildProjectInput, { type : "projects" }, function(item){ | ||
68 | /* successfully selected a project */ | 64 | /* successfully selected a project */ |
69 | newBuildProjectSaveBtn.removeAttr("disabled"); | 65 | newBuildProjectSaveBtn.removeAttr("disabled"); |
70 | selectedProject = item; | 66 | selectedProject = item; |
@@ -93,20 +89,40 @@ function basePageInit (ctx) { | |||
93 | if (!selectedTarget) | 89 | if (!selectedTarget) |
94 | selectedTarget = { name: newBuildTargetInput.val() }; | 90 | selectedTarget = { name: newBuildTargetInput.val() }; |
95 | /* fire and forget */ | 91 | /* fire and forget */ |
96 | libtoaster.startABuild(ctx.projectBuildUrl, currentProjectId, selectedTarget.name, null, null); | 92 | libtoaster.startABuild(ctx.projectBuildUrl, libtoaster.ctx.projectId, selectedTarget.name, null, null); |
97 | window.location.replace(ctx.projectBasePageUrl+currentProjectId); | 93 | window.location.replace(libtoaster.ctx.projectPageUrl); |
98 | }); | 94 | }); |
99 | 95 | ||
100 | newBuildProjectSaveBtn.click(function() { | 96 | newBuildProjectSaveBtn.click(function() { |
101 | currentProjectId = selectedProject.id | 97 | libtoaster.ctx.projectId = selectedProject.pk |
102 | /* Update the typeahead project_id paramater */ | 98 | /* Update the typeahead project_id paramater */ |
103 | _checkProjectBuildable(); | 99 | _checkProjectBuildable(); |
104 | newBuildTargetInput.data('typeahead').options.xhrParams.project_id = currentProjectId; | ||
105 | newBuildTargetInput.val(""); | ||
106 | 100 | ||
107 | $("#new-build-button #project a").text(selectedProject.name).attr('href', ctx.projectBasePageUrl+currentProjectId); | 101 | /* we set the effective context of the page to the currently selected project */ |
108 | $("#new-build-button .alert a").attr('href', ctx.projectBasePageUrl+currentProjectId); | 102 | /* TBD: do we override even if we already have a context project ?? */ |
103 | /* TODO: replace global library context with references to the "selected" project */ | ||
104 | libtoaster.ctx.projectPageUrl = selectedProject.projectPageUrl; | ||
105 | libtoaster.ctx.xhrProjectEditUrl = selectedProject.xhrProjectEditUrl; | ||
106 | libtoaster.ctx.projectName = selectedProject.name; | ||
107 | libtoaster.ctx.projectId = selectedProject.id; | ||
108 | |||
109 | ctx.projectBuildUrl = selectedProject.projectBuildUrl; | ||
110 | |||
111 | /* we can create a target typeahead only after we have a project selected */ | ||
112 | newBuildTargetInput.prop("disabled", false); | ||
113 | newBuildTargetBuildBtn.prop("disabled", false); | ||
114 | |||
115 | libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.xhrProjectDataTypeaheadUrl, { type : "targets" }, function(item){ | ||
116 | /* successfully selected a target */ | ||
117 | selectedTarget = item; | ||
118 | }); | ||
119 | |||
120 | newBuildTargetInput.val(""); | ||
109 | 121 | ||
122 | /* set up new form aspect */ | ||
123 | $("#new-build-button #project a").text(selectedProject.name).attr('href', libtoaster.ctx.projectPageUrl); | ||
124 | $("#new-build-button .alert a").attr('href', libtoaster.ctx.projectPageUrl); | ||
125 | $("#project .icon-pencil").show(); | ||
110 | 126 | ||
111 | $("#change-project-form").slideUp({ 'complete' : function() { | 127 | $("#change-project-form").slideUp({ 'complete' : function() { |
112 | $("#new-build-button #project").show(); | 128 | $("#new-build-button #project").show(); |
@@ -116,6 +132,7 @@ function basePageInit (ctx) { | |||
116 | $('#new-build-button #project .icon-pencil').click(function() { | 132 | $('#new-build-button #project .icon-pencil').click(function() { |
117 | newBuildProjectSaveBtn.attr("disabled", "disabled"); | 133 | newBuildProjectSaveBtn.attr("disabled", "disabled"); |
118 | newBuildProjectInput.val($("#new-build-button #project a").text()); | 134 | newBuildProjectInput.val($("#new-build-button #project a").text()); |
135 | $("#cancel-change-project").show(); | ||
119 | $(this).parent().hide(); | 136 | $(this).parent().hide(); |
120 | $("#change-project-form").slideDown(); | 137 | $("#change-project-form").slideDown(); |
121 | }); | 138 | }); |
diff --git a/bitbake/lib/toaster/toastergui/static/js/importlayer.js b/bitbake/lib/toaster/toastergui/static/js/importlayer.js index 875cc342b8..beb2ede3dc 100644 --- a/bitbake/lib/toaster/toastergui/static/js/importlayer.js +++ b/bitbake/lib/toaster/toastergui/static/js/importlayer.js | |||
@@ -18,7 +18,7 @@ function importLayerPageInit (ctx) { | |||
18 | 18 | ||
19 | $("#new-project-button").hide(); | 19 | $("#new-project-button").hide(); |
20 | 20 | ||
21 | libtoaster.makeTypeahead(layerDepInput, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" }, function(item){ | 21 | libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" }, function(item){ |
22 | currentLayerDepSelection = item; | 22 | currentLayerDepSelection = item; |
23 | 23 | ||
24 | layerDepBtn.removeAttr("disabled"); | 24 | layerDepBtn.removeAttr("disabled"); |
@@ -28,7 +28,7 @@ function importLayerPageInit (ctx) { | |||
28 | /* We automatically add "openembedded-core" layer for convenience as a | 28 | /* We automatically add "openembedded-core" layer for convenience as a |
29 | * dependency as pretty much all layers depend on this one | 29 | * dependency as pretty much all layers depend on this one |
30 | */ | 30 | */ |
31 | $.getJSON(libtoaster.ctx.xhrDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" , value: "openembedded-core" }, function(layer) { | 31 | $.getJSON(libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" , value: "openembedded-core" }, function(layer) { |
32 | if (layer.list.length == 1) { | 32 | if (layer.list.length == 1) { |
33 | currentLayerDepSelection = layer.list[0]; | 33 | currentLayerDepSelection = layer.list[0]; |
34 | layerDepBtn.click(); | 34 | layerDepBtn.click(); |
@@ -211,7 +211,7 @@ function importLayerPageInit (ctx) { | |||
211 | var name = $(this).val(); | 211 | var name = $(this).val(); |
212 | 212 | ||
213 | /* Check if the layer name exists */ | 213 | /* Check if the layer name exists */ |
214 | $.getJSON(libtoaster.ctx.xhrDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" , value: name }, function(layer) { | 214 | $.getJSON(libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" , value: name }, function(layer) { |
215 | if (layer.list.length > 0) { | 215 | if (layer.list.length > 0) { |
216 | for (var i in layer.list){ | 216 | for (var i in layer.list){ |
217 | if (layer.list[i].name == name) { | 217 | if (layer.list[i].name == name) { |
diff --git a/bitbake/lib/toaster/toastergui/static/js/layerdetails.js b/bitbake/lib/toaster/toastergui/static/js/layerdetails.js index 3746ea26e3..8e14b8f277 100644 --- a/bitbake/lib/toaster/toastergui/static/js/layerdetails.js +++ b/bitbake/lib/toaster/toastergui/static/js/layerdetails.js | |||
@@ -9,7 +9,7 @@ function layerDetailsPageInit (ctx) { | |||
9 | var addRmLayerBtn = $("#add-remove-layer-btn"); | 9 | var addRmLayerBtn = $("#add-remove-layer-btn"); |
10 | 10 | ||
11 | /* setup the dependencies typeahead */ | 11 | /* setup the dependencies typeahead */ |
12 | libtoaster.makeTypeahead(layerDepInput, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" }, function(item){ | 12 | libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" }, function(item){ |
13 | currentLayerDepSelection = item; | 13 | currentLayerDepSelection = item; |
14 | 14 | ||
15 | layerDepBtn.removeAttr("disabled"); | 15 | layerDepBtn.removeAttr("disabled"); |
diff --git a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js index 99e1f03095..72fb0a93f5 100644 --- a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js +++ b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js | |||
@@ -10,16 +10,16 @@ var libtoaster = (function (){ | |||
10 | * xhrUrl: the url to get the JSON from expects JSON in the form: | 10 | * xhrUrl: the url to get the JSON from expects JSON in the form: |
11 | * { "list": [ { "name": "test", "detail" : "a test thing" }, .... ] } | 11 | * { "list": [ { "name": "test", "detail" : "a test thing" }, .... ] } |
12 | * xhrParams: the data/parameters to pass to the getJSON url e.g. | 12 | * xhrParams: the data/parameters to pass to the getJSON url e.g. |
13 | * { 'type' : 'projects' } the text typed will be passed as 'value'. | 13 | * { 'type' : 'projects' } the text typed will be passed as 'search'. |
14 | * selectedCB: function to call once an item has been selected one | 14 | * selectedCB: function to call once an item has been selected one |
15 | * arg of the item. | 15 | * arg of the item. |
16 | */ | 16 | */ |
17 | function _makeTypeahead (jQElement, xhrParams, selectedCB) { | 17 | function _makeTypeahead (jQElement, xhrUrl, xhrParams, selectedCB) { |
18 | 18 | ||
19 | jQElement.typeahead({ | 19 | jQElement.typeahead({ |
20 | source: function(query, process){ | 20 | source: function(query, process){ |
21 | xhrParams.value = query; | 21 | xhrParams.search = query; |
22 | $.getJSON(libtoaster.ctx.xhrDataTypeaheadUrl, this.options.xhrParams, function(data){ | 22 | $.getJSON(xhrUrl, this.options.xhrParams, function(data){ |
23 | if (data.error !== "ok") { | 23 | if (data.error !== "ok") { |
24 | console.log("Error getting data from server "+data.error); | 24 | console.log("Error getting data from server "+data.error); |
25 | return; | 25 | return; |
@@ -41,7 +41,7 @@ var libtoaster = (function (){ | |||
41 | return $('<span></span>').text(item.name).get(0); | 41 | return $('<span></span>').text(item.name).get(0); |
42 | }, | 42 | }, |
43 | sorter: function (items) { return items; }, | 43 | sorter: function (items) { return items; }, |
44 | xhrUrl: libtoaster.ctx.xhrDataTypeaheadUrl, | 44 | xhrUrl: xhrUrl, |
45 | xhrParams: xhrParams, | 45 | xhrParams: xhrParams, |
46 | }); | 46 | }); |
47 | 47 | ||
@@ -172,7 +172,7 @@ var libtoaster = (function (){ | |||
172 | 172 | ||
173 | function _getLayerDepsForProject(projectId, layerId, onSuccess, onFail){ | 173 | function _getLayerDepsForProject(projectId, layerId, onSuccess, onFail){ |
174 | /* Check for dependencies not in the current project */ | 174 | /* Check for dependencies not in the current project */ |
175 | $.getJSON(libtoaster.ctx.xhrDataTypeaheadUrl, | 175 | $.getJSON(libtoaster.ctx.xhrProjectDataTypeaheadUrl, |
176 | { type: 'layerdeps', 'value': layerId , project_id: projectId }, | 176 | { type: 'layerdeps', 'value': layerId , project_id: projectId }, |
177 | function(data) { | 177 | function(data) { |
178 | if (data.error != "ok") { | 178 | if (data.error != "ok") { |
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html index 230dee49d6..e10dc11673 100644 --- a/bitbake/lib/toaster/toastergui/templates/base.html +++ b/bitbake/lib/toaster/toastergui/templates/base.html | |||
@@ -31,11 +31,19 @@ | |||
31 | projectId : {{project.id|default:'undefined'}}, | 31 | projectId : {{project.id|default:'undefined'}}, |
32 | jsUrl : "{% static 'js/' %}", | 32 | jsUrl : "{% static 'js/' %}", |
33 | htmlUrl : "{% static 'html/' %}", | 33 | htmlUrl : "{% static 'html/' %}", |
34 | projectsUrl : "{% url 'all-projects' %}", | ||
34 | {% if project.id %} | 35 | {% if project.id %} |
35 | xhrDataTypeaheadUrl : "{% url 'xhr_datatypeahead' project.id %}", | 36 | xhrProjectDataTypeaheadUrl : "{% url 'xhr_datatypeahead' project.id %}", |
36 | xhrProjectEditUrl : "{% url 'xhr_projectedit' project.id %}", | 37 | xhrProjectEditUrl : "{% url 'xhr_projectedit' project.id %}", |
37 | projectPageUrl : "{% url 'project' project.id %}", | 38 | projectPageUrl : "{% url 'project' project.id %}", |
38 | projectName : "{{project.name}}", | 39 | projectName : "{{project.name}}", |
40 | projectId : {{project.id}}, | ||
41 | {% else %} | ||
42 | xhrProjectDataTypeaheadUrl : undefined, | ||
43 | xhrProjectEditUrl : undefined, | ||
44 | projectPageUrl : undefined, | ||
45 | projectName : undefined, | ||
46 | projectId : undefined, | ||
39 | {% endif %} | 47 | {% endif %} |
40 | }; | 48 | }; |
41 | </script> | 49 | </script> |
@@ -45,8 +53,6 @@ | |||
45 | $(document).ready(function () { | 53 | $(document).ready(function () { |
46 | /* Vars needed for base.js */ | 54 | /* Vars needed for base.js */ |
47 | var ctx = {}; | 55 | var ctx = {}; |
48 | ctx.projectBuildUrl = "{% url 'xhr_build' %}"; | ||
49 | ctx.projectBasePageUrl = "{% url 'base_project' %}"; | ||
50 | ctx.projectInfoUrl = "{% url 'xhr_projectinfo' %}"; | 56 | ctx.projectInfoUrl = "{% url 'xhr_projectinfo' %}"; |
51 | ctx.numProjects = {{projects|length}}; | 57 | ctx.numProjects = {{projects|length}}; |
52 | ctx.currentUrl = "{{request.path|escapejs}}"; | 58 | ctx.currentUrl = "{{request.path|escapejs}}"; |
@@ -99,7 +105,7 @@ | |||
99 | <div class="input-append"> | 105 | <div class="input-append"> |
100 | <input type="text" class="input-medium" id="project-name-input" placeholder="Type a project name" autocomplete="off" data-minLength="1" data-autocomplete="off" data-provide="typeahead"/> | 106 | <input type="text" class="input-medium" id="project-name-input" placeholder="Type a project name" autocomplete="off" data-minLength="1" data-autocomplete="off" data-provide="typeahead"/> |
101 | <button id="save-project-button" class="btn" type="button">Save</button> | 107 | <button id="save-project-button" class="btn" type="button">Save</button> |
102 | <a href="#" id="cancel-change-project" class="btn btn-link">Cancel</a> | 108 | <a href="#" id="cancel-change-project" class="btn btn-link" style="display: none">Cancel</a> |
103 | </div> | 109 | </div> |
104 | <p><a id="view-all-projects" href="{% url 'all-projects' %}">View all projects</a></p> | 110 | <p><a id="view-all-projects" href="{% url 'all-projects' %}">View all projects</a></p> |
105 | </form> | 111 | </form> |
@@ -111,9 +117,9 @@ | |||
111 | <li id="targets-form"> | 117 | <li id="targets-form"> |
112 | <h6>Recipe(s):</h6> | 118 | <h6>Recipe(s):</h6> |
113 | <form> | 119 | <form> |
114 | <input type="text" class="input-xlarge" id="build-target-input" placeholder="Type a recipe name" autocomplete="off" data-minLength="1" data-autocomplete="off" data-provide="typeahead" /> | 120 | <input type="text" class="input-xlarge" id="build-target-input" placeholder="Type a recipe name" autocomplete="off" data-minLength="1" data-autocomplete="off" data-provide="typeahead" disabled/> |
115 | <div> | 121 | <div> |
116 | <a class="btn btn-primary" id="build-button" data-project-id="{{project.id}}">Build</a> | 122 | <button class="btn btn-primary" id="build-button" data-project-id="{{project.id}}" disabled>Build</button> |
117 | </div> | 123 | </div> |
118 | </form> | 124 | </form> |
119 | </li> | 125 | </li> |
diff --git a/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html b/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html index 4c28cae810..ce023f51af 100644 --- a/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html +++ b/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html | |||
@@ -57,7 +57,7 @@ | |||
57 | } | 57 | } |
58 | } | 58 | } |
59 | 59 | ||
60 | // load cookie for number of entries to be displayed on page | 60 | // load data for number of entries to be displayed on page |
61 | if ({{request.GET.count}} != "") { | 61 | if ({{request.GET.count}} != "") { |
62 | pagesize = {{request.GET.count}}; | 62 | pagesize = {{request.GET.count}}; |
63 | } | 63 | } |
diff --git a/bitbake/lib/toaster/toastergui/templates/detail_pagination_bottom.html b/bitbake/lib/toaster/toastergui/templates/detail_pagination_bottom.html index 434facba93..f40c21d99f 100644 --- a/bitbake/lib/toaster/toastergui/templates/detail_pagination_bottom.html +++ b/bitbake/lib/toaster/toastergui/templates/detail_pagination_bottom.html | |||
@@ -38,7 +38,7 @@ | |||
38 | <!-- Update page display settings --> | 38 | <!-- Update page display settings --> |
39 | <script> | 39 | <script> |
40 | $(document).ready(function() { | 40 | $(document).ready(function() { |
41 | // load cookie for number of entries to be displayed on page | 41 | // load data for number of entries to be displayed on page |
42 | if ({{request.GET.count}} != "") { | 42 | if ({{request.GET.count}} != "") { |
43 | pagesize = {{request.GET.count}}; | 43 | pagesize = {{request.GET.count}}; |
44 | } | 44 | } |
diff --git a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py index 8028ae0022..e79a4e5848 100644 --- a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py +++ b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py | |||
@@ -51,11 +51,11 @@ def get_tasks(queryset): | |||
51 | 51 | ||
52 | 52 | ||
53 | @register.filter(name = "json") | 53 | @register.filter(name = "json") |
54 | def json(value): | 54 | def json(value, default = None): |
55 | # JSON spec says that "\/" is functionally identical to "/" to allow for HTML-tag embedding in JSON strings | 55 | # JSON spec says that "\/" is functionally identical to "/" to allow for HTML-tag embedding in JSON strings |
56 | # unfortunately, I can't find any option in the json module to turn on forward-slash escaping, so we do | 56 | # unfortunately, I can't find any option in the json module to turn on forward-slash escaping, so we do |
57 | # it manually here | 57 | # it manually here |
58 | return mark_safe(JsonLib.dumps(value, ensure_ascii=False).replace('</', '<\\/')) | 58 | return mark_safe(JsonLib.dumps(value, default = default, ensure_ascii=False).replace('</', '<\\/')) |
59 | 59 | ||
60 | @register.assignment_tag | 60 | @register.assignment_tag |
61 | def query(qs, **kwargs): | 61 | def query(qs, **kwargs): |
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py index 7a1132febc..4e328dae17 100644 --- a/bitbake/lib/toaster/toastergui/urls.py +++ b/bitbake/lib/toaster/toastergui/urls.py | |||
@@ -77,8 +77,6 @@ urlpatterns = patterns('toastergui.views', | |||
77 | 77 | ||
78 | url(r'^projects/$', 'projects', name='all-projects'), | 78 | url(r'^projects/$', 'projects', name='all-projects'), |
79 | 79 | ||
80 | url(r'^project/$', lambda x: HttpResponseBadRequest(), name='base_project'), | ||
81 | |||
82 | url(r'^project/(?P<pid>\d+)/$', 'project', name='project'), | 80 | url(r'^project/(?P<pid>\d+)/$', 'project', name='project'), |
83 | url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'), | 81 | url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'), |
84 | url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'), | 82 | url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'), |
@@ -110,7 +108,6 @@ urlpatterns = patterns('toastergui.views', | |||
110 | name="all-layers"), | 108 | name="all-layers"), |
111 | 109 | ||
112 | 110 | ||
113 | url(r'^xhr_build/$', 'xhr_build', name='xhr_build'), | ||
114 | url(r'^xhr_projectbuild/(?P<pid>\d+)$', 'xhr_projectbuild', name='xhr_projectbuild'), | 111 | url(r'^xhr_projectbuild/(?P<pid>\d+)$', 'xhr_projectbuild', name='xhr_projectbuild'), |
115 | url(r'^xhr_projectinfo/$', 'xhr_projectinfo', name='xhr_projectinfo'), | 112 | url(r'^xhr_projectinfo/$', 'xhr_projectinfo', name='xhr_projectinfo'), |
116 | url(r'^xhr_projectedit/(?P<pid>\d+)$', 'xhr_projectedit', name='xhr_projectedit'), | 113 | url(r'^xhr_projectedit/(?P<pid>\d+)$', 'xhr_projectedit', name='xhr_projectedit'), |
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 0e248a7435..d4a9b4ca0d 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
@@ -129,7 +129,19 @@ def _redirect_parameters(view, g, mandatory_parameters, *args, **kwargs): | |||
129 | if not i in params: | 129 | if not i in params: |
130 | params[i] = urllib.unquote(str(mandatory_parameters[i])) | 130 | params[i] = urllib.unquote(str(mandatory_parameters[i])) |
131 | 131 | ||
132 | return redirect(url + "?%s" % urllib.urlencode(params), *args, **kwargs) | 132 | return redirect(url + "?%s" % urllib.urlencode(params), permanent = False, *args, **kwargs) |
133 | |||
134 | class RedirectException(Exception): | ||
135 | def __init__(self, view, g, mandatory_parameters, *args, **kwargs): | ||
136 | super(RedirectException, self).__init__() | ||
137 | self.view = view | ||
138 | self.g = g | ||
139 | self.mandatory_parameters = mandatory_parameters | ||
140 | self.oargs = args | ||
141 | self.okwargs = kwargs | ||
142 | |||
143 | def get_redirect_response(self): | ||
144 | return _redirect_parameters(self.view, self.g, self.mandatory_parameters, self.oargs, self.okwargs) | ||
133 | 145 | ||
134 | FIELD_SEPARATOR = ":" | 146 | FIELD_SEPARATOR = ":" |
135 | AND_VALUE_SEPARATOR = "!" | 147 | AND_VALUE_SEPARATOR = "!" |
@@ -2200,14 +2212,6 @@ if toastermain.settings.MANAGED: | |||
2200 | response['Pragma'] = "no-cache" | 2212 | response['Pragma'] = "no-cache" |
2201 | return response | 2213 | return response |
2202 | 2214 | ||
2203 | # This is a wrapper for xhr_projectbuild which allows for a project id | ||
2204 | # which only becomes known client side. | ||
2205 | def xhr_build(request): | ||
2206 | if request.POST.has_key("project_id"): | ||
2207 | pid = request.POST['project_id'] | ||
2208 | return xhr_projectbuild(request, pid) | ||
2209 | else: | ||
2210 | raise BadParameterException("invalid project id") | ||
2211 | 2215 | ||
2212 | def xhr_projectbuild(request, pid): | 2216 | def xhr_projectbuild(request, pid): |
2213 | try: | 2217 | try: |
@@ -2333,7 +2337,7 @@ if toastermain.settings.MANAGED: | |||
2333 | # returns layers for current project release that are not in the project set, matching the name | 2337 | # returns layers for current project release that are not in the project set, matching the name |
2334 | if request.GET['type'] == "layers": | 2338 | if request.GET['type'] == "layers": |
2335 | # all layers for the current project | 2339 | # all layers for the current project |
2336 | queryset_all = prj.compatible_layerversions().filter(layer__name__icontains=request.GET.get('value','')) | 2340 | queryset_all = prj.compatible_layerversions().filter(layer__name__icontains=request.GET.get('search','')) |
2337 | 2341 | ||
2338 | # but not layers with equivalent layers already in project | 2342 | # but not layers with equivalent layers already in project |
2339 | if not request.GET.has_key('include_added'): | 2343 | if not request.GET.has_key('include_added'): |
@@ -2348,7 +2352,7 @@ if toastermain.settings.MANAGED: | |||
2348 | # returns layer dependencies for a layer, excluding current project layers | 2352 | # returns layer dependencies for a layer, excluding current project layers |
2349 | if request.GET['type'] == "layerdeps": | 2353 | if request.GET['type'] == "layerdeps": |
2350 | queryset = prj.compatible_layerversions().exclude(pk__in = [x.id for x in prj.projectlayer_equivalent_set()]).filter( | 2354 | queryset = prj.compatible_layerversions().exclude(pk__in = [x.id for x in prj.projectlayer_equivalent_set()]).filter( |
2351 | layer__name__in = [ x.depends_on.layer.name for x in LayerVersionDependency.objects.filter(layer_version_id = request.GET['value'])]) | 2355 | layer__name__in = [ x.depends_on.layer.name for x in LayerVersionDependency.objects.filter(layer_version_id = request.GET['search'])]) |
2352 | 2356 | ||
2353 | final_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset]) | 2357 | final_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset]) |
2354 | 2358 | ||
@@ -2361,7 +2365,7 @@ if toastermain.settings.MANAGED: | |||
2361 | 2365 | ||
2362 | retval = [] | 2366 | retval = [] |
2363 | for i in prj.projectlayer_set.all(): | 2367 | for i in prj.projectlayer_set.all(): |
2364 | lv = prj.compatible_layerversions(release = Release.objects.get(pk=request.GET['value'])).filter(layer__name = i.layercommit.layer.name) | 2368 | lv = prj.compatible_layerversions(release = Release.objects.get(pk=request.GET['search'])).filter(layer__name = i.layercommit.layer.name) |
2365 | # there is no layer_version with the new release id, and the same name | 2369 | # there is no layer_version with the new release id, and the same name |
2366 | if lv.count() < 1: | 2370 | if lv.count() < 1: |
2367 | retval.append(i) | 2371 | retval.append(i) |
@@ -2374,10 +2378,10 @@ if toastermain.settings.MANAGED: | |||
2374 | # returns layer versions that provide the named targets | 2378 | # returns layer versions that provide the named targets |
2375 | if request.GET['type'] == "layers4target": | 2379 | if request.GET['type'] == "layers4target": |
2376 | # we return data only if the recipe can't be provided by the current project layer set | 2380 | # we return data only if the recipe can't be provided by the current project layer set |
2377 | if reduce(lambda x, y: x + y, [x.recipe_layer_version.filter(name=request.GET['value']).count() for x in prj.projectlayer_equivalent_set()], 0): | 2381 | if reduce(lambda x, y: x + y, [x.recipe_layer_version.filter(name=request.GET['search']).count() for x in prj.projectlayer_equivalent_set()], 0): |
2378 | final_list = [] | 2382 | final_list = [] |
2379 | else: | 2383 | else: |
2380 | queryset_all = prj.compatible_layerversions().filter(recipe_layer_version__name = request.GET['value']) | 2384 | queryset_all = prj.compatible_layerversions().filter(recipe_layer_version__name = request.GET['search']) |
2381 | 2385 | ||
2382 | # exclude layers in the project | 2386 | # exclude layers in the project |
2383 | queryset_all = queryset_all.exclude(pk__in = [x.id for x in prj.projectlayer_equivalent_set()]) | 2387 | queryset_all = queryset_all.exclude(pk__in = [x.id for x in prj.projectlayer_equivalent_set()]) |
@@ -2389,7 +2393,7 @@ if toastermain.settings.MANAGED: | |||
2389 | 2393 | ||
2390 | # returns targets provided by current project layers | 2394 | # returns targets provided by current project layers |
2391 | if request.GET['type'] == "targets": | 2395 | if request.GET['type'] == "targets": |
2392 | search_token = request.GET.get('value','') | 2396 | search_token = request.GET.get('search','') |
2393 | queryset_all = Recipe.objects.filter(layer_version__layer__name__in = [x.layercommit.layer.name for x in prj.projectlayer_set.all().select_related("layercommit__layer")]).filter(Q(name__icontains=search_token) | Q(layer_version__layer__name__icontains=search_token)) | 2397 | queryset_all = Recipe.objects.filter(layer_version__layer__name__in = [x.layercommit.layer.name for x in prj.projectlayer_set.all().select_related("layercommit__layer")]).filter(Q(name__icontains=search_token) | Q(layer_version__layer__name__icontains=search_token)) |
2394 | 2398 | ||
2395 | # layer_equivalent_set = [] | 2399 | # layer_equivalent_set = [] |
@@ -2420,7 +2424,7 @@ if toastermain.settings.MANAGED: | |||
2420 | if 'project_id' in request.session: | 2424 | if 'project_id' in request.session: |
2421 | queryset_all = queryset_all.filter(layer_version__in = prj.projectlayer_equivalent_set()).order_by("name") | 2425 | queryset_all = queryset_all.filter(layer_version__in = prj.projectlayer_equivalent_set()).order_by("name") |
2422 | 2426 | ||
2423 | search_token = request.GET.get('value','') | 2427 | search_token = request.GET.get('search','') |
2424 | queryset_all = queryset_all.filter(Q(name__icontains=search_token) | Q(description__icontains=search_token)) | 2428 | queryset_all = queryset_all.filter(Q(name__icontains=search_token) | Q(description__icontains=search_token)) |
2425 | 2429 | ||
2426 | return HttpResponse(jsonfilter({ "error":"ok", | 2430 | return HttpResponse(jsonfilter({ "error":"ok", |
@@ -2432,15 +2436,6 @@ if toastermain.settings.MANAGED: | |||
2432 | ) | 2436 | ) |
2433 | }), content_type = "application/json") | 2437 | }), content_type = "application/json") |
2434 | 2438 | ||
2435 | # returns all projects | ||
2436 | if request.GET['type'] == "projects": | ||
2437 | queryset_all = Project.objects.all() | ||
2438 | ret = { "error": "ok", | ||
2439 | "list": map (lambda x: {"id":x.pk, "name": x.name}, | ||
2440 | queryset_all.filter(name__icontains=request.GET.get('value',''))[:8])} | ||
2441 | |||
2442 | return HttpResponse(jsonfilter(ret), content_type = "application/json") | ||
2443 | |||
2444 | raise Exception("Unknown request! " + request.GET.get('type', "No parameter supplied")) | 2439 | raise Exception("Unknown request! " + request.GET.get('type', "No parameter supplied")) |
2445 | except Exception as e: | 2440 | except Exception as e: |
2446 | return HttpResponse(jsonfilter({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") | 2441 | return HttpResponse(jsonfilter({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") |
@@ -2866,14 +2861,38 @@ if toastermain.settings.MANAGED: | |||
2866 | return build_mru | 2861 | return build_mru |
2867 | 2862 | ||
2868 | 2863 | ||
2869 | def projects(request): | 2864 | def template_renderer(template): |
2870 | template="projects.html" | 2865 | def func_wrapper(view): |
2866 | def returned_wrapper(request, *args, **kwargs): | ||
2867 | try: | ||
2868 | context = view(request, *args, **kwargs) | ||
2869 | except RedirectException as e: | ||
2870 | return e.get_redirect_response() | ||
2871 | |||
2872 | if request.GET.get('format', None) == 'json': | ||
2873 | # objects is a special keyword - it's a Page, but we need the actual objects here | ||
2874 | # in XHR, the objects come in the "list" property | ||
2875 | if "objects" in context: | ||
2876 | context["list"] = context["objects"].object_list | ||
2877 | del context["objects"] | ||
2878 | |||
2879 | # we're about to return; to keep up with the XHR API, we set the error to OK | ||
2880 | context["error"] = "ok" | ||
2881 | |||
2882 | return HttpResponse(jsonfilter(context, default=lambda obj: obj.isoformat() if isinstance(obj, datetime) else obj.__dict__ ), | ||
2883 | content_type = "application/json; charset=utf-8") | ||
2884 | else: | ||
2885 | return render(request, template, context) | ||
2886 | return returned_wrapper | ||
2887 | return func_wrapper | ||
2871 | 2888 | ||
2889 | @template_renderer("projects.html") | ||
2890 | def projects(request): | ||
2872 | (pagesize, orderby) = _get_parameters_values(request, 10, 'updated:-') | 2891 | (pagesize, orderby) = _get_parameters_values(request, 10, 'updated:-') |
2873 | mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby } | 2892 | mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby } |
2874 | retval = _verify_parameters( request.GET, mandatory_parameters ) | 2893 | retval = _verify_parameters( request.GET, mandatory_parameters ) |
2875 | if retval: | 2894 | if retval: |
2876 | return _redirect_parameters( 'all-projects', request.GET, mandatory_parameters) | 2895 | raise RedirectException( 'all-projects', request.GET, mandatory_parameters ) |
2877 | 2896 | ||
2878 | queryset_all = Project.objects.all() | 2897 | queryset_all = Project.objects.all() |
2879 | 2898 | ||
@@ -2886,6 +2905,14 @@ if toastermain.settings.MANAGED: | |||
2886 | # retrieve the objects that will be displayed in the table; projects a paginator and gets a page range to display | 2905 | # retrieve the objects that will be displayed in the table; projects a paginator and gets a page range to display |
2887 | project_info = _build_page_range(Paginator(queryset, pagesize), request.GET.get('page', 1)) | 2906 | project_info = _build_page_range(Paginator(queryset, pagesize), request.GET.get('page', 1)) |
2888 | 2907 | ||
2908 | # add fields needed in JSON dumps for API call support | ||
2909 | for p in project_info.object_list: | ||
2910 | p.id = p.pk | ||
2911 | p.xhrProjectDataTypeaheadUrl = reverse('xhr_datatypeahead', args=(p.id,)) | ||
2912 | p.projectPageUrl = reverse('project', args=(p.id,)) | ||
2913 | p.xhrProjectEditUrl = reverse('xhr_projectedit', args=(p.id,)) | ||
2914 | p.projectBuildUrl = reverse('xhr_projectbuild', args=(p.id,)) | ||
2915 | |||
2889 | # build view-specific information; this is rendered specifically in the builds page, at the top of the page (i.e. Recent builds) | 2916 | # build view-specific information; this is rendered specifically in the builds page, at the top of the page (i.e. Recent builds) |
2890 | build_mru = _managed_get_latest_builds() | 2917 | build_mru = _managed_get_latest_builds() |
2891 | 2918 | ||
@@ -2965,9 +2992,8 @@ if toastermain.settings.MANAGED: | |||
2965 | ] | 2992 | ] |
2966 | } | 2993 | } |
2967 | 2994 | ||
2968 | response = render(request, template, context) | ||
2969 | _set_parameters_values(pagesize, orderby, request) | 2995 | _set_parameters_values(pagesize, orderby, request) |
2970 | return response | 2996 | return context |
2971 | 2997 | ||
2972 | def buildrequestdetails(request, pid, brid): | 2998 | def buildrequestdetails(request, pid, brid): |
2973 | template = "buildrequestdetails.html" | 2999 | template = "buildrequestdetails.html" |
@@ -3185,9 +3211,6 @@ else: | |||
3185 | def xhr_projectbuild(request, pid): | 3211 | def xhr_projectbuild(request, pid): |
3186 | return render(request, 'landing_not_managed.html') | 3212 | return render(request, 'landing_not_managed.html') |
3187 | 3213 | ||
3188 | def xhr_build(request): | ||
3189 | return render(request, 'landing_not_managed.html') | ||
3190 | |||
3191 | def xhr_projectinfo(request): | 3214 | def xhr_projectinfo(request): |
3192 | return render(request, 'landing_not_managed.html') | 3215 | return render(request, 'landing_not_managed.html') |
3193 | 3216 | ||