Skip to contentSkip to conversation

toaster: Add layer details page feature

PATCH In review Alex DAMIAN 2 participants 6 messages Jan 14, 2015

lore
Share & tools
lore
#0 lore raw

PATCH 1/4 toaster: Add layer details page feature

From: Michael Wood <[email protected]>

This commit adds the layer details page which shows the metadata for the layer such as layer description, machines associated with the layer as well as the targets provided.
If the layer is an imported layer this page also allows you to update the layer's configuration.
From this page you can add/remove the layer from the current project

---
 lib/toaster/toastergui/static/css/default.css      |   1 +
 lib/toaster/toastergui/static/js/layerdetails.js   | 404 +++++++++++++
 lib/toaster/toastergui/static/js/libtoaster.js     |  35 ++
 lib/toaster/toastergui/templates/layerdetails.html | 644 ++++++++++++++++-----
 .../toastergui/templates/layers_dep_modal.html     |   9 +
 lib/toaster/toastergui/urls.py                     |   1 +
 lib/toaster/toastergui/views.py                    |  94 ++-
 7 files changed, 1038 insertions(+), 150 deletions(-)
 create mode 100644 lib/toaster/toastergui/static/js/layerdetails.js
lib/toaster/toastergui/static/css/default.css +1 -0
index 199c753..a3fa0dd 100644
@@ -232,3 +232,4 @@ dd > span { line-height: 20px; }
 .animate-repeat.ng-enter.ng-enter-active {
   opacity:1;
 }
+.tab-pane table { margin-top: 10px; }
lib/toaster/toastergui/static/js/layerdetails.js new file +404 -0

404 lines not on this page · raw message

lib/toaster/toastergui/static/js/libtoaster.js +35 -0
index a2a0abd..04264cd 100644
@@ -161,6 +161,39 @@ var libtoaster = (function (){
     });
   };
 
+  /* parses the query string of the current window.location to an object */
+  function _parseUrlParams() {
+    string = window.location.search
+    string = string.substr(1);
+    stringArray = string.split ("&");
+    obj = {};
+
+    for (i in stringArray) {
+      keyVal = stringArray[i].split ("=");
+      obj[keyVal[0]] = keyVal[1];
+    }
+
+    return obj;
+  };
+
+  /* takes a flat object and outputs it as a query string
+   * e.g. the output of dumpsUrlParams
+   */
+  function _dumpsUrlParams(obj) {
+    var str = "?";
+
+    for (key in obj){
+      if (!obj[key])
+        continue;
+
+      str += key+ "="+obj[key].toString();
+      str += "&";
+    }
+
+    return str;
+  };
+
+
   return {
     reload_params : reload_params,
     startABuild : _startABuild,
@@ -169,6 +202,8 @@ var libtoaster = (function (){
     getLayerDepsForProject : _getLayerDepsForProject,
     editProject : _editProject,
     debug: false,
+    parseUrlParams : _parseUrlParams,
+    dumpsUrlParams : _dumpsUrlParams,
   }
 })();
 
lib/toaster/toastergui/templates/layerdetails.html +495 -149

654 lines not on this page · raw message

lib/toaster/toastergui/templates/layers_dep_modal.html +9 -0
index b03fd0b..8222027 100644
@@ -18,7 +18,16 @@
     </div>
 
 <script>
+  /* projectId: current project
+   * layer: Object representing the parent layer { id: .. name: ... url }
+   * dependencies: array of dependency layer objects { id: .. name: ..}
+   * title: optional override for title
+   * body: optional override for body
+   * addToProject: Whether to add layers to project on accept
+   * successAdd: function to run on success
+   */
 function show_layer_deps_modal(projectId, layer, dependencies, title, body, addToProject, successAdd) {
+
     // update layer name
     if (title) {
       $('#dependencies_modal #title').text(title);
lib/toaster/toastergui/urls.py +1 -0
index 6e1b0ab..5c969f8 100644
@@ -94,6 +94,7 @@ urlpatterns = patterns('toastergui.views',
 
         url(r'^xhr_datatypeahead/$', 'xhr_datatypeahead', name='xhr_datatypeahead'),
         url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'),
+        url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'),
 
 
         # default redirection
lib/toaster/toastergui/views.py +93 -1

110 lines not on this page · raw message

Signature · 1 line
1.9.1
#1 lore raw

PATCH 2/4 toaster: layerdetails Remove compatibility setting

From: Michael Wood <[email protected]>

Remove the layer compatibility configuration option from the layer details as this is not in the design.

---
 lib/toaster/toastergui/static/js/layerdetails.js   | 10 ++--------
 lib/toaster/toastergui/templates/layerdetails.html | 21 +--------------------
 lib/toaster/toastergui/views.py                    |  1 -
 3 files changed, 3 insertions(+), 29 deletions(-)
lib/toaster/toastergui/static/js/layerdetails.js +2 -8
index a5a6330..41cbf4b 100644
@@ -309,8 +309,6 @@ function layerDetailsPageInit (ctx) {
     var entryElement = mParent.find("input");
     if (entryElement.length == 0)
       entryElement = mParent.find("textarea");
-    if (entryElement.length == 0)
-      entryElement = mParent.find("select");
     if (entryElement.length == 0) {
       console.warn("Could not find element to get data from for this change");
       return;
@@ -331,12 +329,8 @@ function layerDetailsPageInit (ctx) {
             /* success layer property changed */
             var inputArea = mParent.parents("dd");
             var text;
-            /* We don't actually want the value from the select option we want
-             * the text that represents the value to display
-             */
-            text = entryElement.children("option:selected").text();
-            if (!text)
-              text = entryElement.val();
+
+            text = entryElement.val();
 
             /* Hide the "Not set" text if it's visible */
             inputArea.find(".muted").hide();
lib/toaster/toastergui/templates/layerdetails.html +1 -20
index c69f9e9..5bed0f8 100644
@@ -160,26 +160,7 @@
                     </form>
                     <i class="icon-pencil"></i>
                   </dd>
-                  <dt>
-                    <i class="icon-question-sign get-help" title="The Yocto Project versions with which this layer is compatible. Currently Toaster supports Yocto Project 1.6 and 1.7"></i>
-                    Yocto Project compatibility
-                  </dt>
-                  <dd>
-                    <span class="current-value">{{layerversion.up_branch.name}}</span>
-                    <form style="display:none">
-                      <div class="input-append">
-                        <select name="projectversion" id="projectversion">
-                          {% for compat in yocto_compat %}
-                          <option value="{{compat.id}}" {%if layerversion.up_branch.id == compat.id %} selected{%endif%}>{{compat.name}}</option>
-                          {% endfor %}
-                        </select>
-                        <button  data-layer-prop="up_branch" class="btn change-btn" type="button">Save</button>
-                        <a href="#" style="display:none" class="btn btn-link cancel">Cancel</a>
-                      </div>
-                    </form>
-                    <i class="icon-pencil"></i>
-                  </dd>
-                  <dt>
+                 <dt>
                     <i class="icon-question-sign get-help" title="Other layers this layer depends upon"></i>
                     Layer dependencies
                   </dt>
lib/toaster/toastergui/views.py +0 -1
index 7a9d662..e414b66 100755
@@ -2524,7 +2524,6 @@ if toastermain.settings.MANAGED:
         context = {
             'layerversion': layer_version,
             'layer_in_project' : ProjectLayer.objects.filter(project_id=request.session['project_id'],layercommit=layerid).count(),
-            'yocto_compat': Branch.objects.filter(layer_source=layer_version.layer_source),
             'machines': machines,
             'targets': targets,
             'total_targets': Recipe.objects.filter(layer_version=layer_version).count(),
Signature · 1 line
1.9.1
#2 lore raw

PATCH 3/4 toastergui: all builds page lists failed build requests

In reply to Alex DAMIAN

From: Alexandru DAMIAN <[email protected]>

This patch modifies the all builds page by splitting the page into two variants - the "interactive" (default) and "managed" mode versions.

In the "managed" mode version, we display build requests instead of builds, including the failed build requests that have no build associated with them.

[YOCTO #6671]

---
 .../toastergui/templates/managed_builds.html       | 135 +++++
 .../toastergui/templates/managed_mrb_section.html  | 172 ++++++
 lib/toaster/toastergui/templatetags/projecttags.py |  19 +
 lib/toaster/toastergui/views.py                    | 615 ++++++++++++++-------
 4 files changed, 742 insertions(+), 199 deletions(-)
 create mode 100644 lib/toaster/toastergui/templates/managed_builds.html
 create mode 100644 lib/toaster/toastergui/templates/managed_mrb_section.html
lib/toaster/toastergui/templates/managed_builds.html new file +135 -0
new file mode 100644
index 0000000..5944dc4
@@ -0,0 +1,135 @@
+{% extends "base.html" %}
+
+{% load static %}
+{% load projecttags %}
+{% load humanize %}
+
+{% block pagecontent %}
+<div class="row-fluid">
+
+  {% include "managed_mrb_section.html" %}
+
+
+  {% if 1 %}
+  <div class="page-header top-air">
+     <h1>
+      {% if request.GET.filter and objects.paginator.count > 0 or request.GET.search and objects.paginator.count > 0 %}
+          {{objects.paginator.count}} build{{objects.paginator.count|pluralize}} found
+      {%elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %}
+          No builds found
+      {%else%}
+          All builds
+      {%endif%}
+     </h1>
+  </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 builds</button>
+        </form>
+      </div>
+    </div>
+
+
+  {% else %}
+  {% include "basetable_top_buildprojects.html" %}
+        <!-- Table data rows; the order needs to match the order of "tablecols" definitions; and the <td class value needs to match the tablecols clclass value for show/hide buttons to work -->
+        {% for br in objects %}{% if br.build %}  {% with build=br.build %} {# if we have a build, just display it #}
+        <tr class="data">
+            <td class="outcome"><a href="{% url "builddashboard" build.id %}">{%if build.outcome == build.SUCCEEDED%}<i class="icon-ok-sign success"></i>{%elif build.outcome == build.FAILED%}<i class="icon-minus-sign error"></i>{%else%}{%endif%}</a></td>
+            <td class="target">{% for t in build.target_set.all %} <a href="{% url "builddashboard" build.id %}"> {{t.target}} </a> <br />{% endfor %}</td>
+            <td class="machine"><a href="{% url "builddashboard" build.id %}">{{build.machine}}</a></td>
+            <td class="started_on"><a href="{% url "builddashboard" build.id %}">{{build.started_on|date:"d/m/y H:i"}}</a></td>
+            <td class="completed_on"><a href="{% url "builddashboard" build.id %}">{{build.completed_on|date:"d/m/y H:i"}}</a></td>
+            <td class="failed_tasks error">
+                {% query build.task_build outcome=4 order__gt=0 as exectask%}
+                    {% if exectask.count == 1 %}
+                        <a href="{% url "task" build.id exectask.0.id %}">{{exectask.0.recipe.name}}.{{exectask.0.task_name}}</a>
+                      {% if MANAGED and build.project %}
+                        <a href="{% url 'build_artifact' build.id "tasklogfile" exectask.0.id %}">
+                            <i class="icon-download-alt" title="" data-original-title="Download task log file"></i>
+                        </a>
+                      {% endif %}
+                    {% elif exectask.count > 1%}
+                        <a href="{% url "tasks" build.id %}?filter=outcome%3A4">{{exectask.count}} task{{exectask.count|pluralize}}</a>
+                    {%endif%}
+            </td>
+            <td class="errors_no">
+                {% if  build.errors_no %}
+                    <a class="errors_no error" href="{% url "builddashboard" build.id %}#errors">{{build.errors_no}} error{{build.errors_no|pluralize}}</a>
+                    {% if MANAGED and build.project %}
+                        <a href="{% url 'build_artifact' build.id "cookerlog" build.id %}">
+                            <i class="icon-download-alt" title="" data-original-title="Download build log"></i>
+                        </a>
+                    {% endif %}
+                {%endif%}
+            </td>
+            <td class="warnings_no">{% if  build.warnings_no %}<a class="warnings_no warning" href="{% url "builddashboard" build.id %}#warnings">{{build.warnings_no}} warning{{build.warnings_no|pluralize}}</a>{%endif%}</td>
+            <td class="time"><a href="{% url "buildtime" build.id %}">{{build.timespent|sectohms}}</a></td>
+            {% if not MANAGED or not build.project %}
+                <td class="log">{{build.cooker_log_path}}</td>
+            {% endif %}
+            <td class="output">
+              {% if build.outcome == build.SUCCEEDED %}
+              <a href="{%url "builddashboard" build.id%}#images">{{fstypes|get_dict_value:build.id}}</a>
+              {% endif %}
+            </td>
+   {% if MANAGED %}
+            <td class="project">
+            {% if build.project %}
+                <a href="{% url 'project' build.project.id %}">{{build.project.name}}</a>
+            {% endif %}
+            </td>
+   {% endif %}
+        </tr>
+
+
+              {%endwith%}
+      {% else %} {# we don't have a build for this build request, mask the data with build request data #}
+
+
+
+        <tr class="data">
+            <td class="outcome">{% if buildrequest.state == buildrequest.REQ_FAILED %}<i class="icon-minus-sign error"></i>{%else%}FIXME_build_request_state{%endif%}</td>
+            <td class="target">
+                <span data-toggle="tooltip" {%if br.brtarget_set.all.count > 1%}title="Targets: {%for target in br.brtarget_set.all%}{{target.target}} {%endfor%}"{%endif%}>{{br.brtarget_set.all.0.target}} {%if br.brtarget_set.all.count > 1%}(+ {{br.brtarget_set.all.count|add:"-1"}}){%endif%} </span>
+            </td>
+            <td class="machine">
+                {{br.machine}}
+            </td>
+            <td class="started_on">
+                {{br.created|date:"d/m/y H:i"}}
+            </td>
+            <td class="completed_on">
+                {{br.updated|date:"d/m/y H:i"}}
+            </td>
+            <td class="failed_tasks error">
+                {{br.brerror_set.all.0.errmsg|whitespace_slice:":32"}}
+            </td>
+            <td class="errors_no">
+            </td>
+            <td class="warnings_no">
+            </td>
+            <td class="time">
+                {{br.timespent.total_seconds|sectohms}}
+            </td>
+            <td class="output"> {# we have no output here #}
+            </td>
+            <td class="project">
+                <a href="{% url 'project' br.project.id %}">{{br.project.name}}</a>
+            </td>
+        </tr>
+          {%endif%}
+        {% endfor %}
+
+
+  {% include "basetable_bottom.html" %}
+  {% endif %} {# objects.paginator.count #}
+{% endif %} {# empty #}
+</div><!-- end row-fluid-->
+
+{% endblock %}
lib/toaster/toastergui/templates/managed_mrb_section.html new file +172 -0

172 lines not on this page · raw message

lib/toaster/toastergui/templatetags/projecttags.py +19 -0
index f564edf..276c6eb 100644
@@ -65,6 +65,25 @@ def query(qs, **kwargs):
     """
     return qs.filter(**kwargs)
 
+
[email protected]("whitespace_slice")
+def whitespace_space_filter(value, arg):
+    try:
+        bits = []
+        for x in arg.split(":"):
+            if len(x) == 0:
+                bits.append(None)
+            else:
+                # convert numeric value to the first whitespace after
+                first_whitespace = value.find(" ", int(x))
+                if first_whitespace == -1:
+                    bits.append(int(x))
+                else:
+                    bits.append(first_whitespace)
+        return value[slice(*bits)]
+    except (ValueError, TypeError):
+        raise
+
 @register.filter
 def divide(value, arg):
     if int(arg) == 0:
lib/toaster/toastergui/views.py +416 -199

646 lines not on this page · raw message

Signature · 1 line
1.9.1
#3 lore raw

PATCH 4/4 toasterui: fix variable data error

In reply to Alex DAMIAN

From: Alexandru DAMIAN <[email protected]>

A bug slipped in the toaster ui that prevented saving of build configuration despite the data being retrieved from the server. This patch fixes the shaming mistake.

[YOCTO #7117]

---
 lib/bb/ui/buildinfohelper.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
lib/bb/ui/buildinfohelper.py +1 -1
index f825b57..9e801ac 100644
@@ -757,7 +757,7 @@ class BuildInfoHelper(object):
 
         # Save build configuration
         data = self.server.runCommand(["getAllKeysWithFlags", ["doc", "func"]])[0]
-        self.orm_wrapper.save_build_variables(build_obj, [])
+        self.orm_wrapper.save_build_variables(build_obj, data)
 
         return self.brbe
 
Signature · 1 line
1.9.1
#4 lore raw

cover Toaster feature / bugfix patchset

From: Alexandru DAMIAN <[email protected]>

This patchset brings in the layer details page, and the managed version of the "all builds" page.

The patches have been reviewed on the Toaster mailing list.

Can you please pull at your convenience ?

Cheers,
Alex

The following changes since commit 0557d03c170fba8d7efe82be1b9641d0eb229213:

cooker/cache/parse: Implement pyinofity based reconfigure (2015-01-13 22:23:21 +0000)

are available in the git repository at:

git://git.yoctoproject.org/poky-contrib adamian/20150114-submission-bb
http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=adamian/20150114-submission-bb

Alexandru DAMIAN (2):
toastergui: all builds page lists failed build requests
toasterui: fix variable data error

Michael Wood (2):
toaster: Add layer details page feature
toaster: layerdetails Remove compatibility setting

 lib/bb/ui/buildinfohelper.py                       |   2 +-
 lib/toaster/toastergui/static/css/default.css      |   1 +
 lib/toaster/toastergui/static/js/layerdetails.js   | 398 ++++++++++++
 lib/toaster/toastergui/static/js/libtoaster.js     |  35 +
 lib/toaster/toastergui/templates/layerdetails.html | 625 +++++++++++++-----
 .../toastergui/templates/layers_dep_modal.html     |   9 +
 .../toastergui/templates/managed_builds.html       | 135 ++++
 .../toastergui/templates/managed_mrb_section.html  | 172 +++++
 lib/toaster/toastergui/templatetags/projecttags.py |  19 +
 lib/toaster/toastergui/urls.py                     |   1 +
 lib/toaster/toastergui/views.py                    | 708 +++++++++++++++------
 11 files changed, 1755 insertions(+), 350 deletions(-)
 create mode 100644 lib/toaster/toastergui/static/js/layerdetails.js
 create mode 100644 lib/toaster/toastergui/templates/managed_builds.html
 create mode 100644 lib/toaster/toastergui/templates/managed_mrb_section.html
Signature · 1 line
1.9.1
#5 lore raw

Re: [PATCH 0/4] Toaster feature / bugfix patchset

are any of these needed for dizzy?

- armin

Quoted 47 lines · Alex DAMIAN

From: Alexandru DAMIAN <[email protected]>

This patchset brings in the layer details page, and the managed version of the "all builds" page.

The patches have been reviewed on the Toaster mailing list.

Can you please pull at your convenience ?

Cheers,
Alex

The following changes since commit 0557d03c170fba8d7efe82be1b9641d0eb229213:

   cooker/cache/parse: Implement pyinofity based reconfigure (2015-01-13 22:23:21 +0000)

are available in the git repository at:

   git://git.yoctoproject.org/poky-contrib adamian/20150114-submission-bb
   http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=adamian/20150114-submission-bb

Alexandru DAMIAN (2):
toastergui: all builds page lists failed build requests
toasterui: fix variable data error

Michael Wood (2):
toaster: Add layer details page feature
toaster: layerdetails Remove compatibility setting

  lib/bb/ui/buildinfohelper.py                       |   2 +-
  lib/toaster/toastergui/static/css/default.css      |   1 +
  lib/toaster/toastergui/static/js/layerdetails.js   | 398 ++++++++++++
  lib/toaster/toastergui/static/js/libtoaster.js     |  35 +
  lib/toaster/toastergui/templates/layerdetails.html | 625 +++++++++++++-----
  .../toastergui/templates/layers_dep_modal.html     |   9 +
  .../toastergui/templates/managed_builds.html       | 135 ++++
  .../toastergui/templates/managed_mrb_section.html  | 172 +++++
  lib/toaster/toastergui/templatetags/projecttags.py |  19 +
  lib/toaster/toastergui/urls.py                     |   1 +
  lib/toaster/toastergui/views.py                    | 708 +++++++++++++++------
  11 files changed, 1755 insertions(+), 350 deletions(-)

create mode 100644 lib/toaster/toastergui/static/js/layerdetails.js create mode 100644 lib/toaster/toastergui/templates/managed_builds.html create mode 100644 lib/toaster/toastergui/templates/managed_mrb_section.html