mirror of
git://git.yoctoproject.org/layerindex-web.git
synced 2025-07-19 20:59:01 +02:00
Support selecting more than one layer in other distro comparison search form
Provide a lazy-loaded popup for selecting layers to include in the query instead of having it as a simple drop-down, so you can select more than one layer. Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
parent
8ef315c6bf
commit
26d2bd2f36
|
@ -8,7 +8,7 @@ from django.conf.urls import *
|
||||||
from django.views.generic import TemplateView, DetailView, ListView, RedirectView
|
from django.views.generic import TemplateView, DetailView, ListView, RedirectView
|
||||||
from django.views.defaults import page_not_found
|
from django.views.defaults import page_not_found
|
||||||
from django.core.urlresolvers import reverse_lazy
|
from django.core.urlresolvers import reverse_lazy
|
||||||
from layerindex.views import LayerListView, LayerReviewListView, LayerReviewDetailView, RecipeSearchView, MachineSearchView, LayerDetailView, edit_layer_view, delete_layer_view, edit_layernote_view, delete_layernote_view, HistoryListView, EditProfileFormView, AdvancedRecipeSearchView, BulkChangeView, BulkChangeSearchView, bulk_change_edit_view, bulk_change_patch_view, BulkChangeDeleteView, RecipeDetailView, RedirectParamsView, ClassicRecipeSearchView, ClassicRecipeDetailView, ClassicRecipeStatsView, LayerUpdateDetailView, UpdateListView, UpdateDetailView, StatsView, publish_view
|
from layerindex.views import LayerListView, LayerReviewListView, LayerReviewDetailView, RecipeSearchView, MachineSearchView, LayerDetailView, edit_layer_view, delete_layer_view, edit_layernote_view, delete_layernote_view, HistoryListView, EditProfileFormView, AdvancedRecipeSearchView, BulkChangeView, BulkChangeSearchView, bulk_change_edit_view, bulk_change_patch_view, BulkChangeDeleteView, RecipeDetailView, RedirectParamsView, ClassicRecipeSearchView, ClassicRecipeDetailView, ClassicRecipeStatsView, LayerUpdateDetailView, UpdateListView, UpdateDetailView, StatsView, publish_view, LayerCheckListView
|
||||||
from layerindex.models import LayerItem, Recipe, RecipeChangeset
|
from layerindex.models import LayerItem, Recipe, RecipeChangeset
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
from . import restviews
|
from . import restviews
|
||||||
|
@ -150,5 +150,9 @@ urlpatterns = [
|
||||||
ClassicRecipeDetailView.as_view(
|
ClassicRecipeDetailView.as_view(
|
||||||
template_name='layerindex/classicrecipedetail.html'),
|
template_name='layerindex/classicrecipedetail.html'),
|
||||||
name='comparison_recipe'),
|
name='comparison_recipe'),
|
||||||
|
url(r'^ajax/layerchecklist/(?P<branch>[-\w]+)/$',
|
||||||
|
LayerCheckListView.as_view(
|
||||||
|
template_name='layerindex/layerchecklist.html'),
|
||||||
|
name='layer_checklist'),
|
||||||
url(r'.*', page_not_found, kwargs={'exception': Exception("Page not Found")})
|
url(r'.*', page_not_found, kwargs={'exception': Exception("Page not Found")})
|
||||||
]
|
]
|
||||||
|
|
|
@ -940,6 +940,13 @@ class ClassicRecipeReverseLinkWrapper(LinkWrapper):
|
||||||
setattr(obj, 'cover_vercmp', vercmp)
|
setattr(obj, 'cover_vercmp', vercmp)
|
||||||
|
|
||||||
|
|
||||||
|
class LayerCheckListView(ListView):
|
||||||
|
context_object_name = 'layerbranches'
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
_check_url_branch(self.kwargs)
|
||||||
|
return LayerBranch.objects.filter(branch__name=self.kwargs['branch']).filter(layer__status__in=['P', 'X']).order_by('layer__name')
|
||||||
|
|
||||||
|
|
||||||
class ClassicRecipeSearchView(RecipeSearchView):
|
class ClassicRecipeSearchView(RecipeSearchView):
|
||||||
def render_to_response(self, context, **kwargs):
|
def render_to_response(self, context, **kwargs):
|
||||||
|
@ -952,7 +959,11 @@ class ClassicRecipeSearchView(RecipeSearchView):
|
||||||
cover_status = self.request.GET.get('cover_status', None)
|
cover_status = self.request.GET.get('cover_status', None)
|
||||||
cover_verified = self.request.GET.get('cover_verified', None)
|
cover_verified = self.request.GET.get('cover_verified', None)
|
||||||
category = self.request.GET.get('category', None)
|
category = self.request.GET.get('category', None)
|
||||||
oe_layer = self.request.GET.get('oe_layer', None)
|
selectedlayers_param = self.request.GET.get('selectedlayers', '')
|
||||||
|
if selectedlayers_param:
|
||||||
|
layer_ids = [int(i) for i in selectedlayers_param.split(',')]
|
||||||
|
else:
|
||||||
|
layer_ids = []
|
||||||
has_patches = self.request.GET.get('has_patches', '')
|
has_patches = self.request.GET.get('has_patches', '')
|
||||||
needs_attention = self.request.GET.get('needs_attention', '')
|
needs_attention = self.request.GET.get('needs_attention', '')
|
||||||
qreversed = self.request.GET.get('reversed', '')
|
qreversed = self.request.GET.get('reversed', '')
|
||||||
|
@ -978,8 +989,8 @@ class ClassicRecipeSearchView(RecipeSearchView):
|
||||||
else:
|
else:
|
||||||
init_qs = init_qs.filter(classic_category__icontains=category)
|
init_qs = init_qs.filter(classic_category__icontains=category)
|
||||||
filtered = True
|
filtered = True
|
||||||
if oe_layer:
|
if layer_ids:
|
||||||
init_qs = init_qs.filter(cover_layerbranch__layer=oe_layer)
|
init_qs = init_qs.filter(cover_layerbranch__layer__in=layer_ids)
|
||||||
if has_patches.strip():
|
if has_patches.strip():
|
||||||
if has_patches == '1':
|
if has_patches == '1':
|
||||||
init_qs = init_qs.filter(patch__isnull=False).distinct()
|
init_qs = init_qs.filter(patch__isnull=False).distinct()
|
||||||
|
@ -1015,8 +1026,8 @@ class ClassicRecipeSearchView(RecipeSearchView):
|
||||||
return Recipe.objects.none()
|
return Recipe.objects.none()
|
||||||
if qreversed:
|
if qreversed:
|
||||||
init_rqs = Recipe.objects.filter(layerbranch__branch__name='master')
|
init_rqs = Recipe.objects.filter(layerbranch__branch__name='master')
|
||||||
if oe_layer:
|
if layer_ids:
|
||||||
init_rqs = init_rqs.filter(layerbranch__layer=oe_layer)
|
init_rqs = init_rqs.filter(layerbranch__layer__id__in=layer_ids)
|
||||||
all_values = []
|
all_values = []
|
||||||
if filtered:
|
if filtered:
|
||||||
if isinstance(qs, list):
|
if isinstance(qs, list):
|
||||||
|
@ -1057,6 +1068,16 @@ class ClassicRecipeSearchView(RecipeSearchView):
|
||||||
context['reversed'] = self.request.GET.get('reversed', False)
|
context['reversed'] = self.request.GET.get('reversed', False)
|
||||||
context['search_form'] = search_form
|
context['search_form'] = search_form
|
||||||
context['searched'] = searched
|
context['searched'] = searched
|
||||||
|
selectedlayers_param = self.request.GET.get('selectedlayers', '')
|
||||||
|
if selectedlayers_param:
|
||||||
|
all_layer_names = dict(LayerItem.objects.all().values_list('id', 'name'))
|
||||||
|
layer_ids = [int(i) for i in selectedlayers_param.split(',')]
|
||||||
|
layer_names = [all_layer_names[i] for i in layer_ids]
|
||||||
|
context['selectedlayers_display'] = ','.join(layer_names)
|
||||||
|
else:
|
||||||
|
layer_ids = []
|
||||||
|
context['selectedlayers_display'] = ' (any)'
|
||||||
|
context['selectedlayers'] = layer_ids
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,12 +45,45 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for field in search_form.visible_fields %}
|
{% for field in search_form.visible_fields %}
|
||||||
<tr>
|
<tr>
|
||||||
|
{% if field.name == 'oe_layer' %}
|
||||||
|
<td>
|
||||||
|
{{ field.label }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="input-append">
|
||||||
|
<input type="text" class="input-large" id="id_selectedlayers_display" value="{{ selectedlayers_display }}" />
|
||||||
|
<a href="#layerDialog" id="id_select_layers" role="button" class="btn" data-toggle="modal">...</a>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" id="id_selectedlayers" name="selectedlayers" value="{{ selectedlayers|join:"," }}" />
|
||||||
|
|
||||||
|
<div id="layerDialog" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="layerDialogLabel" aria-hidden="true">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h3 id="layerDialogLabel">Select layers to include</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="scrolling" id="id_layerdialog_list">
|
||||||
|
</div>
|
||||||
|
<div class="buttonblock">
|
||||||
|
<button type="button" class="btn" id="id_layerdialog_select_all">Select all</button>
|
||||||
|
<button type="button" class="btn buttonblock-btn" id="id_layerdialog_select_none">Select none</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-primary" id="id_layerdialog_ok" data-dismiss="modal" aria-hidden="true">OK</button>
|
||||||
|
<button class="btn" id="id_layerdialog_cancel" data-dismiss="modal" aria-hidden="true">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
{% else %}
|
||||||
<td>
|
<td>
|
||||||
{{ field.label }}
|
{{ field.label }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ field }}
|
{{ field }}
|
||||||
</td>
|
</td>
|
||||||
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<tr><td><label class="checkbox"><input type="checkbox" name="compare" {% if compare %}checked{% endif %}></input>Show comparison</label></td></tr>
|
<tr><td><label class="checkbox"><input type="checkbox" name="compare" {% if compare %}checked{% endif %}></input>Show comparison</label></td></tr>
|
||||||
|
@ -169,11 +202,80 @@
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script>
|
<script>
|
||||||
|
update_selected_layer_display = function() {
|
||||||
|
layernames = [];
|
||||||
|
layerids = [];
|
||||||
|
$('.filterlayercheckbox:checked').each(function() {
|
||||||
|
layernames.push($("label[for="+$(this).attr('id')+"]").html());
|
||||||
|
layerids.push($(this).attr('value'))
|
||||||
|
});
|
||||||
|
$('#id_selectedlayers').val(layerids)
|
||||||
|
if(layernames.length)
|
||||||
|
$('#id_selectedlayers_display').val(layernames)
|
||||||
|
else
|
||||||
|
$('#id_selectedlayers_display').val(' (any)')
|
||||||
|
}
|
||||||
|
update_filters_enabled = function() {
|
||||||
|
if( $('#id_reversed').is(":checked") ) {
|
||||||
|
$('#id_reversed_fields').show()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#id_reversed_fields').hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select_layer_checkboxes = function() {
|
||||||
|
$('.filterlayercheckbox').attr('checked', false);
|
||||||
|
selectedlayers = $('#id_selectedlayers').val().split(',');
|
||||||
|
for(i in selectedlayers) {
|
||||||
|
$('#id_layercheckbox_' + selectedlayers[i]).attr('checked', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setup_layer_list = function() {
|
||||||
|
if( $.trim($('#id_layerdialog_list').html()) ) {
|
||||||
|
select_layer_checkboxes()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#id_layerdialog_list').html('Loading...');
|
||||||
|
$('#id_layerdialog_ok').prop('disabled', true)
|
||||||
|
$('#id_layerdialog_ok').addClass('disabled')
|
||||||
|
$.ajax({
|
||||||
|
url: '{% url 'layer_checklist' 'master' %}',
|
||||||
|
dataType: 'html',
|
||||||
|
success: function( resp ) {
|
||||||
|
$('#id_layerdialog_list').html(resp);
|
||||||
|
select_layer_checkboxes()
|
||||||
|
$('#id_layerdialog_ok').prop('disabled', false)
|
||||||
|
$('#id_layerdialog_ok').removeClass('disabled')
|
||||||
|
},
|
||||||
|
error: function( req, status, err ) {
|
||||||
|
$('#id_layerdialog_list').html(err);
|
||||||
|
console.log( 'something went wrong', status, err );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
$('#id_selectedlayers_display').prop('readonly', true)
|
||||||
|
update_filters_enabled()
|
||||||
$('[data-toggle="tooltip"]').tooltip();
|
$('[data-toggle="tooltip"]').tooltip();
|
||||||
firstfield = $("#search-form input:text").first()
|
firstfield = $("#search-form input:text").first()
|
||||||
if( ! firstfield.val() )
|
if( ! firstfield.val() )
|
||||||
firstfield.focus()
|
firstfield.focus()
|
||||||
});
|
});
|
||||||
|
$('#id_layerdialog_select_all').click(function (e) {
|
||||||
|
$('.filterlayercheckbox').attr('checked', true);
|
||||||
|
});
|
||||||
|
$('#id_layerdialog_select_none').click(function (e) {
|
||||||
|
$('.filterlayercheckbox').attr('checked', false);
|
||||||
|
});
|
||||||
|
$('#id_layerdialog_ok').click(function (e) {
|
||||||
|
update_selected_layer_display()
|
||||||
|
});
|
||||||
|
$('#id_select_layers').click(function (e) {
|
||||||
|
setup_layer_list()
|
||||||
|
});
|
||||||
|
$('#id_reversed').click(function (e) {
|
||||||
|
update_filters_enabled()
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
21
templates/layerindex/layerchecklist.html
Normal file
21
templates/layerindex/layerchecklist.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{% comment %}
|
||||||
|
|
||||||
|
layerindex-web - layer check list AJAX template
|
||||||
|
|
||||||
|
Copyright (C) 2018 Intel Corporation
|
||||||
|
Licensed under the MIT license, see COPYING.MIT for details
|
||||||
|
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% autoescape on %}
|
||||||
|
<table><tbody>
|
||||||
|
{% for layerbranch in layerbranches %}
|
||||||
|
<tr>
|
||||||
|
<td class="checkboxtd">
|
||||||
|
<input type="checkbox" class="filterlayercheckbox" value="{{ layerbranch.layer.id }}" id="id_layercheckbox_{{layerbranch.layer.id}}" />
|
||||||
|
</td>
|
||||||
|
<td><label for="id_layercheckbox_{{layerbranch.layer.id}}">{{ layerbranch.layer.name }}</label></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody></table>
|
||||||
|
{% endautoescape %}
|
Loading…
Reference in New Issue
Block a user