diff options
author | Alexandru DAMIAN <alexandru.damian@intel.com> | 2015-06-08 13:36:56 +0100 |
---|---|---|
committer | Alexandru DAMIAN <alexandru.damian@intel.com> | 2015-06-10 15:31:12 +0100 |
commit | 8e7a2c3b125a34fd9d6fa0442ab13290137ecc51 (patch) | |
tree | 6439e625f7fa25d5bd9959265084f77081cd48ce | |
parent | fb5eb1d7759222573565936a964d602c148df139 (diff) | |
download | bitbake-contrib-8e7a2c3b125a34fd9d6fa0442ab13290137ecc51.tar.gz |
toastergui: remove xhr_datatypeahead and xhr_XXXbuild
We remove the endpoints for XHR on the toastergui application.
The endpoints are now replaced with calls to the respective
REST endpoints (i.e. projectlayers, projecttargets, projectmachines).
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
-rw-r--r-- | lib/toaster/contrib/tts/urllist.py | 2 | ||||
-rw-r--r-- | lib/toaster/toastergui/static/js/base.js | 6 | ||||
-rw-r--r-- | lib/toaster/toastergui/static/js/importlayer.js | 6 | ||||
-rw-r--r-- | lib/toaster/toastergui/static/js/layerdetails.js | 4 | ||||
-rw-r--r-- | lib/toaster/toastergui/static/js/libtoaster.js | 8 | ||||
-rw-r--r-- | lib/toaster/toastergui/templates/base.html | 2 | ||||
-rw-r--r-- | lib/toaster/toastergui/templates/layerdetails.html | 4 | ||||
-rw-r--r-- | lib/toaster/toastergui/templates/managed_mrb_section.html | 2 | ||||
-rw-r--r-- | lib/toaster/toastergui/templates/project.html | 52 | ||||
-rw-r--r-- | lib/toaster/toastergui/templates/runagain.html | 2 | ||||
-rw-r--r-- | lib/toaster/toastergui/templatetags/projecttags.py | 2 | ||||
-rw-r--r-- | lib/toaster/toastergui/tests.py | 6 | ||||
-rw-r--r-- | lib/toaster/toastergui/urls.py | 8 | ||||
-rwxr-xr-x | lib/toaster/toastergui/views.py | 208 | ||||
-rw-r--r-- | lib/toaster/toastergui/widgets.py | 6 | ||||
-rw-r--r-- | lib/toaster/toastermain/settings.py | 2 |
16 files changed, 119 insertions, 201 deletions
diff --git a/lib/toaster/contrib/tts/urllist.py b/lib/toaster/contrib/tts/urllist.py index 433ac9fe8..0226334f0 100644 --- a/lib/toaster/contrib/tts/urllist.py +++ b/lib/toaster/contrib/tts/urllist.py @@ -40,9 +40,7 @@ URLS = [ 'toastergui/project/1/importlayer', 'toastergui/project/1/targets/', 'toastergui/project/1/machines/', -'toastergui/xhr_projectbuild/1/', 'toastergui/xhr_configvaredit/1', -'toastergui/xhr_datatypeahead/1', 'toastergui/xhr_importlayer/', 'toastergui/xhr_updatelayer/', 'toastergui/project/1/buildrequest/1', diff --git a/lib/toaster/toastergui/static/js/base.js b/lib/toaster/toastergui/static/js/base.js index 9c8d01ef5..747442cc9 100644 --- a/lib/toaster/toastergui/static/js/base.js +++ b/lib/toaster/toastergui/static/js/base.js @@ -89,7 +89,7 @@ function basePageInit (ctx) { if (!selectedTarget) selectedTarget = { name: newBuildTargetInput.val() }; /* fire and forget */ - libtoaster.startABuild(ctx.projectBuildUrl, libtoaster.ctx.projectId, selectedTarget.name, null, null); + libtoaster.startABuild(ctx.projectBuildsUrl, libtoaster.ctx.projectId, selectedTarget.name, null, null); window.location.replace(libtoaster.ctx.projectPageUrl); }); @@ -105,13 +105,13 @@ function basePageInit (ctx) { libtoaster.ctx.projectName = selectedProject.name; libtoaster.ctx.projectId = selectedProject.id; - ctx.projectBuildUrl = selectedProject.projectBuildUrl; + ctx.projectBuildsUrl = selectedProject.projectBuildsUrl; /* we can create a target typeahead only after we have a project selected */ newBuildTargetInput.prop("disabled", false); newBuildTargetBuildBtn.prop("disabled", false); - libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.xhrProjectDataTypeaheadUrl, { type : "targets" }, function(item){ + libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.projectTargetsUrl, { format: "json" }, function(item){ /* successfully selected a target */ selectedTarget = item; }); diff --git a/lib/toaster/toastergui/static/js/importlayer.js b/lib/toaster/toastergui/static/js/importlayer.js index beb2ede3d..e1fc5c518 100644 --- a/lib/toaster/toastergui/static/js/importlayer.js +++ b/lib/toaster/toastergui/static/js/importlayer.js @@ -18,7 +18,7 @@ function importLayerPageInit (ctx) { $("#new-project-button").hide(); - libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" }, function(item){ + libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.projectLayersUrl, { include_added: "true" }, function(item){ currentLayerDepSelection = item; layerDepBtn.removeAttr("disabled"); @@ -28,7 +28,7 @@ function importLayerPageInit (ctx) { /* We automatically add "openembedded-core" layer for convenience as a * dependency as pretty much all layers depend on this one */ - $.getJSON(libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" , value: "openembedded-core" }, function(layer) { + $.getJSON(libtoaster.ctx.projectLayersUrl, { include_added: "true" , search: "openembedded-core" }, function(layer) { if (layer.list.length == 1) { currentLayerDepSelection = layer.list[0]; layerDepBtn.click(); @@ -211,7 +211,7 @@ function importLayerPageInit (ctx) { var name = $(this).val(); /* Check if the layer name exists */ - $.getJSON(libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" , value: name }, function(layer) { + $.getJSON(libtoaster.ctx.projectLayersUrl, { include_added: "true" , search: name }, function(layer) { if (layer.list.length > 0) { for (var i in layer.list){ if (layer.list[i].name == name) { diff --git a/lib/toaster/toastergui/static/js/layerdetails.js b/lib/toaster/toastergui/static/js/layerdetails.js index 8e14b8f27..ab781829c 100644 --- a/lib/toaster/toastergui/static/js/layerdetails.js +++ b/lib/toaster/toastergui/static/js/layerdetails.js @@ -9,7 +9,7 @@ function layerDetailsPageInit (ctx) { var addRmLayerBtn = $("#add-remove-layer-btn"); /* setup the dependencies typeahead */ - libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" }, function(item){ + libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.projectLayersUrl, { include_added: "true" }, function(item){ currentLayerDepSelection = item; layerDepBtn.removeAttr("disabled"); @@ -170,7 +170,7 @@ function layerDetailsPageInit (ctx) { $(".build-target-btn").click(function(){ /* fire a build */ var target = $(this).data('target-name'); - libtoaster.startABuild(ctx.projectBuildUrl, libtoaster.ctx.projectId, target, null, null); + libtoaster.startABuild(ctx.projectBuildsUrl, libtoaster.ctx.projectId, target, null, null); window.location.replace(libtoaster.ctx.projectPageUrl); }); }); diff --git a/lib/toaster/toastergui/static/js/libtoaster.js b/lib/toaster/toastergui/static/js/libtoaster.js index 87910299a..2a9a79069 100644 --- a/lib/toaster/toastergui/static/js/libtoaster.js +++ b/lib/toaster/toastergui/static/js/libtoaster.js @@ -93,7 +93,7 @@ var libtoaster = (function (){ } /* cancelABuild: - * url: xhr_projectbuild + * url: projectbuilds * builds_ids: space separated list of build request ids * onsuccess: callback for successful execution * onfail: callback for failed execution @@ -172,15 +172,15 @@ var libtoaster = (function (){ function _getLayerDepsForProject(projectId, layerId, onSuccess, onFail){ /* Check for dependencies not in the current project */ - $.getJSON(libtoaster.ctx.xhrProjectDataTypeaheadUrl, - { type: 'layerdeps', 'value': layerId , project_id: projectId }, + $.getJSON(libtoaster.ctx.projectLayersUrl, + { format: 'json', search: layerId }, function(data) { if (data.error != "ok") { console.log(data.error); if (onFail !== undefined) onFail(data); } else { - onSuccess(data); + onSuccess(data.layerdeps); } }, function() { console.log("E: Failed to make request"); diff --git a/lib/toaster/toastergui/templates/base.html b/lib/toaster/toastergui/templates/base.html index 5d51bc3c9..7fee26eb4 100644 --- a/lib/toaster/toastergui/templates/base.html +++ b/lib/toaster/toastergui/templates/base.html @@ -33,12 +33,10 @@ htmlUrl : "{% static 'html/' %}", projectsUrl : "{% url 'all-projects' %}", {% if project.id %} - xhrProjectDataTypeaheadUrl : "{% url 'xhr_datatypeahead' project.id %}", projectPageUrl : "{% url 'project' project.id %}", projectName : "{{project.name}}", projectId : {{project.id}}, {% else %} - xhrProjectDataTypeaheadUrl : undefined, projectPageUrl : undefined, projectName : undefined, projectId : undefined, diff --git a/lib/toaster/toastergui/templates/layerdetails.html b/lib/toaster/toastergui/templates/layerdetails.html index c27d259a8..ef1795c0e 100644 --- a/lib/toaster/toastergui/templates/layerdetails.html +++ b/lib/toaster/toastergui/templates/layerdetails.html @@ -3,7 +3,7 @@ {% load humanize %} {% load static %} {% block localbreadcrumb %} -<li><a href="{% url 'all-layers' project.id %}">All compatible layers</a></li> +<li><a href="{% url 'projectlayers' project.id %}">All compatible layers</a></li> <li> {{layerversion.layer.name}} ({{layerversion.get_vcs_reference|truncatechars:13}}) </li> @@ -33,7 +33,7 @@ $(document).ready(function (){ var ctx = { - projectBuildUrl : "{% url 'xhr_projectbuild' project.id %}", + projectBuildsUrl : "{% url 'projectbuilds' project.id %}", layerDetailsUrl : "{% url 'base_layerdetails' project.id %}", xhrUpdateLayerUrl : "{% url 'xhr_updatelayer' %}", layerVersion : { diff --git a/lib/toaster/toastergui/templates/managed_mrb_section.html b/lib/toaster/toastergui/templates/managed_mrb_section.html index c93c2af30..47e64eaaa 100644 --- a/lib/toaster/toastergui/templates/managed_mrb_section.html +++ b/lib/toaster/toastergui/templates/managed_mrb_section.html @@ -129,7 +129,7 @@ <div class="span4 lead">Build queued <i title="This build will start as soon as a build server is available" class="icon-question-sign get-help get-help-blue heading-help" data-toggle="tooltip"></i> </div> - <button class="btn btn-info pull-right cancel-build-btn" data-build-id="{{buildrequest.id}}" data-request-url="{% url 'xhr_projectbuild' buildrequest.project.id %}" >Cancel</button> + <button class="btn btn-info pull-right cancel-build-btn" data-build-id="{{buildrequest.id}}" data-request-url="{% url 'projectbuilds' buildrequest.project.id %}" >Cancel</button> {% elif buildrequest.state == buildrequest.REQ_CREATED %} diff --git a/lib/toaster/toastergui/templates/project.html b/lib/toaster/toastergui/templates/project.html index e59863130..63fbc40f5 100644 --- a/lib/toaster/toastergui/templates/project.html +++ b/lib/toaster/toastergui/templates/project.html @@ -30,7 +30,7 @@ vim: expandtab tabstop=2 {%else%} -<div id="main" role="main" data-ng-app="project" data-ng-controller="prjCtrl" class="top-padded"> +<div id="main" role="main" data-ng-app="project" data-ng-controller="prjCtrl" class="top-padded" data-ng-cloak> <!-- project name --> <div class="page-header"> @@ -46,10 +46,30 @@ vim: expandtab tabstop=2 <!-- custom templates for ng --> - <script type="text/ng-template" id="suggestion_details"> - <a> {[match.model.name]} {[match.model.detail]} </a> + <style> + .missing-layer { + color: lightgrey; + } + </style> + <script type="text/ng-template" id="recipes_suggestion_details"> + <a> {[match.model.name]} + <span data-ng-class="{'missing-layer':($parent.$parent.$parent.$parent.filterProjectLayerIds().indexOf(match.model.projectcompatible_layer.id) == -1)}"> + [{[match.model.layer_version__layer__name]}] + </span> + </a> </script> + <script type="text/ng-template" id="machines_suggestion_details"> + <a> {[match.model.name]} <span class="{'missing-layer':(filterProjectLayerIds().indexOf(match.model.layer_version_compatible_id) == -1)}">[{[match.model.layer_version__layer__name]}]</span> </a> + </script> + + <script type="text/ng-template" id="layers_suggestion_details"> + <a> {[match.model['layer__name']]} ( {[match.model.layer__vcs_url]} ) </a> + </script> + + + + <!-- modal dialogs --> <script type="text/ng-template" id="dependencies_modal"> <div class="modal-header"> @@ -104,14 +124,14 @@ vim: expandtab tabstop=2 <div class="well"> <form class="build-form" data-ng-submit="buildNamedTarget()"> <div class="input-append controls"> - <input type="text" class="huge input-xxlarge" placeholder="Type the recipe(s) you want to build" autocomplete="off" data-ng-model="targetName" data-typeahead="e.name for e in getAutocompleteSuggestions('targets', $viewValue)|filter:$viewValue" data-typeahead-template-url="suggestion_details" data-ng-disabled="!layers.length"/> + <input type="text" class="huge input-xxlarge" placeholder="Type the recipe(s) you want to build" autocomplete="off" data-ng-model="targetName" data-typeahead="a.name for a in getRecipesAutocompleteSuggestions($viewValue)" data-typeahead-template-url="recipes_suggestion_details" data-ng-disabled="!layers.length"/> <button type="submit" class="btn btn-large btn-primary" data-ng-disabled="!targetName.length"> Build </button> </div> <i class="icon-question-sign get-help get-help-blue" title="Type the name of one or more recipes you want to build, separated by a space. You can also specify a task by appending a semicolon and a task name to a recipe name, like so: <code>core-image-minimal:do_build</code>"></i> <p> - <a href="{% url 'all-targets' project.id %}">View all compatible recipes</a> + <a href="{% url 'projecttargets' project.id %}">View all compatible recipes</a> <i class="icon-question-sign get-help get-help-blue heading-help" title="View all the recipes you can build with the release selected for this project, which is {[project.release.desc]}"></i> {% if completedbuilds.count %} | <a href="{% url 'projectbuilds' project.id %}">View all project builds ({{completedbuilds.count}})</a> @@ -278,7 +298,7 @@ vim: expandtab tabstop=2 <p> You can: <ul> - <li> <a href="{% url 'all-layers' project.id %}">View all compatible layers available in Toaster</a> + <li> <a href="{% url 'projectlayers' project.id %}">View all compatible layers available in Toaster</a> <li> <a href="{% url 'importlayer' project.id %}">Import a layer</a> <li> <a href="https://www.yoctoproject.org/docs/1.6.1/dev-manual/dev-manual.html#understanding-and-creating-layers" target="_blank">Read about layers in the manual</a> </ul> @@ -287,13 +307,13 @@ vim: expandtab tabstop=2 </div> <form data-ng-submit="layerAdd()"> <div class="input-append"> - <input type="text" class="input-xlarge" id="layer" autocomplete="off" placeholder="Type a layer name" data-minLength="1" data-ng-model="layerAddName" data-typeahead="e.name for e in getAutocompleteSuggestions('layers', $viewValue)|filter:$viewValue" data-typeahead-template-url="suggestion_details" data-typeahead-on-select="onLayerSelect($item, $model, $label)" data-typeahead-editable="false" data-ng-class="{ 'has-error': layerAddName.$invalid }" /> + <input type="text" class="input-xlarge" id="layer" autocomplete="off" placeholder="Type a layer name" data-minLength="1" data-ng-model="layerAddName" data-typeahead="e for e in getLayersAutocompleteSuggestions($viewValue)" data-typeahead-template-url="layers_suggestion_details" data-typeahead-on-select="onLayerSelect($item, $model, $label)" data-typeahead-editable="false" data-ng-class="{ 'has-error': layerAddName.$invalid }" /> <input type="submit" id="add-layer" class="btn" value="Add" data-ng-disabled="!layerAddName.length"/> </div> {% csrf_token %} </form> <p> - <a href="{% url 'all-layers' project.id %}">View all compatible layers</a> + <a href="{% url 'projectlayers' project.id %}">View all compatible layers</a> <i class="icon-question-sign get-help" title="View all the layers you can build with the release selected for this project, which is {[project.release.desc]}"></i> | <a href="{% url 'importlayer' project.id %}">Import layer</a></p> @@ -314,14 +334,14 @@ vim: expandtab tabstop=2 </h3> <form data-ng-submit="buildNamedTarget()"> <div class="input-append"> - <input type="text" class="input-xlarge" placeholder="Type the recipe(s) you want to build" autocomplete="off" data-minLength="1" data-ng-model="targetName1" data-typeahead="e.name for e in getAutocompleteSuggestions('targets', $viewValue)|filter:$viewValue" data-typeahead-template-url="suggestion_details" data-ng-disabled="!layers.length"> + <input type="text" class="input-xlarge" placeholder="Type the recipe(s) you want to build" autocomplete="off" data-minLength="1" data-ng-model="targetName1" data-typeahead="a.name for a in getRecipesAutocompleteSuggestions($viewValue)" data-typeahead-template-url="recipes_suggestion_details" data-ng-disabled="!layers.length"> <button type="submit" class="btn btn-primary" data-ng-disabled="!targetName1.length"> Build </button> </div> {% csrf_token %} </form> <p> - <a href="{% url 'all-targets' project.id %}">View all compatible recipes</a> + <a href="{% url 'projecttargets' project.id %}">View all compatible recipes</a> <i class="icon-question-sign get-help" title="View all the recipes you can build with the release selected for this project, which is {[project.release.desc]}"></i> </p> <div data-ng-if="frequenttargets.length"> @@ -355,13 +375,13 @@ vim: expandtab tabstop=2 You cannot really compare the builds for the new machine with the previous ones. </div> <form data-ng-submit="editProjectSettings('#select-machine')" class="input-append"> - <input type="text" id="machine" autocomplete="off" data-ng-model="machineName" value="{[machine.name]}" data-typeahead="m.name for m in getAutocompleteSuggestions('machines', $viewValue)" data-typeahead-template-url="suggestion_details" /> + <input type="text" id="machine" autocomplete="off" data-ng-model="machineName" value="{[machine.name]}" data-typeahead="m.name for m in getMachinesAutocompleteSuggestions($viewValue)" data-typeahead-template-url="machines_suggestion_details" /> <input type="submit" id="apply-change-machine" class="btn" data-ng-disabled="machineName == machine.name || machineName.length == 0" value="Save"/> <input type="reset" id="cancel-machine" class="btn btn-link" data-ng-click="toggle('#select-machine')" value="Cancel"/> {% csrf_token %} </form> <p> - <a href="{% url 'all-machines' project.id %}" class="link">View all compatible machines</a> + <a href="{% url 'projectmachines' project.id %}" class="link">View all compatible machines</a> <i class="icon-question-sign get-help" title="View all the machines you can set with the release selected for this project, which is {[project.release.desc]}"></i> </p> </div> @@ -429,11 +449,11 @@ vim: expandtab tabstop=2 angular.element(document).ready(function() { scope = angular.element("#main").scope(); scope.urls = {}; - scope.urls.xhr_build = "{% url 'xhr_projectbuild' project.id %}"; + scope.urls.xhr_build = "{% url 'projectbuilds' project.id %}"; scope.urls.xhr_edit = "{% url 'project' project.id %}?format=json"; - scope.urls.xhr_datatypeahead = "{% url 'xhr_datatypeahead' project.id %}"; - scope.urls.layers = "{% url 'all-layers' project.id %}"; - scope.urls.targets = "{% url 'all-targets' project.id %}"; + scope.urls.layers = "{% url 'projectlayers' project.id %}"; + scope.urls.targets = "{% url 'projecttargets' project.id %}"; + scope.urls.machines = "{% url 'projectmachines' project.id %}"; scope.urls.importlayer = "{% url 'importlayer' project.id %}"; scope.urls.layer = "{% url 'base_layerdetails' project.id %}"; scope.project = {{prj|json}}; diff --git a/lib/toaster/toastergui/templates/runagain.html b/lib/toaster/toastergui/templates/runagain.html index a78c0ddc7..b4ba5fbf1 100644 --- a/lib/toaster/toastergui/templates/runagain.html +++ b/lib/toaster/toastergui/templates/runagain.html @@ -1,6 +1,6 @@ {% load projecttags %} onclick='scheduleBuild( - {% url 'xhr_projectbuild' buildrequest.project.id as bpi %}{{bpi|json}}, + {% url 'projectbuilds' buildrequest.project.id as bpi %}{{bpi|json}}, {{buildrequest.project.name|json}}, {% url 'project' buildrequest.project.id as bpurl %}{{bpurl|json}}, {{buildrequest.brtarget_set.all|get_tasks|json}}) diff --git a/lib/toaster/toastergui/templatetags/projecttags.py b/lib/toaster/toastergui/templatetags/projecttags.py index e79a4e584..75f2261be 100644 --- a/lib/toaster/toastergui/templatetags/projecttags.py +++ b/lib/toaster/toastergui/templatetags/projecttags.py @@ -55,7 +55,7 @@ def json(value, default = None): # JSON spec says that "\/" is functionally identical to "/" to allow for HTML-tag embedding in JSON strings # unfortunately, I can't find any option in the json module to turn on forward-slash escaping, so we do # it manually here - return mark_safe(JsonLib.dumps(value, default = default, ensure_ascii=False).replace('</', '<\\/')) + return mark_safe(JsonLib.dumps(value, indent=2, default = default, ensure_ascii=False).replace('</', '<\\/')) @register.assignment_tag def query(qs, **kwargs): diff --git a/lib/toaster/toastergui/tests.py b/lib/toaster/toastergui/tests.py index c92c5feeb..77e80fe3a 100644 --- a/lib/toaster/toastergui/tests.py +++ b/lib/toaster/toastergui/tests.py @@ -38,9 +38,9 @@ class AllProjectsViewTestCase(ProvisionedProjectTestCase): self.assertTrue(AllProjectsViewTestCase.TEST_PROJECT_NAME in map(lambda x: x["name"], data["list"])) self.assertTrue("id" in data["list"][0]) - self.assertTrue("xhrProjectDataTypeaheadUrl" in data["list"][0]) + self.assertTrue("projectLayersUrl" in data["list"][0]) self.assertTrue("projectPageUrl" in data["list"][0]) - self.assertTrue("projectBuildUrl" in data["list"][0]) + self.assertTrue("projectBuildsUrl" in data["list"][0]) class ProvisionedLayersProjectTestCase(ProvisionedProjectTestCase): LAYER_NAME = "base-layer" @@ -59,7 +59,7 @@ class XHRDataTypeAheadTestCase(ProvisionedLayersProjectTestCase): self.assertTrue(self.lv in self.project.compatible_layerversions()) def test_xhr_datatypeahead_layer(self): - response = self.client.get(reverse('xhr_datatypeahead', args=(self.project.id,)), {"type": "layers"}) + response = self.client.get(reverse('xhr_datatypeahead', args=(self.project.id,)), {"type": "layerdeps"}) self.assertEqual(response.status_code, 200) self.assertTrue(response['Content-Type'].startswith('application/json')) diff --git a/lib/toaster/toastergui/urls.py b/lib/toaster/toastergui/urls.py index d527be001..f1b74cdd1 100644 --- a/lib/toaster/toastergui/urls.py +++ b/lib/toaster/toastergui/urls.py @@ -91,19 +91,19 @@ urlpatterns = patterns('toastergui.views', tables.MachinesTable.as_view(template_name="generic-toastertable-page.html"), { 'table_name': tables.MachinesTable.__name__.lower(), 'title' : 'All compatible machines' }, - name="all-machines"), + name="projectmachines"), url(r'^project/(?P<pid>\d+)/recipes/$', tables.RecipesTable.as_view(template_name="generic-toastertable-page.html"), { 'table_name': tables.RecipesTable.__name__.lower(), 'title' : 'All compatible recipes' }, - name="all-targets"), + name="projecttargets"), url(r'^project/(?P<pid>\d+)/layers/$', tables.LayersTable.as_view(template_name="generic-toastertable-page.html"), { 'table_name': tables.LayersTable.__name__.lower(), 'title' : 'All compatible layers' }, - name="all-layers"), + name="projectlayers"), url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$', tables.LayerDetails.as_view(template_name='layerdetails.html'), @@ -121,10 +121,8 @@ urlpatterns = patterns('toastergui.views', 'title' : 'All machines in layer' }, name=tables.LayerMachinesTable.__name__.lower()), - url(r'^xhr_projectbuild/(?P<pid>\d+)$', 'xhr_projectbuild', name='xhr_projectbuild'), url(r'^xhr_configvaredit/(?P<pid>\d+)$', 'xhr_configvaredit', name='xhr_configvaredit'), - url(r'^xhr_datatypeahead/(?P<pid>\d+)$', 'xhr_datatypeahead', name='xhr_datatypeahead'), url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'), url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'), diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py index c25c512a8..5221f1f72 100755 --- a/lib/toaster/toastergui/views.py +++ b/lib/toaster/toastergui/views.py @@ -136,28 +136,6 @@ def _template_renderer(template): # we're about to return; to keep up with the XHR API, we set the error to OK context["error"] = "ok" - def _objtojson(obj): - from django.db.models.query import QuerySet - from django.db.models import Model, IntegerField - if isinstance(obj, datetime): - return obj.isoformat() - elif isinstance(obj, timedelta): - return obj.total_seconds() - elif isinstance(obj, QuerySet) or isinstance(obj, set): - return list(obj) - elif hasattr( obj, '__dict__'): - d = obj.__dict__ - nd = dict(d) - for di in d: - if di.startswith("_"): - del nd[di] - elif isinstance(d[di], Model): - nd[di] = d[di].pk - elif isinstance(d[di], int) and hasattr(obj, "get_%s_display" % di): - nd[di] = getattr(obj, "get_%s_display" % di)() - return nd - else: - raise TypeError("Unserializable object %s of type %s" % ( obj, type(obj))) return HttpResponse(jsonfilter(context, default=objtojson ), content_type = "application/json; charset=utf-8") @@ -167,6 +145,21 @@ def _template_renderer(template): return func_wrapper +def _lv_to_dict(prj, x = None): + if x is None: + def wrapper(x): + return _lv_to_dict(prj, x) + return wrapper + + return {"id": x.pk, + "name": x.layer.name, + "tooltip": x.layer.vcs_url+" | "+x.get_vcs_reference(), + "detail": "(" + x.layer.vcs_url + (")" if x.up_branch == None else " | "+x.get_vcs_reference()+")"), + "giturl": x.layer.vcs_url, + "layerdetailurl" : reverse('layerdetails', args=(prj.id,x.pk)), + "revision" : x.get_vcs_reference(), + } + def _build_page_range(paginator, index = 1): try: @@ -335,7 +328,6 @@ def _search_tuple(request, model): def _get_queryset(model, queryset, filter_string, search_term, ordering_string, ordering_secondary=''): if filter_string: filter_query = _get_filtering_query(filter_string) -# raise Exception(filter_query) queryset = queryset.filter(filter_query) else: queryset = queryset.all() @@ -2330,82 +2322,12 @@ if toastermain.settings.MANAGED: return context - def xhr_projectbuild(request, pid): - try: - if request.method != "POST": - raise BadParameterException("invalid method") - pid = pid - prj = Project.objects.get(id = pid) - - - if 'buildCancel' in request.POST: - for i in request.POST['buildCancel'].strip().split(" "): - try: - br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_QUEUED) - br.state = BuildRequest.REQ_DELETED - br.save() - except BuildRequest.DoesNotExist: - pass - - if 'buildDelete' in request.POST: - for i in request.POST['buildDelete'].strip().split(" "): - try: - br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_DELETED).delete() - except BuildRequest.DoesNotExist: - pass - - if 'targets' in request.POST: - ProjectTarget.objects.filter(project = prj).delete() - s = str(request.POST['targets']) - for t in s.translate(None, ";%|\"").split(" "): - if ":" in t: - target, task = t.split(":") - else: - target = t - task = "" - ProjectTarget.objects.create(project = prj, target = target, task = task) - - br = prj.schedule_build() - - return HttpResponse(jsonfilter({"error":"ok", - "builds" : _project_recent_build_list(prj), - }), content_type = "application/json") - except Exception as e: - return HttpResponse(jsonfilter({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") - - from django.views.decorators.csrf import csrf_exempt @csrf_exempt def xhr_datatypeahead(request, pid): try: prj = Project.objects.get(pk = pid) - def _lv_to_dict(x): - return {"id": x.pk, - "name": x.layer.name, - "tooltip": x.layer.vcs_url+" | "+x.get_vcs_reference(), - "detail": "(" + x.layer.vcs_url + (")" if x.up_branch == None else " | "+x.get_vcs_reference()+")"), - "giturl": x.layer.vcs_url, - "layerdetailurl" : reverse('layerdetails', args=(prj.id,x.pk)), - "revision" : x.get_vcs_reference(), - } - - - # returns layers for current project release that are not in the project set, matching the name - if request.GET.get('type', None) == "layers": - # all layers for the current project - queryset_all = prj.compatible_layerversions().filter(layer__name__icontains=request.GET.get('search','')) - - # but not layers with equivalent layers already in project - if not request.GET.has_key('include_added'): - queryset_all = queryset_all.exclude(pk__in = [x.id for x in prj.projectlayer_equivalent_set()])[:8] - - # and show only the selected layers for this project - final_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset_all]) - - return HttpResponse(jsonfilter( { "error":"ok", "list" : map( _lv_to_dict, sorted(final_list, key = lambda x: x.layer.name)) }), content_type = "application/json") - - # returns layer dependencies for a layer, excluding current project layers if request.GET.get('type', None) == "layerdeps": queryset = prj.compatible_layerversions().exclude(pk__in = [x.id for x in prj.projectlayer_equivalent_set()]).filter( @@ -2413,8 +2335,7 @@ if toastermain.settings.MANAGED: final_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset]) - return HttpResponse(jsonfilter( { "error":"ok", "list" : map( _lv_to_dict, sorted(final_list, key = lambda x: x.layer.name)) }), content_type = "application/json") - + return HttpResponse(jsonfilter( { "error":"ok", "list" : map( _lv_to_dict(prj), sorted(final_list, key = lambda x: x.layer.name)) }), content_type = "application/json") # returns layer versions that would be deleted on the new release__pk @@ -2428,7 +2349,7 @@ if toastermain.settings.MANAGED: retval.append(i) return HttpResponse(jsonfilter( {"error":"ok", - "list" : map( _lv_to_dict, map(lambda x: x.layercommit, retval )) + "list" : map( _lv_to_dict(prj), map(lambda x: x.layercommit, retval )) }), content_type = "application/json") @@ -2446,52 +2367,8 @@ if toastermain.settings.MANAGED: # and show only the selected layers for this project final_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset_all]) - return HttpResponse(jsonfilter( { "error":"ok", "list" : map( _lv_to_dict, final_list) }), content_type = "application/json") + return HttpResponse(jsonfilter( { "error":"ok", "list" : map( _lv_to_dict(prj), final_list) }), content_type = "application/json") - # returns targets provided by current project layers - if request.GET.get('type', None) == "targets": - search_token = request.GET.get('search','') - 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)) - -# layer_equivalent_set = [] -# for i in prj.projectlayer_set.all().select_related("layercommit__up_branch", "layercommit__layer"): -# layer_equivalent_set += i.layercommit.get_equivalents_wpriority(prj) - -# queryset_all = queryset_all.filter(layer_version__in = layer_equivalent_set) - - # if we have more than one hit here (for distinct name and version), max the id it out - queryset_all_maxids = queryset_all.values('name').distinct().annotate(max_id=Max('id')).values_list('max_id') - queryset_all = queryset_all.filter(id__in = queryset_all_maxids).order_by("name").select_related("layer_version__layer") - - - return HttpResponse(jsonfilter({ "error":"ok", - "list" : - # 7152 - sort by token position - sorted ( - map ( lambda x: {"id": x.pk, "name": x.name, "detail":"[" + x.layer_version.layer.name +"]"}, - queryset_all[:8]), - key = lambda i: i["name"].find(search_token) if i["name"].find(search_token) > -1 else 9999, - ) - - }), content_type = "application/json") - - # returns machines provided by the current project layers - if request.GET.get('type', None) == "machines": - queryset_all = Machine.objects.all() - if 'project_id' in request.session: - queryset_all = queryset_all.filter(layer_version__in = prj.projectlayer_equivalent_set()).order_by("name") - - search_token = request.GET.get('search','') - queryset_all = queryset_all.filter(Q(name__icontains=search_token) | Q(description__icontains=search_token)) - - return HttpResponse(jsonfilter({ "error":"ok", - "list" : - # 7152 - sort by the token position - sorted ( - map ( lambda x: {"id": x.pk, "name": x.name, "detail":"[" + x.layer_version.layer.name+ "]"}, queryset_all[:8]), - key = lambda i: i["name"].find(search_token) if i["name"].find(search_token) > -1 else 9999, - ) - }), content_type = "application/json") raise Exception("Unknown request! " + request.GET.get('type', "No parameter supplied")) except Exception as e: @@ -2791,7 +2668,41 @@ if toastermain.settings.MANAGED: @_template_renderer('projectbuilds.html') def projectbuilds(request, pid): - buildrequests = BuildRequest.objects.filter(project_id = pid).exclude(state__lte = BuildRequest.REQ_INPROGRESS).exclude(state=BuildRequest.REQ_DELETED) + # process any build request + prj = Project.objects.get(id = pid) + if request.method == "POST": + + if 'buildCancel' in request.POST: + for i in request.POST['buildCancel'].strip().split(" "): + try: + br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_QUEUED) + br.state = BuildRequest.REQ_DELETED + br.save() + except BuildRequest.DoesNotExist: + pass + + if 'buildDelete' in request.POST: + for i in request.POST['buildDelete'].strip().split(" "): + try: + br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_DELETED).delete() + except BuildRequest.DoesNotExist: + pass + + if 'targets' in request.POST: + ProjectTarget.objects.filter(project = prj).delete() + s = str(request.POST['targets']) + for t in s.translate(None, ";%|\"").split(" "): + if ":" in t: + target, task = t.split(":") + else: + target = t + task = "" + ProjectTarget.objects.create(project = prj, target = target, task = task) + + br = prj.schedule_build() + + + buildrequests = BuildRequest.objects.filter(project = prj).exclude(state__lte = BuildRequest.REQ_INPROGRESS).exclude(state=BuildRequest.REQ_DELETED) try: context, pagesize, orderby = _build_list_helper(request, buildrequests, False) @@ -2940,9 +2851,10 @@ if toastermain.settings.MANAGED: # add fields needed in JSON dumps for API call support for p in project_info.object_list: p.id = p.pk - p.xhrProjectDataTypeaheadUrl = reverse('xhr_datatypeahead', args=(p.id,)) p.projectPageUrl = reverse('project', args=(p.id,)) - p.projectBuildUrl = reverse('xhr_projectbuild', args=(p.id,)) + p.projectLayersUrl = reverse('projectlayers', args=(p.id,)) + p.projectBuildsUrl = reverse('projectbuilds', args=(p.id,)) + p.projectTargetsUrl = reverse('projecttargets', args=(p.id,)) # build view-specific information; this is rendered specifically in the builds page, at the top of the page (i.e. Recent builds) build_mru = _managed_get_latest_builds() @@ -3242,14 +3154,6 @@ else: return {} @_template_renderer('landing_not_managed.html') - def xhr_projectbuild(request, pid): - return {} - - @_template_renderer('landing_not_managed.html') - def xhr_datatypeahead(request): - return {} - - @_template_renderer('landing_not_managed.html') def xhr_configvaredit(request, pid): return {} diff --git a/lib/toaster/toastergui/widgets.py b/lib/toaster/toastergui/widgets.py index 8bc3d7f16..f5a1b3e7b 100644 --- a/lib/toaster/toastergui/widgets.py +++ b/lib/toaster/toastergui/widgets.py @@ -253,8 +253,8 @@ class ToasterTable(TemplateView): data = cache.get(cache_name) - if data: - return data + #if data: + # return data self.setup_columns(**kwargs) @@ -277,9 +277,9 @@ class ToasterTable(TemplateView): 'default_orderby' : self.default_orderby, 'columns' : self.columns, 'rows' : [], + 'error' : "ok", } - try: for row in page.object_list: #Use collection to maintain the order diff --git a/lib/toaster/toastermain/settings.py b/lib/toaster/toastermain/settings.py index 225138b32..3c7cb3bc4 100644 --- a/lib/toaster/toastermain/settings.py +++ b/lib/toaster/toastermain/settings.py @@ -223,7 +223,7 @@ CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/tmp/django-default-cache', - 'TIMEOUT': 5, + 'TIMEOUT': 1, } } |