cells: add a cell type "list of links" (#11006)
This commit is contained in:
parent
a00b640090
commit
24619ce6db
|
@ -36,14 +36,18 @@ from .utils import get_wcs_json, is_wcs_enabled, get_wcs_services
|
|||
|
||||
@register_cell_class
|
||||
class WcsFormCell(CellBase):
|
||||
template_name = 'combo/wcs/form.html'
|
||||
|
||||
formdef_reference = models.CharField(_('Form'), max_length=150)
|
||||
|
||||
cached_title = models.CharField(_('Title'), max_length=150)
|
||||
cached_url = models.URLField(_('URL'))
|
||||
cached_json = JSONField(blank=True)
|
||||
|
||||
template_name = 'combo/wcs/form.html'
|
||||
add_as_link_label = _('add a form link')
|
||||
add_link_label = _('New form link')
|
||||
edit_link_label = _('Edit form link')
|
||||
add_as_link_code = 'form-link'
|
||||
|
||||
is_enabled = classmethod(is_wcs_enabled)
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -18,7 +18,7 @@ import copy
|
|||
|
||||
from django import forms
|
||||
|
||||
from .models import Page, ParametersCell, MenuCell, LinkCell, ConfigJsonCell
|
||||
from .models import Page, ParametersCell, MenuCell, LinkCell, LinkListCell, ConfigJsonCell
|
||||
from jsonfield.widgets import JSONWidget
|
||||
|
||||
from combo.utils import cache_during_request
|
||||
|
@ -41,6 +41,7 @@ class ParametersForm(forms.Form):
|
|||
break
|
||||
return self.cleaned_data
|
||||
|
||||
|
||||
class ParametersCellForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = ParametersCell
|
||||
|
@ -61,6 +62,7 @@ def get_page_choices():
|
|||
pages = Page.get_as_reordered_flat_hierarchy(Page.objects.all())
|
||||
return [(x.id, '%s %s' % (u'\u00a0' * x.level * 2, x.title)) for x in pages]
|
||||
|
||||
|
||||
class MenuCellForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = MenuCell
|
||||
|
@ -82,6 +84,15 @@ class LinkCellForm(forms.ModelForm):
|
|||
choices=[(None, '-----')] + get_page_choices())
|
||||
|
||||
|
||||
class LinkListCellForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = LinkListCell
|
||||
fields = ['title']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LinkListCellForm, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class ConfigJsonForm(forms.ModelForm):
|
||||
formdef = []
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0008_alter_user_username_max_length'),
|
||||
('data', '0038_increase_jsoncell_url_max_length'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='LinkListCell',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('placeholder', models.CharField(max_length=20)),
|
||||
('order', models.PositiveIntegerField()),
|
||||
('slug', models.SlugField(blank=True, verbose_name='Slug')),
|
||||
('extra_css_class', models.CharField(blank=True, max_length=100, verbose_name='Extra classes for CSS styling')),
|
||||
('public', models.BooleanField(default=True, verbose_name='Public')),
|
||||
('restricted_to_unlogged', models.BooleanField(default=False, verbose_name='Restrict to unlogged users')),
|
||||
('last_update_timestamp', models.DateTimeField(auto_now=True)),
|
||||
('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Groups')),
|
||||
('title', models.CharField(max_length=150, verbose_name='Title', blank=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'List of links',
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='linklistcell',
|
||||
name='page',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
|
||||
),
|
||||
]
|
|
@ -451,6 +451,8 @@ class Page(models.Model):
|
|||
new_page.groups.set(self.groups.all())
|
||||
|
||||
for cell in self.get_cells():
|
||||
if cell.placeholder and cell.placeholder.startswith('_'):
|
||||
continue
|
||||
cell.duplicate(page_target=new_page)
|
||||
|
||||
return new_page
|
||||
|
@ -756,12 +758,14 @@ class CellBase(six.with_metaclass(CellMeta, models.Model)):
|
|||
def import_subobjects(self, cell_json):
|
||||
pass
|
||||
|
||||
def duplicate(self, page_target=None):
|
||||
def duplicate(self, page_target=None, placeholder=None):
|
||||
# clone current cell
|
||||
new_cell = copy.deepcopy(self)
|
||||
new_cell.pk = None
|
||||
# set page
|
||||
new_cell.page = page_target or self.page
|
||||
# set placeholder
|
||||
new_cell.placeholder = placeholder or new_cell.placeholder
|
||||
# store new cell
|
||||
new_cell.save()
|
||||
|
||||
|
@ -905,6 +909,10 @@ class LinkCell(CellBase):
|
|||
anchor = models.CharField(_('Anchor'), max_length=150, blank=True)
|
||||
|
||||
template_name = 'combo/link-cell.html'
|
||||
add_as_link_label = _('add a link')
|
||||
add_link_label = _('New link')
|
||||
edit_link_label = _('Edit link')
|
||||
add_as_link_code = 'link'
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Link')
|
||||
|
@ -950,6 +958,76 @@ class LinkCell(CellBase):
|
|||
return []
|
||||
|
||||
|
||||
@register_cell_class
|
||||
class LinkListCell(CellBase):
|
||||
title = models.CharField(_('Title'), max_length=150, blank=True)
|
||||
|
||||
template_name = 'combo/link-list-cell.html'
|
||||
manager_form_template = 'combo/manager/link-list-cell-form.html'
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('List of links')
|
||||
|
||||
@property
|
||||
def link_placeholder(self):
|
||||
return '_linkslist:{}'.format(self.pk)
|
||||
|
||||
def get_items(self):
|
||||
return CellBase.get_cells(
|
||||
page=self.page,
|
||||
placeholder=self.link_placeholder,
|
||||
cell_filter=lambda x: hasattr(x, 'add_as_link_label'))
|
||||
|
||||
def get_additional_label(self):
|
||||
title = self.title
|
||||
if not title:
|
||||
return None
|
||||
return utils.ellipsize(title)
|
||||
|
||||
def get_cell_extra_context(self, context):
|
||||
extra_context = super(LinkListCell, self).get_cell_extra_context(context)
|
||||
links = []
|
||||
for cell in context.get('page_cells', []):
|
||||
if not hasattr(cell, 'add_as_link_label'):
|
||||
continue
|
||||
if not cell.placeholder == self.link_placeholder:
|
||||
continue
|
||||
links.append(cell.get_cell_extra_context(context))
|
||||
extra_context['links'] = links
|
||||
extra_context['title'] = self.title
|
||||
return extra_context
|
||||
|
||||
def get_link_cell_classes(self):
|
||||
return CellBase.get_cell_classes(lambda x: hasattr(x, 'add_as_link_label'))
|
||||
|
||||
def get_default_form_class(self):
|
||||
from .forms import LinkListCellForm
|
||||
return LinkListCellForm
|
||||
|
||||
def render_for_search(self):
|
||||
return ''
|
||||
|
||||
def export_subobjects(self):
|
||||
return {'links': json.loads(
|
||||
serializers.serialize(
|
||||
'json',
|
||||
self.get_items(),
|
||||
use_natural_foreign_keys=True,
|
||||
use_natural_primary_keys=True)
|
||||
)}
|
||||
|
||||
def import_subobjects(self, cell_json):
|
||||
for link in cell_json['links']:
|
||||
link['fields']['placeholder'] = self.link_placeholder
|
||||
for link in serializers.deserialize('json', json.dumps(cell_json['links'])):
|
||||
link.save()
|
||||
|
||||
def duplicate_m2m(self, new_cell):
|
||||
# duplicate also link items
|
||||
for link in self.get_items():
|
||||
link.duplicate(page_target=new_cell.page, placeholder=new_cell.link_placeholder)
|
||||
|
||||
|
||||
@register_cell_class
|
||||
class FeedCell(CellBase):
|
||||
title = models.CharField(_('Title'), max_length=150, blank=True)
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
{% extends "combo/cell_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block cell-form %}
|
||||
{{ form.as_p }}
|
||||
{% with cell.get_items as links %}
|
||||
{% if links %}
|
||||
<p><label>{% trans "Links:" %}</label></p>
|
||||
<div>
|
||||
<ul class="objects-list list-of-links" id="list-of-links-{{ cell.pk }}"
|
||||
data-link-list-order-url="{% url 'combo-manager-link-list-order' page_pk=page.pk cell_reference=cell.get_reference %}">
|
||||
{% for link in links %}
|
||||
<li data-link-item-id="{{ link.pk }}"><span class="handle">⣿</span>
|
||||
<span title="{{ link }}">{{ link|truncatechars:100 }}</span>
|
||||
<a rel="popup" title="{% trans "Edit" %}" class="link-action-icon edit" href="{% url 'combo-manager-page-list-cell-edit-link' page_pk=page.id cell_reference=cell.get_reference link_cell_reference=link.get_reference %}">{% trans "Edit" %}</a>
|
||||
<a rel="popup" title="{% trans "Delete" %}" class="link-action-icon delete" href="{% url 'combo-manager-page-list-cell-delete-link' page_pk=page.id cell_reference=cell.get_reference link_cell_reference=link.get_reference %}">{% trans "Delete" %}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$('#list-of-links-{{ cell.pk }}').sortable({
|
||||
handle: '.handle',
|
||||
update: function(event, ui) {
|
||||
var new_order = Object();
|
||||
$(this).find('li').each(function(i, x) {
|
||||
var suffix = $(x).data('link-item-id');
|
||||
new_order['pos_' + suffix] = i;
|
||||
});
|
||||
$.ajax({
|
||||
url: $(this).data('link-list-order-url'),
|
||||
data: new_order
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<div class="buttons">
|
||||
{% for klass in cell.get_link_cell_classes %}
|
||||
<a rel="popup" href="{% url 'combo-manager-page-list-cell-add-link' page_pk=page.id cell_reference=cell.get_reference link_code=klass.add_as_link_code %}">{{ klass.add_as_link_label }}</a> {% if not forloop.last %}|{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -480,3 +480,41 @@ ul.gallery li:last-child a {
|
|||
text-align: center;
|
||||
padding: 45px 1ex 1ex 1ex;
|
||||
}
|
||||
|
||||
ul.objects-list.list-of-links li {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
ul.objects-list.list-of-links li a.link-action-icon {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 3em;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
text-indent: -1000px;
|
||||
line-height: 3em;
|
||||
}
|
||||
|
||||
ul.objects-list.list-of-links li a.link-action-icon::before {
|
||||
font-family: FontAwesome;
|
||||
text-indent: 0px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
ul.objects-list.list-of-links li a.link-action-icon.delete::before {
|
||||
content: "\f057"; /* remove-sign */
|
||||
}
|
||||
|
||||
ul.objects-list.list-of-links li a.link-action-icon.edit {
|
||||
right: 3em;
|
||||
}
|
||||
|
||||
ul.objects-list.list-of-links li a.link-action-icon.edit::before {
|
||||
content: "\f044";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
{% extends "combo/manager_base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block appbar %}
|
||||
{% if form.instance.pk %}
|
||||
<h2>{{ form.instance.edit_link_label }}</h2>
|
||||
{% else %}
|
||||
<h2>{{ form.instance.add_link_label }}</h2>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Save" %}</button>
|
||||
<a class="cancel" href="{% url 'combo-manager-page-view' pk=form.instance.page_id %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -75,6 +75,18 @@ urlpatterns = [
|
|||
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,
|
||||
name='combo-manager-page-list-cell-add-link'),
|
||||
url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/link/(?P<link_cell_reference>[\w_-]+)/$',
|
||||
views.page_list_cell_edit_link,
|
||||
name='combo-manager-page-list-cell-edit-link'),
|
||||
url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/link/(?P<link_cell_reference>[\w_-]+)/delete$',
|
||||
views.page_list_cell_delete_link,
|
||||
name='combo-manager-page-list-cell-delete-link'),
|
||||
url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/order$',
|
||||
views.link_list_order,
|
||||
name='combo-manager-link-list-order'),
|
||||
url(r'^pages/(?P<page_pk>\d+)/order$', views.cell_order,
|
||||
name='combo-manager-cell-order'),
|
||||
url(r'^pages/order$', views.page_order,
|
||||
|
|
|
@ -33,7 +33,7 @@ from django.views.decorators.csrf import requires_csrf_token
|
|||
from django.views.generic import (RedirectView, DetailView,
|
||||
CreateView, UpdateView, ListView, DeleteView, FormView)
|
||||
|
||||
from combo.data.models import Page, CellBase, ParentContentCell, PageSnapshot
|
||||
from combo.data.models import Page, CellBase, ParentContentCell, PageSnapshot, LinkListCell
|
||||
from combo.data.library import get_cell_class
|
||||
from combo.data.utils import export_site, import_site, MissingGroups
|
||||
from combo import plugins
|
||||
|
@ -124,7 +124,6 @@ class PageAddChildView(PageAddView):
|
|||
return super(CreateView, self).get_initial()
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
print(request.POST)
|
||||
self.parent = get_object_or_404(Page, pk=kwargs['pk'])
|
||||
return super(PageAddChildView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
|
@ -399,6 +398,7 @@ class PageEditCellView(UpdateView):
|
|||
def get_context_data(self, **kwargs):
|
||||
context = super(PageEditCellView, self).get_context_data(**kwargs)
|
||||
context['cell'] = self.get_object()
|
||||
context['page'] = context['cell'].page
|
||||
return context
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
|
@ -564,3 +564,143 @@ def menu_json(request):
|
|||
response = HttpResponse(content_type=content_type)
|
||||
response.write(json_str)
|
||||
return response
|
||||
|
||||
|
||||
class PageListCellAddLinkView(CreateView):
|
||||
template_name = 'combo/link_cell_form.html'
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
try:
|
||||
self.cell = CellBase.get_cell(kwargs['cell_reference'], page=kwargs['page_pk'])
|
||||
except LinkListCell.DoesNotExist:
|
||||
raise Http404
|
||||
for klass in self.cell.get_link_cell_classes():
|
||||
if klass.add_as_link_code == kwargs['link_code']:
|
||||
self.model = klass
|
||||
break
|
||||
if self.model is None:
|
||||
raise Http404
|
||||
return super(PageListCellAddLinkView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_form_class(self):
|
||||
return self.model().get_default_form_class()
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(PageListCellAddLinkView, self).get_form_kwargs()
|
||||
kwargs['instance'] = self.model(page=self.cell.page, placeholder=self.cell.link_placeholder)
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
orders = [x.order for x in self.cell.get_items()]
|
||||
if orders:
|
||||
form.instance.order = max(orders)+1
|
||||
else:
|
||||
form.instance.order = 1
|
||||
return super(PageListCellAddLinkView, self).form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return '%s#cell-%s' % (
|
||||
reverse('combo-manager-page-view', kwargs={'pk': self.kwargs.get('page_pk')}),
|
||||
self.kwargs['cell_reference'])
|
||||
|
||||
|
||||
page_list_cell_add_link = PageListCellAddLinkView.as_view()
|
||||
|
||||
|
||||
class PageListCellEditLinkView(UpdateView):
|
||||
template_name = 'combo/link_cell_form.html'
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
try:
|
||||
self.cell = CellBase.get_cell(kwargs['cell_reference'], page=kwargs['page_pk'])
|
||||
except LinkListCell.DoesNotExist:
|
||||
raise Http404
|
||||
try:
|
||||
self.object = CellBase.get_cell(kwargs['link_cell_reference'], page=kwargs['page_pk'])
|
||||
except ObjectDoesNotExist:
|
||||
raise Http404
|
||||
if self.object.placeholder != self.cell.link_placeholder:
|
||||
raise Http404
|
||||
self.model = self.object.__class__
|
||||
return super(PageListCellEditLinkView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
return self.object
|
||||
|
||||
def get_form_class(self):
|
||||
return self.model().get_default_form_class()
|
||||
|
||||
def form_valid(self, form):
|
||||
if self.request.is_ajax():
|
||||
self.object = form.save()
|
||||
response = self.form_invalid(form) # avoid redirection
|
||||
else:
|
||||
response = super(PageListCellEditLinkView, self).form_valid(form)
|
||||
PageSnapshot.take(self.cell.page, request=self.request, comment=_('changed cell "%s"') % self.cell)
|
||||
return response
|
||||
|
||||
def get_success_url(self):
|
||||
return '%s#cell-%s' % (
|
||||
reverse('combo-manager-page-view', kwargs={'pk': self.kwargs.get('page_pk')}),
|
||||
self.kwargs['cell_reference'])
|
||||
|
||||
|
||||
page_list_cell_edit_link = PageListCellEditLinkView.as_view()
|
||||
|
||||
|
||||
class PageListCellDeleteLinkView(DeleteView):
|
||||
template_name = 'combo/generic_confirm_delete.html'
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
try:
|
||||
self.cell = CellBase.get_cell(kwargs['cell_reference'], page=kwargs['page_pk'])
|
||||
except LinkListCell.DoesNotExist:
|
||||
raise Http404
|
||||
try:
|
||||
self.object = CellBase.get_cell(kwargs['link_cell_reference'], page=kwargs['page_pk'])
|
||||
except ObjectDoesNotExist:
|
||||
raise Http404
|
||||
if self.object.placeholder != self.cell.link_placeholder:
|
||||
raise Http404
|
||||
self.model = self.object.__class__
|
||||
return super(PageListCellDeleteLinkView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
return self.object
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
response = super(PageListCellDeleteLinkView, self).delete(request, *args, **kwargs)
|
||||
PageSnapshot.take(self.cell.page, request=self.request, comment=_('changed cell "%s"') % self.cell)
|
||||
return response
|
||||
|
||||
def get_success_url(self):
|
||||
return '%s#cell-%s' % (
|
||||
reverse('combo-manager-page-view', kwargs={'pk': self.kwargs.get('page_pk')}),
|
||||
self.kwargs['cell_reference'])
|
||||
|
||||
|
||||
page_list_cell_delete_link = PageListCellDeleteLinkView.as_view()
|
||||
|
||||
|
||||
def link_list_order(request, page_pk, cell_reference):
|
||||
try:
|
||||
cell = CellBase.get_cell(cell_reference, page=page_pk)
|
||||
except LinkListCell.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
has_changes = False
|
||||
for link in cell.get_items():
|
||||
old_order = link.order
|
||||
try:
|
||||
new_order = int(request.GET.get('pos_' + str(link.pk)))
|
||||
except TypeError:
|
||||
continue
|
||||
if new_order != old_order:
|
||||
link.order = new_order
|
||||
has_changes = True
|
||||
link.save(update_fields=['order'])
|
||||
|
||||
if has_changes:
|
||||
PageSnapshot.take(cell.page, request=request, comment=_('reordered cells'))
|
||||
|
||||
return HttpResponse(status=204)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
{% block cell-content %}
|
||||
{% spaceless %}
|
||||
<div class="links-list">
|
||||
{% if title %}<h2>{{title}}</h2>{% endif %}
|
||||
<ul>
|
||||
{% for link in links %}
|
||||
<li><a href="{{ link.url }}">{{ link.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endspaceless %}
|
||||
{% endblock %}
|
|
@ -4,7 +4,10 @@ import os
|
|||
import pytest
|
||||
import requests
|
||||
|
||||
from combo.data.models import Page, CellBase, TextCell, LinkCell, MenuCell, JsonCellBase, JsonCell, ConfigJsonCell
|
||||
from combo.data.models import (
|
||||
Page, CellBase, TextCell, LinkCell, MenuCell, JsonCellBase,
|
||||
JsonCell, ConfigJsonCell, LinkListCell
|
||||
)
|
||||
from django.conf import settings
|
||||
from django.db import connection
|
||||
from django.forms.widgets import Media
|
||||
|
@ -93,6 +96,7 @@ def test_text_cell_variadic_url():
|
|||
assert 'href=""' in cell.render(ctx)
|
||||
assert 'href="/plop"' in cell.render(ctx)
|
||||
|
||||
|
||||
def test_link_cell():
|
||||
page = Page(title='example page', slug='example-page')
|
||||
page.save()
|
||||
|
@ -130,6 +134,37 @@ def test_link_cell():
|
|||
assert cell.render(ctx).strip() == '<a href="http://example.net/#anchor">altertitle</a>'
|
||||
|
||||
|
||||
def test_link_list_cell():
|
||||
page = Page.objects.create(title='example page', slug='example-page')
|
||||
|
||||
cell = LinkListCell.objects.create(order=0, page=page)
|
||||
item = LinkCell.objects.create(
|
||||
page=page,
|
||||
placeholder=cell.link_placeholder,
|
||||
title='Example Site',
|
||||
url='http://example.net/',
|
||||
order=0,
|
||||
)
|
||||
|
||||
ctx = {'page_cells': [item]}
|
||||
assert '<ul><li><a href="http://example.net/">Example Site</a></li></ul>' in cell.render(ctx)
|
||||
|
||||
item.title = ''
|
||||
assert '<ul><li><a href="http://example.net/">http://example.net/</a></li></ul>' in cell.render(ctx)
|
||||
|
||||
item.link_page = page
|
||||
assert '<ul><li><a href="/example-page/">example page</a></li></ul>' in cell.render(ctx)
|
||||
|
||||
item.title = 'altertitle'
|
||||
assert '<ul><li><a href="/example-page/">altertitle</a></li></ul>' in cell.render(ctx)
|
||||
|
||||
item.anchor = 'anchor'
|
||||
assert '<ul><li><a href="/example-page/#anchor">altertitle</a></li></ul>' in cell.render(ctx)
|
||||
|
||||
item.link_page = None
|
||||
assert '<ul><li><a href="http://example.net/#anchor">altertitle</a></li></ul>' in cell.render(ctx)
|
||||
|
||||
|
||||
def test_menu_cell():
|
||||
Page.objects.all().delete()
|
||||
parent = page = Page(title='Page1', slug='page1', template_name='standard')
|
||||
|
@ -728,3 +763,27 @@ def test_related_cell_types_tracking():
|
|||
|
||||
TextCell(page=page, placeholder='content', order=0, text='hello').save()
|
||||
assert set(Page.objects.get(id=page.id).related_cells['cell_types']) == set(['data_textcell', 'data_linkcell'])
|
||||
|
||||
|
||||
def test_link_list_cell_duplicate():
|
||||
page = Page.objects.create(title='xxx', slug='new', template_name='standard')
|
||||
cell = LinkListCell.objects.create(order=0, page=page)
|
||||
item = LinkCell.objects.create(
|
||||
page=page,
|
||||
placeholder=cell.link_placeholder,
|
||||
title='Example Site',
|
||||
url='http://example.net/',
|
||||
link_page=page,
|
||||
order=1,
|
||||
)
|
||||
|
||||
new_cell = cell.duplicate()
|
||||
assert LinkCell.objects.count() == 2
|
||||
assert len(new_cell.get_items()) == 1
|
||||
new_item = new_cell.get_items()[0]
|
||||
assert new_item.page == page
|
||||
assert new_item.placeholder == new_cell.link_placeholder
|
||||
assert new_item.pk != item.pk
|
||||
assert new_item.title == item.title
|
||||
assert new_item.url == item.url
|
||||
assert new_item.link_page == item.link_page
|
||||
|
|
|
@ -21,7 +21,7 @@ from webtest import TestApp
|
|||
from webtest import Upload
|
||||
|
||||
from combo.wsgi import application
|
||||
from combo.data.models import Page, CellBase, TextCell, LinkCell, ConfigJsonCell, JsonCell, PageSnapshot
|
||||
from combo.data.models import Page, CellBase, TextCell, LinkCell, ConfigJsonCell, JsonCell, PageSnapshot, LinkListCell
|
||||
from combo.apps.assets.models import Asset
|
||||
from combo.apps.family.models import FamilyInfosCell
|
||||
from combo.apps.search.models import SearchCell
|
||||
|
@ -1373,3 +1373,73 @@ def test_json_cell_syntax_validation(app, admin_user):
|
|||
assert 'syntax error' not in resp.text
|
||||
assert JsonCell.objects.count() == 1
|
||||
assert JsonCell.objects.first().template_string == '{{ ok }}'
|
||||
|
||||
|
||||
def test_add_edit_delete_list_link_item(app, admin_user):
|
||||
Page.objects.all().delete()
|
||||
page = Page.objects.create(title='One', slug='one', template_name='standard')
|
||||
cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pages/%s/' % page.pk)
|
||||
|
||||
resp = resp.click(href='.*/add-link/link$')
|
||||
resp.forms[0]['title'] = 'Hello world'
|
||||
resp.forms[0]['url'] = 'http://example.com'
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.status_int == 302
|
||||
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
|
||||
assert LinkCell.objects.count() == 1
|
||||
item = LinkCell.objects.get()
|
||||
assert item.title == 'Hello world'
|
||||
assert item.url == 'http://example.com'
|
||||
assert item.page == page
|
||||
assert item.placeholder == cell.link_placeholder
|
||||
|
||||
resp = resp.follow()
|
||||
resp = resp.click(href='.*/link/%s/$' % item.get_reference())
|
||||
resp.forms[0]['title'] = 'Hello world 2'
|
||||
resp.forms[0]['url'] = 'http://example2.com'
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.status_int == 302
|
||||
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
|
||||
assert LinkCell.objects.count() == 1
|
||||
item.refresh_from_db()
|
||||
assert item.title == 'Hello world 2'
|
||||
assert item.url == 'http://example2.com'
|
||||
|
||||
resp = resp.follow()
|
||||
resp = resp.click(href='.*/link/%s/delete' % item.get_reference())
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.status_int == 302
|
||||
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
|
||||
assert LinkCell.objects.count() == 0
|
||||
|
||||
|
||||
def test_edit_link_list_order(app, admin_user):
|
||||
Page.objects.all().delete()
|
||||
page = Page.objects.create(title='One', slug='one', template_name='standard')
|
||||
cell = LinkListCell.objects.create(order=0, page=page)
|
||||
items = []
|
||||
for i in range(5):
|
||||
items.append(
|
||||
LinkCell.objects.create(
|
||||
page=page,
|
||||
placeholder=cell.link_placeholder,
|
||||
title='Foo %s' % i,
|
||||
url='http://example.net/',
|
||||
link_page=page,
|
||||
order=i+1,
|
||||
)
|
||||
)
|
||||
|
||||
params = []
|
||||
new_order = [2, 3, 1, 4, 5]
|
||||
for i, (item, new_pos) in enumerate(zip(items, new_order)):
|
||||
params.append(('pos_%s' % item.pk, str(new_pos)))
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pages/%s/cell/%s/order?%s' % (page.pk, cell.get_reference(), urlencode(params)))
|
||||
assert resp.status_code == 204
|
||||
for i, item in enumerate(items):
|
||||
item.refresh_from_db()
|
||||
assert item.order == new_order[i]
|
||||
|
|
|
@ -9,7 +9,7 @@ from django.test import override_settings
|
|||
from django.test.client import RequestFactory
|
||||
from django.utils.six import StringIO
|
||||
from django.utils.timezone import now
|
||||
from combo.data.models import Page, PageSnapshot, CellBase, TextCell, LinkCell
|
||||
from combo.data.models import Page, PageSnapshot, CellBase, TextCell, LinkCell, LinkListCell
|
||||
from combo.data.management.commands.import_site import Command as ImportSiteCommand
|
||||
from combo.data.management.commands.export_site import Command as ExportSiteCommand
|
||||
from combo.manager.forms import PageVisibilityForm
|
||||
|
@ -182,6 +182,22 @@ def test_import_export_pages_with_links():
|
|||
cell2 = LinkCell(page=page2, title='foo', placeholder='content', link_page=page, order=1)
|
||||
cell2.save()
|
||||
|
||||
cell3 = LinkListCell.objects.create(page=page, placeholder='content', order=2)
|
||||
item1 = LinkCell.objects.create(
|
||||
page=page,
|
||||
placeholder=cell3.link_placeholder,
|
||||
title='Example Site',
|
||||
url='http://example.net/',
|
||||
order=0,
|
||||
)
|
||||
item2 = LinkCell.objects.create(
|
||||
page=page,
|
||||
placeholder=cell3.link_placeholder,
|
||||
title='blah',
|
||||
link_page=page2,
|
||||
order=1,
|
||||
)
|
||||
|
||||
site_export = [x.get_serialized_page() for x in Page.objects.all()]
|
||||
Page.objects.all().delete()
|
||||
|
||||
|
@ -189,8 +205,21 @@ def test_import_export_pages_with_links():
|
|||
|
||||
new_page_1 = Page.objects.all().order_by('order')[0]
|
||||
new_page_2 = Page.objects.all().order_by('order')[1]
|
||||
assert CellBase.get_cells(page_id=new_page_1.id)[0].link_page_id == new_page_2.id
|
||||
assert CellBase.get_cells(page_id=new_page_2.id)[0].link_page_id == new_page_1.id
|
||||
new_cells_1 = CellBase.get_cells(page_id=new_page_1.id, placeholder='content')
|
||||
new_cells_2 = CellBase.get_cells(page_id=new_page_2.id, placeholder='content')
|
||||
assert new_cells_1[0].link_page_id == new_page_2.id
|
||||
assert new_cells_2[0].link_page_id == new_page_1.id
|
||||
assert len(new_cells_1[1].get_items()) == 2
|
||||
new_item_1 = new_cells_1[1].get_items()[0]
|
||||
assert isinstance(new_item_1, LinkCell)
|
||||
assert new_item_1.title == item1.title
|
||||
assert new_item_1.url == item1.url
|
||||
assert new_item_1.link_page is None
|
||||
new_item_2 = new_cells_1[1].get_items()[1]
|
||||
assert isinstance(new_item_2, LinkCell)
|
||||
assert new_item_2.title == item2.title
|
||||
assert new_item_2.url == ''
|
||||
assert new_item_2.link_page == new_page_2
|
||||
|
||||
|
||||
def test_duplicate_page():
|
||||
|
|
|
@ -22,7 +22,7 @@ from django.utils.six.moves.urllib import parse as urlparse
|
|||
|
||||
import mock
|
||||
|
||||
from combo.data.models import Page
|
||||
from combo.data.models import CellBase, LinkListCell, Page
|
||||
from combo.apps.search.engines import engines
|
||||
from combo.apps.wcs.models import (WcsFormCell, WcsCurrentFormsCell,
|
||||
WcsFormsOfCategoryCell, WcsCurrentDraftsCell, WcsCategoryCell,
|
||||
|
@ -901,3 +901,93 @@ def test_backoffice_submission_cell_render(context):
|
|||
|
||||
result = cell.render(context)
|
||||
assert '/backoffice/submission/a-private-form/' in result
|
||||
|
||||
|
||||
@wcs_present
|
||||
def test_manager_link_list_cell_duplicate():
|
||||
page = Page.objects.create(title='xxx', slug='new', template_name='standard')
|
||||
cell = LinkListCell.objects.create(order=0, page=page)
|
||||
item = WcsFormCell.objects.create(
|
||||
page=page,
|
||||
placeholder=cell.link_placeholder,
|
||||
cached_title='A title',
|
||||
cached_url='http://example.com',
|
||||
cached_json={'foo': 'bar'},
|
||||
order=1)
|
||||
|
||||
new_cell = cell.duplicate()
|
||||
assert WcsFormCell.objects.count() == 2
|
||||
assert len(new_cell.get_items()) == 1
|
||||
new_item = new_cell.get_items()[0]
|
||||
assert new_item.page == page
|
||||
assert new_item.placeholder == new_cell.link_placeholder
|
||||
assert new_item.pk != item.pk
|
||||
assert new_item.cached_title == item.cached_title
|
||||
assert new_item.cached_url == item.cached_url
|
||||
assert new_item.cached_json == item.cached_json
|
||||
|
||||
|
||||
@wcs_present
|
||||
def test_manager_add_edit_delete_list_link_item(app, admin_user):
|
||||
Page.objects.all().delete()
|
||||
page = Page.objects.create(title='One', slug='one', template_name='standard')
|
||||
cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pages/%s/' % page.pk)
|
||||
|
||||
resp = resp.click(href='.*/add-link/form-link$')
|
||||
resp.forms[0]['formdef_reference'] = 'default:form-title'
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.status_int == 302
|
||||
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
|
||||
assert WcsFormCell.objects.count() == 1
|
||||
item = WcsFormCell.objects.get()
|
||||
assert item.formdef_reference == 'default:form-title'
|
||||
assert item.page == page
|
||||
assert item.placeholder == cell.link_placeholder
|
||||
|
||||
resp = resp.follow()
|
||||
resp = resp.click(href='.*/link/%s/$' % item.get_reference())
|
||||
resp.forms[0]['formdef_reference'] = 'default:a-private-form'
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.status_int == 302
|
||||
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
|
||||
assert WcsFormCell.objects.count() == 1
|
||||
item.refresh_from_db()
|
||||
assert item.formdef_reference == 'default:a-private-form'
|
||||
|
||||
resp = resp.follow()
|
||||
resp = resp.click(href='.*/link/%s/delete' % item.get_reference())
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.status_int == 302
|
||||
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
|
||||
assert WcsFormCell.objects.count() == 0
|
||||
|
||||
|
||||
def test_import_export_pages_with_links():
|
||||
page = Page(title=u'bar', slug='bar', order=1)
|
||||
page.save()
|
||||
|
||||
cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
|
||||
item = WcsFormCell.objects.create(
|
||||
page=page,
|
||||
placeholder=cell.link_placeholder,
|
||||
cached_title='A title',
|
||||
cached_url='http://example.com',
|
||||
cached_json={'foo': 'bar'},
|
||||
order=0,
|
||||
)
|
||||
|
||||
site_export = [x.get_serialized_page() for x in Page.objects.all()]
|
||||
Page.objects.all().delete()
|
||||
|
||||
Page.load_serialized_pages(site_export)
|
||||
|
||||
new_page = Page.objects.get()
|
||||
new_cells = CellBase.get_cells(page_id=new_page.id, placeholder='content')
|
||||
assert len(new_cells[0].get_items()) == 1
|
||||
new_item = new_cells[0].get_items()[0]
|
||||
assert isinstance(new_item, WcsFormCell)
|
||||
assert new_item.cached_title == item.cached_title
|
||||
assert new_item.cached_url == item.cached_url
|
||||
assert new_item.cached_json == item.cached_json
|
||||
|
|
Loading…
Reference in New Issue