Projet

Général

Profil

0001-cells-add-a-cell-type-list-of-links-11006.patch

Lauréline Guérin, 14 janvier 2020 15:18

Télécharger (34 ko)

Voir les différences:

Subject: [PATCH] cells: add a cell type "list of links" (#11006)

 combo/apps/wcs/models.py                      |   8 +-
 combo/data/forms.py                           |  13 +-
 combo/data/migrations/0039_link_list_cell.py  |  39 +++++
 combo/data/models.py                          |  80 +++++++++-
 .../combo/manager/link-list-cell-form.html    |  29 ++++
 combo/manager/static/js/combo.manager.js      |  15 ++
 .../templates/combo/link_cell_form.html       |  22 +++
 combo/manager/urls.py                         |  12 ++
 combo/manager/views.py                        | 143 +++++++++++++++++-
 .../templates/combo/link-list-cell.html       |  12 ++
 tests/test_cells.py                           |  61 +++++++-
 tests/test_manager.py                         |  72 ++++++++-
 tests/test_pages.py                           |  35 ++++-
 tests/test_wcs.py                             |  92 ++++++++++-
 14 files changed, 621 insertions(+), 12 deletions(-)
 create mode 100644 combo/data/migrations/0039_link_list_cell.py
 create mode 100644 combo/data/templates/combo/manager/link-list-cell-form.html
 create mode 100644 combo/manager/templates/combo/link_cell_form.html
 create mode 100644 combo/public/templates/combo/link-list-cell.html
combo/apps/wcs/models.py
36 36

  
37 37
@register_cell_class
38 38
class WcsFormCell(CellBase):
39
    template_name = 'combo/wcs/form.html'
40

  
41 39
    formdef_reference = models.CharField(_('Form'), max_length=150)
42 40

  
43 41
    cached_title = models.CharField(_('Title'), max_length=150)
44 42
    cached_url = models.URLField(_('URL'))
45 43
    cached_json = JSONField(blank=True)
46 44

  
45
    template_name = 'combo/wcs/form.html'
46
    add_as_link_label = _('add a form link')
47
    add_link_label = _('New form link')
48
    edit_link_label = _('Edit form link')
49
    add_as_link_code = 'form-link'
50

  
47 51
    is_enabled = classmethod(is_wcs_enabled)
48 52

  
49 53
    class Meta:
combo/data/forms.py
18 18

  
19 19
from django import forms
20 20

  
21
from .models import Page, ParametersCell, MenuCell, LinkCell, ConfigJsonCell
21
from .models import Page, ParametersCell, MenuCell, LinkCell, LinkListCell, ConfigJsonCell
22 22
from jsonfield.widgets import JSONWidget
23 23

  
24 24
from combo.utils import cache_during_request
......
41 41
                break
42 42
        return self.cleaned_data
43 43

  
44

  
44 45
class ParametersCellForm(forms.ModelForm):
45 46
    class Meta:
46 47
        model = ParametersCell
......
61 62
    pages = Page.get_as_reordered_flat_hierarchy(Page.objects.all())
62 63
    return [(x.id, '%s %s' % (u'\u00a0' * x.level * 2, x.title)) for x in pages]
63 64

  
65

  
64 66
class MenuCellForm(forms.ModelForm):
65 67
    class Meta:
66 68
        model = MenuCell
......
82 84
                choices=[(None, '-----')] + get_page_choices())
83 85

  
84 86

  
87
class LinkListCellForm(forms.ModelForm):
88
    class Meta:
89
        model = LinkListCell
90
        fields = ['title']
91

  
92
    def __init__(self, *args, **kwargs):
93
        super(LinkListCellForm, self).__init__(*args, **kwargs)
94

  
95

  
85 96
class ConfigJsonForm(forms.ModelForm):
86 97
    formdef = []
87 98

  
combo/data/migrations/0039_link_list_cell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4
from django.db import migrations, models
5
import django.db.models.deletion
6

  
7

  
8
class Migration(migrations.Migration):
9

  
10
    dependencies = [
11
        ('auth', '0008_alter_user_username_max_length'),
12
        ('data', '0038_increase_jsoncell_url_max_length'),
13
    ]
14

  
15
    operations = [
16
        migrations.CreateModel(
17
            name='LinkListCell',
18
            fields=[
19
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
                ('placeholder', models.CharField(max_length=20)),
21
                ('order', models.PositiveIntegerField()),
22
                ('slug', models.SlugField(blank=True, verbose_name='Slug')),
23
                ('extra_css_class', models.CharField(blank=True, max_length=100, verbose_name='Extra classes for CSS styling')),
24
                ('public', models.BooleanField(default=True, verbose_name='Public')),
25
                ('restricted_to_unlogged', models.BooleanField(default=False, verbose_name='Restrict to unlogged users')),
26
                ('last_update_timestamp', models.DateTimeField(auto_now=True)),
27
                ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Groups')),
28
                ('title', models.CharField(max_length=150, verbose_name='Title', blank=True)),
29
            ],
30
            options={
31
                'verbose_name': 'List of links',
32
            },
33
        ),
34
        migrations.AddField(
35
            model_name='linklistcell',
36
            name='page',
37
            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
38
        ),
39
    ]
combo/data/models.py
451 451
        new_page.groups.set(self.groups.all())
452 452

  
453 453
        for cell in self.get_cells():
454
            if cell.placeholder and cell.placeholder.startswith('_'):
455
                continue
454 456
            cell.duplicate(page_target=new_page)
455 457

  
456 458
        return new_page
......
756 758
    def import_subobjects(self, cell_json):
757 759
        pass
758 760

  
759
    def duplicate(self, page_target=None):
761
    def duplicate(self, page_target=None, placeholder=None):
760 762
        # clone current cell
761 763
        new_cell = copy.deepcopy(self)
762 764
        new_cell.pk = None
763 765
        # set page
764 766
        new_cell.page = page_target or self.page
767
        # set placeholder
768
        new_cell.placeholder = placeholder or new_cell.placeholder
765 769
        # store new cell
766 770
        new_cell.save()
767 771

  
......
905 909
    anchor = models.CharField(_('Anchor'), max_length=150, blank=True)
906 910

  
907 911
    template_name = 'combo/link-cell.html'
912
    add_as_link_label = _('add a link')
913
    add_link_label = _('New link')
914
    edit_link_label = _('Edit link')
915
    add_as_link_code = 'link'
908 916

  
909 917
    class Meta:
910 918
        verbose_name = _('Link')
......
950 958
        return []
951 959

  
952 960

  
961
@register_cell_class
962
class LinkListCell(CellBase):
963
    title = models.CharField(_('Title'), max_length=150, blank=True)
964

  
965
    template_name = 'combo/link-list-cell.html'
966
    manager_form_template = 'combo/manager/link-list-cell-form.html'
967

  
968
    class Meta:
969
        verbose_name = _('List of links')
970

  
971
    @property
972
    def link_placeholder(self):
973
        return '_linkslist:{}'.format(self.pk)
974

  
975
    def get_items(self):
976
        return CellBase.get_cells(
977
            page=self.page,
978
            placeholder=self.link_placeholder,
979
            cell_filter=lambda x: hasattr(x, 'add_as_link_label'))
980

  
981
    def get_additional_label(self):
982
        title = self.title
983
        if not title:
984
            return None
985
        return utils.ellipsize(title)
986

  
987
    def get_cell_extra_context(self, context):
988
        extra_context = super(LinkListCell, self).get_cell_extra_context(context)
989
        links = []
990
        for cell in context.get('page_cells', []):
991
            if not hasattr(cell, 'add_as_link_label'):
992
                continue
993
            if not cell.placeholder == self.link_placeholder:
994
                continue
995
            links.append(cell.get_cell_extra_context(context))
996
        extra_context['links'] = links
997
        extra_context['title'] = self.title
998
        return extra_context
999

  
1000
    def get_link_cell_classes(self):
1001
        return CellBase.get_cell_classes(lambda x: hasattr(x, 'add_as_link_label'))
1002

  
1003
    def get_default_form_class(self):
1004
        from .forms import LinkListCellForm
1005
        return LinkListCellForm
1006

  
1007
    def render_for_search(self):
1008
        return ''
1009

  
1010
    def export_subobjects(self):
1011
        return {'links': json.loads(
1012
            serializers.serialize(
1013
                'json',
1014
                self.get_items(),
1015
                use_natural_foreign_keys=True,
1016
                use_natural_primary_keys=True)
1017
            )}
1018

  
1019
    def import_subobjects(self, cell_json):
1020
        for link in cell_json['links']:
1021
            link['fields']['placeholder'] = self.link_placeholder
1022
        for link in serializers.deserialize('json', json.dumps(cell_json['links'])):
1023
            link.save()
1024

  
1025
    def duplicate_m2m(self, new_cell):
1026
        # duplicate also link items
1027
        for link in self.get_items():
1028
            link.duplicate(page_target=new_cell.page, placeholder=new_cell.link_placeholder)
1029

  
1030

  
953 1031
@register_cell_class
954 1032
class FeedCell(CellBase):
955 1033
    title = models.CharField(_('Title'), max_length=150, blank=True)
combo/data/templates/combo/manager/link-list-cell-form.html
1
{% extends "combo/cell_form.html" %}
2
{% load i18n %}
3

  
4
{% block cell-form %}
5
{% with cell.get_items as links %}
6
{% if links %}
7
<table class="main">
8
  <tbody class="link-list" data-link-list-order-url="{% url 'combo-manager-link-list-order' page_pk=page.pk cell_reference=cell.get_reference %}">
9
    {% for link in links %}
10
    <tr class="link-item" data-link-item-id="{{ link.pk }}">
11
      <td><span class="handle-link-item">⣿</span> {{ link }}</td>
12
      <td>
13
        <a rel="popup" 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> |
14
        <a rel="popup" 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>
15
      </td>
16
    </tr>
17
    {% endfor %}
18
  </tbody>
19
</table>
20
{% endif %}
21
{% endwith %}
22
<div class="buttons">
23
  {% for klass in cell.get_link_cell_classes %}
24
  <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 %}
25
  {% endfor %}
26
</div>
27
<br />
28
{{ form.as_p }}
29
{% endblock %}
combo/manager/static/js/combo.manager.js
220 220
     return false;
221 221
  });
222 222

  
223
  $('.link-list').sortable({
224
     handle: '.handle-link-item',
225
     stop: function(event, ui) {
226
       var new_order = Object();
227
       $('.link-item').each(function(i, x) {
228
           var suffix = $(x).data('link-item-id');
229
           new_order['pos_' + suffix] = i;
230
       });
231
       $.ajax({
232
           url: $(this).data('link-list-order-url'),
233
           data: new_order
234
       });
235
     }
236
  });
237

  
223 238
  function compute_max_height($cell) {
224 239
    var cell_id = $cell.attr('id');
225 240
    $('style#for-' + cell_id).remove();
combo/manager/templates/combo/link_cell_form.html
1
{% extends "combo/manager_base.html" %}
2
{% load i18n %}
3

  
4
{% block appbar %}
5
{% if form.instance.pk %}
6
<h2>{{ form.instance.edit_link_label }}</h2>
7
{% else %}
8
<h2>{{ form.instance.add_link_label }}</h2>
9
{% endif %}
10
{% endblock %}
11

  
12
{% block content %}
13

  
14
<form method="post" enctype="multipart/form-data">
15
  {% csrf_token %}
16
  {{ form.as_p }}
17
  <div class="buttons">
18
    <button class="submit-button">{% trans "Save" %}</button>
19
    <a class="cancel" href="{% url 'combo-manager-page-view' pk=form.instance.page_id %}">{% trans 'Cancel' %}</a>
20
  </div>
21
</form>
22
{% endblock %}
combo/manager/urls.py
75 75
            name='combo-manager-page-visibility-cell'),
76 76
        url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/label$',
77 77
            views.page_get_additional_label, name='combo-manager-page-get-additional-label'),
78
        url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/add-link/(?P<link_code>[\w-]+)$',
79
            views.page_list_cell_add_link,
80
            name='combo-manager-page-list-cell-add-link'),
81
        url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/link/(?P<link_cell_reference>[\w_-]+)/$',
82
            views.page_list_cell_edit_link,
83
            name='combo-manager-page-list-cell-edit-link'),
84
        url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/link/(?P<link_cell_reference>[\w_-]+)/delete$',
85
            views.page_list_cell_delete_link,
86
            name='combo-manager-page-list-cell-delete-link'),
87
        url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/order$',
88
            views.link_list_order,
89
            name='combo-manager-link-list-order'),
78 90
        url(r'^pages/(?P<page_pk>\d+)/order$', views.cell_order,
79 91
            name='combo-manager-cell-order'),
80 92
        url(r'^pages/order$', views.page_order,
combo/manager/views.py
33 33
from django.views.generic import (RedirectView, DetailView,
34 34
        CreateView, UpdateView, ListView, DeleteView, FormView)
35 35

  
36
from combo.data.models import Page, CellBase, ParentContentCell, PageSnapshot
36
from combo.data.models import Page, CellBase, ParentContentCell, PageSnapshot, LinkListCell
37 37
from combo.data.library import get_cell_class
38 38
from combo.data.utils import export_site, import_site, MissingGroups
39 39
from combo import plugins
......
124 124
        return super(CreateView, self).get_initial()
125 125

  
126 126
    def dispatch(self, request, *args, **kwargs):
127
        print(request.POST)
128 127
        self.parent = get_object_or_404(Page, pk=kwargs['pk'])
129 128
        return super(PageAddChildView, self).dispatch(request, *args, **kwargs)
130 129

  
......
564 563
    response = HttpResponse(content_type=content_type)
565 564
    response.write(json_str)
566 565
    return response
566

  
567

  
568
class PageListCellAddLinkView(CreateView):
569
    template_name = 'combo/link_cell_form.html'
570

  
571
    def dispatch(self, request, *args, **kwargs):
572
        try:
573
            self.cell = CellBase.get_cell(kwargs['cell_reference'], page=kwargs['page_pk'])
574
        except LinkListCell.DoesNotExist:
575
            raise Http404
576
        for klass in self.cell.get_link_cell_classes():
577
            if klass.add_as_link_code == kwargs['link_code']:
578
                self.model = klass
579
                break
580
        if self.model is None:
581
            raise Http404
582
        return super(PageListCellAddLinkView, self).dispatch(request, *args, **kwargs)
583

  
584
    def get_form_class(self):
585
        return self.model().get_default_form_class()
586

  
587
    def get_form_kwargs(self):
588
        kwargs = super(PageListCellAddLinkView, self).get_form_kwargs()
589
        kwargs['instance'] = self.model(page=self.cell.page, placeholder=self.cell.link_placeholder)
590
        return kwargs
591

  
592
    def form_valid(self, form):
593
        orders = [x.order for x in self.cell.get_items()]
594
        if orders:
595
            form.instance.order = max(orders)+1
596
        else:
597
            form.instance.order = 1
598
        return super(PageListCellAddLinkView, self).form_valid(form)
599

  
600
    def get_success_url(self):
601
        return '%s#cell-%s' % (
602
            reverse('combo-manager-page-view', kwargs={'pk': self.kwargs.get('page_pk')}),
603
            self.kwargs['cell_reference'])
604

  
605

  
606
page_list_cell_add_link = PageListCellAddLinkView.as_view()
607

  
608

  
609
class PageListCellEditLinkView(UpdateView):
610
    template_name = 'combo/link_cell_form.html'
611

  
612
    def dispatch(self, request, *args, **kwargs):
613
        try:
614
            self.cell = CellBase.get_cell(kwargs['cell_reference'], page=kwargs['page_pk'])
615
        except LinkListCell.DoesNotExist:
616
            raise Http404
617
        try:
618
            self.object = CellBase.get_cell(kwargs['link_cell_reference'], page=kwargs['page_pk'])
619
        except ObjectDoesNotExist:
620
            raise Http404
621
        if self.object.placeholder != self.cell.link_placeholder:
622
            raise Http404
623
        self.model = self.object.__class__
624
        return super(PageListCellEditLinkView, self).dispatch(request, *args, **kwargs)
625

  
626
    def get_object(self, *args, **kwargs):
627
        return self.object
628

  
629
    def get_form_class(self):
630
        return self.model().get_default_form_class()
631

  
632
    def form_valid(self, form):
633
        if self.request.is_ajax():
634
            self.object = form.save()
635
            response = self.form_invalid(form)  # avoid redirection
636
        else:
637
            response = super(PageListCellEditLinkView, self).form_valid(form)
638
        PageSnapshot.take(self.cell.page, request=self.request, comment=_('changed cell "%s"') % self.cell)
639
        return response
640

  
641
    def get_success_url(self):
642
        return '%s#cell-%s' % (
643
            reverse('combo-manager-page-view', kwargs={'pk': self.kwargs.get('page_pk')}),
644
            self.kwargs['cell_reference'])
645

  
646

  
647
page_list_cell_edit_link = PageListCellEditLinkView.as_view()
648

  
649

  
650
class PageListCellDeleteLinkView(DeleteView):
651
    template_name = 'combo/generic_confirm_delete.html'
652

  
653
    def dispatch(self, request, *args, **kwargs):
654
        try:
655
            self.cell = CellBase.get_cell(kwargs['cell_reference'], page=kwargs['page_pk'])
656
        except LinkListCell.DoesNotExist:
657
            raise Http404
658
        try:
659
            self.object = CellBase.get_cell(kwargs['link_cell_reference'], page=kwargs['page_pk'])
660
        except ObjectDoesNotExist:
661
            raise Http404
662
        if self.object.placeholder != self.cell.link_placeholder:
663
            raise Http404
664
        self.model = self.object.__class__
665
        return super(PageListCellDeleteLinkView, self).dispatch(request, *args, **kwargs)
666

  
667
    def get_object(self, *args, **kwargs):
668
        return self.object
669

  
670
    def delete(self, request, *args, **kwargs):
671
        response = super(PageListCellDeleteLinkView, self).delete(request, *args, **kwargs)
672
        PageSnapshot.take(self.cell.page, request=self.request, comment=_('changed cell "%s"') % self.cell)
673
        return response
674

  
675
    def get_success_url(self):
676
        return '%s#cell-%s' % (
677
            reverse('combo-manager-page-view', kwargs={'pk': self.kwargs.get('page_pk')}),
678
            self.kwargs['cell_reference'])
679

  
680

  
681
page_list_cell_delete_link = PageListCellDeleteLinkView.as_view()
682

  
683

  
684
def link_list_order(request, page_pk, cell_reference):
685
    try:
686
        cell = CellBase.get_cell(cell_reference, page=page_pk)
687
    except LinkListCell.DoesNotExist:
688
        raise Http404
689

  
690
    has_changes = False
691
    for link in cell.get_items():
692
        old_order = link.order
693
        try:
694
            new_order = int(request.GET.get('pos_' + str(link.pk)))
695
        except TypeError:
696
            continue
697
        if new_order != old_order:
698
            link.order = new_order
699
            has_changes = True
700
            link.save(update_fields=['order'])
701

  
702
    if has_changes:
703
        PageSnapshot.take(cell.page, request=request, comment=_('reordered cells'))
704

  
705
    return HttpResponse(status=204)
combo/public/templates/combo/link-list-cell.html
1
{% block cell-content %}
2
{% spaceless %}
3
<div class="links-list">
4
  {% if title %}<h2>{{title}}</h2>{% endif %}
5
  <ul>
6
  {% for link in links %}
7
    <li><a href="{{ link.url }}">{{ link.title }}</a></li>
8
  {% endfor %}
9
  </ul>
10
</div>
11
{% endspaceless %}
12
{% endblock %}
tests/test_cells.py
4 4
import pytest
5 5
import requests
6 6

  
7
from combo.data.models import Page, CellBase, TextCell, LinkCell, MenuCell, JsonCellBase, JsonCell, ConfigJsonCell
7
from combo.data.models import (
8
    Page, CellBase, TextCell, LinkCell, MenuCell, JsonCellBase,
9
    JsonCell, ConfigJsonCell, LinkListCell
10
)
8 11
from django.conf import settings
9 12
from django.db import connection
10 13
from django.forms.widgets import Media
......
93 96
    assert 'href=""' in cell.render(ctx)
94 97
    assert 'href="/plop"' in cell.render(ctx)
95 98

  
99

  
96 100
def test_link_cell():
97 101
    page = Page(title='example page', slug='example-page')
98 102
    page.save()
......
130 134
    assert cell.render(ctx).strip() == '<a href="http://example.net/#anchor">altertitle</a>'
131 135

  
132 136

  
137
def test_link_list_cell():
138
    page = Page.objects.create(title='example page', slug='example-page')
139

  
140
    cell = LinkListCell.objects.create(order=0, page=page)
141
    item = LinkCell.objects.create(
142
        page=page,
143
        placeholder=cell.link_placeholder,
144
        title='Example Site',
145
        url='http://example.net/',
146
        order=0,
147
    )
148

  
149
    ctx = {'page_cells': [item]}
150
    assert '<ul><li><a href="http://example.net/">Example Site</a></li></ul>' in cell.render(ctx)
151

  
152
    item.title = ''
153
    assert '<ul><li><a href="http://example.net/">http://example.net/</a></li></ul>' in cell.render(ctx)
154

  
155
    item.link_page = page
156
    assert '<ul><li><a href="/example-page/">example page</a></li></ul>' in cell.render(ctx)
157

  
158
    item.title = 'altertitle'
159
    assert '<ul><li><a href="/example-page/">altertitle</a></li></ul>' in cell.render(ctx)
160

  
161
    item.anchor = 'anchor'
162
    assert '<ul><li><a href="/example-page/#anchor">altertitle</a></li></ul>' in cell.render(ctx)
163

  
164
    item.link_page = None
165
    assert '<ul><li><a href="http://example.net/#anchor">altertitle</a></li></ul>' in cell.render(ctx)
166

  
167

  
133 168
def test_menu_cell():
134 169
    Page.objects.all().delete()
135 170
    parent = page = Page(title='Page1', slug='page1', template_name='standard')
......
728 763

  
729 764
    TextCell(page=page, placeholder='content', order=0, text='hello').save()
730 765
    assert set(Page.objects.get(id=page.id).related_cells['cell_types']) == set(['data_textcell', 'data_linkcell'])
766

  
767

  
768
def test_link_list_cell_duplicate():
769
    page = Page.objects.create(title='xxx', slug='new', template_name='standard')
770
    cell = LinkListCell.objects.create(order=0, page=page)
771
    item = LinkCell.objects.create(
772
        page=page,
773
        placeholder=cell.link_placeholder,
774
        title='Example Site',
775
        url='http://example.net/',
776
        link_page=page,
777
        order=1,
778
    )
779

  
780
    new_cell = cell.duplicate()
781
    assert LinkCell.objects.count() == 2
782
    assert len(new_cell.get_items()) == 1
783
    new_item = new_cell.get_items()[0]
784
    assert new_item.page == page
785
    assert new_item.placeholder == new_cell.link_placeholder
786
    assert new_item.pk != item.pk
787
    assert new_item.title == item.title
788
    assert new_item.url == item.url
789
    assert new_item.link_page == item.link_page
tests/test_manager.py
21 21
from webtest import Upload
22 22

  
23 23
from combo.wsgi import application
24
from combo.data.models import Page, CellBase, TextCell, LinkCell, ConfigJsonCell, JsonCell, PageSnapshot
24
from combo.data.models import Page, CellBase, TextCell, LinkCell, ConfigJsonCell, JsonCell, PageSnapshot, LinkListCell
25 25
from combo.apps.assets.models import Asset
26 26
from combo.apps.family.models import FamilyInfosCell
27 27
from combo.apps.search.models import SearchCell
......
1373 1373
    assert 'syntax error' not in resp.text
1374 1374
    assert JsonCell.objects.count() == 1
1375 1375
    assert JsonCell.objects.first().template_string == '{{ ok }}'
1376

  
1377

  
1378
def test_add_edit_delete_list_link_item(app, admin_user):
1379
    Page.objects.all().delete()
1380
    page = Page.objects.create(title='One', slug='one', template_name='standard')
1381
    cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
1382
    app = login(app)
1383
    resp = app.get('/manage/pages/%s/' % page.pk)
1384

  
1385
    resp = resp.click(href='.*/add-link/link$')
1386
    resp.forms[0]['title'] = 'Hello world'
1387
    resp.forms[0]['url'] = 'http://example.com'
1388
    resp = resp.forms[0].submit()
1389
    assert resp.status_int == 302
1390
    assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
1391
    assert LinkCell.objects.count() == 1
1392
    item = LinkCell.objects.get()
1393
    assert item.title == 'Hello world'
1394
    assert item.url == 'http://example.com'
1395
    assert item.page == page
1396
    assert item.placeholder == cell.link_placeholder
1397

  
1398
    resp = resp.follow()
1399
    resp = resp.click(href='.*/link/%s/$' % item.get_reference())
1400
    resp.forms[0]['title'] = 'Hello world 2'
1401
    resp.forms[0]['url'] = 'http://example2.com'
1402
    resp = resp.forms[0].submit()
1403
    assert resp.status_int == 302
1404
    assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
1405
    assert LinkCell.objects.count() == 1
1406
    item.refresh_from_db()
1407
    assert item.title == 'Hello world 2'
1408
    assert item.url == 'http://example2.com'
1409

  
1410
    resp = resp.follow()
1411
    resp = resp.click(href='.*/link/%s/delete' % item.get_reference())
1412
    resp = resp.forms[0].submit()
1413
    assert resp.status_int == 302
1414
    assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
1415
    assert LinkCell.objects.count() == 0
1416

  
1417

  
1418
def test_edit_link_list_order(app, admin_user):
1419
    Page.objects.all().delete()
1420
    page = Page.objects.create(title='One', slug='one', template_name='standard')
1421
    cell = LinkListCell.objects.create(order=0, page=page)
1422
    items = []
1423
    for i in range(5):
1424
        items.append(
1425
            LinkCell.objects.create(
1426
                page=page,
1427
                placeholder=cell.link_placeholder,
1428
                title='Foo %s' % i,
1429
                url='http://example.net/',
1430
                link_page=page,
1431
                order=i+1,
1432
            )
1433
        )
1434

  
1435
    params = []
1436
    new_order = [2, 3, 1, 4, 5]
1437
    for i, (item, new_pos) in enumerate(zip(items, new_order)):
1438
        params.append(('pos_%s' % item.pk, str(new_pos)))
1439

  
1440
    app = login(app)
1441
    resp = app.get('/manage/pages/%s/cell/%s/order?%s' % (page.pk, cell.get_reference(), urlencode(params)))
1442
    assert resp.status_code == 204
1443
    for i, item in enumerate(items):
1444
        item.refresh_from_db()
1445
        assert item.order == new_order[i]
tests/test_pages.py
9 9
from django.test.client import RequestFactory
10 10
from django.utils.six import StringIO
11 11
from django.utils.timezone import now
12
from combo.data.models import Page, PageSnapshot, CellBase, TextCell, LinkCell
12
from combo.data.models import Page, PageSnapshot, CellBase, TextCell, LinkCell, LinkListCell
13 13
from combo.data.management.commands.import_site import Command as ImportSiteCommand
14 14
from combo.data.management.commands.export_site import Command as ExportSiteCommand
15 15
from combo.manager.forms import PageVisibilityForm
......
182 182
    cell2 = LinkCell(page=page2, title='foo', placeholder='content', link_page=page, order=1)
183 183
    cell2.save()
184 184

  
185
    cell3 = LinkListCell.objects.create(page=page, placeholder='content', order=2)
186
    item1 = LinkCell.objects.create(
187
        page=page,
188
        placeholder=cell3.link_placeholder,
189
        title='Example Site',
190
        url='http://example.net/',
191
        order=0,
192
    )
193
    item2 = LinkCell.objects.create(
194
        page=page,
195
        placeholder=cell3.link_placeholder,
196
        title='blah',
197
        link_page=page2,
198
        order=1,
199
    )
200

  
185 201
    site_export = [x.get_serialized_page() for x in Page.objects.all()]
186 202
    Page.objects.all().delete()
187 203

  
......
189 205

  
190 206
    new_page_1 = Page.objects.all().order_by('order')[0]
191 207
    new_page_2 = Page.objects.all().order_by('order')[1]
192
    assert CellBase.get_cells(page_id=new_page_1.id)[0].link_page_id == new_page_2.id
193
    assert CellBase.get_cells(page_id=new_page_2.id)[0].link_page_id == new_page_1.id
208
    new_cells_1 = CellBase.get_cells(page_id=new_page_1.id, placeholder='content')
209
    new_cells_2 = CellBase.get_cells(page_id=new_page_2.id, placeholder='content')
210
    assert new_cells_1[0].link_page_id == new_page_2.id
211
    assert new_cells_2[0].link_page_id == new_page_1.id
212
    assert len(new_cells_1[1].get_items()) == 2
213
    new_item_1 = new_cells_1[1].get_items()[0]
214
    assert isinstance(new_item_1, LinkCell)
215
    assert new_item_1.title == item1.title
216
    assert new_item_1.url == item1.url
217
    assert new_item_1.link_page is None
218
    new_item_2 = new_cells_1[1].get_items()[1]
219
    assert isinstance(new_item_2, LinkCell)
220
    assert new_item_2.title == item2.title
221
    assert new_item_2.url == ''
222
    assert new_item_2.link_page == new_page_2
194 223

  
195 224

  
196 225
def test_duplicate_page():
tests/test_wcs.py
22 22

  
23 23
import mock
24 24

  
25
from combo.data.models import Page
25
from combo.data.models import CellBase, LinkListCell, Page
26 26
from combo.apps.search.engines import engines
27 27
from combo.apps.wcs.models import (WcsFormCell, WcsCurrentFormsCell,
28 28
        WcsFormsOfCategoryCell, WcsCurrentDraftsCell, WcsCategoryCell,
......
901 901

  
902 902
    result = cell.render(context)
903 903
    assert '/backoffice/submission/a-private-form/' in result
904

  
905

  
906
@wcs_present
907
def test_manager_link_list_cell_duplicate():
908
    page = Page.objects.create(title='xxx', slug='new', template_name='standard')
909
    cell = LinkListCell.objects.create(order=0, page=page)
910
    item = WcsFormCell.objects.create(
911
        page=page,
912
        placeholder=cell.link_placeholder,
913
        cached_title='A title',
914
        cached_url='http://example.com',
915
        cached_json={'foo': 'bar'},
916
        order=1)
917

  
918
    new_cell = cell.duplicate()
919
    assert WcsFormCell.objects.count() == 2
920
    assert len(new_cell.get_items()) == 1
921
    new_item = new_cell.get_items()[0]
922
    assert new_item.page == page
923
    assert new_item.placeholder == new_cell.link_placeholder
924
    assert new_item.pk != item.pk
925
    assert new_item.cached_title == item.cached_title
926
    assert new_item.cached_url == item.cached_url
927
    assert new_item.cached_json == item.cached_json
928

  
929

  
930
@wcs_present
931
def test_manager_add_edit_delete_list_link_item(app, admin_user):
932
    Page.objects.all().delete()
933
    page = Page.objects.create(title='One', slug='one', template_name='standard')
934
    cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
935
    app = login(app)
936
    resp = app.get('/manage/pages/%s/' % page.pk)
937

  
938
    resp = resp.click(href='.*/add-link/form-link$')
939
    resp.forms[0]['formdef_reference'] = 'default:form-title'
940
    resp = resp.forms[0].submit()
941
    assert resp.status_int == 302
942
    assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
943
    assert WcsFormCell.objects.count() == 1
944
    item = WcsFormCell.objects.get()
945
    assert item.formdef_reference == 'default:form-title'
946
    assert item.page == page
947
    assert item.placeholder == cell.link_placeholder
948

  
949
    resp = resp.follow()
950
    resp = resp.click(href='.*/link/%s/$' % item.get_reference())
951
    resp.forms[0]['formdef_reference'] = 'default:a-private-form'
952
    resp = resp.forms[0].submit()
953
    assert resp.status_int == 302
954
    assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
955
    assert WcsFormCell.objects.count() == 1
956
    item.refresh_from_db()
957
    assert item.formdef_reference == 'default:a-private-form'
958

  
959
    resp = resp.follow()
960
    resp = resp.click(href='.*/link/%s/delete' % item.get_reference())
961
    resp = resp.forms[0].submit()
962
    assert resp.status_int == 302
963
    assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
964
    assert WcsFormCell.objects.count() == 0
965

  
966

  
967
def test_import_export_pages_with_links():
968
    page = Page(title=u'bar', slug='bar', order=1)
969
    page.save()
970

  
971
    cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
972
    item = WcsFormCell.objects.create(
973
        page=page,
974
        placeholder=cell.link_placeholder,
975
        cached_title='A title',
976
        cached_url='http://example.com',
977
        cached_json={'foo': 'bar'},
978
        order=0,
979
    )
980

  
981
    site_export = [x.get_serialized_page() for x in Page.objects.all()]
982
    Page.objects.all().delete()
983

  
984
    Page.load_serialized_pages(site_export)
985

  
986
    new_page = Page.objects.get()
987
    new_cells = CellBase.get_cells(page_id=new_page.id, placeholder='content')
988
    assert len(new_cells[0].get_items()) == 1
989
    new_item = new_cells[0].get_items()[0]
990
    assert isinstance(new_item, WcsFormCell)
991
    assert new_item.cached_title == item.cached_title
992
    assert new_item.cached_url == item.cached_url
993
    assert new_item.cached_json == item.cached_json
904
-