7

Merge branch 'simplifications+optimisations' of github.com:LabD/wagtail-personalisation into simplifications+optimisations

This commit is contained in:
Bertrand Bordage
2017-05-31 17:43:18 +02:00
13 changed files with 435 additions and 23 deletions

View File

@ -1,7 +1,7 @@
.. start-no-pypi .. start-no-pypi
.. image:: https://readthedocs.org/projects/wagtail-personalisation/badge/?version=latest .. image:: https://readthedocs.org/projects/wagtail-personalisation/badge/?version=latest
:target: https://readthedocs.org/projects/wagtail-personalisation/ :target: http://wagtail-personalisation.readthedocs.io/en/latest/?badge=latest
.. image:: https://travis-ci.org/LabD/wagtail-personalisation.svg?branch=master .. image:: https://travis-ci.org/LabD/wagtail-personalisation.svg?branch=master
:target: https://travis-ci.org/LabD/wagtail-personalisation :target: https://travis-ci.org/LabD/wagtail-personalisation

View File

@ -0,0 +1,352 @@
# Wagtail Personalisation english translation strings.
# Copyright (C) 2017 Lab Digital B.V.
# This file is distributed under the same license as the wagtail_personalisation package.
# Boris Besemer <b.besemer@labdigital.nl>, 2017.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: wagtail_personalisation 0.1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-31 09:30-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: blocks.py:20
msgid "Personalisation segment"
msgstr ""
#: blocks.py:21
msgid "Only show this content block for users in this segment"
msgstr ""
#: config.py:8
msgid "Wagtail Personalisation"
msgstr ""
#: models.py:26
msgid "Enabled"
msgstr ""
#: models.py:27
msgid "Disabled"
msgstr ""
#: models.py:39
msgid "Should the segment persist between visits?"
msgstr ""
#: models.py:42
msgid "Should the segment match all the rules or just one of them?"
msgstr ""
#: models.py:60
msgid "Rules"
msgstr ""
#: models.py:167
msgid "Content"
msgstr ""
#: models.py:169
msgid "Variations"
msgstr ""
#: models.py:171
msgid "Promote"
msgstr ""
#: models.py:173
msgid "Settings"
msgstr ""
#: rules.py:29 rules.py:48
msgid "Abstract segmentation rule"
msgstr ""
#: rules.py:63
msgid "Starting time"
msgstr ""
#: rules.py:64
msgid "Ending time"
msgstr ""
#: rules.py:74
msgid "Time Rule"
msgstr ""
#: rules.py:85
msgid "These users visit between"
msgstr ""
#: rules.py:86
msgid "{} and {}"
msgstr ""
#: rules.py:103
msgid "Monday"
msgstr ""
#: rules.py:104
msgid "Tuesday"
msgstr ""
#: rules.py:105
msgid "Wednesday"
msgstr ""
#: rules.py:106
msgid "Thursday"
msgstr ""
#: rules.py:107
msgid "Friday"
msgstr ""
#: rules.py:108
msgid "Saturday"
msgstr ""
#: rules.py:109
msgid "Sunday"
msgstr ""
#: rules.py:122
msgid "Day Rule"
msgstr ""
#: rules.py:146
msgid "These users visit on"
msgstr ""
#: rules.py:162
msgid "Regular expression to match the referrer"
msgstr ""
#: rules.py:169
msgid "Referral Rule"
msgstr ""
#: rules.py:182
msgid "These visits originate from"
msgstr ""
#: rules.py:183 rules.py:366
msgid "{}"
msgstr ""
#: rules.py:202
msgid "More than"
msgstr ""
#: rules.py:203
msgid "Less than"
msgstr ""
#: rules.py:204
msgid "Equal to"
msgstr ""
#: rules.py:247
msgid "Visit count Rule"
msgstr ""
#: rules.py:251
msgid "These users visited {}"
msgstr ""
#: rules.py:254
msgid "{} {} times"
msgstr ""
#: rules.py:271
msgid "The query parameter to search for"
msgstr ""
#: rules.py:273
msgid "The value of the parameter to match"
msgstr ""
#: rules.py:282
msgid "Query Rule"
msgstr ""
#: rules.py:293
msgid "These users used a URL with the query"
msgstr ""
#: rules.py:294
msgid "?{}={}"
msgstr ""
#: rules.py:312
msgid "Mobile phone"
msgstr ""
#: rules.py:313
msgid "Tablet"
msgstr ""
#: rules.py:314
msgid "Desktop"
msgstr ""
#: rules.py:323
msgid "Device Rule"
msgstr ""
#: rules.py:354
msgid "Logged in Rule"
msgstr ""
#: rules.py:360
msgid "Logged in"
msgstr ""
#: rules.py:362
msgid "Not logged in"
msgstr ""
#: rules.py:365
msgid "These visitors are"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/base.html:28
msgid "Switch view"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:14
#: templates/modeladmin/wagtail_personalisation/segment/index.html:14
msgid "Filter"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:30
msgid "This segment has been visited"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:31
msgid "time"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:34
msgid "This segment has been active for"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:35
msgid "day"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:43
msgid "The visitor must match"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:45
msgid "Any rule"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:47
msgid "All rules"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:52
msgid "The persistence of this segment is"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:54
msgid "This segment persists in between visits"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:54
msgid "Persistent"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:56
msgid "This segment is re-evaluated on every visit"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:56
msgid "Fleeting"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:76
msgid "Enable this segment"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:78
msgid "Disable this segment"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:80
msgid "Configure this segment"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:88
#, python-format
msgid ""
"\n"
" <a class=\"block suggestion\" href="
"\"%(url)s\">\n"
" <span class=\"suggestive_text\">Add "
"a new %(name)s</span>\n"
" </a>\n"
" "
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/dashboard.html:101
#: templates/modeladmin/wagtail_personalisation/segment/index.html:45
#, python-format
msgid "Page %(current_page)s of %(num_pages)s."
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/index.html:24
#, python-format
msgid ""
"No %(name)s have been created yet. One of the following must be created "
"before you can add any %(name)s:"
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/index.html:29
#, python-format
msgid "No %(name)s have been created yet."
msgstr ""
#: templates/modeladmin/wagtail_personalisation/segment/index.html:31
#, python-format
msgid ""
"\n"
" Why not <a href=\"%(url)s\">add "
"one</a>?\n"
" "
msgstr ""
#: views.py:60
#, python-brace-format
msgid "{visits} visits"
msgstr ""
#: views.py:63
#, python-brace-format
msgid "{days} days"
msgstr ""
#: wagtail_hooks.py:121
msgid "Variants"
msgstr ""
#: wagtail_hooks.py:126
msgid "Create a new variant"
msgstr ""
#: wagtail_hooks.py:146
msgid "Create this variant"
msgstr ""
#: wagtail_hooks.py:159
msgid "Segments"
msgstr ""

View File

@ -28,8 +28,8 @@ class Segment(ClusterableModel):
STATUS_DISABLED = 'disabled' STATUS_DISABLED = 'disabled'
STATUS_CHOICES = ( STATUS_CHOICES = (
(STATUS_ENABLED, 'Enabled'), (STATUS_ENABLED, _('Enabled')),
(STATUS_DISABLED, 'Disabled'), (STATUS_DISABLED, _('Disabled')),
) )
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
@ -64,7 +64,7 @@ class Segment(ClusterableModel):
"{}_related".format(rule_model._meta.db_table), "{}_related".format(rule_model._meta.db_table),
label=rule_model._meta.verbose_name, label=rule_model._meta.verbose_name,
) for rule_model in AbstractBaseRule.__subclasses__() ) for rule_model in AbstractBaseRule.__subclasses__()
], heading="Rules"), ], heading=_("Rules")),
] ]
super(Segment, self).__init__(*args, **kwargs) super(Segment, self).__init__(*args, **kwargs)

View File

@ -47,7 +47,7 @@ class AbstractBaseRule(models.Model):
""" """
description = { description = {
'title': _('Abstract segmentation rule'), 'title': _('Abstract segmentation rule'),
'value': _(''), 'value': '',
} }
return description return description
@ -150,7 +150,7 @@ class ReferralRule(AbstractBaseRule):
""" """
regex_string = models.TextField( regex_string = models.TextField(
_("Regex string to match the referer with")) _("Regular expression to match the referrer"))
panels = [ panels = [
FieldPanel('regex_string'), FieldPanel('regex_string'),
@ -269,7 +269,7 @@ class QueryRule(AbstractBaseRule):
def description(self): def description(self):
return { return {
'title': _('These users used a url with the query'), 'title': _('These users used a URL with the query'),
'value': _('?{}={}').format( 'value': _('?{}={}').format(
self.parameter, self.parameter,
self.value self.value
@ -325,7 +325,7 @@ class UserIsLoggedInRule(AbstractBaseRule):
] ]
class Meta: class Meta:
verbose_name = _('Logged In Rule') verbose_name = _('Logged in Rule')
def test_user(self, request=None): def test_user(self, request=None):
return request.user.is_authenticated() == self.is_logged_in return request.user.is_authenticated() == self.is_logged_in

View File

@ -27,7 +27,7 @@
<div class="inspect_container"> <div class="inspect_container">
<ul class="inspect segment_stats"> <ul class="inspect segment_stats">
<li class="visit_stat"> <li class="visit_stat">
{% trans "This segmented has been visited" %} {% trans "This segment has been visited" %}
<span>{{ segment.visit_count|localize }} {% trans "time" %}{{ segment.visit_count|pluralize }}</span> <span>{{ segment.visit_count|localize }} {% trans "time" %}{{ segment.visit_count|pluralize }}</span>
</li> </li>
<li class="days_stat"> <li class="days_stat">
@ -53,7 +53,7 @@
{% if segment.persistent %} {% if segment.persistent %}
<span title="{% trans "This segment persists in between visits" %}">{% trans "Persistent" %}</span> <span title="{% trans "This segment persists in between visits" %}">{% trans "Persistent" %}</span>
{% else %} {% else %}
<span title="{% trans "This segment is reevaluated on every visit" %}">{% trans "Fleeting" %}</span> <span title="{% trans "This segment is re-evaluated on every visit" %}">{% trans "Fleeting" %}</span>
{% endif %} {% endif %}
</li> </li>

View File

@ -16,7 +16,6 @@
</div> </div>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
<div class="result-list {% if view.has_filters and all_count %}col9{% else %}col12{% endif %}"> <div class="result-list {% if view.has_filters and all_count %}col9{% else %}col12{% endif %}">
{% block result_list %} {% block result_list %}
{% if not all_count %} {% if not all_count %}

View File

@ -4,12 +4,20 @@ import factory
from django.utils.text import slugify from django.utils.text import slugify
from wagtail_factories.factories import MP_NodeFactory from wagtail_factories.factories import MP_NodeFactory
from tests.sandbox.pages.models import HomePage from tests.sandbox.pages.models import HomePage, SpecialPage
class PageFactory(MP_NodeFactory): class HomePageFactory(MP_NodeFactory):
title = 'Test page' title = 'Test page'
slug = factory.LazyAttribute(lambda obj: slugify(obj.title)) slug = factory.LazyAttribute(lambda obj: slugify(obj.title))
class Meta: class Meta:
model = HomePage model = HomePage
class SpecialPageFactory(MP_NodeFactory):
title = 'Test page'
slug = factory.LazyAttribute(lambda obj: slugify(obj.title))
class Meta:
model = SpecialPage

View File

@ -1,14 +1,14 @@
import factory import factory
from wagtail.wagtailcore.models import Site from wagtail.wagtailcore.models import Site
from tests.factories.page import PageFactory from tests.factories.page import HomePageFactory
class SiteFactory(factory.DjangoModelFactory): class SiteFactory(factory.DjangoModelFactory):
hostname = 'localhost' hostname = 'localhost'
port = factory.Sequence(lambda n: 81 + n) port = factory.Sequence(lambda n: 81 + n)
site_name = 'Test site' site_name = 'Test site'
root_page = factory.SubFactory(PageFactory, parent=None) root_page = factory.SubFactory(HomePageFactory, parent=None)
is_default_site = False is_default_site = False
class Meta: class Meta:

View File

@ -1,10 +1,10 @@
import pytest import pytest
from django.contrib.auth.models import AnonymousUser from django.contrib.auth.models import AnonymousUser
from django.contrib.messages.storage.fallback import FallbackStorage from django.contrib.messages.storage.fallback import FallbackStorage
from django.contrib.sessions.backends.db import SessionStore from django.contrib.sessions.backends.db import SessionStore
from django.test.client import RequestFactory as BaseRequestFactory from django.test.client import RequestFactory as BaseRequestFactory
from tests.factories.page import PageFactory
from tests.factories.page import HomePageFactory, SpecialPageFactory
from tests.factories.segment import SegmentFactory from tests.factories.segment import SegmentFactory
from tests.factories.site import SiteFactory from tests.factories.site import SiteFactory
@ -12,14 +12,16 @@ from tests.factories.site import SiteFactory
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def site(): def site():
site = SiteFactory(is_default_site=True) site = SiteFactory(is_default_site=True)
PageFactory(parent=site.root_page, slug='page-1') page1 = HomePageFactory(parent=site.root_page, slug='page-1')
PageFactory(parent=site.root_page, slug='page-2') page2 = HomePageFactory(parent=site.root_page, slug='page-2')
SpecialPageFactory(parent=page1, slug='page-1-1')
SpecialPageFactory(parent=page2, slug='page-2-1')
return site return site
@pytest.fixture @pytest.fixture
def segmented_page(site): def segmented_page(site):
page = PageFactory(parent=site.root_page) page = HomePageFactory(parent=site.root_page)
segment = SegmentFactory() segment = SegmentFactory()
return page.copy_for_segment(segment) return page.copy_for_segment(segment)

View File

@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.1 on 2017-05-31 09:15
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import wagtail.wagtailcore.fields
class Migration(migrations.Migration):
dependencies = [
('wagtail_personalisation', '0009_auto_20170531_0428'),
('wagtailcore', '0033_remove_golive_expiry_help_text'),
('pages', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='SpecialPage',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
('is_segmented', models.BooleanField(default=False)),
('subtitle', models.CharField(blank=True, default='', max_length=255)),
('body', wagtail.wagtailcore.fields.RichTextField(blank=True, default='')),
('special', wagtail.wagtailcore.fields.RichTextField(blank=True, default='')),
('canonical_page', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='variations', to='pages.SpecialPage')),
('segment', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='wagtail_personalisation.Segment')),
],
options={
'abstract': False,
},
bases=('wagtailcore.page', models.Model),
),
migrations.AlterField(
model_name='homepage',
name='segment',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='wagtail_personalisation.Segment'),
),
]

View File

@ -16,3 +16,15 @@ class HomePage(PersonalisablePageMixin, Page):
FieldPanel('subtitle'), FieldPanel('subtitle'),
FieldPanel('body'), FieldPanel('body'),
] ]
class SpecialPage(PersonalisablePageMixin, Page):
subtitle = models.CharField(max_length=255, blank=True, default='')
body = RichTextField(blank=True, default='')
special = RichTextField(blank=True, default='')
content_panels = Page.content_panels + [
FieldPanel('subtitle'),
FieldPanel('body'),
FieldPanel('special'),
]

View File

@ -4,11 +4,11 @@ import datetime
import pytest import pytest
from tests.factories.page import HomePageFactory
from tests.factories.rule import ( from tests.factories.rule import (
DayRuleFactory, DeviceRuleFactory, ReferralRuleFactory, TimeRuleFactory) DayRuleFactory, DeviceRuleFactory, ReferralRuleFactory, TimeRuleFactory)
from tests.factories.segment import SegmentFactory from tests.factories.segment import SegmentFactory
from tests.factories.site import SiteFactory from tests.factories.site import SiteFactory
from tests.factories.page import PageFactory
from wagtail_personalisation.models import Segment from wagtail_personalisation.models import Segment
from wagtail_personalisation.rules import TimeRule from wagtail_personalisation.rules import TimeRule
@ -98,5 +98,5 @@ def test_site_factory():
def test_page_factory(): def test_page_factory():
site = SiteFactory() site = SiteFactory()
assert site.root_page assert site.root_page
page = PageFactory(parent=site.root_page) page = HomePageFactory(parent=site.root_page)
assert page.get_parent() == site.root_page assert page.get_parent() == site.root_page

View File

@ -5,7 +5,6 @@ import datetime
import pytest import pytest
from freezegun import freeze_time from freezegun import freeze_time
from tests.factories.page import PageFactory
from tests.factories.rule import ( from tests.factories.rule import (
DayRuleFactory, DeviceRuleFactory, QueryRuleFactory, ReferralRuleFactory, DayRuleFactory, DeviceRuleFactory, QueryRuleFactory, ReferralRuleFactory,
TimeRuleFactory, VisitCountRuleFactory) TimeRuleFactory, VisitCountRuleFactory)