0001-data-add-site-settings-model-to-configure-welcome-ur.patch
combo/data/migrations/0048_sitesettings.py | ||
---|---|---|
1 |
# Generated by Django 2.2.19 on 2021-08-25 14:12 |
|
2 | ||
3 |
from django.db import migrations, models |
|
4 | ||
5 | ||
6 |
class Migration(migrations.Migration): |
|
7 | ||
8 |
dependencies = [ |
|
9 |
('data', '0047_auto_20210723_1318'), |
|
10 |
] |
|
11 | ||
12 |
operations = [ |
|
13 |
migrations.CreateModel( |
|
14 |
name='SiteSettings', |
|
15 |
fields=[ |
|
16 |
( |
|
17 |
'id', |
|
18 |
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), |
|
19 |
), |
|
20 |
( |
|
21 |
'initial_login_page_path', |
|
22 |
models.CharField( |
|
23 |
max_length=100, |
|
24 |
verbose_name='Initial login page path', |
|
25 |
help_text='Page to redirect to the first time user logs in.', |
|
26 |
), |
|
27 |
), |
|
28 |
( |
|
29 |
'welcome_page_path', |
|
30 |
models.CharField( |
|
31 |
max_length=100, |
|
32 |
verbose_name='Welcome page path', |
|
33 |
help_text='Page to redirect to on the first visit, to suggest user to log in.', |
|
34 |
), |
|
35 |
), |
|
36 |
], |
|
37 |
), |
|
38 |
] |
combo/data/migrations/0049_populate_site_settings.py | ||
---|---|---|
1 |
# Generated by Django 2.2.19 on 2021-08-31 10:10 |
|
2 | ||
3 |
from django.conf import settings |
|
4 |
from django.db import migrations |
|
5 | ||
6 | ||
7 |
def create_site_settings(apps, schema_editor): |
|
8 |
SiteSettings = apps.get_model('data', 'SiteSettings') |
|
9 |
site_settings = SiteSettings.objects.create() |
|
10 |
if hasattr(settings, 'COMBO_INITIAL_LOGIN_PAGE_PATH'): |
|
11 |
site_settings.initial_login_page_path = settings.COMBO_INITIAL_LOGIN_PAGE_PATH or '' |
|
12 |
if hasattr(settings, 'COMBO_WELCOME_PAGE_PATH'): |
|
13 |
site_settings.welcome_page_path = settings.COMBO_WELCOME_PAGE_PATH or '' |
|
14 |
site_settings.save() |
|
15 | ||
16 | ||
17 |
class Migration(migrations.Migration): |
|
18 | ||
19 |
dependencies = [ |
|
20 |
('data', '0048_sitesettings'), |
|
21 |
] |
|
22 | ||
23 |
operations = [ |
|
24 |
migrations.RunPython(create_site_settings), |
|
25 |
] |
combo/data/models.py | ||
---|---|---|
2134 | 2134 |
page.save(update_fields=['last_update_timestamp']) |
2135 | 2135 |
return |
2136 | 2136 |
page.build_cell_cache() |
2137 | ||
2138 | ||
2139 |
class SiteSettings(models.Model): |
|
2140 |
initial_login_page_path = models.CharField( |
|
2141 |
_('Initial login page path'), |
|
2142 |
help_text=_('Page to redirect to the first time user logs in.'), |
|
2143 |
max_length=100, |
|
2144 |
) |
|
2145 |
welcome_page_path = models.CharField( |
|
2146 |
_('Welcome page path'), |
|
2147 |
help_text=_('Page to redirect to on the first visit, to suggest user to log in.'), |
|
2148 |
max_length=100, |
|
2149 |
) |
combo/manager/forms.py | ||
---|---|---|
24 | 24 |
from django.template.loader import TemplateDoesNotExist, get_template |
25 | 25 |
from django.utils.translation import ugettext_lazy as _ |
26 | 26 | |
27 |
from combo.data.models import Page, ParentContentCell, compile_sub_slug |
|
27 |
from combo.data.models import Page, ParentContentCell, SiteSettings, compile_sub_slug
|
|
28 | 28 | |
29 | 29 |
from .fields import ImageIncludingSvgField |
30 | 30 | |
... | ... | |
279 | 279 |
assets = forms.BooleanField(label=_('Assets'), required=False, initial=True) |
280 | 280 |
asset_files = forms.BooleanField(label=_('Assets Files'), required=False, initial=False) |
281 | 281 |
payment = forms.BooleanField(label=_('Online Payment'), required=False, initial=True) |
282 | ||
283 | ||
284 |
class SiteSettingsForm(forms.ModelForm): |
|
285 |
class Meta: |
|
286 |
model = SiteSettings |
|
287 |
fields = '__all__' |
combo/manager/templates/combo/manager_home.html | ||
---|---|---|
10 | 10 |
<li><a href="{% url 'combo-manager-site-export' %}" rel="popup" data-autoclose-dialog="true">{% trans 'Export Site' %}</a></li> |
11 | 11 |
<li><a href="{% url 'combo-manager-site-import' %}">{% trans 'Import Site' %}</a></li> |
12 | 12 |
<li><a href="{% url 'combo-manager-invalid-cell-report' %}">{% trans 'Anomaly report' %}</a></li> |
13 |
<li><a href="{% url 'combo-manager-site-settings' %}" rel="popup" data-autoclose-dialog="true">{% trans 'Site Settings' %}</a></li> |
|
13 | 14 |
{% for extra_action in extra_actions %} |
14 | 15 |
<li><a href="{{ extra_action.href }}">{{ extra_action.text }}</a></li> |
15 | 16 |
{% endfor %} |
combo/manager/templates/combo/site_settings.html | ||
---|---|---|
1 |
{% extends "combo/manager_base.html" %} |
|
2 |
{% load i18n %} |
|
3 | ||
4 |
{% block appbar %} |
|
5 |
<h2>{% trans "Site Settings" %}</h2> |
|
6 |
{% endblock %} |
|
7 | ||
8 |
{% block content %} |
|
9 | ||
10 |
<form method="post"> |
|
11 |
{% csrf_token %} |
|
12 |
{{ form.as_p }} |
|
13 |
<div class="buttons"> |
|
14 |
<button class="submit-button">{% trans "Save" %}</button> |
|
15 |
<a class="cancel" href="{% url 'combo-manager-homepage' %}">{% trans 'Cancel' %}</a> |
|
16 |
</div> |
|
17 |
</form> |
|
18 |
{% endblock %} |
combo/manager/urls.py | ||
---|---|---|
29 | 29 |
url(r'^menu.json$', views.menu_json), |
30 | 30 |
url(r'^site-export$', views.site_export, name='combo-manager-site-export'), |
31 | 31 |
url(r'^site-import$', views.site_import, name='combo-manager-site-import'), |
32 |
url(r'^site-settings$', views.site_settings, name='combo-manager-site-settings'), |
|
32 | 33 |
url(r'^cells/invalid-report/$', views.invalid_cell_report, name='combo-manager-invalid-cell-report'), |
33 | 34 |
url(r'^pages/add/$', views.page_add, name='combo-manager-page-add'), |
34 | 35 |
url(r'^pages/(?P<pk>\d+)/$', views.page_view, name='combo-manager-page-view'), |
combo/manager/views.py | ||
---|---|---|
45 | 45 | |
46 | 46 |
from combo import plugins |
47 | 47 |
from combo.data.library import get_cell_class |
48 |
from combo.data.models import CellBase, LinkListCell, Page, PageSnapshot, ParentContentCell |
|
48 |
from combo.data.models import CellBase, LinkListCell, Page, PageSnapshot, ParentContentCell, SiteSettings
|
|
49 | 49 |
from combo.data.utils import ImportSiteError, export_site, export_site_tar, import_site, import_site_tar |
50 | 50 | |
51 | 51 |
from .forms import ( |
... | ... | |
63 | 63 |
PageVisibilityForm, |
64 | 64 |
SiteExportForm, |
65 | 65 |
SiteImportForm, |
66 |
SiteSettingsForm, |
|
66 | 67 |
) |
67 | 68 | |
68 | 69 | |
... | ... | |
918 | 919 |
PageSnapshot.take(cell.page, request=request, comment=_('reordered cells')) |
919 | 920 | |
920 | 921 |
return HttpResponse(status=204) |
922 | ||
923 | ||
924 |
class SiteSettingsView(UpdateView): |
|
925 |
form_class = SiteSettingsForm |
|
926 |
template_name = 'combo/site_settings.html' |
|
927 |
success_url = reverse_lazy('combo-manager-homepage') |
|
928 | ||
929 |
def get_object(self): |
|
930 |
return SiteSettings.objects.get() |
|
931 | ||
932 | ||
933 |
site_settings = SiteSettingsView.as_view() |
combo/public/views.py | ||
---|---|---|
54 | 54 |
ParentContentCell, |
55 | 55 |
PostException, |
56 | 56 |
Redirect, |
57 |
SiteSettings, |
|
57 | 58 |
TextCell, |
58 | 59 |
extract_context_from_sub_slug, |
59 | 60 |
) |
... | ... | |
459 | 460 |
if not parts: |
460 | 461 |
parts = ['index'] |
461 | 462 | |
463 |
site_settings = SiteSettings.objects.get() |
|
462 | 464 |
if ( |
463 | 465 |
parts == ['index'] |
464 |
and settings.COMBO_INITIAL_LOGIN_PAGE_PATH
|
|
466 |
and site_settings.initial_login_page_path
|
|
465 | 467 |
and (request.user and not request.user.is_anonymous) |
466 | 468 |
): |
467 | 469 |
profile, dummy = Profile.objects.get_or_create(user=request.user) |
... | ... | |
469 | 471 |
# first connection of user, record that and redirect to welcome URL |
470 | 472 |
profile.initial_login_view_timestamp = timezone.now() |
471 | 473 |
profile.save() |
472 |
return HttpResponseRedirect(settings.COMBO_INITIAL_LOGIN_PAGE_PATH)
|
|
474 |
return HttpResponseRedirect(site_settings.initial_login_page_path)
|
|
473 | 475 | |
474 | 476 |
if ( |
475 | 477 |
parts == ['index'] |
476 |
and settings.COMBO_WELCOME_PAGE_PATH
|
|
478 |
and site_settings.welcome_page_path
|
|
477 | 479 |
and (not request.user or request.user.is_anonymous) |
478 | 480 |
): |
479 | 481 |
if not request.session.setdefault('visited', False): |
480 | 482 |
# first visit, the user is not logged in. |
481 | 483 |
request.session['visited'] = True |
482 |
return HttpResponseRedirect(settings.COMBO_WELCOME_PAGE_PATH)
|
|
484 |
return HttpResponseRedirect(site_settings.welcome_page_path)
|
|
483 | 485 | |
484 | 486 |
pages = {} |
485 | 487 |
for page in Page.objects.filter(slug__in=parts): |
combo/settings.py | ||
---|---|---|
267 | 267 | |
268 | 268 |
JSON_CELL_TYPES = {} |
269 | 269 | |
270 |
# page to redirect the first time the user logs in. |
|
271 |
COMBO_INITIAL_LOGIN_PAGE_PATH = None |
|
272 | ||
273 |
# page to redirect on the first visit, to suggest user to log in. |
|
274 |
COMBO_WELCOME_PAGE_PATH = None |
|
275 | ||
276 | 270 |
# dashboard support |
277 | 271 |
COMBO_DASHBOARD_ENABLED = False |
278 | 272 |
tests/test_manager.py | ||
---|---|---|
40 | 40 |
Page, |
41 | 41 |
PageSnapshot, |
42 | 42 |
ParentContentCell, |
43 |
SiteSettings, |
|
43 | 44 |
TextCell, |
44 | 45 |
ValidityInfo, |
45 | 46 |
) |
... | ... | |
2486 | 2487 |
for i, item in enumerate(items): |
2487 | 2488 |
item.refresh_from_db() |
2488 | 2489 |
assert item.order == new_order[i] |
2490 | ||
2491 | ||
2492 |
def test_site_settings(app, admin_user): |
|
2493 |
app = login(app) |
|
2494 | ||
2495 |
resp = app.get('/manage/') |
|
2496 |
resp = resp.click('Site Settings') |
|
2497 |
resp.form['welcome_page_path'] = '/welcome/' |
|
2498 |
resp.form['initial_login_page_path'] = '/initial-login/' |
|
2499 |
resp.form.submit() |
|
2500 | ||
2501 |
site_settings = SiteSettings.objects.get() |
|
2502 |
assert site_settings.welcome_page_path == '/welcome/' |
|
2503 |
assert site_settings.initial_login_page_path == '/initial-login/' |
tests/test_public.py | ||
---|---|---|
33 | 33 |
Page, |
34 | 34 |
ParentContentCell, |
35 | 35 |
Redirect, |
36 |
SiteSettings, |
|
36 | 37 |
TextCell, |
37 | 38 |
) |
38 | 39 | |
... | ... | |
647 | 648 |
page = Page(title='Initial Login', slug='initial-login', template_name='standard', public=False) |
648 | 649 |
page.save() |
649 | 650 | |
650 |
with override_settings(COMBO_INITIAL_LOGIN_PAGE_PATH='/initial-login/'): |
|
651 |
resp = app.get('/', status=200) |
|
651 |
site_settings = SiteSettings.objects.get() |
|
652 |
site_settings.initial_login_page_path = '/initial-login/' |
|
653 |
site_settings.save() |
|
652 | 654 | |
653 |
# first visit |
|
654 |
app = login(app) |
|
655 |
resp = app.get('/', status=302) |
|
656 |
assert urllib.parse.urlparse(resp.location).path == '/initial-login/' |
|
655 |
resp = app.get('/', status=200) |
|
656 | ||
657 |
# first visit |
|
658 |
app = login(app) |
|
659 |
resp = app.get('/', status=302) |
|
660 |
assert urllib.parse.urlparse(resp.location).path == '/initial-login/' |
|
657 | 661 | |
658 |
# visit again
|
|
659 |
resp = app.get('/', status=200)
|
|
662 |
# visit again |
|
663 |
resp = app.get('/', status=200) |
|
660 | 664 | |
661 | 665 | |
662 | 666 |
def test_welcome_page(app, admin_user): |
... | ... | |
666 | 670 |
page = Page(title='Welcome', slug='welcome', template_name='standard') |
667 | 671 |
page.save() |
668 | 672 | |
669 |
with override_settings(COMBO_WELCOME_PAGE_PATH='/welcome/'): |
|
670 |
app.cookiejar.clear() |
|
671 |
resp = app.get('/', status=302) |
|
672 |
assert urllib.parse.urlparse(resp.location).path == '/welcome/' |
|
673 |
site_settings = SiteSettings.objects.get() |
|
674 |
site_settings.welcome_page_path = '/welcome/' |
|
675 |
site_settings.save() |
|
673 | 676 | |
674 |
resp = app.get('/', status=200) |
|
677 |
app.cookiejar.clear() |
|
678 |
resp = app.get('/', status=302) |
|
679 |
assert urllib.parse.urlparse(resp.location).path == '/welcome/' |
|
675 | 680 | |
676 |
app.cookiejar.clear() |
|
677 |
resp = app.get('/', status=302) |
|
678 |
assert urllib.parse.urlparse(resp.location).path == '/welcome/' |
|
681 |
resp = app.get('/', status=200) |
|
682 | ||
683 |
app.cookiejar.clear() |
|
684 |
resp = app.get('/', status=302) |
|
685 |
assert urllib.parse.urlparse(resp.location).path == '/welcome/' |
|
679 | 686 | |
680 |
app.cookiejar.clear()
|
|
681 |
app = login(app)
|
|
682 |
resp = app.get('/', status=200)
|
|
687 |
app.cookiejar.clear() |
|
688 |
app = login(app) |
|
689 |
resp = app.get('/', status=200) |
|
683 | 690 | |
684 | 691 | |
685 | 692 |
def test_post_cell(app): |
tests/test_wcs.py | ||
---|---|---|
2420 | 2420 |
app.get('/') # load once to populate caches |
2421 | 2421 |
with CaptureQueriesContext(connection) as ctx: |
2422 | 2422 |
app.get('/') |
2423 |
assert len(ctx.captured_queries) == 61
|
|
2423 |
assert len(ctx.captured_queries) == 62
|
|
2424 | 2424 | |
2425 | 2425 | |
2426 | 2426 |
def test_hourly(): |
2427 |
- |