please pull Toaster patchset
cover please pull Toaster patchset
From: Alexandru DAMIAN <[email protected]>
Hi,
This is a Toaster patchset which brings in the New Build Button feature, and a number of fixes for both the frontend and the backend, including compatibility with the upstreamed versions of the toasterconf.json files.
Can you please pull at your convenience ?
Cheers,
Alex
The following changes since commit 40d2ae0723de2bf5fee343faafb4afda40546839:
bitbake-worker: exit normally when SIGHUP (2014-11-20 14:15:28 +0000)
are available in the git repository at:
git://git.yoctoproject.org/poky-contrib adamian/20141120-submission
http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=adamian/20141120-submission
Alexandru DAMIAN (1):
toastergui: layer name correlation
Belen Barros Pena (5):
toaster: fix file name collision
toaster: Tiny refinements to the new build button dialog
toaster: add no results state to all layers page
toaster: fix dependencies dialog layout
toaster: do not show target if target name is empty
Michael Wood (5):
toaster: skip virtualenv when searching for django apps
toaster: Create libtoaster.js with some utility functions
toaster: libtoaster: Add getProjectInfo utility function
toaster: Add New Build Button feature
toaster: project page remove additional tooltip for Change pencil
bin/toaster | 4 +- .../management/commands/checksettings.py | 47 ++- .../bldcontrol/management/commands/loadconf.py | 29 +- ...faultlayer__add_releaselayersourcepriority__.py | 396 +++++++++++++++++++++ lib/toaster/orm/models.py | 115 ++++-- lib/toaster/orm/tests.py | 11 +- lib/toaster/toastergui/static/css/default.css | 8 + lib/toaster/toastergui/static/js/base.js | 125 +++++++ lib/toaster/toastergui/static/js/libtoaster.js | 259 ++++++++++++++ lib/toaster/toastergui/static/js/main.js | 111 ------ lib/toaster/toastergui/static/js/projectapp.js | 2 + lib/toaster/toastergui/templates/base.html | 98 +++-- lib/toaster/toastergui/templates/layers.html | 22 +- lib/toaster/toastergui/templates/project.html | 10 +- lib/toaster/toastergui/templates/targets.html | 2 + lib/toaster/toastergui/urls.py | 4 + lib/toaster/toastergui/views.py | 117 ++++-- lib/toaster/toastermain/settings.py | 4 + lib/toaster/toastermain/urls.py | 4 + 19 files changed, 1123 insertions(+), 245 deletions(-) create mode 100644 lib/toaster/orm/migrations/0017_auto__del_toastersettingdefaultlayer__add_releaselayersourcepriority__.py create mode 100644 lib/toaster/toastergui/static/js/base.js create mode 100644 lib/toaster/toastergui/static/js/libtoaster.js delete mode 100644 lib/toaster/toastergui/static/js/main.js
Signature · 1 line
1.9.1
PATCH 1/11 toaster: fix file name collision
From: Belen Barros Pena <[email protected]>
When toaster is used by multiple users on the same machine, it is possible that files in /tmp have a name race.
This patch makes sure that the files have unique names.
--- bin/toaster | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
bin/toaster +1 -1
@@ -69,7 +69,7 @@ function webserverStartAll() fi if [ $retval -eq 0 ]; then echo "Starting webserver" - python $BBBASEDIR/lib/toaster/manage.py runserver "0.0.0.0:$WEB_PORT" </dev/null >${BUILDDIR}/toaster_web.log 2>&1 & echo $! >${BUILDDIR}/.toastermain.pid + python $BBBASEDIR/lib/toaster/manage.py runserver "0.0.0.0:$WEB_PORT" </dev/null >${BUILDDIR}/toaster_web_$$.log 2>&1 & echo $! >${BUILDDIR}/.toastermain.pid sleep 1 if ! cat "${BUILDDIR}/.toastermain.pid" | xargs -I{} kill -0 {} ; then retval=1
Signature · 1 line
1.9.1
PATCH 2/11 toaster: skip virtualenv when searching for django apps
From: Michael Wood <[email protected]>
If we are using a virtualenv in the current search path we end up trying to add modules to the django apps list which do not have the correct load path or are internal to other modules. Fix this by skipping the virtualenv path.
[YOCTO #6896]
--- lib/toaster/toastermain/settings.py | 4 ++++ lib/toaster/toastermain/urls.py | 4 ++++ 2 files changed, 8 insertions(+)
lib/toaster/toastermain/settings.py +4 -0
@@ -264,6 +264,10 @@ import os currentdir = os.path.dirname(__file__) for t in os.walk(os.path.dirname(currentdir)): modulename = os.path.basename(t[0]) + #if we have a virtualenv skip it to avoid incorrect imports + if os.environ.has_key('VIRTUAL_ENV') and os.environ['VIRTUAL_ENV'] in t[0]: + continue + if ("views.py" in t[2] or "models.py" in t[2]) and not modulename in INSTALLED_APPS: INSTALLED_APPS = INSTALLED_APPS + (modulename,)
lib/toaster/toastermain/urls.py +4 -0
@@ -55,6 +55,10 @@ if toastermain.settings.MANAGED: import os currentdir = os.path.dirname(__file__) for t in os.walk(os.path.dirname(currentdir)): + #if we have a virtualenv skip it to avoid incorrect imports + if os.environ.has_key('VIRTUAL_ENV') and os.environ['VIRTUAL_ENV'] in t[0]: + continue + if "urls.py" in t[2] and t[0] != currentdir: modulename = os.path.basename(t[0]) urlpatterns.append( url(r'^' + modulename + '/', include ( modulename + '.urls')))
Signature · 1 line
1.9.1
PATCH 3/11 toastergui: layer name correlation
In reply to Alex DAMIANFrom: Alexandru DAMIAN <[email protected]>
This patch modifies how layers are identified and matched.
Layers were primarely organized by the source of layer information, and Releases were separated by both layer git branches and originating source of layer information. This setup prevented mixing layers from different sources for a certain release, which didn't match the way people use Yocto Project / bitbake.
This patch brings name-based indentification, where layers with the same name are assumed to be equivalent, in the sense of being able to substitute one another. To facilitate this identification to humans, layers are differentiated by GIT URI instead of layer sources, which was a rather arbitrary abstraction.
Additional changes include modification to models in order accomodate for the new data structure, and to config file loading to match the new toasterconf.json layout.
--- bin/toaster | 2 +- .../management/commands/checksettings.py | 47 ++- .../bldcontrol/management/commands/loadconf.py | 29 +- ...faultlayer__add_releaselayersourcepriority__.py | 396 +++++++++++++++++++++ lib/toaster/orm/models.py | 115 ++++-- lib/toaster/orm/tests.py | 11 +- lib/toaster/toastergui/static/js/projectapp.js | 2 + lib/toaster/toastergui/templates/layers.html | 6 +- lib/toaster/toastergui/templates/project.html | 4 +- lib/toaster/toastergui/views.py | 84 +++-- 10 files changed, 599 insertions(+), 97 deletions(-) create mode 100644 lib/toaster/orm/migrations/0017_auto__del_toastersettingdefaultlayer__add_releaselayersourcepriority__.py
bin/toaster +1 -1
@@ -126,7 +126,6 @@ function notify_chldexit() { } - # Verify prerequisites if ! echo "import django; print (1,) == django.VERSION[0:1] and django.VERSION[1:2][0] in (5,6)" | python 2>/dev/null | grep True >/dev/null; then
@@ -139,6 +138,7 @@ if ! echo "import south; print [0,8,4] == map(int,south.__version__.split(\".\" return 2 fi + # read command line parameters BBBASEDIR=`dirname ${BASH_SOURCE}`/..
lib/toaster/bldcontrol/management/commands/checksettings.py +35 -12
65 lines not on this page · raw message
lib/toaster/bldcontrol/management/commands/loadconf.py +19 -10
@@ -1,6 +1,6 @@ from django.core.management.base import BaseCommand, CommandError from orm.models import LayerSource, ToasterSetting, Branch, Layer, Layer_Version -from orm.models import BitbakeVersion, Release, ReleaseDefaultLayer +from orm.models import BitbakeVersion, Release, ReleaseDefaultLayer, ReleaseLayerSourcePriority import os from checksettings import DN
@@ -71,17 +71,23 @@ class Command(BaseCommand): assert 'name' in lsi assert 'branches' in lsi - if lsi['sourcetype'] == LayerSource.TYPE_LAYERINDEX or lsi['apiurl'].startswith("/"): + def _get_id_for_sourcetype(s): + for i in LayerSource.SOURCE_TYPE: + if s == i[1]: + return i[0] + raise Exception("Could not find definition for sourcetype " + s) + + if _get_id_for_sourcetype(lsi['sourcetype']) == LayerSource.TYPE_LAYERINDEX or lsi['apiurl'].startswith("/"): apiurl = lsi['apiurl'] else: apiurl = self._reduce_canon_path(os.path.join(DN(filepath), lsi['apiurl'])) try: - ls = LayerSource.objects.get(sourcetype = lsi['sourcetype'], apiurl = apiurl) + ls = LayerSource.objects.get(sourcetype = _get_id_for_sourcetype(lsi['sourcetype']), apiurl = apiurl) except LayerSource.DoesNotExist: ls = LayerSource.objects.create( name = lsi['name'], - sourcetype = lsi['sourcetype'], + sourcetype = _get_id_for_sourcetype(lsi['sourcetype']), apiurl = apiurl )
@@ -121,17 +127,20 @@ class Command(BaseCommand): bvo = BitbakeVersion.objects.get(name = ri['bitbake']) assert bvo is not None - ro, created = Release.objects.get_or_create(name = ri['name'], bitbake_version = bvo, branch = Branch.objects.get( layer_source__name = ri['layersource'], name=ri['branch'])) + ro, created = Release.objects.get_or_create(name = ri['name'], bitbake_version = bvo, branch_name = ri['branch']) ro.description = ri['description'] ro.helptext = ri['helptext'] ro.save() + # save layer source priority for release + for ls_name in ri['layersourcepriority'].keys(): + rlspo, created = ReleaseLayerSourcePriority.objects.get_or_create(release = ro, layer_source = LayerSource.objects.get(name=ls_name)) + rlspo.priority = ri['layersourcepriority'][ls_name] + rlspo.save() + for dli in ri['defaultlayers']: - layer, created = Layer.objects.get_or_create( - layer_source = LayerSource.objects.get(name = ri['layersource']), - name = dli - ) - ReleaseDefaultLayer.objects.get_or_create( release = ro, layer = layer) + # find layers with the same name + ReleaseDefaultLayer.objects.get_or_create( release = ro, layer_name = dli) # set default release if ToasterSetting.objects.filter(name = "DEFAULT_RELEASE").count() > 0:
lib/toaster/orm/migrations/0017_auto__del_toastersettingdefaultlayer__add_releaselayersourcepriority__.py new file +396 -0
397 lines not on this page · raw message
lib/toaster/orm/models.py +86 -29
246 lines not on this page · raw message
lib/toaster/orm/tests.py +7 -4
@@ -1,16 +1,19 @@ from django.test import TestCase -from orm.models import LocalLayerSource, LayerIndexLayerSource, LayerSource +from orm.models import LocalLayerSource, LayerIndexLayerSource, ImportedLayerSource, LayerSource from orm.models import Branch class LayerSourceVerifyInheritanceSaveLoad(TestCase): def test_object_creation(self): lls = LayerSource.objects.create(name = "a1", sourcetype = LayerSource.TYPE_LOCAL, apiurl = "") - lils = LayerSource.objects.create(name = "a1", sourcetype = LayerSource.TYPE_LAYERINDEX, apiurl = "") + lils = LayerSource.objects.create(name = "a2", sourcetype = LayerSource.TYPE_LAYERINDEX, apiurl = "") + imls = LayerSource.objects.create(name = "a3", sourcetype = LayerSource.TYPE_IMPORTED, apiurl = "") - print LayerSource.objects.all() + import pprint + pprint.pprint([(x.__class__,vars(x)) for x in LayerSource.objects.all()]) self.assertTrue(True in map(lambda x: isinstance(x, LocalLayerSource), LayerSource.objects.all())) self.assertTrue(True in map(lambda x: isinstance(x, LayerIndexLayerSource), LayerSource.objects.all())) + self.assertTrue(True in map(lambda x: isinstance(x, ImportedLayerSource), LayerSource.objects.all())) def test_duplicate_error(self): def duplicate():
@@ -18,7 +21,7 @@ class LayerSourceVerifyInheritanceSaveLoad(TestCase): LayerSource.objects.create(name = "a1", sourcetype = LayerSource.TYPE_LOCAL, apiurl = "") self.assertRaises(Exception, duplicate) - + class LILSUpdateTestCase(TestCase):
lib/toaster/toastergui/static/js/projectapp.js +2 -0
@@ -173,6 +173,8 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc if (_data.error != "ok") { alert("Failed XHR request (" + _status + "): " + _data.error); console.error("Failed XHR request: ", _data, _status, _headers, _config); + // stop refreshing hte page + $interval.cancel($scope.pollHandle); deffered.reject(_data.error); } else {
lib/toaster/toastergui/templates/layers.html +3 -3
@@ -9,9 +9,9 @@ {% block projectinfomain %} <div class="page-header"> <h1> - {% if request.GET.filter and objects.paginator.count > 0 or request.GET.search and objects.paginator.count > 0 %} - {{objects.paginator.count}} layer{{objects.paginator.count|pluralize}} found - {% elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %} + {% if request.GET.filter and total_count > 0 or request.GET.search and total_count > 0 %} + {{total_count}} layer{{total_count|pluralize}} found + {% elif request.GET.filter and total_count == 0 or request.GET.search and total_count == 0 %} No layers found {%else%} All layers
lib/toaster/toastergui/templates/project.html +2 -2
@@ -236,9 +236,9 @@ vim: expandtab tabstop=2 <p><a href="{% url 'layers' %}">View all layers</a> | <a href="{% url 'importlayer' %}">Import layer</a></p> <ul class="unstyled configuration-list"> <li ng-repeat="l in layers track by l.id" class="animate-repeat"> - <a href="{[l.layerdetailurl]}" target="_#" class="layer-info" data-toggle="tooltip" tooltip="{[l.branch.layersource]} | {[l.branch.name]}">{[l.name]} </a> + <a href="{[l.layerdetailurl]}" target="_#" class="layer-info" data-toggle="tooltip" tooltip="{[l.giturl]} | {[l.branch.name]}">{[l.name]}</a> <i class="icon-trash" ng-click="layerDel(l.id)" tooltip="Delete"></i> - </li> + </li> </ul> </div>
lib/toaster/toastergui/views.py +48 -36
190 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH 4/11 toaster: Create libtoaster.js with some utility functions
In reply to Alex DAMIANFrom: Michael Wood <[email protected]>
Replace main.js with libtoaster. This can be a place for common functionality for toaster. Calling it lib... makes it more obvious as well as helps with code readability due to the namespacing.
--- lib/toaster/toastergui/static/js/libtoaster.js | 237 +++++++++++++++++++++++++ lib/toaster/toastergui/static/js/main.js | 111 ------------ lib/toaster/toastergui/templates/base.html | 29 +-- 3 files changed, 239 insertions(+), 138 deletions(-) create mode 100644 lib/toaster/toastergui/static/js/libtoaster.js delete mode 100644 lib/toaster/toastergui/static/js/main.js
lib/toaster/toastergui/static/js/libtoaster.js new file +237 -0
@@ -0,0 +1,237 @@ + +/* All shared functionality to go in libtoaster object. + * This object really just helps readability since we can then have + * a traceable namespace. + */ +var libtoaster = (function (){ + + /* makeTypeahead parameters + * elementSelector: JQuery elementSelector string + * xhrUrl: the url to get the JSON from expects JSON in the form: + * { "list": [ { "name": "test", "detail" : "a test thing" }, .... ] } + * xhrParams: the data/parameters to pass to the getJSON url e.g. + * { 'type' : 'projects' } the text typed will be passed as 'value'. + * selectedCB: function to call once an item has been selected one + * arg of the item. + */ + function _makeTypeahead (jQElement, xhrUrl, xhrParams, selectedCB) { + + jQElement.typeahead({ + source: function(query, process){ + xhrParams.value = query; + $.getJSON(xhrUrl, this.options.xhrParams, function(data){ + return process (data.list); + }); + }, + updater: function(item) { + var itemObj = this.$menu.find('.active').data('itemObject'); + selectedCB(itemObj); + return item; + }, + matcher: function(item) { return ~item.name.toLowerCase().indexOf(this.query.toLowerCase()); }, + highlighter: function (item) { + if (item.hasOwnProperty('detail')) + /* Use jquery to escape the value as text into a span */ + return $('<span></span>').text(item.name+' '+item.detail).get(0); + return $('<span></span>').text(item.name).get(0); + }, + sorter: function (items) { return items; }, + xhrUrl: xhrUrl, + xhrParams: xhrParams, + }); + + + /* Copy of bootstrap's render func but sets selectedObject value */ + function customRenderFunc (items) { + var that = this; + + items = $(items).map(function (i, item) { + i = $(that.options.item).attr('data-value', item.name).data('itemObject', item); + i.find('a').html(that.highlighter(item)); + return i[0]; + }); + + items.first().addClass('active'); + this.$menu.html(items); + return this; + } + + jQElement.data('typeahead').render = customRenderFunc; + }; + + /* + * url - the url of the xhr build */ + function _startABuild (url, project_id, targets, onsuccess, onfail) { + var data; + + if (project_id) + data = 'project_id='+project_id+'&targets='+targets; + else + data = 'targets='+targets; + + $.ajax( { + type: "POST", + url: url, + data: data, + headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, + success: function (_data) { + if (_data.error != "ok") { + console.log(_data.error); + } else { + if (onsuccess != undefined) onsuccess(_data); + } + }, + error: function (_data) { + console.log("Call failed"); + console.log(_data); + if (onfail) onfail(data); + } }); + }; + + return { + reload_params : reload_params, + startABuild : _startABuild, + makeTypeahead : _makeTypeahead, + } +})(); + +/* keep this in the global scope for compatability */ +function reload_params(params) { + uri = window.location.href; + splitlist = uri.split("?"); + url = splitlist[0], parameters=splitlist[1]; + // deserialize the call parameters + if(parameters){ + cparams = parameters.split("&"); + }else{ + cparams = [] + } + nparams = {} + for (i = 0; i < cparams.length; i++) { + temp = cparams[i].split("="); + nparams[temp[0]] = temp[1]; + } + // update parameter values + for (i in params) { + nparams[encodeURIComponent(i)] = encodeURIComponent(params[i]); + } + // serialize the structure + callparams = [] + for (i in nparams) { + callparams.push(i+"="+nparams[i]); + } + window.location.href = url+"?"+callparams.join('&'); +} + + +/* Things that happen for all pages */ +$(document).ready(function() { + + /* + * PrettyPrint plugin. + * + */ + // Init + prettyPrint(); + + // Prevent invalid links from jumping page scroll + $('a[href=#]').click(function() { + return false; + }); + + + /* Belen's additions */ + + // turn Edit columns dropdown into a multiselect menu + $('.dropdown-menu input, .dropdown-menu label').click(function(e) { + e.stopPropagation(); + }); + + // enable popovers in any table cells that contain an anchor with the + // .btn class applied, and make sure popovers work on click, are mutually + // exclusive and they close when your click outside their area + + $('html').click(function(e){ + $('td > a.btn').popover('hide'); + }); + + $('td > a.btn').popover({ + html:true, + placement:'left', + container:'body', + trigger:'manual' + }).click(function(e){ + $('td > a.btn').not(this).popover('hide'); + // ideally we would use 'toggle' here + // but it seems buggy in our Bootstrap version + $(this).popover('show'); + e.stopPropagation(); + }); + + // enable tooltips for applied filters + $('th a.btn-primary').tooltip({container:'body', html:true, placement:'bottom', delay:{hide:1500}}); + + // hide applied filter tooltip when you click on the filter button + $('th a.btn-primary').click(function () { + $('.tooltip').hide(); + }); + + // enable help information tooltip + $(".get-help").tooltip({container:'body', html:true, delay:{show:300}}); + + // show help bubble only on hover inside tables + $(".hover-help").css("visibility","hidden"); + $("th, td").hover(function () { + $(this).find(".hover-help").css("visibility","visible"); + }); + $("th, td").mouseleave(function () { + $(this).find(".hover-help").css("visibility","hidden"); + }); + + // show task type and outcome in task details pages + $(".task-info").tooltip({ container: 'body', html: true, delay: {show: 200}, placement: 'right' }); + + // linking directly to tabs + $(function(){ + var hash = window.location.hash; + hash && $('ul.nav a[href="' + hash + '"]').tab('show'); + + $('.nav-tabs a').click(function (e) { + $(this).tab('show'); + $('body').scrollTop(); + }); + }); + + // toggle for long content (variables, python stack trace, etc) + $('.full, .full-hide').hide(); + $('.full-show').click(function(){ + $('.full').slideDown(function(){ + $('.full-hide').show(); + }); + $(this).hide(); + }); + $('.full-hide').click(function(){ + $(this).hide(); + $('.full').slideUp(function(){ + $('.full-show').show(); + }); + }); + + //toggle the errors and warnings sections + $('.show-errors').click(function() { + $('#collapse-errors').addClass('in'); + }); + $('.toggle-errors').click(function() { + $('#collapse-errors').toggleClass('in'); + }); + $('.show-warnings').click(function() { + $('#collapse-warnings').addClass('in'); + }); + $('.toggle-warnings').click(function() { + $('#collapse-warnings').toggleClass('in'); + }); + //show warnings section when requested from the previous page + if (location.href.search('#warnings') > -1) { + $('#collapse-warnings').addClass('in'); + } +});
lib/toaster/toastergui/static/js/main.js deleted +0 -111
111 lines not on this page · raw message
lib/toaster/toastergui/templates/base.html +2 -27
@@ -18,36 +18,11 @@ </script> <script src="{% static 'js/prettify.js' %}"> </script> -<script src="{% static 'js/main.js' %}"> +<script src="{% static 'js/libtoaster.js' %}"> +</script> </script> <script> -function reload_params(params) { - uri = window.location.href; - splitlist = uri.split("?"); - url = splitlist[0], parameters=splitlist[1]; - // deserialize the call parameters - if(parameters){ - cparams = parameters.split("&"); - }else{ - cparams = [] - } - nparams = {} - for (i = 0; i < cparams.length; i++) { - temp = cparams[i].split("="); - nparams[temp[0]] = temp[1]; - } - // update parameter values - for (i in params) { - nparams[encodeURIComponent(i)] = encodeURIComponent(params[i]); - } - // serialize the structure - callparams = [] - for (i in nparams) { - callparams.push(i+"="+nparams[i]); - } - window.location.href = url+"?"+callparams.join('&'); -} </script> {% block extraheadcontent %}
Signature · 1 line
1.9.1
PATCH 5/11 toaster: libtoaster: Add getProjectInfo utility function
In reply to Alex DAMIANFrom: Michael Wood <[email protected]>
Add a utility function to return a specified project's info/config This re-uses the existing server code path for the project edit except that it allows any project id to be used as a parameter
--- lib/toaster/toastergui/static/js/libtoaster.js | 22 ++++++++++++++++++++++ lib/toaster/toastergui/urls.py | 1 + lib/toaster/toastergui/views.py | 5 ++++- 3 files changed, 27 insertions(+), 1 deletion(-)
lib/toaster/toastergui/static/js/libtoaster.js +22 -0
@@ -88,10 +88,32 @@ var libtoaster = (function (){ } }); }; + /* Get a project's configuration info */ + function _getProjectInfo(url, projectId, onsuccess, onfail){ + $.ajax({ + type: "POST", + url: url, + data: { project_id : projectId }, + headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, + success: function (_data) { + if (_data.error != "ok") { + console.log(_data.error); + } else { + if (onsuccess != undefined) onsuccess(_data); + } + }, + error: function (_data) { + console.log(_data); + if (onfail) onfail(data); + } + }); + }; + return { reload_params : reload_params, startABuild : _startABuild, makeTypeahead : _makeTypeahead, + getProjectInfo: _getProjectInfo, } })();
lib/toaster/toastergui/urls.py +1 -0
@@ -85,6 +85,7 @@ urlpatterns = patterns('toastergui.views', url(r'^project/(?P<pid>\d+)/builds$', 'projectbuilds', name='projectbuilds'), url(r'^xhr_projectbuild/(?P<pid>\d+)/$', 'xhr_projectbuild', name='xhr_projectbuild'), + url(r'^xhr_projectinfo/$', 'xhr_projectinfo', name='xhr_projectinfo'), url(r'^xhr_projectedit/(?P<pid>\d+)/$', 'xhr_projectedit', name='xhr_projectedit'), url(r'^xhr_datatypeahead/$', 'xhr_datatypeahead', name='xhr_datatypeahead'),
lib/toaster/toastergui/views.py +4 -1
@@ -2057,8 +2057,11 @@ if toastermain.settings.MANAGED: except Exception as e: return HttpResponse(jsonfilter({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") + def xhr_projectinfo(request): + if request.POST.has_key("project_id") == False: + raise BadParameterException("invalid project id") - + return xhr_projectedit(request, request.POST['project_id']) def xhr_projectedit(request, pid): try:
Signature · 1 line
1.9.1
PATCH 6/11 toaster: Add New Build Button feature
In reply to Alex DAMIANFrom: Michael Wood <[email protected]>
This adds a quick access dropdown menu feature for running builds on a selected project.
[YOCTO #6677]
--- lib/toaster/toastergui/static/css/default.css | 4 + lib/toaster/toastergui/static/js/base.js | 125 ++++++++++++++++++++++++++ lib/toaster/toastergui/templates/base.html | 69 ++++++++++++-- lib/toaster/toastergui/urls.py | 3 + lib/toaster/toastergui/views.py | 32 ++++++- 5 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 lib/toaster/toastergui/static/js/base.js
lib/toaster/toastergui/static/css/default.css +4 -0
@@ -131,6 +131,10 @@ select { width: auto; } /* make tables Chrome-happy (me, not so much) */ #otable { table-layout: fixed; word-wrap: break-word; } +/* styles for the new build button */ +.new-build .btn-primary { padding: 4px 30px; } +#view-all-projects { display: block; } + /* Configuration styles */ .icon-trash { color: #B94A48; font-size: 16px; padding-left: 2px; } .icon-trash:hover { color: #943A38; text-decoration: none; cursor: pointer; }
lib/toaster/toastergui/static/js/base.js new file +125 -0
125 lines not on this page · raw message
lib/toaster/toastergui/templates/base.html +64 -5
92 lines not on this page · raw message
lib/toaster/toastergui/urls.py +3 -0
@@ -80,10 +80,13 @@ urlpatterns = patterns('toastergui.views', url(r'^machines/$', 'machines', name='machines'), url(r'^projects/$', 'projects', name='all-projects'), + + url(r'^project/$', 'project', name='project'), url(r'^project/(?P<pid>\d+)/$', 'project', name='project'), url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'), url(r'^project/(?P<pid>\d+)/builds$', 'projectbuilds', name='projectbuilds'), + url(r'^xhr_build/$', 'xhr_build', name='xhr_build'), url(r'^xhr_projectbuild/(?P<pid>\d+)/$', 'xhr_projectbuild', name='xhr_projectbuild'), url(r'^xhr_projectinfo/$', 'xhr_projectinfo', name='xhr_projectinfo'), url(r'^xhr_projectedit/(?P<pid>\d+)/$', 'xhr_projectedit', name='xhr_projectedit'),
lib/toaster/toastergui/views.py +31 -1
@@ -2015,10 +2015,20 @@ if toastermain.settings.MANAGED: response['Pragma'] = "no-cache" return response + # This is a wrapper for xhr_projectbuild which allows for a project id + # which only becomes known client side. + def xhr_build(request): + if request.POST.has_key("project_id"): + pid = request.POST['project_id'] + return xhr_projectbuild(request, pid) + else: + raise BadParameterException("invalid project id") + def xhr_projectbuild(request, pid): try: if request.method != "POST": raise BadParameterException("invalid method") + request.session['project_id'] = pid prj = Project.objects.get(id = pid)
@@ -2057,6 +2067,8 @@ if toastermain.settings.MANAGED: except Exception as e: return HttpResponse(jsonfilter({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") + # This is a wraper for xhr_projectedit which allows for a project id + # which only becomes known client side def xhr_projectinfo(request): if request.POST.has_key("project_id") == False: raise BadParameterException("invalid project id")
@@ -2121,8 +2133,12 @@ if toastermain.settings.MANAGED: def xhr_datatypeahead(request): try: prj = None - if 'project_id' in request.session: + if request.GET.has_key('project_id'): + prj = Project.objects.get(pk = request.GET['project_id']) + elif 'project_id' in request.session: prj = Project.objects.get(pk = request.session['project_id']) + else: + raise Exception("No valid project selected") # returns layers for current project release that are not in the project set if request.GET['type'] == "layers":
@@ -2188,6 +2204,14 @@ if toastermain.settings.MANAGED: }), content_type = "application/json") + if request.GET['type'] == "projects": + queryset_all = Project.objects.all() + ret = { "error": "ok", + "list": map (lambda x: {"id":x.pk, "name": x.name}, + queryset_all.filter(name__icontains=request.GET.get('value',''))[:8])} + + return HttpResponse(jsonfilter(ret), content_type = "application/json") + raise Exception("Unknown request! " + request.GET.get('type', "No parameter supplied")) except Exception as e: return HttpResponse(jsonfilter({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
@@ -2773,6 +2797,12 @@ else: def xhr_projectbuild(request, pid): raise Exception("page not available in interactive mode") + def xhr_build(request, pid): + raise Exception("page not available in interactive mode") + + def xhr_projectinfo(request, pid): + raise Exception("page not available in interactive mode") + def xhr_projectedit(request, pid): raise Exception("page not available in interactive mode")
Signature · 1 line
1.9.1
PATCH 7/11 toaster: project page remove additional tooltip for Change pencil
In reply to Alex DAMIANFrom: Michael Wood <[email protected]>
We have a global pencil icon tooltip so avoid two tooltips appearing by removing them from the project page. This also means it's one less place to update it.
--- lib/toaster/toastergui/templates/project.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
lib/toaster/toastergui/templates/project.html +3 -3
@@ -281,7 +281,7 @@ vim: expandtab tabstop=2 </h3> <p class="lead" id="select-machine-opposite"> <span>{[machine.name]}</span> - <i id="change-machine" class="icon-pencil" ng-click="toggle('#select-machine')" tooltip="Change"></i> + <i id="change-machine" class="icon-pencil" ng-click="toggle('#select-machine')"></i> </p> <div id="select-machine" style="display: none"> <div class="alert alert-info">
@@ -318,7 +318,7 @@ vim: expandtab tabstop=2 <h3>Project name</h3> <p class="lead" id="change-project-name-opposite"> <span >{[project.name]}</span> - <i class="icon-pencil" ng-click="toggle('#change-project-name')" tooltip="Change"></i> + <i class="icon-pencil" ng-click="toggle('#change-project-name')" ></i> </p> <div id="change-project-name" style="display:none;"> <form ng-submit="edit('#change-project-name')" class="input-append">
@@ -335,7 +335,7 @@ vim: expandtab tabstop=2 </h3> <p class="lead" id="change-project-version-opposite"> <span id="project-version">{[project.release.name]}</span> - <i id="change-version" class="icon-pencil" ng-click="toggle('#change-project-version')" tooltip="Change"></i> + <i id="change-version" class="icon-pencil" ng-click="toggle('#change-project-version')" ></i> </p> <div class="div-inline" id="change-project-version" style="display:none;"> <form ng-submit="test('#change-project-version')" class="input-append">
Signature · 1 line
1.9.1
PATCH 8/11 toaster: Tiny refinements to the new build button dialog
In reply to Alex DAMIANFrom: Belen Barros Pena <[email protected]>
* Get rid of the display:block attribute for the "View all projects" link, to stop it from firing when you click outside (but next to) the link
* Give some margin to the incomplete configuration alert
--- lib/toaster/toastergui/static/css/default.css | 3 ++- lib/toaster/toastergui/templates/base.html | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-)
lib/toaster/toastergui/static/css/default.css +2 -1
@@ -133,7 +133,8 @@ select { width: auto; } /* styles for the new build button */ .new-build .btn-primary { padding: 4px 30px; } -#view-all-projects { display: block; } +.new-build .alert { margin-top: 10px; } +.new-build .alert p { margin-top: 10px; } /* Configuration styles */ .icon-trash { color: #B94A48; font-size: 16px; padding-left: 2px; }
lib/toaster/toastergui/templates/base.html +2 -2
@@ -81,12 +81,12 @@ <button id="save-project-button" class="btn" type="button">Save</button> <a href="#" id="cancel-change-project" class="btn btn-link">Cancel</a> </div> - <a id="view-all-projects" href="{% url 'all-projects' %}">View all projects</a> + <p><a id="view-all-projects" href="{% url 'all-projects' %}">View all projects</a></p> </form> </li> <div class="alert" style="display:none"> This project's configuration is incomplete,<br/>so you cannot run builds.<br/> - <a href="{% if project.id %}{% url 'project' project.id %}{% endif %}">View project configuration</a> + <p><a href="{% if project.id %}{% url 'project' project.id %}{% endif %}">View project configuration</a></p> </div> <li id="targets-form"> <h6>Target(s):</h6>
Signature · 1 line
1.9.1
PATCH 9/11 toaster: add no results state to all layers page
In reply to Alex DAMIANFrom: Belen Barros Pena <[email protected]>
When you search for a layer and your search returns no results, we should show you an alert and a link to show back all layers, as we do in all other tables.
--- lib/toaster/toastergui/templates/layers.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
lib/toaster/toastergui/templates/layers.html +14 -0
@@ -23,6 +23,18 @@ <div id="zone1alerts"> </div> +{% if objects.paginator.count == 0 %} + <div class="row-fluid"> + <div class="alert"> + <form class="no-results input-append" id="searchform"> + <input id="search" name="search" class="input-xxlarge" type="text" value="{{request.GET.search}}"/>{% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" class="add-on btn" tabindex="-1"><i class="icon-remove"></i></a>{% endif %} + <button class="btn" type="submit" value="Search">Search</button> + <button class="btn btn-link" onclick="javascript:$('#search').val('');searchform.submit()">Show all layers</button> + </form> + </div> + </div> + +{% else %} {% include "basetable_top_layers.html" %} {% for o in objects %}
@@ -264,4 +276,6 @@ $(document).ready(function (){ </script> {%endif%} +{%endif%} + {% endblock %}
Signature · 1 line
1.9.1
PATCH 10/11 toaster: fix dependencies dialog layout
In reply to Alex DAMIANFrom: Belen Barros Pena <[email protected]>
Remove the bottom margin of forms inside dependencies modal dialogs.
--- lib/toaster/toastergui/static/css/default.css | 3 +++ lib/toaster/toastergui/templates/layers.html | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-)
lib/toaster/toastergui/static/css/default.css +3 -0
@@ -136,6 +136,9 @@ select { width: auto; } .new-build .alert { margin-top: 10px; } .new-build .alert p { margin-top: 10px; } +/* Remove bottom margin for forms inside modal dialogs */ +#dependencies_modal_form { margin-bottom: 0px; } + /* Configuration styles */ .icon-trash { color: #B94A48; font-size: 16px; padding-left: 2px; } .icon-trash:hover { color: #943A38; text-decoration: none; cursor: pointer; }
lib/toaster/toastergui/templates/layers.html +1 -1
@@ -89,7 +89,7 @@ <!-- 'Layer dependencies modal' --> <div id="dependencies_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-hidden="true"> - <form id="dependencies_modal_form" style="margin: 0px"> + <form id="dependencies_modal_form"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button> <h3><span class="layer-name"></span> dependencies</h3>
Signature · 1 line
1.9.1
PATCH 11/11 toaster: do not show target if target name is empty
In reply to Alex DAMIANFrom: Belen Barros Pena <[email protected]>
In the all targets table, all entries should have a target name. If a target does not have a name, something has not gone to plan, so don't show it.
--- lib/toaster/toastergui/templates/targets.html | 2 ++ 1 file changed, 2 insertions(+)
lib/toaster/toastergui/templates/targets.html +2 -0
@@ -39,6 +39,7 @@ {% include "basetable_top.html" %} {% for o in objects %} + {% if o.name %} <tr class="data"> <td class="target"> {{o.name}}
@@ -78,6 +79,7 @@ </a> </td> </tr> + {% endif %} {% endfor %} {% include "basetable_bottom.html" %}
Signature · 1 line
1.9.1