wcs: allows filters in card cell when cards mode (#75920)
gitea/combo/pipeline/head This commit looks good Details

This commit is contained in:
Valentin Deniaud 2023-05-15 17:58:34 +02:00
parent 91f16c65f3
commit 5a4372ba2e
8 changed files with 113 additions and 3 deletions

View File

@ -26,6 +26,7 @@ from django.db.models import JSONField
from django.forms import Select
from django.forms import models as model_forms
from django.template import Context, RequestContext, Template, TemplateSyntaxError, VariableDoesNotExist
from django.template.loader import render_to_string
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.text import slugify
@ -891,6 +892,9 @@ class WcsCardCell(CardMixin, CellBase):
js = ('js/combo.filter-cards.js', 'xstatic/select2.min.js')
css = {'all': ('xstatic/select2.min.css',)}
def include_filters(self):
return bool(self.filters and self.display_mode == 'card' and getattr(self, 'repeat_index', 0) == 0)
def get_card_ids(self, context):
lazy_value = context.get(self.global_context_key)
if lazy_value is not None:
@ -1484,6 +1488,14 @@ class WcsCardCell(CardMixin, CellBase):
{('user:%s' % k): v for k, v in card_data.get('user', {}).items() if k not in ['NameId', 'id']}
)
def render_filters(self, context):
from .forms import WcsCardCellFiltersForm
card_ids = self.get_card_ids(context)
cards = self.get_cards_from_ids(card_ids, context, synchronous=True)
form = WcsCardCellFiltersForm(self, cards)
return render_to_string('combo/wcs/card-filters.html', {'form': form, 'cell': self})
def get_cell_extra_context_table_mode(self, context, extra_context):
from .forms import WcsCardCellFiltersForm

View File

@ -7,7 +7,8 @@ $(function () {
var value = $(this).val();
if (value.length) {
var items_to_hide = items.filter(function() {
return $(value).filter($(this).data(filter_id)).length == 0;
elem = $(this).hasClass('cell') ? $(this).find('.cell--body') : $(this);
return $(value).filter(elem.data(filter_id)).length == 0;
});
items_to_hide.hide();
items_to_hide.attr('data-ignore', filter_id);
@ -22,4 +23,11 @@ $(function () {
$(document).trigger('combo:refresh-pagination', cell);
});
});
$('.card-filters--container .wcs-card-filters select').change(function() {
var cells_pk = $(this).parents('form').data('target-cells-pk');
var cells = $('.wcs_wcscardcell-' + cells_pk);
filter_items($(this), cells);
$(document).trigger('combo:refresh-pagination-cards');
});
});

View File

@ -0,0 +1,9 @@
{% load i18n gadjo %}
<div class="card-filters--container">
<h2>{% trans "Filter by:" %}</h2>
<form class="wcs-card-filters" data-target-cells-pk="{{ cell.pk }}">
{{ form|with_template }}
</form>
</div>

View File

@ -12,7 +12,7 @@
{% spaceless %}
{% if cell.custom_schema %}
{% if cell.custom_schema.cells %}
<div class="cell--body">
<div class="cell--body" {{ cell|get_filter_attrs:card }}>
{% with cell.get_custom_schema as custom_schema %}
<div class="{{ custom_schema.grid_class }}">
{% for item in custom_schema.cells %}
@ -91,7 +91,7 @@
{% endif %}
{% else %}
<div class="cell--body">
<div class="cell--body" {{ cell|get_filter_attrs:card }}>
{% for field in schema.fields %}
{% if 'varname' in field and field.varname %}
{% with card.fields|get:field.varname as value %}

View File

@ -402,10 +402,15 @@ $(function() {
function paginate_cards($pagination) {
var items = $pagination.parent().find('.card.' + $pagination.data('cell-reference'));
items = $(items).not('[data-ignore]');
paginate($pagination, items, false);
};
// pagination for cells with list of items or for card cells
$(document).on('combo:refresh-pagination-cards', function() {
var $pagination = $('.cell-items-pagination');
paginate_cards($pagination);
});
$(document).on('combo:cell-loaded combo:refresh-pagination', function(ev, cell) {
var $pagination = $(cell).find('.cell-items-pagination');
if ($pagination.length == 0) return;

View File

@ -6,6 +6,9 @@
{{ skeleton }}
{% endif %}
{% for cell in cells %}
{% if cell.include_filters %}
{% render_filters cell %}
{% endif %}
<div class="cell {{ cell.css_class_names }} {{ cell.asset_css_classes }}{% if cell.slug %} {{cell.slug}}{% endif %}{% if cell|shown_because_admin:request %} shown-because-admin{% endif %}"
{% if cell.slug and cell.use_slug_as_id %}id="{{ cell.slug }}"{% endif %}
data-ajax-cell-url="{{ site_base }}{{ cell.get_ajax_url }}"

View File

@ -162,6 +162,11 @@ def render_cell(context, cell):
raise
@register.simple_tag(takes_context=True)
def render_filters(context, cell):
return cell.render_filters(context)
@register.tag
def skeleton_extra_placeholder(parser, token):
try:

View File

@ -3236,6 +3236,74 @@ def test_card_cell_card_mode_render_identifier_from_related(mock_send, nocache,
)
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_card_cell_card_mode_render_filters(mock_send, context, app):
page = Page.objects.create(title='xxx', template_name='standard')
cell = WcsCardCell.objects.create(
page=page,
placeholder='content',
order=0,
display_mode='card',
carddef_reference='default:card_model_1',
)
resp = app.get(page.get_online_url())
assert not resp.forms
cell.filters = ['related']
cell.save()
resp = app.get(page.get_online_url())
assert len(resp.form.fields) == 1
assert resp.form['related'].options == [('13', False, 'Abc'), ('42', False, 'Foo Bar')]
attributes = [x.attrib for x in resp.pyquery('.cell--body')]
data_attributes = [{k: v for k, v in attr.items() if k.startswith('data')} for attr in attributes]
assert data_attributes == [
{'data-related': '[42]'},
{'data-related': '[13]'},
{},
]
cell.filters = ['related', 'fieldj']
cell.save()
resp = app.get(page.get_online_url())
assert len(resp.form.fields) == 2
assert resp.form['fieldj'].options == [
('first value', False, 'First Value'),
('second value', False, 'Second Value'),
('third value', False, 'Third Value'),
]
attributes = [x.attrib for x in resp.pyquery('.cell--body')]
data_attributes = [{k: v for k, v in attr.items() if k.startswith('data')} for attr in attributes]
assert data_attributes == [
{'data-related': '[42]', 'data-fieldj': '["first value", "second value"]'},
{'data-related': '[13]', 'data-fieldj': '["first value", "third value"]'},
{},
]
cell.custom_schema = {
'cells': [
{'varname': 'fielda', 'field_content': 'value', 'display_mode': 'title'},
{'varname': 'fieldb', 'field_content': 'value', 'display_mode': 'title'},
]
}
cell.save()
resp = app.get(page.get_online_url())
assert len(resp.form.fields) == 2
attributes = [x.attrib for x in resp.pyquery('.cell--body')]
data_attributes = [{k: v for k, v in attr.items() if k.startswith('data')} for attr in attributes]
assert data_attributes == [
{'data-related': '[42]', 'data-fieldj': '["first value", "second value"]'},
{'data-related': '[13]', 'data-fieldj': '["first value", "third value"]'},
{},
]
@pytest.mark.parametrize('carddef_reference', ['default:card_model_1', 'default:card_model_1:foo'])
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_card_cell_only_for_user(mock_send, context, carddef_reference):