manager: use sidetabs to navigate between cell options (#62965)
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:
Frédéric Péters 2022-03-23 22:01:25 +01:00
parent fd6ae4e785
commit 57dec72cb7
21 changed files with 399 additions and 291 deletions

View File

@ -403,14 +403,24 @@ class Map(CellBase):
fields = (
'title',
'initial_state',
'initial_zoom',
'min_zoom',
'max_zoom',
'group_markers',
'marker_behaviour_onclick',
)
return forms.models.modelform_factory(self.__class__, fields=fields)
def get_manager_tabs(self):
zoom_fields = ['initial_zoom', 'min_zoom', 'max_zoom']
tabs = super().get_manager_tabs()
tabs.insert(
1,
{
'slug': 'zoom',
'name': _('Zoom'),
'form': forms.models.modelform_factory(self.__class__, fields=zoom_fields),
},
)
return tabs
@classmethod
def is_enabled(cls):
return MapLayer.objects.exists()

View File

@ -781,6 +781,7 @@ class CellMeta(MediaDefiningClass, ModelBase):
@python_2_unicode_compatible
class CellBase(models.Model, metaclass=CellMeta):
# noqa pylint: disable=too-many-public-methods
page = models.ForeignKey(Page, on_delete=models.CASCADE)
placeholder = models.CharField(max_length=20)
@ -803,6 +804,8 @@ class CellBase(models.Model, metaclass=CellMeta):
default_form_class = None
manager_form_factory_kwargs = {}
manager_form_template = 'combo/cell_form.html'
manager_visibility_template = 'combo/cell_visibility.html'
manager_appearance_template = 'combo/cell_appearance.html'
children_placeholder_prefix = None
visible = True
@ -841,6 +844,21 @@ class CellBase(models.Model, metaclass=CellMeta):
def get_additional_label(self):
return ''
def get_manager_visibility_css_class(self):
if self.public:
return 'visibility-all' if not self.restricted_to_unlogged else ''
elif self.restricted_to_unlogged:
return 'visibility-off'
return ''
def get_manager_visibility_content(self):
if self.public and not self.restricted_to_unlogged:
return ''
group_names = ', '.join([x.name for x in self.groups.all()])
if group_names:
return group_names
return _('unlogged users') if self.restricted_to_unlogged else _('logged users')
@property
def legacy_class_name(self):
# legacy class name used in some themes
@ -1063,6 +1081,38 @@ class CellBase(models.Model, metaclass=CellMeta):
def get_label(self):
return self.get_verbose_name()
def get_manager_tabs(self):
from combo.manager.forms import CellVisibilityForm
tabs = []
form_class = self.get_default_form_class()
if form_class:
tabs.append(
{
'slug': 'general',
'name': _('General'),
'template': self.manager_form_template,
'form': form_class,
}
)
tabs.append(
{
'slug': 'visibility',
'name': _('Visibility'),
'template': self.manager_visibility_template,
'form': CellVisibilityForm,
}
)
tabs.append(
{
'slug': 'appearance',
'name': _('Appearance'),
'template': self.manager_appearance_template,
'form': self.get_appearance_form_class(),
}
)
return tabs
def get_default_form_fields(self):
return [
x.name
@ -1083,19 +1133,20 @@ class CellBase(models.Model, metaclass=CellMeta):
)
]
def get_default_form_class(self):
def get_default_form_class(self, fields=None):
if self.default_form_class:
return self.default_form_class
fields = self.get_default_form_fields()
if not fields:
return None
fields = self.get_default_form_fields()
if not fields:
return None
return model_forms.modelform_factory(
self.__class__, fields=fields, **self.manager_form_factory_kwargs
)
def get_options_form_class(self):
def get_appearance_form_class(self):
fields = ['slug', 'extra_css_class']
widgets = None
extra_templates = settings.COMBO_CELL_TEMPLATES.get(self.get_cell_type_str())

View File

@ -1,3 +1,16 @@
// Only display content to screen readers
@mixin sr-only {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip: rect(0, 0, 0, 0) !important;
white-space: nowrap !important;
border: 0 !important;
}
body.no-header #header {
display: none;
}
@ -48,31 +61,23 @@ div.cell-list > div {
margin: 1ex 0;
box-shadow: rgba(0, 0, 0, 0.04) 0px 1px 1px 0px;
position: relative;
> div {
display: none;
overflow: hidden;
}
&.toggled > div {
display: block;
}
}
div.cell-list > div > div form {
padding: 1ex;
}
div.cell-list > div > div {
display: none;
transition: max-height linear 0.2s;
overflow: hidden;
}
.cell-form textarea {
width: 100%;
}
div.cell-list > div.untoggled > div {
display: block;
max-height: 0;
}
div.cell-list > div.toggled > div {
display: block;
}
div.cell > h3 {
background: #fafafa;
margin: 0;
@ -132,15 +137,19 @@ div.page span.visibility-summary {
div.cell h3 span.visibility-summary::before,
div.page span.visibility-summary::before {
content: "\f06e"; /* fa-eye */
content: "\f06e "; /* fa-eye */
font-family: FontAwesome;
}
div.cell h3 span.visibility-summary.visibility-off::before {
content: "\f070"; /* fa-eye-slash */
content: "\f070 "; /* fa-eye-slash */
font-family: FontAwesome;
}
div.cell h3 span.visibility-summary.visibility-all::before {
content: none;
}
div.cell h3 span.visibility-summary {
max-width: 30%;
}
@ -167,20 +176,6 @@ div.cell-list div.toggled h3:after {
content: "\f106"; /* angle-up */
}
div.cell-list button.save {
position: relative;
right: 2ex;
bottom: 1ex;
float: right;
}
div.cell div.cell-buttons {
clear: both;
margin-top: 2em;
margin-bottom: 1ex;
}
div.cell-list .empty-cell {
list-style: none;
margin: 0;
@ -682,3 +677,36 @@ form .choices {
.search-engine-add {
margin: 2em 0;
}
.cell-properties {
.django-ckeditor-widget {
display: block !important;
}
&--buttons {
margin-top: 1em;
display: flex;
justify-content: space-between;
}
.duplicate-button {
&::before {
font-family: FontAwesome;
content: "\f24d"; /* clone */
}
span {
@include sr-only();
}
}
.delete-button {
&::before {
font-family: FontAwesome;
content: "\f014"; /* trash */
}
span {
@include sr-only();
}
}
}
.cell.map .pk-tabs-container--content-panels .buttons {
margin: 1em 0;
}

View File

@ -190,16 +190,6 @@ function init_pages_list(toggle_state)
});
}
function compute_max_height($cell) {
var cell_id = $cell.attr('id');
$('style#for-' + cell_id).remove();
var h = $cell.find('h3 + div').height() + 40;
h += $cell.find('.multisort').length * 250;
h += $cell.find('.django-ckeditor-widget').length * 200;
var style = '<style id="for-' + cell_id + '">div#' + cell_id + '.toggled h3 + div { max-height: '+h+'px; }</style>';
$(style).appendTo('head');
}
$(function() {
$('div.cell-list h3').on('click', function() {
$(this).parent().toggleClass('toggled').toggleClass('untoggled');
@ -270,6 +260,7 @@ $(function() {
$('div.cell button.save').on('click', function(event) {
var $button = $(this);
var $form = $(this).closest('form');
var $cell = $(this).closest('div.cell');
var button_label = $button.text();
for (instance in CKEDITOR.instances) {
CKEDITOR.instances[instance].updateElement();
@ -281,27 +272,54 @@ $(function() {
beforeSend: function() { $button.attr('disabled', 'disabled'); },
success: function(data) {
$button.attr('disabled', null);
if (data.indexOf('ckeditortype') == -1) {
/* update form with new content, unless it has a ckeditor, as
* this causes an unpleasant flickering */
$button.parents('form').find('div.cell-form').html(data);
compute_max_height($form.parents('div.cell'));
}
$form.parents('div.cell').trigger('combo:cellform-reloaded');
if (data.indexOf('class="errorlist"') == -1) {
$.getJSON($form.data('label-url'),
function(data) {
$form.parents('div.cell').find('.additional-label i').text(data['label']);
if (data['invalid_reason']) {
if (! $form.parents('div.cell').find('.invalid').length) {
$('<span class="invalid"></span>').insertAfter($form.parents('div.cell').find('.additional-label'));
}
$form.parents('div.cell').find('.invalid').text(data['invalid_reason']);
} else {
$form.parents('div.cell').find('.invalid').remove();
}
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) {
/* update form with new content, unless it has a ckeditor, as
* this causes an unpleasant flickering */
$tab_content.html(data.tabs[tab_slug]);
} else {
for (const error in data.errorlist[tab_slug]) {
var $widget_p = $('[name="' + data.prefix + '-' + error).closest('p');
var $widget_ul = $('<ul class="errorlist"></ul>');
for (idx in data.errorlist[form_slug][error]) {
$widget_ul.append($('<li>', {text: data.errorlist[form_slug][error][idx]}));
}
$widget_p.before($widget_ul);
}
);
}
}
// update title labels
$cell.find('.visibility-summary').removeClass(
).addClass('visibility-summary').addClass(data.visibility_css_class
).text(data.visibility_content);
function wrap(label, sign) {
if (! label) return '';
if (sign == '(') return '(' + label + ')';
if (sign == '[') return '[' + label + ']';
return label;
}
$cell.find('h3 .cell-slug').text(wrap(data.slug, '['));
$cell.find('h3 .cell-template-label').text(wrap(data.template_label, '('));
$cell.find('h3 .extra-css-class').text(wrap(data.extra_css_class, '['));
$cell.find('h3 .additional-label i').text(wrap(data.additional_label));
if (data['invalid_reason']) {
if (! $cell.find('.invalid').length) {
$('<span class="invalid"></span>').insertAfter($cell.find('.additional-label'));
}
$cell.find('.invalid').text(data['invalid_reason']);
} else {
$cell.find('.invalid').remove();
}
// select first panel with errors (if any)
const $current_tab = $form.find('[role=tabpanel]:not([hidden])');
if ($current_tab.find('.errorlist').length == 0) {
const $panel_with_error = $form.find('[role=tabpanel] .errorlist').first().parents('[role=tabpanel]').first();
if ($panel_with_error.length) {
const $tab_button = $('[role=tab][aria-controls="' + $panel_with_error.attr('id') + '"]');
$current_tab.closest('.pk-tabs')[0].tabs.selectTab($tab_button[0]);
}
}
}
});
@ -334,7 +352,6 @@ $(function() {
$('.cell.tipi-payment-form-cell select').on('change', function() {
handle_tipi_form($(this));
compute_max_height($(this).parents('div.cell'));
});
$('.cell.tipi-payment-form-cell select').trigger('change');
@ -348,7 +365,6 @@ $(function() {
$('div.cell').each(function(i, x) {
const $cell = $(this);
compute_max_height($cell);
if (window.location.hash == '#' + $cell.attr('id')) {
$cell.addClass('toggled');
} else {
@ -720,7 +736,6 @@ Card_cell_custom.prototype = {
this.grid_cell__add(schema_cell);
$(this.cell).trigger("custom_cell:change");
compute_max_height($(this.cell));
},
grid_cell__init: function() {
if (!this.gridSchema_existing) return;
@ -729,10 +744,6 @@ Card_cell_custom.prototype = {
this.gridSchema.cells.forEach(function(el){
_self.grid_cell__add(el);
});
$(this.cell).on("cell:open", function(){
compute_max_height($(this));
})
},
// Init methods
on: function() {

View File

@ -0,0 +1,6 @@
{% load i18n %}
{{ appearance_form.as_p }}
{% if cell.can_have_assets %}
<p><a rel="popup" data-selector="div#assets-listing" href="{% url 'combo-manager-slot-assets' cell_reference=cell.get_reference %}"
>{% trans 'Assets' %}</a></p>
{% endif %}

View File

@ -1,26 +1,8 @@
{% extends "combo/manager_base.html" %}
{% load i18n %}
{% block appbar %}
<h2>{% trans 'Cell Visibility' %}</h2>
{% endblock %}
{% block content %}
<form method="post" enctype="multipart/form-data" id="visibility-form">
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button class="submit-button">{% trans "Save" %}</button>
{% if object.id %}
<a class="cancel" href="{{ object.get_absolute_url }}">{% trans 'Cancel' %}</a>
{% else %}
<a class="cancel" href="{% url 'combo-manager-homepage' %}">{% trans 'Cancel' %}</a>
{% endif %}
</div>
<div id="visibility-form-{{cell.get_reference}}">
{{ visibility_form.as_p }}
<script>
$(function() {
var $form = $('#visibility-form');
var $form = $('#visibility-form-{{cell.get_reference}}');
$form.find('select').first().on('change', function() {
var val = $(this).val();
var $groups = $form.find('select').last().parent('p');
@ -33,6 +15,4 @@
$form.find('select').first().trigger('change');
});
</script>
</form>
{% endblock %}
</div>

View File

@ -1,28 +1,39 @@
{% load i18n %}
{% block cell-form %}
<form action="{{ url }}" method="post" data-label-url="{% url 'combo-manager-page-get-additional-label' page_pk=page.id cell_reference=cell.get_reference %}">
{% csrf_token %}
{% if form %}
<div class="cell-form">
{% block cell-form-content %}
{% include cell.manager_form_template %}
{% endblock %}
<div class="cell-properties pk-tabs">
<div class="pk-tabs--tab-list" role="tablist" aria-label="{% trans "Cell Properties" %}">
{% 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>
{% endfor %}
</div>
{% else %}
<p>{% trans "There are no options for this cell." %}</p>
{% endif %}
{% endblock %}
<div class="cell-buttons">
<form class="pk-tabs--container" action="{{ url }}" method="post">
{% csrf_token %}
{% for tab in manager_tabs %}
<div id="panel-{{cell.get_reference}}-{{forloop.counter}}"
role="tabpanel" tabindex="0" {% if not forloop.first %}hidden{% endif %}
data-tab-slug="{{ tab.slug }}"
aria-labelledby="tab-{{cell.get_reference}}-{{ forloop.counter }}">
{% if tab.template %}{% include tab.template %}{% else %}{{ tab.form_instance.as_p }}{% endif %}
</div>
{% endfor %}
<div class="cell-properties--buttons">
{% block cell-buttons %}
<a rel="popup" href="{% url 'combo-manager-page-delete-cell' page_pk=page.id cell_reference=cell.get_reference %}">{% trans 'Delete' %}</a> |
<a rel="popup" href="{% url 'combo-manager-page-visibility-cell' page_pk=page.id cell_reference=cell.get_reference %}">{% trans 'Visibility' %}</a> |
<a rel="popup" href="{% url 'combo-manager-page-options-cell' page_pk=page.id cell_reference=cell.get_reference %}">{% trans 'Options' %}</a> |
{% if cell.can_have_assets %}<a rel="popup" data-selector="div#assets-listing" href="{% url 'combo-manager-slot-assets' cell_reference=cell.get_reference %}">{% trans 'Assets' %}</a> |{% endif %}
<a rel="popup" href="{% url 'combo-manager-page-duplicate-cell' page_pk=page.id cell_reference=cell.get_reference %}">{% trans 'Duplicate' %}</a> |
<a class="close-button" href="#">{% trans 'Close' %}</a>
{% if form %}
<button class="save submit-button">{% trans 'Save' %}</button>
{% endif %}
<button class="submit-button save">{% trans 'Save' %}</button>
<span>
<a class="pk-button duplicate-button" rel="popup" title="{% trans 'Duplicate' %}"
href="{% url 'combo-manager-page-duplicate-cell' page_pk=page.id cell_reference=cell.get_reference %}"
><span>{% trans 'Duplicate' %}</span></a>
<a class="pk-button delete-button" rel="popup" title="{% trans 'Delete' %}"
href="{% url 'combo-manager-page-delete-cell' page_pk=page.id cell_reference=cell.get_reference %}"
><span>{% trans 'Delete' %}</span></a>
</span>
{% endblock %}
</div>
</form>
</div>
{% endblock %}

View File

@ -161,12 +161,11 @@
<div id="cell-{{cell.get_reference}}" class="cell {{cell.class_name}}" data-cell-reference="{{ cell.get_reference }}">
<h3><span class="handle"></span>
<span class="group1">
{{ cell.get_label }}
{% if cell.template_name %} ({{cell.get_template_label}}){% endif %}
{% if cell.slug %} [{{cell.slug}}] {% endif %}
{% if cell.extra_css_class %}
<span class="extra-css-class">[{{ cell.extra_css_class }}]</span>
{% endif %}
{{ cell.get_label }}
<span class="cell-template-label"
>{% if cell.template_name %}({{cell.get_template_label}}){% endif %}</span>
<span class="cell-slug">{% if cell.slug %}[{{cell.slug}}]{% endif %}</span>
<span class="extra-css-class">{% if cell.extra_css_class %}[{{ cell.extra_css_class }}]{% endif %}</span>
<span class="additional-label"><i>{{cell.get_additional_label|default_if_none:""}}</i></span>
{% if cell.get_invalid_reason %}
<span class="invalid">{{ cell.get_invalid_reason }}{% if cell.class_name != 'link-list-cell' %} -
@ -178,20 +177,9 @@
{% endif %}</span>
{% endif %}
</span>
{% if not cell.public %}
<span class="visibility-summary
{% if cell.restricted_to_unlogged %}visibility-off{% endif %}" title="{% trans 'Restricted visibility' %}">
{% if cell.groups.all|length %}
{% for group in cell.groups.all %}{{group.name}}{% if not forloop.last %}, {% endif %}{% endfor %}
{% else %}
{% trans "logged users" %}
{% endif %}
</span>
{% elif cell.restricted_to_unlogged %}
<span class="visibility-summary" title="{% trans 'Restricted visibility' %}">
{% trans "unlogged users" %}
</span>
{% endif %}
<span class="visibility-summary {{ cell.get_manager_visibility_css_class }}"
title="{% trans 'Restricted visibility' %}"
>{{ cell.get_manager_visibility_content }}</span>
</h3>
<div>{% cell_form cell %}</div>
</div>

View File

@ -26,11 +26,16 @@ def cell_form(context, cell):
'combo-manager-page-edit-cell',
kwargs={'page_pk': cell.page_id, 'cell_reference': cell.get_reference()},
)
form_class = cell.get_default_form_class()
if cell.is_enabled() and form_class:
context['form'] = form_class(instance=cell, prefix='c%s' % cell.get_reference())
else:
context['form'] = None
context['manager_tabs'] = cell.get_manager_tabs()
for tab in context['manager_tabs']:
if tab['slug'] == 'general':
form_name = 'form'
if not cell.is_enabled():
continue
else:
form_name = '%s_form' % tab['slug']
tab['form_instance'] = tab['form'](initial={}, instance=cell, prefix='c%s' % cell.get_reference())
context[form_name] = tab['form_instance']
context['cell'] = cell
cell_form_template = template.loader.get_template('combo/manager_edit_cell_block.html')
with context.push():

View File

@ -116,21 +116,6 @@ urlpatterns = [
views.page_duplicate_cell,
name='combo-manager-page-duplicate-cell',
),
url(
r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/options$',
views.page_cell_options,
name='combo-manager-page-options-cell',
),
url(
r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/visibility$',
views.page_cell_visibility,
name='combo-manager-page-visibility-cell',
),
url(
r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/label$',
views.page_get_additional_label,
name='combo-manager-page-get-additional-label',
),
url(
r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/add-link/(?P<link_code>[\w-]+)$',
views.page_list_cell_add_link,

View File

@ -20,12 +20,14 @@ import json
import tarfile
from operator import attrgetter, itemgetter
from django import template
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.db import transaction
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.http import Http404, HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.template import engines
from django.urls import reverse, reverse_lazy
from django.utils.encoding import force_bytes, force_text
from django.utils.formats import date_format
@ -61,7 +63,6 @@ from combo.utils.misc import is_portal_agent
from .forms import (
CellDuplicateForm,
CellVisibilityForm,
PageAddForm,
PageDuplicateForm,
PageEditDescriptionForm,
@ -664,6 +665,8 @@ page_add_cell = PageAddCellView.as_view()
class PageEditCellView(ManagedPageMixin, UpdateView):
http_method_names = ['post']
def get_template_names(self):
return [self.template_name or self.object.manager_form_template]
@ -685,15 +688,61 @@ class PageEditCellView(ManagedPageMixin, UpdateView):
def get_prefix(self):
return 'c%s' % self.kwargs.get('cell_reference')
def get_form_class(self):
return self.object.get_default_form_class()
def post(self, request, *args, **kwargs):
self.object = self.get_object()
response = {'errorlist': {}, 'tabs': {}, 'prefix': self.get_prefix()}
context = {}
context['page'] = self.object.page
context['cell'] = self.object
context.update(self.object.get_extra_manager_context())
tab_error_forms = {}
def get_success_url(self):
return (
reverse('combo-manager-page-view', kwargs={'pk': self.kwargs.get('page_pk')})
+ '#cell-'
+ self.object.get_reference()
)
class Rollback(Exception):
pass
try:
with transaction.atomic():
for tab in self.object.get_manager_tabs():
form = tab['form'](**self.get_form_kwargs())
if form.is_valid():
self.object = form.save()
else:
tab_error_forms[tab['slug']] = form
response['errorlist'][tab['slug']] = form.errors
self.object.refresh_from_db()
if response['errorlist']:
raise Rollback()
except Rollback:
pass
for tab in self.object.get_manager_tabs():
# if current form had no errors, create it anew
# so it can get new dynamic fields
form = tab_error_forms.get(tab['slug']) or tab['form'](**self.get_form_kwargs())
if tab['slug'] == 'general':
form_name = 'form'
else:
form_name = '%s_form' % tab['slug']
context[form_name] = form
if tab.get('template'):
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['visibility_css_class'] = self.object.get_manager_visibility_css_class()
response['visibility_content'] = self.object.get_manager_visibility_content()
response['extra_css_class'] = self.object.extra_css_class
response['slug'] = self.object.slug
response['template_label'] = self.object.get_template_label()
response['additional_label'] = self.object.get_additional_label()
response['invalid_reason'] = self.object.get_invalid_reason()
if not response['errorlist']:
PageSnapshot.take(
self.object.page, request=self.request, comment=_('changed cell "%s"') % self.object
)
return JsonResponse(response)
def form_valid(self, form):
if self.request.is_ajax():
@ -787,26 +836,6 @@ class PageDuplicateCellView(ManagedPageMixin, FormView):
page_duplicate_cell = PageDuplicateCellView.as_view()
class PageCellVisibilityView(PageEditCellView):
template_name = 'combo/cell_visibility.html'
def get_form_class(self):
return CellVisibilityForm
page_cell_visibility = PageCellVisibilityView.as_view()
class PageCellOptionsView(PageEditCellView):
template_name = 'combo/cell_options.html'
def get_form_class(self):
return self.object.get_options_form_class()
page_cell_options = PageCellOptionsView.as_view()
class PageCellOrder(ManagedPageMixin, View):
def get(self, *args, **kwargs):
request = self.request
@ -877,19 +906,6 @@ def page_order(request):
return redirect(reverse('combo-manager-homepage'))
def page_get_additional_label(request, page_pk, cell_reference):
cell = CellBase.get_cell(cell_reference, page_id=page_pk)
response = HttpResponse(content_type='application/json')
json.dump(
{
'label': force_text(cell.get_additional_label()) or '',
'invalid_reason': force_text(cell.get_invalid_reason() or ''),
},
response,
)
return response
def menu_json(request):
if settings.TEMPLATE_VARS.get('site_title'):
label = _('Editing "%(site_title)s"') % settings.TEMPLATE_VARS

View File

@ -186,6 +186,7 @@ CKEDITOR_CONFIGS = {
],
'toolbar': 'Own',
'resize_enabled': False,
'width': '100%',
},
}

View File

@ -65,7 +65,7 @@ class MultiSortWidget(forms.SelectMultiple):
def value_from_datadict(self, data, files, name):
if isinstance(data, MultiValueDict):
return {'data': data.getlist(name)}
return json.dumps({'data': data.getlist(name)})
return data.get(name, None)
def format_value(self, value):

View File

@ -15,6 +15,7 @@ from combo.data.models import Page, ValidityInfo
from combo.utils.spooler import refresh_statistics_data
from .test_public import login
from .utils import manager_submit_cell
pytestmark = pytest.mark.django_db
@ -1296,11 +1297,11 @@ def test_chartng_cell_manager_new_api(app, admin_user, new_api_statistics):
('combo', False, 'Combo'),
]
resp.form[field_prefix + 'service'] = ''
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert resp.form[field_prefix + 'service'].value == ''
resp.form[field_prefix + 'ou'] = 'default'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert resp.form[field_prefix + 'ou'].value == 'default'
cell.refresh_from_db()
assert cell.get_filter_params() == {'ou': 'default', 'time_interval': 'month'}
@ -1318,20 +1319,20 @@ def test_chartng_cell_manager_new_api(app, admin_user, new_api_statistics):
]
resp.form[field_prefix + 'ou'] = ''
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert resp.form[field_prefix + 'ou'].value == ''
cell.refresh_from_db()
assert cell.get_filter_params() == {'time_interval': 'month'}
resp.form[field_prefix + 'time_range'] = 'previous-year'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
cell.refresh_from_db()
assert cell.time_range == 'previous-year'
resp.form[field_prefix + 'time_range'] = 'range'
resp.form[field_prefix + 'time_range_start'] = '2020-10-01'
resp.form[field_prefix + 'time_range_end'] = '2020-11-03'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
cell.refresh_from_db()
assert cell.time_range == 'range'
assert cell.time_range_start == date(year=2020, month=10, day=1)
@ -1339,14 +1340,14 @@ def test_chartng_cell_manager_new_api(app, admin_user, new_api_statistics):
resp.form[field_prefix + 'time_range_start'] = ''
resp.form[field_prefix + 'time_range_end'] = ''
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
cell.refresh_from_db()
assert cell.time_range_start is None
assert cell.time_range_end is None
no_filters_stat = Statistic.objects.get(slug='two-series')
resp.form[field_prefix + 'statistic'] = no_filters_stat.pk
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert resp.form[field_prefix + 'statistic'].value == str(no_filters_stat.pk)
assert field_prefix + 'time_interval' not in resp.form.fields
assert field_prefix + 'ou' not in resp.form.fields
@ -1356,9 +1357,9 @@ def test_chartng_cell_manager_new_api(app, admin_user, new_api_statistics):
filter_multiple_stat = Statistic.objects.get(slug='filter-multiple')
resp.form[field_prefix + 'statistic'] = filter_multiple_stat.pk
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
resp.form[field_prefix + 'color'].select_multiple(texts=['Blue', 'Green'])
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert resp.form[field_prefix + 'color'].value == ['green', 'blue']
cell.refresh_from_db()
assert cell.filter_params == {'color': ['green', 'blue']}
@ -1376,7 +1377,7 @@ def test_chartng_cell_manager_new_api(app, admin_user, new_api_statistics):
]
resp.form[field_prefix + 'color'].select_multiple(texts=[])
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert resp.form[field_prefix + 'color'].value is None
cell.refresh_from_db()
assert cell.get_filter_params() == {}
@ -1408,7 +1409,7 @@ def test_chartng_cell_manager_future_data(app, admin_user, new_api_statistics):
stat_with_future_data = Statistic.objects.get(slug='with-future-data')
resp.form[field_prefix + 'statistic'] = stat_with_future_data.pk
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
time_range_field = resp.form[field_prefix + 'time_range']
assert time_range_field.value == ''
assert time_range_field.options == [
@ -1440,20 +1441,20 @@ def test_chartng_cell_manager_subfilters(app, admin_user, new_api_statistics):
# choice with no subfilter
resp.form[field_prefix + 'form'] = 'contact'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert len(new_api_mock.call['requests']) == 1
assert 'menu' not in resp.form.fields
resp.form[field_prefix + 'form'] = 'error'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert len(new_api_mock.call['requests']) == 2
assert 'menu' not in resp.form.fields
# choice with subfilter
resp.form[field_prefix + 'form'] = 'food-request'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert len(new_api_mock.call['requests']) == 3
menu_field = resp.form[field_prefix + 'menu']
@ -1465,14 +1466,14 @@ def test_chartng_cell_manager_subfilters(app, admin_user, new_api_statistics):
]
resp.form[field_prefix + 'menu'] = 'meat'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert resp.form[field_prefix + 'menu'].value == 'meat'
cell.refresh_from_db()
assert cell.get_filter_params() == {'form': 'food-request', 'menu': 'meat'}
# choice with no subfilter
resp.form[field_prefix + 'form'] = 'contact'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert len(new_api_mock.call['requests']) == 4
assert 'menu' not in resp.form.fields
@ -1481,7 +1482,7 @@ def test_chartng_cell_manager_subfilters(app, admin_user, new_api_statistics):
# changing another filter doesn't trigger request
resp.form[field_prefix + 'other'] = 'one'
resp = resp.form.submit().follow()
resp = resp.form.submit()
assert len(new_api_mock.call['requests']) == 4
@ -1500,7 +1501,7 @@ def test_chartng_cell_manager_new_api_time_range_templates(app, admin_user, new_
resp.form[field_prefix + 'time_range'] = 'range-template'
resp.form[field_prefix + 'time_range_start_template'] = 'today|add_days:"7"|adjust_to_week_monday'
resp.form[field_prefix + 'time_range_end_template'] = 'now|add_days:"14"|adjust_to_week_monday'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
cell.refresh_from_db()
assert cell.time_range == 'range-template'
assert cell.time_range_start_template == 'today|add_days:"7"|adjust_to_week_monday'
@ -1508,24 +1509,24 @@ def test_chartng_cell_manager_new_api_time_range_templates(app, admin_user, new_
resp.form[field_prefix + 'time_range_start_template'] = ''
resp.form[field_prefix + 'time_range_end_template'] = ''
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
cell.refresh_from_db()
assert cell.time_range_start_template == ''
assert cell.time_range_end_template == ''
resp.form[field_prefix + 'time_range_start_template'] = 'xxx'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form, expect_errors=True)
cell.refresh_from_db()
assert cell.time_range_start_template == 'xxx'
resp = app.get('/manage/pages/%s/' % page.id)
resp.form[field_prefix + 'time_range_start_template'] = 'today|xxx'
resp = resp.form.submit()
manager_submit_cell(resp.form, expect_errors=True)
assert 'Invalid filter' in resp.text
resp = app.get('/manage/pages/%s/' % page.id)
resp.form[field_prefix + 'time_range_start_template'] = 'today|date:xxx'
resp = resp.form.submit()
manager_submit_cell(resp.form, expect_errors=True)
assert 'Failed lookup for key [xxx]' in resp.text
@ -1540,7 +1541,7 @@ 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.text
assert 'time_interval' in resp.json['tabs']['general']
@with_httmock(new_api_mock)
@ -1576,7 +1577,7 @@ def test_chartng_cell_manager_new_api_page_variables(app, admin_user, new_api_st
]
resp.form[field_prefix + 'ou'] = 'variable:foo'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert resp.form[field_prefix + 'ou'].value == 'variable:foo'
cell.refresh_from_db()
assert cell.filter_params['ou'] == 'variable:foo'
@ -2078,7 +2079,7 @@ def test_chartng_cell_new_api_aggregation(new_api_statistics, app, admin_user, n
('year', False, 'Year'),
('weekday', False, 'Week day'),
]
resp.form.submit()
manager_submit_cell(resp.form)
cell.refresh_from_db()
chart = cell.get_chart()
@ -2088,8 +2089,9 @@ def test_chartng_cell_new_api_aggregation(new_api_statistics, app, admin_user, n
assert chart.raw_series[0][0][:8] == [0, 0, 0, 0, 0, 0, 0, 1]
assert chart.raw_series[1][0][:8] == [2, 0, 0, 0, 0, 0, 0, 2]
time_interval_field = resp.form['cdataviz_chartngcell-%s-time_interval' % cell.id]
time_interval_field.value = 'month'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
time_interval_field = resp.form['cdataviz_chartngcell-%s-time_interval' % cell.id]
assert time_interval_field.options == [
('day', False, 'Day'),
@ -2110,6 +2112,7 @@ def test_chartng_cell_new_api_aggregation(new_api_statistics, app, admin_user, n
([4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], {'title': 'Serie 2'}),
]
time_interval_field = resp.form['cdataviz_chartngcell-%s-time_interval' % cell.id]
time_interval_field.value = 'year'
resp.form.submit()
cell.refresh_from_db()
@ -2122,8 +2125,9 @@ def test_chartng_cell_new_api_aggregation(new_api_statistics, app, admin_user, n
([5, 0, 0], {'title': 'Serie 2'}),
]
time_interval_field = resp.form['cdataviz_chartngcell-%s-time_interval' % cell.id]
time_interval_field.value = 'weekday'
resp.form.submit()
manager_submit_cell(resp.form)
cell.refresh_from_db()
chart = cell.get_chart()
@ -2134,8 +2138,9 @@ def test_chartng_cell_new_api_aggregation(new_api_statistics, app, admin_user, n
([1, 4, 0, 0, 0, 0, 0], {'title': 'Serie 2'}),
]
time_interval_field = resp.form['cdataviz_chartngcell-%s-time_interval' % cell.id]
time_interval_field.value = 'week'
resp.form.submit()
manager_submit_cell(resp.form)
cell.refresh_from_db()
chart = cell.get_chart()
@ -2150,8 +2155,7 @@ def test_chartng_cell_new_api_aggregation(new_api_statistics, app, admin_user, n
cell.statistic = Statistic.objects.get(slug='leap-week')
cell.save()
resp = app.get('/manage/pages/%s/' % page.id)
resp.form.submit()
manager_submit_cell(resp.form)
chart = cell.get_chart()
assert 'time_interval=day' in new_api_mock.call['requests'][1].url
assert len(chart.x_labels) == 1
@ -2370,7 +2374,7 @@ def test_chart_filters_cell_with_subfilters(new_api_statistics, app, admin_user,
# select a choice with subfilters in manager
resp = app.get('/manage/pages/%s/' % page.id)
resp.forms[1]['cdataviz_chartngcell-%s-form' % cell.id] = 'food-request'
resp = resp.forms[1].submit().follow()
manager_submit_cell(resp.forms[1])
resp = app.get('/')
assert 'form' in resp.form.fields

View File

@ -9,6 +9,7 @@ from combo.apps.wcs.context_processors import Cards
from combo.data.models import Page
from .test_manager import login
from .utils import manager_submit_cell
pytestmark = pytest.mark.django_db
@ -63,7 +64,7 @@ def test_manager_weeklyagenda_cell(app, admin_user):
resp.forms[0]['c%s-agenda_categories' % cell.get_reference()].value = 'bar,foo'
resp.forms[0]['c%s-start_date_filter' % cell.get_reference()].value = '{{ start_date }}'
resp.forms[0]['c%s-end_date_filter' % cell.get_reference()].value = '{{ end_date }}'
resp = resp.forms[0].submit().follow()
manager_submit_cell(resp.form)
cell.refresh_from_db()
assert cell.agenda_type == 'subscribed'
assert cell.agenda_references_template == ''
@ -74,7 +75,7 @@ def test_manager_weeklyagenda_cell(app, admin_user):
resp.forms[0]['c%s-agenda_type' % cell.get_reference()].value = 'manual'
resp.forms[0]['c%s-agenda_references_template' % cell.get_reference()].value = 'foo,bar'
resp.forms[0]['c%s-agenda_categories' % cell.get_reference()].value = 'bar,foo'
resp = resp.forms[0].submit().follow()
manager_submit_cell(resp.form)
cell.refresh_from_db()
assert cell.agenda_type == 'manual'
assert cell.agenda_references_template == 'foo,bar'

View File

@ -26,13 +26,7 @@ def test_adding_gallery_images(app, admin_user):
)
app = login(app)
resp = app.get(
reverse(
'combo-manager-page-edit-cell',
kwargs={'page_pk': page.id, 'cell_reference': cell.get_reference()},
),
status=200,
)
resp = app.get('/manage/pages/%s/' % page.id)
assert '<ul class="gallery"' in resp.text
assert 'js/combo.gallery.js' in resp.text

View File

@ -22,6 +22,8 @@ from django.test.client import RequestFactory
from combo.apps.kb.models import LatestPageUpdatesCell
from combo.data.models import CellBase, Page, TextCell
from .utils import manager_submit_cell
pytestmark = pytest.mark.django_db
@ -49,8 +51,7 @@ def test_manage_updated_pages_cell(app, admin_user):
resp = resp.follow()
cells = CellBase.get_cells(page_id=page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.text
resp = resp.forms[0].submit()
assert resp.status_int == 302
manager_submit_cell(resp.forms[0])
resp = app.get('/example-page/', status=200)
div = resp.html.find('div', attrs={'class': 'latest-page-updates-cell'})

View File

@ -46,6 +46,8 @@ from combo.data.models import (
)
from combo.manager.forms import PageAddForm, PageSelectTemplateForm
from .utils import manager_submit_cell
pytestmark = pytest.mark.django_db
TESTS_DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
@ -699,7 +701,7 @@ def test_edit_page_num_queries(settings, app, admin_user):
app.get('/manage/pages/%s/' % page.pk) # load once to populate caches
with CaptureQueriesContext(connection) as ctx:
app.get('/manage/pages/%s/' % page.pk)
assert len(ctx.captured_queries) == 33
assert len(ctx.captured_queries) == 41
def test_delete_page(app, admin_user):
@ -1269,9 +1271,7 @@ def test_add_edit_cell(app, admin_user):
resp = app.get('/manage/pages/%s/' % page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.text
resp.forms[0]['c%s-text' % cells[0].get_reference()].value = 'Hello world'
resp = resp.forms[0].submit()
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.id, cells[0].get_reference()))
manager_submit_cell(resp.forms[0])
resp = app.get('/manage/pages/%s/' % page.id)
assert resp.forms[0]['c%s-text' % cells[0].get_reference()].value == 'Hello world'
@ -1279,9 +1279,8 @@ def test_add_edit_cell(app, admin_user):
resp = app.get('/manage/pages/%s/' % page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.text
resp.forms[0]['c%s-text' % cells[0].get_reference()].value = 'World Hello'
resp = resp.forms[0].submit(xhr=True)
assert resp.status_int == 200
assert resp.text.strip().startswith('<p><label')
manager_submit_cell(resp.forms[0])
assert resp.forms[0]['c%s-text' % cells[0].get_reference()].value == 'World Hello'
resp = app.get('/manage/pages/%s/' % page.id)
assert resp.forms[0]['c%s-text' % cells[0].get_reference()].value == 'World Hello'
@ -1440,7 +1439,6 @@ def test_edit_cell_visibility(app, admin_user):
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/visibility' % cell.id)
assert resp.form['cdata_textcell-%s-visibility' % cell.id].value == 'all'
resp.form['cdata_textcell-%s-visibility' % cell.id] = 'logged'
resp = resp.form.submit('submit')
@ -1449,7 +1447,6 @@ def test_edit_cell_visibility(app, admin_user):
assert TextCell.objects.get(id=cell.id).groups.count() == 0
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/visibility' % cell.id)
assert resp.form['cdata_textcell-%s-visibility' % cell.id].value == 'logged'
resp.form['cdata_textcell-%s-visibility' % cell.id] = 'unlogged'
resp = resp.form.submit('submit')
@ -1458,7 +1455,6 @@ def test_edit_cell_visibility(app, admin_user):
assert TextCell.objects.get(id=cell.id).groups.count() == 0
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/visibility' % cell.id)
assert resp.form['cdata_textcell-%s-visibility' % cell.id].value == 'unlogged'
resp.form['cdata_textcell-%s-visibility' % cell.id] = 'all'
resp = resp.form.submit('submit')
@ -1472,7 +1468,6 @@ def test_edit_cell_visibility(app, admin_user):
group2.save()
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/visibility' % cell.id)
resp.form['cdata_textcell-%s-visibility' % cell.id] = 'groups-any'
resp.form['cdata_textcell-%s-groups' % cell.id] = [group1.id]
resp = resp.form.submit('submit')
@ -1482,7 +1477,6 @@ def test_edit_cell_visibility(app, admin_user):
assert TextCell.objects.get(id=cell.id).groups.all()[0].name == 'A group'
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/visibility' % cell.id)
resp.form['cdata_textcell-%s-visibility' % cell.id] = 'groups-none'
resp.form['cdata_textcell-%s-groups' % cell.id] = [group2.id]
resp = resp.form.submit('submit')
@ -1501,7 +1495,6 @@ def test_edit_cell_options(app, admin_user):
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/options' % cell.id)
assert resp.form['cdata_textcell-%s-slug' % cell.id].value == ''
assert resp.form['cdata_textcell-%s-extra_css_class' % cell.id].value == ''
resp.form['cdata_textcell-%s-slug' % cell.id] = 'SLUG'
@ -1510,14 +1503,12 @@ def test_edit_cell_options(app, admin_user):
assert 'SLUG' in app.get('/manage/pages/%s/' % page.id)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/options' % cell.id)
resp.form['cdata_textcell-%s-slug' % cell.id] = ''
resp = resp.form.submit('submit')
assert TextCell.objects.get(id=cell.id).slug == ''
assert 'SLUG' not in app.get('/manage/pages/%s/' % page.id)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/options' % cell.id)
resp.form['cdata_textcell-%s-extra_css_class' % cell.id] = 'CSS'
resp = resp.form.submit('submit')
assert TextCell.objects.get(id=cell.id).extra_css_class == 'CSS'
@ -1533,16 +1524,13 @@ def test_edit_cell_options_template(app, admin_user):
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/options' % cell.id)
assert 'cdata_textcell-%s-template_name' % cell.id not in resp.form.fields
assert resp.form['cdata_textcell-%s-slug' % cell.id].value == ''
assert resp.form['cdata_textcell-%s-extra_css_class' % cell.id].value == ''
with override_settings(COMBO_CELL_TEMPLATES={'data_textcell': {'extra': {'label': 'Extra'}}}):
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/options' % cell.id)
resp.form['cdata_textcell-%s-template_name' % cell.id].value = 'extra'
resp = resp.form.submit('submit')
assert TextCell.objects.get(id=cell.id).template_name == 'extra'
assert '(Extra)' in app.get('/manage/pages/%s/' % page.id)
@ -1661,7 +1649,10 @@ def test_edit_config_json_cell(app, admin_user):
resp = app.get('/manage/pages/%s/' % page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.text
assert 'There are no options for this cell.' in resp.form.text
assert [x.attrib['data-tab-slug'] for x in resp.pyquery('[data-tab-slug]')] == [
'visibility',
'appearance',
]
# make it configurable
with override_settings(
@ -1697,20 +1688,21 @@ def test_edit_config_json_cell(app, admin_user):
TEMPLATES=templates_settings,
):
resp = app.get('/manage/pages/%s/' % page.id)
assert 'There are no options for this cell.' not in resp.form.text
assert [x.attrib['data-tab-slug'] for x in resp.pyquery('[data-tab-slug]')] == [
'general',
'visibility',
'appearance',
]
resp.form['c%s-test' % cells[0].get_reference()].value = 'Hello world'
resp.form['c%s-test3' % cells[0].get_reference()].value = 'Hello again'
resp = resp.form.submit()
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.id, cells[0].get_reference()))
manager_submit_cell(resp.form)
# test form error
resp = app.get('/manage/pages/%s/' % page.id)
resp.form['c%s-test' % cells[0].get_reference()].value = ''
resp.form['c%s-test3' % cells[0].get_reference()].value = 'Hello'
resp = resp.form.submit()
assert resp.status_int == 200
resp = manager_submit_cell(resp.form, expect_errors=True)
assert resp.context['form'].errors['test'] == ['This field is required.']
resp = app.get('/manage/pages/%s/' % page.id)
@ -1724,9 +1716,8 @@ def test_edit_config_json_cell(app, admin_user):
resp.forms[0]['c%s-test2' % cells[0].get_reference()].checked = True
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 = resp.form.submit(xhr=True)
assert resp.status_int == 200
assert resp.text.strip().startswith('<p><label')
resp = manager_submit_cell(resp.form)
assert resp.json['tabs']['general'].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'
@ -2357,7 +2348,7 @@ def test_page_versionning(app, admin_user):
# change cell text
resp.forms[0]['c%s-text' % cell1.get_reference()].value = 'Hello world'
resp = resp.forms[0].submit().follow()
manager_submit_cell(resp.forms[0])
assert PageSnapshot.objects.all().count() == 2
# reorder cells
@ -2398,15 +2389,15 @@ def test_page_versionning(app, admin_user):
cell_id = JsonCell.objects.last().id
resp.forms[3]['cdata_jsoncell-%s-template_string' % cell_id].value = 'A{{json.data.0.text}}B'
resp.forms[3]['cdata_jsoncell-%s-url' % cell_id].value = 'http://example.com'
resp = resp.forms[3].submit().follow()
manager_submit_cell(resp.forms[3])
assert PageSnapshot.objects.all().count() == 5 # add + change
resp.forms[3]['cdata_jsoncell-%s-template_string' % cell_id].value = 'C{{json.data.0.text}}D'
resp = resp.forms[3].submit().follow()
manager_submit_cell(resp.forms[3])
assert PageSnapshot.objects.all().count() == 6
resp.forms[1]['c%s-text' % cell1.get_reference()].value = 'Foo back to 1'
resp = resp.forms[0].submit().follow()
manager_submit_cell(resp.forms[1])
resp = resp.click('History')
assert 'added cell' in resp.text
@ -2439,7 +2430,7 @@ def test_page_versionning(app, admin_user):
resp = resp.click('restore', index=6)
with CaptureQueriesContext(connection) as ctx:
resp = resp.form.submit().follow()
assert len(ctx.captured_queries) == 146
assert len(ctx.captured_queries) == 152
resp2 = resp.click('See online')
assert resp2.text.index('Foobar1') < resp2.text.index('Foobar2') < resp2.text.index('Foobar3')
@ -2556,14 +2547,14 @@ def test_json_cell_syntax_validation(app, admin_user):
resp.forms[0]['cdata_jsoncell-%s-template_string' % cell_id].value = '{% syntax|error %}'
resp.forms[0]['cdata_jsoncell-%s-url' % cell_id].value = 'http://example.com'
resp = resp.forms[0].submit()
assert 'syntax error: Invalid block tag' in resp.text
assert resp.json['errorlist']['general']['template_string']
assert JsonCell.objects.count() == 1
assert JsonCell.objects.first().template_string is None
# valid syntax
resp = app.get('/manage/pages/%s/' % page.id)
resp.forms[0]['cdata_jsoncell-%s-template_string' % cell_id].value = '{{ ok }}'
resp.forms[0]['cdata_jsoncell-%s-url' % cell_id].value = 'http://example.com'
resp = resp.forms[0].submit().follow()
manager_submit_cell(resp.forms[0])
assert 'syntax error' not in resp.text
assert JsonCell.objects.count() == 1
assert JsonCell.objects.first().template_string == '{{ ok }}'

View File

@ -5,6 +5,8 @@ import pytest
from combo.apps.maps.models import Map, MapLayer, MapLayerOptions
from combo.data.models import Page
from .utils import manager_submit_cell
pytestmark = pytest.mark.django_db
@ -254,7 +256,7 @@ def test_add_delete_layer(app, admin_user, layer, tiles_layer):
resp = resp.click('Cancel')
resp.form['cmaps_map-%s-marker_behaviour_onclick' % cell.pk] = 'display_data'
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
resp = resp.click(href='.*/layer/%s/edit/$' % options.pk)
assert 'this setting has no effect' not in resp.context['form'].fields['properties'].help_text
resp.form['properties'] = 'a, b'

View File

@ -39,6 +39,7 @@ from combo.data.models import CellBase, LinkListCell, Page, ValidityInfo
from combo.utils import NothingInCacheException
from .test_manager import login
from .utils import manager_submit_cell
pytestmark = pytest.mark.django_db
@ -1532,8 +1533,14 @@ def test_manager_forms_of_category_cell(mock_send, app, admin_user):
resp = app.get('/manage/pages/%s/' % page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.text
resp.forms[0]['c%s-ordering' % cells[0].get_reference()].value = 'manual'
resp = resp.forms[0].submit()
assert resp.status_int == 302
manager_submit_cell(resp.forms[0])
cells[0].refresh_from_db()
resp.forms[0]['c%s-manual_order' % cells[0].get_reference()].select_multiple(
['default::a-second-form-title', 'default::third-form-title']
)
manager_submit_cell(resp.forms[0])
cells[0].refresh_from_db()
assert cells[0].manual_order == {'data': ['default::a-second-form-title', 'default::third-form-title']}
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
@ -1554,7 +1561,7 @@ def test_manager_current_forms(mock_send, settings, app, admin_user):
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.text
assert len(resp.form['c%s-categories' % cells[0].get_reference()].options) == 4
resp.form['c%s-categories' % cells[0].get_reference()].value = ['default:test-3', 'default:test-9']
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
assert resp.form['c%s-categories' % cells[0].get_reference()].value == [
'default:test-3',
'default:test-9',
@ -1565,7 +1572,7 @@ def test_manager_current_forms(mock_send, settings, app, admin_user):
assert 'Please choose at least one option among the following: Current Forms, Done Forms' in resp
resp = app.get('/manage/pages/%s/' % page.id)
resp.form['c%s-done_forms' % cells[0].get_reference()] = True
resp = resp.form.submit().follow()
manager_submit_cell(resp.form)
# check wcs_site field is a select box
assert resp.form['c%s-wcs_site' % cells[0].get_reference()].tag == 'select'
@ -1587,7 +1594,7 @@ def test_manager_cards_cell(mock_send, app, admin_user):
assert cell.without_user is False
assert resp.forms[0]['c%s-with_user' % cell.get_reference()].value == 'on'
resp.forms[0]['c%s-with_user' % cell.get_reference()].value = False
resp.forms[0].submit().follow()
manager_submit_cell(resp.forms[0])
cell.refresh_from_db()
assert cell.without_user is True
assert resp.forms[0]['c%s-with_user' % cell.get_reference()].value is None
@ -1947,7 +1954,7 @@ def test_card_cell_setup(mock_send, app, admin_user):
resp = app.get('/manage/pages/%s/' % page.pk)
assert resp.forms[0]['c%s-customize_display' % cell.get_reference()].value == 'on'
resp.forms[0]['c%s-customize_display' % cell.get_reference()].value = False
resp.forms[0].submit().follow()
manager_submit_cell(resp.forms[0])
cell.refresh_from_db()
assert cell.custom_schema == {}
@ -1956,7 +1963,7 @@ def test_card_cell_setup(mock_send, app, admin_user):
resp = app.get('/manage/pages/%s/' % page.pk)
assert resp.forms[0]['c%s-related_card_path' % cell.get_reference()].value == '--'
resp.forms[0]['c%s-card_ids' % cell.get_reference()].value = '42'
resp.forms[0].submit().follow()
manager_submit_cell(resp.forms[0])
cell.refresh_from_db()
assert cell.related_card_path == ''
assert cell.card_ids == ''
@ -1964,7 +1971,7 @@ def test_card_cell_setup(mock_send, app, admin_user):
assert resp.forms[0]['c%s-related_card_path' % cell.get_reference()].value == '--'
resp.forms[0]['c%s-related_card_path' % cell.get_reference()].value = ''
resp.forms[0]['c%s-card_ids' % cell.get_reference()].value = '42'
resp.forms[0].submit().follow()
manager_submit_cell(resp.forms[0])
cell.refresh_from_db()
assert cell.related_card_path == ''
assert cell.card_ids == '42'
@ -2192,7 +2199,7 @@ def test_manager_card_cell(mock_send, app, admin_user):
assert cell.without_user is False
assert resp.forms[0]['c%s-with_user' % cell.get_reference()].value == 'on'
resp.forms[0]['c%s-with_user' % cell.get_reference()].value = False
resp = resp.forms[0].submit().follow()
manager_submit_cell(resp.forms[0])
cell.refresh_from_db()
assert cell.without_user is True
assert resp.forms[0]['c%s-with_user' % cell.get_reference()].value is None

16
tests/utils.py Normal file
View File

@ -0,0 +1,16 @@
from pyquery import PyQuery
def manager_submit_cell(form, expect_errors=False):
# submit cell edit form and replace current page body with
# new tab contents.
resp = form.response
action = form.action
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])
resp.text = pq.html()
resp._forms_indexed = None
assert expect_errors or not resp2.json['errorlist'], 'got unexpected errors'
return resp2