toaster: Add layer details page feature
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
@@ -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
@@ -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
@@ -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
@@ -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
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
@@ -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
@@ -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
@@ -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
PATCH 3/4 toastergui: all builds page lists failed build requests
In reply to Alex DAMIANFrom: 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
@@ -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
@@ -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
PATCH 4/4 toasterui: fix variable data error
In reply to Alex DAMIANFrom: 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
@@ -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
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
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,
AlexThe 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-bbAlexandru DAMIAN (2):
toastergui: all builds page lists failed build requests
toasterui: fix variable data errorMichael Wood (2):
toaster: Add layer details page feature
toaster: layerdetails Remove compatibility settinglib/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.jscreate mode 100644lib/toaster/toastergui/templates/managed_builds.htmlcreate mode 100644lib/toaster/toastergui/templates/managed_mrb_section.html