diff --git a/app/urls.py b/app/urls.py
index 55f7523..b8b2c32 100644
--- a/app/urls.py
+++ b/app/urls.py
@@ -7,6 +7,7 @@
import core.views.book_search
import core.views.chat
import core.views.calendar
+import core.views.newsletter_signup
urlpatterns = [
@@ -17,4 +18,5 @@
path('example/', core.views.example.example, name='example'),
path('chat/', core.views.chat.chat, name='chat'),
path('calendar/', core.views.calendar.calendar, name="calendar"),
+ path('newsletter-signup', core.views.newsletter_signup.view, name='newsletter-signup')
] + staticfiles_urlpatterns()
diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py
new file mode 100644
index 0000000..d3a0aa0
--- /dev/null
+++ b/core/migrations/0001_initial.py
@@ -0,0 +1,22 @@
+# Generated by Django 3.2 on 2021-04-25 17:06
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='NewsletterSubscription',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('email', models.EmailField(max_length=254)),
+ ('name', models.CharField(max_length=256)),
+ ],
+ ),
+ ]
diff --git a/core/models.py b/core/models.py
index 71a8362..94f28bd 100644
--- a/core/models.py
+++ b/core/models.py
@@ -1,3 +1,6 @@
from django.db import models
-# Create your models here.
+
+class NewsletterSubscription(models.Model):
+ email = models.EmailField()
+ name = models.CharField(max_length=256)
diff --git a/core/reflexes/newsletter_signup_reflex.py b/core/reflexes/newsletter_signup_reflex.py
new file mode 100644
index 0000000..2f78573
--- /dev/null
+++ b/core/reflexes/newsletter_signup_reflex.py
@@ -0,0 +1,15 @@
+from sockpuppet.reflex import Reflex
+
+from core.models import NewsletterSubscription
+
+
+class SubscriptionReflex(Reflex):
+ def add_person(self):
+ o = NewsletterSubscription.objects.update_or_create(
+ name=self.params['name'],
+ email=self.params['email']
+ )
+
+ def remove_person(self):
+ id = self.element.dataset['id']
+ NewsletterSubscription.objects.filter(id=id).delete()
diff --git a/core/templates/_newsletter_signup.html b/core/templates/_newsletter_signup.html
new file mode 100644
index 0000000..9513ba4
--- /dev/null
+++ b/core/templates/_newsletter_signup.html
@@ -0,0 +1,30 @@
+{% load static %}
+
+
+
Sign up for newsletter!
+
diff --git a/core/templates/base.html b/core/templates/base.html
index f467c00..b91f595 100644
--- a/core/templates/base.html
+++ b/core/templates/base.html
@@ -38,6 +38,7 @@
Example
BookSearch
Chat
+ Newsletter Signup
diff --git a/core/views/mixins.py b/core/views/mixins.py
index 366d751..f5abed5 100644
--- a/core/views/mixins.py
+++ b/core/views/mixins.py
@@ -51,6 +51,7 @@ class ExampleMixin(MixinBase):
('core/templates/_example_demo.html', 'html', 'htmldjango'),
)
+
class ChatMixin(MixinBase):
files = (
('core/views/chat.py', 'python', 'python3'),
@@ -59,12 +60,19 @@ class ChatMixin(MixinBase):
('core/templates/_chat_demo.html', 'html', 'htmldjango'),
)
+
class CalendarMixin(MixinBase):
files = (
('core/views/calendar.py', 'python', 'python3'),
-# ('core/reflexes/calendar_reflex.py', 'python', 'python3'),
-# ('core/javascript/controllers/calendar_controller.js', 'javascript', 'javascript'),
('core/templates/_calendar.html', 'html', 'htmldjango'),
('core/templates/_td_calendar.html', 'html', 'htmldjango'),
)
+
+
+class NewsletterSignupMixin(MixinBase):
+ files = (
+ ('core/views/newsletter_signup.py', 'python', 'python3'),
+ ('core/reflexes/newsletter_signup_reflex.py', 'python', 'python3'),
+ ('core/templates/_newsletter_signup.html', 'html', 'htmldjango')
+ )
diff --git a/core/views/newsletter_signup.py b/core/views/newsletter_signup.py
new file mode 100644
index 0000000..03a9b76
--- /dev/null
+++ b/core/views/newsletter_signup.py
@@ -0,0 +1,25 @@
+from django.forms import ModelForm
+from django.views.generic.edit import FormView
+
+from core.models import NewsletterSubscription
+from core.views.mixins import NewsletterSignupMixin
+
+
+class NewsletterSubscriptionForm(ModelForm):
+ class Meta:
+ model = NewsletterSubscription
+ fields = ['name', 'email']
+
+
+class NewsletterSignupView(NewsletterSignupMixin, FormView):
+ demo_template = '_newsletter_signup.html'
+ form_class = NewsletterSubscriptionForm
+ subtitle = 'Newsletter Signup'
+
+ def get_context_data(self, *args, **kwargs):
+ context = super().get_context_data(*args, **kwargs)
+ context['people'] = NewsletterSubscription.objects.all()
+ return context
+
+
+view = NewsletterSignupView.as_view()
diff --git a/requirements.in b/requirements.in
index 32f98a0..4d32287 100644
--- a/requirements.in
+++ b/requirements.in
@@ -5,7 +5,7 @@ django-pygments-renderer
django-widget-tweaks
django-redis
-https://github.com/gilmrjc/django-webpack-loader/archive/webpack-bundle-tracker-1.zip
+django-webpack-loader
# deployment
fabric
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..7a3e166
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,65 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file=requirements.txt requirements.in
+#
+aioredis==1.3.1 # via channels-redis
+asgiref==3.3.4 # via channels, channels-redis, daphne, django
+async-timeout==3.0.1 # via aioredis
+attrs==21.2.0 # via automat, service-identity, twisted
+autobahn==21.3.1 # via daphne
+automat==20.2.0 # via twisted
+bcrypt==3.2.0 # via paramiko
+beautifulsoup4==4.9.3 # via bs4
+bs4==0.0.1 # via django-sockpuppet
+certifi==2020.12.5 # via requests
+cffi==1.14.5 # via bcrypt, cryptography, pynacl
+channels-redis==3.2.0 # via django-sockpuppet
+channels==3.0.3 # via channels-redis, django-sockpuppet
+chardet==4.0.0 # via requests
+constantly==15.1.0 # via twisted
+cryptography==3.4.7 # via autobahn, paramiko, pyopenssl, service-identity
+daphne==3.0.2 # via channels
+django-pygments-renderer==0.0.1 # via -r requirements.in
+django-redis==4.12.1 # via -r requirements.in
+django-seed==0.2.2 # via -r requirements.in
+django-sockpuppet==0.6.0 # via -r requirements.in
+django-webpack-loader==0.7.0 # via -r requirements.in
+django-widget-tweaks==1.4.8 # via -r requirements.in
+django==3.2.2 # via -r requirements.in, channels, django-pygments-renderer, django-redis, django-seed
+fabric==2.6.0 # via -r requirements.in, patchwork
+faker==8.1.2 # via django-seed
+gunicorn==20.1.0 # via -r requirements.in
+hiredis==2.0.0 # via aioredis
+hyperlink==21.0.0 # via autobahn, twisted
+idna==2.10 # via hyperlink, requests, twisted
+incremental==21.3.0 # via twisted
+invoke==1.5.0 # via fabric
+msgpack==1.0.2 # via channels-redis
+paramiko==2.7.2 # via fabric
+patchwork==1.0.1 # via -r requirements.in
+pathlib2==2.3.5 # via fabric
+pyasn1-modules==0.2.8 # via service-identity
+pyasn1==0.4.8 # via pyasn1-modules, service-identity
+pycparser==2.20 # via cffi
+pygments==2.9.0 # via django-pygments-renderer
+pynacl==1.4.0 # via paramiko
+pyopenssl==20.0.1 # via twisted
+python-dateutil==2.8.1 # via faker
+pytz==2021.1 # via django
+redis==3.5.3 # via django-redis
+requests==2.25.1 # via -r requirements.in
+service-identity==21.1.0 # via twisted
+six==1.16.0 # via automat, bcrypt, pathlib2, pynacl, pyopenssl, python-dateutil, service-identity
+soupsieve==2.2.1 # via beautifulsoup4
+sqlparse==0.4.1 # via django
+text-unidecode==1.3 # via faker
+twisted[tls]==21.2.0 # via daphne
+txaio==21.2.1 # via autobahn
+urllib3==1.26.4 # via requests
+whitenoise==5.2.0 # via -r requirements.in
+zope.interface==5.4.0 # via twisted
+
+# The following packages are considered to be unsafe in a requirements file:
+# setuptools