From 658dc534e70136f077008143c8e3eed73addde36 Mon Sep 17 00:00:00 2001 From: Albertas Date: Thu, 30 Jul 2015 23:47:58 +0300 Subject: [PATCH 1/3] Add "terms of service" checkbox Add this checkbox both to SignupForm and UserProfileForm. Checkbox is shown in UserProfileForm only if user hasn't already accepted terms of service. User cannot save changes to settings unless he accepts terms of service. --- pylab/accounts/forms.py | 14 +- .../migrations/0002_auto_20150730_1059.py | 30 ++++ pylab/accounts/models.py | 1 + pylab/accounts/static/css/accounts.scss | 4 +- pylab/accounts/tests/test_settings.py | 18 ++- pylab/locale/lt/LC_MESSAGES/django.po | 133 +++++++++++------- 6 files changed, 150 insertions(+), 50 deletions(-) create mode 100644 pylab/accounts/migrations/0002_auto_20150730_1059.py diff --git a/pylab/accounts/forms.py b/pylab/accounts/forms.py index 9c7a71c..a0d4fc0 100644 --- a/pylab/accounts/forms.py +++ b/pylab/accounts/forms.py @@ -13,11 +13,15 @@ class UserProfileForm(forms.ModelForm): class Meta: model = accounts_models.UserProfile - fields = ('first_name', 'last_name', 'email', 'language') + fields = ('first_name', 'last_name', 'email', 'language', 'accepted_terms') help_texts = { 'email': _( "Will be used for communication. If you want not to get any emails, leave this field empty." ), + 'accepted_terms': _( + "[Terms of serivce](http://pylab.lt/terms). Basically, you accept that all your " + "creation and work done for Python workshops will belong to Python workshops." + ), } def __init__(self, *args, **kwargs): @@ -26,6 +30,9 @@ def __init__(self, *args, **kwargs): self.fields['email'].initial = self.instance.user.email self.fields['first_name'].initial = self.instance.user.first_name self.fields['last_name'].initial = self.instance.user.last_name + self.fields['accepted_terms'].required = True + if self.instance.accepted_terms: + self.fields.pop('accepted_terms') def save(self, *args, **kwargs): super(UserProfileForm, self).save(*args, **kwargs) @@ -41,6 +48,10 @@ class SignupForm(forms.ModelForm): ) + tuple(settings.LANGUAGES) language = forms.ChoiceField(label=_('Language'), required=False, choices=LANGUAGE_CHOICES) + accepted_terms = forms.BooleanField(label=_('Accept terms of service'), required=True, help_text=_( + "[Terms of serivce](http://pylab.lt/terms). Basically, you accept that all your " + "creation and work done for Python workshops will belong to Python workshops." + )) class Meta: model = auth_models.User @@ -58,4 +69,5 @@ def signup(self, request, user): # pylint: disable=unused-argument user.email = self.cleaned_data['email'] user.save() user.profile.language = self.cleaned_data['language'] + user.profile.accepted_terms = self.cleaned_data['accepted_terms'] user.profile.save() diff --git a/pylab/accounts/migrations/0002_auto_20150730_1059.py b/pylab/accounts/migrations/0002_auto_20150730_1059.py new file mode 100644 index 0000000..b500c31 --- /dev/null +++ b/pylab/accounts/migrations/0002_auto_20150730_1059.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('accounts', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='accepted_terms', + field=models.BooleanField(default=False, verbose_name='Accept terms of service'), + ), + migrations.AlterField( + model_name='userprofile', + name='language', + field=models.CharField(choices=[('lt', 'Lithuanian'), ('en', 'English')], default='', max_length=7, blank=True, verbose_name='Language'), + ), + migrations.AlterField( + model_name='userprofile', + name='user', + field=models.OneToOneField(related_name='profile', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/pylab/accounts/models.py b/pylab/accounts/models.py index 0e0ebc4..a210f67 100644 --- a/pylab/accounts/models.py +++ b/pylab/accounts/models.py @@ -9,6 +9,7 @@ class UserProfile(models.Model): user = models.OneToOneField(auth_models.User, related_name='profile') language = models.CharField(_('Language'), max_length=7, choices=settings.LANGUAGES, default='', blank=True) + accepted_terms = models.BooleanField(_('Accept terms of service'), default=False) @receiver(post_save, sender=auth_models.User) diff --git a/pylab/accounts/static/css/accounts.scss b/pylab/accounts/static/css/accounts.scss index 9ec1c67..942b8e6 100644 --- a/pylab/accounts/static/css/accounts.scss +++ b/pylab/accounts/static/css/accounts.scss @@ -27,4 +27,6 @@ } } - +#id_accepted_terms { + width: 10%; +} diff --git a/pylab/accounts/tests/test_settings.py b/pylab/accounts/tests/test_settings.py index 0ffd86e..21c9dc4 100644 --- a/pylab/accounts/tests/test_settings.py +++ b/pylab/accounts/tests/test_settings.py @@ -8,7 +8,9 @@ class SettingsTests(django_webtest.WebTest): def setUp(self): super().setUp() - auth_models.User.objects.create_user('u1') + u1 = auth_models.User.objects.create_user('u1') + u1.profile.accepted_terms = True + u1.profile.save() def test_user_settings(self): resp = self.app.get('/accounts/settings/', user='u1') @@ -47,3 +49,17 @@ def test_user_profile_locale_middleware(self): resp = self.app.get('/accounts/settings/', user='u1') # Website interface is displayed in lithuanian self.assertTrue(b'Saugoti' in resp.content) + + def test_requirement_to_accept_terms_of_service(self): + auth_models.User.objects.create_user('u2_not_accepted_terms_yet') + resp = self.app.get('/accounts/settings/', user='u2_not_accepted_terms_yet') + resp.form['language'] = 'en' + resp = resp.form.submit() + # Don't allow to save unless user accepts terms of service + self.assertEqual(resp.status_int, 200) + self.assertTrue(b'has-error' in resp.content) + resp.form['language'] = 'en' + resp.form['accepted_terms'].checked = True + resp = resp.form.submit() + # Allow to save settings changes because user accepted terms of service + self.assertEqual(resp.status_int, 302) diff --git a/pylab/locale/lt/LC_MESSAGES/django.po b/pylab/locale/lt/LC_MESSAGES/django.po index 2014e76..4e32321 100644 --- a/pylab/locale/lt/LC_MESSAGES/django.po +++ b/pylab/locale/lt/LC_MESSAGES/django.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-07-27 06:02-0500\n" +"POT-Creation-Date: 2015-07-30 14:09-0500\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -27,7 +27,7 @@ msgstr "Pavardė" msgid "Email address" msgstr "El. pašto adresas" -#: accounts/forms.py:19 accounts/forms.py:47 +#: accounts/forms.py:19 accounts/forms.py:61 msgid "" "Will be used for communication. If you want not to get any emails, leave " "this field empty." @@ -35,14 +35,28 @@ msgstr "" "Bus naudojamas komunikacijai. Jei pageidaujate negauti jokių laiškų, " "palikite šį lauką tuščią." -#: accounts/forms.py:25 accounts/forms.py:40 +#: accounts/forms.py:22 accounts/forms.py:52 +msgid "" +"[Terms of serivce](http://pylab.lt/terms). Basically, you accept that all " +"your creation and work done for Python workshops will belong to Python " +"workshops." +msgstr "" +"[Paslaugų teikimo sąlygas](http://pylab.lt/terms). Iš esmės, Jūs sutinkate, " +"kad visa Jūsų kūryba ir atliktas darbas Python dirbtuvėms priklausys Python " +"dirbtuvėms." + +#: accounts/forms.py:29 accounts/forms.py:47 msgid "Default" msgstr "Numatytoji" -#: accounts/forms.py:39 accounts/models.py:11 +#: accounts/forms.py:50 accounts/models.py:11 msgid "Language" msgstr "Kalba" +#: accounts/forms.py:51 accounts/models.py:12 +msgid "Accept terms of service" +msgstr "Sutikti su paslaugų teikimo sąlygomis" + #: accounts/templates/accounts/login.html:9 #: accounts/templates/accounts/login.html:24 website/templates/base.html:36 msgid "Login" @@ -97,6 +111,34 @@ msgstr "Profilio nustatymai" msgid "Save" msgstr "Saugoti" +#: core/models.py:15 core/models.py:43 +msgid "Title" +msgstr "Pavadinimas" + +#: core/models.py:16 core/models.py:47 +msgid "Description" +msgstr "Aprašymas" + +#: core/models.py:31 +msgid "Other event" +msgstr "Kitas renginys" + +#: core/models.py:32 +msgid "Project development" +msgstr "Projekto vystymas" + +#: core/models.py:33 +msgid "Initial meeting" +msgstr "Pradinis susitikimas" + +#: core/models.py:34 +msgid "Weekly meeting" +msgstr "Savaitinis susitikimas" + +#: core/models.py:49 +msgid "OpenStreetMap iframe src link." +msgstr "OpenStreetMap iframe src nuoroda." + #: settings/base.py:23 msgid "Lithuanian" msgstr "Lietuvių" @@ -105,7 +147,7 @@ msgstr "Lietuvių" msgid "English" msgstr "Anglų" -#: website/forms.py:16 +#: website/forms.py:17 msgid "" "Describe your project idea. You can use [Markdown](http://daringfireball.net/" "projects/markdown/syntax){:target=_blank} markup." @@ -113,57 +155,18 @@ msgstr "" "Apibūdinkite savo projekto idėją. Galite naudoti [Žymėjimų kalbą](http://" "daringfireball.net/projects/markdown/syntax){:target=_blank}." - #: website/menus.py:18 website/templates/base.html:14 msgid "Summer Python Workshop" msgstr "Vasaros Python dirbtuvės" -#: website/models.py:15 -msgid "Title" -msgstr "Pavadinimas" - -#: website/models.py:16 -msgid "Description" -msgstr "Aprašymas" +#: website/menus.py:19 +msgid "About" +msgstr "Apie" #: website/templates/base.html:34 msgid "Logout" msgstr "Atsijungti" -#: website/templates/website/project_details.html:11 -msgid "Change" -msgstr "Redaguoti" - -#: website/templates/website/project_list.html:8 -msgid "Suggest new project idea" -msgstr "Pasiūlyti naują projekto idėją" - -#: website/templates/website/project_list.html:15 -msgid "Project idea" -msgstr "Projekto idėja" - -#: website/templates/website/project_list.html:27 -msgid "No suggested projects yet." -msgstr "Kol kas nėra pasiūlytų projektų." - -#: website/views.py:35 -#, python-format -msgid "Project „%s“ created." -msgstr "Projektas „%s“ sukurtas." - -#: website/views.py:41 -msgid "Suggest new project" -msgstr "Pasiūlyti naują projektą" - -#: website/views.py:56 -#, python-format -msgid "Project „%s“ updated." -msgstr "Projektas „%s“ atnaujintas." - -#: website/menus.py:19 -msgid "About" -msgstr "Apie" - #: website/templates/website/about.html:7 msgid "About Summer Python Workshop" msgstr "Apie Vasaros Python dirbtuves" @@ -218,6 +221,12 @@ msgid "" "devoted\n" " to clarify aims and user stories for the chosen project." msgstr "" +"Kiekvienos Python dirbtuvės prasideda pradiniu susitikimu, per kurį\n" +" dalyviai balsuoja, kurį projektą jie norėtų įgyvendinti šių dirbtuvių " +"metu.\n" +" Pradinis susitikimas yra truputį ilgesnis, nei įprasti savaitiniai " +"susitikimai ir pagrinde skirti pasirinkto projekto tikslų bei panaudos " +"scenarijų išgryninimui." #: website/templates/website/about.html:34 msgid "" @@ -285,3 +294,33 @@ msgstr "" "serverių, patalpų nuomos, komunalinių mokesčių, hakatonų organizavimo " "sąnaudos, taip pat gali būti samdomi etatiniai Python dirbtuvių " "programuotojai." + +#: website/templates/website/project_details.html:11 +msgid "Change" +msgstr "Redaguoti" + +#: website/templates/website/project_list.html:8 +msgid "Suggest new project idea" +msgstr "Pasiūlyti naują projekto idėją" + +#: website/templates/website/project_list.html:15 +msgid "Project idea" +msgstr "Projekto idėja" + +#: website/templates/website/project_list.html:27 +msgid "No suggested projects yet." +msgstr "Kol kas nėra pasiūlytų projektų." + +#: website/views.py:35 +#, python-format +msgid "Project „%s“ created." +msgstr "Projektas „%s“ sukurtas." + +#: website/views.py:41 +msgid "Suggest new project" +msgstr "Pasiūlyti naują projektą" + +#: website/views.py:56 +#, python-format +msgid "Project „%s“ updated." +msgstr "Projektas „%s“ atnaujintas." From ea6c5dcab1e315135518b941aee366524c215843 Mon Sep 17 00:00:00 2001 From: Albertas Date: Fri, 31 Jul 2015 00:08:47 +0300 Subject: [PATCH 2/3] Add missing / at the end of terms of service link --- pylab/accounts/forms.py | 4 ++-- pylab/locale/lt/LC_MESSAGES/django.po | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pylab/accounts/forms.py b/pylab/accounts/forms.py index a0d4fc0..f61e25d 100644 --- a/pylab/accounts/forms.py +++ b/pylab/accounts/forms.py @@ -19,7 +19,7 @@ class Meta: "Will be used for communication. If you want not to get any emails, leave this field empty." ), 'accepted_terms': _( - "[Terms of serivce](http://pylab.lt/terms). Basically, you accept that all your " + "[Terms of serivce](http://pylab.lt/terms/). Basically, you accept that all your " "creation and work done for Python workshops will belong to Python workshops." ), } @@ -49,7 +49,7 @@ class SignupForm(forms.ModelForm): language = forms.ChoiceField(label=_('Language'), required=False, choices=LANGUAGE_CHOICES) accepted_terms = forms.BooleanField(label=_('Accept terms of service'), required=True, help_text=_( - "[Terms of serivce](http://pylab.lt/terms). Basically, you accept that all your " + "[Terms of serivce](http://pylab.lt/terms/). Basically, you accept that all your " "creation and work done for Python workshops will belong to Python workshops." )) diff --git a/pylab/locale/lt/LC_MESSAGES/django.po b/pylab/locale/lt/LC_MESSAGES/django.po index 4e32321..43e3610 100644 --- a/pylab/locale/lt/LC_MESSAGES/django.po +++ b/pylab/locale/lt/LC_MESSAGES/django.po @@ -37,11 +37,11 @@ msgstr "" #: accounts/forms.py:22 accounts/forms.py:52 msgid "" -"[Terms of serivce](http://pylab.lt/terms). Basically, you accept that all " +"[Terms of serivce](http://pylab.lt/terms/). Basically, you accept that all " "your creation and work done for Python workshops will belong to Python " "workshops." msgstr "" -"[Paslaugų teikimo sąlygas](http://pylab.lt/terms). Iš esmės, Jūs sutinkate, " +"[Paslaugų teikimo sąlygas](http://pylab.lt/terms/). Iš esmės, Jūs sutinkate, " "kad visa Jūsų kūryba ir atliktas darbas Python dirbtuvėms priklausys Python " "dirbtuvėms." From 27ef7804dd5055661ad377e9828f2914f130bf1f Mon Sep 17 00:00:00 2001 From: Albertas Date: Fri, 31 Jul 2015 08:39:42 +0300 Subject: [PATCH 3/3] Fix some typos in README.rst Also rewrite one sentence describing environment for development preparation. --- README.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index e70a3ae..bc51dff 100644 --- a/README.rst +++ b/README.rst @@ -22,7 +22,8 @@ Contacts Development environment ======================= -You need to create database manually:: +Execute these commands in Ubuntu 14.04 or greater to prepare your environment +for development:: $ createdb pylab $ make @@ -119,12 +120,12 @@ you have to be careful with. To avoid refactoring issues, we keep all project data access logic in single Django app called ``core``. Also this helps us to better manage dependencies between apps. Since ``core`` contains data access logic which is lowest layer -according to *multilayered architecture*, this means, that is is very likely, +according to *multilayered architecture*, this means, that it is very likely, that most of the code will depend on this app. So since ``core`` tend to be referenced by many other modules and apps, we keep ``core`` lean. ``website`` app is another special case and it belongs to *application* and -*presentation* layers. This means that no other apps can ``website`` depend on +*presentation* layers. This means that no other apps can depend on ``website``, but ``website`` should depend on all other apps. In other words, ``website`` works like top level app with purpose to connect all components in order to assemble whole project.