Skip to contentSkip to conversation

please pull Toaster patchset

PATCH New Alex DAMIAN 1 participant 12 messages Nov 20, 2014

lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

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
index 4c6ac5a..75f31d0 100755
@@ -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
#2 lore raw

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
index 8de3b52..0974b90 100644
@@ -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
index 1ae6245..549fda1 100644
@@ -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
#3 lore raw

PATCH 3/11 toastergui: layer name correlation

In reply to Alex DAMIAN

From: 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
index 75f31d0..7511012 100755
@@ -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
index c9af487..6e1f97a 100644
@@ -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
index f2f561b..b965d8e 100644
@@ -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
index 9f9a064..e9b07c7 100644
@@ -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
index 8cb079d..2bca84b 100644
@@ -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
index 4e8a7e2..e1ef824 100644
@@ -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
#4 lore raw

PATCH 4/11 toaster: Create libtoaster.js with some utility functions

In reply to Alex DAMIAN

From: 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
new file mode 100644
index 0000000..b899b8d
@@ -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
index f377081..1b9edfd 100644
@@ -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
#5 lore raw

PATCH 5/11 toaster: libtoaster: Add getProjectInfo utility function

In reply to Alex DAMIAN

From: 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
index b899b8d..4983ef6 100644
@@ -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
index f43bb64..bae7103 100644
@@ -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
index 1b4bb9f..9f214bb 100755
@@ -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
#6 lore raw

PATCH 6/11 toaster: Add New Build Button feature

In reply to Alex DAMIAN

From: 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
index 8e60fd8..6194c97 100644
@@ -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
index bae7103..b60f761 100644
@@ -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
index 9f214bb..a0dcf87 100755
@@ -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
#7 lore raw

PATCH 7/11 toaster: project page remove additional tooltip for Change pencil

In reply to Alex DAMIAN

From: 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
index e1ef824..18a52bf 100644
@@ -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
#8 lore raw

PATCH 8/11 toaster: Tiny refinements to the new build button dialog

In reply to Alex DAMIAN

From: 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
index 6194c97..902a2bd 100644
@@ -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
index 87746bf..734d2ad 100644
@@ -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
#9 lore raw

PATCH 9/11 toaster: add no results state to all layers page

In reply to Alex DAMIAN

From: 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
index 2bca84b..e9f910f 100644
@@ -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
#10 lore raw

PATCH 10/11 toaster: fix dependencies dialog layout

In reply to Alex DAMIAN

From: 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
index 902a2bd..dcb8e34 100644
@@ -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
index e9f910f..4e92332 100644
@@ -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
#11 lore raw

PATCH 11/11 toaster: do not show target if target name is empty

In reply to Alex DAMIAN

From: 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
index 1f938aa..f4313f9 100644
@@ -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