From 2de01a68eb6a9ca74384957c674928944c235269 Mon Sep 17 00:00:00 2001 From: Michael Wood Date: Mon, 18 May 2015 20:08:28 +0100 Subject: bitbake: toaster: Port layerdetails to ToasterTables This ports the layerdetails page to using ToasterTables Also some whitespace and strict clean ups in the existing layerdetails js and html template. (Bitbake rev: 8ce35f81631e31539aeb82f8a85abbb3312e5097) Signed-off-by: Michael Wood Signed-off-by: Richard Purdie --- .../toaster/toastergui/static/js/layerdetails.js | 70 ++- .../lib/toaster/toastergui/static/js/libtoaster.js | 3 + bitbake/lib/toaster/toastergui/static/js/table.js | 77 ++- bitbake/lib/toaster/toastergui/tables.py | 87 ++- .../toaster/toastergui/templates/layerdetails.html | 594 +++++++-------------- .../toastergui/templates/toastertable-filter.html | 18 + .../toastergui/templates/toastertable-simple.html | 26 +- .../toaster/toastergui/templates/toastertable.html | 50 +- bitbake/lib/toaster/toastergui/urls.py | 6 +- bitbake/lib/toaster/toastergui/views.py | 49 -- bitbake/lib/toaster/toastergui/widgets.py | 17 +- 11 files changed, 415 insertions(+), 582 deletions(-) create mode 100644 bitbake/lib/toaster/toastergui/templates/toastertable-filter.html diff --git a/bitbake/lib/toaster/toastergui/static/js/layerdetails.js b/bitbake/lib/toaster/toastergui/static/js/layerdetails.js index 3c4d632563..3746ea26e3 100644 --- a/bitbake/lib/toaster/toastergui/static/js/layerdetails.js +++ b/bitbake/lib/toaster/toastergui/static/js/layerdetails.js @@ -1,4 +1,4 @@ -"use strict" +"use strict"; function layerDetailsPageInit (ctx) { @@ -54,7 +54,7 @@ function layerDetailsPageInit (ctx) { /* Add dependency layer button click handler */ layerDepBtn.click(function(){ - if (currentLayerDepSelection == undefined) + if (currentLayerDepSelection === undefined) return; addRemoveDep(currentLayerDepSelection.id, true, function(){ @@ -122,13 +122,6 @@ function layerDetailsPageInit (ctx) { }); }); - $(".build-target-btn").click(function(){ - /* fire a build */ - var target = $(this).data('target-name'); - libtoaster.startABuild(ctx.projectBuildUrl, libtoaster.ctx.projectId, target, null, null); - window.location.replace(libtoaster.ctx.projectPageUrl); - }); - function defaultAddBtnText(){ var text = " Add the "+ctx.layerVersion.name+" layer to your project"; addRmLayerBtn.text(text); @@ -155,9 +148,48 @@ function layerDetailsPageInit (ctx) { } } - window.location.hash = "targets"; + window.location.hash = "recipes"; } + $("#recipestable").on('table-done', function(e, total, tableParams){ + ctx.numTargets = total; + + if (total === 0 && !tableParams.search) { + $("#no-recipes-yet").show(); + } else { + $("#no-recipes-yet").hide(); + } + + $("#targets-tab").removeClass("muted"); + if (window.location.hash === "#recipes"){ + /* re run the machinesTabShow to update the text */ + targetsTabShow(); + } + + $(".build-target-btn").unbind('click'); + $(".build-target-btn").click(function(){ + /* fire a build */ + var target = $(this).data('target-name'); + libtoaster.startABuild(ctx.projectBuildUrl, libtoaster.ctx.projectId, target, null, null); + window.location.replace(libtoaster.ctx.projectPageUrl); + }); + }); + + $("#machinestable").on('table-done', function(e, total, tableParams){ + ctx.numMachines = total; + + if (total === 0 && !tableParams.search) + $("#no-machines-yet").show(); + else + $("#no-machines-yet").hide(); + + $("#machines-tab").removeClass("muted"); + if (window.location.hash === "#machines"){ + /* re run the machinesTabShow to update the text */ + machinesTabShow(); + } + }); + $("#targets-tab").on('show', targetsTabShow); function machinesTabShow(){ @@ -187,7 +219,7 @@ function layerDetailsPageInit (ctx) { /* Enables the Build target and Select Machine buttons and switches the * add/remove button */ - function setLayerInCurrentPrj(added, depsList) { + function setLayerInCurrentPrj(added) { ctx.layerVersion.inCurrentPrj = added; if (added){ @@ -224,18 +256,20 @@ function layerDetailsPageInit (ctx) { } } - $("#dismiss-alert").click(function(){ $(this).parent().hide() }); + $("#dismiss-alert").click(function(){ + $(this).parent().fadeOut(); + }); /* Add or remove this layer from the project */ addRmLayerBtn.click(function() { - var add = ($(this).data('directive') === "add") + var add = ($(this).data('directive') === "add"); libtoaster.addRmLayer(ctx.layerVersion, add, function (layersList){ var alertMsg = $("#alert-msg"); alertMsg.html(libtoaster.makeLayerAddRmAlertMsg(ctx.layerVersion, layersList, add)); - setLayerInCurrentPrj(add, layersList); + setLayerInCurrentPrj(add); $("#alert-area").show(); }); @@ -250,9 +284,9 @@ function layerDetailsPageInit (ctx) { * from. */ var entryElement = mParent.find("input"); - if (entryElement.length == 0) + if (entryElement.length === 0) entryElement = mParent.find("textarea"); - if (entryElement.length == 0) { + if (entryElement.length === 0) { console.warn("Could not find element to get data from for this change"); return; } @@ -293,7 +327,7 @@ function layerDetailsPageInit (ctx) { /* Disable the change button when we have no data in the input */ $("dl input, dl textarea").on("input",function() { - if ($(this).val().length == 0) + if ($(this).val().length === 0) $(this).parent().children(".change-btn").attr("disabled", "disabled"); else $(this).parent().children(".change-btn").removeAttr("disabled"); @@ -322,7 +356,7 @@ function layerDetailsPageInit (ctx) { }); /* Hide the right column if it contains no information */ - if ($("dl.item-info").children(':visible').length == 0) { + if ($("dl.item-info").children(':visible').length === 0) { $("dl.item-info").parent().hide(); } diff --git a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js index 1ac26d4c7f..99e1f03095 100644 --- a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js +++ b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js @@ -216,6 +216,9 @@ var libtoaster = (function (){ str += "&"; } + /* Maintain the current hash */ + str += window.location.hash; + return str; } diff --git a/bitbake/lib/toaster/toastergui/static/js/table.js b/bitbake/lib/toaster/toastergui/static/js/table.js index 97370fd020..2e35e3871c 100644 --- a/bitbake/lib/toaster/toastergui/static/js/table.js +++ b/bitbake/lib/toaster/toastergui/static/js/table.js @@ -64,10 +64,12 @@ function tableInit(ctx){ function updateTable(tableData) { var tableBody = table.children("tbody"); - var paginationBtns = $('#pagination-'+ctx.tableName); + var pagination = $('#pagination-'+ctx.tableName); + var paginationBtns = pagination.children('ul'); + var tableContainer = $("#table-container-"+ctx.tableName); + tableContainer.css("visibility", "hidden"); /* To avoid page re-layout flicker when paging set fixed height */ - table.css("visibility", "hidden"); table.css("padding-bottom", table.height()); /* Reset table components */ @@ -83,19 +85,30 @@ function tableInit(ctx){ tableTotal = tableData.total; if (tableData.total === 0){ - $("#table-container-"+ctx.tableName).hide(); - $("#new-search-input-"+ctx.tableName).val(tableParams.search); - $("#no-results-"+ctx.tableName).show(); + tableContainer.hide(); + /* If we were searching show the new search bar and return */ + if (tableParams.search){ + $("#new-search-input-"+ctx.tableName).val(tableParams.search); + $("#no-results-"+ctx.tableName).show(); + } + table.trigger("table-done", [tableData.total, tableParams]); + return; + + /* We don't want to clutter the place with the table chrome if there + * are only a few results */ + } else if (tableData.total <= 10 && + !tableParams.filter && + !tableParams.search){ + $("#table-chrome-"+ctx.tableName).hide(); + pagination.hide(); } else { - $("#table-container-"+ctx.tableName).show(); + tableContainer.show(); $("#no-results-"+ctx.tableName).hide(); } - setupTableChrome(tableData); - /* Add table data rows */ for (var i in tableData.rows){ var row = $(""); @@ -137,26 +150,31 @@ function tableInit(ctx){ var end = tableParams.page + 2; var numPages = Math.ceil(tableData.total/tableParams.limit); - if (tableParams.page < 3) - end = 5; + if (numPages > 1){ + if (tableParams.page < 3) + end = 5; - for (var page_i=1; page_i <= numPages; page_i++){ - if (page_i >= start && page_i <= end){ - var btn = $('
  • '+page_i+'
  • '); + for (var page_i=1; page_i <= numPages; page_i++){ + if (page_i >= start && page_i <= end){ + var btn = $('
  • '+page_i+'
  • '); - if (page_i === tableParams.page){ - btn.addClass("active"); - } + if (page_i === tableParams.page){ + btn.addClass("active"); + } - /* Add the click handler */ - btn.click(pageButtonClicked); - paginationBtns.append(btn); + /* Add the click handler */ + btn.click(pageButtonClicked); + paginationBtns.append(btn); + } } } - table.css("padding-bottom", 0); + loadColumnsPreference(); - $("table").css("visibility", "visible"); + table.css("padding-bottom", 0); + tableContainer.css("visibility", "visible"); + + table.trigger("table-done", [tableData.total, tableParams]); } function setupTableChrome(tableData){ @@ -374,9 +392,9 @@ function tableInit(ctx){ data: params, headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, success: function (filterData) { - var filterActionRadios = $('#filter-actions'); + var filterActionRadios = $('#filter-actions-'+ctx.tableName); - $('#filter-modal-title').text(filterData.title); + $('#filter-modal-title-'+ctx.tableName).text(filterData.title); filterActionRadios.text(""); @@ -404,7 +422,7 @@ function tableInit(ctx){ filterActionRadios.append(action); } - $('#filter-modal').modal('show'); + $('#filter-modal-'+ctx.tableName).modal('show'); } }); } @@ -417,17 +435,18 @@ function tableInit(ctx){ e.stopPropagation(); }); - $(".pagesize").val(tableParams.limit); + $(".pagesize-"+ctx.tableName).val(tableParams.limit); /* page size selector */ - $(".pagesize").change(function(){ + $(".pagesize-"+ctx.tableName).change(function(e){ tableParams.limit = Number(this.value); if ((tableParams.page * tableParams.limit) > tableTotal) tableParams.page = 1; loadData(tableParams); /* sync the other selectors on the page */ - $(".pagesize").val(this.value); + $(".pagesize-"+ctx.tableName).val(this.value); + e.preventDefault(); }); $("#search-submit-"+ctx.tableName).click(function(e){ @@ -463,12 +482,12 @@ function tableInit(ctx){ e.preventDefault(); }); - $("#clear-filter-btn").click(function(){ + $("#clear-filter-btn-"+ctx.tableName).click(function(){ tableParams.filter = null; loadData(tableParams); }); - $("#filter-modal-form").submit(function(e){ + $("#filter-modal-form-"+ctx.tableName).submit(function(e){ e.preventDefault(); tableParams.filter = $(this).find("input[type='radio']:checked").val(); diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py index e6395834a5..78a7cb095e 100644 --- a/bitbake/lib/toaster/toastergui/tables.py +++ b/bitbake/lib/toaster/toastergui/tables.py @@ -132,7 +132,6 @@ class LayersTable(ToasterTable): static_data_name="add-del-layers", static_data_template='{% include "layer_btn.html" %}') - class MachinesTable(ToasterTable): """Table of Machines in Toaster""" @@ -178,8 +177,7 @@ class MachinesTable(ToasterTable): self.add_column(title="Machine file", hidden=True, static_data_name="machinefile", - static_data_template=machine_file_template, - field_name="name") + static_data_template=machine_file_template) self.add_column(title="Select", help_text="Sets the selected machine as the project machine. You can only have one machine per project", @@ -189,6 +187,33 @@ class MachinesTable(ToasterTable): field_name="layer_version__id") +class LayerMachinesTable(MachinesTable): + """ Smaller version of the Machines table for use in layer details """ + + def __init__(self, *args, **kwargs): + MachinesTable.__init__(self) + + def setup_queryset(self, *args, **kwargs): + MachinesTable.setup_queryset(self, *args, **kwargs) + + self.queryset = self.queryset.filter(layer_version__pk=int(kwargs['layerid'])) + self.static_context_extra['in_prj'] = ProjectLayer.objects.filter(Q(project=kwargs['pid']) and Q(layercommit=kwargs['layerid'])).count() + + def setup_columns(self, *args, **kwargs): + self.add_column(title="Machine", + hideable=False, + orderable=True, + field_name="name") + + self.add_column(title="Description", + field_name="description") + + select_btn_template = 'Select machine' + + self.add_column(title="Select machine", + static_data_name="add-del-layers", + static_data_template=select_btn_template) + class RecipesTable(ToasterTable): """Table of Recipes in Toaster""" @@ -267,13 +292,57 @@ class RecipesTable(ToasterTable): static_data_name="add-del-layers", static_data_template='{% include "recipe_btn.html" %}') +class LayerRecipesTable(RecipesTable): + """ Smaller version of the Machines table for use in layer details """ + + def __init__(self, *args, **kwargs): + RecipesTable.__init__(self) + + def setup_queryset(self, *args, **kwargs): + RecipesTable.setup_queryset(self, *args, **kwargs) + self.queryset = self.queryset.filter(layer_version__pk=int(kwargs['layerid'])) + + self.static_context_extra['in_prj'] = ProjectLayer.objects.filter(Q(project=kwargs['pid']) and Q(layercommit=kwargs['layerid'])).count() + + def setup_columns(self, *args, **kwargs): + self.add_column(title="Recipe", + help_text="Information about a single piece of software, including where to download the source, configuration options, how to compile the source files and how to package the compiled output", + hideable=False, + orderable=True, + field_name="name") + + self.add_column(title="Description", + field_name="get_description_or_summary") + + + build_recipe_template ='' + + self.add_column(title="Build recipe", + static_data_name="add-del-layers", + static_data_template=build_recipe_template) + + + + + + + + # This needs to be staticaly defined here as django reads the url patterns # on start up urlpatterns = ( - url(r'^machines/(?P\w+)*', MachinesTable.as_view(), - name=MachinesTable.__name__.lower()), - url(r'^layers/(?P\w+)*', LayersTable.as_view(), - name=LayersTable.__name__.lower()), - url(r'^recipes/(?P\w+)*', RecipesTable.as_view(), - name=RecipesTable.__name__.lower()), + url(r'^machines/(?P\w+)*', MachinesTable.as_view(), + name=MachinesTable.__name__.lower()), + url(r'^layers/(?P\w+)*', LayersTable.as_view(), + name=LayersTable.__name__.lower()), + url(r'^recipes/(?P\w+)*', RecipesTable.as_view(), + name=RecipesTable.__name__.lower()), + + # layer details tables + url(r'^layer/(?P\d+)/recipes/(?P\w+)*', + LayerRecipesTable.as_view(), + name=LayerRecipesTable.__name__.lower()), + url(r'^layer/(?P\d+)/machines/(?P\w+)*', + LayerMachinesTable.as_view(), + name=LayerMachinesTable.__name__.lower()), ) diff --git a/bitbake/lib/toaster/toastergui/templates/layerdetails.html b/bitbake/lib/toaster/toastergui/templates/layerdetails.html index 7b62b64893..259a59ea0a 100644 --- a/bitbake/lib/toaster/toastergui/templates/layerdetails.html +++ b/bitbake/lib/toaster/toastergui/templates/layerdetails.html @@ -36,13 +36,15 @@ projectBuildUrl : "{% url 'xhr_build' %}", layerDetailsUrl : "{% url 'base_layerdetails' project.id %}", xhrUpdateLayerUrl : "{% url 'xhr_updatelayer' %}", - numTargets : {{total_targets}}, - numMachines: {{machines|length}}, layerVersion : { name : "{{layerversion.layer.name}}", id : {{layerversion.id}}, commit: "{{layerversion.get_vcs_reference}}", - inCurrentPrj : {{layer_in_project}}, + {%if layerversion.id in projectlayers %} + inCurrentPrj : true, + {% else %} + inCurrentPrj : false, + {% endif %} url : "{% url 'layerdetails' project.id layerversion.id %}", sourceId: {{layerversion.layer_source_id|json}}, } @@ -57,437 +59,207 @@ }); -
    - +
    + +
    -
    - - -
    - - {% if layer_in_project == 0 %} - - {% else %} - - {% endif %} - + +
    + + +
    + + {% if layerversion.id not in projectlayers %} + + {% else %} + + {% endif %} + - -
    -
    -
    - - Repository URL + +
    +
    +
    + + Repository URL +
    +
    + {{layerversion.layer.vcs_url}} + {% if layerversion.get_vcs_link_url %} + + {% endif %} + + +
    +
    + + Repository subdirectory +
    +
    + + {{layerversion.dirpath}} + {% if layerversion.get_vcs_dirpath_link_url %} + + {% endif %} + + + +
    +
    + + Revision
    - {{layerversion.layer.vcs_url}} - {% if layerversion.get_vcs_link_url %} - - {% endif %} - - +
    - - Repository subdirectory + + Layer dependencies
    - - {{layerversion.dirpath}} - {% if layerversion.get_vcs_dirpath_link_url %} - - {% endif %} - - - -
    -
    - - Revision -
    -
    - {{layerversion.get_vcs_reference}} -
    -
    - - - -
    -
    - -
    -
    - - Layer dependencies -
    -
    - - - You can only add layers Toaster knows about -
    -
    -
    - -
    - {% if total_targets == 0 %} -
    -

    Toaster does not have recipe information for the {{layerversion.layer.name}} layer.

    -

    Toaster learns about layers when you build them. If this layer provides any recipes, they will be listed here after you build the {{layerversion.layer.name}} layer.

    -
    - {% else %} - -
    - - {% if targets.paginator.count == 0 %} -
    -

    No targets found

    - {% endif %} - - {# only show the search form if we have more than 10 results #} - {% if targets.paginator.count > 10 or request.GET.targets_search %} - {% if targets.paginator.count == 0 %} -
    - {% else %} - - {% endif %} - - - {% if request.GET.targets_search %} - - - - {% endif %} - - {% if targets.paginator.count == 0 %} -
    - -
    - {% else %} - - {% if total_targets > 10 %} -
    - Show rows: - -
    - {% endif %} -
    - - - - - - - - - - - - {% for target in targets %} - - - - - - - {% endfor %} - -
    - - Recipe - {% if request.GET.targets_search %} - {{targets.paginator.count}} - {% endif %} - - - Recipe version - SummaryBuild recipe
    - {{target.name}} - {% if target.up_id %} - - {% endif %} - {{target.version}}{{target.summary}}
    - - {% if total_targets > 10 %} - - - {% endif %} - {% endif %} - {% endif %} -
    - - -
    - {% if total_machines == 0 %} -
    -

    Toaster does not have machine information for the {{layerversion.layer.name}} layer.

    -

    Toaster learns about layers when you build them. If this layer provides any machines, they will be listed here after you build the {{layerversion.layer.name}} layer.

    + + - {% else %} - -
    - - {% if machines.paginator.count == 0 %} -
    -

    No machines found

    - {% endif %} - - {# only show the search form if we have more than 10 results #} - {% if machines.paginator.count > 10 or request.GET.machines_search %} - {% if machines.paginator.count == 0 %} -
    - {% else %} - - {% endif %} + You can only add layers Toaster knows about + + +
    + + +
    + + - - {% if request.GET.machines_search %} - - - - {% endif %} - - {% if machines.paginator.count == 0 %} -
    - -
    - {% else %} + {% url 'layerrecipestable' project.id layerversion.id as xhr_table_url %} + {% with "recipestable" as table_name %} + {% with "Recipes" as title %} + {% include 'toastertable-simple.html' %} + {% endwith %} + {% endwith %} +
    - {% if total_machines > 10 %} -
    - Show rows: - -
    - {% endif %} +
    -
    + - - - - - - - - - - {% for machine in machines %} - - - - - {% endfor %} - -
    - - Machine - {% if request.GET.machines_search %} - {{machines.paginator.count}} - {% endif %} - DescriptionSelect machine
    - {{machine.name}} - {% if machine.get_vcs_machine_file_link_url %} - - {% endif %} - {{machine.description}} - Select machine -
    - {% if total_machines > 10 %} - - - {% endif %} - {% endif %} - {% endif %} -
    -
    + + {% url 'layermachinestable' project.id layerversion.id as xhr_table_url %} + {% with "machinestable" as table_name %} + {% with "Machines" as title %} + {% include 'toastertable-simple.html' %} + {% endwith %} + {% endwith %}
    -
    -

    About {{layerversion.layer.name}}

    -
    +
    +
    -
    - Summary - -
    -
    - - {{layerversion.layer.summary|default_if_none:''}} -
    - - - Cancel -
    - - -
    -
    - Description -
    -
    - - {{layerversion.layer.description|default_if_none:''}} -
    - - - Cancel -
    - - -
    - {% if layerversion.layer.up_id %} -
    Layer index
    -
    - layer index link +
    +

    About {{layerversion.layer.name}}

    +
    -
    - {% endif %} +
    + Summary + +
    +
    + + {{layerversion.layer.summary|default_if_none:''}} +
    + + + Cancel +
    + + +
    +
    + Description +
    +
    + + {{layerversion.layer.description|default_if_none:''}} +
    + + + Cancel +
    + + +
    + {% if layerversion.layer.up_id %} +
    Layer index
    +
    + layer index link + +
    + {% endif %} - -
    + +
    -{% endblock %} + {% endblock %} diff --git a/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html b/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html new file mode 100644 index 0000000000..7c8dc49b33 --- /dev/null +++ b/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html @@ -0,0 +1,18 @@ + + + + diff --git a/bitbake/lib/toaster/toastergui/templates/toastertable-simple.html b/bitbake/lib/toaster/toastergui/templates/toastertable-simple.html index 98cad64a01..23a75260a1 100644 --- a/bitbake/lib/toaster/toastergui/templates/toastertable-simple.html +++ b/bitbake/lib/toaster/toastergui/templates/toastertable-simple.html @@ -24,23 +24,7 @@ }); - - - +{% include 'toastertable-filter.html' %} - - -
    +