manager: add a visual mark to cell tabs with configured settings (#64936)
gitea-wip/combo/pipeline/head There was a failure building this commit Details
gitea/combo/pipeline/head Something is wrong with the build of this commit Details

This commit is contained in:
Lauréline Guérin 2022-06-16 16:49:37 +02:00
parent 02b80dbd53
commit 9428431767
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
12 changed files with 83 additions and 21 deletions

View File

@ -50,7 +50,9 @@ class WcsFormForLinkListCellForm(WcsFormCellForm):
class WcsCardsCellForm(forms.ModelForm):
with_user = forms.BooleanField(label=_('Restrict to cards accessible to the user'), required=False)
with_user = forms.BooleanField(
label=_('Restrict to cards accessible to the user'), required=False, initial=True
)
class Meta:
model = WcsCardsCell
@ -72,7 +74,9 @@ class WcsCardsCellForm(forms.ModelForm):
class WcsCardInfoCellForm(forms.ModelForm):
with_user = forms.BooleanField(label=_('Restrict to cards accessible to the user'), required=False)
with_user = forms.BooleanField(
label=_('Restrict to cards accessible to the user'), required=False, initial=True
)
customize_display = forms.BooleanField(label=_('Customize display'), required=False)
related_card_path = forms.ChoiceField(label=_('Card Identifier'), required=False)
@ -116,6 +120,7 @@ class WcsCardInfoCellForm(forms.ModelForm):
self.fields['related_card_path'].choices += [
('--', _('Identifier from page URL')),
]
self.fields['related_card_path'].initial = '--'
if not self.instance.card_ids and not self.instance.related_card_path:
self.initial['related_card_path'] = '--'
self.fields['related_card_path'].choices += [

View File

@ -62,6 +62,8 @@ class LinkListCellForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance.get_items_with_prefetch():
self.is_not_default = True
class ConfigJsonForm(forms.ModelForm):

View File

@ -1784,7 +1784,9 @@ class LinkListCell(CellBase):
)
def get_items_with_prefetch(self):
return self.get_items(prefetch_validity_info=True)
if not hasattr(self, '_items_with_prefetch_cache'):
self._items_with_prefetch_cache = self.get_items(prefetch_validity_info=True)
return self._items_with_prefetch_cache
def get_additional_label(self):
title = self.title

View File

@ -60,6 +60,19 @@ def get_template_name_choices(with_models=False):
return templates
def build_tab_is_not_default(form):
if getattr(form, 'is_not_default', None) is True:
return True
for field_name, field in form.fields.items():
if field.initial is not None:
if field.initial != form.initial.get(field_name):
return True
else:
if bool(form.initial.get(field_name)):
return True
return False
class PageDuplicateForm(forms.Form):
title = forms.CharField(label=_('New title'), max_length=150, required=False)
@ -274,6 +287,7 @@ class CellVisibilityForm(forms.Form):
('groups-any', _('Users with one of these groups')),
('groups-none', _('Users with none of these groups')),
],
initial='all',
)
groups = forms.MultipleChoiceField(label=_('Groups'), required=False, choices=get_groups_as_choices)

View File

@ -275,10 +275,10 @@ $(function() {
$button.attr('disabled', null);
for (const tab_slug in data.tabs) {
var $tab_content = $form.find('[data-tab-slug="' + tab_slug + '"]');
if (data.tabs[tab_slug].indexOf('ckeditortype') == -1) {
if (data.tabs[tab_slug].form.indexOf('ckeditortype') == -1) {
/* update form with new content, unless it has a ckeditor, as
* this causes an unpleasant flickering */
$tab_content.html(data.tabs[tab_slug]);
$tab_content.html(data.tabs[tab_slug].form);
} else {
for (const error in data.errorlist[tab_slug]) {
var $widget_p = $('[name="' + data.prefix + '-' + error).closest('p');
@ -289,6 +289,11 @@ $(function() {
$widget_p.before($widget_ul);
}
}
if (data.tabs[tab_slug].is_not_default) {
$('#tab-' + $cell.data('cell-reference') + '-' + tab_slug).addClass('pk-tabs--button-marker');
} else {
$('#tab-' + $cell.data('cell-reference') + '-' + tab_slug).removeClass('pk-tabs--button-marker');
}
}
// update title labels
$cell.find('.visibility-summary').removeClass(

View File

@ -5,19 +5,20 @@
{% for tab in manager_tabs %}
<button role="tab"
aria-selected="{{ forloop.first|yesno:"true,false" }}"
aria-controls="panel-{{cell.get_reference}}-{{ forloop.counter }}"
id="tab-{{cell.get_reference}}-{{ forloop.counter }}"
tabindex="{{ forloop.first|yesno:"0,-1" }}">{{ tab.name }}</button>
aria-controls="panel-{{ cell.get_reference }}-{{ tab.slug }}"
id="tab-{{ cell.get_reference }}-{{ tab.slug }}"
tabindex="{{ forloop.first|yesno:"0,-1" }}"
{% if tab.is_not_default %}class="pk-tabs--button-marker"{% endif %}>{{ tab.name }}</button>
{% endfor %}
</div>
<form class="pk-tabs--container" action="{{ url }}" method="post">
{% csrf_token %}
{% for tab in manager_tabs %}
<div id="panel-{{cell.get_reference}}-{{forloop.counter}}"
<div id="panel-{{ cell.get_reference }}-{{ tab.slug }}"
role="tabpanel" tabindex="0" {% if not forloop.first %}hidden{% endif %}
data-tab-slug="{{ tab.slug }}"
aria-labelledby="tab-{{cell.get_reference}}-{{ forloop.counter }}">
aria-labelledby="tab-{{ cell.get_reference }}-{{ tab.slug }}">
{% if tab.template %}{% include tab.template %}{% else %}{{ tab.form_instance.as_p }}{% endif %}
</div>
{% endfor %}

View File

@ -17,6 +17,8 @@
from django import forms, template
from django.urls import reverse
from combo.manager.forms import build_tab_is_not_default
register = template.Library()
@ -37,6 +39,7 @@ def cell_form(context, cell):
if tab.get('fields'):
tab['form'] = forms.models.modelform_factory(cell.__class__, fields=tab['fields'])
tab['form_instance'] = tab['form'](initial={}, instance=cell, prefix='c%s' % cell.get_reference())
tab['is_not_default'] = build_tab_is_not_default(tab['form_instance'])
context[form_name] = tab['form_instance']
context['cell'] = cell
cell_form_template = template.loader.get_template('combo/manager_edit_cell_block.html')

View File

@ -88,6 +88,7 @@ from .forms import (
SiteExportForm,
SiteImportForm,
SiteSettingsForm,
build_tab_is_not_default,
)
@ -736,6 +737,7 @@ class PageEditCellView(ManagedPageMixin, UpdateView):
form = tab_error_forms.get(tab['slug']) or tab['form'](
instance=self.object, prefix=self.get_prefix(), initial={}
)
is_not_default = build_tab_is_not_default(form)
if tab['slug'] == 'general':
form_name = 'form'
else:
@ -745,7 +747,10 @@ class PageEditCellView(ManagedPageMixin, UpdateView):
cell_form_template = template.loader.get_template(tab['template'])
else:
cell_form_template = engines['django'].from_string('{{ %s.as_p }}' % form_name)
response['tabs'][tab['slug']] = cell_form_template.render(context)
response['tabs'][tab['slug']] = {
'form': cell_form_template.render(context),
'is_not_default': is_not_default,
}
response['visibility_css_class'] = self.object.get_manager_visibility_css_class()
response['visibility_content'] = self.object.get_manager_visibility_content()

View File

@ -1624,8 +1624,8 @@ def test_chartng_cell_manager_new_api_dynamic_fields(app, admin_user, new_api_st
field_prefix = 'cdataviz_chartngcell-%s-' % cell.id
resp.form[field_prefix + 'statistic'] = statistic.pk
resp = app.post(resp.form.action, params=resp.form.submit_fields(), xhr=True)
assert 'time_interval' in resp.json['tabs']['general']
assert 'This field is required.' not in resp.json['tabs']['general']
assert 'time_interval' in resp.json['tabs']['general']['form']
assert 'This field is required.' not in resp.json['tabs']['general']['form']
@with_httmock(new_api_mock)

View File

@ -1778,7 +1778,7 @@ def test_edit_config_json_cell(app, admin_user):
assert resp.form['c%s-test4' % cells[0].get_reference()].tag == 'textarea'
resp.forms[0]['c%s-test4' % cells[0].get_reference()].value = 'Text Area'
resp = manager_submit_cell(resp.form)
assert resp.json['tabs']['general'].strip().startswith('<p><label')
assert resp.json['tabs']['general']['form'].strip().startswith('<p><label')
resp = app.get('/manage/pages/%s/' % page.id)
assert resp.form['c%s-test' % cells[0].get_reference()].value == 'World Hello'
@ -2628,13 +2628,22 @@ def test_link_cell_setup():
def test_manager_link_cell_tabs(app, admin_user):
page = Page.objects.create(title='One', slug='one', template_name='standard')
LinkCell.objects.create(order=0, placeholder='content', page=page)
cell = LinkCell.objects.create(order=0, placeholder='content', page=page)
app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk)
assert not resp.pyquery('#tab-%s-general.pk-tabs--button-marker' % cell.get_reference())
assert resp.pyquery('[data-tab-slug="general"] input[name$="title"]')
assert not resp.pyquery('#tab-%s-visibility.pk-tabs--button-marker' % cell.get_reference())
assert not resp.pyquery('[data-tab-slug="appearance"] input[name$="title"]')
cell.title = "Custom"
cell.public = False
cell.save()
resp = app.get('/manage/pages/%s/' % page.pk)
assert resp.pyquery('#tab-%s-general.pk-tabs--button-marker' % cell.get_reference())
assert resp.pyquery('#tab-%s-visibility.pk-tabs--button-marker' % cell.get_reference())
def test_link_cell_validation():
form = LinkCellForm(data={'url': 'http://example.com'})

View File

@ -35,7 +35,7 @@ from combo.apps.wcs.models import (
WcsFormsOfCategoryCell,
)
from combo.data.library import get_cell_classes
from combo.data.models import CellBase, LinkListCell, Page, ValidityInfo
from combo.data.models import CellBase, LinkCell, LinkListCell, Page, ValidityInfo
from combo.utils import NothingInCacheException
from .test_manager import login
@ -1664,12 +1664,13 @@ def test_manager_cards_cell(mock_send, app, admin_user):
def test_manager_cards_cell_tabs(app, admin_user):
page = Page.objects.create(title='xxx', slug='test_cards_cell_save_cache', template_name='standard')
WcsCardsCell.objects.create(page=page, placeholder='content', order=0)
cell = WcsCardsCell.objects.create(page=page, placeholder='content', order=0)
login(app)
resp = app.get('/manage/pages/%s/' % page.pk)
assert not resp.pyquery('[data-tab-slug="general"] input[name$="custom_title"]')
assert not resp.pyquery('#tab-%s-general.pk-tabs--button-marker' % cell.get_reference())
assert resp.pyquery('[data-tab-slug="appearance"] input[name$="custom_title"]')
@ -2496,13 +2497,14 @@ def test_manager_card_cell(mock_send, app, admin_user):
def test_manager_card_cell_tabs(app, admin_user):
page = Page.objects.create(title='xxx', slug='test_cards', template_name='standard', sub_slug='foobar')
WcsCardInfosCell.objects.create(page=page, placeholder='content', order=0)
cell = WcsCardInfosCell.objects.create(page=page, placeholder='content', order=0)
app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk)
assert not resp.pyquery('[data-tab-slug="general"] select[name$="title_type"]')
assert not resp.pyquery('[data-tab-slug="general"] input[name$="custom_title"]')
assert not resp.pyquery('#tab-%s-general.pk-tabs--button-marker' % cell.get_reference())
assert resp.pyquery('[data-tab-slug="appearance"] select[name$="title_type"]')
assert resp.pyquery('[data-tab-slug="appearance"] input[name$="custom_title"]')
@ -4262,13 +4264,25 @@ def test_manager_add_edit_delete_list_link_item(mock_send, app, admin_user):
def test_manager_link_list_tabs(app, admin_user):
page = Page.objects.create(title='One', slug='one', template_name='standard')
LinkListCell.objects.create(order=0, placeholder='content', page=page)
cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk)
assert not resp.pyquery('[data-tab-slug="general"] input[name$="title"]')
assert not resp.pyquery('#tab-%s-general.pk-tabs--button-marker' % cell.get_reference())
assert resp.pyquery('[data-tab-slug="appearance"] input[name$="title"]')
LinkCell.objects.create(
page=page,
placeholder=cell.link_placeholder,
title='Example Site',
url='http://example.net/',
link_page=page,
order=1,
)
resp = app.get('/manage/pages/%s/' % page.id)
assert resp.pyquery('#tab-%s-general.pk-tabs--button-marker' % cell.get_reference())
def test_import_export_pages_with_links():
page = Page(title='bar', slug='bar', order=1)

View File

@ -9,7 +9,9 @@ def manager_submit_cell(form, expect_errors=False):
pq = PyQuery(resp.body)
resp2 = form.submit()
for tab in resp2.json['tabs']:
pq.find('form[action="%s"] [data-tab-slug="%s"]' % (action, tab)).html(resp2.json['tabs'][tab])
pq.find('form[action="%s"] [data-tab-slug="%s"]' % (action, tab)).html(
resp2.json['tabs'][tab]['form']
)
resp.text = pq.html()
resp._forms_indexed = None
assert expect_errors or not resp2.json['errorlist'], 'got unexpected errors'