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): 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: class Meta:
model = WcsCardsCell model = WcsCardsCell
@ -72,7 +74,9 @@ class WcsCardsCellForm(forms.ModelForm):
class WcsCardInfoCellForm(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) customize_display = forms.BooleanField(label=_('Customize display'), required=False)
related_card_path = forms.ChoiceField(label=_('Card Identifier'), 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 += [ self.fields['related_card_path'].choices += [
('--', _('Identifier from page URL')), ('--', _('Identifier from page URL')),
] ]
self.fields['related_card_path'].initial = '--'
if not self.instance.card_ids and not self.instance.related_card_path: if not self.instance.card_ids and not self.instance.related_card_path:
self.initial['related_card_path'] = '--' self.initial['related_card_path'] = '--'
self.fields['related_card_path'].choices += [ self.fields['related_card_path'].choices += [

View File

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

View File

@ -1784,7 +1784,9 @@ class LinkListCell(CellBase):
) )
def get_items_with_prefetch(self): 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): def get_additional_label(self):
title = self.title title = self.title

View File

@ -60,6 +60,19 @@ def get_template_name_choices(with_models=False):
return templates 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): class PageDuplicateForm(forms.Form):
title = forms.CharField(label=_('New title'), max_length=150, required=False) 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-any', _('Users with one of these groups')),
('groups-none', _('Users with none 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) groups = forms.MultipleChoiceField(label=_('Groups'), required=False, choices=get_groups_as_choices)

View File

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

View File

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

View File

@ -17,6 +17,8 @@
from django import forms, template from django import forms, template
from django.urls import reverse from django.urls import reverse
from combo.manager.forms import build_tab_is_not_default
register = template.Library() register = template.Library()
@ -37,6 +39,7 @@ def cell_form(context, cell):
if tab.get('fields'): if tab.get('fields'):
tab['form'] = forms.models.modelform_factory(cell.__class__, fields=tab['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['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[form_name] = tab['form_instance']
context['cell'] = cell context['cell'] = cell
cell_form_template = template.loader.get_template('combo/manager_edit_cell_block.html') cell_form_template = template.loader.get_template('combo/manager_edit_cell_block.html')

View File

@ -88,6 +88,7 @@ from .forms import (
SiteExportForm, SiteExportForm,
SiteImportForm, SiteImportForm,
SiteSettingsForm, SiteSettingsForm,
build_tab_is_not_default,
) )
@ -736,6 +737,7 @@ class PageEditCellView(ManagedPageMixin, UpdateView):
form = tab_error_forms.get(tab['slug']) or tab['form']( form = tab_error_forms.get(tab['slug']) or tab['form'](
instance=self.object, prefix=self.get_prefix(), initial={} instance=self.object, prefix=self.get_prefix(), initial={}
) )
is_not_default = build_tab_is_not_default(form)
if tab['slug'] == 'general': if tab['slug'] == 'general':
form_name = 'form' form_name = 'form'
else: else:
@ -745,7 +747,10 @@ class PageEditCellView(ManagedPageMixin, UpdateView):
cell_form_template = template.loader.get_template(tab['template']) cell_form_template = template.loader.get_template(tab['template'])
else: else:
cell_form_template = engines['django'].from_string('{{ %s.as_p }}' % form_name) 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_css_class'] = self.object.get_manager_visibility_css_class()
response['visibility_content'] = self.object.get_manager_visibility_content() 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 field_prefix = 'cdataviz_chartngcell-%s-' % cell.id
resp.form[field_prefix + 'statistic'] = statistic.pk resp.form[field_prefix + 'statistic'] = statistic.pk
resp = app.post(resp.form.action, params=resp.form.submit_fields(), xhr=True) resp = app.post(resp.form.action, params=resp.form.submit_fields(), xhr=True)
assert 'time_interval' 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'] assert 'This field is required.' not in resp.json['tabs']['general']['form']
@with_httmock(new_api_mock) @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' 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.forms[0]['c%s-test4' % cells[0].get_reference()].value = 'Text Area'
resp = manager_submit_cell(resp.form) 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) resp = app.get('/manage/pages/%s/' % page.id)
assert resp.form['c%s-test' % cells[0].get_reference()].value == 'World Hello' 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): def test_manager_link_cell_tabs(app, admin_user):
page = Page.objects.create(title='One', slug='one', template_name='standard') 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) app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk) 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 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"]') 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(): def test_link_cell_validation():
form = LinkCellForm(data={'url': 'http://example.com'}) form = LinkCellForm(data={'url': 'http://example.com'})

View File

@ -35,7 +35,7 @@ from combo.apps.wcs.models import (
WcsFormsOfCategoryCell, WcsFormsOfCategoryCell,
) )
from combo.data.library import get_cell_classes 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 combo.utils import NothingInCacheException
from .test_manager import login 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): def test_manager_cards_cell_tabs(app, admin_user):
page = Page.objects.create(title='xxx', slug='test_cards_cell_save_cache', template_name='standard') 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) login(app)
resp = app.get('/manage/pages/%s/' % page.pk) resp = app.get('/manage/pages/%s/' % page.pk)
assert not resp.pyquery('[data-tab-slug="general"] input[name$="custom_title"]') 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"]') 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): def test_manager_card_cell_tabs(app, admin_user):
page = Page.objects.create(title='xxx', slug='test_cards', template_name='standard', sub_slug='foobar') 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) app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk) 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"] select[name$="title_type"]')
assert not resp.pyquery('[data-tab-slug="general"] input[name$="custom_title"]') 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"] select[name$="title_type"]')
assert resp.pyquery('[data-tab-slug="appearance"] input[name$="custom_title"]') 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): def test_manager_link_list_tabs(app, admin_user):
page = Page.objects.create(title='One', slug='one', template_name='standard') 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) app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk) resp = app.get('/manage/pages/%s/' % page.pk)
assert not resp.pyquery('[data-tab-slug="general"] input[name$="title"]') 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"]') 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(): def test_import_export_pages_with_links():
page = Page(title='bar', slug='bar', order=1) 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) pq = PyQuery(resp.body)
resp2 = form.submit() resp2 = form.submit()
for tab in resp2.json['tabs']: 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.text = pq.html()
resp._forms_indexed = None resp._forms_indexed = None
assert expect_errors or not resp2.json['errorlist'], 'got unexpected errors' assert expect_errors or not resp2.json['errorlist'], 'got unexpected errors'