cells: display invalidity date or delay (#43605)
This commit is contained in:
parent
6d332a9ca5
commit
4a62897422
|
@ -547,6 +547,12 @@ class ValidityInfo(models.Model):
|
|||
class Meta:
|
||||
unique_together = [('content_type', 'object_id')]
|
||||
|
||||
@property
|
||||
def invalid_datetime(self):
|
||||
if not self.invalid_since:
|
||||
return
|
||||
return self.invalid_since + datetime.timedelta(days=2)
|
||||
|
||||
|
||||
class CellMeta(MediaDefiningClass, ModelBase):
|
||||
pass
|
||||
|
@ -917,7 +923,7 @@ class CellBase(six.with_metaclass(CellMeta, models.Model)):
|
|||
def is_visible(self, user=None, check_validity_info=True):
|
||||
if check_validity_info:
|
||||
validity_info = self.get_validity_info()
|
||||
if validity_info is not None and validity_info.invalid_since and validity_info.invalid_since < now() - datetime.timedelta(days=2):
|
||||
if validity_info is not None and validity_info.invalid_datetime and validity_info.invalid_datetime <= now():
|
||||
return False
|
||||
return element_is_visible(self, user=user)
|
||||
|
||||
|
|
|
@ -150,11 +150,15 @@
|
|||
<span class="extra-css-class">[{{ cell.extra_css_class }}]</span>
|
||||
{% endif %}
|
||||
<span class="additional-label"><i>{{cell.get_additional_label|default_if_none:""}}</i></span>
|
||||
{% with cell.get_invalid_reason as invalid_reason %}
|
||||
{% if invalid_reason %}
|
||||
<span class="invalid">{{ invalid_reason }}</span>
|
||||
{% if cell.get_invalid_reason %}
|
||||
<span class="invalid">{{ cell.get_invalid_reason }} -
|
||||
{% if cell.get_validity_info.invalid_datetime|date_in_past %}
|
||||
{% blocktrans with cell.get_validity_info.invalid_datetime|date:"DATETIME_FORMAT" as invalidity_date %}This cell is no longer displayed since {{ invalidity_date }}.{% endblocktrans %}
|
||||
{% else %}
|
||||
{% blocktrans with cell.get_validity_info.invalid_datetime|timeuntil as invalidity_delay %}This cell will no longer be displayed in {{ invalidity_delay }}.{% endblocktrans %}
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</span>
|
||||
{% if not cell.public %}
|
||||
<span class="visibility-summary
|
||||
|
|
|
@ -25,7 +25,6 @@ import math
|
|||
import time
|
||||
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
from django.core import signing
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
|
@ -43,6 +42,7 @@ from django.utils import dateparse, six
|
|||
from django.utils.encoding import force_text
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.timezone import now
|
||||
|
||||
from combo.data.models import Page, Placeholder
|
||||
from combo.public.menu import get_menu_context
|
||||
|
@ -450,6 +450,16 @@ def age_in_months(value, today=None):
|
|||
return ''
|
||||
return years * 12 + months
|
||||
|
||||
|
||||
@register.filter(expects_localtime=True)
|
||||
def date_in_past(value):
|
||||
value = parse_datetime(value)
|
||||
try:
|
||||
return value <= now()
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
|
||||
def parse_decimal(value, default=Decimal(0)):
|
||||
if isinstance(value, six.string_types):
|
||||
# replace , by . for French users comfort
|
||||
|
|
|
@ -13,7 +13,6 @@ from django.apps import apps
|
|||
from django.conf import settings
|
||||
from django.db import connection
|
||||
from django.forms.widgets import Media
|
||||
from django.template import Context
|
||||
from django.test import override_settings
|
||||
from django.test.client import RequestFactory
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
|
@ -1127,6 +1126,28 @@ def test_cell_is_visible():
|
|||
assert cell.is_visible() is False
|
||||
|
||||
|
||||
def test_cell_invalidity_marker():
|
||||
page = Page.objects.create()
|
||||
cell = TextCell.objects.create(page=page, order=0)
|
||||
cell.mark_as_invalid('foo_bar_reason')
|
||||
validity_info = ValidityInfo.objects.latest('pk')
|
||||
old_reason = validity_info.invalid_reason_code
|
||||
old_date = validity_info.invalid_since
|
||||
|
||||
cell.mark_as_invalid('another_foo_bar_reason', force=False)
|
||||
validity_info.refresh_from_db()
|
||||
assert old_reason == validity_info.invalid_reason_code
|
||||
assert old_date == validity_info.invalid_since
|
||||
|
||||
cell.mark_as_invalid('another_foo_bar_reason')
|
||||
validity_info.refresh_from_db()
|
||||
assert validity_info.invalid_reason_code == 'another_foo_bar_reason'
|
||||
assert old_date < validity_info.invalid_since
|
||||
|
||||
cell.mark_as_valid()
|
||||
assert ValidityInfo.objects.exists() is False
|
||||
|
||||
|
||||
def test_hourly():
|
||||
appconfig = apps.get_app_config('data')
|
||||
page = Page.objects.create(title='xxx', slug='test_current_forms_cell_render', template_name='standard')
|
||||
|
|
|
@ -1,29 +1,27 @@
|
|||
import base64
|
||||
import json
|
||||
import datetime
|
||||
import mock
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
|
||||
import mock
|
||||
|
||||
from django.core.files.storage import default_storage
|
||||
from django.urls import reverse
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.contrib.auth.models import Group
|
||||
from django.db import connection
|
||||
from django.template import TemplateSyntaxError
|
||||
from django.test import override_settings
|
||||
from django.test.client import RequestFactory
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.timezone import now
|
||||
from django.utils.six import BytesIO
|
||||
from django.utils.six.moves.urllib import parse as urlparse
|
||||
|
||||
import pytest
|
||||
from webtest import TestApp
|
||||
from webtest import Upload
|
||||
|
||||
from combo.wsgi import application
|
||||
from combo.data.forms import LinkCellForm
|
||||
from combo.data.models import (
|
||||
Page, CellBase, TextCell, LinkCell, ConfigJsonCell, JsonCell, PageSnapshot,
|
||||
|
@ -169,39 +167,50 @@ def test_edit_page(app, admin_user):
|
|||
assert Page.objects.all()[0].exclude_from_navigation is False
|
||||
|
||||
|
||||
def test_edit_page_cell_invalid_placeholder(app, admin_user):
|
||||
def test_edit_page_cell_invalid_placeholder(freezer, app, admin_user):
|
||||
freezer.move_to('2020-06-05 12:00:01')
|
||||
page = Page.objects.create(title='One', slug='one', template_name='standard')
|
||||
cell = TextCell.objects.create(page=page, placeholder='content', text='Foobar', order=1)
|
||||
cell.mark_as_invalid('foo_bar_reason')
|
||||
validity_info = ValidityInfo.objects.latest('pk')
|
||||
old_reason = validity_info.invalid_reason_code
|
||||
old_date = validity_info.invalid_since
|
||||
|
||||
app = login(app)
|
||||
ValidityInfo.objects.update(invalid_since=now() - datetime.timedelta(minutes=1))
|
||||
resp = app.get('/manage/pages/%s/' % page.pk)
|
||||
assert '<span class="invalid">foo_bar_reason</span>' in resp.text
|
||||
assert '<span class="invalid">foo_bar_reason' in resp.text
|
||||
assert 'This cell will no longer be displayed in 1 day, 23 hours' in resp.text
|
||||
|
||||
cell.mark_as_invalid('another_foo_bar_reason', force=False)
|
||||
validity_info.refresh_from_db()
|
||||
assert old_reason == validity_info.invalid_reason_code
|
||||
assert old_date == validity_info.invalid_since
|
||||
ValidityInfo.objects.update(invalid_since=now() - datetime.timedelta(minutes=47*60-1))
|
||||
resp = app.get('/manage/pages/%s/' % page.pk)
|
||||
assert '<span class="invalid">foo_bar_reason' in resp.text
|
||||
assert 'This cell will no longer be displayed in 1 hour, 1 minute.' in resp.text
|
||||
|
||||
cell.mark_as_invalid('another_foo_bar_reason')
|
||||
validity_info.refresh_from_db()
|
||||
assert validity_info.invalid_reason_code == 'another_foo_bar_reason'
|
||||
assert old_date < validity_info.invalid_since
|
||||
ValidityInfo.objects.update(invalid_since=now() - datetime.timedelta(minutes=47*60+29))
|
||||
resp = app.get('/manage/pages/%s/' % page.pk)
|
||||
assert '<span class="invalid">foo_bar_reason' in resp.text
|
||||
assert 'This cell will no longer be displayed in 31 minutes.' in resp.text
|
||||
|
||||
ValidityInfo.objects.update(invalid_since=now() - datetime.timedelta(days=2))
|
||||
resp = app.get('/manage/pages/%s/' % page.pk)
|
||||
assert '<span class="invalid">foo_bar_reason' in resp.text
|
||||
assert 'This cell is no longer displayed since June 5, 2020, noon.' in resp.text
|
||||
|
||||
ValidityInfo.objects.update(invalid_since=now() - datetime.timedelta(days=2, minutes=10*60+2))
|
||||
resp = app.get('/manage/pages/%s/' % page.pk)
|
||||
assert '<span class="invalid">foo_bar_reason' in resp.text
|
||||
assert 'This cell is no longer displayed since June 5, 2020, 1:58 a.m.' in resp.text
|
||||
|
||||
cell.mark_as_valid()
|
||||
assert ValidityInfo.objects.exists() is False
|
||||
resp = app.get('/manage/pages/%s/' % page.pk)
|
||||
assert '<span class="invalid">foo_bar_reason</span>' not in resp.text
|
||||
assert '<span class="invalid">foo_bar_reason' not in resp.text
|
||||
|
||||
cell2 = LinkListCell.objects.create(order=0, placeholder='content', page=page)
|
||||
item = LinkCell.objects.create(page=page, placeholder=cell2.link_placeholder, order=0)
|
||||
item.mark_as_invalid('foo_bar_reason')
|
||||
cell2.check_validity()
|
||||
resp = app.get('/manage/pages/%s/' % page.pk)
|
||||
assert '<span class="invalid">Invalid link</span>' in resp.text
|
||||
assert '<span class="invalid">Invalid link' in resp.text
|
||||
assert 'This cell will no longer be displayed in 2 days.' in resp.text
|
||||
assert '<span class="invalid">foo_bar_reason</span>' in resp.text
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue