diff options
Diffstat (limited to 'bitbake/lib/toaster')
-rw-r--r-- | bitbake/lib/toaster/orm/management/commands/lsupdates.py | 19 | ||||
-rw-r--r-- | bitbake/lib/toaster/orm/migrations/0017_distro_clone.py | 25 | ||||
-rw-r--r-- | bitbake/lib/toaster/orm/models.py | 31 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/api.py | 13 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/static/js/projectpage.js | 73 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/tables.py | 91 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/base.html | 1 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/baseprojectpage.html | 1 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/distro_btn.html | 20 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/project.html | 16 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/typeaheads.py | 30 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/urls.py | 8 |
12 files changed, 325 insertions, 3 deletions
diff --git a/bitbake/lib/toaster/orm/management/commands/lsupdates.py b/bitbake/lib/toaster/orm/management/commands/lsupdates.py index 90f07c9dc5..0b0d4ff8f9 100644 --- a/bitbake/lib/toaster/orm/management/commands/lsupdates.py +++ b/bitbake/lib/toaster/orm/management/commands/lsupdates.py | |||
@@ -23,6 +23,7 @@ from django.core.management.base import BaseCommand | |||
23 | 23 | ||
24 | from orm.models import LayerSource, Layer, Release, Layer_Version | 24 | from orm.models import LayerSource, Layer, Release, Layer_Version |
25 | from orm.models import LayerVersionDependency, Machine, Recipe | 25 | from orm.models import LayerVersionDependency, Machine, Recipe |
26 | from orm.models import Distro | ||
26 | 27 | ||
27 | import os | 28 | import os |
28 | import sys | 29 | import sys |
@@ -249,6 +250,24 @@ class Command(BaseCommand): | |||
249 | depends_on=lvd) | 250 | depends_on=lvd) |
250 | self.mini_progress("Layer version dependencies", i, total) | 251 | self.mini_progress("Layer version dependencies", i, total) |
251 | 252 | ||
253 | # update Distros | ||
254 | logger.info("Fetching distro information") | ||
255 | distros_info = _get_json_response( | ||
256 | apilinks['distros'] + "?filter=layerbranch__branch__name:%s" % | ||
257 | "OR".join(whitelist_branch_names)) | ||
258 | |||
259 | total = len(distros_info) | ||
260 | for i, di in enumerate(distros_info): | ||
261 | distro, created = Distro.objects.get_or_create( | ||
262 | name=di['name'], | ||
263 | layer_version=Layer_Version.objects.get( | ||
264 | pk=li_layer_branch_id_to_toaster_lv_id[di['layerbranch']])) | ||
265 | distro.up_date = di['updated'] | ||
266 | distro.name = di['name'] | ||
267 | distro.description = di['description'] | ||
268 | distro.save() | ||
269 | self.mini_progress("distros", i, total) | ||
270 | |||
252 | # update machines | 271 | # update machines |
253 | logger.info("Fetching machine information") | 272 | logger.info("Fetching machine information") |
254 | machines_info = _get_json_response( | 273 | machines_info = _get_json_response( |
diff --git a/bitbake/lib/toaster/orm/migrations/0017_distro_clone.py b/bitbake/lib/toaster/orm/migrations/0017_distro_clone.py new file mode 100644 index 0000000000..d3c5901275 --- /dev/null +++ b/bitbake/lib/toaster/orm/migrations/0017_distro_clone.py | |||
@@ -0,0 +1,25 @@ | |||
1 | # -*- coding: utf-8 -*- | ||
2 | from __future__ import unicode_literals | ||
3 | |||
4 | from django.db import migrations, models | ||
5 | |||
6 | class Migration(migrations.Migration): | ||
7 | |||
8 | dependencies = [ | ||
9 | ('orm', '0016_clone_progress'), | ||
10 | ] | ||
11 | |||
12 | operations = [ | ||
13 | migrations.CreateModel( | ||
14 | name='Distro', | ||
15 | fields=[ | ||
16 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), | ||
17 | ('up_id', models.IntegerField(default=None, null=True)), | ||
18 | ('up_date', models.DateTimeField(default=None, null=True)), | ||
19 | ('name', models.CharField(max_length=255)), | ||
20 | ('description', models.CharField(max_length=255)), | ||
21 | ('layer_version', models.ForeignKey(to='orm.Layer_Version')), | ||
22 | ], | ||
23 | ), | ||
24 | ] | ||
25 | |||
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py index 13bd11704a..5c14727a70 100644 --- a/bitbake/lib/toaster/orm/models.py +++ b/bitbake/lib/toaster/orm/models.py | |||
@@ -321,6 +321,22 @@ class Project(models.Model): | |||
321 | 321 | ||
322 | return queryset | 322 | return queryset |
323 | 323 | ||
324 | def get_available_distros(self): | ||
325 | """ Returns QuerySet of all Distros which are provided by the | ||
326 | Layers currently added to the Project """ | ||
327 | queryset = Distro.objects.filter( | ||
328 | layer_version__in=self.get_project_layer_versions()) | ||
329 | |||
330 | return queryset | ||
331 | |||
332 | def get_all_compatible_distros(self): | ||
333 | """ Returns QuerySet of all the compatible Wind River distros available to the | ||
334 | project including ones from Layers not currently added """ | ||
335 | queryset = Distro.objects.filter( | ||
336 | layer_version__in=self.get_all_compatible_layer_versions()) | ||
337 | |||
338 | return queryset | ||
339 | |||
324 | def get_available_recipes(self): | 340 | def get_available_recipes(self): |
325 | """ Returns QuerySet of all the recipes that are provided by layers | 341 | """ Returns QuerySet of all the recipes that are provided by layers |
326 | added to this project """ | 342 | added to this project """ |
@@ -1795,6 +1811,21 @@ def signal_runbuilds(): | |||
1795 | except FileNotFoundError: | 1811 | except FileNotFoundError: |
1796 | logger.info("Stopping existing runbuilds: no current process found") | 1812 | logger.info("Stopping existing runbuilds: no current process found") |
1797 | 1813 | ||
1814 | class Distro(models.Model): | ||
1815 | search_allowed_fields = ["name", "description", "layer_version__layer__name"] | ||
1816 | up_date = models.DateTimeField(null = True, default = None) | ||
1817 | |||
1818 | layer_version = models.ForeignKey('Layer_Version') | ||
1819 | name = models.CharField(max_length=255) | ||
1820 | description = models.CharField(max_length=255) | ||
1821 | |||
1822 | def get_vcs_distro_file_link_url(self): | ||
1823 | path = self.name+'.conf' | ||
1824 | return self.layer_version.get_vcs_file_link_url(path) | ||
1825 | |||
1826 | def __unicode__(self): | ||
1827 | return "Distro " + self.name + "(" + self.description + ")" | ||
1828 | |||
1798 | django.db.models.signals.post_save.connect(invalidate_cache) | 1829 | django.db.models.signals.post_save.connect(invalidate_cache) |
1799 | django.db.models.signals.post_delete.connect(invalidate_cache) | 1830 | django.db.models.signals.post_delete.connect(invalidate_cache) |
1800 | django.db.models.signals.m2m_changed.connect(invalidate_cache) | 1831 | django.db.models.signals.m2m_changed.connect(invalidate_cache) |
diff --git a/bitbake/lib/toaster/toastergui/api.py b/bitbake/lib/toaster/toastergui/api.py index 5b035505c2..88d6aa7f68 100644 --- a/bitbake/lib/toaster/toastergui/api.py +++ b/bitbake/lib/toaster/toastergui/api.py | |||
@@ -874,6 +874,12 @@ class XhrProject(View): | |||
874 | machinevar.value = request.POST['machineName'] | 874 | machinevar.value = request.POST['machineName'] |
875 | machinevar.save() | 875 | machinevar.save() |
876 | 876 | ||
877 | # Distro name change | ||
878 | if 'distroName' in request.POST: | ||
879 | distrovar = prj.projectvariable_set.get(name="DISTRO") | ||
880 | distrovar.value = request.POST['distroName'] | ||
881 | distrovar.save() | ||
882 | |||
877 | return JsonResponse({"error": "ok"}) | 883 | return JsonResponse({"error": "ok"}) |
878 | 884 | ||
879 | def get(self, request, *args, **kwargs): | 885 | def get(self, request, *args, **kwargs): |
@@ -960,10 +966,11 @@ class XhrProject(View): | |||
960 | except ProjectVariable.DoesNotExist: | 966 | except ProjectVariable.DoesNotExist: |
961 | data["machine"] = None | 967 | data["machine"] = None |
962 | try: | 968 | try: |
963 | data["distro"] = project.projectvariable_set.get( | 969 | data["distro"] = {"name": |
964 | name="DISTRO").value | 970 | project.projectvariable_set.get( |
971 | name="DISTRO").value} | ||
965 | except ProjectVariable.DoesNotExist: | 972 | except ProjectVariable.DoesNotExist: |
966 | data["distro"] = "-- not set yet" | 973 | data["distro"] = None |
967 | 974 | ||
968 | data['error'] = "ok" | 975 | data['error'] = "ok" |
969 | 976 | ||
diff --git a/bitbake/lib/toaster/toastergui/static/js/projectpage.js b/bitbake/lib/toaster/toastergui/static/js/projectpage.js index 21adf816c6..506471e091 100644 --- a/bitbake/lib/toaster/toastergui/static/js/projectpage.js +++ b/bitbake/lib/toaster/toastergui/static/js/projectpage.js | |||
@@ -15,6 +15,13 @@ function projectPageInit(ctx) { | |||
15 | var machineInputForm = $("#machine-input-form"); | 15 | var machineInputForm = $("#machine-input-form"); |
16 | var invalidMachineNameHelp = $("#invalid-machine-name-help"); | 16 | var invalidMachineNameHelp = $("#invalid-machine-name-help"); |
17 | 17 | ||
18 | var distroChangeInput = $("#distro-change-input"); | ||
19 | var distroChangeBtn = $("#distro-change-btn"); | ||
20 | var distroForm = $("#select-distro-form"); | ||
21 | var distroChangeFormToggle = $("#change-distro-toggle"); | ||
22 | var distroNameTitle = $("#project-distro-name"); | ||
23 | var distroChangeCancel = $("#cancel-distro-change"); | ||
24 | |||
18 | var freqBuildBtn = $("#freq-build-btn"); | 25 | var freqBuildBtn = $("#freq-build-btn"); |
19 | var freqBuildList = $("#freq-build-list"); | 26 | var freqBuildList = $("#freq-build-list"); |
20 | 27 | ||
@@ -26,6 +33,7 @@ function projectPageInit(ctx) { | |||
26 | 33 | ||
27 | var currentLayerAddSelection; | 34 | var currentLayerAddSelection; |
28 | var currentMachineAddSelection = ""; | 35 | var currentMachineAddSelection = ""; |
36 | var currentDistroAddSelection = ""; | ||
29 | 37 | ||
30 | var urlParams = libtoaster.parseUrlParams(); | 38 | var urlParams = libtoaster.parseUrlParams(); |
31 | 39 | ||
@@ -45,6 +53,17 @@ function projectPageInit(ctx) { | |||
45 | updateMachineName(prjInfo.machine.name); | 53 | updateMachineName(prjInfo.machine.name); |
46 | } | 54 | } |
47 | 55 | ||
56 | /* If we're receiving a distro set from the url and it's different from | ||
57 | * our current distro then activate set machine sequence. | ||
58 | */ | ||
59 | if (urlParams.hasOwnProperty('setDistro') && | ||
60 | urlParams.setDistro !== prjInfo.distro.name){ | ||
61 | distroChangeInput.val(urlParams.setDistro); | ||
62 | distroChangeBtn.click(); | ||
63 | } else { | ||
64 | updateDistroName(prjInfo.distro.name); | ||
65 | } | ||
66 | |||
48 | /* Now we're really ready show the page */ | 67 | /* Now we're really ready show the page */ |
49 | $("#project-page").show(); | 68 | $("#project-page").show(); |
50 | 69 | ||
@@ -278,6 +297,60 @@ function projectPageInit(ctx) { | |||
278 | }); | 297 | }); |
279 | 298 | ||
280 | 299 | ||
300 | /* Change distro functionality */ | ||
301 | |||
302 | distroChangeFormToggle.click(function(){ | ||
303 | distroForm.slideDown(); | ||
304 | distroNameTitle.hide(); | ||
305 | $(this).hide(); | ||
306 | }); | ||
307 | |||
308 | distroChangeCancel.click(function(){ | ||
309 | distroForm.slideUp(function(){ | ||
310 | distroNameTitle.show(); | ||
311 | distroChangeFormToggle.show(); | ||
312 | }); | ||
313 | }); | ||
314 | |||
315 | function updateDistroName(distroName){ | ||
316 | distroChangeInput.val(distroName); | ||
317 | distroNameTitle.text(distroName); | ||
318 | } | ||
319 | |||
320 | libtoaster.makeTypeahead(distroChangeInput, | ||
321 | libtoaster.ctx.distrosTypeAheadUrl, | ||
322 | { }, function(item){ | ||
323 | currentDistroAddSelection = item.name; | ||
324 | distroChangeBtn.removeAttr("disabled"); | ||
325 | }); | ||
326 | |||
327 | distroChangeBtn.click(function(e){ | ||
328 | e.preventDefault(); | ||
329 | /* We accept any value regardless of typeahead selection or not */ | ||
330 | if (distroChangeInput.val().length === 0) | ||
331 | return; | ||
332 | |||
333 | currentDistroAddSelection = distroChangeInput.val(); | ||
334 | |||
335 | libtoaster.editCurrentProject( | ||
336 | { distroName : currentDistroAddSelection }, | ||
337 | function(){ | ||
338 | /* Success machine changed */ | ||
339 | updateDistroName(currentDistroAddSelection); | ||
340 | distroChangeCancel.click(); | ||
341 | |||
342 | /* Show the alert message */ | ||
343 | var message = $('<span>You have changed the distro to: <strong><span id="notify-machine-name"></span></strong></span>'); | ||
344 | message.find("#notify-machine-name").text(currentDistroAddSelection); | ||
345 | libtoaster.showChangeNotification(message); | ||
346 | }, | ||
347 | function(){ | ||
348 | /* Failed machine changed */ | ||
349 | console.warn("Failed to change distro"); | ||
350 | }); | ||
351 | }); | ||
352 | |||
353 | |||
281 | /* Change release functionality */ | 354 | /* Change release functionality */ |
282 | function updateProjectRelease(release){ | 355 | function updateProjectRelease(release){ |
283 | releaseTitle.text(release.description); | 356 | releaseTitle.text(release.description); |
diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py index e2d23c1e81..dca2fa2913 100644 --- a/bitbake/lib/toaster/toastergui/tables.py +++ b/bitbake/lib/toaster/toastergui/tables.py | |||
@@ -23,6 +23,7 @@ from toastergui.widgets import ToasterTable | |||
23 | from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project | 23 | from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project |
24 | from orm.models import CustomImageRecipe, Package, Target, Build, LogMessage, Task | 24 | from orm.models import CustomImageRecipe, Package, Target, Build, LogMessage, Task |
25 | from orm.models import CustomImagePackage, Package_DependencyManager | 25 | from orm.models import CustomImagePackage, Package_DependencyManager |
26 | from orm.models import Distro | ||
26 | from django.db.models import Q, Max, Sum, Count, When, Case, Value, IntegerField | 27 | from django.db.models import Q, Max, Sum, Count, When, Case, Value, IntegerField |
27 | from django.conf.urls import url | 28 | from django.conf.urls import url |
28 | from django.core.urlresolvers import reverse, resolve | 29 | from django.core.urlresolvers import reverse, resolve |
@@ -1536,3 +1537,93 @@ class ProjectBuildsTable(BuildsTable): | |||
1536 | context['build_in_progress_none_completed'] = False | 1537 | context['build_in_progress_none_completed'] = False |
1537 | 1538 | ||
1538 | return context | 1539 | return context |
1540 | |||
1541 | |||
1542 | class DistrosTable(ToasterTable): | ||
1543 | """Table of Distros in Toaster""" | ||
1544 | |||
1545 | def __init__(self, *args, **kwargs): | ||
1546 | super(DistrosTable, self).__init__(*args, **kwargs) | ||
1547 | self.empty_state = "Toaster has no distro information for this project. Sadly, distro information cannot be obtained from builds, so this page will remain empty." | ||
1548 | self.title = "Compatible Distros" | ||
1549 | self.default_orderby = "name" | ||
1550 | |||
1551 | def get_context_data(self, **kwargs): | ||
1552 | context = super(DistrosTable, self).get_context_data(**kwargs) | ||
1553 | context['project'] = Project.objects.get(pk=kwargs['pid']) | ||
1554 | return context | ||
1555 | |||
1556 | def setup_filters(self, *args, **kwargs): | ||
1557 | project = Project.objects.get(pk=kwargs['pid']) | ||
1558 | |||
1559 | in_current_project_filter = TableFilter( | ||
1560 | "in_current_project", | ||
1561 | "Filter by project Distros" | ||
1562 | ) | ||
1563 | |||
1564 | in_project_action = TableFilterActionToggle( | ||
1565 | "in_project", | ||
1566 | "Distro provided by layers added to this project", | ||
1567 | ProjectFilters.in_project(self.project_layers) | ||
1568 | ) | ||
1569 | |||
1570 | not_in_project_action = TableFilterActionToggle( | ||
1571 | "not_in_project", | ||
1572 | "Distros provided by layers not added to this project", | ||
1573 | ProjectFilters.not_in_project(self.project_layers) | ||
1574 | ) | ||
1575 | |||
1576 | in_current_project_filter.add_action(in_project_action) | ||
1577 | in_current_project_filter.add_action(not_in_project_action) | ||
1578 | self.add_filter(in_current_project_filter) | ||
1579 | |||
1580 | def setup_queryset(self, *args, **kwargs): | ||
1581 | prj = Project.objects.get(pk = kwargs['pid']) | ||
1582 | self.queryset = prj.get_all_compatible_distros() | ||
1583 | self.queryset = self.queryset.order_by(self.default_orderby) | ||
1584 | |||
1585 | self.static_context_extra['current_layers'] = \ | ||
1586 | self.project_layers = \ | ||
1587 | prj.get_project_layer_versions(pk=True) | ||
1588 | |||
1589 | def setup_columns(self, *args, **kwargs): | ||
1590 | |||
1591 | self.add_column(title="Distro", | ||
1592 | hideable=False, | ||
1593 | orderable=True, | ||
1594 | field_name="name") | ||
1595 | |||
1596 | self.add_column(title="Description", | ||
1597 | field_name="description") | ||
1598 | |||
1599 | layer_link_template = ''' | ||
1600 | <a href="{% url 'layerdetails' extra.pid data.layer_version.id %}"> | ||
1601 | {{data.layer_version.layer.name}}</a> | ||
1602 | ''' | ||
1603 | |||
1604 | self.add_column(title="Layer", | ||
1605 | static_data_name="layer_version__layer__name", | ||
1606 | static_data_template=layer_link_template, | ||
1607 | orderable=True) | ||
1608 | |||
1609 | self.add_column(title="Git revision", | ||
1610 | help_text="The Git branch, tag or commit. For the layers from the OpenEmbedded layer source, the revision is always the branch compatible with the Yocto Project version you selected for this project", | ||
1611 | hidden=True, | ||
1612 | field_name="layer_version__get_vcs_reference") | ||
1613 | |||
1614 | wrtemplate_file_template = '''<code>conf/machine/{{data.name}}.conf</code> | ||
1615 | <a href="{{data.get_vcs_machine_file_link_url}}" target="_blank"><span class="glyphicon glyphicon-new-window"></i></a>''' | ||
1616 | |||
1617 | self.add_column(title="Distro file", | ||
1618 | hidden=True, | ||
1619 | static_data_name="templatefile", | ||
1620 | static_data_template=wrtemplate_file_template) | ||
1621 | |||
1622 | |||
1623 | self.add_column(title="Select", | ||
1624 | help_text="Sets the selected distro to the project", | ||
1625 | hideable=False, | ||
1626 | filter_name="in_current_project", | ||
1627 | static_data_name="add-del-layers", | ||
1628 | static_data_template='{% include "distro_btn.html" %}') | ||
1629 | |||
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html index 11c6f91260..0fbe17b5d8 100644 --- a/bitbake/lib/toaster/toastergui/templates/base.html +++ b/bitbake/lib/toaster/toastergui/templates/base.html | |||
@@ -49,6 +49,7 @@ | |||
49 | recipesTypeAheadUrl: {% url 'xhr_recipestypeahead' project.id as paturl%}{{paturl|json}}, | 49 | recipesTypeAheadUrl: {% url 'xhr_recipestypeahead' project.id as paturl%}{{paturl|json}}, |
50 | layersTypeAheadUrl: {% url 'xhr_layerstypeahead' project.id as paturl%}{{paturl|json}}, | 50 | layersTypeAheadUrl: {% url 'xhr_layerstypeahead' project.id as paturl%}{{paturl|json}}, |
51 | machinesTypeAheadUrl: {% url 'xhr_machinestypeahead' project.id as paturl%}{{paturl|json}}, | 51 | machinesTypeAheadUrl: {% url 'xhr_machinestypeahead' project.id as paturl%}{{paturl|json}}, |
52 | distrosTypeAheadUrl: {% url 'xhr_distrostypeahead' project.id as paturl%}{{paturl|json}}, | ||
52 | projectBuildsUrl: {% url 'projectbuilds' project.id as pburl %}{{pburl|json}}, | 53 | projectBuildsUrl: {% url 'projectbuilds' project.id as pburl %}{{pburl|json}}, |
53 | xhrCustomRecipeUrl : "{% url 'xhr_customrecipe' %}", | 54 | xhrCustomRecipeUrl : "{% url 'xhr_customrecipe' %}", |
54 | projectId : {{project.id}}, | 55 | projectId : {{project.id}}, |
diff --git a/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html b/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html index 8427d25210..f2bb2ebf63 100644 --- a/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html +++ b/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html | |||
@@ -32,6 +32,7 @@ $(document).ready(function(){ | |||
32 | <li><a href="{% url 'projectsoftwarerecipes' project.id %}">Software recipes</a></li> | 32 | <li><a href="{% url 'projectsoftwarerecipes' project.id %}">Software recipes</a></li> |
33 | <li><a href="{% url 'projectmachines' project.id %}">Machines</a></li> | 33 | <li><a href="{% url 'projectmachines' project.id %}">Machines</a></li> |
34 | <li><a href="{% url 'projectlayers' project.id %}">Layers</a></li> | 34 | <li><a href="{% url 'projectlayers' project.id %}">Layers</a></li> |
35 | <li><a href="{% url 'projectdistros' project.id %}">Distros</a></li> | ||
35 | <li class="nav-header">Extra configuration</li> | 36 | <li class="nav-header">Extra configuration</li> |
36 | <li><a href="{% url 'projectconf' project.id %}">BitBake variables</a></li> | 37 | <li><a href="{% url 'projectconf' project.id %}">BitBake variables</a></li> |
37 | 38 | ||
diff --git a/bitbake/lib/toaster/toastergui/templates/distro_btn.html b/bitbake/lib/toaster/toastergui/templates/distro_btn.html new file mode 100644 index 0000000000..fac79472cc --- /dev/null +++ b/bitbake/lib/toaster/toastergui/templates/distro_btn.html | |||
@@ -0,0 +1,20 @@ | |||
1 | <a href="{% url 'project' extra.pid %}?setDistro={{data.name}}" class="btn btn-default btn-block layer-exists-{{data.layer_version.id}}" | ||
2 | {% if data.layer_version.pk not in extra.current_layers %} | ||
3 | style="display:none;" | ||
4 | {% endif %}> | ||
5 | Set distro</a> | ||
6 | <a class="btn btn-default btn-block layerbtn layer-add-{{data.layer_version.id}}" data-layer='{ | ||
7 | "id": {{data.layer_version.id}}, | ||
8 | "name": "{{data.layer_version.layer.name}}", | ||
9 | "xhrLayerUrl": "{% url "xhr_layer" extra.pid data.pk %}", | ||
10 | "layerdetailurl": "{%url 'layerdetails' extra.pid data.layer_version.id %}" | ||
11 | }' data-directive="add" | ||
12 | {% if data.layer_version.pk in extra.current_layers %} | ||
13 | style="display:none;" | ||
14 | {% endif %} | ||
15 | > | ||
16 | <span class="glyphicon glyphicon-plus"></span> | ||
17 | Add layer | ||
18 | <span class="glyphicon glyphicon-question-sign get-help" title="To select this distro, you must first add the {{data.layer_version.layer.name}} layer to your project"></i> | ||
19 | </a> | ||
20 | |||
diff --git a/bitbake/lib/toaster/toastergui/templates/project.html b/bitbake/lib/toaster/toastergui/templates/project.html index ab7e665b64..11603d1e12 100644 --- a/bitbake/lib/toaster/toastergui/templates/project.html +++ b/bitbake/lib/toaster/toastergui/templates/project.html | |||
@@ -77,6 +77,22 @@ | |||
77 | </form> | 77 | </form> |
78 | </div> | 78 | </div> |
79 | 79 | ||
80 | <div class="well well-transparent" id="distro-section"> | ||
81 | <h3>Distro</h3> | ||
82 | |||
83 | <p class="lead"><span id="project-distro-name"></span> <span class="glyphicon glyphicon-edit" id="change-distro-toggle"></span></p> | ||
84 | |||
85 | <form id="select-distro-form" style="display:none;" class="form-inline"> | ||
86 | <span class="help-block">Distro suggestions come from the Layer Index</a></span> | ||
87 | <div class="form-group"> | ||
88 | <input class="form-control" id="distro-change-input" autocomplete="off" value="" data-provide="typeahead" data-minlength="1" data-autocomplete="off" type="text"> | ||
89 | </div> | ||
90 | <button id="distro-change-btn" class="btn btn-default" type="button">Save</button> | ||
91 | <a href="#" id="cancel-distro-change" class="btn btn-link">Cancel</a> | ||
92 | <p class="form-link"><a href="{% url 'projectdistros' project.id %}">View compatible distros</a></p> | ||
93 | </form> | ||
94 | </div> | ||
95 | |||
80 | <div class="well well-transparent"> | 96 | <div class="well well-transparent"> |
81 | <h3>Most built recipes</h3> | 97 | <h3>Most built recipes</h3> |
82 | 98 | ||
diff --git a/bitbake/lib/toaster/toastergui/typeaheads.py b/bitbake/lib/toaster/toastergui/typeaheads.py index 58c650f8fc..5aa0f8d889 100644 --- a/bitbake/lib/toaster/toastergui/typeaheads.py +++ b/bitbake/lib/toaster/toastergui/typeaheads.py | |||
@@ -100,6 +100,36 @@ class MachinesTypeAhead(ToasterTypeAhead): | |||
100 | return results | 100 | return results |
101 | 101 | ||
102 | 102 | ||
103 | class DistrosTypeAhead(ToasterTypeAhead): | ||
104 | """ Typeahead for all the distros available in the current project's | ||
105 | configuration """ | ||
106 | def __init__(self): | ||
107 | super(DistrosTypeAhead, self).__init__() | ||
108 | |||
109 | def apply_search(self, search_term, prj, request): | ||
110 | distros = prj.get_available_distros() | ||
111 | distros = distros.order_by("name") | ||
112 | |||
113 | primary_results = distros.filter(name__istartswith=search_term) | ||
114 | secondary_results = distros.filter(name__icontains=search_term).exclude(pk__in=primary_results) | ||
115 | tertiary_results = distros.filter(layer_version__layer__name__icontains=search_term).exclude(pk__in=primary_results).exclude(pk__in=secondary_results) | ||
116 | |||
117 | results = [] | ||
118 | |||
119 | for distro in list(primary_results) + list(secondary_results) + list(tertiary_results): | ||
120 | |||
121 | detail = "[ %s ]" % (distro.layer_version.layer.name) | ||
122 | needed_fields = { | ||
123 | 'id' : distro.pk, | ||
124 | 'name' : distro.name, | ||
125 | 'detail' : detail, | ||
126 | } | ||
127 | |||
128 | results.append(needed_fields) | ||
129 | |||
130 | return results | ||
131 | |||
132 | |||
103 | class RecipesTypeAhead(ToasterTypeAhead): | 133 | class RecipesTypeAhead(ToasterTypeAhead): |
104 | """ Typeahead for all the recipes available in the current project's | 134 | """ Typeahead for all the recipes available in the current project's |
105 | configuration """ | 135 | configuration """ |
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py index 1ad79a4dd3..6aebc3f833 100644 --- a/bitbake/lib/toaster/toastergui/urls.py +++ b/bitbake/lib/toaster/toastergui/urls.py | |||
@@ -158,6 +158,11 @@ urlpatterns = [ | |||
158 | name=tables.LayerMachinesTable.__name__.lower()), | 158 | name=tables.LayerMachinesTable.__name__.lower()), |
159 | 159 | ||
160 | 160 | ||
161 | url(r'^project/(?P<pid>\d+)/distros/$', | ||
162 | tables.DistrosTable.as_view(template_name="generic-toastertable-page.html"), | ||
163 | name="projectdistros"), | ||
164 | |||
165 | |||
161 | url(r'^project/(?P<pid>\d+)/customrecipe/(?P<custrecipeid>\d+)/selectpackages/$', | 166 | url(r'^project/(?P<pid>\d+)/customrecipe/(?P<custrecipeid>\d+)/selectpackages/$', |
162 | tables.SelectPackagesTable.as_view(), name="recipeselectpackages"), | 167 | tables.SelectPackagesTable.as_view(), name="recipeselectpackages"), |
163 | 168 | ||
@@ -187,6 +192,9 @@ urlpatterns = [ | |||
187 | typeaheads.GitRevisionTypeAhead.as_view(), | 192 | typeaheads.GitRevisionTypeAhead.as_view(), |
188 | name='xhr_gitrevtypeahead'), | 193 | name='xhr_gitrevtypeahead'), |
189 | 194 | ||
195 | url(r'^xhr_typeahead/(?P<pid>\d+)/distros$', | ||
196 | typeaheads.DistrosTypeAhead.as_view(), name='xhr_distrostypeahead'), | ||
197 | |||
190 | url(r'^xhr_testreleasechange/(?P<pid>\d+)$', views.xhr_testreleasechange, | 198 | url(r'^xhr_testreleasechange/(?P<pid>\d+)$', views.xhr_testreleasechange, |
191 | name='xhr_testreleasechange'), | 199 | name='xhr_testreleasechange'), |
192 | url(r'^xhr_configvaredit/(?P<pid>\d+)$', views.xhr_configvaredit, | 200 | url(r'^xhr_configvaredit/(?P<pid>\d+)$', views.xhr_configvaredit, |