summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/base.js51
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/importlayer.js6
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/layerdetails.js2
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/libtoaster.js12
-rw-r--r--bitbake/lib/toaster/toastergui/templates/base.html24
-rw-r--r--bitbake/lib/toaster/toastergui/templates/basetable_bottom.html2
-rw-r--r--bitbake/lib/toaster/toastergui/templates/detail_pagination_bottom.html2
-rw-r--r--bitbake/lib/toaster/toastergui/templatetags/projecttags.py4
-rw-r--r--bitbake/lib/toaster/toastergui/urls.py3
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py89
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")
54def json(value): 54def 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
61def query(qs, **kwargs): 61def 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
134class 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
134FIELD_SEPARATOR = ":" 146FIELD_SEPARATOR = ":"
135AND_VALUE_SEPARATOR = "!" 147AND_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